summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2007-06-06 17:46:49 +0000
committerDave Chapman <dave@dchapman.com>2007-06-06 17:46:49 +0000
commitc995ae8026b4e22159695a7b8c856bc0d8d5328b (patch)
tree9fec68ba229fbcd9a115de4d7a87a4421e621797
parent6c31a9a9d3611edb811964a80e15449a54634c83 (diff)
downloadrockbox-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.c90
-rw-r--r--apps/metadata.c45
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)