1use crate::common::{complex::Scaler, config::FrameDuration};
2
3use super::side_info::Bandwidth;
4
5pub fn apply_noise_filling(
19 is_zero_frame: bool,
20 noise_filling_seed: i32,
21 bandwidth: Bandwidth,
22 duration: FrameDuration,
23 noise_factor: usize,
24 spec_lines_int: &[i32],
25 spec_lines_float: &mut [Scaler],
26) {
27 if !is_zero_frame {
28 const BW_STOP_TABLE_7P5MS: [usize; 5] = [60, 120, 180, 240, 300];
29 const BW_STOP_TABLE_10MS: [usize; 5] = [80, 160, 240, 320, 400];
30
31 let (bw_stop, nf_start, nf_width) = match duration {
32 FrameDuration::SevenPointFiveMs => (BW_STOP_TABLE_7P5MS[bandwidth as usize], 18, 2),
33 FrameDuration::TenMs => (BW_STOP_TABLE_10MS[bandwidth as usize], 24, 3),
34 };
35
36 let mut noise_fill = noise_filling_seed;
37 let noise_level = (8.0 - noise_factor as Scaler) / 16.0;
38
39 for (k, spec_line) in spec_lines_float.iter_mut().enumerate().take(bw_stop).skip(nf_start) {
41 let from = k - nf_width;
42 let to = (bw_stop - 1).min(k + nf_width);
43
44 let apply_noise_fill = &spec_lines_int[from..=to].iter().all(|x| *x == 0);
48
49 if *apply_noise_fill {
51 noise_fill = (13849 + noise_fill * 31821) & 0xFFFF;
52 *spec_line = if noise_fill < 0x8000 { noise_level } else { -noise_level };
53 }
54 }
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 extern crate std;
61 use super::*;
62 use crate::common::{config::FrameDuration, constants::MAX_LEN_SPECTRAL};
63
64 #[test]
65 fn decode_noise_filling() {
66 let is_zero_frame = false;
67 let noise_filling_seed = 56909;
68 let bandwidth = Bandwidth::FullBand;
69 let duration = FrameDuration::TenMs;
70 let noise_factor = 3;
71 let mut spec_lines_float: [f32; MAX_LEN_SPECTRAL] = [
72 -9.3125, 32.3125, 65.3125, 40.3125, -4.3125, -48.3125, -36.3125, 2.3125, 20.8125, -6.3125, 27.3125, 9.3125,
73 -8.8125, -26.3125, 8.8125, -4.3125, -0.8125, 12.3125, -7.8125, -2.3125, 23.3125, -33.3125, -9.8125, 3.3125,
74 -15.3125, -3.3125, 5.3125, 17.3125, -1.3125, 12.3125, 27.3125, -4.3125, 8.3125, 2.3125, 10.3125, -7.3125,
75 8.3125, -6.3125, 3.3125, -21.8125, 23.8125, -6.3125, -0.8125, 2.3125, 0.0, 1.3125, -8.0, 3.0, -2.0, 0.0,
76 0.0, 2.0, -6.0, -2.0, -4.0, -3.0, 0.0, 1.0, 0.0, -7.0, -4.0, -11.0, -7.0, -6.0, 0.0, 3.0, 10.0, 2.0, 9.0,
77 3.0, 7.0, -2.0, 2.0, -2.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 4.0, -1.0, -1.0, -1.0, 2.0, 1.0, 3.0, 3.0,
78 1.0, -2.0, -2.0, 1.0, 5.0, 2.0, -2.0, -5.0, -4.0, -2.0, 0.0, 0.0, 0.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0,
79 -1.0, -3.0, -1.0, 1.0, 3.0, 0.0, 0.0, 1.0, 2.0, -1.0, -1.0, 1.0, 2.0, 2.0, 1.0, 2.0, 0.0, -2.0, -3.0, 0.0,
80 3.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.0, -1.0, -1.0, 1.0, 2.0, 0.0, 0.0, 0.0, 0.0,
81 0.0, 0.0, 0.0, -1.0, 2.0, 0.0, -1.0, -1.0, 0.0, 2.0, 0.0, 2.0, 0.0, 0.0, -2.0, -1.0, 0.0, 1.0, 0.0, -1.0,
82 0.0, 1.0, 2.0, 0.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0, -1.0, -1.0, 0.0,
83 0.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0,
84 0.0, -1.0, 1.0, 2.0, -1.0, 0.0, 2.0, 0.0, 1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 2.0, -1.0, -1.0, 0.0, 0.0,
85 0.0, 0.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0,
86 0.0, 1.0, 2.0, -2.0, 0.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 1.0, 1.0, 1.0, -2.0, -1.0,
87 -1.0, 0.0, 1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.0, 1.0, -1.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0, 0.0,
88 1.0, 1.0, 0.0, -1.0, -1.0, 0.0, -1.0, 0.0, -1.0, -1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1.0, 1.0,
89 0.0, 0.0, 0.0, 0.0, -1.0, -1.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 0.0, -1.0, 0.0, 1.0, 0.0, 0.0,
90 0.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
91 0.0, 0.0, 0.0, 0.0, -1.0, -1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0,
92 -1.0, 0.0, 0.0, 1.0, -1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0,
93 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0,
94 ];
95 let spec_lines_int: [i32; MAX_LEN_SPECTRAL] = [
96 -9, 32, 65, 40, -4, -48, -36, 2, 21, -6, 27, 9, -9, -26, 9, -4, -1, 12, -8, -2, 23, -33, -10, 3, -15, -3,
97 5, 17, -1, 12, 27, -4, 8, 2, 10, -7, 8, -6, 3, -22, 24, -6, -1, 2, 0, 1, -8, 3, -2, 0, 0, 2, -6, -2, -4,
98 -3, 0, 1, 0, -7, -4, -11, -7, -6, 0, 3, 10, 2, 9, 3, 7, -2, 2, -2, -1, -1, 0, 0, 0, 0, 1, 4, -1, -1, -1, 2,
99 1, 3, 3, 1, -2, -2, 1, 5, 2, -2, -5, -4, -2, 0, 0, 0, -1, 1, -1, 1, 1, 1, -1, -3, -1, 1, 3, 0, 0, 1, 2, -1,
100 -1, 1, 2, 2, 1, 2, 0, -2, -3, 0, 3, 2, 0, 0, 0, 0, 1, 1, 0, -1, 0, 0, 0, -1, -1, 1, 2, 0, 0, 0, 0, 0, 0, 0,
101 -1, 2, 0, -1, -1, 0, 2, 0, 2, 0, 0, -2, -1, 0, 1, 0, -1, 0, 1, 2, 0, -1, 0, 1, 0, 1, 0, 1, -1, -1, 0, 0, 0,
102 0, -1, -1, 0, 0, 1, 0, -1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, -1, 1, 2, -1, 0, 2, 0, 1,
103 -1, 0, 0, -1, 0, 0, 2, -1, -1, 0, 0, 0, 0, -1, 1, -1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1,
104 2, -2, 0, -1, -1, 0, 0, 0, 0, -1, 0, 0, -1, 1, 1, 1, -2, -1, -1, 0, 1, -1, 0, 0, 1, 0, 0, 0, -1, 1, -1, 0,
105 0, -1, 1, 0, 0, 0, 1, 1, 0, -1, -1, 0, -1, 0, -1, -1, 0, 1, 0, 0, 0, 0, -1, 0, 1, 1, 0, 0, 0, 0, -1, -1,
106 -1, 0, 0, 0, -1, 0, 0, 1, 0, -1, 0, 1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0,
107 1, 0, 0, 0, 0, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 1, -1, -1, 0, 0, 1, 0, 0, 0,
108 0, -1, 0, 1, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 1,
109 ];
110
111 apply_noise_filling(
112 is_zero_frame,
113 noise_filling_seed,
114 bandwidth,
115 duration,
116 noise_factor,
117 &spec_lines_int,
118 &mut spec_lines_float,
119 );
120
121 let x_hat_expected: [f32; MAX_LEN_SPECTRAL] = [
122 -9.3125, 32.3125, 65.3125, 40.3125, -4.3125, -48.3125, -36.3125, 2.3125, 20.8125, -6.3125, 27.3125, 9.3125,
123 -8.8125, -26.3125, 8.8125, -4.3125, -0.8125, 12.3125, -7.8125, -2.3125, 23.3125, -33.3125, -9.8125, 3.3125,
124 -15.3125, -3.3125, 5.3125, 17.3125, -1.3125, 12.3125, 27.3125, -4.3125, 8.3125, 2.3125, 10.3125, -7.3125,
125 8.3125, -6.3125, 3.3125, -21.8125, 23.8125, -6.3125, -0.8125, 2.3125, 0.0, 1.3125, -8.0, 3.0, -2.0, 0.0,
126 0.0, 2.0, -6.0, -2.0, -4.0, -3.0, 0.0, 1.0, 0.0, -7.0, -4.0, -11.0, -7.0, -6.0, 0.0, 3.0, 10.0, 2.0, 9.0,
127 3.0, 7.0, -2.0, 2.0, -2.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 4.0, -1.0, -1.0, -1.0, 2.0, 1.0, 3.0, 3.0,
128 1.0, -2.0, -2.0, 1.0, 5.0, 2.0, -2.0, -5.0, -4.0, -2.0, 0.0, 0.0, 0.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0,
129 -1.0, -3.0, -1.0, 1.0, 3.0, 0.0, 0.0, 1.0, 2.0, -1.0, -1.0, 1.0, 2.0, 2.0, 1.0, 2.0, 0.0, -2.0, -3.0, 0.0,
130 3.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.0, -1.0, -1.0, 1.0, 2.0, 0.0, 0.0, 0.0,
131 0.3125, 0.0, 0.0, 0.0, -1.0, 2.0, 0.0, -1.0, -1.0, 0.0, 2.0, 0.0, 2.0, 0.0, 0.0, -2.0, -1.0, 0.0, 1.0, 0.0,
132 -1.0, 0.0, 1.0, 2.0, 0.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0, -1.0, -1.0,
133 0.0, 0.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0,
134 0.0, 0.0, -1.0, 1.0, 2.0, -1.0, 0.0, 2.0, 0.0, 1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 2.0, -1.0, -1.0, 0.0,
135 0.0, 0.0, 0.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0,
136 0.0, 0.0, 1.0, 2.0, -2.0, 0.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 1.0, 1.0, 1.0, -2.0,
137 -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.0, 1.0, -1.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0,
138 0.0, 1.0, 1.0, 0.0, -1.0, -1.0, 0.0, -1.0, 0.0, -1.0, -1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1.0,
139 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, -1.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 0.0, -1.0, 0.0, 1.0, 0.0,
140 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0, 0.0, 0.0,
141 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, -1.0, 1.0, 0.0, 0.0, 0.0, -0.3125, -0.3125, -0.3125, -0.3125, 0.3125,
142 -0.3125, 0.3125, 0.0, 0.0, 0.0, -1.0, -1.0, 0.0, 0.0, 1.0, -1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0,
143 -1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0,
144 ];
145 assert_eq![spec_lines_float, x_hat_expected];
146 }
147}