summaryrefslogtreecommitdiff
path: root/apps/pcmbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/pcmbuf.c')
-rw-r--r--apps/pcmbuf.c122
1 files changed, 52 insertions, 70 deletions
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c
index a39a69a21c..cda20d9f48 100644
--- a/apps/pcmbuf.c
+++ b/apps/pcmbuf.c
@@ -92,7 +92,7 @@ static bool crossfade_enabled;
92static bool crossfade_enable_request; 92static bool crossfade_enable_request;
93static bool crossfade_mixmode; 93static bool crossfade_mixmode;
94static bool crossfade_active IDATA_ATTR; 94static bool crossfade_active IDATA_ATTR;
95static bool crossfade_init IDATA_ATTR; 95static bool crossfade_track_change_started IDATA_ATTR;
96 96
97/* Track the current location for processing crossfade */ 97/* Track the current location for processing crossfade */
98static struct chunkdesc *crossfade_chunk IDATA_ATTR; 98static struct chunkdesc *crossfade_chunk IDATA_ATTR;
@@ -132,12 +132,11 @@ extern unsigned int codec_thread_id;
132#define LOW_DATA(quarter_secs) \ 132#define LOW_DATA(quarter_secs) \
133 (pcmbuf_unplayed_bytes < NATIVE_FREQUENCY * quarter_secs) 133 (pcmbuf_unplayed_bytes < NATIVE_FREQUENCY * quarter_secs)
134 134
135static void pcmbuf_finish_track_change(void); 135static void finish_gapless_track_change(void);
136#ifdef HAVE_CROSSFADE 136#ifdef HAVE_CROSSFADE
137static void crossfade_start(void); 137static void crossfade_start(void);
138static void flush_crossfade(char *buf, size_t length); 138static void flush_crossfade(char *buf, size_t length);
139#endif 139#endif
140static bool pcmbuf_crossfade_init(bool manual_skip);
141static void pcmbuf_finish_crossfade_enable(void); 140static void pcmbuf_finish_crossfade_enable(void);
142static bool pcmbuf_is_crossfade_enabled(void); 141static bool pcmbuf_is_crossfade_enabled(void);
143 142
@@ -348,7 +347,7 @@ static bool prepare_insert(size_t length)
348void *pcmbuf_request_buffer(int *count) 347void *pcmbuf_request_buffer(int *count)
349{ 348{
350#ifdef HAVE_CROSSFADE 349#ifdef HAVE_CROSSFADE
351 if (crossfade_init) 350 if (crossfade_track_change_started)
352 crossfade_start(); 351 crossfade_start();
353#endif 352#endif
354 353
@@ -401,7 +400,7 @@ void pcmbuf_write_complete(int count)
401 400
402/* Init */ 401/* Init */
403 402
404static void pcmbuf_init_pcmbuffers(void) 403static inline void init_pcmbuffers(void)
405{ 404{
406#ifdef DESC_DEBUG 405#ifdef DESC_DEBUG
407 first_desc = write_chunk; 406 first_desc = write_chunk;
@@ -417,7 +416,7 @@ static void pcmbuf_init_pcmbuffers(void)
417 DISPLAY_DESC("init"); 416 DISPLAY_DESC("init");
418} 417}
419 418
420static size_t pcmbuf_get_next_required_pcmbuf_size(void) 419static size_t get_next_required_pcmbuf_size(void)
421{ 420{
422 size_t seconds = 1; 421 size_t seconds = 1;
423 422
@@ -444,13 +443,13 @@ static char *pcmbuf_calc_pcmbuffer_ptr(size_t bufsize)
444size_t pcmbuf_init(unsigned char *bufend) 443size_t pcmbuf_init(unsigned char *bufend)
445{ 444{
446 pcmbuf_bufend = bufend; 445 pcmbuf_bufend = bufend;
447 pcmbuf_size = pcmbuf_get_next_required_pcmbuf_size(); 446 pcmbuf_size = get_next_required_pcmbuf_size();
448 pcmbuffer = pcmbuf_calc_pcmbuffer_ptr(pcmbuf_size); 447 pcmbuffer = pcmbuf_calc_pcmbuffer_ptr(pcmbuf_size);
449 fadebuf = &pcmbuffer[pcmbuf_size]; 448 fadebuf = &pcmbuffer[pcmbuf_size];
450 voicebuf = &fadebuf[PCMBUF_MIX_CHUNK]; 449 voicebuf = &fadebuf[PCMBUF_MIX_CHUNK];
451 write_chunk = (struct chunkdesc *)&voicebuf[PCMBUF_MIX_CHUNK]; 450 write_chunk = (struct chunkdesc *)&voicebuf[PCMBUF_MIX_CHUNK];
452 451
453 pcmbuf_init_pcmbuffers(); 452 init_pcmbuffers();
454 453
455 if(track_transition){logf("pcmbuf: (init) track transition false");} 454 if(track_transition){logf("pcmbuf: (init) track transition false");}
456 end_of_track = false; 455 end_of_track = false;
@@ -488,7 +487,7 @@ static void pcmbuf_pcm_callback(unsigned char** start, size_t* size)
488 487
489 /* if last buffer in the track, let the audio thread know */ 488 /* if last buffer in the track, let the audio thread know */
490 if (pcmbuf_current->end_of_track) 489 if (pcmbuf_current->end_of_track)
491 pcmbuf_finish_track_change(); 490 finish_gapless_track_change();
492 491
493 /* Put the finished buffer back into circulation */ 492 /* Put the finished buffer back into circulation */
494 write_end_chunk->link = pcmbuf_current; 493 write_end_chunk->link = pcmbuf_current;
@@ -532,7 +531,7 @@ static void pcmbuf_pcm_callback(unsigned char** start, size_t* size)
532 *realsize = 0; 531 *realsize = 0;
533 *realstart = NULL; 532 *realstart = NULL;
534 if (end_of_track) 533 if (end_of_track)
535 pcmbuf_finish_track_change(); 534 finish_gapless_track_change();
536 } 535 }
537 } 536 }
538 DISPLAY_DESC("callback"); 537 DISPLAY_DESC("callback");
@@ -563,7 +562,7 @@ void pcmbuf_play_stop(void)
563 } 562 }
564 pcmbuffer_pos = 0; 563 pcmbuffer_pos = 0;
565 pcmbuffer_fillpos = 0; 564 pcmbuffer_fillpos = 0;
566 crossfade_init = false; 565 crossfade_track_change_started = false;
567 crossfade_active = false; 566 crossfade_active = false;
568 flush_pcmbuf = false; 567 flush_pcmbuf = false;
569 DISPLAY_DESC("play_stop"); 568 DISPLAY_DESC("play_stop");
@@ -587,7 +586,7 @@ void pcmbuf_pause(bool pause)
587 * still playing. Set flags to make sure the elapsed time of the current 586 * still playing. Set flags to make sure the elapsed time of the current
588 * track is updated properly, and mark the currently written chunk as the 587 * track is updated properly, and mark the currently written chunk as the
589 * last one in the track. */ 588 * last one in the track. */
590static void pcmbuf_gapless_track_change(void) 589static void start_gapless_track_change(void)
591{ 590{
592 /* we're starting a track transition */ 591 /* we're starting a track transition */
593 track_transition = true; 592 track_transition = true;
@@ -596,22 +595,42 @@ static void pcmbuf_gapless_track_change(void)
596 end_of_track = true; 595 end_of_track = true;
597} 596}
598 597
599static void pcmbuf_crossfade_track_change(void) 598static void start_crossfade_track_change(bool auto_skip)
600{ 599{
601 /* Initiate automatic crossfade mode */
602 pcmbuf_crossfade_init(false);
603 /* Notify the wps that the track change starts now */ 600 /* Notify the wps that the track change starts now */
604 audio_post_track_change(false); 601 audio_post_track_change(false);
602
603 /* Can't do two crossfades at once and, no fade if pcm is off now */
604 if (pcmbuf_is_crossfade_active() || !pcm_is_playing())
605 {
606 pcmbuf_play_stop();
607 return;
608 }
609
610 trigger_cpu_boost();
611
612 /* Not enough data, or crossfade disabled, flush the old data instead */
613 if (LOW_DATA(2) || !pcmbuf_is_crossfade_enabled() || low_latency_mode)
614 {
615 /* commit everything to this point and keep going, but... */
616 commit_chunk();
617 /* ... when the next chunk commits, throw away everything but itself */
618 flush_pcmbuf = true;
619 return;
620 }
621
622 /* Don't enable mix mode when skipping tracks manually. */
623 crossfade_mixmode = auto_skip && global_settings.crossfade_fade_out_mixmode;
624
625 crossfade_track_change_started = true;
605} 626}
606 627
607void pcmbuf_start_track_change(bool manual_skip) 628void pcmbuf_start_track_change(bool auto_skip)
608{ 629{
609 /* Manual track change (always crossfade or flush audio). */ 630 /* Manual track change (always crossfade or flush audio). */
610 if (manual_skip) 631 if (!auto_skip)
611 { 632 start_crossfade_track_change(false);
612 pcmbuf_crossfade_init(true); 633
613 audio_post_track_change(false);
614 }
615 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */ 634 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
616 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active() 635 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
617 && global_settings.crossfade != CROSSFADE_ENABLE_TRACKSKIP) 636 && global_settings.crossfade != CROSSFADE_ENABLE_TRACKSKIP)
@@ -620,22 +639,22 @@ void pcmbuf_start_track_change(bool manual_skip)
620 { 639 {
621 if (global_settings.playlist_shuffle) 640 if (global_settings.playlist_shuffle)
622 /* shuffle mode is on, so crossfade: */ 641 /* shuffle mode is on, so crossfade: */
623 pcmbuf_crossfade_track_change(); 642 start_crossfade_track_change(true);
624 else 643 else
625 /* shuffle mode is off, so normal gapless playback */ 644 /* shuffle mode is off, so normal gapless playback */
626 pcmbuf_gapless_track_change(); 645 start_gapless_track_change();
627 } 646 }
628 else 647 else
629 /* normal crossfade: */ 648 /* normal crossfade: */
630 pcmbuf_crossfade_track_change(); 649 start_crossfade_track_change(true);
631 } 650 }
632 else 651 else
633 /* normal gapless playback. */ 652 /* normal gapless playback. */
634 pcmbuf_gapless_track_change(); 653 start_gapless_track_change();
635} 654}
636 655
637/* Called when the last chunk in the track has been played */ 656/* Called when the last chunk in the track has been played */
638static void pcmbuf_finish_track_change(void) 657static void finish_gapless_track_change(void)
639{ 658{
640 /* not in a track transition anymore */ 659 /* not in a track transition anymore */
641 if(track_transition){logf("pcmbuf: (finish change) track transition false");} 660 if(track_transition){logf("pcmbuf: (finish change) track transition false");}
@@ -732,7 +751,7 @@ static void crossfade_start(void)
732 size_t fade_out_delay; 751 size_t fade_out_delay;
733 size_t fade_in_delay; 752 size_t fade_in_delay;
734 753
735 crossfade_init = false; 754 crossfade_track_change_started = false;
736 /* Reject crossfade if less than .5s of data */ 755 /* Reject crossfade if less than .5s of data */
737 if (LOW_DATA(2)) { 756 if (LOW_DATA(2)) {
738 logf("crossfade rejected"); 757 logf("crossfade rejected");
@@ -900,37 +919,6 @@ static void flush_crossfade(char *buf, size_t length)
900} 919}
901#endif /* HAVE_CROSSFADE */ 920#endif /* HAVE_CROSSFADE */
902 921
903static bool pcmbuf_crossfade_init(bool manual_skip)
904{
905 /* Can't do two crossfades at once and, no fade if pcm is off now */
906 if (crossfade_init || crossfade_active || !pcm_is_playing())
907 {
908 pcmbuf_play_stop();
909 return false;
910 }
911
912 trigger_cpu_boost();
913
914 /* Not enough data, or crossfade disabled, flush the old data instead */
915 if (LOW_DATA(2) || !pcmbuf_is_crossfade_enabled() || low_latency_mode)
916 {
917 commit_chunk();
918 flush_pcmbuf = true;
919 return false;
920 }
921
922 /* Don't enable mix mode when skipping tracks manually. */
923 if (manual_skip)
924 crossfade_mixmode = false;
925 else
926 crossfade_mixmode = global_settings.crossfade_fade_out_mixmode;
927
928 crossfade_init = true;
929
930 return true;
931
932}
933
934static void pcmbuf_finish_crossfade_enable(void) 922static void pcmbuf_finish_crossfade_enable(void)
935{ 923{
936 /* Copy the pending setting over now */ 924 /* Copy the pending setting over now */
@@ -953,7 +941,7 @@ static bool pcmbuf_is_crossfade_enabled(void)
953 941
954bool pcmbuf_is_crossfade_active(void) 942bool pcmbuf_is_crossfade_active(void)
955{ 943{
956 return crossfade_active || crossfade_init; 944 return crossfade_active || crossfade_track_change_started;
957} 945}
958 946
959void pcmbuf_request_crossfade_enable(bool on_off) 947void pcmbuf_request_crossfade_enable(bool on_off)
@@ -964,16 +952,11 @@ void pcmbuf_request_crossfade_enable(bool on_off)
964 952
965bool pcmbuf_is_same_size(void) 953bool pcmbuf_is_same_size(void)
966{ 954{
967 bool same_size; 955 /* if pcmbuffer is NULL, then not set up yet even once so always */
968 956 bool same_size = pcmbuffer ?
969 if (pcmbuffer == NULL) 957 (get_next_required_pcmbuf_size() == pcmbuf_size) : true;
970 same_size = true; /* Not set up yet even once so always */
971 else
972 {
973 size_t bufsize = pcmbuf_get_next_required_pcmbuf_size();
974 same_size = pcmbuf_calc_pcmbuffer_ptr(bufsize) == pcmbuffer;
975 }
976 958
959 /* no buffer change needed, so finish crossfade setup now */
977 if (same_size) 960 if (same_size)
978 pcmbuf_finish_crossfade_enable(); 961 pcmbuf_finish_crossfade_enable();
979 962
@@ -1128,8 +1111,7 @@ unsigned char * pcmbuf_get_meminfo(size_t *length)
1128 1111
1129bool pcmbuf_is_lowdata(void) 1112bool pcmbuf_is_lowdata(void)
1130{ 1113{
1131 if (!pcm_is_playing() || pcm_is_paused() || 1114 if (!pcm_is_playing() || pcm_is_paused() || pcmbuf_is_crossfade_active())
1132 crossfade_init || crossfade_active)
1133 return false; 1115 return false;
1134 1116
1135#if MEMORYSIZE > 2 1117#if MEMORYSIZE > 2