1use crate::g729::basic_operations::*;
2use crate::g729::cng::*;
3use crate::g729::decode_adaptative_code_vector::*;
4use crate::g729::decode_fixed_code_vector::*;
5use crate::g729::decode_gains::*;
6use crate::g729::decode_lsp::*;
7use crate::g729::interpolate_q_lsp::interpolate_q_lsp;
8use crate::g729::ld8k::*;
9use crate::g729::lp_synthesis_filter::lp_synthesis_filter;
10use crate::g729::post_filter::*;
11use crate::g729::post_processing::*;
12use crate::g729::q_lsp_2_lp::q_lsp_2_lp;
13use crate::g729::utils::*;
14
15static PREVIOUS_Q_LSP_INITIAL_VALUES: [Word16; NB_LSP_COEFF] = [
17 30000, 26000, 21000, 15000, 8000, 0, -8000, -15000, -21000, -26000,
18]; pub struct DecoderChannelContext {
21 pub previous_q_lsp: [Word16; NB_LSP_COEFF], pub excitation_vector: [Word16; L_PAST_EXCITATION + L_FRAME], pub bounded_adaptative_codebook_gain: Word16, pub adaptative_codebook_gain: Word16, pub fixed_codebook_gain: Word16, pub reconstructed_speech: [Word16; NB_LSP_COEFF + L_FRAME], pub pseudo_random_seed: u16, pub cng_pseudo_random_seed: u16, pub last_q_lsf: [Word16; NB_LSP_COEFF], pub previous_l_code_word: [[Word16; NB_LSP_COEFF]; MA_MAX_K], pub last_valid_l0: u16, pub previous_int_pitch_delay: i16, pub previous_gain_prediction_error: [Word16; 4], pub residual_signal_buffer: [Word16; MAXIMUM_INT_PITCH_DELAY + L_FRAME], pub scaled_residual_signal_buffer: [Word16; MAXIMUM_INT_PITCH_DELAY + L_FRAME], pub long_term_filtered_residual_signal_buffer: [Word16; 1 + L_SUBFRAME], pub short_term_filtered_residual_signal_buffer: [Word16; NB_LSP_COEFF + L_SUBFRAME], pub previous_adaptative_gain: Word16, pub input_x0: Word16,
55 pub input_x1: Word16,
56 pub output_y2: Word32,
57 pub output_y1: Word32,
58
59 pub cng_channel_context: CngChannelContext, pub previous_frame_is_active_flag: u8, }
63
64pub fn init_bcg729_decoder_channel() -> DecoderChannelContext {
65 let mut ctx = DecoderChannelContext {
66 previous_q_lsp: PREVIOUS_Q_LSP_INITIAL_VALUES,
67 excitation_vector: [0; L_PAST_EXCITATION + L_FRAME],
68 bounded_adaptative_codebook_gain: BOUNDED_PITCH_GAIN_MIN,
69 adaptative_codebook_gain: 0,
70 fixed_codebook_gain: 0,
71 reconstructed_speech: [0; NB_LSP_COEFF + L_FRAME],
72 pseudo_random_seed: 21845,
73 cng_pseudo_random_seed: CNG_DTX_RANDOM_SEED_INIT,
74 last_q_lsf: [0; NB_LSP_COEFF],
75 previous_l_code_word: [[0; NB_LSP_COEFF]; MA_MAX_K],
76 last_valid_l0: 0,
77 previous_int_pitch_delay: 0,
78 previous_gain_prediction_error: [0; 4],
79 residual_signal_buffer: [0; MAXIMUM_INT_PITCH_DELAY + L_FRAME],
80 scaled_residual_signal_buffer: [0; MAXIMUM_INT_PITCH_DELAY + L_FRAME],
81 long_term_filtered_residual_signal_buffer: [0; 1 + L_SUBFRAME],
82 short_term_filtered_residual_signal_buffer: [0; NB_LSP_COEFF + L_SUBFRAME],
83 previous_adaptative_gain: 0,
84 input_x0: 0,
85 input_x1: 0,
86 output_y2: 0,
87 output_y1: 0,
88 cng_channel_context: init_bcg729_cng_channel(),
89 previous_frame_is_active_flag: 1,
90 };
91
92 init_decode_lsp(
93 &mut ctx.previous_l_code_word,
94 &mut ctx.last_valid_l0,
95 &mut ctx.last_q_lsf,
96 );
97 init_decode_adaptative_code_vector(&mut ctx.previous_int_pitch_delay);
98 init_decode_gains(&mut ctx.previous_gain_prediction_error);
99 init_post_filter(
100 &mut ctx.residual_signal_buffer,
101 &mut ctx.scaled_residual_signal_buffer,
102 &mut ctx.long_term_filtered_residual_signal_buffer,
103 &mut ctx.short_term_filtered_residual_signal_buffer,
104 &mut ctx.previous_adaptative_gain,
105 );
106 init_post_processing(
107 &mut ctx.output_y2,
108 &mut ctx.output_y1,
109 &mut ctx.input_x0,
110 &mut ctx.input_x1,
111 );
112
113 ctx
114}
115
116pub fn bcg729_decoder(
117 decoder_channel_context: &mut DecoderChannelContext,
118 bit_stream: Option<&[u8]>,
119 bit_stream_length: u8,
120 frame_erasure_flag: u8,
121 mut sid_frame_flag: u8,
122 rfc3389_payload_flag: u8,
123 signal: &mut [Word16],
124) {
125 let mut parameters = [0 as u16; NB_PARAMETERS];
126 let mut q_lsp = [0 as Word16; NB_LSP_COEFF]; let mut interpolated_q_lsp = [0 as Word16; NB_LSP_COEFF]; let mut lp = [0 as Word16; 2 * NB_LSP_COEFF]; let mut int_pitch_delay: i16 = 0; let mut fixed_codebook_vector = [0 as Word16; L_SUBFRAME]; let mut post_filtered_signal = [0 as Word16; L_SUBFRAME]; let parity_error_flag: u8;
135 let mut parameters_index = 4; let mut lp_coefficients_index = 0; if let Some(bs) = bit_stream {
140 if sid_frame_flag == 0 {
141 parameters_bit_stream_2_array(bs, &mut parameters);
142 }
143 } else {
144 for i in 0..NB_PARAMETERS {
145 parameters[i] = 0;
146 }
147 }
148
149 if frame_erasure_flag != 0 {
151 if decoder_channel_context.previous_frame_is_active_flag != 0 {
152 sid_frame_flag = 0;
153 } else {
154 sid_frame_flag = 1;
155 }
156 }
157
158 if sid_frame_flag == 1 {
160 decode_sid_frame(
161 &mut decoder_channel_context.cng_channel_context,
162 decoder_channel_context.previous_frame_is_active_flag,
163 bit_stream,
164 bit_stream_length,
165 &mut decoder_channel_context.excitation_vector[L_PAST_EXCITATION..],
166 &mut decoder_channel_context.previous_q_lsp,
167 &mut lp,
168 &mut decoder_channel_context.cng_pseudo_random_seed,
169 &mut decoder_channel_context.previous_l_code_word,
170 rfc3389_payload_flag,
171 );
172 decoder_channel_context.previous_frame_is_active_flag = 0;
173
174 for subframe_index in (0..L_FRAME).step_by(L_SUBFRAME) {
176 lp_synthesis_filter(
180 &decoder_channel_context.excitation_vector[L_PAST_EXCITATION + subframe_index..],
181 &lp[lp_coefficients_index..],
182 &mut decoder_channel_context.reconstructed_speech[subframe_index..],
183 );
184
185 post_filter(
190 &mut decoder_channel_context.residual_signal_buffer,
191 &mut decoder_channel_context.scaled_residual_signal_buffer,
192 &mut decoder_channel_context.long_term_filtered_residual_signal_buffer,
193 &mut decoder_channel_context.short_term_filtered_residual_signal_buffer,
194 &mut decoder_channel_context.previous_adaptative_gain,
195 &lp[lp_coefficients_index..],
196 &decoder_channel_context.reconstructed_speech[subframe_index..],
197 decoder_channel_context.previous_int_pitch_delay,
198 subframe_index,
199 &mut post_filtered_signal,
200 );
201
202 post_processing(
204 &mut decoder_channel_context.output_y2,
205 &mut decoder_channel_context.output_y1,
206 &mut decoder_channel_context.input_x0,
207 &mut decoder_channel_context.input_x1,
208 &mut post_filtered_signal,
209 );
210
211 for i in 0..L_SUBFRAME {
213 signal[subframe_index + i] = post_filtered_signal[i];
214 }
215
216 lp_coefficients_index += NB_LSP_COEFF;
218 }
219
220 decoder_channel_context.bounded_adaptative_codebook_gain = BOUNDED_PITCH_GAIN_MIN;
221
222 for i in 0..L_PAST_EXCITATION {
225 decoder_channel_context.excitation_vector[i] =
226 decoder_channel_context.excitation_vector[L_FRAME + i];
227 }
228 for i in 0..NB_LSP_COEFF {
231 decoder_channel_context.reconstructed_speech[i] =
232 decoder_channel_context.reconstructed_speech[L_FRAME + i];
233 }
234
235 return;
236 }
237
238 decoder_channel_context.previous_frame_is_active_flag = 1;
239 decoder_channel_context.cng_pseudo_random_seed = CNG_DTX_RANDOM_SEED_INIT; decode_lsp(
245 &mut decoder_channel_context.previous_l_code_word,
246 &mut decoder_channel_context.last_valid_l0,
247 &mut decoder_channel_context.last_q_lsf,
248 ¶meters[0..4],
249 &mut q_lsp,
250 frame_erasure_flag,
251 ); interpolate_q_lsp(
254 &decoder_channel_context.previous_q_lsp,
255 &q_lsp,
256 &mut interpolated_q_lsp,
257 );
258 for i in 0..NB_LSP_COEFF {
260 decoder_channel_context.previous_q_lsp[i] = q_lsp[i];
261 }
262
263 q_lsp_2_lp(&interpolated_q_lsp, &mut lp[0..NB_LSP_COEFF]);
265 q_lsp_2_lp(&q_lsp, &mut lp[NB_LSP_COEFF..]);
267
268 parity_error_flag = (compute_parity(parameters[4]) ^ parameters[5]) as u8;
270
271 for subframe_index in (0..L_FRAME).step_by(L_SUBFRAME) {
273 decode_adaptative_code_vector(
275 &mut decoder_channel_context.previous_int_pitch_delay,
276 subframe_index,
277 parameters[parameters_index],
278 parity_error_flag,
279 frame_erasure_flag,
280 &mut int_pitch_delay,
281 &mut decoder_channel_context.excitation_vector,
282 );
283 if subframe_index == 0 {
284 parameters_index += 2;
286 } else {
287 parameters_index += 1;
288 }
289
290 if frame_erasure_flag != 0 {
292 parameters[parameters_index] =
293 pseudo_random(&mut decoder_channel_context.pseudo_random_seed) & 0x1fff; parameters[parameters_index + 1] =
295 pseudo_random(&mut decoder_channel_context.pseudo_random_seed) & 0x000f;
296 }
298
299 decode_fixed_code_vector(
301 parameters[parameters_index + 1],
302 parameters[parameters_index],
303 int_pitch_delay,
304 decoder_channel_context.bounded_adaptative_codebook_gain,
305 &mut fixed_codebook_vector,
306 );
307 parameters_index += 2;
308
309 decode_gains(
311 &mut decoder_channel_context.previous_gain_prediction_error,
312 parameters[parameters_index],
313 parameters[parameters_index + 1],
314 &fixed_codebook_vector,
315 frame_erasure_flag,
316 &mut decoder_channel_context.adaptative_codebook_gain,
317 &mut decoder_channel_context.fixed_codebook_gain,
318 );
319
320 parameters_index += 2;
321
322 decoder_channel_context.bounded_adaptative_codebook_gain =
324 decoder_channel_context.adaptative_codebook_gain;
325 if decoder_channel_context.bounded_adaptative_codebook_gain > BOUNDED_PITCH_GAIN_MAX {
326 decoder_channel_context.bounded_adaptative_codebook_gain = BOUNDED_PITCH_GAIN_MAX;
327 }
328 if decoder_channel_context.bounded_adaptative_codebook_gain < BOUNDED_PITCH_GAIN_MIN {
329 decoder_channel_context.bounded_adaptative_codebook_gain = BOUNDED_PITCH_GAIN_MIN;
330 }
331
332 for i in 0..L_SUBFRAME {
338 decoder_channel_context.excitation_vector[L_PAST_EXCITATION + subframe_index + i] =
339 saturate(
340 pshr(
341 add32(
342 mult16_16(
343 decoder_channel_context.excitation_vector
344 [L_PAST_EXCITATION + subframe_index + i],
345 decoder_channel_context.adaptative_codebook_gain,
346 ),
347 mult16_16(
348 fixed_codebook_vector[i],
349 decoder_channel_context.fixed_codebook_gain,
350 ),
351 ),
352 14,
353 ),
354 MAX_INT16 as Word32,
355 ) as Word16;
356 }
357
358 lp_synthesis_filter(
362 &decoder_channel_context.excitation_vector[L_PAST_EXCITATION + subframe_index..],
363 &lp[lp_coefficients_index..],
364 &mut decoder_channel_context.reconstructed_speech[subframe_index..],
365 );
366
367 post_filter(
372 &mut decoder_channel_context.residual_signal_buffer,
373 &mut decoder_channel_context.scaled_residual_signal_buffer,
374 &mut decoder_channel_context.long_term_filtered_residual_signal_buffer,
375 &mut decoder_channel_context.short_term_filtered_residual_signal_buffer,
376 &mut decoder_channel_context.previous_adaptative_gain,
377 &lp[lp_coefficients_index..],
378 &decoder_channel_context.reconstructed_speech[subframe_index..],
379 int_pitch_delay,
380 subframe_index,
381 &mut post_filtered_signal,
382 ); post_processing(
385 &mut decoder_channel_context.output_y2,
386 &mut decoder_channel_context.output_y1,
387 &mut decoder_channel_context.input_x0,
388 &mut decoder_channel_context.input_x1,
389 &mut post_filtered_signal,
390 );
391
392 for i in 0..L_SUBFRAME {
394 signal[subframe_index + i] = post_filtered_signal[i];
395 }
396
397 lp_coefficients_index += NB_LSP_COEFF;
399 }
400
401 for i in 0..L_PAST_EXCITATION {
404 decoder_channel_context.excitation_vector[i] =
405 decoder_channel_context.excitation_vector[L_FRAME + i];
406 }
407 for i in 0..NB_LSP_COEFF {
410 decoder_channel_context.reconstructed_speech[i] =
411 decoder_channel_context.reconstructed_speech[L_FRAME + i];
412 }
413}
414
415pub struct Decoder {
416 context: DecoderChannelContext,
417}
418
419impl Decoder {
420 pub fn new() -> Self {
421 Decoder {
422 context: init_bcg729_decoder_channel(),
423 }
424 }
425
426 pub fn decode(
427 &mut self,
428 bit_stream: Option<&[u8]>,
429 bit_stream_length: u8,
430 frame_erasure_flag: u8,
431 sid_frame_flag: u8,
432 rfc3389_payload_flag: u8,
433 signal: &mut [i16],
434 ) {
435 bcg729_decoder(
436 &mut self.context,
437 bit_stream,
438 bit_stream_length,
439 frame_erasure_flag,
440 sid_frame_flag,
441 rfc3389_payload_flag,
442 signal,
443 );
444 }
445}