use std::sync::{
Arc,
atomic::{AtomicU32, Ordering},
};
use kira::{
AudioManager, AudioManagerSettings, Frame,
backend::mock::{MockBackend, MockBackendSettings},
effect::{Effect, EffectBuilder},
info::Info,
track::TrackBuilder,
};
use rtrb::{Consumer, Producer, RingBuffer};
struct TestEffect {
sample_rate: Arc<AtomicU32>,
dt_producer: Producer<f64>,
}
impl Effect for TestEffect {
fn init(&mut self, sample_rate: u32, _internal_buffer_size: usize) {
self.sample_rate.store(sample_rate, Ordering::SeqCst);
}
fn on_change_sample_rate(&mut self, sample_rate: u32) {
self.sample_rate.store(sample_rate, Ordering::SeqCst);
}
fn process(&mut self, _input: &mut [Frame], dt: f64, _info: &Info) {
self.dt_producer.push(dt).unwrap();
}
}
struct TestEffectHandle {
sample_rate: Arc<AtomicU32>,
dt_consumer: Consumer<f64>,
}
struct TestEffectBuilder;
impl EffectBuilder for TestEffectBuilder {
type Handle = TestEffectHandle;
fn build(self) -> (Box<dyn Effect>, Self::Handle) {
let (dt_producer, dt_consumer) = RingBuffer::new(100);
let sample_rate = Arc::new(AtomicU32::new(0));
(
Box::new(TestEffect {
sample_rate: sample_rate.clone(),
dt_producer,
}),
TestEffectHandle {
sample_rate,
dt_consumer,
},
)
}
}
#[test]
fn change_sample_rate() {
let mut manager = AudioManager::<MockBackend>::new(AudioManagerSettings {
backend_settings: MockBackendSettings { sample_rate: 100 },
..Default::default()
})
.unwrap();
let mut effect_handle;
let _track = manager
.add_sub_track({
let mut builder = TrackBuilder::new();
effect_handle = builder.add_effect(TestEffectBuilder);
builder
})
.unwrap();
let backend = manager.backend_mut();
backend.on_start_processing();
assert_eq!(effect_handle.sample_rate.load(Ordering::SeqCst), 100);
backend.process();
assert_eq!(effect_handle.dt_consumer.pop(), Ok(1.0 / 100.0));
backend.set_sample_rate(200);
assert_eq!(effect_handle.sample_rate.load(Ordering::SeqCst), 200);
backend.process();
assert_eq!(effect_handle.dt_consumer.pop(), Ok(1.0 / 200.0));
}