pub struct TwoStageFFTConvolver<F: FftNum> {Show 14 fields
ir_len: usize,
head_block_size: usize,
tail_block_size: usize,
head_convolver: FFTConvolver<F>,
tail_convolver0: FFTConvolver<F>,
tail_convolver: FFTConvolver<F>,
tail_input: Vec<F>,
tail_input_fill: usize,
tail_output0: Vec<F>,
tail_precalculated0: Vec<F>,
tail_output: Vec<F>,
tail_precalculated: Vec<F>,
processing_buffer: Vec<F>,
precalculated_pos: usize,
}Expand description
TwoStageFFTConvolver Implementation of a partitioned FFT convolution algorithm with non-uniform block sizes.
Uses two different block sizes: a small head block size for low latency and a
larger tail block size for efficient processing of long impulse responses.
Internally uses three FFTConvolver instances:
- Head: Processes the first portion of the IR at the small block size (zero latency)
- Tail0: Transition stage that bridges the latency gap between head and tail
- Tail: Processes the remaining IR at the larger block size (efficient)
Some notes on how to use it:
- After initialization with an impulse response, subsequent data portions of arbitrary length can be convolved. The convolver internally can handle this by using appropriate buffering.
- The convolver works without “latency” (except for the required processing time, of course), i.e. the output always is the convolved input for each processing call.
- The convolver is suitable for real-time processing which means that no “unpredictable” operations like allocations, locking, API calls, etc. are performed during processing (all necessary allocations and preparations take place during initialization).
Fields§
§ir_len: usize§head_block_size: usize§tail_block_size: usize§head_convolver: FFTConvolver<F>§tail_convolver0: FFTConvolver<F>§tail_convolver: FFTConvolver<F>§tail_input: Vec<F>§tail_input_fill: usize§tail_output0: Vec<F>§tail_precalculated0: Vec<F>§tail_output: Vec<F>§tail_precalculated: Vec<F>§processing_buffer: Vec<F>§precalculated_pos: usizeImplementations§
Source§impl<F: FftNum> TwoStageFFTConvolver<F>
impl<F: FftNum> TwoStageFFTConvolver<F>
Sourcepub fn init(
&mut self,
head_block_size: usize,
tail_block_size: usize,
impulse_response: &[F],
) -> Result<(), FFTConvolverError>
pub fn init( &mut self, head_block_size: usize, tail_block_size: usize, impulse_response: &[F], ) -> Result<(), FFTConvolverError>
Initializes the two-stage convolver with an impulse response
This method sets up all internal buffers and prepares the convolver for processing. The head block size determines latency and will be rounded up to the next power of 2. The tail block size determines efficiency for the tail portion and will also be rounded up to the next power of 2.
Use compute_tail_block_size to calculate an
optimal tail block size based on García’s formula.
All memory allocations happen during initialization, making subsequent processing operations real-time safe.
§Arguments
head_block_size- Block size for the head convolver (determines latency). Will be rounded up to the next power of 2. Must be > 0.tail_block_size- Block size for the tail convolver (determines efficiency). Will be rounded up to the next power of 2. Must be > 0. If smaller thanhead_block_size, the two values are automatically swapped.impulse_response- The impulse response to convolve with. Can be empty.
§Returns
Returns BlockSizeZero if either block size is 0.
§Example
use fft_convolver::{TwoStageFFTConvolver, compute_tail_block_size};
let ir = vec![0.5_f32; 10000];
let head_block_size = 64;
let tail_block_size = compute_tail_block_size(head_block_size, ir.len());
let mut convolver = TwoStageFFTConvolver::default();
convolver.init(head_block_size, tail_block_size, &ir).unwrap();Sourcepub fn init_default(
&mut self,
head_block_size: usize,
impulse_response: &[F],
) -> Result<(), FFTConvolverError>
pub fn init_default( &mut self, head_block_size: usize, impulse_response: &[F], ) -> Result<(), FFTConvolverError>
Initializes the two-stage convolver with an automatically computed tail block size
This is a convenience method that computes the optimal tail block size using
García’s formula and then calls init.
§Arguments
head_block_size- Block size for the head convolver (determines latency). Will be rounded up to the next power of 2. Must be > 0.impulse_response- The impulse response to convolve with. Can be empty.
§Returns
Returns BlockSizeZero if head_block_size is 0.
§Example
use fft_convolver::TwoStageFFTConvolver;
let ir = vec![0.5_f32; 10000];
let mut convolver = TwoStageFFTConvolver::default();
convolver.init_default(64, &ir).unwrap();Sourcepub fn set_response(
&mut self,
impulse_response: &[F],
) -> Result<(), FFTConvolverError>
pub fn set_response( &mut self, impulse_response: &[F], ) -> Result<(), FFTConvolverError>
Updates the impulse response without reallocating buffers
This method allows changing the impulse response at runtime while maintaining real-time safety by avoiding allocations. The new impulse response must not exceed the length of the original impulse response used during initialization.
§Arguments
impulse_response- The new impulse response (must be ≤ original length)
§Returns
Returns ImpulseResponseExceedsCapacity if the new impulse response is longer
than the original one.
§Example
use fft_convolver::{TwoStageFFTConvolver, compute_tail_block_size};
let ir1 = vec![0.5_f32; 10000];
let head_block_size = 64;
let tail_block_size = compute_tail_block_size(head_block_size, ir1.len());
let mut convolver = TwoStageFFTConvolver::default();
convolver.init(head_block_size, tail_block_size, &ir1).unwrap();
let ir2 = vec![0.8_f32; 5000];
convolver.set_response(&ir2).unwrap();Sourcepub fn process(
&mut self,
input: &[F],
output: &mut [F],
) -> Result<(), FFTConvolverError>
pub fn process( &mut self, input: &[F], output: &mut [F], ) -> Result<(), FFTConvolverError>
Convolves the input samples with the impulse response and outputs the result
This is a real-time safe operation that performs no allocations. Internal buffering handles arbitrary sizes and ensures the output is always properly aligned with the input (zero latency except for processing time).
§Arguments
input- The input samples to convolveoutput- Buffer to write the convolution result. Must have the same length asinput.
§Returns
Returns InputOutputLengthMismatch if input and output have different lengths.
Returns Fft error if an FFT operation fails.
§Example
use fft_convolver::{TwoStageFFTConvolver, compute_tail_block_size};
let ir = vec![0.5_f32; 10000];
let head_block_size = 64;
let tail_block_size = compute_tail_block_size(head_block_size, ir.len());
let mut convolver = TwoStageFFTConvolver::default();
convolver.init(head_block_size, tail_block_size, &ir).unwrap();
let input = vec![1.0_f32; 256];
let mut output = vec![0.0_f32; 256];
convolver.process(&input, &mut output).unwrap();Sourcepub fn reset(&mut self)
pub fn reset(&mut self)
Clears the internal processing state while preserving the impulse response
This real-time safe operation resets all internal buffers that store the convolution state, effectively removing any “history” or “tail” from previous processing. The impulse response configuration remains intact, so processing can continue immediately.
This is useful when handling stream discontinuities such as:
- Seeking in audio playback
- Pause/resume operations with large time gaps
- Switching between different audio sources
After calling reset(), the next process() call will produce output as if
the convolver had just been initialized.
§Example
use fft_convolver::{TwoStageFFTConvolver, compute_tail_block_size};
let ir = vec![0.5_f32; 10000];
let head_block_size = 64;
let tail_block_size = compute_tail_block_size(head_block_size, ir.len());
let mut convolver = TwoStageFFTConvolver::default();
convolver.init(head_block_size, tail_block_size, &ir).unwrap();
let input = vec![1.0_f32; 256];
let mut output = vec![0.0_f32; 256];
convolver.process(&input, &mut output).unwrap();
convolver.reset();
convolver.process(&input, &mut output).unwrap();Trait Implementations§
Source§impl<F: Clone + FftNum> Clone for TwoStageFFTConvolver<F>
impl<F: Clone + FftNum> Clone for TwoStageFFTConvolver<F>
Source§fn clone(&self) -> TwoStageFFTConvolver<F>
fn clone(&self) -> TwoStageFFTConvolver<F>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more