use audio_garbage_collector::{make_shared, Shared};
use std::marker::PhantomData;
use std::ops::Mul;
use audio_processor_traits::simple_processor::MonoAudioProcessor;
use audio_processor_traits::{AtomicF32, AudioContext, Float};
pub struct GainProcessorHandle {
gain: AtomicF32,
}
impl GainProcessorHandle {
pub fn new(gain: impl Into<f32>) -> Self {
Self {
gain: AtomicF32::new(gain.into()),
}
}
pub fn set_gain(&self, gain: impl Into<f32>) {
self.gain.set(gain.into());
}
pub fn gain(&self) -> f32 {
self.gain.get()
}
}
pub struct GainProcessor<SampleType> {
handle: Shared<GainProcessorHandle>,
phantom: PhantomData<SampleType>,
}
impl<SampleType> Default for GainProcessor<SampleType> {
fn default() -> Self {
Self::new(1.0)
}
}
impl<SampleType> GainProcessor<SampleType> {
pub fn new(gain: impl Into<f32>) -> Self {
Self::new_with_handle(make_shared(GainProcessorHandle::new(gain)))
}
pub fn new_with_handle(handle: Shared<GainProcessorHandle>) -> Self {
Self {
handle,
phantom: PhantomData::default(),
}
}
pub fn set_gain(&self, gain: impl Into<f32>) {
self.handle.set_gain(gain)
}
pub fn gain(&self) -> f32 {
self.handle.gain()
}
pub fn handle(&self) -> &Shared<GainProcessorHandle> {
&self.handle
}
}
impl<SampleType> MonoAudioProcessor for GainProcessor<SampleType>
where
SampleType: Float + Send + Sync + Mul<Output = SampleType>,
{
type SampleType = SampleType;
fn m_process(&mut self, _context: &mut AudioContext, sample: SampleType) -> SampleType {
SampleType::from(self.gain()).unwrap() * sample
}
}
#[cfg(test)]
mod test {
use audio_processor_testing_helpers::assert_f_eq;
use audio_processor_traits::{simple_processor, AudioBuffer};
use super::*;
#[test]
fn test_gain_does_its_thing() {
let mut gain = GainProcessor::new(0.8);
let input = [1., 1., 1., 1., 1., 1.];
let mut input = AudioBuffer::from_interleaved(1, &input);
let mut context = AudioContext::default();
simple_processor::process_buffer(&mut context, &mut gain, &mut input);
for sample in input.channel(0) {
assert_f_eq!(*sample, 0.8);
}
}
#[test]
fn test_gain_can_be_changed() {
let mut gain = GainProcessor::default();
gain.set_gain(0.8);
let input = [1., 1., 1., 1., 1., 1.];
let mut input = AudioBuffer::from_interleaved(1, &input);
let mut context = AudioContext::default();
simple_processor::process_buffer(&mut context, &mut gain, &mut input);
for sample in input.channel(0) {
assert_f_eq!(*sample, 0.8);
}
}
}