big worky on sequencer and launcher

This commit is contained in:
🪞👃🪞 2024-06-28 23:19:25 +03:00
parent a4c3593840
commit 8a8d7b8704
14 changed files with 852 additions and 680 deletions

View file

@ -1,82 +1,101 @@
use crate::prelude::*;
pub const ACTIONS: [(&'static str, &'static str);2] = [
("Enter", "Play sample"),
("Ins/Del", "Add/remove sample"),
];
pub struct Sampler {
name: String,
input: ::jack::Port<::jack::MidiIn>,
samples: Arc<Mutex<Vec<Sample>>>,
selected_sample: usize,
selected_column: usize,
midi_ins: Vec<Port<MidiIn>>,
audio_ins: Vec<Port<AudioIn>>,
audio_outs: Vec<Port<AudioOut>>,
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 {
port: Port<AudioOut>,
name: String,
rate: u32,
gain: f64,
channels: u8,
data: Vec<Vec<f32>>,
trigger: (u8, u8),
playing: Option<usize>,
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)?;
let samples = vec![
Sample::new("Kick", &client, 1, 35)?,
Sample::new("Snare", &client, 1, 38)?,
];
let samples = Arc::new(Mutex::new(samples));
let input = client.register_port("trigger", ::jack::MidiIn::default())?;
DynamicDevice::new(render, handle, Self::process, Self {
name: name.into(),
input,
selected_sample: 0,
selected_column: 0,
samples,
midi_ins: vec![],
audio_ins: vec![],
audio_outs: vec![],
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 {
let mut samples = self.samples.lock().unwrap();
for event in self.input.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 samples.iter_mut() {
if sample.trigger.0 == channel && sample.trigger.1 == note {
sample.play(velocity);
}
}
}
for sample in 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)
}
}
}
}
// 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
}
@ -84,6 +103,9 @@ impl Sampler {
}
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() {
@ -98,42 +120,14 @@ impl PortList for Sampler {
}
Ok(ports)
}
fn midi_ins (&self) -> Usually<Vec<String>> {
let mut ports = vec![];
for port in self.midi_ins.iter() {
ports.push(port.name()?);
}
Ok(ports)
}
}
impl Sample {
pub fn new (name: &str, client: &Client, channel: u8, note: u8) -> Result<Self, Box<dyn Error>> {
Ok(Self {
port: client.register_port(name, ::jack::AudioOut::default())?,
name: name.into(),
rate: 44100,
channels: 1,
gain: 0.0,
data: vec![vec![1.0, 0.0, 0.0, 0.0]],
trigger: (channel, note),
playing: None
})
}
fn play (&mut self, _velocity: u8) {
self.playing = Some(0)
}
}
pub fn render (state: &Sampler, buf: &mut Buffer, Rect { x, y, width, .. }: Rect)
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 });
//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()));
@ -153,7 +147,7 @@ pub fn render (state: &Sampler, buf: &mut Buffer, Rect { x, y, width, .. }: Rect
format!(" {cut}")
.blit(buf, x+2, y+4+i*2, Some(style));
}
Ok(Rect { x, y, width, height: 11 })
Ok(Rect { x, y, width, height: height - 3 })
}
//fn render_table (
@ -202,6 +196,11 @@ pub fn render (state: &Sampler, buf: &mut Buffer, Rect { x, y, width, .. }: Rect
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') => {