Commit c85b570a authored by Max Kellermann's avatar Max Kellermann

pcm_utils: pass only one buffer size to pcm_mix()

pcm_mix() might overflow the destination buffer if it is smaller than the second buffer. This is ok because the physical buffer size passed by cross_fade_apply() is always big enough, but clutters pcm_mix() with complicated length checks and contains a dangerous buffer overflow pitfall. Simplify pcm_mix()/pcm_add() and pass only the smaller buffer size; let cross_fade_apply() do the memcpy().
parent 6e21e24c
......@@ -49,14 +49,28 @@ void cross_fade_apply(ob_chunk * a, const ob_chunk * b,
const struct audio_format *format,
unsigned int current_chunk, unsigned int num_chunks)
{
size_t size;
assert(current_chunk <= num_chunks);
size = b->chunkSize > a->chunkSize
? a->chunkSize
: b->chunkSize;
pcm_mix(a->data,
b->data,
a->chunkSize,
b->chunkSize,
size,
format,
((float)current_chunk) / num_chunks);
if (b->chunkSize > a->chunkSize)
if (b->chunkSize > a->chunkSize) {
/* the second buffer is larger than the first one:
there is unmixed rest at the end. Copy it over.
The output buffer API guarantees that there is
enough room in a->data. */
memcpy(a->data + a->chunkSize,
b->data + a->chunkSize,
b->chunkSize - a->chunkSize);
a->chunkSize = b->chunkSize;
}
}
......@@ -90,8 +90,8 @@ void pcm_volumeChange(char *buffer, int bufferSize,
}
}
static void pcm_add(char *buffer1, const char *buffer2, size_t bufferSize1,
size_t bufferSize2, int vol1, int vol2,
static void pcm_add(char *buffer1, const char *buffer2, size_t size,
int vol1, int vol2,
const struct audio_format *format)
{
int32_t temp32;
......@@ -102,7 +102,7 @@ static void pcm_add(char *buffer1, const char *buffer2, size_t bufferSize1,
switch (format->bits) {
case 16:
while (bufferSize1 > 0 && bufferSize2 > 0) {
while (size > 0) {
temp32 =
(vol1 * (*buffer16_1) +
vol2 * (*buffer16_2));
......@@ -112,14 +112,11 @@ static void pcm_add(char *buffer1, const char *buffer2, size_t bufferSize1,
*buffer16_1 = pcm_range(temp32, 16);
buffer16_1++;
buffer16_2++;
bufferSize1 -= 2;
bufferSize2 -= 2;
size -= 2;
}
if (bufferSize2 > 0)
memcpy(buffer16_1, buffer16_2, bufferSize2);
break;
case 8:
while (bufferSize1 > 0 && bufferSize2 > 0) {
while (size > 0) {
temp32 =
(vol1 * (*buffer8_1) + vol2 * (*buffer8_2));
temp32 += pcm_dither();
......@@ -128,20 +125,16 @@ static void pcm_add(char *buffer1, const char *buffer2, size_t bufferSize1,
*buffer8_1 = pcm_range(temp32, 8);
buffer8_1++;
buffer8_2++;
bufferSize1--;
bufferSize2--;
size--;
}
if (bufferSize2 > 0)
memcpy(buffer8_1, buffer8_2, bufferSize2);
break;
default:
FATAL("%i bits not supported by pcm_add!\n", format->bits);
}
}
void pcm_mix(char *buffer1, const char *buffer2, size_t bufferSize1,
size_t bufferSize2, const struct audio_format *format,
float portion1)
void pcm_mix(char *buffer1, const char *buffer2, size_t size,
const struct audio_format *format, float portion1)
{
int vol1;
float s = sin(M_PI_2 * portion1);
......@@ -150,8 +143,7 @@ void pcm_mix(char *buffer1, const char *buffer2, size_t bufferSize1,
vol1 = s * 1000 + 0.5;
vol1 = vol1 > 1000 ? 1000 : (vol1 < 0 ? 0 : vol1);
pcm_add(buffer1, buffer2, bufferSize1, bufferSize2, vol1, 1000 - vol1,
format);
pcm_add(buffer1, buffer2, size, vol1, 1000 - vol1, format);
}
#ifdef HAVE_LIBSAMPLERATE
......
......@@ -47,8 +47,8 @@ typedef struct _ConvState {
void pcm_volumeChange(char *buffer, int bufferSize, const struct audio_format *format,
int volume);
void pcm_mix(char *buffer1, const char *buffer2, size_t bufferSize1,
size_t bufferSize2, const struct audio_format *format, float portion1);
void pcm_mix(char *buffer1, const char *buffer2, size_t size,
const struct audio_format *format, float portion1);
size_t pcm_convertAudioFormat(const struct audio_format *inFormat,
const char *inBuffer, size_t inSize,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment