use std::thread;
use std::time::Duration;
use audio_opus_bsd::{AudioEncoder, OpusDecodeWorker, OpusEncoder};
const SAMPLE_RATE: u32 = 48_000;
const CHANNELS: u16 = 1;
const BLOCK: usize = 960;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut enc = OpusEncoder::new(SAMPLE_RATE, CHANNELS, opus::Application::Audio)?;
enc.set_bitrate(64_000);
let packets: Vec<Vec<u8>> = (0..50)
.map(|b| {
let pcm: Vec<f32> = (0..BLOCK)
.map(|i| {
let idx = b * BLOCK + i;
0.5 * (2.0 * std::f32::consts::PI * 440.0 * idx as f32 / SAMPLE_RATE as f32)
.sin()
})
.collect();
enc.encode(&pcm).expect("encode")
})
.collect();
let total_bytes: usize = packets.iter().map(Vec::len).sum();
eprintln!(
"encoded {} packets ({} bytes total)",
packets.len(),
total_bytes
);
let (mut worker, mut rt_consumer) = OpusDecodeWorker::new(SAMPLE_RATE, CHANNELS, 64)?;
for pkt in &packets {
assert!(
worker.submit_packet(pkt.clone()),
"input ring unexpectedly full"
);
}
let want = packets.len();
let mut received = 0usize;
let mut poll = 0u32;
while received < want && poll < 50_000 {
while let Ok(frame) = rt_consumer.pop() {
received += 1;
assert_eq!(frame.channels, CHANNELS);
assert_eq!(frame.num_frames(), BLOCK);
if received >= want {
break;
}
}
if received < want {
thread::sleep(Duration::from_micros(200));
poll += 1;
}
}
drop(rt_consumer);
worker.join().expect("worker join");
eprintln!("RT loop received {received}/{want} AudioFrames via wait-free pop");
assert_eq!(received, want, "underrun: not all frames decoded in time");
eprintln!("OK — RT-safe Opus decode pipeline verified.");
Ok(())
}