Add triple buffers to share analyzer data in SC
This commit is contained in:
parent
510bc3f131
commit
9647f8f3dd
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -3762,6 +3762,7 @@ dependencies = [
|
|||
"open",
|
||||
"realfft",
|
||||
"serde",
|
||||
"triple_buffer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -30,8 +30,8 @@ const SPECTRUM_WINDOW_OVERLAP: usize = 2;
|
|||
/// peak meter.
|
||||
const SMOOTHING_DECAY_MS: f32 = 100.0;
|
||||
|
||||
/// The amplitudes of all frequency bins in a windowed FFT of the input. Also includes the DC offset
|
||||
/// bin which we don't draw, just to make this a bit less confusing.
|
||||
/// The amplitudes of all frequency bins in a windowed FFT of Diopser's output. Also includes the DC
|
||||
/// offset bin which we don't draw, just to make this a bit less confusing.
|
||||
pub type Spectrum = [f32; SPECTRUM_WINDOW_SIZE / 2 + 1];
|
||||
/// A receiver for a spectrum computed by [`SpectrumInput`].
|
||||
pub type SpectrumOutput = triple_buffer::Output<Spectrum>;
|
||||
|
|
|
@ -19,3 +19,4 @@ realfft = "3.0"
|
|||
crossbeam = "0.8"
|
||||
open = "3.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
triple_buffer = "6.2"
|
||||
|
|
|
@ -7,9 +7,13 @@
|
|||
/// This pulls the data directly from the spectral compression part of Spectral Compressor, so the
|
||||
/// window size and overlap amounts are equal to the ones used by SC's main algorithm. If the
|
||||
/// current window size is 2048, then only the first `2048 / 2 + 1` elements in the arrays are used.
|
||||
#[derive(Debug)]
|
||||
pub struct AnalyzerData {
|
||||
/// The amplitudes of all frequency bins in a windowed FFT of Spectral Compressor's output. Also
|
||||
/// includes the DC offset bin which we don't draw, just to make this a bit less confusing.
|
||||
///
|
||||
/// This data is taken directly from the envelope followers, so it has the same rise and fall
|
||||
/// time as what is used by the compressors.
|
||||
pub spectrum: [f32; crate::MAX_WINDOW_SIZE / 2 + 1],
|
||||
/// The gain reduction applied to each band, in decibels. Positive values mean that a band
|
||||
/// becomes louder, and negative values mean a band got attenuated. Does not (and should not)
|
||||
|
@ -19,3 +23,12 @@ pub struct AnalyzerData {
|
|||
// threshold curve or to also show the individual upwards/downwards thresholds. Or omit
|
||||
// this and implement it in a nicer way for the premium Spectral Compressor.
|
||||
}
|
||||
|
||||
impl Default for AnalyzerData {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
spectrum: [0.0; crate::MAX_WINDOW_SIZE / 2 + 1],
|
||||
gain_reduction_db: [0.0; crate::MAX_WINDOW_SIZE / 2 + 1],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ use realfft::num_complex::Complex32;
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::analyzer::AnalyzerData;
|
||||
use crate::SpectralCompressorParams;
|
||||
|
||||
// These are the parameter name prefixes used for the downwards and upwards compression parameters.
|
||||
|
@ -97,6 +98,11 @@ pub struct CompressorBank {
|
|||
/// The sample rate this compressor bank was configured for. This is used to compute the
|
||||
/// coefficients for the envelope followers in the process function.
|
||||
sample_rate: f32,
|
||||
|
||||
/// The input data for the spectrum analyzer. Stores both the spectrum analyzer values and the
|
||||
/// current gain reduction. Used to draw the spectrum analyzer and gain reduction display in the
|
||||
/// editor.
|
||||
analyzer_input_data: triple_buffer::Input<AnalyzerData>,
|
||||
}
|
||||
|
||||
#[derive(Params)]
|
||||
|
@ -393,7 +399,11 @@ impl CompressorParams {
|
|||
impl CompressorBank {
|
||||
/// Set up the compressor for the given channel count and maximum FFT window size. The
|
||||
/// compressors won't be initialized yet.
|
||||
pub fn new(num_channels: usize, max_window_size: usize) -> Self {
|
||||
pub fn new(
|
||||
analyzer_input_data: triple_buffer::Input<AnalyzerData>,
|
||||
num_channels: usize,
|
||||
max_window_size: usize,
|
||||
) -> Self {
|
||||
let complex_buffer_len = max_window_size / 2 + 1;
|
||||
|
||||
CompressorBank {
|
||||
|
@ -423,6 +433,8 @@ impl CompressorBank {
|
|||
],
|
||||
window_size: 0,
|
||||
sample_rate: 1.0,
|
||||
|
||||
analyzer_input_data,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,13 +14,15 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use analyzer::AnalyzerData;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use editor::EditorMode;
|
||||
use nih_plug::prelude::*;
|
||||
use nih_plug_vizia::ViziaState;
|
||||
use realfft::num_complex::Complex32;
|
||||
use realfft::{ComplexToReal, RealFftPlanner, RealToComplex};
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use triple_buffer::TripleBuffer;
|
||||
|
||||
mod analyzer;
|
||||
mod compressor_bank;
|
||||
|
@ -69,6 +71,10 @@ pub struct SpectralCompressor {
|
|||
plan_for_order: Option<[Plan; MAX_WINDOW_ORDER - MIN_WINDOW_ORDER + 1]>,
|
||||
/// The output of our real->complex FFT.
|
||||
complex_fft_buffer: Vec<Complex32>,
|
||||
|
||||
/// The output for the analyzer data computed in `CompressorBank` while the editor is open. This
|
||||
/// can be cloned and moved into the editor.
|
||||
analyzer_output_data: Arc<Mutex<triple_buffer::Output<AnalyzerData>>>,
|
||||
}
|
||||
|
||||
/// An FFT plan for a specific window size, all of which will be precomputed during initilaization.
|
||||
|
@ -141,9 +147,15 @@ pub struct GlobalParams {
|
|||
|
||||
impl Default for SpectralCompressor {
|
||||
fn default() -> Self {
|
||||
// The spectrum analyzer and gain reduction data is computed directly in the spectral
|
||||
// compression routine in `compressor_bank`. `analyzer_output_data` can then be used in the
|
||||
// editor to draw the data.
|
||||
let (analyzer_input_data, analyzer_output_data) = TripleBuffer::default().split();
|
||||
|
||||
// Changing any of the compressor threshold or ratio parameters will set an atomic flag in
|
||||
// this object that causes the compressor thresholds and ratios to be recalcualted
|
||||
let compressor_bank = compressor_bank::CompressorBank::new(2, MAX_WINDOW_SIZE);
|
||||
let compressor_bank =
|
||||
compressor_bank::CompressorBank::new(analyzer_input_data, 2, MAX_WINDOW_SIZE);
|
||||
|
||||
SpectralCompressor {
|
||||
params: Arc::new(SpectralCompressorParams::new(&compressor_bank)),
|
||||
|
@ -165,6 +177,8 @@ impl Default for SpectralCompressor {
|
|||
// the plugin is initialized
|
||||
plan_for_order: None,
|
||||
complex_fft_buffer: Vec::with_capacity(MAX_WINDOW_SIZE / 2 + 1),
|
||||
|
||||
analyzer_output_data: Arc::new(Mutex::new(analyzer_output_data)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue