Skip to content

Commit 78fc252

Browse files
committed
refactor: make silk_NLSF2A safe
1 parent 26ec39e commit 78fc252

File tree

6 files changed

+95
-92
lines changed

6 files changed

+95
-92
lines changed

src/silk/CNG.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,7 @@ pub unsafe fn silk_CNG(
112112
if psDec.lossCnt != 0 {
113113
let vla = (length + 16) as usize;
114114
let mut CNG_sig_Q14: Vec<i32> = ::std::vec::from_elem(0, vla);
115-
gain_Q16 = (psDec.sPLC.randScale_Q14 as i64
116-
* psDec.sPLC.prevGain_Q16[1 as usize] as i64
115+
gain_Q16 = (psDec.sPLC.randScale_Q14 as i64 * psDec.sPLC.prevGain_Q16[1 as usize] as i64
117116
>> 16) as i32;
118117
if gain_Q16 >= (1) << 21 || (*psCNG).CNG_smth_Gain_Q16 > (1) << 23 {
119118
gain_Q16 = (gain_Q16 >> 16) * (gain_Q16 >> 16);
@@ -135,10 +134,8 @@ pub unsafe fn silk_CNG(
135134
&mut (*psCNG).rand_seed,
136135
);
137136
silk_NLSF2A(
138-
A_Q12.as_mut_ptr(),
139-
((*psCNG).CNG_smth_NLSF_Q15).as_mut_ptr(),
140-
psDec.LPC_order,
141-
psDec.arch,
137+
&mut A_Q12[..psDec.LPC_order as usize],
138+
&(*psCNG).CNG_smth_NLSF_Q15[..psDec.LPC_order as usize],
142139
);
143140
memcpy(
144141
CNG_sig_Q14.as_mut_ptr() as *mut core::ffi::c_void,

src/silk/NLSF2A.rs

Lines changed: 76 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use crate::silk::bwexpander_32::silk_bwexpander_32;
2-
use crate::silk::define::MAX_LPC_STABILIZE_ITERATIONS;
2+
use crate::silk::define::{LSF_COS_TAB_SZ_FIX, MAX_LPC_STABILIZE_ITERATIONS};
33
use crate::silk::table_LSF_cos::silk_LSFCosTab_FIX_Q12;
44
use crate::silk::LPC_fit::silk_LPC_fit;
55
use crate::silk::LPC_inv_pred_gain::silk_LPC_inverse_pred_gain_c;
6-
use crate::silk::SigProc_FIX::{silk_RSHIFT_ROUND64, SILK_MAX_ORDER_LPC};
6+
use crate::silk::SigProc_FIX::{silk_RSHIFT_ROUND, silk_RSHIFT_ROUND64, SILK_MAX_ORDER_LPC};
7+
use ndarray::azip;
78

89
pub const QA: i32 = 16;
910

@@ -36,74 +37,86 @@ fn silk_NLSF2A_find_poly(out: &mut [i32], cLSF: &[i32]) {
3637
}
3738

3839
/// compute whitening filter coefficients from normalized line spectral frequencies
39-
pub unsafe fn silk_NLSF2A(a_Q12: *mut i16, NLSF: *const i16, d: i32, _arch: i32) {
40+
///
41+
/// ```text
42+
/// a_Q12 O monic whitening filter coefficients in Q12, [ d ]
43+
/// NLSF I normalized line spectral frequencies in Q15, [ d ]
44+
/// d I filter order (should be even)
45+
/// arch I Run-time architecture
46+
/// ```
47+
pub fn silk_NLSF2A(a_Q12: &mut [i16], NLSF: &[i16]) {
48+
let d = a_Q12.len();
49+
50+
/* This ordering was found to maximize quality. It improves the numerical accuracy of
51+
silk_NLSF2A_find_poly() compared to "standard" ordering. */
4052
static ordering16: [u8; 16] = [0, 15, 8, 7, 4, 11, 12, 3, 2, 13, 10, 5, 6, 9, 14, 1];
4153
static ordering10: [u8; 10] = [0, 9, 6, 3, 4, 5, 8, 1, 2, 7];
42-
let mut ordering: *const u8 = 0 as *const u8;
43-
let mut k: i32 = 0;
44-
let mut i: i32 = 0;
45-
let mut dd: i32 = 0;
54+
55+
assert!(d == 10 || d == 16);
56+
57+
/* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */
58+
let ordering = if d == 16 {
59+
ordering16.as_slice()
60+
} else {
61+
ordering10.as_slice()
62+
};
63+
4664
let mut cos_LSF_QA: [i32; SILK_MAX_ORDER_LPC] = [0; 24];
65+
let cos_LSF_QA = &mut cos_LSF_QA[..d + 1];
66+
azip!((&ordering in ordering, &NLSF in NLSF) {
67+
debug_assert!(NLSF >= 0);
68+
69+
/* f_int on a scale 0-127 (rounded down) */
70+
let f_int = NLSF as i32 >> (15 - 7);
71+
72+
/* f_frac, range: 0..255 */
73+
let f_frac = NLSF as i32 - (f_int << (15 - 7));
74+
75+
debug_assert!(f_int >= 0);
76+
debug_assert!(f_int < LSF_COS_TAB_SZ_FIX);
77+
78+
/* Read start and end value from table */
79+
let cos_val = silk_LSFCosTab_FIX_Q12[f_int as usize] as i32; /* Q12 */
80+
let delta = silk_LSFCosTab_FIX_Q12[(f_int + 1) as usize] as i32 - cos_val; /* Q12, with a range of 0..200 */
81+
82+
cos_LSF_QA[ordering as usize] =
83+
silk_RSHIFT_ROUND((cos_val << 8) + delta * f_frac, 20 - QA); /* QA */
84+
});
85+
86+
let dd = d / 2;
87+
88+
/* generate even and odd polynomials using convolution */
4789
let mut P: [i32; SILK_MAX_ORDER_LPC / 2 + 1] = [0; 13];
4890
let mut Q: [i32; SILK_MAX_ORDER_LPC / 2 + 1] = [0; 13];
49-
let mut Ptmp: i32 = 0;
50-
let mut Qtmp: i32 = 0;
51-
let mut f_int: i32 = 0;
52-
let mut f_frac: i32 = 0;
53-
let mut cos_val: i32 = 0;
54-
let mut delta: i32 = 0;
91+
let P = &mut P[..dd + 1];
92+
let Q = &mut Q[..dd + 1];
93+
silk_NLSF2A_find_poly(P, &cos_LSF_QA[..d]);
94+
silk_NLSF2A_find_poly(Q, &cos_LSF_QA[1..][..d]);
95+
96+
/* convert even and odd polynomials to opus_int32 Q12 filter coefs */
5597
let mut a32_QA1: [i32; SILK_MAX_ORDER_LPC] = [0; 24];
56-
assert!(d == 10 || d == 16);
57-
ordering = if d == 16 {
58-
ordering16.as_ptr()
59-
} else {
60-
ordering10.as_ptr()
61-
};
62-
k = 0;
63-
while k < d {
64-
f_int = *NLSF.offset(k as isize) as i32 >> 15 - 7;
65-
f_frac = *NLSF.offset(k as isize) as i32 - ((f_int as u32) << 15 - 7) as i32;
66-
cos_val = silk_LSFCosTab_FIX_Q12[f_int as usize] as i32;
67-
delta = silk_LSFCosTab_FIX_Q12[(f_int + 1) as usize] as i32 - cos_val;
68-
cos_LSF_QA[*ordering.offset(k as isize) as usize] = if 20 - 16 == 1 {
69-
(((cos_val as u32) << 8) as i32 + delta * f_frac >> 1)
70-
+ (((cos_val as u32) << 8) as i32 + delta * f_frac & 1)
71-
} else {
72-
(((cos_val as u32) << 8) as i32 + delta * f_frac >> 20 - 16 - 1) + 1 >> 1
73-
};
74-
k += 1;
75-
}
76-
dd = d >> 1;
77-
silk_NLSF2A_find_poly(&mut P[..dd as usize + 1], &cos_LSF_QA[..d as usize]);
78-
silk_NLSF2A_find_poly(&mut Q[..dd as usize + 1], &cos_LSF_QA[1..][..d as usize]);
79-
k = 0;
80-
while k < dd {
81-
Ptmp = P[(k + 1) as usize] + P[k as usize];
82-
Qtmp = Q[(k + 1) as usize] - Q[k as usize];
83-
a32_QA1[k as usize] = -Qtmp - Ptmp;
84-
a32_QA1[(d - k - 1) as usize] = Qtmp - Ptmp;
85-
k += 1;
98+
let a32_QA1 = &mut a32_QA1[..d];
99+
for k in 0..dd {
100+
let Ptmp = P[k + 1] + P[k];
101+
let Qtmp = Q[k + 1] - Q[k];
102+
/* the Ptmp and Qtmp values at this stage need to fit in int32 */
103+
a32_QA1[k] = -Qtmp - Ptmp; /* QA+1 */
104+
a32_QA1[d - k - 1] = Qtmp - Ptmp; /* QA+1 */
86105
}
87-
silk_LPC_fit(
88-
std::slice::from_raw_parts_mut(a_Q12, d as usize),
89-
&mut a32_QA1[..d as usize],
90-
12,
91-
QA + 1,
92-
);
93-
i = 0;
94-
while silk_LPC_inverse_pred_gain_c(std::slice::from_raw_parts(a_Q12, d as usize)) == 0
95-
&& i < MAX_LPC_STABILIZE_ITERATIONS
96-
{
97-
silk_bwexpander_32(&mut a32_QA1[..d as usize], 65536 - ((2) << i) as i32);
98-
k = 0;
99-
while k < d {
100-
*a_Q12.offset(k as isize) = (if 16 + 1 - 12 == 1 {
101-
(a32_QA1[k as usize] >> 1) + (a32_QA1[k as usize] & 1)
102-
} else {
103-
(a32_QA1[k as usize] >> 16 + 1 - 12 - 1) + 1 >> 1
104-
}) as i16;
105-
k += 1;
106-
}
106+
107+
/* Convert int32 coefficients to Q12 int16 coefs */
108+
silk_LPC_fit(a_Q12, &mut a32_QA1[..d], 12, QA + 1);
109+
110+
let mut i = 0;
111+
while silk_LPC_inverse_pred_gain_c(a_Q12) == 0 && i < MAX_LPC_STABILIZE_ITERATIONS {
112+
/* Prediction coefficients are (too close to) unstable; apply bandwidth expansion */
113+
/* on the unscaled coefficients, convert to Q12 and measure again */
114+
silk_bwexpander_32(a32_QA1, 65536 - (2 << i));
115+
116+
azip!((a_Q12 in &mut a_Q12[..], &a32_QA1 in &a32_QA1[..]) {
117+
*a_Q12 = silk_RSHIFT_ROUND(a32_QA1, QA + 1 - 12) as i16; /* QA+1 -> Q12 */
118+
});
119+
107120
i += 1;
108121
}
109122
}

src/silk/decode_parameters.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,8 @@ pub unsafe fn silk_decode_parameters(
3232
psDec.psNLSF_CB,
3333
);
3434
silk_NLSF2A(
35-
((*psDecCtrl).PredCoef_Q12[1 as usize]).as_mut_ptr(),
36-
pNLSF_Q15.as_mut_ptr(),
37-
psDec.LPC_order,
38-
psDec.arch,
35+
&mut (*psDecCtrl).PredCoef_Q12[1][..psDec.LPC_order as usize],
36+
&pNLSF_Q15[..psDec.LPC_order as usize],
3937
);
4038
if psDec.first_frame_after_reset == 1 {
4139
psDec.indices.NLSFInterpCoef_Q2 = 4;
@@ -50,10 +48,8 @@ pub unsafe fn silk_decode_parameters(
5048
i += 1;
5149
}
5250
silk_NLSF2A(
53-
((*psDecCtrl).PredCoef_Q12[0 as usize]).as_mut_ptr(),
54-
pNLSF0_Q15.as_mut_ptr(),
55-
psDec.LPC_order,
56-
psDec.arch,
51+
&mut (*psDecCtrl).PredCoef_Q12[0][..psDec.LPC_order as usize],
52+
&pNLSF0_Q15[..psDec.LPC_order as usize],
5753
);
5854
} else {
5955
memcpy(

src/silk/float/find_LPC_FLP.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ pub unsafe fn silk_find_LPC_FLP(
6969
a_tmp.as_mut_ptr(),
7070
NLSF0_Q15.as_mut_ptr(),
7171
psEncC.predictLPCOrder,
72-
psEncC.arch,
7372
);
7473
silk_LPC_analysis_filter_FLP(
7574
LPC_res.as_mut_ptr(),

src/silk/float/wrappers_FLP.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@ pub unsafe fn silk_A2NLSF_FLP(NLSF_Q15: *mut i16, pAR: *const f32, LPC_order: i3
2121
}
2222
silk_A2NLSF(NLSF_Q15, a_fix_Q16.as_mut_ptr(), LPC_order);
2323
}
24-
pub unsafe fn silk_NLSF2A_FLP(pAR: *mut f32, NLSF_Q15: *const i16, LPC_order: i32, arch: i32) {
24+
pub unsafe fn silk_NLSF2A_FLP(pAR: *mut f32, NLSF_Q15: *const i16, LPC_order: i32) {
2525
let mut i: i32 = 0;
2626
let mut a_fix_Q12: [i16; 16] = [0; 16];
27-
silk_NLSF2A(a_fix_Q12.as_mut_ptr(), NLSF_Q15, LPC_order, arch);
27+
silk_NLSF2A(
28+
&mut a_fix_Q12[..LPC_order as usize],
29+
std::slice::from_raw_parts(NLSF_Q15, LPC_order as usize),
30+
);
2831
i = 0;
2932
while i < LPC_order {
3033
*pAR.offset(i as isize) = a_fix_Q12[i as usize] as f32 * (1.0f32 / 4096.0f32);

src/silk/process_NLSFs.rs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ pub unsafe fn silk_process_NLSFs(
1919
let mut pNLSFW_QW: [i16; 16] = [0; 16];
2020
let mut pNLSFW0_temp_QW: [i16; 16] = [0; 16];
2121
assert!(
22-
psEncC.useInterpolatedNLSFs == 1
23-
|| psEncC.indices.NLSFInterpCoef_Q2 as i32 == (1) << 2
22+
psEncC.useInterpolatedNLSFs == 1 || psEncC.indices.NLSFInterpCoef_Q2 as i32 == (1) << 2
2423
);
2524
NLSF_mu_Q20 = ((0.003f64 * ((1) << 20) as f64 + 0.5f64) as i32 as i64
2625
+ ((-0.001f64 * ((1) << 28) as f64 + 0.5f64) as i32 as i64
@@ -34,8 +33,8 @@ pub unsafe fn silk_process_NLSFs(
3433
&mut pNLSFW_QW[..psEncC.predictLPCOrder as usize],
3534
std::slice::from_raw_parts(pNLSF_Q15, psEncC.predictLPCOrder as usize),
3635
);
37-
doInterpolate = (psEncC.useInterpolatedNLSFs == 1
38-
&& (psEncC.indices.NLSFInterpCoef_Q2 as i32) < 4) as i32;
36+
doInterpolate =
37+
(psEncC.useInterpolatedNLSFs == 1 && (psEncC.indices.NLSFInterpCoef_Q2 as i32) < 4) as i32;
3938
if doInterpolate != 0 {
4039
silk_interpolate(
4140
&mut pNLSF0_temp_Q15[..psEncC.predictLPCOrder as usize],
@@ -68,10 +67,8 @@ pub unsafe fn silk_process_NLSFs(
6867
psEncC.indices.signalType as i32,
6968
);
7069
silk_NLSF2A(
71-
(*PredCoef_Q12.offset(1 as isize)).as_mut_ptr(),
72-
pNLSF_Q15 as *const i16,
73-
psEncC.predictLPCOrder,
74-
psEncC.arch,
70+
&mut (*PredCoef_Q12.offset(1))[..psEncC.predictLPCOrder as usize],
71+
std::slice::from_raw_parts(pNLSF_Q15, psEncC.predictLPCOrder as usize),
7572
);
7673
if doInterpolate != 0 {
7774
silk_interpolate(
@@ -81,10 +78,8 @@ pub unsafe fn silk_process_NLSFs(
8178
psEncC.indices.NLSFInterpCoef_Q2 as i32,
8279
);
8380
silk_NLSF2A(
84-
(*PredCoef_Q12.offset(0 as isize)).as_mut_ptr(),
85-
pNLSF0_temp_Q15.as_mut_ptr(),
86-
psEncC.predictLPCOrder,
87-
psEncC.arch,
81+
&mut (*PredCoef_Q12)[..psEncC.predictLPCOrder as usize],
82+
&pNLSF0_temp_Q15[..psEncC.predictLPCOrder as usize],
8883
);
8984
} else {
9085
assert!(psEncC.predictLPCOrder <= 16);

0 commit comments

Comments
 (0)