use super::config::*;
use super::filter::Filter;
use dasp_sample::{ FromSample, Sample };
use rayon::prelude::*;
use std::fmt::Debug;
use std::iter::ExactSizeIterator;
use std::slice::IterMut;
use rand::prelude::*;
use rand::rngs::ThreadRng;
use rand_distr::StandardNormal;
const twopi: Flt = 2.0 * pi;
pub trait Source: Send {
fn genSignal_unscaled(&mut self, sig: &mut dyn ExactSizeIterator<Item = &mut Flt>);
fn reset(&mut self, fs: Flt);
fn clone_dyn(&self) -> Box<dyn Source>;
}
impl Clone for Box<dyn Source> {
fn clone(&self) -> Self {
self.clone_dyn()
}
}
#[derive(Clone)]
struct Silence {}
impl Source for Silence {
fn genSignal_unscaled(&mut self, sig: &mut dyn ExactSizeIterator<Item = &mut Flt>) {
sig.for_each(|s| {
*s = 0.0;
});
}
fn reset(&mut self, _fs: Flt) {}
fn clone_dyn(&self) -> Box<dyn Source> {
Box::new(self.clone())
}
}
#[derive(Clone)]
struct WhiteNoise {}
impl WhiteNoise {
fn new() -> WhiteNoise {
WhiteNoise {}
}
}
impl Source for WhiteNoise {
fn genSignal_unscaled(&mut self, sig: &mut dyn ExactSizeIterator<Item = &mut Flt>) {
sig.for_each(|s| {
*s = thread_rng().sample(StandardNormal);
});
}
fn reset(&mut self, _fs: Flt) {}
fn clone_dyn(&self) -> Box<dyn Source> {
Box::new(self.clone())
}
}
#[derive(Clone)]
struct Sine {
fs: Flt,
phase: Flt,
omg: Flt,
}
impl Sine {
fn new(freq: Flt) -> Sine {
Sine {
fs: -1.0,
phase: 0.0,
omg: 2.0 * pi * freq,
}
}
}
impl Source for Sine {
fn genSignal_unscaled(&mut self, sig: &mut dyn ExactSizeIterator<Item = &mut Flt>) {
if self.fs <= 0.0 {
sig.for_each(|s| {
*s = 0.0;
});
return;
}
sig.for_each(|s| {
*s = Flt::sin(self.phase);
self.phase += self.omg / self.fs;
self.phase %= twopi;
});
}
fn reset(&mut self, fs: Flt) {
self.fs = fs;
self.phase = 0.0;
}
fn clone_dyn(&self) -> Box<dyn Source> {
Box::new(self.clone())
}
}
#[derive(Clone)]
#[cfg_attr(feature = "python-bindings", pyclass)]
pub struct Siggen {
source: Box<dyn Source>,
channels: Vec<SiggenChannelConfig>,
source_buf: Vec<Flt>,
chout_buf: Vec<Vec<Flt>>,
}
#[cfg(feature="python-bindings")]
#[cfg_attr(feature = "python-bindings", pymethods)]
impl Siggen {
#[pyo3(name = "newWhiteNoise")]
#[staticmethod]
fn newWhiteNoise_py() -> Siggen {
Siggen::newWhiteNoise(0)
}
#[pyo3(name = "newSine")]
#[staticmethod]
fn newSine_py(freq: Flt) -> Siggen {
Siggen::newSine(0, freq)
}
}
impl Siggen {
pub fn nchannels(&self) -> usize {
self.channels.len()
}
pub fn newSilence(nchannels: usize) -> Siggen {
Siggen {
channels: vec![SiggenChannelConfig::new(); nchannels],
source: Box::new(Silence {}),
source_buf: vec![],
chout_buf: vec![],
}
}
pub fn newWhiteNoise(nchannels: usize) -> Siggen {
Siggen::new(nchannels, Box::new(WhiteNoise::new()))
}
pub fn setAllGains(&mut self, g: Flt) {
self.channels.iter_mut().for_each(|set| set.setGain(g))
}
pub fn setNChannels(&mut self, nch: usize) {
self.channels.truncate(nch);
while self.channels.len() < nch {
self.channels.push(SiggenChannelConfig::new());
}
}
pub fn setDCOffset(&mut self, dc: &[Flt]) {
self.channels
.iter_mut()
.zip(dc)
.for_each(|(ch, dc)| {
ch.DCOffset = *dc;
});
}
pub fn newSine(nchannels: usize, freq: Flt) -> Siggen {
Siggen::new(nchannels, Box::new(Sine::new(freq)))
}
pub fn new(nchannels: usize, source: Box<dyn Source>) -> Siggen {
Siggen {
source,
channels: vec![SiggenChannelConfig::new(); nchannels],
source_buf: vec![],
chout_buf: vec![],
}
}
pub fn genSignal<T>(&mut self, out: &mut [T])
where T: Sample + FromSample<Flt> + Debug, Flt: Sample
{
let nch = self.nchannels();
let nsamples: usize = out.len() / nch;
assert!(out.len() % self.nchannels() == 0);
self.source_buf.resize(nsamples, 0.0);
self.source.genSignal_unscaled(&mut self.source_buf.iter_mut());
self.chout_buf.resize(nch, vec![]);
for (channelno, (channel, chout)) in self.channels
.iter_mut()
.zip(self.chout_buf.iter_mut())
.enumerate() {
chout.resize(nsamples, 0.0);
channel.genSignal(&self.source_buf, chout);
let out_iterator = out.iter_mut().skip(channelno).step_by(nch);
out_iterator.zip(chout).for_each(|(out, chin)| {
*out = chin.to_sample();
});
}
}
pub fn reset(&mut self, fs: Flt) {
self.source.reset(fs);
self.channels.iter_mut().for_each(|x| x.reset(fs))
}
pub fn setAllMute(&mut self, mute: bool) {
self.channels.iter_mut().for_each(|s| {
s.setMute(mute);
});
}
pub fn setMute(&mut self, mute: &[bool]) {
assert!(mute.len() == self.nchannels());
self.channels
.iter_mut()
.zip(mute)
.for_each(|(s, m)| {
s.setMute(*m);
});
}
}
#[derive(Clone)]
struct SiggenChannelConfig {
muted: bool,
prefilter: Option<Box<dyn Filter>>,
gain: Flt,
DCOffset: Flt,
}
unsafe impl Send for SiggenChannelConfig {}
impl SiggenChannelConfig {
pub fn setPreFilter(&mut self, pref: Option<Box<dyn Filter>>) {
self.prefilter = pref;
}
pub fn setGain(&mut self, g: Flt) {
self.gain = g;
}
pub fn reset(&mut self, _fs: Flt) {
if let Some(f) = &mut self.prefilter {
f.reset()
}
}
pub fn new() -> SiggenChannelConfig {
SiggenChannelConfig {
muted: false,
prefilter: None,
gain: 1.0,
DCOffset: 0.0,
}
}
pub fn setMute(&mut self, mute: bool) {
self.muted = mute;
}
pub fn genSignal(&mut self, source: &[Flt], result: &mut [Flt]) {
if self.muted {
result.iter_mut().for_each(|x| {
*x = 0.0;
});
} else {
result.copy_from_slice(source);
if let Some(f) = &mut self.prefilter {
f.filter(result);
}
}
result.iter_mut().for_each(|x| {
*x *= self.gain;
*x += self.DCOffset;
});
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_whitenoise() {
let mut t = [0.0; 10];
Siggen::newWhiteNoise(1).genSignal(&mut t);
}
#[test]
fn test_sine() {
const N: usize = 10000;
let mut s1 = [0.0; N];
let mut s2 = [0.0; N];
let mut siggen = Siggen::newSine(1, 1.0);
siggen.reset(10.0);
siggen.setAllMute(false);
siggen.genSignal(&mut s1);
siggen.genSignal(&mut s2);
let absdiff = s1
.iter()
.zip(s2.iter())
.map(|(s1, s2)| { Flt::abs(*s1 - *s2) })
.sum::<Flt>();
assert!(absdiff < 1e-10);
}
#[test]
fn test_sine2() {
const fs: Flt = 10.0;
const Nframes: usize = 10000;
const Nch: usize = 2;
let mut signal = [0.0; Nch * Nframes];
let mut siggen = Siggen::newSine(Nch, 1.0);
siggen.reset(fs);
siggen.setMute(&[false, true]);
siggen.genSignal(&mut signal[..Nframes / 2]);
siggen.genSignal(&mut signal[Nframes / 2..]);
let ms1 =
signal
.iter()
.step_by(2)
.map(|s1| { *s1 * *s1 })
.sum::<Flt>() / (Nframes as Flt);
println!("ms1: {}", ms1);
let ms2 =
signal
.iter()
.skip(1)
.step_by(2)
.map(|s1| { *s1 * *s1 })
.sum::<Flt>() / (Nframes as Flt);
assert!(Flt::abs(ms1 - 0.5) < 1e-12);
assert_eq!(ms2, 0.0);
}
#[test]
fn test_sample() {
assert_eq!((0.5f32).to_sample::<i8>(), 64);
assert_eq!((1.0f32).to_sample::<i8>(), 127);
assert_eq!(-(1.0f32).to_sample::<i8>(), -127);
assert_eq!((1.0f32).to_sample::<i16>(), i16::MAX);
}
}