use core::f64::consts::FRAC_PI_2;
pub const BASIC_WINDOW_LEN: usize = 240;
pub const CELT_OVERLAP_48K: usize = 120;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MdctWindowError {
PositionOutOfRange {
n: usize,
len: usize,
},
ZeroLength,
OddOverlap {
overlap: usize,
},
}
impl core::fmt::Display for MdctWindowError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match *self {
MdctWindowError::PositionOutOfRange { n, len } => write!(
f,
"oxideav-opus: CELT §4.3.7 window position {n} out of range \
(window length {len} allows 0..={})",
len.saturating_sub(1)
),
MdctWindowError::ZeroLength => {
write!(f, "oxideav-opus: CELT §4.3.7 window requires length L >= 1")
}
MdctWindowError::OddOverlap { overlap } => write!(
f,
"oxideav-opus: CELT §4.3.7 low-overlap window requires an even \
overlap (got {overlap})"
),
}
}
}
impl std::error::Error for MdctWindowError {}
pub fn window_tap(n: usize, len: usize) -> Result<f64, MdctWindowError> {
if len == 0 {
return Err(MdctWindowError::ZeroLength);
}
if n >= len {
return Err(MdctWindowError::PositionOutOfRange { n, len });
}
let t = (n as f64 + 0.5) / len as f64;
let inner = (FRAC_PI_2 * t).sin();
let inner_sq = inner * inner;
Ok((FRAC_PI_2 * inner_sq).sin())
}
pub fn basic_window() -> [f64; BASIC_WINDOW_LEN] {
let mut w = [0.0_f64; BASIC_WINDOW_LEN];
for (n, slot) in w.iter_mut().enumerate() {
*slot = window_tap(n, BASIC_WINDOW_LEN).expect("in-range basic-window tap");
}
w
}
pub fn mdct_window(overlap: usize) -> Result<Vec<f64>, MdctWindowError> {
if overlap == 0 {
return Err(MdctWindowError::ZeroLength);
}
if overlap % 2 != 0 {
return Err(MdctWindowError::OddOverlap { overlap });
}
let mut w = Vec::with_capacity(overlap);
for n in 0..overlap {
w.push(window_tap(n, overlap)?);
}
Ok(w)
}
pub fn celt_overlap_window() -> [f64; CELT_OVERLAP_48K] {
let mut w = [0.0_f64; CELT_OVERLAP_48K];
for (n, slot) in w.iter_mut().enumerate() {
*slot = window_tap(n, CELT_OVERLAP_48K).expect("in-range CELT overlap tap");
}
w
}
#[cfg(test)]
mod tests {
use super::*;
const EPS: f64 = 1e-12;
#[test]
fn basic_window_len_is_240() {
assert_eq!(BASIC_WINDOW_LEN, 240);
assert_eq!(basic_window().len(), 240);
}
#[test]
fn celt_overlap_is_120() {
assert_eq!(CELT_OVERLAP_48K, 120);
assert_eq!(celt_overlap_window().len(), 120);
}
#[test]
fn window_tap_matches_formula() {
let len = 240;
for &n in &[0_usize, 1, 59, 119, 120, 179, 239] {
let t = (n as f64 + 0.5) / len as f64;
let want = (FRAC_PI_2 * (FRAC_PI_2 * t).sin().powi(2)).sin();
let got = window_tap(n, len).unwrap();
assert!((got - want).abs() < EPS, "n={n}: {got} != {want}");
}
}
#[test]
fn window_taps_are_within_unit_interval() {
for len in [2_usize, 16, 120, 240] {
for n in 0..len {
let w = window_tap(n, len).unwrap();
assert!((0.0..=1.0).contains(&w), "len={len} n={n} w={w}");
}
}
}
#[test]
fn window_is_monotonically_increasing() {
for len in [2_usize, 16, 120, 240] {
for n in 1..len {
let prev = window_tap(n - 1, len).unwrap();
let cur = window_tap(n, len).unwrap();
assert!(cur >= prev, "len={len} n={n}: {cur} < {prev}");
}
}
}
#[test]
fn power_complementarity_holds_basic() {
let len = BASIC_WINDOW_LEN;
for n in 0..len {
let a = window_tap(n, len).unwrap();
let b = window_tap(len - 1 - n, len).unwrap();
assert!((a * a + b * b - 1.0).abs() < EPS, "n={n}: {a}^2+{b}^2 != 1");
}
}
#[test]
fn power_complementarity_holds_overlap() {
for len in [2_usize, 4, 16, 120, 240] {
for n in 0..len {
let a = window_tap(n, len).unwrap();
let b = window_tap(len - 1 - n, len).unwrap();
assert!(
(a * a + b * b - 1.0).abs() < EPS,
"len={len} n={n}: {a}^2+{b}^2 != 1"
);
}
}
}
#[test]
fn window_centre_is_one_over_sqrt_two() {
let half_power = core::f64::consts::FRAC_1_SQRT_2;
for len in [2_usize, 16, 120, 240] {
let lo = window_tap(len / 2 - 1, len).unwrap();
let hi = window_tap(len / 2, len).unwrap();
assert!((lo * lo + hi * hi - 1.0).abs() < EPS);
assert!(
lo <= half_power + EPS && hi >= half_power - EPS,
"len={len}"
);
}
}
#[test]
fn first_and_last_tap_endpoints() {
let len = BASIC_WINDOW_LEN;
let first = window_tap(0, len).unwrap();
let last = window_tap(len - 1, len).unwrap();
assert!(first > 0.0 && first < 0.01, "first={first}");
assert!(last > 0.99 && last < 1.0, "last={last}");
assert!((first * first + last * last - 1.0).abs() < EPS);
}
#[test]
fn mdct_window_matches_window_tap() {
let w = mdct_window(120).unwrap();
assert_eq!(w.len(), 120);
for (n, &got) in w.iter().enumerate() {
assert_eq!(got, window_tap(n, 120).unwrap());
}
}
#[test]
fn mdct_window_is_power_complementary() {
let w = mdct_window(120).unwrap();
let len = w.len();
for n in 0..len {
assert!((w[n] * w[n] + w[len - 1 - n] * w[len - 1 - n] - 1.0).abs() < EPS);
}
}
#[test]
fn celt_overlap_window_matches_mdct_window() {
let arr = celt_overlap_window();
let vec = mdct_window(CELT_OVERLAP_48K).unwrap();
assert_eq!(arr.len(), vec.len());
for (a, b) in arr.iter().zip(vec.iter()) {
assert_eq!(a, b);
}
}
#[test]
fn basic_window_matches_window_tap() {
let w = basic_window();
for (n, &got) in w.iter().enumerate() {
assert_eq!(got, window_tap(n, BASIC_WINDOW_LEN).unwrap());
}
}
#[test]
fn window_tap_rejects_out_of_range_position() {
assert_eq!(
window_tap(240, 240),
Err(MdctWindowError::PositionOutOfRange { n: 240, len: 240 })
);
assert_eq!(
window_tap(5, 5),
Err(MdctWindowError::PositionOutOfRange { n: 5, len: 5 })
);
}
#[test]
fn window_tap_rejects_zero_length() {
assert_eq!(window_tap(0, 0), Err(MdctWindowError::ZeroLength));
}
#[test]
fn mdct_window_rejects_zero_overlap() {
assert_eq!(mdct_window(0), Err(MdctWindowError::ZeroLength));
}
#[test]
fn mdct_window_rejects_odd_overlap() {
assert_eq!(
mdct_window(121),
Err(MdctWindowError::OddOverlap { overlap: 121 })
);
}
#[test]
fn error_display_messages() {
assert!(MdctWindowError::PositionOutOfRange { n: 7, len: 4 }
.to_string()
.contains("position 7"));
assert!(MdctWindowError::ZeroLength.to_string().contains("L >= 1"));
assert!(MdctWindowError::OddOverlap { overlap: 3 }
.to_string()
.contains("even"));
}
}