rodio/source/
signal_generator.rs1use super::SeekError;
15use crate::common::{ChannelCount, SampleRate};
16use crate::Source;
17use std::f32::consts::TAU;
18use std::time::Duration;
19
20pub type GeneratorFunction = fn(f32) -> f32;
37
38#[derive(Clone, Debug)]
40pub enum Function {
41 Sine,
43 Triangle,
45 Square,
47 Sawtooth,
49}
50
51fn sine_signal(phase: f32) -> f32 {
52 (TAU * phase).sin()
53}
54
55fn triangle_signal(phase: f32) -> f32 {
56 4.0f32 * (phase - (phase + 0.5f32).floor()).abs() - 1f32
57}
58
59fn square_signal(phase: f32) -> f32 {
60 if phase % 1.0f32 < 0.5f32 {
61 1.0f32
62 } else {
63 -1.0f32
64 }
65}
66
67fn sawtooth_signal(phase: f32) -> f32 {
68 2.0f32 * (phase - (phase + 0.5f32).floor())
69}
70
71#[derive(Clone, Debug)]
73pub struct SignalGenerator {
74 sample_rate: SampleRate,
75 function: GeneratorFunction,
76 phase_step: f32,
77 phase: f32,
78 period: f32,
79}
80
81impl SignalGenerator {
82 #[inline]
89 pub fn new(sample_rate: SampleRate, frequency: f32, f: Function) -> Self {
90 let function: GeneratorFunction = match f {
91 Function::Sine => sine_signal,
92 Function::Triangle => triangle_signal,
93 Function::Square => square_signal,
94 Function::Sawtooth => sawtooth_signal,
95 };
96
97 Self::with_function(sample_rate, frequency, function)
98 }
99
100 #[inline]
107 pub fn with_function(
108 sample_rate: SampleRate,
109 frequency: f32,
110 generator_function: GeneratorFunction,
111 ) -> Self {
112 assert!(frequency != 0.0, "frequency must be greater than zero");
113 let period = sample_rate as f32 / frequency;
114 let phase_step = 1.0f32 / period;
115
116 SignalGenerator {
117 sample_rate,
118 function: generator_function,
119 phase_step,
120 phase: 0.0f32,
121 period,
122 }
123 }
124}
125
126impl Iterator for SignalGenerator {
127 type Item = f32;
128
129 #[inline]
130 fn next(&mut self) -> Option<f32> {
131 let f = self.function;
132 let val = Some(f(self.phase));
133 self.phase = (self.phase + self.phase_step).rem_euclid(1.0f32);
134 val
135 }
136}
137
138impl Source for SignalGenerator {
139 #[inline]
140 fn current_span_len(&self) -> Option<usize> {
141 None
142 }
143
144 #[inline]
145 fn channels(&self) -> ChannelCount {
146 1
147 }
148
149 #[inline]
150 fn sample_rate(&self) -> SampleRate {
151 self.sample_rate
152 }
153
154 #[inline]
155 fn total_duration(&self) -> Option<Duration> {
156 None
157 }
158
159 #[inline]
160 fn try_seek(&mut self, duration: Duration) -> Result<(), SeekError> {
161 let seek = duration.as_secs_f32() * (self.sample_rate as f32) / self.period;
162 self.phase = seek.rem_euclid(1.0f32);
163 Ok(())
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use crate::source::{Function, SignalGenerator};
170 use approx::assert_abs_diff_eq;
171
172 #[test]
173 fn square() {
174 let mut wf = SignalGenerator::new(2000, 500.0f32, Function::Square);
175 assert_eq!(wf.next(), Some(1.0f32));
176 assert_eq!(wf.next(), Some(1.0f32));
177 assert_eq!(wf.next(), Some(-1.0f32));
178 assert_eq!(wf.next(), Some(-1.0f32));
179 assert_eq!(wf.next(), Some(1.0f32));
180 assert_eq!(wf.next(), Some(1.0f32));
181 assert_eq!(wf.next(), Some(-1.0f32));
182 assert_eq!(wf.next(), Some(-1.0f32));
183 }
184
185 #[test]
186 fn triangle() {
187 let mut wf = SignalGenerator::new(8000, 1000.0f32, Function::Triangle);
188 assert_eq!(wf.next(), Some(-1.0f32));
189 assert_eq!(wf.next(), Some(-0.5f32));
190 assert_eq!(wf.next(), Some(0.0f32));
191 assert_eq!(wf.next(), Some(0.5f32));
192 assert_eq!(wf.next(), Some(1.0f32));
193 assert_eq!(wf.next(), Some(0.5f32));
194 assert_eq!(wf.next(), Some(0.0f32));
195 assert_eq!(wf.next(), Some(-0.5f32));
196 assert_eq!(wf.next(), Some(-1.0f32));
197 assert_eq!(wf.next(), Some(-0.5f32));
198 assert_eq!(wf.next(), Some(0.0f32));
199 assert_eq!(wf.next(), Some(0.5f32));
200 assert_eq!(wf.next(), Some(1.0f32));
201 assert_eq!(wf.next(), Some(0.5f32));
202 assert_eq!(wf.next(), Some(0.0f32));
203 assert_eq!(wf.next(), Some(-0.5f32));
204 }
205
206 #[test]
207 fn saw() {
208 let mut wf = SignalGenerator::new(200, 50.0f32, Function::Sawtooth);
209 assert_eq!(wf.next(), Some(0.0f32));
210 assert_eq!(wf.next(), Some(0.5f32));
211 assert_eq!(wf.next(), Some(-1.0f32));
212 assert_eq!(wf.next(), Some(-0.5f32));
213 assert_eq!(wf.next(), Some(0.0f32));
214 assert_eq!(wf.next(), Some(0.5f32));
215 assert_eq!(wf.next(), Some(-1.0f32));
216 }
217
218 #[test]
219 fn sine() {
220 let mut wf = SignalGenerator::new(1000, 100f32, Function::Sine);
221
222 assert_abs_diff_eq!(wf.next().unwrap(), 0.0f32);
223 assert_abs_diff_eq!(wf.next().unwrap(), 0.58778525f32);
224 assert_abs_diff_eq!(wf.next().unwrap(), 0.95105652f32);
225 assert_abs_diff_eq!(wf.next().unwrap(), 0.95105652f32);
226 assert_abs_diff_eq!(wf.next().unwrap(), 0.58778525f32);
227 assert_abs_diff_eq!(wf.next().unwrap(), 0.0f32);
228 assert_abs_diff_eq!(wf.next().unwrap(), -0.58778554f32);
229 }
230}