summaryrefslogtreecommitdiff
path: root/src/proc.rs
blob: 2b32747e7495e26e894f05eba6b2d5ced334b27d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
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]);
    }
}