pub mod decode;
pub mod encode;
pub mod resample;
#[derive(thiserror::Error, Debug)]
pub enum AudioError {
#[error("decode failed: {0}")]
Decode(String),
#[error("encode failed: {0}")]
Encode(String),
#[error("resample failed: {0}")]
Resample(String),
#[error("unsupported: {0}")]
Unsupported(String),
}
#[derive(Clone, Debug)]
pub struct AudioFrame {
pub samples: Vec<f32>,
pub sample_rate: u32,
pub channels: u8,
pub pts: i64,
}
#[derive(Clone, Debug)]
pub struct EncodedAudioPacket {
pub data: Vec<u8>,
pub pts: i64,
pub duration: i64,
}
#[derive(Clone, Debug)]
pub struct AudioEncoderConfig {
pub codec: AudioCodec,
pub sample_rate: u32,
pub channels: u8,
pub bitrate: u32,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AudioCodec {
Opus,
}
pub trait AudioDecoder: Send {
fn decode(&mut self, packet: &[u8], pts: i64) -> Result<Vec<AudioFrame>, AudioError>;
fn flush(&mut self) -> Result<Vec<AudioFrame>, AudioError>;
}
pub trait AudioEncoder: Send {
fn encode(&mut self, frame: &AudioFrame) -> Result<Vec<EncodedAudioPacket>, AudioError>;
fn flush(&mut self) -> Result<Vec<EncodedAudioPacket>, AudioError>;
fn pre_skip(&self) -> u16;
fn extra_data(&self) -> Vec<u8>;
}
pub fn create_decoder(
codec: &str,
extra_data: Option<&[u8]>,
sample_rate: u32,
channels: u8,
) -> Result<Box<dyn AudioDecoder>, AudioError> {
match codec.to_ascii_lowercase().as_str() {
"mp3" | "mpeg" | "mp3a" => Ok(Box::new(decode::mp3::Mp3Decoder::new(
sample_rate,
channels,
)?)),
"vorbis" => Ok(Box::new(decode::vorbis::VorbisDecoder::new(
extra_data,
sample_rate,
channels,
)?)),
other => Err(AudioError::Unsupported(format!(
"audio decoder for codec {other}"
))),
}
}
pub fn create_encoder(config: AudioEncoderConfig) -> Result<Box<dyn AudioEncoder>, AudioError> {
match config.codec {
AudioCodec::Opus => Ok(Box::new(encode::opus::OpusEncoder::new(config)?)),
}
}