Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 : #include <stdint.h>
5 : #include "options.h" /* Compilation switches */
6 : #include "cnst.h" /* Common constants */
7 : #include "prot_fx.h" /* Function prototypes */
8 : #include "rom_com.h"
9 : #include "ivas_prot_fx.h"
10 :
11 :
12 : /*---------------------------------------------------------------------*
13 : * Local function prototypes
14 : *---------------------------------------------------------------------*/
15 : static Word16 FEC_phase_matching_fx( HQ_NBFEC_HANDLE st_fx, Word32 *ImdctOut_fx, Word16 *auOut_fx, Word16 *OldauOut_fx, Word16 OldauOut_pha_fx[2][N_LEAD_NB] );
16 : static void FEC_phase_matching_nextgood_fx( const Word32 *ImdctOut_fx, Word16 *auOut_fx, Word16 *OldauOut_fx, Word16 OldauOut_pha_fx[2][N_LEAD_NB], Word16 mean_en_high_fx );
17 : static void FEC_phase_matching_burst_fx( const Word32 *ImdctOut_fx, Word16 *auOut_fx, Word16 *OldauOut_fx, Word16 OldauOut_pha_fx[2][N_LEAD_NB], Word16 *prev_oldauOut_fx );
18 : static void Repetition_smoothing_nextgood_fx( const Word32 *ImdctOut_fx, Word16 *auOut_fx, Word32 *OldImdctOut_fx, Word16 *OldauOut_fx, Word16 cur_data_use_flag, Word16 overlap_time );
19 : static Word16 Repetition_smoothing_fx( const Word32 *ImdctOut_fx, Word16 *auOut_fx, Word32 *OldImdctOut_fx, Word16 *OldauOut_fx, const Word16 L, Word16 *prev_oldauOut_fx, Word16 overlap_time );
20 : static void Smoothing_vector_scaledown_NB_fx( const Word16 OldauOutnoWin_fx[], const Word16 ImdctOutWin_fx[], const Word16 SmoothingWin_fx[], Word16 auOut_fx[], const Word16 ol_size );
21 : static void Smoothing_vector_NB_fx( const Word16 OldauOutnoWin_fx[], const Word16 ImdctOutWin_fx[], const Word16 SmoothingWin_fx[], Word16 auOut_fx[], const Word16 ol_size );
22 : static void Windowing_1st_NB_fx( Word16 *ImdctOutWin_fx, const Word32 *ImdctOut_fx, const Word16 *win_fx, const Word16 *smoothingWin_fx, Word16 smoothing_flag );
23 : static void Windowing_2nd_NB_fx( Word16 *ImdctOutWin_fx, const Word32 *ImdctOut_fx, const Word16 *win_fx );
24 : static void Scaledown_fx( Word16 x[], Word16 y[], Word16 scale_v, const Word16 N );
25 : static void Next_good_after_burst_erasures_fx( const Word32 *ImdctOut_fx, Word16 *auOut_fx, Word16 *OldauOut_fx, const Word16 ol_size );
26 : static void common_overlapping_fx( Word16 *auOut_fx, Word16 *ImdctOutWin_fx, Word16 *OldauOut_fx, Word16 end1, Word16 offset1, Word16 start2, Word16 end2, Word16 offset_i2, Word16 offset2 );
27 :
28 : /*--------------------------------------------------------------------------*
29 : * Regression_Anal()
30 : *
31 : *
32 : *--------------------------------------------------------------------------*/
33 0 : static void Regression_Anal_fx(
34 : const Word32 *values_fx,
35 : /* i : Previous values */ // Q12
36 : Word32 *r_p_fx,
37 : /* o : Output r[a b] array : y=ax+b */ // Q5
38 : const Word16 num_pgf /* i : Number of previous good frame */
39 : )
40 : {
41 : Word16 i;
42 : Word16 tmp;
43 : Word32 L_tmp1, L_tmp2;
44 : Word16 aindex_fx[MAX_PGF + 1]; // Q0
45 : Word32 b_p_fx[MAX_PGF + 1]; // Q10
46 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
47 0 : Flag Overflow = 0;
48 0 : move32();
49 : #endif
50 :
51 : /* Initialize */
52 0 : FOR( i = 0; i < add( num_pgf, 1 ); i++ )
53 : {
54 0 : aindex_fx[i] = 0;
55 0 : move16();
56 0 : b_p_fx[i] = 0;
57 0 : move16();
58 : }
59 :
60 : /* [aindex[0] aindex[1]][r[0]]=[b[0]]*/
61 : /* [aindex[1] aindex[2]][r[1]] [b[1]]*/
62 : /* r[0] is the y-intercept(initial value). r[1] is slope*/
63 :
64 : /* r[0] = (b[0]a[2]-a[1]b[1])/(a[0]a[2]-a[1]a[1])
65 : r[1] = (b[0]a[1]-a[0]b[1])/(a[1]a[1]-a[0]a[2]) */
66 : /*aindex[0]=num_pgf; */
67 0 : aindex_fx[0] = num_pgf;
68 0 : move16();
69 0 : FOR( i = 1; i < add( num_pgf, 1 ); i++ )
70 : {
71 0 : aindex_fx[1] = add( aindex_fx[1], i );
72 0 : move16();
73 0 : aindex_fx[2] = add( aindex_fx[2], i_mult( i, i ) );
74 0 : move16();
75 : }
76 : /* Calculate b[] */
77 0 : FOR( i = 0; i < num_pgf; i++ )
78 : {
79 0 : b_p_fx[0] = L_add( b_p_fx[0], L_shr( values_fx[i], 2 ) ); /*10 */
80 0 : move32();
81 0 : b_p_fx[1] = L_add( b_p_fx[1], Mult_32_16( values_fx[i], shl_o( sub( num_pgf, i ), 13, &Overflow ) ) ); /*10 */
82 0 : move32();
83 : }
84 :
85 0 : tmp = sub( i_mult( aindex_fx[0], aindex_fx[2] ), i_mult( aindex_fx[1], aindex_fx[1] ) );
86 0 : tmp = inv_tbl_fx[tmp];
87 0 : move16(); /*15 */
88 0 : L_tmp1 = L_sub( Mult_32_16( b_p_fx[0], shl( aindex_fx[2], 10 ) ), Mult_32_16( b_p_fx[1], shl( aindex_fx[1], 10 ) ) ); /*5 */
89 0 : L_tmp2 = L_sub( Mult_32_16( b_p_fx[1], shl( aindex_fx[0], 10 ) ), Mult_32_16( b_p_fx[0], shl( aindex_fx[1], 10 ) ) ); /*5 */
90 0 : r_p_fx[0] = Mult_32_16( L_tmp1, tmp );
91 0 : move32();
92 0 : r_p_fx[1] = Mult_32_16( L_tmp2, tmp ); // Q15 + Q5 - Q15
93 0 : move32();
94 :
95 0 : return;
96 : }
97 :
98 0 : static void FEC_scaling_fx(
99 : Word32 *old_coeffs_fx,
100 : /* i/o : Pointer to old MDCT coeffs. */ // Q12
101 : Word32 *t_audio_q_fx,
102 : /* o : MDCT coeffs. (for synthesis) */ // Q12
103 : Word16 *Norm_gain_fx,
104 : /* i : Gain for Norm of each band */ // Q15
105 : Word16 *HQ_FEC_seed, /* i/o : Seed for Ransom number Generator */
106 : Word16 nb_sfm, /* i : Number of sub-band */
107 : const Word16 *start_band,
108 : const Word16 *end_band )
109 : {
110 : Word16 i, j;
111 :
112 0 : FOR( i = 0; i < RANDOM_START; i++ )
113 : {
114 0 : FOR( j = start_band[i]; j < end_band[i]; j++ )
115 : {
116 0 : t_audio_q_fx[j] = Mult_32_16( old_coeffs_fx[j], Norm_gain_fx[i] ); // Q12 + Q15 - Q15
117 0 : move32();
118 : }
119 : }
120 :
121 0 : FOR( i = RANDOM_START; i < nb_sfm; i++ )
122 : {
123 0 : FOR( j = start_band[i]; j < end_band[i]; j++ )
124 : {
125 0 : IF( Random( HQ_FEC_seed ) < 0 )
126 : {
127 0 : t_audio_q_fx[j] = Mult_32_16( L_negate( old_coeffs_fx[j] ), Norm_gain_fx[i] ); // Q12 + Q15 - Q15
128 0 : move32();
129 : }
130 : ELSE
131 : {
132 0 : t_audio_q_fx[j] = Mult_32_16( old_coeffs_fx[j], Norm_gain_fx[i] ); // Q12 + Q15 - Q15
133 0 : move32();
134 : }
135 : }
136 : }
137 0 : return;
138 : }
139 :
140 0 : void HQ_FEC_processing_fx(
141 : Decoder_State *st_fx, /* i/o: decoder state structure */
142 : Word32 *t_audio_q_fx, /* o : MDCT coeffs. (for synthesis) Q12 */
143 : Word16 is_transient, /* i : Old flag for transient */
144 : Word32 ynrm_values_fx[][MAX_PGF], /* i : Old average Norm values for each group of bands Q12 */
145 : Word32 r_p_values_fx[][MAX_ROW], /* i : Computed y-intercept and slope by Regression Q5 */
146 : Word16 num_Sb, /* i : Number of sub-band group */
147 : Word16 nb_sfm, /* i : Number of sub-band */
148 : Word16 *Num_bands_p, /* i : Number of coeffs. for each sub-band */
149 : Word16 output_frame, /* i : Frame size */
150 : const Word16 *sfm_start, /* i : Start of bands */
151 : const Word16 *sfm_end /* i : End of bands */
152 : )
153 : {
154 : Word16 i, j, k;
155 : Word16 mute_start, num_pgf;
156 : Word16 Num_sb_bwe;
157 : Word16 sfm;
158 :
159 : Word16 tmp_fx, exp1, exp2;
160 : Word32 norm_p_fx[MAX_SB_NB];
161 : Word32 *norm_values_fx /*Q12*/, *r_p_fx /*Q5*/;
162 : Word16 energy_diff_fx; // Q10
163 : HQ_NBFEC_HANDLE hHQ_nbfec;
164 : HQ_DEC_HANDLE hHQ_core;
165 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
166 0 : Flag Overflow = 0;
167 0 : move32();
168 : #endif
169 0 : hHQ_nbfec = st_fx->hHQ_nbfec;
170 0 : hHQ_core = st_fx->hHQ_core;
171 :
172 :
173 : /* Decide the start frame number for adaptive muting */
174 : /* Normalized energy difference between the current frame and the moving average */
175 0 : tmp_fx = abs_s( sub( hHQ_nbfec->energy_MA_Curr_fx[1], hHQ_nbfec->energy_MA_Curr_fx[0] ) );
176 0 : exp1 = sub( norm_s( tmp_fx ), 1 );
177 0 : hHQ_nbfec->energy_MA_Curr_fx[0] = s_max( hHQ_nbfec->energy_MA_Curr_fx[0], 1 );
178 0 : move16();
179 0 : exp2 = norm_s( hHQ_nbfec->energy_MA_Curr_fx[0] );
180 0 : tmp_fx = div_s( shl( tmp_fx, exp1 ), shl( hHQ_nbfec->energy_MA_Curr_fx[0], exp2 ) ); /*15 + exp1 - exp2*/
181 0 : energy_diff_fx = shl( tmp_fx, sub( sub( exp2, exp1 ), 5 ) ); /*10*/
182 0 : test();
183 0 : IF( ( LT_16( energy_diff_fx, 1024 ) ) && ( is_transient == 0 ) ) /* First erasure frame */
184 : {
185 0 : mute_start = 5;
186 0 : move16();
187 : }
188 : ELSE
189 : {
190 0 : mute_start = 2;
191 0 : move16();
192 : }
193 0 : test();
194 0 : test();
195 0 : IF( EQ_16( st_fx->prev_old_bfi, 1 ) && EQ_16( st_fx->nbLostCmpt, 1 ) && EQ_16( output_frame, L_FRAME8k ) )
196 : {
197 0 : st_fx->nbLostCmpt = add( st_fx->nbLostCmpt, 1 );
198 0 : move32();
199 : }
200 :
201 : /* Frequency-domain FEC */
202 0 : IF( EQ_16( st_fx->nbLostCmpt, 1 ) ) /* First erasure frame */
203 : {
204 0 : IF( is_transient == 0 )
205 : {
206 0 : IF( LT_16( energy_diff_fx, 1024 ) )
207 : {
208 0 : FOR( i = 0; i < output_frame; i++ )
209 : {
210 0 : t_audio_q_fx[i] = hHQ_nbfec->old_coeffs_fx[i];
211 0 : move32();
212 : }
213 : }
214 : ELSE
215 : {
216 0 : FOR( i = 0; i < output_frame; i++ )
217 : {
218 0 : hHQ_nbfec->old_coeffs_fx[i] = Mult_32_16( hHQ_nbfec->old_coeffs_fx[i], 23170 ); /*23170, 3dB, Q15*/
219 0 : move32();
220 0 : t_audio_q_fx[i] = hHQ_nbfec->old_coeffs_fx[i];
221 0 : move32();
222 : }
223 : }
224 :
225 : /* Sign prediction in 4-dim bands up to 1.6 kHz*/
226 0 : IF( hHQ_core->old_is_transient[1] == 0 )
227 : {
228 0 : IF( hHQ_core->old_is_transient[2] == 0 )
229 : {
230 0 : FOR( sfm = 0; sfm < HQ_FEC_SIGN_SFM; sfm++ )
231 : {
232 0 : IF( GE_16( hHQ_nbfec->prev_sign_switch[sfm], HQ_FEC_SIGN_THRES ) )
233 : {
234 0 : FOR( i = 0; i < HQ_FEC_BAND_SIZE; i++ )
235 : {
236 0 : t_audio_q_fx[i + sfm * HQ_FEC_BAND_SIZE] = L_negate( t_audio_q_fx[i + sfm * HQ_FEC_BAND_SIZE] );
237 0 : move32();
238 : }
239 : }
240 : }
241 : }
242 : ELSE
243 : {
244 0 : FOR( sfm = 0; sfm < HQ_FEC_SIGN_SFM; sfm++ )
245 : {
246 0 : IF( GE_16( hHQ_nbfec->prev_sign_switch[sfm], HQ_FEC_SIGN_THRES_TRANS ) )
247 : {
248 0 : FOR( i = 0; i < HQ_FEC_BAND_SIZE; i++ )
249 : {
250 0 : t_audio_q_fx[i + sfm * HQ_FEC_BAND_SIZE] = L_negate( t_audio_q_fx[i + sfm * HQ_FEC_BAND_SIZE] );
251 0 : move32();
252 : }
253 : }
254 : }
255 : }
256 : }
257 : ELSE
258 : {
259 0 : FOR( i = RANDOM_START * 8; i < output_frame; i++ )
260 : {
261 0 : IF( Random( &hHQ_nbfec->HQ_FEC_seed ) < 0 )
262 : {
263 0 : t_audio_q_fx[i] = L_negate( t_audio_q_fx[i] );
264 0 : move32();
265 : }
266 : }
267 : }
268 : }
269 : ELSE
270 : {
271 0 : IF( hHQ_core->old_is_transient[1] ) /* hangover */
272 : {
273 0 : FOR( i = 0; i < output_frame; i++ )
274 : {
275 0 : hHQ_nbfec->old_coeffs_fx[i] = Mult_32_16( hHQ_nbfec->old_coeffs_fx[i], 23170 );
276 0 : move32();
277 0 : t_audio_q_fx[i] = hHQ_nbfec->old_coeffs_fx[i];
278 0 : move32();
279 : }
280 : }
281 : ELSE
282 : {
283 0 : FOR( i = 0; i < RANDOM_START * 8; i++ )
284 : {
285 0 : hHQ_nbfec->old_coeffs_fx[i] = Mult_32_16( hHQ_nbfec->old_coeffs_fx[i], 23170 );
286 0 : move32();
287 0 : t_audio_q_fx[i] = hHQ_nbfec->old_coeffs_fx[i];
288 0 : move32();
289 : }
290 :
291 0 : FOR( i = RANDOM_START * 8; i < output_frame; i++ )
292 : {
293 0 : hHQ_nbfec->old_coeffs_fx[i] = Mult_32_16( hHQ_nbfec->old_coeffs_fx[i], 23170 );
294 0 : move32();
295 0 : IF( Random( &hHQ_nbfec->HQ_FEC_seed ) < 0 )
296 : {
297 0 : t_audio_q_fx[i] = L_negate( hHQ_nbfec->old_coeffs_fx[i] );
298 0 : move32();
299 : }
300 : ELSE
301 : {
302 0 : t_audio_q_fx[i] = hHQ_nbfec->old_coeffs_fx[i];
303 0 : move32();
304 : }
305 : }
306 : }
307 : }
308 : }
309 : ELSE /* st_fx->nbLostCmpt > 1 */
310 : {
311 0 : test();
312 0 : IF( LT_16( energy_diff_fx, 1024 ) && is_transient == 0 )
313 : {
314 0 : num_pgf = 4;
315 0 : move16();
316 : }
317 : ELSE
318 : {
319 0 : num_pgf = 2;
320 0 : move16();
321 : }
322 :
323 0 : Num_sb_bwe = num_Sb;
324 0 : move16();
325 0 : IF( EQ_16( st_fx->nbLostCmpt, 2 ) )
326 : {
327 :
328 0 : FOR( i = 0; i < Num_sb_bwe; i++ )
329 : {
330 0 : norm_values_fx = &ynrm_values_fx[i][0]; /*Q12*/
331 0 : r_p_fx = &r_p_values_fx[i][0]; /*Q5*/
332 0 : Regression_Anal_fx( norm_values_fx, r_p_fx, num_pgf );
333 : }
334 : }
335 :
336 : /* Fade-out Norm by the result of Regression */
337 0 : IF( GE_16( st_fx->nbLostCmpt, mute_start ) )
338 : {
339 : /* Scaling */
340 0 : FOR( i = 0; i < output_frame; i++ )
341 : {
342 0 : hHQ_nbfec->old_coeffs_fx[i] = Mult_32_16( hHQ_nbfec->old_coeffs_fx[i], 23170 );
343 0 : move32();
344 : }
345 : }
346 :
347 0 : k = 0;
348 0 : move16();
349 0 : FOR( i = 0; i < Num_sb_bwe; i++ )
350 : {
351 0 : norm_values_fx = &ynrm_values_fx[i][0];
352 0 : r_p_fx = &r_p_values_fx[i][0];
353 :
354 : /* Predict the average energy of each sub-band using Regression */
355 : /* Linear Regression */
356 0 : IF( r_p_fx[1] > 0 )
357 : {
358 0 : r_p_fx[1] = L_deposit_l( 0 );
359 0 : move32();
360 0 : norm_p_fx[i] = L_shr( norm_values_fx[0], 7 ); /*5*/
361 0 : move32();
362 : }
363 : ELSE
364 : {
365 0 : norm_p_fx[i] = L_add( r_p_fx[0], L_mult0( extract_l( r_p_fx[1] ), sub( add( st_fx->nbLostCmpt, num_pgf ), 1 ) ) );
366 0 : move32();
367 : }
368 :
369 0 : test();
370 0 : IF( norm_values_fx[0] != 0 && norm_p_fx[i] > 0 ) /* Avoid negative value of the predicted energy */
371 : {
372 0 : exp1 = sub( norm_l( norm_p_fx[i] ), 1 );
373 0 : exp2 = norm_l( norm_values_fx[0] );
374 0 : tmp_fx = div_s( extract_h( L_shl( norm_p_fx[i], exp1 ) ),
375 0 : extract_h( L_shl( norm_values_fx[0], exp2 ) ) ); /*15 + (5 + exp1 - 16) - (12 + exp2 - 16)*/
376 0 : tmp_fx = shl_sat( tmp_fx, add( 6, sub( exp2, exp1 ) ) ); /*14*/
377 0 : if ( GT_16( tmp_fx, 16384 ) )
378 : {
379 0 : tmp_fx = 16384;
380 0 : move16();
381 : }
382 :
383 0 : FOR( j = 0; j < Num_bands_p[i]; j++ )
384 : {
385 0 : hHQ_nbfec->Norm_gain_fx[k] = shl_o( tmp_fx, 1, &Overflow );
386 0 : move16();
387 0 : k = add( k, 1 );
388 : }
389 : }
390 : ELSE
391 : {
392 : /* Scale down the last gain with the fixed gain(-3dB) */
393 0 : FOR( j = 0; j < Num_bands_p[i]; j++ )
394 : {
395 0 : hHQ_nbfec->Norm_gain_fx[k] = mult_r( hHQ_nbfec->Norm_gain_fx[k], 23170 );
396 0 : move16();
397 0 : k = add( k, 1 );
398 : }
399 : }
400 : }
401 :
402 : /* Scaling for core band */
403 0 : FEC_scaling_fx( hHQ_nbfec->old_coeffs_fx, t_audio_q_fx, hHQ_nbfec->Norm_gain_fx, &hHQ_nbfec->HQ_FEC_seed, nb_sfm, sfm_start, sfm_end );
404 : }
405 :
406 :
407 0 : return;
408 : }
409 :
410 7331 : void ivas_HQ_FEC_Mem_update_fx(
411 : Decoder_State *st_fx, /* i/o: decoder state structure */
412 : Word32 *t_audio_q_fx, /*Q12*/
413 : Word32 *normq_fx, /*Q14*/
414 : Word16 *ynrm,
415 : Word16 *Num_bands_p,
416 : Word16 is_transient,
417 : Word16 hqswb_clas,
418 : Word16 c_switching_flag,
419 : Word16 nb_sfm,
420 : Word16 num_Sb,
421 : Word16 *mean_en_high_fx, /*Q5*/
422 : Word16 hq_core_type, /* i : normal or low-rate MDCT(HQ) core */
423 : Word16 output_frame )
424 : {
425 : Word16 Min_ind;
426 : Word32 Min_value;
427 : Word16 Max_ind;
428 : Word16 stat_mode_curr;
429 :
430 : Word16 i, j, k;
431 : Word16 offset;
432 : Word16 exp, exp1, exp2, tmp_fx;
433 : Word32 *norm_values_fx; // Q12
434 7331 : Word32 L_tmp, tmp_energy_fx = 0 /*Q8*/, Max_coeff_fx /*Q12*/;
435 : Word32 en_high_fx[MAX_SB_NB]; // Q12
436 : HQ_NBFEC_HANDLE hHQ_nbfec;
437 : HQ_DEC_HANDLE hHQ_core;
438 7331 : hHQ_nbfec = st_fx->hHQ_nbfec;
439 7331 : hHQ_core = st_fx->hHQ_core;
440 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
441 7331 : Flag Overflow = 0;
442 7331 : move32();
443 : #endif
444 7331 : move32(); // for tmp_energy_fx
445 7331 : IF( EQ_16( output_frame, L_FRAME8k ) )
446 : {
447 :
448 0 : IF( is_transient )
449 : {
450 0 : set16_fx( hHQ_nbfec->prev_sign_switch_2, 0, HQ_FEC_SIGN_SFM );
451 0 : set16_fx( hHQ_nbfec->prev_sign_switch, 0, HQ_FEC_SIGN_SFM );
452 : }
453 : ELSE
454 : {
455 0 : FOR( j = 0; j < HQ_FEC_SIGN_SFM; j++ )
456 : {
457 0 : hHQ_nbfec->prev_sign_switch[j] = hHQ_nbfec->prev_sign_switch_2[j];
458 0 : move16();
459 0 : hHQ_nbfec->prev_sign_switch_2[j] = 0;
460 0 : move16();
461 :
462 0 : FOR( i = 0; i < HQ_FEC_BAND_SIZE; i++ )
463 : {
464 0 : test();
465 0 : test();
466 0 : test();
467 0 : IF( ( hHQ_nbfec->old_coeffs_fx[i + j * HQ_FEC_BAND_SIZE] > 0 && t_audio_q_fx[i + j * HQ_FEC_BAND_SIZE] < 0 ) || ( hHQ_nbfec->old_coeffs_fx[i + j * HQ_FEC_BAND_SIZE] < 0 && t_audio_q_fx[i + j * HQ_FEC_BAND_SIZE] > 0 ) )
468 : {
469 0 : hHQ_nbfec->prev_sign_switch[j] = add( hHQ_nbfec->prev_sign_switch[j], 1 );
470 0 : move16();
471 0 : hHQ_nbfec->prev_sign_switch_2[j] = add( hHQ_nbfec->prev_sign_switch_2[j], 1 );
472 0 : move16();
473 : }
474 : }
475 : }
476 : }
477 : /* if LR MDCT core is used, recalculate norms from decoded MDCT spectrum (using code from hq_hr_enc_fx()) */
478 0 : test();
479 0 : IF( ( EQ_16( hqswb_clas, HQ_HVQ ) ) || ( EQ_16( hq_core_type, LOW_RATE_HQ_CORE ) ) )
480 : {
481 : /* First group */
482 0 : logqnorm_fx( t_audio_q_fx, 12, ynrm, 32, WID_G1, (const Word16) EQ_16( hqswb_clas, HQ_HVQ ) );
483 0 : j = ynrm[0];
484 0 : move16();
485 0 : offset = WID_G1;
486 0 : move16();
487 :
488 0 : FOR( i = 1; i < SFM_G1; i++ )
489 : {
490 0 : logqnorm_fx( &t_audio_q_fx[offset], 12, &ynrm[i], 40, WID_G1, (const Word16) EQ_16( hqswb_clas, HQ_HVQ ) );
491 0 : offset = add( offset, WID_G1 );
492 : }
493 :
494 : /* Second group */
495 0 : FOR( i = SFM_G1; i < SFM_G1 + 2; i++ )
496 : {
497 0 : logqnorm_fx( &t_audio_q_fx[offset], 12, &ynrm[i], 40, WID_G2, (const Word16) EQ_16( hqswb_clas, HQ_HVQ ) );
498 0 : offset = add( offset, WID_G2 );
499 : }
500 : }
501 :
502 : /* Memory update for the LGF log2 Norm */
503 0 : FOR( i = 0; i < nb_sfm; i++ )
504 : {
505 0 : normq_fx[i] = dicn_fx[ynrm[i]];
506 0 : move32();
507 : }
508 0 : k = 0;
509 0 : move16();
510 0 : FOR( i = 0; i < num_Sb; i++ )
511 : {
512 0 : norm_values_fx = &hHQ_nbfec->ynrm_values_fx[i][0];
513 0 : Copy32( norm_values_fx, &norm_values_fx[1], MAX_PGF - 1 );
514 :
515 0 : L_tmp = L_deposit_l( 0 );
516 0 : FOR( j = 0; j < Num_bands_p[i]; j++ )
517 : {
518 0 : L_tmp = L_add( L_tmp, L_shr( normq_fx[k], 3 ) ); /*11*/
519 0 : k = add( k, 1 );
520 : }
521 0 : tmp_fx = shl_o( inv_tbl_fx[Num_bands_p[i]], 1, &Overflow ); /*16*/
522 0 : norm_values_fx[0] = Mult_32_16( L_tmp, tmp_fx ); /*11 + 16 - 15*/
523 0 : move32();
524 0 : tmp_energy_fx = L_add( tmp_energy_fx, L_shr( L_tmp, 3 ) ); /*8*/
525 : }
526 0 : test();
527 0 : test();
528 0 : IF( ( c_switching_flag ) || ( ( st_fx->last_core == ACELP_CORE ) && ( EQ_16( st_fx->core, HQ_CORE ) ) ) )
529 : {
530 0 : FOR( i = 0; i < MAX_SB_NB; i++ )
531 : {
532 0 : FOR( j = 1; j < MAX_PGF; j++ )
533 : {
534 0 : hHQ_nbfec->ynrm_values_fx[i][j] = hHQ_nbfec->ynrm_values_fx[i][0];
535 0 : move32();
536 : }
537 : }
538 : }
539 0 : set16_fx( hHQ_nbfec->Norm_gain_fx, 32767, SFM_N_NB ); /*15*/
540 : /* st->energy_MA_Curr[1]=Energy of the current frame */
541 0 : tmp_fx = inv_tbl_fx[nb_sfm];
542 0 : move16(); /*15*/
543 0 : L_tmp = Mult_32_16( tmp_energy_fx, tmp_fx ); /*8 + 15 - 15*/
544 :
545 0 : hHQ_nbfec->energy_MA_Curr_fx[1] = extract_h( L_shl( L_tmp, 16 - 8 ) );
546 0 : move16();
547 : /* Moving Average */
548 0 : hHQ_nbfec->energy_MA_Curr_fx[0] = s_max( 1, add( mult_r( 26214, hHQ_nbfec->energy_MA_Curr_fx[0] ), mult_r( 6554, hHQ_nbfec->energy_MA_Curr_fx[1] ) ) );
549 0 : move16();
550 :
551 : /*st->diff_energy = (float)fabs((st->energy_MA_Curr[1] - st->energy_MA_Curr[0])/st->energy_MA_Curr[0]); */
552 0 : hHQ_nbfec->diff_energy_fx = abs_s( sub( hHQ_nbfec->energy_MA_Curr_fx[1], hHQ_nbfec->energy_MA_Curr_fx[0] ) );
553 0 : move16();
554 0 : exp1 = sub( norm_l( hHQ_nbfec->diff_energy_fx ), 1 );
555 0 : exp2 = norm_l( hHQ_nbfec->energy_MA_Curr_fx[0] );
556 0 : hHQ_nbfec->diff_energy_fx = div_s( extract_h( L_shl( hHQ_nbfec->diff_energy_fx, exp1 ) ), extract_h( L_shl( hHQ_nbfec->energy_MA_Curr_fx[0], exp2 ) ) );
557 0 : move16();
558 0 : exp = add( 15, sub( exp1, exp2 ) );
559 0 : hHQ_nbfec->diff_energy_fx = shl( hHQ_nbfec->diff_energy_fx, sub( 11, exp ) ); /*11*/
560 0 : move16();
561 :
562 : /* Classify the stationary mode : 12% */
563 0 : IF( LT_16( hHQ_nbfec->diff_energy_fx, ED_THRES_12P_fx ) )
564 : {
565 0 : stat_mode_curr = 1;
566 0 : move16();
567 : }
568 : ELSE
569 : {
570 0 : stat_mode_curr = 0;
571 0 : move16();
572 : }
573 :
574 : /* Apply Hysteresis to prevent frequent mode changing */
575 0 : if ( EQ_16( hHQ_nbfec->stat_mode_old, stat_mode_curr ) )
576 : {
577 0 : hHQ_nbfec->stat_mode_out = stat_mode_curr;
578 0 : move16();
579 : }
580 :
581 0 : hHQ_nbfec->stat_mode_old = stat_mode_curr;
582 0 : move16();
583 :
584 : /* Find max. band index (Minimum value means maximum energy) */
585 0 : Min_ind = 0;
586 0 : move16();
587 0 : Min_value = L_deposit_l( 100 );
588 0 : FOR( i = 0; i < num_Sb; i++ )
589 : {
590 0 : IF( GT_32( Min_value, ynrm[i] ) )
591 : {
592 0 : Min_value = ynrm[i];
593 0 : move16();
594 0 : Min_ind = i;
595 0 : move16();
596 : }
597 : }
598 :
599 : /* Find max. coeff in band 0 */
600 0 : Max_ind = 0;
601 0 : move16();
602 0 : IF( Min_ind == 0 )
603 : {
604 0 : Max_coeff_fx = L_deposit_l( 0 );
605 0 : FOR( i = 0; i < 8; i++ )
606 : {
607 0 : L_tmp = L_abs( t_audio_q_fx[i] ); // Q12
608 0 : IF( LT_32( Max_coeff_fx, L_tmp ) )
609 : {
610 0 : Max_coeff_fx = L_add( L_tmp, 0 );
611 0 : Max_ind = i;
612 0 : move16();
613 : }
614 : }
615 : }
616 :
617 : /* Find energy difference from band 16 */
618 0 : k = 1;
619 0 : move16();
620 :
621 0 : FOR( i = k; i < num_Sb; i++ )
622 : {
623 0 : en_high_fx[i] = L_deposit_l( 0 );
624 0 : FOR( j = 0; j < 2; j++ )
625 : {
626 : /*en_high[i] += 0.5f*st->ynrm_values[i][j+1];*/
627 0 : en_high_fx[i] = L_add( en_high_fx[i], L_shr( hHQ_nbfec->ynrm_values_fx[i][j + 1], 1 ) ); /*Q12*/
628 0 : move32();
629 : }
630 : }
631 :
632 0 : *mean_en_high_fx = 0;
633 0 : move16();
634 0 : FOR( i = k; i < num_Sb; i++ )
635 : {
636 : /* *mean_en_high += (float)(en_high[i]/st->ynrm_values[i][0]);*/
637 0 : exp1 = sub( norm_l( en_high_fx[i] ), 1 );
638 0 : exp2 = norm_l( hHQ_nbfec->ynrm_values_fx[i][0] );
639 0 : tmp_fx = div_s( extract_h( L_shl( en_high_fx[i], exp1 ) ), extract_h( L_shl( hHQ_nbfec->ynrm_values_fx[i][0], exp2 ) ) );
640 0 : exp = add( 15, sub( exp1, exp2 ) );
641 0 : *mean_en_high_fx = add_o( *mean_en_high_fx, shr_o( tmp_fx, sub( exp, 5 ), &Overflow ), &Overflow );
642 0 : move16();
643 : }
644 0 : *mean_en_high_fx = mult( *mean_en_high_fx, inv_tbl_fx[sub( num_Sb, k )] );
645 0 : move16();
646 :
647 0 : test();
648 0 : test();
649 0 : test();
650 0 : test();
651 0 : test();
652 0 : test();
653 0 : test();
654 0 : test();
655 0 : test();
656 0 : IF( ( LT_16( Min_ind, 5 ) ) && ( LT_16( abs_s( sub( Min_ind, hHQ_nbfec->old_Min_ind ) ), 2 ) ) && ( LT_16( hHQ_nbfec->diff_energy_fx, ED_THRES_90P_fx ) ) && ( !st_fx->bfi ) && ( !st_fx->prev_bfi ) && ( !st_fx->prev_old_bfi ) && ( !is_transient ) && ( !hHQ_core->old_is_transient[1] ) && ( EQ_16( hHQ_nbfec->prev_last_core, HQ_CORE ) ) && ( EQ_16( st_fx->last_core, HQ_CORE ) ) )
657 : {
658 0 : hHQ_nbfec->phase_mat_flag = 1;
659 0 : move16();
660 0 : test();
661 0 : if ( ( Min_ind == 0 ) && ( LT_16( Max_ind, 3 ) ) )
662 : {
663 0 : hHQ_nbfec->phase_mat_flag = 0;
664 0 : move16();
665 : }
666 : }
667 : ELSE
668 : {
669 0 : hHQ_nbfec->phase_mat_flag = 0;
670 0 : move16();
671 : }
672 :
673 0 : hHQ_nbfec->old_Min_ind = Min_ind;
674 0 : move16();
675 :
676 0 : FOR( i = 0; i < L_FRAME8k; i++ )
677 : {
678 0 : hHQ_nbfec->old_coeffs_fx[i] = t_audio_q_fx[i];
679 0 : move32();
680 : }
681 : }
682 :
683 7331 : hHQ_core->old_is_transient[2] = hHQ_core->old_is_transient[1];
684 7331 : move16();
685 7331 : hHQ_core->old_is_transient[1] = hHQ_core->old_is_transient[0];
686 7331 : move16();
687 7331 : hHQ_core->old_is_transient[0] = is_transient;
688 7331 : move16();
689 :
690 7331 : return;
691 : }
692 :
693 429 : void HQ_FEC_Mem_update_fx(
694 : Decoder_State *st_fx, /* i/o: decoder state structure */
695 : Word32 *t_audio_q_fx, /*Q12*/
696 : Word32 *normq_fx, /*Q14*/
697 : Word16 *ynrm,
698 : Word16 *Num_bands_p,
699 : Word16 is_transient,
700 : Word16 hqswb_clas,
701 : Word16 c_switching_flag,
702 : Word16 nb_sfm,
703 : Word16 num_Sb,
704 : Word16 *mean_en_high_fx, /*Q5*/
705 : Word16 hq_core_type, /* i : normal or low-rate MDCT(HQ) core */
706 : Word16 output_frame )
707 : {
708 : Word16 Min_ind;
709 : Word32 Min_value;
710 : Word16 Max_ind;
711 : Word16 stat_mode_curr;
712 :
713 : Word16 i, j, k;
714 : Word16 offset;
715 : Word16 exp, exp1, exp2, tmp_fx;
716 : Word32 *norm_values_fx; // Q12
717 429 : Word32 L_tmp, tmp_energy_fx = 0 /*Q8*/, Max_coeff_fx /*Q12*/;
718 : Word32 en_high_fx[MAX_SB_NB]; // Q12
719 : HQ_NBFEC_HANDLE hHQ_nbfec;
720 : HQ_DEC_HANDLE hHQ_core;
721 429 : hHQ_nbfec = st_fx->hHQ_nbfec;
722 429 : hHQ_core = st_fx->hHQ_core;
723 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
724 429 : Flag Overflow = 0;
725 429 : move32();
726 : #endif
727 429 : move32(); // tmp_energy_fx
728 :
729 429 : IF( EQ_16( output_frame, L_FRAME8k ) )
730 : {
731 :
732 0 : IF( is_transient )
733 : {
734 0 : set16_fx( hHQ_nbfec->prev_sign_switch_2, 0, HQ_FEC_SIGN_SFM );
735 0 : set16_fx( hHQ_nbfec->prev_sign_switch, 0, HQ_FEC_SIGN_SFM );
736 : }
737 : ELSE
738 : {
739 0 : FOR( j = 0; j < HQ_FEC_SIGN_SFM; j++ )
740 : {
741 0 : hHQ_nbfec->prev_sign_switch[j] = hHQ_nbfec->prev_sign_switch_2[j];
742 0 : move16();
743 0 : hHQ_nbfec->prev_sign_switch_2[j] = 0;
744 0 : move16();
745 :
746 0 : FOR( i = 0; i < HQ_FEC_BAND_SIZE; i++ )
747 : {
748 0 : test();
749 0 : test();
750 0 : test();
751 0 : IF( ( hHQ_nbfec->old_coeffs_fx[i + j * HQ_FEC_BAND_SIZE] > 0 && t_audio_q_fx[i + j * HQ_FEC_BAND_SIZE] < 0 ) || ( hHQ_nbfec->old_coeffs_fx[i + j * HQ_FEC_BAND_SIZE] < 0 && t_audio_q_fx[i + j * HQ_FEC_BAND_SIZE] > 0 ) )
752 : {
753 0 : hHQ_nbfec->prev_sign_switch[j] = add( hHQ_nbfec->prev_sign_switch[j], 1 );
754 0 : move16();
755 0 : hHQ_nbfec->prev_sign_switch_2[j] = add( hHQ_nbfec->prev_sign_switch_2[j], 1 );
756 0 : move16();
757 : }
758 : }
759 : }
760 : }
761 :
762 : /* if LR MDCT core is used, recalculate norms from decoded MDCT spectrum (using code from hq_hr_enc_fx()) */
763 0 : test();
764 0 : IF( ( EQ_16( hqswb_clas, HQ_HVQ ) ) || ( EQ_16( hq_core_type, LOW_RATE_HQ_CORE ) ) )
765 : {
766 : /* First group */
767 0 : logqnorm_fx( t_audio_q_fx, 12, ynrm, 32, WID_G1, (const Word16) EQ_16( hqswb_clas, HQ_HVQ ) );
768 0 : j = ynrm[0];
769 0 : move16();
770 0 : offset = WID_G1;
771 0 : move16();
772 :
773 0 : FOR( i = 1; i < SFM_G1; i++ )
774 : {
775 0 : logqnorm_fx( &t_audio_q_fx[offset], 12, &ynrm[i], 40, WID_G1, (const Word16) EQ_16( hqswb_clas, HQ_HVQ ) );
776 0 : offset = add( offset, WID_G1 );
777 : }
778 :
779 : /* Second group */
780 0 : FOR( i = SFM_G1; i < SFM_G1 + 2; i++ )
781 : {
782 0 : logqnorm_fx( &t_audio_q_fx[offset], 12, &ynrm[i], 40, WID_G2, (const Word16) EQ_16( hqswb_clas, HQ_HVQ ) );
783 0 : offset = add( offset, WID_G2 );
784 : }
785 : }
786 :
787 : /* Memory update for the LGF log2 Norm */
788 0 : FOR( i = 0; i < nb_sfm; i++ )
789 : {
790 0 : normq_fx[i] = dicn_fx[ynrm[i]];
791 0 : move32();
792 : }
793 0 : k = 0;
794 0 : move16();
795 0 : FOR( i = 0; i < num_Sb; i++ )
796 : {
797 0 : norm_values_fx = &hHQ_nbfec->ynrm_values_fx[i][0];
798 0 : Copy32( norm_values_fx, &norm_values_fx[1], MAX_PGF - 1 );
799 :
800 0 : L_tmp = L_deposit_l( 0 );
801 0 : FOR( j = 0; j < Num_bands_p[i]; j++ )
802 : {
803 0 : L_tmp = L_add( L_tmp, L_shr( normq_fx[k], 3 ) ); /*11*/
804 0 : k = add( k, 1 );
805 : }
806 0 : tmp_fx = shl_o( inv_tbl_fx[Num_bands_p[i]], 1, &Overflow ); /*16*/
807 0 : norm_values_fx[0] = Mult_32_16( L_tmp, tmp_fx ); /*11 + 16 - 15*/
808 0 : move32();
809 0 : tmp_energy_fx = L_add( tmp_energy_fx, L_shr( L_tmp, 3 ) ); /*8*/
810 : }
811 0 : test();
812 0 : test();
813 0 : IF( ( c_switching_flag ) || ( ( st_fx->last_core == ACELP_CORE ) && ( EQ_16( st_fx->core, HQ_CORE ) ) ) )
814 : {
815 0 : FOR( i = 0; i < MAX_SB_NB; i++ )
816 : {
817 0 : FOR( j = 1; j < MAX_PGF; j++ )
818 : {
819 0 : hHQ_nbfec->ynrm_values_fx[i][j] = hHQ_nbfec->ynrm_values_fx[i][0];
820 0 : move32();
821 : }
822 : }
823 : }
824 0 : set16_fx( hHQ_nbfec->Norm_gain_fx, 32767, SFM_N_NB ); /*15*/
825 : /* st->energy_MA_Curr[1]=Energy of the current frame */
826 0 : tmp_fx = inv_tbl_fx[nb_sfm];
827 0 : move16(); /*15*/
828 0 : L_tmp = Mult_32_16( tmp_energy_fx, tmp_fx ); /*8 + 15 - 15*/
829 :
830 0 : hHQ_nbfec->energy_MA_Curr_fx[1] = extract_h( L_shl_sat( L_tmp, 16 - 8 ) );
831 0 : move16();
832 : /* Moving Average */
833 0 : hHQ_nbfec->energy_MA_Curr_fx[0] = s_max( 1, add( mult_r( 26214, hHQ_nbfec->energy_MA_Curr_fx[0] ), mult_r( 6554, hHQ_nbfec->energy_MA_Curr_fx[1] ) ) );
834 0 : move16();
835 :
836 : /*st->diff_energy = (float)fabs((st->energy_MA_Curr[1] - st->energy_MA_Curr[0])/st->energy_MA_Curr[0]); */
837 0 : hHQ_nbfec->diff_energy_fx = abs_s( sub( hHQ_nbfec->energy_MA_Curr_fx[1], hHQ_nbfec->energy_MA_Curr_fx[0] ) );
838 0 : move16();
839 0 : exp1 = sub( norm_l( hHQ_nbfec->diff_energy_fx ), 1 );
840 0 : exp2 = norm_l( hHQ_nbfec->energy_MA_Curr_fx[0] );
841 0 : hHQ_nbfec->diff_energy_fx = div_s( extract_h( L_shl( hHQ_nbfec->diff_energy_fx, exp1 ) ), extract_h( L_shl( hHQ_nbfec->energy_MA_Curr_fx[0], exp2 ) ) );
842 0 : move16();
843 0 : exp = add( 15, sub( exp1, exp2 ) );
844 0 : hHQ_nbfec->diff_energy_fx = shl( hHQ_nbfec->diff_energy_fx, sub( 11, exp ) ); /*11*/
845 0 : move16();
846 :
847 : /* Classify the stationary mode : 12% */
848 0 : IF( LT_16( hHQ_nbfec->diff_energy_fx, ED_THRES_12P_fx ) )
849 : {
850 0 : stat_mode_curr = 1;
851 0 : move16();
852 : }
853 : ELSE
854 : {
855 0 : stat_mode_curr = 0;
856 0 : move16();
857 : }
858 :
859 : /* Apply Hysteresis to prevent frequent mode changing */
860 0 : if ( EQ_16( hHQ_nbfec->stat_mode_old, stat_mode_curr ) )
861 : {
862 0 : hHQ_nbfec->stat_mode_out = stat_mode_curr;
863 0 : move16();
864 : }
865 :
866 0 : hHQ_nbfec->stat_mode_old = stat_mode_curr;
867 0 : move16();
868 :
869 : /* Find max. band index (Minimum value means maximum energy) */
870 0 : Min_ind = 0;
871 0 : move16();
872 0 : Min_value = L_deposit_l( 100 );
873 0 : FOR( i = 0; i < num_Sb; i++ )
874 : {
875 0 : IF( GT_32( Min_value, ynrm[i] ) )
876 : {
877 0 : Min_value = ynrm[i];
878 0 : move16();
879 0 : Min_ind = i;
880 0 : move16();
881 : }
882 : }
883 :
884 : /* Find max. coeff in band 0 */
885 0 : Max_ind = 0;
886 0 : move16();
887 0 : IF( Min_ind == 0 )
888 : {
889 0 : Max_coeff_fx = L_deposit_l( 0 );
890 0 : FOR( i = 0; i < 8; i++ )
891 : {
892 0 : L_tmp = L_abs( t_audio_q_fx[i] );
893 0 : IF( LT_32( Max_coeff_fx, L_tmp ) )
894 : {
895 0 : Max_coeff_fx = L_add( L_tmp, 0 );
896 0 : Max_ind = i;
897 0 : move16();
898 : }
899 : }
900 : }
901 :
902 : /* Find energy difference from band 16 */
903 0 : k = 1;
904 0 : move16();
905 :
906 0 : FOR( i = k; i < num_Sb; i++ )
907 : {
908 0 : en_high_fx[i] = L_deposit_l( 0 );
909 0 : move16();
910 0 : FOR( j = 0; j < 2; j++ )
911 : {
912 : /*en_high[i] += 0.5f*st->ynrm_values[i][j+1];*/
913 0 : en_high_fx[i] = L_add( en_high_fx[i], L_shr( hHQ_nbfec->ynrm_values_fx[i][j + 1], 1 ) ); /*Q12*/
914 0 : move32();
915 : }
916 : }
917 :
918 0 : *mean_en_high_fx = 0;
919 0 : move16();
920 0 : FOR( i = k; i < num_Sb; i++ )
921 : {
922 : /* *mean_en_high += (float)(en_high[i]/st->ynrm_values[i][0]);*/
923 0 : exp1 = sub( norm_l( en_high_fx[i] ), 1 );
924 0 : exp2 = norm_l( hHQ_nbfec->ynrm_values_fx[i][0] );
925 0 : tmp_fx = div_s( extract_h( L_shl( en_high_fx[i], exp1 ) ), extract_h( L_shl( hHQ_nbfec->ynrm_values_fx[i][0], exp2 ) ) );
926 0 : exp = add( 15, sub( exp1, exp2 ) );
927 0 : *mean_en_high_fx = add_o( *mean_en_high_fx, shr_o( tmp_fx, sub( exp, 5 ), &Overflow ), &Overflow );
928 0 : move16();
929 : }
930 0 : *mean_en_high_fx = mult( *mean_en_high_fx, inv_tbl_fx[sub( num_Sb, k )] );
931 0 : move16();
932 :
933 0 : test();
934 0 : test();
935 0 : test();
936 0 : test();
937 0 : test();
938 0 : test();
939 0 : test();
940 0 : test();
941 0 : test();
942 0 : IF( ( LT_16( Min_ind, 5 ) ) && ( LT_16( abs_s( sub( Min_ind, hHQ_nbfec->old_Min_ind ) ), 2 ) ) && ( LT_16( hHQ_nbfec->diff_energy_fx, ED_THRES_90P_fx ) ) && ( !st_fx->bfi ) && ( !st_fx->prev_bfi ) && ( !st_fx->prev_old_bfi ) && ( !is_transient ) && ( !hHQ_core->old_is_transient[1] ) && EQ_16( hHQ_nbfec->prev_last_core, HQ_CORE ) && EQ_16( st_fx->last_core, HQ_CORE ) )
943 : {
944 0 : hHQ_nbfec->phase_mat_flag = 1;
945 0 : move16();
946 0 : test();
947 0 : if ( Min_ind == 0 && ( LT_16( Max_ind, 3 ) ) )
948 : {
949 0 : hHQ_nbfec->phase_mat_flag = 0;
950 0 : move16();
951 : }
952 : }
953 : ELSE
954 : {
955 0 : hHQ_nbfec->phase_mat_flag = 0;
956 0 : move16();
957 : }
958 :
959 0 : hHQ_nbfec->old_Min_ind = Min_ind;
960 0 : move16();
961 :
962 :
963 0 : FOR( i = 0; i < L_FRAME8k; i++ )
964 : {
965 0 : hHQ_nbfec->old_coeffs_fx[i] = t_audio_q_fx[i];
966 0 : move32();
967 : }
968 : }
969 :
970 429 : hHQ_core->old_is_transient[2] = hHQ_core->old_is_transient[1];
971 429 : move16();
972 429 : hHQ_core->old_is_transient[1] = hHQ_core->old_is_transient[0];
973 429 : move16();
974 429 : hHQ_core->old_is_transient[0] = is_transient;
975 429 : move16();
976 :
977 429 : return;
978 : }
979 :
980 0 : static Word16 find_best_delay_fx(
981 : Word16 *mu_o_fx, // Qx
982 : Word16 *in_fx, // Qx
983 : Word16 mind1,
984 : Word16 maxd1,
985 : Word16 lin,
986 : Word16 delta,
987 : Word16 *false_flag )
988 : {
989 : Word16 i, d1, k;
990 0 : Word16 d1m = 0;
991 :
992 : Word16 tmp, exp1, exp2;
993 : Word32 L_tmp1, L_tmp2;
994 :
995 : Word32 min_sq_cross_fx, min_corr_fx;
996 : Word32 accA_fx, accB_fx;
997 : Word32 Rxy_fx[MAXDELAY_FEC], Ryy_fx[MAXDELAY_FEC];
998 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
999 0 : Flag Overflow = 0;
1000 0 : move32();
1001 : #endif
1002 0 : move16(); // d1m
1003 :
1004 :
1005 0 : d1 = mind1;
1006 0 : move16();
1007 0 : FOR( k = 0; k < idiv1616( sub( maxd1, mind1 ), delta ); k++ )
1008 : {
1009 0 : accA_fx = L_deposit_l( 0 );
1010 0 : accB_fx = L_deposit_l( 0 );
1011 0 : FOR( i = 0; i < lin; i += delta )
1012 : {
1013 0 : accA_fx = L_add_sat( accA_fx, L_shr( L_mult_sat( mu_o_fx[d1 + i], mu_o_fx[d1 + i] ), 2 ) );
1014 0 : accB_fx = L_add_sat( accB_fx, L_shr( L_mult_sat( mu_o_fx[d1 + i], in_fx[i] ), 2 ) );
1015 : }
1016 :
1017 0 : Rxy_fx[k] = accB_fx;
1018 0 : move32();
1019 0 : Ryy_fx[k] = accA_fx;
1020 0 : move32();
1021 :
1022 0 : d1 = add( d1, delta );
1023 : }
1024 :
1025 : /* Obtain the best delay values */
1026 0 : min_sq_cross_fx = 0x80000000;
1027 0 : move32();
1028 0 : min_corr_fx = L_deposit_l( 0 );
1029 0 : exp2 = 0;
1030 0 : move16();
1031 0 : FOR( d1 = 0; d1 < ( maxd1 - mind1 ) / delta; d1++ )
1032 : {
1033 0 : IF( GT_32( L_abs( Rxy_fx[d1] ), L_abs( Ryy_fx[d1] ) ) )
1034 0 : exp1 = norm_l( Rxy_fx[d1] );
1035 : ELSE
1036 0 : exp1 = norm_l( Ryy_fx[d1] );
1037 :
1038 0 : L_tmp1 = Mult_32_32( L_shl( Rxy_fx[d1], exp1 ), L_shl( min_corr_fx, exp2 ) );
1039 0 : L_tmp2 = Mult_32_32( L_shl( Ryy_fx[d1], exp1 ), L_shl( min_sq_cross_fx, exp2 ) );
1040 0 : IF( GE_32( L_tmp1, L_tmp2 ) )
1041 : {
1042 0 : d1m = d1;
1043 0 : move16();
1044 0 : min_corr_fx = L_add( Ryy_fx[d1], 0 ); /*12 + 12 - 31 */
1045 0 : min_sq_cross_fx = L_add( Rxy_fx[d1], 0 ); /*12 + 12 - 31 */
1046 0 : exp2 = exp1;
1047 0 : move16();
1048 : }
1049 : }
1050 :
1051 0 : test();
1052 0 : IF( ( min_sq_cross_fx <= 0 ) || ( min_corr_fx <= 0 ) )
1053 : {
1054 0 : tmp = 0;
1055 0 : move16(); /* If cross correlation is negative, the division per the energy will always be negative --> tmp will be < 8192, no need to do the division per say */
1056 : }
1057 : ELSE
1058 : {
1059 : /*d1m *= delta; */
1060 0 : d1m = extract_l( L_mult0( d1m, delta ) );
1061 :
1062 0 : exp1 = sub( norm_l( min_sq_cross_fx ), 1 );
1063 0 : exp2 = norm_l( min_corr_fx );
1064 0 : L_tmp1 = L_shl( min_sq_cross_fx, exp1 );
1065 0 : L_tmp2 = L_shl( min_corr_fx, exp2 );
1066 0 : tmp = div_s( extract_h( L_tmp1 ), extract_h( L_tmp2 ) ); /*15 + exp1 - exp2 */
1067 0 : tmp = shl_o( tmp, sub( exp2, add( exp1, 1 ) ), &Overflow ); /*14 */
1068 : }
1069 :
1070 0 : *false_flag = 0;
1071 0 : move16();
1072 0 : test();
1073 0 : if ( LT_16( tmp, 8192 ) || GT_16( tmp, 24576 ) )
1074 : {
1075 0 : *false_flag = 1;
1076 0 : move16();
1077 : }
1078 :
1079 0 : return d1m;
1080 : }
1081 :
1082 0 : static Word16 Search_Max_Corr_fx(
1083 : Word16 *mu_o_fx,
1084 : /* i : *old_auOut_2fr, */ // Qx
1085 : Word16 old_Min_ind, /* i : *old_auOut_2fr, */
1086 : const Word16 L /* i : L/2 */
1087 : )
1088 : {
1089 : Word16 pos;
1090 : Word16 pos2, delta2;
1091 : Word16 lin, delta;
1092 : Word16 mind1, maxd1;
1093 : Word16 false_flag;
1094 : Word16 min_d1, max_d1;
1095 : Word16 tmp1, tmp2;
1096 : Word16 *in_fx; // Qx
1097 :
1098 0 : IF( old_Min_ind == 0 )
1099 : {
1100 : /*lin = 8*L/20; */ /* Basic size of the block for phase matching */
1101 0 : lin = mult_r( L, 13107 ); /* Basic size of the block for phase matching */
1102 : /*min_dist = -1e35f; */
1103 0 : mind1 = 0;
1104 0 : move16(); /* min value of delay d1 to search for */
1105 : /*maxd1 = 12*L/20; */ /* max value of delay d1 to search for */
1106 0 : maxd1 = mult_r( L, 19661 ); /* max value of delay d1 to search for */
1107 :
1108 : /*in = mu_o + 2*L -lin; */
1109 0 : in_fx = mu_o_fx + sub( shl( L, 1 ), lin );
1110 :
1111 : /* generate correlation */
1112 0 : delta = 2;
1113 0 : move16();
1114 0 : delta2 = 1;
1115 0 : move16();
1116 :
1117 0 : pos = find_best_delay_fx( mu_o_fx, in_fx, mind1, maxd1, lin, delta, &false_flag );
1118 :
1119 0 : if ( false_flag )
1120 : {
1121 0 : return 0;
1122 : }
1123 :
1124 0 : tmp1 = add( mind1, sub( add( pos, 1 ), delta ) );
1125 0 : tmp2 = add( mind1, add( pos, delta ) );
1126 0 : min_d1 = s_max( mind1, tmp1 );
1127 0 : max_d1 = s_min( maxd1, tmp2 );
1128 0 : pos2 = find_best_delay_fx( mu_o_fx, in_fx, min_d1, max_d1, lin, delta2, &false_flag );
1129 0 : IF( GT_16( mind1, tmp1 ) )
1130 : {
1131 0 : pos = pos2;
1132 0 : move16();
1133 : }
1134 : ELSE
1135 : {
1136 0 : pos = add( pos, add( sub( pos2, delta ), 1 ) );
1137 : }
1138 :
1139 0 : pos = add( pos, add( lin, mind1 ) );
1140 : }
1141 : ELSE
1142 : {
1143 0 : lin = mult_r( L, 9830 );
1144 0 : mind1 = mult_r( L, 14746 ); /* min value of delay d1 to search for */
1145 0 : maxd1 = mult_r( L, 22938 ); /* max value of delay d1 to search for */
1146 0 : in_fx = mu_o_fx + sub( shl( L, 1 ), lin );
1147 :
1148 : /* generate correlation */
1149 0 : delta = 2;
1150 0 : move16();
1151 0 : delta2 = 1;
1152 0 : move16();
1153 :
1154 0 : pos = find_best_delay_fx( mu_o_fx, in_fx, mind1, maxd1, lin, delta, &false_flag );
1155 :
1156 0 : if ( false_flag )
1157 : {
1158 0 : return 0;
1159 : }
1160 :
1161 0 : tmp1 = add( mind1, add( sub( pos, delta ), 1 ) );
1162 0 : tmp2 = add( mind1, add( pos, delta ) );
1163 0 : min_d1 = s_max( mind1, tmp1 );
1164 0 : max_d1 = s_min( maxd1, tmp2 );
1165 0 : pos2 = find_best_delay_fx( mu_o_fx, in_fx, min_d1, max_d1, lin, delta2, &false_flag );
1166 :
1167 0 : IF( GT_16( mind1, tmp1 ) )
1168 : {
1169 0 : pos = pos2;
1170 0 : move16();
1171 : }
1172 : ELSE
1173 : {
1174 0 : pos = add( pos, add( sub( pos2, delta ), 1 ) );
1175 : }
1176 0 : pos = add( pos, add( lin, mind1 ) );
1177 : }
1178 :
1179 0 : return pos;
1180 : }
1181 :
1182 0 : static Word16 FEC_phase_matching_fx(
1183 : HQ_NBFEC_HANDLE st_fx, /* i : Decoder State */
1184 : Word32 *ImdctOut_fx, /* i : input, Q6 */
1185 : Word16 *auOut_fx, /* o : output audio, Q0 */
1186 : Word16 *OldauOut_fx, // Q0
1187 : Word16 OldauOut_pha_fx[2][N_LEAD_NB] ) // Qx
1188 : {
1189 : Word16 i;
1190 : Word16 pos, remain;
1191 : Word16 ol_size;
1192 : Word16 L_overlap, L;
1193 : Word16 ImdctOutWin_fx[2 * L_FRAME8k];
1194 : Word16 OldauOutnoWin_fx[L_FRAME8k];
1195 : Word16 OldauOut2_fx[L_FRAME8k];
1196 : Word16 win_NB_fx[L_FRAME8k + 25]; // Q15
1197 : Word16 exp1, exp2, tmp;
1198 : Word32 pow1_fx, pow22_fx;
1199 : Word16 SmoothingWin_NB3_fx[24]; // Q15
1200 :
1201 0 : L = L_FRAME8k;
1202 0 : move16();
1203 0 : ol_size = idiv1616( shl( L, 1 ), 20 );
1204 0 : move16();
1205 0 : L_overlap = idiv1616( imult1616( 3, L ), 20 );
1206 0 : move16();
1207 :
1208 0 : FOR( i = 0; i < L_overlap; i++ )
1209 : {
1210 0 : SmoothingWin_NB3_fx[i] = SmoothingWin_NB875_fx[i * 3];
1211 0 : move16();
1212 : }
1213 :
1214 0 : FOR( i = 0; i < L + 25; i++ )
1215 : {
1216 0 : win_NB_fx[i] = window_48kHz_fx[i * 6 + 3]; // Q15
1217 0 : move16();
1218 : }
1219 0 : set16_fx( ImdctOutWin_fx, 0, shl( L, 1 ) );
1220 :
1221 0 : pos = Search_Max_Corr_fx( st_fx->old_auOut_2fr_fx, st_fx->old_Min_ind, L );
1222 :
1223 0 : if ( pos == 0 )
1224 : {
1225 0 : return 1;
1226 : }
1227 :
1228 : /* Repetition */
1229 0 : remain = sub( add( L, N_Z_L_NB ), sub( shl( L, 1 ), pos ) );
1230 0 : Copy( &st_fx->old_auOut_2fr_fx[pos], &ImdctOutWin_fx[N_ZERO_NB], sub( shl( L, 1 ), pos ) );
1231 :
1232 : /* OldauOut without windowing */
1233 0 : FOR( i = N_ZERO_NB; i < L / 2; i++ )
1234 : {
1235 0 : OldauOutnoWin_fx[i - N_ZERO_NB] = extract_l( L_shr( L_negate( st_fx->oldIMDCTout_fx[L / 2 - 1 - i] ), 6 ) ); // Q6 -> Q0
1236 0 : move16();
1237 : }
1238 0 : FOR( i = 0; i < L / 2; i++ )
1239 : {
1240 0 : OldauOutnoWin_fx[i + N_ZERO_O_NB] = extract_l( L_shr( L_negate( st_fx->oldIMDCTout_fx[i] ), 6 ) ); // Q6 -> Q0
1241 0 : move16();
1242 : }
1243 :
1244 0 : Copy( OldauOutnoWin_fx, &ImdctOutWin_fx[N_ZERO_NB + ( 2 * L ) - pos], remain );
1245 :
1246 0 : pow1_fx = L_deposit_l( 0 );
1247 0 : pow22_fx = L_deposit_l( 0 );
1248 0 : FOR( i = 0; i < L; i++ )
1249 : {
1250 0 : pow1_fx = L_add( pow1_fx, shr( abs_s( st_fx->old_auOut_2fr_fx[L + i] ), 1 ) );
1251 0 : pow22_fx = L_add( pow22_fx, shr( abs_s( ImdctOutWin_fx[N_ZERO_NB + i] ), 1 ) );
1252 : }
1253 0 : IF( pow22_fx != 0 )
1254 : {
1255 0 : exp1 = sub( norm_l( pow1_fx ), 1 );
1256 0 : exp2 = norm_l( pow22_fx );
1257 0 : tmp = div_s( extract_h( L_shl( pow1_fx, exp1 ) ), extract_h( L_shl( pow22_fx, exp2 ) ) ); /*15 + exp1 - exp2*/
1258 0 : tmp = shl( tmp, sub( sub( exp2, exp1 ), 1 ) ); /*14*/
1259 0 : FOR( i = N_ZERO_NB; i < L * 2; i++ )
1260 : {
1261 0 : ImdctOutWin_fx[i] = shl_sat( mult( ImdctOutWin_fx[i], tmp ), 1 );
1262 0 : move16();
1263 : }
1264 : }
1265 0 : Smoothing_vector_NB_fx( OldauOutnoWin_fx, &ImdctOutWin_fx[N_ZERO_NB], SmoothingWin_NB2_fx, auOut_fx, ol_size );
1266 :
1267 0 : FOR( i = 0; i < L / 2; i++ )
1268 : {
1269 : /*ImdctOutWin[3*L/2 + i] *= win_NB[L/2-i-1];*/
1270 0 : ImdctOutWin_fx[3 * L / 2 + i] = mult( ImdctOutWin_fx[3 * L / 2 + i], win_NB_fx[L / 2 - i - 1] );
1271 0 : move16();
1272 : }
1273 :
1274 0 : FOR( i = N_ZERO_NB; i < L / 2; i++ )
1275 : {
1276 : /*ImdctOutWin_fx[L + i] *= win_NB_fx[(L-1-i)];*/
1277 0 : ImdctOutWin_fx[L + i] = mult( ImdctOutWin_fx[L + i], win_NB_fx[( L - 1 - i )] );
1278 0 : move16();
1279 : }
1280 :
1281 0 : Copy( &ImdctOutWin_fx[N_Z_L_O_NB], &OldauOut_pha_fx[0][0], N_LEAD_NB );
1282 0 : Copy( &ImdctOutWin_fx[ol_size + N_ZERO_NB], &auOut_fx[ol_size], sub( N_Z_L_NB, ol_size ) );
1283 0 : Copy( &ImdctOutWin_fx[L], &auOut_fx[N_Z_L_NB], N_ZERO_NB );
1284 0 : Copy( &ImdctOutWin_fx[L], OldauOut_fx, L );
1285 :
1286 0 : FOR( i = 0; i < shr( L, 1 ); i++ )
1287 : {
1288 0 : OldauOut2_fx[i] = extract_l( L_shr( L_negate( ImdctOut_fx[L / 2 - 1 - i] ), 6 ) );
1289 0 : move16();
1290 0 : OldauOut2_fx[L / 2 + i] = extract_l( L_shr( L_negate( ImdctOut_fx[i] ), 6 ) );
1291 0 : move16();
1292 : }
1293 :
1294 0 : Smoothing_vector_NB_fx( &ImdctOutWin_fx[N_Z_L_O_NB], &OldauOut2_fx[N_ZERO_NB], SmoothingWin_NB3_fx, &OldauOut_pha_fx[1][0], L_overlap );
1295 :
1296 0 : FOR( i = L_overlap; i < N_LEAD_NB; i++ )
1297 : {
1298 0 : OldauOut_pha_fx[1][i] = OldauOut2_fx[i + N_ZERO_NB];
1299 0 : move32();
1300 : }
1301 :
1302 0 : return 0;
1303 : }
1304 :
1305 0 : static void FEC_phase_matching_nextgood_fx(
1306 : const Word32 *ImdctOut_fx, /* i : input Q6 */
1307 : Word16 *auOut_fx, /* o : output audio */
1308 : Word16 *OldauOut_fx, /* i/o: audio from previous frame Q0 */
1309 : Word16 OldauOut_pha_fx[2][N_LEAD_NB],
1310 : Word16 mean_en_high_fx /*Q5 */
1311 : )
1312 : {
1313 : Word16 i;
1314 : Word16 L_overlap, L;
1315 : Word16 oldout_pha_idx;
1316 : Word16 *OldOut_pha_fx; // Qx
1317 : Word16 ImdctOutWin_fx[2 * L_FRAME48k];
1318 : Word16 win_NB_fx[L_FRAME8k + 25];
1319 :
1320 0 : L = L_FRAME8k;
1321 0 : move16();
1322 0 : FOR( i = 0; i < L + 25; i++ )
1323 : {
1324 : /* win_NB[i] = window_48kHz[i*6+3]; */
1325 0 : win_NB_fx[i] = window_48kHz_fx[i * 6 + 3]; // Q15
1326 0 : move16();
1327 : }
1328 :
1329 0 : test();
1330 0 : IF( ( GT_16( mean_en_high_fx, 64 ) ) || ( LT_16( mean_en_high_fx, 16 ) ) )
1331 : {
1332 0 : oldout_pha_idx = 1;
1333 0 : move16();
1334 : }
1335 : ELSE
1336 : {
1337 0 : oldout_pha_idx = 0;
1338 0 : move16();
1339 : }
1340 :
1341 : /* Overlapping with next good frame : Overlapping to remove the discontinuity */
1342 0 : L_overlap = N_LEAD_NB;
1343 0 : move16();
1344 0 : OldOut_pha_fx = OldauOut_pha_fx[oldout_pha_idx];
1345 0 : FOR( i = 0; i < N_LEAD_NB; i++ )
1346 : {
1347 : /* OldOut_pha[i] *= SmoothingWin_NB875[L_overlap-i-1]; */
1348 0 : OldOut_pha_fx[i] = mult( OldOut_pha_fx[i], SmoothingWin_NB875_fx[L_overlap - i - 1] );
1349 0 : move16();
1350 : }
1351 :
1352 0 : IF( EQ_16( oldout_pha_idx, 1 ) )
1353 : {
1354 : /* Use phase matching and overlapping with the Oldauout*/
1355 : /* Windowing */
1356 : /*Windowing_1st_NB(ImdctOutWin, ImdctOut, win_NB, NULL, 0);*/
1357 : /*Windowing_2nd_NB(ImdctOutWin, ImdctOut, win_NB); */
1358 0 : Windowing_1st_NB_fx( ImdctOutWin_fx, ImdctOut_fx, win_NB_fx, NULL, 0 );
1359 0 : Windowing_2nd_NB_fx( ImdctOutWin_fx, ImdctOut_fx, win_NB_fx );
1360 : }
1361 : ELSE
1362 : {
1363 : /* Only use phase matching */
1364 : /* Windowing */
1365 0 : Windowing_1st_NB_fx( ImdctOutWin_fx, ImdctOut_fx, win_NB_fx, SmoothingWin_NB875_fx, 1 );
1366 0 : Windowing_2nd_NB_fx( ImdctOutWin_fx, ImdctOut_fx, win_NB_fx );
1367 : }
1368 : /* common_overlapping(auOut, ImdctOutWin, OldOut_pha, N_LEAD_NB, 0, N_LEAD_NB, L, N_ZERO_NB, 0, L);*/
1369 0 : common_overlapping_fx( auOut_fx, ImdctOutWin_fx, OldOut_pha_fx, N_LEAD_NB, 0, N_LEAD_NB, L, N_ZERO_NB, 0 );
1370 0 : Copy( &ImdctOutWin_fx[L], OldauOut_fx, L );
1371 :
1372 0 : return;
1373 : }
1374 :
1375 0 : static void FEC_phase_matching_burst_fx(
1376 : const Word32 *ImdctOut_fx, /* i : input Q6 */
1377 : Word16 *auOut_fx, /* o : output audio Q0 */
1378 : Word16 *OldauOut_fx, /* i/o: audio from previous frame Q0 */
1379 : Word16 OldauOut_pha_fx[2][N_LEAD_NB],
1380 : Word16 *prev_oldauOut_fx /* i : OldauOut from previous frame Q0 */
1381 : )
1382 : {
1383 : Word16 i;
1384 : Word16 L_overlap;
1385 : Word16 L;
1386 : Word16 OldauOut2_fx[L_FRAME8k];
1387 : Word16 ImdctOutWin_fx[2 * L_FRAME8k];
1388 : Word16 win_NB_fx[L_FRAME8k + 25];
1389 : Word16 SmoothingWin_NB3_fx[24];
1390 :
1391 0 : L = L_FRAME8k;
1392 0 : move16();
1393 0 : L_overlap = idiv1616( imult1616( 3, L ), 20 );
1394 0 : move16();
1395 :
1396 0 : FOR( i = 0; i < L_overlap; i++ )
1397 : {
1398 0 : SmoothingWin_NB3_fx[i] = SmoothingWin_NB875_fx[i * 3];
1399 0 : move16();
1400 : }
1401 :
1402 0 : FOR( i = 0; i < add( L, 25 ); i++ )
1403 : {
1404 0 : win_NB_fx[i] = window_48kHz_fx[i * 6 + 3]; // Q15
1405 0 : move16();
1406 : }
1407 :
1408 : /* Windowing */
1409 0 : Windowing_1st_NB_fx( ImdctOutWin_fx, ImdctOut_fx, win_NB_fx, NULL, 0 );
1410 0 : Windowing_2nd_NB_fx( ImdctOutWin_fx, ImdctOut_fx, win_NB_fx );
1411 :
1412 : /* Repetition with old frame to reserve energy */
1413 : /*common_overlapping(auOut, ImdctOutWin, prev_oldauOut, N_Z_L_NB, 0, N_Z_L_NB, L, N_ZERO_NB, 0, L);*/
1414 0 : common_overlapping_fx( auOut_fx, ImdctOutWin_fx, prev_oldauOut_fx, N_Z_L_NB, 0, N_Z_L_NB, L, N_ZERO_NB, 0 );
1415 :
1416 : /* data transition from OldauOut to auOut using smoothing win*/
1417 0 : Smoothing_vector_NB_fx( OldauOut_pha_fx[0], auOut_fx, SmoothingWin_NB875_fx, auOut_fx, N_LEAD_NB );
1418 :
1419 : /* Update the OldauOut array for next overlapping */
1420 0 : Copy( &ImdctOutWin_fx[N_Z_L_O_NB], &OldauOut_pha_fx[0][0], N_LEAD_NB );
1421 0 : Copy( &ImdctOutWin_fx[L], OldauOut_fx, L );
1422 0 : Scaledown_fx( prev_oldauOut_fx, prev_oldauOut_fx, 23170, L );
1423 :
1424 0 : FOR( i = 0; i < L / 2; i++ )
1425 : {
1426 : /* OldauOut2[i] = -ImdctOut[L/2 - 1 - i];*/
1427 : /* OldauOut2[L/2+i] = -ImdctOut[i];*/
1428 0 : OldauOut2_fx[i] = extract_l( L_shr( L_negate( ImdctOut_fx[L / 2 - 1 - i] ), 6 ) ); // Q6 -> Q0
1429 0 : move16();
1430 0 : OldauOut2_fx[L / 2 + i] = extract_l( L_shr( L_negate( ImdctOut_fx[i] ), 6 ) ); // Q6 -> Q0
1431 0 : move16();
1432 : }
1433 :
1434 0 : Smoothing_vector_NB_fx( &ImdctOutWin_fx[N_Z_L_O_NB], &OldauOut2_fx[N_ZERO_NB], SmoothingWin_NB3_fx, &OldauOut_pha_fx[1][0], L_overlap );
1435 :
1436 0 : FOR( i = L_overlap; i < N_LEAD_NB; i++ )
1437 : {
1438 : /* OldauOut_pha[1][i] = OldauOut2[i+N_ZERO_NB]; */
1439 0 : OldauOut_pha_fx[1][i] = OldauOut2_fx[i + N_ZERO_NB];
1440 0 : move16();
1441 : }
1442 :
1443 0 : return;
1444 : }
1445 :
1446 0 : static void Repetition_smoothing_nextgood_fx(
1447 : const Word32 *ImdctOut_fx, /* i : input Q6 */
1448 : Word16 *auOut_fx, /* o : output audio Q0 */
1449 : Word32 *OldImdctOut_fx, /* i : input Q6 */
1450 : Word16 *OldauOut_fx, /* i/o: audio from previous frame Q0 */
1451 : Word16 cur_data_use_flag, /* i : current imdct data use flag */
1452 : Word16 overlap_time )
1453 : {
1454 : Word16 i;
1455 : Word16 L_overlap;
1456 : Word16 ol_size;
1457 : Word16 L;
1458 : Word16 ImdctOutWin_fx[2 * L_FRAME8k]; // Q0
1459 : Word16 win_NB_fx[L_FRAME8k + 25];
1460 :
1461 0 : L = L_FRAME8k;
1462 0 : move16();
1463 :
1464 0 : FOR( i = 0; i < L_FRAME8k + 25; i++ )
1465 : {
1466 : /*win_NB[i] = window_48kHz[i*6+3];*/
1467 0 : win_NB_fx[i] = window_48kHz_fx[i * 6 + 3]; // Q15
1468 0 : move16();
1469 : }
1470 :
1471 0 : FOR( i = N_ZERO_NB; i < L / 2; i++ )
1472 : {
1473 : /*OldauOut[i-N_ZERO_NB] = -OldImdctOut[L/2 - 1 - i];*/
1474 0 : OldauOut_fx[i - N_ZERO_NB] = extract_l( L_shr( L_negate( OldImdctOut_fx[L / 2 - 1 - i] ), 6 ) ); /* Q6 -> Q0 */
1475 0 : move16();
1476 : }
1477 0 : FOR( i = 0; i < L / 4; i++ )
1478 : {
1479 : /*OldauOut[i+N_ZERO_O_NB] = -OldImdctOut[i];*/
1480 0 : OldauOut_fx[i + N_ZERO_O_NB] = extract_l( L_shr( L_negate( OldImdctOut_fx[i] ), 6 ) ); /* Q6 -> Q0 */
1481 0 : move16();
1482 : }
1483 :
1484 : /* Overlapping with next good frame : Overlapping to remove the discontinuity */
1485 0 : IF( cur_data_use_flag )
1486 : {
1487 0 : ol_size = N_LEAD_NB;
1488 0 : move16();
1489 :
1490 0 : FOR( i = N_ZERO_NB; i < L / 2; i++ )
1491 : {
1492 : /* ImdctOutWin[i+L] = -ImdctOut[L/2 - 1 - i]; */
1493 0 : ImdctOutWin_fx[add( i, L )] = extract_l( L_shr( L_negate( ImdctOut_fx[L / 2 - 1 - i] ), 6 ) ); /* Q6 -> Q0 */
1494 0 : move16();
1495 : }
1496 0 : FOR( i = 0; i < L / 2; i++ )
1497 : {
1498 0 : ImdctOutWin_fx[i + 3 * L / 2] = extract_l( L_shr( L_negate( ImdctOut_fx[i] ), 6 ) ); /* Q6 -> Q0 */
1499 0 : move16();
1500 : }
1501 :
1502 : /*a = (float)(1./(float)(ol_size)); y = ax */
1503 0 : Smoothing_vector_scaledown_NB_fx( OldauOut_fx, &ImdctOutWin_fx[N_Z_L_O_NB], SmoothingWin_NB875_fx, OldauOut_fx, ol_size );
1504 :
1505 : /* Scale down the overlapped signal */
1506 0 : Scaledown_fx( &ImdctOutWin_fx[ol_size + N_Z_L_O_NB], &OldauOut_fx[ol_size], 23170, sub( N_Z_L_NB, ol_size ) ); // SCALE_DOWN_3dB.Q15 = 23170
1507 : }
1508 :
1509 0 : L_overlap = overlap_time;
1510 0 : move16();
1511 0 : FOR( i = 0; i < L_overlap; i++ )
1512 : {
1513 : /*OldauOut[i] *= SmoothingWin_NB875[L_overlap-i-1];*/
1514 0 : OldauOut_fx[i] = mult( OldauOut_fx[i], SmoothingWin_NB875_fx[L_overlap - i - 1] );
1515 0 : move16();
1516 : }
1517 0 : FOR( i = L_overlap; i < L; i++ )
1518 : {
1519 0 : OldauOut_fx[i] = 0;
1520 0 : move16();
1521 : }
1522 :
1523 : /* Windowing */
1524 : /*Windowing_1st_NB(ImdctOutWin, ImdctOut, win_NB, SmoothingWin_NB875, 1);*/
1525 : /*Windowing_2nd_NB(ImdctOutWin, ImdctOut, win_NB);*/
1526 0 : Windowing_1st_NB_fx( ImdctOutWin_fx, ImdctOut_fx, win_NB_fx, SmoothingWin_NB875_fx, 1 );
1527 0 : Windowing_2nd_NB_fx( ImdctOutWin_fx, ImdctOut_fx, win_NB_fx );
1528 :
1529 : /*v_add(&ImdctOutWin[N_ZERO_NB], OldauOut, auOut, L);*/
1530 : /*mvr2r(&ImdctOutWin[L], OldauOut, L);*/
1531 0 : FOR( i = 0; i < L; i++ )
1532 : {
1533 0 : auOut_fx[i] = add_sat( ImdctOutWin_fx[N_ZERO_NB + i], OldauOut_fx[i] ); // Q0
1534 0 : move16();
1535 : }
1536 0 : Copy( &ImdctOutWin_fx[L], OldauOut_fx, L );
1537 :
1538 0 : return;
1539 : }
1540 :
1541 0 : static Word16 Repetition_smoothing_fx(
1542 : const Word32 *ImdctOut_fx, /* i : input Q6 */
1543 : Word16 *auOut_fx, /* o : output audio Q0 */
1544 : Word32 *OldImdctOut_fx, /* i : input Q6 */
1545 : Word16 *OldauOut_fx, /* i/o: audio from previous frame Q0 */
1546 : const Word16 L, /* i : length */
1547 : Word16 *prev_oldauOut_fx, /* i : OldauOut from previous frame Q0 */
1548 : Word16 overlap_time /* i : overlap time */
1549 : )
1550 : {
1551 : Word16 i;
1552 : Word32 pow1_fx;
1553 : Word32 pow22_fx;
1554 : Word16 ImdctOutWin_fx[2 * L_FRAME8k]; // Q0
1555 : Word16 OldauOutnoWin_fx[L_FRAME8k]; // Q0
1556 : Word16 win_NB_fx[L_FRAME8k + 25];
1557 :
1558 0 : FOR( i = 0; i < L_FRAME8k + 25; i++ )
1559 : {
1560 : /*win_NB[i] = window_48kHz[i*6+3];*/
1561 0 : win_NB_fx[i] = window_48kHz_fx[i * 6 + 3]; // Q15
1562 0 : move16();
1563 : }
1564 :
1565 : /* Windowing */
1566 0 : Windowing_1st_NB_fx( ImdctOutWin_fx, ImdctOut_fx, win_NB_fx, NULL, 0 );
1567 0 : Windowing_2nd_NB_fx( ImdctOutWin_fx, ImdctOut_fx, win_NB_fx );
1568 :
1569 : /* Repetition with old frame to reserve energy */
1570 0 : common_overlapping_fx( auOut_fx, ImdctOutWin_fx, prev_oldauOut_fx, N_Z_L_NB, 0, N_Z_L_NB, L, N_ZERO_NB, 0 );
1571 :
1572 : /* OldauOut without windowing */
1573 0 : FOR( i = N_ZERO_NB; i < L / 2; i++ )
1574 : {
1575 0 : OldauOutnoWin_fx[i - N_ZERO_NB] = extract_l( L_shr( L_negate( OldImdctOut_fx[L / 2 - 1 - i] ), 6 ) ); /* Q6 -> Q0 */
1576 0 : move16();
1577 : }
1578 0 : FOR( i = 0; i < L / 2; i++ )
1579 : {
1580 0 : OldauOutnoWin_fx[i + N_ZERO_O_NB] = extract_l( L_shr( L_negate( OldImdctOut_fx[i] ), 6 ) ); /* Q6 -> Q0 */
1581 0 : move16();
1582 : }
1583 :
1584 : /* data transition from OldauOut to auOut using smoothing win*/
1585 0 : Smoothing_vector_NB_fx( OldauOutnoWin_fx, auOut_fx, SmoothingWin_NB875_fx, auOut_fx, overlap_time );
1586 :
1587 0 : pow1_fx = L_deposit_l( 0 );
1588 0 : pow22_fx = L_deposit_l( 0 );
1589 0 : FOR( i = 0; i < ( 4 * L ) / 20; i++ )
1590 : {
1591 0 : pow1_fx = L_add( pow1_fx, Mult_32_32( L_shl( (Word32) auOut_fx[( L / 20 ) + i], 6 ), L_shl( (Word32) auOut_fx[( L / 20 ) + i], 6 ) ) );
1592 0 : pow22_fx = L_add( pow22_fx, Mult_32_32( L_shl( (Word32) auOut_fx[N_LEAD_NB + i], 6 ), L_shl( (Word32) auOut_fx[N_LEAD_NB + i], 6 ) ) );
1593 : }
1594 :
1595 :
1596 0 : if ( GT_32( pow22_fx, L_add( pow1_fx, L_shl( pow1_fx, 1 ) ) ) )
1597 : {
1598 0 : return 1;
1599 : }
1600 :
1601 : /* Update the OldauOut array for next overlapping */
1602 0 : Copy( &ImdctOutWin_fx[L], OldauOut_fx, L );
1603 0 : Scaledown_fx( prev_oldauOut_fx, prev_oldauOut_fx, 23170, L );
1604 :
1605 0 : return 0;
1606 : }
1607 :
1608 0 : static void common_overlapping_fx(
1609 : Word16 *auOut_fx, /* i : Input Q0 */
1610 : Word16 *ImdctOutWin_fx, /* o : Output Q0 */
1611 : Word16 *OldauOut_fx, /* i : Window Q0 */
1612 : Word16 end1, /* i : Decay */
1613 : Word16 offset1,
1614 : Word16 start2,
1615 : Word16 end2,
1616 : Word16 offset_i2,
1617 : Word16 offset2 )
1618 : {
1619 : Word16 i;
1620 :
1621 : /* Common Overlapping */
1622 0 : FOR( i = 0; i < end1; i++ )
1623 : {
1624 : /*auOut_fx[i] = L_add(ImdctOutWin_fx[i+7*L/20], OldauOut_fx[i+offset1]);*/
1625 0 : auOut_fx[i] = add_sat( ImdctOutWin_fx[i + N_ZERO_NB], OldauOut_fx[i + offset1] );
1626 0 : move16();
1627 : }
1628 0 : FOR( i = start2; i < end2; i++ )
1629 : {
1630 : /*auOut_fx[i+offset2] = ImdctOutWin_fx[i+offset_i2]; move32();*/
1631 0 : auOut_fx[i + offset2] = ImdctOutWin_fx[i + offset_i2];
1632 0 : move16();
1633 : }
1634 :
1635 0 : return;
1636 : }
1637 :
1638 :
1639 0 : static void Smoothing_vector_NB_fx(
1640 : const Word16 OldauOutnoWin_fx[], /* i : Input vector 1 Qx */
1641 : const Word16 ImdctOutWin_fx[], /* i : Input vector 2 Qx */
1642 : const Word16 SmoothingWin_fx[], /* i : Smoothing window Q15 */
1643 : Word16 auOut_fx[], /* o : Output vector that contains vector 1 .* vector 2 Qx*/
1644 : const Word16 ol_size /* i : Overlap size */
1645 : )
1646 : {
1647 : Word16 i;
1648 : Word16 weight_fx; // Q15
1649 :
1650 0 : FOR( i = 0; i < ol_size; i++ )
1651 : {
1652 0 : weight_fx = SmoothingWin_fx[i];
1653 0 : move16();
1654 0 : auOut_fx[i] = add( mult( OldauOutnoWin_fx[i], sub( 32767, weight_fx ) ), mult( ImdctOutWin_fx[i], weight_fx ) );
1655 0 : move16();
1656 : }
1657 :
1658 0 : return;
1659 : }
1660 :
1661 :
1662 0 : static void Windowing_1st_NB_fx(
1663 : Word16 *ImdctOutWin_fx, /* o : Output Q0 */
1664 : const Word32 *ImdctOut_fx, /* i : Input Q6 */
1665 : const Word16 *win_fx, /* i : Window Q15 */
1666 : const Word16 *smoothingWin_fx, /* i : Smoothing Window Q15 */
1667 : Word16 smoothing_flag /* i : 1=Smoothing window, 0=Original window */
1668 : )
1669 : {
1670 : Word16 i;
1671 : Word16 L;
1672 :
1673 0 : L = L_FRAME8k;
1674 0 : move16();
1675 0 : IF( smoothing_flag == 0 )
1676 : {
1677 0 : FOR( i = N_ZERO_NB; i < L / 2; i++ )
1678 : {
1679 : /*ImdctOutWin[i] = ImdctOut[L/2 + i] * win[(2*L-1-i)-N_LEAD_O_NB];*/
1680 0 : ImdctOutWin_fx[i] = extract_l( L_shr( Mult_32_16( ImdctOut_fx[L / 2 + i], win_fx[( 2 * L - 1 - i ) - N_LEAD_O_NB] ), 6 ) ); // Q6 -> Q0
1681 0 : move16();
1682 : }
1683 :
1684 0 : FOR( i = 0; i < N_ZERO_O_NB; i++ )
1685 : {
1686 : /*ImdctOutWin[L/2 + i] = -ImdctOut[L - 1 - i] * win[(3*L/2-1-i)-N_LEAD_O_NB];*/
1687 : /*ImdctOutWin[3*L/2 + i] = -ImdctOut[i] * win[(L/2-i-1)];*/
1688 0 : ImdctOutWin_fx[L / 2 + i] = extract_l( L_shr( Mult_32_16( L_negate( ImdctOut_fx[L - 1 - i] ), win_fx[( 3 * L / 2 - 1 - i ) - N_LEAD_O_NB] ), 6 ) ); // Q6 -> Q0
1689 0 : move16();
1690 0 : ImdctOutWin_fx[3 * L / 2 + i] = extract_l( L_shr( Mult_32_16( L_negate( ImdctOut_fx[i] ), win_fx[( L / 2 - i - 1 )] ), 6 ) ); // Q6 -> Q0
1691 0 : move16();
1692 : }
1693 : }
1694 : ELSE
1695 : {
1696 0 : FOR( i = N_ZERO_NB; i < L / 2; i++ )
1697 : {
1698 : /*ImdctOutWin[i] = ImdctOut[L/2 + i] * smoothingWin[(i-N_ZERO_NB)];*/ /*win[(2*L-i)*decimate-1-decay-14*L_FRAME48k/20];*/
1699 0 : ImdctOutWin_fx[i] = extract_l( L_shr( Mult_32_16( ImdctOut_fx[L / 2 + i], smoothingWin_fx[( i - N_ZERO_NB )] ), 6 ) ); /*win[(2*L-i)*decimate-1-decay-14*L_FRAME48k/20];*/
1700 0 : move16();
1701 : }
1702 :
1703 0 : FOR( i = 0; i < N_ZERO_O_NB; i++ )
1704 : {
1705 : /*ImdctOutWin[L/2 + i] = -ImdctOut[L - 1 - i] * smoothingWin[(i+N_ZERO_O_NB)];*/ /*win[(3*L/2-1-i)*decimate+decay-L_FRAME48k*14/20];*/
1706 : /*ImdctOutWin[3*L/2 + i] = -ImdctOut[i] * win[(L/2-i-1)];*/
1707 0 : ImdctOutWin_fx[L / 2 + i] = extract_l( L_shr( Mult_32_16( L_negate( ImdctOut_fx[L - 1 - i] ), smoothingWin_fx[( i + N_ZERO_O_NB )] ), 6 ) ); /*win[(3*L/2-1-i)*decimate+decay-L_FRAME48k*14/20];*/ // Q6 -> Q0
1708 0 : move16();
1709 0 : ImdctOutWin_fx[3 * L / 2 + i] = extract_l( L_shr( Mult_32_16( L_negate( ImdctOut_fx[i] ), win_fx[( L / 2 - i - 1 )] ), 6 ) ); // Q6 -> Q0
1710 0 : move16();
1711 : }
1712 : }
1713 :
1714 0 : return;
1715 : }
1716 0 : static void Windowing_2nd_NB_fx(
1717 : Word16 *ImdctOutWin_fx, /* o : Output Q0 */
1718 : const Word32 *ImdctOut_fx, /* i : Input Q6 */
1719 : const Word16 *win_fx /* i : Window Q15 */
1720 : )
1721 : {
1722 : Word16 i;
1723 : Word16 L;
1724 :
1725 0 : L = L_FRAME8k;
1726 0 : move16();
1727 0 : FOR( i = N_ZERO_O_NB; i < L / 2; i++ )
1728 : {
1729 : /*ImdctOutWin[L/2 + i] = -ImdctOut[L - 1 - i];*/
1730 : /*ImdctOutWin[3*L/2 + i] = -ImdctOut[i] * win[L/2-i-1];*/
1731 0 : ImdctOutWin_fx[L / 2 + i] = extract_l( L_shr( L_negate( ImdctOut_fx[L - 1 - i] ), 6 ) );
1732 0 : move16();
1733 0 : ImdctOutWin_fx[3 * L / 2 + i] = extract_l( L_shr( Mult_32_16( L_negate( ImdctOut_fx[i] ), win_fx[L / 2 - i - 1] ), 6 ) );
1734 0 : move16();
1735 : }
1736 :
1737 0 : FOR( i = 0; i < N_ZERO_NB; i++ )
1738 : {
1739 : /*ImdctOutWin[L + i] = -ImdctOut[L/2 - 1 - i];*/
1740 0 : ImdctOutWin_fx[L + i] = extract_l( L_shr( L_negate( ImdctOut_fx[L / 2 - 1 - i] ), 6 ) );
1741 0 : move16();
1742 : }
1743 :
1744 0 : FOR( i = N_ZERO_NB; i < L / 2; i++ )
1745 : {
1746 : /*ImdctOutWin[L + i] = -ImdctOut[L/2 - 1 - i] * win[L - 1 - i];*/
1747 0 : ImdctOutWin_fx[L + i] = extract_l( L_shr( Mult_32_16( L_negate( ImdctOut_fx[L / 2 - 1 - i] ), win_fx[L - 1 - i] ), 6 ) );
1748 0 : move16();
1749 : }
1750 :
1751 0 : return;
1752 : }
1753 :
1754 0 : static void Smoothing_vector_scaledown_NB_fx(
1755 : const Word16 OldauOutnoWin_fx[], /* i : Input vector 1 Q0 */
1756 : const Word16 ImdctOutWin_fx[], /* i : Input vector 2 Q0 */
1757 : const Word16 SmoothingWin_fx[], /* i : Smoothing window Q15 */
1758 : Word16 auOut_fx[], /* o : Output vector that contains vector 1 .* vector 2 Q0 */
1759 : const Word16 ol_size /* i : Overlap size */
1760 :
1761 : )
1762 : {
1763 : Word16 i;
1764 : Word16 weight_fx; // Q15
1765 :
1766 0 : FOR( i = 0; i < ol_size; i++ )
1767 : {
1768 0 : weight_fx = SmoothingWin_fx[i];
1769 0 : move16();
1770 0 : auOut_fx[i] = add( mult( OldauOutnoWin_fx[i], sub( 32767, weight_fx ) ),
1771 0 : mult( ImdctOutWin_fx[i], mult_r( 23170, weight_fx ) ) );
1772 0 : move16();
1773 : }
1774 :
1775 0 : return;
1776 : }
1777 :
1778 :
1779 0 : static void Scaledown_fx(
1780 : Word16 x[], /* i : Input vector */
1781 : Word16 y[], /* o : Output vector that contains vector 1 .* vector 2 */
1782 : Word16 scale_v, /*Q15 */
1783 : const Word16 N /* i : Overlap size */
1784 : )
1785 : {
1786 : Word16 i;
1787 :
1788 0 : FOR( i = 0; i < N; i++ )
1789 : {
1790 0 : y[i] = mult( x[i], scale_v );
1791 0 : move16();
1792 : }
1793 :
1794 0 : return;
1795 : }
1796 :
1797 0 : void time_domain_FEC_HQ_fx(
1798 : Decoder_State *st_fx, /* i : Decoder State */
1799 : Word32 *wtda_audio_fx, /* i : input Q6 */
1800 : Word16 *out_fx, /* o : output audio Q0 */
1801 : Word16 mean_en_high_fx, /* i : transient flag */
1802 : const Word16 output_frame,
1803 : Word16 *Q_synth )
1804 : {
1805 : HQ_NBFEC_HANDLE hHQ_nbfec;
1806 : HQ_DEC_HANDLE hHQ_core;
1807 0 : hHQ_nbfec = st_fx->hHQ_nbfec;
1808 0 : hHQ_core = st_fx->hHQ_core;
1809 :
1810 0 : IF( hHQ_core->Q_old_wtda != 0 )
1811 : {
1812 0 : Scale_sig( hHQ_core->old_out_fx, output_frame, negate( hHQ_core->Q_old_wtda ) );
1813 0 : hHQ_core->Q_old_wtda = 0;
1814 0 : move16();
1815 : }
1816 :
1817 0 : test();
1818 0 : test();
1819 0 : test();
1820 0 : test();
1821 0 : test();
1822 0 : test();
1823 0 : IF( ( EQ_16( st_fx->nbLostCmpt, 1 ) ) && ( EQ_16( hHQ_nbfec->phase_mat_flag, 1 ) ) && ( hHQ_nbfec->phase_mat_next == 0 ) )
1824 : {
1825 0 : IF( FEC_phase_matching_fx( hHQ_nbfec, wtda_audio_fx, out_fx, hHQ_core->old_out_fx, hHQ_nbfec->old_out_pha_fx ) )
1826 : {
1827 : /* window_ola( wtda_audio, out, st->old_out, output_frame, 0, 0, 0 ); */
1828 0 : window_ola_fx( wtda_audio_fx, out_fx, Q_synth, hHQ_core->old_out_fx, &hHQ_core->Q_old_wtda, output_frame, ALDO_WINDOW, ALDO_WINDOW, 0, 0, 0 );
1829 0 : hHQ_nbfec->phase_mat_next = 0;
1830 0 : move16();
1831 : }
1832 : ELSE
1833 : {
1834 0 : hHQ_nbfec->phase_mat_next = 1;
1835 0 : move16();
1836 0 : *Q_synth = 0;
1837 0 : move16();
1838 : }
1839 : }
1840 0 : ELSE IF( ( EQ_16( st_fx->prev_bfi, 1 ) ) && ( st_fx->bfi == 0 ) && ( EQ_16( hHQ_nbfec->phase_mat_next, 1 ) ) )
1841 : {
1842 0 : FEC_phase_matching_nextgood_fx( wtda_audio_fx, out_fx, hHQ_core->old_out_fx, hHQ_nbfec->old_out_pha_fx, mean_en_high_fx );
1843 :
1844 0 : hHQ_nbfec->phase_mat_next = 0;
1845 0 : move16();
1846 0 : *Q_synth = 0;
1847 0 : move16();
1848 : }
1849 0 : ELSE IF( ( EQ_16( st_fx->prev_bfi, 1 ) ) && ( EQ_16( st_fx->bfi, 1 ) ) && ( EQ_16( hHQ_nbfec->phase_mat_next, 1 ) ) )
1850 : {
1851 0 : FEC_phase_matching_burst_fx( wtda_audio_fx, out_fx, hHQ_core->old_out_fx, hHQ_nbfec->old_out_pha_fx, hHQ_nbfec->prev_oldauOut_fx );
1852 0 : hHQ_nbfec->phase_mat_next = 1;
1853 0 : move16();
1854 0 : *Q_synth = 0;
1855 0 : move16();
1856 : }
1857 : ELSE
1858 : {
1859 : /*n4 = (short)(N_LEAD_MDCT*(float)(output_frame/20));*/
1860 0 : test();
1861 0 : IF( st_fx->bfi == 0 && EQ_16( st_fx->prev_bfi, 1 ) )
1862 : {
1863 0 : test();
1864 0 : IF( ( EQ_16( hHQ_nbfec->stat_mode_out, 1 ) ) || ( LT_16( hHQ_nbfec->diff_energy_fx, ED_THRES_50P_fx ) ) ) /* Q11 */
1865 0 : {
1866 : Word16 tmp;
1867 :
1868 0 : tmp = 0;
1869 0 : move16();
1870 0 : if ( GT_16( st_fx->old_bfi_cnt, 1 ) )
1871 : {
1872 0 : tmp = 1;
1873 0 : move16();
1874 : }
1875 0 : Repetition_smoothing_nextgood_fx( wtda_audio_fx, out_fx, hHQ_nbfec->oldIMDCTout_fx, hHQ_core->old_out_fx, tmp, N_LEAD_NB );
1876 0 : *Q_synth = 0;
1877 0 : move16();
1878 : }
1879 0 : ELSE IF( GT_16( st_fx->old_bfi_cnt, 1 ) )
1880 : {
1881 0 : Next_good_after_burst_erasures_fx( wtda_audio_fx, out_fx, hHQ_core->old_out_fx, N_LEAD_NB );
1882 0 : *Q_synth = 0;
1883 0 : move16();
1884 : }
1885 : ELSE
1886 : {
1887 : /*window_ola( wtda_audio, out, st->old_out, output_frame, 0, 0, 0); */
1888 0 : window_ola_fx( wtda_audio_fx, out_fx, Q_synth, hHQ_core->old_out_fx, &hHQ_core->Q_old_wtda, output_frame,
1889 0 : st_fx->hTcxCfg->tcx_last_overlap_mode, st_fx->hTcxCfg->tcx_curr_overlap_mode, st_fx->prev_bfi, hHQ_core->oldHqVoicing, hHQ_core->oldgapsynth_fx );
1890 : }
1891 : }
1892 : ELSE /* if(st->bfi == 1) */
1893 : {
1894 0 : test();
1895 0 : IF( ( EQ_16( hHQ_nbfec->stat_mode_out, 1 ) ) || ( LT_16( hHQ_nbfec->diff_energy_fx, ED_THRES_50P_fx ) ) )
1896 : {
1897 : /* if( window_ola_bfi( wtda_audio, out, st->oldIMDCTout, st->old_out, output_frame, st->prev_oldauOut, N_LEAD_NB) ) */
1898 0 : IF( Repetition_smoothing_fx( wtda_audio_fx, out_fx, hHQ_nbfec->oldIMDCTout_fx, hHQ_core->old_out_fx, output_frame, hHQ_nbfec->prev_oldauOut_fx, N_LEAD_NB ) )
1899 : {
1900 : /*window_ola( wtda_audio, out, st->old_out, output_frame, 0, 0, 0);*/
1901 0 : window_ola_fx( wtda_audio_fx, out_fx, Q_synth, hHQ_core->old_out_fx, &hHQ_core->Q_old_wtda, output_frame,
1902 0 : st_fx->hTcxCfg->tcx_last_overlap_mode, st_fx->hTcxCfg->tcx_curr_overlap_mode, st_fx->prev_bfi, hHQ_core->oldHqVoicing, hHQ_core->oldgapsynth_fx );
1903 : }
1904 : ELSE
1905 : {
1906 0 : *Q_synth = 0;
1907 0 : move16();
1908 : }
1909 : }
1910 : ELSE
1911 : {
1912 : /*window_ola( wtda_audio, out, st->old_out, output_frame, 0, 0, 0 );*/
1913 0 : window_ola_fx( wtda_audio_fx, out_fx, Q_synth, hHQ_core->old_out_fx, &hHQ_core->Q_old_wtda, output_frame,
1914 0 : st_fx->hTcxCfg->tcx_last_overlap_mode, st_fx->hTcxCfg->tcx_curr_overlap_mode, st_fx->prev_bfi, hHQ_core->oldHqVoicing, hHQ_core->oldgapsynth_fx );
1915 : }
1916 : }
1917 0 : hHQ_nbfec->phase_mat_next = 0;
1918 0 : move16();
1919 : }
1920 :
1921 0 : return;
1922 : }
1923 :
1924 0 : static void Next_good_after_burst_erasures_fx(
1925 : const Word32 *ImdctOut_fx, // Q6
1926 : Word16 *auOut_fx, // Q0
1927 : Word16 *OldauOut_fx, // Q0
1928 : const Word16 ol_size )
1929 : {
1930 : Word16 i, L;
1931 : Word16 ImdctOutWin_fx[2 * L_FRAME48k]; // Q0
1932 : Word16 win_NB_fx[L_FRAME8k + 25];
1933 :
1934 0 : L = L_FRAME8k;
1935 0 : move16();
1936 0 : FOR( i = 0; i < add( L, 25 ); i++ )
1937 : {
1938 0 : win_NB_fx[i] = window_48kHz_fx[i * 6 + 3]; // Q15
1939 0 : move16();
1940 : }
1941 :
1942 : /* Windowing */
1943 0 : Windowing_1st_NB_fx( ImdctOutWin_fx, ImdctOut_fx, win_NB_fx, NULL, 0 );
1944 0 : Windowing_2nd_NB_fx( ImdctOutWin_fx, ImdctOut_fx, win_NB_fx );
1945 :
1946 : /* Overlapping with next good frame : Overlapping to remove the discontinuity */
1947 0 : Smoothing_vector_scaledown_NB_fx( &OldauOut_fx[N_ZERO_NB], &ImdctOutWin_fx[N_Z_L_O_NB], SmoothingWin_NB875_fx, &OldauOut_fx[N_ZERO_NB], ol_size );
1948 :
1949 : /* Scale down the overlapped signal */
1950 0 : Scaledown_fx( &ImdctOutWin_fx[ol_size + N_Z_L_O_NB], &OldauOut_fx[ol_size + N_ZERO_NB], 23170, sub( N_Z_L_NB, ol_size ) );
1951 :
1952 : /* Common Overlapping */
1953 0 : common_overlapping_fx( auOut_fx, ImdctOutWin_fx, OldauOut_fx, N_Z_L_NB, N_ZERO_NB, 0, N_ZERO_NB, L, N_Z_L_NB );
1954 0 : Copy( &ImdctOutWin_fx[L], OldauOut_fx, L );
1955 :
1956 0 : return;
1957 : }
1958 :
1959 : /*--------------------------------------------------------------------------
1960 : * save_synthesis_hq_fec_fx()
1961 : *
1962 : * Save synthesis for HQ FEC
1963 : *-------------------------------------------------------------------------*/
1964 :
1965 1028179 : void save_synthesis_hq_fec_fx(
1966 : Decoder_State *st, /* i/o: decoder state structure */
1967 : const Word16 synth_fx[], /* i : decoded synthesis (EVS) */
1968 : const Word32 output_fx[], /* i : decoded synthesis */
1969 : const Word16 output_frame, /* i : decoded synthesis */
1970 : const Word16 Qpostd, /* i : Q value of delayed signal */
1971 : CPE_DEC_HANDLE hCPE /* i : CPE decoder structure */
1972 : )
1973 : {
1974 : Word16 post_hq_delay;
1975 :
1976 1028179 : SWITCH( st->element_mode )
1977 : {
1978 3100 : case EVS_MONO:
1979 3100 : post_hq_delay = NS2SA_FX2( st->output_Fs, POST_HQ_DELAY_NS );
1980 3100 : BREAK;
1981 311046 : case IVAS_SCE:
1982 311046 : post_hq_delay = NS2SA_FX2( st->output_Fs, DELAY_CLDFB_NS );
1983 311046 : BREAK;
1984 59047 : case IVAS_CPE_DFT:
1985 59047 : test();
1986 59047 : IF( EQ_16( hCPE->nchan_out, 1 ) && hCPE->hStereoDft->hConfig->res_cod_mode == STEREO_DFT_RES_COD_OFF )
1987 : {
1988 17001 : post_hq_delay = NS2SA_FX2( st->output_Fs, DELAY_CLDFB_NS );
1989 : }
1990 : ELSE
1991 : {
1992 42046 : post_hq_delay = 0;
1993 42046 : move16();
1994 : }
1995 59047 : BREAK;
1996 654986 : default:
1997 654986 : post_hq_delay = 0;
1998 654986 : move16();
1999 654986 : BREAK;
2000 : }
2001 :
2002 1028179 : test();
2003 1028179 : test();
2004 1028179 : test();
2005 1028179 : test();
2006 1028179 : test();
2007 1028179 : IF( ( EQ_16( st->codec_mode, MODE1 ) && st->hTcxDec != NULL ) && ( ( ( st->core == ACELP_CORE ) && !( EQ_16( st->bfi, 1 ) && EQ_16( st->con_tcx, 1 ) ) ) || EQ_16( st->core, HQ_CORE ) ) )
2008 : {
2009 171099 : IF( st->element_mode == EVS_MONO )
2010 : {
2011 1852 : Copy( st->hTcxDec->synth_history_fx + output_frame, st->hTcxDec->synth_history_fx, add( sub( output_frame, post_hq_delay ), NS2SA_FX2( st->output_Fs, PH_ECU_MEM_NS ) ) ); /*hTcxDec->q_synth_history_fx*/
2012 1852 : Copy_Scale_sig( synth_fx, st->hTcxDec->old_synthFB_fx + sub( output_frame, post_hq_delay ), output_frame, negate( Qpostd ) ); /* output_sp not initialized yet */
2013 : /* reset the remaining buffer, which is read in TCX concealment the necessary samples to fill
2014 : this buffer are not available for all cases, the impact on the output is limited */
2015 1852 : set16_fx( st->hTcxDec->old_synthFB_fx + sub( shl( output_frame, 1 ), post_hq_delay ), 0, post_hq_delay );
2016 :
2017 1852 : IF( GE_16( output_frame, L_FRAME16k ) )
2018 : {
2019 1852 : Copy_Scale_sig( st->prev_synth_buffer_fx, st->hTcxDec->old_synthFB_fx + sub( shl( output_frame, 1 ), NS2SA_FX2( st->output_Fs, DELAY_BWE_TOTAL_NS ) ), NS2SA_FX2( st->output_Fs, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS ), negate( st->Qprev_synth_buffer_fx ) ); /*Q0*/
2020 : }
2021 : /* IVAS Floating point code has the commented-out else branch below, but it does not appear to be necessary. To be verified
2022 : else
2023 : {
2024 : mvr2r( st->hHQ_core->old_out + NS2SA( st->output_Fs, N_ZERO_MDCT_NS ), st->hTcxDec->old_synthFB + 2 * output_frame, NS2SA( st->output_Fs, PH_ECU_LOOKAHEAD_NS ) );
2025 : }
2026 : */
2027 :
2028 1852 : IF( st->core != ACELP_CORE )
2029 : {
2030 429 : IF( GE_16( output_frame, L_FRAME16k ) )
2031 : {
2032 429 : Copy_Scale_sig( st->delay_buf_out_fx, st->hTcxDec->old_synthFB_fx + sub( shl( output_frame, 1 ), NS2SA_FX2( st->output_Fs, DELAY_CLDFB_NS ) ), NS2SA_FX2( st->output_Fs, DELAY_CLDFB_NS ), negate( Qpostd ) ); /*Q0*/
2033 429 : Copy_Scale_sig( st->hHQ_core->old_out_fx + NS2SA_FX2( st->output_Fs, N_ZERO_MDCT_NS ), st->hTcxDec->old_synthFB_fx + shl( output_frame, 1 ), NS2SA_FX2( st->output_Fs, PH_ECU_LOOKAHEAD_NS ), negate( st->hHQ_core->Q_old_wtda ) ); /*Q0*/
2034 : }
2035 : ELSE
2036 : {
2037 :
2038 0 : Copy_Scale_sig( st->delay_buf_out_fx, st->hTcxDec->old_synthFB_fx + sub( shl( output_frame, 1 ), NS2SA_FX2( st->output_Fs, DELAY_BWE_TOTAL_NS ) ), NS2SA_FX2( st->output_Fs, DELAY_CLDFB_NS ), negate( Qpostd ) ); /*Q0*/
2039 0 : Copy_Scale_sig( st->hHQ_core->old_out_fx + NS2SA_FX2( st->output_Fs, N_ZERO_MDCT_NS ), st->hTcxDec->old_synthFB_fx + sub( shl( output_frame, 1 ), NS2SA_FX2( st->output_Fs, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS ) ), NS2SA_FX2( st->output_Fs, PH_ECU_LOOKAHEAD_NS ), negate( st->hHQ_core->Q_old_wtda ) ); /*Q0*/
2040 : }
2041 : }
2042 : }
2043 : ELSE
2044 : {
2045 169247 : Copy( st->hTcxDec->synth_history_fx + output_frame, st->hTcxDec->synth_history_fx, add( sub( output_frame, post_hq_delay ), NS2SA_FX2( st->output_Fs, PH_ECU_MEM_NS ) ) );
2046 137452447 : FOR( Word16 i = 0; i < output_frame; i++ )
2047 : {
2048 137283200 : st->hTcxDec->old_synthFB_fx[( ( i + output_frame ) - post_hq_delay )] = extract_h( L_shl_sat( output_fx[i], 16 ) ); // Q16
2049 137283200 : move16();
2050 : }
2051 :
2052 169247 : IF( st->core != ACELP_CORE )
2053 : {
2054 7400 : Copy( st->delay_buf_out_fx, st->hTcxDec->old_synthFB_fx + sub( shl( output_frame, 1 ), post_hq_delay ), post_hq_delay );
2055 7400 : Copy( st->hHQ_core->old_out_fx + NS2SA_FX2( st->output_Fs, N_ZERO_MDCT_NS ), st->hTcxDec->old_synthFB_fx + shl( output_frame, 1 ), NS2SA_FX2( st->output_Fs, PH_ECU_LOOKAHEAD_NS ) );
2056 : }
2057 : }
2058 : }
2059 1028179 : return;
2060 : }
|