symphonia_core/dsp/mdct/
mod.rs1#[cfg(any(feature = "opt-simd-sse", feature = "opt-simd-avx", feature = "opt-simd-neon"))]
13mod simd;
14
15#[cfg(any(feature = "opt-simd-sse", feature = "opt-simd-avx", feature = "opt-simd-neon"))]
16pub use simd::*;
17
18#[cfg(not(any(feature = "opt-simd-sse", feature = "opt-simd-avx", feature = "opt-simd-neon")))]
19mod no_simd;
20#[cfg(not(any(
21 feature = "opt-simd-sse",
22 feature = "opt-simd-avx",
23 feature = "opt-simd-neon"
24)))]
25pub use no_simd::*;
26
27#[cfg(test)]
28mod tests {
29 use super::*;
30 use std::f64;
31
32 fn imdct_analytical(x: &[f32], y: &mut [f32], scale: f64) {
33 assert!(y.len() == 2 * x.len());
34
35 let n_in = x.len();
37 let n_out = x.len() << 1;
38
39 let pi_2n = f64::consts::PI / (2 * n_out) as f64;
40
41 for (i, item) in y.iter_mut().enumerate().take(n_out) {
42 let accum: f64 = x
43 .iter()
44 .copied()
45 .map(f64::from)
46 .enumerate()
47 .take(n_in)
48 .map(|(j, jtem)| jtem * (pi_2n * ((2 * i + 1 + n_in) * (2 * j + 1)) as f64).cos())
49 .sum();
50
51 *item = (scale * accum) as f32;
52 }
53 }
54
55 #[test]
56 fn verify_imdct() {
57 #[rustfmt::skip]
58 const TEST_VECTOR: [f32; 32] = [
59 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
60 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0,
61 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0,
62 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0,
63 ];
64
65 let mut actual = [0f32; 64];
66 let mut expected = [0f32; 64];
67
68 let scale = (2.0f64 / 64.0).sqrt();
69
70 imdct_analytical(&TEST_VECTOR, &mut expected, scale);
71
72 let mut mdct = Imdct::new_scaled(32, scale);
73 mdct.imdct(&TEST_VECTOR, &mut actual);
74
75 for i in 0..64 {
76 let delta = f64::from(actual[i]) - f64::from(expected[i]);
77 assert!(delta.abs() < 0.00001);
78 }
79 }
80}