use super::*;
#[test]
fn inner_processor_applies_before_stage2() {
let mut n = Normalizer::new(48_000, 2, default_out())
.expect("normalizer")
.with_inner_processor(Box::new(DoubleProcessor));
let stereo: Vec<f32> = (0..CHUNK_FRAMES * 2).map(|i| (i as f32) * 1e-4).collect();
n.push(&stereo, 0).expect("push");
let (chunk, _) = n.pop_chunk().expect("one chunk");
for (i, &s) in chunk.iter().enumerate() {
assert!(
(s - stereo[i] * 2.0).abs() < 1e-6,
"sample {i} should be doubled"
);
}
}
#[test]
fn inner_processor_affects_both_taps() {
let secondary = OutputFormat {
sample_rate: 48_000,
channels: 2,
};
let mut n = Normalizer::new(48_000, 2, default_out())
.expect("normalizer")
.with_secondary(secondary)
.expect("secondary")
.with_inner_processor(Box::new(DoubleProcessor));
let stereo = vec![0.25f32; CHUNK_FRAMES * 2];
n.push(&stereo, 0).expect("push");
let (p, _) = n.pop_chunk().expect("primary chunk");
let (s, _) = n.pop_secondary().expect("secondary chunk");
assert!(
p.iter().all(|&x| (x - 0.5).abs() < 1e-6),
"primary is doubled"
);
assert!(
s.iter().all(|&x| (x - 0.5).abs() < 1e-6),
"secondary is doubled"
);
}
#[test]
fn stop_flush_emits_processor_tail() {
let mut n = Normalizer::new(48_000, 2, default_out())
.expect("normalizer")
.with_inner_processor(Box::new(DelayProcessor::new(4)));
let stereo: Vec<f32> = (0..CHUNK_FRAMES * 2)
.map(|i| (i as f32 + 1.0) * 1e-4)
.collect();
n.push(&stereo, 0).expect("push");
let (c0, _) = n.pop_chunk().expect("first chunk");
assert_eq!(c0.len(), CHUNK_FRAMES * 2);
assert!(
c0[..4].iter().all(|&x| x == 0.0),
"first 4 samples should be silent due to the delay"
);
assert!(
n.pop_chunk().is_none(),
"only one chunk should be available before flush"
);
n.flush().unwrap();
let (c1, _) = n.pop_chunk().expect("flushed tail chunk");
assert_eq!(c1.len(), CHUNK_FRAMES * 2, "final chunk is padded to 20ms");
let last4 = &stereo[stereo.len() - 4..];
for (i, &x) in c1[..4].iter().enumerate() {
assert!(
(x - last4[i]).abs() < 1e-6,
"flush tail should match the end of the input"
);
}
}
#[test]
fn stop_flush_drains_secondary_resampler() {
let secondary = OutputFormat {
sample_rate: 16_000,
channels: 1,
};
let mut n = Normalizer::new(48_000, 2, default_out())
.expect("normalizer")
.with_secondary(secondary)
.expect("secondary");
let stereo = vec![0.3f32; CHUNK_FRAMES * 2];
n.push(&stereo, 0).expect("push");
let mut before = 0usize;
while n.pop_secondary().is_some() {
before += 1;
}
n.flush().unwrap();
let mut after = 0usize;
while let Some((c, _)) = n.pop_secondary() {
assert_eq!(c.len(), 320, "secondary aligns to the fixed 20ms boundary");
after += 1;
}
assert!(after >= 1, "flush should emit the secondary tap's tail");
let _ = before;
}