use std::f32::consts::PI;
pub struct SineWav {
freq: f32,
sample_rate: u32,
sample_num: u32,
reset_num: u32,
}
impl SineWav {
pub fn new(freq: f32) -> SineWav {
Self::with_sample_rate(freq, 44100)
}
pub fn with_sample_rate(freq: f32, sample_rate: u32) -> SineWav {
let reset_num = sample_rate as f32 / freq;
let cycles = (u32::MAX as f32 / reset_num).floor();
let reset_num = (reset_num * cycles).round() as u32;
SineWav {
freq,
sample_rate,
sample_num: 0,
reset_num,
}
}
}
impl crate::Sound for SineWav {
fn channel_count(&self) -> u16 {
1
}
fn sample_rate(&self) -> u32 {
self.sample_rate
}
fn next_sample(&mut self) -> Result<crate::NextSample, crate::Error> {
let value = 2.0 * self.sample_num as f32 * self.freq * PI / self.sample_rate as f32;
if self.sample_num == self.reset_num {
self.sample_num = 0;
} else {
self.sample_num += 1;
}
Ok(crate::NextSample::Sample(
(value.sin() * i16::MAX as f32) as i16,
))
}
fn on_start_of_batch(&mut self) {}
}
#[cfg(test)]
#[path = "./tests/sine_wav.rs"]
mod tests;