diff options
author | Wavy Harp <wavyharp@gmail.com> | 2023-05-07 23:04:53 -0600 |
---|---|---|
committer | Kyle McFarland <tfkyle@gmail.com> | 2023-05-07 23:04:53 -0600 |
commit | 991849b32acf83dd14a5096540bb053d2572502a (patch) | |
tree | 279b59d75d4ad6081f5242cf77d843ae6b37fc3d /src/proc.rs | |
download | rustynotes-991849b32acf83dd14a5096540bb053d2572502a.zip rustynotes-991849b32acf83dd14a5096540bb053d2572502a.tar.gz rustynotes-991849b32acf83dd14a5096540bb053d2572502a.tar.bz2 |
currently everything is very tied to alsa and my system,
for the moment you'll need to manually change the device names
and maybe channels/period_size in src/main.rs, src/bin/smolguitar.rs
and src/bin/loopbacker.rs, i'll fix that and add runtime period
size/updater allocation soon, (and probably make a cpal backend as well
so it can work on other platforms), but doing this initial commit to play
around with stereo for now~
Diffstat (limited to 'src/proc.rs')
-rw-r--r-- | src/proc.rs | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/src/proc.rs b/src/proc.rs new file mode 100644 index 0000000..2b32747 --- /dev/null +++ b/src/proc.rs @@ -0,0 +1,162 @@ +//#![feature(split_array)] +//#![feature(adt_const_params)] +//#![feature(generic_const_exprs)] +use crate::notes::{Note, NoteValue, ProcerNote, ProcerNotes}; +//use std::sync::Arc; +use std::collections::VecDeque; + +// Arc does heap allocate, so it might make sense to just pass owned arrays around and copy/clone +// when needed +//pub type Update<const S: usize> = Arc<[f64; S]>; +pub type Update<I, const S: usize> = [I; S]; +pub type UpDequer<I, const S: usize> = VecDeque<Update<I, S>>; + +pub trait Procer<I: NoteValue, const US: usize> { + fn get_size(&self) -> usize; + fn get_frequency(&self) -> usize; + fn make_pnotes<'nl>(&self, notes: &'nl [Note]) -> Vec<ProcerNote<'nl, I>>; + // this function only modifies ProcerNotes when you have enough data + // otherwise it leaves them alone or sets them to 0 (not sure which yet) + fn process_data(&mut self, input: &Update<I, US>, notes: &mut [ProcerNote<I>]) -> bool; +} + +pub trait DequerUtils<I, const BS: usize> { + fn cur_max_buffer_size(&self) -> usize; + fn update_buffer_array(&self, buf: &mut [I; BS]) -> bool; + //fn make_buffer(&self) -> Option<[I; BS]>; +} + +// the tuple this returns is (plan_size (ie the - index of the first element to copy from), +// Option<copy_size>), if the option is None copy the entire update, otherwise copy +// copy_size from the end of the first array +const fn make_buf_plan(buf_size: usize, update_size: usize) -> (usize, Option<usize>) { + let remainder_size = buf_size % update_size; + let plan_size = buf_size / update_size; + if remainder_size > 0 { + return (plan_size+1, Some(remainder_size)); + } else { + return (plan_size, None); + } +} + +impl<I: Clone, const S: usize, const BS: usize> DequerUtils<I, BS> for UpDequer<I, S> { + #[inline(always)] + fn cur_max_buffer_size(&self) -> usize { + S * self.len() + } + + fn update_buffer_array(&self, buf: &mut [I; BS]) -> bool { + let total_bufs = self.len(); + let max_size = S * total_bufs; + if BS > max_size { + return false; + } + // XXX: calculate this at runtime for now, const generics (atleast currently) can't be used + // for calculating consts + // <https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#when-a-const-variable-can-be-used> + // TODO: this could be made const itself by making a consts mod and putting the update and + // buffer sizes as consts in there instead of having them as const generic arguments + let plan = make_buf_plan(BS, S); + //let mut cur_start = 0; + let mut cur_index = total_bufs - plan.0; + //println!("{:?}, {}, {}", plan, cur_index, S); + let (copy_s, slicey) = match plan.1 { + None => (S, self.get(cur_index).unwrap().as_slice()), + Some(copy_size) => (copy_size, &self.get(cur_index).unwrap()[(S-copy_size)..]) + }; + //println!("{:?}", slicey); + // do the copy n stuff + let (mut left, mut right) = buf.split_at_mut(copy_s); + left.clone_from_slice(slicey); + //cur_start += copy_s; + cur_index += 1; + for up_i in cur_index..total_bufs { + //let (mut l2, r2) = right.split_at_mut(S); + //right = r2; + (left, right) = right.split_at_mut(S); + left.clone_from_slice(self.get(up_i).unwrap().as_slice()); + } + return true; + } + + /*fn make_buffer_vec(&self) -> Option<[I; BS]> { + let total_bufs = self.len(); + let max_size = S * total_bufs; + if BS > max_size { + return None; + } + // convert this bit to a const fn, because it can be :o, could maybe make a const + // copy_bytes_from_iter function or something + //const remainder_size: usize = BS / S; + //const S_2: usize = S; + //const PLAN: (usize, Option<usize>) = make_buf_plan(BS_2, S_2); + /*const PARTIAL_FIRST: bool = PLAN.1.is_some(); + let mut cur_start = 0; + let mut cur_index = total_bufs - PLAN.0; + let mut ret: [f64; BS] = [0.0; BS]; + if PARTIAL_FIRST { + const Some(PVAL): usize = PARTIAL_FIRST; + let slicey = self.get(cur_index).rsplit_array_ref(copy_size); + let (left, _) = ret.split_array_mut::<PVAL>(); + left.clone_from(slicey); + }*/ + /*let slicey = match PLAN.1 { + None => &self.get(cur_index) + Some(copy_size) => &self.get(cur_index).rsplit_array_ref(copy_size) + }*/ + let mut ret: [I; BS] = [I::default(); BS]; + return Some(ret); + }*/ +} + +#[derive(Debug)] +pub struct ProcerData<'nl, I: NoteValue> { + pub pnotes: ProcerNotes<'nl, I>, + size: usize, + frequency: usize, + pub current: bool, +} + +impl<'nl, I: NoteValue> ProcerData<'nl, I> { + pub fn new<const US: usize>(procer: &impl Procer<I, US>, pnotes: ProcerNotes<'nl, I>) -> Self { + return Self { + pnotes: pnotes, + size: procer.get_size(), + frequency: procer.get_frequency(), + current: false, + } + } +} + +#[cfg(test)] +mod tests { + use crate::proc::{Update, UpDequer, DequerUtils}; + use std::collections::VecDeque; + #[test] + fn test_update_buffer_array() { + let mut data_dq: UpDequer<f32, 5> = VecDeque::with_capacity(6); + let updates: [Update<f32, 5>; 5] = [[1.0, 2.0, 3.0, 4.0, 5.0], [6.0, 7.0, 8.0, 9.0, 10.0], [11.0, 12.0, 13.0, 14.0, 15.0], [16.0, 17.0, 18.0, 19.0, 20.0], [21.0, 22.0, 23.0, 24.0, 25.0]]; + data_dq.push_back(updates[0]); + data_dq.push_back(updates[1]); + data_dq.push_back(updates[2]); + data_dq.push_back(updates[3]); + data_dq.push_back(updates[4]); + let mut ba: [f32; 24] = [0.0; 24]; + let copied = data_dq.update_buffer_array(&mut ba); + assert_eq!(copied, true); + assert_eq!(ba, [2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0]); + let mut small_ba: [f32; 3] = [0.0; 3]; + let copied2 = data_dq.update_buffer_array(&mut small_ba); + assert_eq!(copied2, true); + assert_eq!(small_ba, [23.0, 24.0, 25.0]); + let mut full_ba: [f32; 25] = [0.0; 25]; + let copied3 = data_dq.update_buffer_array(&mut full_ba); + assert_eq!(copied2, true); + assert_eq!(full_ba, [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0]); + let mut toobig: [f32; 26] = [0.0; 26]; + let copied4 = data_dq.update_buffer_array(&mut toobig); + assert_eq!(copied4, false); + assert_eq!(toobig, [0.0; 26]); + } +} + |