compact sampler

This commit is contained in:
🪞👃🪞 2024-06-29 16:22:47 +03:00
parent 2432f27e8c
commit 15f71d0973
4 changed files with 135 additions and 131 deletions

View file

@ -1,29 +1,5 @@
use crate::prelude::*;
pub struct Sampler {
name: String,
cursor: (usize, usize),
samples: Vec<Arc<Sample>>,
voices: Vec<Voice>,
midi_in: Port<MidiIn>,
audio_ins: Vec<Port<AudioIn>>,
audio_outs: Vec<Port<AudioOut>>,
}
pub struct Sample {
name: String,
channels: Vec<Vec<f32>>,
start: usize,
}
impl Sample {
fn new (name: &str) -> Arc<Self> {
Arc::new(Self { name: name.to_string(), channels: vec![], start: 0 })
}
fn play (self: &Arc<Self>) -> Voice {
Voice { sample: self.clone(), position: self.start }
}
}
pub struct Voice {
sample: Arc<Sample>,
position: usize,
@ -39,18 +15,76 @@ impl Voice {
}
}
pub struct Sample {
name: String,
start: usize,
end: usize,
channels: Vec<Vec<f32>>,
}
impl Sample {
fn new (name: &str) -> Arc<Self> {
Arc::new(Self { name: name.to_string(), start: 0, end: 0, channels: vec![] })
}
fn play (self: &Arc<Self>) -> Voice {
Voice { sample: self.clone(), position: self.start }
}
}
pub struct Sampler {
name: String,
cursor: (usize, usize),
samples: BTreeMap<u7, Arc<Sample>>,
voices: Vec<Voice>,
midi_in: Port<MidiIn>,
audio_ins: Vec<Port<AudioIn>>,
audio_outs: Vec<Port<AudioOut>>,
}
impl Sampler {
pub fn new (name: &str) -> Result<DynamicDevice<Self>, Box<dyn Error>> {
let (client, _) = Client::new(name, ClientOptions::NO_START_SERVER)?;
DynamicDevice::new(render, handle, Self::process, Self {
name: name.into(),
cursor: (0, 0),
samples: vec![
Sample::new("Kick"),
Sample::new("Snare"),
],
voices: vec![
],
samples: BTreeMap::from([
(u7::from_int_lossy(35), Sample {
name: "Kick 1".into(),
start: 0,
end: 100000,
channels: vec![],
}.into()),
(u7::from_int_lossy(36).into(), Sample {
name: "Kick 2".into(),
start: 0,
end: 100000,
channels: vec![],
}.into()),
(u7::from_int_lossy(38).into(), Sample {
name: "Snare 1".into(),
start: 0,
end: 100000,
channels: vec![],
}.into()),
(u7::from_int_lossy(40).into(), Sample {
name: "Snare 2".into(),
start: 50000,
end: 100000,
channels: vec![],
}.into()),
(u7::from_int_lossy(42).into(), Sample {
name: "HH Closed".into(),
start: 0,
end: 50000,
channels: vec![],
}.into()),
(u7::from_int_lossy(46).into(), Sample {
name: "HH Open".into(),
start: 0,
end: 25000,
channels: vec![]
}.into()),
]),
voices: vec![],
midi_in: client.register_port("midi", ::jack::MidiIn::default())?,
audio_ins: vec![
client.register_port("recL", ::jack::AudioIn::default())?,
@ -127,27 +161,27 @@ pub fn render (state: &Sampler, buf: &mut Buffer, Rect { x, y, height, .. }: Rec
{
let width = 40;
let style = Style::default().gray();
//draw_box(buf, Rect { x, y: y, width: 40, height: 12 });
let separator = format!("{}", "-".repeat((width - 2).into()));
separator.blit(buf, x, y + 2, Some(style.dim()));
format!(" {}", state.name).blit(buf, x+1, y+1, Some(style.white().bold()));
for (i, (note, name, cut)) in [
("C4", "Sample#000", format!("{:.03}s",
100000.0/44100.0)),
("C#4", "Sample#001", format!("{:.03}-{:.03}s",
50000.0/44100.0, 100000.0/44100.0)),
("D4", "Sample#002", format!("{:.03}-{:.03}/{:.03}s",
0.0, 50000.0/44100.0, 100000.0/44100.0)),
("D#4", "Sample#003", format!("{:.03}-[{:.03}-{:.03}]/{:.03}s ",
10000.0/44100.0, 25000.0/44100.0, 50000.0/44100.0, 100000.0/44100.0)),
].iter().enumerate() {
format!(" {}", state.name).blit(buf, x+1, y, Some(style.white().bold()));
for (i, (note, sample)) in state.samples.iter().enumerate() {
let style = if i == state.cursor.0 {
Style::default().green()
} else {
Style::default()
};
let i = i as u16;
format!("{note:3} {name}")
.blit(buf, x+2, y+3+i*2, Some(style.bold()));
format!(" {cut}")
.blit(buf, x+2, y+4+i*2, Some(style));
let y1 = y+1+i;
if y1 >= y + height {
break
}
if i as usize == state.cursor.0 {
"".blit(buf, x+1, y1, Some(style.bold()));
}
let label1 = format!("{note:3} {:10}", sample.name);
let label2 = format!("{:>7} {:>7}", sample.start, sample.end);
label1.blit(buf, x+2, y1, Some(style.bold()));
label2.blit(buf, x+3+label1.len()as u16, y1, Some(style));
}
Ok(Rect { x, y, width, height: height - 3 })
Ok(Rect { x, y, width, height })
}
//fn render_table (
@ -194,49 +228,26 @@ pub fn render (state: &Sampler, buf: &mut Buffer, Rect { x, y, height, .. }: Rec
//Ok(())
//}
pub fn handle (_: &mut Sampler, _: &AppEvent) -> Usually<bool> {
Ok(false)
//pub const ACTIONS: [(&'static str, &'static str);2] = [
//("Enter", "Play sample"),
//("Ins/Del", "Add/remove sample"),
//];
//if let Event::Input(crossterm::event::Event::Key(event)) = event {
//match event.code {
//KeyCode::Char('c') => {
//if event.modifiers == KeyModifiers::CONTROL {
//state.exit();
//}
//},
//KeyCode::Down => {
//state.selected_sample = (state.selected_sample + 1) % state.samples.lock().unwrap().len();
//println!("{}", state.selected_sample);
//},
//KeyCode::Up => {
//if state.selected_sample == 0 {
//state.selected_sample = state.samples.lock().unwrap().len() - 1;
//} else {
//state.selected_sample = state.selected_sample - 1;
//}
//println!("{}", state.selected_sample);
//},
//KeyCode::Left => {
//if state.selected_column == 0 {
//state.selected_column = 6
//} else {
//state.selected_column = state.selected_column - 1;
//}
//},
//KeyCode::Right => {
//if state.selected_column == 6 {
//state.selected_column = 0
//} else {
//state.selected_column = state.selected_column + 1;
//}
//},
//_ => {
//println!("{event:?}");
//}
//}
//}
pub fn handle (state: &mut Sampler, event: &AppEvent) -> Usually<bool> {
Ok(handle_keymap(state, event, KEYMAP)?)
}
pub const KEYMAP: &'static [KeyBinding<Sampler>] = keymap!(Sampler {
[Up, NONE, "cursor_up", "move cursor up", cursor_up],
[Down, NONE, "cursor_down", "move cursor down", cursor_down],
[Enter, NONE, "enter", "activate", enter],
});
fn cursor_up (state: &mut Sampler) -> Usually<bool> {
state.cursor.0 = if state.cursor.0 == 0 {
state.samples.len() - 1
} else {
state.cursor.0 - 1
};
Ok(true)
}
fn cursor_down (state: &mut Sampler) -> Usually<bool> {
state.cursor.0 = (state.cursor.0 + 1) % state.samples.len();
Ok(true)
}
fn enter (state: &mut Sampler) -> Usually<bool> {
Ok(true)
}