summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohamed Tarek <mt@rockbox.org>2010-02-16 03:34:39 +0000
committerMohamed Tarek <mt@rockbox.org>2010-02-16 03:34:39 +0000
commit82f05895af2e361b983aa782e4294a641b287429 (patch)
treee2c6dd216900418ca41d3d4a6c19e460a666543e
parentfd5f8f987396a63ff75b5322e922a9dcfd2b229b (diff)
downloadrockbox-82f05895af2e361b983aa782e4294a641b287429.zip
rockbox-82f05895af2e361b983aa782e4294a641b287429.tar.gz
rockbox-82f05895af2e361b983aa782e4294a641b287429.tar.bz2
rockbox-82f05895af2e361b983aa782e4294a641b287429.tar.xz
Initial support for ATRAC3 streams in wav containers.
Current state : - Playback and seeking are possible. - We now support ATRAC3 in any of its possible containers (wav/at3, oma/aa3, and rm/ra). TODO : - Fix joint-stereo decoding for ATRAC3 - the decoder currently produces lots of glitches. - Rename atrac3_oma.c since it works for both oma and wav containers. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24689 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs/atrac3_oma.c1
-rw-r--r--apps/filetypes.c1
-rw-r--r--apps/metadata.c4
-rw-r--r--apps/metadata/wave.c47
4 files changed, 47 insertions, 6 deletions
diff --git a/apps/codecs/atrac3_oma.c b/apps/codecs/atrac3_oma.c
index 5529900..df34999 100644
--- a/apps/codecs/atrac3_oma.c
+++ b/apps/codecs/atrac3_oma.c
@@ -75,6 +75,7 @@ next_track:
frame_counter = 0;
ci->set_elapsed(0);
+ ci->seek_buffer(0);
ci->advance_buffer(ci->id3->first_frame_offset);
/* The main decoder loop */
diff --git a/apps/filetypes.c b/apps/filetypes.c
index 3feb0f5..e74edff 100644
--- a/apps/filetypes.c
+++ b/apps/filetypes.c
@@ -100,6 +100,7 @@ static const struct filetype inbuilt_filetypes[] = {
{ "tm2", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
{ "oma", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
{ "aa3", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
+ { "at3", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
#endif
{ "m3u", FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },
{ "m3u8",FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },
diff --git a/apps/metadata.c b/apps/metadata.c
index 619a06e..ce3a4ec 100644
--- a/apps/metadata.c
+++ b/apps/metadata.c
@@ -60,9 +60,9 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
/* Audio Interchange File Format */
[AFMT_AIFF] =
AFMT_ENTRY("AIFF", "aiff", "aiff_enc", "aiff\0aif\0"),
- /* Uncompressed PCM in a WAV file */
+ /* Uncompressed PCM in a WAV file OR ATRAC3 stream in WAV file (.at3) */
[AFMT_PCM_WAV] =
- AFMT_ENTRY("WAV", "wav", "wav_enc", "wav\0" ),
+ AFMT_ENTRY("WAV", "wav", "wav_enc", "wav\0at3\0" ),
/* Ogg Vorbis */
[AFMT_OGG_VORBIS] =
AFMT_ENTRY("Ogg", "vorbis", NULL, "ogg\0oga\0" ),
diff --git a/apps/metadata/wave.c b/apps/metadata/wave.c
index cf676f8..acef32d 100644
--- a/apps/metadata/wave.c
+++ b/apps/metadata/wave.c
@@ -29,6 +29,17 @@
#include "metadata_common.h"
#include "metadata_parsers.h"
+# define AV_WL32(p, d) do { \
+ ((uint8_t*)(p))[0] = (d); \
+ ((uint8_t*)(p))[1] = (d)>>8; \
+ ((uint8_t*)(p))[2] = (d)>>16; \
+ ((uint8_t*)(p))[3] = (d)>>24; \
+ } while(0)
+# define AV_WL16(p, d) do { \
+ ((uint8_t*)(p))[0] = (d); \
+ ((uint8_t*)(p))[1] = (d)>>8; \
+ } while(0)
+
bool get_wave_metadata(int fd, struct mp3entry* id3)
{
/* Use the trackname part of the id3 structure as a temporary buffer */
@@ -37,6 +48,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
unsigned long channels = 0;
unsigned long bitspersample = 0;
unsigned long numbytes = 0;
+ unsigned long offset = 0;
int read_bytes;
int i;
@@ -46,6 +58,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
{
return false;
}
+ offset += 12;
if ((memcmp(buf, "RIFF",4) != 0)
|| (memcmp(&buf[8], "WAVE", 4) !=0 ))
@@ -59,6 +72,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
/* get chunk header */
if ((read_bytes = read(fd, buf, 8)) < 8)
return false;
+ offset += 8;
/* chunkSize */
i = get_long_le(&buf[4]);
@@ -68,9 +82,10 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
/* get rest of chunk */
if ((read_bytes = read(fd, buf, 16)) < 16)
return false;
-
+ offset += 16;
i -= 16;
+
/* skipping wFormatTag */
/* wChannels */
channels = buf[2] | (buf[3] << 8);
@@ -78,13 +93,33 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
id3->frequency = get_long_le(&buf[4]);
/* dwAvgBytesPerSec */
id3->bitrate = (get_long_le(&buf[8]) * 8) / 1000;
- /* skipping wBlockAlign */
+ /* wBlockAlign */
+ id3->bytesperframe = buf[12] | (buf[13] << 8);
/* wBitsPerSample */
bitspersample = buf[14] | (buf[15] << 8);
+ /* Check for ATRAC3 stream */
+ if((buf[0] | (buf[1] << 8)) == 0x0270)
+ {
+ int jsflag = 0;
+ if(id3->bitrate == 66 || id3->bitrate == 94)
+ jsflag = 1;
+
+ id3->extradata_size = 14;
+ id3->channels = 2;
+ id3->codectype = AFMT_OMA_ATRAC3;
+ /* 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
+ AV_WL16(&id3->id3v2buf[8], jsflag); // coding mode
+ AV_WL16(&id3->id3v2buf[10], 1); // always 1
+ AV_WL16(&id3->id3v2buf[12], 0); // always 0
+ }
}
else if (memcmp(buf, "data", 4) == 0)
{
numbytes = i;
+ id3->first_frame_offset = offset;
break;
}
else if (memcmp(buf, "fact", 4) == 0)
@@ -95,7 +130,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
/* get rest of chunk */
if ((read_bytes = read(fd, buf, 4)) < 4)
return false;
-
+ offset += 4;
i -= 4;
totalsamples = get_long_le(buf);
}
@@ -107,6 +142,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
if(lseek(fd, i, SEEK_CUR) < 0)
return false;
+ offset += i;
}
if ((numbytes == 0) || (channels == 0))
@@ -125,7 +161,10 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
id3->filesize = filesize(fd);
/* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */
- id3->length = ((int64_t) totalsamples * 1000) / id3->frequency;
+ if(id3->codectype != AFMT_OMA_ATRAC3)
+ id3->length = ((int64_t) totalsamples * 1000) / id3->frequency;
+ else
+ id3->length = ((id3->filesize - id3->first_frame_offset) * 8) / id3->bitrate;
return true;
}