lc3_codec/decoder/
temporal_noise_shaping.rs

1use crate::{
2    common::{complex::Scaler, config::FrameDuration},
3    tables::temporal_noise_shaping_tables::{MAXLAG, TNS_NUMFILTERS_MAX},
4};
5use core::f64::consts::PI;
6use heapless::Vec;
7#[allow(unused_imports)]
8use num_traits::real::Real;
9
10use super::side_info::Bandwidth;
11
12// checked against spec
13
14/// Apply temportal noise shaping for decoded spectral lines
15///
16/// # Arguments
17///
18/// * `duration` - Frame Duration in milliseconds (N_MS)
19/// * `bandwidth` - Bandwidth cutoff index (P_BW)
20/// * `num_tns_filters` - Number of TNS filters
21/// * `reflect_coef_order` - Order of quantized reflection coefficients
22/// * `reflect_coef_ints` - Integer reflection coefficients
23/// * `spec_lines` - Spectral lines of the frame to mutate (input and output)
24pub fn apply_temporal_noise_shaping(
25    duration: FrameDuration,
26    bandwidth: Bandwidth,
27    num_tns_filters: usize,
28    reflect_coef_order: &[usize],
29    reflect_coef_ints: &[usize],
30    spec_lines: &mut [Scaler],
31) {
32    // NOTE: We should probably check the range of the values in rc_order and rc_i
33    // because out of range values will cause a panic
34
35    let mut bands = split_into_frequency_bands(duration, bandwidth, spec_lines);
36
37    // quantized reflection coefficients will have no more than TNS_NUMFILTERS_MAX * MAXLAG entries
38    let mut rc_quant: [Scaler; TNS_NUMFILTERS_MAX * MAXLAG] = [0.0; TNS_NUMFILTERS_MAX * MAXLAG];
39    const QUANTIZER_STEPSIZE: Scaler = (PI / 17.0) as Scaler;
40
41    // 0.489 ms - precompute 8 entries because using sin is very expensive in loops later on
42    for (rc_q_item, rc_i_item) in rc_quant.iter_mut().zip(reflect_coef_ints) {
43        if *rc_i_item != 0 {
44            *rc_q_item = (QUANTIZER_STEPSIZE * (*rc_i_item as i32 - 8) as Scaler).sin()
45        }
46    }
47
48    let mut lattice_state = [0.0; 8];
49
50    // loop through each tns filter
51    for (f, (band, order)) in bands
52        .iter_mut()
53        .zip(reflect_coef_order[..num_tns_filters].iter())
54        .enumerate()
55    {
56        if *order > 0 {
57            let offset = f * 8;
58
59            // mutate each spectral line in the band associated with this filter
60            for spectral_line in band.iter_mut() {
61                let k = *order - 1;
62                let mut t = *spectral_line - rc_quant[k + offset] * lattice_state[k];
63                for k in (0..*order - 1).rev() {
64                    let rc = rc_quant[k + offset];
65                    t -= rc * lattice_state[k];
66                    lattice_state[k + 1] = rc * t + lattice_state[k];
67                }
68
69                *spectral_line = t;
70                lattice_state[0] = t;
71            }
72        }
73    }
74}
75
76/// Split input spectral lines into slices according to frequency bands associated with the frame duration and bandwidth
77///
78/// # Arguments
79///
80/// * `duration` - Frame Duration in milliseconds
81/// * `bandwidth` - Bandwidth cutoff index
82/// * `spec_lines` - Spectral lines of the frame to split into bands (slices)
83fn split_into_frequency_bands(
84    duration: FrameDuration,
85    bandwidth: Bandwidth,
86    spec_lines: &mut [Scaler],
87) -> Vec<&mut [Scaler], 2> {
88    let mut bands: Vec<&mut [Scaler], 2> = Vec::new();
89    match duration {
90        FrameDuration::TenMs => match bandwidth {
91            Bandwidth::NarrowBand => {
92                bands.push(&mut spec_lines[12..80]).ok();
93            }
94            Bandwidth::WideBand => {
95                bands.push(&mut spec_lines[12..160]).ok();
96            }
97            Bandwidth::SemiSuperWideBand => {
98                bands.push(&mut spec_lines[12..240]).ok();
99            }
100            Bandwidth::SuperWideBand => {
101                // 12..160 and 160..320
102                let (left, right) = spec_lines.split_at_mut(160);
103                bands.push(&mut left[12..]).ok();
104                bands.push(&mut right[..160]).ok();
105            }
106            Bandwidth::FullBand => {
107                // 12..200 and 200..400
108                let (left, right) = spec_lines.split_at_mut(200);
109                bands.push(&mut left[12..]).ok();
110                bands.push(&mut right[..200]).ok();
111            }
112        },
113        FrameDuration::SevenPointFiveMs => match bandwidth {
114            Bandwidth::NarrowBand => {
115                bands.push(&mut spec_lines[9..60]).ok();
116            }
117            Bandwidth::WideBand => {
118                bands.push(&mut spec_lines[9..120]).ok();
119            }
120            Bandwidth::SemiSuperWideBand => {
121                bands.push(&mut spec_lines[9..180]).ok();
122            }
123            Bandwidth::SuperWideBand => {
124                // 9..120 and 120..240
125                let (left, right) = spec_lines.split_at_mut(120);
126                bands.push(&mut left[9..]).ok();
127                bands.push(&mut right[..120]).ok();
128            }
129            Bandwidth::FullBand => {
130                // 9..150 and 150..300
131                let (left, right) = spec_lines.split_at_mut(150);
132                bands.push(&mut left[9..]).ok();
133                bands.push(&mut right[..150]).ok();
134            }
135        },
136    };
137    bands
138}
139
140#[cfg(test)]
141mod tests {
142    extern crate std;
143    use super::*;
144    use crate::common::config::FrameDuration;
145
146    #[test]
147    fn decode_test() {
148        let duration = FrameDuration::TenMs;
149        let bandwidth = Bandwidth::FullBand;
150        let num_tns_filters = 2;
151        let reflect_coef_order = [8, 0];
152        let reflect_coef_ints = [6, 10, 7, 8, 7, 9, 7, 7];
153        let mut spec_lines: [f32; 400] = [
154            -568.56555, 1972.808, 3987.5906, 2461.2402, -263.29547, -2949.6724, -2217.0242, 141.18742, 1270.6868,
155            -385.4035, 1667.538, 568.56555, -538.0386, -1606.4839, 538.0386, -263.29547, -49.60639, 751.7276,
156            -476.98453, -141.18742, 1423.3219, -2033.862, -599.0926, 202.24144, -934.8897, -202.24144, 324.3495,
157            1056.9977, -80.1334, 751.7276, 1667.538, -263.29547, 507.51154, 141.18742, 629.61957, -446.45752,
158            507.51154, -385.4035, 202.24144, -1331.7408, 1453.8489, -385.4035, -49.60639, 141.18742, 0.0, 80.1334,
159            -488.43216, 183.16206, -122.10804, 0.0, 0.0, 122.10804, -366.32413, -122.10804, -244.21608, -183.16206,
160            0.0, 61.05402, 0.0, -427.37814, -244.21608, -671.59424, -427.37814, -366.32413, 0.0, 183.16206, 610.5402,
161            122.10804, 549.4862, 183.16206, 427.37814, -122.10804, 122.10804, -122.10804, -61.05402, -61.05402, 0.0,
162            0.0, 0.0, 0.0, 61.05402, 244.21608, -61.05402, -61.05402, -61.05402, 122.10804, 61.05402, 183.16206,
163            183.16206, 61.05402, -122.10804, -122.10804, 61.05402, 305.2701, 122.10804, -122.10804, -305.2701,
164            -244.21608, -122.10804, 0.0, 0.0, 0.0, -61.05402, 61.05402, -61.05402, 61.05402, 61.05402, 61.05402,
165            -61.05402, -183.16206, -61.05402, 61.05402, 183.16206, 0.0, 0.0, 61.05402, 122.10804, -61.05402, -61.05402,
166            61.05402, 122.10804, 122.10804, 61.05402, 122.10804, 0.0, -122.10804, -183.16206, 0.0, 183.16206,
167            122.10804, 0.0, 0.0, 0.0, 0.0, 61.05402, 61.05402, 0.0, -61.05402, 0.0, 0.0, 0.0, -61.05402, -61.05402,
168            61.05402, 122.10804, 0.0, 0.0, 0.0, 19.079382, 0.0, 0.0, 0.0, -61.05402, 122.10804, 0.0, -61.05402,
169            -61.05402, 0.0, 122.10804, 0.0, 122.10804, 0.0, 0.0, -122.10804, -61.05402, 0.0, 61.05402, 0.0, -61.05402,
170            0.0, 61.05402, 122.10804, 0.0, -61.05402, 0.0, 61.05402, 0.0, 61.05402, 0.0, 61.05402, -61.05402,
171            -61.05402, 0.0, 0.0, 0.0, 0.0, -61.05402, -61.05402, 0.0, 0.0, 61.05402, 0.0, -61.05402, 0.0, 0.0, 0.0,
172            0.0, 61.05402, 0.0, 61.05402, 0.0, 0.0, 0.0, 61.05402, 0.0, 61.05402, 0.0, 61.05402, 0.0, 0.0, 0.0,
173            -61.05402, 61.05402, 122.10804, -61.05402, 0.0, 122.10804, 0.0, 61.05402, -61.05402, 0.0, 0.0, -61.05402,
174            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,
175            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,
176            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,
177            0.0, -61.05402, 61.05402, 61.05402, 61.05402, -122.10804, -61.05402, -61.05402, 0.0, 61.05402, -61.05402,
178            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,
179            0.0, 61.05402, 61.05402, 0.0, -61.05402, -61.05402, 0.0, -61.05402, 0.0, -61.05402, -61.05402, 0.0,
180            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,
181            -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,
182            -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,
183            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,
184            -19.079382, -19.079382, -19.079382, 19.079382, -19.079382, 19.079382, 0.0, 0.0, 0.0, -61.05402, -61.05402,
185            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,
186            0.0, 61.05402, 0.0, 0.0, 0.0, 0.0, 0.0, -61.05402, 0.0, 0.0, 61.05402, 61.05402,
187        ];
188
189        apply_temporal_noise_shaping(
190            duration,
191            bandwidth,
192            num_tns_filters,
193            &reflect_coef_order,
194            &reflect_coef_ints,
195            &mut spec_lines,
196        );
197
198        #[rustfmt::skip]
199        let spec_lines_expected: [f32; 400] = [
200            -568.56555, 1972.808, 3987.5906, 2461.2402, -263.29547, -2949.6724, -2217.0242, 141.18742, 1270.6868,
201            -385.4035, 1667.538, 568.56555, -538.0386, -1924.9376, -330.6227, 358.01404, -103.25958, 640.72064,
202            -380.6663, -565.7268, 1425.4789, -1620.2815, -2171.777, 65.41626, -630.4777, -241.61359, 70.17501,
203            648.6986, 913.1724, 377.05695, 1248.8955, 447.55414, 122.224335, 387.0873, 670.9608, 202.11314, 470.52597,
204            9.777176, 250.14848, -869.4124, 705.27844, 764.594, -196.6836, 162.10555, 32.383907, 212.68384, -200.68219,
205            -385.05658, 74.749176, 244.4491, 75.39133, 71.7427, -370.58853, -284.1499, -221.86317, -378.81683,
206            -78.224205, 120.7565, 49.39573, -431.70422, -639.2284, -863.50916, -762.39795, -557.4247, -210.2326,
207            207.37712, 667.06, 268.28708, 266.76526, 180.27934, 266.1345, 18.510933, -71.35217, -18.678001, 61.719135,
208            78.072945, 41.07525, 31.682747, 65.34431, 39.83117, 50.713173, 265.0006, 87.029144, -105.01486, -92.9501,
209            109.07149, 213.51758, 237.69977, 244.04578, 169.18098, -60.653255, -202.20692, -5.709038, 418.32336,
210            390.42206, -52.63867, -409.54736, -371.99884, -123.08209, 15.460239, -13.179712, 10.579021, 10.312677,
211            49.179047, -104.04299, -108.42853, 45.232265, 106.2404, -18.412956, -252.0934, -189.36148, 85.68147,
212            260.1948, 66.20917, -89.14935, 37.372047, 196.89316, 4.2800827, -186.45068, -10.664055, 251.7307,
213            283.97842, 87.595795, 65.05641, 91.597, -64.72161, -260.67474, -120.33, 275.7829, 360.36444, 76.64067,
214            -85.21214, -19.708641, 59.083878, 71.03325, 37.62242, 41.2656, 33.881153, 25.94694, -3.6607666, -15.336594,
215            -46.333282, -68.63583, 51.637062, 181.11745, 75.242294, -25.19682, -26.834858, 23.40418, 38.82212,
216            -11.055281, -14.305193, -22.998611, 129.22333, 87.56438, -91.969635, -113.919846, -21.006641, 165.25201,
217            93.82325, 70.90962, 56.982315, 15.586489, -109.50122, -156.43475, -32.77449, 127.61873, 86.515625,
218            -71.82623, -60.272907, 74.61493, 174.22997, 35.206467, -130.87024, -37.255043, 125.10912, 72.04756,
219            28.948765, 1.5288572, 89.77242, 28.662163, -122.471275, -64.80139, 35.938797, 56.74036, 19.603413,
220            -92.18097, -95.45599, 4.2908516, 4.6752024, 39.53695, 19.507534, -69.66742, -24.112461, -4.6465445,
221            -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,
222            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,
223            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,
224            -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,
225            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,
226            0.0, -61.05402, 0.0, 0.0, -61.05402, 61.05402, 61.05402, 61.05402, -122.10804, -61.05402, -61.05402, 0.0,
227            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,
228            -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,
229            -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,
230            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,
231            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,
232            -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,
233            0.0, 0.0, -19.079382, -19.079382, -19.079382, -19.079382, 19.079382, -19.079382, 19.079382, 0.0, 0.0, 0.0,
234            -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,
235            -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,
236        ];
237
238        assert_eq![spec_lines, spec_lines_expected];
239    }
240}