use serde::{Deserialize, Serialize};
use super::core::{Oscillator, Waveform};
use crate::error::Result;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HardSync {
master: Oscillator,
slave: Oscillator,
}
impl HardSync {
pub fn new(
master_freq: f32,
slave_freq: f32,
slave_waveform: Waveform,
sample_rate: f32,
) -> Result<Self> {
let master = Oscillator::new(Waveform::Saw, master_freq, sample_rate)?;
let slave = Oscillator::new(slave_waveform, slave_freq, sample_rate)?;
Ok(Self { master, slave })
}
#[inline]
#[must_use]
pub fn next_sample(&mut self) -> f32 {
let master_phase_before = self.master.phase();
let _ = self.master.next_sample();
let master_phase_after = self.master.phase();
if master_phase_after < master_phase_before {
self.slave.reset_phase();
}
self.slave.next_sample()
}
#[inline]
pub fn fill_buffer(&mut self, buffer: &mut [f32]) {
for sample in buffer.iter_mut() {
*sample = self.next_sample();
}
}
#[must_use]
pub fn master(&self) -> &Oscillator {
&self.master
}
#[must_use]
pub fn slave(&self) -> &Oscillator {
&self.slave
}
pub fn set_master_freq(&mut self, freq: f32) -> Result<()> {
self.master.set_frequency(freq)
}
pub fn set_slave_freq(&mut self, freq: f32) -> Result<()> {
self.slave.set_frequency(freq)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hard_sync_resets_slave() {
let mut sync = HardSync::new(440.0, 880.0, Waveform::Saw, 44100.0).unwrap();
let mut buf = [0.0f32; 1024];
sync.fill_buffer(&mut buf);
assert!(buf.iter().all(|s| s.is_finite()));
assert!(buf.iter().any(|&s| s != 0.0));
}
#[test]
fn test_hard_sync_serde_roundtrip() {
let hs = HardSync::new(440.0, 880.0, Waveform::Saw, 44100.0).unwrap();
let json = serde_json::to_string(&hs).unwrap();
let back: HardSync = serde_json::from_str(&json).unwrap();
assert!((hs.master().frequency() - back.master().frequency()).abs() < f32::EPSILON);
}
}