use crate::repacketizer::{parse_packet, Repacketizer};
use crate::{Application, Bandwidth, OpusDecoder, OpusEncoder};
const VORBIS_MAPPINGS: [(usize, usize, &[u8]); 8] = [
(1, 0, &[0]), (1, 1, &[0, 1]), (2, 1, &[0, 2, 1]), (2, 2, &[0, 1, 2, 3]), (3, 2, &[0, 4, 1, 2, 3]), (4, 2, &[0, 4, 1, 2, 3, 5]), (4, 3, &[0, 4, 1, 2, 3, 5, 6]), (5, 3, &[0, 6, 1, 2, 3, 4, 5, 7]), ];
#[derive(Clone)]
pub struct ChannelLayout {
pub nb_channels: usize,
pub nb_streams: usize,
pub nb_coupled_streams: usize,
pub mapping: Vec<u8>,
}
impl ChannelLayout {
pub fn surround(channels: usize, mapping_family: i32) -> Result<Self, &'static str> {
match mapping_family {
0 => {
if channels == 1 {
Ok(ChannelLayout {
nb_channels: 1,
nb_streams: 1,
nb_coupled_streams: 0,
mapping: vec![0],
})
} else if channels == 2 {
Ok(ChannelLayout {
nb_channels: 2,
nb_streams: 1,
nb_coupled_streams: 1,
mapping: vec![0, 1],
})
} else {
Err("family 0 supports only 1-2 channels")
}
}
1 => {
if !(1..=8).contains(&channels) {
return Err("family 1 supports 1-8 channels");
}
let (ns, nc, m) = VORBIS_MAPPINGS[channels - 1];
Ok(ChannelLayout {
nb_channels: channels,
nb_streams: ns,
nb_coupled_streams: nc,
mapping: m.to_vec(),
})
}
_ => Err("unsupported mapping family"),
}
}
fn left_channel(&self, stream_id: usize, prev: i32) -> i32 {
let start = if prev < 0 { 0 } else { prev as usize + 1 };
for (i, &m) in self.mapping.iter().enumerate().skip(start) {
if m as usize == stream_id * 2 {
return i as i32;
}
}
-1
}
fn right_channel(&self, stream_id: usize, prev: i32) -> i32 {
let start = if prev < 0 { 0 } else { prev as usize + 1 };
for (i, &m) in self.mapping.iter().enumerate().skip(start) {
if m as usize == stream_id * 2 + 1 {
return i as i32;
}
}
-1
}
fn mono_channel(&self, stream_id: usize, prev: i32) -> i32 {
let start = if prev < 0 { 0 } else { prev as usize + 1 };
for (i, &m) in self.mapping.iter().enumerate().skip(start) {
if m as usize == stream_id + self.nb_coupled_streams {
return i as i32;
}
}
-1
}
}
pub struct OpusMSEncoder {
layout: ChannelLayout,
encoders: Vec<OpusEncoder>,
sample_rate: i32,
pub bitrate_bps: i32,
}
impl OpusMSEncoder {
pub fn new(
sample_rate: i32,
channels: usize,
mapping_family: i32,
application: Application,
) -> Result<Self, &'static str> {
let layout = ChannelLayout::surround(channels, mapping_family)?;
let mut encoders = Vec::with_capacity(layout.nb_streams);
for s in 0..layout.nb_streams {
let ch = if s < layout.nb_coupled_streams { 2 } else { 1 };
encoders.push(OpusEncoder::new(sample_rate, ch, application)?);
}
let mut enc = OpusMSEncoder {
layout,
encoders,
sample_rate,
bitrate_bps: 64000 * channels as i32,
};
enc.set_bitrate(enc.bitrate_bps);
Ok(enc)
}
pub fn set_bitrate(&mut self, total: i32) {
self.bitrate_bps = total;
let units = self.layout.nb_coupled_streams * 2
+ (self.layout.nb_streams - self.layout.nb_coupled_streams);
let per_unit = if units > 0 { total / units as i32 } else { total };
for (s, e) in self.encoders.iter_mut().enumerate() {
e.bitrate_bps = if s < self.layout.nb_coupled_streams {
per_unit * 2
} else {
per_unit
};
}
}
pub fn nb_streams(&self) -> usize {
self.layout.nb_streams
}
pub fn encode(&mut self, input: &[f32], frame_size: usize) -> Result<Vec<u8>, &'static str> {
let nch = self.layout.nb_channels;
let mut out: Vec<u8> = Vec::new();
let mut stream_buf = vec![0f32; frame_size * 2];
let mut pkt = vec![0u8; 1500 + frame_size];
for s in 0..self.layout.nb_streams {
let coupled = s < self.layout.nb_coupled_streams;
let sch = if coupled { 2 } else { 1 };
if coupled {
let l = self.layout.left_channel(s, -1);
let r = self.layout.right_channel(s, -1);
for i in 0..frame_size {
stream_buf[i * 2] = if l >= 0 { input[i * nch + l as usize] } else { 0.0 };
stream_buf[i * 2 + 1] =
if r >= 0 { input[i * nch + r as usize] } else { 0.0 };
}
} else {
let m = self.layout.mono_channel(s, -1);
for i in 0..frame_size {
stream_buf[i] = if m >= 0 { input[i * nch + m as usize] } else { 0.0 };
}
}
let n = self.encoders[s].encode(&stream_buf[..frame_size * sch], frame_size, &mut pkt)?;
if s != self.layout.nb_streams - 1 {
let mut rp = Repacketizer::new();
rp.cat(&pkt[..n])?;
out.extend_from_slice(&rp.out_self_delimited()?);
} else {
out.extend_from_slice(&pkt[..n]);
}
}
Ok(out)
}
pub fn sample_rate(&self) -> i32 {
self.sample_rate
}
}
pub struct OpusMSDecoder {
layout: ChannelLayout,
decoders: Vec<OpusDecoder>,
}
impl OpusMSDecoder {
pub fn new(
sample_rate: i32,
channels: usize,
mapping_family: i32,
) -> Result<Self, &'static str> {
let layout = ChannelLayout::surround(channels, mapping_family)?;
let mut decoders = Vec::with_capacity(layout.nb_streams);
for s in 0..layout.nb_streams {
let ch = if s < layout.nb_coupled_streams { 2 } else { 1 };
decoders.push(OpusDecoder::new(sample_rate, ch)?);
}
Ok(OpusMSDecoder { layout, decoders })
}
pub fn decode(
&mut self,
packet: &[u8],
frame_size: usize,
output: &mut [f32],
) -> Result<usize, &'static str> {
let nch = self.layout.nb_channels;
let mut buf = vec![0f32; frame_size * 2];
let mut data = packet;
let mut produced = frame_size;
for s in 0..self.layout.nb_streams {
let coupled = s < self.layout.nb_coupled_streams;
let last = s == self.layout.nb_streams - 1;
let (stream_slice, advance) = if last {
(data, data.len())
} else {
let (_toc, _frames, off) = parse_packet(data, true)?;
(&data[..off], off)
};
let n = self.decoders[s].decode(stream_slice, frame_size, &mut buf)?;
produced = n;
if coupled {
let mut prev = -1;
loop {
let chan = self.layout.left_channel(s, prev);
if chan == -1 {
break;
}
for i in 0..n {
output[i * nch + chan as usize] = buf[i * 2];
}
prev = chan;
}
let mut prev = -1;
loop {
let chan = self.layout.right_channel(s, prev);
if chan == -1 {
break;
}
for i in 0..n {
output[i * nch + chan as usize] = buf[i * 2 + 1];
}
prev = chan;
}
} else {
let mut prev = -1;
loop {
let chan = self.layout.mono_channel(s, prev);
if chan == -1 {
break;
}
for i in 0..n {
output[i * nch + chan as usize] = buf[i];
}
prev = chan;
}
}
if !last {
data = &data[advance..];
}
}
for c in 0..nch {
if self.layout.mapping.get(c).copied() == Some(255) {
for i in 0..produced {
output[i * nch + c] = 0.0;
}
}
}
Ok(produced)
}
}
impl OpusMSEncoder {
pub fn set_max_bandwidth(&mut self, bw: Bandwidth) {
for e in &mut self.encoders {
e.max_bandwidth = bw;
}
}
}