diff --git a/crates/device/src/meter.rs b/crates/device/src/meter.rs index e791aefc..0c2e749a 100644 --- a/crates/device/src/meter.rs +++ b/crates/device/src/meter.rs @@ -8,14 +8,14 @@ pub enum MeteringMode { } #[derive(Debug, Default, Clone)] -pub struct Meter(pub f32); +pub struct Log10Meter(pub f32); -render!(TuiOut: |self: Meter, to| { +render!(TuiOut: |self: Log10Meter, to| { let [x, y, w, h] = to.area(); let signal = 100.0 - f32::max(0.0, f32::min(100.0, self.0.abs())); let v = (signal * h as f32 / 100.0).ceil() as u16; let y2 = y + h; - //to.blit(&format!("\r{v} {} {signal}", self.0), x * 30, y, Some(Style::default())); + //to.blit(&format!("\r{v} {} {signal}", self.0), x * 20, y, None); for y in y..(y + v) { for x in x..(x + w) { to.blit(&"▌", x, y2 - y, Some(Style::default().green())); @@ -23,16 +23,32 @@ render!(TuiOut: |self: Meter, to| { } }); -pub fn to_rms (samples: &[f32]) -> f32 { - let sum = samples.iter() - .map(|s|*s) - .reduce(|sum, sample|sum + sample) - .unwrap_or(0.0); - (sum / samples.len() as f32).sqrt() -} - pub fn to_log10 (samples: &[f32]) -> f32 { let total: f32 = samples.iter().map(|x|x.abs()).sum(); let count = samples.len() as f32; 10. * (total / count).log10() } + +#[derive(Debug, Default, Clone)] +pub struct RmsMeter(pub f32); + +render!(TuiOut: |self: RmsMeter, to| { + let [x, y, w, h] = to.area(); + let signal = f32::max(0.0, f32::min(100.0, self.0.abs())); + let v = (signal * h as f32).ceil() as u16; + let y2 = y + h; + //to.blit(&format!("\r{v} {} {signal}", self.0), x * 30, y, Some(Style::default())); + for y in y..(y + v) { + for x in x..(x + w) { + to.blit(&"▌", x, y2.saturating_sub(y), Some(Style::default().green())); + } + } +}); + +pub fn to_rms (samples: &[f32]) -> f32 { + let sum = samples.iter() + .map(|s|*s) + .reduce(|sum, sample|sum + sample.abs()) + .unwrap_or(0.0); + (sum / samples.len() as f32).sqrt() +} diff --git a/crates/device/src/sampler/sampler_api.rs b/crates/device/src/sampler/sampler_api.rs index fd120976..f490350e 100644 --- a/crates/device/src/sampler/sampler_api.rs +++ b/crates/device/src/sampler/sampler_api.rs @@ -57,14 +57,11 @@ impl SamplerCommand { Self::record_begin(sampler, sample) } } - fn record_begin (sampler: &mut Sampler, sample: usize) -> Perhaps { + fn record_begin (sampler: &mut Sampler, pitch: usize) -> Perhaps { sampler.recording = Some(( - sample, + pitch, Arc::new(RwLock::new(Sample::new( - "Sample", - 0, - 0, - vec![vec![];sampler.audio_ins.len()] + "Sample", 0, 0, vec![vec![];sampler.audio_ins.len()] ))) )); Ok(None) diff --git a/crates/device/src/sampler/sampler_audio.rs b/crates/device/src/sampler/sampler_audio.rs index 64c7ba82..87d0a78e 100644 --- a/crates/device/src/sampler/sampler_audio.rs +++ b/crates/device/src/sampler/sampler_audio.rs @@ -41,7 +41,7 @@ impl Sampler { for ((input, meter), channel) in samples_with_meters { let slice = input.port().as_slice(scope); length = length.max(slice.len()); - *meter = to_log10(slice); + *meter = to_rms(slice); channel.extend_from_slice(slice); } sample.end += length; @@ -51,7 +51,7 @@ impl Sampler { fn update_input_meters (&mut self, scope: &ProcessScope) { for (input, meter) in self.audio_ins.iter().zip(self.input_meters.iter_mut()) { let slice = input.port().as_slice(scope); - *meter = to_log10(slice); + *meter = to_rms(slice); } } diff --git a/crates/device/src/sampler/sampler_model.rs b/crates/device/src/sampler/sampler_model.rs index d51d106a..ad429a9d 100644 --- a/crates/device/src/sampler/sampler_model.rs +++ b/crates/device/src/sampler/sampler_model.rs @@ -52,8 +52,8 @@ impl Default for Sampler { Self { midi_in: None, audio_ins: vec![], - input_meters: vec![f32::MIN;2], - output_meters: vec![f32::MIN;2], + input_meters: vec![0.0;2], + output_meters: vec![0.0;2], audio_outs: vec![], name: "tek_sampler".to_string(), mapped: [const { None };128], diff --git a/crates/device/src/sampler/sampler_view.rs b/crates/device/src/sampler/sampler_view.rs index c73b4908..63647804 100644 --- a/crates/device/src/sampler/sampler_view.rs +++ b/crates/device/src/sampler/sampler_view.rs @@ -90,13 +90,14 @@ impl Sampler { } pub fn view_sample (&self, note_pt: usize) -> impl Content + use<'_> { - Outer(true, Style::default().fg(Tui::g(96))).enclose(draw_viewer(if let Some((_, sample)) = &self.recording { - Some(sample) - } else if let Some(sample) = &self.mapped[note_pt] { - Some(sample) - } else { - None - })) + Outer(true, Style::default().fg(Tui::g(96))) + .enclose(Fill::xy(draw_viewer(if let Some((_, sample)) = &self.recording { + Some(sample) + } else if let Some(sample) = &self.mapped[note_pt] { + Some(sample) + } else { + None + }))) } pub fn status (&self, index: usize) -> impl Content { @@ -105,13 +106,13 @@ impl Sampler { pub fn view_meters_input (&self) -> impl Content + use<'_> { Tui::bg(Black, Fixed::x(2, Map::east(1, ||self.input_meters.iter(), |value, _index|{ - Fill::y(Meter(*value)) + Fill::y(RmsMeter(*value)) }))) } pub fn view_meters_output (&self) -> impl Content + use<'_> { Tui::bg(Black, Fixed::x(2, Map::east(1, ||self.output_meters.iter(), |value, _index|{ - Fill::y(Meter(*value)) + Fill::y(RmsMeter(*value)) }))) } } @@ -132,7 +133,7 @@ fn draw_list_item (sample: &Option>>) -> String { } fn draw_viewer (sample: Option<&Arc>>) -> impl Content + use<'_> { - let min_db = -40.0; + let min_db = -64.0; ThunkRender::new(move|to: &mut TuiOut|{ let [x, y, width, height] = to.area(); let area = Rect { x, y, width, height };