summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorRani Hod <raenye@gmail.com>2006-09-25 16:13:05 +0000
committerRani Hod <raenye@gmail.com>2006-09-25 16:13:05 +0000
commita875ed5d57ce33663fbf49331d2992d2e4f296d5 (patch)
tree74707f68109f5d7ed42fc3dc9a1f3fee4ffd0d47 /apps
parentb7c87ac5a30e2b9d064ded1ed6dedc1b56d23a0d (diff)
downloadrockbox-a875ed5d57ce33663fbf49331d2992d2e4f296d5.zip
rockbox-a875ed5d57ce33663fbf49331d2992d2e4f296d5.tar.gz
rockbox-a875ed5d57ce33663fbf49331d2992d2e4f296d5.tar.bz2
rockbox-a875ed5d57ce33663fbf49331d2992d2e4f296d5.tar.xz
Accepted FS#6023 - ADX codec (some kind of ADPCM).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11046 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/codecs/Makefile1
-rw-r--r--apps/codecs/SOURCES1
-rw-r--r--apps/metadata.c121
-rw-r--r--apps/tree.c1
4 files changed, 124 insertions, 0 deletions
diff --git a/apps/codecs/Makefile b/apps/codecs/Makefile
index fb1228d..62312e2 100644
--- a/apps/codecs/Makefile
+++ b/apps/codecs/Makefile
@@ -50,6 +50,7 @@ $(BUILDDIR)/%.a : % $(CODECDEPS)
$(OBJDIR)/wav.elf : $(OBJDIR)/wav.o
$(OBJDIR)/sid.elf : $(OBJDIR)/sid.o
+$(OBJDIR)/adx.elf : $(OBJDIR)/adx.o
$(OBJDIR)/aiff.elf : $(OBJDIR)/aiff.o
$(OBJDIR)/mpa.elf : $(OBJDIR)/mpa.o $(BUILDDIR)/libmad.a
$(OBJDIR)/a52.elf : $(OBJDIR)/a52.o $(BUILDDIR)/liba52.a
diff --git a/apps/codecs/SOURCES b/apps/codecs/SOURCES
index 3bd09b4..feadcde 100644
--- a/apps/codecs/SOURCES
+++ b/apps/codecs/SOURCES
@@ -14,6 +14,7 @@ aac.c
shorten.c
aiff.c
sid.c
+adx.c
#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
/* encoders */
mp3_enc.c
diff --git a/apps/metadata.c b/apps/metadata.c
index 6761081..1b2dde3 100644
--- a/apps/metadata.c
+++ b/apps/metadata.c
@@ -82,6 +82,7 @@ static const struct format_list formats[] =
{ AFMT_AIFF, "aif" },
{ AFMT_AIFF, "aiff" },
{ AFMT_SID, "sid" },
+ { AFMT_ADX, "adx" },
#endif
};
@@ -1333,6 +1334,118 @@ static bool get_sid_metadata(int fd, struct mp3entry* id3)
return true;
}
+static bool get_adx_metadata(int fd, struct mp3entry* id3)
+{
+ /* Use the trackname part of the id3 structure as a temporary buffer */
+ unsigned char * buf = id3->path;
+ int chanstart, channels, read_bytes;
+ int looping = 0, start_adr = 0, end_adr = 0;
+
+ /* try to get the basic header */
+ if ((lseek(fd, 0, SEEK_SET) < 0)
+ || ((read_bytes = read(fd, buf, 0x38)) < 0x38))
+ {
+ DEBUGF("lseek or read failed\n");
+ return false;
+ }
+
+ /* ADX starts with 0x80 */
+ if (buf[0] != 0x80) {
+ DEBUGF("get_adx_metadata: wrong first byte %c\n",buf[0]);
+ return false;
+ }
+
+ /* check for a reasonable offset */
+ chanstart = ((buf[2] << 8) | buf[3]) + 4;
+ if (chanstart > 4096) {
+ DEBUGF("get_adx_metadata: bad chanstart %i\n", chanstart);
+ return false;
+ }
+
+ /* check for a workable number of channels */
+ channels = buf[7];
+ if (channels != 1 && channels != 2) {
+ DEBUGF("get_adx_metadata: bad channel count %i\n",channels);
+ return false;
+ }
+
+ id3->frequency = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11];
+ /* 32 samples per 18 bytes */
+ id3->bitrate = id3->frequency * channels * 18 * 8 / 32 / 1000;
+ id3->length = ((unsigned long)
+ (buf[12] << 24) | (buf[13] << 16) | (buf[14] << 8) | buf[15]) /
+ id3->frequency * 1000;
+ id3->vbr = false;
+ id3->filesize = filesize(fd);
+
+ /* get loop info */
+ if (!memcmp(buf+0x10,"\x01\xF4\x03\x00",4)) {
+ /* Soul Calibur 2 style (type 03) */
+ DEBUGF("get_adx_metadata: type 03 found\n");
+ /* check if header is too small for loop data */
+ if (chanstart-6 < 0x2c) looping=0;
+ else {
+ looping = (buf[0x18]) ||
+ (buf[0x19]) ||
+ (buf[0x1a]) ||
+ (buf[0x1b]);
+ end_adr = (buf[0x28]<<24) |
+ (buf[0x29]<<16) |
+ (buf[0x2a]<<8) |
+ (buf[0x2b]);
+
+ start_adr = (
+ (buf[0x1c]<<24) |
+ (buf[0x1d]<<16) |
+ (buf[0x1e]<<8) |
+ (buf[0x1f])
+ )/32*channels*18+chanstart;
+ }
+ } else if (!memcmp(buf+0x10,"\x01\xF4\x04\x00",4)) {
+ /* Standard (type 04) */
+ DEBUGF("get_adx_metadata: type 04 found\n");
+ /* check if header is too small for loop data */
+ if (chanstart-6 < 0x38) looping=0;
+ else {
+ looping = (buf[0x24]) ||
+ (buf[0x25]) ||
+ (buf[0x26]) ||
+ (buf[0x27]);
+ end_adr = (buf[0x34]<<24) |
+ (buf[0x35]<<16) |
+ (buf[0x36]<<8) |
+ buf[0x37];
+ start_adr = (
+ (buf[0x28]<<24) |
+ (buf[0x29]<<16) |
+ (buf[0x2a]<<8) |
+ (buf[0x2b])
+ )/32*channels*18+chanstart;
+ }
+ } else {
+ DEBUGF("get_adx_metadata: error, couldn't determine ADX type\n");
+ return false;
+ }
+
+ if (looping) {
+ /* 2 loops, 10 second fade */
+ id3->length = (start_adr-chanstart + 2*(end_adr-start_adr))
+ *8 / id3->bitrate + 10000;
+ }
+
+ /* try to get the channel header */
+ if ((lseek(fd, chanstart-6, SEEK_SET) < 0)
+ || ((read_bytes = read(fd, buf, 6)) < 6))
+ {
+ return false;
+ }
+
+ /* check channel header */
+ if (memcmp(buf, "(c)CRI", 6) != 0) return false;
+
+ return true;
+}
+
#endif /* CONFIG_CODEC == SWCODEC */
static bool get_aiff_metadata(int fd, struct mp3entry* id3)
@@ -1629,6 +1742,14 @@ bool get_metadata(struct track_info* track, int fd, const char* trackname,
}
break;
+ case AFMT_ADX:
+ if (!get_adx_metadata(fd, &(track->id3)))
+ {
+ DEBUGF("get_adx_metadata error\n");
+ return false;
+ }
+
+ break;
#endif /* CONFIG_CODEC == SWCODEC */
case AFMT_AIFF:
diff --git a/apps/tree.c b/apps/tree.c
index 8e155a9..3ee3061 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -104,6 +104,7 @@ const struct filetype filetypes[] = {
{ "aif", TREE_ATTR_MPA, Icon_Audio, VOICE_EXT_MPA },
{ "aiff",TREE_ATTR_MPA, Icon_Audio, VOICE_EXT_MPA },
{ "sid", TREE_ATTR_MPA, Icon_Audio, VOICE_EXT_MPA },
+ { "adx", TREE_ATTR_MPA, Icon_Audio, VOICE_EXT_MPA },
#endif
{ "m3u", TREE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },
{ "m3u8", TREE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },