diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/pcmbuf.c | 66 |
1 files changed, 45 insertions, 21 deletions
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index da4b76fc20..20eafb5865 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c | |||
@@ -92,6 +92,7 @@ static char *fadebuf IDATA_ATTR; | |||
92 | static bool crossfade_enabled; | 92 | static bool crossfade_enabled; |
93 | static bool crossfade_enable_request; | 93 | static bool crossfade_enable_request; |
94 | static bool crossfade_mixmode; | 94 | static bool crossfade_mixmode; |
95 | static bool crossfade_auto_skip; | ||
95 | static bool crossfade_active IDATA_ATTR; | 96 | static bool crossfade_active IDATA_ATTR; |
96 | static bool crossfade_track_change_started IDATA_ATTR; | 97 | static bool crossfade_track_change_started IDATA_ATTR; |
97 | 98 | ||
@@ -537,6 +538,8 @@ void pcmbuf_start_track_change(bool auto_skip) | |||
537 | #ifdef HAVE_CROSSFADE | 538 | #ifdef HAVE_CROSSFADE |
538 | /* Don't enable mix mode when skipping tracks manually. */ | 539 | /* Don't enable mix mode when skipping tracks manually. */ |
539 | crossfade_mixmode = auto_skip && global_settings.crossfade_fade_out_mixmode; | 540 | crossfade_mixmode = auto_skip && global_settings.crossfade_fade_out_mixmode; |
541 | |||
542 | crossfade_auto_skip = auto_skip; | ||
540 | 543 | ||
541 | crossfade_track_change_started = crossfade; | 544 | crossfade_track_change_started = crossfade; |
542 | #endif | 545 | #endif |
@@ -702,6 +705,27 @@ static size_t find_chunk(size_t length, struct chunkdesc **chunk) | |||
702 | return length / 2; | 705 | return length / 2; |
703 | } | 706 | } |
704 | 707 | ||
708 | /* Fade samples in the PCM buffer */ | ||
709 | static void fade_block(int factor, size_t length, size_t *fade_sample, | ||
710 | struct chunkdesc **fade_chunk) | ||
711 | { | ||
712 | while (length > 0 && *fade_chunk != NULL) | ||
713 | { | ||
714 | /* Fade one sample */ | ||
715 | int16_t *buf = (int16_t *)((*fade_chunk)->addr); | ||
716 | int32_t sample = buf[*fade_sample]; | ||
717 | buf[(*fade_sample)++] = (sample * factor) >> 8; | ||
718 | length -= 2; | ||
719 | |||
720 | /* Move to the next chunk as needed */ | ||
721 | if (*fade_sample * 2 >= (*fade_chunk)->size) | ||
722 | { | ||
723 | *fade_chunk = (*fade_chunk)->link; | ||
724 | *fade_sample = 0; | ||
725 | } | ||
726 | } | ||
727 | } | ||
728 | |||
705 | /* Initializes crossfader, calculates all necessary parameters and performs | 729 | /* Initializes crossfader, calculates all necessary parameters and performs |
706 | * fade-out with the PCM buffer. */ | 730 | * fade-out with the PCM buffer. */ |
707 | static void crossfade_start(void) | 731 | static void crossfade_start(void) |
@@ -737,15 +761,25 @@ static void crossfade_start(void) | |||
737 | NATIVE_FREQUENCY * global_settings.crossfade_fade_out_duration * 4; | 761 | NATIVE_FREQUENCY * global_settings.crossfade_fade_out_duration * 4; |
738 | 762 | ||
739 | crossfade_need = fade_out_delay + fade_out_rem; | 763 | crossfade_need = fade_out_delay + fade_out_rem; |
740 | /* We want only to modify the last part of the buffer, so find | ||
741 | * the right chunk and sample to start the crossfade */ | ||
742 | if (crossfade_rem > crossfade_need) | 764 | if (crossfade_rem > crossfade_need) |
743 | { | 765 | { |
744 | crossfade_sample = find_chunk(crossfade_rem - crossfade_need, | 766 | if (crossfade_auto_skip) |
745 | &crossfade_chunk); | 767 | /* Automatic track changes only modify the last part of the buffer, |
768 | * so find the right chunk and sample to start the crossfade */ | ||
769 | { | ||
770 | crossfade_sample = find_chunk(crossfade_rem - crossfade_need, | ||
771 | &crossfade_chunk); | ||
772 | crossfade_rem = crossfade_need; | ||
773 | } | ||
774 | else | ||
775 | /* Manual skips occur immediately, but give time to process */ | ||
776 | { | ||
777 | crossfade_rem -= crossfade_chunk->size; | ||
778 | crossfade_chunk = crossfade_chunk->link; | ||
779 | } | ||
746 | } | 780 | } |
747 | /* Truncate fade out duration if necessary. */ | 781 | /* Truncate fade out duration if necessary. */ |
748 | else if (crossfade_rem < crossfade_need) | 782 | if (crossfade_rem < crossfade_need) |
749 | { | 783 | { |
750 | size_t crossfade_short = crossfade_need - crossfade_rem; | 784 | size_t crossfade_short = crossfade_need - crossfade_rem; |
751 | if (fade_out_rem >= crossfade_short) | 785 | if (fade_out_rem >= crossfade_short) |
@@ -756,6 +790,7 @@ static void crossfade_start(void) | |||
756 | fade_out_rem = 0; | 790 | fade_out_rem = 0; |
757 | } | 791 | } |
758 | } | 792 | } |
793 | crossfade_rem -= fade_out_delay + fade_out_rem; | ||
759 | 794 | ||
760 | /* Completely process the crossfade fade-out effect with current PCM buffer */ | 795 | /* Completely process the crossfade fade-out effect with current PCM buffer */ |
761 | if (!crossfade_mixmode) | 796 | if (!crossfade_mixmode) |
@@ -777,23 +812,11 @@ static void crossfade_start(void) | |||
777 | 812 | ||
778 | fade_out_rem -= block_rem; | 813 | fade_out_rem -= block_rem; |
779 | 814 | ||
780 | /* Fade this block */ | 815 | fade_block(factor, block_rem, &fade_out_sample, &fade_out_chunk); |
781 | while (block_rem > 0 && fade_out_chunk != NULL) | ||
782 | { | ||
783 | /* Fade one sample */ | ||
784 | int16_t *buf = (int16_t *)fade_out_chunk->addr; | ||
785 | int32_t sample = buf[fade_out_sample]; | ||
786 | buf[fade_out_sample++] = (sample * factor) >> 8; | ||
787 | |||
788 | block_rem -= 2; | ||
789 | /* Move to the next chunk as needed */ | ||
790 | if (fade_out_sample * 2 >= fade_out_chunk->size) | ||
791 | { | ||
792 | fade_out_chunk = fade_out_chunk->link; | ||
793 | fade_out_sample = 0; | ||
794 | } | ||
795 | } | ||
796 | } | 816 | } |
817 | |||
818 | /* zero out the rest of the buffer */ | ||
819 | fade_block(0, crossfade_rem, &fade_out_sample, &fade_out_chunk); | ||
797 | } | 820 | } |
798 | 821 | ||
799 | /* Initialize fade-in counters */ | 822 | /* Initialize fade-in counters */ |
@@ -890,6 +913,7 @@ static void write_to_crossfade(char *buf, size_t length) | |||
890 | { | 913 | { |
891 | /* Mix the data */ | 914 | /* Mix the data */ |
892 | size_t mix_total = length; | 915 | size_t mix_total = length; |
916 | /* A factor of 256 means no fading */ | ||
893 | length = crossfade_mix(256, buf, length); | 917 | length = crossfade_mix(256, buf, length); |
894 | buf += mix_total - length; | 918 | buf += mix_total - length; |
895 | if (!length) | 919 | if (!length) |