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, ...@@ -49,14 +49,28 @@ void cross_fade_apply(ob_chunk * a, const ob_chunk * b,
const struct audio_format *format, const struct audio_format *format,
unsigned int current_chunk, unsigned int num_chunks) unsigned int current_chunk, unsigned int num_chunks)
{ {
size_t size;
assert(current_chunk <= num_chunks); assert(current_chunk <= num_chunks);
size = b->chunkSize > a->chunkSize
? a->chunkSize
: b->chunkSize;
pcm_mix(a->data, pcm_mix(a->data,
b->data, b->data,
a->chunkSize, size,
b->chunkSize,
format, format,
((float)current_chunk) / num_chunks); ((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; a->chunkSize = b->chunkSize;
}
} }
...@@ -90,8 +90,8 @@ void pcm_volumeChange(char *buffer, int bufferSize, ...@@ -90,8 +90,8 @@ void pcm_volumeChange(char *buffer, int bufferSize,
} }
} }
static void pcm_add(char *buffer1, const char *buffer2, size_t bufferSize1, static void pcm_add(char *buffer1, const char *buffer2, size_t size,
size_t bufferSize2, int vol1, int vol2, int vol1, int vol2,
const struct audio_format *format) const struct audio_format *format)
{ {
int32_t temp32; int32_t temp32;
...@@ -102,7 +102,7 @@ static void pcm_add(char *buffer1, const char *buffer2, size_t bufferSize1, ...@@ -102,7 +102,7 @@ static void pcm_add(char *buffer1, const char *buffer2, size_t bufferSize1,
switch (format->bits) { switch (format->bits) {
case 16: case 16:
while (bufferSize1 > 0 && bufferSize2 > 0) { while (size > 0) {
temp32 = temp32 =
(vol1 * (*buffer16_1) + (vol1 * (*buffer16_1) +
vol2 * (*buffer16_2)); vol2 * (*buffer16_2));
...@@ -112,14 +112,11 @@ static void pcm_add(char *buffer1, const char *buffer2, size_t bufferSize1, ...@@ -112,14 +112,11 @@ static void pcm_add(char *buffer1, const char *buffer2, size_t bufferSize1,
*buffer16_1 = pcm_range(temp32, 16); *buffer16_1 = pcm_range(temp32, 16);
buffer16_1++; buffer16_1++;
buffer16_2++; buffer16_2++;
bufferSize1 -= 2; size -= 2;
bufferSize2 -= 2;
} }
if (bufferSize2 > 0)
memcpy(buffer16_1, buffer16_2, bufferSize2);
break; break;
case 8: case 8:
while (bufferSize1 > 0 && bufferSize2 > 0) { while (size > 0) {
temp32 = temp32 =
(vol1 * (*buffer8_1) + vol2 * (*buffer8_2)); (vol1 * (*buffer8_1) + vol2 * (*buffer8_2));
temp32 += pcm_dither(); temp32 += pcm_dither();
...@@ -128,20 +125,16 @@ static void pcm_add(char *buffer1, const char *buffer2, size_t bufferSize1, ...@@ -128,20 +125,16 @@ static void pcm_add(char *buffer1, const char *buffer2, size_t bufferSize1,
*buffer8_1 = pcm_range(temp32, 8); *buffer8_1 = pcm_range(temp32, 8);
buffer8_1++; buffer8_1++;
buffer8_2++; buffer8_2++;
bufferSize1--; size--;
bufferSize2--;
} }
if (bufferSize2 > 0)
memcpy(buffer8_1, buffer8_2, bufferSize2);
break; break;
default: default:
FATAL("%i bits not supported by pcm_add!\n", format->bits); FATAL("%i bits not supported by pcm_add!\n", format->bits);
} }
} }
void pcm_mix(char *buffer1, const char *buffer2, size_t bufferSize1, void pcm_mix(char *buffer1, const char *buffer2, size_t size,
size_t bufferSize2, const struct audio_format *format, const struct audio_format *format, float portion1)
float portion1)
{ {
int vol1; int vol1;
float s = sin(M_PI_2 * portion1); float s = sin(M_PI_2 * portion1);
...@@ -150,8 +143,7 @@ void pcm_mix(char *buffer1, const char *buffer2, size_t bufferSize1, ...@@ -150,8 +143,7 @@ void pcm_mix(char *buffer1, const char *buffer2, size_t bufferSize1,
vol1 = s * 1000 + 0.5; vol1 = s * 1000 + 0.5;
vol1 = vol1 > 1000 ? 1000 : (vol1 < 0 ? 0 : vol1); vol1 = vol1 > 1000 ? 1000 : (vol1 < 0 ? 0 : vol1);
pcm_add(buffer1, buffer2, bufferSize1, bufferSize2, vol1, 1000 - vol1, pcm_add(buffer1, buffer2, size, vol1, 1000 - vol1, format);
format);
} }
#ifdef HAVE_LIBSAMPLERATE #ifdef HAVE_LIBSAMPLERATE
......
...@@ -47,8 +47,8 @@ typedef struct _ConvState { ...@@ -47,8 +47,8 @@ typedef struct _ConvState {
void pcm_volumeChange(char *buffer, int bufferSize, const struct audio_format *format, void pcm_volumeChange(char *buffer, int bufferSize, const struct audio_format *format,
int volume); int volume);
void pcm_mix(char *buffer1, const char *buffer2, size_t bufferSize1, void pcm_mix(char *buffer1, const char *buffer2, size_t size,
size_t bufferSize2, const struct audio_format *format, float portion1); const struct audio_format *format, float portion1);
size_t pcm_convertAudioFormat(const struct audio_format *inFormat, size_t pcm_convertAudioFormat(const struct audio_format *inFormat,
const char *inBuffer, size_t inSize, 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