use num_complex::Complex32 as C32;
use crate::core::{Block, WorkReport};
use crate::dsp::{Nco, mix_with_nco};
#[derive(Debug, Clone)]
pub struct AmDsbMod {
nco: Nco,
modulation_index: f32,
carrier_level: f32,
clamp: bool,
gain: f32,
}
impl AmDsbMod {
pub fn new(sample_rate: f32, carrier_hz: f32, modulation_index: f32, carrier_level: f32) -> Self {
Self {
nco: Nco::new(carrier_hz, sample_rate),
modulation_index,
carrier_level,
clamp: true,
gain: 1.0,
}
}
pub fn set_gain(&mut self, g: f32) { self.gain = g; }
pub fn set_modulation_index(&mut self, m: f32) { self.modulation_index = m; }
pub fn set_carrier_level(&mut self, c: f32) { self.carrier_level = c; }
pub fn set_limiter(&mut self, on: bool) { self.clamp = on; }
}
impl Block for AmDsbMod {
type In = f32; type Out = C32;
fn process(&mut self, input: &[Self::In], output: &mut [Self::Out]) -> WorkReport {
let n = input.len().min(output.len());
for i in 0..n {
let m = self.carrier_level + self.modulation_index * input[i];
let a = if self.clamp { m.clamp(-1.0, 1.0) } else { m };
let base = C32::new(a * self.gain, 0.0);
output[i] = mix_with_nco(base, &mut self.nco);
}
WorkReport { in_read: n, out_written: n }
}
}