lc3_codec/decoder/output_scaling.rs
1use crate::common::complex::Scaler;
2
3// checked against spec
4
5/// Convert from floating point to signed integer by rounding to the
6/// nearest integer value then clipping to max and min of a 16 bit integer
7///
8/// # Arguments
9///
10/// * `x_hat_ltpf` - Input samples from the output of the long term post filter
11/// * `_bits_per_audio_sample_dec` - Bits per audio sample (e.g. 16). Assumed to be 16 and not currently used
12/// * `x_hat_clip` - 16 bit integer output samples rounded and clipped
13pub fn scale_and_round(x_hat_ltpf: &[Scaler], _bits_per_audio_sample_dec: usize, x_hat_clip: &mut [i16]) {
14 // only 16 bit audio is supported so this is always 1 (otherwise we would multiply by the output scale)
15 // let _output_scale = 1 << (-15 + _bits_per_audio_sample_dec as i32 - 1);
16
17 for (to, from) in x_hat_clip.iter_mut().zip(x_hat_ltpf) {
18 let tmp = if *from > 0. {
19 (*from + 0.5) as i32
20 } else {
21 (*from - 0.5) as i32
22 };
23
24 *to = tmp.min(32767).max(-32768) as i16;
25 }
26}
27
28#[cfg(test)]
29mod tests {
30 extern crate std;
31 use super::*;
32
33 #[test]
34 fn scale_and_round_test() {
35 let x_hat_ltpf = [0.0, -0.4, -0.5, -0.6, 0.4, 0.5, 0.6, 32767.6, -32768.6];
36 let mut x_hat_clip = [0; 9];
37
38 scale_and_round(&x_hat_ltpf, 16, &mut x_hat_clip);
39
40 assert_eq!(x_hat_clip, [0, 0, -1, -1, 0, 1, 1, 32767, -32768])
41 }
42}