use crate::building_blocks::{
Modulator, MonoSource, SampleBuffer, SynthParameterLabel, SynthParameterValue,
};
use std::f32::consts::PI;
#[derive(Clone)]
pub struct SineOsc<const BUFSIZE: usize> {
freq: f32,
amp: f32,
amp_buf: [f32; BUFSIZE],
samplerate: f32,
delta_t: f32,
x1_last: f32, x2_last: f32, mcf_buf: [f32; BUFSIZE],
freq_mod: Option<Modulator<BUFSIZE>>, amp_mod: Option<Modulator<BUFSIZE>>, }
impl<const BUFSIZE: usize> SineOsc<BUFSIZE> {
pub fn new(freq: f32, amp: f32, sr: f32) -> Self {
SineOsc {
freq,
amp,
amp_buf: [amp; BUFSIZE],
delta_t: 1.0 / sr,
samplerate: sr,
x1_last: ((-2.0 * PI * freq) / sr).cos(),
x2_last: ((-2.0 * PI * freq) / sr).sin(),
mcf_buf: [-2.0 * (PI * (freq / sr)).sin(); BUFSIZE],
freq_mod: None,
amp_mod: None,
}
}
}
impl<const BUFSIZE: usize> MonoSource<BUFSIZE> for SineOsc<BUFSIZE> {
fn reset(&mut self) {}
fn set_modulator(
&mut self,
par: SynthParameterLabel,
init: f32,
modulator: Modulator<BUFSIZE>,
) {
match par {
SynthParameterLabel::PitchFrequency => {
self.freq = init;
self.freq_mod = Some(modulator);
}
SynthParameterLabel::OscillatorAmplitude => {
self.amp = init;
self.amp_mod = Some(modulator);
}
_ => {}
}
}
fn set_parameter(&mut self, par: SynthParameterLabel, value: &SynthParameterValue) {
match par {
SynthParameterLabel::OscillatorPhaseRelative => {
if let SynthParameterValue::ScalarF32(p) = value {
self.x1_last = ((-2.0 * PI * self.freq / self.samplerate) + (p * PI)).cos();
self.x2_last = ((-2.0 * PI * self.freq / self.samplerate) + (p * PI)).sin();
}
}
SynthParameterLabel::OscillatorPhaseEffective => {
if let SynthParameterValue::ScalarF32(p) = value {
self.x1_last =
((-2.0 * PI * self.freq / self.samplerate) + (p / self.amp)).cos();
self.x2_last =
((-2.0 * PI * self.freq / self.samplerate) + (p / self.amp)).sin();
}
}
SynthParameterLabel::PitchFrequency => {
if let SynthParameterValue::ScalarF32(f) = value {
self.freq = *f;
self.x1_last = ((-2.0 * PI * self.freq) / self.samplerate).cos();
self.x2_last = ((-2.0 * PI * self.freq) / self.samplerate).sin();
self.mcf_buf = [-2.0 * (PI * (self.freq / self.samplerate)).sin(); BUFSIZE];
}
}
SynthParameterLabel::OscillatorAmplitude => {
if let SynthParameterValue::ScalarF32(l) = value {
self.amp = *l;
self.amp_buf = [self.amp; BUFSIZE];
}
}
_ => (),
};
}
fn finish(&mut self) {
}
fn is_finished(&self) -> bool {
false
}
fn get_next_block(
&mut self,
start_sample: usize,
in_buffers: &[SampleBuffer],
) -> [f32; BUFSIZE] {
let mut out_buf: [f32; BUFSIZE] = [0.0; BUFSIZE];
if let Some(fm) = self.freq_mod.as_mut() {
self.mcf_buf = fm
.process(self.freq, start_sample, in_buffers)
.map(|f| -2.0 * (PI * f * self.delta_t).sin());
}
if let Some(am) = self.amp_mod.as_mut() {
self.amp_buf = am.process(self.amp, start_sample, in_buffers);
}
for (idx, current_sample) in out_buf
.iter_mut()
.enumerate()
.take(BUFSIZE)
.skip(start_sample)
{
let x1 = self.x1_last + (self.mcf_buf[idx] * self.x2_last);
let x2 = -self.mcf_buf[idx] * x1 + self.x2_last;
*current_sample = x2 * self.amp_buf[idx];
self.x1_last = x1;
self.x2_last = x2;
}
out_buf
}
}