1use super::side_info::SnsVq;
2use crate::tables::{
3 band_index_tables::*,
4 spec_noise_shape_quant_tables::{
5 D, HFCB, LFCB, SNS_VQ_FAR_ADJ_GAINS, SNS_VQ_NEAR_ADJ_GAINS, SNS_VQ_REG_ADJ_GAINS, SNS_VQ_REG_LF_ADJ_GAINS,
6 },
7};
8use crate::{
9 common::{
10 complex::Scaler,
11 config::{FrameDuration, Lc3Config},
12 },
13 tables::spec_noise_shape_quant_tables::MPVQ_OFFSETS,
14};
15
16#[allow(unused_imports)]
19use num_traits::real::Real;
20
21pub fn decode(config: &Lc3Config, sns: &SnsVq, spec_lines: &mut [Scaler]) {
22 let mut quant_1st_stage_vec = [0.0; 16];
23 quant_1st_stage_vec[..8].copy_from_slice(&LFCB[sns.ind_lf]);
24 quant_1st_stage_vec[8..].copy_from_slice(&HFCB[sns.ind_hf]);
25
26 let shape_j = (sns.submode_msb << 1) + sns.submode_lsb;
27 let gain_i = sns.g_ind;
28
29 let mut y = [0; 16];
30 let mut z = [0; 16];
31
32 match shape_j {
34 0 => {
35 mpvq_deenum(10, 10, sns.ls_inda, sns.idx_a, &mut y);
36 mpvq_deenum(6, 1, sns.ls_indb, sns.idx_b, &mut z);
37 y[10..16].copy_from_slice(&z[..6]);
38 }
39 1 => {
40 mpvq_deenum(10, 10, sns.ls_inda, sns.idx_a, &mut y);
41 for y_n in &mut y[10..16] {
42 *y_n = 0;
43 }
44 }
45 2 => mpvq_deenum(16, 8, sns.ls_inda, sns.idx_a, &mut y),
46 3 => mpvq_deenum(16, 6, sns.ls_inda, sns.idx_a, &mut y),
47 _ => panic!("invalid shape_j when making mpvq denum calls: {}", shape_j),
48 };
49
50 let y_norm = y[..16]
52 .iter()
53 .map(|x| *x as Scaler * *x as Scaler)
54 .sum::<Scaler>()
55 .sqrt();
56
57 let mut quant_adj_gain = match shape_j {
59 0 => SNS_VQ_REG_ADJ_GAINS[gain_i],
60 1 => SNS_VQ_REG_LF_ADJ_GAINS[gain_i],
61 2 => SNS_VQ_NEAR_ADJ_GAINS[gain_i],
62 3 => SNS_VQ_FAR_ADJ_GAINS[gain_i],
63 _ => panic!(
64 "invalid shape_j when loopking up adjustment gain candidates: {}",
65 shape_j
66 ),
67 };
68
69 if y_norm != 0.0 {
70 quant_adj_gain /= y_norm;
71 }
72
73 let mut quant_scale_factor = [0.0; 16];
75 for n in 0..16 {
76 let mut factor = 0.0;
77 for (col, y_col) in y[..16].iter().enumerate() {
78 factor += *y_col as Scaler * D[n][col];
79 }
80
81 quant_scale_factor[n] = quant_1st_stage_vec[n] + quant_adj_gain * factor;
82 }
83
84 let mut scale_factor_interp = [0.0; 64];
86 scale_factor_interp[0] = quant_scale_factor[0];
87 scale_factor_interp[1] = quant_scale_factor[0];
88
89 for n in 0..=14 {
90 let factor_n = quant_scale_factor[n];
91 let diff_next = quant_scale_factor[n + 1] - factor_n;
92 scale_factor_interp[4 * n + 2] = factor_n + (1.0 / 8.0 * diff_next);
93 scale_factor_interp[4 * n + 3] = factor_n + (3.0 / 8.0 * diff_next);
94 scale_factor_interp[4 * n + 4] = factor_n + (5.0 / 8.0 * diff_next);
95 scale_factor_interp[4 * n + 5] = factor_n + (7.0 / 8.0 * diff_next);
96 }
97 scale_factor_interp[62] = quant_scale_factor[15] + 1.0 / 8.0 * (quant_scale_factor[15] - quant_scale_factor[14]);
98 scale_factor_interp[63] = quant_scale_factor[15] + 3.0 / 8.0 * (quant_scale_factor[15] - quant_scale_factor[14]);
99
100 let nb = config.nb;
103 let n2 = 64 - nb;
104 if n2 != 0 {
105 for i in 0..n2 {
106 scale_factor_interp[i] = (scale_factor_interp[2 * i] + scale_factor_interp[2 * i + 1]) / 2.0;
107 }
108 for i in n2..nb {
109 scale_factor_interp[i] = scale_factor_interp[i + n2];
110 }
111 }
112
113 let mut g_sns = [0.0; 64];
114
115 for b in 0..nb {
117 g_sns[b] = fast_math::exp2_raw(scale_factor_interp[b]);
123 }
124
125 let i_fs: &[usize] = match config.n_ms {
126 FrameDuration::SevenPointFiveMs => match config.fs_ind {
127 0 => &I_8000_7P5MS,
128 1 => &I_16000_7P5MS,
129 2 => &I_24000_7P5MS,
130 3 => &I_32000_7P5MS,
131 4 => &I_48000_7P5MS,
132 _ => panic!("invalid fs_ind"),
133 },
134 FrameDuration::TenMs => match config.fs_ind {
135 0 => &I_8000_10MS,
136 1 => &I_16000_10MS,
137 2 => &I_24000_10MS,
138 3 => &I_32000_10MS,
139 4 => &I_48000_10MS,
140 _ => panic!("invalid fs_ind"),
141 },
142 };
143
144 for (b, g_sns_b) in g_sns[..nb].iter().enumerate() {
146 for spec_line in spec_lines[i_fs[b]..i_fs[b + 1]].iter_mut() {
148 *spec_line *= *g_sns_b;
149 }
150 }
151}
152
153fn mpvq_deenum(dim_in: usize, k_val_in: usize, ls_ind: usize, mpvq_ind: usize, vec_out: &mut [i32]) {
156 for x in vec_out.iter_mut().take(dim_in) {
157 *x = 0;
158 }
159
160 let mut leading_sign = if ls_ind == 0 { 1 } else { -1 };
161 let mut k_max_local = k_val_in;
162 let mut ind = mpvq_ind;
163
164 let mut k_acc;
166
167 for pos in 0..dim_in {
169 let h_row_ptr = &MPVQ_OFFSETS[dim_in - 1 - pos];
170 let k_delta;
171 if ind != 0 {
172 k_acc = k_max_local;
173 let ul_tmp_offset = h_row_ptr[k_acc];
174 let mut wrap_flag = ind < ul_tmp_offset;
175 let mut ul_diff = 0;
176 if !wrap_flag {
177 ul_diff = ind - ul_tmp_offset;
179 }
180
181 while wrap_flag {
182 k_acc -= 1;
183 wrap_flag = ind < h_row_ptr[k_acc];
184 if !wrap_flag {
185 ul_diff = ind - h_row_ptr[k_acc];
187 }
188 }
189
190 ind = ul_diff;
191 k_delta = k_max_local - k_acc;
192 } else {
193 vec_out[pos] = mind2vec_one(k_max_local, leading_sign);
194 break;
195 }
196
197 k_max_local = setval_update_sign(k_delta, k_max_local, &mut leading_sign, &mut ind, &mut vec_out[pos])
198 }
199}
200
201fn setval_update_sign(
202 k_delta: usize,
203 k_max_local_in: usize,
204 leading_sign: &mut i32,
205 ind_in: &mut usize,
206 vec_out_item: &mut i32,
207) -> usize {
208 let mut k_max_local_out = k_max_local_in;
209 if k_delta != 0 {
210 *vec_out_item = mind2vec_one(k_delta, *leading_sign);
211 *leading_sign = get_lead_sign(ind_in);
212 k_max_local_out -= k_delta;
213 }
214
215 k_max_local_out
216}
217
218fn get_lead_sign(ind_in: &mut usize) -> i32 {
219 let mut leading_sign = 1;
220
221 if *ind_in & 0x1 != 0 {
222 leading_sign = -1;
223 }
224
225 *ind_in >>= 1;
226 leading_sign
227}
228
229fn mind2vec_one(k_val_in: usize, leading_sign: i32) -> i32 {
230 if leading_sign < 0 {
231 -(k_val_in as i32)
232 } else {
233 k_val_in as i32
234 }
235}
236
237#[cfg(test)]
238mod tests {
239 extern crate std;
240 use super::*;
241 use crate::common::config::FrameDuration;
242
243 #[test]
244 fn spectral_noise_shaping_decode() {
245 let config = Lc3Config {
246 fs_ind: 4,
247 n_ms: FrameDuration::TenMs,
248 nb: 64,
249 fs: 0,
251 ne: 0,
252 nf: 0,
253 z: 0,
254 };
255 let sns = SnsVq {
256 ind_lf: 13,
257 ind_hf: 4,
258 ls_inda: 1,
259 ls_indb: 0,
260 idx_a: 1718290,
261 idx_b: 2,
262 submode_lsb: 0,
263 submode_msb: 0,
264 g_ind: 0,
265 };
266 #[rustfmt::skip]
267 let mut spec_lines = [
268 -568.56555, 1972.808, 3987.5906, 2461.2402, -263.29547, -2949.6724, -2217.0242, 141.18742, 1270.6868,
269 -385.4035, 1667.538, 568.56555, -538.0386, -1924.9376, -330.6227, 358.01404, -103.25958, 640.72064,
270 -380.6663, -565.7268, 1425.4789, -1620.2815, -2171.777, 65.41626, -630.4777, -241.61359, 70.17501,
271 648.6986, 913.1724, 377.05695, 1248.8955, 447.55414, 122.224335, 387.0873, 670.9608, 202.11314, 470.52597,
272 9.777176, 250.14848, -869.4124, 705.27844, 764.594, -196.6836, 162.10555, 32.383907, 212.68384, -200.68219,
273 -385.05658, 74.749176, 244.4491, 75.39133, 71.7427, -370.58853, -284.1499, -221.86317, -378.81683,
274 -78.224205, 120.7565, 49.39573, -431.70422, -639.2284, -863.50916, -762.39795, -557.4247, -210.2326,
275 207.37712, 667.06, 268.28708, 266.76526, 180.27934, 266.1345, 18.510933, -71.35217, -18.678001, 61.719135,
276 78.072945, 41.07525, 31.682747, 65.34431, 39.83117, 50.713173, 265.0006, 87.029144, -105.01486, -92.9501,
277 109.07149, 213.51758, 237.69977, 244.04578, 169.18098, -60.653255, -202.20692, -5.709038, 418.32336,
278 390.42206, -52.63867, -409.54736, -371.99884, -123.08209, 15.460239, -13.179712, 10.579021, 10.312677,
279 49.179047, -104.04299, -108.42853, 45.232265, 106.2404, -18.412956, -252.0934, -189.36148, 85.68147,
280 260.1948, 66.20917, -89.14935, 37.372047, 196.89316, 4.2800827, -186.45068, -10.664055, 251.7307,
281 283.97842, 87.595795, 65.05641, 91.597, -64.72161, -260.67474, -120.33, 275.7829, 360.36444, 76.64067,
282 -85.21214, -19.708641, 59.083878, 71.03325, 37.62242, 41.2656, 33.881153, 25.94694, -3.6607666, -15.336594,
283 -46.333282, -68.63583, 51.637062, 181.11745, 75.242294, -25.19682, -26.834858, 23.40418, 38.82212,
284 -11.055281, -14.305193, -22.998611, 129.22333, 87.56438, -91.969635, -113.919846, -21.006641, 165.25201,
285 93.82325, 70.90962, 56.982315, 15.586489, -109.50122, -156.43475, -32.77449, 127.61873, 86.515625,
286 -71.82623, -60.272907, 74.61493, 174.22997, 35.206467, -130.87024, -37.255043, 125.10912, 72.04756,
287 28.948765, 1.5288572, 89.77242, 28.662163, -122.471275, -64.80139, 35.938797, 56.74036, 19.603413,
288 -92.18097, -95.45599, 4.2908516, 4.6752024, 39.53695, 19.507534, -69.66742, -24.112461, -4.6465445,
289 -19.89853, -2.2964888, 51.27441, 41.12713, 64.92945, 0.0, 0.0, 0.0, 61.05402, 0.0, 61.05402, 0.0, 61.05402,
290 0.0, 0.0, 0.0, -61.05402, 61.05402, 122.10804, -61.05402, 0.0, 122.10804, 0.0, 61.05402, -61.05402, 0.0,
291 0.0, -61.05402, 0.0, 0.0, 122.10804, -61.05402, -61.05402, 0.0, 0.0, 0.0, 0.0, -61.05402, 61.05402,
292 -61.05402, 61.05402, 61.05402, 61.05402, 0.0, 0.0, 61.05402, 0.0, 0.0, 0.0, 61.05402, 61.05402, 61.05402,
293 0.0, 0.0, 61.05402, 0.0, 0.0, 61.05402, 122.10804, -122.10804, 0.0, -61.05402, -61.05402, 0.0, 0.0, 0.0,
294 0.0, -61.05402, 0.0, 0.0, -61.05402, 61.05402, 61.05402, 61.05402, -122.10804, -61.05402, -61.05402, 0.0,
295 61.05402, -61.05402, 0.0, 0.0, 61.05402, 0.0, 0.0, 0.0, -61.05402, 61.05402, -61.05402, 0.0, 0.0,
296 -61.05402, 61.05402, 0.0, 0.0, 0.0, 61.05402, 61.05402, 0.0, -61.05402, -61.05402, 0.0, -61.05402, 0.0,
297 -61.05402, -61.05402, 0.0, 61.05402, 0.0, 0.0, 0.0, 0.0, -61.05402, 0.0, 61.05402, 61.05402, 0.0, 0.0, 0.0,
298 0.0, -61.05402, -61.05402, -61.05402, 0.0, 0.0, 0.0, -61.05402, 0.0, 0.0, 61.05402, 0.0, -61.05402, 0.0,
299 61.05402, 0.0, 0.0, 0.0, -61.05402, 0.0, 0.0, 0.0, -61.05402, 0.0, 0.0, -61.05402, 0.0, 0.0, 0.0, 0.0,
300 -61.05402, 61.05402, 0.0, 0.0, 0.0, 0.0, 61.05402, 0.0, 0.0, 0.0, 0.0, -61.05402, -61.05402, 61.05402, 0.0,
301 0.0, 0.0, -19.079382, -19.079382, -19.079382, -19.079382, 19.079382, -19.079382, 19.079382, 0.0, 0.0, 0.0,
302 -61.05402, -61.05402, 0.0, 0.0, 61.05402, -61.05402, -61.05402, 0.0, 0.0, 61.05402, 0.0, 0.0, 0.0, 0.0,
303 -61.05402, 0.0, 61.05402, 0.0, 61.05402, 0.0, 0.0, 0.0, 0.0, 0.0, -61.05402, 0.0, 0.0, 61.05402, 61.05402,
304 ];
305
306 decode(&config, &sns, &mut spec_lines);
307
308 #[rustfmt::skip]
309 let spec_lines_expected = [
310 -2268.137, 7869.9785, 15884.984, 9776.979, -1042.96, -11651.202, -8543.342, 519.08997, 4455.2827, -1288.14,
311 5093.401, 1520.3356, -1260.0343, -3961.906, -641.0432, 703.6705, -205.72899, 1298.229, -831.222,
312 -1235.3197, 3581.536, -4070.9802, -6290.9507, 189.4902, -2103.3403, -806.0485, 248.62497, 2298.2922,
313 3174.625, 1310.8307, 4260.057, 1526.6339, 409.04425, 1295.4526, 2116.6775, 637.6055, 1343.3187, 27.913153,
314 714.1564, -2245.3208, 1821.4329, 1974.6196, -459.77234, 378.94186, 75.70141, 449.14334, -423.7984,
315 -813.15814, 141.91173, 464.08798, 143.13086, 122.60409, -633.3142, -485.5956, -379.15125, -581.63947,
316 -120.10629, 185.41084, 75.84274, -589.5617, -872.96936, -1179.2609, -1041.1772, -671.12726, -253.11552,
317 249.67758, 803.12585, 285.46893, 283.84964, 191.82494, 283.1785, 17.406265, -67.094124, -17.563364,
318 58.03595, 73.413826, 35.959316, 27.736652, 57.205654, 34.870186, 44.39683, 227.21794, 74.620895, -90.04228,
319 -79.69767, 93.52053, 179.29234, 199.59831, 204.92711, 142.06258, -50.931004, -169.79471, -4.6945424,
320 343.98734, 321.0441, -43.284782, -336.7708, -305.89468, -90.73599, 11.397272, -9.71607, 7.7988434,
321 7.6024947, 36.25474, -76.700386, -65.53449, 27.338501, 64.21198, -11.1288395, -152.36592, -114.450584,
322 51.78611, 129.27042, 32.89415, -44.291332, 18.567244, 97.82079, 2.126438, -92.632744, -4.3691993,
323 103.137276, 116.34959, 35.889114, 26.654442, 37.52846, -26.51727, -106.801765, -40.06586, 91.82647,
324 119.98929, 25.518776, -28.37279, -6.5623174, 19.672953, 23.651693, 10.104294, 11.0827465, 9.099498,
325 6.9685974, -0.98317605, -4.1189656, -12.44378, -18.4336, 13.868221, 39.34896, 16.346886, -5.4741755,
326 -5.83005, 5.084713, 8.434362, -2.4018328, -3.1078978, -4.9966, 28.074621, 15.33394, -16.105371, -19.94921,
327 -3.678603, 28.938301, 16.42997, 12.417422, 9.978525, 2.7294464, -19.175436, -23.296207, -4.8807654,
328 19.004936, 12.883876, -10.696337, -8.97582, 11.111629, 25.946264, 5.242934, -19.48915, -5.5480075,
329 16.77535, 9.660551, 3.8816166, 0.20499796, 12.037202, 3.8431873, -16.421652, -8.688943, 4.8188806,
330 7.608073, 2.6285381, -11.124037, -11.519255, 0.51780313, 0.564185, 4.7711635, 2.3540926, -8.40719,
331 -2.909797, -0.5607267, -2.4012764, -0.27713123, 6.1875944, 4.4743004, 7.0638013, 0.0, 0.0, 0.0, 6.6421857,
332 0.0, 6.6421857, 0.0, 6.6421857, 0.0, 0.0, 0.0, -6.4278693, 6.4278693, 12.855739, -6.4278693, 0.0,
333 12.855739, 0.0, 6.4278693, -6.4278693, 0.0, 0.0, -6.4278693, 0.0, 0.0, 13.372511, -6.6862555, -6.6862555,
334 0.0, 0.0, 0.0, 0.0, -6.6862555, 6.6862555, -6.6862555, 6.6862555, 6.6862555, 6.6862555, 0.0, 0.0,
335 6.9530754, 0.0, 0.0, 0.0, 6.9530754, 6.9530754, 6.9530754, 0.0, 0.0, 6.9530754, 0.0, 0.0, 6.9530754,
336 13.906151, -13.906151, 0.0, -7.2283335, -7.2283335, 0.0, 0.0, 0.0, 0.0, -7.2283335, 0.0, 0.0, -7.2283335,
337 7.2283335, 7.2283335, 7.2283335, -14.456667, -7.2283335, -7.2283335, 0.0, 8.2442, -8.2442, 0.0, 0.0,
338 8.2442, 0.0, 0.0, 0.0, -8.2442, 8.2442, -8.2442, 0.0, 0.0, -8.2442, 8.2442, 0.0, 0.0, 0.0, 10.337095,
339 10.337095, 0.0, -10.337095, -10.337095, 0.0, -10.337095, 0.0, -10.337095, -10.337095, 0.0, 10.337095, 0.0,
340 0.0, 0.0, 0.0, -10.337095, 0.0, 10.337095, 12.974136, 0.0, 0.0, 0.0, 0.0, -12.974136, -12.974136,
341 -12.974136, 0.0, 0.0, 0.0, -12.974136, 0.0, 0.0, 12.974136, 0.0, -12.974136, 0.0, 12.974136, 0.0, 0.0, 0.0,
342 -16.216764, 0.0, 0.0, 0.0, -16.216764, 0.0, 0.0, -16.216764, 0.0, 0.0, 0.0, 0.0, -16.216764, 16.216764,
343 0.0, 0.0, 0.0, 0.0, 16.216764, 0.0, 0.0, 0.0, 0.0, -20.320456, -20.320456, 20.320456, 0.0, 0.0, 0.0,
344 -6.3501425, -6.3501425, -6.3501425, -6.3501425, 6.3501425, -6.3501425, 6.3501425, 0.0, 0.0, 0.0,
345 -20.320456, -20.320456, 0.0, 0.0, 25.512432, -25.512432, -25.512432, 0.0, 0.0, 25.512432, 0.0, 0.0, 0.0,
346 0.0, -25.512432, 0.0, 25.512432, 0.0, 25.512432, 0.0, 0.0, 0.0, 0.0, 0.0, -25.512432, 0.0, 0.0, 25.512432,
347 25.512432,
348 ];
349 assert_eq!(spec_lines, spec_lines_expected);
350 }
351
352 #[test]
353 fn mpvq_deenum_test1() {
354 let mut vec_out = [0; 16];
355
356 mpvq_deenum(10, 10, 1, 1718290, &mut vec_out);
357
358 assert_eq!(vec_out, [0, -2, 0, 0, 1, 1, 3, -2, 1, 0, 0, 0, 0, 0, 0, 0]);
359 }
360
361 #[test]
362 fn mpvq_deenum_test2() {
363 let mut vec_out = [0; 16];
364
365 mpvq_deenum(6, 1, 0, 2, &mut vec_out);
366
367 assert_eq!(vec_out, [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
368 }
369}