X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=write.c;h=dda1b705c19151000dd08098f99d2b9d4c71f11c;hp=d2169f26c9ed499c300c03ca01a81b0c9f1963db;hb=b62e2796b85c7d7f3138fe729f4637853e0fafe0;hpb=1c859dfc274c592eca267197131d6497b650b24c diff --git a/write.c b/write.c index d2169f26..dda1b705 100644 --- a/write.c +++ b/write.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Andre Noll + * Copyright (C) 2005-2011 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -32,10 +32,12 @@ enum check_wav_state { CWS_NO_HEADER, }; +/* Information extracted from the wav header. */ struct check_wav_task { int state; - /** Number of channels specified in wav header given by \a buf. */ + /** Number of channels. */ unsigned channels; + unsigned sample_format; /** Sample rate specified in wav header given by \a buf. */ unsigned sample_rate; /** The task structure used by the scheduler. */ @@ -51,12 +53,6 @@ static struct stdin_task sit; /** Length of a standard wav header. */ #define WAV_HEADER_LEN 44 -/** - * Test if audio buffer contains a valid wave header. - * - * \return If not, return -E_NO_WAV_HEADER, otherwise, return zero. If - * there is less than WAV_HEADER_LEN bytes available, return one. - */ static void check_wav_pre_select(struct sched *s, struct task *t) { struct check_wav_task *cwt = container_of(t, struct check_wav_task, task); @@ -71,7 +67,7 @@ static void check_wav_pre_select(struct sched *s, struct task *t) if (!strcmp(cmd, #_cmd)) { \ if (!conf._cmd ## _given && cwt->state == CWS_NEED_HEADER) \ return -E_BTR_NAVAIL; \ - *result = make_message("%d", cwt->state == CWS_NO_HEADER? \ + *result = make_message("%d", cwt->state == CWS_NO_HEADER || conf._cmd ## _given? \ conf._cmd ## _arg : cwt->_cmd); \ return 1; \ } \ @@ -83,6 +79,7 @@ static int check_wav_exec(struct btr_node *btrn, const char *cmd, char **result) HANDLE_EXEC(sample_rate); HANDLE_EXEC(channels); + HANDLE_EXEC(sample_format); return -ERRNO_TO_PARA_ERROR(ENOTSUP); } @@ -93,6 +90,8 @@ static void check_wav_post_select(__a_unused struct sched *s, struct task *t) unsigned char *a; size_t sz; int ret; + uint16_t bps; /* bits per sample */ + const char *sample_formats[] = {SAMPLE_FORMATS}; t->error = 0; ret = btr_node_status(btrn, cwt->min_iqs, BTR_NT_INTERNAL); @@ -105,9 +104,13 @@ static void check_wav_post_select(__a_unused struct sched *s, struct task *t) if (sz < cwt->min_iqs) /* file size less than WAV_HEADER_SIZE */ goto pushdown; cwt->min_iqs = 0; - cwt->channels = 2; - cwt->sample_rate = 44100; - if (a[0] != 'R' || a[1] != 'I' || a[2] != 'F' || a[3] != 'F') { + /* + * The default byte ordering assumed for WAVE data files is + * little-endian. Files written using the big-endian byte ordering + * scheme have the identifier RIFX instead of RIFF. + */ + if (a[0] != 'R' || a[1] != 'I' || a[2] != 'F' || + (a[3] != 'F' && a[3] != 'X')) { PARA_NOTICE_LOG("wav header not found\n"); cwt->state = CWS_NO_HEADER; sprintf(t->status, "check wav: no header"); @@ -118,7 +121,23 @@ static void check_wav_post_select(__a_unused struct sched *s, struct task *t) sprintf(t->status, "check wav: have header"); cwt->channels = (unsigned) a[22]; cwt->sample_rate = a[24] + (a[25] << 8) + (a[26] << 16) + (a[27] << 24); - PARA_INFO_LOG("channels: %d, sample rate: %d\n", cwt->channels, cwt->sample_rate); + bps = a[34] + ((unsigned)a[35] << 8); + if (bps != 8 && bps != 16) { + PARA_WARNING_LOG("%u bps not supported, assuming 16\n", bps); + bps = 16; + } + /* + * 8-bit samples are stored as unsigned bytes, ranging from 0 to 255. + * 16-bit samples are stored as 2's-complement signed integers, ranging + * from -32768 to 32767. + */ + if (bps == 8) + cwt->sample_format = SF_U8; + else + cwt->sample_format = (a[3] == 'F')? SF_S16_LE : SF_S16_BE; + PARA_NOTICE_LOG("%dHz, %s, %s\n", cwt->sample_rate, + cwt->channels == 1? "mono" : "stereo", + sample_formats[cwt->sample_format]); btr_consume(btrn, WAV_HEADER_LEN); pushdown: btr_pushdown(btrn);