Skip to content

Commit 4a794d8

Browse files
committed
refactor: make silk_LPC_fit safe
1 parent a65e74f commit 4a794d8

File tree

3 files changed

+78
-92
lines changed

3 files changed

+78
-92
lines changed

src/silk/LPC_fit.rs

Lines changed: 39 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,59 @@
11
use crate::silk::bwexpander_32::silk_bwexpander_32;
2+
use crate::silk::SigProc_FIX::{silk_RSHIFT_ROUND, silk_SAT16, SILK_FIX_CONST};
3+
use ndarray::azip;
24

3-
pub mod typedef_h {
4-
pub const silk_int16_MIN: i32 = i16::MIN as i32;
5-
pub const silk_int16_MAX: i32 = i16::MAX as i32;
6-
}
7-
8-
pub use self::typedef_h::{silk_int16_MAX, silk_int16_MIN};
5+
/// Convert int32 coefficients to int16 coefs and make sure there's no wrap-around
6+
///
7+
/// ```text
8+
/// a_QOUT O Output signal
9+
/// a_QIN I/O Input signal
10+
/// QOUT I Input Q domain
11+
/// QIN I Input Q domain
12+
/// d I Filter order
13+
/// ```
14+
pub fn silk_LPC_fit(a_QOUT: &mut [i16], a_QIN: &mut [i32], QOUT: i32, QIN: i32) {
15+
let d = a_QOUT.len();
16+
assert_eq!(a_QIN.len(), d);
917

10-
pub unsafe fn silk_LPC_fit(a_QOUT: *mut i16, a_QIN: *mut i32, QOUT: i32, QIN: i32, d: i32) {
11-
let mut i: i32 = 0;
12-
let mut k: i32 = 0;
13-
let mut idx: i32 = 0;
14-
let mut maxabs: i32 = 0;
15-
let mut absval: i32 = 0;
16-
let mut chirp_Q16: i32 = 0;
17-
i = 0;
18+
/* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */
19+
let mut i = 0;
1820
while i < 10 {
19-
maxabs = 0;
20-
k = 0;
21+
/* Find maximum absolute value and its index */
22+
let mut maxabs = 0;
23+
let mut idx = 0;
24+
let mut k = 0;
2125
while k < d {
22-
absval = if *a_QIN.offset(k as isize) > 0 {
23-
*a_QIN.offset(k as isize)
24-
} else {
25-
-*a_QIN.offset(k as isize)
26-
};
26+
let absval = a_QIN[k].abs();
2727
if absval > maxabs {
2828
maxabs = absval;
2929
idx = k;
3030
}
3131
k += 1;
3232
}
33-
maxabs = if QIN - QOUT == 1 {
34-
(maxabs >> 1) + (maxabs & 1)
33+
maxabs = silk_RSHIFT_ROUND(maxabs, QIN - QOUT);
34+
35+
if maxabs > i16::MAX as i32 {
36+
/* Reduce magnitude of prediction coefficients */
37+
maxabs = std::cmp::min(maxabs, 163838); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
38+
let chirp_Q16 = SILK_FIX_CONST(0.999f64, 16)
39+
- ((maxabs - i16::MAX as i32) << 14) / ((maxabs * (idx as i32 + 1)) >> 2);
40+
silk_bwexpander_32(a_QIN, chirp_Q16);
3541
} else {
36-
(maxabs >> QIN - QOUT - 1) + 1 >> 1
37-
};
38-
if !(maxabs > silk_int16_MAX) {
3942
break;
4043
}
41-
maxabs = if maxabs < 163838 { maxabs } else { 163838 };
42-
chirp_Q16 = (0.999f64 * ((1) << 16) as f64 + 0.5f64) as i32
43-
- (((maxabs - 0x7fff) as u32) << 14) as i32 / (maxabs * (idx + 1) >> 2);
44-
silk_bwexpander_32(std::slice::from_raw_parts_mut(a_QIN, d as usize), chirp_Q16);
44+
4545
i += 1;
4646
}
47+
4748
if i == 10 {
48-
k = 0;
49-
while k < d {
50-
*a_QOUT.offset(k as isize) = (if (if QIN - QOUT == 1 {
51-
(*a_QIN.offset(k as isize) >> 1) + (*a_QIN.offset(k as isize) & 1)
52-
} else {
53-
(*a_QIN.offset(k as isize) >> QIN - QOUT - 1) + 1 >> 1
54-
}) > silk_int16_MAX
55-
{
56-
silk_int16_MAX
57-
} else if (if QIN - QOUT == 1 {
58-
(*a_QIN.offset(k as isize) >> 1) + (*a_QIN.offset(k as isize) & 1)
59-
} else {
60-
(*a_QIN.offset(k as isize) >> QIN - QOUT - 1) + 1 >> 1
61-
}) < silk_int16_MIN
62-
{
63-
silk_int16_MIN
64-
} else if QIN - QOUT == 1 {
65-
(*a_QIN.offset(k as isize) >> 1) + (*a_QIN.offset(k as isize) & 1)
66-
} else {
67-
(*a_QIN.offset(k as isize) >> QIN - QOUT - 1) + 1 >> 1
68-
}) as i16;
69-
*a_QIN.offset(k as isize) =
70-
((*a_QOUT.offset(k as isize) as i32 as u32) << QIN - QOUT) as i32;
71-
k += 1;
72-
}
49+
/* Reached the last iteration, clip the coefficients */
50+
azip!((out in a_QOUT, input in a_QIN) {
51+
*out = silk_SAT16(silk_RSHIFT_ROUND(*input, QIN - QOUT)) as i16;
52+
*input = (*out as i32) << (QIN - QOUT);
53+
});
7354
} else {
74-
k = 0;
75-
while k < d {
76-
*a_QOUT.offset(k as isize) = (if QIN - QOUT == 1 {
77-
(*a_QIN.offset(k as isize) >> 1) + (*a_QIN.offset(k as isize) & 1)
78-
} else {
79-
(*a_QIN.offset(k as isize) >> QIN - QOUT - 1) + 1 >> 1
80-
}) as i16;
81-
k += 1;
82-
}
55+
azip!((out in a_QOUT, &mut input in a_QIN) {
56+
*out = silk_RSHIFT_ROUND(input, QIN - QOUT) as i16;
57+
});
8358
};
8459
}

src/silk/NLSF2A.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,12 @@ pub unsafe fn silk_NLSF2A(a_Q12: *mut i16, NLSF: *const i16, d: i32, _arch: i32)
8484
a32_QA1[(d - k - 1) as usize] = Qtmp - Ptmp;
8585
k += 1;
8686
}
87-
silk_LPC_fit(a_Q12, a32_QA1.as_mut_ptr(), 12, QA + 1, d);
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+
);
8893
i = 0;
8994
while silk_LPC_inverse_pred_gain_c(a_Q12, d) == 0 && i < MAX_LPC_STABILIZE_ITERATIONS {
9095
silk_bwexpander_32(&mut a32_QA1[..d as usize], 65536 - ((2) << i) as i32);

src/silk/SigProc_FIX.rs

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
/// max order of the LPC analysis in schur() and k2a()
22
pub const SILK_MAX_ORDER_LPC: usize = 24;
33

4+
#[inline]
5+
pub fn silk_SAT16(a: i32) -> i32 {
6+
if a > i16::MAX as i32 {
7+
i16::MAX as i32
8+
} else if a < i16::MIN as i32 {
9+
i16::MIN as i32
10+
} else {
11+
a
12+
}
13+
}
14+
415
#[inline]
516
pub fn silk_ROR32(a32: i32, rot: i32) -> i32 {
617
let x: u32 = a32 as u32;
@@ -16,17 +27,27 @@ pub fn silk_ROR32(a32: i32, rot: i32) -> i32 {
1627
}
1728

1829
#[inline]
19-
pub fn silk_max_16(a: i16, b: i16) -> i16 {
20-
a.max(b)
30+
pub fn silk_RSHIFT_ROUND(a: i32, shift: i32) -> i32 {
31+
if shift == 1 {
32+
((a) >> 1) + ((a) & 1)
33+
} else {
34+
(((a) >> ((shift) - 1)) + 1) >> 1
35+
}
2136
}
2237

2338
#[inline]
24-
pub fn silk_min_32(a: i32, b: i32) -> i32 {
25-
a.min(b)
39+
pub fn silk_RSHIFT_ROUND64(a: i64, shift: i32) -> i64 {
40+
if shift == 1 {
41+
((a) >> 1) + ((a) & 1)
42+
} else {
43+
(((a) >> ((shift) - 1)) + 1) >> 1
44+
}
2645
}
46+
47+
/// Convert floating-point constants to fixed-point
2748
#[inline]
28-
pub fn silk_max_32(a: i32, b: i32) -> i32 {
29-
a.max(b)
49+
pub fn SILK_FIX_CONST(C: f64, Q: i32) -> i32 {
50+
(C * (1i64 << Q) as f64 + 0.5f64) as i32
3051
}
3152

3253
#[inline]
@@ -39,32 +60,17 @@ pub fn silk_max_int(a: i32, b: i32) -> i32 {
3960
}
4061

4162
#[inline]
42-
pub fn silk_RSHIFT_ROUND(a: i32, shift: i32) -> i32 {
43-
if shift == 1 {
44-
((a) >> 1) + ((a) & 1)
45-
} else {
46-
(((a) >> ((shift) - 1)) + 1) >> 1
47-
}
63+
pub fn silk_max_16(a: i16, b: i16) -> i16 {
64+
a.max(b)
4865
}
4966

5067
#[inline]
51-
pub fn silk_RSHIFT_ROUND64(a: i64, shift: i32) -> i64 {
52-
if shift == 1 {
53-
((a) >> 1) + ((a) & 1)
54-
} else {
55-
(((a) >> ((shift) - 1)) + 1) >> 1
56-
}
68+
pub fn silk_min_32(a: i32, b: i32) -> i32 {
69+
a.min(b)
5770
}
58-
5971
#[inline]
60-
pub fn silk_SAT16(a: i32) -> i32 {
61-
if a > i16::MAX as i32 {
62-
i16::MAX as i32
63-
} else if a < i16::MIN as i32 {
64-
i16::MIN as i32
65-
} else {
66-
a
67-
}
72+
pub fn silk_max_32(a: i32, b: i32) -> i32 {
73+
a.max(b)
6874
}
6975

7076
#[inline]

0 commit comments

Comments
 (0)