summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2005-06-26 19:41:29 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2005-06-26 19:41:29 +0000
commitd8cb703b1e86c9f910211a976d8bed0c7a99379a (patch)
tree6db3b698d83e639974bd6603225ff11891652113 /firmware
parent316eb6538e2fc88efa93248deb761679071409f1 (diff)
downloadrockbox-d8cb703b1e86c9f910211a976d8bed0c7a99379a.tar.gz
rockbox-d8cb703b1e86c9f910211a976d8bed0c7a99379a.zip
Initial DSP implementation. DSP supports resampling audio stream from
codecs (currently works corrently only with mp3's, somebody should fix that). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6877 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/pcm_playback.h8
-rw-r--r--firmware/pcm_playback.c133
2 files changed, 120 insertions, 21 deletions
diff --git a/firmware/export/pcm_playback.h b/firmware/export/pcm_playback.h
index aa29601f70..3fe60670b3 100644
--- a/firmware/export/pcm_playback.h
+++ b/firmware/export/pcm_playback.h
@@ -19,6 +19,10 @@
19#ifndef PCM_PLAYBACK_H 19#ifndef PCM_PLAYBACK_H
20#define PCM_PLAYBACK_H 20#define PCM_PLAYBACK_H
21 21
22/* Guard buffer for crossfader when dsp is enabled. */
23#define PCMBUF_GUARD 32768
24
25/* PCM audio buffer. */
22#define PCMBUF_SIZE (1*1024*1024) 26#define PCMBUF_SIZE (1*1024*1024)
23 27
24void pcm_init(void); 28void pcm_init(void);
@@ -44,7 +48,9 @@ bool pcm_is_lowdata(void);
44bool pcm_crossfade_init(void); 48bool pcm_crossfade_init(void);
45void audiobuffer_add_event(void (*event_handler)(void)); 49void audiobuffer_add_event(void (*event_handler)(void));
46unsigned int audiobuffer_get_latency(void); 50unsigned int audiobuffer_get_latency(void);
47bool audiobuffer_insert(char *buf, size_t length); 51bool pcm_insert_buffer(char *buf, size_t length);
52void pcm_flush_buffer(size_t length);
53void* pcm_request_buffer(size_t length, size_t *realsize);
48bool pcm_is_crossfade_enabled(void); 54bool pcm_is_crossfade_enabled(void);
49void pcm_crossfade_enable(bool on_off); 55void pcm_crossfade_enable(bool on_off);
50 56
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index 24fc5d4530..12ecfd14e2 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -67,6 +67,7 @@ static int crossfade_pos;
67static int crossfade_amount; 67static int crossfade_amount;
68static int crossfade_rem; 68static int crossfade_rem;
69 69
70static char *guardbuf;
70static void (*pcm_event_handler)(void); 71static void (*pcm_event_handler)(void);
71 72
72static unsigned char *next_start; 73static unsigned char *next_start;
@@ -258,7 +259,6 @@ void pcm_play_pause(bool play)
258 IIS2CONFIG = 0x800; 259 IIS2CONFIG = 0x800;
259 } 260 }
260 pcm_paused = !play; 261 pcm_paused = !play;
261 pcm_boost(false);
262} 262}
263 263
264bool pcm_is_playing(void) 264bool pcm_is_playing(void)
@@ -401,15 +401,8 @@ bool pcm_crossfade_init(void)
401 401
402} 402}
403 403
404static void crossfade_start(void) 404void pcm_flush_fillpos(void)
405{ 405{
406 if (!crossfade_init)
407 return ;
408
409 crossfade_init = 0;
410 if (PCMBUF_SIZE - audiobuffer_free < CHUNK_SIZE * 6)
411 return ;
412
413 if (audiobuffer_fillpos) { 406 if (audiobuffer_fillpos) {
414 while (!pcm_play_add_chunk(&audiobuffer[audiobuffer_pos], 407 while (!pcm_play_add_chunk(&audiobuffer[audiobuffer_pos],
415 audiobuffer_fillpos, pcm_event_handler)) { 408 audiobuffer_fillpos, pcm_event_handler)) {
@@ -419,13 +412,26 @@ static void crossfade_start(void)
419 audiobuffer_pos += audiobuffer_fillpos; 412 audiobuffer_pos += audiobuffer_fillpos;
420 if (audiobuffer_pos >= PCMBUF_SIZE) 413 if (audiobuffer_pos >= PCMBUF_SIZE)
421 audiobuffer_pos -= PCMBUF_SIZE; 414 audiobuffer_pos -= PCMBUF_SIZE;
415 audiobuffer_free -= audiobuffer_fillpos;
416 audiobuffer_fillpos = 0;
422 } 417 }
418}
419
420static void crossfade_start(void)
421{
422 if (!crossfade_init)
423 return ;
424
425 crossfade_init = 0;
426 if (PCMBUF_SIZE - audiobuffer_free < CHUNK_SIZE * 6)
427 return ;
428
429 pcm_flush_fillpos();
423 pcm_boost(true); 430 pcm_boost(true);
424 crossfade_active = true; 431 crossfade_active = true;
425 crossfade_pos = audiobuffer_pos; 432 crossfade_pos = audiobuffer_pos;
426 crossfade_amount = (PCMBUF_SIZE - audiobuffer_free - (CHUNK_SIZE * 2))/2; 433 crossfade_amount = (PCMBUF_SIZE - audiobuffer_free - (CHUNK_SIZE * 2))/2;
427 crossfade_rem = crossfade_amount; 434 crossfade_rem = crossfade_amount;
428 audiobuffer_fillpos = 0;
429 435
430 crossfade_pos -= crossfade_amount*2; 436 crossfade_pos -= crossfade_amount*2;
431 if (crossfade_pos < 0) 437 if (crossfade_pos < 0)
@@ -451,12 +457,11 @@ int crossfade(short *buf, const short *buf2, int length)
451 return size; 457 return size;
452} 458}
453 459
454bool audiobuffer_insert(char *buf, size_t length) 460inline static bool prepare_insert(size_t length)
455{ 461{
456 size_t copy_n = 0;
457
458 crossfade_start(); 462 crossfade_start();
459 if (audiobuffer_free < length + CHUNK_SIZE && !crossfade_active) { 463 if (audiobuffer_free < length + audiobuffer_fillpos
464 + CHUNK_SIZE && !crossfade_active) {
460 pcm_boost(false); 465 pcm_boost(false);
461 return false; 466 return false;
462 } 467 }
@@ -467,7 +472,94 @@ bool audiobuffer_insert(char *buf, size_t length)
467 if (audiobuffer_free < PCMBUF_SIZE - CHUNK_SIZE*4) 472 if (audiobuffer_free < PCMBUF_SIZE - CHUNK_SIZE*4)
468 pcm_play_start(); 473 pcm_play_start();
469 } 474 }
475
476 return true;
477}
478
479void* pcm_request_buffer(size_t length, size_t *realsize)
480{
481 void *ptr = NULL;
482
483 if (!prepare_insert(length)) {
484 *realsize = 0;
485 return NULL;
486 }
487
488 if (crossfade_active) {
489 *realsize = MIN(length, PCMBUF_GUARD);
490 ptr = &guardbuf[0];
491 } else {
492 *realsize = MIN(length, PCMBUF_SIZE - audiobuffer_pos
493 - audiobuffer_fillpos);
494 if (*realsize < length) {
495 *realsize += MIN((long)(length - *realsize), PCMBUF_GUARD);
496 //logf("gbr:%d/%d", *realsize, length);
497 }
498 ptr = &audiobuffer[audiobuffer_pos + audiobuffer_fillpos];
499 }
500
501 return ptr;
502}
503
504void pcm_flush_buffer(size_t length)
505{
506 int copy_n;
507 char *buf;
508
509 if (crossfade_active) {
510 buf = &guardbuf[0];
511 length = MIN(length, PCMBUF_GUARD);
512 while (length > 0 && crossfade_active) {
513 copy_n = MIN(length, PCMBUF_SIZE - (unsigned int)crossfade_pos);
514 copy_n = 2 * crossfade((short *)&audiobuffer[crossfade_pos],
515 (const short *)buf, copy_n/2);
516 buf += copy_n;
517 length -= copy_n;
518 crossfade_pos += copy_n;
519 if (crossfade_pos >= PCMBUF_SIZE)
520 crossfade_pos -= PCMBUF_SIZE;
521 }
522
523 if (length > 0) {
524 memcpy(&audiobuffer[audiobuffer_pos], buf, length);
525 audiobuffer_fillpos = length;
526 goto try_flush;
527 }
528 } else {
529 /* if (length == 0) {
530 pcm_flush_fillpos();
531 audiobuffer_pos = 0;
532 return ;
533 } */
534
535 audiobuffer_fillpos += length;
536
537 try_flush:
538 if (audiobuffer_fillpos < CHUNK_SIZE && PCMBUF_SIZE
539 - audiobuffer_pos - audiobuffer_fillpos > 0)
540 return ;
541
542 copy_n = MIN((long)(audiobuffer_fillpos - (PCMBUF_SIZE
543 - audiobuffer_pos)), PCMBUF_GUARD);
544 if (copy_n > 0) {
545 //logf("guard buf used:%d", copy_n);
546 audiobuffer_fillpos -= copy_n;
547 pcm_flush_fillpos();
548 memcpy(&audiobuffer[0], &guardbuf[0], copy_n);
549 audiobuffer_fillpos = copy_n;
550 goto try_flush;
551 }
552 pcm_flush_fillpos();
553 }
554}
470 555
556bool pcm_insert_buffer(char *buf, size_t length)
557{
558 size_t copy_n = 0;
559
560 if (!prepare_insert(length))
561 return false;
562
471 while (length > 0) { 563 while (length > 0) {
472 if (crossfade_active) { 564 if (crossfade_active) {
473 copy_n = MIN(length, PCMBUF_SIZE - (unsigned int)crossfade_pos); 565 copy_n = MIN(length, PCMBUF_SIZE - (unsigned int)crossfade_pos);
@@ -521,7 +613,8 @@ bool audiobuffer_insert(char *buf, size_t length)
521void pcm_play_init(void) 613void pcm_play_init(void)
522{ 614{
523 audiobuffer = &audiobuf[(audiobufend - audiobuf) - 615 audiobuffer = &audiobuf[(audiobufend - audiobuf) -
524 PCMBUF_SIZE]; 616 PCMBUF_SIZE - PCMBUF_GUARD];
617 guardbuf = &audiobuffer[PCMBUF_SIZE];
525 audiobuffer_free = PCMBUF_SIZE; 618 audiobuffer_free = PCMBUF_SIZE;
526 audiobuffer_pos = 0; 619 audiobuffer_pos = 0;
527 audiobuffer_fillpos = 0; 620 audiobuffer_fillpos = 0;
@@ -532,11 +625,6 @@ void pcm_play_init(void)
532 crossfade_active = false; 625 crossfade_active = false;
533 crossfade_init = false; 626 crossfade_init = false;
534 pcm_event_handler = NULL; 627 pcm_event_handler = NULL;
535 if (crossfade_enabled) {
536 pcm_play_set_watermark(PCM_CF_WATERMARK, pcm_watermark_callback);
537 } else {
538 pcm_play_set_watermark(PCM_WATERMARK, pcm_watermark_callback);
539 }
540} 628}
541 629
542void pcm_crossfade_enable(bool on_off) 630void pcm_crossfade_enable(bool on_off)
@@ -555,6 +643,11 @@ void pcm_play_start(void)
555 int size; 643 int size;
556 char *start; 644 char *start;
557 645
646 if (crossfade_enabled) {
647 pcm_play_set_watermark(PCM_CF_WATERMARK, pcm_watermark_callback);
648 } else {
649 pcm_play_set_watermark(PCM_WATERMARK, pcm_watermark_callback);
650 }
558 crossfade_active = false; 651 crossfade_active = false;
559 if(!pcm_is_playing()) 652 if(!pcm_is_playing())
560 { 653 {