summaryrefslogtreecommitdiff
path: root/apps/pcmbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/pcmbuf.c')
-rw-r--r--apps/pcmbuf.c67
1 files changed, 47 insertions, 20 deletions
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c
index 93ce4266c1..2cec40b7e7 100644
--- a/apps/pcmbuf.c
+++ b/apps/pcmbuf.c
@@ -26,6 +26,7 @@
26#include "pcmbuf.h" 26#include "pcmbuf.h"
27#include "pcm.h" 27#include "pcm.h"
28#include "playback.h" 28#include "playback.h"
29#include "codec_thread.h"
29 30
30/* Define LOGF_ENABLE to enable logf output in this file */ 31/* Define LOGF_ENABLE to enable logf output in this file */
31/*#define LOGF_ENABLE*/ 32/*#define LOGF_ENABLE*/
@@ -86,8 +87,7 @@ static size_t pcmbuffer_pos IDATA_ATTR;
86static size_t pcmbuffer_fillpos IDATA_ATTR; 87static size_t pcmbuffer_fillpos IDATA_ATTR;
87 88
88/* Gapless playback */ 89/* Gapless playback */
89static bool end_of_track IDATA_ATTR; 90static bool track_transition IDATA_ATTR;
90bool track_transition IDATA_ATTR;
91 91
92#ifdef HAVE_CROSSFADE 92#ifdef HAVE_CROSSFADE
93/* Crossfade buffer */ 93/* Crossfade buffer */
@@ -131,8 +131,6 @@ static bool flush_pcmbuf = false;
131static int codec_thread_priority = PRIORITY_PLAYBACK; 131static int codec_thread_priority = PRIORITY_PLAYBACK;
132#endif 132#endif
133 133
134extern unsigned int codec_thread_id;
135
136/* Helpful macros for use in conditionals this assumes some of the above 134/* Helpful macros for use in conditionals this assumes some of the above
137 * static variable names */ 135 * static variable names */
138#define COMMIT_IF_NEEDED if(pcmbuffer_fillpos > PCMBUF_TARGET_CHUNK || \ 136#define COMMIT_IF_NEEDED if(pcmbuffer_fillpos > PCMBUF_TARGET_CHUNK || \
@@ -223,9 +221,8 @@ static void commit_chunk(bool flush_next_time)
223 /* Fill in the values in the new buffer chunk */ 221 /* Fill in the values in the new buffer chunk */
224 pcmbuf_current->addr = &pcmbuffer[pcmbuffer_pos]; 222 pcmbuf_current->addr = &pcmbuffer[pcmbuffer_pos];
225 pcmbuf_current->size = size; 223 pcmbuf_current->size = size;
226 pcmbuf_current->end_of_track = end_of_track; 224 pcmbuf_current->end_of_track = false;
227 pcmbuf_current->link = NULL; 225 pcmbuf_current->link = NULL;
228 end_of_track = false; /* This is single use only */
229 226
230 if (read_chunk != NULL) 227 if (read_chunk != NULL)
231 { 228 {
@@ -297,7 +294,7 @@ static void boost_codec_thread(int pcm_fill_state)
297 * will starve if the codec thread's priority is boosted. */ 294 * will starve if the codec thread's priority is boosted. */
298 if (new_prio != codec_thread_priority) 295 if (new_prio != codec_thread_priority)
299 { 296 {
300 thread_set_priority(codec_thread_id, new_prio); 297 codec_thread_set_priority(new_prio);
301 voice_thread_set_priority(new_prio); 298 voice_thread_set_priority(new_prio);
302 codec_thread_priority = new_prio; 299 codec_thread_priority = new_prio;
303 } 300 }
@@ -327,7 +324,7 @@ static bool prepare_insert(size_t length)
327 /* Only codec thread initiates boost - voice boosts the cpu when playing 324 /* Only codec thread initiates boost - voice boosts the cpu when playing
328 a clip */ 325 a clip */
329#ifndef SIMULATOR 326#ifndef SIMULATOR
330 if (thread_get_current() == codec_thread_id) 327 if (is_codec_thread())
331#endif /* SIMULATOR */ 328#endif /* SIMULATOR */
332 { 329 {
333 /* boost cpu if necessary */ 330 /* boost cpu if necessary */
@@ -487,6 +484,27 @@ size_t pcmbuf_init(unsigned char *bufend)
487 484
488 485
489/** Track change */ 486/** Track change */
487void pcmbuf_monitor_track_change(bool monitor)
488{
489 pcm_play_lock();
490
491 if (last_chunksize != 0)
492 {
493 /* If monitoring, wait until this track runs out. Place in
494 currently playing chunk. If not, cancel notification. */
495 track_transition = monitor;
496 read_end_chunk->end_of_track = monitor;
497 }
498 else
499 {
500 /* Post now if PCM stopped and last buffer was sent. */
501 track_transition = false;
502 if (monitor)
503 audio_post_track_change(false);
504 }
505
506 pcm_play_unlock();
507}
490 508
491void pcmbuf_start_track_change(bool auto_skip) 509void pcmbuf_start_track_change(bool auto_skip)
492{ 510{
@@ -523,6 +541,11 @@ void pcmbuf_start_track_change(bool auto_skip)
523 { logf(" crossfade track change"); } 541 { logf(" crossfade track change"); }
524 else 542 else
525 { logf(" manual track change"); } 543 { logf(" manual track change"); }
544
545 pcm_play_lock();
546
547 /* Cancel any pending automatic gapless transition */
548 pcmbuf_monitor_track_change(false);
526 549
527 /* Notify the wps that the track change starts now */ 550 /* Notify the wps that the track change starts now */
528 audio_post_track_change(false); 551 audio_post_track_change(false);
@@ -535,26 +558,32 @@ void pcmbuf_start_track_change(bool auto_skip)
535 !pcm_is_playing()) 558 !pcm_is_playing())
536 { 559 {
537 pcmbuf_play_stop(); 560 pcmbuf_play_stop();
561 pcm_play_unlock();
538 return; 562 return;
539 } 563 }
540 564
541 trigger_cpu_boost();
542
543 /* Not enough data, or not crossfading, flush the old data instead */ 565 /* Not enough data, or not crossfading, flush the old data instead */
544 if (LOW_DATA(2) || !crossfade || low_latency_mode) 566 if (LOW_DATA(2) || !crossfade || low_latency_mode)
545 { 567 {
546 commit_chunk(true); 568 commit_chunk(true);
547 return;
548 } 569 }
549
550#ifdef HAVE_CROSSFADE 570#ifdef HAVE_CROSSFADE
551 /* Don't enable mix mode when skipping tracks manually. */ 571 else
552 crossfade_mixmode = auto_skip && global_settings.crossfade_fade_out_mixmode; 572 {
553 573 /* Don't enable mix mode when skipping tracks manually. */
554 crossfade_auto_skip = auto_skip; 574 crossfade_mixmode = auto_skip &&
575 global_settings.crossfade_fade_out_mixmode;
576
577 crossfade_auto_skip = auto_skip;
555 578
556 crossfade_track_change_started = crossfade; 579 crossfade_track_change_started = crossfade;
580 }
557#endif 581#endif
582 pcm_play_unlock();
583
584 /* Keep trigger outside the play lock or HW FIFO underruns can happen
585 since frequency scaling is *not* always fast */
586 trigger_cpu_boost();
558 } 587 }
559 else /* automatic and not crossfading, so do gapless track change */ 588 else /* automatic and not crossfading, so do gapless track change */
560 { 589 {
@@ -563,8 +592,7 @@ void pcmbuf_start_track_change(bool auto_skip)
563 * current track will be updated properly, and mark the current chunk 592 * current track will be updated properly, and mark the current chunk
564 * as the last one in the track. */ 593 * as the last one in the track. */
565 logf(" gapless track change"); 594 logf(" gapless track change");
566 track_transition = true; 595 pcmbuf_monitor_track_change(true);
567 end_of_track = true;
568 } 596 }
569} 597}
570 598
@@ -674,7 +702,6 @@ void pcmbuf_play_stop(void)
674 crossfade_track_change_started = false; 702 crossfade_track_change_started = false;
675 crossfade_active = false; 703 crossfade_active = false;
676#endif 704#endif
677 end_of_track = false;
678 track_transition = false; 705 track_transition = false;
679 flush_pcmbuf = false; 706 flush_pcmbuf = false;
680 DISPLAY_DESC("play_stop"); 707 DISPLAY_DESC("play_stop");