use super::side_info::SnsVq;
use crate::tables::{
band_index_tables::*,
spec_noise_shape_quant_tables::{
D, HFCB, LFCB, SNS_VQ_FAR_ADJ_GAINS, SNS_VQ_NEAR_ADJ_GAINS, SNS_VQ_REG_ADJ_GAINS, SNS_VQ_REG_LF_ADJ_GAINS,
},
};
use crate::{
common::{
complex::Scaler,
config::{FrameDuration, Lc3Config},
},
tables::spec_noise_shape_quant_tables::MPVQ_OFFSETS,
};
#[allow(unused_imports)]
use num_traits::real::Real;
pub fn decode(config: &Lc3Config, sns: &SnsVq, spec_lines: &mut [Scaler]) {
let mut quant_1st_stage_vec = [0.0; 16];
quant_1st_stage_vec[..8].copy_from_slice(&LFCB[sns.ind_lf]);
quant_1st_stage_vec[8..].copy_from_slice(&HFCB[sns.ind_hf]);
let shape_j = (sns.submode_msb << 1) + sns.submode_lsb;
let gain_i = sns.g_ind;
let mut y = [0; 16];
let mut z = [0; 16];
match shape_j {
0 => {
mpvq_deenum(10, 10, sns.ls_inda, sns.idx_a, &mut y);
mpvq_deenum(6, 1, sns.ls_indb, sns.idx_b, &mut z);
y[10..16].copy_from_slice(&z[..6]);
}
1 => {
mpvq_deenum(10, 10, sns.ls_inda, sns.idx_a, &mut y);
for y_n in &mut y[10..16] {
*y_n = 0;
}
}
2 => mpvq_deenum(16, 8, sns.ls_inda, sns.idx_a, &mut y),
3 => mpvq_deenum(16, 6, sns.ls_inda, sns.idx_a, &mut y),
_ => panic!("invalid shape_j when making mpvq denum calls: {}", shape_j),
};
let y_norm = y[..16]
.iter()
.map(|x| *x as Scaler * *x as Scaler)
.sum::<Scaler>()
.sqrt();
let mut quant_adj_gain = match shape_j {
0 => SNS_VQ_REG_ADJ_GAINS[gain_i],
1 => SNS_VQ_REG_LF_ADJ_GAINS[gain_i],
2 => SNS_VQ_NEAR_ADJ_GAINS[gain_i],
3 => SNS_VQ_FAR_ADJ_GAINS[gain_i],
_ => panic!(
"invalid shape_j when loopking up adjustment gain candidates: {}",
shape_j
),
};
if y_norm != 0.0 {
quant_adj_gain /= y_norm;
}
let mut quant_scale_factor = [0.0; 16];
for n in 0..16 {
let mut factor = 0.0;
for (col, y_col) in y[..16].iter().enumerate() {
factor += *y_col as Scaler * D[n][col];
}
quant_scale_factor[n] = quant_1st_stage_vec[n] + quant_adj_gain * factor;
}
let mut scale_factor_interp = [0.0; 64];
scale_factor_interp[0] = quant_scale_factor[0];
scale_factor_interp[1] = quant_scale_factor[0];
for n in 0..=14 {
let factor_n = quant_scale_factor[n];
let diff_next = quant_scale_factor[n + 1] - factor_n;
scale_factor_interp[4 * n + 2] = factor_n + (1.0 / 8.0 * diff_next);
scale_factor_interp[4 * n + 3] = factor_n + (3.0 / 8.0 * diff_next);
scale_factor_interp[4 * n + 4] = factor_n + (5.0 / 8.0 * diff_next);
scale_factor_interp[4 * n + 5] = factor_n + (7.0 / 8.0 * diff_next);
}
scale_factor_interp[62] = quant_scale_factor[15] + 1.0 / 8.0 * (quant_scale_factor[15] - quant_scale_factor[14]);
scale_factor_interp[63] = quant_scale_factor[15] + 3.0 / 8.0 * (quant_scale_factor[15] - quant_scale_factor[14]);
let nb = config.nb;
let n2 = 64 - nb;
if n2 != 0 {
for i in 0..n2 {
scale_factor_interp[i] = (scale_factor_interp[2 * i] + scale_factor_interp[2 * i + 1]) / 2.0;
}
for i in n2..nb {
scale_factor_interp[i] = scale_factor_interp[i + n2];
}
}
let mut g_sns = [0.0; 64];
for b in 0..nb {
g_sns[b] = fast_math::exp2_raw(scale_factor_interp[b]);
}
let i_fs: &[usize] = match config.n_ms {
FrameDuration::SevenPointFiveMs => match config.fs_ind {
0 => &I_8000_7P5MS,
1 => &I_16000_7P5MS,
2 => &I_24000_7P5MS,
3 => &I_32000_7P5MS,
4 => &I_48000_7P5MS,
_ => panic!("invalid fs_ind"),
},
FrameDuration::TenMs => match config.fs_ind {
0 => &I_8000_10MS,
1 => &I_16000_10MS,
2 => &I_24000_10MS,
3 => &I_32000_10MS,
4 => &I_48000_10MS,
_ => panic!("invalid fs_ind"),
},
};
for (b, g_sns_b) in g_sns[..nb].iter().enumerate() {
for spec_line in spec_lines[i_fs[b]..i_fs[b + 1]].iter_mut() {
*spec_line *= *g_sns_b;
}
}
}
fn mpvq_deenum(dim_in: usize, k_val_in: usize, ls_ind: usize, mpvq_ind: usize, vec_out: &mut [i32]) {
for x in vec_out.iter_mut().take(dim_in) {
*x = 0;
}
let mut leading_sign = if ls_ind == 0 { 1 } else { -1 };
let mut k_max_local = k_val_in;
let mut ind = mpvq_ind;
let mut k_acc;
for pos in 0..dim_in {
let h_row_ptr = &MPVQ_OFFSETS[dim_in - 1 - pos];
let k_delta;
if ind != 0 {
k_acc = k_max_local;
let ul_tmp_offset = h_row_ptr[k_acc];
let mut wrap_flag = ind < ul_tmp_offset;
let mut ul_diff = 0;
if !wrap_flag {
ul_diff = ind - ul_tmp_offset;
}
while wrap_flag {
k_acc -= 1;
wrap_flag = ind < h_row_ptr[k_acc];
if !wrap_flag {
ul_diff = ind - h_row_ptr[k_acc];
}
}
ind = ul_diff;
k_delta = k_max_local - k_acc;
} else {
vec_out[pos] = mind2vec_one(k_max_local, leading_sign);
break;
}
k_max_local = setval_update_sign(k_delta, k_max_local, &mut leading_sign, &mut ind, &mut vec_out[pos])
}
}
fn setval_update_sign(
k_delta: usize,
k_max_local_in: usize,
leading_sign: &mut i32,
ind_in: &mut usize,
vec_out_item: &mut i32,
) -> usize {
let mut k_max_local_out = k_max_local_in;
if k_delta != 0 {
*vec_out_item = mind2vec_one(k_delta, *leading_sign);
*leading_sign = get_lead_sign(ind_in);
k_max_local_out -= k_delta;
}
k_max_local_out
}
fn get_lead_sign(ind_in: &mut usize) -> i32 {
let mut leading_sign = 1;
if *ind_in & 0x1 != 0 {
leading_sign = -1;
}
*ind_in >>= 1;
leading_sign
}
fn mind2vec_one(k_val_in: usize, leading_sign: i32) -> i32 {
if leading_sign < 0 {
-(k_val_in as i32)
} else {
k_val_in as i32
}
}
#[cfg(test)]
mod tests {
extern crate std;
use super::*;
use crate::common::config::FrameDuration;
#[test]
fn spectral_noise_shaping_decode() {
let config = Lc3Config {
fs_ind: 4,
n_ms: FrameDuration::TenMs,
nb: 64,
fs: 0,
ne: 0,
nf: 0,
z: 0,
};
let sns = SnsVq {
ind_lf: 13,
ind_hf: 4,
ls_inda: 1,
ls_indb: 0,
idx_a: 1718290,
idx_b: 2,
submode_lsb: 0,
submode_msb: 0,
g_ind: 0,
};
#[rustfmt::skip]
let mut spec_lines = [
-568.56555, 1972.808, 3987.5906, 2461.2402, -263.29547, -2949.6724, -2217.0242, 141.18742, 1270.6868,
-385.4035, 1667.538, 568.56555, -538.0386, -1924.9376, -330.6227, 358.01404, -103.25958, 640.72064,
-380.6663, -565.7268, 1425.4789, -1620.2815, -2171.777, 65.41626, -630.4777, -241.61359, 70.17501,
648.6986, 913.1724, 377.05695, 1248.8955, 447.55414, 122.224335, 387.0873, 670.9608, 202.11314, 470.52597,
9.777176, 250.14848, -869.4124, 705.27844, 764.594, -196.6836, 162.10555, 32.383907, 212.68384, -200.68219,
-385.05658, 74.749176, 244.4491, 75.39133, 71.7427, -370.58853, -284.1499, -221.86317, -378.81683,
-78.224205, 120.7565, 49.39573, -431.70422, -639.2284, -863.50916, -762.39795, -557.4247, -210.2326,
207.37712, 667.06, 268.28708, 266.76526, 180.27934, 266.1345, 18.510933, -71.35217, -18.678001, 61.719135,
78.072945, 41.07525, 31.682747, 65.34431, 39.83117, 50.713173, 265.0006, 87.029144, -105.01486, -92.9501,
109.07149, 213.51758, 237.69977, 244.04578, 169.18098, -60.653255, -202.20692, -5.709038, 418.32336,
390.42206, -52.63867, -409.54736, -371.99884, -123.08209, 15.460239, -13.179712, 10.579021, 10.312677,
49.179047, -104.04299, -108.42853, 45.232265, 106.2404, -18.412956, -252.0934, -189.36148, 85.68147,
260.1948, 66.20917, -89.14935, 37.372047, 196.89316, 4.2800827, -186.45068, -10.664055, 251.7307,
283.97842, 87.595795, 65.05641, 91.597, -64.72161, -260.67474, -120.33, 275.7829, 360.36444, 76.64067,
-85.21214, -19.708641, 59.083878, 71.03325, 37.62242, 41.2656, 33.881153, 25.94694, -3.6607666, -15.336594,
-46.333282, -68.63583, 51.637062, 181.11745, 75.242294, -25.19682, -26.834858, 23.40418, 38.82212,
-11.055281, -14.305193, -22.998611, 129.22333, 87.56438, -91.969635, -113.919846, -21.006641, 165.25201,
93.82325, 70.90962, 56.982315, 15.586489, -109.50122, -156.43475, -32.77449, 127.61873, 86.515625,
-71.82623, -60.272907, 74.61493, 174.22997, 35.206467, -130.87024, -37.255043, 125.10912, 72.04756,
28.948765, 1.5288572, 89.77242, 28.662163, -122.471275, -64.80139, 35.938797, 56.74036, 19.603413,
-92.18097, -95.45599, 4.2908516, 4.6752024, 39.53695, 19.507534, -69.66742, -24.112461, -4.6465445,
-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,
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,
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,
-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,
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,
0.0, -61.05402, 0.0, 0.0, -61.05402, 61.05402, 61.05402, 61.05402, -122.10804, -61.05402, -61.05402, 0.0,
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,
-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,
-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,
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,
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,
-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,
0.0, 0.0, -19.079382, -19.079382, -19.079382, -19.079382, 19.079382, -19.079382, 19.079382, 0.0, 0.0, 0.0,
-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,
-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,
];
decode(&config, &sns, &mut spec_lines);
#[rustfmt::skip]
let spec_lines_expected = [
-2268.137, 7869.9785, 15884.984, 9776.979, -1042.96, -11651.202, -8543.342, 519.08997, 4455.2827, -1288.14,
5093.401, 1520.3356, -1260.0343, -3961.906, -641.0432, 703.6705, -205.72899, 1298.229, -831.222,
-1235.3197, 3581.536, -4070.9802, -6290.9507, 189.4902, -2103.3403, -806.0485, 248.62497, 2298.2922,
3174.625, 1310.8307, 4260.057, 1526.6339, 409.04425, 1295.4526, 2116.6775, 637.6055, 1343.3187, 27.913153,
714.1564, -2245.3208, 1821.4329, 1974.6196, -459.77234, 378.94186, 75.70141, 449.14334, -423.7984,
-813.15814, 141.91173, 464.08798, 143.13086, 122.60409, -633.3142, -485.5956, -379.15125, -581.63947,
-120.10629, 185.41084, 75.84274, -589.5617, -872.96936, -1179.2609, -1041.1772, -671.12726, -253.11552,
249.67758, 803.12585, 285.46893, 283.84964, 191.82494, 283.1785, 17.406265, -67.094124, -17.563364,
58.03595, 73.413826, 35.959316, 27.736652, 57.205654, 34.870186, 44.39683, 227.21794, 74.620895, -90.04228,
-79.69767, 93.52053, 179.29234, 199.59831, 204.92711, 142.06258, -50.931004, -169.79471, -4.6945424,
343.98734, 321.0441, -43.284782, -336.7708, -305.89468, -90.73599, 11.397272, -9.71607, 7.7988434,
7.6024947, 36.25474, -76.700386, -65.53449, 27.338501, 64.21198, -11.1288395, -152.36592, -114.450584,
51.78611, 129.27042, 32.89415, -44.291332, 18.567244, 97.82079, 2.126438, -92.632744, -4.3691993,
103.137276, 116.34959, 35.889114, 26.654442, 37.52846, -26.51727, -106.801765, -40.06586, 91.82647,
119.98929, 25.518776, -28.37279, -6.5623174, 19.672953, 23.651693, 10.104294, 11.0827465, 9.099498,
6.9685974, -0.98317605, -4.1189656, -12.44378, -18.4336, 13.868221, 39.34896, 16.346886, -5.4741755,
-5.83005, 5.084713, 8.434362, -2.4018328, -3.1078978, -4.9966, 28.074621, 15.33394, -16.105371, -19.94921,
-3.678603, 28.938301, 16.42997, 12.417422, 9.978525, 2.7294464, -19.175436, -23.296207, -4.8807654,
19.004936, 12.883876, -10.696337, -8.97582, 11.111629, 25.946264, 5.242934, -19.48915, -5.5480075,
16.77535, 9.660551, 3.8816166, 0.20499796, 12.037202, 3.8431873, -16.421652, -8.688943, 4.8188806,
7.608073, 2.6285381, -11.124037, -11.519255, 0.51780313, 0.564185, 4.7711635, 2.3540926, -8.40719,
-2.909797, -0.5607267, -2.4012764, -0.27713123, 6.1875944, 4.4743004, 7.0638013, 0.0, 0.0, 0.0, 6.6421857,
0.0, 6.6421857, 0.0, 6.6421857, 0.0, 0.0, 0.0, -6.4278693, 6.4278693, 12.855739, -6.4278693, 0.0,
12.855739, 0.0, 6.4278693, -6.4278693, 0.0, 0.0, -6.4278693, 0.0, 0.0, 13.372511, -6.6862555, -6.6862555,
0.0, 0.0, 0.0, 0.0, -6.6862555, 6.6862555, -6.6862555, 6.6862555, 6.6862555, 6.6862555, 0.0, 0.0,
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,
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,
7.2283335, 7.2283335, 7.2283335, -14.456667, -7.2283335, -7.2283335, 0.0, 8.2442, -8.2442, 0.0, 0.0,
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,
10.337095, 0.0, -10.337095, -10.337095, 0.0, -10.337095, 0.0, -10.337095, -10.337095, 0.0, 10.337095, 0.0,
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,
-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,
-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,
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,
-6.3501425, -6.3501425, -6.3501425, -6.3501425, 6.3501425, -6.3501425, 6.3501425, 0.0, 0.0, 0.0,
-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,
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,
25.512432,
];
assert_eq!(spec_lines, spec_lines_expected);
}
#[test]
fn mpvq_deenum_test1() {
let mut vec_out = [0; 16];
mpvq_deenum(10, 10, 1, 1718290, &mut vec_out);
assert_eq!(vec_out, [0, -2, 0, 0, 1, 1, 3, -2, 1, 0, 0, 0, 0, 0, 0, 0]);
}
#[test]
fn mpvq_deenum_test2() {
let mut vec_out = [0; 16];
mpvq_deenum(6, 1, 0, 2, &mut vec_out);
assert_eq!(vec_out, [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
}
}