use super::audionode::*;
use super::filter::*;
use super::fir::*;
use super::math::*;
use super::signal::*;
use super::*;
use funutd::Rnd;
use numeric_array::*;
use std::marker::PhantomData;
#[derive(Default, Clone)]
pub struct Sine<T: Real> {
phase: T,
sample_duration: T,
hash: u64,
initial_phase: Option<T>,
}
impl<T: Real> Sine<T> {
pub fn new(sample_rate: f64) -> Self {
let mut sine = Sine::default();
sine.reset(Some(sample_rate));
sine
}
pub fn with_phase(sample_rate: f64, initial_phase: Option<T>) -> Self {
let mut sine = Self {
phase: T::zero(),
sample_duration: T::zero(),
hash: 0,
initial_phase,
};
sine.reset(Some(sample_rate));
sine
}
}
impl<T: Real> AudioNode for Sine<T> {
const ID: u64 = 21;
type Sample = T;
type Inputs = typenum::U1;
type Outputs = typenum::U1;
type Setting = ();
fn reset(&mut self, sample_rate: Option<f64>) {
self.phase = match self.initial_phase {
Some(phase) => phase,
None => T::from_f64(rnd(self.hash as i64)),
};
if let Some(sr) = sample_rate {
self.sample_duration = T::from_f64(1.0 / sr);
}
}
#[inline]
fn tick(
&mut self,
input: &Frame<Self::Sample, Self::Inputs>,
) -> Frame<Self::Sample, Self::Outputs> {
self.phase += input[0] * self.sample_duration;
self.phase -= self.phase.floor();
[sin(self.phase * T::from_f64(TAU))].into()
}
fn process(
&mut self,
size: usize,
input: &[&[Self::Sample]],
output: &mut [&mut [Self::Sample]],
) {
for i in 0..size {
self.phase += input[0][i] * self.sample_duration;
output[0][i] = sin(self.phase * T::from_f64(TAU));
}
self.phase -= self.phase.floor();
}
fn set_hash(&mut self, hash: u64) {
self.hash = hash;
self.reset(None);
}
fn route(&mut self, _input: &SignalFrame, _frequency: f64) -> SignalFrame {
let mut output = new_signal_frame(self.outputs());
output[0] = Signal::Latency(0.0);
output
}
}
fn dsf<T: Real>(f: T, d: T, r: T, n: T) -> T {
(sin(f)
- r * sin(f - d)
- pow(r, n + T::one()) * (sin(f + (n + T::one()) * d) - r * sin(f + n * d)))
/ (T::one() + r * r - T::new(2) * r * cos(d))
}
#[derive(Clone)]
pub struct Dsf<T: Real, N: Size<T>> {
phase: T,
roughness: T,
harmonic_spacing: T,
sample_duration: T,
hash: u64,
_marker: PhantomData<N>,
}
impl<T: Real, N: Size<T>> Dsf<T, N> {
pub fn new(sample_rate: f64, harmonic_spacing: T, roughness: T) -> Self {
let mut node = Dsf {
phase: T::zero(),
roughness,
harmonic_spacing,
sample_duration: T::zero(),
hash: 0,
_marker: PhantomData::default(),
};
node.reset(Some(sample_rate));
node.set_roughness(roughness);
node
}
#[inline]
pub fn roughness(&self) -> T {
self.roughness
}
#[inline]
pub fn set_roughness(&mut self, roughness: T) {
self.roughness = clamp(T::from_f64(0.0001), T::from_f64(0.9999), roughness);
}
}
impl<T: Real, N: Size<T>> AudioNode for Dsf<T, N> {
const ID: u64 = 55;
type Sample = T;
type Inputs = N;
type Outputs = typenum::U1;
type Setting = T;
fn set(&mut self, setting: Self::Setting) {
self.set_roughness(setting);
}
fn reset(&mut self, sample_rate: Option<f64>) {
self.phase = T::from_f64(rnd(self.hash as i64));
if let Some(sr) = sample_rate {
self.sample_duration = T::from_f64(1.0 / sr);
}
}
#[inline]
fn tick(
&mut self,
input: &Frame<Self::Sample, Self::Inputs>,
) -> Frame<Self::Sample, Self::Outputs> {
if N::USIZE > 1 {
self.set_roughness(input[1]);
}
self.phase = (self.phase + input[0] * self.sample_duration).fract();
let n = floor(T::new(22_050) / input[0] / self.harmonic_spacing);
Frame::from([dsf(
self.phase * T::from_f64(TAU),
self.phase * T::from_f64(TAU) * self.harmonic_spacing,
self.roughness,
n,
)])
}
fn set_hash(&mut self, hash: u64) {
self.hash = hash;
self.reset(None);
}
fn route(&mut self, _input: &SignalFrame, _frequency: f64) -> SignalFrame {
let mut output = new_signal_frame(self.outputs());
output[0] = Signal::Latency(0.0);
output
}
}
#[derive(Clone)]
pub struct Pluck<T: Float> {
damping: Fir<T, typenum::U3>,
tuning: Allpole<T, T, typenum::U1>,
line: Vec<T>,
gain: T,
pos: usize,
hash: u64,
frequency: T,
sample_rate: f64,
initialized: bool,
}
impl<T: Float> Pluck<T> {
pub fn new(
sample_rate: f64,
frequency: T,
gain_per_second: T,
high_frequency_damping: T,
) -> Self {
Self {
damping: fir3(T::one() - high_frequency_damping),
tuning: Allpole::new(sample_rate, T::one()),
line: Vec::new(),
gain: T::from_f64(pow(gain_per_second.to_f64(), 1.0 / frequency.to_f64())),
pos: 0,
hash: 0,
frequency,
sample_rate,
initialized: false,
}
}
fn initialize_line(&mut self) {
let epsilon = 0.2;
let total_delay = self.sample_rate / self.frequency.to_f64() - 1.0;
let loop_delay = floor(total_delay - epsilon);
let allpass_delay = total_delay - loop_delay;
self.tuning = Allpole::new(self.sample_rate, T::from_f64(allpass_delay));
self.line.resize(loop_delay as usize, T::zero());
let mut rnd = Rnd::from_u64(self.hash);
for i in 0..self.line.len() {
self.line[i] = T::from_f32(rnd.f32() * 2.0 - 1.0);
}
self.pos = 0;
self.initialized = true;
}
}
impl<T: Float> AudioNode for Pluck<T> {
const ID: u64 = 58;
type Sample = T;
type Inputs = typenum::U1;
type Outputs = typenum::U1;
type Setting = ();
fn reset(&mut self, sample_rate: Option<f64>) {
if let Some(sr) = sample_rate {
self.sample_rate = sr;
}
self.damping.reset(sample_rate);
self.initialized = false;
}
#[inline]
fn tick(
&mut self,
input: &Frame<Self::Sample, Self::Inputs>,
) -> Frame<Self::Sample, Self::Outputs> {
if !self.initialized {
self.initialize_line();
}
let output = self.line[self.pos] * self.gain + input[0];
let output = self.damping.filter_mono(output);
let output = self.tuning.filter_mono(output);
self.line[self.pos] = output;
self.pos += 1;
if self.pos == self.line.len() {
self.pos = 0;
}
[output].into()
}
fn set_hash(&mut self, hash: u64) {
self.hash = hash;
self.initialized = false;
}
fn route(&mut self, _input: &SignalFrame, _frequency: f64) -> SignalFrame {
let mut output = new_signal_frame(self.outputs());
output[0] = Signal::Latency(0.0);
output
}
}