lc3_codec/decoder/
modified_dct.rs

1use crate::{
2    common::{
3        complex::{Complex, Scaler},
4        config::{FrameDuration, Lc3Config},
5        dct_iv::DiscreteCosTransformIv,
6    },
7    tables::mdct_windows::*,
8};
9#[allow(unused_imports)]
10use num_traits::real::Real;
11
12/// Modified Discrete Cosine Transform
13pub struct ModDiscreteCosTrans<'a> {
14    config: Lc3Config,
15    dct_iv: DiscreteCosTransformIv<'a>,
16    mem_ola_add: &'a mut [Scaler],
17    t_hat_mdct: &'a mut [Scaler],
18    wn: &'static [Scaler],
19    zeros: &'a [Scaler],
20    half_nf_scratch: &'a mut [Scaler],
21}
22
23impl<'a> ModDiscreteCosTrans<'a> {
24    pub fn new(
25        config: Lc3Config,
26        scaler_buf: &'a mut [Scaler],
27        complex_buf: &'a mut [Complex],
28    ) -> (Self, &'a mut [Scaler], &'a mut [Complex]) {
29        let (dctiv_dbl, complex_buf) = DiscreteCosTransformIv::new(config.nf, complex_buf);
30        let (mem_ola_add, scaler_buf) = scaler_buf.split_at_mut(config.nf - config.z);
31        let (t_hat_mdct, scaler_buf) = scaler_buf.split_at_mut(config.nf * 2);
32        let (zeros, scaler_buf) = scaler_buf.split_at_mut(config.nf - config.ne);
33        zeros.fill(0.0);
34        let (half_nf_scratch, scaler_buf) = scaler_buf.split_at_mut(config.nf / 2);
35
36        let wn: &'static [Scaler] = match config.n_ms {
37            FrameDuration::SevenPointFiveMs => match config.nf {
38                60 => &W_N60_7P5MS,
39                120 => &W_N120_7P5MS,
40                180 => &W_N180_7P5MS,
41                240 => &W_N240_7P5MS,
42                360 => &W_N360_7P5MS,
43                _ => panic!("Cannot lookup wn for 7.5ms, invalid nf: {}", config.nf),
44            },
45            FrameDuration::TenMs => match config.nf {
46                80 => &W_N80_10MS,
47                160 => &W_N160_10MS,
48                240 => &W_N240_10MS,
49                320 => &W_N320_10MS,
50                480 => &W_N480_10MS,
51                _ => panic!("Cannot lookup wn for 10ms, invalid nf: {}", config.nf),
52            },
53        };
54
55        (
56            Self {
57                config,
58                dct_iv: dctiv_dbl,
59                mem_ola_add,
60                t_hat_mdct,
61                wn,
62                zeros,
63                half_nf_scratch,
64            },
65            scaler_buf,
66            complex_buf,
67        )
68    }
69
70    /// Split input spectral lines into slices according to frequency bands associated with the frame duration and bandwidth
71    ///
72    /// # Arguments
73    ///
74    /// * `spec_lines` - Input spectral lines (e.g. 400 entries)
75    /// * `freq_samples` - Output frequency samples (e.g. 480 entries)
76    pub fn run(&mut self, spec_lines: &[Scaler], freq_samples: &mut [Scaler]) {
77        assert_eq!(spec_lines.len(), self.config.ne);
78        assert_eq!(freq_samples.len(), self.config.nf);
79
80        // copy spectral lines to the output buffer for in-place processing and pad the remaining entries with zero
81        freq_samples[..self.config.ne].copy_from_slice(spec_lines);
82        freq_samples[self.config.ne..].copy_from_slice(self.zeros);
83
84        // 1. generation of the time domain aliasing buffer
85        self.apply_mdct_inverse(freq_samples);
86
87        // 2. windowing of the time-aliased buffer - read wn in reverse order
88        // it is assumed that t_hat_mdct and wn are nf * 2 in length
89        for (t_hat, wn) in self.t_hat_mdct.iter_mut().zip(self.wn.iter().rev()) {
90            *t_hat *= *wn;
91        }
92
93        // 3. conduct overlap-add operation to get reconstructed time samples
94        self.overlap_add(freq_samples);
95    }
96
97    fn apply_mdct_inverse(&mut self, buf: &mut [Scaler]) {
98        self.dct_iv.run(buf);
99
100        let nf = self.config.nf;
101        assert_eq!(buf.len(), nf);
102
103        self.t_hat_mdct[..nf].copy_from_slice(buf);
104        for (to, from) in self.t_hat_mdct[nf..(nf * 2)].iter_mut().zip(buf.iter().rev()) {
105            *to = -*from;
106        }
107
108        let half_nf = nf / 2;
109        self.half_nf_scratch.copy_from_slice(&self.t_hat_mdct[..half_nf]);
110
111        // move chunks of data half nf to the left (not sure if this is the best way to do this)
112        {
113            let (left, right) = self.t_hat_mdct.split_at_mut(half_nf);
114            left.copy_from_slice(&right[..half_nf]);
115        }
116        {
117            let (left, right) = self.t_hat_mdct[half_nf..].split_at_mut(half_nf);
118            left.copy_from_slice(&right[..half_nf]);
119        }
120        {
121            let (left, right) = self.t_hat_mdct[nf..].split_at_mut(half_nf);
122            left.copy_from_slice(&right[..half_nf]);
123        }
124
125        for (to, from) in self.t_hat_mdct[(half_nf * 3)..]
126            .iter_mut()
127            .zip(self.half_nf_scratch.iter())
128        {
129            *to = -*from;
130        }
131
132        let gain = 1. / (2. * nf as Scaler).sqrt();
133        for item in self.t_hat_mdct.iter_mut().take(2 * nf) {
134            *item *= gain;
135        }
136    }
137
138    fn overlap_add(&mut self, freq_buf: &mut [Scaler]) {
139        let nf = self.config.nf;
140        let z = self.config.z;
141
142        for (freq_buf_n, (mem_ola_add_n, t_hat_mdct_z)) in freq_buf[..(nf - z)]
143            .iter_mut()
144            .zip(self.mem_ola_add[..(nf - z)].iter().zip(self.t_hat_mdct[z..nf].iter()))
145        {
146            *freq_buf_n = *mem_ola_add_n + *t_hat_mdct_z;
147        }
148
149        self.mem_ola_add[..(nf - z)].copy_from_slice(&self.t_hat_mdct[(nf + z)..(nf * 2)]);
150        freq_buf[(nf - z)..nf].copy_from_slice(&self.t_hat_mdct[nf..(nf + z)]);
151    }
152
153    pub const fn calc_working_buffer_length(config: &Lc3Config) -> (usize, usize) {
154        let dct_complex_length = DiscreteCosTransformIv::calc_working_buffer_length(config);
155        let mem_ola_add_length = config.nf - config.z;
156        let t_hat_mdct_length = config.nf * 2;
157        let zeros_length = config.nf - config.ne;
158        let half_nf_length = config.nf / 2;
159        let x_hat_mdct_length = config.nf;
160        (
161            half_nf_length + zeros_length + mem_ola_add_length + t_hat_mdct_length + x_hat_mdct_length,
162            dct_complex_length,
163        )
164    }
165}
166
167#[cfg(test)]
168mod tests {
169    extern crate std;
170    use super::*;
171    use crate::common::config::{FrameDuration, SamplingFrequency};
172
173    #[test]
174    fn modified_dct_decode() {
175        const CONFIG: Lc3Config = Lc3Config::new(SamplingFrequency::Hz48000, FrameDuration::TenMs);
176        const SCALER_COMPLEX_LENS: (usize, usize) = ModDiscreteCosTrans::calc_working_buffer_length(&CONFIG);
177        let mut scaler_buf = [0f32; SCALER_COMPLEX_LENS.0];
178        let mut complex_buf = [Complex { r: 0., i: 0. }; SCALER_COMPLEX_LENS.1];
179        let (mut mdct, _, _) = ModDiscreteCosTrans::new(CONFIG, &mut scaler_buf, &mut complex_buf);
180        let mut freq_buf = [0.0; CONFIG.nf];
181
182        // since the modified dct result is based on some data from the previous frame we need to plocess two frames in our test
183        #[rustfmt::skip]
184        let x_hat = [
185            -1293.1299, 245.53099, 5084.983, -5084.029, 161.85847, -1601.2933, 2313.1963, 5822.268, -15994.899,
186            6625.739, 15630.219, 8686.201, -275.8873, -472.84, -249.1974, 1216.9434, 1066.6044, 0.0, -320.7793,
187            -520.7456, 1869.116, -568.8614, -654.3916, 548.98627, -1249.3191, 239.03938, -898.2346, 425.92346,
188            -621.90796, -880.73676, 384.04172, 0.0, -305.9874, -54.920815, -367.12482, 170.01082, 589.13873,
189            -465.65112, 95.18835, -572.1217, 249.79962, -185.33519, 58.88405, -89.72807, 44.864037, -128.30061,
190            85.53374, -42.76687, -483.6944, 148.82904, -37.20726, 32.418316, -259.34653, -64.83663, 226.9282,
191            56.562077, -56.562077, -141.40518, -28.281038, 76.8806, -281.8955, -128.13432, 102.50746, -48.093624,
192            96.18725, 96.18725, 96.18725, -180.40393, 0.0, -157.85344, 0.0, 21.137903, 63.41371, 126.82742, 21.137903,
193            0.0, 118.98418, 39.661392, 0.0, -118.98418, -337.12183, 37.249435, 0.0, 148.99774, -111.74831, 55.874153,
194            -34.993866, -52.490803, 34.993866, -34.993866, -34.993866, 0.0, 32.8947, 32.8947, -49.34205, -16.44735,
195            -32.8947, -16.44735, -77.540886, -15.508177, -15.508177, 108.557236, 0.0, -46.52453, 15.508177, 0.0,
196            29.343197, -29.343197, 44.014793, 0.0, 0.0, -14.671598, 13.829894, 55.319576, 0.0, -27.659788, -13.829894,
197            13.829894, 0.0, 26.142889, 0.0, 52.285778, -39.214333, 39.214333, 26.142889, 65.35722, -26.142889, 0.0,
198            0.0, -25.882666, 51.76533, -25.882666, 51.76533, -12.941333, 51.76533, 0.0, 40.274414, 40.274414,
199            -40.274414, 0.0, 40.274414, -26.84961, 40.274414, -13.424805, -13.92249, 27.84498, 0.0, 13.92249,
200            -27.84498, -13.92249, -41.76747, -13.92249, 0.0, 0.0, -72.17195, -28.86878, -14.43439, 0.0, 0.0, 28.86878,
201            14.43439, 14.43439, 28.86878, 14.43439, 13.464998, 13.464998, -13.464998, 0.0, 0.0, 0.0, -13.464998,
202            -13.464998, 0.0, -26.929996, 26.929996, 11.253014, 11.253014, 0.0, -11.253014, 22.506027, 0.0, -11.253014,
203            -11.253014, 0.0, 0.0, 11.253014, 9.373507, -18.747013, 9.373507, -9.373507, 0.0, -28.12052, -37.494026,
204            0.0, 0.0, -18.747013, -28.12052, -9.373507, 0.0, 0.0, 0.0, 0.0, 0.0, 7.8264794, -7.8264794, 23.479439,
205            15.652959, -7.8264794, 7.8264794, 7.8264794, 0.0, 0.0, 0.0, 0.0, 19.732956, 0.0, 6.577652, 0.0, 13.155304,
206            -19.732956, 6.577652, 6.577652, 19.732956, 0.0, -13.155304, -5.5446987, 0.0, 0.0, 0.0, -11.089397,
207            -5.5446987, 0.0, 0.0, 0.0, 0.0, 11.089397, 0.0, 5.5446987, 0.0, 5.5446987, -4.661485, -4.661485, 0.0, 0.0,
208            -4.661485, 0.0, 0.0, 4.661485, -9.32297, 4.661485, -4.661485, -4.661485, -4.661485, -9.32297, 0.0,
209            4.661485, 0.0, -3.9280114, 3.9280114, 0.0, 3.9280114, -11.784035, 3.9280114, 3.9280114, 0.0, 0.0,
210            -3.9280114, 0.0, -3.9280114, 3.9280114, 0.0, -3.9280114, -3.9280114, 3.5038724, -3.5038724, 7.007745, 0.0,
211            0.0, -7.007745, 10.511617, 0.0, 0.0, 3.5038724, 0.0, 0.0, 0.0, -3.5038724, 7.007745, 0.0, -3.5038724,
212            3.5038724, 0.0, 0.0, -3.3093805, -3.3093805, 0.0, 0.0, 3.3093805, 3.3093805, 0.0, -3.3093805, -6.618761,
213            3.3093805, -3.3093805, -3.3093805, 0.0, 3.3093805, 0.0, -6.618761, 6.618761, 0.0, 0.0, 0.0, 0.39045277,
214            -0.39045277, 0.39045277, -0.39045277, 0.39045277, 0.39045277, -0.39045277, -0.39045277, 0.39045277,
215            0.39045277, -0.39045277, -0.39045277, 0.39045277, 0.39045277, -0.39045277, -0.39045277, -0.39045277,
216            -0.36832458, 0.36832458, -0.36832458, -0.36832458, -0.36832458, 0.36832458, 0.36832458, -0.36832458,
217            -0.36832458, -0.36832458, -0.36832458, 0.36832458, -0.36832458, 0.36832458, -0.36832458, 0.36832458,
218            -0.36832458, 0.36832458, -0.36832458, 0.36832458, 0.36832458, -0.36832458, 0.347288, 0.347288, 0.347288,
219            -0.347288, 0.347288, 0.347288, -0.347288, 0.347288, -0.347288, 0.347288, -0.347288, -0.347288, 0.347288,
220            -0.347288, 0.347288, 0.347288, -0.347288, 0.347288, -0.347288, -0.347288, -0.347288, 0.347288, -0.347288,
221            -0.32734314, -0.32734314, -0.32734314, -0.32734314, -0.32734314, -0.32734314, 0.32734314, -0.32734314,
222            0.32734314, -0.32734314, 0.32734314, -0.32734314, -0.32734314, -0.32734314, 0.32734314, -0.32734314,
223            0.32734314, -0.32734314, -0.32734314, -0.32734314, -0.32734314, 0.32734314, -0.32734314, -0.32734314,
224            -0.32734314,
225        ];
226        mdct.run(&x_hat, &mut freq_buf);
227
228        #[rustfmt::skip]
229        let x_hat = [
230            -1206.3026, -5241.9336, -155.86848, -6830.6084, -1300.3838, -3559.517, 710.1283, 3473.764, -9982.126,
231            13719.041, 16283.188, 11467.5205, 6554.3584, -908.4256, 1152.2314, 1950.774, 2570.5566, 3246.4722,
232            1030.247, -679.5246, 1077.3108, 902.3161, -610.1385, 1887.744, 482.0292, 334.6572, 176.37881, 299.07712,
233            -373.0097, 239.96167, -435.3793, -223.21477, 26.76417, 158.52623, 315.89703, 239.31595, 123.17562,
234            180.30057, -180.30057, 48.224026, 114.73992, 354.19717, -24.764124, 123.82062, -74.29237, 48.767937,
235            -243.83968, -268.22363, 203.26685, 76.22507, 406.5337, 0.0, -158.81937, 52.939785, -79.40968, 55.13717,
236            82.70576, 0.0, 82.70576, -84.65056, 84.65056, 253.95168, -225.73482, 28.387463, -283.87463, 28.387463,
237            170.32478, -228.47122, -171.35342, -57.117805, 28.558903, -86.19353, 28.731174, -57.46235, 57.46235,
238            -114.9247, 26.455284, -185.187, 158.73172, -158.73172, 26.455284, -66.682495, -44.454994, -66.682495,
239            22.227497, -22.227497, -18.662209, 0.0, 111.97325, -55.986626, 130.63545, 0.0, -62.814857, 31.407429,
240            31.407429, 62.814857, -15.703714, 62.814857, -14.205091, 0.0, -56.820366, -28.410183, -113.64073,
241            -14.205091, -28.410183, -13.7488165, -41.246452, -41.246452, 54.995266, 13.7488165, 0.0, 13.7488165,
242            39.913975, 53.21863, 0.0, -66.523285, 13.304658, -66.523285, 0.0, -38.61785, 25.745234, 12.872617, 0.0,
243            -38.61785, 77.2357, -25.745234, 12.872617, -37.42575, 24.9505, -24.9505, -37.42575, 0.0, 37.42575,
244            -24.9505, -12.47525, 24.22137, -12.110685, 12.110685, -12.110685, 0.0, -12.110685, 0.0, 0.0, 12.110685,
245            0.0, 35.26723, -11.755743, 11.755743, 11.755743, 0.0, -11.755743, -23.511486, 23.511486, -11.755743,
246            45.64168, 11.41042, 45.64168, 0.0, -22.82084, -34.231262, 0.0, 0.0, -11.41042, 0.0, -21.812521, 0.0,
247            21.812521, -21.812521, -21.812521, -10.9062605, 10.9062605, -10.9062605, 10.9062605, 0.0, 21.812521,
248            -30.796978, 41.062637, 10.265659, -10.265659, -20.531319, -20.531319, -20.531319, 30.796978, 10.265659,
249            -30.796978, 30.796978, 0.0, 0.0, -19.329084, 0.0, -9.664542, -19.329084, -9.664542, 19.329084, -9.664542,
250            -9.664542, 9.664542, -19.329084, -9.102908, 9.102908, 0.0, 0.0, -9.102908, 0.0, -18.205816, -9.102908, 0.0,
251            18.205816, 0.0, -27.308725, 9.102908, 0.0, -8.259274, -16.518547, 8.259274, 16.518547, 0.0, 16.518547, 0.0,
252            -8.259274, 8.259274, -8.259274, 0.0, 0.0, -8.259274, 7.201717, 0.0, 0.0, 0.0, -14.403434, 14.403434,
253            21.605152, 0.0, -7.201717, -7.201717, 0.0, 14.403434, 0.0, 0.0, 0.0, 0.0, 6.2782655, 6.2782655, 0.0, 0.0,
254            6.2782655, -18.834797, 0.0, 0.0, 0.0, 6.2782655, 0.0, -6.2782655, -6.2782655, 6.2782655, 6.2782655, 0.0,
255            0.0, 0.0, -5.460496, 5.460496, -5.460496, 0.0, 0.0, 0.0, 0.0, 0.0, -5.460496, 5.460496, 5.460496, 5.460496,
256            0.0, 10.920992, 0.0, 4.7637267, 0.0, 0.0, 0.0, 14.29118, 4.7637267, -4.7637267, -9.527453, -4.7637267, 0.0,
257            0.0, 0.0, 0.0, 0.0, 0.0, 4.7637267, -4.7637267, 0.0, 4.180775, 0.0, 0.0, 4.180775, 0.0, 0.0, 0.0,
258            0.5225969, -0.5225969, -0.5225969, 0.0, 0.0, 0.0, -4.180775, 0.0, 0.0, 0.0, 0.0, 3.6689022, 0.0, 0.0, 0.0,
259            -0.45861277, 0.45861277, -0.45861277, 0.45861277, -0.45861277, 0.45861277, -0.45861277, 0.45861277,
260            0.45861277, -0.45861277, 0.45861277, 0.45861277, -0.45861277, -0.45861277, -0.45861277, 0.45861277,
261            -0.40255708, 0.40255708, 0.40255708, 0.40255708, 0.40255708, 0.40255708, -0.40255708, -0.40255708,
262            0.40255708, -0.40255708, -0.40255708, -0.40255708, -0.40255708, 0.40255708, -0.40255708, 0.40255708,
263            -0.40255708, -0.40255708, -0.40255708, -0.40255708, -0.40255708, -0.40255708, 0.35250783, 0.35250783,
264            0.35250783, -0.35250783, -0.35250783, -0.35250783, 0.35250783, -0.35250783, -0.35250783, 0.35250783,
265            -0.35250783, 0.35250783, -0.35250783, -0.35250783, -0.35250783, -0.35250783, -0.35250783, 0.35250783,
266            0.35250783, -0.35250783, -0.35250783, 0.35250783, -0.35250783, -0.30846497, -0.30846497, 0.30846497,
267            0.30846497, 0.30846497, -0.30846497, 0.30846497, 0.30846497, 0.30846497, 0.30846497, -0.30846497,
268            -0.30846497, 0.30846497, 0.30846497, -0.30846497, -0.30846497, 0.30846497, -0.30846497, -0.30846497,
269            -0.30846497, -0.30846497, 0.30846497, 0.30846497, 0.30846497, -0.30846497,
270        ];
271        mdct.run(&x_hat, &mut freq_buf);
272
273        #[rustfmt::skip]
274        let freq_buf_expected = [
275            329.20435, 408.6457, 478.11908, 539.0993, 594.16406, 648.3305, 708.14233, 785.74414, 890.35443, 999.2488,
276            1079.0262, 1132.4252, 1189.0614, 1263.9072, 1339.4902, 1392.2119, 1417.1182, 1425.354, 1435.8098,
277            1460.9797, 1491.7046, 1497.5272, 1465.1193, 1420.476, 1384.7596, 1346.7651, 1290.0562, 1215.2373,
278            1128.5273, 1029.5582, 915.7318, 790.9405, 676.49603, 585.3717, 487.85953, 352.15723, 193.05173, 43.70752,
279            -79.54181, -179.14104, -281.92233, -413.2743, -559.9556, -692.07996, -803.9083, -909.9745, -1006.51044,
280            -1082.2643, -1151.0464, -1224.5739, -1292.6034, -1336.433, -1347.5631, -1328.6221, -1280.745, -1216.1796,
281            -1151.6594, -1093.9952, -1048.0684, -1017.9504, -1002.10223, -981.77826, -941.59033, -890.55035, -838.1291,
282            -788.71924, -745.4917, -699.9309, -636.0759, -554.6262, -479.2781, -425.42758, -386.08118, -344.19168,
283            -287.30737, -217.94397, -140.66211, -46.776215, 76.1028, 217.96478, 339.66168, 412.4326, 450.45532,
284            480.96487, 510.65192, 541.6527, 586.5333, 656.83167, 752.2529, 860.5596, 959.82214, 1028.0052, 1065.2461,
285            1087.8615, 1102.1747, 1105.4282, 1092.1143, 1056.633, 1004.8624, 952.7927, 911.83606, 885.2831, 866.05597,
286            835.6201, 786.88513, 736.35693, 700.3611, 670.18115, 619.1756, 535.6963, 431.58707, 319.88318, 203.31271,
287            78.91724, -53.230103, -184.99063, -304.14954, -404.76013, -498.30124, -603.3264, -718.1176, -831.5375,
288            -946.0727, -1062.2368, -1171.7661, -1261.2023, -1324.2283, -1379.13, -1441.5575, -1501.7023, -1546.9458,
289            -1582.2595, -1623.7994, -1677.4894, -1734.4379, -1783.2451, -1820.1002, -1845.3433, -1857.4204, -1863.7135,
290            -1877.6727, -1903.2032, -1934.5334, -1962.7538, -1982.2228, -1992.1484, -1995.6678, -1992.619, -1970.0658,
291            -1915.6781, -1840.9904, -1768.373, -1697.097, -1619.3698, -1553.3435, -1520.7733, -1514.5142, -1512.3151,
292            -1509.3231, -1509.7914, -1500.1134, -1459.1165, -1381.5653, -1284.494, -1187.2854, -1092.2422, -999.8038,
293            -914.18146, -831.5862, -746.8167, -657.23517, -561.62384, -470.5669, -401.41376, -355.1119, -316.1234,
294            -273.3612, -220.13834, -140.40962, -27.668236, 91.87787, 194.59889, 296.8533, 423.2619, 564.4658,
295            689.93066, 789.94775, 884.6697, 985.54364, 1071.3992, 1121.791, 1150.5063, 1183.1925, 1224.354, 1264.9,
296            1297.5225, 1312.7068, 1304.2473, 1285.2727, 1275.0349, 1267.9458, 1240.7292, 1187.8523, 1125.2488,
297            1066.385, 1009.6876, 940.5224, 854.1314, 773.353, 711.5303, 651.4366, 588.53516, 538.88916, 501.15363,
298            460.14825, 417.98517, 380.1871, 333.3568, 277.82996, 230.22473, 186.98016, 143.14145, 110.92619, 100.39982,
299            107.083916, 119.45348, 137.12384, 160.98726, 174.99513, 162.14423, 130.455, 99.70367, 62.298042, 4.0239563,
300            -58.60829, -103.73868, -128.57013, -144.392, -170.60661, -222.13486, -290.05865, -350.91632, -402.0981,
301            -461.86868, -539.67, -625.82086, -707.11646, -778.95703, -844.86743, -916.68207, -997.6924, -1076.9763,
302            -1150.6418, -1219.973, -1282.46, -1339.4653, -1390.8987, -1416.168, -1399.9817, -1376.8962, -1387.8058,
303            -1416.9409, -1424.0131, -1404.2661, -1376.866, -1343.6855, -1300.4259, -1247.3698, -1182.5712, -1117.4323,
304            -1060.2775, -995.8147, -917.5809, -845.83, -796.4136, -758.16846, -709.4432, -638.02594, -551.52637,
305            -469.62595, -393.0194, -309.57413, -224.32016, -150.69379, -91.381134, -34.44581, 37.568058, 125.91611,
306            209.85504, 270.8642, 314.46622, 356.9047, 406.0201, 466.33603, 539.5211, 622.6745, 710.3698, 786.0053,
307            835.6237, 866.8232, 888.69714, 900.2288, 909.47723, 932.9227, 969.8758, 997.0238, 1002.7095, 1009.33136,
308            1048.7474, 1127.7412, 1219.3196, 1292.7708, 1351.3141, 1411.5253, 1465.7561, 1495.715, 1499.3107,
309            1489.0054, 1472.5387, 1454.7802, 1442.8802, 1432.2278, 1415.7853, 1393.7463, 1366.791, 1334.939, 1297.4614,
310            1256.5587, 1210.1974, 1156.0198, 1096.314, 1022.3505, 931.98035, 840.32, 748.7633, 643.3313, 535.3086,
311            452.84384, 381.41998, 293.76593, 202.78804, 115.46181, 2.848444, -151.9073, -315.988, -457.49225,
312            -591.46155, -733.57104, -875.484, -1002.2885, -1102.3705, -1184.0809, -1268.6567, -1360.0754, -1442.1298,
313            -1509.4015, -1572.1705, -1630.7217, -1685.3574, -1752.377, -1837.0332, -1918.3508, -1982.0349, -2037.1409,
314            -2092.9355, -2144.748, -2174.662, -2165.587, -2123.4956, -2071.455, -2016.8064, -1944.9612, -1851.5173,
315            -1746.4093, -1632.6666, -1517.7556, -1421.2119, -1339.8651, -1240.179, -1111.1624, -976.6043, -840.7785,
316            -681.29553, -500.35257, -324.06122, -155.56522, 19.897705, 205.10396, 389.51694, 560.6322, 717.99316,
317            867.77563, 1009.13904, 1137.5709, 1255.1805, 1365.9401, 1459.4799, 1532.2576, 1601.7274, 1669.4132,
318            1715.4548, 1736.9218, 1754.1222, 1773.0212, 1781.6361, 1784.0096, 1790.7439, 1790.9458, 1766.7467,
319            1726.7048, 1691.5796, 1660.4906, 1625.6824, 1576.5885, 1493.2614, 1380.699, 1264.4869, 1138.5354, 976.7996,
320            789.5482, 608.6704, 441.64578, 282.43655, 132.52983, -8.380628, -143.74124, -273.22894, -404.35336,
321            -539.1669, -655.6166, -743.24457, -817.8242, -894.0151, -973.0729, -1050.8239, -1129.0627, -1205.7386,
322            -1281.3607, -1371.6538, -1479.0549, -1584.6927, -1671.814, -1738.4567, -1796.37, -1858.8871, -1929.8475,
323            -1994.8425, -2030.4064, -2036.6422, -2041.9125, -2065.5054, -2098.5696, -2120.4485, -2115.4963, -2089.7668,
324            -2063.8184, -2039.3445, -2008.1306, -1978.6305, -1954.6621, -1917.1207, -1848.9496, -1749.2766, -1624.4669,
325            -1483.1907, -1332.5011, -1180.8673, -1035.2605, -889.9849, -734.8095, -569.74023, -401.98657, -229.24869,
326            -44.59149, 142.64136, 313.80316, 463.89514, 610.44507, 771.859, 947.2708,
327        ];
328        assert_eq!(freq_buf, freq_buf_expected);
329    }
330}