use glicol_synth::{
compound::{Bd, Hh, SawSynth, Sn, SquSynth, TriSynth},
delay::{DelayMs, DelayN},
effect::{Balance, Pan, Plate},
envelope::{Adsr, EnvPerc},
filter::{AllPassFilterGain, OnePole, ResonantHighPassFilter, ResonantLowPassFilter},
operator::{Add, Mul},
oscillator::{SawOsc, SinOsc, SquOsc, TriOsc},
sequencer::{Arrange, Choose, Sequencer, Speed},
signal::{ConstSig, Impulse, Noise, Points},
synth::{MsgSynth, PatternSynth},
Pass, Sum2,
};
#[cfg(feature = "use-meta")]
use glicol_synth::dynamic::Meta;
use glicol_synth::dynamic::Eval;
#[cfg(feature = "use-samples")]
use glicol_synth::sampling::{PSampler, Sampler};
use crate::EngineError;
use glicol_macros::{get_one_para_from_number_or_ref, get_one_para_from_number_or_ref2};
use glicol_synth::{BoxedNodeSend, GlicolPara, NodeData}; use hashbrown::HashMap;
pub type GlicolNodeData<const N: usize> = NodeData<BoxedNodeSend<N>, N>;
#[allow(unused_variables, unused_mut)]
pub fn makenode<const N: usize>(
name: &str,
paras: &mut [GlicolPara],
samples_dict: &HashMap<String, (&'static [f32], usize, usize)>,
sr: usize,
bpm: f32,
seed: usize,
) -> Result<(GlicolNodeData<N>, Vec<String>), EngineError> {
let (nodedata, reflist) = match name {
#[cfg(feature = "use-samples")]
"psampler" => {
let pattern_info = match ¶s[0] {
GlicolPara::Pattern(pattern, span) => (pattern, span),
_ => unimplemented!(),
};
let mut samples_dict_selected = HashMap::new();
let pattern = (*pattern_info.0).iter().map(|v| {
let value = match &v.0 {
GlicolPara::Number(_) => "".to_owned(),
GlicolPara::Symbol(s) => s.to_string(),
_ => unimplemented!(),
};
let time = v.1;
if !samples_dict.contains_key(&value) {
return Err(EngineError::NonExsitSample(value.clone()));
} else {
samples_dict_selected.insert(value.clone(), samples_dict[&value]);
}
Ok((value, time))
}).collect::<Result<Vec<_>, EngineError>>()?;
let span = *pattern_info.1;
(
PSampler::new(samples_dict_selected, sr, bpm, vec![], pattern, span)
.to_boxed_nodedata(2),
vec![],
)
}
"points" => {
let points = paras[0].clone();
let span = match ¶s[1] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
};
let is_looping = match ¶s[2] {
GlicolPara::Bool(v) => *v,
_ => unimplemented!(),
};
(
Points::new()
.bpm(bpm)
.sr(sr)
.span(span)
.points(points)
.is_looping(is_looping)
.to_boxed_nodedata(1),
vec![],
)
}
"msgsynth" => (
MsgSynth::new()
.sr(sr)
.attack(match ¶s[1] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
})
.decay(match ¶s[2] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
})
.to_boxed_nodedata(1),
vec![],
),
"pattern_synth" => {
match ¶s[0] {
GlicolPara::Symbol(s) => {
let pattern = s.replace('`', "");
let events = pattern.split(',')
.map(|event| {
let mut result = event
.split(' ')
.filter(|x| !x.is_empty())
.map(|x| x.replace(' ', "").parse::<f32>().unwrap());
(result.next().unwrap(), result.next().unwrap())
}).collect();
(
PatternSynth::new(events).sr(sr).to_boxed_nodedata(1),
vec![],
)
}
_ => unimplemented!(),
}
}
#[cfg(feature = "bela")]
"adc" => {
let port = match ¶s[0] {
GlicolPara::Number(v) => *v as usize,
_ => unimplemented!(),
};
(
NodeData::new1(BoxedNodeSend::new(Pass {})),
vec![format!("~adc{}", port + 1)],
)
}
#[cfg(feature = "use-samples")]
"sp" => match ¶s[0] {
GlicolPara::SampleSymbol(s) => {
if !samples_dict.contains_key(s) {
return Err(EngineError::NonExsitSample(s.to_owned()));
}
(
Sampler::new(samples_dict[s], sr).to_boxed_nodedata(2),
vec![],
)
}
_ => unimplemented!(),
},
#[cfg(feature = "use-meta")]
"meta" => match ¶s[0] {
GlicolPara::Symbol(s) => (
Meta::new().sr(sr).code(s.to_owned()).to_boxed_nodedata(1),
vec![],
),
_ => unimplemented!(),
},
"eval" => match ¶s[0] {
GlicolPara::Symbol(s) => (
Eval::new().sr(sr).code(s.to_owned()).to_boxed_nodedata(1),
vec![],
),
_ => unimplemented!(),
},
"lpf" => {
let qvalue = match ¶s[1] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
};
let mut reflist = vec![];
let data = match ¶s[0] {
GlicolPara::Number(v) => ResonantLowPassFilter::new()
.cutoff(*v)
.q(qvalue)
.sr(sr)
.to_boxed_nodedata(1),
GlicolPara::Reference(s) => {
reflist.push(s.to_owned());
ResonantLowPassFilter::new()
.q(qvalue)
.sr(sr)
.to_boxed_nodedata(1)
}
GlicolPara::Pattern(events, span) => {
let pattern = events.iter()
.map(|v| {
let value = match v.0 {
GlicolPara::Number(num) => num,
_ => 100.0,
};
(value, v.1)
}).collect();
ResonantLowPassFilter::new()
.q(qvalue)
.pattern(pattern)
.span(*span)
.bpm(bpm)
.sr(sr)
.to_boxed_nodedata(1)
}
_ => unimplemented!(),
};
(data, reflist)
}
"balance" => {
let data = Balance::new().to_boxed_nodedata(2);
let reflist = vec![
match ¶s[0] {
GlicolPara::Reference(s) => s.to_owned(),
_ => "".to_owned(),
},
match ¶s[1] {
GlicolPara::Reference(s) => s.to_owned(),
_ => "".to_owned(),
},
];
(data, reflist)
}
"rhpf" => {
let data = ResonantHighPassFilter::new()
.cutoff(match ¶s[0] {
GlicolPara::Number(v) => *v,
GlicolPara::Reference(_) => 100.0,
_ => unimplemented!(),
})
.q(match ¶s[1] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
})
.to_boxed_nodedata(1);
let mut reflist = vec![];
if let GlicolPara::Reference(s) = ¶s[0] {
reflist.push(s.to_owned());
};
(data, reflist)
}
"apfmsgain" => {
let data = AllPassFilterGain::new()
.sr(sr)
.delay(match ¶s[0] {
GlicolPara::Number(v) => *v,
GlicolPara::Reference(_) => 0.0,
_ => unimplemented!(),
})
.gain(match ¶s[1] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
})
.to_boxed_nodedata(2);
let mut reflist = vec![];
if let GlicolPara::Reference(s) = ¶s[0] {
reflist.push(s.to_owned());
};
(data, reflist)
}
"envperc" => {
let data = EnvPerc::new()
.sr(sr)
.attack(match ¶s[0] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
})
.decay(match ¶s[1] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
})
.to_boxed_nodedata(2);
let reflist = vec![];
(data, reflist)
}
"adsr" => {
let data = Adsr::new()
.sr(sr)
.attack(match ¶s[0] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
})
.decay(match ¶s[1] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
})
.sustain(match ¶s[2] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
})
.release(match ¶s[3] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
})
.to_boxed_nodedata(2);
let reflist = vec![];
(data, reflist)
}
"tri" => match ¶s[0] {
GlicolPara::Number(v) => (TriOsc::new().sr(sr).freq(*v).to_boxed_nodedata(1), vec![]),
GlicolPara::Reference(s) => (
TriOsc::new().sr(sr).freq(0.0).to_boxed_nodedata(1),
vec![s.to_owned()],
),
_ => {
unimplemented!();
}
},
"squ" => match ¶s[0] {
GlicolPara::Number(v) => (SquOsc::new().sr(sr).freq(*v).to_boxed_nodedata(1), vec![]),
GlicolPara::Reference(s) => (
SquOsc::new().sr(sr).freq(0.0).to_boxed_nodedata(1),
vec![s.to_owned()],
),
_ => {
unimplemented!();
}
},
"saw" => match ¶s[0] {
GlicolPara::Number(v) => (SawOsc::new().sr(sr).freq(*v).to_boxed_nodedata(1), vec![]),
GlicolPara::Reference(s) => (
SawOsc::new().sr(sr).freq(0.0).to_boxed_nodedata(1),
vec![s.to_owned()],
),
_ => {
unimplemented!();
}
},
"sin" => match ¶s[0] {
GlicolPara::Number(v) => (SinOsc::new().sr(sr).freq(*v).to_boxed_nodedata(1), vec![]),
GlicolPara::Reference(s) => (
SinOsc::new().sr(sr).freq(0.0).to_boxed_nodedata(1),
vec![s.to_owned()],
),
_ => {
unimplemented!();
}
},
"plate" => match ¶s[0] {
GlicolPara::Number(v) => (Plate::new(*v).to_boxed_nodedata(2), vec![]),
_ => {
unimplemented!();
}
},
"imp" => match ¶s[0] {
GlicolPara::Number(v) => (Impulse::new().sr(sr).freq(*v).to_boxed_nodedata(1), vec![]),
GlicolPara::Reference(s) => (
Impulse::new().sr(sr).freq(0.0).to_boxed_nodedata(1),
vec![s.to_owned()],
),
_ => {
unimplemented!();
}
},
"mul" => match ¶s[0] {
GlicolPara::Number(v) => (Mul::new(*v).to_boxed_nodedata(2), vec![]),
GlicolPara::Reference(s) => (Mul::new(0.0).to_boxed_nodedata(2), vec![s.to_string()]),
_ => {
unimplemented!();
}
},
"pan" => match ¶s[0] {
GlicolPara::Number(v) => (Pan::new(*v).to_boxed_nodedata(2), vec![]),
GlicolPara::Reference(s) => (Pan::new(0.0).to_boxed_nodedata(2), vec![s.to_string()]),
_ => {
unimplemented!();
}
},
"delayn" => match ¶s[0] {
GlicolPara::Number(v) => (DelayN::new(*v as usize).to_boxed_nodedata(2), vec![]),
GlicolPara::Reference(s) => (DelayN::new(0).to_boxed_nodedata(2), vec![s.to_string()]),
_ => {
unimplemented!();
}
},
"delayms" => match ¶s[0] {
GlicolPara::Number(v) => (
DelayMs::new().sr(sr).delay(*v, 2).to_boxed_nodedata(2),
vec![],
),
GlicolPara::Reference(s) => (
DelayMs::new().sr(sr).delay(2000., 2).to_boxed_nodedata(2),
vec![s.to_string()],
),
_ => {
unimplemented!();
}
},
"noise" => match ¶s[0] {
GlicolPara::Number(v) => (Noise::new(*v as usize).to_boxed_nodedata(1), vec![]),
_ => {
unimplemented!();
}
},
"speed" => get_one_para_from_number_or_ref!(Speed),
"onepole" => get_one_para_from_number_or_ref!(OnePole),
"add" => match ¶s[0] {
GlicolPara::Number(v) => (Add::new(*v).to_boxed_nodedata(2), vec![]),
GlicolPara::Reference(s) => (Add::new(0.0).to_boxed_nodedata(2), vec![s.to_string()]),
_ => {
unimplemented!();
}
},
"constsig" => {
let mut reflist = vec![];
let data = match ¶s[0] {
GlicolPara::Number(v) => ConstSig::new(*v).sr(sr).to_boxed_nodedata(1),
GlicolPara::Pattern(events, span) => {
let pattern = events.iter()
.map(|v| {
let value = match v.0 {
GlicolPara::Number(num) => num,
_ => 100.0,
};
(value, v.1)
}).collect();
ConstSig::new(0.0)
.pattern(pattern)
.span(*span)
.bpm(bpm)
.sr(sr)
.to_boxed_nodedata(1)
}
_ => unimplemented!(),
};
(data, reflist)
}
"bd" => get_one_para_from_number_or_ref2!(Bd),
"hh" => get_one_para_from_number_or_ref2!(Hh),
"sn" => get_one_para_from_number_or_ref2!(Sn),
"sawsynth" => {
let data = SawSynth::new(
match ¶s[0] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
},
match ¶s[1] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
},
)
.to_boxed_nodedata(2);
(data, vec![])
}
"squsynth" => {
let data = SquSynth::new(
match ¶s[0] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
},
match ¶s[1] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
},
)
.to_boxed_nodedata(2);
(data, vec![])
}
"trisynth" => {
let data = TriSynth::new(
match ¶s[0] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
},
match ¶s[1] {
GlicolPara::Number(v) => *v,
_ => unimplemented!(),
},
)
.to_boxed_nodedata(2);
(data, vec![])
}
"get" => {
let mut reflist = Vec::<String>::new();
match ¶s[0] {
GlicolPara::Reference(s) => reflist.push(s.to_string()),
_ => unimplemented!(),
}
(NodeData::new2(BoxedNodeSend::new(Pass {})), reflist)
}
"seq" => {
let mut reflist = Vec::<String>::new();
let events = match ¶s[0] {
GlicolPara::Sequence(s) => s,
_ => unimplemented!(),
};
let mut order = HashMap::new();
let mut count = 0;
for event in events {
if let GlicolPara::Reference(s) = &event.1 {
if !reflist.contains(s) {
reflist.push(s.to_string());
order.insert(s.to_string(), count);
count += 1;
}
}
}
(
Sequencer::new(events.clone())
.sr(sr)
.bpm(bpm)
.ref_order(order)
.to_boxed_nodedata(2),
reflist,
)
}
"choose" => {
let list = match ¶s[0] {
GlicolPara::NumberList(v) => v,
_ => unimplemented!(),
};
(
Choose::new(list.clone(), seed as u64).to_boxed_nodedata(2),
vec![],
)
}
"mix" => {
let list: Vec<_> = paras
.iter()
.map(|x| match x {
GlicolPara::Reference(s) => (*s).clone(),
_ => unimplemented!(),
})
.collect();
(NodeData::new2(BoxedNodeSend::new(Sum2 {})), list)
}
"arrange" => {
let mut reflist = vec![];
for p in paras.iter() {
if let GlicolPara::Reference(s) = p {
reflist.push((*s).clone());
}
}
(
Arrange::new(paras.to_vec())
.sr(sr)
.bpm(bpm)
.to_boxed_nodedata(2),
reflist,
)
}
_ => unimplemented!(),
};
Ok((nodedata, reflist))
}