mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 04:36:45 +01:00
compact sampler
This commit is contained in:
parent
2432f27e8c
commit
15f71d0973
4 changed files with 135 additions and 131 deletions
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue