1use super::SeekError;
15use crate::common::{ChannelCount, SampleRate};
16use crate::math::{duration_to_float, nz, TAU};
17use crate::{Float, Sample, Source};
18use std::time::Duration;
19
20pub type GeneratorFunction = fn(Float) -> Sample;
37
38#[derive(Clone, Debug)]
40pub enum Function {
41 Sine,
43 Triangle,
45 Square,
47 Sawtooth,
49}
50
51fn sine_signal(phase: Float) -> Sample {
52 (TAU * phase).sin()
53}
54
55fn triangle_signal(phase: Float) -> Sample {
56 4.0 * (phase - (phase + 0.5).floor()).abs() - 1.0
57}
58
59fn square_signal(phase: Float) -> Sample {
60 if phase % 1.0 < 0.5 {
61 1.0
62 } else {
63 -1.0
64 }
65}
66
67fn sawtooth_signal(phase: Float) -> Sample {
68 2.0 * (phase - (phase + 0.5).floor())
69}
70
71#[derive(Clone, Debug)]
73pub struct SignalGenerator {
74 sample_rate: SampleRate,
75 function: GeneratorFunction,
76 phase_step: Float,
77 phase: Float,
78 period: Float,
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.get() as Float / frequency as Float;
114 let phase_step = 1.0 / period;
115
116 SignalGenerator {
117 sample_rate,
118 function: generator_function,
119 phase_step,
120 phase: 0.0,
121 period,
122 }
123 }
124}
125
126impl Iterator for SignalGenerator {
127 type Item = Sample;
128
129 #[inline]
130 fn next(&mut self) -> Option<Sample> {
131 let f = self.function;
132 let val = Some(f(self.phase));
133 self.phase = (self.phase + self.phase_step).rem_euclid(1.0);
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 nz!(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_to_float(duration) * (self.sample_rate.get() as Float) / self.period;
162 self.phase = seek.rem_euclid(1.0);
163 Ok(())
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use crate::math::nz;
170 use crate::source::{Function, SignalGenerator};
171 use crate::Sample;
172 use approx::assert_abs_diff_eq;
173
174 const TEST_EPSILON: Sample = 0.0001;
175
176 #[test]
177 fn square() {
178 let mut wf = SignalGenerator::new(nz!(2000), 500.0, Function::Square);
179 assert_eq!(wf.next(), Some(1.0));
180 assert_eq!(wf.next(), Some(1.0));
181 assert_eq!(wf.next(), Some(-1.0));
182 assert_eq!(wf.next(), Some(-1.0));
183 assert_eq!(wf.next(), Some(1.0));
184 assert_eq!(wf.next(), Some(1.0));
185 assert_eq!(wf.next(), Some(-1.0));
186 assert_eq!(wf.next(), Some(-1.0));
187 }
188
189 #[test]
190 fn triangle() {
191 let mut wf = SignalGenerator::new(nz!(8000), 1000.0, Function::Triangle);
192 assert_eq!(wf.next(), Some(-1.0));
193 assert_eq!(wf.next(), Some(-0.5));
194 assert_eq!(wf.next(), Some(0.0));
195 assert_eq!(wf.next(), Some(0.5));
196 assert_eq!(wf.next(), Some(1.0));
197 assert_eq!(wf.next(), Some(0.5));
198 assert_eq!(wf.next(), Some(0.0));
199 assert_eq!(wf.next(), Some(-0.5));
200 assert_eq!(wf.next(), Some(-1.0));
201 assert_eq!(wf.next(), Some(-0.5));
202 assert_eq!(wf.next(), Some(0.0));
203 assert_eq!(wf.next(), Some(0.5));
204 assert_eq!(wf.next(), Some(1.0));
205 assert_eq!(wf.next(), Some(0.5));
206 assert_eq!(wf.next(), Some(0.0));
207 assert_eq!(wf.next(), Some(-0.5));
208 }
209
210 #[test]
211 fn saw() {
212 let mut wf = SignalGenerator::new(nz!(200), 50.0, Function::Sawtooth);
213 assert_eq!(wf.next(), Some(0.0));
214 assert_eq!(wf.next(), Some(0.5));
215 assert_eq!(wf.next(), Some(-1.0));
216 assert_eq!(wf.next(), Some(-0.5));
217 assert_eq!(wf.next(), Some(0.0));
218 assert_eq!(wf.next(), Some(0.5));
219 assert_eq!(wf.next(), Some(-1.0));
220 }
221
222 #[test]
223 fn sine() {
224 let mut wf = SignalGenerator::new(nz!(1000), 100f32, Function::Sine);
225
226 assert_abs_diff_eq!(wf.next().unwrap(), 0.0, epsilon = TEST_EPSILON);
227 assert_abs_diff_eq!(wf.next().unwrap(), 0.58778525, epsilon = TEST_EPSILON);
228 assert_abs_diff_eq!(wf.next().unwrap(), 0.95105652, epsilon = TEST_EPSILON);
229 assert_abs_diff_eq!(wf.next().unwrap(), 0.95105652, epsilon = TEST_EPSILON);
230 assert_abs_diff_eq!(wf.next().unwrap(), 0.58778525, epsilon = TEST_EPSILON);
231 assert_abs_diff_eq!(wf.next().unwrap(), 0.0, epsilon = TEST_EPSILON);
232 assert_abs_diff_eq!(wf.next().unwrap(), -0.58778554, epsilon = TEST_EPSILON);
233 }
234}