1#![forbid(unsafe_code)]
39#![allow(clippy::cast_possible_truncation)]
40#![allow(clippy::cast_sign_loss)]
41#![allow(clippy::cast_precision_loss)]
42#![allow(clippy::cast_lossless)]
43#![allow(dead_code)]
44
45use crate::audio::{AudioFrame, SampleFormat};
46use crate::error::{CodecError, CodecResult};
47
48#[derive(Clone, Copy, Debug, PartialEq, Eq)]
54pub enum PcmFormat {
55 U8,
57 I16,
59 I24,
61 I32,
63 F32,
65 F64,
67}
68
69impl PcmFormat {
70 #[must_use]
72 pub const fn bytes_per_sample(self) -> usize {
73 match self {
74 Self::U8 => 1,
75 Self::I16 => 2,
76 Self::I24 => 3,
77 Self::I32 => 4,
78 Self::F32 => 4,
79 Self::F64 => 8,
80 }
81 }
82}
83
84#[derive(Clone, Copy, Debug, PartialEq, Eq)]
90pub enum ByteOrder {
91 Little,
93 Big,
95}
96
97#[derive(Clone, Debug)]
103pub struct PcmConfig {
104 pub format: PcmFormat,
106 pub byte_order: ByteOrder,
108 pub sample_rate: u32,
110 pub channels: u8,
112}
113
114impl Default for PcmConfig {
115 fn default() -> Self {
116 Self {
117 format: PcmFormat::I16,
118 byte_order: ByteOrder::Little,
119 sample_rate: 48000,
120 channels: 2,
121 }
122 }
123}
124
125#[inline]
131fn f32_to_i16(s: f32) -> i16 {
132 let v = (s.clamp(-1.0, 1.0) * 32767.0) as i32;
133 v.clamp(-32768, 32767) as i16
134}
135
136#[inline]
138fn f32_to_i24(s: f32) -> i32 {
139 let v = (s.clamp(-1.0, 1.0) * 8_388_607.0) as i64;
140 v.clamp(-8_388_608, 8_388_607) as i32
141}
142
143#[inline]
145fn f32_to_i32(s: f32) -> i32 {
146 let v = (s.clamp(-1.0, 1.0) * 2_147_483_647.0_f64 as f32) as i64;
147 v.clamp(-2_147_483_648, 2_147_483_647) as i32
148}
149
150#[inline]
152fn f32_to_u8(s: f32) -> u8 {
153 let v = ((s.clamp(-1.0, 1.0) + 1.0) * 127.5) as i32;
154 v.clamp(0, 255) as u8
155}
156
157#[inline]
162fn i16_to_f32(v: i16) -> f32 {
163 v as f32 / 32768.0
164}
165
166#[inline]
167fn i24_to_f32(v: i32) -> f32 {
168 v as f32 / 8_388_608.0
169}
170
171#[inline]
172fn i32_to_f32(v: i32) -> f32 {
173 v as f32 / 2_147_483_648.0_f64 as f32
174}
175
176#[inline]
177fn u8_to_f32(v: u8) -> f32 {
178 (v as f32 - 128.0) / 128.0
179}
180
181fn frame_to_f32_samples(frame: &AudioFrame) -> CodecResult<Vec<f32>> {
190 match frame.format {
191 SampleFormat::F32 => {
192 if frame.samples.len() % 4 != 0 {
193 return Err(CodecError::InvalidData(
194 "F32 frame: sample byte count is not a multiple of 4".to_string(),
195 ));
196 }
197 let mut out = Vec::with_capacity(frame.samples.len() / 4);
198 for chunk in frame.samples.chunks_exact(4) {
199 let arr = [chunk[0], chunk[1], chunk[2], chunk[3]];
200 out.push(f32::from_le_bytes(arr));
201 }
202 Ok(out)
203 }
204 SampleFormat::I16 => {
205 if frame.samples.len() % 2 != 0 {
206 return Err(CodecError::InvalidData(
207 "I16 frame: sample byte count is not a multiple of 2".to_string(),
208 ));
209 }
210 let mut out = Vec::with_capacity(frame.samples.len() / 2);
211 for chunk in frame.samples.chunks_exact(2) {
212 let arr = [chunk[0], chunk[1]];
213 let v = i16::from_le_bytes(arr);
214 out.push(i16_to_f32(v));
215 }
216 Ok(out)
217 }
218 SampleFormat::I32 => {
219 if frame.samples.len() % 4 != 0 {
220 return Err(CodecError::InvalidData(
221 "I32 frame: sample byte count is not a multiple of 4".to_string(),
222 ));
223 }
224 let mut out = Vec::with_capacity(frame.samples.len() / 4);
225 for chunk in frame.samples.chunks_exact(4) {
226 let arr = [chunk[0], chunk[1], chunk[2], chunk[3]];
227 let v = i32::from_le_bytes(arr);
228 out.push(i32_to_f32(v));
229 }
230 Ok(out)
231 }
232 SampleFormat::U8 => {
233 let mut out = Vec::with_capacity(frame.samples.len());
234 for &b in &frame.samples {
235 out.push(u8_to_f32(b));
236 }
237 Ok(out)
238 }
239 }
240}
241
242fn f32_samples_to_bytes(samples: &[f32]) -> Vec<u8> {
244 let mut out = Vec::with_capacity(samples.len() * 4);
245 for &s in samples {
246 out.extend_from_slice(&s.to_le_bytes());
247 }
248 out
249}
250
251#[derive(Debug, Clone)]
260pub struct PcmEncoder {
261 config: PcmConfig,
262}
263
264impl PcmEncoder {
265 #[must_use]
267 pub fn new(config: PcmConfig) -> Self {
268 Self { config }
269 }
270
271 pub fn encode_frame(&self, frame: &AudioFrame) -> CodecResult<Vec<u8>> {
281 let ch = frame.channels as u8;
282 if ch != self.config.channels {
283 return Err(CodecError::InvalidParameter(format!(
284 "PCM encoder: expected {} channels, got {}",
285 self.config.channels, ch
286 )));
287 }
288 if frame.sample_rate != self.config.sample_rate {
289 return Err(CodecError::InvalidParameter(format!(
290 "PCM encoder: expected sample_rate={}, got {}",
291 self.config.sample_rate, frame.sample_rate
292 )));
293 }
294
295 let f32_samples = frame_to_f32_samples(frame)?;
297
298 let bps = self.config.format.bytes_per_sample();
299 let mut out = Vec::with_capacity(f32_samples.len() * bps);
300 let le = self.config.byte_order == ByteOrder::Little;
301
302 for s in f32_samples {
303 match self.config.format {
304 PcmFormat::U8 => out.push(f32_to_u8(s)),
305 PcmFormat::I16 => {
306 let v = f32_to_i16(s);
307 if le {
308 out.extend_from_slice(&v.to_le_bytes());
309 } else {
310 out.extend_from_slice(&v.to_be_bytes());
311 }
312 }
313 PcmFormat::I24 => {
314 let v = f32_to_i24(s);
315 if le {
316 out.push((v & 0xFF) as u8);
317 out.push(((v >> 8) & 0xFF) as u8);
318 out.push(((v >> 16) & 0xFF) as u8);
319 } else {
320 out.push(((v >> 16) & 0xFF) as u8);
321 out.push(((v >> 8) & 0xFF) as u8);
322 out.push((v & 0xFF) as u8);
323 }
324 }
325 PcmFormat::I32 => {
326 let v = f32_to_i32(s);
327 if le {
328 out.extend_from_slice(&v.to_le_bytes());
329 } else {
330 out.extend_from_slice(&v.to_be_bytes());
331 }
332 }
333 PcmFormat::F32 => {
334 if le {
335 out.extend_from_slice(&s.to_le_bytes());
336 } else {
337 out.extend_from_slice(&s.to_be_bytes());
338 }
339 }
340 PcmFormat::F64 => {
341 let d = f64::from(s);
342 if le {
343 out.extend_from_slice(&d.to_le_bytes());
344 } else {
345 out.extend_from_slice(&d.to_be_bytes());
346 }
347 }
348 }
349 }
350
351 Ok(out)
352 }
353
354 pub fn encode_raw(&self, samples: &[f32]) -> CodecResult<Vec<u8>> {
360 if self.config.channels > 0 && samples.len() % self.config.channels as usize != 0 {
361 return Err(CodecError::InvalidParameter(
362 "PCM encode_raw: sample count not multiple of channels".to_string(),
363 ));
364 }
365 let sample_count = if self.config.channels > 0 {
366 samples.len() / self.config.channels as usize
367 } else {
368 samples.len()
369 };
370 let raw_bytes = f32_samples_to_bytes(samples);
372 let frame = AudioFrame::new(
373 raw_bytes,
374 sample_count,
375 self.config.sample_rate,
376 self.config.channels as usize,
377 SampleFormat::F32,
378 );
379 self.encode_frame(&frame)
380 }
381
382 #[must_use]
384 pub fn config(&self) -> &PcmConfig {
385 &self.config
386 }
387}
388
389#[derive(Debug, Clone)]
397pub struct PcmDecoder {
398 config: PcmConfig,
399}
400
401impl PcmDecoder {
402 #[must_use]
404 pub fn new(config: PcmConfig) -> Self {
405 Self { config }
406 }
407
408 pub fn decode_bytes(&self, bytes: &[u8]) -> CodecResult<AudioFrame> {
418 let bps = self.config.format.bytes_per_sample();
419 if bytes.len() % bps != 0 {
420 return Err(CodecError::InvalidBitstream(format!(
421 "PCM decode: byte count {} is not a multiple of bytes-per-sample {}",
422 bytes.len(),
423 bps
424 )));
425 }
426
427 let n_samples = bytes.len() / bps;
428 let mut f32_samples: Vec<f32> = Vec::with_capacity(n_samples);
429 let le = self.config.byte_order == ByteOrder::Little;
430
431 let mut i = 0;
432 while i < bytes.len() {
433 let s = match self.config.format {
434 PcmFormat::U8 => {
435 let v = bytes[i];
436 i += 1;
437 u8_to_f32(v)
438 }
439 PcmFormat::I16 => {
440 let arr = [bytes[i], bytes[i + 1]];
441 let v = if le {
442 i16::from_le_bytes(arr)
443 } else {
444 i16::from_be_bytes(arr)
445 };
446 i += 2;
447 i16_to_f32(v)
448 }
449 PcmFormat::I24 => {
450 let raw = if le {
451 (bytes[i] as i32)
452 | ((bytes[i + 1] as i32) << 8)
453 | ((bytes[i + 2] as i32) << 16)
454 } else {
455 ((bytes[i] as i32) << 16)
456 | ((bytes[i + 1] as i32) << 8)
457 | (bytes[i + 2] as i32)
458 };
459 let v = if raw & 0x80_0000 != 0 {
461 raw | !0xFF_FFFF_i32
462 } else {
463 raw
464 };
465 i += 3;
466 i24_to_f32(v)
467 }
468 PcmFormat::I32 => {
469 let arr = [bytes[i], bytes[i + 1], bytes[i + 2], bytes[i + 3]];
470 let v = if le {
471 i32::from_le_bytes(arr)
472 } else {
473 i32::from_be_bytes(arr)
474 };
475 i += 4;
476 i32_to_f32(v)
477 }
478 PcmFormat::F32 => {
479 let arr = [bytes[i], bytes[i + 1], bytes[i + 2], bytes[i + 3]];
480 let v = if le {
481 f32::from_le_bytes(arr)
482 } else {
483 f32::from_be_bytes(arr)
484 };
485 i += 4;
486 v
487 }
488 PcmFormat::F64 => {
489 let arr = [
490 bytes[i],
491 bytes[i + 1],
492 bytes[i + 2],
493 bytes[i + 3],
494 bytes[i + 4],
495 bytes[i + 5],
496 bytes[i + 6],
497 bytes[i + 7],
498 ];
499 let v = if le {
500 f64::from_le_bytes(arr)
501 } else {
502 f64::from_be_bytes(arr)
503 };
504 i += 8;
505 v as f32
506 }
507 };
508 f32_samples.push(s);
509 }
510
511 let raw_bytes = f32_samples_to_bytes(&f32_samples);
513 let channels = self.config.channels as usize;
514 let sample_count = f32_samples
515 .len()
516 .checked_div(channels)
517 .unwrap_or(f32_samples.len());
518
519 Ok(AudioFrame::new(
520 raw_bytes,
521 sample_count,
522 self.config.sample_rate,
523 channels,
524 SampleFormat::F32,
525 ))
526 }
527
528 #[must_use]
530 pub fn config(&self) -> &PcmConfig {
531 &self.config
532 }
533
534 #[must_use]
536 pub fn frame_count(&self, bytes: &[u8]) -> usize {
537 let bps = self.config.format.bytes_per_sample();
538 let total_samples = bytes.len() / bps;
539 let ch = self.config.channels as usize;
540 total_samples.checked_div(ch).unwrap_or(0)
541 }
542}
543
544#[cfg(test)]
549mod tests {
550 use super::*;
551
552 fn make_frame(samples: Vec<f32>, sample_rate: u32, channels: u8) -> AudioFrame {
554 let sample_count = if channels > 0 {
555 samples.len() / channels as usize
556 } else {
557 samples.len()
558 };
559 let raw_bytes = f32_samples_to_bytes(&samples);
560 AudioFrame::new(
561 raw_bytes,
562 sample_count,
563 sample_rate,
564 channels as usize,
565 SampleFormat::F32,
566 )
567 }
568
569 fn frame_samples(frame: &AudioFrame) -> Vec<f32> {
571 frame_to_f32_samples(frame).expect("frame_to_f32_samples")
572 }
573
574 #[test]
577 fn test_u8_roundtrip() {
578 let cfg = PcmConfig {
579 format: PcmFormat::U8,
580 byte_order: ByteOrder::Little,
581 sample_rate: 44100,
582 channels: 1,
583 };
584 let input = vec![0.0f32, 0.5, -0.5, 1.0, -1.0];
585 let enc = PcmEncoder::new(cfg.clone());
586 let dec = PcmDecoder::new(cfg);
587 let frame = make_frame(input.clone(), 44100, 1);
588 let bytes = enc.encode_frame(&frame).expect("encode");
589 assert_eq!(bytes.len(), input.len());
590 let decoded = dec.decode_bytes(&bytes).expect("decode");
591 let got = frame_samples(&decoded);
592 assert_eq!(got.len(), input.len());
593 for (&orig, &g) in input.iter().zip(got.iter()) {
595 assert!((orig - g).abs() < 0.02, "U8 roundtrip: orig={orig} got={g}");
596 }
597 }
598
599 #[test]
602 fn test_i16_le_roundtrip() {
603 let cfg = PcmConfig {
604 format: PcmFormat::I16,
605 byte_order: ByteOrder::Little,
606 sample_rate: 48000,
607 channels: 2,
608 };
609 let input: Vec<f32> = (0..256).map(|i| i as f32 / 128.0 - 1.0).collect();
610 let enc = PcmEncoder::new(cfg.clone());
611 let dec = PcmDecoder::new(cfg);
612 let frame = make_frame(input.clone(), 48000, 2);
613 let bytes = enc.encode_frame(&frame).expect("encode");
614 assert_eq!(bytes.len(), input.len() * 2);
615 let decoded = dec.decode_bytes(&bytes).expect("decode");
616 let got = frame_samples(&decoded);
617 assert_eq!(got.len(), input.len());
618 for (&orig, &g) in input.iter().zip(got.iter()) {
619 assert!(
620 (orig - g).abs() < 0.0001,
621 "I16 roundtrip: orig={orig} got={g}"
622 );
623 }
624 }
625
626 #[test]
629 fn test_i16_be_roundtrip() {
630 let cfg = PcmConfig {
631 format: PcmFormat::I16,
632 byte_order: ByteOrder::Big,
633 sample_rate: 44100,
634 channels: 1,
635 };
636 let input = vec![0.0f32, 0.25, -0.25, 0.99, -0.99];
637 let enc = PcmEncoder::new(cfg.clone());
638 let dec = PcmDecoder::new(cfg);
639 let frame = make_frame(input.clone(), 44100, 1);
640 let bytes = enc.encode_frame(&frame).expect("encode");
641 assert_eq!(bytes.len(), input.len() * 2);
642 let decoded = dec.decode_bytes(&bytes).expect("decode");
643 let got = frame_samples(&decoded);
644 for (&orig, &g) in input.iter().zip(got.iter()) {
645 assert!((orig - g).abs() < 0.0001, "I16 BE roundtrip");
646 }
647 }
648
649 #[test]
652 fn test_i24_le_roundtrip() {
653 let cfg = PcmConfig {
654 format: PcmFormat::I24,
655 byte_order: ByteOrder::Little,
656 sample_rate: 96000,
657 channels: 2,
658 };
659 let input: Vec<f32> = vec![0.0, 0.5, -0.5, 0.999, -0.999];
660 let enc = PcmEncoder::new(cfg.clone());
661 let dec = PcmDecoder::new(cfg);
662 let frame = make_frame(input.clone(), 96000, 2);
663 let bytes = enc.encode_frame(&frame).expect("encode");
664 assert_eq!(bytes.len(), input.len() * 3);
665 let decoded = dec.decode_bytes(&bytes).expect("decode");
666 let got = frame_samples(&decoded);
667 for (&orig, &g) in input.iter().zip(got.iter()) {
668 assert!(
669 (orig - g).abs() < 0.000001,
670 "I24 LE roundtrip orig={orig} got={g}"
671 );
672 }
673 }
674
675 #[test]
676 fn test_i24_be_roundtrip() {
677 let cfg = PcmConfig {
678 format: PcmFormat::I24,
679 byte_order: ByteOrder::Big,
680 sample_rate: 96000,
681 channels: 1,
682 };
683 let input: Vec<f32> = vec![0.0, -0.1, 0.3, -0.7, 0.9];
684 let enc = PcmEncoder::new(cfg.clone());
685 let dec = PcmDecoder::new(cfg);
686 let frame = make_frame(input.clone(), 96000, 1);
687 let bytes = enc.encode_frame(&frame).expect("encode");
688 let decoded = dec.decode_bytes(&bytes).expect("decode");
689 let got = frame_samples(&decoded);
690 for (&orig, &g) in input.iter().zip(got.iter()) {
691 assert!(
692 (orig - g).abs() < 0.000001,
693 "I24 BE roundtrip orig={orig} got={g}"
694 );
695 }
696 }
697
698 #[test]
701 fn test_i32_le_roundtrip() {
702 let cfg = PcmConfig {
703 format: PcmFormat::I32,
704 byte_order: ByteOrder::Little,
705 sample_rate: 192000,
706 channels: 1,
707 };
708 let input = vec![0.0f32, 0.5, -0.5, 0.9999, -0.9999];
709 let enc = PcmEncoder::new(cfg.clone());
710 let dec = PcmDecoder::new(cfg);
711 let frame = make_frame(input.clone(), 192000, 1);
712 let bytes = enc.encode_frame(&frame).expect("encode");
713 assert_eq!(bytes.len(), input.len() * 4);
714 let decoded = dec.decode_bytes(&bytes).expect("decode");
715 let got = frame_samples(&decoded);
716 for (&orig, &g) in input.iter().zip(got.iter()) {
717 assert!(
718 (orig - g).abs() < 0.0001,
719 "I32 LE roundtrip orig={orig} got={g}"
720 );
721 }
722 }
723
724 #[test]
727 fn test_f32_le_roundtrip() {
728 let cfg = PcmConfig {
729 format: PcmFormat::F32,
730 byte_order: ByteOrder::Little,
731 sample_rate: 48000,
732 channels: 2,
733 };
734 let input: Vec<f32> = (0..64).map(|i| (i as f32 / 32.0) - 1.0).collect();
735 let enc = PcmEncoder::new(cfg.clone());
736 let dec = PcmDecoder::new(cfg);
737 let frame = make_frame(input.clone(), 48000, 2);
738 let bytes = enc.encode_frame(&frame).expect("encode");
739 assert_eq!(bytes.len(), input.len() * 4);
740 let decoded = dec.decode_bytes(&bytes).expect("decode");
741 let got = frame_samples(&decoded);
742 for (&orig, &g) in input.iter().zip(got.iter()) {
743 assert_eq!(orig, g, "F32 LE should be lossless");
744 }
745 }
746
747 #[test]
748 fn test_f32_be_roundtrip() {
749 let cfg = PcmConfig {
750 format: PcmFormat::F32,
751 byte_order: ByteOrder::Big,
752 sample_rate: 44100,
753 channels: 1,
754 };
755 let input = vec![0.0f32, 0.5, -0.5, 1.0, -1.0];
756 let enc = PcmEncoder::new(cfg.clone());
757 let dec = PcmDecoder::new(cfg);
758 let frame = make_frame(input.clone(), 44100, 1);
759 let bytes = enc.encode_frame(&frame).expect("encode");
760 let decoded = dec.decode_bytes(&bytes).expect("decode");
761 let got = frame_samples(&decoded);
762 for (&orig, &g) in input.iter().zip(got.iter()) {
763 assert_eq!(orig, g, "F32 BE should be lossless");
764 }
765 }
766
767 #[test]
770 fn test_f64_le_roundtrip() {
771 let cfg = PcmConfig {
772 format: PcmFormat::F64,
773 byte_order: ByteOrder::Little,
774 sample_rate: 48000,
775 channels: 1,
776 };
777 let input = vec![0.0f32, 0.123, -0.456, 0.789, -0.999];
778 let enc = PcmEncoder::new(cfg.clone());
779 let dec = PcmDecoder::new(cfg);
780 let frame = make_frame(input.clone(), 48000, 1);
781 let bytes = enc.encode_frame(&frame).expect("encode");
782 assert_eq!(bytes.len(), input.len() * 8);
783 let decoded = dec.decode_bytes(&bytes).expect("decode");
784 let got = frame_samples(&decoded);
785 for (&orig, &g) in input.iter().zip(got.iter()) {
786 assert!(
787 (orig - g).abs() < 1e-6,
788 "F64 LE roundtrip orig={orig} got={g}"
789 );
790 }
791 }
792
793 #[test]
796 fn test_mismatched_channels_error() {
797 let cfg = PcmConfig {
798 format: PcmFormat::I16,
799 byte_order: ByteOrder::Little,
800 sample_rate: 44100,
801 channels: 2,
802 };
803 let enc = PcmEncoder::new(cfg);
804 let frame = make_frame(vec![0.0f32; 128], 44100, 1);
806 assert!(enc.encode_frame(&frame).is_err());
807 }
808
809 #[test]
810 fn test_mismatched_sample_rate_error() {
811 let cfg = PcmConfig {
812 format: PcmFormat::I16,
813 byte_order: ByteOrder::Little,
814 sample_rate: 44100,
815 channels: 1,
816 };
817 let enc = PcmEncoder::new(cfg);
818 let frame = make_frame(vec![0.0f32; 64], 48000, 1); assert!(enc.encode_frame(&frame).is_err());
820 }
821
822 #[test]
823 fn test_decode_bad_alignment_error() {
824 let cfg = PcmConfig {
825 format: PcmFormat::I16,
826 byte_order: ByteOrder::Little,
827 sample_rate: 48000,
828 channels: 1,
829 };
830 let dec = PcmDecoder::new(cfg);
831 let bytes = vec![0u8; 3]; assert!(dec.decode_bytes(&bytes).is_err());
833 }
834
835 #[test]
836 fn test_encode_raw_roundtrip() {
837 let cfg = PcmConfig {
838 format: PcmFormat::I16,
839 byte_order: ByteOrder::Little,
840 sample_rate: 44100,
841 channels: 2,
842 };
843 let enc = PcmEncoder::new(cfg.clone());
844 let dec = PcmDecoder::new(cfg);
845 let raw: Vec<f32> = (0..64).map(|i| (i as f32 / 32.0) - 1.0).collect();
846 let bytes = enc.encode_raw(&raw).expect("encode_raw");
847 let decoded = dec.decode_bytes(&bytes).expect("decode");
848 let got = frame_samples(&decoded);
849 assert_eq!(got.len(), raw.len());
850 }
851
852 #[test]
853 fn test_encode_raw_bad_alignment_error() {
854 let cfg = PcmConfig {
855 format: PcmFormat::I16,
856 byte_order: ByteOrder::Little,
857 sample_rate: 44100,
858 channels: 2,
859 };
860 let enc = PcmEncoder::new(cfg);
861 let raw = vec![0.0f32; 3];
863 assert!(enc.encode_raw(&raw).is_err());
864 }
865
866 #[test]
867 fn test_frame_count() {
868 let cfg = PcmConfig {
869 format: PcmFormat::I16,
870 byte_order: ByteOrder::Little,
871 sample_rate: 44100,
872 channels: 2,
873 };
874 let dec = PcmDecoder::new(cfg);
875 assert_eq!(dec.frame_count(&vec![0u8; 256]), 64);
877 }
878
879 #[test]
880 fn test_silence_encode_decode() {
881 let cfg = PcmConfig {
882 format: PcmFormat::I16,
883 byte_order: ByteOrder::Little,
884 sample_rate: 44100,
885 channels: 2,
886 };
887 let enc = PcmEncoder::new(cfg.clone());
888 let dec = PcmDecoder::new(cfg);
889 let silence = make_frame(vec![0.0f32; 512], 44100, 2);
890 let bytes = enc.encode_frame(&silence).expect("encode");
891 assert!(bytes.iter().all(|&b| b == 0));
893 let decoded = dec.decode_bytes(&bytes).expect("decode");
894 let got = frame_samples(&decoded);
895 assert!(got.iter().all(|&s| s == 0.0));
896 }
897
898 #[test]
899 fn test_config_accessor() {
900 let cfg = PcmConfig::default();
901 let enc = PcmEncoder::new(cfg.clone());
902 let dec = PcmDecoder::new(cfg);
903 assert_eq!(enc.config().channels, 2);
904 assert_eq!(dec.config().sample_rate, 48000);
905 }
906}