mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-02-12 04:28:02 -05:00
filter-chain: handle 0 length IR
Make sure we copy the DSP functions in the convolver before leaving the function because we need them to clear memory. Don't store the DSP functions in the head and tail convolvers but pass them from the main convolver because the convolvers might be NULL but we still need the DSP functions to clear memory. Fixes #4433
This commit is contained in:
parent
e42de413e8
commit
8d9269374d
1 changed files with 49 additions and 47 deletions
|
|
@ -11,8 +11,6 @@
|
|||
#include <math.h>
|
||||
|
||||
struct convolver1 {
|
||||
struct dsp_ops *dsp;
|
||||
|
||||
int blockSize;
|
||||
int segSize;
|
||||
int segCount;
|
||||
|
|
@ -76,15 +74,15 @@ static int next_power_of_two(int val)
|
|||
return r;
|
||||
}
|
||||
|
||||
static void convolver1_reset(struct convolver1 *conv)
|
||||
static void convolver1_reset(struct dsp_ops *dsp, struct convolver1 *conv)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < conv->segCount; i++)
|
||||
fft_cpx_clear(conv->dsp, conv->segments[i], conv->fftComplexSize);
|
||||
dsp_ops_clear(conv->dsp, conv->overlap, conv->blockSize);
|
||||
dsp_ops_clear(conv->dsp, conv->inputBuffer, conv->segSize);
|
||||
fft_cpx_clear(conv->dsp, conv->pre_mult, conv->fftComplexSize);
|
||||
fft_cpx_clear(conv->dsp, conv->conv, conv->fftComplexSize);
|
||||
fft_cpx_clear(dsp, conv->segments[i], conv->fftComplexSize);
|
||||
dsp_ops_clear(dsp, conv->overlap, conv->blockSize);
|
||||
dsp_ops_clear(dsp, conv->inputBuffer, conv->segSize);
|
||||
fft_cpx_clear(dsp, conv->pre_mult, conv->fftComplexSize);
|
||||
fft_cpx_clear(dsp, conv->conv, conv->fftComplexSize);
|
||||
conv->inputBufferFill = 0;
|
||||
conv->current = 0;
|
||||
}
|
||||
|
|
@ -107,16 +105,15 @@ static struct convolver1 *convolver1_new(struct dsp_ops *dsp, int block, const f
|
|||
if (irlen == 0)
|
||||
return conv;
|
||||
|
||||
conv->dsp = dsp;
|
||||
conv->blockSize = next_power_of_two(block);
|
||||
conv->segSize = 2 * conv->blockSize;
|
||||
conv->segCount = (irlen + conv->blockSize-1) / conv->blockSize;
|
||||
conv->fftComplexSize = (conv->segSize / 2) + 1;
|
||||
|
||||
conv->fft = dsp_ops_fft_new(conv->dsp, conv->segSize, true);
|
||||
conv->fft = dsp_ops_fft_new(dsp, conv->segSize, true);
|
||||
if (conv->fft == NULL)
|
||||
goto error;
|
||||
conv->ifft = dsp_ops_fft_new(conv->dsp, conv->segSize, true);
|
||||
conv->ifft = dsp_ops_fft_new(dsp, conv->segSize, true);
|
||||
if (conv->ifft == NULL)
|
||||
goto error;
|
||||
|
||||
|
|
@ -134,18 +131,18 @@ static struct convolver1 *convolver1_new(struct dsp_ops *dsp, int block, const f
|
|||
conv->segments[i] = fft_cpx_alloc(conv->fftComplexSize);
|
||||
conv->segmentsIr[i] = fft_cpx_alloc(conv->fftComplexSize);
|
||||
|
||||
dsp_ops_copy(conv->dsp, conv->fft_buffer, &ir[i * conv->blockSize], copy);
|
||||
dsp_ops_copy(dsp, conv->fft_buffer, &ir[i * conv->blockSize], copy);
|
||||
if (copy < conv->segSize)
|
||||
dsp_ops_clear(conv->dsp, conv->fft_buffer + copy, conv->segSize - copy);
|
||||
dsp_ops_clear(dsp, conv->fft_buffer + copy, conv->segSize - copy);
|
||||
|
||||
dsp_ops_fft_run(conv->dsp, conv->fft, 1, conv->fft_buffer, conv->segmentsIr[i]);
|
||||
dsp_ops_fft_run(dsp, conv->fft, 1, conv->fft_buffer, conv->segmentsIr[i]);
|
||||
}
|
||||
conv->pre_mult = fft_cpx_alloc(conv->fftComplexSize);
|
||||
conv->conv = fft_cpx_alloc(conv->fftComplexSize);
|
||||
conv->overlap = fft_alloc(conv->blockSize);
|
||||
conv->inputBuffer = fft_alloc(conv->segSize);
|
||||
conv->scale = 1.0f / conv->segSize;
|
||||
convolver1_reset(conv);
|
||||
convolver1_reset(dsp, conv);
|
||||
|
||||
return conv;
|
||||
error:
|
||||
|
|
@ -159,7 +156,7 @@ error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void convolver1_free(struct convolver1 *conv)
|
||||
static void convolver1_free(struct dsp_ops *dsp, struct convolver1 *conv)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < conv->segCount; i++) {
|
||||
|
|
@ -167,9 +164,9 @@ static void convolver1_free(struct convolver1 *conv)
|
|||
fft_cpx_free(conv->segmentsIr[i]);
|
||||
}
|
||||
if (conv->fft)
|
||||
dsp_ops_fft_free(conv->dsp, conv->fft);
|
||||
dsp_ops_fft_free(dsp, conv->fft);
|
||||
if (conv->ifft)
|
||||
dsp_ops_fft_free(conv->dsp, conv->ifft);
|
||||
dsp_ops_fft_free(dsp, conv->ifft);
|
||||
if (conv->fft_buffer)
|
||||
fft_free(conv->fft_buffer);
|
||||
free(conv->segments);
|
||||
|
|
@ -181,12 +178,12 @@ static void convolver1_free(struct convolver1 *conv)
|
|||
free(conv);
|
||||
}
|
||||
|
||||
static int convolver1_run(struct convolver1 *conv, const float *input, float *output, int len)
|
||||
static int convolver1_run(struct dsp_ops *dsp, struct convolver1 *conv, const float *input, float *output, int len)
|
||||
{
|
||||
int i, processed = 0;
|
||||
|
||||
if (conv == NULL || conv->segCount == 0) {
|
||||
dsp_ops_clear(conv->dsp, output, len);
|
||||
dsp_ops_clear(dsp, output, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
@ -194,17 +191,17 @@ static int convolver1_run(struct convolver1 *conv, const float *input, float *ou
|
|||
const int processing = SPA_MIN(len - processed, conv->blockSize - conv->inputBufferFill);
|
||||
const int inputBufferPos = conv->inputBufferFill;
|
||||
|
||||
dsp_ops_copy(conv->dsp, conv->inputBuffer + inputBufferPos, input + processed, processing);
|
||||
dsp_ops_copy(dsp, conv->inputBuffer + inputBufferPos, input + processed, processing);
|
||||
if (inputBufferPos == 0 && processing < conv->blockSize)
|
||||
dsp_ops_clear(conv->dsp, conv->inputBuffer + processing, conv->blockSize - processing);
|
||||
dsp_ops_clear(dsp, conv->inputBuffer + processing, conv->blockSize - processing);
|
||||
|
||||
dsp_ops_fft_run(conv->dsp, conv->fft, 1, conv->inputBuffer, conv->segments[conv->current]);
|
||||
dsp_ops_fft_run(dsp, conv->fft, 1, conv->inputBuffer, conv->segments[conv->current]);
|
||||
|
||||
if (conv->segCount > 1) {
|
||||
if (conv->inputBufferFill == 0) {
|
||||
int indexAudio = (conv->current + 1) % conv->segCount;
|
||||
|
||||
dsp_ops_fft_cmul(conv->dsp, conv->fft, conv->pre_mult,
|
||||
dsp_ops_fft_cmul(dsp, conv->fft, conv->pre_mult,
|
||||
conv->segmentsIr[1],
|
||||
conv->segments[indexAudio],
|
||||
conv->fftComplexSize, conv->scale);
|
||||
|
|
@ -212,7 +209,7 @@ static int convolver1_run(struct convolver1 *conv, const float *input, float *ou
|
|||
for (i = 2; i < conv->segCount; i++) {
|
||||
indexAudio = (conv->current + i) % conv->segCount;
|
||||
|
||||
dsp_ops_fft_cmuladd(conv->dsp, conv->fft,
|
||||
dsp_ops_fft_cmuladd(dsp, conv->fft,
|
||||
conv->pre_mult,
|
||||
conv->pre_mult,
|
||||
conv->segmentsIr[i],
|
||||
|
|
@ -220,30 +217,30 @@ static int convolver1_run(struct convolver1 *conv, const float *input, float *ou
|
|||
conv->fftComplexSize, conv->scale);
|
||||
}
|
||||
}
|
||||
dsp_ops_fft_cmuladd(conv->dsp, conv->fft,
|
||||
dsp_ops_fft_cmuladd(dsp, conv->fft,
|
||||
conv->conv,
|
||||
conv->pre_mult,
|
||||
conv->segments[conv->current],
|
||||
conv->segmentsIr[0],
|
||||
conv->fftComplexSize, conv->scale);
|
||||
} else {
|
||||
dsp_ops_fft_cmul(conv->dsp, conv->fft,
|
||||
dsp_ops_fft_cmul(dsp, conv->fft,
|
||||
conv->conv,
|
||||
conv->segments[conv->current],
|
||||
conv->segmentsIr[0],
|
||||
conv->fftComplexSize, conv->scale);
|
||||
}
|
||||
|
||||
dsp_ops_fft_run(conv->dsp, conv->ifft, -1, conv->conv, conv->fft_buffer);
|
||||
dsp_ops_fft_run(dsp, conv->ifft, -1, conv->conv, conv->fft_buffer);
|
||||
|
||||
dsp_ops_sum(conv->dsp, output + processed, conv->fft_buffer + inputBufferPos,
|
||||
dsp_ops_sum(dsp, output + processed, conv->fft_buffer + inputBufferPos,
|
||||
conv->overlap + inputBufferPos, processing);
|
||||
|
||||
conv->inputBufferFill += processing;
|
||||
if (conv->inputBufferFill == conv->blockSize) {
|
||||
conv->inputBufferFill = 0;
|
||||
|
||||
dsp_ops_copy(conv->dsp, conv->overlap, conv->fft_buffer + conv->blockSize, conv->blockSize);
|
||||
dsp_ops_copy(dsp, conv->overlap, conv->fft_buffer + conv->blockSize, conv->blockSize);
|
||||
|
||||
conv->current = (conv->current > 0) ? (conv->current - 1) : (conv->segCount - 1);
|
||||
}
|
||||
|
|
@ -272,17 +269,18 @@ struct convolver
|
|||
|
||||
void convolver_reset(struct convolver *conv)
|
||||
{
|
||||
struct dsp_ops *dsp = conv->dsp;
|
||||
if (conv->headConvolver)
|
||||
convolver1_reset(conv->headConvolver);
|
||||
convolver1_reset(dsp, conv->headConvolver);
|
||||
if (conv->tailConvolver0) {
|
||||
convolver1_reset(conv->tailConvolver0);
|
||||
dsp_ops_clear(conv->dsp, conv->tailOutput0, conv->tailBlockSize);
|
||||
dsp_ops_clear(conv->dsp, conv->tailPrecalculated0, conv->tailBlockSize);
|
||||
convolver1_reset(dsp, conv->tailConvolver0);
|
||||
dsp_ops_clear(dsp, conv->tailOutput0, conv->tailBlockSize);
|
||||
dsp_ops_clear(dsp, conv->tailPrecalculated0, conv->tailBlockSize);
|
||||
}
|
||||
if (conv->tailConvolver) {
|
||||
convolver1_reset(conv->tailConvolver);
|
||||
dsp_ops_clear(conv->dsp, conv->tailOutput, conv->tailBlockSize);
|
||||
dsp_ops_clear(conv->dsp, conv->tailPrecalculated, conv->tailBlockSize);
|
||||
convolver1_reset(dsp, conv->tailConvolver);
|
||||
dsp_ops_clear(dsp, conv->tailOutput, conv->tailBlockSize);
|
||||
dsp_ops_clear(dsp, conv->tailPrecalculated, conv->tailBlockSize);
|
||||
}
|
||||
conv->tailInputFill = 0;
|
||||
conv->precalculatedPos = 0;
|
||||
|
|
@ -307,10 +305,11 @@ struct convolver *convolver_new(struct dsp_ops *dsp_ops, int head_block, int tai
|
|||
if (conv == NULL)
|
||||
return NULL;
|
||||
|
||||
conv->dsp = dsp_ops;
|
||||
|
||||
if (irlen == 0)
|
||||
return conv;
|
||||
|
||||
conv->dsp = dsp_ops;
|
||||
conv->headBlockSize = next_power_of_two(head_block);
|
||||
conv->tailBlockSize = next_power_of_two(tail_block);
|
||||
|
||||
|
|
@ -341,12 +340,13 @@ struct convolver *convolver_new(struct dsp_ops *dsp_ops, int head_block, int tai
|
|||
|
||||
void convolver_free(struct convolver *conv)
|
||||
{
|
||||
struct dsp_ops *dsp = conv->dsp;
|
||||
if (conv->headConvolver)
|
||||
convolver1_free(conv->headConvolver);
|
||||
convolver1_free(dsp, conv->headConvolver);
|
||||
if (conv->tailConvolver0)
|
||||
convolver1_free(conv->tailConvolver0);
|
||||
convolver1_free(dsp, conv->tailConvolver0);
|
||||
if (conv->tailConvolver)
|
||||
convolver1_free(conv->tailConvolver);
|
||||
convolver1_free(dsp, conv->tailConvolver);
|
||||
fft_free(conv->tailOutput0);
|
||||
fft_free(conv->tailPrecalculated0);
|
||||
fft_free(conv->tailOutput);
|
||||
|
|
@ -357,7 +357,9 @@ void convolver_free(struct convolver *conv)
|
|||
|
||||
int convolver_run(struct convolver *conv, const float *input, float *output, int length)
|
||||
{
|
||||
convolver1_run(conv->headConvolver, input, output, length);
|
||||
struct dsp_ops *dsp = conv->dsp;
|
||||
|
||||
convolver1_run(dsp, conv->headConvolver, input, output, length);
|
||||
|
||||
if (conv->tailInput) {
|
||||
int processed = 0;
|
||||
|
|
@ -367,21 +369,21 @@ int convolver_run(struct convolver *conv, const float *input, float *output, int
|
|||
int processing = SPA_MIN(remaining, conv->headBlockSize - (conv->tailInputFill % conv->headBlockSize));
|
||||
|
||||
if (conv->tailPrecalculated0)
|
||||
dsp_ops_sum(conv->dsp, &output[processed], &output[processed],
|
||||
dsp_ops_sum(dsp, &output[processed], &output[processed],
|
||||
&conv->tailPrecalculated0[conv->precalculatedPos],
|
||||
processing);
|
||||
if (conv->tailPrecalculated)
|
||||
dsp_ops_sum(conv->dsp, &output[processed], &output[processed],
|
||||
dsp_ops_sum(dsp, &output[processed], &output[processed],
|
||||
&conv->tailPrecalculated[conv->precalculatedPos],
|
||||
processing);
|
||||
conv->precalculatedPos += processing;
|
||||
|
||||
dsp_ops_copy(conv->dsp, conv->tailInput + conv->tailInputFill, input + processed, processing);
|
||||
dsp_ops_copy(dsp, conv->tailInput + conv->tailInputFill, input + processed, processing);
|
||||
conv->tailInputFill += processing;
|
||||
|
||||
if (conv->tailPrecalculated0 && (conv->tailInputFill % conv->headBlockSize == 0)) {
|
||||
int blockOffset = conv->tailInputFill - conv->headBlockSize;
|
||||
convolver1_run(conv->tailConvolver0,
|
||||
convolver1_run(dsp, conv->tailConvolver0,
|
||||
conv->tailInput + blockOffset,
|
||||
conv->tailOutput0 + blockOffset,
|
||||
conv->headBlockSize);
|
||||
|
|
@ -392,7 +394,7 @@ int convolver_run(struct convolver *conv, const float *input, float *output, int
|
|||
if (conv->tailPrecalculated &&
|
||||
conv->tailInputFill == conv->tailBlockSize) {
|
||||
SPA_SWAP(conv->tailPrecalculated, conv->tailOutput);
|
||||
convolver1_run(conv->tailConvolver, conv->tailInput,
|
||||
convolver1_run(dsp, conv->tailConvolver, conv->tailInput,
|
||||
conv->tailOutput, conv->tailBlockSize);
|
||||
}
|
||||
if (conv->tailInputFill == conv->tailBlockSize) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue