From c81de2123f7fb806d42958e8bf2540dc60ad87d5 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Fri, 12 Jul 2024 18:41:00 +0300 Subject: [PATCH] wip: adding samples --- src/control/sampler.rs | 32 ++++++++++---------- src/model/sampler.rs | 67 ++++++++++++++++++------------------------ 2 files changed, 46 insertions(+), 53 deletions(-) diff --git a/src/control/sampler.rs b/src/control/sampler.rs index 00d7bf0c..bbdf51a4 100644 --- a/src/control/sampler.rs +++ b/src/control/sampler.rs @@ -5,15 +5,16 @@ pub fn handle (state: &mut Sampler, event: &AppEvent) -> Usually { } pub const KEYMAP: &'static [KeyBinding] = keymap!(Sampler { - [Up, NONE, "cursor_up", "move cursor up", cursor_up], - [Down, NONE, "cursor_down", "move cursor down", cursor_down], - [Char('t'), NONE, "trigger", "play current sample", trigger], - [Enter, NONE, "select", "select item under cursor", select], + [Up, NONE, "cursor_up", "move cursor up", cursor_up], + [Down, NONE, "cursor_down", "move cursor down", cursor_down], + [Char('t'), NONE, "sample_play", "play current sample", trigger], + [Char('a'), NONE, "sample_add", "add a new sample", add_sample], + [Enter, NONE, "sample_edit", "edit selected sample", edit_sample], }); fn cursor_up (state: &mut Sampler) -> Usually { state.cursor.0 = if state.cursor.0 == 0 { - state.samples.len() - 1 + state.mapped.len() - 1 } else { state.cursor.0 - 1 }; @@ -21,24 +22,25 @@ fn cursor_up (state: &mut Sampler) -> Usually { } fn cursor_down (state: &mut Sampler) -> Usually { - state.cursor.0 = (state.cursor.0 + 1) % state.samples.len(); + state.cursor.0 = (state.cursor.0 + 1) % state.mapped.len(); Ok(true) } fn trigger (state: &mut Sampler) -> Usually { - for (i, sample) in state.samples.values().enumerate() { - if i == state.cursor.0 { - state.voices.push(sample.play(0, &100.into())) - } + if let Some(sample) = state.sample() { + state.voices.push(sample.play(0, &100.into())) } Ok(true) } -fn select (state: &mut Sampler) -> Usually { - for (i, _sample) in state.samples.values().enumerate() { - if i == state.cursor.0 { - //state.voices.push(sample.play(0)) - } +fn add_sample (state: &mut Sampler) -> Usually { + state.unmapped.push(Sample::new("", 0, 0, vec![])); + Ok(true) +} + +fn edit_sample (state: &mut Sampler) -> Usually { + if let Some(sample) = state.sample() { + state.editing = Some(sample.clone()); } Ok(true) } diff --git a/src/model/sampler.rs b/src/model/sampler.rs index d5a5cde6..e73ba723 100644 --- a/src/model/sampler.rs +++ b/src/model/sampler.rs @@ -1,12 +1,14 @@ use crate::core::*; pub struct Sampler { - pub name: String, - pub cursor: (usize, usize), - pub samples: BTreeMap>, - pub voices: Vec, - pub ports: JackPorts, - pub buffer: Vec>, + pub name: String, + pub cursor: (usize, usize), + pub editing: Option>, + pub mapped: BTreeMap>, + pub unmapped: Vec>, + pub voices: Vec, + pub ports: JackPorts, + pub buffer: Vec>, pub output_gain: f32 } render!(Sampler |self, buf, area| { @@ -15,7 +17,7 @@ render!(Sampler |self, buf, area| { let title = format!(" {} ({})", self.name, self.voices.len()); title.blit(buf, x+1, y, Some(style.white().bold().not_dim()))?; let mut width = title.len() + 2; - for (i, (note, sample)) in self.samples.iter().enumerate() { + for (i, (note, sample)) in self.mapped.iter().enumerate() { let style = if i == self.cursor.0 { Style::default().green() } else { @@ -35,38 +37,15 @@ render!(Sampler |self, buf, area| { label2.blit(buf, x+3+label1.len()as u16, y1, Some(style))?; width = width.max(label1.len() + label2.len() + 4); } - let height = ((2 + self.samples.len()) as u16).min(height); + let height = ((2 + self.mapped.len()) as u16).min(height); Ok(Rect { x, y, width: (width as u16).min(area.width), height }) }); handle!(Sampler = crate::control::sampler::handle); -//jack!(Sampler { - //process = Sampler::process, - //audio = { - //ins = |s|Ok(s.jack.audio_ins.values().collect()), - //outs = |s|Ok(s.jack.audio_outs.values().collect()), - //} - //midi = { - //ins = |s|Ok(s.jack.midi_ins.values().collect()), - //outs = |s|Ok(s.jack.midi_outs.values().collect()), - //} -//}); process!(Sampler = Sampler::process); -//ports!(Sampler { - //audio: { - //ins: |s|Ok(s.ports.audio_ins.values().collect()), - //outs: |s|Ok(s.ports.audio_outs.values().collect()), - //} - //midi: { - //ins: |s|Ok(s.ports.midi_ins.values().collect()), - //outs: |s|Ok(s.ports.midi_outs.values().collect()), - //} -//}); impl Sampler { - pub fn new ( - name: &str, samples: Option>>, - ) -> Usually { + pub fn new (name: &str, mapped: Option>>) -> Usually { Jack::new(name)? .midi_in("midi") .audio_in("recL") @@ -74,16 +53,28 @@ impl Sampler { .audio_out("outL") .audio_out("outR") .run(|ports|Box::new(Self { - name: name.into(), - cursor: (0, 0), - samples: samples.unwrap_or(BTreeMap::new()), - voices: vec![], + name: name.into(), + cursor: (0, 0), + editing: None, + mapped: mapped.unwrap_or_else(||BTreeMap::new()), + unmapped: vec![], + voices: vec![], ports, - buffer: vec![vec![0.0;16384];2], + buffer: vec![vec![0.0;16384];2], output_gain: 0.5, })) } + /// Immutable reference to sample at cursor. + pub fn sample (&self) -> Option<&Arc> { + for (i, sample) in self.mapped.values().enumerate() { + if i == self.cursor.0 { + return Some(sample) + } + } + None + } + pub fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control { self.process_midi_in(scope); self.clear_output_buffer(); @@ -96,7 +87,7 @@ impl Sampler { for RawMidi { time, bytes } in self.ports.midi_ins.get("midi").unwrap().iter(scope) { if let LiveEvent::Midi { message, .. } = LiveEvent::parse(bytes).unwrap() { if let MidiMessage::NoteOn { ref key, ref vel } = message { - if let Some(sample) = self.samples.get(key) { + if let Some(sample) = self.mapped.get(key) { self.voices.push(sample.play(time as usize, vel)); } }