summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey Goode <jeffg7@gmail.com>2009-11-13 21:58:41 +0000
committerJeffrey Goode <jeffg7@gmail.com>2009-11-13 21:58:41 +0000
commitd1963e14dede231129a9ae9988b55c157181e8a0 (patch)
tree9c082a4e82b31731f61eac320d4efdd2938442e9
parent29d2711115c81520e1ef27b67594d6ead507d8dd (diff)
downloadrockbox-d1963e14dede231129a9ae9988b55c157181e8a0.tar.gz
rockbox-d1963e14dede231129a9ae9988b55c157181e8a0.zip
Crossfade: crossfaded manual skips now start fading immediately
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23622 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/pcmbuf.c66
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;
92static bool crossfade_enabled; 92static bool crossfade_enabled;
93static bool crossfade_enable_request; 93static bool crossfade_enable_request;
94static bool crossfade_mixmode; 94static bool crossfade_mixmode;
95static bool crossfade_auto_skip;
95static bool crossfade_active IDATA_ATTR; 96static bool crossfade_active IDATA_ATTR;
96static bool crossfade_track_change_started IDATA_ATTR; 97static 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 */
709static 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. */
707static void crossfade_start(void) 731static 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)