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:
parent
fd5f8f9873
commit
82f05895af
4 changed files with 47 additions and 6 deletions
|
|
@ -75,6 +75,7 @@ next_track:
|
||||||
frame_counter = 0;
|
frame_counter = 0;
|
||||||
|
|
||||||
ci->set_elapsed(0);
|
ci->set_elapsed(0);
|
||||||
|
ci->seek_buffer(0);
|
||||||
ci->advance_buffer(ci->id3->first_frame_offset);
|
ci->advance_buffer(ci->id3->first_frame_offset);
|
||||||
|
|
||||||
/* The main decoder loop */
|
/* The main decoder loop */
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,7 @@ static const struct filetype inbuilt_filetypes[] = {
|
||||||
{ "tm2", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
{ "tm2", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
||||||
{ "oma", 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 },
|
{ "aa3", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
||||||
|
{ "at3", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
|
||||||
#endif
|
#endif
|
||||||
{ "m3u", FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },
|
{ "m3u", FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },
|
||||||
{ "m3u8",FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },
|
{ "m3u8",FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },
|
||||||
|
|
|
||||||
|
|
@ -60,9 +60,9 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
|
||||||
/* Audio Interchange File Format */
|
/* Audio Interchange File Format */
|
||||||
[AFMT_AIFF] =
|
[AFMT_AIFF] =
|
||||||
AFMT_ENTRY("AIFF", "aiff", "aiff_enc", "aiff\0aif\0"),
|
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_PCM_WAV] =
|
||||||
AFMT_ENTRY("WAV", "wav", "wav_enc", "wav\0" ),
|
AFMT_ENTRY("WAV", "wav", "wav_enc", "wav\0at3\0" ),
|
||||||
/* Ogg Vorbis */
|
/* Ogg Vorbis */
|
||||||
[AFMT_OGG_VORBIS] =
|
[AFMT_OGG_VORBIS] =
|
||||||
AFMT_ENTRY("Ogg", "vorbis", NULL, "ogg\0oga\0" ),
|
AFMT_ENTRY("Ogg", "vorbis", NULL, "ogg\0oga\0" ),
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,17 @@
|
||||||
#include "metadata_common.h"
|
#include "metadata_common.h"
|
||||||
#include "metadata_parsers.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)
|
bool get_wave_metadata(int fd, struct mp3entry* id3)
|
||||||
{
|
{
|
||||||
/* Use the trackname part of the id3 structure as a temporary buffer */
|
/* 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 channels = 0;
|
||||||
unsigned long bitspersample = 0;
|
unsigned long bitspersample = 0;
|
||||||
unsigned long numbytes = 0;
|
unsigned long numbytes = 0;
|
||||||
|
unsigned long offset = 0;
|
||||||
int read_bytes;
|
int read_bytes;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
@ -46,6 +58,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
offset += 12;
|
||||||
|
|
||||||
if ((memcmp(buf, "RIFF",4) != 0)
|
if ((memcmp(buf, "RIFF",4) != 0)
|
||||||
|| (memcmp(&buf[8], "WAVE", 4) !=0 ))
|
|| (memcmp(&buf[8], "WAVE", 4) !=0 ))
|
||||||
|
|
@ -59,6 +72,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
|
||||||
/* get chunk header */
|
/* get chunk header */
|
||||||
if ((read_bytes = read(fd, buf, 8)) < 8)
|
if ((read_bytes = read(fd, buf, 8)) < 8)
|
||||||
return false;
|
return false;
|
||||||
|
offset += 8;
|
||||||
|
|
||||||
/* chunkSize */
|
/* chunkSize */
|
||||||
i = get_long_le(&buf[4]);
|
i = get_long_le(&buf[4]);
|
||||||
|
|
@ -68,9 +82,10 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
|
||||||
/* get rest of chunk */
|
/* get rest of chunk */
|
||||||
if ((read_bytes = read(fd, buf, 16)) < 16)
|
if ((read_bytes = read(fd, buf, 16)) < 16)
|
||||||
return false;
|
return false;
|
||||||
|
offset += 16;
|
||||||
i -= 16;
|
i -= 16;
|
||||||
|
|
||||||
|
|
||||||
/* skipping wFormatTag */
|
/* skipping wFormatTag */
|
||||||
/* wChannels */
|
/* wChannels */
|
||||||
channels = buf[2] | (buf[3] << 8);
|
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]);
|
id3->frequency = get_long_le(&buf[4]);
|
||||||
/* dwAvgBytesPerSec */
|
/* dwAvgBytesPerSec */
|
||||||
id3->bitrate = (get_long_le(&buf[8]) * 8) / 1000;
|
id3->bitrate = (get_long_le(&buf[8]) * 8) / 1000;
|
||||||
/* skipping wBlockAlign */
|
/* wBlockAlign */
|
||||||
|
id3->bytesperframe = buf[12] | (buf[13] << 8);
|
||||||
/* wBitsPerSample */
|
/* wBitsPerSample */
|
||||||
bitspersample = buf[14] | (buf[15] << 8);
|
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)
|
else if (memcmp(buf, "data", 4) == 0)
|
||||||
{
|
{
|
||||||
numbytes = i;
|
numbytes = i;
|
||||||
|
id3->first_frame_offset = offset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (memcmp(buf, "fact", 4) == 0)
|
else if (memcmp(buf, "fact", 4) == 0)
|
||||||
|
|
@ -95,7 +130,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
|
||||||
/* get rest of chunk */
|
/* get rest of chunk */
|
||||||
if ((read_bytes = read(fd, buf, 4)) < 4)
|
if ((read_bytes = read(fd, buf, 4)) < 4)
|
||||||
return false;
|
return false;
|
||||||
|
offset += 4;
|
||||||
i -= 4;
|
i -= 4;
|
||||||
totalsamples = get_long_le(buf);
|
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)
|
if(lseek(fd, i, SEEK_CUR) < 0)
|
||||||
return false;
|
return false;
|
||||||
|
offset += i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((numbytes == 0) || (channels == 0))
|
if ((numbytes == 0) || (channels == 0))
|
||||||
|
|
@ -125,7 +161,10 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
|
||||||
id3->filesize = filesize(fd);
|
id3->filesize = filesize(fd);
|
||||||
|
|
||||||
/* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */
|
/* 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue