summaryrefslogtreecommitdiff
path: root/src/proc.rs
diff options
context:
space:
mode:
authorWavy Harp <wavyharp@gmail.com>2023-05-07 23:04:53 -0600
committerKyle McFarland <tfkyle@gmail.com>2023-05-07 23:04:53 -0600
commit991849b32acf83dd14a5096540bb053d2572502a (patch)
tree279b59d75d4ad6081f5242cf77d843ae6b37fc3d /src/proc.rs
downloadrustynotes-master.zip
rustynotes-master.tar.gz
rustynotes-master.tar.bz2
initial importHEADmaster
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.rs162
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]);
+ }
+}
+