summaryrefslogtreecommitdiff
path: root/apps/codecs/wav64.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-04-27 03:08:23 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-04-27 03:08:23 +0000
commitc537d5958e8b421ac4f9bef6c8b9e7425a6cf167 (patch)
tree7ed36518fb6524da7bbd913ba7619b85b5d15d23 /apps/codecs/wav64.c
parentdcf0f8de4a37ff1d2ea510aef75fa67977a8bdcc (diff)
downloadrockbox-c537d5958e8b421ac4f9bef6c8b9e7425a6cf167.tar.gz
rockbox-c537d5958e8b421ac4f9bef6c8b9e7425a6cf167.zip
Commit FS#12069 - Playback rework - first stages. Gives as thorough as possible a treatment of codec management, track change and metadata logic as possible while maintaining fairly narrow focus and not rewriting everything all at once. Please see the rockbox-dev mail archive on 2011-04-25 (Playback engine rework) for a more thorough manifest of what was addressed. Plugins and codecs become incompatible.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29785 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/wav64.c')
-rw-r--r--apps/codecs/wav64.c113
1 files changed, 48 insertions, 65 deletions
diff --git a/apps/codecs/wav64.c b/apps/codecs/wav64.c
index 9dbdab8368..c763e6f7f0 100644
--- a/apps/codecs/wav64.c
+++ b/apps/codecs/wav64.c
@@ -159,9 +159,19 @@ static uint8_t *read_buffer(size_t *realsize)
159} 159}
160 160
161/* this is the codec entry point */ 161/* this is the codec entry point */
162enum codec_status codec_main(void) 162enum codec_status codec_main(enum codec_entry_call_reason reason)
163{
164 if (reason == CODEC_LOAD) {
165 /* Generic codec initialisation */
166 ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
167 }
168
169 return CODEC_OK;
170}
171
172/* this is called for each file to process */
173enum codec_status codec_run(void)
163{ 174{
164 int status;
165 uint32_t decodedsamples; 175 uint32_t decodedsamples;
166 size_t n; 176 size_t n;
167 int bufcount; 177 int bufcount;
@@ -171,39 +181,29 @@ enum codec_status codec_main(void)
171 off_t firstblockposn; /* position of the first block in file */ 181 off_t firstblockposn; /* position of the first block in file */
172 const struct pcm_codec *codec; 182 const struct pcm_codec *codec;
173 uint64_t size; 183 uint64_t size;
174 184 intptr_t param;
175 /* Generic codec initialisation */
176 ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
177
178next_track:
179 status = CODEC_OK;
180 185
181 if (codec_init()) { 186 if (codec_init()) {
182 DEBUGF("codec_init() error\n"); 187 DEBUGF("codec_init() error\n");
183 status = CODEC_ERROR; 188 return CODEC_ERROR;
184 goto exit;
185 } 189 }
186 190
187 if (codec_wait_taginfo() != 0)
188 goto done;
189
190 codec_set_replaygain(ci->id3); 191 codec_set_replaygain(ci->id3);
191 192
192 /* Need to save offset for later use (cleared indirectly by advance_buffer) */ 193 /* Need to save offset for later use (cleared indirectly by advance_buffer) */
193 bytesdone = ci->id3->offset; 194 bytesdone = ci->id3->offset;
194 195
195 /* get RIFF chunk header */ 196 /* get RIFF chunk header */
197 ci->seek_buffer(0);
196 buf = ci->request_buffer(&n, 40); 198 buf = ci->request_buffer(&n, 40);
197 if (n < 40) { 199 if (n < 40) {
198 DEBUGF("request_buffer error\n"); 200 DEBUGF("request_buffer error\n");
199 status = CODEC_ERROR; 201 return CODEC_ERROR;
200 goto done;
201 } 202 }
202 if ((memcmp(buf , WAVE64_GUID_RIFF, 16) != 0) || 203 if ((memcmp(buf , WAVE64_GUID_RIFF, 16) != 0) ||
203 (memcmp(buf+24, WAVE64_GUID_WAVE, 16) != 0)) 204 (memcmp(buf+24, WAVE64_GUID_WAVE, 16) != 0))
204 { 205 {
205 status = CODEC_ERROR; 206 return CODEC_ERROR;
206 goto done;
207 } 207 }
208 208
209 /* advance to first WAVE chunk */ 209 /* advance to first WAVE chunk */
@@ -224,8 +224,7 @@ next_track:
224 if (n < 8) { 224 if (n < 8) {
225 DEBUGF("data chunk request_buffer error\n"); 225 DEBUGF("data chunk request_buffer error\n");
226 /* no more chunks, 'data' chunk must not have been found */ 226 /* no more chunks, 'data' chunk must not have been found */
227 status = CODEC_ERROR; 227 return CODEC_ERROR;
228 goto done;
229 } 228 }
230 229
231 /* chunkSize */ 230 /* chunkSize */
@@ -233,8 +232,7 @@ next_track:
233 if (memcmp(buf, WAVE64_GUID_FMT, 16) == 0) { 232 if (memcmp(buf, WAVE64_GUID_FMT, 16) == 0) {
234 if (size < 16) { 233 if (size < 16) {
235 DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%d < 16\n", (int)size); 234 DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%d < 16\n", (int)size);
236 status = CODEC_ERROR; 235 return CODEC_ERROR;
237 goto done;
238 } 236 }
239 /* wFormatTag */ 237 /* wFormatTag */
240 format.formattag=buf[24]|(buf[25]<<8); 238 format.formattag=buf[24]|(buf[25]<<8);
@@ -263,8 +261,7 @@ next_track:
263 if (format.size < 22) { 261 if (format.size < 22) {
264 DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " 262 DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is "
265 "missing extension\n"); 263 "missing extension\n");
266 status = CODEC_ERROR; 264 return CODEC_ERROR;
267 goto done;
268 } 265 }
269 /* wValidBitsPerSample */ 266 /* wValidBitsPerSample */
270 format.bitspersample = buf[42]|(buf[43]<<8); 267 format.bitspersample = buf[42]|(buf[43]<<8);
@@ -279,10 +276,7 @@ next_track:
279 if (format.formattag == WAVE_FORMAT_ADPCM) 276 if (format.formattag == WAVE_FORMAT_ADPCM)
280 { 277 {
281 if (!set_msadpcm_coeffs(buf)) 278 if (!set_msadpcm_coeffs(buf))
282 { 279 return CODEC_ERROR;
283 status = CODEC_ERROR;
284 goto done;
285 }
286 } 280 }
287 281
288 /* get codec */ 282 /* get codec */
@@ -291,8 +285,7 @@ next_track:
291 { 285 {
292 DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n", 286 DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n",
293 (unsigned int) format.formattag); 287 (unsigned int) format.formattag);
294 status = CODEC_ERROR; 288 return CODEC_ERROR;
295 goto done;
296 } 289 }
297 290
298 /* riff 8bit linear pcm is unsigned */ 291 /* riff 8bit linear pcm is unsigned */
@@ -301,10 +294,7 @@ next_track:
301 294
302 /* check format, and calculate chunk size */ 295 /* check format, and calculate chunk size */
303 if (!codec->set_format(&format)) 296 if (!codec->set_format(&format))
304 { 297 return CODEC_ERROR;
305 status = CODEC_ERROR;
306 goto done;
307 }
308 } else if (memcmp(buf, WAVE64_GUID_DATA, 16) == 0) { 298 } else if (memcmp(buf, WAVE64_GUID_DATA, 16) == 0) {
309 format.numbytes = size; 299 format.numbytes = size;
310 /* advance to start of data */ 300 /* advance to start of data */
@@ -330,31 +320,26 @@ next_track:
330 if (!codec) 320 if (!codec)
331 { 321 {
332 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n"); 322 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n");
333 status = CODEC_ERROR; 323 return CODEC_ERROR;
334 goto done;
335 } 324 }
336 325
337 /* common format check */ 326 /* common format check */
338 if (format.channels == 0) { 327 if (format.channels == 0) {
339 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); 328 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n");
340 status = CODEC_ERROR; 329 return CODEC_ERROR;
341 goto done;
342 } 330 }
343 if (format.samplesperblock == 0) { 331 if (format.samplesperblock == 0) {
344 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n"); 332 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n");
345 status = CODEC_ERROR; 333 return CODEC_ERROR;
346 goto done;
347 } 334 }
348 if (format.blockalign == 0) 335 if (format.blockalign == 0)
349 { 336 {
350 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n"); 337 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n");
351 status = CODEC_ERROR; 338 return CODEC_ERROR;
352 goto done;
353 } 339 }
354 if (format.numbytes == 0) { 340 if (format.numbytes == 0) {
355 DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); 341 DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n");
356 status = CODEC_ERROR; 342 return CODEC_ERROR;
357 goto done;
358 } 343 }
359 344
360 /* check chunksize */ 345 /* check chunksize */
@@ -364,8 +349,7 @@ next_track:
364 if (format.chunksize == 0) 349 if (format.chunksize == 0)
365 { 350 {
366 DEBUGF("CODEC_ERROR: chunksize is 0\n"); 351 DEBUGF("CODEC_ERROR: chunksize is 0\n");
367 status = CODEC_ERROR; 352 return CODEC_ERROR;
368 goto done;
369 } 353 }
370 354
371 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); 355 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
@@ -375,8 +359,7 @@ next_track:
375 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); 359 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
376 } else { 360 } else {
377 DEBUGF("CODEC_ERROR: more than 2 channels\n"); 361 DEBUGF("CODEC_ERROR: more than 2 channels\n");
378 status = CODEC_ERROR; 362 return CODEC_ERROR;
379 goto done;
380 } 363 }
381 364
382 /* make sure we're at the correct offset */ 365 /* make sure we're at the correct offset */
@@ -385,14 +368,14 @@ next_track:
385 struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, 368 struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn,
386 PCM_SEEK_POS, &read_buffer); 369 PCM_SEEK_POS, &read_buffer);
387 370
388 if (newpos->pos > format.numbytes) 371 if (newpos->pos > format.numbytes) {
389 goto done; 372 return CODEC_OK;
373 }
390 if (ci->seek_buffer(firstblockposn + newpos->pos)) 374 if (ci->seek_buffer(firstblockposn + newpos->pos))
391 { 375 {
392 bytesdone = newpos->pos; 376 bytesdone = newpos->pos;
393 decodedsamples = newpos->samples; 377 decodedsamples = newpos->samples;
394 } 378 }
395 ci->seek_complete();
396 } else { 379 } else {
397 /* already where we need to be */ 380 /* already where we need to be */
398 bytesdone = 0; 381 bytesdone = 0;
@@ -402,22 +385,29 @@ next_track:
402 endofstream = 0; 385 endofstream = 0;
403 386
404 while (!endofstream) { 387 while (!endofstream) {
405 ci->yield(); 388 enum codec_command_action action = ci->get_command(&param);
406 if (ci->stop_codec || ci->new_track) { 389
390 if (action == CODEC_ACTION_HALT)
407 break; 391 break;
408 }
409 392
410 if (ci->seek_time) { 393 if (action == CODEC_ACTION_SEEK_TIME) {
411 struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, 394 struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME,
412 &read_buffer); 395 &read_buffer);
413 396
414 if (newpos->pos > format.numbytes) 397 if (newpos->pos > format.numbytes)
398 {
399 ci->set_elapsed(ci->id3->length);
400 ci->seek_complete();
415 break; 401 break;
402 }
403
416 if (ci->seek_buffer(firstblockposn + newpos->pos)) 404 if (ci->seek_buffer(firstblockposn + newpos->pos))
417 { 405 {
418 bytesdone = newpos->pos; 406 bytesdone = newpos->pos;
419 decodedsamples = newpos->samples; 407 decodedsamples = newpos->samples;
420 } 408 }
409
410 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
421 ci->seek_complete(); 411 ci->seek_complete();
422 } 412 }
423 413
@@ -429,11 +419,10 @@ next_track:
429 endofstream = 1; 419 endofstream = 1;
430 } 420 }
431 421
432 status = codec->decode(wavbuf, n, samples, &bufcount); 422 if (codec->decode(wavbuf, n, samples, &bufcount) == CODEC_ERROR)
433 if (status == CODEC_ERROR)
434 { 423 {
435 DEBUGF("codec error\n"); 424 DEBUGF("codec error\n");
436 goto done; 425 return CODEC_ERROR;
437 } 426 }
438 427
439 ci->pcmbuf_insert(samples, NULL, bufcount); 428 ci->pcmbuf_insert(samples, NULL, bufcount);
@@ -445,12 +434,6 @@ next_track:
445 endofstream = 1; 434 endofstream = 1;
446 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); 435 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
447 } 436 }
448 status = CODEC_OK;
449
450done:
451 if (ci->request_next_track())
452 goto next_track;
453 437
454exit: 438 return CODEC_OK;
455 return status;
456} 439}