diff --git a/README.md b/README.md index 642fa41f..6239b0d8 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ examples. - **gain** is a simple smoothed gain plugin that shows off a couple other parts of the API, like support for storing arbitrary serializable state. - **gain-gui** is the same plugin as gain, but with a GUI to control the - parameter and a VU meter. + parameter and a digital peak meter. - **sine** is a simple test tone generator plugin with frequency smoothing that can also make use of MIDI input instead of generating a static signal based on the plugin's parameters. diff --git a/plugins/examples/gain-gui/src/lib.rs b/plugins/examples/gain-gui/src/lib.rs index 2f3c2225..5caac48c 100644 --- a/plugins/examples/gain-gui/src/lib.rs +++ b/plugins/examples/gain-gui/src/lib.rs @@ -32,14 +32,14 @@ struct Gain { params: Pin>, editor_size: Arc>, - /// Needed to normalize the VU meter's response based on the sample rate. - vu_meter_decay_weight: f32, - /// The current data for the VU meter (which technically isn't a VU meter). This is stored as an - /// [Arc] so we can share it between the GUI and the audio processing parts. If you have more - /// state to share, then it's a good idea to put all of that in a struct behind a single `Arc`. + /// Needed to normalize the peak meter's response based on the sample rate. + peak_meter_decay_weight: f32, + /// The current data for the peak meter. This is stored as an [Arc] so we can share it between + /// the GUI and the audio processing parts. If you have more state to share, then it's a good + /// idea to put all of that in a struct behind a single `Arc`. /// /// This is stored as voltage gain. - vu_meter: Arc, + peak_meter: Arc, } #[derive(Params)] @@ -54,8 +54,8 @@ impl Default for Gain { params: Arc::pin(GainParams::default()), editor_size: Arc::new(AtomicCell::new((300, 100))), - vu_meter_decay_weight: 1.0, - vu_meter: Arc::new(AtomicF32::new(util::MINUS_INFINITY_DB)), + peak_meter_decay_weight: 1.0, + peak_meter: Arc::new(AtomicF32::new(util::MINUS_INFINITY_DB)), } } } @@ -103,7 +103,7 @@ impl Plugin for Gain { context: Arc, ) -> Option> { let params = self.params.clone(); - let vu_meter = self.vu_meter.clone(); + let peak_meter = self.peak_meter.clone(); create_egui_editor( parent, context, @@ -135,19 +135,20 @@ impl Plugin for Gain { ); // TODO: Add a proper custom widget instead of reusing a progress bar - let vu_meter = - util::gain_to_db(vu_meter.load(std::sync::atomic::Ordering::Relaxed)); - let vu_meter_text = if vu_meter > util::MINUS_INFINITY_DB { - format!("{:.0} dBFS", vu_meter) + let peak_meter = + util::gain_to_db(peak_meter.load(std::sync::atomic::Ordering::Relaxed)); + let peak_meter_text = if peak_meter > util::MINUS_INFINITY_DB { + format!("{:.0} dBFS", peak_meter) } else { String::from("-inf dBFS") }; - let vu_meter_normalized = - (vu_meter - util::MINUS_INFINITY_DB) / -util::MINUS_INFINITY_DB; + let peak_meter_normalized = + (peak_meter - util::MINUS_INFINITY_DB) / -util::MINUS_INFINITY_DB; ui.allocate_space(egui::Vec2::splat(2.0)); ui.add( - egui::widgets::ProgressBar::new(vu_meter_normalized).text(vu_meter_text), + egui::widgets::ProgressBar::new(peak_meter_normalized) + .text(peak_meter_text), ); }); }, @@ -170,7 +171,7 @@ impl Plugin for Gain { _context: &mut impl ProcessContext, ) -> bool { // TODO: How do you tie this exponential decay to an actual time span? - self.vu_meter_decay_weight = 0.999f32.powf(44_100.0 / buffer_config.sample_rate); + self.peak_meter_decay_weight = 0.999f32.powf(44_100.0 / buffer_config.sample_rate); true } @@ -181,27 +182,26 @@ impl Plugin for Gain { _context: &mut impl ProcessContext, ) -> ProcessStatus { for samples in buffer.iter_mut() { - let gain = self.params.gain.smoothed.next(); - let mut amplitude = 0.0; let num_samples = samples.len(); + + let gain = self.params.gain.smoothed.next(); for sample in samples { *sample *= util::db_to_gain(gain); amplitude += *sample; } - // This is technically not really a VU meter but just an arbitrary digital peak meter amplitude /= num_samples as f32; - let current_vu_meter = self.vu_meter.load(std::sync::atomic::Ordering::Relaxed); - let new_vu_meter = if amplitude > current_vu_meter { + let current_peak_meter = self.peak_meter.load(std::sync::atomic::Ordering::Relaxed); + let new_peak_meter = if amplitude > current_peak_meter { amplitude } else { - current_vu_meter * self.vu_meter_decay_weight - + amplitude * (1.0 - self.vu_meter_decay_weight) + current_peak_meter * self.peak_meter_decay_weight + + amplitude * (1.0 - self.peak_meter_decay_weight) }; - self.vu_meter - .store(new_vu_meter, std::sync::atomic::Ordering::Relaxed) + self.peak_meter + .store(new_peak_meter, std::sync::atomic::Ordering::Relaxed) } ProcessStatus::Normal