audio_processor_utility/
pan.rs1use audio_processor_traits::{AudioBuffer, AudioProcessor};
24use audio_processor_traits::{AudioContext, Float};
25
26pub struct PanProcessor<SampleType> {
30 panning: SampleType,
33}
34
35impl<SampleType: Float> Default for PanProcessor<SampleType> {
36 fn default() -> Self {
37 Self::new(SampleType::from(0.0).unwrap())
38 }
39}
40
41impl<SampleType: Float> PanProcessor<SampleType> {
42 pub fn new(panning: SampleType) -> Self {
45 PanProcessor { panning }
46 }
47
48 pub fn panning(&self) -> SampleType {
50 self.panning
51 }
52
53 pub fn set_panning(&mut self, panning: SampleType) {
57 self.panning = panning;
58 }
59}
60
61impl<SampleType> AudioProcessor for PanProcessor<SampleType>
62where
63 SampleType: Float + Sync + Send,
64{
65 type SampleType = SampleType;
66
67 fn process(&mut self, _context: &mut AudioContext, buffer: &mut AudioBuffer<SampleType>) {
68 for sample_num in 0..buffer.num_samples() {
69 let zero = SampleType::zero();
70 let one = SampleType::one();
71 let panning = self.panning;
72
73 let left_input = *buffer.get(0, sample_num);
74 let right_input = *buffer.get(0, sample_num);
75
76 if panning > zero {
77 let left_output = left_input * (one - panning);
78 let right_output = right_input + left_input * panning;
79
80 buffer.set(0, sample_num, left_output);
81 buffer.set(1, sample_num, right_output);
82 } else if panning < zero {
83 let left_output = left_input + right_input * (-panning);
84 let right_output = right_input * (one + panning);
85
86 buffer.set(0, sample_num, left_output);
87 buffer.set(1, sample_num, right_output);
88 }
89 }
90 }
91}
92
93#[cfg(test)]
94mod test {
95 use audio_processor_testing_helpers::assert_f_eq;
96 use audio_processor_traits::AudioBuffer;
97
98 use super::*;
99
100 #[test]
101 fn test_pan_noop() {
102 let mut pan = PanProcessor::default();
103 let samples = [1., 1., 1., 1., 1., 1.];
104 let mut input = AudioBuffer::from_interleaved(2, &samples);
105 let mut context = AudioContext::default();
106
107 pan.process(&mut context, &mut input);
108
109 for sample_num in 0..input.num_samples() {
110 for channel_num in 0..input.num_channels() {
111 let sample = input.get(channel_num, sample_num);
112 assert_f_eq!(*sample, 1.);
113 }
114 }
115 }
116
117 #[test]
118 fn test_hard_pan_to_left() {
119 let mut pan = PanProcessor::new(-1.0);
120 let samples = [1., 1., 1., 1., 1., 1.];
121 let mut input = AudioBuffer::from_interleaved(2, &samples);
122 let mut context = AudioContext::default();
123
124 pan.process(&mut context, &mut input);
125
126 for sample_index in 0..input.num_samples() {
127 let left = *input.get(0, sample_index);
128 let right = *input.get(1, sample_index);
129 assert_f_eq!(left, 2.0);
130 assert_f_eq!(right, 0.0);
131 }
132 }
133
134 #[test]
135 fn test_hard_pan_to_right() {
136 let mut pan = PanProcessor::new(1.0);
137 let samples = [1., 1., 1., 1., 1., 1.];
138 let mut input = AudioBuffer::from_interleaved(2, &samples);
139 let mut context = AudioContext::default();
140
141 pan.process(&mut context, &mut input);
142
143 for sample_index in 0..input.num_samples() {
144 let left = *input.get(0, sample_index);
145 let right = *input.get(1, sample_index);
146 assert_f_eq!(right, 2.0);
147 assert_f_eq!(left, 0.0);
148 }
149 }
150}