mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
compact sampler
This commit is contained in:
parent
2432f27e8c
commit
15f71d0973
4 changed files with 135 additions and 131 deletions
|
|
@ -118,13 +118,13 @@ pub fn render (state: &Chain, buf: &mut Buffer, area: Rect)
|
|||
}
|
||||
|
||||
pub fn draw_as_row (
|
||||
state: &Chain, buf: &mut Buffer, area: Rect, selected: Option<Style>
|
||||
state: &Chain, buf: &mut Buffer, area: Rect, _: Option<Style>
|
||||
) -> Usually<(Rect, Vec<Rect>)> {
|
||||
let Rect { mut x, mut y, width, height } = area;
|
||||
let Rect { mut x, y, width, height } = area;
|
||||
x = x + 1;
|
||||
let mut h = 0u16;
|
||||
let mut frames = vec![];
|
||||
for (i, device) in state.items.iter().enumerate() {
|
||||
for device in state.items.iter() {
|
||||
let mut x2 = 1u16;
|
||||
let mut y2 = 1u16;
|
||||
for port in device.midi_ins()?.iter() {
|
||||
|
|
@ -160,56 +160,43 @@ pub fn draw_as_row (
|
|||
pub fn draw_as_column (
|
||||
state: &Chain, buf: &mut Buffer, area: Rect, selected: Option<Style>
|
||||
) -> Usually<Rect> {
|
||||
let Rect { mut x, mut y, width, height } = area;
|
||||
let Rect { x, y, width, height } = area;
|
||||
//let (area, areas) = Column::draw(buf, area, &state.items, 0)?;
|
||||
let mut w = 0u16;
|
||||
let mut y = area.y;
|
||||
let mut frames = vec![];
|
||||
for (i, device) in state.items.iter().enumerate() {
|
||||
|
||||
let midi_ins = device.midi_ins()?;
|
||||
let midi_outs = device.midi_outs()?;
|
||||
let audio_ins = device.audio_ins()?;
|
||||
let audio_outs = device.audio_outs()?;
|
||||
|
||||
for device in state.items.iter() {
|
||||
let style_midi = Style::default().black().bold().on_green();
|
||||
let style_audio = Style::default().black().bold().on_red();
|
||||
let midi_ins = device.midi_ins()?;
|
||||
let midi_outs = device.midi_outs()?;
|
||||
let audio_ins = device.audio_ins()?;
|
||||
let audio_outs = device.audio_outs()?;
|
||||
y = y + midi_ins.len() as u16;
|
||||
let frame = device.render(buf, Rect {
|
||||
x, y, width, height: height.saturating_sub(y)
|
||||
})?;
|
||||
frames.push(frame);
|
||||
w = w.max(frame.width);
|
||||
|
||||
y = y - midi_ins.len() as u16;
|
||||
for port in midi_ins.iter() {
|
||||
buf.set_string(x + frame.width - 10, y,
|
||||
&format!(" <i> MIDI {port} "),
|
||||
Style::default().black().bold().on_green());
|
||||
buf.set_string(x + frame.width - 10, y, &format!(" <i> MIDI {port} "), style_midi);
|
||||
y = y + 1;
|
||||
}
|
||||
|
||||
y = y - audio_ins.len() as u16;
|
||||
for port in audio_ins.iter() {
|
||||
buf.set_string(x + frame.width - 10, y,
|
||||
&format!(" <i> MIDI {port} "),
|
||||
Style::default().black().bold().on_red());
|
||||
buf.set_string(x + frame.width - 10, y, &format!(" <i> MIDI {port} "), style_audio);
|
||||
y = y + 1;
|
||||
}
|
||||
|
||||
y = y + frame.height - 1;
|
||||
|
||||
y = y + midi_outs.len() as u16;
|
||||
for port in midi_outs.iter() {
|
||||
buf.set_string(x + 2, y,
|
||||
&format!(" <o> MIDI {port} "),
|
||||
Style::default().black().bold().on_green());
|
||||
buf.set_string(x + 2, y, &format!(" <o> MIDI {port} "), style_midi);
|
||||
y = y + 1;
|
||||
}
|
||||
|
||||
y = y + audio_outs.len() as u16;
|
||||
for port in audio_outs.iter() {
|
||||
buf.set_string(x + 2, y,
|
||||
&format!(" <o> Audio {port} "),
|
||||
Style::default().black().bold().on_red());
|
||||
buf.set_string(x + 2, y, &format!(" <o> Audio {port} "), style_audio);
|
||||
y = y + 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,12 @@ pub fn handle (state: &mut Launcher, event: &AppEvent) -> Usually<bool> {
|
|||
}
|
||||
},
|
||||
LauncherView::Chains => {
|
||||
true
|
||||
let i = state.col().saturating_sub(1);
|
||||
if let Some(track) = state.tracks.get_mut(i) {
|
||||
crate::device::chain::handle(&mut *track.chain.state(), event)?
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,9 +171,10 @@ pub fn process (state: &mut Launcher, _: &Client, _: &ProcessScope) -> Control {
|
|||
state.position = transport.pos.frame() as usize;
|
||||
Control::Continue
|
||||
}
|
||||
pub fn render (state: &Launcher, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
||||
pub fn render (state: &Launcher, buf: &mut Buffer, mut area: Rect) -> Usually<Rect> {
|
||||
area.width = 80;
|
||||
area.height = 25;
|
||||
let Rect { x, y, width, height } = area;
|
||||
let width = 80;
|
||||
crate::device::sequencer::draw_play_stop(buf, x + 1, y, &state.playing);
|
||||
crate::device::sequencer::draw_rec(buf, x + 12, y, state.recording);
|
||||
crate::device::sequencer::draw_mon(buf, x + 19, y, state.monitoring);
|
||||
|
|
@ -287,12 +288,12 @@ fn draw_section_chains (state: &Launcher, buf: &mut Buffer, area: Rect) -> Usual
|
|||
} else {
|
||||
vec![]
|
||||
};
|
||||
match state.view {
|
||||
LauncherView::Chains => {
|
||||
draw_box_styled(buf, Rect { height: 18, ..area }, style);
|
||||
},
|
||||
_ => {},
|
||||
};
|
||||
//match state.view {
|
||||
//LauncherView::Chains => {
|
||||
//draw_box_styled(buf, Rect { height: 18, ..area }, style);
|
||||
//},
|
||||
//_ => {},
|
||||
//};
|
||||
draw_highlight(buf, &Some(area), match state.view {
|
||||
LauncherView::Chains => Style::default().green().dim(),
|
||||
_ => Style::default().dim()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue