use crate::{Error, Result};
use crate::encoder::MAX_ENCODING_DEPTH;
use crate::repacketizer::{Repacketizer, take_self_delimited_into};
use crate::soft_clip::{float_to_i16, i16_to_float};
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(Debug, Clone)]
pub struct ChannelLayout {
pub mapping_family: u8,
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: u8) -> Result<Self> {
match mapping_family {
0 => {
if channels == 1 {
Ok(ChannelLayout {
mapping_family: 0,
nb_channels: 1,
nb_streams: 1,
nb_coupled_streams: 0,
mapping: vec![0],
})
} else if channels == 2 {
Ok(ChannelLayout {
mapping_family: 0,
nb_channels: 2,
nb_streams: 1,
nb_coupled_streams: 1,
mapping: vec![0, 1],
})
} else {
Err(Error::InvalidArgument(
"family 0 supports only 1-2 channels",
))
}
}
1 => {
if !(1..=8).contains(&channels) {
return Err(Error::InvalidArgument("family 1 supports 1-8 channels"));
}
let (ns, nc, m) = VORBIS_MAPPINGS[channels - 1];
Ok(ChannelLayout {
mapping_family: 1,
nb_channels: channels,
nb_streams: ns,
nb_coupled_streams: nc,
mapping: m.to_vec(),
})
}
_ => Err(Error::InvalidArgument("unsupported mapping family")),
}
}
fn channels_for(&self, target: usize) -> impl Iterator<Item = usize> + '_ {
self.mapping
.iter()
.enumerate()
.filter_map(move |(i, &m)| (m as usize == target).then_some(i))
}
fn left_target(stream_id: usize) -> usize {
stream_id * 2
}
fn right_target(stream_id: usize) -> usize {
stream_id * 2 + 1
}
fn mono_target(&self, stream_id: usize) -> usize {
stream_id + self.nb_coupled_streams
}
}
pub struct OpusMSEncoder {
layout: ChannelLayout,
encoders: Vec<OpusEncoder>,
sample_rate: i32,
bitrate_bps: i32,
buf_stream: Vec<f32>,
buf_packet: Vec<u8>,
buf_out: Vec<u8>,
buf_from_s16: Vec<f32>,
framer: Repacketizer,
}
impl std::fmt::Debug for OpusMSEncoder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OpusMSEncoder")
.field("sample_rate", &self.sample_rate)
.field("bitrate_bps", &self.bitrate_bps)
.field("layout", &self.layout)
.finish_non_exhaustive()
}
}
impl OpusMSEncoder {
pub fn new(
sample_rate: i32,
channels: usize,
mapping_family: u8,
application: Application,
) -> Result<Self> {
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,
buf_stream: Vec::new(),
buf_packet: Vec::new(),
buf_out: Vec::new(),
buf_from_s16: Vec::new(),
framer: Repacketizer::new(),
};
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 layout(&self) -> &ChannelLayout {
&self.layout
}
pub fn bitrate_bps(&self) -> i32 {
self.bitrate_bps
}
pub fn streams_mut(&mut self) -> &mut [OpusEncoder] {
&mut self.encoders
}
pub fn streams(&self) -> &[OpusEncoder] {
&self.encoders
}
pub fn encode(&mut self, input: &[f32], frame_size: usize, output: &mut [u8]) -> Result<usize> {
self.encode_native(input, frame_size, output, MAX_ENCODING_DEPTH)
}
pub fn encode_s16(
&mut self,
input: &[i16],
frame_size: usize,
output: &mut [u8],
) -> Result<usize> {
let wanted = frame_size * self.layout.nb_channels;
if input.len() < wanted {
return Err(Error::InvalidArgument(
"input is shorter than frame_size * channels",
));
}
let mut converted = std::mem::take(&mut self.buf_from_s16);
converted.clear();
converted.extend(input[..wanted].iter().copied().map(i16_to_float));
let r = self.encode_native(&converted, frame_size, output, 16);
self.buf_from_s16 = converted;
r
}
fn encode_native(
&mut self,
input: &[f32],
frame_size: usize,
output: &mut [u8],
api_lsb_depth: i32,
) -> Result<usize> {
let nch = self.layout.nb_channels;
if input.len() < frame_size * nch {
return Err(Error::InvalidArgument(
"input is shorter than frame_size * channels",
));
}
let mut stream_buf = std::mem::take(&mut self.buf_stream);
let mut pkt = std::mem::take(&mut self.buf_packet);
let mut out = std::mem::take(&mut self.buf_out);
let mut framer = std::mem::take(&mut self.framer);
stream_buf.clear();
stream_buf.resize(frame_size * 2, 0.0);
pkt.clear();
pkt.resize(1500 + frame_size, 0);
out.clear();
let result = (|| -> Result<usize> {
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
.channels_for(ChannelLayout::left_target(s))
.next();
let r = self
.layout
.channels_for(ChannelLayout::right_target(s))
.next();
for i in 0..frame_size {
stream_buf[i * 2] = l.map_or(0.0, |c| input[i * nch + c]);
stream_buf[i * 2 + 1] = r.map_or(0.0, |c| input[i * nch + c]);
}
} else {
let m = self.layout.channels_for(self.layout.mono_target(s)).next();
for i in 0..frame_size {
stream_buf[i] = m.map_or(0.0, |c| input[i * nch + c]);
}
}
let n = self.encoders[s].encode_native(
&stream_buf[..frame_size * sch],
frame_size,
&mut pkt,
api_lsb_depth,
)?;
if s != self.layout.nb_streams - 1 {
framer.clear();
framer.cat(&pkt[..n])?;
framer.out_self_delimited_into(&mut out)?;
} else {
out.extend_from_slice(&pkt[..n]);
}
}
if output.len() < out.len() {
return Err(Error::buffer_too_small(out.len(), output.len()));
}
output[..out.len()].copy_from_slice(&out);
Ok(out.len())
})();
self.buf_stream = stream_buf;
self.buf_packet = pkt;
self.buf_out = out;
self.framer = framer;
result
}
pub fn sample_rate(&self) -> i32 {
self.sample_rate
}
pub fn channels(&self) -> usize {
self.layout.nb_channels
}
pub fn reset_state(&mut self) -> Result<()> {
for e in &mut self.encoders {
e.reset_state()?;
}
Ok(())
}
}
pub struct OpusMSDecoder {
layout: ChannelLayout,
decoders: Vec<OpusDecoder>,
buf_stream: Vec<f32>,
buf_f32: Vec<f32>,
buf_rebuilt: Vec<u8>,
}
impl std::fmt::Debug for OpusMSDecoder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OpusMSDecoder")
.field("layout", &self.layout)
.finish_non_exhaustive()
}
}
impl OpusMSDecoder {
pub fn new(sample_rate: i32, channels: usize, mapping_family: u8) -> Result<Self> {
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,
buf_stream: Vec::new(),
buf_f32: Vec::new(),
buf_rebuilt: Vec::new(),
})
}
pub fn decode(
&mut self,
packet: &[u8],
frame_size: usize,
output: &mut [f32],
) -> Result<usize> {
self.decode_native(packet, frame_size, output, false)
}
pub fn decode_s16(
&mut self,
packet: &[u8],
frame_size: usize,
output: &mut [i16],
) -> Result<usize> {
let nch = self.layout.nb_channels;
let capacity = frame_size * nch;
if output.len() < capacity {
return Err(Error::buffer_too_small(capacity, output.len()));
}
let mut pcm = std::mem::take(&mut self.buf_f32);
pcm.clear();
pcm.resize(capacity, 0.0);
let result = self.decode_native(packet, frame_size, &mut pcm, true);
if let Ok(produced) = result {
let n = produced * nch;
for (o, &s) in output[..n].iter_mut().zip(&pcm[..n]) {
*o = float_to_i16(s);
}
}
self.buf_f32 = pcm;
result
}
fn decode_native(
&mut self,
packet: &[u8],
frame_size: usize,
output: &mut [f32],
soft_clip: bool,
) -> Result<usize> {
let nch = self.layout.nb_channels;
if output.len() < frame_size * nch {
return Err(Error::buffer_too_small(frame_size * nch, output.len()));
}
let mut buf = std::mem::take(&mut self.buf_stream);
let mut rebuilt = std::mem::take(&mut self.buf_rebuilt);
buf.clear();
buf.resize(frame_size * 2, 0.0);
let mut data = packet;
let mut produced = frame_size;
let result = (|| -> Result<usize> {
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 off = take_self_delimited_into(data, &mut rebuilt)?;
(rebuilt.as_slice(), off)
};
let n = self.decoders[s].decode_native(
stream_slice,
frame_size,
&mut buf,
soft_clip,
)?;
produced = n;
if coupled {
for chan in self.layout.channels_for(ChannelLayout::left_target(s)) {
for i in 0..n {
output[i * nch + chan] = buf[i * 2];
}
}
for chan in self.layout.channels_for(ChannelLayout::right_target(s)) {
for i in 0..n {
output[i * nch + chan] = buf[i * 2 + 1];
}
}
} else {
for chan in self.layout.channels_for(self.layout.mono_target(s)) {
for i in 0..n {
output[i * nch + chan] = buf[i];
}
}
}
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)
})();
self.buf_stream = buf;
self.buf_rebuilt = rebuilt;
result
}
pub fn layout(&self) -> &ChannelLayout {
&self.layout
}
pub fn nb_streams(&self) -> usize {
self.layout.nb_streams
}
pub fn channels(&self) -> usize {
self.layout.nb_channels
}
pub fn sample_rate(&self) -> i32 {
self.decoders[0].sample_rate()
}
pub fn streams_mut(&mut self) -> &mut [OpusDecoder] {
&mut self.decoders
}
pub fn streams(&self) -> &[OpusDecoder] {
&self.decoders
}
pub fn reset_state(&mut self) -> Result<()> {
for d in &mut self.decoders {
d.reset_state()?;
}
Ok(())
}
}
impl OpusMSEncoder {
pub fn set_max_bandwidth(&mut self, bw: Bandwidth) {
for e in &mut self.encoders {
e.max_bandwidth = bw;
}
}
}