use float_eq::assert_float_eq;
use web_audio_api::buffer::AudioBuffer;
use web_audio_api::context::AsBaseAudioContext;
use web_audio_api::context::OfflineAudioContext;
use web_audio_api::media::MediaElement;
use web_audio_api::node::{AudioControllableSourceNode, AudioNode, AudioScheduledSourceNode};
use web_audio_api::{SampleRate, RENDER_QUANTUM_SIZE};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread;
use std::time::Duration;
struct SlowMedia {
block: Arc<AtomicBool>,
finished: Arc<AtomicBool>,
sample_rate: SampleRate,
value: f32,
}
impl Iterator for SlowMedia {
type Item = Result<AudioBuffer, Box<dyn std::error::Error + Send + Sync>>;
fn next(&mut self) -> Option<Self::Item> {
while self.block.load(Ordering::SeqCst) {}
self.block.store(true, Ordering::SeqCst);
if self.finished.load(Ordering::SeqCst) {
return None;
}
self.value += 1.;
let samples = vec![vec![self.value; RENDER_QUANTUM_SIZE]];
let buffer = AudioBuffer::from(samples, self.sample_rate);
Some(Ok(buffer))
}
}
#[test]
fn test_media_buffering() {
let mut context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, SampleRate(44_100));
let block = Arc::new(AtomicBool::new(true));
let finished = Arc::new(AtomicBool::new(false));
{
let media = SlowMedia {
block: block.clone(),
finished: finished.clone(),
sample_rate: SampleRate(44_100),
value: 1.,
};
let element = MediaElement::new(media);
let node = context.create_media_element_source(element);
node.connect(&context.destination());
node.set_loop(true); node.start();
}
let output = context.start_rendering();
assert_float_eq!(
output.get_channel_data(0),
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
block.store(false, Ordering::SeqCst); thread::sleep(Duration::from_millis(10));
let output = context.start_rendering();
assert_float_eq!(
output.get_channel_data(0),
&[2.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
let output = context.start_rendering();
assert_float_eq!(
output.get_channel_data(0),
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
block.store(false, Ordering::SeqCst); thread::sleep(Duration::from_millis(10));
let output = context.start_rendering();
assert_float_eq!(
output.get_channel_data(0),
&[3.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
finished.store(true, Ordering::SeqCst); block.store(false, Ordering::SeqCst); thread::sleep(Duration::from_millis(10));
let output = context.start_rendering();
assert_float_eq!(
output.get_channel_data(0),
&[2.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
let output = context.start_rendering();
assert_float_eq!(
output.get_channel_data(0),
&[3.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
let output = context.start_rendering();
assert_float_eq!(
output.get_channel_data(0),
&[2.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
}
#[test]
fn test_media_seeking() {
const SAMPLE_RATE: SampleRate = SampleRate(RENDER_QUANTUM_SIZE as u32); let mut context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, SAMPLE_RATE);
let block = Arc::new(AtomicBool::new(true));
{
let media = SlowMedia {
block: block.clone(),
finished: Arc::new(AtomicBool::new(false)),
sample_rate: SAMPLE_RATE,
value: 1.,
};
let element = MediaElement::new(media);
let node = context.create_media_element_source(element);
node.connect(&context.destination());
node.seek(2.); node.start();
}
let output = context.start_rendering();
assert_float_eq!(
output.get_channel_data(0),
&[0.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
block.store(false, Ordering::SeqCst); thread::sleep(Duration::from_millis(10)); block.store(false, Ordering::SeqCst); thread::sleep(Duration::from_millis(10)); block.store(false, Ordering::SeqCst); thread::sleep(Duration::from_millis(10));
let output = context.start_rendering();
assert_float_eq!(
output.get_channel_data(0),
&[4.; RENDER_QUANTUM_SIZE][..],
abs_all <= 0.
);
}