summaryrefslogtreecommitdiff
path: root/apps/codecs/aiff.c
diff options
context:
space:
mode:
authorYoshihisa Uchida <uchida@rockbox.org>2010-02-20 02:04:56 +0000
committerYoshihisa Uchida <uchida@rockbox.org>2010-02-20 02:04:56 +0000
commit3716abba9274f544dd31cdf4e6c83a845bf2a801 (patch)
tree07bca7cdd3e40bb176e938fcb5ea8eb2f7c3e9cb /apps/codecs/aiff.c
parent93caf52db5e0afe826278c148936bdfa563724f1 (diff)
downloadrockbox-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.c58
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
41static const struct pcm_entry pcm_codecs[] = { 42static 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
51static int32_t samples[PCM_CHUNK_SIZE] IBSS_ATTR; 53static 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