// SDD-120 §3 items 3-4 — Opus encode/decode latency benches. // // Both benches measure the codec-level call directly (audiopus // Encoder::encode_float / Decoder::decode_float) and not the // composite tsclientlib AudioHandler::fill_buffer call. Rationale // per SDD-120 §3 item 4: AudioHandler::fill_buffer conflates // jitter-buffer dequeue + Opus decode + PCM mix in a single call // and the wall-clock measurement would conflate three distinct // concerns. The canonical `opus_decode_latency` metric here is // codec-only. use audiopus::coder::{Decoder, Encoder}; use audiopus::packet::Packet; use audiopus::{Application, Channels, MutSignals, SampleRate}; use criterion::{black_box, criterion_group, criterion_main, Criterion}; use std::convert::TryFrom; mod common; use common::{synthetic_opus_bytes, synthetic_opus_frame}; fn bench_opus_encode_latency(c: &mut Criterion) { let enc = Encoder::new(SampleRate::Hz48000, Channels::Mono, Application::Voip) .expect("opus encoder init"); let pcm = synthetic_opus_frame(); let mut out = vec![0u8; 1275]; c.bench_function("opus_encode_latency", |b| { b.iter(|| { let len = enc .encode_float(black_box(&pcm[..]), &mut out[..]) .expect("encode"); black_box(len); }); }); } fn bench_opus_decode_latency(c: &mut Criterion) { let mut dec = Decoder::new(SampleRate::Hz48000, Channels::Mono).expect("opus decoder init"); let bytes = synthetic_opus_bytes(); let mut pcm_out = vec![0.0f32; 960]; c.bench_function("opus_decode_latency", |b| { b.iter(|| { let input = Packet::try_from(black_box(&bytes[..])).expect("packet"); let output = MutSignals::try_from(&mut pcm_out[..]).expect("signals"); let n = dec .decode_float(Some(input), output, false) .expect("decode"); black_box(n); }); }); } criterion_group!( opus_codec, bench_opus_encode_latency, bench_opus_decode_latency ); criterion_main!(opus_codec);