use audio_processor_traits::{AudioBuffer, AudioProcessor};
use audio_processor_traits::{AudioContext, Float};
pub struct PanProcessor<SampleType> {
panning: SampleType,
}
impl<SampleType: Float> Default for PanProcessor<SampleType> {
fn default() -> Self {
Self::new(SampleType::from(0.0).unwrap())
}
}
impl<SampleType: Float> PanProcessor<SampleType> {
pub fn new(panning: SampleType) -> Self {
PanProcessor { panning }
}
pub fn panning(&self) -> SampleType {
self.panning
}
pub fn set_panning(&mut self, panning: SampleType) {
self.panning = panning;
}
}
impl<SampleType> AudioProcessor for PanProcessor<SampleType>
where
SampleType: Float + Sync + Send,
{
type SampleType = SampleType;
fn process(&mut self, _context: &mut AudioContext, buffer: &mut AudioBuffer<SampleType>) {
for sample_num in 0..buffer.num_samples() {
let zero = SampleType::zero();
let one = SampleType::one();
let panning = self.panning;
let left_input = *buffer.get(0, sample_num);
let right_input = *buffer.get(0, sample_num);
if panning > zero {
let left_output = left_input * (one - panning);
let right_output = right_input + left_input * panning;
buffer.set(0, sample_num, left_output);
buffer.set(1, sample_num, right_output);
} else if panning < zero {
let left_output = left_input + right_input * (-panning);
let right_output = right_input * (one + panning);
buffer.set(0, sample_num, left_output);
buffer.set(1, sample_num, right_output);
}
}
}
}
#[cfg(test)]
mod test {
use audio_processor_testing_helpers::assert_f_eq;
use audio_processor_traits::AudioBuffer;
use super::*;
#[test]
fn test_pan_noop() {
let mut pan = PanProcessor::default();
let samples = [1., 1., 1., 1., 1., 1.];
let mut input = AudioBuffer::from_interleaved(2, &samples);
let mut context = AudioContext::default();
pan.process(&mut context, &mut input);
for sample_num in 0..input.num_samples() {
for channel_num in 0..input.num_channels() {
let sample = input.get(channel_num, sample_num);
assert_f_eq!(*sample, 1.);
}
}
}
#[test]
fn test_hard_pan_to_left() {
let mut pan = PanProcessor::new(-1.0);
let samples = [1., 1., 1., 1., 1., 1.];
let mut input = AudioBuffer::from_interleaved(2, &samples);
let mut context = AudioContext::default();
pan.process(&mut context, &mut input);
for sample_index in 0..input.num_samples() {
let left = *input.get(0, sample_index);
let right = *input.get(1, sample_index);
assert_f_eq!(left, 2.0);
assert_f_eq!(right, 0.0);
}
}
#[test]
fn test_hard_pan_to_right() {
let mut pan = PanProcessor::new(1.0);
let samples = [1., 1., 1., 1., 1., 1.];
let mut input = AudioBuffer::from_interleaved(2, &samples);
let mut context = AudioContext::default();
pan.process(&mut context, &mut input);
for sample_index in 0..input.num_samples() {
let left = *input.get(0, sample_index);
let right = *input.get(1, sample_index);
assert_f_eq!(right, 2.0);
assert_f_eq!(left, 0.0);
}
}
}