summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/pcmbuf.c123
1 files changed, 56 insertions, 67 deletions
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c
index e62fc892cc..9bf4c96233 100644
--- a/apps/pcmbuf.c
+++ b/apps/pcmbuf.c
@@ -690,63 +690,16 @@ static inline int32_t clip_sample_16(int32_t sample)
}
#ifdef HAVE_CROSSFADE
-/* Completely process the crossfade fade-out effect with current PCM buffer */
-static void crossfade_process_buffer(size_t fade_in_delay,
- size_t fade_out_delay, size_t fade_out_rem)
+/* Find the chunk that's (length) deep in the list. Return the position within
+ * the chunk, and leave the chunkdesc pointer pointing to the chunk. */
+static size_t find_chunk(size_t length, struct chunkdesc **chunk)
{
- if (!crossfade_mixmode)
+ while (*chunk && length >= (*chunk)->size)
{
- /* Fade out the specified amount of the already processed audio */
- size_t total_fade_out = fade_out_rem;
- size_t fade_out_sample;
- struct chunkdesc *fade_out_chunk = crossfade_chunk;
-
- /* Find the right chunk to start fading out */
- fade_out_delay += crossfade_sample * 2;
- while (fade_out_delay != 0 && fade_out_delay >= fade_out_chunk->size)
- {
- fade_out_delay -= fade_out_chunk->size;
- fade_out_chunk = fade_out_chunk->link;
- }
- /* The start sample within the chunk */
- fade_out_sample = fade_out_delay / 2;
-
- while (fade_out_rem > 0)
- {
- /* Each 1/10 second of audio will have the same fade applied */
- size_t block_rem = MIN(NATIVE_FREQUENCY * 4 / 10, fade_out_rem);
- int factor = (fade_out_rem << 8) / total_fade_out;
-
- 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;
- }
- }
- }
- }
-
- /* Find the right chunk and sample to start fading in */
- fade_in_delay += crossfade_sample * 2;
- while (fade_in_delay != 0 && fade_in_delay >= crossfade_chunk->size)
- {
- fade_in_delay -= crossfade_chunk->size;
- crossfade_chunk = crossfade_chunk->link;
+ length -= (*chunk)->size;
+ *chunk = (*chunk)->link;
}
- crossfade_sample = fade_in_delay / 2;
- logf("process done!");
+ return length / 2;
}
/* Initializes crossfader, calculates all necessary parameters and performs
@@ -777,25 +730,19 @@ static void crossfade_start(void)
crossfade_chunk = read_chunk->link;
crossfade_sample = 0;
- /* Get fade out delay from settings. */
+ /* Get fade out info from settings. */
fade_out_delay =
NATIVE_FREQUENCY * global_settings.crossfade_fade_out_delay * 4;
-
- /* Get fade out duration from settings. */
fade_out_rem =
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. */
+ /* 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)
{
- size_t crossfade_extra = crossfade_rem - crossfade_need;
- while (crossfade_extra > crossfade_chunk->size)
- {
- crossfade_extra -= crossfade_chunk->size;
- crossfade_chunk = crossfade_chunk->link;
- }
- crossfade_sample = crossfade_extra / 2;
+ crossfade_sample = find_chunk(crossfade_rem - crossfade_need,
+ &crossfade_chunk);
}
/* Truncate fade out duration if necessary. */
else if (crossfade_rem < crossfade_need)
@@ -810,7 +757,46 @@ static void crossfade_start(void)
}
}
- /* Get also fade in duration and delays from settings. */
+ /* Completely process the crossfade fade-out effect with current PCM buffer */
+ if (!crossfade_mixmode)
+ {
+ /* Fade out the specified amount of the already processed audio */
+ size_t total_fade_out = fade_out_rem;
+ size_t fade_out_sample;
+ struct chunkdesc *fade_out_chunk = crossfade_chunk;
+
+ /* Find the right chunk and sample to start fading out */
+ fade_out_delay += crossfade_sample * 2;
+ fade_out_sample = find_chunk(fade_out_delay, &fade_out_chunk);
+
+ while (fade_out_rem > 0)
+ {
+ /* Each 1/10 second of audio will have the same fade applied */
+ size_t block_rem = MIN(NATIVE_FREQUENCY * 4 / 10, fade_out_rem);
+ int factor = (fade_out_rem << 8) / total_fade_out;
+
+ 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;
+ }
+ }
+ }
+ }
+
+ /* Initialize fade-in counters */
crossfade_fade_in_total =
NATIVE_FREQUENCY * global_settings.crossfade_fade_in_duration * 4;
crossfade_fade_in_rem = crossfade_fade_in_total;
@@ -818,7 +804,10 @@ static void crossfade_start(void)
fade_in_delay =
NATIVE_FREQUENCY * global_settings.crossfade_fade_in_delay * 4;
- crossfade_process_buffer(fade_in_delay, fade_out_delay, fade_out_rem);
+ /* Find the right chunk and sample to start fading in */
+ fade_in_delay += crossfade_sample * 2;
+ crossfade_sample = find_chunk(fade_in_delay, &crossfade_chunk);
+ logf("crossfade_start done!");
}
/* Returns the number of bytes _NOT_ mixed */