use audiopus::{
coder::{Decoder, Encoder},
Application, Channels, SampleRate,
};
use crate::audio_process::resamplers::{ResamplerQuality, StreamResampler};
const OPUS_RATE: u32 = 48_000;
const OPUS_FRAME_SAMPLES: usize = 960;
pub trait Denoiser48k: Send {
fn process(&mut self, pcm_48k: &[i16]) -> Vec<i16>;
fn flush(&mut self) -> Vec<i16>;
fn reset(&mut self);
}
pub struct OpusInbound {
decoder: Decoder,
denoiser: Option<Box<dyn Denoiser48k>>,
resampler: Option<StreamResampler>, out_rate: u32,
pcm_48k: Vec<i16>, }
impl OpusInbound {
pub fn new(out_rate: u32, denoiser: Option<Box<dyn Denoiser48k>>) -> Self {
let decoder = Decoder::new(SampleRate::Hz48000, Channels::Mono)
.expect("failed to create Opus decoder");
let resampler = (out_rate != OPUS_RATE)
.then(|| StreamResampler::new(OPUS_RATE, out_rate, ResamplerQuality::Quick));
Self {
decoder,
denoiser,
resampler,
out_rate,
pcm_48k: vec![0i16; OPUS_FRAME_SAMPLES * 6],
}
}
pub fn push_rtp(&mut self, opus_payload: &[u8]) -> bytes::Bytes {
if opus_payload.is_empty() {
return bytes::Bytes::new();
}
let n = match self
.decoder
.decode(Some(opus_payload), &mut self.pcm_48k[..], false)
{
Ok(n) => n,
Err(e) => {
log::warn!("OpusInbound: decode error: {}", e);
return bytes::Bytes::new();
}
};
let mut pcm: Vec<i16> = self.pcm_48k[..n].to_vec();
if let Some(d) = self.denoiser.as_mut() {
pcm = d.process(&pcm);
if pcm.is_empty() {
return bytes::Bytes::new();
}
}
let out_samples: Vec<i16> = match self.resampler.as_mut() {
Some(r) => {
let f32_in: Vec<f32> = pcm.iter().map(|&s| s as f32 / 32_768.0).collect();
f32_to_i16(&r.process(&f32_in))
}
None => pcm,
};
if out_samples.is_empty() {
return bytes::Bytes::new();
}
let mut out = Vec::with_capacity(out_samples.len() * 2);
for s in out_samples {
out.extend_from_slice(&s.to_le_bytes());
}
bytes::Bytes::from(out)
}
pub fn out_rate(&self) -> u32 {
self.out_rate
}
}
pub struct OpusOutbound {
encoder: Encoder,
resampler: Option<StreamResampler>, src_rate: u32,
buf_48k: Vec<i16>, enc_out: Vec<u8>, }
impl OpusOutbound {
pub fn new() -> Self {
let encoder = Encoder::new(SampleRate::Hz48000, Channels::Mono, Application::Voip)
.expect("failed to create Opus encoder");
Self {
encoder,
resampler: None,
src_rate: 0,
buf_48k: Vec::with_capacity(OPUS_FRAME_SAMPLES * 4),
enc_out: vec![0u8; 4_000],
}
}
pub fn push_pcm(&mut self, pcm_bytes: &[u8], src_rate: u32) -> Vec<Vec<u8>> {
if self.src_rate != src_rate {
self.src_rate = src_rate;
self.resampler = (src_rate != OPUS_RATE)
.then(|| StreamResampler::new(src_rate, OPUS_RATE, ResamplerQuality::Quick));
self.buf_48k.clear();
}
let f32_in: Vec<f32> = pcm_bytes
.chunks_exact(2)
.map(|b| i16::from_le_bytes([b[0], b[1]]) as f32 / 32_768.0)
.collect();
let f32_48k = match self.resampler.as_mut() {
Some(r) => r.process(&f32_in),
None => f32_in,
};
self.buf_48k.extend(f32_48k.iter().map(|&s| {
(s * 32_768.0).clamp(-32_768.0, 32_767.0) as i16
}));
let mut packets = Vec::new();
while self.buf_48k.len() >= OPUS_FRAME_SAMPLES {
let frame: Vec<i16> = self.buf_48k.drain(..OPUS_FRAME_SAMPLES).collect();
match self.encoder.encode(&frame, &mut self.enc_out[..]) {
Ok(len) => packets.push(self.enc_out[..len].to_vec()),
Err(e) => log::warn!("OpusOutbound: encode error: {}", e),
}
}
packets
}
pub fn reset(&mut self) {
self.buf_48k.clear();
if let Some(r) = self.resampler.as_mut() {
r.reset();
}
}
}
impl Default for OpusOutbound {
fn default() -> Self {
Self::new()
}
}
fn f32_to_i16(samples: &[f32]) -> Vec<i16> {
samples
.iter()
.map(|&s| (s * 32_768.0).clamp(-32_768.0, 32_767.0) as i16)
.collect()
}