audio_processor_utility/
gain.rs1use audio_garbage_collector::{make_shared, Shared};
24use std::marker::PhantomData;
25use std::ops::Mul;
26
27use audio_processor_traits::simple_processor::MonoAudioProcessor;
28use audio_processor_traits::{AtomicF32, AudioContext, Float};
29
30pub struct GainProcessorHandle {
31 gain: AtomicF32,
32}
33
34impl GainProcessorHandle {
35 pub fn new(gain: impl Into<f32>) -> Self {
36 Self {
37 gain: AtomicF32::new(gain.into()),
38 }
39 }
40
41 pub fn set_gain(&self, gain: impl Into<f32>) {
42 self.gain.set(gain.into());
43 }
44
45 pub fn gain(&self) -> f32 {
46 self.gain.get()
47 }
48}
49
50pub struct GainProcessor<SampleType> {
52 handle: Shared<GainProcessorHandle>,
53 phantom: PhantomData<SampleType>,
54}
55
56impl<SampleType> Default for GainProcessor<SampleType> {
57 fn default() -> Self {
59 Self::new(1.0)
60 }
61}
62
63impl<SampleType> GainProcessor<SampleType> {
64 pub fn new(gain: impl Into<f32>) -> Self {
66 Self::new_with_handle(make_shared(GainProcessorHandle::new(gain)))
67 }
68
69 pub fn new_with_handle(handle: Shared<GainProcessorHandle>) -> Self {
71 Self {
72 handle,
73 phantom: PhantomData::default(),
74 }
75 }
76
77 pub fn set_gain(&self, gain: impl Into<f32>) {
79 self.handle.set_gain(gain)
80 }
81
82 pub fn gain(&self) -> f32 {
84 self.handle.gain()
85 }
86
87 pub fn handle(&self) -> &Shared<GainProcessorHandle> {
88 &self.handle
89 }
90}
91
92impl<SampleType> MonoAudioProcessor for GainProcessor<SampleType>
93where
94 SampleType: Float + Send + Sync + Mul<Output = SampleType>,
95{
96 type SampleType = SampleType;
97
98 fn m_process(&mut self, _context: &mut AudioContext, sample: SampleType) -> SampleType {
99 SampleType::from(self.gain()).unwrap() * sample
100 }
101}
102
103#[cfg(test)]
104mod test {
105 use audio_processor_testing_helpers::assert_f_eq;
106 use audio_processor_traits::{simple_processor, AudioBuffer};
107
108 use super::*;
109
110 #[test]
111 fn test_gain_does_its_thing() {
112 let mut gain = GainProcessor::new(0.8);
113 let input = [1., 1., 1., 1., 1., 1.];
114 let mut input = AudioBuffer::from_interleaved(1, &input);
115
116 let mut context = AudioContext::default();
117 simple_processor::process_buffer(&mut context, &mut gain, &mut input);
118
119 for sample in input.channel(0) {
120 assert_f_eq!(*sample, 0.8);
121 }
122 }
123
124 #[test]
125 fn test_gain_can_be_changed() {
126 let mut gain = GainProcessor::default();
127 gain.set_gain(0.8);
128 let input = [1., 1., 1., 1., 1., 1.];
129 let mut input = AudioBuffer::from_interleaved(1, &input);
130
131 let mut context = AudioContext::default();
132 simple_processor::process_buffer(&mut context, &mut gain, &mut input);
133
134 for sample in input.channel(0) {
135 assert_f_eq!(*sample, 0.8);
136 }
137 }
138}