1use super::{
2 buffer_reader::{BufferReader, BufferReaderError},
3 side_info::{Bandwidth, LongTermPostFilterInfo, SideInfo, SnsVq},
4};
5
6#[allow(unused_imports)]
7use num_traits::real::Real;
8
9const NBITS_BW_TABLE: [usize; 5] = [0, 1, 2, 2, 3];
12
13#[derive(Debug)]
14pub enum SideInfoError {
15 BandwidthIdxOutOfRange(usize),
16 LastNonZeroTupleGreaterThanYLen(usize, usize),
17 NotImplemented,
18 PlcTriggerSns1OutOfRange(usize),
19 PlcTriggerSns2OutOfRange(usize),
20 BufferReaderError(BufferReaderError),
21}
22
23impl From<BufferReaderError> for SideInfoError {
24 fn from(err: BufferReaderError) -> Self {
25 Self::BufferReaderError(err)
26 }
27}
28
29pub fn read(
30 buf: &[u8],
31 reader: &mut BufferReader,
32 fs_ind: usize, ne: usize, ) -> Result<SideInfo, SideInfoError> {
35 let nbits_bw = NBITS_BW_TABLE[fs_ind];
36
37 let p_bw = if nbits_bw > 0 {
39 let idx = reader.read_tail_usize(buf, nbits_bw)?;
40 if fs_ind < idx {
41 return Err(SideInfoError::BandwidthIdxOutOfRange(idx));
42 } else {
43 idx
44 }
45 } else {
46 0
47 };
48
49 let lastnz_num_bits = ((ne / 2) as f32).log2().ceil() as usize;
51 let lastnz = reader.read_tail_usize(buf, lastnz_num_bits)?;
52 let lastnz = (lastnz + 1) << 1;
53 if lastnz > ne {
54 return Err(SideInfoError::LastNonZeroTupleGreaterThanYLen(lastnz, ne));
55 }
56
57 let lsb_mode = reader.read_tail_bool(buf)?;
59
60 let gg_ind = reader.read_tail_usize(buf, 8)?;
62
63 let num_tns_filters = if p_bw < 3 { 1 } else { 2 };
65
66 let mut rc_order: [usize; 2] = [0; 2];
68 for item in rc_order.iter_mut().take(num_tns_filters) {
69 *item = reader.read_tail_bool(buf)? as usize;
70 }
71
72 let pitch_present = reader.read_tail_bool(buf)?;
74
75 let sns_vq = read_sns_vq(buf, reader)?;
77
78 let long_term_post_filter_info = read_long_term_post_filter_info(buf, reader, pitch_present)?;
80
81 let f_nf = reader.read_tail_usize(buf, 3)?;
82
83 let bandwidth = match p_bw {
84 0 => Bandwidth::NarrowBand,
85 1 => Bandwidth::WideBand,
86 2 => Bandwidth::SemiSuperWideBand,
87 3 => Bandwidth::SuperWideBand,
88 4 => Bandwidth::FullBand,
89 _ => return Err(SideInfoError::BandwidthIdxOutOfRange(p_bw)),
90 };
91
92 Ok(SideInfo {
93 bandwidth,
94 lastnz,
95 lsb_mode,
96 global_gain_index: gg_ind,
97 num_tns_filters,
98 reflect_coef_order_ari_input: rc_order,
99 sns_vq,
100 long_term_post_filter_info,
101 noise_factor: f_nf,
102 })
103}
104
105fn read_long_term_post_filter_info(
106 buf: &[u8],
107 reader: &mut BufferReader,
108 pitch_present: bool,
109) -> Result<LongTermPostFilterInfo, SideInfoError> {
110 let ltpf_active;
111 let pitch_index;
112 if pitch_present {
113 ltpf_active = reader.read_tail_bool(buf)?;
114 pitch_index = reader.read_tail_usize(buf, 9)?;
115 } else {
116 ltpf_active = false;
117 pitch_index = 0;
118 }
119
120 Ok(LongTermPostFilterInfo {
121 pitch_present,
122 is_active: ltpf_active,
123 pitch_index,
124 })
125}
126
127fn read_sns_vq(buf: &[u8], reader: &mut BufferReader) -> Result<SnsVq, SideInfoError> {
128 let ind_lf = reader.read_tail_usize(buf, 5)?;
130 let ind_hf = reader.read_tail_usize(buf, 5)?;
131
132 let submode_msb = reader.read_tail_bool(buf)? as u8;
134 let mut g_ind = if submode_msb == 0 {
135 reader.read_tail_usize(buf, 1)?
136 } else {
137 reader.read_tail_usize(buf, 2)?
138 };
139
140 let ls_inda = reader.read_tail_bool(buf)? as usize;
141 let ls_indb;
142 let idx_a;
143 let idx_b;
144 let mut submode_lsb;
145
146 if submode_msb == 0 {
147 let tmp = reader.read_tail_usize(buf, 25)?;
148 if tmp >= 33460056 {
149 return Err(SideInfoError::PlcTriggerSns1OutOfRange(tmp));
150 }
151
152 let idx_bor_gain_lsb = tmp / 2390004;
153 idx_a = tmp - idx_bor_gain_lsb * 2390004;
154 submode_lsb = 0;
155 let idx_bor_gain_lsb: i32 = idx_bor_gain_lsb as i32 - 2_i32;
156 if idx_bor_gain_lsb < 0 {
157 submode_lsb = 1;
158 }
159
160 let idx_bor_gain_lsb = (idx_bor_gain_lsb + submode_lsb as i32 * 2) as usize;
161 if submode_lsb != 0 {
162 g_ind = (g_ind << 1) + idx_bor_gain_lsb;
163 idx_b = 0;
164 ls_indb = 0;
165 } else {
166 idx_b = idx_bor_gain_lsb >> 1;
167 ls_indb = idx_bor_gain_lsb & 1;
168 }
169 } else {
170 ls_indb = 0;
171 idx_b = 0;
172 submode_lsb = 0;
173 let tmp = reader.read_tail_usize(buf, 24)?;
174
175 if tmp >= 16708096 {
176 return Err(SideInfoError::PlcTriggerSns2OutOfRange(tmp));
177 }
178
179 if tmp >= 15158272 {
180 let tmp = tmp - 15158272;
181 submode_lsb = 1;
182 g_ind = (g_ind << 1) + (tmp & 1);
183 idx_a = tmp >> 1;
184 } else {
185 idx_a = tmp;
186 }
187 }
188
189 Ok(SnsVq {
190 ind_lf,
191 ind_hf,
192 ls_inda,
193 ls_indb,
194 idx_a,
195 idx_b,
196 submode_lsb,
197 submode_msb,
198 g_ind,
199 })
200}
201
202#[cfg(test)]
203mod tests {
204 extern crate std;
205 use super::*;
206
207 #[test]
208 fn read_side_info_test() {
209 let buf = [192, 74, 255, 80, 28, 187, 134, 52];
212 let mut reader = BufferReader::new();
213
214 let side_info = read(&buf, &mut reader, 4, 400).unwrap();
215
216 assert_eq!(side_info.bandwidth, Bandwidth::FullBand);
217 assert_eq!(side_info.lastnz, 398);
218 assert_eq!(side_info.lsb_mode, false);
219 assert_eq!(side_info.global_gain_index, 184);
220 assert_eq!(side_info.num_tns_filters, 2);
221 assert_eq!(side_info.reflect_coef_order_ari_input, [1, 1]);
222 let sns_vq = side_info.sns_vq;
223 assert_eq!(sns_vq.ind_lf, 25);
224 assert_eq!(sns_vq.ind_hf, 1);
225 assert_eq!(sns_vq.ls_inda, 0);
226 assert_eq!(sns_vq.ls_indb, 0);
227 assert_eq!(sns_vq.idx_a, 307189);
228 assert_eq!(sns_vq.idx_b, 0);
229 assert_eq!(sns_vq.submode_lsb, 1);
230 assert_eq!(sns_vq.submode_msb, 0);
231 assert_eq!(sns_vq.g_ind, 0);
232 let post_filter = side_info.long_term_post_filter_info;
233 assert_eq!(post_filter.pitch_present, false);
234 assert_eq!(post_filter.is_active, false);
235 assert_eq!(post_filter.pitch_index, 0);
236 assert_eq!(side_info.noise_factor, 6);
237 }
238}