1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Mohamed Tarek 2010-02-16 03:34:39 +00:00
parent fd5f8f9873
commit 82f05895af
4 changed files with 47 additions and 6 deletions

View file

@ -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 */

View file

@ -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 },

View file

@ -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" ),

View file

@ -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;
}