diff options
author | Thom Johansen <thomj@rockbox.org> | 2006-03-20 20:32:19 +0000 |
---|---|---|
committer | Thom Johansen <thomj@rockbox.org> | 2006-03-20 20:32:19 +0000 |
commit | 0968536c4b25e33089e42819cb11a0d176565792 (patch) | |
tree | a029254128a828315c66adfa7035172f83052acb /apps/codecs | |
parent | d8eaefe29a769a7ef937c9d098144a6f400d00e5 (diff) | |
download | rockbox-0968536c4b25e33089e42819cb11a0d176565792.tar.gz rockbox-0968536c4b25e33089e42819cb11a0d176565792.zip |
Code policed. Converted to generate internal s3.28 format directly (next
task is removing use of interleaved audio). Could not test ADPCM due to
difficulty in finding files it could play, so tell me if it is broken.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9136 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs')
-rw-r--r-- | apps/codecs/wav.c | 679 |
1 files changed, 319 insertions, 360 deletions
diff --git a/apps/codecs/wav.c b/apps/codecs/wav.c index f6daf25564..32cff6a758 100644 --- a/apps/codecs/wav.c +++ b/apps/codecs/wav.c | |||
@@ -22,12 +22,15 @@ | |||
22 | 22 | ||
23 | CODEC_HEADER | 23 | CODEC_HEADER |
24 | 24 | ||
25 | struct codec_api* rb; | 25 | /* Macro that sign extends an unsigned byte */ |
26 | #define SE(x) ((int32_t)((int8_t)(x))) | ||
27 | |||
28 | struct codec_api *rb; | ||
26 | 29 | ||
27 | /* This codec support WAVE files with the following formats: | 30 | /* This codec support WAVE files with the following formats: |
28 | * - PCM, up to 32 bits, supporting 32 bits playback when useful. | 31 | * - PCM, up to 32 bits, supporting 32 bits playback when useful. |
29 | * - ALAW and MULAW (16 bits compressed on 8 bits). | 32 | * - ALAW and MULAW (16 bits compressed on 8 bits). |
30 | * - DVI_ADPCM (16 bits compressed on 4 bits). | 33 | * - DVI_ADPCM (16 bits compressed on 3 or 4 bits). |
31 | * | 34 | * |
32 | * For a good documentation on WAVE files, see: | 35 | * For a good documentation on WAVE files, see: |
33 | * http://www.tsp.ece.mcgill.ca/MMSP/Documents/AudioFormats/WAVE/WAVE.html | 36 | * http://www.tsp.ece.mcgill.ca/MMSP/Documents/AudioFormats/WAVE/WAVE.html |
@@ -100,8 +103,6 @@ extern char iedata[]; | |||
100 | extern char iend[]; | 103 | extern char iend[]; |
101 | #endif | 104 | #endif |
102 | 105 | ||
103 | /* Those are lookup tables, so they should be in the idata section | ||
104 | * (fast but small RAM on the coldfire processor) */ | ||
105 | static const int16_t alaw2linear16[256] ICONST_ATTR = { | 106 | static const int16_t alaw2linear16[256] ICONST_ATTR = { |
106 | -5504, -5248, -6016, -5760, -4480, -4224, -4992, | 107 | -5504, -5248, -6016, -5760, -4480, -4224, -4992, |
107 | -4736, -7552, -7296, -8064, -7808, -6528, -6272, | 108 | -4736, -7552, -7296, -8064, -7808, -6528, -6272, |
@@ -182,7 +183,7 @@ static const int16_t ulaw2linear16[256] ICONST_ATTR = { | |||
182 | 24, 16, 8, 0 | 183 | 24, 16, 8, 0 |
183 | }; | 184 | }; |
184 | 185 | ||
185 | static const uint16_t dvi_adpcm_steptab[ 89 ] ICONST_ATTR = { | 186 | static const uint16_t dvi_adpcm_steptab[89] ICONST_ATTR = { |
186 | 7, 8, 9, 10, 11, 12, 13, 14, | 187 | 7, 8, 9, 10, 11, 12, 13, 14, |
187 | 16, 17, 19, 21, 23, 25, 28, 31, | 188 | 16, 17, 19, 21, 23, 25, 28, 31, |
188 | 34, 37, 41, 45, 50, 55, 60, 66, | 189 | 34, 37, 41, 45, 50, 55, 60, 66, |
@@ -195,387 +196,348 @@ static const uint16_t dvi_adpcm_steptab[ 89 ] ICONST_ATTR = { | |||
195 | 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, | 196 | 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, |
196 | 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, | 197 | 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, |
197 | 32767 }; | 198 | 32767 }; |
198 | static const int dvi_adpcm_indextab4[ 8 ] ICONST_ATTR = { -1, -1, -1, -1, 2, 4, 6, 8 }; | ||
199 | static const int dvi_adpcm_indextab3[ 4 ] ICONST_ATTR = { -1, -1, 1, 2 }; | ||
200 | 199 | ||
201 | static int16_t int16_samples[WAV_CHUNK_SIZE] IBSS_ATTR; | 200 | static const int dvi_adpcm_indextab4[8] ICONST_ATTR = { |
201 | -1, -1, -1, -1, 2, 4, 6, 8 }; | ||
202 | |||
203 | static const int dvi_adpcm_indextab3[4] ICONST_ATTR = { -1, -1, 1, 2 }; | ||
204 | |||
205 | static int32_t samples[WAV_CHUNK_SIZE] IBSS_ATTR; | ||
202 | 206 | ||
203 | static enum codec_status | 207 | static enum codec_status |
204 | decode_dvi_adpcm(struct codec_api* ci, | 208 | decode_dvi_adpcm(struct codec_api *ci, |
205 | const uint8_t *buf, | 209 | const uint8_t *buf, |
206 | int n, | 210 | int n, |
207 | uint16_t channels, uint16_t bitspersample, | 211 | uint16_t channels, uint16_t bitspersample, |
208 | int16_t *pcmout, | 212 | int32_t *pcmout, |
209 | size_t *pcmoutsize); | 213 | size_t *pcmoutsize); |
210 | 214 | ||
211 | /* this is the codec entry point */ | 215 | /* this is the codec entry point */ |
212 | enum codec_status codec_start(struct codec_api* api) | 216 | enum codec_status codec_start(struct codec_api *api) |
213 | { | 217 | { |
214 | struct codec_api* ci; | 218 | struct codec_api *ci; |
215 | uint32_t numbytes, bytesdone; | 219 | uint32_t numbytes, bytesdone; |
216 | uint32_t totalsamples = 0; | 220 | uint32_t totalsamples = 0; |
217 | uint16_t channels=0; | 221 | uint16_t channels = 0; |
218 | uint16_t samplesperblock = 0; | 222 | uint16_t samplesperblock = 0; |
219 | int bytespersample=0; | 223 | int bytespersample = 0; |
220 | uint16_t bitspersample; | 224 | uint16_t bitspersample; |
221 | uint32_t i; | 225 | uint32_t i; |
222 | size_t n, wavbufsize; | 226 | size_t n, bufsize; |
223 | int endofstream; | 227 | int endofstream; |
224 | unsigned char* buf; | 228 | unsigned char *buf; |
225 | uint16_t* wavbuf; | 229 | uint8_t *wavbuf; |
226 | long chunksize; | 230 | long chunksize; |
227 | uint16_t formattag = 0; | 231 | uint16_t formattag = 0; |
228 | uint16_t blockalign = 0; | 232 | uint16_t blockalign = 0; |
229 | uint32_t avgbytespersec = 0; | 233 | uint32_t avgbytespersec = 0; |
230 | off_t firstblockposn; /* position of the first block in file */ | 234 | off_t firstblockposn; /* position of the first block in file */ |
231 | int shortorlong = 1; /* do we output shorts (1) or longs (2)? */ | 235 | |
232 | int32_t * const int32_samples = (int32_t*)int16_samples; | 236 | /* Generic codec initialisation */ |
233 | 237 | rb = api; | |
234 | /* Generic codec initialisation */ | 238 | ci = api; |
235 | rb = api; | ||
236 | ci = api; | ||
237 | 239 | ||
238 | #ifdef USE_IRAM | 240 | #ifdef USE_IRAM |
239 | ci->memcpy(iramstart, iramcopy, iramend-iramstart); | 241 | ci->memcpy(iramstart, iramcopy, iramend - iramstart); |
240 | ci->memset(iedata, 0, iend - iedata); | 242 | ci->memset(iedata, 0, iend - iedata); |
241 | #endif | 243 | #endif |
242 | 244 | ||
243 | ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512)); | 245 | ci->configure(CODEC_DSP_ENABLE, (bool *)true); |
244 | ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*256)); | 246 | ci->configure(DSP_SET_SAMPLE_DEPTH, (long *)28); |
245 | 247 | ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512)); | |
246 | ci->configure(DSP_DITHER, (bool *)false); | 248 | ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*256)); |
249 | ci->configure(DSP_DITHER, (bool *)false); | ||
247 | 250 | ||
248 | next_track: | 251 | next_track: |
249 | 252 | if (codec_init(api)) { | |
250 | if (codec_init(api)) { | 253 | i = CODEC_ERROR; |
251 | i = CODEC_ERROR; | 254 | goto exit; |
252 | goto exit; | 255 | } |
253 | } | ||
254 | 256 | ||
255 | while (!*ci->taginfo_ready) | 257 | while (!*ci->taginfo_ready) |
256 | ci->yield(); | 258 | ci->yield(); |
257 | 259 | ||
258 | /* assume the WAV header is less than 1024 bytes */ | 260 | /* assume the WAV header is less than 1024 bytes */ |
259 | buf=ci->request_buffer((long *)&n,1024); | 261 | buf = ci->request_buffer((long *)&n, 1024); |
260 | if (n<44) { | 262 | if (n < 44) { |
261 | i = CODEC_ERROR; | 263 | i = CODEC_ERROR; |
262 | goto exit; | 264 | goto exit; |
263 | } | 265 | } |
264 | if ((memcmp(buf,"RIFF",4)!=0) || (memcmp(&buf[8],"WAVE",4)!=0)) { | 266 | if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) { |
265 | i = CODEC_ERROR; | 267 | i = CODEC_ERROR; |
266 | goto exit; | 268 | goto exit; |
267 | } | ||
268 | |||
269 | buf += 12; | ||
270 | n -= 12; | ||
271 | bitspersample = 0; | ||
272 | numbytes = 0; | ||
273 | totalsamples = 0; | ||
274 | /* read until the data chunk, which should be last */ | ||
275 | while(numbytes == 0 && n >= 8) { | ||
276 | /* chunkSize */ | ||
277 | i = (buf[4]|(buf[5]<<8)|(buf[6]<<16)|(buf[7]<<24)); | ||
278 | if (memcmp(buf,"fmt ",4)==0) { | ||
279 | if (i<16) { | ||
280 | DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%lu < 16\n",i); | ||
281 | i = CODEC_ERROR; | ||
282 | goto exit; | ||
283 | } | ||
284 | /* wFormatTag */ | ||
285 | formattag=buf[8]|(buf[9]<<8); | ||
286 | /* wChannels */ | ||
287 | channels=buf[10]|(buf[11]<<8); | ||
288 | /* skipping dwSamplesPerSec */ | ||
289 | /* dwAvgBytesPerSec */ | ||
290 | avgbytespersec = buf[16]|(buf[17]<<8)|(buf[18]<<16)|(buf[19]<<24); | ||
291 | /* wBlockAlign */ | ||
292 | blockalign=buf[20]|(buf[21]<<8); | ||
293 | /* wBitsPerSample */ | ||
294 | bitspersample=buf[22]|(buf[23]<<8); | ||
295 | if (formattag != WAVE_FORMAT_PCM) { | ||
296 | uint16_t size; | ||
297 | if (i<18) { | ||
298 | /* this is not a fatal error with some formats, | ||
299 | * we'll see later if we can't decode it */ | ||
300 | DEBUGF("CODEC_WARNING: non-PCM WAVE (formattag=0x%x) " | ||
301 | "doesn't have ext. fmt descr (chunksize=%d<18).\n", | ||
302 | formattag, i); | ||
303 | } | ||
304 | size = buf[24]|(buf[25]<<8); | ||
305 | if (formattag == WAVE_FORMAT_DVI_ADPCM) { | ||
306 | if (size < 2) { | ||
307 | DEBUGF("CODEC_ERROR: dvi_adpcm is missing " | ||
308 | "SamplesPerBlock value\n"); | ||
309 | i = CODEC_ERROR; | ||
310 | goto exit; | ||
311 | } | ||
312 | samplesperblock = buf[26]|(buf[27]<<8); | ||
313 | } | ||
314 | else if (formattag == WAVE_FORMAT_EXTENSIBLE) { | ||
315 | if (size < 22) { | ||
316 | DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " | ||
317 | "missing extension\n"); | ||
318 | i = CODEC_ERROR; | ||
319 | goto exit; | ||
320 | } | ||
321 | /* wValidBitsPerSample */ | ||
322 | bitspersample = buf[26]|(buf[27]<<8); | ||
323 | /* skipping dwChannelMask (4bytes) */ | ||
324 | /* SubFormat (only get the first two bytes) */ | ||
325 | formattag = buf[32]|(buf[33]<<8); | ||
326 | } | ||
327 | } | ||
328 | } | ||
329 | else if (memcmp(buf,"data",4)==0) { | ||
330 | numbytes=i; | ||
331 | i=0; /* advance to the beginning of data */ | ||
332 | } | ||
333 | else if (memcmp(buf,"fact",4)==0) { | ||
334 | /* dwSampleLength */ | ||
335 | if (i>=4) { | ||
336 | totalsamples = (buf[8]|(buf[9]<<8)|(buf[10]<<16)|(buf[11]<<24)); | ||
337 | } | ||
338 | } | ||
339 | else { | ||
340 | DEBUGF("unknown WAVE chunk: '%c%c%c%c', size=%lu\n", | ||
341 | buf[0], buf[1], buf[2], buf[3],i); | ||
342 | } | ||
343 | /* go to next chunk (even chunk sizes must be padded) */ | ||
344 | if (i & 0x01) | ||
345 | i++; | ||
346 | buf += i+8; | ||
347 | if (n < (i+8)) { | ||
348 | DEBUGF("CODEC_ERROR: WAVE header size > 1024\n"); | ||
349 | i = CODEC_ERROR; | ||
350 | goto exit; | ||
351 | } | ||
352 | n -= i+8; | ||
353 | } | ||
354 | |||
355 | if (channels == 0) { | ||
356 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); | ||
357 | i = CODEC_ERROR; | ||
358 | goto exit; | ||
359 | } | ||
360 | if (numbytes == 0) { | ||
361 | DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); | ||
362 | i = CODEC_ERROR; | ||
363 | goto exit; | ||
364 | } | ||
365 | if (formattag != WAVE_FORMAT_PCM && totalsamples == 0) { | ||
366 | /* This is non-fatal for some formats */ | ||
367 | DEBUGF("CODEC_WARNING: non-PCM WAVE doesn't have a 'fact' chunk\n"); | ||
368 | } | ||
369 | if (formattag == WAVE_FORMAT_ALAW || formattag == WAVE_FORMAT_MULAW || | ||
370 | formattag == IBM_FORMAT_ALAW || formattag == IBM_FORMAT_MULAW) { | ||
371 | if (bitspersample != 8) { | ||
372 | DEBUGF("CODEC_ERROR: alaw and mulaw must have 8 bitspersample\n"); | ||
373 | i = CODEC_ERROR; | ||
374 | goto exit; | ||
375 | } | ||
376 | bytespersample = channels; | ||
377 | } | ||
378 | if ( formattag == WAVE_FORMAT_DVI_ADPCM | ||
379 | && bitspersample != 4 && bitspersample != 3) { | ||
380 | DEBUGF("CODEC_ERROR: dvi_adpcm must have 3 or 4 bitspersample\n"); | ||
381 | i = CODEC_ERROR; | ||
382 | goto exit; | ||
383 | } | ||
384 | if (formattag == WAVE_FORMAT_PCM && bitspersample > 32) { | ||
385 | DEBUGF("CODEC_ERROR: pcm with more than 32 bitspersample " | ||
386 | "is unsupported\n"); | ||
387 | i = CODEC_ERROR; | ||
388 | goto exit; | ||
389 | } | ||
390 | |||
391 | ci->configure(CODEC_DSP_ENABLE, (bool *)true); | ||
392 | ci->configure(DSP_SET_FREQUENCY, (long *)(ci->id3->frequency)); | ||
393 | |||
394 | if (bitspersample <= 16) { | ||
395 | ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(16)); | ||
396 | } else { | ||
397 | shortorlong = 2; | ||
398 | ci->configure(DSP_DITHER, (bool *)false); | ||
399 | ci->configure(DSP_SET_SAMPLE_DEPTH, (long *) (32)); | ||
400 | ci->configure(DSP_SET_CLIP_MAX, (long *) (2147483647)); | ||
401 | ci->configure(DSP_SET_CLIP_MIN, (long *) (-2147483647-1)); | ||
402 | } | ||
403 | |||
404 | if (channels == 2) { | ||
405 | ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_INTERLEAVED); | ||
406 | } else if (channels == 1) { | ||
407 | ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_MONO); | ||
408 | } else { | ||
409 | DEBUGF("CODEC_ERROR: more than 2 channels\n"); | ||
410 | i = CODEC_ERROR; | ||
411 | goto exit; | ||
412 | } | ||
413 | |||
414 | if (totalsamples == 0) { | ||
415 | if (formattag == WAVE_FORMAT_PCM || | ||
416 | formattag == WAVE_FORMAT_ALAW || formattag == WAVE_FORMAT_MULAW || | ||
417 | formattag == IBM_FORMAT_ALAW || formattag == IBM_FORMAT_MULAW) { | ||
418 | /* for PCM and derived formats only */ | ||
419 | bytespersample=(((bitspersample-1)/8+1)*channels); | ||
420 | totalsamples=numbytes/bytespersample; | ||
421 | } | ||
422 | else { | ||
423 | DEBUGF("CODEC_ERROR: cannot compute totalsamples\n"); | ||
424 | i = CODEC_ERROR; | ||
425 | goto exit; | ||
426 | } | ||
427 | } | ||
428 | |||
429 | firstblockposn = (1024-n); | ||
430 | ci->advance_buffer(firstblockposn); | ||
431 | |||
432 | /* The main decoder loop */ | ||
433 | |||
434 | bytesdone=0; | ||
435 | ci->set_elapsed(0); | ||
436 | endofstream=0; | ||
437 | /* chunksize is computed so that one chunk is about 1/50s. | ||
438 | * this make 4096 for 44.1kHz 16bits stereo. | ||
439 | * It also has to be a multiple of blockalign */ | ||
440 | chunksize = (1 + avgbytespersec / (50*blockalign)) * blockalign; | ||
441 | /* check that the output buffer is big enough (convert to samplespersec, | ||
442 | then round to the blockalign multiple below) */ | ||
443 | if (((uint64_t)chunksize*ci->id3->frequency*channels*shortorlong) | ||
444 | / (uint64_t)avgbytespersec >= WAV_CHUNK_SIZE) { | ||
445 | chunksize = ((uint64_t)WAV_CHUNK_SIZE * avgbytespersec | ||
446 | / ((uint64_t)ci->id3->frequency * channels * shortorlong | ||
447 | * blockalign)) * blockalign; | ||
448 | } | ||
449 | |||
450 | while (!endofstream) { | ||
451 | uint8_t *wavbuf8; | ||
452 | |||
453 | ci->yield(); | ||
454 | if (ci->stop_codec || ci->reload_codec) { | ||
455 | break; | ||
456 | } | 269 | } |
457 | 270 | ||
458 | if (ci->seek_time) { | 271 | buf += 12; |
459 | uint32_t newpos; | 272 | n -= 12; |
273 | bitspersample = 0; | ||
274 | numbytes = 0; | ||
275 | totalsamples = 0; | ||
276 | /* read until the data chunk, which should be last */ | ||
277 | while (numbytes == 0 && n >= 8) { | ||
278 | /* chunkSize */ | ||
279 | i = (buf[4]|(buf[5]<<8)|(buf[6]<<16)|(buf[7]<<24)); | ||
280 | if (memcmp(buf, "fmt ", 4) == 0) { | ||
281 | if (i < 16) { | ||
282 | DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%lu < 16\n", i); | ||
283 | i = CODEC_ERROR; | ||
284 | goto exit; | ||
285 | } | ||
286 | /* wFormatTag */ | ||
287 | formattag=buf[8]|(buf[9]<<8); | ||
288 | /* wChannels */ | ||
289 | channels=buf[10]|(buf[11]<<8); | ||
290 | /* skipping dwSamplesPerSec */ | ||
291 | /* dwAvgBytesPerSec */ | ||
292 | avgbytespersec = buf[16]|(buf[17]<<8)|(buf[18]<<16)|(buf[19]<<24); | ||
293 | /* wBlockAlign */ | ||
294 | blockalign=buf[20]|(buf[21]<<8); | ||
295 | /* wBitsPerSample */ | ||
296 | bitspersample=buf[22]|(buf[23]<<8); | ||
297 | if (formattag != WAVE_FORMAT_PCM) { | ||
298 | uint16_t size; | ||
299 | if (i < 18) { | ||
300 | /* this is not a fatal error with some formats, | ||
301 | * we'll see later if we can't decode it */ | ||
302 | DEBUGF("CODEC_WARNING: non-PCM WAVE (formattag=0x%x) " | ||
303 | "doesn't have ext. fmt descr (chunksize=%d<18).\n", | ||
304 | formattag, i); | ||
305 | } | ||
306 | size = buf[24]|(buf[25]<<8); | ||
307 | if (formattag == WAVE_FORMAT_DVI_ADPCM) { | ||
308 | if (size < 2) { | ||
309 | DEBUGF("CODEC_ERROR: dvi_adpcm is missing " | ||
310 | "SamplesPerBlock value\n"); | ||
311 | i = CODEC_ERROR; | ||
312 | goto exit; | ||
313 | } | ||
314 | samplesperblock = buf[26]|(buf[27]<<8); | ||
315 | } else if (formattag == WAVE_FORMAT_EXTENSIBLE) { | ||
316 | if (size < 22) { | ||
317 | DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " | ||
318 | "missing extension\n"); | ||
319 | i = CODEC_ERROR; | ||
320 | goto exit; | ||
321 | } | ||
322 | /* wValidBitsPerSample */ | ||
323 | bitspersample = buf[26]|(buf[27]<<8); | ||
324 | /* skipping dwChannelMask (4bytes) */ | ||
325 | /* SubFormat (only get the first two bytes) */ | ||
326 | formattag = buf[32]|(buf[33]<<8); | ||
327 | } | ||
328 | } | ||
329 | } else if (memcmp(buf, "data", 4) == 0) { | ||
330 | numbytes = i; | ||
331 | i = 0; /* advance to the beginning of data */ | ||
332 | } else if (memcmp(buf, "fact", 4) == 0) { | ||
333 | /* dwSampleLength */ | ||
334 | if (i >= 4) | ||
335 | totalsamples = (buf[8]|(buf[9]<<8)|(buf[10]<<16)|(buf[11]<<24)); | ||
336 | } else { | ||
337 | DEBUGF("unknown WAVE chunk: '%c%c%c%c', size=%lu\n", | ||
338 | buf[0], buf[1], buf[2], buf[3], i); | ||
339 | } | ||
340 | /* go to next chunk (even chunk sizes must be padded) */ | ||
341 | if (i & 0x01) | ||
342 | i++; | ||
343 | buf += i + 8; | ||
344 | if (n < (i + 8)) { | ||
345 | DEBUGF("CODEC_ERROR: WAVE header size > 1024\n"); | ||
346 | i = CODEC_ERROR; | ||
347 | goto exit; | ||
348 | } | ||
349 | n -= i + 8; | ||
350 | } | ||
460 | 351 | ||
461 | /* use avgbytespersec to round to the closest blockalign multiple, | 352 | if (channels == 0) { |
462 | add firstblockposn. 64-bit casts to avoid overflows. */ | 353 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); |
463 | newpos = (((uint64_t)avgbytespersec * (ci->seek_time - 1)) | 354 | i = CODEC_ERROR; |
464 | / (1000LL*blockalign)) * blockalign; | 355 | goto exit; |
465 | if (newpos > numbytes) | 356 | } |
466 | break; | 357 | if (numbytes == 0) { |
467 | if (ci->seek_buffer(firstblockposn + newpos)) { | 358 | DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); |
468 | bytesdone = newpos; | 359 | i = CODEC_ERROR; |
360 | goto exit; | ||
361 | } | ||
362 | if (formattag != WAVE_FORMAT_PCM && totalsamples == 0) { | ||
363 | /* This is non-fatal for some formats */ | ||
364 | DEBUGF("CODEC_WARNING: non-PCM WAVE doesn't have a 'fact' chunk\n"); | ||
365 | } | ||
366 | if (formattag == WAVE_FORMAT_ALAW || formattag == WAVE_FORMAT_MULAW || | ||
367 | formattag == IBM_FORMAT_ALAW || formattag == IBM_FORMAT_MULAW) { | ||
368 | if (bitspersample != 8) { | ||
369 | DEBUGF("CODEC_ERROR: alaw and mulaw must have 8 bitspersample\n"); | ||
370 | i = CODEC_ERROR; | ||
371 | goto exit; | ||
469 | } | 372 | } |
470 | ci->seek_complete(); | 373 | bytespersample = channels; |
374 | } | ||
375 | if (formattag == WAVE_FORMAT_DVI_ADPCM | ||
376 | && bitspersample != 4 && bitspersample != 3) { | ||
377 | DEBUGF("CODEC_ERROR: dvi_adpcm must have 3 or 4 bitspersample\n"); | ||
378 | i = CODEC_ERROR; | ||
379 | goto exit; | ||
380 | } | ||
381 | if (formattag == WAVE_FORMAT_PCM && bitspersample > 32) { | ||
382 | DEBUGF("CODEC_ERROR: pcm with more than 32 bitspersample " | ||
383 | "is unsupported\n"); | ||
384 | i = CODEC_ERROR; | ||
385 | goto exit; | ||
471 | } | 386 | } |
472 | wavbuf=ci->request_buffer((long *)&n,chunksize); | ||
473 | wavbuf8 = (uint8_t*)wavbuf; | ||
474 | 387 | ||
475 | if (n==0) | 388 | ci->configure(DSP_SET_FREQUENCY, (long *)(ci->id3->frequency)); |
476 | break; /* End of stream */ | 389 | if (channels == 2) { |
390 | ci->configure(DSP_SET_STEREO_MODE, (long *)STEREO_INTERLEAVED); | ||
391 | } else if (channels == 1) { | ||
392 | ci->configure(DSP_SET_STEREO_MODE, (long *)STEREO_MONO); | ||
393 | } else { | ||
394 | DEBUGF("CODEC_ERROR: more than 2 channels\n"); | ||
395 | i = CODEC_ERROR; | ||
396 | goto exit; | ||
397 | } | ||
477 | 398 | ||
478 | if (bytesdone + n > numbytes) { | 399 | if (totalsamples == 0) { |
479 | n = numbytes - bytesdone; | 400 | if (formattag == WAVE_FORMAT_PCM || |
480 | endofstream = 1; | 401 | formattag == WAVE_FORMAT_ALAW || formattag == WAVE_FORMAT_MULAW || |
402 | formattag == IBM_FORMAT_ALAW || formattag == IBM_FORMAT_MULAW) { | ||
403 | /* for PCM and derived formats only */ | ||
404 | bytespersample = (((bitspersample - 1)/8 + 1)*channels); | ||
405 | totalsamples = numbytes/bytespersample; | ||
406 | } else { | ||
407 | DEBUGF("CODEC_ERROR: cannot compute totalsamples\n"); | ||
408 | i = CODEC_ERROR; | ||
409 | goto exit; | ||
410 | } | ||
481 | } | 411 | } |
482 | 412 | ||
483 | wavbufsize = sizeof(int16_samples); | 413 | firstblockposn = 1024 - n; |
414 | ci->advance_buffer(firstblockposn); | ||
415 | |||
416 | /* The main decoder loop */ | ||
417 | bytesdone = 0; | ||
418 | ci->set_elapsed(0); | ||
419 | endofstream = 0; | ||
420 | /* chunksize is computed so that one chunk is about 1/50s. | ||
421 | * this make 4096 for 44.1kHz 16bits stereo. | ||
422 | * It also has to be a multiple of blockalign */ | ||
423 | chunksize = (1 + avgbytespersec / (50*blockalign))*blockalign; | ||
424 | /* check that the output buffer is big enough (convert to samplespersec, | ||
425 | then round to the blockalign multiple below) */ | ||
426 | if (((uint64_t)chunksize*ci->id3->frequency*channels*sizeof(long)) | ||
427 | /(uint64_t)avgbytespersec >= WAV_CHUNK_SIZE) { | ||
428 | chunksize = ((uint64_t)WAV_CHUNK_SIZE*avgbytespersec | ||
429 | /((uint64_t)ci->id3->frequency*channels*sizeof(long) | ||
430 | *blockalign))*blockalign; | ||
431 | } | ||
484 | 432 | ||
485 | if (formattag == WAVE_FORMAT_PCM) { | 433 | while (!endofstream) { |
486 | if (bitspersample > 24) { | 434 | ci->yield(); |
487 | for (i=0;i<n;i+=4) { | 435 | if (ci->stop_codec || ci->reload_codec) { |
488 | int32_samples[i/4]=(int32_t)(wavbuf8[i]|(wavbuf8[i+1]<<8)| | 436 | break; |
489 | (wavbuf8[i+2]<<16)|(wavbuf8[i+3]<<24)); | ||
490 | } | ||
491 | wavbufsize = n; | ||
492 | } | 437 | } |
493 | else if (bitspersample > 16) { | 438 | |
494 | for (i=0;i<n;i+=3) { | 439 | if (ci->seek_time) { |
495 | int32_samples[i/3]=(int32_t)((wavbuf8[i]<<8)| | 440 | uint32_t newpos; |
496 | (wavbuf8[i+1]<<16)|(wavbuf8[i+2]<<24)); | 441 | |
497 | } | 442 | /* use avgbytespersec to round to the closest blockalign multiple, |
498 | wavbufsize = n*4/3; | 443 | add firstblockposn. 64-bit casts to avoid overflows. */ |
444 | newpos = (((uint64_t)avgbytespersec*(ci->seek_time - 1)) | ||
445 | / (1000LL*blockalign))*blockalign; | ||
446 | if (newpos > numbytes) | ||
447 | break; | ||
448 | if (ci->seek_buffer(firstblockposn + newpos)) | ||
449 | bytesdone = newpos; | ||
450 | ci->seek_complete(); | ||
499 | } | 451 | } |
500 | else if (bitspersample > 8) { | 452 | wavbuf = (uint8_t *)ci->request_buffer((long *)&n, chunksize); |
501 | /* Byte-swap data. */ | 453 | |
502 | for (i=0;i<n/2;i++) { | 454 | if (n == 0) |
503 | int16_samples[i]=(int16_t)letoh16(wavbuf[i]); | 455 | break; /* End of stream */ |
504 | } | 456 | |
505 | wavbufsize = n; | 457 | if (bytesdone + n > numbytes) { |
458 | n = numbytes - bytesdone; | ||
459 | endofstream = 1; | ||
506 | } | 460 | } |
507 | else { | 461 | |
508 | for (i=0;i<n;i++) { | 462 | if (formattag == WAVE_FORMAT_PCM) { |
509 | int16_samples[i] = (wavbuf8[i]<<8) - 0x8000; | 463 | if (bitspersample > 24) { |
464 | for (i = 0; i < n; i += 4) { | ||
465 | samples[i/4] = (wavbuf[i] >> 3)| | ||
466 | (wavbuf[i + 1]<<5)|(wavbuf[i + 2]<<13)| | ||
467 | (SE(wavbuf[i + 3])<<21); | ||
468 | } | ||
469 | bufsize = n; | ||
470 | } else if (bitspersample > 16) { | ||
471 | for (i = 0; i < n; i += 3) { | ||
472 | samples[i/3] = (wavbuf[i]<<5)| | ||
473 | (wavbuf[i + 1]<<13)|(SE(wavbuf[i + 2])<<21); | ||
474 | } | ||
475 | bufsize = n*4/3; | ||
476 | } else if (bitspersample > 8) { | ||
477 | for (i = 0; i < n; i += 2) { | ||
478 | samples[i/2] = (wavbuf[i]<<13)|(SE(wavbuf[i + 1])<<21); | ||
479 | } | ||
480 | bufsize = n*2; | ||
481 | } else { | ||
482 | for (i = 0; i < n; i++) { | ||
483 | samples[i] = (wavbuf[i] - 0x80)<<21; | ||
484 | } | ||
485 | bufsize = n*4; | ||
510 | } | 486 | } |
511 | wavbufsize = n*2; | 487 | } else if (formattag == WAVE_FORMAT_ALAW |
512 | } | 488 | || formattag == IBM_FORMAT_ALAW) { |
513 | } | 489 | for (i = 0; i < n; i++) |
514 | else if (formattag == WAVE_FORMAT_ALAW || formattag == IBM_FORMAT_ALAW) { | 490 | samples[i] = alaw2linear16[wavbuf[i]] << 13; |
515 | for (i=0;i<n;i++) { | 491 | bufsize = n*4; |
516 | int16_samples[i] = alaw2linear16[wavbuf8[i]]; | 492 | } else if (formattag == WAVE_FORMAT_MULAW |
517 | } | 493 | || formattag == IBM_FORMAT_MULAW) { |
518 | wavbufsize = n*2; | 494 | for (i = 0; i < n; i++) |
519 | } | 495 | samples[i] = ulaw2linear16[wavbuf[i]] << 13; |
520 | else if (formattag == WAVE_FORMAT_MULAW || formattag == IBM_FORMAT_MULAW) { | 496 | bufsize = n*4; |
521 | for (i=0;i<n;i++) { | ||
522 | int16_samples[i] = ulaw2linear16[wavbuf8[i]]; | ||
523 | } | 497 | } |
524 | wavbufsize = n*2; | 498 | else if (formattag == WAVE_FORMAT_DVI_ADPCM) { |
525 | } | 499 | unsigned int nblocks = chunksize/blockalign; |
526 | else if (formattag == WAVE_FORMAT_DVI_ADPCM) { | 500 | |
527 | unsigned int nblocks = chunksize/blockalign; | 501 | for (i = 0; i < nblocks; i++) { |
528 | 502 | size_t decodedsize = samplesperblock*channels; | |
529 | for (i=0; i<nblocks; i++) { | 503 | if (decode_dvi_adpcm(ci, ((uint8_t *)wavbuf) + i*blockalign, |
530 | size_t decodedsize = samplesperblock*channels; | 504 | blockalign, channels, bitspersample, |
531 | if (decode_dvi_adpcm(ci, ((uint8_t*)wavbuf)+i*blockalign, | 505 | samples + i*samplesperblock*channels, |
532 | blockalign, channels, bitspersample, | 506 | &decodedsize) != CODEC_OK) |
533 | int16_samples+i*samplesperblock*channels, | 507 | i = CODEC_ERROR; |
534 | &decodedsize) | ||
535 | != CODEC_OK) { | ||
536 | i = CODEC_ERROR; | ||
537 | goto exit; | ||
538 | } | ||
539 | if (decodedsize != samplesperblock) { | ||
540 | i = CODEC_ERROR; | ||
541 | goto exit; | 508 | goto exit; |
542 | } | 509 | } |
510 | bufsize = nblocks*samplesperblock*channels*2; | ||
511 | } else { | ||
512 | DEBUGF("CODEC_ERROR: unsupported format %x\n", formattag); | ||
513 | i = CODEC_ERROR; | ||
514 | goto exit; | ||
543 | } | 515 | } |
544 | wavbufsize = nblocks*samplesperblock*channels*2; | ||
545 | } | ||
546 | else { | ||
547 | DEBUGF("CODEC_ERROR: unsupported format %x\n", formattag); | ||
548 | i = CODEC_ERROR; | ||
549 | goto exit; | ||
550 | } | ||
551 | 516 | ||
552 | while (!ci->pcmbuf_insert((char*)int16_samples, wavbufsize)) { | 517 | while (!ci->pcmbuf_insert((char *)samples, bufsize)) |
553 | ci->yield(); | 518 | ci->yield(); |
554 | } | ||
555 | 519 | ||
556 | ci->advance_buffer(n); | 520 | ci->advance_buffer(n); |
557 | bytesdone += n; | 521 | bytesdone += n; |
558 | if (bytesdone >= numbytes) { | 522 | if (bytesdone >= numbytes) |
559 | endofstream=1; | 523 | endofstream = 1; |
524 | ci->set_elapsed(bytesdone*1000LL/avgbytespersec); | ||
560 | } | 525 | } |
561 | 526 | ||
562 | ci->set_elapsed(bytesdone*1000LL/avgbytespersec); | 527 | if (ci->request_next_track()) |
563 | } | 528 | goto next_track; |
564 | |||
565 | if (ci->request_next_track()) | ||
566 | goto next_track; | ||
567 | 529 | ||
568 | i = CODEC_OK; | 530 | i = CODEC_OK; |
569 | exit: | 531 | exit: |
570 | return i; | 532 | return i; |
571 | } | 533 | } |
572 | 534 | ||
573 | static enum codec_status | 535 | static enum codec_status |
574 | decode_dvi_adpcm(struct codec_api* ci, | 536 | decode_dvi_adpcm(struct codec_api *ci, |
575 | const uint8_t *buf, | 537 | const uint8_t *buf, |
576 | int n, | 538 | int n, |
577 | uint16_t channels, uint16_t bitspersample, | 539 | uint16_t channels, uint16_t bitspersample, |
578 | int16_t *pcmout, | 540 | int32_t *pcmout, |
579 | size_t *pcmoutsize) | 541 | size_t *pcmoutsize) |
580 | { | 542 | { |
581 | size_t nsamples = 0; | 543 | size_t nsamples = 0; |
@@ -596,7 +558,7 @@ decode_dvi_adpcm(struct codec_api* ci, | |||
596 | } | 558 | } |
597 | 559 | ||
598 | /* decode block header */ | 560 | /* decode block header */ |
599 | for(c=0; c<channels && n>=4; c++) { | 561 | for (c = 0; c < channels && n >= 4; c++) { |
600 | /* decode + push first sample */ | 562 | /* decode + push first sample */ |
601 | sample[c] = (short)(buf[0]|(buf[1]<<8));/* need cast for sign-extend */ | 563 | sample[c] = (short)(buf[0]|(buf[1]<<8));/* need cast for sign-extend */ |
602 | pcmout[c] = sample[c]; | 564 | pcmout[c] = sample[c]; |
@@ -612,8 +574,8 @@ decode_dvi_adpcm(struct codec_api* ci, | |||
612 | n -= 4; | 574 | n -= 4; |
613 | } | 575 | } |
614 | if (bitspersample == 4) { | 576 | if (bitspersample == 4) { |
615 | while( n>= channels*4 && (nsamples+8*channels) <= *pcmoutsize ) { | 577 | while (n>= channels*4 && (nsamples + 8*channels) <= *pcmoutsize) { |
616 | for (c=0; c<channels; c++) { | 578 | for (c = 0; c < channels; c++) { |
617 | samplecode[0][c] = buf[0]&0xf; | 579 | samplecode[0][c] = buf[0]&0xf; |
618 | samplecode[1][c] = buf[0]>>4; | 580 | samplecode[1][c] = buf[0]>>4; |
619 | samplecode[2][c] = buf[1]&0xf; | 581 | samplecode[2][c] = buf[1]&0xf; |
@@ -625,9 +587,8 @@ decode_dvi_adpcm(struct codec_api* ci, | |||
625 | buf += 4; | 587 | buf += 4; |
626 | n -= 4; | 588 | n -= 4; |
627 | } | 589 | } |
628 | 590 | for (i = 0; i < 8; i++) { | |
629 | for (i=0; i<8; i++) { | 591 | for (c = 0; c < channels; c++) { |
630 | for (c=0; c<channels; c++) { | ||
631 | step = dvi_adpcm_steptab[stepindex[c]]; | 592 | step = dvi_adpcm_steptab[stepindex[c]]; |
632 | codem = samplecode[i][c]; | 593 | codem = samplecode[i][c]; |
633 | code = codem & 0x07; | 594 | code = codem & 0x07; |
@@ -653,7 +614,7 @@ decode_dvi_adpcm(struct codec_api* ci, | |||
653 | step = step >> 1; | 614 | step = step >> 1; |
654 | diff += step; | 615 | diff += step; |
655 | #else | 616 | #else |
656 | diff = ((code+code+1) * step) >> 3; /* faster */ | 617 | diff = ((code + code + 1) * step) >> 3; /* faster */ |
657 | #endif | 618 | #endif |
658 | /* check the sign bit */ | 619 | /* check the sign bit */ |
659 | /* check for overflow and underflow errors */ | 620 | /* check for overflow and underflow errors */ |
@@ -661,25 +622,23 @@ decode_dvi_adpcm(struct codec_api* ci, | |||
661 | sample[c] -= diff; | 622 | sample[c] -= diff; |
662 | if (sample[c] < -32768) | 623 | if (sample[c] < -32768) |
663 | sample[c] = -32768; | 624 | sample[c] = -32768; |
664 | } | 625 | } else { |
665 | else { | ||
666 | sample[c] += diff; | 626 | sample[c] += diff; |
667 | if (sample[c] > 32767) | 627 | if (sample[c] > 32767) |
668 | sample[c] = 32767; | 628 | sample[c] = 32767; |
669 | } | 629 | } |
670 | /* output the new sample */ | 630 | /* output the new sample */ |
671 | pcmout[nsamples] = sample[c]; | 631 | pcmout[nsamples] = sample[c] << 13; |
672 | nsamples++; | 632 | nsamples++; |
673 | } | 633 | } |
674 | } | 634 | } |
675 | } | 635 | } |
676 | } | 636 | } else { /* bitspersample == 3 */ |
677 | else { /* bitspersample == 3 */ | 637 | while (n >= channels*12 && (nsamples + 32*channels) <= *pcmoutsize) { |
678 | while( n>= channels*12 && (nsamples+32*channels) <= *pcmoutsize) { | 638 | for (c = 0; c < channels; c++) { |
679 | for (c=0; c<channels; c++) { | ||
680 | uint16_t bitstream = 0; | 639 | uint16_t bitstream = 0; |
681 | int bitsread = 0; | 640 | int bitsread = 0; |
682 | for (i=0; i<32 && n>0; i++) { | 641 | for (i = 0; i < 32 && n > 0; i++) { |
683 | if (bitsread < 3) { | 642 | if (bitsread < 3) { |
684 | /* read 8 more bits */ | 643 | /* read 8 more bits */ |
685 | bitstream |= buf[0]<<bitsread; | 644 | bitstream |= buf[0]<<bitsread; |
@@ -698,8 +657,8 @@ decode_dvi_adpcm(struct codec_api* ci, | |||
698 | } | 657 | } |
699 | } | 658 | } |
700 | 659 | ||
701 | for (i=0; i<32; i++) { | 660 | for (i = 0; i < 32; i++) { |
702 | for (c=0; c<channels; c++) { | 661 | for (c = 0; c < channels; c++) { |
703 | step = dvi_adpcm_steptab[stepindex[c]]; | 662 | step = dvi_adpcm_steptab[stepindex[c]]; |
704 | codem = samplecode[i][c]; | 663 | codem = samplecode[i][c]; |
705 | code = codem & 0x03; | 664 | code = codem & 0x03; |
@@ -722,7 +681,7 @@ decode_dvi_adpcm(struct codec_api* ci, | |||
722 | step = step >> 1; | 681 | step = step >> 1; |
723 | diff += step; | 682 | diff += step; |
724 | #else | 683 | #else |
725 | diff = ((code+code+1) * step) >> 3; /* faster */ | 684 | diff = ((code + code + 1) * step) >> 3; /* faster */ |
726 | #endif | 685 | #endif |
727 | /* check the sign bit */ | 686 | /* check the sign bit */ |
728 | /* check for overflow and underflow errors */ | 687 | /* check for overflow and underflow errors */ |
@@ -737,7 +696,7 @@ decode_dvi_adpcm(struct codec_api* ci, | |||
737 | sample[c] = 32767; | 696 | sample[c] = 32767; |
738 | } | 697 | } |
739 | /* output the new sample */ | 698 | /* output the new sample */ |
740 | pcmout[nsamples] = sample[c]; | 699 | pcmout[nsamples] = sample[c] << 13; |
741 | nsamples++; | 700 | nsamples++; |
742 | } | 701 | } |
743 | } | 702 | } |
@@ -749,8 +708,8 @@ decode_dvi_adpcm(struct codec_api* ci, | |||
749 | return CODEC_ERROR; | 708 | return CODEC_ERROR; |
750 | } | 709 | } |
751 | *pcmoutsize = nsamples; | 710 | *pcmoutsize = nsamples; |
752 | if (n!=0) { | 711 | if (n != 0) { |
753 | DEBUGF("decode_dvi_adpcm: n=%d unprocessed bytes\n",n); | 712 | DEBUGF("decode_dvi_adpcm: n=%d unprocessed bytes\n", n); |
754 | } | 713 | } |
755 | return CODEC_OK; | 714 | return CODEC_OK; |
756 | } | 715 | } |