diff --git a/Cargo.lock b/Cargo.lock index 5f50ab8d..e828726a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3756,6 +3756,7 @@ dependencies = [ name = "spectral_compressor" version = "0.3.0" dependencies = [ + "atomic_float", "crossbeam", "nih_plug", "nih_plug_vizia", diff --git a/plugins/spectral_compressor/Cargo.toml b/plugins/spectral_compressor/Cargo.toml index 13d57060..07b375e0 100644 --- a/plugins/spectral_compressor/Cargo.toml +++ b/plugins/spectral_compressor/Cargo.toml @@ -16,6 +16,7 @@ nih_plug_vizia = { path = "../../nih_plug_vizia" } realfft = "3.0" # For the GUI +atomic_float = "0.1" crossbeam = "0.8" open = "3.0" serde = { version = "1.0", features = ["derive"] } diff --git a/plugins/spectral_compressor/src/editor.rs b/plugins/spectral_compressor/src/editor.rs index 9ebe7e27..9f7a7457 100644 --- a/plugins/spectral_compressor/src/editor.rs +++ b/plugins/spectral_compressor/src/editor.rs @@ -14,15 +14,17 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use atomic_float::AtomicF32; use crossbeam::atomic::AtomicCell; use nih_plug::prelude::*; use nih_plug_vizia::vizia::prelude::*; use nih_plug_vizia::widgets::*; use nih_plug_vizia::{assets, create_vizia_editor, ViziaState, ViziaTheming}; use serde::{Deserialize, Serialize}; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use self::mode_button::EditorModeButton; +use crate::analyzer::AnalyzerData; use crate::{SpectralCompressor, SpectralCompressorParams}; mod mode_button; @@ -52,11 +54,16 @@ pub enum EditorMode { AnalyzerVisible, } -#[derive(Lens)] -struct Data { - params: Arc, +#[derive(Clone, Lens)] +pub struct Data { + pub(crate) params: Arc, - editor_mode: Arc>, + /// Determines which parts of the GUI are visible, and in turn decides the GUI's size. + pub(crate) editor_mode: Arc>, + + pub(crate) analyzer_data: Arc>>, + /// Used by the analyzer to determine which FFT bins belong to which frequencies. + pub(crate) sample_rate: Arc, } impl Model for Data {} @@ -69,20 +76,12 @@ pub(crate) fn default_state(editor_mode: Arc>) -> Arc, - editor_state: Arc, -) -> Option> { +pub(crate) fn create(editor_state: Arc, editor_data: Data) -> Option> { create_vizia_editor(editor_state, ViziaTheming::Custom, move |cx, _| { assets::register_noto_sans_light(cx); assets::register_noto_sans_thin(cx); - Data { - params: params.clone(), - - editor_mode: params.editor_mode.clone(), - } - .build(cx); + editor_data.clone().build(cx); ResizeHandle::new(cx); diff --git a/plugins/spectral_compressor/src/lib.rs b/plugins/spectral_compressor/src/lib.rs index e9cf7b86..df4690f8 100644 --- a/plugins/spectral_compressor/src/lib.rs +++ b/plugins/spectral_compressor/src/lib.rs @@ -15,12 +15,14 @@ // along with this program. If not, see . use analyzer::AnalyzerData; +use atomic_float::AtomicF32; 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::atomic::Ordering; use std::sync::{Arc, Mutex}; use triple_buffer::TripleBuffer; @@ -54,6 +56,9 @@ pub struct SpectralCompressor { /// The current buffer config, used for updating the compressors. buffer_config: BufferConfig, + /// The current sample rate. Stores the same information as in `BufferConfig`, but this can be + /// shared with the editor where it's used to compute frequencies for the spectrum analyzer. + sample_rate: Arc, /// An adapter that performs most of the overlap-add algorithm for us. stft: util::StftHelper<1>, @@ -166,6 +171,7 @@ impl Default for SpectralCompressor { max_buffer_size: 0, process_mode: ProcessMode::Realtime, }, + sample_rate: Arc::new(AtomicF32::new(1.0)), // These three will be set to the correct values in the initialize function stft: util::StftHelper::new(2, MAX_WINDOW_SIZE, 0), @@ -311,7 +317,17 @@ impl Plugin for SpectralCompressor { } fn editor(&self, _async_executor: AsyncExecutor) -> Option> { - editor::create(self.params.clone(), self.params.editor_state.clone()) + editor::create( + self.params.editor_state.clone(), + editor::Data { + params: self.params.clone(), + + editor_mode: self.params.editor_mode.clone(), + + analyzer_data: self.analyzer_output_data.clone(), + sample_rate: self.sample_rate.clone(), + }, + ) } fn initialize( @@ -323,6 +339,10 @@ impl Plugin for SpectralCompressor { // Needed to update the compressors later self.buffer_config = *buffer_config; + // And this is used in the editor to draw the analyzer + self.sample_rate + .store(buffer_config.sample_rate, Ordering::Relaxed); + // This plugin can accept a variable number of audio channels, so we need to resize // channel-dependent data structures accordingly let num_output_channels = audio_io_layout