use melpe::core_types::{
SAMPLE_RATE, SUPERFRAME_SAMPLES, SUPERFRAME_BYTES_600, FRAME_SAMPLES,
};
use melpe::encoder::Encoder;
use melpe::decoder::Decoder;
fn sine_wave(freq: f32, amplitude: f32, n: usize) -> Vec<f32> {
(0..n)
.map(|i| {
amplitude * (2.0 * std::f32::consts::PI * freq * i as f32 / SAMPLE_RATE as f32).sin()
})
.collect()
}
fn to_superframe_buf(samples: &[f32]) -> [f32; SUPERFRAME_SAMPLES] {
let mut buf = [0.0f32; SUPERFRAME_SAMPLES];
let n = samples.len().min(SUPERFRAME_SAMPLES);
buf[..n].copy_from_slice(&samples[..n]);
buf
}
fn rms(samples: &[f32]) -> f32 {
if samples.is_empty() { return 0.0; }
(samples.iter().map(|x| x * x).sum::<f32>() / samples.len() as f32).sqrt()
}
fn peak(samples: &[f32]) -> f32 {
samples.iter().fold(0.0f32, |m, &s| m.max(s.abs()))
}
fn loopback(
enc: &mut Encoder,
dec: &mut Decoder,
input: &[f32; SUPERFRAME_SAMPLES],
) -> [f32; SUPERFRAME_SAMPLES] {
let mut bitstream = [0u8; SUPERFRAME_BYTES_600];
let mut output = [0.0f32; SUPERFRAME_SAMPLES];
enc.encode(input, &mut bitstream);
dec.decode(&bitstream, &mut output);
output
}
#[test]
fn test_loopback_sine_produces_output() {
let mut enc = Encoder::new();
let mut dec = Decoder::new();
let input = to_superframe_buf(&sine_wave(200.0, 0.5, SUPERFRAME_SAMPLES));
let output = loopback(&mut enc, &mut dec, &input);
assert!(output.iter().all(|x| x.is_finite()), "Output must be finite");
let out_rms = rms(&output);
assert!(
out_rms > 1e-6,
"Loopback of sine should produce output, rms={}",
out_rms
);
}
#[test]
fn test_loopback_silence() {
let mut enc = Encoder::new();
let mut dec = Decoder::new();
let input = [0.0f32; SUPERFRAME_SAMPLES];
let output = loopback(&mut enc, &mut dec, &input);
assert!(output.iter().all(|x| x.is_finite()), "Output must be finite");
let out_rms = rms(&output);
assert!(
out_rms < 0.1,
"Silence loopback should be quiet, rms={}",
out_rms
);
}
#[test]
fn test_loopback_deterministic() {
let input = to_superframe_buf(&sine_wave(150.0, 0.4, SUPERFRAME_SAMPLES));
let mut enc1 = Encoder::new();
let mut dec1 = Decoder::new();
let out1 = loopback(&mut enc1, &mut dec1, &input);
let mut enc2 = Encoder::new();
let mut dec2 = Decoder::new();
let out2 = loopback(&mut enc2, &mut dec2, &input);
for i in 0..SUPERFRAME_SAMPLES {
assert!(
(out1[i] - out2[i]).abs() < 1e-6,
"Determinism failed at [{}]: {} vs {}",
i, out1[i], out2[i]
);
}
}
#[test]
fn test_loopback_loud_vs_quiet() {
let loud = to_superframe_buf(&sine_wave(200.0, 0.8, SUPERFRAME_SAMPLES));
let quiet = to_superframe_buf(&sine_wave(200.0, 0.02, SUPERFRAME_SAMPLES));
let mut enc = Encoder::new();
let mut dec = Decoder::new();
let out_loud = loopback(&mut enc, &mut dec, &loud);
enc.reset();
dec.reset();
let out_quiet = loopback(&mut enc, &mut dec, &quiet);
let rms_loud = rms(&out_loud);
let rms_quiet = rms(&out_quiet);
assert!(
rms_loud > rms_quiet,
"Louder input should produce louder output: loud_rms={}, quiet_rms={}",
rms_loud, rms_quiet
);
}
#[test]
fn test_loopback_different_freqs_differ() {
let low = to_superframe_buf(&sine_wave(100.0, 0.5, SUPERFRAME_SAMPLES));
let high = to_superframe_buf(&sine_wave(300.0, 0.5, SUPERFRAME_SAMPLES));
let mut enc = Encoder::new();
let mut dec = Decoder::new();
let out_low = loopback(&mut enc, &mut dec, &low);
enc.reset();
dec.reset();
let out_high = loopback(&mut enc, &mut dec, &high);
let diff: f32 = out_low.iter().zip(out_high.iter())
.map(|(a, b)| (a - b).abs())
.sum::<f32>() / SUPERFRAME_SAMPLES as f32;
assert!(
diff > 1e-6,
"Different frequencies should produce different output, avg_diff={}",
diff
);
}
#[test]
fn test_loopback_multi_superframe_stable() {
let mut enc = Encoder::new();
let mut dec = Decoder::new();
let samples = sine_wave(180.0, 0.5, SUPERFRAME_SAMPLES * 10);
let mut prev_peak = 0.0f32;
for i in 0..10 {
let start = i * SUPERFRAME_SAMPLES;
let input = to_superframe_buf(&samples[start..start + SUPERFRAME_SAMPLES]);
let output = loopback(&mut enc, &mut dec, &input);
assert!(
output.iter().all(|x| x.is_finite()),
"Output not finite at superframe {}",
i
);
let p = peak(&output);
assert!(
p < 50.0,
"Output blowing up at superframe {}: peak={}",
i, p
);
}
}
#[test]
fn test_loopback_multi_superframe_no_clicks() {
let mut enc = Encoder::new();
let mut dec = Decoder::new();
let samples = sine_wave(150.0, 0.5, SUPERFRAME_SAMPLES * 4);
let mut all_output = Vec::with_capacity(SUPERFRAME_SAMPLES * 4);
for i in 0..4 {
let start = i * SUPERFRAME_SAMPLES;
let input = to_superframe_buf(&samples[start..start + SUPERFRAME_SAMPLES]);
let output = loopback(&mut enc, &mut dec, &input);
all_output.extend_from_slice(&output);
}
for boundary in 1..3 {
let idx = boundary * SUPERFRAME_SAMPLES;
let jump = (all_output[idx] - all_output[idx - 1]).abs();
let local_rms = rms(&all_output[idx - 10..idx + 10]);
if local_rms > 1e-4 {
let jump_ratio = jump / local_rms;
assert!(
jump_ratio < 20.0,
"Possible click at boundary {}: jump={}, local_rms={}, ratio={}",
boundary, jump, local_rms, jump_ratio
);
}
}
}
#[test]
fn test_loopback_bitstream_not_constant() {
let mut enc = Encoder::new();
let samples = sine_wave(200.0, 0.5, SUPERFRAME_SAMPLES * 2);
let mut samples2 = samples.clone();
for i in SUPERFRAME_SAMPLES..SUPERFRAME_SAMPLES * 2 {
samples2[i] = 0.5 * (2.0 * std::f32::consts::PI * 350.0 * i as f32 / SAMPLE_RATE as f32).sin();
}
let mut bs1 = [0u8; SUPERFRAME_BYTES_600];
let mut bs2 = [0u8; SUPERFRAME_BYTES_600];
let input1 = to_superframe_buf(&samples2[..SUPERFRAME_SAMPLES]);
let input2 = to_superframe_buf(&samples2[SUPERFRAME_SAMPLES..]);
enc.encode(&input1, &mut bs1);
enc.encode(&input2, &mut bs2);
assert_ne!(
bs1, bs2,
"Different signal content should produce different bitstreams"
);
}
#[test]
fn test_loopback_6_bytes_sufficient() {
let mut enc = Encoder::new();
let input = to_superframe_buf(&sine_wave(200.0, 0.5, SUPERFRAME_SAMPLES));
let mut bitstream = [0u8; SUPERFRAME_BYTES_600];
enc.encode(&input, &mut bitstream);
let mut dec1 = Decoder::new();
let mut dec2 = Decoder::new();
let mut out1 = [0.0f32; SUPERFRAME_SAMPLES];
let mut out2 = [0.0f32; SUPERFRAME_SAMPLES];
dec1.decode(&bitstream, &mut out1);
dec2.decode(&bitstream, &mut out2);
for i in 0..SUPERFRAME_SAMPLES {
assert!(
(out1[i] - out2[i]).abs() < 1e-6,
"Two decoders should match at [{}]",
i
);
}
}
#[test]
fn test_loopback_dc_signal() {
let mut enc = Encoder::new();
let mut dec = Decoder::new();
let input = [0.3f32; SUPERFRAME_SAMPLES];
let output = loopback(&mut enc, &mut dec, &input);
assert!(output.iter().all(|x| x.is_finite()), "DC output must be finite");
}
#[test]
fn test_loopback_full_scale() {
let mut enc = Encoder::new();
let mut dec = Decoder::new();
let input = to_superframe_buf(&sine_wave(200.0, 1.0, SUPERFRAME_SAMPLES));
let output = loopback(&mut enc, &mut dec, &input);
assert!(output.iter().all(|x| x.is_finite()), "Full-scale output must be finite");
assert!(peak(&output) < 100.0, "Full-scale output should not explode");
}
#[test]
fn test_loopback_impulse() {
let mut enc = Encoder::new();
let mut dec = Decoder::new();
let mut input = [0.0f32; SUPERFRAME_SAMPLES];
input[0] = 1.0;
let output = loopback(&mut enc, &mut dec, &input);
assert!(output.iter().all(|x| x.is_finite()), "Impulse output must be finite");
}
#[test]
fn test_encoder_decoder_independent_reset() {
let input = to_superframe_buf(&sine_wave(200.0, 0.5, SUPERFRAME_SAMPLES));
let mut enc = Encoder::new();
let mut dec = Decoder::new();
let out1 = loopback(&mut enc, &mut dec, &input);
enc.reset();
dec.reset();
let out2 = loopback(&mut enc, &mut dec, &input);
for i in 0..SUPERFRAME_SAMPLES {
assert!(
(out1[i] - out2[i]).abs() < 1e-6,
"Post-reset loopback should match at [{}]: {} vs {}",
i, out1[i], out2[i]
);
}
}