diff --git a/spa/plugins/filter-graph/convolver.c b/spa/plugins/filter-graph/convolver.c index 788b118e3..955a33475 100644 --- a/spa/plugins/filter-graph/convolver.c +++ b/spa/plugins/filter-graph/convolver.c @@ -10,7 +10,7 @@ #include -struct convolver1 { +struct partition { int blockSize; int segSize; int segCount; @@ -42,48 +42,48 @@ static int next_power_of_two(int val) return r; } -static void convolver1_reset(struct spa_fga_dsp *dsp, struct convolver1 *conv) +static void partition_reset(struct spa_fga_dsp *dsp, struct partition *part) { int i; - for (i = 0; i < conv->segCount; i++) - spa_fga_dsp_fft_memclear(dsp, conv->segments[i], conv->fftComplexSize, false); - spa_fga_dsp_fft_memclear(dsp, conv->fft_buffer[0], conv->segSize, true); - spa_fga_dsp_fft_memclear(dsp, conv->fft_buffer[1], conv->segSize, true); - spa_fga_dsp_fft_memclear(dsp, conv->inputBuffer, conv->segSize, true); - spa_fga_dsp_fft_memclear(dsp, conv->pre_mult, conv->fftComplexSize, false); - spa_fga_dsp_fft_memclear(dsp, conv->conv, conv->fftComplexSize, false); - conv->inputBufferFill = 0; - conv->current = 0; + for (i = 0; i < part->segCount; i++) + spa_fga_dsp_fft_memclear(dsp, part->segments[i], part->fftComplexSize, false); + spa_fga_dsp_fft_memclear(dsp, part->fft_buffer[0], part->segSize, true); + spa_fga_dsp_fft_memclear(dsp, part->fft_buffer[1], part->segSize, true); + spa_fga_dsp_fft_memclear(dsp, part->inputBuffer, part->segSize, true); + spa_fga_dsp_fft_memclear(dsp, part->pre_mult, part->fftComplexSize, false); + spa_fga_dsp_fft_memclear(dsp, part->conv, part->fftComplexSize, false); + part->inputBufferFill = 0; + part->current = 0; } -static void convolver1_free(struct spa_fga_dsp *dsp, struct convolver1 *conv) +static void partition_free(struct spa_fga_dsp *dsp, struct partition *part) { int i; - for (i = 0; i < conv->segCount; i++) { - if (conv->segments) - spa_fga_dsp_fft_memfree(dsp, conv->segments[i]); - if (conv->segmentsIr) - spa_fga_dsp_fft_memfree(dsp, conv->segmentsIr[i]); + for (i = 0; i < part->segCount; i++) { + if (part->segments) + spa_fga_dsp_fft_memfree(dsp, part->segments[i]); + if (part->segmentsIr) + spa_fga_dsp_fft_memfree(dsp, part->segmentsIr[i]); } - if (conv->fft) - spa_fga_dsp_fft_free(dsp, conv->fft); - if (conv->ifft) - spa_fga_dsp_fft_free(dsp, conv->ifft); - if (conv->fft_buffer[0]) - spa_fga_dsp_fft_memfree(dsp, conv->fft_buffer[0]); - if (conv->fft_buffer[1]) - spa_fga_dsp_fft_memfree(dsp, conv->fft_buffer[1]); - free(conv->segments); - free(conv->segmentsIr); - spa_fga_dsp_fft_memfree(dsp, conv->pre_mult); - spa_fga_dsp_fft_memfree(dsp, conv->conv); - spa_fga_dsp_fft_memfree(dsp, conv->inputBuffer); - free(conv); + if (part->fft) + spa_fga_dsp_fft_free(dsp, part->fft); + if (part->ifft) + spa_fga_dsp_fft_free(dsp, part->ifft); + if (part->fft_buffer[0]) + spa_fga_dsp_fft_memfree(dsp, part->fft_buffer[0]); + if (part->fft_buffer[1]) + spa_fga_dsp_fft_memfree(dsp, part->fft_buffer[1]); + free(part->segments); + free(part->segmentsIr); + spa_fga_dsp_fft_memfree(dsp, part->pre_mult); + spa_fga_dsp_fft_memfree(dsp, part->conv); + spa_fga_dsp_fft_memfree(dsp, part->inputBuffer); + free(part); } -static struct convolver1 *convolver1_new(struct spa_fga_dsp *dsp, int block, const float *ir, int irlen) +static struct partition *partition_new(struct spa_fga_dsp *dsp, int block, const float *ir, int irlen) { - struct convolver1 *conv; + struct partition *part; int i; if (block == 0) @@ -92,139 +92,139 @@ static struct convolver1 *convolver1_new(struct spa_fga_dsp *dsp, int block, con while (irlen > 0 && fabs(ir[irlen-1]) < 0.000001f) irlen--; - conv = calloc(1, sizeof(*conv)); - if (conv == NULL) + part = calloc(1, sizeof(*part)); + if (part == NULL) return NULL; if (irlen == 0) - return conv; + return part; - 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; + part->blockSize = next_power_of_two(block); + part->segSize = 2 * part->blockSize; + part->segCount = (irlen + part->blockSize-1) / part->blockSize; + part->fftComplexSize = (part->segSize / 2) + 1; - conv->fft = spa_fga_dsp_fft_new(dsp, conv->segSize, true); - if (conv->fft == NULL) + part->fft = spa_fga_dsp_fft_new(dsp, part->segSize, true); + if (part->fft == NULL) goto error; - conv->ifft = spa_fga_dsp_fft_new(dsp, conv->segSize, true); - if (conv->ifft == NULL) + part->ifft = spa_fga_dsp_fft_new(dsp, part->segSize, true); + if (part->ifft == NULL) goto error; - conv->fft_buffer[0] = spa_fga_dsp_fft_memalloc(dsp, conv->segSize, true); - conv->fft_buffer[1] = spa_fga_dsp_fft_memalloc(dsp, conv->segSize, true); - if (conv->fft_buffer[0] == NULL || conv->fft_buffer[1] == NULL) + part->fft_buffer[0] = spa_fga_dsp_fft_memalloc(dsp, part->segSize, true); + part->fft_buffer[1] = spa_fga_dsp_fft_memalloc(dsp, part->segSize, true); + if (part->fft_buffer[0] == NULL || part->fft_buffer[1] == NULL) goto error; - conv->segments = calloc(conv->segCount, sizeof(float*)); - conv->segmentsIr = calloc(conv->segCount, sizeof(float*)); - if (conv->segments == NULL || conv->segmentsIr == NULL) + part->segments = calloc(part->segCount, sizeof(float*)); + part->segmentsIr = calloc(part->segCount, sizeof(float*)); + if (part->segments == NULL || part->segmentsIr == NULL) goto error; - for (i = 0; i < conv->segCount; i++) { - int left = irlen - (i * conv->blockSize); - int copy = SPA_MIN(conv->blockSize, left); + for (i = 0; i < part->segCount; i++) { + int left = irlen - (i * part->blockSize); + int copy = SPA_MIN(part->blockSize, left); - conv->segments[i] = spa_fga_dsp_fft_memalloc(dsp, conv->fftComplexSize, false); - conv->segmentsIr[i] = spa_fga_dsp_fft_memalloc(dsp, conv->fftComplexSize, false); - if (conv->segments[i] == NULL || conv->segmentsIr[i] == NULL) + part->segments[i] = spa_fga_dsp_fft_memalloc(dsp, part->fftComplexSize, false); + part->segmentsIr[i] = spa_fga_dsp_fft_memalloc(dsp, part->fftComplexSize, false); + if (part->segments[i] == NULL || part->segmentsIr[i] == NULL) goto error; - spa_fga_dsp_copy(dsp, conv->fft_buffer[0], &ir[i * conv->blockSize], copy); - if (copy < conv->segSize) - spa_fga_dsp_fft_memclear(dsp, conv->fft_buffer[0] + copy, conv->segSize - copy, true); + spa_fga_dsp_copy(dsp, part->fft_buffer[0], &ir[i * part->blockSize], copy); + if (copy < part->segSize) + spa_fga_dsp_fft_memclear(dsp, part->fft_buffer[0] + copy, part->segSize - copy, true); - spa_fga_dsp_fft_run(dsp, conv->fft, 1, conv->fft_buffer[0], conv->segmentsIr[i]); + spa_fga_dsp_fft_run(dsp, part->fft, 1, part->fft_buffer[0], part->segmentsIr[i]); } - conv->pre_mult = spa_fga_dsp_fft_memalloc(dsp, conv->fftComplexSize, false); - conv->conv = spa_fga_dsp_fft_memalloc(dsp, conv->fftComplexSize, false); - conv->inputBuffer = spa_fga_dsp_fft_memalloc(dsp, conv->segSize, true); - if (conv->pre_mult == NULL || conv->conv == NULL || conv->inputBuffer == NULL) + part->pre_mult = spa_fga_dsp_fft_memalloc(dsp, part->fftComplexSize, false); + part->conv = spa_fga_dsp_fft_memalloc(dsp, part->fftComplexSize, false); + part->inputBuffer = spa_fga_dsp_fft_memalloc(dsp, part->segSize, true); + if (part->pre_mult == NULL || part->conv == NULL || part->inputBuffer == NULL) goto error; - conv->scale = 1.0f / conv->segSize; - convolver1_reset(dsp, conv); + part->scale = 1.0f / part->segSize; + partition_reset(dsp, part); - return conv; + return part; error: - convolver1_free(dsp, conv); + partition_free(dsp, part); return NULL; } -static int convolver1_run(struct spa_fga_dsp *dsp, struct convolver1 *conv, const float *input, float *output, int len) +static int partition_run(struct spa_fga_dsp *dsp, struct partition *part, const float *input, float *output, int len) { int i, processed = 0; - if (conv == NULL || conv->segCount == 0) { + if (part == NULL || part->segCount == 0) { spa_fga_dsp_fft_memclear(dsp, output, len, true); return len; } - int inputBufferFill = conv->inputBufferFill; + int inputBufferFill = part->inputBufferFill; while (processed < len) { - const int processing = SPA_MIN(len - processed, conv->blockSize - inputBufferFill); + const int processing = SPA_MIN(len - processed, part->blockSize - inputBufferFill); - spa_fga_dsp_copy(dsp, conv->inputBuffer + inputBufferFill, input + processed, processing); - if (inputBufferFill == 0 && processing < conv->blockSize) - spa_fga_dsp_fft_memclear(dsp, conv->inputBuffer + processing, - conv->blockSize - processing, true); - spa_fga_dsp_fft_run(dsp, conv->fft, 1, conv->inputBuffer, conv->segments[conv->current]); + spa_fga_dsp_copy(dsp, part->inputBuffer + inputBufferFill, input + processed, processing); + if (inputBufferFill == 0 && processing < part->blockSize) + spa_fga_dsp_fft_memclear(dsp, part->inputBuffer + processing, + part->blockSize - processing, true); + spa_fga_dsp_fft_run(dsp, part->fft, 1, part->inputBuffer, part->segments[part->current]); - if (conv->segCount > 1) { + if (part->segCount > 1) { if (inputBufferFill == 0) { - int indexAudio = conv->current; + int indexAudio = part->current; - if (++indexAudio == conv->segCount) + if (++indexAudio == part->segCount) indexAudio = 0; - spa_fga_dsp_fft_cmul(dsp, conv->fft, conv->pre_mult, - conv->segmentsIr[1], - conv->segments[indexAudio], - conv->fftComplexSize, conv->scale); + spa_fga_dsp_fft_cmul(dsp, part->fft, part->pre_mult, + part->segmentsIr[1], + part->segments[indexAudio], + part->fftComplexSize, part->scale); - for (i = 2; i < conv->segCount; i++) { - if (++indexAudio == conv->segCount) + for (i = 2; i < part->segCount; i++) { + if (++indexAudio == part->segCount) indexAudio = 0; - spa_fga_dsp_fft_cmuladd(dsp, conv->fft, - conv->pre_mult, - conv->pre_mult, - conv->segmentsIr[i], - conv->segments[indexAudio], - conv->fftComplexSize, conv->scale); + spa_fga_dsp_fft_cmuladd(dsp, part->fft, + part->pre_mult, + part->pre_mult, + part->segmentsIr[i], + part->segments[indexAudio], + part->fftComplexSize, part->scale); } } - spa_fga_dsp_fft_cmuladd(dsp, conv->fft, - conv->conv, - conv->pre_mult, - conv->segments[conv->current], - conv->segmentsIr[0], - conv->fftComplexSize, conv->scale); + spa_fga_dsp_fft_cmuladd(dsp, part->fft, + part->conv, + part->pre_mult, + part->segments[part->current], + part->segmentsIr[0], + part->fftComplexSize, part->scale); } else { - spa_fga_dsp_fft_cmul(dsp, conv->fft, - conv->conv, - conv->segments[conv->current], - conv->segmentsIr[0], - conv->fftComplexSize, conv->scale); + spa_fga_dsp_fft_cmul(dsp, part->fft, + part->conv, + part->segments[part->current], + part->segmentsIr[0], + part->fftComplexSize, part->scale); } - spa_fga_dsp_fft_run(dsp, conv->ifft, -1, conv->conv, conv->fft_buffer[0]); + spa_fga_dsp_fft_run(dsp, part->ifft, -1, part->conv, part->fft_buffer[0]); - spa_fga_dsp_sum(dsp, output + processed, conv->fft_buffer[0] + inputBufferFill, - conv->fft_buffer[1] + conv->blockSize + inputBufferFill, processing); + spa_fga_dsp_sum(dsp, output + processed, part->fft_buffer[0] + inputBufferFill, + part->fft_buffer[1] + part->blockSize + inputBufferFill, processing); inputBufferFill += processing; - if (inputBufferFill == conv->blockSize) { + if (inputBufferFill == part->blockSize) { inputBufferFill = 0; - SPA_SWAP(conv->fft_buffer[0], conv->fft_buffer[1]); + SPA_SWAP(part->fft_buffer[0], part->fft_buffer[1]); - if (conv->current == 0) - conv->current = conv->segCount; - conv->current--; + if (part->current == 0) + part->current = part->segCount; + part->current--; } processed += processing; } - conv->inputBufferFill = inputBufferFill; + part->inputBufferFill = inputBufferFill; return len; } @@ -233,11 +233,11 @@ struct convolver struct spa_fga_dsp *dsp; int headBlockSize; int tailBlockSize; - struct convolver1 *headConvolver; - struct convolver1 *tailConvolver0; + struct partition *headPartition; + struct partition *tailPartition0; float *tailOutput0; float *tailPrecalculated0; - struct convolver1 *tailConvolver; + struct partition *tailPartition; float *tailOutput; float *tailPrecalculated; float *tailInput; @@ -248,15 +248,15 @@ void convolver_reset(struct convolver *conv) { struct spa_fga_dsp *dsp = conv->dsp; - if (conv->headConvolver) - convolver1_reset(dsp, conv->headConvolver); - if (conv->tailConvolver0) { - convolver1_reset(dsp, conv->tailConvolver0); + if (conv->headPartition) + partition_reset(dsp, conv->headPartition); + if (conv->tailPartition0) { + partition_reset(dsp, conv->tailPartition0); spa_fga_dsp_fft_memclear(dsp, conv->tailOutput0, conv->tailBlockSize, true); spa_fga_dsp_fft_memclear(dsp, conv->tailPrecalculated0, conv->tailBlockSize, true); } - if (conv->tailConvolver) { - convolver1_reset(dsp, conv->tailConvolver); + if (conv->tailPartition) { + partition_reset(dsp, conv->tailPartition); spa_fga_dsp_fft_memclear(dsp, conv->tailOutput, conv->tailBlockSize, true); spa_fga_dsp_fft_memclear(dsp, conv->tailPrecalculated, conv->tailBlockSize, true); } @@ -291,31 +291,31 @@ struct convolver *convolver_new(struct spa_fga_dsp *dsp, int head_block, int tai conv->tailBlockSize = next_power_of_two(tail_block); head_ir_len = SPA_MIN(irlen, conv->tailBlockSize); - conv->headConvolver = convolver1_new(dsp, conv->headBlockSize, ir, head_ir_len); - if (conv->headConvolver == NULL) + conv->headPartition = partition_new(dsp, conv->headBlockSize, ir, head_ir_len); + if (conv->headPartition == NULL) goto error; if (irlen > conv->tailBlockSize) { int conv1IrLen = SPA_MIN(irlen - conv->tailBlockSize, conv->tailBlockSize); - conv->tailConvolver0 = convolver1_new(dsp, conv->headBlockSize, ir + conv->tailBlockSize, conv1IrLen); + conv->tailPartition0 = partition_new(dsp, conv->headBlockSize, ir + conv->tailBlockSize, conv1IrLen); conv->tailOutput0 = spa_fga_dsp_fft_memalloc(dsp, conv->tailBlockSize, true); conv->tailPrecalculated0 = spa_fga_dsp_fft_memalloc(dsp, conv->tailBlockSize, true); - if (conv->tailConvolver0 == NULL || conv->tailOutput0 == NULL || + if (conv->tailPartition0 == NULL || conv->tailOutput0 == NULL || conv->tailPrecalculated0 == NULL) goto error; } if (irlen > 2 * conv->tailBlockSize) { int tailIrLen = irlen - (2 * conv->tailBlockSize); - conv->tailConvolver = convolver1_new(dsp, conv->tailBlockSize, ir + (2 * conv->tailBlockSize), tailIrLen); + conv->tailPartition = partition_new(dsp, conv->tailBlockSize, ir + (2 * conv->tailBlockSize), tailIrLen); conv->tailOutput = spa_fga_dsp_fft_memalloc(dsp, conv->tailBlockSize, true); conv->tailPrecalculated = spa_fga_dsp_fft_memalloc(dsp, conv->tailBlockSize, true); - if (conv->tailConvolver == NULL || conv->tailOutput == NULL || + if (conv->tailPartition == NULL || conv->tailOutput == NULL || conv->tailPrecalculated == NULL) goto error; } - if (conv->tailConvolver0 || conv->tailConvolver) { + if (conv->tailPartition0 || conv->tailPartition) { conv->tailInput = spa_fga_dsp_fft_memalloc(dsp, conv->tailBlockSize, true); if (conv->tailInput == NULL) goto error; @@ -333,12 +333,12 @@ void convolver_free(struct convolver *conv) { struct spa_fga_dsp *dsp = conv->dsp; - if (conv->headConvolver) - convolver1_free(dsp, conv->headConvolver); - if (conv->tailConvolver0) - convolver1_free(dsp, conv->tailConvolver0); - if (conv->tailConvolver) - convolver1_free(dsp, conv->tailConvolver); + if (conv->headPartition) + partition_free(dsp, conv->headPartition); + if (conv->tailPartition0) + partition_free(dsp, conv->tailPartition0); + if (conv->tailPartition) + partition_free(dsp, conv->tailPartition); spa_fga_dsp_fft_memfree(dsp, conv->tailOutput0); spa_fga_dsp_fft_memfree(dsp, conv->tailPrecalculated0); spa_fga_dsp_fft_memfree(dsp, conv->tailOutput); @@ -351,7 +351,7 @@ int convolver_run(struct convolver *conv, const float *input, float *output, int { struct spa_fga_dsp *dsp = conv->dsp; - convolver1_run(dsp, conv->headConvolver, input, output, length); + partition_run(dsp, conv->headPartition, input, output, length); if (conv->tailInput) { int processed = 0; @@ -374,7 +374,7 @@ int convolver_run(struct convolver *conv, const float *input, float *output, int if (conv->tailPrecalculated0 && (conv->tailInputFill % conv->headBlockSize == 0)) { int blockOffset = conv->tailInputFill - conv->headBlockSize; - convolver1_run(dsp, conv->tailConvolver0, + partition_run(dsp, conv->tailPartition0, conv->tailInput + blockOffset, conv->tailOutput0 + blockOffset, conv->headBlockSize); @@ -385,7 +385,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(dsp, conv->tailConvolver, conv->tailInput, + partition_run(dsp, conv->tailPartition, conv->tailInput, conv->tailOutput, conv->tailBlockSize); } if (conv->tailInputFill == conv->tailBlockSize)