From 768c2337e7b547e498bdf77c3b14d5b71bbc8cfb Mon Sep 17 00:00:00 2001 From: unspeaker Date: Fri, 5 Jul 2024 01:28:27 +0300 Subject: [PATCH] jammable again - and autoconnects! --- src/control.rs | 45 ++++++++++++++++----------- src/main.rs | 29 +++++++++++++---- src/model/sampler.rs | 3 +- src/model/track.rs | 74 +++++++++++++++++++++++++------------------- src/view.rs | 6 ++-- 5 files changed, 98 insertions(+), 59 deletions(-) diff --git a/src/control.rs b/src/control.rs index 98b6734e..34cf2577 100644 --- a/src/control.rs +++ b/src/control.rs @@ -63,9 +63,32 @@ const KEYMAP: &'static [KeyBinding] = keymap!(App { } }], [F(1), NONE, "toggle_help", "toggle help", |_: &mut App| {Ok(true)}], - [Char('r'), NONE, "toggle_record", "toggle recording", |_: &mut App| {Ok(true)}], - [Char('d'), NONE, "toggle_overdub", "toggle overdub", |_: &mut App| {Ok(true)}], - [Char('m'), NONE, "toggle_monitor", "toggle input monitoring", |_: &mut App| {Ok(true)}], + [Char('r'), NONE, "toggle_record", "toggle recording", |app: &mut App| { + app.track_mut().map(|t|t.1.toggle_record()); + Ok(true) + }], + [Char('d'), NONE, "toggle_overdub", "toggle overdub", |app: &mut App| { + app.track_mut().map(|t|t.1.toggle_overdub()); + Ok(true) + }], + [Char('m'), NONE, "toggle_monitor", "toggle input monitoring", |app: &mut App| { + app.track_mut().map(|t|t.1.toggle_monitor()); + Ok(true) + }], +//fn toggle_record (s: &mut Launcher) -> Usually { + //s.sequencer_mut().map(|s|s.recording = !s.recording); + //Ok(true) +//} + +//fn toggle_overdub (s: &mut Launcher) -> Usually { + //s.sequencer_mut().map(|s|s.overdub = !s.overdub); + //Ok(true) +//} + +//fn toggle_monitor (s: &mut Launcher) -> Usually { + //s.sequencer_mut().map(|s|s.monitoring = !s.monitoring); + //Ok(true) +//} [Up, NONE, "cursor_up", "move cursor up", |app: &mut App| { if app.entered { match app.section { @@ -152,7 +175,7 @@ const KEYMAP: &'static [KeyBinding] = keymap!(App { [Char('d'), CONTROL, "duplicate", "duplicate scene or track", duplicate], [Enter, NONE, "activate", "activate item at cursor", enter], [Esc, NONE, "escape", "unfocus", escape], - [Char('r'), CONTROL, "rename", "rename current element", rename], + //[Char('r'), CONTROL, "rename", "rename current element", rename], // [Char('='), NONE, "zoom_in", "Zoom in", zoom_in], // [Char('-'), NONE, "zoom_out", "Zoom out", zoom_out], // [Char('a'), NONE, "note_add", "Add note", note_add], @@ -347,20 +370,6 @@ fn duplicate (_: &mut App) -> Usually { Ok(true) } fn rename (_: &mut App) -> Usually { Ok(true) } -//fn toggle_record (s: &mut Launcher) -> Usually { - //s.sequencer_mut().map(|s|s.recording = !s.recording); - //Ok(true) -//} - -//fn toggle_overdub (s: &mut Launcher) -> Usually { - //s.sequencer_mut().map(|s|s.overdub = !s.overdub); - //Ok(true) -//} - -//fn toggle_monitor (s: &mut Launcher) -> Usually { - //s.sequencer_mut().map(|s|s.monitoring = !s.monitoring); - //Ok(true) -//} //use crate::{core::*, model::*}; //use super::focus::*; diff --git a/src/main.rs b/src/main.rs index 1d683a98..9b97db4c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,6 +33,20 @@ pub fn main () -> Usually<()> { state.playing = Some(TransportState::Stopped); state.midi_in = Some(client.register_port("midi-in", MidiIn)?); + let _ = ["nanoKEY Studio.*capture.*"] + .iter() + .map(|name|client + .ports(Some(name), None, PortFlags::empty()) + .iter() + .map(|name|{ + if let Some(port) = client.port_by_name(name) { + client.connect_ports(&port, &state.midi_in.as_ref().unwrap())?; + } + Ok(()) + }) + .collect::>()) + .collect::>()?; + let timebase = &state.timebase; let ppq = timebase.ppq() as usize; state.track_cursor = 1; @@ -54,7 +68,9 @@ pub fn main () -> Usually<()> { state.add_track_with_cb(Some("Drums"), |_, track|{ track.add_device_with_cb(Sampler::new("Sampler", Some(BTreeMap::from([ - sample!(36, "Kick", "/home/user/Lab/Music/pak/kik.wav"), + sample!(34, "808", "/home/user/Lab/Music/pak/808.wav"), + sample!(35, "Kick1", "/home/user/Lab/Music/pak/kik.wav"), + sample!(36, "Kick2", "/home/user/Lab/Music/pak/kik2.wav"), sample!(40, "Snare", "/home/user/Lab/Music/pak/sna.wav"), sample!(44, "Hihat", "/home/user/Lab/Music/pak/chh.wav"), ])))?, |track, device|{ @@ -89,13 +105,13 @@ pub fn main () -> Usually<()> { 00 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }, 04 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() }, 08 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }, - 10 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }, + 10 * ppq/4 => MidiMessage::NoteOn { key: 35.into(), vel: 100.into() }, 12 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() }, })); track.add_phrase("Garage", ppq * 4, Some(phrase! { - 00 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }, + 00 * ppq/4 => MidiMessage::NoteOn { key: 35.into(), vel: 100.into() }, 04 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() }, - 11 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }, + 11 * ppq/4 => MidiMessage::NoteOn { key: 35.into(), vel: 100.into() }, 12 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() }, })); Ok(()) @@ -105,7 +121,8 @@ pub fn main () -> Usually<()> { track.add_device_with_cb(Plugin::lv2( "Odin2", "file:///home/user/.lv2/Odin2.lv2" - )?, |_, device|{ + )?, |track, device|{ + device.connect_midi_in(0, &track.midi_out.clone_unowned())?; if let Some(Some(left)) = outputs.get(0) { device.connect_audio_out(0, left)?; } @@ -208,7 +225,7 @@ process!(App |self, _client, scope| { &self.timebase, self.playing, &scope, - frame, + self.playhead, frames, panic, ); diff --git a/src/model/sampler.rs b/src/model/sampler.rs index 3305a423..d6af341a 100644 --- a/src/model/sampler.rs +++ b/src/model/sampler.rs @@ -70,6 +70,7 @@ impl Sampler { // dropping voices that have reached their ends. let mut voices = vec![]; std::mem::swap(&mut voices, &mut self.voices); + let gain = 0.5; loop { if voices.len() < 1 { break @@ -79,7 +80,7 @@ impl Sampler { for (i, channel) in chunk.iter().enumerate() { let buffer = &mut mixed[i % channel_count]; for (i, sample) in channel.iter().enumerate() { - buffer[i] += sample; + buffer[i] += sample * gain; } } self.voices.push(voice); diff --git a/src/model/track.rs b/src/model/track.rs index da7bdc1c..ddf9fd94 100644 --- a/src/model/track.rs +++ b/src/model/track.rs @@ -61,7 +61,7 @@ impl Track { frames: usize, panic: bool, ) { - // Need to be borrowed outside the conditional + // Need to be borrowed outside the conditionals? let recording = self.recording; let monitoring = self.monitoring; // Output buffer @@ -82,39 +82,42 @@ impl Track { } } // Monitor and record input - let phrase = &mut self.phrase_mut(); - for (time, event, bytes) in parse_midi_input(input) { - let pulse = timebase.frames_pulses((frame0 + time) as f64) as usize; - match event { - LiveEvent::Midi { message, .. } => { - if monitoring { - if let Some(Some(frame)) = output.get_mut(time) { - frame.push(bytes.into()) - } else { - output[time] = Some(vec![bytes.into()]); - } - } - if recording { - if let Some(phrase) = phrase { - let contains = phrase.notes.contains_key(&pulse); - if contains { - phrase.notes.get_mut(&pulse).unwrap().push(message.clone()); + if self.recording || self.monitoring { + let phrase = &mut self.phrase_mut(); + for (time, event, bytes) in parse_midi_input(input) { + match event { + LiveEvent::Midi { message, .. } => { + if monitoring { + if let Some(Some(frame)) = output.get_mut(time) { + frame.push(bytes.into()) } else { - phrase.notes.insert(pulse, vec![message.clone()]); + output[time] = Some(vec![bytes.into()]); } - }; - } - match message { - MidiMessage::NoteOn { key, .. } => { - notes_on[key.as_int() as usize] = true; } - MidiMessage::NoteOff { key, .. } => { - notes_on[key.as_int() as usize] = false; - }, - _ => {} - } - }, - _ => {} + if recording { + if let Some(phrase) = phrase { + let pulse = timebase.frames_pulses((frame0 + time) as f64) as usize; + let pulse = pulse % phrase.length; + let contains = phrase.notes.contains_key(&pulse); + if contains { + phrase.notes.get_mut(&pulse).unwrap().push(message.clone()); + } else { + phrase.notes.insert(pulse, vec![message.clone()]); + } + }; + } + match message { + MidiMessage::NoteOn { key, .. } => { + notes_on[key.as_int() as usize] = true; + } + MidiMessage::NoteOff { key, .. } => { + notes_on[key.as_int() as usize] = false; + }, + _ => {} + } + }, + _ => {} + } } } self.notes_on = notes_on; @@ -171,4 +174,13 @@ impl Track { let index = self.phrases.len() - 1; &mut self.phrases[index] } + pub fn toggle_monitor (&mut self) { + self.monitoring = !self.monitoring; + } + pub fn toggle_record (&mut self) { + self.recording = !self.recording; + } + pub fn toggle_overdub (&mut self) { + self.overdub = !self.overdub; + } } diff --git a/src/view.rs b/src/view.rs index ba4be97b..df3483be 100644 --- a/src/view.rs +++ b/src/view.rs @@ -21,9 +21,9 @@ render!(App |self, buf, area| { y = y + TransportView { timebase: &self.timebase, playing: *self.playing.as_ref().unwrap_or(&TransportState::Stopped), - record: false, - overdub: false, - monitor: false, + monitor: self.track().map(|t|t.1.monitoring).unwrap_or(false), + record: self.track().map(|t|t.1.recording).unwrap_or(false), + overdub: self.track().map(|t|t.1.overdub).unwrap_or(false), frame: self.playhead, }.render(buf, area)?.height;