use super::traits::AudioProcessor;
pub struct DspChain {
processors: Vec<Box<dyn AudioProcessor>>,
}
impl DspChain {
pub fn new(_sample_rate: f64) -> Self {
Self {
processors: Vec::new(),
}
}
pub fn with_capacity(capacity: usize, _sample_rate: f64) -> Self {
Self {
processors: Vec::with_capacity(capacity),
}
}
pub fn add<P: AudioProcessor + 'static>(&mut self, processor: P) -> &mut Self {
self.processors.push(Box::new(processor));
self
}
pub fn process(&mut self, buffer: &mut [f64], channels: usize) {
for processor in &mut self.processors {
processor.process(buffer, channels);
}
}
pub fn reset(&mut self) {
for processor in &mut self.processors {
processor.reset();
}
}
pub fn set_sample_rate(&mut self, sample_rate: f64) {
for processor in &mut self.processors {
processor.set_sample_rate(sample_rate);
}
}
pub fn len(&self) -> usize {
self.processors.len()
}
pub fn is_empty(&self) -> bool {
self.processors.is_empty()
}
pub fn clear(&mut self) {
self.processors.clear();
}
}
impl Default for DspChain {
fn default() -> Self {
Self::new(44100.0)
}
}
#[cfg(test)]
mod tests {
use super::super::traits::ProcessResult;
use super::*;
struct DoublerProcessor {
enabled: bool,
processed_count: u64,
}
impl DoublerProcessor {
fn new() -> Self {
Self {
enabled: true,
processed_count: 0,
}
}
}
impl AudioProcessor for DoublerProcessor {
fn name(&self) -> &'static str {
"Doubler"
}
fn process(&mut self, buffer: &mut [f64], _channels: usize) -> ProcessResult {
if !self.enabled {
return ProcessResult::Bypassed;
}
for sample in buffer.iter_mut() {
*sample *= 2.0;
}
self.processed_count += 1;
ProcessResult::Ok
}
fn reset(&mut self) {
self.processed_count = 0;
}
fn is_enabled(&self) -> bool {
self.enabled
}
fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
}
struct AdderProcessor {
enabled: bool,
}
impl AdderProcessor {
fn new() -> Self {
Self { enabled: true }
}
}
impl AudioProcessor for AdderProcessor {
fn name(&self) -> &'static str {
"Adder"
}
fn process(&mut self, buffer: &mut [f64], _channels: usize) -> ProcessResult {
if !self.enabled {
return ProcessResult::Bypassed;
}
for sample in buffer.iter_mut() {
*sample += 1.0;
}
ProcessResult::Ok
}
fn reset(&mut self) {}
fn is_enabled(&self) -> bool {
self.enabled
}
fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
}
#[test]
fn test_empty_chain() {
let mut chain = DspChain::new(44100.0);
let mut buffer = vec![1.0, 2.0, 3.0];
chain.process(&mut buffer, 1);
assert_eq!(buffer, vec![1.0, 2.0, 3.0]);
}
#[test]
fn test_single_processor() {
let mut chain = DspChain::new(44100.0);
chain.add(DoublerProcessor::new());
let mut buffer = vec![1.0, 2.0, 3.0];
chain.process(&mut buffer, 1);
assert_eq!(buffer, vec![2.0, 4.0, 6.0]);
}
#[test]
fn test_chain_order() {
let mut chain = DspChain::new(44100.0);
chain.add(DoublerProcessor::new()); chain.add(AdderProcessor::new());
let mut buffer = vec![1.0];
chain.process(&mut buffer, 1);
assert_eq!(buffer, vec![3.0]);
}
#[test]
fn test_bypassed_processor() {
let mut chain = DspChain::new(44100.0);
let mut doubler = DoublerProcessor::new();
doubler.set_enabled(false);
chain.add(doubler);
let mut buffer = vec![5.0];
chain.process(&mut buffer, 1);
assert_eq!(buffer, vec![5.0]);
}
#[test]
fn test_reset() {
let mut chain = DspChain::new(44100.0);
chain.add(DoublerProcessor::new());
let mut buffer = vec![1.0; 100];
chain.process(&mut buffer, 1);
chain.reset();
}
}