summaryrefslogtreecommitdiff
path: root/apps/metadata
diff options
context:
space:
mode:
authorYoshihisa Uchida <uchida@rockbox.org>2010-02-20 02:04:56 +0000
committerYoshihisa Uchida <uchida@rockbox.org>2010-02-20 02:04:56 +0000
commit3716abba9274f544dd31cdf4e6c83a845bf2a801 (patch)
tree07bca7cdd3e40bb176e938fcb5ea8eb2f7c3e9cb /apps/metadata
parent93caf52db5e0afe826278c148936bdfa563724f1 (diff)
downloadrockbox-3716abba9274f544dd31cdf4e6c83a845bf2a801.zip
rockbox-3716abba9274f544dd31cdf4e6c83a845bf2a801.tar.gz
rockbox-3716abba9274f544dd31cdf4e6c83a845bf2a801.tar.bz2
rockbox-3716abba9274f544dd31cdf4e6c83a845bf2a801.tar.xz
commit FS#10424 and FS#10425
- wav(RIFF) supports Microsoft ADPCM, Dialogic OKI ADPCM, YAMAHA ADPCM, Adobe SWF ADPCM. - AIFF supports QuickTime IMA ADPCM. - DVI ADPCM(IMA ADPCM) reworks. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24782 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/metadata')
-rw-r--r--apps/metadata/aiff.c23
-rw-r--r--apps/metadata/wave.c138
2 files changed, 132 insertions, 29 deletions
diff --git a/apps/metadata/aiff.c b/apps/metadata/aiff.c
index 67fb43b..aba327f 100644
--- a/apps/metadata/aiff.c
+++ b/apps/metadata/aiff.c
@@ -29,6 +29,9 @@
#include "metadata_common.h"
#include "metadata_parsers.h"
+/* compressionType: AIFC QuickTime IMA ADPCM */
+#define AIFC_FORMAT_QT_IMA_ADPCM "ima4"
+
bool get_aiff_metadata(int fd, struct mp3entry* id3)
{
/* Use the trackname part of the id3 structure as a temporary buffer */
@@ -40,6 +43,7 @@ bool get_aiff_metadata(int fd, struct mp3entry* id3)
unsigned long numbytes = 0;
int read_bytes;
int i;
+ bool is_aifc = false;
if ((lseek(fd, 0, SEEK_SET) < 0)
|| ((read_bytes = read(fd, buf, sizeof(id3->path))) < 54))
@@ -47,10 +51,15 @@ bool get_aiff_metadata(int fd, struct mp3entry* id3)
return false;
}
- if ((memcmp(buf, "FORM",4) != 0)
- || ((memcmp(&buf[8], "AIFF", 4) !=0) && (memcmp(&buf[8], "AIFC", 4) !=0)))
- {
+ if (memcmp(buf, "FORM",4) != 0)
return false;
+
+ if (memcmp(&buf[8], "AIFF", 4) != 0)
+ {
+ if (memcmp(&buf[8], "AIFC", 4) != 0)
+ return false;
+
+ is_aifc = true;
}
buf += 12;
@@ -75,7 +84,13 @@ bool get_aiff_metadata(int fd, struct mp3entry* id3)
/* save format infos */
id3->bitrate = (sampleSize * numChannels * sampleRate) / 1000;
id3->frequency = sampleRate;
- id3->length = ((int64_t) numSampleFrames * 1000) / id3->frequency;
+ if (!is_aifc || memcmp(&buf[26], AIFC_FORMAT_QT_IMA_ADPCM, 4) != 0)
+ id3->length = ((int64_t) numSampleFrames * 1000) / id3->frequency;
+ else
+ {
+ /* QuickTime IMA ADPCM is 1block = 64 data for each channel */
+ id3->length = (int64_t)(numSampleFrames * 64000LL) / id3->frequency;
+ }
id3->vbr = false; /* AIFF files are CBR */
id3->filesize = filesize(fd);
diff --git a/apps/metadata/wave.c b/apps/metadata/wave.c
index acef32d..79bb817 100644
--- a/apps/metadata/wave.c
+++ b/apps/metadata/wave.c
@@ -28,6 +28,7 @@
#include "metadata.h"
#include "metadata_common.h"
#include "metadata_parsers.h"
+#include "logf.h"
# define AV_WL32(p, d) do { \
((uint8_t*)(p))[0] = (d); \
@@ -40,29 +41,101 @@
((uint8_t*)(p))[1] = (d)>>8; \
} while(0)
+enum
+{
+ WAVE_FORMAT_PCM = 0x0001, /* Microsoft PCM Format */
+ WAVE_FORMAT_ADPCM = 0x0002, /* Microsoft ADPCM Format */
+ WAVE_FORMAT_IEEE_FLOAT = 0x0003, /* IEEE Float */
+ WAVE_FORMAT_ALAW = 0x0006, /* Microsoft ALAW */
+ WAVE_FORMAT_MULAW = 0x0007, /* Microsoft MULAW */
+ WAVE_FORMAT_DVI_ADPCM = 0x0011, /* Intel's DVI ADPCM */
+ WAVE_FORMAT_DIALOGIC_OKI_ADPCM = 0x0017, /* Dialogic OKI ADPCM */
+ WAVE_FORMAT_YAMAHA_ADPCM = 0x0020, /* Yamaha ADPCM */
+ WAVE_FORMAT_XBOX_ADPCM = 0x0069, /* XBOX ADPCM */
+ IBM_FORMAT_MULAW = 0x0101, /* same as WAVE_FORMAT_MULAW */
+ IBM_FORMAT_ALAW = 0x0102, /* same as WAVE_FORMAT_ALAW */
+ WAVE_FORMAT_ATRAC3 = 0x0270, /* Atrac3 stream */
+ WAVE_FORMAT_SWF_ADPCM = 0x5346, /* Adobe SWF ADPCM */
+};
+
+struct wave_fmt {
+ unsigned int formattag;
+ unsigned long channels;
+ unsigned int blockalign;
+ unsigned long bitspersample;
+ unsigned int samplesperblock;
+ unsigned long numbytes;
+};
+
+static unsigned long get_totalsamples(struct wave_fmt *fmt, struct mp3entry* id3)
+{
+ unsigned long totalsamples = 0;
+
+ switch (fmt->formattag)
+ {
+ case WAVE_FORMAT_PCM:
+ case WAVE_FORMAT_IEEE_FLOAT:
+ case WAVE_FORMAT_ALAW:
+ case WAVE_FORMAT_MULAW:
+ case IBM_FORMAT_ALAW:
+ case IBM_FORMAT_MULAW:
+ totalsamples =
+ fmt->numbytes / ((((fmt->bitspersample - 1) / 8) + 1) * fmt->channels);
+ break;
+ case WAVE_FORMAT_ADPCM:
+ case WAVE_FORMAT_DVI_ADPCM:
+ case WAVE_FORMAT_XBOX_ADPCM:
+ totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock;
+ break;
+ case WAVE_FORMAT_YAMAHA_ADPCM:
+ if (fmt->samplesperblock == 0)
+ {
+ if (fmt->blockalign == ((id3->frequency / 60) + 4) * fmt->channels)
+ fmt->samplesperblock = id3->frequency / 30;
+ else
+ fmt->samplesperblock = fmt->blockalign * 2 / fmt->channels;
+ }
+ totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock;
+ break;
+ case WAVE_FORMAT_DIALOGIC_OKI_ADPCM:
+ totalsamples = 2 * fmt->numbytes;
+ break;
+ case WAVE_FORMAT_SWF_ADPCM:
+ if (fmt->samplesperblock == 0)
+ fmt->samplesperblock = (((fmt->blockalign << 3) - 2) / fmt->channels - 22)
+ / fmt->bitspersample;
+
+ totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock;
+ break;
+ default:
+ totalsamples = 0;
+ break;
+ }
+ return totalsamples;
+}
+
bool get_wave_metadata(int fd, struct mp3entry* id3)
{
/* Use the trackname part of the id3 structure as a temporary buffer */
unsigned char* buf = (unsigned char *)id3->path;
+ struct wave_fmt fmt;
unsigned long totalsamples = 0;
- unsigned long channels = 0;
- unsigned long bitspersample = 0;
- unsigned long numbytes = 0;
unsigned long offset = 0;
int read_bytes;
int i;
+ memset(&fmt, 0, sizeof(struct wave_fmt));
+
/* get RIFF chunk header */
- if ((lseek(fd, 0, SEEK_SET) < 0)
- || ((read_bytes = read(fd, buf, 12)) < 12))
+ if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, buf, 12) < 12))
{
return false;
}
offset += 12;
- if ((memcmp(buf, "RIFF",4) != 0)
- || (memcmp(&buf[8], "WAVE", 4) !=0 ))
+ if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0))
{
+ DEBUGF("metadata error: missing riff header.\n");
return false;
}
@@ -70,7 +143,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
while (true)
{
/* get chunk header */
- if ((read_bytes = read(fd, buf, 8)) < 8)
+ if (read(fd, buf, 8) < 8)
return false;
offset += 8;
@@ -80,26 +153,41 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
if (memcmp(buf, "fmt ", 4) == 0)
{
/* get rest of chunk */
- if ((read_bytes = read(fd, buf, 16)) < 16)
+ if (i < 16)
return false;
- offset += 16;
- i -= 16;
+ read_bytes = 16;
+ if (i > 19)
+ read_bytes = 20;
- /* skipping wFormatTag */
+ if (read(fd, buf, read_bytes) != read_bytes)
+ return false;
+
+ offset += read_bytes;
+ i -= read_bytes;
+
+ /* wFormatTag */
+ fmt.formattag = buf[0] | (buf[1] << 8);
/* wChannels */
- channels = buf[2] | (buf[3] << 8);
+ fmt.channels = buf[2] | (buf[3] << 8);
/* dwSamplesPerSec */
id3->frequency = get_long_le(&buf[4]);
/* dwAvgBytesPerSec */
id3->bitrate = (get_long_le(&buf[8]) * 8) / 1000;
/* wBlockAlign */
- id3->bytesperframe = buf[12] | (buf[13] << 8);
+ fmt.blockalign = buf[12] | (buf[13] << 8);
+ id3->bytesperframe = fmt.blockalign;
/* wBitsPerSample */
- bitspersample = buf[14] | (buf[15] << 8);
+ fmt.bitspersample = buf[14] | (buf[15] << 8);
+ if (read_bytes > 19)
+ {
+ /* wSamplesPerBlock */
+ fmt.samplesperblock = buf[18] | (buf[19] << 8);
+ }
+
/* Check for ATRAC3 stream */
- if((buf[0] | (buf[1] << 8)) == 0x0270)
- {
+ if (fmt.formattag == WAVE_FORMAT_ATRAC3)
+ {
int jsflag = 0;
if(id3->bitrate == 66 || id3->bitrate == 94)
jsflag = 1;
@@ -107,7 +195,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
id3->extradata_size = 14;
id3->channels = 2;
id3->codectype = AFMT_OMA_ATRAC3;
- /* Store the extradata for the codec */
+ /* Store the extradata for the codec */
AV_WL16(&id3->id3v2buf[0], 1); // always 1
AV_WL32(&id3->id3v2buf[2], id3->frequency); // samples rate
AV_WL16(&id3->id3v2buf[6], jsflag); // coding mode
@@ -118,8 +206,9 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
}
else if (memcmp(buf, "data", 4) == 0)
{
- numbytes = i;
- id3->first_frame_offset = offset;
+ fmt.numbytes = i;
+ if (fmt.formattag == WAVE_FORMAT_ATRAC3)
+ id3->first_frame_offset = offset;
break;
}
else if (memcmp(buf, "fact", 4) == 0)
@@ -128,7 +217,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
if (i >= 4)
{
/* get rest of chunk */
- if ((read_bytes = read(fd, buf, 4)) < 4)
+ if (read(fd, buf, 4) < 4)
return false;
offset += 4;
i -= 4;
@@ -145,16 +234,15 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
offset += i;
}
- if ((numbytes == 0) || (channels == 0))
+ if ((fmt.numbytes == 0) || (fmt.channels == 0) || (fmt.blockalign == 0))
{
+ DEBUGF("metadata error: numbytes, channels, or blockalign is 0.\n");
return false;
}
if (totalsamples == 0)
{
- /* for PCM only */
- totalsamples = numbytes
- / ((((bitspersample - 1) / 8) + 1) * channels);
+ totalsamples = get_totalsamples(&fmt, id3);
}
id3->vbr = false; /* All WAV files are CBR */