diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2014-10-03 14:12:10 +0200 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2014-10-03 14:12:10 +0200 |
commit | 707fe9a47cda5aed258c9dcf913716076390bccf (patch) | |
tree | d4e120687a5896a7c40578dee264b3a963874700 /src | |
parent | f066b0aa840f5c9c95185d6da39702e1084dc2ff (diff) | |
download | ODR-AudioEnc-707fe9a47cda5aed258c9dcf913716076390bccf.tar.gz ODR-AudioEnc-707fe9a47cda5aed258c9dcf913716076390bccf.tar.bz2 ODR-AudioEnc-707fe9a47cda5aed258c9dcf913716076390bccf.zip |
Backport mstorjo's changes to wavreader.c
These include commits:
f825104 Add support for waveformatex files
16f75a5 Support reading sox style piped wav files
43cb942 Use skip instead of fseek
cb19aa7 Allow reading wav files with a 0 bytes RIFF chunk
3951d0a Allow opening stdin when "-" is specified
e7348e7 Support streamed wav files with a 0 bytes data chunk
Diffstat (limited to 'src')
-rw-r--r-- | src/wavreader.c | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/src/wavreader.c b/src/wavreader.c index c62a885..c8bb05d 100644 --- a/src/wavreader.c +++ b/src/wavreader.c @@ -34,6 +34,8 @@ struct wav_reader { int channels; int byte_rate; int block_align; + + int streamed; }; static uint32_t read_tag(struct wav_reader* wr) { @@ -61,12 +63,21 @@ static uint16_t read_int16(struct wav_reader* wr) { return value; } +static void skip(FILE *f, int n) { + int i; + for (i = 0; i < n; i++) + fgetc(f); +} + void* wav_read_open(const char *filename) { struct wav_reader* wr = (struct wav_reader*) malloc(sizeof(*wr)); long data_pos = 0; memset(wr, 0, sizeof(*wr)); - wr->wav = fopen(filename, "rb"); + if (!strcmp(filename, "-")) + wr->wav = stdin; + else + wr->wav = fopen(filename, "rb"); if (wr->wav == NULL) { free(wr); return NULL; @@ -78,6 +89,10 @@ void* wav_read_open(const char *filename) { if (feof(wr->wav)) break; length = read_int32(wr); + if (!length || length >= 0x7fff0000) { + wr->streamed = 1; + length = ~0; + } if (tag != TAG('R', 'I', 'F', 'F') || length < 4) { fseek(wr->wav, length, SEEK_CUR); continue; @@ -109,13 +124,27 @@ void* wav_read_open(const char *filename) { wr->byte_rate = read_int32(wr); wr->block_align = read_int16(wr); wr->bits_per_sample = read_int16(wr); - fseek(wr->wav, sublength - 16, SEEK_CUR); + if (wr->format == 0xfffe) { + if (sublength < 28) { + // Insufficient data for waveformatex + break; + } + skip(wr->wav, 8); + wr->format = read_int32(wr); + skip(wr->wav, sublength - 28); + } else { + skip(wr->wav, sublength - 16); + } } else if (subtag == TAG('d', 'a', 't', 'a')) { data_pos = ftell(wr->wav); wr->data_length = sublength; + if (!wr->data_length || wr->streamed) { + wr->streamed = 1; + return wr; + } fseek(wr->wav, sublength, SEEK_CUR); } else { - fseek(wr->wav, sublength, SEEK_CUR); + skip(wr->wav, sublength); } length -= sublength; } @@ -130,7 +159,8 @@ void* wav_read_open(const char *filename) { void wav_read_close(void* obj) { struct wav_reader* wr = (struct wav_reader*) obj; - fclose(wr->wav); + if (wr->wav != stdin) + fclose(wr->wav); free(wr); } @@ -154,7 +184,7 @@ int wav_read_data(void* obj, unsigned char* data, unsigned int length) { int n; if (wr->wav == NULL) return -1; - if (length > wr->data_length) + if (length > wr->data_length && !wr->streamed) length = wr->data_length; n = fread(data, 1, length, wr->wav); wr->data_length -= length; |