use std::f32::consts::TAU;
use super::config::{BinauralPreset, NoiseConfig};
use super::generator::NoiseGenerator;
use super::{NoiseError, NoiseResult};
#[derive(Debug)]
pub struct BinauralGenerator {
generator: NoiseGenerator,
frequency_offset: f32,
carrier_freq: f32,
phase_l: f32,
phase_r: f32,
sample_rate: f32,
}
impl BinauralGenerator {
pub fn new(config: NoiseConfig, frequency_offset: f32) -> NoiseResult<Self> {
let sample_rate = config.sample_rate as f32;
let generator = NoiseGenerator::new(config)?;
Ok(Self {
generator,
frequency_offset: frequency_offset.abs(),
carrier_freq: 200.0, phase_l: 0.0,
phase_r: 0.0,
sample_rate,
})
}
pub fn from_preset(config: NoiseConfig, preset: BinauralPreset) -> NoiseResult<Self> {
Self::new(config, preset.frequency())
}
pub fn generate_stereo(
&mut self,
output_l: &mut [f32],
output_r: &mut [f32],
) -> NoiseResult<()> {
if output_l.len() != output_r.len() {
return Err(NoiseError::BufferSizeMismatch {
expected: output_l.len(),
actual: output_r.len(),
});
}
let buffer_size = self.generator.config().buffer_size;
if output_l.len() != buffer_size {
return Err(NoiseError::BufferSizeMismatch {
expected: buffer_size,
actual: output_l.len(),
});
}
let mut mono_buffer = vec![0.0; buffer_size];
self.generator.generate(&mut mono_buffer)?;
let freq_l = self.carrier_freq;
let freq_r = self.carrier_freq + self.frequency_offset;
let phase_inc_l = TAU * freq_l / self.sample_rate;
let phase_inc_r = TAU * freq_r / self.sample_rate;
let mod_depth = 0.1;
for i in 0..buffer_size {
let noise_sample = mono_buffer[i];
let mod_l = 1.0 + mod_depth * self.phase_l.sin();
output_l[i] = (noise_sample * mod_l).clamp(-1.0, 1.0);
let mod_r = 1.0 + mod_depth * self.phase_r.sin();
output_r[i] = (noise_sample * mod_r).clamp(-1.0, 1.0);
self.phase_l += phase_inc_l;
self.phase_r += phase_inc_r;
if self.phase_l > TAU {
self.phase_l -= TAU;
}
if self.phase_r > TAU {
self.phase_r -= TAU;
}
}
Ok(())
}
pub fn generate_interleaved(&mut self, output: &mut [f32]) -> NoiseResult<()> {
let buffer_size = self.generator.config().buffer_size;
if output.len() != buffer_size * 2 {
return Err(NoiseError::BufferSizeMismatch {
expected: buffer_size * 2,
actual: output.len(),
});
}
let mut left = vec![0.0; buffer_size];
let mut right = vec![0.0; buffer_size];
self.generate_stereo(&mut left, &mut right)?;
for i in 0..buffer_size {
output[i * 2] = left[i];
output[i * 2 + 1] = right[i];
}
Ok(())
}
pub fn set_frequency_offset(&mut self, hz: f32) {
self.frequency_offset = hz.abs();
}
#[must_use]
pub fn frequency_offset(&self) -> f32 {
self.frequency_offset
}
pub fn update_config(&mut self, config: NoiseConfig) -> NoiseResult<()> {
self.sample_rate = config.sample_rate as f32;
self.generator.update_config(config)
}
#[must_use]
pub fn config(&self) -> &NoiseConfig {
self.generator.config()
}
pub fn reset(&mut self) {
self.generator.reset();
self.phase_l = 0.0;
self.phase_r = 0.0;
}
#[must_use]
pub fn time(&self) -> f64 {
self.generator.time()
}
}
#[cfg(test)]
#[path = "binaural_tests.rs"]
mod tests;