diff --git a/examples/histogram/src/editor.rs b/examples/histogram/src/editor.rs index cad833c..fd01ea4 100644 --- a/examples/histogram/src/editor.rs +++ b/examples/histogram/src/editor.rs @@ -1,7 +1,7 @@ use cyma::prelude::*; use cyma::{ utils::HistogramBuffer, - visualizers::{Histogram, Grid, UnitRuler}, + visualizers::{Grid, Histogram, UnitRuler}, }; use nih_plug::editor::Editor; use nih_plug_vizia::{assets, create_vizia_editor, vizia::prelude::*, ViziaState, ViziaTheming}; diff --git a/examples/histogram/src/main.rs b/examples/histogram/src/main.rs index fa77cee..53f0b66 100644 --- a/examples/histogram/src/main.rs +++ b/examples/histogram/src/main.rs @@ -1,5 +1,5 @@ -use nih_plug::prelude::*; use histogram::HistogramPlugin; +use nih_plug::prelude::*; fn main() { nih_export_standalone::(); diff --git a/src/utils/buffers/histogram_buffer.rs b/src/utils/buffers/histogram_buffer.rs index f937825..3c1f99d 100644 --- a/src/utils/buffers/histogram_buffer.rs +++ b/src/utils/buffers/histogram_buffer.rs @@ -1,6 +1,6 @@ use std::fmt::Debug; +use super::VisualizerBuffer; use std::ops::{Index, IndexMut}; -use super::{VisualizerBuffer}; /// This buffer creates histogram data with variable decay from a signal. /// @@ -40,7 +40,7 @@ impl HistogramBuffer { sample_rate: 48000., decay, decay_weight, - edges: vec![f32::default(); size-1], + edges: vec![f32::default(); size - 1], } } @@ -82,14 +82,18 @@ impl HistogramBuffer { } fn decay_weight(decay: f32, sample_rate: f32) -> f32 { - 0.25f64.powf((decay as f64 * sample_rate as f64 ).recip()) as f32 + 0.25f64.powf((decay as f64 * sample_rate as f64).recip()) as f32 } fn update(self: &mut Self) { // calculate the linear edge values from MIN_EDGE to MAX_EDGE, evenly spaced in the db domain let nr_edges: usize = self.size - 1; self.edges = (0..nr_edges) - .map(|x| Self::db_to_linear(MIN_EDGE + x as f32 * ((MAX_EDGE - MIN_EDGE) / (nr_edges as f32 - 1.0)))) + .map(|x| { + Self::db_to_linear( + MIN_EDGE + x as f32 * ((MAX_EDGE - MIN_EDGE) / (nr_edges as f32 - 1.0)), + ) + }) .collect::>() .try_into() .unwrap(); @@ -128,11 +132,8 @@ impl HistogramBuffer { // Return the bin index left as usize } - } - - impl VisualizerBuffer for HistogramBuffer { /// Add an element into the HistogramBuffer. /// Once added, all values are scaled so the largest is 1 @@ -140,15 +141,15 @@ impl VisualizerBuffer for HistogramBuffer { let value = value.abs(); if value > 0.0 { let bin_index = self.find_bin(value); - self.data[bin_index] += (1.0-self.decay_weight); // Increment the count for the bin - for i in 0..self.size-1 { + self.data[bin_index] += (1.0 - self.decay_weight); // Increment the count for the bin + for i in 0..self.size - 1 { self.data[i] *= self.decay_weight; } } } -fn enqueue_buffer( - self: &mut Self, + fn enqueue_buffer( + self: &mut Self, buffer: &mut nih_plug::buffer::Buffer, channel: Option, ) { @@ -178,7 +179,6 @@ fn enqueue_buffer( self.update(); } - /// Clears the entire buffer, filling it with default values (usually 0) fn clear(self: &mut Self) { self.data.iter_mut().for_each(|x| *x = f32::default()); @@ -211,107 +211,107 @@ impl Index for HistogramBuffer { } &self.data[index] } - } - impl IndexMut for HistogramBuffer { - fn index_mut(&mut self, index: usize) -> &mut Self::Output { - if index >= self.size { - panic!( - "Invalid histogram buffer access: Index {} is out of range for histogram buffer of size {}", - index, self.size +} +impl IndexMut for HistogramBuffer { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + if index >= self.size { + panic!( + "Invalid histogram buffer access: Index {} is out of range for histogram buffer of size {}", + index, self.size ); - } - &mut self.data[index] } + &mut self.data[index] } +} - #[cfg(test)] - mod tests { - use super::HistogramBuffer; +#[cfg(test)] +mod tests { + use super::HistogramBuffer; - #[test] - fn basics() { - let mut rb = HistogramBuffer::::new(4); + #[test] + fn basics() { + let mut rb = HistogramBuffer::::new(4); - // Is the buffer filled with zeroes? - assert_eq!(rb.data, vec![0; 4]); + // Is the buffer filled with zeroes? + assert_eq!(rb.data, vec![0; 4]); - rb.enqueue(1); - rb.enqueue(2); - rb.enqueue(3); + rb.enqueue(1); + rb.enqueue(2); + rb.enqueue(3); - // Is the value at the tail (before the head) equal to 3? - assert_eq!(rb.data[(rb.head + rb.size - 1) % rb.size], 3); + // Is the value at the tail (before the head) equal to 3? + assert_eq!(rb.data[(rb.head + rb.size - 1) % rb.size], 3); - // Is the value at the head equal to 0? - assert_eq!(rb.data[rb.head], 0); + // Is the value at the head equal to 0? + assert_eq!(rb.data[rb.head], 0); - rb.enqueue(4); - rb.enqueue(5); - rb.enqueue(6); + rb.enqueue(4); + rb.enqueue(5); + rb.enqueue(6); - // Have the earlier values been overwritten? - assert!(!rb.data.contains(&1)); - assert!(!rb.data.contains(&2)); + // Have the earlier values been overwritten? + assert!(!rb.data.contains(&1)); + assert!(!rb.data.contains(&2)); - // Do the last 4 values exist? - assert!(rb.data.contains(&3)); - assert!(rb.data.contains(&4)); - assert!(rb.data.contains(&5)); - assert!(rb.data.contains(&6)); - } + // Do the last 4 values exist? + assert!(rb.data.contains(&3)); + assert!(rb.data.contains(&4)); + assert!(rb.data.contains(&5)); + assert!(rb.data.contains(&6)); + } - #[test] - fn clear() { - let mut rb = HistogramBuffer::::new(4); + #[test] + fn clear() { + let mut rb = HistogramBuffer::::new(4); - rb.enqueue(1); - rb.enqueue(2); - rb.enqueue(3); + rb.enqueue(1); + rb.enqueue(2); + rb.enqueue(3); - assert_ne!(rb.data, vec![0; 4]); + assert_ne!(rb.data, vec![0; 4]); - rb.clear(); + rb.clear(); - assert_eq!(rb.data, vec![0; 4]); - } + assert_eq!(rb.data, vec![0; 4]); + } - #[test] - fn resize() { - let mut rb = HistogramBuffer::::new(4); - rb.enqueue(1); - rb.enqueue(2); - rb.enqueue(3); - rb.enqueue(4); - rb.enqueue(5); - rb.enqueue(6); - - // Growing HistogramBuffers - { - let mut rb_grown = rb.clone(); - rb_grown.grow(6); - let mut rb_resized = rb.clone(); - rb_resized.resize(6); - // Is the last inserted datum the same? - assert_eq!( - rb_grown.data[(rb_grown.head + rb_grown.size - 1) % rb_grown.size], - rb_resized.data[(rb_resized.head + rb_resized.size - 1) % rb_resized.size] - ); - // Is the buffer zero-padded? - assert_eq!(rb_grown.data[rb_grown.head], 0); - } + #[test] + fn resize() { + let mut rb = HistogramBuffer::::new(4); + rb.enqueue(1); + rb.enqueue(2); + rb.enqueue(3); + rb.enqueue(4); + rb.enqueue(5); + rb.enqueue(6); + + // Growing HistogramBuffers + { + let mut rb_grown = rb.clone(); + rb_grown.grow(6); + let mut rb_resized = rb.clone(); + rb_resized.resize(6); + // Is the last inserted datum the same? + assert_eq!( + rb_grown.data[(rb_grown.head + rb_grown.size - 1) % rb_grown.size], + rb_resized.data[(rb_resized.head + rb_resized.size - 1) % rb_resized.size] + ); + // Is the buffer zero-padded? + assert_eq!(rb_grown.data[rb_grown.head], 0); + } - // Shrinking HistogramBuffers - { - let mut rb_shrunk = rb.clone(); - rb_shrunk.shrink(3); - let mut rb_resized = rb.clone(); - rb_resized.resize(3); - // Is the last inserted datum the same? - assert_eq!( - rb_shrunk.data[(rb_shrunk.head + rb_shrunk.size - 1) % rb_shrunk.size], - rb_resized.data[(rb_resized.head + rb_resized.size - 1) % rb_resized.size] - ); - } + // Shrinking HistogramBuffers + { + let mut rb_shrunk = rb.clone(); + rb_shrunk.shrink(3); + let mut rb_resized = rb.clone(); + rb_resized.resize(3); + // Is the last inserted datum the same? + assert_eq!( + rb_shrunk.data[(rb_shrunk.head + rb_shrunk.size - 1) % rb_shrunk.size], + rb_resized.data[(rb_resized.head + rb_resized.size - 1) % rb_resized.size] + ); + } } #[test] diff --git a/src/visualizers/histogram.rs b/src/visualizers/histogram.rs index 70a4bd0..8e481ab 100644 --- a/src/visualizers/histogram.rs +++ b/src/visualizers/histogram.rs @@ -1,5 +1,5 @@ use super::{FillFrom, FillModifiers, RangeModifiers}; -use crate::utils::{HistogramBuffer, VisualizerBuffer, ValueScaling}; +use crate::utils::{HistogramBuffer, ValueScaling, VisualizerBuffer}; use nih_plug_vizia::vizia::{prelude::*, vg}; use std::sync::{Arc, Mutex}; @@ -36,11 +36,7 @@ impl Histogram where L: Lens>>, { - pub fn new( - cx: &mut Context, - buffer: L, - range: impl Res<(f32, f32)> + Clone, - ) -> Handle { + pub fn new(cx: &mut Context, buffer: L, range: impl Res<(f32, f32)> + Clone) -> Handle { Self { buffer, range: range.get_val(cx), @@ -86,18 +82,20 @@ where } // start of the graph - stroke.move_to(x + bins[nr_bins-1] * w, y); + stroke.move_to(x + bins[nr_bins - 1] * w, y); // the actual histogram - for i in 1..nr_bins { - stroke.line_to( - x + ( - // scale so the largest value becomes 1. - (bins[nr_bins-i] / largest) - * w) - , y + h * i as f32 / (nr_bins - 1) as f32); + if largest > 0.0 { + for i in 1..nr_bins { + stroke.line_to( + x + ( + // scale so the largest value becomes 1. + (bins[nr_bins - i] / largest) * w + ), + y + h * i as f32 / (nr_bins - 1) as f32, + ); + } } - // fill in with background color let mut fill = stroke.clone(); fill.line_to(x, y + h); @@ -112,14 +110,17 @@ where } } - impl<'a, L> FillModifiers for Handle<'a, Histogram> where L: Lens>>, { // stubs - fn fill_from_max(self) -> Self { self } - fn fill_from_value(self, level: f32) -> Self { self } + fn fill_from_max(self) -> Self { + self + } + fn fill_from_value(self, level: f32) -> Self { + self + } } impl<'a, L> RangeModifiers for Handle<'a, Histogram>