use crate::{Wave, WaveIterator};
use alloc::vec::Vec;
use core::{
iter::{IntoIterator, Iterator},
marker::PhantomData,
};
use num_traits::{AsPrimitive, Bounded, NumCast};
#[derive(Debug, Clone)]
pub struct Waveform<BitDepth: Clone> {
sample_rate: f32,
components: Vec<Wave>,
_marker: PhantomData<BitDepth>,
}
impl<BitDepth: Clone> Waveform<BitDepth> {
pub fn new(sample_rate: f32) -> Self {
Self {
sample_rate,
components: Vec::new(),
_marker: PhantomData,
}
}
pub fn with_wave(sample_rate: f32, wave: Wave) -> Self {
Self::new(sample_rate).superpose(wave).clone()
}
pub fn superpose(&mut self, wave: Wave) -> &mut Self {
self.components.push(Wave {
sample_rate: self.sample_rate,
..wave
});
self
}
pub fn normalize_amplitudes(&mut self) -> &mut Self {
let amp_ratio = 1.0 / self.components.len() as f32;
self.components
.iter_mut()
.for_each(|c| c.amplitude = amp_ratio);
self
}
pub fn iter(&self) -> WaveformIterator<BitDepth> {
WaveformIterator {
_inner: self,
iters: self.components.iter().map(|c| c.iter()).collect(),
}
}
}
impl<'a, BitDepth: Bounded + NumCast + AsPrimitive<f32>> IntoIterator for &'a Waveform<BitDepth> {
type Item = BitDepth;
type IntoIter = WaveformIterator<'a, BitDepth>;
fn into_iter(self) -> Self::IntoIter {
WaveformIterator {
_inner: self,
iters: self.components.iter().map(|c| c.iter()).collect(),
}
}
}
#[derive(Debug, Clone)]
pub struct WaveformIterator<'a, BitDepth: Clone> {
_inner: &'a Waveform<BitDepth>,
iters: Vec<WaveIterator<'a>>,
}
impl<'a, BitDepth: Bounded + NumCast + AsPrimitive<f32>> Iterator
for WaveformIterator<'a, BitDepth>
{
type Item = BitDepth;
fn next(&mut self) -> Option<Self::Item> {
let superposition: f32 = self
.iters
.iter_mut()
.map(|x| x.next().expect("waves are infinite"))
.sum();
NumCast::from(superposition * BitDepth::max_value().as_())
}
}
#[cfg(test)]
mod tests {
use super::*;
use core::i16;
#[test]
fn test_waveform_single_wave_match() {
let w3khz = Wave {
sample_rate: 44100.0,
frequency: 3000.0,
..Default::default()
};
let wf = Waveform::<i16>::with_wave(44100.0, w3khz);
let w1: Vec<i16> = wf.iter().take(100).collect();
let w2: Vec<i16> = w3khz
.iter()
.take(100)
.map(|c| (c * i16::MAX as f32) as i16)
.collect();
assert_eq!(w1, w2);
}
#[test]
fn test_waveform_empty_zeros() {
let wf = Waveform::<i8>::new(44100.0);
let v: Vec<i8> = wf.iter().take(10).collect();
assert_eq!(v, [0i8; 10]);
}
#[test]
fn test_waveform_iteration() {
let wf = Waveform::<i8>::new(44100.0);
let mut itr = wf.into_iter();
assert_eq!(itr.next().unwrap(), 0);
}
#[test]
fn test_waveform_construct() {
let wf1 = Waveform::<i16>::with_wave(
44100.0,
Wave {
frequency: 3400.0,
amplitude: 1.0,
..Default::default()
},
);
let mut wf2 = Waveform::<i16>::new(44100.0);
let v1: Vec<i16> = wf1.iter().take(100).collect();
let v2: Vec<i16> = wf2
.superpose(Wave {
frequency: 3400.0,
..Default::default()
})
.iter()
.take(100)
.collect();
assert_eq!(v1, v2);
}
#[test]
fn test_waveform_amplitude_normalization() {
let mut wf = Waveform::<i16>::with_wave(
44100.0,
Wave {
frequency: 4000.0,
amplitude: 1.5,
..Default::default()
},
);
wf.superpose(Wave {
frequency: 5000.0,
amplitude: 0.5,
..Default::default()
})
.normalize_amplitudes();
wf.components
.iter()
.for_each(|c| assert_eq!(c.amplitude, 0.5));
}
#[test]
fn test_waveform_iterator_halt_numerical_instability() {
let mut wf = Waveform::<i16>::with_wave(
44100.0,
Wave {
frequency: 4000.0,
amplitude: 1.0,
..Default::default()
},
);
let v: Vec<i16> = wf
.superpose(Wave {
frequency: 5000.0,
amplitude: 0.5,
..Default::default()
})
.iter()
.take(100)
.collect();
assert_ne!(v.len(), 100);
}
}