diff options
Diffstat (limited to 'src/pcm_mix.c')
-rw-r--r-- | src/pcm_mix.c | 96 |
1 files changed, 69 insertions, 27 deletions
diff --git a/src/pcm_mix.c b/src/pcm_mix.c index 3145c07be..9f76d568f 100644 --- a/src/pcm_mix.c +++ b/src/pcm_mix.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -22,7 +22,6 @@ #include "pcm_volume.h" #include "pcm_utils.h" #include "audio_format.h" -#include "mpd_error.h" #include <glib.h> @@ -100,35 +99,60 @@ pcm_add_vol_32(int32_t *buffer1, const int32_t *buffer2, } static void +pcm_add_vol_float(float *buffer1, const float *buffer2, + unsigned num_samples, float volume1, float volume2) +{ + while (num_samples > 0) { + float sample1 = *buffer1; + float sample2 = *buffer2++; + + sample1 = (sample1 * volume1 + sample2 * volume2); + *buffer1++ = sample1; + --num_samples; + } +} + +static bool pcm_add_vol(void *buffer1, const void *buffer2, size_t size, int vol1, int vol2, - const struct audio_format *format) + enum sample_format format) { - switch (format->format) { + switch (format) { + case SAMPLE_FORMAT_UNDEFINED: + case SAMPLE_FORMAT_S24: + /* not implemented */ + return false; + case SAMPLE_FORMAT_S8: pcm_add_vol_8((int8_t *)buffer1, (const int8_t *)buffer2, size, vol1, vol2); - break; + return true; case SAMPLE_FORMAT_S16: pcm_add_vol_16((int16_t *)buffer1, (const int16_t *)buffer2, size / 2, vol1, vol2); - break; + return true; case SAMPLE_FORMAT_S24_P32: pcm_add_vol_24((int32_t *)buffer1, (const int32_t *)buffer2, size / 4, vol1, vol2); - break; + return true; case SAMPLE_FORMAT_S32: pcm_add_vol_32((int32_t *)buffer1, (const int32_t *)buffer2, size / 4, vol1, vol2); - break; + return true; - default: - MPD_ERROR("format %s not supported by pcm_add_vol", - sample_format_to_string(format->format)); + case SAMPLE_FORMAT_FLOAT: + pcm_add_vol_float(buffer1, buffer2, size / 4, + pcm_volume_to_float(vol1), + pcm_volume_to_float(vol2)); + return true; } + + /* unreachable */ + assert(false); + return false; } static void @@ -188,45 +212,63 @@ pcm_add_32(int32_t *buffer1, const int32_t *buffer2, unsigned num_samples) } static void +pcm_add_float(float *buffer1, const float *buffer2, unsigned num_samples) +{ + while (num_samples > 0) { + float sample1 = *buffer1; + float sample2 = *buffer2++; + *buffer1++ = sample1 + sample2; + --num_samples; + } +} + +static bool pcm_add(void *buffer1, const void *buffer2, size_t size, - const struct audio_format *format) + enum sample_format format) { - switch (format->format) { + switch (format) { + case SAMPLE_FORMAT_UNDEFINED: + case SAMPLE_FORMAT_S24: + /* not implemented */ + return false; + case SAMPLE_FORMAT_S8: pcm_add_8((int8_t *)buffer1, (const int8_t *)buffer2, size); - break; + return true; case SAMPLE_FORMAT_S16: pcm_add_16((int16_t *)buffer1, (const int16_t *)buffer2, size / 2); - break; + return true; case SAMPLE_FORMAT_S24_P32: pcm_add_24((int32_t *)buffer1, (const int32_t *)buffer2, size / 4); - break; + return true; case SAMPLE_FORMAT_S32: pcm_add_32((int32_t *)buffer1, (const int32_t *)buffer2, size / 4); - break; + return true; - default: - MPD_ERROR("format %s not supported by pcm_add", - sample_format_to_string(format->format)); + case SAMPLE_FORMAT_FLOAT: + pcm_add_float(buffer1, buffer2, size / 4); + return true; } + + /* unreachable */ + assert(false); + return false; } -void +bool pcm_mix(void *buffer1, const void *buffer2, size_t size, - const struct audio_format *format, float portion1) + enum sample_format format, float portion1) { int vol1; float s; /* portion1 is between 0.0 and 1.0 for crossfading, MixRamp uses NaN * to signal mixing rather than fading */ - if (isnan(portion1)) { - pcm_add(buffer1, buffer2, size, format); - return; - } + if (isnan(portion1)) + return pcm_add(buffer1, buffer2, size, format); s = sin(M_PI_2 * portion1); s *= s; @@ -234,5 +276,5 @@ pcm_mix(void *buffer1, const void *buffer2, size_t size, vol1 = s * PCM_VOLUME_1 + 0.5; vol1 = vol1 > PCM_VOLUME_1 ? PCM_VOLUME_1 : (vol1 < 0 ? 0 : vol1); - pcm_add_vol(buffer1, buffer2, size, vol1, PCM_VOLUME_1 - vol1, format); + return pcm_add_vol(buffer1, buffer2, size, vol1, PCM_VOLUME_1 - vol1, format); } |