From 3833717c15ef246849c4e2bd22c2ed7865da84fd Mon Sep 17 00:00:00 2001 From: mt Date: Tue, 16 Feb 2010 03:34:39 +0000 Subject: [PATCH] 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 --- apps/codecs/atrac3_oma.c | 1 + apps/filetypes.c | 1 + apps/metadata.c | 4 ++-- apps/metadata/wave.c | 47 +++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/apps/codecs/atrac3_oma.c b/apps/codecs/atrac3_oma.c index 55299007d..df3499913 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 3feb0f5ab..e74edff5c 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 619a06e72..ce3a4ec22 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 cf676f89b..acef32dd3 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; } -- 2.11.4.GIT