Skip to main content

wmv_decoder/wma/
mdct.rs

1//! MDCT/IMDCT implementation.
2//!
3
4use std::f64::consts::PI;
5
6pub struct MdctNaive {
7    /// Frame size (N). Full IMDCT output is 2N.
8    pub len: usize,
9    /// Scale factor (double precision in upstream).
10    pub scale: f64,
11}
12
13impl MdctNaive {
14    pub fn new(len: usize, scale: f64) -> Self {
15        Self { len, scale }
16    }
17
18    /// Half-length inverse MDCT.
19    ///
20    /// Input: N coefficients.
21    /// Output: N samples (half IMDCT), matching upstream's MDCT semantics.
22    pub fn imdct_half(&self, dst: &mut [f32], src: &[f32]) {
23        // Translated from `ff_tx_mdct_naive_inv`.
24        // In upstream: len = s->len >> 1; len2 = len*2 (== s->len)
25        let len = self.len >> 1;
26        let len2 = len * 2;
27        let phase = PI / (4.0 * (len2 as f64));
28
29        for i in 0..len {
30            let mut sum_d: f64 = 0.0;
31            let mut sum_u: f64 = 0.0;
32
33            let i_d = phase * ((4 * len - 2 * i - 1) as f64);
34            let i_u = phase * ((3 * len2 + 2 * i + 1) as f64);
35
36            for j in 0..len2 {
37                let a = (2 * j + 1) as f64;
38                let a_d = (a * i_d).cos();
39                let a_u = (a * i_u).cos();
40                let val = src[j] as f64;
41                sum_d += a_d * val;
42                sum_u += a_u * val;
43            }
44
45            dst[i] = (sum_d * self.scale) as f32;
46            dst[i + len] = (-(sum_u * self.scale)) as f32;
47        }
48    }
49
50    /// Full IMDCT.
51    ///
52    /// Input: N coefficients.
53    /// Output: 2N samples.
54    pub fn imdct_full(&self, dst: &mut [f32], src: &[f32]) {
55        // Translated from `ff_tx_mdct_inv_full`.
56        let len = self.len * 2;
57        let len2 = len / 2;
58        let len4 = len / 4;
59
60        // The half IMDCT is written into the middle of the output.
61        self.imdct_half(&mut dst[len4..len4 + len2], src);
62
63        for i in 0..len4 {
64            dst[i] = -dst[len2 - i - 1];
65            dst[len - i - 1] = dst[len2 + i];
66        }
67    }
68}