mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
flatten midi recording code
This commit is contained in:
parent
198a730e33
commit
1d7d816899
5 changed files with 68 additions and 58 deletions
|
|
@ -93,7 +93,8 @@ from_edn!("sample" => |(_jack, dir): (&Arc<RwLock<JackClient>>, &str), args| ->
|
|||
start,
|
||||
end,
|
||||
channels: data,
|
||||
rate: None
|
||||
rate: None,
|
||||
gain: 1.0
|
||||
}))))
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Vec<Vec<u8>>>) {
|
||||
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<Vec<Vec<u8>>>) {
|
||||
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<Arc<RwLock<MidiClip>>>,
|
||||
midi_buf: &mut Vec<Vec<Vec<u8>>>
|
||||
) {
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ pub struct Sample {
|
|||
pub end: usize,
|
||||
pub channels: Vec<Vec<f32>>,
|
||||
pub rate: Option<usize>,
|
||||
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<Vec<f32>>) -> 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<RwLock<Self>>, after: usize, velocity: &u7) -> Voice {
|
||||
Voice {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue