Precompute 2-log frequencies for the compressors
This commit is contained in:
parent
b8525cac4d
commit
fad560ab9f
|
@ -34,6 +34,10 @@ pub struct CompressorBank {
|
|||
/// The same as `should_update_downwards_ratios`, but for upwards ratios.
|
||||
pub should_update_upwards_ratios: Arc<AtomicBool>,
|
||||
|
||||
/// For each compressor bin, `log2(freq)` where `freq` is the frequency associated with that
|
||||
/// compressor. This is precomputed since all update functions need it.
|
||||
log2_freqs: Vec<f32>,
|
||||
|
||||
/// Downwards compressor thresholds, in linear space.
|
||||
downwards_thresholds: Vec<f32>,
|
||||
/// Upwards compressor thresholds, in linear space.
|
||||
|
@ -336,6 +340,8 @@ impl CompressorBank {
|
|||
should_update_downwards_ratios: Arc::new(AtomicBool::new(true)),
|
||||
should_update_upwards_ratios: Arc::new(AtomicBool::new(true)),
|
||||
|
||||
log2_freqs: Vec::with_capacity(complex_buffer_len),
|
||||
|
||||
downwards_thresholds: Vec::with_capacity(complex_buffer_len),
|
||||
upwards_thresholds: Vec::with_capacity(complex_buffer_len),
|
||||
downwards_ratios: Vec::with_capacity(complex_buffer_len),
|
||||
|
@ -350,6 +356,9 @@ impl CompressorBank {
|
|||
pub fn update_capacity(&mut self, num_channels: usize, max_window_size: usize) {
|
||||
let complex_buffer_len = max_window_size / 2 + 1;
|
||||
|
||||
self.log2_freqs
|
||||
.reserve_exact(complex_buffer_len.saturating_sub(self.log2_freqs.len()));
|
||||
|
||||
self.downwards_thresholds
|
||||
.reserve_exact(complex_buffer_len.saturating_sub(self.downwards_thresholds.len()));
|
||||
self.upwards_thresholds
|
||||
|
@ -365,12 +374,21 @@ impl CompressorBank {
|
|||
}
|
||||
}
|
||||
|
||||
/// Resize the number of compressors to match the current window size.
|
||||
/// Resize the number of compressors to match the current window size. Also precomputes the
|
||||
/// 2-log frequencies for each bin.
|
||||
///
|
||||
/// If the window size is larger than the maximum window size, then this will allocate.
|
||||
pub fn resize(&mut self, window_size: usize) {
|
||||
pub fn resize(&mut self, buffer_config: &BufferConfig, window_size: usize) {
|
||||
let complex_buffer_len = window_size / 2 + 1;
|
||||
|
||||
// These 2-log frequencies are needed when updating the compressor parameters, so we'll just
|
||||
// precompute them to avoid having to repeat the same expensive computations all the time
|
||||
self.log2_freqs.resize(complex_buffer_len, 0.0);
|
||||
for (i, log2_freq) in self.log2_freqs.iter_mut().enumerate() {
|
||||
let freq = (i as f32 / window_size as f32) * buffer_config.sample_rate;
|
||||
*log2_freq = freq.log2();
|
||||
}
|
||||
|
||||
self.downwards_thresholds.resize(complex_buffer_len, 1.0);
|
||||
self.upwards_thresholds.resize(complex_buffer_len, 1.0);
|
||||
self.downwards_ratios.resize(complex_buffer_len, 1.0);
|
||||
|
|
|
@ -48,6 +48,9 @@ struct SpectralCompressor {
|
|||
params: Arc<SpectralCompressorParams>,
|
||||
editor_state: Arc<ViziaState>,
|
||||
|
||||
/// The current buffer config, used for updating the compressors.
|
||||
buffer_config: BufferConfig,
|
||||
|
||||
/// An adapter that performs most of the overlap-add algorithm for us.
|
||||
stft: util::StftHelper,
|
||||
/// Contains a Hann window function of the current window length, passed to the overlap-add
|
||||
|
@ -122,6 +125,13 @@ impl Default for SpectralCompressor {
|
|||
params: Arc::new(SpectralCompressorParams::new(&compressor_bank)),
|
||||
editor_state: editor::default_state(),
|
||||
|
||||
buffer_config: BufferConfig {
|
||||
sample_rate: 1.0,
|
||||
min_buffer_size: None,
|
||||
max_buffer_size: 0,
|
||||
process_mode: ProcessMode::Realtime,
|
||||
},
|
||||
|
||||
// These three will be set to the correct values in the initialize function
|
||||
stft: util::StftHelper::new(Self::DEFAULT_NUM_OUTPUTS as usize, MAX_WINDOW_SIZE, 0),
|
||||
window_function: Vec::with_capacity(MAX_WINDOW_SIZE),
|
||||
|
@ -222,6 +232,9 @@ impl Plugin for SpectralCompressor {
|
|||
buffer_config: &BufferConfig,
|
||||
context: &mut impl InitContext,
|
||||
) -> bool {
|
||||
// Needed to update the compressors later
|
||||
self.buffer_config = *buffer_config;
|
||||
|
||||
// This plugin can accept any number of channels, so we need to resize channel-dependent
|
||||
// data structures accordinly
|
||||
if self.stft.num_channels() != bus_config.num_output_channels as usize {
|
||||
|
@ -284,7 +297,6 @@ impl Plugin for SpectralCompressor {
|
|||
let fft_plan = &mut self.plan_for_order.as_mut().unwrap()
|
||||
[self.params.window_size_order.value as usize - MIN_WINDOW_ORDER];
|
||||
let num_bins = self.complex_fft_buffer.len();
|
||||
let sample_rate = context.transport().sample_rate;
|
||||
|
||||
// The overlap gain compensation is based on a squared Hann window, which will sum perfectly
|
||||
// at four times overlap or higher. We'll apply a regular Hann window before the analysis
|
||||
|
@ -329,8 +341,9 @@ impl Plugin for SpectralCompressor {
|
|||
if self.params.dc_filter.value {
|
||||
// The Hann window function spreads the DC signal out slightly, so we'll clear
|
||||
// all 0-20 Hz bins for this.
|
||||
let highest_dcish_bin_idx =
|
||||
(20.0 / ((sample_rate / 2.0) / num_bins as f32)).floor() as usize;
|
||||
let highest_dcish_bin_idx = (20.0
|
||||
/ ((self.buffer_config.sample_rate / 2.0) / num_bins as f32))
|
||||
.floor() as usize;
|
||||
self.complex_fft_buffer[..highest_dcish_bin_idx + 1].fill(Complex32::default());
|
||||
}
|
||||
|
||||
|
@ -386,7 +399,8 @@ impl SpectralCompressor {
|
|||
.resize(window_size / 2 + 1, Complex32::default());
|
||||
|
||||
// This also causes the thresholds and ratios to be updated on the next STFT process cycle.
|
||||
self.compressor_bank.resize(window_size);
|
||||
self.compressor_bank
|
||||
.resize(&self.buffer_config, window_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue