use flac_io::{decode, encode, encode_ogg, info, FlacAudio};
use std::path::Path;
fn fixture(name: &str) -> Vec<u8> {
let path = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("tests/fixtures")
.join(name);
std::fs::read(path).unwrap()
}
#[test]
fn decodes_real_reference_ogg_bit_exact() {
let oga = fixture("realmusic_16_44.oga");
let native = fixture("realmusic_16_44.flac");
let from_ogg = decode(&oga).expect("decode .oga");
let from_native = decode(&native).expect("decode .flac");
assert_eq!(from_ogg.samples, from_native.samples);
assert_eq!(from_ogg.sample_rate, from_native.sample_rate);
assert_eq!(from_ogg.channels, from_native.channels);
assert_eq!(from_ogg.bits_per_sample, from_native.bits_per_sample);
}
#[test]
fn info_auto_detects_ogg() {
let oga = fixture("realmusic_16_44.oga");
let i = info(&oga).expect("info on .oga");
let d = decode(&oga).unwrap();
assert_eq!(i.sample_rate, d.sample_rate);
assert_eq!(i.channels, d.channels);
assert_eq!(i.bits_per_sample, d.bits_per_sample);
}
fn audio(channels: u8, bps: u8, rate: u32, len: usize) -> FlacAudio {
let (lo, hi) = (-(1i64 << (bps - 1)), (1i64 << (bps - 1)) - 1);
let samples = (0..channels)
.map(|c| {
(0..len)
.map(|n| {
let v = ((n as i64 * (c as i64 + 3) * 131) % (hi - lo + 1)) + lo;
v as i32
})
.collect()
})
.collect();
FlacAudio {
sample_rate: rate,
channels,
bits_per_sample: bps,
samples,
}
}
#[test]
fn encode_ogg_round_trips_across_configs() {
let cases = [
(1u8, 8u8, 8000u32, 1), (1, 16, 44100, 4096), (2, 16, 44100, 10_000), (2, 24, 96000, 9000),
(6, 16, 48000, 5000),
(8, 16, 48000, 4097), (2, 32, 48000, 6000),
];
for (ch, bps, rate, len) in cases {
let a = audio(ch, bps, rate, len);
let bytes = encode_ogg(&a).expect("encode_ogg");
let back = decode(&bytes).expect("decode our .oga");
assert_eq!(back.samples, a.samples, "round-trip {ch}ch/{bps}bit/{len}");
assert_eq!(back.sample_rate, rate);
assert_eq!(back.bits_per_sample, bps);
let i = info(&bytes).unwrap();
assert_eq!(i.channels, ch);
assert_eq!(i.total_samples as usize, len);
}
}
#[test]
fn encode_ogg_is_deterministic() {
let a = audio(2, 16, 44100, 12_000);
assert_eq!(encode_ogg(&a).unwrap(), encode_ogg(&a).unwrap());
}
#[test]
fn empty_stream_round_trips_through_ogg() {
let a = FlacAudio {
sample_rate: 44100,
channels: 1,
bits_per_sample: 16,
samples: vec![vec![]],
};
let bytes = encode_ogg(&a).expect("encode empty .oga");
let back = decode(&bytes).expect("decode empty .oga");
assert_eq!(back.samples_per_channel(), 0);
}
#[test]
fn ogg_and_native_decode_to_the_same_samples() {
let a = audio(2, 16, 44100, 9000);
let native = decode(&encode(&a).unwrap()).unwrap();
let ogg = decode(&encode_ogg(&a).unwrap()).unwrap();
assert_eq!(native.samples, ogg.samples);
}
#[test]
fn large_stream_spanning_many_pages_round_trips() {
let a = audio(2, 16, 44100, 4096 * 30 + 7);
let bytes = encode_ogg(&a).expect("encode large .oga");
let back = decode(&bytes).expect("decode large .oga");
assert_eq!(back.samples, a.samples);
assert_eq!(back.samples_per_channel(), 4096 * 30 + 7);
}