use crate::*; /// The sampler device plays sounds in response to MIDI notes. #[derive(Debug)] pub struct Sampler { /// Name of sampler. pub name: String, /// Device color. pub color: ItemTheme, /// Audio input ports. Samples get recorded here. pub audio_ins: Vec, /// Audio input meters. pub input_meters: Vec, /// Sample currently being recorded. pub recording: Option<(usize, Arc>)>, /// Recording buffer. pub buffer: Vec>, /// Samples mapped to MIDI notes. pub mapped: [Option>>;128], /// Samples that are not mapped to MIDI notes. pub unmapped: Vec>>, /// Sample currently being edited. pub editing: Option>>, /// MIDI input port. Triggers sample playback. pub midi_in: Option, /// Collection of currently playing instances of samples. pub voices: Arc>>, /// Audio output ports. Voices get played here. pub audio_outs: Vec, /// Audio output meters. pub output_meters: Vec, /// How to mix the voices. pub mixing_mode: MixingMode, /// How to meter the inputs and outputs. pub metering_mode: MeteringMode, /// Fixed gain applied to all output. pub output_gain: f32, /// Currently active modal, if any. pub mode: Option, /// Size of rendered sampler. pub size: Measure, /// Lowest note displayed. pub note_lo: AtomicUsize, /// Currently selected note. pub note_pt: AtomicUsize, /// Selected note as row/col. pub cursor: (AtomicUsize, AtomicUsize), } impl Default for Sampler { fn default () -> Self { Self { midi_in: None, audio_ins: vec![], input_meters: vec![0.0;2], output_meters: 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, editing: None, size: Default::default(), note_lo: 0.into(), note_pt: 0.into(), cursor: (0.into(), 0.into()), color: Default::default(), mixing_mode: Default::default(), metering_mode: 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 { name: name.into(), 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() }) } /// Value of cursor pub fn cursor (&self) -> (usize, usize) { (self.cursor.0.load(Relaxed), self.cursor.1.load(Relaxed)) } } impl NoteRange for Sampler { fn note_lo (&self) -> &AtomicUsize { &self.note_lo } fn note_axis (&self) -> &AtomicUsize { &self.size.y } } impl NotePoint for Sampler { fn note_len (&self) -> &AtomicUsize { unreachable!(); } fn get_note_len (&self) -> usize { 0 } fn set_note_len (&self, x: usize) -> usize { 0 /*TODO?*/ } fn note_pos (&self) -> &AtomicUsize { &self.note_pt } fn get_note_pos (&self) -> usize { self.note_pt.load(Relaxed) } fn set_note_pos (&self, x: usize) -> usize { let old = self.note_pt.swap(x, Relaxed); self.cursor.0.store(x % 8, Relaxed); self.cursor.1.store(x / 8, Relaxed); old } } /// 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), }