1#[macro_export]
28macro_rules! wf {
29 ($sample_type:ty, $sample_rate:expr) => {
30 $crate::Waveform::<$sample_type>::new($sample_rate)
31 };
32 ($sample_type:ty, $sample_rate:expr, $($comp:expr),+ $(,)?) => {
33 {
34 extern crate alloc;
35 let __wf = $crate::Waveform::<$sample_type>::with_components($sample_rate, alloc::vec![$($comp,)+]);
36
37 __wf
38 }
39 };
40}
41
42#[macro_export]
58macro_rules! dc_bias {
59 ($bias:expr) => {
60 $crate::PeriodicFunction::dc_bias($bias)
61 };
62}
63
64#[macro_export]
76macro_rules! sawtooth {
77 ($frequency:expr) => {
78 $crate::sawtooth!($frequency, 1.0, 0.0)
79 };
80 (frequency: $frequency:expr) => {
81 $crate::sawtooth!($frequency)
82 };
83 ($frequency:expr, $amplitude:expr) => {
84 $crate::sawtooth!($frequency, $amplitude, 0.0)
85 };
86 (frequency: $frequency:expr, amplitude: $amplitude:expr) => {
87 $crate::sawtooth!($frequency, $amplitude)
88 };
89 (frequency: $frequency:expr, amplitude: $amplitude:expr, phase: $phase:expr) => {
90 $crate::sawtooth!($frequency, $amplitude, 0.0)
91 };
92 ($frequency:expr, $amplitude:expr, $phase:expr) => {
93 $crate::PeriodicFunction::sawtooth($frequency, $amplitude, $phase)
94 };
95}
96
97#[macro_export]
126macro_rules! sine {
127 (frequency: $frequency:expr) => {
128 $crate::sine!($frequency)
129 };
130 (frequency: $frequency:expr, amplitude: $amplitude:expr) => {
131 $crate::sine!($frequency, $amplitude)
132 };
133 (frequency: $frequency:expr, amplitude: $amplitude:expr, phase: $phase:expr) => {
134 $crate::sine!($frequency, $amplitude, $phase)
135 };
136 ($frequency:expr) => {
137 $crate::sine!($frequency, 1.0, 0.0)
138 };
139 ($frequency:expr, $amplitude:expr) => {
140 $crate::sine!($frequency, $amplitude, 0.0)
141 };
142 ($frequency:expr, $amplitude:expr, $phase:expr) => {
143 $crate::PeriodicFunction::sine($frequency, $amplitude, $phase)
144 };
145}
146
147#[macro_export]
159macro_rules! square {
160 (frequency: $frequency:expr) => {
161 $crate::square!($frequency)
162 };
163 (frequency: $frequency:expr, amplitude: $amplitude:expr) => {
164 $crate::square!($frequency, $amplitude)
165 };
166 (frequency: $frequency:expr, amplitude: $amplitude:expr, phase: $phase:expr) => {
167 $crate::square!($frequency, $amplitude, 0.0)
168 };
169 ($frequency:expr) => {
170 $crate::square!($frequency, 1.0, 0.0)
171 };
172 ($frequency:expr, $amplitude:expr) => {
173 $crate::square!($frequency, $amplitude, 0.0)
174 };
175 ($frequency:expr, $amplitude:expr, $phase:expr) => {
176 $crate::PeriodicFunction::square($frequency, $amplitude, $phase)
177 };
178}
179
180#[cfg(test)]
181mod tests {
182 use float_cmp::approx_eq;
183
184 use crate::PeriodicFunction;
185
186 const EPS: f64 = 1e-3;
187
188 #[test]
189 fn empty_waveform_has_zero_components() {
190 let wf = wf!(f64, 44100.);
191 assert_eq!(0, wf.components().len());
192 }
193
194 #[test]
195 fn wavefrom_with_one_component() {
196 let wf = wf!(f64, 44100., sine!(500.));
197 assert_eq!(1, wf.components().len());
198 }
199 #[test]
200 fn wavefrom_with_three_components() {
201 let wf = wf!(f64, 44100., sine!(500.), square!(1000.), sawtooth!(1500.));
202 assert_eq!(3, wf.components().len());
203 }
204
205 #[test]
206 fn dc_bias_is_const_for_any_input() {
207 let y = 42.0;
208 let dc: PeriodicFunction<f64> = dc_bias!(y);
209 for x in (0..10000000).map(|x| x.into()) {
210 assert_eq!(dc.sample(x), y);
211 }
212 }
213
214 #[test]
215 fn default_sawtooth_has_amplitude_of_one() {
216 let f = sawtooth!(2.0);
217
218 assert!(approx_eq!(f64, f.sample(0.49999), 1.0, epsilon = EPS));
219 assert!(approx_eq!(f64, f.sample(0.5), -1.0, epsilon = EPS));
220 }
221
222 #[test]
223 fn default_sine_has_amplitude_of_one_and_no_phase_shift() {
224 let sine = sine!(1);
225
226 let max = sine.sample(0.25);
227 let min = sine.sample(0.75);
228 let zero = sine.sample(0.5);
229
230 assert!(approx_eq!(f64, max, 1.0, epsilon = EPS));
231 assert!(approx_eq!(f64, min, -1.0, epsilon = EPS));
232 assert!(approx_eq!(f64, zero, 0.0, epsilon = EPS));
233 }
234
235 #[test]
236 fn sine_phase_affects_min_max_amplitude_position() {
237 let sine = sine!(1, 1, 0.5);
238
239 let max = sine.sample(0.75);
240 let min = sine.sample(0.25);
241 let zero = sine.sample(0.5);
242
243 assert!(approx_eq!(f64, max, 1.0, epsilon = EPS));
244 assert!(approx_eq!(f64, min, -1.0, epsilon = EPS));
245 assert!(approx_eq!(f64, zero, 0.0, epsilon = EPS));
246 }
247
248 #[test]
249 fn default_square_has_amplitude_of_one() {
250 let square = square!(1);
251
252 for x in [0.0, 0.1, 0.2, 0.3, 0.4] {
253 assert!(approx_eq!(f64, square.sample(x), 1.0, epsilon = EPS))
254 }
255
256 for x in [0.5, 0.6, 0.7, 0.8, 0.9] {
257 assert!(approx_eq!(f64, square.sample(x), -1.0, epsilon = EPS))
258 }
259 }
260}