lc3_codec/encoder/
spectral_quantization.rs

1use crate::{
2    common::{complex::Scaler, constants::MAX_LEN_SPECTRAL},
3    encoder::spectral_noise_shaping::NBITS_SNS,
4    tables::spectral_data_tables::*,
5};
6
7use itertools::Itertools;
8#[allow(unused_imports)]
9use num_traits::real::Real;
10
11struct GlobalGainEstimationParams {
12    nbits_offset: Scaler,
13    nbits_spec_adj: usize,
14    gg_off: i16,
15}
16
17struct BitConsumption {
18    rate_flag: usize,
19    lastnz: usize,
20    nbits_lsb: usize,
21    lastnz_trunc: usize,
22    nbits_est: usize,
23    nbits_trunc: usize,
24    mode_flag: bool,
25}
26
27struct GlobalGainEstimation {
28    gg_ind: i16,
29    gg_min: i16,
30    est_params: GlobalGainEstimationParams,
31    reset_offset: bool,
32}
33
34struct QuantizeResult {
35    lsb_mode: bool,
36    bit_consumption: BitConsumption,
37    gg: Scaler,
38}
39
40pub struct SpectralQuantizationResult {
41    pub gg_ind: i16,
42    pub nbits_spec: usize,
43    pub nbits_lsb: usize,
44    pub nbits_trunc: usize,
45    pub lsb_mode: bool,
46    pub rate_flag: usize,
47    pub lastnz_trunc: usize,
48    pub gg: f32,
49}
50
51pub struct SpectralQuantization {
52    // constant
53    ne: usize,
54    fs_ind: usize,
55
56    // state
57    reset_offset_old: bool,
58    nbits_offset_old: f32,
59    nbits_spec_old: usize,
60    nbits_est_old: usize,
61}
62
63impl SpectralQuantization {
64    pub fn new(ne: usize, fs_ind: usize) -> Self {
65        Self {
66            fs_ind,
67            ne,
68            nbits_est_old: 0,
69            nbits_offset_old: 0.0,
70            nbits_spec_old: 0,
71            reset_offset_old: false,
72        }
73    }
74
75    pub fn run<'a>(
76        &mut self,
77        x_f: &[Scaler],
78        x_q: &'a mut [i16],
79        nbits: usize,
80        nbits_bandwidth: usize,
81        nbits_tns: usize,
82        nbits_ltpf: usize,
83    ) -> SpectralQuantizationResult {
84        assert_eq!(x_f.len(), self.ne);
85        assert_eq!(x_q.len(), self.ne);
86
87        // bit budget
88        let nbits_spec = self.calc_bit_budget(nbits, nbits_bandwidth, nbits_tns, nbits_ltpf);
89
90        // first global gain estimation
91        let mut gg = self.first_global_gain_estimation(x_f, nbits, nbits_spec);
92
93        // quantization
94        let mut quant = self.quantize_spectrum(x_f, x_q, nbits, gg.est_params.gg_off, gg.gg_ind, nbits_spec);
95
96        // save state for next frame
97        self.nbits_offset_old = gg.est_params.nbits_offset;
98        self.nbits_est_old = quant.bit_consumption.nbits_est;
99        self.reset_offset_old = gg.reset_offset;
100        self.nbits_offset_old = gg.est_params.nbits_offset;
101
102        // global gain adjustment
103        let is_adjusted = self.global_gain_adjustment(&mut gg, nbits_spec, quant.bit_consumption.nbits_est);
104        if is_adjusted {
105            // requantize spectrum
106            quant = self.quantize_spectrum(x_f, x_q, nbits, gg.est_params.gg_off, gg.gg_ind, nbits_spec);
107        }
108
109        SpectralQuantizationResult {
110            //  output: x_q,
111            gg_ind: gg.gg_ind,
112            nbits_spec,
113            nbits_lsb: quant.bit_consumption.nbits_lsb,
114            lsb_mode: quant.lsb_mode,
115            nbits_trunc: quant.bit_consumption.nbits_trunc,
116            rate_flag: quant.bit_consumption.rate_flag,
117            lastnz_trunc: quant.bit_consumption.lastnz_trunc,
118            gg: quant.gg,
119        }
120    }
121
122    fn calc_bit_budget(&self, nbits: usize, nbits_bandwidth: usize, nbits_tns: usize, nbits_ltpf: usize) -> usize {
123        let nbits_ari = (self.ne as Scaler / 2.0).log2().ceil() as usize
124            + if nbits <= 1280 {
125                3
126            } else if nbits <= 2560 {
127                4
128            } else {
129                5
130            };
131        const NBITS_GAIN: usize = 8;
132        const NBITS_NF: usize = 3;
133        nbits - (nbits_bandwidth + nbits_tns + nbits_ltpf + NBITS_SNS + NBITS_GAIN + NBITS_NF + nbits_ari)
134    }
135
136    fn first_global_gain_estimation(&self, x_f: &[Scaler], nbits: usize, nbits_spec: usize) -> GlobalGainEstimation {
137        let est_params = self.get_global_gain_estimation_parameter(nbits, nbits_spec);
138
139        let mut e_buf = [0.0; MAX_LEN_SPECTRAL / 4];
140        let e = &mut e_buf[..self.ne / 4];
141        Self::compute_spectral_energy(e, x_f);
142
143        let gg_ind = self.global_gain_estimation(e, &est_params);
144
145        // finally, the quantized gain index shall be limited such that the quantized spectrum stays within the range [-32,768, 32,767]
146        let (reset_offset, gg_min, gg_ind) = Self::global_gain_limitation(x_f, est_params.gg_off, gg_ind);
147
148        GlobalGainEstimation {
149            gg_ind,
150            gg_min,
151            est_params,
152            reset_offset,
153        }
154    }
155
156    fn get_global_gain_estimation_parameter(&self, nbits: usize, nbits_spec: usize) -> GlobalGainEstimationParams {
157        let nbits_offset = if self.reset_offset_old {
158            0.0
159        } else {
160            let prev_nbits = self.nbits_offset_old + self.nbits_spec_old as f32 - self.nbits_est_old as f32;
161            0.8 * self.nbits_offset_old + 0.2 * (40.0).min((-40.0).max(prev_nbits))
162        };
163
164        let nbits_spec_adj = (nbits_spec as f32 + nbits_offset + 0.5) as u16 as usize;
165        let gg_off = -(115.min(nbits as i16 / (10 * (self.fs_ind as i16 + 1)))) - 105 - 5 * (self.fs_ind as i16 + 1);
166
167        GlobalGainEstimationParams {
168            nbits_offset,
169            nbits_spec_adj,
170            gg_off,
171        }
172    }
173
174    fn global_gain_estimation(&self, e: &[Scaler], gg_est_params: &GlobalGainEstimationParams) -> i16 {
175        let mut fac: i16 = 256;
176        let mut gg_ind = 255;
177
178        for _ in 0..8 {
179            fac >>= 1;
180            gg_ind -= fac;
181            let mut tmp = 0.0;
182            let mut is_zero = true;
183
184            for e_item in e.iter().rev() {
185                if *e_item * 28.0 / 20.0 < (gg_ind as Scaler + gg_est_params.gg_off as Scaler) {
186                    if !is_zero {
187                        tmp += 2.7 * 28.0 / 20.0;
188                    }
189                } else {
190                    if (gg_ind as Scaler + gg_est_params.gg_off as Scaler)
191                        < (*e_item * 28.0 / 20.0 - 43.0 * 28.0 / 20.0)
192                    {
193                        tmp += 2.0 * *e_item * 28.0 / 20.0
194                            - 2.0 * (gg_ind as Scaler + gg_est_params.gg_off as Scaler)
195                            - 36.0 * 28.0 / 20.0;
196                    } else {
197                        tmp += *e_item * 28.0 / 20.0 - (gg_ind as Scaler + gg_est_params.gg_off as Scaler)
198                            + 7.0 * 28.0 / 20.0;
199                    }
200                    is_zero = false;
201                }
202            }
203            if (tmp > gg_est_params.nbits_spec_adj as Scaler * 1.4 * 28.0 / 20.0) && !is_zero {
204                gg_ind += fac;
205            }
206        }
207
208        gg_ind
209    }
210
211    // returns (reset_offset, gg_min, gg_ind)
212    fn global_gain_limitation(x_f: &[Scaler], gg_off: i16, gg_ind: i16) -> (bool, i16, i16) {
213        let mut x_f_max = 0.0;
214        for x in x_f {
215            x_f_max = x_f_max.max((*x).abs());
216        }
217        let gg_min = if x_f_max > 0.0 {
218            (28.0 * (x_f_max / (32768.0 - 0.375)).log10()).ceil() as i16 - gg_off
219        } else {
220            0
221        };
222
223        if gg_ind < gg_min || x_f_max == 0.0 {
224            (true, gg_min, gg_min)
225        } else {
226            (false, gg_min, gg_ind)
227        }
228    }
229
230    fn quantize_spectrum(
231        &self,
232        x_f: &[Scaler],
233        x_q: &mut [i16],
234        nbits: usize,
235        gg_off: i16,
236        gg_ind: i16,
237        nbits_spec: usize,
238    ) -> QuantizeResult {
239        let gg = (10.0).powf((gg_ind as Scaler + gg_off as Scaler) / 28.0) as f32;
240        for (output, input) in x_q.iter_mut().zip(x_f) {
241            *output = if *input >= 0.0 {
242                (*input / gg + 0.375) as i16
243            } else {
244                (*input / gg - 0.375) as i16
245            };
246        }
247
248        // bit consumption
249        let bit_consumption = self.compute_bit_consumption(x_q, nbits, nbits_spec);
250
251        // truncation
252        for item in x_q[bit_consumption.lastnz_trunc..bit_consumption.lastnz].iter_mut() {
253            *item = 0;
254        }
255
256        let lsb_mode = bit_consumption.mode_flag && bit_consumption.nbits_est > nbits_spec;
257
258        QuantizeResult {
259            lsb_mode,
260            bit_consumption,
261            gg,
262        }
263    }
264
265    fn compute_bit_consumption(&self, x_q: &mut [i16], nbits: usize, nbits_spec: usize) -> BitConsumption {
266        let rate_flag = if nbits > (160 + self.fs_ind * 160) { 512 } else { 0 };
267
268        let mode_flag = nbits >= (480 + self.fs_ind * 160);
269
270        let mut lastnz = self.ne;
271        while lastnz > 2 && x_q[lastnz - 1] == 0 && x_q[lastnz - 2] == 0 {
272            lastnz -= 2;
273        }
274
275        let mut nbits_est_local: u32 = 0;
276        let mut nbits_trunc_local: u32 = 0;
277        let mut nbits_lsb = 0;
278        let mut lastnz_trunc = 2;
279        let mut c = 0;
280
281        for n in (0..lastnz).step_by(2) {
282            let mut t = c + rate_flag;
283            if n > self.ne / 2 {
284                t += 256;
285            }
286
287            let mut a = x_q[n].unsigned_abs();
288            let mut a_lsb = a;
289            let mut b = x_q[n + 1].unsigned_abs();
290            let mut b_lsb = b;
291            let mut lev = 0;
292            while a.max(b) >= 4 {
293                let pki = AC_SPEC_LOOKUP[t + lev * 1024];
294                nbits_est_local += AC_SPEC_BITS[pki as usize][16] as u32;
295                if lev == 0 && mode_flag {
296                    nbits_lsb += 2;
297                } else {
298                    nbits_est_local += 2 * 2048;
299                }
300                a >>= 1;
301                b >>= 1;
302                lev = 3.min(lev + 1);
303            }
304            let pki = AC_SPEC_LOOKUP[t + lev * 1024];
305            let sym = a + 4 * b;
306            nbits_est_local += AC_SPEC_BITS[pki as usize][sym as usize] as u32;
307
308            // alternative implementation (more clear, more performant?)
309            if a_lsb > 0 {
310                nbits_est_local += 2048;
311            }
312            if b_lsb > 0 {
313                nbits_est_local += 2048;
314            }
315            if lev > 0 && mode_flag {
316                a_lsb >>= 1;
317                b_lsb >>= 1;
318                if a_lsb == 0 && x_q[n] != 0 {
319                    nbits_lsb += 1;
320                }
321                if b_lsb == 0 && x_q[n + 1] != 0 {
322                    nbits_lsb += 1;
323                }
324            }
325
326            if (x_q[n] != 0 || x_q[n + 1] != 0) && (nbits_est_local as Scaler / 2048.0).ceil() as usize <= nbits_spec {
327                lastnz_trunc = n + 2;
328                nbits_trunc_local = nbits_est_local;
329            }
330            t = if lev <= 1 {
331                1 + (a + b) as usize * (lev + 1)
332            } else {
333                12 + lev
334            };
335            c = (c & 15) * 16 + t;
336        }
337        let nbits_est = (nbits_est_local as Scaler / 2048.0).ceil() as usize + nbits_lsb;
338        let nbits_trunc = (nbits_trunc_local as Scaler / 2048.0).ceil() as usize;
339        BitConsumption {
340            lastnz,
341            lastnz_trunc,
342            nbits_est,
343            mode_flag,
344            nbits_lsb,
345            nbits_trunc,
346            rate_flag,
347        }
348    }
349
350    fn global_gain_adjustment(&self, gg: &mut GlobalGainEstimation, nbits_spec: usize, nbits_est: usize) -> bool {
351        const T1: [usize; 5] = [80, 230, 380, 530, 680];
352        const T2: [usize; 5] = [500, 1025, 1550, 2075, 2600];
353        const T3: [usize; 5] = [850, 1700, 2550, 3400, 4250];
354
355        let t1 = T1[self.fs_ind];
356        let t2 = T2[self.fs_ind];
357        let t3 = T3[self.fs_ind];
358
359        let delta = if nbits_est < t1 {
360            (nbits_est as Scaler + 48.0) / 16.0
361        } else if nbits_est < t2 {
362            let tmp1 = t1 as Scaler / 16.0 + 3.0;
363            let tmp2 = t2 as Scaler / 48.0;
364            (nbits_est as Scaler - t1 as Scaler) * (tmp2 - tmp1) / (t2 as Scaler - t1 as Scaler) + tmp1
365        } else if nbits_est < t3 {
366            nbits_est as Scaler / 48.0
367        } else {
368            t3 as Scaler / 48.0
369        };
370        let delta = (delta + 0.5).floor();
371        let delta2 = delta + 2.0;
372
373        let gg_ind_origin = gg.gg_ind;
374        if gg.gg_ind < 255 && nbits_est > nbits_spec
375            || gg.gg_ind > 0 && (nbits_est as Scaler) < (nbits_spec as Scaler - delta2)
376        {
377            if (nbits_est as Scaler) < (nbits_spec as Scaler - delta2) {
378                gg.gg_ind -= 1;
379            } else if gg.gg_ind == 254 || (nbits_est as Scaler) < (nbits_spec as Scaler + delta) {
380                gg.gg_ind += 1;
381            } else {
382                gg.gg_ind += 2;
383            }
384            gg.gg_ind = gg.gg_ind.max(gg.gg_min);
385        }
386
387        gg_ind_origin != gg.gg_ind
388    }
389
390    fn compute_spectral_energy(e: &mut [Scaler], x_f: &[Scaler]) {
391        for (e, (x0, x1, x2, x3)) in e.iter_mut().zip(x_f.iter().tuples()) {
392            let total = *x0 * *x0 + *x1 * *x1 + *x2 * *x2 + *x3 * *x3;
393            *e = 10.0 * (Scaler::EPSILON + total).log10();
394        }
395    }
396}
397
398#[cfg(test)]
399mod tests {
400    extern crate std;
401    use super::*;
402
403    #[test]
404    fn spectral_quantization_run() {
405        let mut quant = SpectralQuantization::new(400, 4);
406        #[rustfmt::skip]
407        let x_f = [
408            2511.287, -3606.8093, -453.28122, -360.71924, -2574.9756, -3166.2068, 6525.6, 6284.0137, -10303.951,
409            -4442.8755, 2318.4038, -691.36865, 509.12134, -938.29266, 525.9005, -1542.4482, -3091.5273, 262.27206,
410            -379.65656, -98.486786, 668.16437, -213.70082, -114.14174, 80.94827, 83.418945, -16.794994, 6.197174,
411            -332.66284, -48.91777, 0.084522665, -281.5821, 78.69863, 133.78897, 102.63185, -259.9021, -450.69684,
412            -538.17615, 102.73462, 256.75674, -122.24531, 414.3129, 90.33753, -141.62321, 64.58323, 158.11197,
413            264.04486, -70.996445, -74.847595, 715.87695, 398.03842, -383.14874, 81.798744, 100.61626, 183.76709,
414            107.91918, -74.72749, 137.34314, -12.11866, 145.58879, -8.319928, -146.90816, 21.44834, -14.692991,
415            -26.504921, -44.41256, 169.60251, 157.3852, 57.295708, -223.72159, -105.66721, 85.917145, -124.74416,
416            67.12806, 148.09708, 108.51118, -38.312347, 85.37175, 124.25812, -19.708088, -252.26158, -396.83145,
417            30.49828, 24.158318, 4.4514937, -100.692856, -19.743237, 174.73466, -129.2712, -94.76638, -48.278133,
418            -12.916355, -108.09598, 15.809202, 102.17793, -36.756264, -59.4923, -168.1815, 18.80262, -43.62355,
419            23.15091, 16.152151, -187.13437, 30.643784, 90.79638, -16.21843, -39.05421, 62.11714, -2.155285, -19.06319,
420            -42.414265, 35.171066, 84.379585, -116.602325, -33.51855, -7.659307, 44.801598, -11.07798, -14.886959,
421            62.95822, 14.218942, 31.104227, -83.76815, 17.044928, 55.428146, -13.889921, -126.15556, -27.248165,
422            120.640366, -19.761774, 14.046745, -73.71858, 0.10803318, 10.083524, -16.70562, 4.7014112, -62.691025,
423            50.462833, -84.346176, -13.629369, 36.10631, -46.619267, -21.598942, -48.490704, -6.3323555, 15.65649,
424            48.896317, -56.442543, -6.640568, -17.761715, -70.73248, -40.4366, -36.27153, 74.86966, -46.19746,
425            -44.013317, 2.0889094, 26.809942, -6.282827, -65.310585, 33.484646, -9.667151, 15.079562, -16.305983,
426            9.046168, 29.939863, 5.129214, 16.5475, -50.21096, 31.017387, 38.323303, -3.0681198, -36.80033, -1.2009478,
427            11.490404, 26.555166, 44.298775, -31.610435, 4.04779, -32.927948, 29.660675, 11.896004, -18.109625,
428            25.200207, -23.730797, 15.500507, -25.358208, 6.163124, -7.3798866, -7.921206, -16.156162, -36.149162,
429            -1.5045524, -43.494595, 29.947332, -15.511134, -17.982704, -28.039505, -30.445019, -3.5225277, -46.805386,
430            -1.0227482, -23.363768, -17.676548, -3.6520846, -12.88875, 4.756609, 31.271141, -6.629322, -37.832882,
431            -0.21950912, 38.885174, 21.138603, 6.2617035, -9.60021, -11.284341, -19.242826, -1.6980145, -9.359415,
432            -41.126484, -29.448069, -5.9372683, 25.94433, 1.3254867, -14.705631, 15.379487, 16.574158, -27.095804,
433            -19.93113, 20.497425, 0.79107094, -7.7554317, -36.76988, -52.092567, -38.030884, -20.167278, -0.28380156,
434            -7.2491307, 8.2373905, 7.9681587, 12.655432, 23.266579, 13.15513, 5.5212536, 12.821712, 10.402097, -1.8669,
435            17.029139, 7.877034, -3.6022367, -13.437171, -10.018736, 6.7936516, 12.0322485, 17.809977, -13.797862,
436            -19.886257, -20.896944, -13.391824, -3.7870193, -6.042081, 9.495218, -8.35246, -16.302475, -16.089418,
437            -2.2239032, 5.133191, -1.9499176, -12.571083, -26.08479, -8.472019, -4.010655, 5.987412, -1.6527638,
438            -5.525652, -1.8339038, -6.3098893, -2.546278, -14.999996, -4.8673024, -21.751396, -23.044847, 0.98999345,
439            3.2206738, 1.6813838, -5.9552116, -2.9898171, -6.6439576, 10.739187, -0.41604716, -6.192164, 10.029629,
440            -8.77803, -3.0170813, -3.2569091, -16.77877, -12.368547, 2.8054588, -1.341449, 4.0487995, 9.832774,
441            9.444449, 19.458578, -5.653375, -5.7151184, -1.1136432, 2.3793151, 5.6741295, -4.6841993, -0.53913784,
442            -5.0413313, -4.085096, -17.153347, -1.8630176, 11.785563, 1.1223254, -0.71278524, -4.503395, 1.1829545,
443            -10.829809, -1.1153163, 3.7169714, -0.4367964, -0.591923, -2.8435392, 1.75674, -4.178983, 4.8031635,
444            -5.574907, -0.26360065, -4.317787, -11.108944, 12.20769, 3.0794377, -0.6653844, -2.5413795, -2.403656,
445            -0.8925853, 13.288289, 6.883606, -15.778875, -1.6005001, 5.696593, 8.6179, -7.1294184, -5.413874,
446            5.2202096, 2.9486847, -2.3101602, -2.2582812, 15.61281, -0.8072282, -0.08025418, -4.076133, -9.068343,
447            4.1847715, -2.2272792, -1.0373013, -4.7336984, 1.2461259, -0.5397187, 0.18704754, -0.1272373, 0.41515422,
448            4.11998, -5.550728, 0.5320622, 3.4917614, 8.215734, -10.053921, -7.784162, 3.4075887, -8.748142,
449            0.87312615, -1.6497533, 1.9920977, -0.20973617, -1.9895163, -3.3932712, 1.6009337, 7.0630236, -3.209106,
450            5.2722173, -5.2088814, -1.2551317, 2.55086, -3.7561512, -1.9274446, -2.2996173, 5.709345, -2.3815656,
451            -0.94840765, 0.60572165, 4.09223, -2.2723556, -4.731332, 2.7107785, -2.495332, 3.3961606, -2.640641,
452            -1.3273795,
453        ];
454        let mut x_q = [0; 400];
455
456        let result = quant.run(&x_f, &mut x_q, 1200, 3, 42, 11);
457
458        let x_q_expected = [
459            102, -146, -18, -14, -104, -128, 264, 254, -417, -180, 94, -28, 20, -38, 21, -62, -125, 10, -15, -4, 27,
460            -9, -4, 3, 3, -1, 0, -13, -2, 0, -11, 3, 5, 4, -10, -18, -22, 4, 10, -5, 17, 4, -6, 2, 6, 11, -3, -3, 29,
461            16, -15, 3, 4, 7, 4, -3, 5, 0, 6, 0, -6, 1, 0, -1, -2, 7, 6, 2, -9, -4, 3, -5, 3, 6, 4, -1, 3, 5, -1, -10,
462            -16, 1, 1, 0, -4, -1, 7, -5, -4, -2, 0, -4, 1, 4, -1, -2, -7, 1, -2, 1, 1, -7, 1, 4, -1, -1, 2, 0, -1, -2,
463            1, 3, -5, -1, 0, 2, 0, 0, 2, 0, 1, -3, 1, 2, 0, -5, -1, 5, -1, 0, -3, 0, 0, -1, 0, -2, 2, -3, 0, 1, -2, -1,
464            -2, 0, 1, 2, -2, 0, -1, -3, -2, -1, 3, -2, -2, 0, 1, 0, -3, 1, 0, 0, -1, 0, 1, 0, 1, -2, 1, 1, 0, -1, 0, 0,
465            1, 2, -1, 0, -1, 1, 0, -1, 1, -1, 1, -1, 0, 0, 0, -1, -1, 0, -2, 1, -1, -1, -1, -1, 0, -2, 0, -1, -1, 0, 0,
466            0, 1, 0, -1, 0, 1, 1, 0, 0, 0, -1, 0, 0, -2, -1, 0, 1, 0, 0, 0, 1, -1, -1, 1, 0, 0, -1, -2, -1, -1, 0, 0,
467            0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, -1, -1, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, -1, 0, 0,
468            0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
469            0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0,
470            0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
471            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
472        ];
473        assert_eq!(x_q, x_q_expected);
474        assert_eq!(result.gg, 24.7091141);
475        assert_eq!(result.lastnz_trunc, 350);
476        assert_eq!(result.lsb_mode, false);
477        assert_eq!(result.gg_ind, 193);
478        assert_eq!(result.rate_flag, 512);
479        assert_eq!(result.nbits_lsb, 107);
480    }
481}