summaryrefslogtreecommitdiffstats
path: root/apps/pcmbuf.c
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 /apps/pcmbuf.c
parent29d2711115c81520e1ef27b67594d6ead507d8dd (diff)
downloadrockbox-d1963e14dede231129a9ae9988b55c157181e8a0.tar.gz
rockbox-d1963e14dede231129a9ae9988b55c157181e8a0.tar.bz2
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
Diffstat (limited to 'apps/pcmbuf.c')
-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;
static bool crossfade_enabled;
static bool crossfade_enable_request;
static bool crossfade_mixmode;
+static bool crossfade_auto_skip;
static bool crossfade_active IDATA_ATTR;
static bool crossfade_track_change_started IDATA_ATTR;
@@ -537,6 +538,8 @@ void pcmbuf_start_track_change(bool auto_skip)
#ifdef HAVE_CROSSFADE
/* Don't enable mix mode when skipping tracks manually. */
crossfade_mixmode = auto_skip && global_settings.crossfade_fade_out_mixmode;
+
+ crossfade_auto_skip = auto_skip;
crossfade_track_change_started = crossfade;
#endif
@@ -702,6 +705,27 @@ static size_t find_chunk(size_t length, struct chunkdesc **chunk)
return length / 2;
}
+/* Fade samples in the PCM buffer */
+static void fade_block(int factor, size_t length, size_t *fade_sample,
+ struct chunkdesc **fade_chunk)
+{
+ while (length > 0 && *fade_chunk != NULL)
+ {
+ /* Fade one sample */
+ int16_t *buf = (int16_t *)((*fade_chunk)->addr);
+ int32_t sample = buf[*fade_sample];
+ buf[(*fade_sample)++] = (sample * factor) >> 8;
+ length -= 2;
+
+ /* Move to the next chunk as needed */
+ if (*fade_sample * 2 >= (*fade_chunk)->size)
+ {
+ *fade_chunk = (*fade_chunk)->link;
+ *fade_sample = 0;
+ }
+ }
+}
+
/* Initializes crossfader, calculates all necessary parameters and performs
* fade-out with the PCM buffer. */
static void crossfade_start(void)
@@ -737,15 +761,25 @@ static void crossfade_start(void)
NATIVE_FREQUENCY * global_settings.crossfade_fade_out_duration * 4;
crossfade_need = fade_out_delay + fade_out_rem;
- /* We want only to modify the last part of the buffer, so find
- * the right chunk and sample to start the crossfade */
if (crossfade_rem > crossfade_need)
{
- crossfade_sample = find_chunk(crossfade_rem - crossfade_need,
- &crossfade_chunk);
+ if (crossfade_auto_skip)
+ /* Automatic track changes only modify the last part of the buffer,
+ * so find the right chunk and sample to start the crossfade */
+ {
+ crossfade_sample = find_chunk(crossfade_rem - crossfade_need,
+ &crossfade_chunk);
+ crossfade_rem = crossfade_need;
+ }
+ else
+ /* Manual skips occur immediately, but give time to process */
+ {
+ crossfade_rem -= crossfade_chunk->size;
+ crossfade_chunk = crossfade_chunk->link;
+ }
}
/* Truncate fade out duration if necessary. */
- else if (crossfade_rem < crossfade_need)
+ if (crossfade_rem < crossfade_need)
{
size_t crossfade_short = crossfade_need - crossfade_rem;
if (fade_out_rem >= crossfade_short)
@@ -756,6 +790,7 @@ static void crossfade_start(void)
fade_out_rem = 0;
}
}
+ crossfade_rem -= fade_out_delay + fade_out_rem;
/* Completely process the crossfade fade-out effect with current PCM buffer */
if (!crossfade_mixmode)
@@ -777,23 +812,11 @@ static void crossfade_start(void)
fade_out_rem -= block_rem;
- /* Fade this block */
- while (block_rem > 0 && fade_out_chunk != NULL)
- {
- /* Fade one sample */
- int16_t *buf = (int16_t *)fade_out_chunk->addr;
- int32_t sample = buf[fade_out_sample];
- buf[fade_out_sample++] = (sample * factor) >> 8;
-
- block_rem -= 2;
- /* Move to the next chunk as needed */
- if (fade_out_sample * 2 >= fade_out_chunk->size)
- {
- fade_out_chunk = fade_out_chunk->link;
- fade_out_sample = 0;
- }
- }
+ fade_block(factor, block_rem, &fade_out_sample, &fade_out_chunk);
}
+
+ /* zero out the rest of the buffer */
+ fade_block(0, crossfade_rem, &fade_out_sample, &fade_out_chunk);
}
/* Initialize fade-in counters */
@@ -890,6 +913,7 @@ static void write_to_crossfade(char *buf, size_t length)
{
/* Mix the data */
size_t mix_total = length;
+ /* A factor of 256 means no fading */
length = crossfade_mix(256, buf, length);
buf += mix_total - length;
if (!length)