use rusty_opus::{Application, OpusEncoder};
use std::fs::File;
use std::io::{Read, Write};
fn main() {
let args: Vec<String> = std::env::args().collect();
if args.len() != 8 {
eprintln!(
"usage: encode_bit <rate> <channels> <bitrate_bps> <frame_ms> <voip|audio|lowdelay> <in.sw> <out.bit>"
);
std::process::exit(2);
}
let rate: i32 = args[1].parse().unwrap();
let channels: usize = args[2].parse().unwrap();
let bitrate: i32 = args[3].parse().unwrap();
let frame_ms: f64 = args[4].parse().unwrap();
let app = match args[5].as_str() {
"voip" => Application::Voip,
"lowdelay" => Application::RestrictedLowDelay,
_ => Application::Audio,
};
let frame_size = (rate as f64 * frame_ms / 1000.0) as usize;
let mut data = Vec::new();
File::open(&args[6]).unwrap().read_to_end(&mut data).unwrap();
let mut out = std::io::BufWriter::new(File::create(&args[7]).unwrap());
let mut enc = OpusEncoder::new(rate, channels, app).unwrap();
enc.bitrate_bps = bitrate;
enc.use_cbr = std::env::var("VBR").is_err();
enc.lsb_depth = 16;
enc.use_dtx = std::env::var("DTX").is_ok();
match std::env::var("SIGNAL").ok().as_deref() {
Some("voice") => enc.signal_type = Some(rusty_opus::SignalType::Voice),
Some("music") => enc.signal_type = Some(rusty_opus::SignalType::Music),
_ => {}
}
match std::env::var("MAXBW").ok().as_deref() {
Some("nb") => enc.max_bandwidth = rusty_opus::Bandwidth::Narrowband,
Some("wb") => enc.max_bandwidth = rusty_opus::Bandwidth::Wideband,
Some("swb") => enc.max_bandwidth = rusty_opus::Bandwidth::Superwideband,
_ => {}
}
if std::env::var("FEC").is_ok() {
enc.use_inband_fec = true;
enc.packet_loss_perc = 30;
}
if let Ok(bw) = std::env::var("FORCE_BW") {
enc.force_bandwidth = Some(match bw.as_str() {
"nb" => rusty_opus::Bandwidth::Narrowband,
"wb" => rusty_opus::Bandwidth::Wideband,
"swb" => rusty_opus::Bandwidth::Superwideband,
_ => rusty_opus::Bandwidth::Fullband,
});
}
let samples_per_frame = frame_size * channels;
let total_samples = data.len() / 2;
let mut pcm = vec![0f32; samples_per_frame];
let mut packet = vec![0u8; 4000];
let (mut pos, mut packets, mut bytes) = (0usize, 0u64, 0u64);
while pos + samples_per_frame <= total_samples {
for (i, v) in pcm.iter_mut().enumerate() {
let off = (pos + i) * 2;
*v = i16::from_le_bytes([data[off], data[off + 1]]) as f32 / 32768.0;
}
let n = match enc.encode(&pcm, frame_size, &mut packet) {
Ok(n) => n,
Err(e) => {
eprintln!("encode error at packet {packets}: {e}");
std::process::exit(1);
}
};
out.write_all(&(n as u32).to_be_bytes()).unwrap();
out.write_all(&enc.final_range().to_be_bytes()).unwrap();
out.write_all(&packet[..n]).unwrap();
pos += samples_per_frame;
packets += 1;
bytes += n as u64;
}
let dur = (pos / channels) as f64 / rate as f64;
eprintln!(
" packets={packets} bytes={bytes} ({:.1} kbps over {:.1}s)",
bytes as f64 * 8.0 / dur / 1000.0,
dur
);
}