use std::path::PathBuf;
use audio_codec_bsd::{open, ContainerDecoder, FormatKind};
use hound::{SampleFormat, WavSpec, WavWriter};
fn write_pcm_wav(channels: u16, sample_rate: u32, interleaved: &[i16], name: &str) -> PathBuf {
let spec = WavSpec {
channels,
sample_rate,
bits_per_sample: 16,
sample_format: SampleFormat::Int,
};
let mut path = std::env::temp_dir();
path.push(format!(
"audio_codec_bsd_byte_exact_{id}_{name}.wav",
id = std::process::id(),
));
let mut writer = WavWriter::create(&path, spec).expect("create wav");
for &v in interleaved {
writer.write_sample(v).expect("write sample");
}
writer.finalize().expect("finalize wav");
path
}
fn drain_to_planar_i16(dec: &mut dyn ContainerDecoder) -> Vec<i16> {
let mut out: Vec<i16> = Vec::new();
while let Ok(Some(frame)) = dec.next_frame() {
for &s in &frame.samples {
let scaled = s * 32_768.0_f32;
let clamped = scaled.clamp(-32_768.0_f32, 32_767.0_f32);
out.push((clamped.round()) as i16);
}
}
out
}
#[test]
fn mono_byte_exact_roundtrip() {
let original: Vec<i16> = vec![
-32768, -16384, -1, 0, 1, 16383, 32767, 100, 200, -300, 16000, -16000,
];
let path = write_pcm_wav(1, 48_000, &original, "mono_byte_exact");
let mut dec = open(&path).expect("factory open");
let info = dec.open(&path).expect("trait open");
assert_eq!(info.format, FormatKind::Wav);
let recovered = drain_to_planar_i16(&mut *dec);
let _ = std::fs::remove_file(&path);
assert_eq!(recovered, original);
}
#[test]
fn stereo_byte_exact_roundtrip() {
let want_ch0: Vec<i16> = vec![-32768, -16384, -1, 0, 1, 16383, 32767, 100];
let want_ch1: Vec<i16> = vec![200, -300, 16000, -16000, 32767, -32768, 500, -500];
let frames = want_ch0.len();
let interleaved: Vec<i16> = want_ch0
.iter()
.zip(&want_ch1)
.flat_map(|(&a, &b)| [a, b])
.collect();
let path = write_pcm_wav(2, 48_000, &interleaved, "stereo_byte_exact");
let mut dec = open(&path).expect("factory open");
let _info = dec.open(&path).expect("trait open");
let recovered = drain_to_planar_i16(&mut *dec);
let _ = std::fs::remove_file(&path);
assert_eq!(recovered.len(), frames * 2);
let (ch0, ch1) = recovered.split_at(frames);
assert_eq!(ch0, want_ch0.as_slice());
assert_eq!(ch1, want_ch1.as_slice());
}
#[test]
fn byte_exact_holds_across_sample_rates() {
let pattern: Vec<i16> = vec![-32768, -16384, -1, 0, 1, 16383, 32767, 12345, -12345, 7];
for &sr in &[8000u32, 22050, 44100, 48000, 96000] {
let path = write_pcm_wav(1, sr, &pattern, "sr_param");
let mut dec = open(&path).expect("factory open");
let info = dec.open(&path).expect("trait open");
assert_eq!(info.sample_rate, sr);
let recovered = drain_to_planar_i16(&mut *dec);
let _ = std::fs::remove_file(&path);
assert_eq!(recovered, pattern, "byte-exact failed at sample rate {sr}");
}
}