mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
sampler, meter: switch to rms; reenable viewer
This commit is contained in:
parent
6db5df5210
commit
b9c101081b
5 changed files with 45 additions and 31 deletions
|
|
@ -8,14 +8,14 @@ pub enum MeteringMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
#[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 [x, y, w, h] = to.area();
|
||||||
let signal = 100.0 - f32::max(0.0, f32::min(100.0, self.0.abs()));
|
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 v = (signal * h as f32 / 100.0).ceil() as u16;
|
||||||
let y2 = y + h;
|
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 y in y..(y + v) {
|
||||||
for x in x..(x + w) {
|
for x in x..(x + w) {
|
||||||
to.blit(&"▌", x, y2 - y, Some(Style::default().green()));
|
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 {
|
pub fn to_log10 (samples: &[f32]) -> f32 {
|
||||||
let total: f32 = samples.iter().map(|x|x.abs()).sum();
|
let total: f32 = samples.iter().map(|x|x.abs()).sum();
|
||||||
let count = samples.len() as f32;
|
let count = samples.len() as f32;
|
||||||
10. * (total / count).log10()
|
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()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,14 +57,11 @@ impl SamplerCommand {
|
||||||
Self::record_begin(sampler, sample)
|
Self::record_begin(sampler, sample)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn record_begin (sampler: &mut Sampler, sample: usize) -> Perhaps<Self> {
|
fn record_begin (sampler: &mut Sampler, pitch: usize) -> Perhaps<Self> {
|
||||||
sampler.recording = Some((
|
sampler.recording = Some((
|
||||||
sample,
|
pitch,
|
||||||
Arc::new(RwLock::new(Sample::new(
|
Arc::new(RwLock::new(Sample::new(
|
||||||
"Sample",
|
"Sample", 0, 0, vec![vec![];sampler.audio_ins.len()]
|
||||||
0,
|
|
||||||
0,
|
|
||||||
vec![vec![];sampler.audio_ins.len()]
|
|
||||||
)))
|
)))
|
||||||
));
|
));
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ impl Sampler {
|
||||||
for ((input, meter), channel) in samples_with_meters {
|
for ((input, meter), channel) in samples_with_meters {
|
||||||
let slice = input.port().as_slice(scope);
|
let slice = input.port().as_slice(scope);
|
||||||
length = length.max(slice.len());
|
length = length.max(slice.len());
|
||||||
*meter = to_log10(slice);
|
*meter = to_rms(slice);
|
||||||
channel.extend_from_slice(slice);
|
channel.extend_from_slice(slice);
|
||||||
}
|
}
|
||||||
sample.end += length;
|
sample.end += length;
|
||||||
|
|
@ -51,7 +51,7 @@ impl Sampler {
|
||||||
fn update_input_meters (&mut self, scope: &ProcessScope) {
|
fn update_input_meters (&mut self, scope: &ProcessScope) {
|
||||||
for (input, meter) in self.audio_ins.iter().zip(self.input_meters.iter_mut()) {
|
for (input, meter) in self.audio_ins.iter().zip(self.input_meters.iter_mut()) {
|
||||||
let slice = input.port().as_slice(scope);
|
let slice = input.port().as_slice(scope);
|
||||||
*meter = to_log10(slice);
|
*meter = to_rms(slice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,8 @@ impl Default for Sampler {
|
||||||
Self {
|
Self {
|
||||||
midi_in: None,
|
midi_in: None,
|
||||||
audio_ins: vec![],
|
audio_ins: vec![],
|
||||||
input_meters: vec![f32::MIN;2],
|
input_meters: vec![0.0;2],
|
||||||
output_meters: vec![f32::MIN;2],
|
output_meters: vec![0.0;2],
|
||||||
audio_outs: vec![],
|
audio_outs: vec![],
|
||||||
name: "tek_sampler".to_string(),
|
name: "tek_sampler".to_string(),
|
||||||
mapped: [const { None };128],
|
mapped: [const { None };128],
|
||||||
|
|
|
||||||
|
|
@ -90,13 +90,14 @@ impl Sampler {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_sample (&self, note_pt: usize) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_sample (&self, note_pt: usize) -> impl Content<TuiOut> + use<'_> {
|
||||||
Outer(true, Style::default().fg(Tui::g(96))).enclose(draw_viewer(if let Some((_, sample)) = &self.recording {
|
Outer(true, Style::default().fg(Tui::g(96)))
|
||||||
Some(sample)
|
.enclose(Fill::xy(draw_viewer(if let Some((_, sample)) = &self.recording {
|
||||||
} else if let Some(sample) = &self.mapped[note_pt] {
|
Some(sample)
|
||||||
Some(sample)
|
} else if let Some(sample) = &self.mapped[note_pt] {
|
||||||
} else {
|
Some(sample)
|
||||||
None
|
} else {
|
||||||
}))
|
None
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn status (&self, index: usize) -> impl Content<TuiOut> {
|
pub fn status (&self, index: usize) -> impl Content<TuiOut> {
|
||||||
|
|
@ -105,13 +106,13 @@ impl Sampler {
|
||||||
|
|
||||||
pub fn view_meters_input (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_meters_input (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
Tui::bg(Black, Fixed::x(2, Map::east(1, ||self.input_meters.iter(), |value, _index|{
|
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<TuiOut> + use<'_> {
|
pub fn view_meters_output (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
Tui::bg(Black, Fixed::x(2, Map::east(1, ||self.output_meters.iter(), |value, _index|{
|
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<Arc<RwLock<Sample>>>) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_viewer (sample: Option<&Arc<RwLock<Sample>>>) -> impl Content<TuiOut> + use<'_> {
|
fn draw_viewer (sample: Option<&Arc<RwLock<Sample>>>) -> impl Content<TuiOut> + use<'_> {
|
||||||
let min_db = -40.0;
|
let min_db = -64.0;
|
||||||
ThunkRender::new(move|to: &mut TuiOut|{
|
ThunkRender::new(move|to: &mut TuiOut|{
|
||||||
let [x, y, width, height] = to.area();
|
let [x, y, width, height] = to.area();
|
||||||
let area = Rect { x, y, width, height };
|
let area = Rect { x, y, width, height };
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue