use svod_arch::vad::AudioChunk;
use crate::audio::{EncoderBounds, FixedLengthSplitter, Splitter};
fn bounds_realistic() -> EncoderBounds {
EncoderBounds { sample_rate: 16_000, hop_length: 160, subsampling_factor: 4, max_mel_frames: 2_080 }
}
fn bounds_tiny() -> EncoderBounds {
EncoderBounds { sample_rate: 16_000, hop_length: 2, subsampling_factor: 2, max_mel_frames: 12 }
}
#[test]
fn encoder_bounds_getters() {
let b = bounds_realistic();
assert_eq!(b.align_to_samples(), 640);
assert_eq!(b.max_samples(), 331_520);
let secs = b.encoder_capacity_secs();
assert!((secs - 20.72).abs() < 0.01, "got {secs}");
}
#[test]
fn encoder_bounds_underflow_safe() {
let b = EncoderBounds { sample_rate: 16_000, hop_length: 160, subsampling_factor: 8, max_mel_frames: 4 };
assert_eq!(b.max_samples(), 0);
assert_eq!(b.encoder_capacity_secs(), 0.0);
}
#[test]
fn fixed_length_splitter_empty_waveform() {
let mut s = FixedLengthSplitter::new();
let chunks = s.split(&[], &bounds_tiny()).unwrap();
assert!(chunks.is_empty());
}
#[test]
fn fixed_length_splitter_shorter_than_max() {
let mut s = FixedLengthSplitter::new();
let wf = vec![0.0; 10];
let chunks = s.split(&wf, &bounds_tiny()).unwrap();
assert_eq!(chunks, vec![AudioChunk { start_sample: 0, end_sample: 10 }]);
}
#[test]
fn fixed_length_splitter_exact_one_chunk() {
let mut s = FixedLengthSplitter::new();
let wf = vec![0.0; 16];
let chunks = s.split(&wf, &bounds_tiny()).unwrap();
assert_eq!(chunks, vec![AudioChunk { start_sample: 0, end_sample: 16 }]);
}
#[test]
fn fixed_length_splitter_exact_two_chunks() {
let mut s = FixedLengthSplitter::new();
let wf = vec![0.0; 32];
let chunks = s.split(&wf, &bounds_tiny()).unwrap();
assert_eq!(
chunks,
vec![AudioChunk { start_sample: 0, end_sample: 16 }, AudioChunk { start_sample: 16, end_sample: 32 },]
);
}
#[test]
fn fixed_length_splitter_two_chunks_plus_tail() {
let mut s = FixedLengthSplitter::new();
let wf = vec![0.0; 33];
let chunks = s.split(&wf, &bounds_tiny()).unwrap();
assert_eq!(
chunks,
vec![
AudioChunk { start_sample: 0, end_sample: 16 },
AudioChunk { start_sample: 16, end_sample: 32 },
AudioChunk { start_sample: 32, end_sample: 33 },
]
);
}
#[test]
fn fixed_length_splitter_final_chunk_can_be_unaligned() {
let mut s = FixedLengthSplitter::new();
let wf = vec![0.0; 30];
let chunks = s.split(&wf, &bounds_tiny()).unwrap();
assert_eq!(
chunks,
vec![AudioChunk { start_sample: 0, end_sample: 16 }, AudioChunk { start_sample: 16, end_sample: 30 },]
);
}
#[test]
fn fixed_length_splitter_progress_under_degenerate_bounds() {
let bounds = EncoderBounds { sample_rate: 16_000, hop_length: 2, subsampling_factor: 2, max_mel_frames: 0 };
let mut s = FixedLengthSplitter::new();
let chunks = s.split(&[0.0_f32; 9], &bounds).unwrap();
assert_eq!(
chunks,
vec![
AudioChunk { start_sample: 0, end_sample: 4 },
AudioChunk { start_sample: 4, end_sample: 8 },
AudioChunk { start_sample: 8, end_sample: 9 },
]
);
}
#[test]
fn fixed_length_splitter_alignment_does_not_divide_max() {
let bounds = EncoderBounds { sample_rate: 16_000, hop_length: 3, subsampling_factor: 2, max_mel_frames: 8 };
let mut s = FixedLengthSplitter::new();
let wf = vec![0.0; 26];
let chunks = s.split(&wf, &bounds).unwrap();
assert_eq!(
chunks,
vec![
AudioChunk { start_sample: 0, end_sample: 12 },
AudioChunk { start_sample: 12, end_sample: 24 },
AudioChunk { start_sample: 24, end_sample: 26 },
]
);
}