1pub use crate::decoder::{Decoder, DecoderOptions};
16#[cfg(all(feature = "file-stream", not(target_family = "wasm")))]
17mod file;
18use crate::{Audio, Endian, Error, Limits, Result, SampleFormat};
19#[cfg(all(feature = "file-stream", not(target_family = "wasm")))]
20pub use file::{FileStream, FileStreamHandle, FileStreamOptions, FileStreamStatus};
21
22#[derive(Debug)]
23pub struct PcmDecoder {
24 format: SampleFormat,
25 endian: Endian,
26 channels: usize,
27 rate: u32,
28 limits: Limits,
29 pending: Vec<u8>,
30 frames: usize,
31}
32impl PcmDecoder {
33 pub fn new(
34 format: SampleFormat,
35 endian: Endian,
36 channels: usize,
37 rate: u32,
38 limits: Limits,
39 ) -> Result<Self> {
40 limits.check(0, channels, rate)?;
41 Ok(Self {
42 format,
43 endian,
44 channels,
45 rate,
46 limits,
47 pending: Vec::new(),
48 frames: 0,
49 })
50 }
51 pub fn push(&mut self, bytes: &[u8]) -> Result<Audio> {
52 let stride = self
53 .channels
54 .checked_mul(self.format.bytes())
55 .ok_or_else(|| Error::invalid("PCM stride overflow"))?;
56 let n = self
57 .pending
58 .len()
59 .checked_add(bytes.len())
60 .ok_or_else(|| Error::limit("PCM input size overflow"))?;
61 let frames = n / stride;
62 let total = self
63 .frames
64 .checked_add(frames)
65 .ok_or_else(|| Error::limit("PCM frame overflow"))?;
66 self.limits.check(total, self.channels, self.rate)?;
67 let mut combined = std::mem::take(&mut self.pending);
68 combined.extend_from_slice(bytes);
69 let complete = frames * stride;
70 let result = crate::pcm::decode_pcm(
71 &combined[..complete],
72 self.format,
73 self.endian,
74 self.channels,
75 self.rate,
76 &self.limits,
77 )?;
78 self.pending = combined[complete..].to_vec();
79 self.frames = total;
80 Ok(result)
81 }
82 pub fn finish(self) -> Result<()> {
83 if self.pending.is_empty() {
84 Ok(())
85 } else {
86 Err(Error::decode("Incomplete final PCM frame"))
87 }
88 }
89}
90#[derive(Debug)]
91pub struct PcmEncoder {
92 format: SampleFormat,
93 endian: Endian,
94 shape: Option<(usize, u32)>,
95 dither: crate::Dither,
96 quantizers: Vec<crate::pcm::Quantizer>,
97}
98impl PcmEncoder {
99 pub fn new(format: SampleFormat, endian: Endian) -> Self {
100 Self {
101 format,
102 endian,
103 shape: None,
104 dither: crate::Dither::None,
105 quantizers: Vec::new(),
106 }
107 }
108 pub fn with_dither(
113 format: SampleFormat,
114 endian: Endian,
115 dither: crate::Dither,
116 ) -> Result<Self> {
117 crate::pcm::validate_dither(format, dither)?;
118 Ok(Self {
119 dither,
120 ..Self::new(format, endian)
121 })
122 }
123 pub fn push(&mut self, audio: &Audio) -> Result<Vec<u8>> {
124 let shape = (audio.channels(), audio.sample_rate());
125 if self.shape.is_some_and(|s| s != shape) {
126 return Err(Error::invalid("PCM stream shape changed"));
127 }
128 if self.shape.is_none() {
129 self.quantizers = crate::pcm::quantizers(self.format, self.dither, audio.channels());
130 }
131 let bytes =
132 crate::pcm::encode_quantized(audio, self.format, self.endian, &mut self.quantizers)?;
133 self.shape = Some(shape);
134 Ok(bytes)
135 }
136}
137
138pub struct Resampler {
141 from_rate: u32,
142 to_rate: u32,
143 channels: usize,
144 limits: Limits,
145 pending: Vec<std::collections::VecDeque<f32>>,
146 first: Vec<f32>,
147 start: usize,
148 inputs: usize,
149 outputs: usize,
150}
151impl Resampler {
152 pub fn new(from_rate: u32, to_rate: u32, channels: usize, limits: Limits) -> Result<Self> {
153 limits.check(0, channels, from_rate)?;
154 limits.check(0, channels, to_rate)?;
155 Ok(Self {
156 from_rate,
157 to_rate,
158 channels,
159 limits,
160 pending: vec![std::collections::VecDeque::new(); channels],
161 first: vec![0.0; channels],
162 start: 0,
163 inputs: 0,
164 outputs: 0,
165 })
166 }
167 pub fn push(&mut self, audio: &Audio) -> Result<Audio> {
168 if audio.sample_rate() != self.from_rate || audio.channels() != self.channels {
169 return Err(Error::invalid("Resampler input shape changed"));
170 }
171 let total = self
172 .inputs
173 .checked_add(audio.frames())
174 .ok_or_else(|| Error::limit("Resampler frame count overflow"))?;
175 self.limits.check(total, self.channels, self.from_rate)?;
176 self.limits.check(
177 (total as f64 * self.to_rate as f64 / self.from_rate as f64).round() as usize,
178 self.channels,
179 self.to_rate,
180 )?;
181 for (c, data) in self.pending.iter_mut().enumerate() {
182 if self.inputs == 0 && audio.frames() > 0 {
183 self.first[c] = audio.data[c][0];
184 }
185 data.extend(audio.data[c].iter().copied());
186 }
187 self.inputs = total;
188 self.drain(false)
189 }
190 fn drain(&mut self, finish: bool) -> Result<Audio> {
191 let ratio = self.to_rate as f64 / self.from_rate as f64;
192 let half = 32.0 / (ratio.min(1.0) * 0.97);
193 let target = (self.inputs as f64 * ratio).round() as usize;
194 let mut data = vec![Vec::new(); self.channels];
195 while self.outputs < target {
196 let center = self.outputs as f64 / ratio;
197 if !finish && center + half >= self.inputs as f64 {
198 break;
199 }
200 for (c, dst) in data.iter_mut().enumerate() {
201 let value = if self.from_rate == self.to_rate {
202 self.pending[c][self.outputs - self.start]
203 } else {
204 crate::dsp::sinc_sample(center, ratio, |index| {
205 if index < 0 {
206 return self.first[c];
207 }
208 if index as usize >= self.inputs {
209 return self.pending[c].back().copied().unwrap_or(0.0);
210 }
211 self.pending[c][index as usize - self.start]
212 })
213 };
214 dst.push(value);
215 }
216 self.outputs += 1;
217 }
218 let keep = ((self.outputs as f64 / ratio - half).ceil().max(0.0) as usize)
219 .min(self.inputs.saturating_sub(1));
220 if keep > self.start {
221 for c in &mut self.pending {
222 c.drain(..keep - self.start);
223 }
224 self.start = keep;
225 }
226 Audio::decoded(data, self.to_rate, crate::DecodeInfo::default())
227 }
228 pub fn finish(mut self) -> Result<Audio> {
229 self.drain(true)
230 }
231}