1use arrayvec::ArrayVec;
2
3pub fn linear_resample<const N: usize>(input: &[f32], output: &mut ArrayVec<f32, N>) {
4 let input_len = input.len();
5 let output_len = output.len();
6 let scale = (input_len - 1) as f32 / (output_len - 1) as f32;
7
8 for i in 0..output_len {
9 let pos = i as f32 * scale;
10 let pos_floor = pos.floor() as usize;
11 let pos_ceil = pos.ceil() as usize;
12
13 if pos_ceil >= input_len {
14 output[i] = input[input_len - 1];
15 } else if pos_floor == pos_ceil {
16 output[i] = input[pos_floor];
17 } else {
18 let weight = pos - pos_floor as f32;
19 output[i] = input[pos_floor] * (1.0 - weight) + input[pos_ceil] * weight;
20 }
21 }
22}
23
24pub fn cubic_interpolation(y0: f32, y1: f32, y2: f32, y3: f32, t: f32) -> f32 {
38 let a0 = -0.5 * y0 + 1.5 * y1 - 1.5 * y2 + 0.5 * y3;
39 let a1 = y0 - 2.5 * y1 + 2.0 * y2 - 0.5 * y3;
40 let a2 = -0.5 * y0 + 0.5 * y2;
41 let a3 = y1;
42
43 a0 * t * t * t + a1 * t * t + a2 * t + a3
44}
45
46pub fn cubic_resample<const N: usize>(input: &[f32], output: &mut ArrayVec<f32, N>) {
47 let input_len = input.len();
48 let output_len = output.len();
49 let scale = (input_len - 1) as f32 / (output_len - 1) as f32;
50
51 for i in 0..output_len {
52 let pos = i as f32 * scale;
53 let pos_floor = pos.floor() as usize;
54
55 let y0 = if pos_floor == 0 {
56 input[pos_floor]
57 } else {
58 input[pos_floor - 1]
59 };
60 let y1 = input[pos_floor];
61 let y2 = if pos_floor + 1 < input_len {
62 input[pos_floor + 1]
63 } else {
64 input[input_len - 1]
65 };
66 let y3 = if pos_floor + 2 < input_len {
67 input[pos_floor + 2]
68 } else {
69 input[input_len - 1]
70 };
71
72 let t = pos - pos_floor as f32;
73 output[i] = cubic_interpolation(y0, y1, y2, y3, t);
74 }
75}
76
77