Rename the VU meter to generic digital peak meter
Before I get a visit from the VU police.
This commit is contained in:
parent
bad5d0ace6
commit
a10e1e1152
|
@ -33,7 +33,7 @@ examples.
|
||||||
- **gain** is a simple smoothed gain plugin that shows off a couple other parts
|
- **gain** is a simple smoothed gain plugin that shows off a couple other parts
|
||||||
of the API, like support for storing arbitrary serializable state.
|
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
|
- **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
|
- **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
|
can also make use of MIDI input instead of generating a static signal based on
|
||||||
the plugin's parameters.
|
the plugin's parameters.
|
||||||
|
|
|
@ -32,14 +32,14 @@ struct Gain {
|
||||||
params: Pin<Arc<GainParams>>,
|
params: Pin<Arc<GainParams>>,
|
||||||
editor_size: Arc<AtomicCell<(u32, u32)>>,
|
editor_size: Arc<AtomicCell<(u32, u32)>>,
|
||||||
|
|
||||||
/// Needed to normalize the VU meter's response based on the sample rate.
|
/// Needed to normalize the peak meter's response based on the sample rate.
|
||||||
vu_meter_decay_weight: f32,
|
peak_meter_decay_weight: f32,
|
||||||
/// The current data for the VU meter (which technically isn't a VU meter). This is stored as an
|
/// The current data for the peak meter. This is stored as an [Arc] so we can share it between
|
||||||
/// [Arc] so we can share it between the GUI and the audio processing parts. If you have more
|
/// the GUI and the audio processing parts. If you have more state to share, then it's a good
|
||||||
/// state to share, then it's a good idea to put all of that in a struct behind a single `Arc`.
|
/// idea to put all of that in a struct behind a single `Arc`.
|
||||||
///
|
///
|
||||||
/// This is stored as voltage gain.
|
/// This is stored as voltage gain.
|
||||||
vu_meter: Arc<AtomicF32>,
|
peak_meter: Arc<AtomicF32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Params)]
|
#[derive(Params)]
|
||||||
|
@ -54,8 +54,8 @@ impl Default for Gain {
|
||||||
params: Arc::pin(GainParams::default()),
|
params: Arc::pin(GainParams::default()),
|
||||||
editor_size: Arc::new(AtomicCell::new((300, 100))),
|
editor_size: Arc::new(AtomicCell::new((300, 100))),
|
||||||
|
|
||||||
vu_meter_decay_weight: 1.0,
|
peak_meter_decay_weight: 1.0,
|
||||||
vu_meter: Arc::new(AtomicF32::new(util::MINUS_INFINITY_DB)),
|
peak_meter: Arc::new(AtomicF32::new(util::MINUS_INFINITY_DB)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ impl Plugin for Gain {
|
||||||
context: Arc<dyn GuiContext>,
|
context: Arc<dyn GuiContext>,
|
||||||
) -> Option<Box<dyn Editor>> {
|
) -> Option<Box<dyn Editor>> {
|
||||||
let params = self.params.clone();
|
let params = self.params.clone();
|
||||||
let vu_meter = self.vu_meter.clone();
|
let peak_meter = self.peak_meter.clone();
|
||||||
create_egui_editor(
|
create_egui_editor(
|
||||||
parent,
|
parent,
|
||||||
context,
|
context,
|
||||||
|
@ -135,19 +135,20 @@ impl Plugin for Gain {
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: Add a proper custom widget instead of reusing a progress bar
|
// TODO: Add a proper custom widget instead of reusing a progress bar
|
||||||
let vu_meter =
|
let peak_meter =
|
||||||
util::gain_to_db(vu_meter.load(std::sync::atomic::Ordering::Relaxed));
|
util::gain_to_db(peak_meter.load(std::sync::atomic::Ordering::Relaxed));
|
||||||
let vu_meter_text = if vu_meter > util::MINUS_INFINITY_DB {
|
let peak_meter_text = if peak_meter > util::MINUS_INFINITY_DB {
|
||||||
format!("{:.0} dBFS", vu_meter)
|
format!("{:.0} dBFS", peak_meter)
|
||||||
} else {
|
} else {
|
||||||
String::from("-inf dBFS")
|
String::from("-inf dBFS")
|
||||||
};
|
};
|
||||||
|
|
||||||
let vu_meter_normalized =
|
let peak_meter_normalized =
|
||||||
(vu_meter - util::MINUS_INFINITY_DB) / -util::MINUS_INFINITY_DB;
|
(peak_meter - util::MINUS_INFINITY_DB) / -util::MINUS_INFINITY_DB;
|
||||||
ui.allocate_space(egui::Vec2::splat(2.0));
|
ui.allocate_space(egui::Vec2::splat(2.0));
|
||||||
ui.add(
|
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,
|
_context: &mut impl ProcessContext,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// TODO: How do you tie this exponential decay to an actual time span?
|
// 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
|
true
|
||||||
}
|
}
|
||||||
|
@ -181,27 +182,26 @@ impl Plugin for Gain {
|
||||||
_context: &mut impl ProcessContext,
|
_context: &mut impl ProcessContext,
|
||||||
) -> ProcessStatus {
|
) -> ProcessStatus {
|
||||||
for samples in buffer.iter_mut() {
|
for samples in buffer.iter_mut() {
|
||||||
let gain = self.params.gain.smoothed.next();
|
|
||||||
|
|
||||||
let mut amplitude = 0.0;
|
let mut amplitude = 0.0;
|
||||||
let num_samples = samples.len();
|
let num_samples = samples.len();
|
||||||
|
|
||||||
|
let gain = self.params.gain.smoothed.next();
|
||||||
for sample in samples {
|
for sample in samples {
|
||||||
*sample *= util::db_to_gain(gain);
|
*sample *= util::db_to_gain(gain);
|
||||||
amplitude += *sample;
|
amplitude += *sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is technically not really a VU meter but just an arbitrary digital peak meter
|
|
||||||
amplitude /= num_samples as f32;
|
amplitude /= num_samples as f32;
|
||||||
let current_vu_meter = self.vu_meter.load(std::sync::atomic::Ordering::Relaxed);
|
let current_peak_meter = self.peak_meter.load(std::sync::atomic::Ordering::Relaxed);
|
||||||
let new_vu_meter = if amplitude > current_vu_meter {
|
let new_peak_meter = if amplitude > current_peak_meter {
|
||||||
amplitude
|
amplitude
|
||||||
} else {
|
} else {
|
||||||
current_vu_meter * self.vu_meter_decay_weight
|
current_peak_meter * self.peak_meter_decay_weight
|
||||||
+ amplitude * (1.0 - self.vu_meter_decay_weight)
|
+ amplitude * (1.0 - self.peak_meter_decay_weight)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.vu_meter
|
self.peak_meter
|
||||||
.store(new_vu_meter, std::sync::atomic::Ordering::Relaxed)
|
.store(new_peak_meter, std::sync::atomic::Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessStatus::Normal
|
ProcessStatus::Normal
|
||||||
|
|
Loading…
Reference in a new issue