wip: reenable sampling

This commit is contained in:
🪞👃🪞 2025-04-27 17:19:33 +03:00
parent e9c825e865
commit efd182f302
6 changed files with 61 additions and 38 deletions

View file

@ -10,4 +10,4 @@
(@right select :sample-right) (@right select :sample-right)
(@d select :sample-right) (@d select :sample-right)
(@r record/begin :sample) (@r record/toggle :sample)

View file

@ -24,12 +24,16 @@ expose!([self: Tek]
([isize]) ([isize])
([Color]) ([Color])
([Arc<RwLock<MidiClip>>]) ([Arc<RwLock<MidiClip>>])
([u7] (":pitch" (self.editor().map(|e|e.note_pos()).unwrap() as u8).into())) ([u7]
([u16] (":w-sidebar" self.w_sidebar())) (":pitch" (self.editor().map(|e|e.note_pos()).unwrap() as u8).into()))
([usize] (":scene-last" self.scenes.len()) ([u16]
(":track-last" self.tracks.len())) (":w-sidebar" self.w_sidebar()))
([Option<usize>] (":scene" self.selected.scene()) ([usize]
(":track" self.selected.track())) (":scene-last" self.scenes.len())
(":track-last" self.tracks.len()))
([Option<usize>]
(":scene" self.selected.scene())
(":track" self.selected.track()))
([MaybeClip] ([MaybeClip]
(":clip" match self.selected { (":clip" match self.selected {
Selection::Clip(t, s) => self.scenes[s].clips[t].clone(), Selection::Clip(t, s) => self.scenes[s].clips[t].clone(),
@ -108,7 +112,7 @@ impose!([app: Tek]
defcom!([self, app: Tek] defcom!([self, app: Tek]
(TekCommand (TekCommand
(Sampler [cmd: SamplerCommand] cmd_todo!("\n\rtodo: sampler {cmd:?}")) (Sampler [cmd: SamplerCommand] app.sampler_mut().map(|s|cmd.delegate(s, Self::Sampler)).transpose()?.flatten())
(Scene [cmd: SceneCommand] cmd.delegate(app, Self::Scene)?) (Scene [cmd: SceneCommand] cmd.delegate(app, Self::Scene)?)
(Track [cmd: TrackCommand] cmd.delegate(app, Self::Track)?) (Track [cmd: TrackCommand] cmd.delegate(app, Self::Track)?)
(Output [cmd: OutputCommand] cmd.delegate(app, Self::Output)?) (Output [cmd: OutputCommand] cmd.delegate(app, Self::Output)?)

View file

@ -316,7 +316,12 @@ impl Tek {
/// Get the first sampler of the active track /// Get the first sampler of the active track
pub fn sampler (&self) -> Option<&Sampler> { pub fn sampler (&self) -> Option<&Sampler> {
self.tracks.get(0).map(|t|t.sampler(0)).flatten() self.track().map(|t|t.sampler(0)).flatten()
}
/// Get the first sampler of the active track
pub fn sampler_mut (&mut self) -> Option<&mut Sampler> {
self.track_mut().map(|t|t.sampler_mut(0)).flatten()
} }
/// Set the color of the selected entity /// Set the color of the selected entity

View file

@ -149,6 +149,7 @@ impl Cli {
_ => vec![] _ => vec![]
}, },
scenes, scenes,
selected: Selection::Clip(0, 0),
..Default::default() ..Default::default()
}; };
if let &LaunchMode::Arranger { scenes, tracks, track_width, .. } = mode { if let &LaunchMode::Arranger { scenes, tracks, track_width, .. } = mode {

View file

@ -2,15 +2,17 @@ use crate::*;
expose!([self: Sampler] expose!([self: Sampler]
([Arc<str>]) ([Arc<str>])
([Option<Arc<RwLock<Sample>>>]) ([MaybeSample])
([PathBuf]) ([PathBuf])
([f32]) ([f32])
([u7] (":pitch" (self.note_pos() as u8).into()) // TODO ([u7]
(":sample" (self.note_pos() as u8).into())) (":pitch" (self.note_pos() as u8).into()) // TODO
([usize] (":sample-up" self.note_pos().min(119) + 8) (":sample" (self.note_pos() as u8).into()))
(":sample-down" self.note_pos().max(8) - 8) ([usize]
(":sample-left" self.note_pos().min(126) + 1) (":sample-up" self.note_pos().min(119) + 8)
(":sample-right" self.note_pos().max(1) - 1))); (":sample-down" self.note_pos().max(8) - 8)
(":sample-left" self.note_pos().min(126) + 1)
(":sample-right" self.note_pos().max(1) - 1)));
impose!([state: Sampler] impose!([state: Sampler]
(FileBrowserCommand: (FileBrowserCommand:
@ -31,7 +33,7 @@ impose!([state: Sampler]
Some(Self::RecordCancel)) Some(Self::RecordCancel))
("record/finish" [] ("record/finish" []
Some(Self::RecordFinish)) Some(Self::RecordFinish))
("set/sample" [i: u7, s: Option<Arc<RwLock<Sample>>>] ("set/sample" [i: u7, s: MaybeSample]
Some(Self::SetSample(i.expect("no index"), s.expect("no sampler")))) Some(Self::SetSample(i.expect("no index"), s.expect("no sampler"))))
("set/start" [i: u7, s: usize] ("set/start" [i: u7, s: usize]
Some(Self::SetStart(i.expect("no index"), s.expect("no start")))) Some(Self::SetStart(i.expect("no index"), s.expect("no start"))))
@ -42,17 +44,21 @@ impose!([state: Sampler]
("note/off" [p: u7] ("note/off" [p: u7]
Some(Self::NoteOff(p.expect("no pitch")))))); Some(Self::NoteOff(p.expect("no pitch"))))));
macro_rules! cmd { ($cmd:expr) => {{ $cmd; None }}; }
macro_rules! cmd_todo { ($msg:literal) => {{ println!($msg); None }}; }
defcom!([self, state: Sampler] defcom!([self, state: Sampler]
(SamplerCommand (SamplerCommand
(Select [i: usize] Some(Self::Select(state.set_note_pos(i)))) (Select [i: usize] Some(Self::Select(state.set_note_pos(i))))
(RecordBegin [p: u7] { state.begin_recording(p.as_int() as usize); None }) (RecordBegin [p: u7] cmd!(state.begin_recording(p.as_int() as usize)))
(RecordCancel [] { state.cancel_recording(); None }) (RecordCancel [] cmd!(state.cancel_recording()))
(RecordFinish [] { state.finish_recording(); None }) (RecordFinish [] cmd!(state.finish_recording()))
(SetStart [pitch: u7, frame: usize] { println!("\n\rtodo: {self:?}"); None }) (SetStart [p: u7, frame: usize] cmd_todo!("\n\rtodo: {self:?}"))
(SetGain [pitch: u7, gain: f32] { println!("\n\rtodo: {self:?}"); None }) (SetGain [p: u7, gain: f32] cmd_todo!("\n\rtodo: {self:?}"))
(NoteOn [pitch: u7, velocity: u7] { println!("\n\rtodo: {self:?}"); None }) (NoteOn [p: u7, velocity: u7] cmd_todo!("\n\rtodo: {self:?}"))
(NoteOff [pitch: u7] { println!("\n\rtodo: {self:?}"); None }) (NoteOff [p: u7] cmd_todo!("\n\rtodo: {self:?}"))
(Import [cmd: FileBrowserCommand] match cmd { (SetSample [p: u7, s: MaybeSample] Some(Self::SetSample(p, state.set_sample(p, s))))
(Import [c: FileBrowserCommand] match c {
FileBrowserCommand::Begin => { FileBrowserCommand::Begin => {
//let voices = &state.state.voices; //let voices = &state.state.voices;
//let sample = Arc::new(RwLock::new(Sample::new("", 0, 0, vec![]))); //let sample = Arc::new(RwLock::new(Sample::new("", 0, 0, vec![])));
@ -60,13 +66,7 @@ defcom!([self, state: Sampler]
None None
}, },
_ => { _ => {
println!("\n\rtodo: import: filebrowser: {cmd:?}"); println!("\n\rtodo: import: filebrowser: {c:?}");
None None
} }
})
(SetSample [pitch: u7, sample: Option<Arc<RwLock<Sample>>>] {
let i = pitch.as_int() as usize;
let old = state.mapped[i].clone();
state.mapped[i] = sample;
Some(Self::SetSample(pitch, old))
}))); })));

View file

@ -1,10 +1,12 @@
use crate::*; use crate::*;
pub type MaybeSample = Option<Arc<RwLock<Sample>>>;
/// The sampler device plays sounds in response to MIDI notes. /// The sampler device plays sounds in response to MIDI notes.
#[derive(Debug)] #[derive(Debug)]
pub struct Sampler { pub struct Sampler {
pub name: String, pub name: String,
pub mapped: [Option<Arc<RwLock<Sample>>>;128], pub mapped: [MaybeSample;128],
pub recording: Option<(usize, Arc<RwLock<Sample>>)>, pub recording: Option<(usize, Arc<RwLock<Sample>>)>,
pub unmapped: Vec<Arc<RwLock<Sample>>>, pub unmapped: Vec<Arc<RwLock<Sample>>>,
pub voices: Arc<RwLock<Vec<Voice>>>, pub voices: Arc<RwLock<Vec<Voice>>>,
@ -14,7 +16,7 @@ pub struct Sampler {
pub audio_outs: Vec<JackAudioOut>, pub audio_outs: Vec<JackAudioOut>,
pub buffer: Vec<Vec<f32>>, pub buffer: Vec<Vec<f32>>,
pub output_gain: f32, pub output_gain: f32,
pub editing: Option<Arc<RwLock<Sample>>>, pub editing: MaybeSample,
pub mode: Option<SamplerMode>, pub mode: Option<SamplerMode>,
/// Size of actual notes area /// Size of actual notes area
pub size: Measure<TuiOut>, pub size: Measure<TuiOut>,
@ -83,7 +85,7 @@ impl Sampler {
Arc::new(RwLock::new(Sample::new("Sample", 0, 0, vec![vec![];self.audio_ins.len()]))) Arc::new(RwLock::new(Sample::new("Sample", 0, 0, vec![vec![];self.audio_ins.len()])))
)); ));
} }
pub fn finish_recording (&mut self) -> Option<Arc<RwLock<Sample>>> { pub fn finish_recording (&mut self) -> MaybeSample {
let recording = self.recording.take(); let recording = self.recording.take();
if let Some((index, sample)) = recording { if let Some((index, sample)) = recording {
let old = self.mapped[index].clone(); let old = self.mapped[index].clone();
@ -111,6 +113,13 @@ impl Sampler {
pub fn cursor (&self) -> (usize, usize) { pub fn cursor (&self) -> (usize, usize) {
(self.cursor.0.load(Relaxed), self.cursor.1.load(Relaxed)) (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 { impl NoteRange for Sampler {
@ -123,8 +132,12 @@ impl NoteRange for Sampler {
} }
impl NotePoint for Sampler { impl NotePoint for Sampler {
fn note_len (&self) -> usize { 0/*TODO*/ } fn note_len (&self) -> usize {
fn set_note_len (&self, x: usize) -> usize { 0 /*TODO*/ } 0 /*TODO?*/
}
fn set_note_len (&self, x: usize) -> usize {
0 /*TODO?*/
}
fn note_pos (&self) -> usize { fn note_pos (&self) -> usize {
self.note_pt.load(Relaxed) self.note_pt.load(Relaxed)
} }