wmv_decoder/wma/
mdct.rs

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