plays crackly samples

This commit is contained in:
🪞👃🪞 2024-06-29 22:52:07 +03:00
parent de2e2a2124
commit 1672cbfc68
5 changed files with 90 additions and 26 deletions

View file

@ -22,8 +22,8 @@ pub struct Sample {
pub 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![] })
pub fn new (name: &str, start: usize, end: usize, channels: Vec<Vec<f32>>) -> Arc<Self> {
Arc::new(Self { name: name.to_string(), start, end, channels })
}
fn play (self: &Arc<Self>) -> Voice {
Voice { sample: self.clone(), position: self.start }
@ -64,7 +64,27 @@ impl Sampler {
}
pub fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
// Output buffer. This will be copied to the audio outs.
let channel_count = self.audio_outs.len();
let mut mixed = vec![vec![0.0;scope.n_frames() as usize];channel_count];
// emit currently playing voices
for voice in self.voices.iter_mut() {
let chunk = voice.chunk(scope.n_frames() as usize);
for (i, channel) in chunk.iter().enumerate() {
let buffer = &mut mixed[i % channel_count];
for (i, sample) in channel.iter().enumerate() {
buffer[i] += sample;
}
}
}
for (i, port) in self.audio_outs.iter_mut().enumerate() {
let buffer = &mixed[i];
for (i, value) in port.as_mut_slice(scope).iter_mut().enumerate() {
*value = *buffer.get(i).unwrap_or(&0.0);
}
}
Control::Continue
// process midi in
// add new voices
// emit new voices starting from midi event frames
@ -96,7 +116,6 @@ impl Sampler {
//}
//}
//}
Control::Continue
}
fn load_sample (&mut self, _path: &str) {}
@ -127,7 +146,7 @@ pub fn render (state: &Sampler, buf: &mut Buffer, Rect { x, y, height, .. }: Rec
{
let width = 40;
let style = Style::default().gray();
format!(" {} ", state.name).blit(buf, x+1, y, Some(style.white().bold().not_dim()));
format!(" {} ({})", state.name, state.voices.len()).blit(buf, x+1, y, Some(style.white().bold().not_dim()));
for (i, (note, sample)) in state.samples.iter().enumerate() {
let style = if i == state.cursor.0 {
Style::default().green()
@ -215,8 +234,10 @@ fn cursor_down (state: &mut Sampler) -> Usually<bool> {
Ok(true)
}
fn select (state: &mut Sampler) -> Usually<bool> {
if let Some(sample) = state.samples.get(&u7::from_int_lossy(state.cursor.0 as u8)) {
state.voices.push(sample.play())
for (i, sample) in state.samples.values().enumerate() {
if i == state.cursor.0 {
state.voices.push(sample.play())
}
}
Ok(true)
}

View file

@ -53,14 +53,14 @@ impl Launcher {
let ppq = timebase.ppq() as u32;
DynamicDevice::new(render, handle, process, Self {
name: name.into(),
view: LauncherView::Tracks,
view: LauncherView::Chains,
playing: transport.query_state()?,
transport,
timebase: timebase.clone(),
monitoring: true,
recording: false,
overdub: true,
cursor: (0, 0),
cursor: (1, 1),
position: 0,
scenes: scenes.unwrap_or_else(||vec![Scene::new(&"Scene 1", &[None])]),
tracks: if let Some(tracks) = tracks { tracks } else { vec![

View file

@ -15,6 +15,25 @@ pub mod time;
use crate::prelude::*;
macro_rules! sample {
($note:expr, $name:expr, $src:expr) => {
{
let mut channels: Vec<wavers::Samples<f32>> = vec![];
for channel in wavers::Wav::from_path($src)?.channels() {
channels.push(channel);
}
let mut end = 0;
let mut data: Vec<Vec<f32>> = vec![];
for samples in channels.iter() {
let channel = Vec::from(samples.as_ref());
end = end.max(channel.len());
data.push(channel);
}
(u7::from_int_lossy($note).into(), Sample::new($name, 0, end, data).into())
}
};
}
fn main () -> Result<(), Box<dyn Error>> {
let _cli = cli::Cli::parse();
let xdg = microxdg::XdgApp::new("tek")?;
@ -35,24 +54,8 @@ fn main () -> Result<(), Box<dyn Error>> {
Track::new("Kick", &timebase, Some(vec![
//Plugin::lv2("Kick/ChowKick", "file:///home/user/.lv2/ChowKick.lv2", &[1, 1, 0, 2])?.boxed(),
Sampler::new("Sampler", Some(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()),
sample!(36, "Kick", "/home/user/Lab/Music/pak/kik.wav"),
sample!(40, "Snare", "/home/user/Lab/Music/pak/sna.wav"),
])))?.boxed(),
]), Some(vec![
Phrase::new("HelloKick", ppq * 4, Some(BTreeMap::from([