use crate::building_blocks::SynthParameterAddress;
use crate::building_blocks::ambisonics::encoder::Encoder;
use crate::building_blocks::envelopes::*;
use crate::building_blocks::filters::*;
use crate::building_blocks::oscillators::*;
use crate::building_blocks::routing::PanChan;
use crate::building_blocks::{
Modulator, MonoEffect, MonoSource, Panner, SampleBuffer, Synth, SynthParameterLabel,
SynthParameterValue,
};
pub struct RissetBell<const BUFSIZE: usize, const NCHAN: usize> {
oscillators: [SineOsc<BUFSIZE>; 11],
envelopes: [ExpPercEnvelope<BUFSIZE>; 11],
main_envelope: LinearASREnvelope<BUFSIZE>,
amps: [f32; 11],
durs: [f32; 11],
freqs: [f32; 11],
dets: [f32; 11],
lpf: Lpf18<BUFSIZE>,
balance: Box<dyn Panner<BUFSIZE, NCHAN> + Sync + Send>,
atk: f32,
sus: f32,
rel: f32,
freq: f32,
main_level: f32,
reverb: f32,
delay: f32,
}
impl<const BUFSIZE: usize, const NCHAN: usize> RissetBell<BUFSIZE, NCHAN> {
pub fn new(ambi: bool, sr: f32) -> RissetBell<BUFSIZE, NCHAN> {
let mut bell = RissetBell {
oscillators: [(); 11].map(|_| SineOsc::new(440.0, 0.4, sr)),
envelopes: [ExpPercEnvelope::new(1.0, 0.005, 0.0, 0.05, sr); 11],
main_envelope: LinearASREnvelope::new(1.0, 0.05, 0.5, 0.05, sr),
amps: [1.0, 0.67, 1.0, 1.8, 2.67, 1.67, 1.46, 1.33, 1.33, 1.0, 1.33],
durs: [
1.0, 0.9, 0.65, 0.55, 0.325, 0.35, 0.25, 0.2, 0.15, 0.1, 0.075,
],
freqs: [
0.56, 0.56, 0.92, 0.92, 1.19, 1.7, 2.0, 2.74, 3.0, 3.76, 4.07,
],
dets: [0.0, 1.0, 0.0, 1.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
lpf: Lpf18::new(19500.0, 0.01, 0.01, sr),
balance: if ambi {
Box::new(Encoder::new())
} else {
Box::new(PanChan::new())
},
atk: 0.05,
sus: 0.7,
rel: 0.05,
main_level: 0.7,
freq: 1000.0,
reverb: 0.0,
delay: 0.0,
};
let freq = 1000.0;
let length = 0.8;
for i in 0..11 {
bell.envelopes[i].set_parameter(
SynthParameterLabel::EnvelopeLevel,
&SynthParameterValue::ScalarF32(bell.amps[i] * bell.main_level),
);
bell.envelopes[i].set_parameter(
SynthParameterLabel::Release,
&SynthParameterValue::ScalarF32(bell.durs[i] * length),
);
bell.oscillators[i].set_parameter(
SynthParameterLabel::PitchFrequency,
&SynthParameterValue::ScalarF32(freq * bell.freqs[i] + bell.dets[i]),
);
}
bell
}
}
impl<const BUFSIZE: usize, const NCHAN: usize> Synth<BUFSIZE, NCHAN>
for RissetBell<BUFSIZE, NCHAN>
{
fn set_modulator(
&mut self,
par: SynthParameterAddress,
init: f32,
modulator: Modulator<BUFSIZE>,
) {
self.lpf.set_modulator(par.label, init, modulator.clone());
self.main_envelope
.set_modulator(par.label, init, modulator.clone());
self.balance.set_modulator(par.label, init, modulator);
}
fn set_parameter(&mut self, par: SynthParameterAddress, val: &SynthParameterValue) {
self.lpf.set_parameter(par.label, val);
self.main_envelope.set_parameter(par.label, val);
self.balance.set_parameter(par.label, val);
let mut update_internals = false;
match par.label {
SynthParameterLabel::ReverbMix => {
if let SynthParameterValue::ScalarF32(r) = val {
self.reverb = *r
}
}
SynthParameterLabel::DelayMix => {
if let SynthParameterValue::ScalarF32(d) = val {
self.delay = *d
}
}
SynthParameterLabel::PitchFrequency => {
if let SynthParameterValue::ScalarF32(f) = val {
self.freq = *f
};
update_internals = true;
}
SynthParameterLabel::Attack => {
if let SynthParameterValue::ScalarF32(f) = val {
self.atk = *f
};
update_internals = true;
}
SynthParameterLabel::Sustain => {
if let SynthParameterValue::ScalarF32(s) = val {
self.sus = *s
};
update_internals = true;
}
SynthParameterLabel::Release => {
if let SynthParameterValue::ScalarF32(r) = val {
self.rel = *r
};
update_internals = true;
}
SynthParameterLabel::EnvelopeLevel => {
if let SynthParameterValue::ScalarF32(l) = val {
self.main_level = *l
};
update_internals = true;
}
SynthParameterLabel::Envelope => {
if let SynthParameterValue::MultiPointEnvelope(segments, _, _) = val {
if segments.len() == 3 {
self.atk = segments[0].time;
self.sus = segments[1].time;
self.rel = segments[2].time;
self.main_level = segments[1].from;
} else if segments.len() == 4 {
self.atk = segments[0].time;
self.sus = segments[2].time;
self.rel = segments[3].time;
self.main_level = segments[2].from;
} else {
}
update_internals = true;
}
}
_ => (),
};
if update_internals {
let length = self.atk + self.sus + self.rel;
for i in 0..11 {
self.envelopes[i].set_parameter(
SynthParameterLabel::EnvelopeLevel,
&SynthParameterValue::ScalarF32(self.amps[i] * self.main_level),
);
self.envelopes[i].set_parameter(
SynthParameterLabel::Release,
&SynthParameterValue::ScalarF32(self.durs[i] * length),
);
self.oscillators[i].set_parameter(
SynthParameterLabel::PitchFrequency,
&SynthParameterValue::ScalarF32(self.freq * self.freqs[i] + self.dets[i]),
);
}
}
}
fn finish(&mut self) {
self.main_envelope.finish();
}
fn is_finished(&self) -> bool {
self.main_envelope.is_finished()
}
fn get_next_block(
&mut self,
start_sample: usize,
sample_buffers: &[SampleBuffer],
) -> [[f32; BUFSIZE]; NCHAN] {
let mut out: [f32; BUFSIZE] =
self.oscillators[0].get_next_block(start_sample, sample_buffers);
out = self.envelopes[0].process_block(out, start_sample, sample_buffers);
for i in 1..11 {
let mut tmp_out: [f32; BUFSIZE] =
self.oscillators[i].get_next_block(start_sample, sample_buffers);
tmp_out = self.envelopes[i].process_block(tmp_out, start_sample, sample_buffers);
for s in 0..BUFSIZE {
out[s] += tmp_out[s];
}
}
out = self.lpf.process_block(out, start_sample, sample_buffers);
out = self
.main_envelope
.process_block(out, start_sample, sample_buffers);
self.balance
.process_block(out, start_sample, sample_buffers) }
fn reverb_level(&self) -> f32 {
self.reverb
}
fn delay_level(&self) -> f32 {
self.delay
}
}