diff options
| author | Dave Chapman <dave@dchapman.com> | 2007-06-06 17:46:49 +0000 |
|---|---|---|
| committer | Dave Chapman <dave@dchapman.com> | 2007-06-06 17:46:49 +0000 |
| commit | c995ae8026b4e22159695a7b8c856bc0d8d5328b (patch) | |
| tree | 9fec68ba229fbcd9a115de4d7a87a4421e621797 | |
| parent | 6c31a9a9d3611edb811964a80e15449a54634c83 (diff) | |
| download | rockbox-c995ae8026b4e22159695a7b8c856bc0d8d5328b.zip rockbox-c995ae8026b4e22159695a7b8c856bc0d8d5328b.tar.gz rockbox-c995ae8026b4e22159695a7b8c856bc0d8d5328b.tar.bz2 rockbox-c995ae8026b4e22159695a7b8c856bc0d8d5328b.tar.xz | |
Make v3.97 APE files work in Rockbox
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13571 a1c6a512-1295-4272-9138-f99709370657
| -rw-r--r-- | apps/codecs/demac/libdemac/parser.c | 90 | ||||
| -rw-r--r-- | apps/metadata.c | 45 |
2 files changed, 95 insertions, 40 deletions
diff --git a/apps/codecs/demac/libdemac/parser.c b/apps/codecs/demac/libdemac/parser.c index bcb542d..4e90730 100644 --- a/apps/codecs/demac/libdemac/parser.c +++ b/apps/codecs/demac/libdemac/parser.c @@ -2,7 +2,7 @@ libdemac - A Monkey's Audio decoder -$Id:$ +$Id$ Copyright (C) Dave Chapman 2007 @@ -70,39 +70,71 @@ int ape_parseheaderbuf(unsigned char* buf, struct ape_ctx_t* ape_ctx) if (ape_ctx->fileversion >= 3980) { - ape_ctx->padding1 = get_int16(buf + 6); - ape_ctx->descriptorlength = get_uint32(buf + 8); - ape_ctx->headerlength = get_uint32(buf + 12); - ape_ctx->seektablelength = get_uint32(buf + 16); - ape_ctx->wavheaderlength = get_uint32(buf + 20); - ape_ctx->audiodatalength = get_uint32(buf + 24); - ape_ctx->audiodatalength_high = get_uint32(buf + 28); - ape_ctx->wavtaillength = get_uint32(buf + 32); - memcpy(ape_ctx->md5, buf + 36, 16); - - header = buf + ape_ctx->descriptorlength; - - /* Read header data */ - ape_ctx->compressiontype = get_uint16(header + 0); - ape_ctx->formatflags = get_uint16(header + 2); - ape_ctx->blocksperframe = get_uint32(header + 4); - ape_ctx->finalframeblocks = get_uint32(header + 8); - ape_ctx->totalframes = get_uint32(header + 12); - ape_ctx->bps = get_uint16(header + 16); - ape_ctx->channels = get_uint16(header + 18); - ape_ctx->samplerate = get_uint32(header + 20); + ape_ctx->padding1 = get_int16(buf + 6); + ape_ctx->descriptorlength = get_uint32(buf + 8); + ape_ctx->headerlength = get_uint32(buf + 12); + ape_ctx->seektablelength = get_uint32(buf + 16); + ape_ctx->wavheaderlength = get_uint32(buf + 20); + ape_ctx->audiodatalength = get_uint32(buf + 24); + ape_ctx->audiodatalength_high = get_uint32(buf + 28); + ape_ctx->wavtaillength = get_uint32(buf + 32); + memcpy(ape_ctx->md5, buf + 36, 16); + + header = buf + ape_ctx->descriptorlength; - ape_ctx->firstframe = ape_ctx->junklength + ape_ctx->descriptorlength + - ape_ctx->headerlength + ape_ctx->seektablelength + - ape_ctx->wavheaderlength; + /* Read header data */ + ape_ctx->compressiontype = get_uint16(header + 0); + ape_ctx->formatflags = get_uint16(header + 2); + ape_ctx->blocksperframe = get_uint32(header + 4); + ape_ctx->finalframeblocks = get_uint32(header + 8); + ape_ctx->totalframes = get_uint32(header + 12); + ape_ctx->bps = get_uint16(header + 16); + ape_ctx->channels = get_uint16(header + 18); + ape_ctx->samplerate = get_uint32(header + 20); + + ape_ctx->firstframe = ape_ctx->junklength + ape_ctx->descriptorlength + + ape_ctx->headerlength + ape_ctx->seektablelength + + ape_ctx->wavheaderlength; } else { + ape_ctx->headerlength = 32; ape_ctx->compressiontype = get_uint16(buf + 6); ape_ctx->formatflags = get_uint16(buf + 8); ape_ctx->channels = get_uint16(buf + 10); - ape_ctx->samplerate = get_uint32(buf + 14); - ape_ctx->wavheaderlength = get_uint32(buf + 18); - ape_ctx->totalframes = get_uint32(buf + 26); - ape_ctx->finalframeblocks = get_uint32(buf + 30); + ape_ctx->samplerate = get_uint32(buf + 12); + ape_ctx->wavheaderlength = get_uint32(buf + 16); + ape_ctx->totalframes = get_uint32(buf + 24); + ape_ctx->finalframeblocks = get_uint32(buf + 28); + + if (ape_ctx->formatflags & MAC_FORMAT_FLAG_HAS_PEAK_LEVEL) + { + ape_ctx->headerlength += 4; + } + + if (ape_ctx->formatflags & MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS) + { + ape_ctx->seektablelength = get_uint32(buf + ape_ctx->headerlength); + ape_ctx->seektablelength *= sizeof(int32_t); + ape_ctx->headerlength += 4; + } else { + ape_ctx->seektablelength = ape_ctx->totalframes * sizeof(int32_t); + } + + if (ape_ctx->formatflags & MAC_FORMAT_FLAG_8_BIT) + ape_ctx->bps = 8; + else if (ape_ctx->formatflags & MAC_FORMAT_FLAG_24_BIT) + ape_ctx->bps = 24; + else + ape_ctx->bps = 16; + + if (ape_ctx->fileversion >= 3950) + ape_ctx->blocksperframe = 73728 * 4; + else if ((ape_ctx->fileversion >= 3900) || (ape_ctx->fileversion >= 3800 && ape_ctx->compressiontype >= 4000)) + ape_ctx->blocksperframe = 73728; + else + ape_ctx->blocksperframe = 9216; + + ape_ctx->firstframe = ape_ctx->junklength + ape_ctx->headerlength + + ape_ctx->seektablelength + ape_ctx->wavheaderlength; } ape_ctx->totalsamples = ape_ctx->finalframeblocks; diff --git a/apps/metadata.c b/apps/metadata.c index 60191b1..594226b 100644 --- a/apps/metadata.c +++ b/apps/metadata.c @@ -183,6 +183,14 @@ static unsigned long get_long_le(void* buf) return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); } +/* Read an unaligned 16-bit little endian short from buffer. */ +static unsigned short get_short_le(void* buf) +{ + unsigned char* p = (unsigned char*) buf; + + return p[0] | (p[1] << 8); +} + /* Read an unaligned 32-bit big endian long from buffer. */ static unsigned long get_long_be(void* buf) { @@ -991,6 +999,7 @@ static bool get_monkeys_metadata(int fd, struct mp3entry* id3) uint32_t descriptorlength; uint32_t totalsamples; uint32_t blocksperframe, finalframeblocks, totalframes; + int fileversion; lseek(fd, 0, SEEK_SET); @@ -1006,22 +1015,36 @@ static bool get_monkeys_metadata(int fd, struct mp3entry* id3) read(fd, buf + 4, MAX_PATH - 4); - descriptorlength = buf[8] | (buf[9] << 8) | - (buf[10] << 16) | (buf[11] << 24); + fileversion = get_short_le(buf+4); + if (fileversion < 3970) + { + /* Not supported */ + return false; + } - header = buf + descriptorlength; + if (fileversion >= 3980) + { + descriptorlength = get_long_le(buf+8); + + header = buf + descriptorlength; - blocksperframe = header[4] | (header[5] << 8) | - (header[6] << 16) | (header[7] << 24); - finalframeblocks = header[8] | (header[9] << 8) | - (header[10] << 16) | (header[11] << 24); - totalframes = header[12] | (header[13] << 8) | - (header[14] << 16) | (header[15] << 24); + blocksperframe = get_long_le(header+4); + finalframeblocks = get_long_le(header+8); + totalframes = get_long_le(header+12); + id3->frequency = get_long_le(header+20); + } + else + { + /* v3.95 and later files all have a fixed framesize */ + blocksperframe = 73728 * 4; + + finalframeblocks = get_long_le(buf+30); + totalframes = get_long_le(buf+26); + id3->frequency = get_long_le(buf+14); + } id3->vbr = true; /* All FLAC files are VBR */ id3->filesize = filesize(fd); - id3->frequency = header[20] | (header[21] << 8) | - (header[22] << 16) | (header[23] << 24); totalsamples = finalframeblocks; if (totalframes > 1) |