How to apply Convolution Reverb¶
Mono version¶
Input/Output data: See how to pass data to KFR
univector<float> audio;
univector<float> impulse_response;
convolve_filter<float> reverb(impulse_response);
reverb.apply(audio);
Note
convolve_filter
uses Filter API and preserves its internal state between calls to apply
.
Audio can be processed in chunks.
Use reset
function to reset its internal state.
convolve_filter
has zero latency.
Internally, FFT is used for performing convolution
True stereo version¶
Formula
where is convolution operator.
Input/Output data:
univector<float, 2> stereo_audio;
univector<float, 4> impulse_response;
// impulse_response[0] is left to left
// impulse_response[1] is right to left
// impulse_response[2] is left to right
// impulse_response[3] is right to right
// Prepare filters
convolve_filter<float> reverb_LL(impulse_response[0]);
convolve_filter<float> reverb_LR(impulse_response[1]);
convolve_filter<float> reverb_RL(impulse_response[2]);
convolve_filter<float> reverb_RR(impulse_response[3]);
// Allocate temp data
univector<float> tmp1(stereo_audio[0].size());
univector<float> tmp2(stereo_audio[0].size());
univector<float> tmp3(stereo_audio[0].size());
univector<float> tmp4(stereo_audio[0].size());
// Apply convolution
reverb_LL.apply(tmp1, audio[0]);
reverb_RL.apply(tmp2, audio[1]);
reverb_LR.apply(tmp3, audio[0]);
reverb_RR.apply(tmp4, audio[1]);
// final downmix
audio[0] = tmp1 + tmp2;
audio[1] = tmp3 + tmp4;
Implementation Details¶
The convolution filter efficiently computes the convolution of two signals. The efficiency is achieved by employing the FFT and the circular convolution theorem. The algorithm is a variant of the overlap-add method. It works on a fixed block size for arbitrarily long input signals. Thus, the convolution of a streaming input signal with a long FIR filter (where the length of may exceed the block size ) is computed with a fixed complexity .
More formally, the convolution filter computes by partitioning the input and filter into blocks and applies the overlap-add method. Let be an input signal of arbitrary length. Often, is a streaming input with unknown length. Let be an FIR filter with taps. The convolution filter works on a fixed block size .
First, the input and filter are windowed and shifted to the origin to give the -th block input and -th block filter . The convolution is efficiently computed with length FFTs as [ y_{k,j}[n] = \mathrm{IFFT}(\mathrm{FFT}(x_k[n])\cdot\mathrm{FFT}(h_j[n])) . ]
The overlap-add method sums the "overlap" from the previous block with the current block. To complete the -th block, the contribution of all blocks of the filter are summed together to give [ y_{k}[n] = \sum_j y_{k-j,j}[n] . ] The final convolution is then the sum of the shifted blocks [ y[n] = \sum_k y_{k}[n - kB] . ] Note that is of length so its second half overlaps and adds into the first half of the block.
Maximum efficiency criterion¶
To avoid excess computation or maximize throughput, the convolution filter should be given input samples in multiples of the block size . Otherwise, the FFT of a block is computed twice as many times as would be necessary and hence throughput is reduced.