mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 04:36:45 +01:00
wip: refactor into fewer crates
This commit is contained in:
parent
c367a0444e
commit
77703d83a5
105 changed files with 64 additions and 131 deletions
191
crates/device/src/sampler/sampler_model.rs
Normal file
191
crates/device/src/sampler/sampler_model.rs
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
use crate::*;
|
||||
|
||||
pub type MaybeSample = Option<Arc<RwLock<Sample>>>;
|
||||
|
||||
/// The sampler device plays sounds in response to MIDI notes.
|
||||
#[derive(Debug)]
|
||||
pub struct Sampler {
|
||||
pub name: String,
|
||||
pub mapped: [MaybeSample;128],
|
||||
pub recording: Option<(usize, Arc<RwLock<Sample>>)>,
|
||||
pub unmapped: Vec<Arc<RwLock<Sample>>>,
|
||||
pub voices: Arc<RwLock<Vec<Voice>>>,
|
||||
pub midi_in: Option<JackMidiIn>,
|
||||
pub audio_ins: Vec<JackAudioIn>,
|
||||
pub input_meter: Vec<f32>,
|
||||
pub audio_outs: Vec<JackAudioOut>,
|
||||
pub buffer: Vec<Vec<f32>>,
|
||||
pub output_gain: f32,
|
||||
pub editing: MaybeSample,
|
||||
pub mode: Option<SamplerMode>,
|
||||
/// Size of actual notes area
|
||||
pub size: Measure<TuiOut>,
|
||||
/// Lowest note displayed
|
||||
pub note_lo: AtomicUsize,
|
||||
/// Selected note
|
||||
pub note_pt: AtomicUsize,
|
||||
/// Selected note as row/col
|
||||
pub cursor: (AtomicUsize, AtomicUsize),
|
||||
pub color: ItemTheme
|
||||
}
|
||||
|
||||
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,
|
||||
editing: None,
|
||||
size: Default::default(),
|
||||
note_lo: 0.into(),
|
||||
note_pt: 0.into(),
|
||||
cursor: (0.into(), 0.into()),
|
||||
color: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sampler {
|
||||
pub fn new (
|
||||
jack: &Jack,
|
||||
name: impl AsRef<str>,
|
||||
midi_from: &[PortConnect],
|
||||
audio_from: &[&[PortConnect];2],
|
||||
audio_to: &[&[PortConnect];2],
|
||||
) -> Usually<Self> {
|
||||
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) -> MaybeSample {
|
||||
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<RwLock<Sample>>> {
|
||||
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
|
||||
}
|
||||
/// Value of cursor
|
||||
pub fn cursor (&self) -> (usize, usize) {
|
||||
(self.cursor.0.load(Relaxed), self.cursor.1.load(Relaxed))
|
||||
}
|
||||
/// Assign sample to pitch
|
||||
pub fn set_sample (&mut self, pitch: u7, sample: MaybeSample) -> MaybeSample {
|
||||
let i = pitch.as_int() as usize;
|
||||
let old = self.mapped[i].clone();
|
||||
self.mapped[i] = sample;
|
||||
old
|
||||
}
|
||||
}
|
||||
|
||||
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) -> usize {
|
||||
0 /*TODO?*/
|
||||
}
|
||||
fn set_note_len (&self, x: usize) -> usize {
|
||||
0 /*TODO?*/
|
||||
}
|
||||
fn 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<str>,
|
||||
pub start: usize,
|
||||
pub end: usize,
|
||||
pub channels: Vec<Vec<f32>>,
|
||||
pub rate: Option<usize>,
|
||||
pub gain: f32,
|
||||
}
|
||||
|
||||
impl Sample {
|
||||
pub fn new (name: impl AsRef<str>, start: usize, end: usize, channels: Vec<Vec<f32>>) -> Self {
|
||||
Self { name: name.as_ref().into(), start, end, channels, rate: None, gain: 1.0 }
|
||||
}
|
||||
pub fn play (sample: &Arc<RwLock<Self>>, 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<RwLock<Sample>>,
|
||||
pub after: usize,
|
||||
pub position: usize,
|
||||
pub velocity: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SamplerMode {
|
||||
// Load sample from path
|
||||
Import(usize, FileBrowser),
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue