use std::sync::Arc;
use rubato::{FftFixedIn, Resampler};
use crossbeam::atomic::AtomicCell;
use dashmap::DashMap;
use crate::building_blocks::{
SampleBuffer, SynthParameterAddress, SynthParameterLabel, SynthParameterValue,
resolve_parameter_value,
};
use crate::ruffbox::{ControlMessage, ScheduledEvent};
use crate::synths::*;
use crate::ruffbox::ScheduledSource;
use crate::synths::{KarPlusPlus, MultiOscillatorSynth};
pub struct PreparedInstance<const BUFSIZE: usize, const NCHAN: usize> {
ev: ScheduledEvent<BUFSIZE, NCHAN>,
sr: f32,
}
impl<const BUFSIZE: usize, const NCHAN: usize> PreparedInstance<BUFSIZE, NCHAN> {
pub fn set_instance_parameter(
&mut self,
par: SynthParameterAddress,
val: &SynthParameterValue,
) {
self.ev.set_param_or_modulator(
par,
resolve_parameter_value::<BUFSIZE>(par.label, val, self.sr),
);
}
}
enum BufferType {
Mono,
Stereo,
}
pub struct RuffboxControls<const BUFSIZE: usize, const NCHAN: usize> {
buffer_counter: AtomicCell<usize>,
buffer_lengths: DashMap<usize, usize>,
buffer_types: DashMap<usize, BufferType>,
freeze_buffer_offset: usize,
num_live_buffers: usize,
num_freeze_buffers: usize,
max_buffers: usize,
control_q_send: crossbeam::channel::Sender<ControlMessage<BUFSIZE, NCHAN>>,
now: Arc<AtomicCell<f64>>, pub samplerate: f32, }
impl<const BUFSIZE: usize, const NCHAN: usize> RuffboxControls<BUFSIZE, NCHAN> {
pub(crate) fn new(
samplerate: f64,
live_buffers: usize,
live_buffer_time: f64,
max_buffers: usize,
freeze_buffers: usize,
now: &Arc<AtomicCell<f64>>,
tx: crossbeam::channel::Sender<ControlMessage<BUFSIZE, NCHAN>>,
) -> RuffboxControls<BUFSIZE, NCHAN> {
let buffer_lengths = DashMap::new();
let buffer_types = DashMap::new();
if live_buffers > 0 {
for b in 0..live_buffers + freeze_buffers {
buffer_lengths.insert(b, (samplerate * live_buffer_time) as usize);
buffer_types.insert(b, BufferType::Mono);
}
}
RuffboxControls {
buffer_counter: AtomicCell::new(if live_buffers > 0 {
live_buffers + freeze_buffers
} else {
0
}),
freeze_buffer_offset: live_buffers,
num_live_buffers: live_buffers,
num_freeze_buffers: freeze_buffers,
buffer_lengths,
buffer_types,
max_buffers,
control_q_send: tx,
samplerate: samplerate as f32,
now: Arc::clone(now),
}
}
pub fn prepare_instance(
&self,
src_type: SynthType,
timestamp: f64,
sample_buf: usize,
) -> Option<PreparedInstance<BUFSIZE, NCHAN>> {
Some(PreparedInstance {
sr: self.samplerate,
ev: match src_type {
SynthType::KarPlusPlus(desc) => ScheduledEvent::new(
timestamp,
if desc.ambisonic {
ScheduledSource::Ambi(Box::new(KarPlusPlus::new(desc, self.samplerate)))
} else {
ScheduledSource::Channel(Box::new(KarPlusPlus::new(desc, self.samplerate)))
},
),
SynthType::SingleOscillator(desc) => ScheduledEvent::new(
timestamp,
if desc.ambisonic {
ScheduledSource::Ambi(Box::new(SingleOscillatorSynth::new(
desc,
self.samplerate,
)))
} else {
ScheduledSource::Channel(Box::new(SingleOscillatorSynth::new(
desc,
self.samplerate,
)))
},
),
SynthType::MultiOscillator(desc) => ScheduledEvent::new(
timestamp,
if desc.ambisonic {
ScheduledSource::Ambi(Box::new(MultiOscillatorSynth::new(
desc,
self.samplerate,
)))
} else {
ScheduledSource::Channel(Box::new(MultiOscillatorSynth::new(
desc,
self.samplerate,
)))
},
),
SynthType::RissetBell(ambi) => ScheduledEvent::new(
timestamp,
if ambi {
ScheduledSource::Ambi(Box::new(RissetBell::new(ambi, self.samplerate)))
} else {
ScheduledSource::Channel(Box::new(RissetBell::new(ambi, self.samplerate)))
},
),
SynthType::Sampler(desc) => ScheduledEvent::new(
timestamp,
if desc.ambisonic {
match *self.buffer_types.get(&sample_buf).unwrap() {
BufferType::Mono => ScheduledSource::Ambi(Box::new(Sampler::new(
desc,
sample_buf,
*self.buffer_lengths.get(&sample_buf).unwrap(),
self.samplerate,
))),
BufferType::Stereo => {
ScheduledSource::Ambi(Box::new(StereoSampler::new(
desc,
sample_buf,
*self.buffer_lengths.get(&sample_buf).unwrap(),
self.samplerate,
)))
}
}
} else {
match *self.buffer_types.get(&sample_buf).unwrap() {
BufferType::Mono => ScheduledSource::Channel(Box::new(Sampler::new(
desc,
sample_buf,
*self.buffer_lengths.get(&sample_buf).unwrap(),
self.samplerate,
))),
BufferType::Stereo => {
ScheduledSource::Channel(Box::new(StereoSampler::new(
desc,
sample_buf,
*self.buffer_lengths.get(&sample_buf).unwrap(),
self.samplerate,
)))
}
}
},
),
SynthType::LiveSampler(desc) if self.num_live_buffers > 0 => {
let final_bufnum = if sample_buf < self.num_live_buffers {
sample_buf
} else {
0
};
ScheduledEvent::new(
timestamp,
if desc.ambisonic {
ScheduledSource::Ambi(Box::new(Sampler::new(
desc,
final_bufnum,
*self.buffer_lengths.get(&final_bufnum).unwrap(),
self.samplerate,
)))
} else {
ScheduledSource::Channel(Box::new(Sampler::new(
desc,
final_bufnum,
*self.buffer_lengths.get(&final_bufnum).unwrap(),
self.samplerate,
)))
},
)
}
SynthType::FrozenSampler(desc) if self.num_freeze_buffers > 0 => {
let final_bufnum = if sample_buf < self.num_freeze_buffers {
sample_buf + self.freeze_buffer_offset
} else {
self.freeze_buffer_offset
};
ScheduledEvent::new(
timestamp,
if desc.ambisonic {
ScheduledSource::Ambi(Box::new(Sampler::new(
desc,
final_bufnum,
*self.buffer_lengths.get(&final_bufnum).unwrap(),
self.samplerate,
)))
} else {
ScheduledSource::Channel(Box::new(Sampler::new(
desc,
final_bufnum,
*self.buffer_lengths.get(&final_bufnum).unwrap(),
self.samplerate,
)))
},
)
}
_ => {
return None;
} },
})
}
pub fn set_global_parameter(
&self,
fx: super::GlobalEffect,
par: SynthParameterLabel,
val: SynthParameterValue,
) {
self.control_q_send
.send(ControlMessage::SetGlobalParamOrModulator(
fx,
par,
resolve_parameter_value(par, &val, self.samplerate),
))
.unwrap();
}
pub fn clear_all_buffers(&self) {
self.control_q_send
.send(ControlMessage::ClearAllBuffers)
.unwrap();
}
pub fn clear_all_live_buffers(&self) {
self.control_q_send
.send(ControlMessage::ClearAllLiveBuffers)
.unwrap();
}
pub fn clear_all_freeze_buffers(&self) {
self.control_q_send
.send(ControlMessage::ClearAllFreezeBuffers)
.unwrap();
}
pub fn clear_live_buffer(&self, bufnum: usize) {
self.control_q_send
.send(ControlMessage::ClearLiveBuffer(bufnum))
.unwrap();
}
pub fn clear_freeze_buffer(&self, bufnum: usize) {
self.control_q_send
.send(ControlMessage::ClearFreezeBuffer(bufnum))
.unwrap();
}
pub fn trigger(&self, instance: PreparedInstance<BUFSIZE, NCHAN>) {
self.control_q_send
.send(ControlMessage::ScheduleEvent(instance.ev))
.unwrap();
}
pub fn get_now(&self) -> f64 {
self.now.load()
}
pub fn freeze_buffer(&self, freezbuf: usize, inbuf: usize) {
self.control_q_send
.send(ControlMessage::FreezeBuffer(
freezbuf + self.freeze_buffer_offset,
inbuf,
))
.unwrap();
}
pub fn freeze_add_buffer(&self, freezbuf: usize, inbuf: usize) {
self.control_q_send
.send(ControlMessage::FreezeAddBuffer(
freezbuf + self.freeze_buffer_offset,
inbuf,
))
.unwrap();
}
pub fn freeze_after_rec(&self, freezbuf: usize, inbuf: usize, time_secs: f64, add: bool) {
let num_samples = (self.samplerate as f64 * time_secs).ceil() as usize;
self.control_q_send
.send(ControlMessage::FreezeAfterRec(
freezbuf + self.freeze_buffer_offset,
inbuf,
num_samples,
add,
))
.unwrap();
}
pub fn load_mono_sample(&self, samples: &mut Vec<f32>, resample: bool, sr: f32) -> usize {
let buffer_id = self.buffer_counter.fetch_add(1);
if buffer_id > self.max_buffers {
println!(
"warning, this buffer won't be loaded, as the maximum allowed number of buffers has been reached!"
);
return buffer_id;
}
let (buflen, buffer) = if resample && (self.samplerate != sr) {
if (samples.len() as f32 % 1024.0) > 0.0 {
let diff = 1024 - (samples.len() % 1024);
samples.append(&mut vec![0.0; diff]);
}
let mut samples_resampled: Vec<f32> = Vec::new();
let mut resampler =
FftFixedIn::<f32>::new(sr as usize, self.samplerate as usize, 1024, 1, 1).unwrap();
samples_resampled.push(0.0);
samples_resampled.push(0.0);
let num_chunks = samples.len() / 1024;
for chunk in 0..num_chunks {
let chunk = vec![samples[(1024 * chunk)..(1024 * (chunk + 1))].to_vec()];
let mut waves_out = resampler.process(&chunk, None).unwrap();
samples_resampled.append(&mut waves_out[0]);
}
samples_resampled.push(0.0);
samples_resampled.push(0.0);
(samples_resampled.len() - 4, samples_resampled)
} else {
samples.insert(0, 0.0);
samples.insert(0, 0.0);
samples.push(0.0);
samples.push(0.0);
(samples.len() - 4, samples.to_vec())
};
self.buffer_lengths.insert(buffer_id, buflen);
self.buffer_types.insert(buffer_id, BufferType::Mono);
self.control_q_send
.send(ControlMessage::LoadSample(
buffer_id,
buflen,
SampleBuffer::Mono(buffer),
))
.unwrap();
buffer_id
}
pub fn load_stereo_sample(
&self,
samples_left: &mut Vec<f32>,
samples_right: &mut Vec<f32>,
resample: bool,
sr: f32,
) -> usize {
let buffer_id = self.buffer_counter.fetch_add(1);
if buffer_id > self.max_buffers {
println!(
"warning, this buffer won't be loaded, as the maximum allowed number of buffers has been reached!"
);
return buffer_id;
}
if samples_right.len() < samples_left.len() {
samples_right.append(&mut vec![0.0; samples_left.len() - samples_right.len()]);
}
let (buflen, buffer_left, buffer_right) = if resample && (self.samplerate != sr) {
if (samples_left.len() as f32 % 1024.0) > 0.0 {
let diff = 1024 - (samples_left.len() % 1024);
samples_left.append(&mut vec![0.0; diff]);
}
let mut samples_left_resampled: Vec<f32> = Vec::new();
let mut samples_right_resampled: Vec<f32> = Vec::new();
let mut resampler_l =
FftFixedIn::<f32>::new(sr as usize, self.samplerate as usize, 1024, 1, 1).unwrap();
let mut resampler_r =
FftFixedIn::<f32>::new(sr as usize, self.samplerate as usize, 1024, 1, 1).unwrap();
samples_left_resampled.push(0.0);
samples_left_resampled.push(0.0);
samples_right_resampled.push(0.0);
samples_right_resampled.push(0.0);
let num_chunks = samples_left.len() / 1024;
for chunk in 0..num_chunks {
let chunk_left = vec![samples_left[(1024 * chunk)..(1024 * (chunk + 1))].to_vec()];
let mut waves_out_left = resampler_l.process(&chunk_left, None).unwrap();
samples_left_resampled.append(&mut waves_out_left[0]);
let chunk_right = vec![samples_left[(1024 * chunk)..(1024 * (chunk + 1))].to_vec()];
let mut waves_out_right = resampler_r.process(&chunk_right, None).unwrap();
samples_right_resampled.append(&mut waves_out_right[0]);
}
samples_left_resampled.push(0.0);
samples_left_resampled.push(0.0);
samples_right_resampled.push(0.0);
samples_right_resampled.push(0.0);
(
samples_left_resampled.len() - 4,
samples_left_resampled,
samples_right_resampled,
)
} else {
samples_left.insert(0, 0.0);
samples_left.insert(0, 0.0);
samples_right.insert(0, 0.0);
samples_right.insert(0, 0.0);
samples_left.push(0.0);
samples_left.push(0.0);
samples_right.push(0.0);
samples_right.push(0.0);
(
samples_left.len() - 4,
samples_left.to_vec(),
samples_right.to_vec(),
)
};
self.buffer_lengths.insert(buffer_id, buflen);
self.buffer_types.insert(buffer_id, BufferType::Stereo);
self.control_q_send
.send(ControlMessage::LoadSample(
buffer_id,
buflen,
SampleBuffer::Stereo(buffer_left, buffer_right),
))
.unwrap();
buffer_id
}
}