From 1d7d81689946c7ed3bd58d8337a127733c98bbbb Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 28 Dec 2024 21:40:18 +0100 Subject: [PATCH] flatten midi recording code --- crates/edn/src/lib.rs | 3 +- crates/tek/src/groovebox.rs | 29 ++++++----- crates/tek/src/midi/midi_rec.rs | 87 +++++++++++++++++--------------- crates/tek/src/sampler/sample.rs | 3 +- crates/tek/src/sampler/voice.rs | 4 +- 5 files changed, 68 insertions(+), 58 deletions(-) diff --git a/crates/edn/src/lib.rs b/crates/edn/src/lib.rs index 9b814a17..1465b951 100644 --- a/crates/edn/src/lib.rs +++ b/crates/edn/src/lib.rs @@ -93,7 +93,8 @@ from_edn!("sample" => |(_jack, dir): (&Arc>, &str), args| -> start, end, channels: data, - rate: None + rate: None, + gain: 1.0 })))) }); diff --git a/crates/tek/src/groovebox.rs b/crates/tek/src/groovebox.rs index ac138f5c..fbad7ed9 100644 --- a/crates/tek/src/groovebox.rs +++ b/crates/tek/src/groovebox.rs @@ -64,19 +64,22 @@ audio!(|self: GrooveboxTui, client, scope|{ self.editor.set_note_point(key.as_int() as usize); }, MidiMessage::Controller { controller, value } => { - if controller == u7::from(20) { - if let Some(sample) = &self.sampler.mapped[self.editor.note_point()] { - let mut sample = sample.write().unwrap(); - let percentage = value.as_int() as f64 / 127.; - sample.start = (percentage * sample.end as f64) as usize; - } - } else if controller == u7::from(21) { - if let Some(sample) = &self.sampler.mapped[self.editor.note_point()] { - let mut sample = sample.write().unwrap(); - let percentage = value.as_int() as f64 / 127.; - let length = sample.channels[0].len(); - sample.end = sample.start + (percentage * (length as f64 - sample.start as f64)) as usize; - sample.end = sample.end.min(length); + if let Some(sample) = &self.sampler.mapped[self.editor.note_point()] { + let mut sample = sample.write().unwrap(); + let percentage = value.as_int() as f64 / 127.; + match controller.as_int() { + 20 => { + sample.start = (percentage * sample.end as f64) as usize; + }, + 21 => { + let length = sample.channels[0].len(); + sample.end = sample.start + (percentage * (length as f64 - sample.start as f64)) as usize; + sample.end = sample.end.min(length); + }, + 24 => { + sample.gain = percentage as f32 * 2.0; + }, + _ => {} } } } diff --git a/crates/tek/src/midi/midi_rec.rs b/crates/tek/src/midi/midi_rec.rs index 94abf84d..6c2bb768 100644 --- a/crates/tek/src/midi/midi_rec.rs +++ b/crates/tek/src/midi/midi_rec.rs @@ -8,46 +8,6 @@ pub trait MidiRecordApi: HasClock + HasPlayPhrase + HasMidiIns { fn toggle_record (&mut self) { *self.recording_mut() = !self.recording(); } - fn record (&mut self, scope: &ProcessScope, midi_buf: &mut Vec>>) { - let sample0 = scope.last_frame_time() as usize; - // For highlighting keys and note repeat - let notes_in = self.notes_in().clone(); - if self.clock().is_rolling() { - if let Some((started, ref phrase)) = self.play_phrase().clone() { - let start = started.sample.get() as usize; - let quant = self.clock().quant.get(); - let timebase = self.clock().timebase().clone(); - let monitoring = self.monitoring(); - let recording = self.recording(); - for input in self.midi_ins_mut().iter() { - for (sample, event, bytes) in parse_midi_input(input.iter(scope)) { - if let LiveEvent::Midi { message, .. } = event { - if monitoring { - midi_buf[sample].push(bytes.to_vec()) - } - if recording { - if let Some(phrase) = phrase { - let mut phrase = phrase.write().unwrap(); - let length = phrase.length; - phrase.record_event({ - let sample = (sample0 + sample - start) as f64; - let pulse = timebase.samples_to_pulse(sample); - let quantized = (pulse / quant).round() * quant; - quantized as usize % length - }, message); - } - } - update_keys(&mut notes_in.write().unwrap(), &message); - } - } - } - } - if let Some((start_at, _clip)) = &self.next_phrase() { - // TODO switch to next phrase and record into it - } - } - } - fn monitoring (&self) -> bool; fn monitoring_mut (&mut self) -> &mut bool; fn toggle_monitor (&mut self) { @@ -65,7 +25,52 @@ pub trait MidiRecordApi: HasClock + HasPlayPhrase + HasMidiIns { } } } - + fn record (&mut self, scope: &ProcessScope, midi_buf: &mut Vec>>) { + if self.monitoring() { + self.monitor(scope, midi_buf); + } + if !self.clock().is_rolling() { + return + } + if let Some((started, ref clip)) = self.play_phrase().clone() { + self.record_clip(scope, started, clip, midi_buf); + } + if let Some((start_at, phrase)) = &self.next_phrase() { + self.record_next(); + } + } + fn record_clip ( + &mut self, + scope: &ProcessScope, + started: Moment, + phrase: &Option>>, + midi_buf: &mut Vec>> + ) { + let sample0 = scope.last_frame_time() as usize; + let start = started.sample.get() as usize; + let recording = self.recording(); + let timebase = self.clock().timebase().clone(); + let quant = self.clock().quant.get(); + if let Some(phrase) = phrase { + let mut phrase = phrase.write().unwrap(); + let length = phrase.length; + for input in self.midi_ins_mut().iter() { + for (sample, event, bytes) in parse_midi_input(input.iter(scope)) { + if let LiveEvent::Midi { message, .. } = event { + phrase.record_event({ + let sample = (sample0 + sample - start) as f64; + let pulse = timebase.samples_to_pulse(sample); + let quantized = (pulse / quant).round() * quant; + quantized as usize % length + }, message); + } + } + } + } + } + fn record_next (&mut self) { + // TODO switch to next clip and record into it + } fn overdub (&self) -> bool; fn overdub_mut (&mut self) -> &mut bool; fn toggle_overdub (&mut self) { diff --git a/crates/tek/src/sampler/sample.rs b/crates/tek/src/sampler/sample.rs index adfc9fa0..39f6d9b6 100644 --- a/crates/tek/src/sampler/sample.rs +++ b/crates/tek/src/sampler/sample.rs @@ -9,6 +9,7 @@ pub struct Sample { pub end: usize, pub channels: Vec>, pub rate: Option, + pub gain: f32, } /// Load sample from WAV and assign to MIDI note. @@ -24,7 +25,7 @@ pub struct Sample { impl Sample { pub fn new (name: &str, start: usize, end: usize, channels: Vec>) -> Self { - Self { name: name.to_string(), start, end, channels, rate: None } + Self { name: name.to_string(), start, end, channels, rate: None, gain: 1.0 } } pub fn play (sample: &Arc>, after: usize, velocity: &u7) -> Voice { Voice { diff --git a/crates/tek/src/sampler/voice.rs b/crates/tek/src/sampler/voice.rs index 738f51aa..be4d8918 100644 --- a/crates/tek/src/sampler/voice.rs +++ b/crates/tek/src/sampler/voice.rs @@ -21,8 +21,8 @@ impl Iterator for Voice { let position = self.position; self.position += 1; return sample.channels[0].get(position).map(|_amplitude|[ - sample.channels[0][position] * self.velocity, - sample.channels[0][position] * self.velocity, + sample.channels[0][position] * self.velocity * sample.gain, + sample.channels[0][position] * self.velocity * sample.gain, ]) } None