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 output_gain: f32 } render!(Sampler = crate::view::sampler::render); 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 { Jack::new(name)? .midi_in("midi") .audio_in("recL") .audio_in("recR") .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![], ports, buffer: vec![vec![0.0;16384];2], output_gain: 0.5, })) } pub fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control { self.process_midi_in(scope); self.clear_output_buffer(); self.process_audio_out(scope); self.write_output_buffer(scope); Control::Continue } fn process_midi_in (&mut self, scope: &ProcessScope) { 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, .. } = message { if let Some(sample) = self.samples.get(key) { self.voices.push(sample.play(time as usize)); } } } } } fn clear_output_buffer (&mut self) { for buffer in self.buffer.iter_mut() { buffer.fill(0.0); } } fn process_audio_out (&mut self, scope: &ProcessScope) { let channel_count = self.buffer.len(); self.voices.retain_mut(|voice|{ for index in 0..scope.n_frames() as usize { if let Some(frame) = voice.next() { for (channel, sample) in frame.iter().enumerate() { self.buffer[channel % channel_count][index] += sample * self.output_gain; } } else { return false } } return true }); } /// Write output buffer to output ports. fn write_output_buffer (&mut self, scope: &ProcessScope) { for (i, port) in self.ports.audio_outs.values_mut().enumerate() { let buffer = &self.buffer[i]; for (i, value) in port.as_mut_slice(scope).iter_mut().enumerate() { *value = *buffer.get(i).unwrap_or(&0.0); } } } } /// Load sample from WAV and assign to MIDI note. #[macro_export] macro_rules! sample { ($note:expr, $name:expr, $src:expr) => { { let mut channels: Vec> = vec![]; for channel in wavers::Wav::from_path($src)?.channels() { channels.push(channel); } let mut end = 0; let mut data: Vec> = vec![]; for samples in channels.iter() { let channel = Vec::from(samples.as_ref()); end = end.max(channel.len()); data.push(channel); } (u7::from_int_lossy($note).into(), Sample::new($name, 0, end, data).into()) } }; } pub struct Sample { pub name: String, pub start: usize, pub end: usize, pub channels: Vec>, } impl Sample { pub fn new (name: &str, start: usize, end: usize, channels: Vec>) -> Arc { Arc::new(Self { name: name.to_string(), start, end, channels }) } pub fn play (self: &Arc, after: usize) -> Voice { Voice { sample: self.clone(), after, position: self.start } } } pub struct Voice { pub sample: Arc, pub after: usize, pub position: usize, } const BUFFER: [f32;64] = [0.0f32;64]; impl Iterator for Voice { type Item = [f32;2]; fn next (&mut self) -> Option { if self.after > 0 { self.after = self.after - 1; return Some([0.0, 0.0]) } if self.position < self.sample.end { let position = self.position; self.position = self.position + 1; return Some([ self.sample.channels[0][position], self.sample.channels[0][position], ]) } None } }