augmented_oscillator/
wavetable.rs1use crate::Oscillator;
24
25pub fn get_cursor_step(frequency: f32, sample_rate: f32, table_len: f32) -> f32 {
29 table_len * frequency / sample_rate
30}
31
32pub fn get_interpolated(cursor: f32, table: &[f32]) -> f32 {
34 let c1 = cursor;
35 let diff = c1 - c1.floor();
36 let c1 = c1 as usize;
37 let mut c2 = c1 + 1;
38 if c2 >= table.len() {
39 c2 = 0;
40 }
41
42 let v1 = table[c1];
43 let v2 = table[c2];
44 v1 + diff * (v2 - v1)
45}
46
47pub struct WaveTableOscillator {
48 cursor: f32,
49 cursor_step: f32,
50 table: Vec<f32>,
51 table_len: f32,
52 sample_rate: f32,
53 frequency: f32,
54}
55
56impl WaveTableOscillator {
57 pub fn from_oscillator(mut oscillator: Oscillator<f32>, table_len: usize) -> Self {
58 let frequency = oscillator.get_frequency();
59 let sample_rate = oscillator.sample_rate;
60
61 oscillator.set_frequency(sample_rate / table_len as f32);
62
63 let table: Vec<f32> = (0..table_len).map(|_| oscillator.next_sample()).collect();
64
65 let mut result = Self::new(table);
66 result.set_sample_rate(sample_rate);
67 result.set_frequency(frequency);
68 result
69 }
70
71 pub fn new(table: Vec<f32>) -> Self {
72 let frequency = 440.0;
73 let sample_rate = 44100.0;
74 Self {
75 cursor: 0.0,
76 cursor_step: get_cursor_step(frequency, sample_rate, table.len() as f32),
77 sample_rate,
78 frequency,
79 table_len: table.len() as f32,
80 table,
81 }
82 }
83
84 pub fn frequency(&self) -> f32 {
85 self.frequency
86 }
87
88 pub fn sample_rate(&self) -> f32 {
89 self.sample_rate
90 }
91
92 pub fn table(&self) -> &[f32] {
93 &self.table
94 }
95
96 pub fn table_mut(&mut self) -> &mut [f32] {
97 &mut self.table
98 }
99
100 pub fn set_sample_rate(&mut self, value: f32) {
101 self.sample_rate = value;
102 self.update();
103 }
104
105 pub fn set_frequency(&mut self, value: f32) {
106 self.frequency = value;
107 self.update();
108 }
109
110 fn update(&mut self) {
111 let frequency = self.frequency;
112 let sample_rate = self.sample_rate;
113 let table_len = self.table_len;
114 let cursor_step = get_cursor_step(frequency, sample_rate, table_len);
115 self.cursor_step = cursor_step
116 }
117
118 pub fn tick(&mut self) {
119 let cursor = &mut self.cursor;
120 *cursor += self.cursor_step;
121 while *cursor >= self.table_len {
122 *cursor -= self.table_len;
123 }
124 }
125
126 pub fn tick_n(&mut self, samples: f32) {
127 let cursor = &mut self.cursor;
128 *cursor += self.cursor_step * samples;
129 while *cursor >= self.table_len {
130 *cursor -= self.table_len;
131 }
132 }
133
134 pub fn get(&self) -> f32 {
135 let cursor = self.cursor;
136 let table = &self.table;
137
138 get_interpolated(cursor, table)
139 }
140
141 pub fn next_sample(&mut self) -> f32 {
142 let result = self.get();
143 self.tick();
144 result
145 }
146}
147
148#[cfg(test)]
149mod test {
150 use crate::test_utils::generate_plot;
151
152 use super::*;
153
154 #[test]
155 fn test_get_cursor_step() {
156 let step = get_cursor_step(220.0, 44100.0, 512.0);
157 assert!((step - 2.554_195).abs() < f32::EPSILON);
158 }
159
160 #[test]
161 fn test_generate_plots() {
162 let root_path = format!("{}/src/wavetable.rs", env!("CARGO_MANIFEST_DIR"));
163 let mut oscillator = Oscillator::sine(44100.0);
164 oscillator.set_frequency(440.0);
165 let mut wave_table = WaveTableOscillator::from_oscillator(oscillator.clone(), 1000);
166
167 generate_plot(&root_path, || wave_table.next_sample(), "wave_table");
168 generate_plot(&root_path, || oscillator.next_sample(), "sine_oscillator");
169 }
170
171 #[test]
172 fn test_cursor_step_is_properly_set() {
173 let mut oscillator = Oscillator::sine(44100.0);
174 oscillator.set_frequency(440.0);
175 let mut wave_table = WaveTableOscillator::from_oscillator(oscillator.clone(), 1000);
176 wave_table.set_sample_rate(44100.0);
177 wave_table.set_frequency(440.0);
178 assert!((wave_table.cursor - 0.0).abs() < f32::EPSILON);
179 assert!((wave_table.frequency - 440.0).abs() < f32::EPSILON);
180 assert!((wave_table.sample_rate - 44100.0).abs() < f32::EPSILON);
181
182 let cursor_step = wave_table.cursor_step;
183 assert!(
184 (cursor_step - 9.977_324_5_f32).abs() < f32::EPSILON,
185 "{}",
186 cursor_step
187 );
188 }
189
190 #[test]
191 fn test_smoke_test_wave_table_error() {
192 let mut oscillator = Oscillator::sine(44100.0);
193 oscillator.set_frequency(440.0);
194 let mut wave_table = WaveTableOscillator::from_oscillator(oscillator.clone(), 4000);
195 wave_table.set_sample_rate(44100.0);
196 wave_table.set_frequency(440.0);
197 let oscillator_result: Vec<f32> = (0..44100).map(|_| oscillator.next_sample()).collect();
198 let wave_table_result: Vec<f32> = (0..44100).map(|_| wave_table.next_sample()).collect();
199 for (o, w) in oscillator_result.iter().zip(wave_table_result.iter()) {
200 assert!((o - w).abs() < 0.01)
201 }
202 }
203}