simplify sample mapping

This commit is contained in:
🪞👃🪞 2024-12-28 17:06:19 +01:00
parent 48f341ba2c
commit 2feb21bd1f
4 changed files with 40 additions and 23 deletions

View file

@ -61,6 +61,7 @@ render!(<Tui>|self:GrooveboxTui|{
let phrase_w = if w > 60 { 20 } else if w > 40 { 15 } else { 10 };
let pool_w = if self.pool.visible { phrase_w } else { 0 };
let sampler_w = 11;
let note_pt = self.editor.note_point();
Fill::wh(lay!([
&self.size,
Fill::wh(Align::s(Fixed::h(2, GrooveboxStatus::from(self)))),
@ -84,11 +85,14 @@ render!(<Tui>|self:GrooveboxTui|{
&format!("L/{:>+9.3}", self.sampler.input_meter[0]),
&format!("R/{:>+9.3}", self.sampler.input_meter[1]),
Fill::wh(col!(note in (self.editor.note_lo().load(Relaxed)..=self.editor.note_hi()).rev() => {
if self.sampler.mapped.contains_key(&u7::from(note as u8)) {
todo!()
} else {
Tui::fg(TuiTheme::g(96), format!("{note:3} (none)"))
}
Tui::bg(
if note == note_pt { TuiTheme::g(64) } else { Color::Reset },
if let Some(sample) = &self.sampler.mapped[note] {
todo!()
} else {
Tui::fg(TuiTheme::g(160), format!("{note:3} (none)"))
}
)
})),
])), Fill::h(&self.editor))
)
@ -188,6 +192,7 @@ command!(|self:GrooveboxCommand,state:GrooveboxTui|match self {
}
},
Self::Clock(cmd) => cmd.execute(state)?.map(Clock),
Self::Sampler(cmd) => cmd.execute(&mut state.sampler)?.map(Sampler),
Self::Enqueue(phrase) => {
state.player.enqueue_next(phrase.as_ref());
None
@ -195,7 +200,4 @@ command!(|self:GrooveboxCommand,state:GrooveboxTui|match self {
Self::History(delta) => {
todo!("undo/redo")
},
Self::Sampler(command) => {
todo!("sampler")
}
});

View file

@ -38,7 +38,7 @@ pub(crate) use self::sample_import::*;
pub struct Sampler {
pub jack: Arc<RwLock<JackClient>>,
pub name: String,
pub mapped: BTreeMap<u7, Arc<RwLock<Sample>>>,
pub mapped: [Option<Arc<RwLock<Sample>>>;128],
pub unmapped: Vec<Arc<RwLock<Sample>>>,
pub voices: Arc<RwLock<Vec<Voice>>>,
pub midi_in: Port<MidiIn>,
@ -63,7 +63,7 @@ impl Sampler {
],
jack: jack.clone(),
name: name.into(),
mapped: BTreeMap::new(),
mapped: [const { None };128],
unmapped: vec![],
voices: Arc::new(RwLock::new(vec![])),
buffer: vec![vec![0.0;16384];2],
@ -86,9 +86,9 @@ pub struct SamplerTui {
impl SamplerTui {
/// Immutable reference to sample at cursor.
pub fn sample (&self) -> Option<&Arc<RwLock<Sample>>> {
for (i, sample) in self.state.mapped.values().enumerate() {
for (i, sample) in self.state.mapped.iter().enumerate() {
if i == self.cursor.0 {
return Some(sample)
return sample.as_ref()
}
}
for (i, sample) in self.state.unmapped.iter().enumerate() {

View file

@ -37,7 +37,7 @@ impl Sampler {
if let LiveEvent::Midi {
message: MidiMessage::NoteOn { ref key, ref vel }, ..
} = LiveEvent::parse(bytes).unwrap() {
if let Some(sample) = mapped.get(key) {
if let Some(ref sample) = mapped[key.as_int() as usize] {
voices.write().unwrap().push(Sample::play(sample, time as usize, vel));
}
}

View file

@ -1,21 +1,24 @@
use crate::*;
use KeyCode::Char;
handle!(<Tui>|self:SamplerTui,input|SamplerCommand::execute_with_state(self, input));
handle!(<Tui>|self: SamplerTui, input|SamplerTuiCommand::execute_with_state(self, input));
pub enum SamplerCommand {
pub enum SamplerTuiCommand {
Import(FileBrowserCommand),
SelectNote(usize),
SelectField(usize),
SetName(String),
SetNote(u7, Option<Arc<RwLock<Sample>>>),
Sample(SamplerCommand),
}
pub enum SamplerCommand {
Record(u7),
SetSample(u7, Option<Arc<RwLock<Sample>>>),
SetGain(f32),
NoteOn(u7, u7),
NoteOff(u7),
Record(u7),
}
input_to_command!(SamplerCommand: <Tui>|state: SamplerTui, input|match state.mode {
input_to_command!(SamplerTuiCommand: <Tui>|state: SamplerTui, input|match state.mode {
Some(SamplerMode::Import(..)) => Self::Import(
FileBrowserCommand::input_to_command(state, input)?
),
@ -51,7 +54,8 @@ input_to_command!(SamplerCommand: <Tui>|state: SamplerTui, input|match state.mod
//}
//}
});
command!(|self:SamplerCommand,state:SamplerTui|match self {
command!(|self: SamplerTuiCommand, state: SamplerTui|match self {
Self::Import(FileBrowserCommand::Begin) => {
let voices = &state.state.voices;
let sample = Arc::new(RwLock::new(Sample::new("", 0, 0, vec![])));
@ -63,10 +67,21 @@ command!(|self:SamplerCommand,state:SamplerTui|match self {
state.set_note_point(index);
Some(Self::SelectNote(old))
},
Self::Sample(cmd) => cmd.execute(&mut state.state)?.map(Self::Sample),
_ => todo!()
});
command!(|self: SamplerCommand, state: Sampler|match self {
Self::SetSample(index, sample) => {
let i = index.as_int() as usize;
let old = state.mapped[i].clone();
state.mapped[i] = sample;
Some(Self::SetSample(index, old))
},
Self::Record(index) => {
let old = state.state.mapped.get(&index).cloned();
Some(Self::SetNote(index, old))
let i = index.as_int() as usize;
let old = state.mapped[i].clone();
Some(Self::SetSample(index, old))
},
_ => todo!()
});