pitch_detection/utils/
buffer.rs1use rustfft::num_complex::Complex;
2use rustfft::num_traits::Zero;
3use std::{cell::RefCell, rc::Rc};
4
5use crate::float::Float;
6
7pub enum ComplexComponent {
8 Re,
9 Im,
10}
11
12pub fn new_real_buffer<T: Float>(size: usize) -> Vec<T> {
13 vec![T::zero(); size]
14}
15
16pub fn new_complex_buffer<T: Float>(size: usize) -> Vec<Complex<T>> {
17 vec![Complex::zero(); size]
18}
19
20pub fn copy_real_to_complex<T: Float>(
21 input: &[T],
22 output: &mut [Complex<T>],
23 component: ComplexComponent,
24) {
25 assert!(input.len() <= output.len());
26 match component {
27 ComplexComponent::Re => input.iter().zip(output.iter_mut()).for_each(|(i, o)| {
28 o.re = *i;
29 o.im = T::zero();
30 }),
31 ComplexComponent::Im => input.iter().zip(output.iter_mut()).for_each(|(i, o)| {
32 o.im = *i;
33 o.re = T::zero();
34 }),
35 }
36 output[input.len()..]
37 .iter_mut()
38 .for_each(|o| *o = Complex::zero())
39}
40
41pub fn copy_complex_to_real<T: Float>(
42 input: &[Complex<T>],
43 output: &mut [T],
44 component: ComplexComponent,
45) {
46 assert!(input.len() <= output.len());
47 match component {
48 ComplexComponent::Re => input
49 .iter()
50 .map(|c| c.re)
51 .zip(output.iter_mut())
52 .for_each(|(i, o)| *o = i),
53 ComplexComponent::Im => input
54 .iter()
55 .map(|c| c.im)
56 .zip(output.iter_mut())
57 .for_each(|(i, o)| *o = i),
58 }
59
60 output[input.len()..]
61 .iter_mut()
62 .for_each(|o| *o = T::zero());
63}
64
65pub fn modulus_squared<'a, T: Float>(arr: &'a mut [Complex<T>]) {
68 for mut s in arr {
69 s.re = s.re * s.re + s.im * s.im;
70 s.im = T::zero();
71 }
72}
73
74pub fn square_sum<T>(arr: &[T]) -> T
76where
77 T: Float + std::iter::Sum,
78{
79 arr.iter().map(|&s| s * s).sum::<T>()
80}
81
82#[derive(Debug)]
83pub struct BufferPool<T> {
117 real_buffers: Vec<Rc<RefCell<Vec<T>>>>,
118 complex_buffers: Vec<Rc<RefCell<Vec<Complex<T>>>>>,
119 pub buffer_size: usize,
120}
121
122impl<T: Float> BufferPool<T> {
123 pub fn new(buffer_size: usize) -> Self {
124 BufferPool {
125 real_buffers: vec![],
126 complex_buffers: vec![],
127 buffer_size,
128 }
129 }
130 fn add_real_buffer(&mut self) -> Rc<RefCell<Vec<T>>> {
131 self.real_buffers
132 .push(Rc::new(RefCell::new(new_real_buffer::<T>(
133 self.buffer_size,
134 ))));
135 Rc::clone(&self.real_buffers.last().unwrap())
136 }
137 fn add_complex_buffer(&mut self) -> Rc<RefCell<Vec<Complex<T>>>> {
138 self.complex_buffers
139 .push(Rc::new(RefCell::new(new_complex_buffer::<T>(
140 self.buffer_size,
141 ))));
142 Rc::clone(&self.complex_buffers.last().unwrap())
143 }
144 pub fn get_real_buffer(&mut self) -> Rc<RefCell<Vec<T>>> {
147 self.real_buffers
148 .iter()
149 .find(|&buf| Rc::strong_count(buf) == 1)
151 .map(|buf| Rc::clone(buf))
152 .unwrap_or_else(|| self.add_real_buffer())
154 }
155 pub fn get_complex_buffer(&mut self) -> Rc<RefCell<Vec<Complex<T>>>> {
158 self.complex_buffers
159 .iter()
160 .find(|&buf| Rc::strong_count(buf) == 1)
162 .map(|buf| Rc::clone(buf))
163 .unwrap_or_else(|| self.add_complex_buffer())
165 }
166}
167
168#[test]
169fn test_buffers() {
170 let mut buffers = BufferPool::new(3);
171 let buf_cell1 = buffers.get_real_buffer();
172 {
173 let mut buf1 = buf_cell1.borrow_mut();
175 buf1[0] = 5.5;
176 }
177 {
178 let buf_cell2 = buffers.get_real_buffer();
180 let mut buf2 = buf_cell2.borrow_mut();
181 buf2[1] = 6.6;
182 }
183 {
184 let buf_cell3 = buffers.get_real_buffer();
187 let mut buf3 = buf_cell3.borrow_mut();
188 buf3[2] = 7.7;
189 }
190 assert_eq!(&buffers.real_buffers[0].borrow()[..], &[5.5, 0., 0.]);
192 assert_eq!(&buffers.real_buffers[1].borrow()[..], &[0.0, 6.6, 7.7]);
193}