#![allow(clippy::print_stderr)]
use std::hint::black_box;
use wacore::voip::{MlowDecoder, MlowEncoder};
#[cfg(feature = "dhat-heap")]
#[global_allocator]
static ALLOC: dhat::Alloc = dhat::Alloc;
const SAMPLES: usize = 960;
fn tone(phase: usize) -> Vec<f32> {
(0..SAMPLES)
.map(|i| 0.3 * (((i + phase) as f32) * 0.07).sin())
.collect()
}
#[inline(never)]
fn hot_encode(enc: &mut MlowEncoder, frames: &[Vec<f32>], n: usize) {
for k in 0..n {
black_box(enc.encode(black_box(&frames[k % frames.len()])).unwrap());
}
}
#[inline(never)]
fn hot_encode_into(enc: &mut MlowEncoder, frames: &[Vec<f32>], n: usize) {
let mut output = Vec::with_capacity(2048);
for k in 0..n {
enc.encode_into(black_box(&frames[k % frames.len()]), &mut output)
.unwrap();
black_box(output.as_slice());
}
}
#[inline(never)]
fn hot_decode(dec: &mut MlowDecoder, packets: &[Vec<u8>], n: usize) {
for k in 0..n {
black_box(dec.decode(black_box(&packets[k % packets.len()])));
}
}
fn main() {
let args: Vec<String> = std::env::args().collect();
let mode = args.get(1).map(String::as_str).unwrap_or("encode");
let n: usize = args.get(2).and_then(|s| s.parse().ok()).unwrap_or(30);
#[cfg(feature = "dhat-heap")]
let _profiler = dhat::Profiler::new_heap();
let frames: Vec<Vec<f32>> = (0..8).map(|i| tone(i * SAMPLES)).collect();
match mode {
"encode" => {
let mut enc = MlowEncoder::new();
let _ = enc.encode(&frames[0]); hot_encode(&mut enc, &frames, n);
}
"encode-into" => {
let mut enc = MlowEncoder::new();
let _ = enc.encode(&frames[0]);
hot_encode_into(&mut enc, &frames, n);
}
"decode" => {
let mut enc = MlowEncoder::new();
let _ = enc.encode(&frames[0]);
let packets: Vec<Vec<u8>> = frames.iter().map(|f| enc.encode(f).unwrap()).collect();
let mut dec = MlowDecoder::new();
let _ = dec.decode(&packets[0]); hot_decode(&mut dec, &packets, n);
}
other => eprintln!("usage: voip_profile <encode|encode-into|decode> <n>; got {other:?}"),
}
}