use super::noise::{ColoredNoise, WhiteNoise};
use super::siggen::DUMMY_SAMPLING_FREQ;
use super::sweep::{SweepParams, SweepType};
use crate::config::*;
use std::fmt::Debug;
use std::ops::{Deref, DerefMut};
const twopi: Flt = 2.0 * pi;
use crate::config::*;
use anyhow::{bail, Result};
use rand::prelude::*;
#[cfg_attr(feature = "python-bindings", pyclass)]
#[derive(Clone, Debug)]
pub struct Source {
src: Box<dyn SourceImpl>,
}
impl Source {
pub fn newSine(fs: Flt, freq: Flt) -> Result<Source> {
Ok(Source {
src: Box::new(Sine::new(fs, freq)?),
})
}
pub fn newSilence() -> Source {
Source {
src: Box::new(Silence {}),
}
}
pub fn newWhiteNoise(fs: Flt, interrupt_period: Option<Flt>) -> Source {
Source {
src: Box::new(WhiteNoise::new(fs, interrupt_period)),
}
}
pub fn newPinkNoise(fs: Flt, interrupt_period: Option<Flt>) -> Source {
Source {
src: Box::new(ColoredNoise::newPinkNoise(fs, interrupt_period)),
}
}
pub fn newSweep(
fs: Flt,
fl: Flt,
fu: Flt,
sweep_time: Flt,
quiet_time: Flt,
sweep_type: SweepType,
) -> Result<Source> {
Ok(Source {
src: Box::new(Sweep::new(fs, fl, fu, sweep_time, quiet_time, sweep_type)?),
})
}
}
#[cfg(feature = "python-bindings")]
#[cfg_attr(feature = "python-bindings", pymethods)]
impl Source {
#[staticmethod]
#[pyo3(name = "newSine")]
fn newSine_py(fs: Flt, freq: Flt) -> PyResult<Source> {
Ok(Self::newSine(fs, freq)?)
}
#[pyo3(name = "newSilence")]
#[staticmethod]
fn newSilence_py() -> Source {
Self::newSilence()
}
#[staticmethod]
#[pyo3(name = "newWhiteNoise", signature=(interrupt_period=None))]
fn newWhiteNoise_py(interrupt_period: Option<Flt>) -> Source {
Self::newWhiteNoise(DUMMY_SAMPLING_FREQ, interrupt_period)
}
#[staticmethod]
#[pyo3(name = "newPinkNoise", signature=(interrupt_period=None))]
fn newPinkNoise_py(interrupt_period: Option<Flt>) -> Source {
Self::newPinkNoise(DUMMY_SAMPLING_FREQ, interrupt_period)
}
#[staticmethod]
#[pyo3(name = "newSweep")]
fn newSweep_py(
fs: Flt,
fl: Flt,
fu: Flt,
sweep_time: Flt,
quiet_time: Flt,
sweep_type: SweepType,
) -> PyResult<Source> {
Ok(Self::newSweep(
fs, fl, fu, sweep_time, quiet_time, sweep_type,
)?)
}
}
#[derive(Clone, Debug)]
struct Silence {}
impl SourceImpl 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 SourceImpl> {
Box::new(self.clone())
}
}
#[derive(Clone, Debug)]
struct Sine {
fs: Flt,
phase: Flt,
omg: Flt,
}
impl Sine {
pub fn new(fs: Flt, freq: Flt) -> Result<Sine> {
if fs <= 0. {
bail!("Invalid sampling frequency");
}
if freq >= fs / 2. {
bail!("Frequency of sine wave should be smaller than Nyquist frequency");
}
Ok(Sine {
fs,
phase: 0.0,
omg: 2.0 * pi * freq,
})
}
}
impl SourceImpl 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 SourceImpl> {
Box::new(self.clone())
}
}
#[cfg_attr(feature = "python-bindings", pyclass)]
#[derive(Debug, Clone)]
struct Sweep {
params: SweepParams,
gen: Dcol,
N: usize,
}
impl Sweep {
fn new(
fs: Flt,
fl_: Flt,
fu_: Flt,
sweep_time: Flt,
quiet_time: Flt,
sweeptype: SweepType,
) -> Result<Self> {
let params = SweepParams::new(fs, fl_, fu_, sweep_time, quiet_time, sweeptype)?;
let gen = params.getSignal();
Ok(Sweep { params, gen, N: 0 })
}
}
impl SourceImpl for Sweep {
fn genSignal_unscaled(&mut self, sig: &mut dyn ExactSizeIterator<Item = &mut Flt>) {
let sweep_iter = self.gen.as_slice().unwrap().iter().cycle().skip(self.N);
for (sig, sweep_sample) in sig.zip(sweep_iter) {
*sig = *sweep_sample;
self.N += 1;
}
self.N %= self.gen.len();
}
fn reset(&mut self, fs: Flt) {
self.gen = self.params.reset(fs);
self.N = 0;
}
fn clone_dyn(&self) -> Box<dyn SourceImpl> {
Box::new(self.clone())
}
}
impl Deref for Source {
type Target = Box<dyn SourceImpl>;
fn deref(&self) -> &Self::Target {
&self.src
}
}
impl DerefMut for Source {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.src
}
}
pub trait SourceImpl: Send + Debug {
fn genSignal_unscaled(&mut self, sig: &mut dyn ExactSizeIterator<Item = &mut Flt>);
fn reset(&mut self, fs: Flt);
fn clone_dyn(&self) -> Box<dyn SourceImpl>;
}
impl Clone for Box<dyn SourceImpl> {
fn clone(&self) -> Self {
self.clone_dyn()
}
}