mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
plays crackly samples
This commit is contained in:
parent
de2e2a2124
commit
1672cbfc68
5 changed files with 90 additions and 26 deletions
39
Cargo.lock
generated
39
Cargo.lock
generated
|
|
@ -127,6 +127,12 @@ version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.16.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cassowary"
|
name = "cassowary"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
|
@ -889,6 +895,27 @@ dependencies = [
|
||||||
"ratatui",
|
"ratatui",
|
||||||
"toml",
|
"toml",
|
||||||
"vst",
|
"vst",
|
||||||
|
"wavers",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.61"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.61"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -996,6 +1023,18 @@ version = "0.11.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wavers"
|
||||||
|
version = "1.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ab501e9e5b13446d3a6e846de0c190c96b85ca3eced3bd00460edc67654500c8"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"num-traits",
|
||||||
|
"paste",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|
|
||||||
|
|
@ -17,3 +17,4 @@ vst = "0.4.0"
|
||||||
#vst3 = "0.1.0"
|
#vst3 = "0.1.0"
|
||||||
livi = "0.7.4"
|
livi = "0.7.4"
|
||||||
#atomic_enum = "0.3.0"
|
#atomic_enum = "0.3.0"
|
||||||
|
wavers = "1.4.3"
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ pub struct Sample {
|
||||||
pub channels: Vec<Vec<f32>>,
|
pub channels: Vec<Vec<f32>>,
|
||||||
}
|
}
|
||||||
impl Sample {
|
impl Sample {
|
||||||
fn new (name: &str) -> Arc<Self> {
|
pub fn new (name: &str, start: usize, end: usize, channels: Vec<Vec<f32>>) -> Arc<Self> {
|
||||||
Arc::new(Self { name: name.to_string(), start: 0, end: 0, channels: vec![] })
|
Arc::new(Self { name: name.to_string(), start, end, channels })
|
||||||
}
|
}
|
||||||
fn play (self: &Arc<Self>) -> Voice {
|
fn play (self: &Arc<Self>) -> Voice {
|
||||||
Voice { sample: self.clone(), position: self.start }
|
Voice { sample: self.clone(), position: self.start }
|
||||||
|
|
@ -64,7 +64,27 @@ impl Sampler {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
|
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
|
// 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
|
// process midi in
|
||||||
// add new voices
|
// add new voices
|
||||||
// emit new voices starting from midi event frames
|
// emit new voices starting from midi event frames
|
||||||
|
|
@ -96,7 +116,6 @@ impl Sampler {
|
||||||
//}
|
//}
|
||||||
//}
|
//}
|
||||||
//}
|
//}
|
||||||
Control::Continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_sample (&mut self, _path: &str) {}
|
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 width = 40;
|
||||||
let style = Style::default().gray();
|
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() {
|
for (i, (note, sample)) in state.samples.iter().enumerate() {
|
||||||
let style = if i == state.cursor.0 {
|
let style = if i == state.cursor.0 {
|
||||||
Style::default().green()
|
Style::default().green()
|
||||||
|
|
@ -215,8 +234,10 @@ fn cursor_down (state: &mut Sampler) -> Usually<bool> {
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
fn select (state: &mut Sampler) -> Usually<bool> {
|
fn select (state: &mut Sampler) -> Usually<bool> {
|
||||||
if let Some(sample) = state.samples.get(&u7::from_int_lossy(state.cursor.0 as u8)) {
|
for (i, sample) in state.samples.values().enumerate() {
|
||||||
state.voices.push(sample.play())
|
if i == state.cursor.0 {
|
||||||
|
state.voices.push(sample.play())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,14 +53,14 @@ impl Launcher {
|
||||||
let ppq = timebase.ppq() as u32;
|
let ppq = timebase.ppq() as u32;
|
||||||
DynamicDevice::new(render, handle, process, Self {
|
DynamicDevice::new(render, handle, process, Self {
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
view: LauncherView::Tracks,
|
view: LauncherView::Chains,
|
||||||
playing: transport.query_state()?,
|
playing: transport.query_state()?,
|
||||||
transport,
|
transport,
|
||||||
timebase: timebase.clone(),
|
timebase: timebase.clone(),
|
||||||
monitoring: true,
|
monitoring: true,
|
||||||
recording: false,
|
recording: false,
|
||||||
overdub: true,
|
overdub: true,
|
||||||
cursor: (0, 0),
|
cursor: (1, 1),
|
||||||
position: 0,
|
position: 0,
|
||||||
scenes: scenes.unwrap_or_else(||vec![Scene::new(&"Scene 1", &[None])]),
|
scenes: scenes.unwrap_or_else(||vec![Scene::new(&"Scene 1", &[None])]),
|
||||||
tracks: if let Some(tracks) = tracks { tracks } else { vec![
|
tracks: if let Some(tracks) = tracks { tracks } else { vec![
|
||||||
|
|
|
||||||
39
src/main.rs
39
src/main.rs
|
|
@ -15,6 +15,25 @@ pub mod time;
|
||||||
|
|
||||||
use crate::prelude::*;
|
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>> {
|
fn main () -> Result<(), Box<dyn Error>> {
|
||||||
let _cli = cli::Cli::parse();
|
let _cli = cli::Cli::parse();
|
||||||
let xdg = microxdg::XdgApp::new("tek")?;
|
let xdg = microxdg::XdgApp::new("tek")?;
|
||||||
|
|
@ -35,24 +54,8 @@ fn main () -> Result<(), Box<dyn Error>> {
|
||||||
Track::new("Kick", &timebase, Some(vec![
|
Track::new("Kick", &timebase, Some(vec![
|
||||||
//Plugin::lv2("Kick/ChowKick", "file:///home/user/.lv2/ChowKick.lv2", &[1, 1, 0, 2])?.boxed(),
|
//Plugin::lv2("Kick/ChowKick", "file:///home/user/.lv2/ChowKick.lv2", &[1, 1, 0, 2])?.boxed(),
|
||||||
Sampler::new("Sampler", Some(BTreeMap::from([
|
Sampler::new("Sampler", Some(BTreeMap::from([
|
||||||
(u7::from_int_lossy(35), Sample {
|
sample!(36, "Kick", "/home/user/Lab/Music/pak/kik.wav"),
|
||||||
name: "Kick 1".into(), start: 0, end: 100000, channels: vec![],
|
sample!(40, "Snare", "/home/user/Lab/Music/pak/sna.wav"),
|
||||||
}.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()),
|
|
||||||
])))?.boxed(),
|
])))?.boxed(),
|
||||||
]), Some(vec![
|
]), Some(vec![
|
||||||
Phrase::new("HelloKick", ppq * 4, Some(BTreeMap::from([
|
Phrase::new("HelloKick", ppq * 4, Some(BTreeMap::from([
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue