mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
chore: tidy
This commit is contained in:
parent
1b7892d11f
commit
f48f17e9a4
8 changed files with 66 additions and 73 deletions
242
src/device/chain/sampler.rs
Normal file
242
src/device/chain/sampler.rs
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
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,
|
||||
}
|
||||
impl Voice {
|
||||
fn chunk (&mut self, frames: usize) -> Vec<Vec<f32>> {
|
||||
let mut chunk = vec![];
|
||||
for channel in self.sample.channels.iter() {
|
||||
chunk.push(channel[self.position..self.position+frames].into());
|
||||
};
|
||||
self.position = self.position + frames;
|
||||
chunk
|
||||
}
|
||||
}
|
||||
|
||||
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![
|
||||
],
|
||||
midi_in: client.register_port("midi", ::jack::MidiIn::default())?,
|
||||
audio_ins: vec![
|
||||
client.register_port("recL", ::jack::AudioIn::default())?,
|
||||
client.register_port("recR", ::jack::AudioIn::default())?,
|
||||
],
|
||||
audio_outs: vec![
|
||||
client.register_port("outL", ::jack::AudioOut::default())?,
|
||||
client.register_port("outR", ::jack::AudioOut::default())?,
|
||||
],
|
||||
}).activate(client)
|
||||
}
|
||||
|
||||
pub fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
|
||||
// emit currently playing voices
|
||||
// process midi in
|
||||
// add new voices
|
||||
// emit new voices starting from midi event frames
|
||||
|
||||
//for event in self.midi_in.iter(scope) {
|
||||
//let len = 3.min(event.bytes.len());
|
||||
//let mut data = [0; 3];
|
||||
//data[..len].copy_from_slice(&event.bytes[..len]);
|
||||
//if (data[0] >> 4) == 0b1001 { // note on
|
||||
//let channel = data[0] & 0b00001111;
|
||||
//let note = data[1];
|
||||
//let velocity = data[2];
|
||||
//for sample in self.samples.iter_mut() {
|
||||
//if sample.trigger.0 == channel && sample.trigger.1 == note {
|
||||
//sample.play(velocity);
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
//for sample in self.samples.iter_mut() {
|
||||
//if let Some(playing) = sample.playing {
|
||||
//for (index, value) in sample.port.as_mut_slice(scope).iter_mut().enumerate() {
|
||||
//*value = *sample.data[0].get(playing + index).unwrap_or(&0f32);
|
||||
//}
|
||||
//if playing + scope.n_frames() as usize > sample.data[0].len() {
|
||||
//sample.playing = None
|
||||
//} else {
|
||||
//sample.playing = Some(playing + scope.n_frames() as usize)
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
Control::Continue
|
||||
}
|
||||
|
||||
fn load_sample (&mut self, _path: &str) {}
|
||||
}
|
||||
|
||||
impl PortList for Sampler {
|
||||
fn midi_ins (&self) -> Usually<Vec<String>> {
|
||||
Ok(vec![self.midi_in.name()?])
|
||||
}
|
||||
fn audio_ins (&self) -> Usually<Vec<String>> {
|
||||
let mut ports = vec![];
|
||||
for port in self.audio_ins.iter() {
|
||||
ports.push(port.name()?);
|
||||
}
|
||||
Ok(ports)
|
||||
}
|
||||
fn audio_outs (&self) -> Usually<Vec<String>> {
|
||||
let mut ports = vec![];
|
||||
for port in self.audio_outs.iter() {
|
||||
ports.push(port.name()?);
|
||||
}
|
||||
Ok(ports)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render (state: &Sampler, buf: &mut Buffer, Rect { x, y, height, .. }: Rect)
|
||||
-> Usually<Rect>
|
||||
{
|
||||
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() {
|
||||
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));
|
||||
}
|
||||
Ok(Rect { x, y, width, height: height - 3 })
|
||||
}
|
||||
|
||||
//fn render_table (
|
||||
//state: &mut Sampler,
|
||||
//stdout: &mut Stdout,
|
||||
//offset: (u16, u16),
|
||||
//) -> Result<(), Box<dyn Error>> {
|
||||
//let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row);
|
||||
//stdout.queue(move_to(0, 3))?.queue(
|
||||
//Print(" Name Rate Trigger Route")
|
||||
//)?;
|
||||
//for (i, sample) in state.samples.lock().unwrap().iter().enumerate() {
|
||||
//let row = 4 + i as u16;
|
||||
//for (j, (column, field)) in [
|
||||
//(0, format!(" {:7} ", sample.name)),
|
||||
//(9, format!(" {:.1}Hz ", sample.rate)),
|
||||
//(18, format!(" MIDI C{} {} ", sample.trigger.0, sample.trigger.1)),
|
||||
//(33, format!(" {:.1}dB -> Output ", sample.gain)),
|
||||
//(50, format!(" {} ", sample.playing.unwrap_or(0))),
|
||||
//].into_iter().enumerate() {
|
||||
//stdout.queue(move_to(column, row))?;
|
||||
//if state.selected_sample == i && state.selected_column == j {
|
||||
//stdout.queue(PrintStyledContent(field.to_string().bold().reverse()))?;
|
||||
//} else {
|
||||
//stdout.queue(PrintStyledContent(field.to_string().bold()))?;
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
//Ok(())
|
||||
//}
|
||||
|
||||
//fn render_meters (
|
||||
//state: &mut Sampler,
|
||||
//stdout: &mut Stdout,
|
||||
//offset: (u16, u16),
|
||||
//) -> Result<(), Box<dyn Error>> {
|
||||
//let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row);
|
||||
//for (i, sample) in state.samples.lock().iter().enumerate() {
|
||||
//let row = 4 + i as u16;
|
||||
//stdout.queue(move_to(32, row))?.queue(
|
||||
//PrintStyledContent("▁".green())
|
||||
//)?;
|
||||
//}
|
||||
//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:?}");
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue