use super::audionode::*;
use super::combinator::*;
use super::*;
use numeric_array::typenum::*;
use std::sync::atomic::AtomicU32;
use std::sync::atomic::AtomicU64;
use std::sync::Arc;
pub trait Atomic: Float {
type Storage;
fn storage(t: Self) -> Self::Storage;
fn store(stored: &Self::Storage, t: Self);
fn get_stored(stored: &Self::Storage) -> Self;
}
impl Atomic for f32 {
type Storage = AtomicU32;
fn storage(t: Self) -> Self::Storage {
AtomicU32::from(t.to_bits())
}
fn store(stored: &Self::Storage, t: Self) {
stored.store(t.to_bits(), std::sync::atomic::Ordering::Relaxed);
}
fn get_stored(stored: &Self::Storage) -> Self {
let u = stored.load(std::sync::atomic::Ordering::Relaxed);
f32::from_bits(u)
}
}
impl Atomic for f64 {
type Storage = AtomicU64;
fn storage(t: Self) -> Self::Storage {
AtomicU64::from(t.to_bits())
}
fn store(stored: &Self::Storage, t: Self) {
stored.store(t.to_bits(), std::sync::atomic::Ordering::Relaxed);
}
fn get_stored(stored: &Self::Storage) -> Self {
let u = stored.load(std::sync::atomic::Ordering::Relaxed);
f64::from_bits(u)
}
}
#[derive(Default)]
pub struct Shared<T: Atomic> {
value: Arc<T::Storage>,
}
impl<T: Atomic> Clone for Shared<T> {
fn clone(&self) -> Self {
Self {
value: Arc::clone(&self.value),
}
}
}
impl<T: Atomic> Shared<T> {
pub fn new(value: T) -> Self {
Self {
value: Arc::new(T::storage(value)),
}
}
pub fn get_shared(&self) -> &Arc<T::Storage> {
&self.value
}
pub fn set_value(&self, t: T) {
T::store(&self.value, t)
}
pub fn value(&self) -> T {
T::get_stored(&self.value)
}
}
#[derive(Default)]
pub struct Var<T: Atomic> {
value: Arc<T::Storage>,
}
impl<T: Atomic> Clone for Var<T> {
fn clone(&self) -> Self {
Self {
value: Arc::clone(&self.value),
}
}
}
impl<T: Atomic> Var<T> {
pub fn new(shared: &Shared<T>) -> Self {
Self {
value: Arc::clone(shared.get_shared()),
}
}
pub fn set_value(&self, t: T) {
T::store(&self.value, t)
}
pub fn value(&self) -> T {
T::get_stored(&self.value)
}
}
impl<T: Atomic> AudioNode for Var<T> {
const ID: u64 = 68;
type Sample = T;
type Inputs = U0;
type Outputs = U1;
type Setting = ();
fn tick(
&mut self,
_: &Frame<Self::Sample, Self::Inputs>,
) -> Frame<Self::Sample, Self::Outputs> {
let sample: T = self.value();
[sample].into()
}
fn process(
&mut self,
size: usize,
_input: &[&[Self::Sample]],
output: &mut [&mut [Self::Sample]],
) {
let sample = self.value();
output[0][..size].fill(sample);
}
}
#[derive(Default)]
pub struct VarFn<T, F, R>
where
T: Atomic,
F: Clone + Fn(T) -> R,
R: ConstantFrame<Sample = T>,
R::Size: Size<T>,
{
value: Arc<T::Storage>,
f: F,
}
impl<T, F, R> Clone for VarFn<T, F, R>
where
T: Atomic,
F: Clone + Fn(T) -> R,
R: ConstantFrame<Sample = T>,
R::Size: Size<T>,
{
fn clone(&self) -> Self {
Self {
value: Arc::clone(&self.value),
f: self.f.clone(),
}
}
}
impl<T, F, R> VarFn<T, F, R>
where
T: Atomic,
F: Clone + Fn(T) -> R,
R: ConstantFrame<Sample = T>,
R::Size: Size<T>,
{
pub fn new(shared: &Shared<T>, f: F) -> Self {
Self {
value: Arc::clone(shared.get_shared()),
f,
}
}
}
impl<T, F, R> AudioNode for VarFn<T, F, R>
where
T: Atomic,
F: Clone + Fn(T) -> R,
R: ConstantFrame<Sample = T>,
R::Size: Size<T>,
{
const ID: u64 = 70;
type Sample = T;
type Inputs = U0;
type Outputs = R::Size;
type Setting = ();
fn tick(
&mut self,
_: &Frame<Self::Sample, Self::Inputs>,
) -> Frame<Self::Sample, Self::Outputs> {
(self.f)(T::get_stored(&self.value)).convert()
}
fn process(
&mut self,
size: usize,
_input: &[&[Self::Sample]],
output: &mut [&mut [Self::Sample]],
) {
let frame = (self.f)(T::get_stored(&self.value)).convert();
for channel in 0..self.outputs() {
output[channel][..size].fill(frame[channel]);
}
}
}
#[derive(Clone)]
pub struct Timer<T: Atomic> {
shared: Shared<T>,
time: f64,
sample_duration: f64,
}
impl<T: Atomic> Timer<T> {
pub fn new(sample_rate: f64, shared: &Shared<T>) -> Self {
shared.set_value(T::zero());
Self {
shared: shared.clone(),
time: 0.0,
sample_duration: 1.0 / sample_rate,
}
}
}
impl<T: Atomic> AudioNode for Timer<T> {
const ID: u64 = 57;
type Sample = T;
type Inputs = U0;
type Outputs = U0;
type Setting = ();
fn reset(&mut self, sample_rate: Option<f64>) {
self.time = 0.0;
if let Some(sr) = sample_rate {
self.sample_duration = 1.0 / sr;
}
self.shared.set_value(T::zero());
}
#[inline]
fn tick(
&mut self,
input: &Frame<Self::Sample, Self::Inputs>,
) -> Frame<Self::Sample, Self::Outputs> {
self.time += self.sample_duration;
self.shared.set_value(T::from_f64(self.time));
*input
}
fn process(
&mut self,
size: usize,
_input: &[&[Self::Sample]],
_output: &mut [&mut [Self::Sample]],
) {
self.time += size as f64 * self.sample_duration;
self.shared.set_value(T::from_f64(self.time));
}
}