summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/pcm_playback.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index da7f06fa29..e91984f842 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -47,7 +47,8 @@
47/* Must be a power of 2 */ 47/* Must be a power of 2 */
48#define NUM_PCM_BUFFERS (PCMBUF_SIZE / CHUNK_SIZE) 48#define NUM_PCM_BUFFERS (PCMBUF_SIZE / CHUNK_SIZE)
49#define NUM_PCM_BUFFERS_MASK (NUM_PCM_BUFFERS - 1) 49#define NUM_PCM_BUFFERS_MASK (NUM_PCM_BUFFERS - 1)
50#define PCM_WATERMARK (CHUNK_SIZE * 6) 50#define PCM_WATERMARK (CHUNK_SIZE * 4)
51#define PCM_CF_WATERMARK (PCMBUF_SIZE - CHUNK_SIZE*4)
51 52
52static bool pcm_playing; 53static bool pcm_playing;
53static bool pcm_paused; 54static bool pcm_paused;
@@ -345,7 +346,8 @@ void pcm_watermark_callback(int bytes_left)
345 346
346 /* Fill audio buffer by boosting cpu */ 347 /* Fill audio buffer by boosting cpu */
347 pcm_boost(true); 348 pcm_boost(true);
348 crossfade_active = false; 349 if (bytes_left <= CHUNK_SIZE * 2)
350 crossfade_active = false;
349} 351}
350 352
351void pcm_set_boost_mode(bool state) 353void pcm_set_boost_mode(bool state)
@@ -378,7 +380,7 @@ bool pcm_is_lowdata(void)
378 if (!pcm_is_playing() || pcm_paused) 380 if (!pcm_is_playing() || pcm_paused)
379 return false; 381 return false;
380 382
381 if (pcmbuf_unplayed_bytes < PCM_WATERMARK) 383 if (pcmbuf_unplayed_bytes < PCM_WATERMARK || crossfade_active)
382 return true; 384 return true;
383 385
384 return false; 386 return false;
@@ -386,14 +388,22 @@ bool pcm_is_lowdata(void)
386 388
387bool pcm_crossfade_start(void) 389bool pcm_crossfade_start(void)
388{ 390{
389 if (PCMBUF_SIZE - audiobuffer_free < CHUNK_SIZE * 4 || !crossfade_enabled) { 391 if (PCMBUF_SIZE - audiobuffer_free < CHUNK_SIZE * 8 || !crossfade_enabled) {
390 return false; 392 return false;
391 } 393 }
392 logf("crossfading!"); 394 logf("crossfading!");
395
396 if (audiobuffer_fillpos) {
397 while (!pcm_play_add_chunk(&audiobuffer[audiobuffer_pos],
398 audiobuffer_fillpos, pcm_event_handler)) {
399 yield();
400 }
401 pcm_event_handler = NULL;
402 }
393 pcm_boost(true); 403 pcm_boost(true);
394 crossfade_active = true; 404 crossfade_active = true;
395 crossfade_pos = audiobuffer_pos; 405 crossfade_pos = audiobuffer_pos;
396 crossfade_amount = (PCMBUF_SIZE - audiobuffer_free - (CHUNK_SIZE * 4))/2; 406 crossfade_amount = (PCMBUF_SIZE - audiobuffer_free - (CHUNK_SIZE * 6))/2;
397 crossfade_rem = crossfade_amount; 407 crossfade_rem = crossfade_amount;
398 audiobuffer_fillpos = 0; 408 audiobuffer_fillpos = 0;
399 409
@@ -404,20 +414,22 @@ bool pcm_crossfade_start(void)
404} 414}
405 415
406static __inline 416static __inline
407void crossfade(short *buf, const short *buf2, int length) 417int crossfade(short *buf, const short *buf2, int length)
408{ 418{
409 int i, size; 419 int i, size;
420 int val1 = (crossfade_rem)*1000/crossfade_amount;
421 int val2 = (crossfade_amount-crossfade_rem)*1000/crossfade_amount;
410 422
411 logf("cfi: %d/%d", length, crossfade_rem); 423 logf("cfi: %d/%d", length, crossfade_rem);
412 size = MIN(length, crossfade_rem); 424 size = MIN(length, crossfade_rem);
413 for (i = 0; i < length; i++) { 425 for (i = 0; i < length; i++) {
414 /* This is not yet realtime, needs optimizations for crossfade to work. */ 426 buf[i] = ((buf[i] * val1) + (buf2[i] * val2)) / 1000;
415 buf[i] = ((buf[i] * ((crossfade_rem)*1000/crossfade_amount))/1000)
416 + ((buf2[i] * ((crossfade_amount-crossfade_rem)*1000/crossfade_amount))/1000);
417 } 427 }
418 428 crossfade_rem -= i;
419 if (--crossfade_rem <= 0) 429 if (crossfade_rem <= 0)
420 crossfade_active = false; 430 crossfade_active = false;
431
432 return size;
421} 433}
422 434
423bool audiobuffer_insert(char *buf, size_t length) 435bool audiobuffer_insert(char *buf, size_t length)
@@ -440,7 +452,7 @@ bool audiobuffer_insert(char *buf, size_t length)
440 if (crossfade_active) { 452 if (crossfade_active) {
441 copy_n = MIN(length, PCMBUF_SIZE - (unsigned int)crossfade_pos); 453 copy_n = MIN(length, PCMBUF_SIZE - (unsigned int)crossfade_pos);
442 454
443 crossfade((short *)&audiobuffer[crossfade_pos], 455 copy_n = 2 * crossfade((short *)&audiobuffer[crossfade_pos],
444 (const short *)buf, copy_n/2); 456 (const short *)buf, copy_n/2);
445 buf += copy_n; 457 buf += copy_n;
446 length -= copy_n; 458 length -= copy_n;
@@ -497,9 +509,13 @@ void pcm_play_init(void)
497 pcmbuf_read_index = 0; 509 pcmbuf_read_index = 0;
498 pcmbuf_write_index = 0; 510 pcmbuf_write_index = 0;
499 pcmbuf_unplayed_bytes = 0; 511 pcmbuf_unplayed_bytes = 0;
500 crossfade_enabled = false; 512 crossfade_active = false;
501 pcm_event_handler = NULL; 513 pcm_event_handler = NULL;
502 pcm_play_set_watermark(PCM_WATERMARK, pcm_watermark_callback); 514 if (crossfade_enabled) {
515 pcm_play_set_watermark(PCM_CF_WATERMARK, pcm_watermark_callback);
516 } else {
517 pcm_play_set_watermark(PCM_WATERMARK, pcm_watermark_callback);
518 }
503} 519}
504 520
505void pcm_crossfade_enable(bool on_off) 521void pcm_crossfade_enable(bool on_off)