use std::{
any::Any,
collections::HashMap,
f64::consts::PI,
ops::{Index, IndexMut},
sync::{Arc, Mutex},
};
use uuid::Uuid;
pub const TAU: f64 = 2.0 * PI;
pub type Real = f64;
pub type Tag = Uuid;
pub fn mk_tag() -> Tag {
Uuid::new_v4()
}
pub trait Signal: Any {
fn as_any_mut(&mut self) -> &mut dyn Any;
fn signal(&mut self, rack: &Rack, sample_rate: Real) -> Real;
fn tag(&self) -> Tag;
}
#[macro_export]
macro_rules! as_any_mut {
() => {
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
};
}
#[macro_export]
macro_rules! std_signal {
() => {
as_any_mut!();
fn tag(&self) -> Tag {
self.tag
}
};
}
pub trait Gate {
fn gate_on(rack: &Rack, n: Tag);
fn gate_off(rack: &Rack, n: Tag);
}
#[macro_export]
macro_rules! gate {
($t:ty) => {
impl Gate for $t {
fn gate_on(rack: &Rack, n: Tag) {
if let Some(v) = rack.modules[&n]
.module
.lock()
.unwrap()
.as_any_mut()
.downcast_mut::<Self>()
{
v.on();
}
}
fn gate_off(rack: &Rack, n: Tag) {
if let Some(v) = rack.modules[&n]
.module
.lock()
.unwrap()
.as_any_mut()
.downcast_mut::<Self>()
{
v.off();
}
}
}
};
}
pub type Sig = dyn Signal + Send;
pub type ArcMutex<T> = Arc<Mutex<T>>;
pub fn arc<T>(x: T) -> Arc<Mutex<T>> {
Arc::new(Mutex::new(x))
}
impl<T> Signal for ArcMutex<T>
where
T: Signal,
{
as_any_mut!();
fn signal(&mut self, rack: &Rack, sample_rate: Real) -> Real {
self.lock().unwrap().signal(rack, sample_rate)
}
fn tag(&self) -> Tag {
self.lock().unwrap().tag()
}
}
impl Signal for ArcMutex<dyn Signal + Send> {
as_any_mut!();
fn signal(&mut self, rack: &Rack, sample_rate: Real) -> Real {
self.lock().unwrap().signal(rack, sample_rate)
}
fn tag(&self) -> Tag {
self.lock().unwrap().tag()
}
}
pub trait Builder {
fn build(&mut self) -> Self
where
Self: Sized + Clone,
{
self.clone()
}
fn wrap(&mut self) -> ArcMutex<Self>
where
Self: Sized + Clone,
{
arc(self.clone())
}
fn rack(&mut self, rack: &mut Rack) -> ArcMutex<Self>
where
Self: Signal + Send + Sized + Clone,
{
let result = arc(self.clone());
rack.append(result.clone());
result
}
fn rack_pre(&mut self, rack: &mut Rack) -> ArcMutex<Self>
where
Self: Signal + Send + Sized + Clone,
{
let result = arc(self.clone());
rack.preppend(result.clone());
result
}
}
#[derive(Copy, Clone, Debug)]
pub enum In {
Cv(Tag),
Fix(Real),
}
impl In {
pub fn val(rack: &Rack, inp: In) -> Real {
match inp {
In::Fix(x) => x,
In::Cv(n) => rack.output(n),
}
}
}
impl From<Real> for In {
fn from(x: Real) -> Self {
In::Fix(x)
}
}
impl From<Tag> for In {
fn from(t: Tag) -> Self {
In::Cv(t)
}
}
impl From<i32> for In {
fn from(i: i32) -> Self {
In::Fix(i as Real)
}
}
impl Default for In {
fn default() -> Self {
Self::Fix(0.0)
}
}
pub fn connect<T, U>(source: &T, dest: &mut U, field: &'static str)
where
T: Signal,
U: Index<&'static str, Output = In> + IndexMut<&'static str>,
{
dest[field] = source.tag().into();
}
#[derive(Clone)]
pub struct SynthModule {
pub module: ArcMutex<Sig>,
pub output: Real,
}
impl SynthModule {
fn new(signal: ArcMutex<Sig>) -> Self {
Self {
module: signal,
output: 0.0,
}
}
}
impl Signal for SynthModule {
as_any_mut!();
fn signal(&mut self, rack: &Rack, sample_rate: Real) -> Real {
self.module.signal(rack, sample_rate)
}
fn tag(&self) -> Tag {
self.module.tag()
}
}
#[derive(Clone)]
pub struct Rack {
pub modules: HashMap<Tag, SynthModule>,
pub order: Vec<Tag>,
}
impl Rack {
pub fn new(ws: Vec<ArcMutex<Sig>>) -> Self {
let mut nodes: HashMap<Tag, SynthModule> = HashMap::new();
let mut order: Vec<Tag> = Vec::new();
for s in ws {
let t = s.lock().unwrap().tag();
nodes.insert(t, SynthModule::new(s));
order.push(t)
}
Rack { modules: nodes, order }
}
pub fn iter<'a>(&'a self) -> Iter<'a> {
Iter {
rack: self,
index: 0,
}
}
pub fn out_tag(&self) -> Tag {
let n = self.modules.len() - 1;
self.order[n]
}
pub fn output(&self, n: Tag) -> Real {
self.modules
.get(&n)
.expect("Function output could not find tag")
.output
}
pub fn append(&mut self, sig: ArcMutex<Sig>) {
let tag = sig.tag();
let node = SynthModule::new(sig);
self.modules.insert(tag, node);
self.order.push(tag);
}
pub fn preppend(&mut self, sig: ArcMutex<Sig>) {
let tag = sig.tag();
let node = SynthModule::new(sig);
self.modules.insert(tag, node);
self.order.insert(0, tag);
}
pub fn before(&mut self, before: Tag, sig: ArcMutex<Sig>) {
if let Some(pos) = self.order.iter().position(|&x| x == before) {
let tag = sig.tag();
let node = SynthModule::new(sig);
self.modules.insert(tag, node);
self.order.insert(pos, tag);
} else {
panic!("rack does not contain {} tag", before);
}
}
pub fn insert(&mut self, rack: Rack, loc: usize) {
let n = rack.modules.len() + self.modules.len();
let mut new_order: Vec<Tag> = Vec::with_capacity(n);
for i in 0..loc {
new_order.push(self.order[i])
}
for i in 0..rack.order.len() {
new_order.push(rack.order[i])
}
for i in loc..self.modules.len() {
new_order.push(self.order[i])
}
self.order = new_order;
self.modules.extend(rack.modules);
}
pub fn signal(&mut self, sample_rate: Real) -> Real {
let mut outs: Vec<Real> = Vec::new();
for node in self.iter() {
outs.push(
node.module
.lock()
.expect("Function rack::signal could not find tag in first loop")
.signal(&self, sample_rate),
)
}
for (i, o) in self.order.iter().enumerate() {
self.modules
.get_mut(o)
.expect("Function rack::signal could not find tag in second loop")
.output = outs[i];
}
self.modules[&self.out_tag()].output
}
}
pub struct Iter<'a> {
rack: &'a Rack,
index: usize,
}
impl<'a> IntoIterator for &'a Rack {
type Item = &'a SynthModule;
type IntoIter = Iter<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> Iterator for Iter<'a> {
type Item = &'a SynthModule;
fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.rack.order.len() {
return None;
}
let tag = self.rack.order[self.index];
self.index += 1;
self.rack.modules.get(&tag)
}
}
#[derive(Clone)]
pub struct Link {
tag: Tag,
value: In,
}
impl Link {
pub fn new() -> Self {
Self {
tag: mk_tag(),
value: 0.into(),
}
}
pub fn value<T: Into<In>>(&mut self, arg: T) -> &mut Self {
self.value = arg.into();
self
}
}
impl Builder for Link {}
impl Signal for Link {
std_signal!();
fn signal(&mut self, rack: &Rack, _sample_rate: Real) -> Real {
In::val(rack, self.value)
}
}
impl Index<&str> for Link {
type Output = In;
fn index(&self, index: &str) -> &Self::Output {
match index {
"value" => &self.value,
_ => panic!("Link does not have a field named: {}", index),
}
}
}
impl IndexMut<&str> for Link {
fn index_mut(&mut self, index: &str) -> &mut Self::Output {
match index {
"value" => &mut self.value,
_ => panic!("Link does not have a field named: {}", index),
}
}
}