1pub mod decoder {
2 use super::resample::LinearResampler;
3 use std::io::ErrorKind;
4 use symphonia::core::audio::SampleBuffer;
5 use symphonia::core::codecs::{CODEC_TYPE_NULL, Decoder, DecoderOptions};
6 use symphonia::core::errors::Error;
7 use symphonia::core::formats::{FormatOptions, FormatReader};
8 use symphonia::core::io::{MediaSource, MediaSourceStream};
9 use symphonia::core::meta::MetadataOptions;
10 use symphonia::core::probe::Hint;
11 pub struct AudioDecoder {
12 format: Box<dyn FormatReader>,
13 decoder: Box<dyn Decoder>,
14 track_id: u32,
15 resampler: LinearResampler,
16 sample_buf: Option<SampleBuffer<i16>>,
17 raw_buffer: Vec<i16>,
18 downmix_buf: Vec<i16>,
19 }
20 impl AudioDecoder {
21 pub fn new(source: Box<dyn MediaSource>, ext_hint: Option<&str>) -> Result<Self, String> {
22 let mss = MediaSourceStream::new(source, Default::default());
23 let mut hint = Hint::new();
24 if let Some(ext) = ext_hint {
25 hint.with_extension(ext);
26 }
27 let probed = symphonia::default::get_probe()
28 .format(
29 &hint,
30 mss,
31 &FormatOptions::default(),
32 &MetadataOptions::default(),
33 )
34 .map_err(|e| format!("Failed to probe format: {e}"))?;
35 let format = probed.format;
36 let track = format
37 .tracks()
38 .iter()
39 .find(|t| t.codec_params.codec != CODEC_TYPE_NULL)
40 .ok_or_else(|| "No audio track found in media source".to_string())?;
41 let track_id = track.id;
42 let sample_rate = track.codec_params.sample_rate.unwrap_or(48000);
43 let decoder = symphonia::default::get_codecs()
44 .make(&track.codec_params, &DecoderOptions::default())
45 .map_err(|e| format!("Failed to create decoder: {e}"))?;
46 let resampler = LinearResampler::new(sample_rate, 48000, 2);
47 Ok(Self {
48 format,
49 decoder,
50 track_id,
51 resampler,
52 sample_buf: None,
53 raw_buffer: Vec::with_capacity(48000 * 2),
54 downmix_buf: Vec::new(),
55 })
56 }
57 pub fn read_frame(&mut self) -> Result<Option<Vec<i16>>, String> {
58 const TARGET_FRAME_SAMPLES: usize = 960 * 2;
59 while self.raw_buffer.len() < TARGET_FRAME_SAMPLES {
60 let packet = match self.format.next_packet() {
61 Ok(p) => p,
62 Err(Error::IoError(ref e)) if e.kind() == ErrorKind::UnexpectedEof => {
63 break;
64 }
65 Err(e) => return Err(format!("Format read error: {e}")),
66 };
67 if packet.track_id() != self.track_id {
68 continue;
69 }
70 match self.decoder.decode(&packet) {
71 Ok(decoded) => {
72 let spec = *decoded.spec();
73 let mut buf = self.sample_buf.take().unwrap_or_else(|| {
74 SampleBuffer::<i16>::new(decoded.capacity() as u64, spec)
75 });
76 buf.copy_interleaved_ref(decoded);
77 let samples = buf.samples();
78 if !samples.is_empty() {
79 let frame_channels = spec.channels.count();
80 let stereo_pcm = if frame_channels == 2 {
81 samples
82 } else {
83 self.downmix_buf.clear();
84 let num_frames = samples.len() / frame_channels;
85 for i in 0..num_frames {
86 let frame =
87 &samples[i * frame_channels..(i + 1) * frame_channels];
88 let mut l = 0i32;
89 let mut r = 0i32;
90 for (ch, &sample) in frame.iter().enumerate() {
91 if ch % 2 == 0 {
92 l += sample as i32;
93 } else {
94 r += sample as i32;
95 }
96 }
97 let left_count = frame_channels.div_ceil(2);
98 let right_count = frame_channels / 2;
99 self.downmix_buf.push((l / left_count as i32) as i16);
100 if right_count > 0 {
101 self.downmix_buf.push((r / right_count as i32) as i16);
102 } else {
103 self.downmix_buf.push((l / left_count as i32) as i16);
104 }
105 }
106 &self.downmix_buf[..]
107 };
108 if self.resampler.is_passthrough() {
109 self.raw_buffer.extend_from_slice(stereo_pcm);
110 } else {
111 self.resampler.process(stereo_pcm, &mut self.raw_buffer);
112 }
113 }
114 self.sample_buf = Some(buf);
115 }
116 Err(Error::IoError(ref e)) if e.kind() == ErrorKind::UnexpectedEof => {
117 break;
118 }
119 Err(Error::ResetRequired) => {
120 self.decoder.reset();
121 self.resampler.reset();
122 self.sample_buf = None;
123 }
124 Err(e) => return Err(format!("Decode error: {e}")),
125 }
126 }
127 if self.raw_buffer.len() >= TARGET_FRAME_SAMPLES {
128 let frame = self.raw_buffer.drain(0..TARGET_FRAME_SAMPLES).collect();
129 Ok(Some(frame))
130 } else if !self.raw_buffer.is_empty() {
131 let mut frame = std::mem::take(&mut self.raw_buffer);
132 frame.resize(TARGET_FRAME_SAMPLES, 0);
133 Ok(Some(frame))
134 } else {
135 Ok(None)
136 }
137 }
138 pub fn seek(&mut self, position_ms: u64) -> Result<(), String> {
139 use symphonia::core::formats::{SeekMode, SeekTo};
140 use symphonia::core::units::Time;
141 let time = Time::from(position_ms as f64 / 1000.0);
142 self.format
143 .seek(
144 SeekMode::Coarse,
145 SeekTo::Time {
146 time,
147 track_id: Some(self.track_id),
148 },
149 )
150 .map_err(|e| format!("Symphonia seek error: {e}"))?;
151 self.decoder.reset();
152 self.resampler.reset();
153 self.sample_buf = None;
154 self.raw_buffer.clear();
155 Ok(())
156 }
157 }
158}
159pub mod encoder {
160 use audiopus::{Application, Bitrate, Channels, SampleRate, coder::Encoder as OpusEncoder};
161 pub struct AudioEncoder {
162 encoder: OpusEncoder,
163 }
164 impl AudioEncoder {
165 pub fn new() -> Result<Self, String> {
166 let mut encoder =
167 OpusEncoder::new(SampleRate::Hz48000, Channels::Stereo, Application::Audio)
168 .map_err(|e| format!("Failed to create Opus encoder: {e:?}"))?;
169 encoder
170 .set_bitrate(Bitrate::Auto)
171 .map_err(|e| format!("Failed to set Opus bitrate: {e:?}"))?;
172 Ok(Self { encoder })
173 }
174 pub fn encode(&mut self, pcm: &[i16], out: &mut [u8]) -> Result<usize, String> {
175 self.encoder
176 .encode(pcm, out)
177 .map_err(|e| format!("Opus encoding failed: {e:?}"))
178 }
179 }
180}
181pub mod resample {
182 pub struct LinearResampler {
183 ratio: f32,
184 index: f32,
185 last_samples: Vec<i16>,
186 channels: usize,
187 }
188 impl LinearResampler {
189 pub fn new(source_rate: u32, target_rate: u32, channels: usize) -> Self {
190 Self {
191 ratio: source_rate as f32 / target_rate as f32,
192 index: 0.0,
193 last_samples: vec![0; channels],
194 channels,
195 }
196 }
197 pub fn process(&mut self, input: &[i16], output: &mut Vec<i16>) {
198 let num_frames = input.len() / self.channels;
199 while self.index < num_frames as f32 {
200 let idx = self.index as usize;
201 let fract = self.index.fract();
202 for c in 0..self.channels {
203 let s1 = if idx == 0 {
204 self.last_samples[c]
205 } else {
206 input[(idx - 1) * self.channels + c]
207 } as f32;
208 let s2 = if idx < num_frames {
209 input[idx * self.channels + c]
210 } else {
211 input[(num_frames - 1) * self.channels + c]
212 } as f32;
213 output.push((s1 * (1.0 - fract) + s2 * fract) as i16);
214 }
215 self.index += self.ratio;
216 }
217 self.index -= num_frames as f32;
218 if num_frames > 0 {
219 for c in 0..self.channels {
220 self.last_samples[c] = input[(num_frames - 1) * self.channels + c];
221 }
222 }
223 }
224 pub fn reset(&mut self) {
225 self.index = 0.0;
226 self.last_samples.fill(0);
227 }
228 pub fn is_passthrough(&self) -> bool {
229 (self.ratio - 1.0).abs() < f32::EPSILON
230 }
231 }
232}