Struct nih_plug::util::StftHelper
source · pub struct StftHelper<const NUM_SIDECHAIN_INPUTS: usize = 0> { /* private fields */ }
Expand description
Process the input buffer in equal sized blocks, running a callback on each block to transform the block and then writing back the results from the previous block to the buffer. This introduces latency equal to the size of the block.
Additional inputs can be processed by setting the NUM_SIDECHAIN_INPUTS
constant. These buffers
will not be written to, so they are purely used for analysis. These sidechain inputs will have
the same number of channels as the main input.
TODO: Better name? TODO: We may need something like this purely for analysis, e.g. for showing spectrums in a GUI. Figure out the cleanest way to adapt this for the non-processing use case.
Implementations§
source§impl<const NUM_SIDECHAIN_INPUTS: usize> StftHelper<NUM_SIDECHAIN_INPUTS>
impl<const NUM_SIDECHAIN_INPUTS: usize> StftHelper<NUM_SIDECHAIN_INPUTS>
sourcepub fn new(
num_channels: usize,
max_block_size: usize,
max_padding: usize
) -> Self
pub fn new( num_channels: usize, max_block_size: usize, max_padding: usize ) -> Self
Initialize the StftHelper
for Buffer
s with the specified number of channels and the
given maximum block size. When the option is set, then every yielded sample buffer will have
this many zero samples appended at the end of the block. Call
set_block_size()
afterwards if you do not need the full capacity
upfront. If the padding option is non zero, then all yielded blocks will have that many
zeroes added to the end of it and the results stored in the padding area will be added to
the outputs in the next iteration(s). You may also change how much padding is added with
set_padding()
.
Panics
Panics if num_channels == 0 || max_block_size == 0
.
sourcepub fn set_block_size(&mut self, block_size: usize)
pub fn set_block_size(&mut self, block_size: usize)
Change the current block size. This will clear the buffers, causing the next block to output silence.
Panics
Will panic if block_size > max_block_size
.
sourcepub fn set_padding(&mut self, padding: usize)
pub fn set_padding(&mut self, padding: usize)
Change the current padding amount. This will clear the buffers, causing the next block to output silence.
Panics
Will panic if padding > max_padding
.
sourcepub fn num_channels(&self) -> usize
pub fn num_channels(&self) -> usize
The number of channels this StftHelper
was configured for
sourcepub fn max_block_size(&self) -> usize
pub fn max_block_size(&self) -> usize
The maximum block size supported by this instance.
sourcepub fn max_padding(&self) -> usize
pub fn max_padding(&self) -> usize
The maximum amount of padding supported by this instance.
sourcepub fn latency_samples(&self) -> u32
pub fn latency_samples(&self) -> u32
The amount of latency introduced when processing audio through this StftHelper
.
sourcepub fn process_overlap_add<M, F>(
&mut self,
main_buffer: &mut M,
overlap_times: usize,
process_cb: F
)where
M: StftInputMut,
F: FnMut(usize, &mut [f32]),
pub fn process_overlap_add<M, F>( &mut self, main_buffer: &mut M, overlap_times: usize, process_cb: F )where M: StftInputMut, F: FnMut(usize, &mut [f32]),
Process the audio in main_buffer
in small overlapping blocks, adding up the results for
the main buffer so they can eventually be written back to the host one block later. This
means that this function will introduce one block of latency. This can be compensated by
calling InitContext::set_latency()
in your plugin’s initialization function.
If a padding value was specified in new()
, then the yielded blocks will
have that many zeroes appended at the end of them. The padding values will be added to the
next block before process_cb()
is called.
Since there are a couple different ways to do it, any window functions needs to be applied
in the callbacks. Check the nih_plug::util::window
module for more information.
For efficiency’s sake this function will reuse the same vector for all calls to
process_cb
. This means you can only access a single channel’s worth of windowed data at a
time. The arguments to that function are process_cb(channel_idx, real_fft_buffer)
.
real_fft_buffer
will be a slice of block_size
real valued samples. This can be passed
directly to an FFT algorithm.
Panics
Panics if main_buffer
or the buffers in sidechain_buffers
do not have the same number of
channels as this StftHelper
, or if the sidechain buffers do not contain the same number of
samples as the main buffer.
TODO: Add more useful ways to do STFT and other buffered operations. I just went with this approach because it’s what I needed myself, but generic combinators like this could also be useful for other operations.
sourcepub fn process_overlap_add_sidechain<M, S, F>(
&mut self,
main_buffer: &mut M,
sidechain_buffers: [&S; NUM_SIDECHAIN_INPUTS],
overlap_times: usize,
process_cb: F
)where
M: StftInputMut,
S: StftInput,
F: FnMut(usize, Option<usize>, &mut [f32]),
pub fn process_overlap_add_sidechain<M, S, F>( &mut self, main_buffer: &mut M, sidechain_buffers: [&S; NUM_SIDECHAIN_INPUTS], overlap_times: usize, process_cb: F )where M: StftInputMut, S: StftInput, F: FnMut(usize, Option<usize>, &mut [f32]),
The same as process_overlap_add()
, but with sidechain
inputs that can be analyzed before the main input gets processed.
The extra argument in the process function is sidechain_buffer_idx
, which will be None
for the main buffer.
sourcepub fn process_analyze_only<B, F>(
&mut self,
buffer: &B,
overlap_times: usize,
analyze_cb: F
)where
B: StftInput,
F: FnMut(usize, &mut [f32]),
pub fn process_analyze_only<B, F>( &mut self, buffer: &B, overlap_times: usize, analyze_cb: F )where B: StftInput, F: FnMut(usize, &mut [f32]),
Similar to process_overlap_add()
, but without the inverse
STFT part. buffer
will only ever be read from. This can be useful for providing FFT data
for a spectrum analyzer in a plugin GUI. These is still a delay to the analysis equal to the
block size.