diff options
-rw-r--r-- | src/pcm_utils.c | 165 |
1 files changed, 93 insertions, 72 deletions
diff --git a/src/pcm_utils.c b/src/pcm_utils.c index 6e7156aea..a1f79f430 100644 --- a/src/pcm_utils.c +++ b/src/pcm_utils.c @@ -43,14 +43,38 @@ pcm_range(int32_t sample, unsigned bits) return sample; } +static void +pcm_volume_change_8(int8_t *buffer, unsigned num_samples, + unsigned volume) +{ + while (num_samples > 0) { + int32_t sample = *buffer; + + sample = (sample * volume + pcm_dither() + 500) / 1000; + + *buffer++ = pcm_range(sample, 8); + --num_samples; + } +} + +static void +pcm_volume_change_16(int16_t *buffer, unsigned num_samples, + unsigned volume) +{ + while (num_samples > 0) { + int32_t sample = *buffer; + + sample = (sample * volume + pcm_dither() + 500) / 1000; + + *buffer++ = pcm_range(sample, 16); + --num_samples; + } +} + void pcm_volumeChange(char *buffer, int bufferSize, const struct audio_format *format, int volume) { - int32_t temp32; - int8_t *buffer8 = (int8_t *) buffer; - int16_t *buffer16 = (int16_t *) buffer; - if (volume >= 1000) return; @@ -60,74 +84,68 @@ void pcm_volumeChange(char *buffer, int bufferSize, } switch (format->bits) { - case 16: - while (bufferSize > 0) { - temp32 = *buffer16; - temp32 *= volume; - temp32 += pcm_dither(); - temp32 += 500; - temp32 /= 1000; - *buffer16 = pcm_range(temp32, 16); - buffer16++; - bufferSize -= 2; - } - break; case 8: - while (bufferSize > 0) { - temp32 = *buffer8; - temp32 *= volume; - temp32 += pcm_dither(); - temp32 += 500; - temp32 /= 1000; - *buffer8 = pcm_range(temp32, 8); - buffer8++; - bufferSize--; - } + pcm_volume_change_8((int8_t *)buffer, bufferSize, volume); break; + + case 16: + pcm_volume_change_16((int16_t *)buffer, bufferSize / 2, + volume); + break; + default: FATAL("%i bits not supported by pcm_volumeChange!\n", format->bits); } } +static void +pcm_add_8(int8_t *buffer1, const int8_t *buffer2, + unsigned num_samples, int volume1, int volume2) +{ + while (num_samples > 0) { + int32_t sample1 = *buffer1; + int32_t sample2 = *buffer2++; + + sample1 = ((sample1 * volume1 + sample2 * volume2) + + pcm_dither() + 500) / 1000; + + *buffer1++ = pcm_range(sample1, 8); + --num_samples; + } +} + +static void +pcm_add_16(int16_t *buffer1, const int16_t *buffer2, + unsigned num_samples, int volume1, int volume2) +{ + while (num_samples > 0) { + int32_t sample1 = *buffer1; + int32_t sample2 = *buffer2++; + + sample1 = ((sample1 * volume1 + sample2 * volume2) + + pcm_dither() + 500) / 1000; + + *buffer1++ = pcm_range(sample1, 16); + --num_samples; + } +} + static void pcm_add(char *buffer1, const char *buffer2, size_t size, int vol1, int vol2, const struct audio_format *format) { - int32_t temp32; - int8_t *buffer8_1 = (int8_t *) buffer1; - const int8_t *buffer8_2 = (const int8_t *) buffer2; - int16_t *buffer16_1 = (int16_t *) buffer1; - const int16_t *buffer16_2 = (const int16_t *) buffer2; - switch (format->bits) { - case 16: - while (size > 0) { - temp32 = - (vol1 * (*buffer16_1) + - vol2 * (*buffer16_2)); - temp32 += pcm_dither(); - temp32 += 500; - temp32 /= 1000; - *buffer16_1 = pcm_range(temp32, 16); - buffer16_1++; - buffer16_2++; - size -= 2; - } - break; case 8: - while (size > 0) { - temp32 = - (vol1 * (*buffer8_1) + vol2 * (*buffer8_2)); - temp32 += pcm_dither(); - temp32 += 500; - temp32 /= 1000; - *buffer8_1 = pcm_range(temp32, 8); - buffer8_1++; - buffer8_2++; - size--; - } + pcm_add_8((int8_t *)buffer1, (const int8_t *)buffer2, + size, vol1, vol2); + break; + + case 16: + pcm_add_16((int16_t *)buffer1, (const int16_t *)buffer2, + size / 2, vol1, vol2); break; + default: FATAL("%i bits not supported by pcm_add!\n", format->bits); } @@ -357,41 +375,44 @@ static char *pcm_convertChannels(int8_t channels, const char *inBuffer, return outBuffer; } +static void +pcm_convert_8_to_16(int16_t *out, const int8_t *in, + unsigned num_samples) +{ + while (num_samples > 0) { + *out++ = *in++ << 8; + --num_samples; + } +} + static const char *pcm_convertTo16bit(int8_t bits, const char *inBuffer, size_t inSize, size_t *outSize) { static char *buf; static size_t len; - char *outBuffer = NULL; - const int8_t *in; - int16_t *out; - size_t i; + unsigned num_samples; switch (bits) { case 8: + num_samples = inSize; *outSize = inSize << 1; if (*outSize > len) { len = *outSize; buf = xrealloc(buf, len); } - outBuffer = buf; - in = (const int8_t *)inBuffer; - out = (int16_t *)outBuffer; - for (i = 0; i < inSize; i++) - *out++ = (*in++) << 8; + pcm_convert_8_to_16((int16_t *)buf, + (const int8_t *)inBuffer, + num_samples); + return buf; - break; case 16: *outSize = inSize; return inBuffer; - case 24: - /* put dithering code from mp3_decode here */ - default: - ERROR("only 8 or 16 bits are supported for conversion!\n"); } - return outBuffer; + ERROR("only 8 or 16 bits are supported for conversion!\n"); + return NULL; } /* outFormat bits must be 16 and channels must be 1 or 2! */ |