lc3_codec/encoder/
temporal_noise_shaping.rs

1#![allow(clippy::excessive_precision)]
2
3use crate::{
4    common::{
5        complex::Scaler,
6        config::{FrameDuration, Lc3Config},
7    },
8    tables::temporal_noise_shaping_tables::*,
9};
10use core::{f64::consts::PI, panic};
11#[allow(unused_imports)]
12use num_traits::real::Real;
13
14pub struct TemporalNoiseShaping {
15    config: Lc3Config,
16}
17
18pub struct TnsResult {
19    pub nbits_tns: usize,
20    pub lpc_weighting: u8,
21    pub num_tns_filters: usize,
22    pub rc_order: [usize; 2], // The order of quantized reflection coefficients
23    pub rc_i: [usize; 16],    // integer reflection coefficients
24    pub rc_q: [Scaler; 16],   // quantized reflection coefficients
25}
26
27struct TnsParams {
28    pub num_tns_filters: usize,
29    pub start_freq: [usize; 2],
30    pub stop_freq: [usize; 2],
31    pub sub_start: [[usize; 3]; 2],
32    pub sub_stop: [[usize; 3]; 2],
33}
34
35impl TemporalNoiseShaping {
36    pub fn new(config: Lc3Config) -> Self {
37        Self { config }
38    }
39
40    pub fn run(&self, x_s: &mut [Scaler], p_bw: usize, nbits: usize, near_nyquist_flag: bool) -> TnsResult {
41        assert_eq!(x_s.len(), self.config.ne);
42        let tns = self.get_tns_params(p_bw);
43        let mut rc_order = [0; 2];
44        let mut rc_i = [0; 16];
45        let mut rc_q = [0.0; 16];
46        let num_tns_filters = tns.num_tns_filters;
47
48        // tns analysis
49        let lpc_weighting = match self.config.n_ms {
50            FrameDuration::TenMs if nbits < 480 => 1,
51            FrameDuration::SevenPointFiveMs if nbits < 360 => 1,
52            _ => 0,
53        };
54
55        for (f, (sub_start, sub_stop)) in tns.sub_start[..num_tns_filters].iter().zip(&tns.sub_stop).enumerate() {
56            let r = Self::compute_normalized_autocorrelation(sub_start, sub_stop, x_s);
57            Self::tns_analysis(&r, f, near_nyquist_flag, lpc_weighting, &mut rc_q);
58        }
59
60        // quantization
61        Self::apply_quantization(num_tns_filters, &mut rc_q, &mut rc_i, &mut rc_order);
62
63        // bit budget
64        let nbits_tns = Self::calc_bit_budget(num_tns_filters, lpc_weighting, &rc_i, &rc_order);
65
66        // filtering
67        Self::apply_filtering(&tns, x_s, &mut rc_q, &mut rc_order);
68
69        TnsResult {
70            //output: x_s,
71            nbits_tns,
72            num_tns_filters,
73            rc_i,
74            rc_q,
75            rc_order,
76            lpc_weighting,
77        }
78    }
79
80    fn compute_normalized_autocorrelation(sub_start: &[usize], sub_stop: &[usize], x_s: &[Scaler]) -> [Scaler; 9] {
81        let lag_window = [
82            1.0, 0.9980280260203829, 0.9921354055113971, 0.9823915844707989, 0.9689107911912967, 0.9518498073692735,
83            0.9314049334023056, 0.9078082299969592, 0.8813231366694713,
84        ];
85
86        let mut r = [0.0; 9];
87        for (k, (r, lag_window)) in r.iter_mut().zip(&lag_window).enumerate() {
88            let r0 = if k == 0 { 3.0 } else { 0.0 };
89            let mut rk = 0.0;
90            let mut e_prod = 1.0;
91
92            for (start, stop) in sub_start.iter().zip(sub_stop.iter()) {
93                let es: Scaler = x_s[*start..*stop].iter().map(|x| *x * *x).sum();
94
95                // ac = sum(x[n] * x[n+k]) for n = start..stop
96                let k_from = *start + k;
97                let ac: Scaler = if k_from < x_s.len() && k_from < *stop {
98                    x_s[k_from..*stop]
99                        .iter()
100                        .zip(x_s[*start..*stop].iter())
101                        .map(|(kx, x)| *x * *kx)
102                        .sum()
103                } else {
104                    0.0
105                };
106
107                e_prod *= es;
108                rk += ac / es;
109            }
110
111            *r = if e_prod == 0.0 { r0 } else { rk } * *lag_window;
112        }
113
114        r
115    }
116
117    fn get_tns_params(&self, p_bw: usize) -> TnsParams {
118        match self.config.n_ms {
119            FrameDuration::TenMs => match p_bw {
120                0 => TnsParams {
121                    num_tns_filters: 1,
122                    start_freq: [12, 160],
123                    stop_freq: [80, 0],
124                    sub_start: [[12, 34, 57], [0, 0, 0]],
125                    sub_stop: [[34, 57, 80], [0, 0, 0]],
126                },
127                1 => TnsParams {
128                    num_tns_filters: 1,
129                    start_freq: [12, 160],
130                    stop_freq: [160, 0],
131                    sub_start: [[12, 61, 110], [0, 0, 0]],
132                    sub_stop: [[61, 110, 160], [0, 0, 0]],
133                },
134                2 => TnsParams {
135                    num_tns_filters: 1,
136                    start_freq: [12, 160],
137                    stop_freq: [200, 0],
138                    sub_start: [[12, 88, 164], [0, 0, 0]],
139                    sub_stop: [[88, 164, 240], [0, 0, 0]],
140                },
141                3 => TnsParams {
142                    num_tns_filters: 2,
143                    start_freq: [12, 160],
144                    stop_freq: [160, 320],
145                    sub_start: [[12, 61, 110], [160, 213, 266]],
146                    sub_stop: [[61, 110, 160], [213, 266, 320]],
147                },
148                4 => TnsParams {
149                    num_tns_filters: 2,
150                    start_freq: [12, 200],
151                    stop_freq: [200, 400],
152                    sub_start: [[12, 74, 137], [200, 266, 333]],
153                    sub_stop: [[74, 137, 200], [266, 333, 400]],
154                },
155                _ => panic!(
156                    "Cannot create valid start and stop freq indexes because of an invalid p_bw: {}",
157                    p_bw
158                ),
159            },
160            FrameDuration::SevenPointFiveMs => match p_bw {
161                0 => TnsParams {
162                    num_tns_filters: 1,
163                    start_freq: [9, 120],
164                    stop_freq: [60, 0],
165                    sub_start: [[9, 26, 43], [0, 0, 0]],
166                    sub_stop: [[26, 43, 60], [0, 0, 0]],
167                },
168                1 => TnsParams {
169                    num_tns_filters: 1,
170                    start_freq: [9, 120],
171                    stop_freq: [120, 0],
172                    sub_start: [[9, 46, 83], [0, 0, 0]],
173                    sub_stop: [[46, 83, 120], [0, 0, 0]],
174                },
175                2 => TnsParams {
176                    num_tns_filters: 1,
177                    start_freq: [9, 120],
178                    stop_freq: [180, 0],
179                    sub_start: [[9, 66, 123], [0, 0, 0]],
180                    sub_stop: [[66, 123, 180], [0, 0, 0]],
181                },
182                3 => TnsParams {
183                    num_tns_filters: 2,
184                    start_freq: [9, 120],
185                    stop_freq: [120, 240],
186                    sub_start: [[9, 46, 82], [120, 159, 200]],
187                    sub_stop: [[46, 82, 120], [159, 200, 240]],
188                },
189                4 => TnsParams {
190                    num_tns_filters: 2,
191                    start_freq: [9, 150],
192                    stop_freq: [150, 300],
193                    sub_start: [[9, 56, 103], [150, 200, 250]],
194                    sub_stop: [[56, 103, 150], [200, 250, 300]],
195                },
196                _ => panic!(
197                    "Cannot create valid start and stop freq indexes because of an invalid p_bw: {}",
198                    p_bw
199                ),
200            },
201        }
202    }
203
204    fn tns_analysis(r: &[Scaler], f: usize, near_nyquist_flag: bool, lpc_weighting: u8, rc_q: &mut [Scaler]) {
205        // use Levinson-Durbin recursion to obtain  LPC (Linear Predictive Coding) coefficients and a predictor error
206        let mut a_memory = [[0.0; 9]; 2];
207        let (a, a_last) = a_memory.split_at_mut(1);
208        let mut a = &mut a[0];
209        let mut a_last = &mut a_last[0];
210
211        let mut e = r[0];
212        a[0] = 1.0;
213        for k in 1..9 {
214            core::mem::swap(&mut a_last, &mut a);
215
216            // calculate reflection coefficients
217            let mut rc = 0.0;
218            for n in 0..k {
219                rc -= a_last[n] * r[k - n];
220            }
221            if e != 0.0 {
222                rc /= e;
223            }
224
225            // calculate error
226            a[0] = 1.0;
227            for n in 1..k {
228                a[n] = a_last[n] + rc * a_last[k - n];
229            }
230            a[k] = rc;
231            e *= 1.0 - rc * rc;
232        }
233
234        let pred_gain = if e == 0.0 { r[0] } else { r[0] / e };
235        const THRESH: Scaler = 1.5;
236        if pred_gain > THRESH && !near_nyquist_flag {
237            // turn on the tns filter
238            let mut gamma = 1.0;
239            const THRESH2: Scaler = 2.0;
240            if lpc_weighting > 0 && pred_gain < THRESH2 {
241                gamma -= (1.0 - 0.85) * (THRESH2 - pred_gain) / (THRESH2 - THRESH);
242            }
243            for (k, a_k) in a.iter_mut().enumerate() {
244                *a_k *= gamma.powi(k as i32);
245            }
246            let rc = &mut rc_q[f * 8..];
247            let mut a_k = a;
248            let mut a_km1 = a_last;
249            for k in (1..9).rev() {
250                rc[k - 1] = a_k[k];
251                let e = 1.0 - rc[k - 1] * rc[k - 1];
252                for n in 1..k {
253                    a_km1[n] = a_k[n] - rc[k - 1] * a_k[k - n];
254                    a_km1[n] /= e;
255                }
256                core::mem::swap(&mut a_k, &mut a_km1);
257            }
258        } else {
259            // turn off the tns filter
260            let rc = &mut rc_q[f * 8..];
261            for rc_n in rc[..8].iter_mut() {
262                *rc_n = 0.0;
263            }
264        }
265    }
266
267    fn apply_quantization(num_tns_filters: usize, rc_q: &mut [Scaler], rc_i: &mut [usize], rc_order: &mut [usize]) {
268        const QUANTIZER_STEPSIZE: Scaler = PI as Scaler / 17.0;
269        for f in 0..num_tns_filters {
270            let rc = &mut rc_q[f * 8..];
271            for (rc_quant, rc_int) in rc[..8].iter_mut().zip(rc_i[(f * 8)..(f * 8 + 8)].iter_mut()) {
272                *rc_int = (to_int((*rc_quant).asin() / QUANTIZER_STEPSIZE) + 8) as usize;
273                *rc_quant = (QUANTIZER_STEPSIZE * (*rc_int as Scaler - 8.0)).sin();
274            }
275
276            // calculate the order of the quantized reflection coefficients
277            let mut k: i8 = 7;
278            while k >= 0 && rc_i[f * 8 + k as usize] == 8 {
279                k -= 1;
280            }
281            rc_order[f] = (k + 1) as usize;
282        }
283
284        // TODO: double check against spec
285        for f in num_tns_filters..2 {
286            for k in 0..8 {
287                rc_i[f * 8 + k] = 8;
288                rc_q[f * 8 + k] = 0.0;
289            }
290            rc_order[f] = 0;
291        }
292    }
293
294    fn calc_bit_budget(num_tns_filters: usize, tns_lpc_weighting: u8, rc_i: &[usize], rc_order: &[usize]) -> usize {
295        let mut nbits_tns = 0;
296        for f in 0..num_tns_filters {
297            let nbits_tns_order = if rc_order[f] != 0 {
298                AC_TNS_ORDER_BITS[tns_lpc_weighting as usize][rc_order[f] - 1]
299            } else {
300                0
301            };
302            let mut nbits_tns_coef = 0;
303            for (k, coef_bits) in AC_TNS_COEF_BITS[..rc_order[f]].iter().enumerate() {
304                nbits_tns_coef += coef_bits[rc_i[f * 8 + k]];
305            }
306
307            nbits_tns += ((2048.0 + nbits_tns_order as Scaler + nbits_tns_coef as Scaler) / 2048.0).ceil() as usize;
308        }
309
310        nbits_tns
311    }
312
313    fn apply_filtering(tns: &TnsParams, x_s: &mut [Scaler], rc_q: &mut [Scaler], rc_order: &mut [usize]) {
314        let mut st = [0.0; 8];
315        for f in 0..tns.num_tns_filters {
316            if rc_order[f] != 0 {
317                let from = tns.start_freq[f];
318                let to = tns.stop_freq[f];
319
320                // TODO: check this assertion below
321                // we can safely modify x_s in place because ther is no overlap with from and to
322                for x_f in &mut x_s[from..to] {
323                    let mut t = *x_f;
324                    let mut st_save = t;
325                    let prev_order = rc_order[f] - 1;
326
327                    for (st, rcq) in st[..prev_order].iter_mut().zip(&rc_q[f * 8..f * 8 + prev_order]) {
328                        let st_tmp = *rcq * t + *st;
329                        t += *rcq * *st;
330                        *st = st_save;
331                        st_save = st_tmp;
332                    }
333
334                    t += rc_q[f * 8 + prev_order] * st[prev_order];
335                    st[prev_order] = st_save;
336                    *x_f = t;
337                }
338            }
339        }
340    }
341}
342
343fn to_int(x: Scaler) -> i8 {
344    if x >= 0.0 {
345        (x + 0.5) as i8
346    } else {
347        -(-x + 0.5) as i8
348    }
349}
350
351#[cfg(test)]
352mod tests {
353    extern crate std;
354    use super::*;
355    use crate::common::config::SamplingFrequency;
356
357    #[rustfmt::skip]
358    #[test]
359    fn temporal_noise_shaping_run() {
360        let config = Lc3Config::new(SamplingFrequency::Hz48000, FrameDuration::TenMs);
361        let tns = TemporalNoiseShaping::new(config);
362        let mut x_s = [
363            2511.287, -3606.8093, -453.28122, -360.71924, -2574.9756, -3166.2068, 6525.6, 6284.0137, -10303.951,
364            -4442.8755, 2318.4038, -691.36865, 509.12134, -1054.0342, 852.0186, -1959.2595, -2463.084, 583.8584,
365            -1045.9277, 886.3083, 94.29779, 106.0552, 262.7902, 195.86151, 748.0028, -369.72824, 326.68167, -706.81616,
366            83.90518, -101.80473, -425.53433, 248.85109, -246.2868, 415.67813, -428.0742, -195.10165, -497.12534,
367            148.11542, 351.7376, -259.38834, 639.9149, -232.2877, 182.4239, 30.73989, 139.50827, 315.7314, -314.8985,
368            111.07428, 464.2896, 352.44342, -380.097, 82.403694, -41.359577, 195.84523, 114.65242, -207.70195,
369            156.48032, -178.95581, 313.9437, -130.90295, -105.89414, 22.376598, -114.98715, 120.20845, -164.51794,
370            261.76236, 37.331238, 106.96828, -198.03798, -108.76448, 134.22601, -216.93547, 195.3998, -21.63419,
371            156.55684, -51.93392, 101.626854, 149.68706, -94.93349, -155.7282, -464.9618, 119.154236, -82.80184,
372            72.36793, -122.200264, -39.244514, 270.96143, -173.43079, 107.70619, -164.70389, 55.223305, -111.1405,
373            17.96329, 125.23528, -135.59274, 60.439613, -251.46301, 131.2461, -101.01771, 69.59965, 16.21791,
374            -239.07864, 166.54358, -27.770905, 100.91532, -84.49127, 69.28591, 2.6135557, -31.626968, 20.677122,
375            -36.27791, 119.84301, -173.36378, 35.84611, -57.688297, 60.183567, 4.423961, -44.209984, 105.70867,
376            -50.634827, 109.67776, -134.32838, 61.955124, 21.708387, -28.346958, -83.66344, -70.2042, 154.10416,
377            -77.64532, 88.29541, -130.808, 36.89496, 16.645363, -25.276045, 51.67908, -137.08151, 124.83691, -152.0996,
378            65.79087, 0.93463665, -60.837196, 39.439693, -114.28214, 81.32954, -45.443783, 96.88175, -80.02808,
379            6.91597, -0.9586373, -92.0962, 23.475348, -94.339935, 125.18178, -98.72728, 9.358742, -2.886684, 14.301312,
380            43.602825, -103.58884, 91.13613, -73.82291, 71.59755, -40.91015, 9.037108, 43.62777, -32.685516, 69.14355,
381            -105.05149, 82.54336, -8.614124, 11.804503, -27.901173, -29.564074, 41.35118, -8.069561, 77.09149,
382            -70.76394, 31.398144, -49.828518, 43.814983, 11.879899, -39.018723, 49.713158, -68.79033, 65.760086,
383            -60.97088, 33.07043, -20.903938, -14.867276, 9.887002, -65.46376, 41.143112, -80.06619, 70.94139,
384            -43.88703, 2.1660235, -17.16438, -44.083027, 38.160618, -81.36653, 70.78228, -76.33006, 38.737568,
385            -12.454603, -29.338528, 56.428005, -39.599926, 39.25371, -73.31344, 69.79237, -17.97577, 12.852926,
386            12.684623, -32.4752, 36.446888, -65.407234, 61.598774, -65.757484, 10.238938, -20.029032, -2.825231,
387            42.594162, -56.822716, 53.156845, -30.462795, 38.866444, -56.68353, 24.660025, 14.751921, -35.350494,
388            37.21626, -76.86587, 29.546429, -62.394695, 27.275826, -14.183131, -10.919811, 38.614643, -38.49674,
389            59.394817, -34.20599, 41.272846, -23.526806, 22.555021, 1.7496673, -19.42429, 46.749092, -46.406094,
390            42.399597, -50.664745, 32.1371, -13.392963, 7.2786326, 24.364573, -48.878193, 39.617836, -60.437885,
391            40.904007, -37.622654, 16.281404, 10.157282, -32.828197, 30.448824, -50.824665, 49.72176, -41.46506,
392            27.87757, -24.912022, -13.79381, 20.7759, -37.632587, 48.469193, -50.989594, 42.78355, -32.603626,
393            12.9430275, -0.48920912, -29.010874, 36.240032, -65.120476, 43.169476, -36.05779, 27.190653, -12.357571,
394            -6.6507573, 20.675322, -37.217205, 53.199875, -54.718746, 43.378906, -21.585281, -1.6675593, 13.522394,
395            -29.79583, 22.414072, -39.135113, 40.94145, -37.682613, 31.857054, -8.821981, 6.641381, 25.134476,
396            -40.58887, 42.64201, -44.198082, 40.230164, -27.744131, 10.078336, 4.423329, -22.164833, 27.893787,
397            -50.982807, 50.552082, -34.822014, 24.829428, -12.062506, -3.7417355, 18.681189, -40.84422, 45.581814,
398            -42.326923, 35.923992, -27.111525, 13.07634, 2.8001645, -20.283352, 35.183113, -46.604267, 47.304718,
399            -47.010338, 26.623617, -1.2559637, -11.157539, 23.359474, -34.244343, 38.091057, -39.234665, 46.234547,
400            -30.573185, 2.6562088, 11.293563, -17.823277, 33.29007, -46.73799, 43.705185, -32.237366, 23.87085,
401            -14.893113, 0.8721875, 27.640835, -39.741753, 45.260857, -47.98558, 33.93777, -20.93668, 4.6949544,
402            7.7584434, -24.253351, 35.06494, -40.09654, 39.286926, -33.447765, 24.822977, -8.966054, -9.330206,
403            21.831121, -26.851707, 38.898933, -49.516945, 38.540756, -25.502691, 3.2083294, 10.038194, -23.048763,
404            34.32631, -39.45431, 37.582066, -34.85849, 27.25857, -8.987542, -7.2581387, 24.746119, -38.36987, 41.85204,
405            -39.183273, 29.537968, -22.075731, 8.153215, 10.045177, -24.236364, 31.76943, -34.252445, 37.48698,
406            -35.33923, 22.365273, -7.9304223, -7.034074, 20.73084, -31.455378, 35.02656,
407        ];
408
409        let result = tns.run(&mut x_s, 4, 1200, false);
410
411        let x_f_expected = [
412            2511.287, -3606.8093, -453.28122, -360.71924, -2574.9756, -3166.2068, 6525.6, 6284.0137, -10303.951,
413            -4442.8755, 2318.4038, -691.36865, 509.12134, -938.29266, 525.9005, -1542.4482, -3091.5273, 262.27206,
414            -379.65656, -98.486786, 668.16437, -213.70082, -114.14174, 80.94827, 83.418945, -16.794994, 6.197174,
415            -332.66284, -48.91777, 0.084522665, -281.5821, 78.69863, 133.78897, 102.63185, -259.9021, -450.69684,
416            -538.17615, 102.73462, 256.75674, -122.24531, 414.3129, 90.33753, -141.62321, 64.58323, 158.11197,
417            264.04486, -70.996445, -74.847595, 715.87695, 398.03842, -383.14874, 81.798744, 100.61626, 183.76709,
418            107.91918, -74.72749, 137.34314, -12.11866, 145.58879, -8.319928, -146.90816, 21.44834, -14.692991,
419            -26.504921, -44.41256, 169.60251, 157.3852, 57.295708, -223.72159, -105.66721, 85.917145, -124.74416,
420            67.12806, 148.09708, 108.51118, -38.312347, 85.37175, 124.25812, -19.708088, -252.26158, -396.83145,
421            30.49828, 24.158318, 4.4514937, -100.692856, -19.743237, 174.73466, -129.2712, -94.76638, -48.278133,
422            -12.916355, -108.09598, 15.809202, 102.17793, -36.756264, -59.4923, -168.1815, 18.80262, -43.62355,
423            23.15091, 16.152151, -187.13437, 30.643784, 90.79638, -16.21843, -39.05421, 62.11714, -2.155285, -19.06319,
424            -42.414265, 35.171066, 84.379585, -116.602325, -33.51855, -7.659307, 44.801598, -11.07798, -14.886959,
425            62.95822, 14.218942, 31.104227, -83.76815, 17.044928, 55.428146, -13.889921, -126.15556, -27.248165,
426            120.640366, -19.761774, 14.046745, -73.71858, 0.10803318, 10.083524, -16.70562, 4.7014112, -62.691025,
427            50.462833, -84.346176, -13.629369, 36.10631, -46.619267, -21.598942, -48.490704, -6.3323555, 15.65649,
428            48.896317, -56.442543, -6.640568, -17.761715, -70.73248, -40.4366, -36.27153, 74.86966, -46.19746,
429            -44.013317, 2.0889094, 26.809942, -6.282827, -65.310585, 33.484646, -9.667151, 15.079562, -16.305983,
430            9.046168, 29.939863, 5.129214, 16.5475, -50.21096, 31.017387, 38.323303, -3.0681198, -36.80033, -1.2009478,
431            11.490404, 26.555166, 44.298775, -31.610435, 4.04779, -32.927948, 29.660675, 11.896004, -18.109625,
432            25.200207, -23.730797, 15.500507, -25.358208, 6.163124, -7.3798866, -7.921206, -16.156162, -36.149162,
433            -1.5045524, -43.494595, 29.947332, -15.511134, -17.982704, -28.039505, -30.445019, -3.5225277, -46.805386,
434            -1.0227482, -23.363768, -17.676548, -3.6520846, -12.88875, 4.756609, 31.271141, -6.629322, -37.832882,
435            -0.21950912, 38.885174, 21.138603, 6.2617035, -9.60021, -11.284341, -19.242826, -1.6980145, -9.359415,
436            -41.126484, -29.448069, -5.9372683, 25.94433, 1.3254867, -14.705631, 15.379487, 16.574158, -27.095804,
437            -19.93113, 20.497425, 0.79107094, -7.7554317, -36.76988, -52.092567, -38.030884, -20.167278, -0.28380156,
438            -7.2491307, 8.2373905, 7.9681587, 12.655432, 23.266579, 13.15513, 5.5212536, 12.821712, 10.402097, -1.8669,
439            17.029139, 7.877034, -3.6022367, -13.437171, -10.018736, 6.7936516, 12.0322485, 17.809977, -13.797862,
440            -19.886257, -20.896944, -13.391824, -3.7870193, -6.042081, 9.495218, -8.35246, -16.302475, -16.089418,
441            -2.2239032, 5.133191, -1.9499176, -12.571083, -26.08479, -8.472019, -4.010655, 5.987412, -1.6527638,
442            -5.525652, -1.8339038, -6.3098893, -2.546278, -14.999996, -4.8673024, -21.751396, -23.044847, 0.98999345,
443            3.2206738, 1.6813838, -5.9552116, -2.9898171, -6.6439576, 10.739187, -0.41604716, -6.192164, 10.029629,
444            -8.77803, -3.0170813, -3.2569091, -16.77877, -12.368547, 2.8054588, -1.341449, 4.0487995, 9.832774,
445            9.444449, 19.458578, -5.653375, -5.7151184, -1.1136432, 2.3793151, 5.6741295, -4.6841993, -0.53913784,
446            -5.0413313, -4.085096, -17.153347, -1.8630176, 11.785563, 1.1223254, -0.71278524, -4.503395, 1.1829545,
447            -10.829809, -1.1153163, 3.7169714, -0.4367964, -0.591923, -2.8435392, 1.75674, -4.178983, 4.8031635,
448            -5.574907, -0.26360065, -4.317787, -11.108944, 12.20769, 3.0794377, -0.6653844, -2.5413795, -2.403656,
449            -0.8925853, 13.288289, 6.883606, -15.778875, -1.6005001, 5.696593, 8.6179, -7.1294184, -5.413874,
450            5.2202096, 2.9486847, -2.3101602, -2.2582812, 15.61281, -0.8072282, -0.08025418, -4.076133, -9.068343,
451            4.1847715, -2.2272792, -1.0373013, -4.7336984, 1.2461259, -0.5397187, 0.18704754, -0.1272373, 0.41515422,
452            4.11998, -5.550728, 0.5320622, 3.4917614, 8.215734, -10.053921, -7.784162, 3.4075887, -8.748142,
453            0.87312615, -1.6497533, 1.9920977, -0.20973617, -1.9895163, -3.3932712, 1.6009337, 7.0630236, -3.209106,
454            5.2722173, -5.2088814, -1.2551317, 2.55086, -3.7561512, -1.9274446, -2.2996173, 5.709345, -2.3815656,
455            -0.94840765, 0.60572165, 4.09223, -2.2723556, -4.731332, 2.7107785, -2.495332, 3.3961606, -2.640641,
456            -1.3273795,
457        ];
458        assert_eq!(x_s, x_f_expected);
459        assert_eq!(result.rc_i, [10, 7, 8, 9, 7, 9, 8, 9, 14, 11, 6, 9, 7, 9, 8, 8]);
460        assert_eq!(
461            result.rc_q,
462            [
463                0.36124167, -0.18374951, 0.0, 0.18374951, -0.18374951, 0.18374951, 0.0, 0.18374951, 0.8951633,
464                0.52643216, -0.36124167, 0.18374951, -0.18374951, 0.18374951, 0.0, 0.0
465            ]
466        );
467        assert_eq!(result.lpc_weighting, 0);
468        assert_eq!(result.num_tns_filters, 2);
469        assert_eq!(result.rc_order, [8, 6]);
470        assert_eq!(result.nbits_tns, 42)
471    }
472}