From 71cf604d8d317b7c2b167aac37493795046431cd Mon Sep 17 00:00:00 2001 From: Adam Boot Date: Tue, 27 Jun 2006 22:27:21 +0000 Subject: Fix for wav files where the fmt chunk is not close to the start of the file git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10149 a1c6a512-1295-4272-9138-f99709370657 --- apps/codecs/wav.c | 47 ++++++++++++++++++++++---------------- apps/metadata.c | 68 ++++++++++++++++++++++++++++++++----------------------- 2 files changed, 68 insertions(+), 47 deletions(-) diff --git a/apps/codecs/wav.c b/apps/codecs/wav.c index f83f1d1e58..6bf2cb5864 100644 --- a/apps/codecs/wav.c +++ b/apps/codecs/wav.c @@ -256,9 +256,9 @@ next_track: while (!*ci->taginfo_ready) ci->yield(); - /* assume the WAV header is less than 1024 bytes */ - buf = ci->request_buffer(&n, 1024); - if (n < 44) { + /* get RIFF chunk header */ + buf = ci->request_buffer(&n, 12); + if (n < 12) { i = CODEC_ERROR; goto done; } @@ -267,13 +267,24 @@ next_track: goto done; } - buf += 12; - n -= 12; + /* advance to first WAVE chunk */ + ci->advance_buffer(12); + + firstblockposn = 12; bitspersample = 0; numbytes = 0; totalsamples = 0; - /* read until the data chunk, which should be last */ - while (numbytes == 0 && n >= 8) { + + /* iterate over WAVE chunks until the 'data' chunk, which should be after the 'fmt ' chunk */ + while (true) { + /* get WAVE chunk header */ + buf = ci->request_buffer(&n, 1024); + if (n < 8) { + /* no more chunks, 'data' chunk must not have been found */ + i = CODEC_ERROR; + goto done; + } + /* chunkSize */ i = (buf[4]|(buf[5]<<8)|(buf[6]<<16)|(buf[7]<<24)); if (memcmp(buf, "fmt ", 4) == 0) { @@ -327,7 +338,10 @@ next_track: } } else if (memcmp(buf, "data", 4) == 0) { numbytes = i; - i = 0; /* advance to the beginning of data */ + /* advance to start of data */ + ci->advance_buffer(8); + firstblockposn += 8; + break; } else if (memcmp(buf, "fact", 4) == 0) { /* dwSampleLength */ if (i >= 4) @@ -336,16 +350,12 @@ next_track: DEBUGF("unknown WAVE chunk: '%c%c%c%c', size=%lu\n", buf[0], buf[1], buf[2], buf[3], i); } + /* go to next chunk (even chunk sizes must be padded) */ if (i & 0x01) i++; - buf += i + 8; - if (n < (i + 8)) { - DEBUGF("CODEC_ERROR: WAVE header size > 1024\n"); - i = CODEC_ERROR; - goto done; - } - n -= i + 8; + ci->advance_buffer(i+8); + firstblockposn += i + 8; } if (channels == 0) { @@ -409,16 +419,15 @@ next_track: } } - firstblockposn = 1024 - n; - + /* make sure we're at the correct offset */ if (ci->id3->offset > (uint32_t) firstblockposn) { /* Round down to previous block */ uint32_t offset = ci->id3->offset - ci->id3->offset % blockalign; - ci->advance_buffer(offset); + ci->advance_buffer(offset-firstblockposn); bytesdone = offset - firstblockposn; } else { - ci->advance_buffer(firstblockposn); + /* already where we need to be */ bytesdone = 0; } diff --git a/apps/metadata.c b/apps/metadata.c index 9cb055608a..bdf65b2639 100644 --- a/apps/metadata.c +++ b/apps/metadata.c @@ -829,71 +829,84 @@ static bool get_wave_metadata(int fd, struct mp3entry* id3) int read_bytes; int i; - if ((lseek(fd, 0, SEEK_SET) < 0) - || ((read_bytes = read(fd, buf, sizeof(id3->path))) < 44)) + /* get RIFF chunk header */ + if ((lseek(fd, 0, SEEK_SET) < 0) + || ((read_bytes = read(fd, buf, 12)) < 12)) { return false; } - + if ((memcmp(buf, "RIFF",4) != 0) || (memcmp(&buf[8], "WAVE", 4) !=0 )) { return false; } - buf += 12; - read_bytes -= 12; - - while ((numbytes == 0) && (read_bytes >= 8)) + /* iterate over WAVE chunks until 'data' chunk */ + while (true) { + /* get chunk header */ + if ((read_bytes = read(fd, buf, 8)) < 8) + return false; + /* chunkSize */ i = get_long(&buf[4]); - + if (memcmp(buf, "fmt ", 4) == 0) { + /* get rest of chunk */ + if ((read_bytes = read(fd, buf, 16)) < 16) + return false; + + i -= 16; + /* skipping wFormatTag */ /* wChannels */ - channels = buf[10] | (buf[11] << 8); + channels = buf[2] | (buf[3] << 8); /* dwSamplesPerSec */ - id3->frequency = get_long(&buf[12]); + id3->frequency = get_long(&buf[4]); /* dwAvgBytesPerSec */ - id3->bitrate = (get_long(&buf[16]) * 8) / 1000; + id3->bitrate = (get_long(&buf[8]) * 8) / 1000; /* skipping wBlockAlign */ /* wBitsPerSample */ - bitspersample = buf[22] | (buf[23] << 8); + bitspersample = buf[14] | (buf[15] << 8); } - else if (memcmp(buf, "data", 4) == 0) + else if (memcmp(buf, "data", 4) == 0) { numbytes = i; + break; } - else if (memcmp(buf, "fact", 4) == 0) + else if (memcmp(buf, "fact", 4) == 0) { /* dwSampleLength */ - if (i >= 4) + if (i >= 4) { - totalsamples = get_long(&buf[8]); + /* get rest of chunk */ + if ((read_bytes = read(fd, buf, 2)) < 2) + return false; + + i -= 2; + totalsamples = get_long(buf); } } - - /* go to next chunk (even chunk sizes must be padded) */ + + /* seek to next chunk (even chunk sizes must be padded) */ if (i & 0x01) - { i++; - } - - buf += i + 8; - read_bytes -= i + 8; + + if(lseek(fd, i, SEEK_CUR) < 0) + return false; } - if ((numbytes == 0) || (channels == 0)) + if ((numbytes == 0) || (channels == 0)) { return false; } - - if (totalsamples == 0) + + if (totalsamples == 0) { /* for PCM only */ - totalsamples = numbytes + totalsamples = numbytes / ((((bitspersample - 1) / 8) + 1) * channels); } @@ -906,7 +919,6 @@ static bool get_wave_metadata(int fd, struct mp3entry* id3) return true; } - static bool get_m4a_metadata(int fd, struct mp3entry* id3) { unsigned char* buf; -- cgit v1.2.3