mod import;
pub use import::*;
use bytes::{Buf, Bytes};
const OPUS_HEAD: u64 = u64::from_be_bytes(*b"OpusHead");
pub struct Config {
pub sample_rate: u32,
pub channel_count: u32,
}
impl Config {
pub fn parse<T: Buf>(buf: &mut T) -> anyhow::Result<Self> {
anyhow::ensure!(buf.remaining() >= 19, "OpusHead must be at least 19 bytes");
let signature = buf.get_u64();
anyhow::ensure!(signature == OPUS_HEAD, "invalid OpusHead signature");
buf.advance(1); let channel_count = buf.get_u8() as u32;
buf.advance(2); let sample_rate = buf.get_u32_le();
if buf.remaining() > 0 {
buf.advance(buf.remaining());
}
Ok(Self {
sample_rate,
channel_count,
})
}
pub fn encode(&self) -> Bytes {
assert!(
self.channel_count <= 2,
"OpusHead mapping family 0 only supports mono/stereo (got channel_count={})",
self.channel_count
);
let mut head = Vec::with_capacity(19);
head.extend_from_slice(b"OpusHead");
head.push(1); head.push(self.channel_count as u8);
head.extend_from_slice(&0u16.to_le_bytes()); head.extend_from_slice(&self.sample_rate.to_le_bytes());
head.extend_from_slice(&0i16.to_le_bytes()); head.push(0); Bytes::from(head)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parses_valid_opus_head() {
let cfg = Config {
sample_rate: 48000,
channel_count: 2,
};
let encoded = cfg.encode();
assert_eq!(encoded.len(), 19);
let parsed = Config::parse(&mut encoded.as_ref()).unwrap();
assert_eq!(parsed.sample_rate, 48000);
assert_eq!(parsed.channel_count, 2);
}
#[test]
fn parse_rejects_invalid_signature() {
let mut bytes = Config {
sample_rate: 48000,
channel_count: 1,
}
.encode()
.to_vec();
bytes[0] = b'X';
assert!(Config::parse(&mut bytes.as_slice()).is_err());
}
#[test]
#[should_panic(expected = "mapping family 0")]
fn encode_panics_for_multichannel() {
Config {
sample_rate: 48000,
channel_count: 6,
}
.encode();
}
}