diff options
author | Mohamed Tarek <mt@rockbox.org> | 2010-02-16 03:34:39 +0000 |
---|---|---|
committer | Mohamed Tarek <mt@rockbox.org> | 2010-02-16 03:34:39 +0000 |
commit | 82f05895af2e361b983aa782e4294a641b287429 (patch) | |
tree | e2c6dd216900418ca41d3d4a6c19e460a666543e /apps | |
parent | fd5f8f987396a63ff75b5322e922a9dcfd2b229b (diff) | |
download | rockbox-82f05895af2e361b983aa782e4294a641b287429.tar.gz rockbox-82f05895af2e361b983aa782e4294a641b287429.zip |
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
Diffstat (limited to 'apps')
-rw-r--r-- | apps/codecs/atrac3_oma.c | 1 | ||||
-rw-r--r-- | apps/filetypes.c | 1 | ||||
-rw-r--r-- | apps/metadata.c | 4 | ||||
-rw-r--r-- | 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 55299007d7..df3499913c 100644 --- a/apps/codecs/atrac3_oma.c +++ b/apps/codecs/atrac3_oma.c | |||
@@ -75,6 +75,7 @@ next_track: | |||
75 | frame_counter = 0; | 75 | frame_counter = 0; |
76 | 76 | ||
77 | ci->set_elapsed(0); | 77 | ci->set_elapsed(0); |
78 | ci->seek_buffer(0); | ||
78 | ci->advance_buffer(ci->id3->first_frame_offset); | 79 | ci->advance_buffer(ci->id3->first_frame_offset); |
79 | 80 | ||
80 | /* The main decoder loop */ | 81 | /* The main decoder loop */ |
diff --git a/apps/filetypes.c b/apps/filetypes.c index 3feb0f5ab8..e74edff5c2 100644 --- a/apps/filetypes.c +++ b/apps/filetypes.c | |||
@@ -100,6 +100,7 @@ static const struct filetype inbuilt_filetypes[] = { | |||
100 | { "tm2", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, | 100 | { "tm2", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, |
101 | { "oma", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, | 101 | { "oma", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, |
102 | { "aa3", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, | 102 | { "aa3", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, |
103 | { "at3", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, | ||
103 | #endif | 104 | #endif |
104 | { "m3u", FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, | 105 | { "m3u", FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, |
105 | { "m3u8",FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, | 106 | { "m3u8",FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, |
diff --git a/apps/metadata.c b/apps/metadata.c index 619a06e72d..ce3a4ec22a 100644 --- a/apps/metadata.c +++ b/apps/metadata.c | |||
@@ -60,9 +60,9 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] = | |||
60 | /* Audio Interchange File Format */ | 60 | /* Audio Interchange File Format */ |
61 | [AFMT_AIFF] = | 61 | [AFMT_AIFF] = |
62 | AFMT_ENTRY("AIFF", "aiff", "aiff_enc", "aiff\0aif\0"), | 62 | AFMT_ENTRY("AIFF", "aiff", "aiff_enc", "aiff\0aif\0"), |
63 | /* Uncompressed PCM in a WAV file */ | 63 | /* Uncompressed PCM in a WAV file OR ATRAC3 stream in WAV file (.at3) */ |
64 | [AFMT_PCM_WAV] = | 64 | [AFMT_PCM_WAV] = |
65 | AFMT_ENTRY("WAV", "wav", "wav_enc", "wav\0" ), | 65 | AFMT_ENTRY("WAV", "wav", "wav_enc", "wav\0at3\0" ), |
66 | /* Ogg Vorbis */ | 66 | /* Ogg Vorbis */ |
67 | [AFMT_OGG_VORBIS] = | 67 | [AFMT_OGG_VORBIS] = |
68 | AFMT_ENTRY("Ogg", "vorbis", NULL, "ogg\0oga\0" ), | 68 | AFMT_ENTRY("Ogg", "vorbis", NULL, "ogg\0oga\0" ), |
diff --git a/apps/metadata/wave.c b/apps/metadata/wave.c index cf676f89b0..acef32dd38 100644 --- a/apps/metadata/wave.c +++ b/apps/metadata/wave.c | |||
@@ -29,6 +29,17 @@ | |||
29 | #include "metadata_common.h" | 29 | #include "metadata_common.h" |
30 | #include "metadata_parsers.h" | 30 | #include "metadata_parsers.h" |
31 | 31 | ||
32 | # define AV_WL32(p, d) do { \ | ||
33 | ((uint8_t*)(p))[0] = (d); \ | ||
34 | ((uint8_t*)(p))[1] = (d)>>8; \ | ||
35 | ((uint8_t*)(p))[2] = (d)>>16; \ | ||
36 | ((uint8_t*)(p))[3] = (d)>>24; \ | ||
37 | } while(0) | ||
38 | # define AV_WL16(p, d) do { \ | ||
39 | ((uint8_t*)(p))[0] = (d); \ | ||
40 | ((uint8_t*)(p))[1] = (d)>>8; \ | ||
41 | } while(0) | ||
42 | |||
32 | bool get_wave_metadata(int fd, struct mp3entry* id3) | 43 | bool get_wave_metadata(int fd, struct mp3entry* id3) |
33 | { | 44 | { |
34 | /* Use the trackname part of the id3 structure as a temporary buffer */ | 45 | /* 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) | |||
37 | unsigned long channels = 0; | 48 | unsigned long channels = 0; |
38 | unsigned long bitspersample = 0; | 49 | unsigned long bitspersample = 0; |
39 | unsigned long numbytes = 0; | 50 | unsigned long numbytes = 0; |
51 | unsigned long offset = 0; | ||
40 | int read_bytes; | 52 | int read_bytes; |
41 | int i; | 53 | int i; |
42 | 54 | ||
@@ -46,6 +58,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
46 | { | 58 | { |
47 | return false; | 59 | return false; |
48 | } | 60 | } |
61 | offset += 12; | ||
49 | 62 | ||
50 | if ((memcmp(buf, "RIFF",4) != 0) | 63 | if ((memcmp(buf, "RIFF",4) != 0) |
51 | || (memcmp(&buf[8], "WAVE", 4) !=0 )) | 64 | || (memcmp(&buf[8], "WAVE", 4) !=0 )) |
@@ -59,6 +72,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
59 | /* get chunk header */ | 72 | /* get chunk header */ |
60 | if ((read_bytes = read(fd, buf, 8)) < 8) | 73 | if ((read_bytes = read(fd, buf, 8)) < 8) |
61 | return false; | 74 | return false; |
75 | offset += 8; | ||
62 | 76 | ||
63 | /* chunkSize */ | 77 | /* chunkSize */ |
64 | i = get_long_le(&buf[4]); | 78 | i = get_long_le(&buf[4]); |
@@ -68,9 +82,10 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
68 | /* get rest of chunk */ | 82 | /* get rest of chunk */ |
69 | if ((read_bytes = read(fd, buf, 16)) < 16) | 83 | if ((read_bytes = read(fd, buf, 16)) < 16) |
70 | return false; | 84 | return false; |
71 | 85 | offset += 16; | |
72 | i -= 16; | 86 | i -= 16; |
73 | 87 | ||
88 | |||
74 | /* skipping wFormatTag */ | 89 | /* skipping wFormatTag */ |
75 | /* wChannels */ | 90 | /* wChannels */ |
76 | channels = buf[2] | (buf[3] << 8); | 91 | channels = buf[2] | (buf[3] << 8); |
@@ -78,13 +93,33 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
78 | id3->frequency = get_long_le(&buf[4]); | 93 | id3->frequency = get_long_le(&buf[4]); |
79 | /* dwAvgBytesPerSec */ | 94 | /* dwAvgBytesPerSec */ |
80 | id3->bitrate = (get_long_le(&buf[8]) * 8) / 1000; | 95 | id3->bitrate = (get_long_le(&buf[8]) * 8) / 1000; |
81 | /* skipping wBlockAlign */ | 96 | /* wBlockAlign */ |
97 | id3->bytesperframe = buf[12] | (buf[13] << 8); | ||
82 | /* wBitsPerSample */ | 98 | /* wBitsPerSample */ |
83 | bitspersample = buf[14] | (buf[15] << 8); | 99 | bitspersample = buf[14] | (buf[15] << 8); |
100 | /* Check for ATRAC3 stream */ | ||
101 | if((buf[0] | (buf[1] << 8)) == 0x0270) | ||
102 | { | ||
103 | int jsflag = 0; | ||
104 | if(id3->bitrate == 66 || id3->bitrate == 94) | ||
105 | jsflag = 1; | ||
106 | |||
107 | id3->extradata_size = 14; | ||
108 | id3->channels = 2; | ||
109 | id3->codectype = AFMT_OMA_ATRAC3; | ||
110 | /* Store the extradata for the codec */ | ||
111 | AV_WL16(&id3->id3v2buf[0], 1); // always 1 | ||
112 | AV_WL32(&id3->id3v2buf[2], id3->frequency); // samples rate | ||
113 | AV_WL16(&id3->id3v2buf[6], jsflag); // coding mode | ||
114 | AV_WL16(&id3->id3v2buf[8], jsflag); // coding mode | ||
115 | AV_WL16(&id3->id3v2buf[10], 1); // always 1 | ||
116 | AV_WL16(&id3->id3v2buf[12], 0); // always 0 | ||
117 | } | ||
84 | } | 118 | } |
85 | else if (memcmp(buf, "data", 4) == 0) | 119 | else if (memcmp(buf, "data", 4) == 0) |
86 | { | 120 | { |
87 | numbytes = i; | 121 | numbytes = i; |
122 | id3->first_frame_offset = offset; | ||
88 | break; | 123 | break; |
89 | } | 124 | } |
90 | else if (memcmp(buf, "fact", 4) == 0) | 125 | else if (memcmp(buf, "fact", 4) == 0) |
@@ -95,7 +130,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
95 | /* get rest of chunk */ | 130 | /* get rest of chunk */ |
96 | if ((read_bytes = read(fd, buf, 4)) < 4) | 131 | if ((read_bytes = read(fd, buf, 4)) < 4) |
97 | return false; | 132 | return false; |
98 | 133 | offset += 4; | |
99 | i -= 4; | 134 | i -= 4; |
100 | totalsamples = get_long_le(buf); | 135 | totalsamples = get_long_le(buf); |
101 | } | 136 | } |
@@ -107,6 +142,7 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
107 | 142 | ||
108 | if(lseek(fd, i, SEEK_CUR) < 0) | 143 | if(lseek(fd, i, SEEK_CUR) < 0) |
109 | return false; | 144 | return false; |
145 | offset += i; | ||
110 | } | 146 | } |
111 | 147 | ||
112 | if ((numbytes == 0) || (channels == 0)) | 148 | if ((numbytes == 0) || (channels == 0)) |
@@ -125,7 +161,10 @@ bool get_wave_metadata(int fd, struct mp3entry* id3) | |||
125 | id3->filesize = filesize(fd); | 161 | id3->filesize = filesize(fd); |
126 | 162 | ||
127 | /* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */ | 163 | /* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */ |
128 | id3->length = ((int64_t) totalsamples * 1000) / id3->frequency; | 164 | if(id3->codectype != AFMT_OMA_ATRAC3) |
165 | id3->length = ((int64_t) totalsamples * 1000) / id3->frequency; | ||
166 | else | ||
167 | id3->length = ((id3->filesize - id3->first_frame_offset) * 8) / id3->bitrate; | ||
129 | 168 | ||
130 | return true; | 169 | return true; |
131 | } | 170 | } |