Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : #include <stdint.h>
6 : #include "options.h" /* Compilation switches */
7 : #include "prot_fx.h" /* Function prototypes */
8 : #include "rom_com.h"
9 :
10 : /*===================================================================*/
11 : /* FUNCTION : normalize_arr() */
12 : /*-------------------------------------------------------------------*/
13 : /* PURPOSE : Normalize array */
14 : /* */
15 : /*-------------------------------------------------------------------*/
16 : /* GLOBAL INPUT ARGUMENTS : */
17 : /* _ (Word16*) qf */
18 : /* _ (Word16*) size */
19 : /* _ (Word16*) hdr */
20 : /*-------------------------------------------------------------------*/
21 : /* OUTPUT ARGUMENTS : */
22 : /* _ (Word16*) arr : Normalized array */
23 : /*-------------------------------------------------------------------*/
24 :
25 : /* _ None */
26 : /*-------------------------------------------------------------------*/
27 : /* RETURN ARGUMENTS : */
28 : /* _ None */
29 : /*===================================================================*/
30 0 : static void normalize_arr( Word16 *arr, Word16 *qf, Word16 size, Word16 hdr )
31 : {
32 0 : Word16 i, max_s = 0;
33 0 : move16();
34 :
35 0 : FOR( i = 0; i < size; i++ )
36 : {
37 0 : max_s = s_max( max_s, abs_s( arr[i] ) );
38 : }
39 :
40 0 : *qf = norm_s( (Word16) max_s );
41 0 : test();
42 0 : IF( ( *qf == 0 ) && ( ( (Word16) max_s ) == 0 ) )
43 : {
44 0 : *qf = 15;
45 0 : move16();
46 : }
47 :
48 0 : *qf = sub( *qf, hdr );
49 0 : move16();
50 :
51 0 : FOR( i = 0; i < size; i++ )
52 : {
53 0 : arr[i] = shl( arr[i], *qf );
54 0 : move16(); /* saturation can occur here */
55 : }
56 :
57 0 : return;
58 : }
59 :
60 : /*===================================================================*/
61 : /* FUNCTION : nelp_decoder_fx() */
62 : /*-------------------------------------------------------------------*/
63 : /* PURPOSE : NELP decoding for the current frame */
64 : /* */
65 : /*-------------------------------------------------------------------*/
66 : /* GLOBAL INPUT ARGUMENTS : */
67 : /* _ (Struct) st */
68 : /* _ (Word16[]) exc_nelp : adapt. excitation/total exc (Q0) */
69 : /* _ (Word16[]) exc : adapt. excitation exc (Q0) */
70 : /* _ (Word16) bfi : frame error rate */
71 : /* _ (Word16) coder_type : coding type */
72 : /*-------------------------------------------------------------------*/
73 : /* OUTPUT ARGUMENTS : */
74 : /* _ (Word16[]) exc_nelp : adapt. excitation/total exc (Q0) */
75 : /* (Word16[]) gain_buf : floating pitch gain for each subframe */
76 : /*-------------------------------------------------------------------*/
77 :
78 : /* _ (Word16[]) shape1_filt_mem_dec : filter memory (Q0) */
79 : /* _ (Word16[]) shape2_filt_mem_dec : filter memory (Q0) */
80 : /* _ (Word16[]) shape3_filt_mem_dec : filter memory (Q0) */
81 : /* _ (Word16[]) bp1_filt_mem_wb_dec : filter memory (Q0) */
82 : /* _ (Word16[]) bp1_filt_mem_nb_dec : filter memory (Q0) */
83 : /*-------------------------------------------------------------------*/
84 : /* RETURN ARGUMENTS : */
85 : /* _ None */
86 : /*===================================================================*/
87 :
88 0 : void nelp_decoder_fx(
89 : Decoder_State *st_fx,
90 : Word16 *exc_nelp, /* Q0 */
91 : Word16 *exc, /* Q_exc */
92 : Word16 *Q_exc,
93 : Word16 bfi, /* Q0 */
94 : const Word16 coder_type, /* Q0 */
95 : Word16 *gain_buf /* Q14 */
96 : )
97 : {
98 0 : Word16 i, fid = 0;
99 0 : move16();
100 : Word16 ptr[L_FRAME], filtRes[L_FRAME], gain_fac; /*ptr, filtRes - Q0, gain_fac - Q14 */
101 : Word16 Gains[10]; /* Q0 */
102 : Word32 Gain, E3, E2;
103 0 : Word16 BP1_ORDER = 4;
104 0 : move16();
105 : Word16 ptr_tmp[L_FRAME]; /* Q0 */
106 : Word16 iG1, iG2[2];
107 : Word16 exp_E2, exp_E3, frac_E2, frac_E3;
108 : Word16 tmp, scale, exp, frac;
109 : Word32 L_tmp, L_tmp1;
110 : Word32 exc_sqr[L_SUBFR];
111 : Word32 max_exc_sqr;
112 : Word16 n;
113 0 : Word16 max_val = 0, norm_val = 0;
114 0 : move16();
115 0 : move16();
116 0 : Word16 qGain = 0;
117 0 : move16();
118 : SC_VBR_DEC_HANDLE hSC_VBR;
119 :
120 0 : hSC_VBR = st_fx->hSC_VBR;
121 :
122 0 : test();
123 0 : if ( EQ_16( st_fx->last_nelp_mode_dec, 1 ) && NE_16( st_fx->bwidth, st_fx->last_bwidth ) )
124 : {
125 0 : st_fx->last_nelp_mode_dec = 0;
126 0 : move16();
127 : }
128 :
129 0 : test();
130 0 : test();
131 0 : test();
132 0 : IF( EQ_16( coder_type, UNVOICED ) && EQ_16( st_fx->bwidth, NB ) )
133 : {
134 0 : IF( NE_16( st_fx->last_nelp_mode_dec, 1 ) )
135 : {
136 0 : BP1_ORDER = 7; /* Q0 */
137 0 : move16();
138 :
139 0 : set32_fx( hSC_VBR->bp1_filt_mem_nb_dec_fx, 0, BP1_ORDER * 2 );
140 : }
141 : }
142 0 : ELSE IF( EQ_16( coder_type, UNVOICED ) && ( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) )
143 : {
144 0 : BP1_ORDER = 4; /* Q0 */
145 0 : move16();
146 0 : IF( NE_16( st_fx->last_nelp_mode_dec, 1 ) )
147 : {
148 0 : set16_fx( hSC_VBR->bp1_filt_mem_wb_dec_fx, 0, shl( BP1_ORDER, 1 ) );
149 : }
150 : }
151 :
152 0 : IF( NE_16( st_fx->last_nelp_mode_dec, 1 ) )
153 : {
154 0 : set16_fx( hSC_VBR->shape1_filt_mem_dec_fx, 0, 10 );
155 0 : set16_fx( hSC_VBR->shape2_filt_mem_dec_fx, 0, 10 );
156 0 : set16_fx( hSC_VBR->shape3_filt_mem_dec_fx, 0, 10 );
157 : }
158 :
159 0 : IF( bfi == 0 )
160 : {
161 0 : test();
162 0 : IF( EQ_16( st_fx->rf_frame_type, RF_NELP ) && EQ_16( st_fx->use_partial_copy, 1 ) )
163 : {
164 0 : iG1 = st_fx->rf_indx_nelp_iG1; /* Q0 */
165 0 : move16();
166 0 : iG2[0] = st_fx->rf_indx_nelp_iG2[0]; /* Q0 */
167 0 : move16();
168 0 : iG2[1] = st_fx->rf_indx_nelp_iG2[1]; /* Q0 */
169 0 : move16();
170 : }
171 : ELSE
172 : {
173 : /* Do Unvoiced/NELP Decoding */
174 0 : iG1 = (Word16) get_next_indice_fx( st_fx, 5 ); /* Q0 */
175 0 : move16();
176 0 : iG2[0] = (Word16) get_next_indice_fx( st_fx, 6 ); /* Q0 */
177 0 : move16();
178 0 : iG2[1] = (Word16) get_next_indice_fx( st_fx, 6 ); /* Q0 */
179 0 : move16();
180 : }
181 :
182 0 : test();
183 0 : test();
184 0 : IF( EQ_16( coder_type, UNVOICED ) && ( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) )
185 : {
186 0 : test();
187 0 : IF( EQ_16( st_fx->rf_frame_type, RF_NELP ) && EQ_16( st_fx->use_partial_copy, 1 ) )
188 : {
189 0 : fid = st_fx->rf_indx_nelp_fid; /* Q0 */
190 0 : move16();
191 : }
192 : ELSE
193 : {
194 0 : fid = (Word16) get_next_indice_fx( st_fx, 2 ); /* Q0 */
195 0 : move16();
196 : }
197 : }
198 :
199 0 : *Q_exc = dequantize_uvg_fx( iG1, iG2, Gains, st_fx->bwidth, 1 );
200 0 : move16(); /* Gains - Q0/Q3 */
201 : }
202 : ELSE
203 : {
204 0 : FOR( i = 1; i <= L_SUBFR; i++ )
205 : {
206 0 : exc_sqr[i - 1] = L_mult0( exc[-i], exc[-i] );
207 0 : move32(); /*2*Q_exc */
208 : }
209 0 : max_exc_sqr = L_deposit_l( 0 );
210 0 : FOR( i = 0; i < L_SUBFR; i++ )
211 : {
212 0 : max_exc_sqr = L_max( max_exc_sqr, exc_sqr[i] ); /*2*Q_exc */
213 : }
214 0 : IF( max_exc_sqr != 0 )
215 : {
216 0 : exp = norm_l( max_exc_sqr );
217 0 : FOR( i = 0; i < L_SUBFR; i++ )
218 : {
219 0 : exc_sqr[i] = L_shl( exc_sqr[i], exp );
220 0 : move32(); /*Q30 */
221 : }
222 0 : exp = sub( 30, add( exp, add( *Q_exc, *Q_exc ) ) );
223 :
224 0 : Gain = L_deposit_l( 1 );
225 0 : FOR( i = 0; i < L_SUBFR; i++ )
226 : {
227 0 : Gain = L_add( Gain, L_shr( exc_sqr[i], 6 ) ); /*Q24 */
228 : }
229 0 : Gain = Mult_32_16( Gain, 20972 ); /*Q24; 20972=sqr(0.8) in Q15 */
230 0 : exp = sub( exp, 6 ); /*due to /L_SUBFR */
231 :
232 0 : IF( s_and( exp, 1 ) != 0 )
233 : {
234 0 : Gain = L_shr( Gain, 1 ); /*Q24 */
235 0 : exp = add( exp, 1 );
236 : }
237 0 : exp = shr( exp, 1 );
238 0 : n = norm_l( Gain );
239 0 : frac = round_fx( L_shl( Gain, n ) );
240 0 : n = sub( add( n, 24 ), 30 );
241 0 : frac = div_s( 16384, frac ); /* Q15 */
242 0 : Gain = Isqrt_lc( L_deposit_h( frac ), &n ); /*Q(31-n-exp) */
243 0 : tmp = round_fx( L_shl( Gain, sub( add( n, exp ), 15 ) ) ); /*Q0 */
244 : }
245 : ELSE
246 : {
247 0 : tmp = 0;
248 0 : move16();
249 : }
250 :
251 0 : set16_fx( Gains, tmp, 10 );
252 0 : *Q_exc = 0;
253 0 : move16();
254 : }
255 :
256 :
257 0 : gain_fac = 22446;
258 0 : move16(); /* 1.37f - Q14 */
259 0 : test();
260 0 : test();
261 0 : if ( EQ_16( coder_type, UNVOICED ) && ( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) )
262 : {
263 0 : gain_fac = 19005;
264 0 : move16(); /* 1.16f - Q14 */
265 : }
266 :
267 0 : test();
268 0 : IF( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) )
269 : {
270 : /* Normalize Gains[10] with headroom 4, qGain is the new Q value os Gains, not Q0*/
271 : /* This is done to avoid internal overflow observed in the wb bp filter below, similar to encoder */
272 0 : normalize_arr( Gains, &qGain, 10, 4 );
273 : }
274 :
275 0 : generate_nelp_excitation_fx( &( hSC_VBR->nelp_dec_seed ), Gains, ptr, gain_fac );
276 : /* o: ptr = nelp_exc in Q=qGain, qGain = 0 always for NB */
277 :
278 0 : test();
279 0 : test();
280 0 : IF( EQ_16( coder_type, UNVOICED ) && ( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) )
281 : {
282 0 : BP1_ORDER = 4; /* Q0 */
283 0 : move16();
284 0 : Scale_sig( hSC_VBR->bp1_filt_mem_wb_dec_fx, shl( BP1_ORDER, 1 ), qGain ); /* bring filter prev memory from Q0 to qGain */
285 0 : pz_filter_sp_fx( bp1_num_coef_wb_fx, bp1_den_coef_wb_fx, ptr, ptr_tmp, hSC_VBR->bp1_filt_mem_wb_dec_fx,
286 0 : BP1_ORDER, BP1_ORDER, L_FRAME, ( sub( 16, BP1_COEF_WB_QF ) ) );
287 :
288 0 : Scale_sig( hSC_VBR->bp1_filt_mem_wb_dec_fx, shl( BP1_ORDER, 1 ), negate( qGain ) ); /* bring filter prev memory from qGain to Q0 */
289 0 : Scale_sig( ptr_tmp, L_FRAME, -qGain ); /* bring nelp_exc to Q0 */
290 0 : Copy( ptr_tmp, ptr, L_FRAME ); /* Q0 */
291 : }
292 :
293 0 : test();
294 0 : IF( EQ_16( coder_type, UNVOICED ) && ( EQ_16( st_fx->bwidth, NB ) ) )
295 : {
296 0 : BP1_ORDER = 7; /* Q0 */
297 0 : move16();
298 :
299 0 : FOR( i = 0; i < L_FRAME; i++ )
300 : {
301 0 : max_val = s_max( ptr[i], max_val ); /* Q0 */
302 : }
303 0 : tmp = shl( BP1_ORDER, 1 );
304 0 : FOR( i = 0; i < tmp; i++ )
305 : {
306 0 : max_val = s_max( round_fx( L_shr( hSC_VBR->bp1_filt_mem_nb_dec_fx[i], 16 ) ), max_val );
307 : }
308 0 : norm_val = norm_s( max_val );
309 :
310 0 : norm_val = s_max( 0, sub( norm_val, 4 ) ); /* 4 bit head room */
311 :
312 0 : norm_val = s_min( norm_val, 8 ); /* scale only for very low level signals */
313 :
314 0 : IF( norm_val > 0 )
315 : {
316 0 : Scale_sig32( hSC_VBR->bp1_filt_mem_nb_dec_fx, shl( BP1_ORDER, 1 ), norm_val ); /* norm_val */
317 0 : Scale_sig( ptr, L_FRAME, norm_val ); /* norm_val + Q_exc */
318 0 : *Q_exc = add( norm_val, *Q_exc );
319 0 : move16();
320 : }
321 :
322 0 : BP1_ORDER = 7; /* Q0 */
323 0 : move16();
324 0 : pz_filter_dp_fx( bp1_num_coef_nb_fx_order7, bp1_den_coef_nb_fx_order7, ptr, ptr_tmp, hSC_VBR->bp1_filt_mem_nb_dec_fx,
325 0 : BP1_ORDER, BP1_ORDER, L_FRAME, ( sub( 16, BP1_COEF_NB_QF_ORDER7 ) ) );
326 :
327 :
328 0 : IF( norm_val > 0 )
329 : {
330 0 : Scale_sig32( hSC_VBR->bp1_filt_mem_nb_dec_fx, shl( BP1_ORDER, 1 ), negate( norm_val ) );
331 : }
332 :
333 0 : Copy( ptr_tmp, ptr, L_FRAME ); /*Q_exc */
334 : }
335 :
336 0 : E3 = L_deposit_l( 1 );
337 0 : FOR( i = 0; i < L_FRAME; i++ )
338 : {
339 0 : E3 = L_mac0_sat( E3, ptr[i], ptr[i] ); /*2*Q_exc */
340 : }
341 :
342 :
343 0 : test();
344 0 : test();
345 0 : IF( EQ_16( coder_type, UNVOICED ) && ( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) )
346 : {
347 0 : pz_filter_sp_fx( shape1_num_coef_fx, shape1_den_coef_fx, ptr, ptr_tmp, hSC_VBR->shape1_filt_mem_dec_fx,
348 0 : 10, 10, L_FRAME, ( sub( 16, SHAPE1_COEF_QF ) ) );
349 0 : Copy( ptr_tmp, ptr, L_FRAME ); /*Q_exc */
350 :
351 0 : SWITCH( fid )
352 : {
353 0 : case 1:
354 : /* Update other filter memory */
355 0 : pz_filter_sp_fx( shape3_num_coef_fx, shape3_den_coef_fx, ptr, filtRes, hSC_VBR->shape3_filt_mem_dec_fx,
356 0 : 10, 10, L_FRAME, ( sub( 16, SHAPE3_COEF_QF ) ) );
357 :
358 : /* filter the residual to desired shape */
359 0 : pz_filter_sp_fx( shape2_num_coef_fx, shape2_den_coef_fx, ptr, ptr_tmp, hSC_VBR->shape2_filt_mem_dec_fx,
360 0 : 10, 10, L_FRAME, ( sub( 16, SHAPE2_COEF_QF ) ) );
361 :
362 0 : Copy( ptr_tmp, ptr, L_FRAME ); /*Q_exc */
363 :
364 0 : BREAK;
365 0 : case 2:
366 : /* Update other filter memory */
367 0 : pz_filter_sp_fx( shape2_num_coef_fx, shape2_den_coef_fx, ptr, filtRes, hSC_VBR->shape2_filt_mem_dec_fx,
368 0 : 10, 10, L_FRAME, ( sub( 16, SHAPE2_COEF_QF ) ) );
369 :
370 : /* filter the residual to desired shape */
371 0 : pz_filter_sp_fx( shape3_num_coef_fx, shape3_den_coef_fx, ptr, ptr_tmp, hSC_VBR->shape3_filt_mem_dec_fx,
372 0 : 10, 10, L_FRAME, ( sub( 16, SHAPE3_COEF_QF ) ) );
373 :
374 0 : Copy( ptr_tmp, ptr, L_FRAME ); /*Q_exc */
375 :
376 0 : BREAK;
377 0 : default:
378 : /* Update other filter memory */
379 0 : pz_filter_sp_fx( shape2_num_coef_fx, shape2_den_coef_fx, ptr, filtRes, hSC_VBR->shape2_filt_mem_dec_fx,
380 0 : 10, 10, L_FRAME, ( sub( 16, SHAPE2_COEF_QF ) ) );
381 0 : pz_filter_sp_fx( shape3_num_coef_fx, shape3_den_coef_fx, ptr, filtRes, hSC_VBR->shape3_filt_mem_dec_fx,
382 0 : 10, 10, L_FRAME, ( sub( 16, SHAPE3_COEF_QF ) ) );
383 :
384 0 : BREAK;
385 : }
386 :
387 0 : E2 = L_deposit_l( 1 );
388 0 : FOR( i = 0; i < L_FRAME; i++ )
389 : {
390 0 : E2 = L_mac0_sat( E2, ptr[i], ptr[i] ); /*2*Q_exc */
391 : }
392 :
393 0 : exp_E3 = norm_l( E3 );
394 0 : frac_E3 = extract_h( L_shl( E3, exp_E3 ) );
395 0 : exp_E3 = sub( 30, add( exp_E3, 2 * ( *Q_exc ) ) );
396 :
397 0 : exp_E2 = norm_l( E2 );
398 0 : frac_E2 = round_fx_sat( L_shl_sat( E2, exp_E2 ) );
399 0 : exp_E2 = sub( 30, add( exp_E2, shl( ( *Q_exc ), 1 ) ) );
400 :
401 0 : scale = shr( sub( frac_E3, frac_E2 ), 15 );
402 0 : frac_E2 = shl( frac_E2, scale );
403 0 : exp_E2 = sub( exp_E2, scale );
404 :
405 0 : tmp = div_s( frac_E2, frac_E3 );
406 0 : exp = sub( exp_E2, exp_E3 );
407 :
408 0 : L_tmp1 = Isqrt_lc( L_deposit_h( tmp ), &exp ); /*Q(31-exp) */
409 :
410 0 : FOR( i = 0; i < L_FRAME; i++ )
411 : {
412 0 : L_tmp = Mult_32_16( L_tmp1, ptr[i] ); /*Q(16-exp+Q_exc) */
413 0 : ptr[i] = round_fx( L_shl( L_tmp, exp ) ); /*Q_exc */
414 0 : move16();
415 : }
416 : }
417 :
418 0 : Copy( ptr, exc_nelp, L_FRAME ); /*Q_exc */
419 0 : set16_fx( gain_buf, 0, NB_SUBFR16k );
420 0 : return;
421 : }
|