1use bytes::Bytes;
4
5use crate::error::{AudioError, AudioResult};
6use crate::frame::AudioFrame;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
10pub enum AudioFormat {
11 #[default]
13 Pcm16,
14 Opus,
16 Mp3,
18 Wav,
20 Flac,
22 Ogg,
24}
25
26impl AudioFormat {
27 pub fn supports_encode(&self) -> bool {
31 match self {
32 AudioFormat::Pcm16 => true,
33 AudioFormat::Wav => true,
34 AudioFormat::Opus => false,
35 AudioFormat::Mp3 => false,
36 AudioFormat::Flac => false,
37 AudioFormat::Ogg => false,
38 }
39 }
40
41 pub fn supports_decode(&self) -> bool {
45 match self {
46 AudioFormat::Pcm16 => true,
47 AudioFormat::Wav => true,
48 AudioFormat::Opus => false,
49 AudioFormat::Mp3 => false,
50 AudioFormat::Flac => false,
51 AudioFormat::Ogg => false,
52 }
53 }
54}
55
56pub fn decode(data: &[u8], format: AudioFormat) -> AudioResult<AudioFrame> {
61 match format {
62 AudioFormat::Pcm16 => {
63 Ok(AudioFrame::new(Bytes::copy_from_slice(data), 16000, 1))
65 }
66 AudioFormat::Wav => decode_wav(data),
67 _ => Err(AudioError::Codec(format!("decoding {format:?} is not yet supported"))),
68 }
69}
70
71pub fn encode(frame: &AudioFrame, format: AudioFormat) -> AudioResult<Bytes> {
76 match format {
77 AudioFormat::Pcm16 => Ok(frame.data.clone()),
78 AudioFormat::Wav => encode_wav(frame),
79 _ => Err(AudioError::Codec(format!("encoding {format:?} is not yet supported"))),
80 }
81}
82
83fn encode_wav(frame: &AudioFrame) -> AudioResult<Bytes> {
85 let data_len = frame.data.len() as u32;
86 let channels = frame.channels as u16;
87 let sample_rate = frame.sample_rate;
88 let bits_per_sample: u16 = 16;
89 let byte_rate = sample_rate * u32::from(channels) * u32::from(bits_per_sample) / 8;
90 let block_align = channels * bits_per_sample / 8;
91 let file_size = 36 + data_len;
92
93 let mut buf = Vec::with_capacity(44 + frame.data.len());
94 buf.extend_from_slice(b"RIFF");
96 buf.extend_from_slice(&file_size.to_le_bytes());
97 buf.extend_from_slice(b"WAVE");
98 buf.extend_from_slice(b"fmt ");
100 buf.extend_from_slice(&16u32.to_le_bytes()); buf.extend_from_slice(&1u16.to_le_bytes()); buf.extend_from_slice(&channels.to_le_bytes());
103 buf.extend_from_slice(&sample_rate.to_le_bytes());
104 buf.extend_from_slice(&byte_rate.to_le_bytes());
105 buf.extend_from_slice(&block_align.to_le_bytes());
106 buf.extend_from_slice(&bits_per_sample.to_le_bytes());
107 buf.extend_from_slice(b"data");
109 buf.extend_from_slice(&data_len.to_le_bytes());
110 buf.extend_from_slice(&frame.data);
111
112 Ok(Bytes::from(buf))
113}
114
115fn decode_wav(data: &[u8]) -> AudioResult<AudioFrame> {
117 if data.len() < 44 {
118 return Err(AudioError::Codec("WAV data too short for header".into()));
119 }
120 if &data[0..4] != b"RIFF" || &data[8..12] != b"WAVE" {
121 return Err(AudioError::Codec("invalid WAV header".into()));
122 }
123 let channels = u16::from_le_bytes([data[22], data[23]]);
124 let sample_rate = u32::from_le_bytes([data[24], data[25], data[26], data[27]]);
125 let bits_per_sample = u16::from_le_bytes([data[34], data[35]]);
126 if bits_per_sample != 16 {
127 return Err(AudioError::Codec(format!(
128 "unsupported bits per sample: {bits_per_sample}, expected 16"
129 )));
130 }
131 let mut offset = 12;
133 while offset + 8 <= data.len() {
134 let chunk_id = &data[offset..offset + 4];
135 let chunk_size = u32::from_le_bytes([
136 data[offset + 4],
137 data[offset + 5],
138 data[offset + 6],
139 data[offset + 7],
140 ]) as usize;
141 if chunk_id == b"data" {
142 let start = offset + 8;
143 let end = (start + chunk_size).min(data.len());
144 let pcm = Bytes::copy_from_slice(&data[start..end]);
145 return Ok(AudioFrame::new(pcm, sample_rate, channels as u8));
146 }
147 offset += 8 + chunk_size;
148 }
149 Err(AudioError::Codec("WAV data chunk not found".into()))
150}