use crate::*; /// The sampler device plays sounds in response to MIDI notes. #[derive(Debug)] pub struct Sampler { pub name: String, pub mapped: [Option>>;128], pub recording: Option<(usize, Arc>)>, pub unmapped: Vec>>, pub voices: Arc>>, pub midi_in: Option, pub audio_ins: Vec, pub input_meter: Vec, pub audio_outs: Vec, pub buffer: Vec>, pub output_gain: f32, pub cursor: (usize, usize), pub editing: Option>>, pub mode: Option, /// Size of actual notes area pub size: Measure, /// Lowest note displayed pub note_lo: AtomicUsize, pub note_pt: AtomicUsize, pub color: ItemPalette } impl Default for Sampler { fn default () -> Self { Self { midi_in: None, audio_ins: vec![], input_meter: vec![0.0;2], audio_outs: vec![], name: "tek_sampler".to_string(), mapped: [const { None };128], unmapped: vec![], voices: Arc::new(RwLock::new(vec![])), buffer: vec![vec![0.0;16384];2], output_gain: 1., recording: None, mode: None, cursor: (0, 0), editing: None, size: Default::default(), note_lo: 0.into(), note_pt: 0.into(), color: Default::default(), } } } impl Sampler { pub fn new ( jack: &Jack, name: impl AsRef, midi_from: &[PortConnect], audio_from: &[&[PortConnect];2], audio_to: &[&[PortConnect];2], ) -> Usually { let name = name.as_ref(); Ok(Self { midi_in: Some(JackMidiIn::new(jack, format!("M/{name}"), midi_from)?), audio_ins: vec![ JackAudioIn::new(jack, &format!("L/{name}"), audio_from[0])?, JackAudioIn::new(jack, &format!("R/{name}"), audio_from[1])?, ], audio_outs: vec![ JackAudioOut::new(jack, &format!("{name}/L"), audio_to[0])?, JackAudioOut::new(jack, &format!("{name}/R"), audio_to[1])?, ], ..Default::default() }) } pub fn cancel_recording (&mut self) { self.recording = None; } pub fn begin_recording (&mut self, index: usize) { self.recording = Some(( index, Arc::new(RwLock::new(Sample::new("Sample", 0, 0, vec![vec![];self.audio_ins.len()]))) )); } pub fn finish_recording (&mut self) -> Option>> { let recording = self.recording.take(); if let Some((index, sample)) = recording { let old = self.mapped[index].clone(); self.mapped[index] = Some(sample); old } else { None } } /// Immutable reference to sample at cursor. pub fn sample (&self) -> Option<&Arc>> { for (i, sample) in self.mapped.iter().enumerate() { if i == self.cursor.0 { return sample.as_ref() } } for (i, sample) in self.unmapped.iter().enumerate() { if i + self.mapped.len() == self.cursor.0 { return Some(sample) } } None } } /// A sound sample. #[derive(Default, Debug)] pub struct Sample { pub name: Arc, pub start: usize, pub end: usize, pub channels: Vec>, pub rate: Option, pub gain: f32, } impl Sample { pub fn new (name: impl AsRef, start: usize, end: usize, channels: Vec>) -> Self { Self { name: name.as_ref().into(), start, end, channels, rate: None, gain: 1.0 } } pub fn play (sample: &Arc>, after: usize, velocity: &u7) -> Voice { Voice { sample: sample.clone(), after, position: sample.read().unwrap().start, velocity: velocity.as_int() as f32 / 127.0, } } } /// A currently playing instance of a sample. #[derive(Default, Debug, Clone)] pub struct Voice { pub sample: Arc>, pub after: usize, pub position: usize, pub velocity: f32, } #[derive(Debug)] pub enum SamplerMode { // Load sample from path Import(usize, FileBrowser), }