1use std::num::NonZeroU32;
2
3#[cfg(feature = "decode-native")]
4use symphonia::core::audio::{conv::FromSample, sample::u24};
5
6#[derive(Clone)]
8pub struct DecodedAudioF32 {
9 pub data: Vec<Vec<f32>>,
10 pub sample_rate: NonZeroU32,
12 pub original_sample_rate: NonZeroU32,
15}
16
17impl DecodedAudioF32 {
18 pub fn new(
25 data: Vec<Vec<f32>>,
26 sample_rate: NonZeroU32,
27 original_sample_rate: NonZeroU32,
28 ) -> Self {
29 let frames = data[0].len();
30
31 for ch in data.iter().skip(1) {
32 assert_eq!(ch.len(), frames);
33 }
34
35 Self {
36 data,
37 sample_rate,
38 original_sample_rate,
39 }
40 }
41
42 pub fn channels(&self) -> usize {
44 self.data.len()
45 }
46
47 pub fn frames(&self) -> usize {
50 self.data[0].len()
51 }
52}
53
54impl std::fmt::Debug for DecodedAudioF32 {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 write!(
57 f,
58 "DecodedAudioF32 {{ channels: {}, frames: {}, sample_rate: {} }}",
59 self.data.len(),
60 self.data[0].len(),
61 self.sample_rate
62 )
63 }
64}
65
66#[cfg(feature = "decode-native")]
67impl From<DecodedAudioF32> for DecodedAudio {
68 fn from(value: DecodedAudioF32) -> Self {
69 let channels = value.channels();
70 let frames = value.frames();
71
72 DecodedAudio {
73 resource_type: DecodedAudioType::F32(value.data),
74 sample_rate: value.sample_rate,
75 original_sample_rate: value.original_sample_rate,
76 channels,
77 frames,
78 }
79 }
80}
81
82#[cfg(feature = "decode-native")]
87#[derive(Debug, Clone)]
88pub struct DecodedAudio {
89 resource_type: DecodedAudioType,
90 sample_rate: NonZeroU32,
91 original_sample_rate: NonZeroU32,
92 channels: usize,
93 frames: usize,
94}
95
96#[cfg(feature = "decode-native")]
103#[derive(Clone)]
104pub enum DecodedAudioType {
105 U8(Vec<Vec<u8>>),
106 S8(Vec<Vec<i8>>),
107 U16(Vec<Vec<u16>>),
108 S16(Vec<Vec<i16>>),
109 U24(Vec<Vec<[u8; 3]>>),
111 U32(Vec<Vec<u32>>),
112 S32(Vec<Vec<i32>>),
113 F32(Vec<Vec<f32>>),
114 F64(Vec<Vec<f64>>),
115}
116
117#[cfg(feature = "decode-native")]
118impl DecodedAudio {
119 pub fn new(
126 resource_type: DecodedAudioType,
127 sample_rate: NonZeroU32,
128 original_sample_rate: NonZeroU32,
129 ) -> Self {
130 let (channels, frames) = match &resource_type {
131 DecodedAudioType::U8(b) => {
132 let len = b[0].len();
133
134 for ch in b.iter().skip(1) {
135 assert_eq!(ch.len(), len);
136 }
137
138 (b.len(), len)
139 }
140 DecodedAudioType::S8(b) => {
141 let len = b[0].len();
142
143 for ch in b.iter().skip(1) {
144 assert_eq!(ch.len(), len);
145 }
146
147 (b.len(), len)
148 }
149 DecodedAudioType::U16(b) => {
150 let len = b[0].len();
151
152 for ch in b.iter().skip(1) {
153 assert_eq!(ch.len(), len);
154 }
155
156 (b.len(), len)
157 }
158 DecodedAudioType::S16(b) => {
159 let len = b[0].len();
160
161 for ch in b.iter().skip(1) {
162 assert_eq!(ch.len(), len);
163 }
164
165 (b.len(), len)
166 }
167 DecodedAudioType::U24(b) => {
168 let len = b[0].len();
169
170 for ch in b.iter().skip(1) {
171 assert_eq!(ch.len(), len);
172 }
173
174 (b.len(), len)
175 }
176 DecodedAudioType::U32(b) => {
177 let len = b[0].len();
178
179 for ch in b.iter().skip(1) {
180 assert_eq!(ch.len(), len);
181 }
182
183 (b.len(), len)
184 }
185 DecodedAudioType::S32(b) => {
186 let len = b[0].len();
187
188 for ch in b.iter().skip(1) {
189 assert_eq!(ch.len(), len);
190 }
191
192 (b.len(), len)
193 }
194 DecodedAudioType::F32(b) => {
195 let len = b[0].len();
196
197 for ch in b.iter().skip(1) {
198 assert_eq!(ch.len(), len);
199 }
200
201 (b.len(), len)
202 }
203 DecodedAudioType::F64(b) => {
204 let len = b[0].len();
205
206 for ch in b.iter().skip(1) {
207 assert_eq!(ch.len(), len);
208 }
209
210 (b.len(), len)
211 }
212 };
213
214 Self {
215 resource_type,
216 sample_rate,
217 original_sample_rate,
218 channels,
219 frames,
220 }
221 }
222
223 pub fn channels(&self) -> usize {
225 self.channels
226 }
227
228 pub fn frames(&self) -> usize {
231 self.frames
232 }
233
234 pub fn sample_rate(&self) -> NonZeroU32 {
236 self.sample_rate
237 }
238
239 pub fn original_sample_rate(&self) -> NonZeroU32 {
242 self.original_sample_rate
243 }
244
245 pub fn raw(&self) -> &DecodedAudioType {
247 &self.resource_type
248 }
249
250 pub fn raw_mut(&mut self) -> &mut DecodedAudioType {
254 &mut self.resource_type
255 }
256
257 pub fn fill_channel(
269 &self,
270 channel: usize,
271 frame: usize,
272 buf: &mut [f32],
273 ) -> Result<usize, FillChannelError> {
274 if channel >= self.channels {
275 return Err(FillChannelError {
276 got_index: channel,
277 num_channels: self.channels,
278 });
279 }
280
281 if frame >= self.frames {
282 buf.fill(0.0);
284 return Ok(0);
285 }
286
287 let fill_frames = if frame.saturating_add(buf.len()) > self.frames {
288 let fill_frames = self.frames.saturating_sub(frame);
290 buf[fill_frames..].fill(0.0);
291 fill_frames
292 } else {
293 buf.len()
294 };
295 let end_frame = frame.saturating_add(fill_frames);
296
297 let buf_part = &mut buf[0..fill_frames];
298
299 match &self.resource_type {
300 DecodedAudioType::U8(pcm) => {
301 let pcm_part = &pcm[channel][frame..end_frame];
302
303 for i in 0..fill_frames {
304 buf_part[i] = FromSample::from_sample(pcm_part[i]);
305 }
306 }
307 DecodedAudioType::S8(pcm) => {
308 let pcm_part = &pcm[channel][frame..end_frame];
309
310 for i in 0..fill_frames {
311 buf_part[i] = FromSample::from_sample(pcm_part[i]);
312 }
313 }
314 DecodedAudioType::U16(pcm) => {
315 let pcm_part = &pcm[channel][frame..end_frame];
316
317 for i in 0..fill_frames {
318 buf_part[i] = FromSample::from_sample(pcm_part[i]);
319 }
320 }
321 DecodedAudioType::S16(pcm) => {
322 let pcm_part = &pcm[channel][frame..end_frame];
323
324 for i in 0..fill_frames {
325 buf_part[i] = FromSample::from_sample(pcm_part[i]);
326 }
327 }
328 DecodedAudioType::U24(pcm) => {
329 let pcm_part = &pcm[channel][frame..end_frame];
330
331 for i in 0..fill_frames {
332 let b = &pcm_part[i];
333
334 #[cfg(target_endian = "little")]
335 let s = u24(u32::from_ne_bytes([b[0], b[1], b[2], 0]));
336
337 #[cfg(target_endian = "big")]
338 let s = u24(u32::from_ne_bytes([0, b[0], b[1], b[2]]));
339
340 buf_part[i] = FromSample::from_sample(s);
341 }
342 }
343 DecodedAudioType::U32(pcm) => {
344 let pcm_part = &pcm[channel][frame..end_frame];
345
346 for i in 0..fill_frames {
347 buf_part[i] = FromSample::from_sample(pcm_part[i]);
348 }
349 }
350 DecodedAudioType::S32(pcm) => {
351 let pcm_part = &pcm[channel][frame..end_frame];
352
353 for i in 0..fill_frames {
354 buf_part[i] = FromSample::from_sample(pcm_part[i]);
355 }
356 }
357 DecodedAudioType::F32(pcm) => {
358 let pcm_part = &pcm[channel][frame..end_frame];
359
360 buf_part.copy_from_slice(pcm_part);
361 }
362 DecodedAudioType::F64(pcm) => {
363 let pcm_part = &pcm[channel][frame..end_frame];
364
365 for i in 0..fill_frames {
366 buf_part[i] = pcm_part[i] as f32;
367 }
368 }
369 }
370
371 Ok(fill_frames)
372 }
373
374 pub fn fill_stereo(&self, frame: usize, buf_l: &mut [f32], buf_r: &mut [f32]) -> usize {
386 let buf_len = buf_l.len().min(buf_r.len());
387 let buf_l = &mut buf_l[..buf_len];
388 let buf_r = &mut buf_r[..buf_len];
389
390 let fill_frames = if self.channels > 0 {
391 self.fill_channel(0, frame, buf_l).unwrap()
392 } else {
393 return 0;
394 };
395
396 if self.channels > 1 {
397 self.fill_channel(1, frame, buf_r).unwrap();
398 } else {
399 buf_r.copy_from_slice(buf_l);
400 }
401
402 fill_frames
403 }
404
405 pub fn into_raw(self) -> DecodedAudioType {
407 self.resource_type
408 }
409}
410
411#[cfg(feature = "decode-native")]
412impl std::fmt::Debug for DecodedAudioType {
413 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
414 match self {
415 Self::U8(c) => write!(
416 f,
417 "DecodedAudioType::U8 {{ channels: {}, frames: {} }}",
418 c.len(),
419 c[0].len()
420 ),
421 Self::S8(c) => write!(
422 f,
423 "DecodedAudioType::S8 {{ channels: {}, frames: {} }}",
424 c.len(),
425 c[0].len()
426 ),
427 Self::U16(c) => write!(
428 f,
429 "DecodedAudioType::U16 {{ channels: {}, frames: {} }}",
430 c.len(),
431 c[0].len()
432 ),
433 Self::S16(c) => write!(
434 f,
435 "DecodedAudioType::S16 {{ channels: {}, frames: {} }}",
436 c.len(),
437 c[0].len()
438 ),
439 Self::U24(c) => write!(
440 f,
441 "DecodedAudioType::U24 {{ channels: {}, frames: {} }}",
442 c.len(),
443 c[0].len()
444 ),
445 Self::U32(c) => write!(
446 f,
447 "DecodedAudioType::U32 {{ channels: {}, frames: {} }}",
448 c.len(),
449 c[0].len()
450 ),
451 Self::S32(c) => write!(
452 f,
453 "DecodedAudioType::S32 {{ channels: {}, frames: {} }}",
454 c.len(),
455 c[0].len()
456 ),
457 Self::F32(c) => write!(
458 f,
459 "DecodedAudioType::F32 {{ channels: {}, frames: {} }}",
460 c.len(),
461 c[0].len()
462 ),
463 Self::F64(c) => write!(
464 f,
465 "DecodedAudioType::F64 {{ channels: {}, frames: {} }}",
466 c.len(),
467 c[0].len()
468 ),
469 }
470 }
471}
472
473#[cfg(all(test, feature = "decode-native"))]
474mod tests {
475 use super::*;
476
477 #[test]
478 fn pcm_fill_range_test() {
479 let test_pcm = DecodedAudio::new(
480 DecodedAudioType::F32(vec![vec![1.0, 2.0, 3.0, 4.0]]),
481 NonZeroU32::new(44100).unwrap(),
482 NonZeroU32::new(44100).unwrap(),
483 );
484
485 let mut out_buf: [f32; 8] = [10.0; 8];
486
487 let fill_frames = test_pcm.fill_channel(0, 0, &mut out_buf[0..4]);
488 assert_eq!(fill_frames, Ok(4));
489 assert_eq!(&out_buf[0..4], &[1.0, 2.0, 3.0, 4.0]);
490
491 out_buf = [10.0; 8];
492 let fill_frames = test_pcm.fill_channel(0, 0, &mut out_buf[0..5]);
493 assert_eq!(fill_frames, Ok(4));
494 assert_eq!(&out_buf[0..5], &[1.0, 2.0, 3.0, 4.0, 0.0]);
495
496 out_buf = [10.0; 8];
497 let fill_frames = test_pcm.fill_channel(0, 2, &mut out_buf[0..4]);
498 assert_eq!(fill_frames, Ok(2));
499 assert_eq!(&out_buf[0..4], &[3.0, 4.0, 0.0, 0.0]);
500
501 out_buf = [10.0; 8];
502 let fill_frames = test_pcm.fill_channel(0, 3, &mut out_buf[0..4]);
503 assert_eq!(fill_frames, Ok(1));
504 assert_eq!(&out_buf[0..4], &[4.0, 0.0, 0.0, 0.0]);
505
506 out_buf = [10.0; 8];
507 let fill_frames = test_pcm.fill_channel(0, 4, &mut out_buf[0..4]);
508 assert_eq!(fill_frames, Ok(0));
509 assert_eq!(&out_buf[0..4], &[0.0, 0.0, 0.0, 0.0]);
510
511 out_buf = [10.0; 8];
512 let fill_frames = test_pcm.fill_channel(0, 1, &mut out_buf[0..2]);
513 assert_eq!(fill_frames, Ok(2));
514 assert_eq!(&out_buf[0..2], &[2.0, 3.0]);
515
516 out_buf = [10.0; 8];
517 let fill_frames = test_pcm.fill_channel(0, 1, &mut out_buf[0..4]);
518 assert_eq!(fill_frames, Ok(3));
519 assert_eq!(&out_buf[0..4], &[2.0, 3.0, 4.0, 0.0]);
520 }
521}
522
523#[derive(Debug, Clone, Copy, PartialEq, Eq)]
525pub struct FillChannelError {
526 pub got_index: usize,
527 pub num_channels: usize,
528}
529
530impl std::error::Error for FillChannelError {}
531
532impl std::fmt::Display for FillChannelError {
533 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
534 write!(
535 f,
536 "channel index {} out of bounds for DecodedAudio with {} channels",
537 self.got_index, self.num_channels
538 )
539 }
540}