diff options
author | Yoshihisa Uchida <uchida@rockbox.org> | 2010-02-20 02:04:56 +0000 |
---|---|---|
committer | Yoshihisa Uchida <uchida@rockbox.org> | 2010-02-20 02:04:56 +0000 |
commit | 3716abba9274f544dd31cdf4e6c83a845bf2a801 (patch) | |
tree | 07bca7cdd3e40bb176e938fcb5ea8eb2f7c3e9cb /apps/codecs/aiff.c | |
parent | 93caf52db5e0afe826278c148936bdfa563724f1 (diff) | |
download | rockbox-3716abba9274f544dd31cdf4e6c83a845bf2a801.tar.gz rockbox-3716abba9274f544dd31cdf4e6c83a845bf2a801.zip |
commit FS#10424 and FS#10425
- wav(RIFF) supports Microsoft ADPCM, Dialogic OKI ADPCM, YAMAHA ADPCM, Adobe SWF ADPCM.
- AIFF supports QuickTime IMA ADPCM.
- DVI ADPCM(IMA ADPCM) reworks.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24782 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/aiff.c')
-rw-r--r-- | apps/codecs/aiff.c | 58 |
1 files changed, 45 insertions, 13 deletions
diff --git a/apps/codecs/aiff.c b/apps/codecs/aiff.c index 2e10d1e416..4b870386c1 100644 --- a/apps/codecs/aiff.c +++ b/apps/codecs/aiff.c | |||
@@ -36,6 +36,7 @@ enum { | |||
36 | AIFC_FORMAT_MULAW = FOURCC('u', 'l', 'a', 'w'), /* AIFC uLaw compressed */ | 36 | AIFC_FORMAT_MULAW = FOURCC('u', 'l', 'a', 'w'), /* AIFC uLaw compressed */ |
37 | AIFC_FORMAT_IEEE_FLOAT32 = FOURCC('f', 'l', '3', '2'), /* AIFC IEEE float 32 bit */ | 37 | AIFC_FORMAT_IEEE_FLOAT32 = FOURCC('f', 'l', '3', '2'), /* AIFC IEEE float 32 bit */ |
38 | AIFC_FORMAT_IEEE_FLOAT64 = FOURCC('f', 'l', '6', '4'), /* AIFC IEEE float 64 bit */ | 38 | AIFC_FORMAT_IEEE_FLOAT64 = FOURCC('f', 'l', '6', '4'), /* AIFC IEEE float 64 bit */ |
39 | AIFC_FORMAT_QT_IMA_ADPCM = FOURCC('i', 'm', 'a', '4'), /* AIFC QuickTime IMA ADPCM */ | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | static const struct pcm_entry pcm_codecs[] = { | 42 | static const struct pcm_entry pcm_codecs[] = { |
@@ -44,9 +45,10 @@ static const struct pcm_entry pcm_codecs[] = { | |||
44 | { AIFC_FORMAT_MULAW, get_itut_g711_mulaw_codec }, | 45 | { AIFC_FORMAT_MULAW, get_itut_g711_mulaw_codec }, |
45 | { AIFC_FORMAT_IEEE_FLOAT32, get_ieee_float_codec }, | 46 | { AIFC_FORMAT_IEEE_FLOAT32, get_ieee_float_codec }, |
46 | { AIFC_FORMAT_IEEE_FLOAT64, get_ieee_float_codec }, | 47 | { AIFC_FORMAT_IEEE_FLOAT64, get_ieee_float_codec }, |
48 | { AIFC_FORMAT_QT_IMA_ADPCM, get_qt_ima_adpcm_codec }, | ||
47 | }; | 49 | }; |
48 | 50 | ||
49 | #define NUM_FORMATS 5 | 51 | #define NUM_FORMATS 6 |
50 | 52 | ||
51 | static int32_t samples[PCM_CHUNK_SIZE] IBSS_ATTR; | 53 | static int32_t samples[PCM_CHUNK_SIZE] IBSS_ATTR; |
52 | 54 | ||
@@ -70,7 +72,7 @@ enum codec_status codec_main(void) | |||
70 | { | 72 | { |
71 | int status = CODEC_OK; | 73 | int status = CODEC_OK; |
72 | struct pcm_format format; | 74 | struct pcm_format format; |
73 | uint32_t bytesdone, decodedbytes; | 75 | uint32_t bytesdone, decodedsamples; |
74 | uint32_t num_sample_frames = 0; | 76 | uint32_t num_sample_frames = 0; |
75 | uint32_t i = CODEC_OK; | 77 | uint32_t i = CODEC_OK; |
76 | size_t n; | 78 | size_t n; |
@@ -128,7 +130,7 @@ next_track: | |||
128 | format.is_signed = true; | 130 | format.is_signed = true; |
129 | format.is_little_endian = false; | 131 | format.is_little_endian = false; |
130 | 132 | ||
131 | decodedbytes = 0; | 133 | decodedsamples = 0; |
132 | codec = 0; | 134 | codec = 0; |
133 | 135 | ||
134 | /* read until 'SSND' chunk, which typically is last */ | 136 | /* read until 'SSND' chunk, which typically is last */ |
@@ -168,8 +170,11 @@ next_track: | |||
168 | * aiff's sample_size is uncompressed sound data size. | 170 | * aiff's sample_size is uncompressed sound data size. |
169 | * But format.bitspersample is compressed sound data size. | 171 | * But format.bitspersample is compressed sound data size. |
170 | */ | 172 | */ |
171 | if (format.formattag == AIFC_FORMAT_ALAW || format.formattag == AIFC_FORMAT_MULAW) | 173 | if (format.formattag == AIFC_FORMAT_ALAW || |
174 | format.formattag == AIFC_FORMAT_MULAW) | ||
172 | format.bitspersample = 8; | 175 | format.bitspersample = 8; |
176 | else if (format.formattag == AIFC_FORMAT_QT_IMA_ADPCM) | ||
177 | format.bitspersample = 4; | ||
173 | } | 178 | } |
174 | else | 179 | else |
175 | format.formattag = AIFC_FORMAT_PCM; | 180 | format.formattag = AIFC_FORMAT_PCM; |
@@ -184,9 +189,9 @@ next_track: | |||
184 | /* offset2snd */ | 189 | /* offset2snd */ |
185 | offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11]; | 190 | offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11]; |
186 | /* block_size */ | 191 | /* block_size */ |
187 | format.blockalign = (buf[12]<<24)|(buf[13]<<16)|(buf[14]<<8)|buf[15]; | 192 | format.blockalign = ((buf[12]<<24)|(buf[13]<<16)|(buf[14]<<8)|buf[15]) >> 3; |
188 | if (format.blockalign == 0) | 193 | if (format.blockalign == 0) |
189 | format.blockalign = format.channels*format.bitspersample; | 194 | format.blockalign = format.channels * format.bitspersample >> 3; |
190 | format.numbytes = i - 8 - offset2snd; | 195 | format.numbytes = i - 8 - offset2snd; |
191 | i = 8 + offset2snd; /* advance to the beginning of data */ | 196 | i = 8 + offset2snd; /* advance to the beginning of data */ |
192 | } else if (is_aifc && (memcmp(buf, "FVER", 4)==0)) { | 197 | } else if (is_aifc && (memcmp(buf, "FVER", 4)==0)) { |
@@ -228,7 +233,7 @@ next_track: | |||
228 | goto done; | 233 | goto done; |
229 | } | 234 | } |
230 | 235 | ||
231 | if (!codec->set_format(&format, 0)) | 236 | if (!codec->set_format(&format)) |
232 | { | 237 | { |
233 | i = CODEC_ERROR; | 238 | i = CODEC_ERROR; |
234 | goto done; | 239 | goto done; |
@@ -246,6 +251,30 @@ next_track: | |||
246 | goto done; | 251 | goto done; |
247 | } | 252 | } |
248 | 253 | ||
254 | if (format.samplesperblock == 0) | ||
255 | { | ||
256 | DEBUGF("CODEC_ERROR: samplesperblock is 0\n"); | ||
257 | i = CODEC_ERROR; | ||
258 | goto done; | ||
259 | } | ||
260 | if (format.blockalign == 0) | ||
261 | { | ||
262 | DEBUGF("CODEC_ERROR: blockalign is 0\n"); | ||
263 | i = CODEC_ERROR; | ||
264 | goto done; | ||
265 | } | ||
266 | |||
267 | /* check chunksize */ | ||
268 | if ((format.chunksize / format.blockalign) * format.samplesperblock * format.channels | ||
269 | > PCM_CHUNK_SIZE) | ||
270 | format.chunksize = (PCM_CHUNK_SIZE / format.blockalign) * format.blockalign; | ||
271 | if (format.chunksize == 0) | ||
272 | { | ||
273 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); | ||
274 | i = CODEC_ERROR; | ||
275 | goto done; | ||
276 | } | ||
277 | |||
249 | firstblockposn = 1024 - n; | 278 | firstblockposn = 1024 - n; |
250 | ci->advance_buffer(firstblockposn); | 279 | ci->advance_buffer(firstblockposn); |
251 | 280 | ||
@@ -260,11 +289,14 @@ next_track: | |||
260 | break; | 289 | break; |
261 | 290 | ||
262 | if (ci->seek_time) { | 291 | if (ci->seek_time) { |
263 | uint32_t newpos = codec->get_seek_pos(ci->seek_time); | 292 | /* 2nd args(read_buffer) is unnecessary in the format which AIFF supports. */ |
264 | if (newpos > format.numbytes) | 293 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, NULL); |
294 | |||
295 | decodedsamples = newpos->samples; | ||
296 | if (newpos->pos > format.numbytes) | ||
265 | break; | 297 | break; |
266 | if (ci->seek_buffer(firstblockposn + newpos)) | 298 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
267 | bytesdone = newpos; | 299 | bytesdone = newpos->pos; |
268 | ci->seek_complete(); | 300 | ci->seek_complete(); |
269 | } | 301 | } |
270 | aifbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); | 302 | aifbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); |
@@ -288,11 +320,11 @@ next_track: | |||
288 | 320 | ||
289 | ci->advance_buffer(n); | 321 | ci->advance_buffer(n); |
290 | bytesdone += n; | 322 | bytesdone += n; |
291 | decodedbytes += bufcount; | 323 | decodedsamples += bufcount; |
292 | if (bytesdone >= format.numbytes) | 324 | if (bytesdone >= format.numbytes) |
293 | endofstream = 1; | 325 | endofstream = 1; |
294 | 326 | ||
295 | ci->set_elapsed(decodedbytes*1000LL/ci->id3->frequency); | 327 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); |
296 | } | 328 | } |
297 | i = CODEC_OK; | 329 | i = CODEC_OK; |
298 | 330 | ||