diff options
author | Miika Pekkarinen <miipekk@ihme.org> | 2005-06-19 20:20:16 +0000 |
---|---|---|
committer | Miika Pekkarinen <miipekk@ihme.org> | 2005-06-19 20:20:16 +0000 |
commit | fe8eb3b69859fefcadf5885427fc217dde58a58b (patch) | |
tree | 46fa43ad5acb92771380300f59b184cb898a2df4 /firmware | |
parent | b08e2acf452d9cb857e9578d93ea9ad2d14ca854 (diff) | |
download | rockbox-fe8eb3b69859fefcadf5885427fc217dde58a58b.tar.gz rockbox-fe8eb3b69859fefcadf5885427fc217dde58a58b.zip |
crossfade works much better but costs some cpu power if enabled.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6768 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/pcm_playback.c | 44 |
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 | ||
52 | static bool pcm_playing; | 53 | static bool pcm_playing; |
53 | static bool pcm_paused; | 54 | static 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 | ||
351 | void pcm_set_boost_mode(bool state) | 353 | void 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 | ||
387 | bool pcm_crossfade_start(void) | 389 | bool 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 | ||
406 | static __inline | 416 | static __inline |
407 | void crossfade(short *buf, const short *buf2, int length) | 417 | int 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 | ||
423 | bool audiobuffer_insert(char *buf, size_t length) | 435 | bool 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 | ||
505 | void pcm_crossfade_enable(bool on_off) | 521 | void pcm_crossfade_enable(bool on_off) |