Skip to content

FFT-Based Sample Rate Conversion

dft_resampler resamples real-valued signals by applying a low-pass filter in the frequency domain with an FFT overlap-save algorithm. It is designed for power-of-two conversion ratios: use a positive shift to upsample and a negative shift to downsample.

For long filters, this block-based approach can be faster than the sample-by-sample polyphase implementation in samplerate_converter. Use samplerate_converter when the ratio is not a power of two or when sample-based processing is required; see Sample Rate Conversion.

Feature samplerate_converter dft_resampler
Algorithm Polyphase FIR FFT-based overlap-save
Resampling ratio Any rational ratio Power of two (\(2^n\))
Processing Sample-based Block-based

Creating a Resampler

Configure the conversion with dft_resampler_params. Its shift argument specifies the ratio: 1 is 2× upsampling, -1 is 2× downsampling, and 0 applies only the filter. The remaining parameters control the filter cutoff, stopband attenuation, and transition width.

// 2x upsampling (shift = 1)
dft_resampler_params params(1);
dft_resampler<float> resampler(params);

Processing Blocks and Streams

.process_frame(const T *) processes one explicit overlap-save frame. The input buffer must contain .input_block_size() samples, and the output buffer must hold .output_hop() samples.

univector<float> input(resampler.input_block_size(), 1.0f);
univector<float> output(resampler.output_hop());

// Process one input frame.
resampler.process_frame(output.data(), input.data());

For input that does not already arrive in complete frames, use .process(std::span<T>, std::span<const T>). It accumulates samples into .input_hop()-sized hops and calls .process_frame(const T *) for each complete frame. Each complete input hop produces one output hop; ensure the output span has room for all produced samples.

See Fast Fourier Transform with KFR for the underlying DFT API.