Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 :
6 : #include <stdlib.h>
7 : #include <stdio.h>
8 : #include <assert.h>
9 : #include "rom_com.h"
10 : #include "stat_com.h"
11 : // #include "prot_fx.h"
12 : #include "prot_fx.h"
13 : #include "basop_util.h"
14 : #include "stl.h"
15 : // #include "basop_mpy.h"
16 : #include "prot_fx_enc.h"
17 : #include <math.h>
18 : #include "ivas_prot_fx.h"
19 : #include "ivas_rom_com_fx.h"
20 : #ifdef DEBUGGING
21 : #include "debug.h"
22 : #endif
23 :
24 : #define SIMILAR_TNS_THRESHOLD_FX_IN_Q15 ( 1311 )
25 : #define TNS_GAIN_THRESHOLD_FOR_WHITE_FX_IN_Q7 ( 384 )
26 : #define TNS_GAIN_THRESHOLD_FOR_WHITE_FX_IN_Q23 ( 25165824 )
27 :
28 : /* Up to the Autocorrelation it is the same code as in GetMDCT, with the difference in the parameters in the call to tcx_windowing_analysis */
29 108933 : void HBAutocorrelation_fx(
30 : TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
31 : Word16 left_overlap_mode, /* input: overlap mode of left window half */
32 : Word16 right_overlap_mode, /* input: overlap mode of right window half */
33 : Word16 speech[], /* input: speech[-LFAC..L_frame+LFAC] Qx*/
34 : Word16 L_frame, /* input: frame length */
35 : Word32 *r, /* output: autocorrelations vector */
36 : Word16 m /* input : order of LP filter */
37 : )
38 : {
39 : Word16 i, j, left_overlap, right_overlap;
40 : Word16 len, norm, shift, fact;
41 : Word32 L_tmp, L_sum;
42 : Word16 y[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX];
43 :
44 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
45 108933 : Flag Overflow = 0;
46 108933 : move32();
47 : #endif
48 :
49 : /*-----------------------------------------------------------*
50 : * Windowing *
51 : *-----------------------------------------------------------*/
52 :
53 108933 : WindowSignal( hTcxCfg, hTcxCfg->tcx_offset, left_overlap_mode, right_overlap_mode, &left_overlap, &right_overlap, speech, &L_frame, y, 1, 0 );
54 :
55 : /*-----------------------------------------------------------*
56 : * Autocorrelation *
57 : *-----------------------------------------------------------*/
58 :
59 108933 : len = add( L_frame, shr( add( left_overlap, right_overlap ), 1 ) );
60 :
61 : /* calculate shift */
62 108933 : shift = 0;
63 108933 : move16();
64 108933 : L_sum = L_deposit_l( 0 );
65 108933 : Overflow = 0;
66 108933 : move32();
67 96660494 : FOR( i = 0; i < len; i += 1 )
68 : {
69 : /* Test Addition */
70 96551563 : L_mac0_o( L_sum, y[i], y[i], &Overflow );
71 96551563 : IF( Overflow )
72 : {
73 2 : Overflow = 0;
74 2 : move32();
75 2 : shift = 1;
76 2 : move16();
77 2 : L_tmp = L_msu0( 0, y[i], y[i] );
78 2 : L_tmp = L_shr( L_tmp, 1 );
79 2 : L_sum = L_add( L_shr( L_sub_o( L_sum, 1, &Overflow ), 1 ), 1 );
80 2 : L_sum = L_sub_o( L_sum, L_tmp, &Overflow );
81 375 : FOR( j = i + 1; j < len; j++ )
82 : {
83 373 : L_tmp = L_msu0( 0, y[j], y[j] );
84 373 : L_tmp = L_shr( L_tmp, shift );
85 :
86 : /* Test Addition */
87 373 : L_sub_o( L_sum, L_tmp, &Overflow );
88 373 : IF( Overflow )
89 : {
90 0 : Overflow = 0;
91 0 : move32();
92 0 : shift = add( shift, 1 );
93 0 : L_tmp = L_shr( L_tmp, 1 );
94 0 : L_sum = L_add( L_shr( L_sub_o( L_sum, 1, &Overflow ), 1 ), 1 );
95 : }
96 373 : L_sum = L_sub_o( L_sum, L_tmp, &Overflow );
97 : }
98 2 : BREAK;
99 : }
100 : /* Perform Addition */
101 96551561 : L_sum = L_mac0_o( L_sum, y[i], y[i], &Overflow );
102 : }
103 :
104 : /* scale signal to avoid overflow in autocorrelation */
105 108933 : IF( shift > 0 )
106 : {
107 2 : fact = lshr( -32768, shift );
108 1474 : FOR( i = 0; i < len; i++ )
109 : {
110 1472 : y[i] = mult_r( y[i], fact );
111 1472 : move16();
112 : }
113 : }
114 :
115 : /* Compute and normalize r[0] */
116 108933 : L_sum = L_mac0( 1, y[0], y[0] );
117 96551936 : FOR( i = 1; i < len; i++ )
118 : {
119 96443003 : L_sum = L_mac0( L_sum, y[i], y[i] );
120 : }
121 :
122 108933 : norm = norm_l( L_sum );
123 108933 : L_sum = L_shl( L_sum, norm );
124 108933 : r[0] = L_sum;
125 108933 : move32();
126 :
127 : /* Compute r[1] to r[m] */
128 1851861 : FOR( i = 1; i <= m; i++ )
129 : {
130 1742928 : L_sum = L_mult0( y[0], y[i] );
131 1530016088 : FOR( j = 1; j < len - i; j++ )
132 : {
133 1528273160 : L_sum = L_mac0( L_sum, y[j], y[j + i] );
134 : }
135 :
136 1742928 : L_sum = L_shl( L_sum, norm );
137 1742928 : r[i] = L_sum;
138 1742928 : move32();
139 : }
140 108933 : }
141 :
142 402 : void TNSAnalysis_fx(
143 : TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
144 : Word16 L_frame, /* input: frame length */
145 : Word16 L_spec,
146 : Word16 tcxMode, /* input: TCX mode for the frame/subframe - TCX20 | TCX10 | TCX 5 (meaning 2 x TCX 5) */
147 : Word8 isAfterACELP, /* input: Flag indicating if the last frame was ACELP. For the second TCX subframe it should be 0 */
148 : Word32 spectrum[], /* input: MDCT spectrum Qx*/
149 : STnsData *pTnsData, /* output: Tns data */
150 : Word8 *pfUseTns, /* output: Flag indicating if TNS is used */
151 : Word16 *predictionGain /*Q7*/
152 : )
153 : {
154 : Word32 buff[8];
155 402 : Word16 tmp = 0; /* initialization only to avoid compiler warning, not counted */
156 402 : Word16 tmp2 = 0; /* initialization only to avoid compiler warning, not counted */
157 402 : move16();
158 402 : move16();
159 :
160 : /* Init TNS */
161 402 : *pfUseTns = 0;
162 402 : move16();
163 :
164 402 : IF( hTcxCfg->fIsTNSAllowed != 0 )
165 : {
166 402 : hTcxCfg->pCurrentTnsConfig = &hTcxCfg->tnsConfig[( tcxMode - TCX_20 ) == 0][isAfterACELP];
167 402 : L_spec = hTcxCfg->pCurrentTnsConfig->iFilterBorders[0];
168 402 : move16();
169 :
170 : /*-----------------------------------------------------------*
171 : * Temporal Noise Shaping analysis *
172 : *-----------------------------------------------------------*/
173 :
174 402 : IF( EQ_16( tcxMode, TCX_5 ) )
175 : {
176 0 : tmp = shr( L_frame, 2 );
177 :
178 : /* rearrange LF sub-window lines prior to TNS analysis & filtering */
179 0 : tmp2 = shr( L_spec, 1 );
180 :
181 0 : IF( LT_16( tmp2, tmp ) )
182 : {
183 0 : Copy32( spectrum + 8, spectrum + 16, sub( tmp2, 8 ) );
184 0 : Copy32( spectrum + tmp, spectrum + 8, 8 );
185 0 : Copy32( spectrum + tmp + 8, spectrum + tmp2 + 8, sub( tmp2, 8 ) );
186 : }
187 : ELSE
188 : {
189 0 : Copy32( spectrum + tmp, buff, 8 );
190 0 : Copy32( spectrum + 8, spectrum + 16, sub( tmp, 8 ) );
191 0 : Copy32( buff, spectrum + 8, 8 );
192 : }
193 : }
194 :
195 402 : move16();
196 402 : *pfUseTns = (Word8) DetectTnsFilt_fx( hTcxCfg->pCurrentTnsConfig, spectrum, pTnsData, predictionGain );
197 :
198 : /* If TNS should be used then get the residual after applying it inplace in spectrum */
199 402 : IF( *pfUseTns != 0 )
200 : {
201 4 : ApplyTnsFilter( hTcxCfg->pCurrentTnsConfig, pTnsData, spectrum, 1 );
202 : }
203 :
204 402 : IF( EQ_16( tcxMode, TCX_5 ) )
205 : {
206 : /* undo rearrangement of LF sub-window lines prior to TNS analysis */
207 0 : IF( LT_16( tmp2, tmp ) )
208 : {
209 0 : Copy32( spectrum + tmp2 + 8, spectrum + tmp + 8, sub( tmp2, 8 ) );
210 0 : Copy32( spectrum + 8, spectrum + tmp, 8 );
211 0 : Copy32( spectrum + 16, spectrum + 8, sub( tmp2, 8 ) );
212 0 : set32_fx( spectrum + tmp2, 0, sub( tmp, tmp2 ) );
213 0 : set32_fx( spectrum + tmp + tmp2, 0, sub( tmp, tmp2 ) );
214 : }
215 : ELSE
216 : {
217 0 : Copy32( spectrum + 8, buff, 8 );
218 0 : Copy32( spectrum + 16, spectrum + 8, sub( tmp, 8 ) );
219 0 : Copy32( buff, spectrum + tmp, 8 );
220 : }
221 : }
222 : }
223 402 : }
224 :
225 237838 : void TNSAnalysis_ivas_fx(
226 : TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
227 : Word16 L_frame, /* i : frame length */
228 : Word16 L_spec, /* i : length of the spectrum */
229 : Word16 transform_type, /* i : transform type for the frame/subframe - TCX20 | TCX10 | TCX 5 (meaning 2 x TCX 5) */
230 : Word8 isAfterACELP, /* i : Flag indicating if the last frame was ACELP. For the second TCX subframe it should be 0 */
231 : Word32 spectrum[], /* i : MDCT spectrum Q=Qx*/
232 : TRAN_DET_HANDLE hTranDet, /* i : handle transient detection */
233 : Word16 ltp_gain, /* i : ltp gain Q=15*/
234 : STnsData *pTnsData, /* o : Tns data */
235 : Word8 *pfUseTns, /* o : Flag indicating if TNS is used */
236 : Word16 *predictionGain /* o : TNS prediction gain Q=7 */
237 : )
238 : {
239 : Word32 buff[8];
240 237838 : Word16 tmp = 0; /* initialization only to avoid compiler warning, not counted */
241 237838 : Word16 tmp2 = 0; /* initialization only to avoid compiler warning, not counted */
242 237838 : move16();
243 237838 : move16();
244 :
245 : /* Init TNS */
246 237838 : *pfUseTns = 0;
247 237838 : move16();
248 :
249 237838 : IF( hTcxCfg->fIsTNSAllowed != 0 )
250 : {
251 161707 : hTcxCfg->pCurrentTnsConfig = &hTcxCfg->tnsConfig[( transform_type - TCX_20 ) == 0][isAfterACELP];
252 161707 : L_spec = hTcxCfg->pCurrentTnsConfig->iFilterBorders[0];
253 161707 : move16();
254 :
255 : /*-----------------------------------------------------------*
256 : * Temporal Noise Shaping analysis *
257 : *-----------------------------------------------------------*/
258 :
259 161707 : IF( EQ_16( transform_type, TCX_5 ) )
260 : {
261 2197 : tmp = shr( L_frame, 2 );
262 :
263 : /* rearrange LF sub-window lines prior to TNS analysis & filtering */
264 2197 : tmp2 = shr( L_spec, 1 );
265 :
266 2197 : IF( LT_16( tmp2, tmp ) )
267 : {
268 2129 : Copy32( spectrum + 8, spectrum + 16, sub( tmp2, 8 ) );
269 2129 : Copy32( spectrum + tmp, spectrum + 8, 8 );
270 2129 : Copy32( spectrum + tmp + 8, spectrum + tmp2 + 8, sub( tmp2, 8 ) );
271 : }
272 : ELSE
273 : {
274 68 : Copy32( spectrum + tmp, buff, 8 );
275 68 : Copy32( spectrum + 8, spectrum + 16, sub( tmp, 8 ) );
276 68 : Copy32( buff, spectrum + 8, 8 );
277 : }
278 : }
279 :
280 161707 : move16();
281 161707 : *pfUseTns = (Word8) DetectTnsFilt_ivas_fx( hTcxCfg->pCurrentTnsConfig, spectrum, pTnsData, hTranDet, (Word8) NE_16( transform_type, TCX_20 ), ltp_gain, predictionGain );
282 :
283 : /* If TNS should be used then get the residual after applying it inplace in spectrum */
284 161707 : IF( *pfUseTns != 0 )
285 : {
286 17613 : ApplyTnsFilter( hTcxCfg->pCurrentTnsConfig, pTnsData, spectrum, 1 );
287 : }
288 :
289 161707 : IF( EQ_16( transform_type, TCX_5 ) )
290 : {
291 : /* undo rearrangement of LF sub-window lines prior to TNS analysis */
292 2197 : IF( LT_16( tmp2, tmp ) )
293 : {
294 2129 : Copy32( spectrum + tmp2 + 8, spectrum + tmp + 8, sub( tmp2, 8 ) );
295 2129 : Copy32( spectrum + 8, spectrum + tmp, 8 );
296 2129 : Copy32( spectrum + 16, spectrum + 8, sub( tmp2, 8 ) );
297 2129 : set32_fx( spectrum + tmp2, 0, sub( tmp, tmp2 ) );
298 2129 : set32_fx( spectrum + tmp + tmp2, 0, sub( tmp, tmp2 ) );
299 : }
300 : ELSE
301 : {
302 68 : Copy32( spectrum + 8, buff, 8 );
303 68 : Copy32( spectrum + 16, spectrum + 8, sub( tmp, 8 ) );
304 68 : Copy32( buff, spectrum + tmp, 8 );
305 : }
306 : }
307 : }
308 237838 : }
309 :
310 662 : void ShapeSpectrum_fx(
311 : TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
312 : Word16 A[], /* input: quantized coefficients NxAz_q[M+1] Q = 14 - norm(A[0])*/
313 : Word16 gainlpc[], /* output: MDCT gains for the previous frame Q(15-gainlpc_e)*/
314 : Word16 gainlpc_e[], /* output: MDCT gains exponents */
315 : Word16 L_frame_glob, /* input: frame length */
316 : Word16 L_spec,
317 : Word32 spectrum[], /* i/o: MDCT spectrum */
318 : Word8 pfUseTns, /* output: Flag indicating if TNS is used */
319 : Encoder_State *st )
320 : {
321 : Word16 L_frame;
322 : Word16 Ap[M + 2];
323 : Word16 gamma1;
324 : Word16 gainlpc_noinv[FDNS_NPTS];
325 : Word16 gainlpc_noinv_e[FDNS_NPTS];
326 : Word16 i;
327 662 : Word32 max_low_pre = 0, max_high_pre = 0;
328 662 : move32();
329 662 : move32();
330 662 : TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
331 :
332 : /*-----------------------------------------------------------*
333 : * Init *
334 : *-----------------------------------------------------------*/
335 :
336 : /* Init lengths */
337 662 : L_frame = L_frame_glob;
338 662 : move16();
339 662 : gamma1 = st->gamma;
340 662 : move16();
341 662 : if ( st->enableTcxLpc != 0 )
342 : {
343 0 : gamma1 = 0x7FFF;
344 0 : move16();
345 : }
346 :
347 : /* if past frame is ACELP */
348 :
349 662 : IF( st->last_core == ACELP_CORE )
350 : {
351 39 : L_frame = add( L_frame, hTcxCfg->tcx_offset );
352 39 : L_spec = add( L_spec, shr( hTcxCfg->tcx_coded_lines, 2 ) );
353 39 : if ( hTcxCfg->lfacNext < 0 )
354 : {
355 39 : L_frame = sub( L_frame, hTcxCfg->lfacNext );
356 39 : move16();
357 : }
358 : }
359 :
360 662 : test();
361 662 : tcxGetNoiseFillingTilt( A,
362 : M,
363 : L_frame,
364 662 : ( GE_32( st->total_brate, ACELP_13k20 ) && st->rf_mode == 0 ),
365 : &hTcxEnc->noiseTiltFactor );
366 :
367 : /* Calculate Spectrum Flatness Measure for the TCX Concealment */
368 662 : IF( st->enablePlcWaveadjust )
369 : {
370 0 : hTcxCfg->SFM2 = SFM_Cal_fx( spectrum, s_min( 200, L_frame ) );
371 0 : move32();
372 : }
373 :
374 662 : test();
375 662 : test();
376 662 : test();
377 662 : IF( ( EQ_32( st->total_brate, ACELP_9k60 ) && EQ_16( st->bwidth, SWB ) ) ||
378 : ( EQ_32( st->total_brate, ACELP_13k20 ) && EQ_16( st->bwidth, SWB ) ) )
379 : {
380 260 : max_low_pre = 0;
381 260 : move32();
382 67652 : FOR( i = 0; i < L_frame; i++ )
383 : {
384 67392 : Word32 tmp = L_abs( spectrum[i] );
385 67392 : if ( GT_32( tmp, max_low_pre ) )
386 : {
387 1614 : max_low_pre = tmp;
388 1614 : move32();
389 : }
390 : }
391 :
392 260 : max_high_pre = 0;
393 260 : move32();
394 101348 : FOR( i = 0; i < L_spec - L_frame; i++ )
395 : {
396 101088 : Word32 tmp = L_abs( spectrum[L_frame + i] );
397 101088 : if ( GT_32( tmp, max_high_pre ) )
398 : {
399 2 : max_high_pre = tmp;
400 2 : move32();
401 : }
402 : }
403 : }
404 :
405 : /*-----------------------------------------------------------*
406 : * Pre-shaping in frequency domain using weighted LPC (Wz) *
407 : *-----------------------------------------------------------*/
408 :
409 662 : weight_a_fx( A, Ap, gamma1, M );
410 :
411 662 : lpc2mdct( Ap, M, gainlpc_noinv, gainlpc_noinv_e, gainlpc, gainlpc_e, FDNS_NPTS, 0 );
412 :
413 662 : mdct_shaping( spectrum, L_frame, gainlpc_noinv, gainlpc_noinv_e );
414 232470 : FOR( i = L_frame; i < L_spec; i++ )
415 : {
416 231808 : spectrum[i] = L_shl( Mpy_32_16_1( spectrum[i], gainlpc_noinv[FDNS_NPTS - 1] ), gainlpc_noinv_e[FDNS_NPTS - 1] );
417 231808 : move32();
418 : }
419 :
420 : /* reduce the peaks in the IGF region, to make life of the core-coder easier... */
421 662 : test();
422 662 : test();
423 662 : test();
424 662 : IF( ( EQ_32( st->total_brate, ACELP_9k60 ) && EQ_16( st->bwidth, SWB ) ) ||
425 : ( EQ_32( st->total_brate, ACELP_13k20 ) && EQ_16( st->bwidth, SWB ) ) )
426 : {
427 : Word16 sf_width;
428 : Word16 dist_low, dist_high;
429 : Word16 max_fac_s, max_fac_m;
430 : Word32 max_low, max_low1, max_low2, max_high;
431 : Word16 headroom, shift, tmp16;
432 :
433 :
434 260 : max_fac_m = 24576;
435 260 : move16();
436 : /* max_fac = 3 */
437 260 : max_fac_s = 2;
438 260 : move16();
439 260 : if ( hTcxEnc->tcx_lpc_shaped_ari )
440 : {
441 : /* max_fac = 1.5 */
442 0 : max_fac_s = 1;
443 0 : move16();
444 : }
445 :
446 260 : sf_width = shr( L_frame, 1 );
447 :
448 260 : max_low2 = 0;
449 260 : move32();
450 260 : dist_low = 0;
451 260 : move16();
452 33956 : FOR( i = 0; i < sf_width; i++ )
453 : {
454 33696 : Word32 tmp = L_abs( spectrum[L_frame - 1 - i] );
455 33696 : IF( GT_32( tmp, max_low2 ) )
456 : {
457 1493 : max_low2 = tmp;
458 1493 : move32();
459 1493 : dist_low = i;
460 1493 : move16();
461 : }
462 : }
463 :
464 260 : max_low1 = 0;
465 260 : move32();
466 33956 : FOR( i = 0; i < ( L_frame - sf_width ); i++ )
467 : {
468 33696 : Word32 tmp = L_abs( spectrum[L_frame - sf_width - 1 - i] );
469 33696 : if ( GT_32( tmp, max_low1 ) )
470 : {
471 2316 : max_low1 = tmp;
472 2316 : move32();
473 : }
474 33696 : if ( GT_32( tmp, max_low2 ) )
475 : {
476 3794 : dist_low = add( sf_width, i );
477 : }
478 : }
479 :
480 260 : max_low = L_max( max_low1, max_low2 );
481 :
482 260 : max_high = 0;
483 260 : move32();
484 260 : dist_high = 0;
485 260 : move16();
486 101348 : FOR( i = 0; i < ( L_spec - L_frame ); i++ )
487 : {
488 101088 : Word32 tmp = L_abs( spectrum[L_frame + i] );
489 101088 : IF( GT_32( tmp, max_high ) )
490 : {
491 2 : max_high = tmp;
492 2 : move32();
493 2 : dist_high = i;
494 2 : move16();
495 : }
496 : }
497 :
498 : /* at least 9 bits headroom are needed for below multiplicitions */
499 260 : shift = 0;
500 260 : move16();
501 260 : headroom = 31;
502 260 : move16();
503 :
504 260 : tmp16 = norm_l( max_low );
505 260 : if ( max_low != 0 )
506 260 : headroom = s_min( headroom, tmp16 );
507 :
508 260 : tmp16 = norm_l( max_low2 );
509 260 : if ( max_low2 != 0 )
510 260 : headroom = s_min( headroom, tmp16 );
511 :
512 260 : tmp16 = norm_l( max_high );
513 260 : if ( max_high != 0 )
514 1 : headroom = s_min( headroom, tmp16 );
515 :
516 260 : if ( LT_16( headroom, 9 ) )
517 : {
518 0 : shift = sub( 9, headroom );
519 : }
520 260 : max_low = L_shr( max_low, shift );
521 260 : max_low2 = L_shr( max_low2, shift );
522 260 : max_high = L_shr( max_high, shift );
523 :
524 260 : test();
525 260 : test();
526 260 : IF( GT_32( imult3216( max_high, dist_high ), imult3216( L_shr( max_low, 2 ), dist_low ) ) && ( GT_32( max_low_pre, L_shr( max_high_pre, 4 ) ) ) && ( GT_32( max_high, L_shl( Mpy_32_16_r( max_low2, max_fac_m ), max_fac_s ) ) ) )
527 : {
528 : Word16 fac;
529 1 : fac = divide3232( max_low2, max_high );
530 1 : fac = shl( mult_r( fac, max_fac_m ), max_fac_s );
531 :
532 385 : FOR( i = 0; i < sub( L_spec, L_frame ); i++ )
533 : {
534 384 : spectrum[L_frame + i] = Mpy_32_16_1( spectrum[L_frame + i], fac );
535 384 : move32();
536 : }
537 : }
538 : }
539 :
540 :
541 662 : test();
542 662 : test();
543 662 : test();
544 662 : IF( st->tcxonly && hTcxEnc->tcxltp && ( hTcxEnc->tcxltp_gain > 0 ) && !pfUseTns )
545 : {
546 0 : PsychAdaptLowFreqEmph_fx( spectrum, gainlpc, gainlpc_e );
547 : }
548 662 : }
549 1414922 : void ShapeSpectrum_ivas_fx(
550 : TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
551 : Word16 A[], /* input: quantized coefficients NxAz_q[M+1], Q = 14 - norm(A[0]) */
552 : Word16 gainlpc[], /* output: MDCT gains for the previous frame Q(15-gainlpc_e)*/
553 : Word16 gainlpc_e[], /* output: MDCT gains exponents */
554 : Word16 L_frame_glob, /* input: frame length */
555 : Word16 L_spec,
556 : Word32 spectrum[], /* i/o: MDCT spectrum Q(31-spectrum_e) */
557 : Word16 *spectrum_e, /* i/o: MDCT spectrum exponent */
558 : Word8 pfUseTns, /* output: Flag indicating if TNS is used */
559 : Encoder_State *st,
560 : Word32 *scf /* Q16 */
561 : )
562 : {
563 : Word16 L_frame;
564 : Word16 Ap[M + 2];
565 : Word16 gamma1;
566 : Word16 gainlpc_noinv[FDNS_NPTS];
567 : Word16 gainlpc_noinv_e[FDNS_NPTS];
568 : Word32 sns_int_scf[FDNS_NPTS];
569 : Word16 i;
570 : Word16 q_spectrum;
571 1414922 : Word32 max_low_pre = 0, max_high_pre = 0;
572 1414922 : TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
573 1414922 : move32();
574 1414922 : move32();
575 1414922 : Word32 total_brate = st->total_brate;
576 1414922 : move32();
577 1414922 : if ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) )
578 : {
579 1177084 : total_brate = st->element_brate;
580 1177084 : move32();
581 : }
582 :
583 : /*-----------------------------------------------------------*
584 : * Init *
585 : *-----------------------------------------------------------*/
586 :
587 : /* Init lengths */
588 1414922 : L_frame = L_frame_glob;
589 1414922 : move16();
590 1414922 : gamma1 = st->gamma;
591 1414922 : move16();
592 1414922 : if ( st->enableTcxLpc != 0 )
593 : {
594 17495 : gamma1 = 0x7FFF;
595 17495 : move16();
596 : }
597 :
598 : /* if past frame is ACELP */
599 1414922 : IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) /* in MDCT, this is already done outside the function */
600 : {
601 237838 : IF( st->last_core == ACELP_CORE )
602 : {
603 7856 : L_frame = add( L_frame, hTcxCfg->tcx_offset );
604 7856 : L_spec = add( L_spec, shr( hTcxCfg->tcx_coded_lines, 2 ) );
605 7856 : if ( hTcxCfg->lfacNext < 0 )
606 : {
607 7856 : L_frame = sub( L_frame, hTcxCfg->lfacNext );
608 7856 : move16();
609 : }
610 : }
611 : }
612 :
613 1414922 : test();
614 1414922 : tcxGetNoiseFillingTilt( A,
615 : M,
616 : L_frame,
617 1414922 : ( GE_32( total_brate, ACELP_13k20 ) && st->rf_mode == 0 ),
618 : &hTcxEnc->noiseTiltFactor );
619 :
620 : /* Calculate Spectrum Flatness Measure for the TCX Concealment */
621 1414922 : IF( st->enablePlcWaveadjust )
622 : {
623 0 : hTcxCfg->SFM2 = SFM_Cal_fx( spectrum, s_min( 200, L_frame ) );
624 0 : move32();
625 : }
626 :
627 1414922 : test();
628 1414922 : IF( LE_32( total_brate, ACELP_13k20 ) && EQ_16( st->bwidth, SWB ) )
629 : {
630 31136 : max_low_pre = 0;
631 31136 : move32();
632 8142752 : FOR( i = 0; i < L_frame; i++ )
633 : {
634 8111616 : Word32 tmp = L_abs( spectrum[i] );
635 8111616 : if ( GT_32( tmp, max_low_pre ) )
636 : {
637 137781 : max_low_pre = tmp;
638 137781 : move32();
639 : }
640 : }
641 :
642 31136 : max_high_pre = 0;
643 31136 : move32();
644 12198560 : FOR( i = 0; i < L_spec - L_frame; i++ )
645 : {
646 12167424 : Word32 tmp = L_abs( spectrum[L_frame + i] );
647 12167424 : if ( GT_32( tmp, max_high_pre ) )
648 : {
649 2473 : max_high_pre = tmp;
650 2473 : move32();
651 : }
652 : }
653 : }
654 :
655 1414922 : IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) )
656 : {
657 : Word64 W_tmp;
658 : Word16 len;
659 1177084 : q_spectrum = sub( 31, *spectrum_e );
660 1177084 : sns_interpolate_scalefactors_fx( &sns_int_scf[0], scf, ENC );
661 1177084 : sns_shape_spectrum_fx( spectrum, &q_spectrum, st->hTcxCfg->psychParamsCurrent, &sns_int_scf[0], Q16, L_frame, &len ); // The output spectrum from sns_shape_spectrum_fx has Q = q_spectrum + 1
662 :
663 1177084 : test();
664 1177084 : test();
665 1177084 : IF( NE_16( len, L_spec ) && LT_16( add( q_spectrum, 1 ), sub( 31, *spectrum_e ) ) )
666 : {
667 417 : scale_sig32( spectrum + len, sub( L_spec, len ), sub( add( q_spectrum, 1 ), sub( 31, *spectrum_e ) ) ); // Q31
668 : }
669 1176667 : ELSE IF( NE_16( len, L_spec ) && GT_16( add( q_spectrum, 1 ), sub( 31, *spectrum_e ) ) )
670 : {
671 946184 : scale_sig32( spectrum, len, sub( sub( 31, *spectrum_e ), add( q_spectrum, 1 ) ) ); // Q(30-specturm_e)
672 946184 : q_spectrum = sub( 31 - 1, *spectrum_e );
673 : }
674 :
675 297527964 : FOR( i = L_frame; i < L_spec; i++ )
676 : {
677 296350880 : W_tmp = W_mult0_32_32( spectrum[i], sns_int_scf[hTcxCfg->psychParamsCurrent->nBands - 1] );
678 296350880 : spectrum[i] = W_extract_h( W_shl( W_tmp, Q16 ) );
679 296350880 : move32();
680 : }
681 1177084 : *spectrum_e = sub( 31 - 1, q_spectrum ); // As the output spectrum from sns_shape_spectrum_fx has Q = q_spectrum + 1
682 1177084 : move16();
683 : }
684 : ELSE
685 : {
686 : /*-----------------------------------------------------------*
687 : * Pre-shaping in frequency domain using weighted LPC (Wz) *
688 : *-----------------------------------------------------------*/
689 :
690 237838 : weight_a_fx( A, Ap, gamma1, M );
691 :
692 237838 : lpc2mdct( Ap, M, gainlpc_noinv, gainlpc_noinv_e, gainlpc, gainlpc_e, FDNS_NPTS, 0 );
693 :
694 237838 : mdct_shaping( spectrum, L_frame, gainlpc_noinv, gainlpc_noinv_e );
695 93229870 : FOR( i = L_frame; i < L_spec; i++ )
696 : {
697 92992032 : spectrum[i] = L_shl( Mpy_32_16_1( spectrum[i], gainlpc_noinv[FDNS_NPTS - 1] ), gainlpc_noinv_e[FDNS_NPTS - 1] );
698 92992032 : move32();
699 : }
700 : }
701 :
702 : /* reduce the peaks in the IGF region, to make life of the core-coder easier... */
703 1414922 : test();
704 1414922 : IF( LE_32( total_brate, ACELP_13k20 ) && EQ_16( st->bwidth, SWB ) )
705 : {
706 : Word16 sf_width;
707 : Word16 dist_low, dist_high;
708 : Word16 max_fac_s, max_fac_m;
709 : Word32 max_low, max_low1, max_low2, max_high;
710 : Word16 headroom, shift, tmp16;
711 :
712 :
713 31136 : max_fac_m = 24576;
714 31136 : move16();
715 : /* max_fac = 3 */
716 31136 : max_fac_s = 2;
717 31136 : move16();
718 31136 : if ( hTcxEnc->tcx_lpc_shaped_ari )
719 : {
720 : /* max_fac = 1.5 */
721 13428 : max_fac_s = 1;
722 13428 : move16();
723 : }
724 :
725 31136 : sf_width = shr( L_frame, 1 );
726 :
727 31136 : max_low2 = 0;
728 31136 : move32();
729 31136 : dist_low = 0;
730 31136 : move16();
731 4086944 : FOR( i = 0; i < sf_width; i++ )
732 : {
733 4055808 : Word32 tmp = L_abs( spectrum[L_frame - 1 - i] );
734 4055808 : IF( GT_32( tmp, max_low2 ) )
735 : {
736 187927 : max_low2 = tmp;
737 187927 : move32();
738 187927 : dist_low = i;
739 187927 : move16();
740 : }
741 : }
742 :
743 31136 : max_low1 = 0;
744 31136 : move32();
745 4086944 : FOR( i = 0; i < sub( L_frame, sf_width ); i++ )
746 : {
747 4055808 : Word32 tmp = L_abs( spectrum[L_frame - sf_width - 1 - i] );
748 4055808 : if ( GT_32( tmp, max_low1 ) )
749 : {
750 286435 : max_low1 = tmp;
751 286435 : move32();
752 : }
753 4055808 : if ( GT_32( tmp, max_low2 ) )
754 : {
755 556872 : dist_low = add( sf_width, i );
756 : }
757 : }
758 :
759 31136 : max_low = L_max( max_low1, max_low2 );
760 :
761 31136 : max_high = 0;
762 31136 : move32();
763 31136 : dist_high = 0;
764 31136 : move16();
765 12198560 : FOR( i = 0; i < ( L_spec - L_frame ); i++ )
766 : {
767 12167424 : Word32 tmp = L_abs( spectrum[L_frame + i] );
768 12167424 : IF( GT_32( tmp, max_high ) )
769 : {
770 2473 : max_high = tmp;
771 2473 : move32();
772 2473 : dist_high = i;
773 2473 : move16();
774 : }
775 : }
776 :
777 : /* at least 9 bits headroom are needed for below multiplicitions */
778 31136 : shift = 0;
779 31136 : move16();
780 31136 : headroom = 31;
781 31136 : move16();
782 :
783 31136 : tmp16 = norm_l( max_low );
784 31136 : if ( max_low != 0 )
785 31132 : headroom = s_min( headroom, tmp16 );
786 :
787 31136 : tmp16 = norm_l( max_low2 );
788 31136 : if ( max_low2 != 0 )
789 31132 : headroom = s_min( headroom, tmp16 );
790 :
791 31136 : tmp16 = norm_l( max_high );
792 31136 : if ( max_high != 0 )
793 841 : headroom = s_min( headroom, tmp16 );
794 :
795 31136 : if ( LT_16( headroom, 9 ) )
796 : {
797 30058 : shift = sub( 9, headroom );
798 : }
799 31136 : max_low = L_shr( max_low, shift );
800 31136 : max_low2 = L_shr( max_low2, shift );
801 31136 : max_high = L_shr( max_high, shift );
802 :
803 31136 : test();
804 31136 : test();
805 31136 : IF( GT_32( imult3216( max_high, dist_high ), imult3216( L_shr( max_low, 2 ), dist_low ) ) && ( GT_32( max_low_pre, L_shr( max_high_pre, 4 ) ) ) && ( GT_32( max_high, L_shl( Mpy_32_16_r( max_low2, max_fac_m ), max_fac_s ) ) ) )
806 : {
807 : Word16 fac;
808 607 : fac = divide3232( max_low2, max_high );
809 607 : IF( GE_16( norm_s( fac ), max_fac_s ) )
810 : {
811 539 : fac = shl( mult_r( fac, max_fac_m ), max_fac_s );
812 212411 : FOR( i = 0; i < ( L_spec - L_frame ); i++ )
813 : {
814 211872 : spectrum[L_frame + i] = Mpy_32_16_1( spectrum[L_frame + i], fac );
815 211872 : move32();
816 : }
817 : }
818 : ELSE
819 : {
820 68 : fac = mult_r( fac, max_fac_m );
821 26852 : FOR( i = 0; i < ( L_spec - L_frame ); i++ )
822 : {
823 26784 : spectrum[L_frame + i] = L_shl( Mpy_32_16_1( spectrum[L_frame + i], fac ), max_fac_s );
824 26784 : move32();
825 : }
826 : }
827 : }
828 : }
829 :
830 :
831 1414922 : test();
832 1414922 : test();
833 1414922 : test();
834 1414922 : IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) && st->tcxonly && hTcxEnc->tcxltp && ( hTcxEnc->tcxltp_gain > 0 ) && !pfUseTns )
835 : {
836 3726 : PsychAdaptLowFreqEmph_fx( spectrum, gainlpc, gainlpc_e );
837 : }
838 1414922 : }
839 :
840 : /*-------------------------------------------------------------------*
841 : * GetTransWidth()
842 : *
843 : *
844 : *-------------------------------------------------------------------*/
845 :
846 1042589 : static Word16 GetTransWidth_ivas_fx(
847 : const Word16 tcxonly,
848 : const Word16 tcx10,
849 : const Word16 tcxltp_gain, // Q15
850 : const Word16 hm_active )
851 : {
852 1042589 : Word16 noiseTransWidth = MIN_NOISE_FILLING_HOLE;
853 1042589 : move16();
854 :
855 1042589 : IF( tcxonly )
856 : {
857 785280 : IF( hm_active )
858 : {
859 8956 : noiseTransWidth = HOLE_SIZE_FROM_LTP( s_max( tcxltp_gain, 10240 /*0.3125f Q15*/ ) );
860 : }
861 : ELSE
862 : {
863 776324 : noiseTransWidth = HOLE_SIZE_FROM_LTP( s_max( tcxltp_gain, 0 ) );
864 : }
865 :
866 785280 : if ( tcx10 )
867 : {
868 33183 : noiseTransWidth = 3; /* minimum transition for noise filling in TCX-10 */
869 33183 : move16();
870 : }
871 : }
872 :
873 1042589 : return noiseTransWidth;
874 : }
875 :
876 : /*-----------------------------------------------------------*
877 : * EstimateTCXNoiseLevel()
878 : *
879 : * Estimate and quantize noise factor *
880 : *-----------------------------------------------------------*/
881 :
882 237838 : static void EstimateTCXNoiseLevel_ivas_fx(
883 : Encoder_State *st, /* i : encoder state handle */
884 : Word32 x_orig[], /* i : shaped MDCT spectrum Q(31-x_orig_e) */
885 : Word16 x_orig_e, /* i : shaped MDCT spectrum exponent */
886 : Word32 spectrum[], /* i/o: quantized MDCT spectrum */
887 : const Word16 gain_tcx, /* i : global gain Q(15-gain_tcx_e) */
888 : const Word16 gain_tcx_e, /* i : global gain exponent */
889 : const Word16 L_frame, /* i : frame length */
890 : const Word16 noiseFillingBorder, /* i : noise filling border */
891 : const Word16 hm_active, /* i : flag indicating if the harmonic model is active */
892 : Word16 *fac_ns, /* o : noise filling level, fac_ns_q */
893 : Word16 *fac_ns_q /* o : quantized noise filling level, Q0 */
894 : )
895 : {
896 : Word16 maxNfCalcBw, iStart, noiseTransWidth;
897 237838 : TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
898 :
899 237838 : maxNfCalcBw = s_min( noiseFillingBorder, round_fx( L_shl( L_mult( hTcxEnc->measuredBwRatio, L_frame ), 1 ) ) );
900 :
901 237838 : IF( GE_32( st->total_brate, HQ_96k ) )
902 : {
903 18133 : *fac_ns = 0;
904 18133 : *fac_ns_q = 0;
905 18133 : move16();
906 18133 : move16();
907 : }
908 : ELSE
909 : {
910 : Word16 minLevel;
911 219705 : minLevel = 1;
912 219705 : move16();
913 219705 : test();
914 219705 : if ( hTcxEnc->tcx_lpc_shaped_ari && GT_16( st->element_mode, IVAS_SCE ) )
915 : {
916 4758 : minLevel = 0;
917 4758 : move16();
918 : }
919 :
920 : /* noise filling start bin */
921 219705 : iStart = shr( L_frame, 3 );
922 219705 : test();
923 219705 : IF( GE_32( st->total_brate, ACELP_13k20 ) && st->rf_mode == 0 )
924 : {
925 186459 : iStart = idiv1616U( L_frame, 6 );
926 : }
927 :
928 219705 : noiseTransWidth = GetTransWidth_ivas_fx( st->tcxonly, (Word16) EQ_16( L_frame, shr( st->L_frame, 1 ) ), st->hTcxEnc->tcxltp_gain, ( st->hTcxCfg->ctx_hm && st->last_core != ACELP_CORE && hm_active ) );
929 :
930 219705 : tcx_noise_factor_ivas_fx( x_orig, x_orig_e, spectrum, iStart, maxNfCalcBw, noiseTransWidth, L_frame, gain_tcx, gain_tcx_e, hTcxEnc->noiseTiltFactor, fac_ns, fac_ns_q, st->element_mode );
931 :
932 : /* hysteresis for very tonal passages (more stationary noise filling level) */
933 219705 : IF( EQ_16( *fac_ns_q, minLevel ) )
934 : {
935 12733 : hTcxEnc->noiseLevelMemory_cnt = s_min( INT16_MAX, add( 1, abs_s( hTcxEnc->noiseLevelMemory_cnt ) ) ); /* update counter */
936 12733 : move16();
937 : }
938 : ELSE
939 : {
940 206972 : test();
941 206972 : IF( EQ_16( *fac_ns_q, add( minLevel, 1 ) ) && GT_16( abs_s( hTcxEnc->noiseLevelMemory_cnt ), 5 ) )
942 : {
943 790 : *fac_ns_q = minLevel; /* reduce noise filling level by one step */
944 790 : *fac_ns = 0;
945 790 : move16();
946 790 : move16();
947 790 : IF( minLevel != 0 )
948 : {
949 790 : *fac_ns = shr( 0x6000, NBITS_NOISE_FILL_LEVEL );
950 790 : move16();
951 : }
952 : /* signal that noise level is changed by inverting sign of level memory */
953 790 : IF( hTcxEnc->noiseLevelMemory_cnt < 0 )
954 : {
955 265 : hTcxEnc->noiseLevelMemory_cnt = 5;
956 265 : move16();
957 : }
958 : ELSE
959 : {
960 525 : hTcxEnc->noiseLevelMemory_cnt = negate( add( 1, hTcxEnc->noiseLevelMemory_cnt ) );
961 525 : move16();
962 : }
963 : }
964 : ELSE
965 : {
966 206182 : hTcxEnc->noiseLevelMemory_cnt = 0; /* reset memory since level is too different */
967 206182 : move16();
968 : }
969 : }
970 : } /* bitrate */
971 :
972 237838 : return;
973 : }
974 :
975 :
976 : /*-------------------------------------------------------------------*
977 : * QuantizeSpectrum()
978 : *
979 : *
980 : *-------------------------------------------------------------------*/
981 :
982 237838 : void QuantizeSpectrum_ivas_fx(
983 : Encoder_State *st, /* i/o: encoder state structure */
984 : const Word16 A_fx[], /* i : quantized coefficients NxAz_q[M+1], Q = 14 - norm_s(A_fx[0]) */
985 : const Word16 Aqind[], /* i : frame-independent quantized coefficients (M+1) */
986 : Word16 gainlpc_fx[], /* i : MDCT gains of the previous frame Q(15-gainlpc_e) */
987 : Word16 gainlpc_e[], /* i : exponents of MDCT gains of the previous frame */
988 : Word16 synth[], /* o : synthesis buffer, Q0 */
989 : const Word16 nb_bits, /* i : bit budget */
990 : const Word16 tnsSize, /* i : number of tns parameters put into prm */
991 : Word16 prm[], /* o : tcx parameters */
992 : const Word16 frame_cnt, /* i : frame counter in the super_frame */
993 : CONTEXT_HM_CONFIG *hm_cfg, /* i : HM configuration */
994 : const Word16 vad_hover_flag /* i : VAD hangover flag */
995 : )
996 : {
997 : Word16 L_frameTCX; /* full frame length */
998 : Word16 L_frame; /* frame length */
999 : Word16 L_spec; /* length of the coded spectrum */
1000 : Word16 tcx_offset; /* folding point offset relative to the end of the previous frame */
1001 : Word16 noiseFillingBorder; /* noise filling border */
1002 : Word32 quantized_spectrum_fx[N_MAX]; /* quantized MDCT spectrum */
1003 : Word16 quantized_spectrum_e; /* quantized MDCT spectrum */
1004 : Word16 lf_deemph_fact_fx[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX]; /* low frequency deemphasis factors */
1005 : Word16 hm_active; /* flag indicating if the harmonic model is active */
1006 : Word16 fac_ns_fx; /* noise filling level, Q15 */
1007 : Word16 nf_seed; /* noise filling random seed */
1008 : Word32 ener_fx; /* energy of the quantized spectrum */
1009 : Word16 ener_e; /* energy of the quantized spectrum */
1010 : Word16 gain_tcx_fx; /* global gain */
1011 : Word16 gain_tcx_e; /* global gain */
1012 :
1013 237838 : TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
1014 :
1015 237838 : set32_fx( quantized_spectrum_fx, 0, N_MAX );
1016 :
1017 : /*-----------------------------------------------------------*
1018 : * Quantize the MDCT spectrum *
1019 : *-----------------------------------------------------------*/
1020 :
1021 237838 : QuantizeTCXSpectrum_fx( st, frame_cnt, hTcxEnc->spectrum_fx[frame_cnt], hTcxEnc->spectrum_e[frame_cnt], gainlpc_fx, gainlpc_e, Aqind, tnsSize, nb_bits, vad_hover_flag,
1022 : &L_frameTCX, &L_frame, &L_spec, &tcx_offset, &noiseFillingBorder, quantized_spectrum_fx, &quantized_spectrum_e, hm_cfg, &hm_active, lf_deemph_fact_fx, &nf_seed, &ener_fx, &ener_e, &gain_tcx_fx, &gain_tcx_e, prm );
1023 237838 : if ( hTcxEnc->spectrum_e[frame_cnt] < 0 )
1024 : {
1025 : /*buffer is already scaled inside QuantizeTCXSpectrum_fx*/
1026 0 : hTcxEnc->spectrum_e[frame_cnt] = 0;
1027 0 : move16();
1028 : }
1029 :
1030 237838 : Word16 s1 = sub( getScaleFactor32( st->hTcxEnc->spectrum_fx[frame_cnt], L_frame ), 6 );
1031 237838 : Word16 s2 = getScaleFactor32( quantized_spectrum_fx, s_max( L_frame, L_spec ) );
1032 237838 : Word16 max_e = s_max( sub( hTcxEnc->spectrum_e[frame_cnt], s1 ), sub( quantized_spectrum_e, s2 ) );
1033 :
1034 237838 : scale_sig32( quantized_spectrum_fx, s_max( L_frame, L_spec ), sub( quantized_spectrum_e, max_e ) ); // max_e
1035 237838 : scale_sig32( st->hTcxEnc->spectrum_fx[frame_cnt], L_frame, sub( hTcxEnc->spectrum_e[frame_cnt], max_e ) ); // max_e
1036 237838 : hTcxEnc->spectrum_e[frame_cnt] = max_e;
1037 237838 : move16();
1038 :
1039 : /*-----------------------------------------------------------*
1040 : * Estimate and quantize noise factor *
1041 : *-----------------------------------------------------------*/
1042 :
1043 237838 : EstimateTCXNoiseLevel_ivas_fx( st, hTcxEnc->spectrum_fx[frame_cnt], hTcxEnc->spectrum_e[frame_cnt], quantized_spectrum_fx, gain_tcx_fx, gain_tcx_e, L_frame, noiseFillingBorder, hm_active, &fac_ns_fx, &prm[1] );
1044 :
1045 : /*-----------------------------------------------------------*
1046 : * Internal decoder *
1047 : *-----------------------------------------------------------*/
1048 :
1049 237838 : InternalTCXDecoder_fx( st, frame_cnt, L_frameTCX, L_frame, L_spec, tcx_offset, noiseFillingBorder, quantized_spectrum_fx, ener_fx, ener_e, lf_deemph_fact_fx, fac_ns_fx, nf_seed, A_fx, gainlpc_fx, gainlpc_e, hm_active, gain_tcx_fx, &gain_tcx_e, hTcxEnc->spectrum_fx[frame_cnt], &hTcxEnc->spectrum_e[frame_cnt], synth, &prm[0] );
1050 :
1051 : /* Update L_frame_past */
1052 237838 : st->L_frame_past = L_frame;
1053 237838 : move16();
1054 :
1055 : /* Update overlap */
1056 237838 : test();
1057 237838 : test();
1058 237838 : test();
1059 237838 : if ( ( ( EQ_16( L_frameTCX, shr( hTcxEnc->L_frameTCX, 1 ) ) && frame_cnt > 0 ) || EQ_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) && ( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) )
1060 : {
1061 8831 : st->hTcxCfg->tcx_curr_overlap_mode = ALDO_WINDOW;
1062 8831 : move16();
1063 : }
1064 :
1065 :
1066 237838 : return;
1067 : }
1068 :
1069 343049 : void EstimateStereoTCXNoiseLevel_fx(
1070 : Encoder_State **sts, /* i : state handle */
1071 : Word32 *q_spectrum[CPE_CHANNELS][NB_DIV], /* i : quantized MDCT spectrum Qx */
1072 : Word16 gain_tcx[][NB_DIV], /* i : global gain Q(15-gain_tcx_e) */
1073 : Word16 gain_tcx_e[][NB_DIV], /* i : global gain exponent */
1074 : Word16 L_frame[][NB_DIV], /* i : frame length */
1075 : Word16 noiseFillingBorder[][NB_DIV], /* i : noise filling border */
1076 : Word16 hm_active[][NB_DIV], /* i : flag indicating if the harmonic model is active */
1077 : const Word16 ignore_chan[], /* i : flag indicating whether the channel should be ignored */
1078 : Word16 fac_ns[][NB_DIV], /* o : noise filling level Q15 */
1079 : Word16 param_core[][NB_DIV * NPRM_DIV], /* o : quantized noise filling level */
1080 : const Word16 MCT_flag /* i : hMCT handle allocated (1) or not (0) */
1081 : )
1082 : {
1083 : Word16 ch, n, i;
1084 : Word16 nSubframes, maxNfCalcBw, iStart, noiseTransWidth;
1085 : Word16 smooth_gain;
1086 : Word32 combined_q_spectrum[N_MAX];
1087 : Word16 *fac_ns_q;
1088 : Word32 total_brate;
1089 :
1090 343049 : set32_fx( combined_q_spectrum, 0, N_MAX );
1091 :
1092 1029147 : FOR( ch = 0; ch < CPE_CHANNELS; ch++ )
1093 : {
1094 686098 : Encoder_State *st = sts[ch];
1095 686098 : TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
1096 :
1097 686098 : IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) )
1098 : {
1099 672352 : nSubframes = 1;
1100 672352 : move16();
1101 : }
1102 : ELSE
1103 : {
1104 13746 : nSubframes = NB_DIV;
1105 13746 : move16();
1106 : }
1107 :
1108 686098 : IF( ignore_chan[ch] )
1109 : {
1110 76235 : CONTINUE;
1111 : }
1112 :
1113 609863 : IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) && !MCT_flag )
1114 : {
1115 163762 : total_brate = st->element_brate;
1116 163762 : move32();
1117 : }
1118 : ELSE
1119 : {
1120 446101 : total_brate = st->total_brate;
1121 446101 : move32();
1122 : }
1123 :
1124 1233466 : FOR( n = 0; n < nSubframes; n++ )
1125 : {
1126 623603 : fac_ns_q = param_core[ch] + add( i_mult( n, NPRM_DIV ), 1 );
1127 :
1128 623603 : maxNfCalcBw = s_min( noiseFillingBorder[ch][n], round_fx( L_shl( L_mult( hTcxEnc->measuredBwRatio, L_frame[ch][n] ), 1 ) ) );
1129 :
1130 623603 : test();
1131 623603 : test();
1132 623603 : test();
1133 623603 : IF( ( GE_32( total_brate, HQ_96k ) && ( LE_16( st->element_mode, IVAS_SCE ) || LT_16( st->bwidth, SWB ) ) ) || GT_32( total_brate, IVAS_192k ) )
1134 : {
1135 19918 : fac_ns[ch][n] = 0;
1136 19918 : move16();
1137 19918 : *fac_ns_q = 0;
1138 19918 : move16();
1139 : }
1140 : ELSE
1141 : {
1142 603685 : test();
1143 603685 : IF( GE_32( total_brate, ACELP_13k20 ) && !st->rf_mode )
1144 : {
1145 592615 : iStart = idiv1616( L_frame[ch][n], 6 );
1146 : }
1147 : ELSE
1148 : {
1149 11070 : iStart = shr( L_frame[ch][n], 3 );
1150 : }
1151 :
1152 603685 : IF( n == 0 )
1153 : {
1154 590397 : Copy( hTcxEnc->ltpGainMemory_fx, &hTcxEnc->ltpGainMemory_fx[1], N_LTP_GAIN_MEMS - 1 );
1155 590397 : hTcxEnc->ltpGainMemory_fx[0] = st->hTcxEnc->tcxltp_gain;
1156 590397 : move16();
1157 : }
1158 :
1159 603685 : Word32 temp = L_mult0( hTcxEnc->ltpGainMemory_fx[0], nf_tw_smoothing_coeffs_fx[0] );
1160 :
1161 2414740 : FOR( i = 1; i < N_LTP_GAIN_MEMS; i++ )
1162 : {
1163 1811055 : temp = L_mac0( temp, hTcxEnc->ltpGainMemory_fx[i], nf_tw_smoothing_coeffs_fx[i] );
1164 : }
1165 603685 : smooth_gain = round_fx( L_shl( temp, 1 ) );
1166 603685 : noiseTransWidth = GetTransWidth_ivas_fx( st->tcxonly, (Word16) EQ_16( L_frame[ch][n], shr( st->L_frame, 1 ) ), smooth_gain, ( st->hTcxCfg->ctx_hm && NE_16( st->last_core, ACELP_CORE ) && hm_active[ch][n] ) );
1167 :
1168 603685 : Copy32( q_spectrum[ch][n], combined_q_spectrum, L_frame[ch][n] );
1169 :
1170 : /* Scaling down 1-bit to resolve crashes during accumulation in tcx_noise_factor_ivas_fx() */
1171 : Word32 L_tmp, L_tmp1;
1172 603685 : maximum_abs_32_fx( hTcxEnc->spectrum_fx[n], L_frame[ch][n], &L_tmp );
1173 603685 : maximum_abs_32_fx( combined_q_spectrum, L_frame[ch][n], &L_tmp1 );
1174 603685 : test();
1175 603685 : IF( L_tmp != 0 || L_tmp1 != 0 )
1176 : {
1177 603507 : scale_sig32( hTcxEnc->spectrum_fx[n], L_frame[ch][n], -Q1 ); // Q(31-(spectrum_e+1)
1178 603507 : scale_sig32( combined_q_spectrum, L_frame[ch][n], -Q1 ); // Q(31-(spectrum_e+1)
1179 603507 : hTcxEnc->spectrum_e[n] = add( hTcxEnc->spectrum_e[n], Q1 );
1180 603507 : move16();
1181 : }
1182 603685 : tcx_noise_factor_ivas_fx( hTcxEnc->spectrum_fx[n], hTcxEnc->spectrum_e[n], combined_q_spectrum, iStart, maxNfCalcBw, noiseTransWidth, L_frame[ch][n], gain_tcx[ch][n], gain_tcx_e[ch][n], hTcxEnc->noiseTiltFactor, &fac_ns[ch][n], fac_ns_q, st->element_mode );
1183 :
1184 : /* hysteresis for very tonal passages (more stationary noise filling level) */
1185 603685 : IF( EQ_16( *fac_ns_q, 1 ) )
1186 : {
1187 69870 : hTcxEnc->noiseLevelMemory_cnt = s_min( INT16_MAX, 1 + abs_s( hTcxEnc->noiseLevelMemory_cnt ) ); /* update counter */
1188 69870 : move16();
1189 : }
1190 : ELSE
1191 : {
1192 533815 : test();
1193 533815 : IF( EQ_16( *fac_ns_q, 2 ) && GT_16( abs_s( hTcxEnc->noiseLevelMemory_cnt ), 5 ) )
1194 : {
1195 5655 : *fac_ns_q = 1; /* reduce noise filling level by one step */
1196 5655 : fac_ns[ch][n] = 3072; /* 0.75f / ( 1 << NBITS_NOISE_FILL_LEVEL ) in Q15*/
1197 5655 : move16();
1198 5655 : move16();
1199 : /* signal that noise level is changed by inverting sign of level memory */
1200 5655 : IF( ( hTcxEnc->noiseLevelMemory_cnt < 0 ) )
1201 : {
1202 1956 : hTcxEnc->noiseLevelMemory_cnt = 5;
1203 1956 : move16();
1204 : }
1205 : ELSE
1206 : {
1207 3699 : hTcxEnc->noiseLevelMemory_cnt = sub( -1, hTcxEnc->noiseLevelMemory_cnt );
1208 3699 : move16();
1209 : }
1210 : }
1211 : ELSE
1212 : {
1213 528160 : hTcxEnc->noiseLevelMemory_cnt = 0; /* reset memory since level is too different */
1214 528160 : move16();
1215 : }
1216 : }
1217 : } /* bitrate */
1218 : }
1219 : }
1220 :
1221 343049 : return;
1222 : }
1223 :
1224 662 : void QuantizeSpectrum_fx(
1225 : TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
1226 : Word16 A[], /* input: quantized coefficients NxAz_q[M+1] */
1227 : Word16 Aqind[], /* input: frame-independent quantized coefficients (M+1) */
1228 : Word16 gainlpc[], /* input: MDCT gains of the previous frame Q(15-gainlpc_e)*/
1229 : Word16 gainlpc_e[], /* input: MDCT gains exponents */
1230 : Word16 synth[],
1231 : Word16 L_frame_glob, /* input: frame length */
1232 : Word16 L_frameTCX_glob,
1233 : Word16 L_spec,
1234 : Word16 nb_bits, /*input: bit budget*/
1235 : Word8 tcxonly, /*input: only TCX flag*/
1236 : Word32 spectrum[], /* i/o: MDCT spectrum, input is shaped MDCT spectrum Q(31-spectrum_e) */
1237 : Word16 *spectrum_e, /* i/o: MDCT spectrum exponent */
1238 : STnsData *pTnsData, /* input: Tns data */
1239 : Word8 fUseTns, /* input: Flag indicating if TNS is used */
1240 : Word16 tnsSize, /* input: number of tns parameters put into prm */
1241 : Word16 prm[], /* output: tcx parameters */
1242 : Word16 frame_cnt, /* input: frame counter in the super_frame */
1243 : Encoder_State *st,
1244 : CONTEXT_HM_CONFIG *hm_cfg )
1245 : {
1246 : Word16 i, L_frame, tcx_offset;
1247 : Word16 stop;
1248 : Word16 tmp1, tmp2, tmp3, tmp4, s;
1249 : Word32 tmp32;
1250 : Word8 tmp8;
1251 : Word16 *tmpP16;
1252 : Word16 L_frameTCX;
1253 : Word16 fac_ns;
1254 : Word16 nf_seed;
1255 : Word32 ener;
1256 : Word16 ener_e;
1257 : Word16 gain_tcx, gain_tcx_e;
1258 : Word16 sqBits;
1259 : Word16 overlap;
1260 : Word16 noiseFillingSize;
1261 : Word16 noiseTransWidth;
1262 : Word32 *OriginalSpectrum;
1263 : Word16 OriginalSpectrum_e;
1264 : Word16 ctxHmBits;
1265 : Word16 resQBits;
1266 : Word16 *signs;
1267 : Word16 signaling_bits;
1268 : Word16 *prm_ltp, *prm_tns, *prm_hm, *prm_lastnz, *prm_target;
1269 : Word16 Aq_old[M + 1];
1270 : Word32 SFM;
1271 : Word32 K, K2;
1272 : Word16 aldo; /* ALDO flag in current frame*/
1273 : Word16 nz; /* non-zero length in ALDO window*/
1274 : CONTEXT_HM_CONFIG *phm_cfg;
1275 662 : TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
1276 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
1277 662 : Flag Overflow = 0;
1278 662 : Flag Carry = 0;
1279 : #endif
1280 :
1281 : /* Stack memory is split between encoder and internal decoder to reduce max
1282 : stack memory usage. */
1283 : {
1284 : Word16 sqTargetBits;
1285 : Word16 gain_tcx_opt, gain_tcx_opt_e;
1286 : Word16 sqGain, sqGain_e;
1287 : Word16 sqBits_noStop;
1288 : Word16 nEncoded;
1289 : Word16 maxNfCalcBw;
1290 : Word16 PeriodicityIndex;
1291 : Word16 NumIndexBits;
1292 : Word16 nEncodedCtxHm, stopCtxHm, sqBitsCtxHm, Selector;
1293 : Word16 lastnz, lastnzCtxHm;
1294 : Word16 RelativeScore;
1295 : Word32 x_orig[N_MAX];
1296 : Word16 x_orig_e;
1297 : Word16 resQTargetBits;
1298 : Word16 xn_buf16[L_FRAME_PLUS];
1299 : Word16 *sqQ;
1300 : Word16 LtpPitchLag;
1301 :
1302 :
1303 662 : sqGain = 0x4000;
1304 662 : move16();
1305 662 : sqGain_e = 1;
1306 662 : move16();
1307 662 : noiseTransWidth = MIN_NOISE_FILLING_HOLE;
1308 662 : move16();
1309 662 : resQTargetBits = 0;
1310 662 : move16();
1311 :
1312 : /*-----------------------------------------------------------*
1313 : * Init *
1314 : *-----------------------------------------------------------*/
1315 :
1316 : /* Init lengths */
1317 662 : L_frame = L_frame_glob;
1318 662 : move16();
1319 662 : L_frameTCX = L_frameTCX_glob;
1320 662 : move16();
1321 662 : overlap = hTcxCfg->tcx_mdct_window_length;
1322 662 : move16();
1323 662 : aldo = 0;
1324 662 : move16();
1325 662 : nz = NS2SA_FX2( st->sr_core, N_ZERO_MDCT_NS );
1326 662 : move16();
1327 : /* Modified the overlap to the delay in case of short blocks*/
1328 662 : tcx_offset = hTcxCfg->tcx_offset;
1329 662 : move16();
1330 :
1331 662 : OriginalSpectrum = NULL;
1332 662 : signs = NULL; /* silence warning */
1333 662 : NumIndexBits = 0;
1334 662 : move16();
1335 662 : sqBits = 0;
1336 662 : move16();
1337 662 : ctxHmBits = 0;
1338 662 : move16();
1339 662 : resQBits = 0;
1340 662 : move16();
1341 662 : prm_ltp = &prm[1 + NOISE_FILL_RANGES];
1342 662 : move16();
1343 662 : prm_tns = prm_ltp + LTPSIZE;
1344 662 : move16();
1345 662 : prm_hm = prm_tns + tnsSize;
1346 662 : move16();
1347 662 : prm_lastnz = prm_hm + 2;
1348 662 : move16();
1349 662 : sqQ = prm_hm + NPRM_CTX_HM;
1350 662 : move16();
1351 :
1352 : /* if past frame is ACELP */
1353 :
1354 662 : IF( st->last_core == ACELP_CORE )
1355 : {
1356 39 : hTcxCfg->last_aldo = 0;
1357 39 : move16();
1358 :
1359 39 : L_frame = add( L_frame, tcx_offset );
1360 39 : L_frameTCX = add( L_frameTCX, hTcxCfg->tcx_offsetFB );
1361 39 : L_spec = add( L_spec, shr( hTcxCfg->tcx_coded_lines, 2 ) );
1362 39 : tcx_offset = 0;
1363 39 : move16();
1364 39 : IF( hTcxCfg->lfacNext < 0 )
1365 : {
1366 39 : L_frame = sub( L_frame, hTcxCfg->lfacNext );
1367 39 : L_frameTCX = sub( L_frameTCX, hTcxCfg->lfacNextFB );
1368 39 : tcx_offset = hTcxCfg->lfacNext;
1369 39 : move16();
1370 : }
1371 39 : hTcxEnc->noiseLevelMemory_cnt = 0;
1372 39 : move16();
1373 : }
1374 :
1375 :
1376 662 : E_LPC_f_lsp_a_conversion( st->lsp_old_fx, Aq_old, M );
1377 :
1378 : /* target bitrate for SQ */
1379 662 : sqTargetBits = sub( nb_bits, 7 + NBITS_NOISE_FILL_LEVEL );
1380 :
1381 : /*Unquantized spectrum here*/
1382 662 : IF( st->enablePlcWaveadjust )
1383 : {
1384 :
1385 :
1386 0 : SFM = SFM_Cal_fx( spectrum, s_min( 200, L_frame_glob ) );
1387 0 : test();
1388 0 : IF( LE_16( L_frame_glob, 256 ) )
1389 : {
1390 0 : K = 0x33333333;
1391 0 : move32();
1392 0 : K2 = 0xCCCCCCD;
1393 0 : move32();
1394 : }
1395 0 : ELSE IF( EQ_16( L_frame_glob, 320 ) || EQ_16( L_frame_glob, 512 ) )
1396 : {
1397 0 : K = 0x33333333;
1398 0 : move32();
1399 0 : K2 = 0xCCCCCCD;
1400 0 : move32();
1401 : }
1402 : ELSE /*FrameSize_Core == 640*/
1403 : {
1404 0 : K = 0x2CCCCCCD;
1405 0 : move32();
1406 0 : K2 = 0x51EB852;
1407 0 : move32();
1408 : }
1409 :
1410 :
1411 0 : IF( LT_32( SFM, K ) )
1412 : {
1413 0 : st->Tonal_SideInfo = 1;
1414 0 : move16();
1415 : }
1416 : ELSE
1417 : {
1418 0 : st->Tonal_SideInfo = 0;
1419 0 : move16();
1420 : }
1421 :
1422 0 : if ( LT_32( hTcxCfg->SFM2, K2 ) )
1423 : {
1424 0 : st->Tonal_SideInfo = 1;
1425 0 : move16();
1426 : }
1427 : }
1428 :
1429 : /* Save pre-shaped spectrum*/
1430 662 : Copy32( spectrum, x_orig, L_spec );
1431 662 : x_orig_e = *spectrum_e;
1432 662 : move16();
1433 :
1434 : /*-----------------------------------------------------------*
1435 : * Bandwidth Limitation *
1436 : *-----------------------------------------------------------*/
1437 :
1438 662 : noiseFillingSize = L_spec;
1439 662 : move16();
1440 662 : IF( st->igf != 0 )
1441 : {
1442 662 : noiseFillingSize = st->hIGFEnc->infoStartLine;
1443 662 : move16();
1444 : }
1445 : ELSE
1446 : {
1447 0 : st->hIGFEnc->infoStopLine = noiseFillingSize;
1448 0 : move16();
1449 : }
1450 :
1451 150856 : FOR( i = st->hIGFEnc->infoStopLine; i < L_frameTCX; i++ )
1452 : {
1453 150194 : spectrum[i] = L_deposit_l( 0 );
1454 150194 : move32();
1455 : }
1456 :
1457 : /*-----------------------------------------------------------*
1458 : * Quantization *
1459 : *-----------------------------------------------------------*/
1460 :
1461 662 : IF( hTcxEnc->tcx_lpc_shaped_ari == 0 ) /* old arithmetic coder */
1462 : {
1463 :
1464 : /* Fast estimation of the scalar quantizer step size */
1465 662 : test();
1466 662 : IF( ( hTcxCfg->ctx_hm != 0 ) && ( st->last_core != ACELP_CORE ) )
1467 : {
1468 623 : LtpPitchLag = -1;
1469 623 : move16();
1470 :
1471 623 : test();
1472 623 : IF( ( tcxonly == 0 ) && ( LT_16( hTcxEnc->tcxltp_pitch_int, st->L_frame ) ) )
1473 : {
1474 443 : tmp32 = L_shl( L_mult0( st->L_frame, st->pit_res_max ), 1 + kLtpHmFractionalResolution + 1 );
1475 443 : tmp1 = add( imult1616( hTcxEnc->tcxltp_pitch_int, st->pit_res_max ), hTcxEnc->tcxltp_pitch_fr );
1476 443 : LtpPitchLag = div_l( tmp32, tmp1 );
1477 : }
1478 :
1479 623 : ctxHmBits = add( ctxHmBits, 1 ); /* ContextHM flag */
1480 623 : sqTargetBits = sub( sqTargetBits, 1 ); /* ContextHM flag */
1481 :
1482 623 : OriginalSpectrum = spectrum;
1483 623 : OriginalSpectrum_e = *spectrum_e;
1484 623 : move16();
1485 :
1486 623 : tmp1 = -1;
1487 623 : move16();
1488 623 : if ( hTcxEnc->tcxltp != 0 )
1489 : {
1490 623 : tmp1 = hTcxEnc->tcxltp_gain;
1491 623 : move16();
1492 : }
1493 623 : PeriodicityIndex = SearchPeriodicityIndex_fx(
1494 : OriginalSpectrum,
1495 : NULL,
1496 : L_spec,
1497 : sqTargetBits,
1498 : LtpPitchLag,
1499 : tmp1,
1500 : &RelativeScore );
1501 :
1502 623 : ConfigureContextHm(
1503 : L_spec,
1504 : sqTargetBits,
1505 : PeriodicityIndex,
1506 : LtpPitchLag,
1507 : hm_cfg );
1508 :
1509 623 : tmp1 = 1;
1510 623 : move16();
1511 623 : if ( LT_16( L_spec, 256 ) )
1512 : {
1513 0 : tmp1 = 0;
1514 0 : move16();
1515 : }
1516 623 : NumIndexBits = CountIndexBits( tmp1, PeriodicityIndex );
1517 :
1518 :
1519 : /* Quantize original spectrum */
1520 :
1521 623 : sqGain = SQ_gain_fx( OriginalSpectrum, OriginalSpectrum_e,
1522 623 : shl( mult( hTcxEnc->tcx_target_bits_fac, sqTargetBits ), 1 ),
1523 : L_spec,
1524 : &sqGain_e );
1525 :
1526 623 : tcx_scalar_quantization_fx( OriginalSpectrum, OriginalSpectrum_e,
1527 : sqQ,
1528 : L_spec,
1529 : sqGain, sqGain_e,
1530 623 : hTcxCfg->sq_rounding,
1531 623 : hTcxEnc->memQuantZeros,
1532 : tcxonly );
1533 :
1534 : /* Estimate original bitrate */
1535 623 : stop = 0;
1536 623 : move16();
1537 :
1538 623 : sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ,
1539 : L_spec,
1540 : &lastnz,
1541 : &nEncoded,
1542 : sqTargetBits,
1543 : &stop,
1544 : NULL );
1545 :
1546 : /* Estimate context mapped bitrate */
1547 :
1548 623 : stopCtxHm = 0;
1549 623 : move16();
1550 :
1551 : /* Context Mapping */
1552 623 : sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ,
1553 : L_spec,
1554 : &lastnzCtxHm,
1555 : &nEncodedCtxHm,
1556 623 : sub( sqTargetBits, NumIndexBits ),
1557 : &stopCtxHm,
1558 : hm_cfg );
1559 :
1560 : /* Decide whether or not to use context mapping */
1561 623 : Selector = sub( s_max( stop, sqBits ), add( s_max( stopCtxHm, sqBitsCtxHm ), NumIndexBits ) );
1562 :
1563 623 : test();
1564 623 : test();
1565 623 : IF( ( GT_16( Selector, 2 ) ) || ( ( LE_16( abs_s( Selector ), 2 ) ) &&
1566 : ( LT_16( kCtxHmOlRSThr, RelativeScore ) ) ) )
1567 : {
1568 : /* CtxHm is likely better */
1569 53 : sqTargetBits = sub( sqTargetBits, NumIndexBits );
1570 53 : ctxHmBits = add( ctxHmBits, NumIndexBits );
1571 53 : prm_hm[0] = 1;
1572 53 : move16();
1573 53 : prm_hm[1] = PeriodicityIndex;
1574 53 : move16();
1575 53 : *prm_lastnz = lastnzCtxHm;
1576 53 : move16();
1577 53 : sqBits_noStop = sqBits = sqBitsCtxHm;
1578 53 : move16();
1579 53 : move16();
1580 53 : nEncoded = nEncodedCtxHm;
1581 53 : move16();
1582 53 : stop = stopCtxHm;
1583 53 : move16();
1584 : }
1585 : ELSE /* Original is better or not much difference */
1586 : {
1587 570 : prm_hm[0] = 0;
1588 570 : move16();
1589 570 : prm_hm[1] = PeriodicityIndex;
1590 570 : move16();
1591 570 : *prm_lastnz = lastnz;
1592 570 : move16();
1593 570 : PeriodicityIndex = -1;
1594 570 : move16();
1595 :
1596 570 : sqBits_noStop = sqBits;
1597 570 : move16();
1598 : }
1599 :
1600 :
1601 623 : if ( stop != 0 )
1602 : {
1603 :
1604 237 : sqBits = stop;
1605 237 : move16();
1606 : }
1607 : }
1608 : ELSE /* no context hm*/
1609 : {
1610 39 : PeriodicityIndex = -1;
1611 39 : move16();
1612 :
1613 39 : sqGain = SQ_gain_fx( spectrum, *spectrum_e,
1614 39 : shl( mult( hTcxEnc->tcx_target_bits_fac, sqTargetBits ), 1 ),
1615 : L_spec,
1616 : &sqGain_e );
1617 :
1618 : /* Quantize spectrum */
1619 :
1620 39 : tcx_scalar_quantization_fx( spectrum, *spectrum_e,
1621 : sqQ,
1622 : L_spec,
1623 : sqGain, sqGain_e,
1624 39 : hTcxCfg->sq_rounding,
1625 39 : hTcxEnc->memQuantZeros,
1626 : tcxonly );
1627 :
1628 : /* Estimate bitrate */
1629 39 : stop = 0;
1630 39 : move16();
1631 39 : sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ,
1632 : L_spec,
1633 : prm_lastnz, /* lastnz */
1634 : &nEncoded,
1635 : sqTargetBits,
1636 : &stop,
1637 : NULL );
1638 :
1639 39 : sqBits_noStop = sqBits;
1640 39 : move16();
1641 :
1642 39 : if ( stop != 0 )
1643 : {
1644 10 : sqBits = stop;
1645 10 : move16();
1646 : }
1647 : } /* end of if (ctx_hm) */
1648 :
1649 : /* Adjust correction factor */
1650 662 : tmp1 = sqBits;
1651 662 : move16();
1652 :
1653 662 : if ( s_and( L_spec, sub( L_spec, 1 ) ) == 0 ) /* power-of-2 */
1654 : {
1655 0 : tmp1 = add( tmp1, 1 );
1656 : }
1657 :
1658 662 : tmp1 = BASOP_Util_Divide1616_Scale( sqTargetBits, tmp1, &tmp2 );
1659 : BASOP_SATURATE_WARNING_OFF_EVS
1660 662 : hTcxEnc->tcx_target_bits_fac = shl_o( mult( hTcxEnc->tcx_target_bits_fac, tmp1 ), tmp2, &Overflow );
1661 662 : move16();
1662 : BASOP_SATURATE_WARNING_ON_EVS
1663 :
1664 662 : if ( GT_16( hTcxEnc->tcx_target_bits_fac, 0x5000 ) )
1665 : {
1666 215 : hTcxEnc->tcx_target_bits_fac = 0x5000;
1667 215 : move16();
1668 : }
1669 662 : if ( LT_16( hTcxEnc->tcx_target_bits_fac, 0x3000 ) )
1670 : {
1671 0 : hTcxEnc->tcx_target_bits_fac = 0x3000;
1672 0 : move16();
1673 : }
1674 :
1675 : /* Refine quantizer step size with a rate-control-loop (optional) */
1676 662 : phm_cfg = NULL;
1677 662 : move16();
1678 662 : if ( PeriodicityIndex >= 0 )
1679 : {
1680 53 : phm_cfg = hm_cfg;
1681 53 : move16();
1682 : }
1683 1324 : sqBits = tcx_scalar_quantization_rateloop_fx( spectrum, *spectrum_e,
1684 : sqQ,
1685 : L_spec,
1686 : &sqGain, &sqGain_e,
1687 662 : hTcxCfg->sq_rounding,
1688 662 : hTcxEnc->memQuantZeros,
1689 : prm_lastnz, /* lastnz */
1690 : sqTargetBits,
1691 : &nEncoded,
1692 : &stop,
1693 : sqBits_noStop,
1694 : sqBits,
1695 662 : hTcxCfg->tcxRateLoopOpt,
1696 : tcxonly,
1697 : phm_cfg );
1698 :
1699 662 : IF( ctxHmBits > 0 ) /* Mapping tool is enabled */
1700 : {
1701 : /* Truncate spectrum */
1702 623 : set16_fx( sqQ + nEncoded, 0, sub( L_spec, nEncoded ) );
1703 :
1704 623 : IF( PeriodicityIndex >= 0 ) /* Mapping is used */
1705 : {
1706 : /* Estimate non-mapped bitrate */
1707 53 : stopCtxHm = 1;
1708 53 : move16();
1709 :
1710 53 : sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ,
1711 : L_spec,
1712 : &lastnz,
1713 : &nEncodedCtxHm,
1714 : sqTargetBits,
1715 : &stopCtxHm,
1716 : NULL );
1717 :
1718 : /* Decide whether or not to revert mapping */
1719 53 : Selector = sub( sqBits, add( sqBitsCtxHm, NumIndexBits ) );
1720 :
1721 53 : test();
1722 53 : IF( stopCtxHm == 0 && Selector > 0 ) /* Non-mapped is better */
1723 : {
1724 1 : sqTargetBits = add( sqTargetBits, NumIndexBits );
1725 1 : ctxHmBits = sub( ctxHmBits, NumIndexBits );
1726 1 : prm_hm[0] = 0;
1727 1 : move16();
1728 1 : *prm_lastnz = lastnz;
1729 1 : move16();
1730 1 : PeriodicityIndex = -1;
1731 1 : move16();
1732 1 : sqBits_noStop = sqBits = sqBitsCtxHm;
1733 1 : move16();
1734 1 : move16();
1735 1 : nEncoded = nEncodedCtxHm;
1736 1 : move16();
1737 1 : stop = stopCtxHm;
1738 1 : move16();
1739 : }
1740 : }
1741 : ELSE /* Mapping is not used */
1742 : {
1743 : /* Estimate mapped bitrate */
1744 570 : stopCtxHm = 1;
1745 570 : move16();
1746 570 : sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ,
1747 : L_spec,
1748 : &lastnzCtxHm,
1749 : &nEncodedCtxHm,
1750 570 : sub( sqTargetBits, NumIndexBits ),
1751 : &stopCtxHm,
1752 : hm_cfg );
1753 :
1754 : /* Decide whether or not to use mapping */
1755 570 : Selector = sub( sqBits, add( sqBitsCtxHm, NumIndexBits ) );
1756 :
1757 570 : test();
1758 570 : IF( stopCtxHm == 0 && Selector > 0 ) /* Mapped is better */
1759 : {
1760 3 : sqTargetBits = sub( sqTargetBits, NumIndexBits );
1761 3 : ctxHmBits = add( ctxHmBits, NumIndexBits );
1762 3 : prm_hm[0] = 1;
1763 3 : move16();
1764 3 : *prm_lastnz = lastnzCtxHm;
1765 3 : move16();
1766 3 : PeriodicityIndex = prm_hm[1];
1767 3 : move16();
1768 3 : sqBits_noStop = sqBits = sqBitsCtxHm;
1769 3 : move16();
1770 3 : move16();
1771 3 : nEncoded = nEncodedCtxHm;
1772 3 : move16();
1773 3 : stop = stopCtxHm;
1774 3 : move16();
1775 : }
1776 : }
1777 : }
1778 :
1779 : /* Limit low sqGain for avoiding saturation of the gain quantizer*/
1780 662 : tmp1 = mult_r( shl_o( L_spec, 5, &Overflow ), 26214 /*128.f/NORM_MDCT_FACTOR Q15*/ );
1781 662 : s = 15 - 5 - 7;
1782 662 : IF( L_spec >= 1024 )
1783 : {
1784 : /*reduce precision for avoiding overflow*/
1785 0 : tmp1 = mult_r( shl( L_spec, 4 ), 26214 /*128.f/NORM_MDCT_FACTOR Q15*/ );
1786 0 : s = 15 - 4 - 7;
1787 : }
1788 662 : tmp1 = ISqrt16( tmp1, &s );
1789 :
1790 662 : tmp2 = sub( sqGain_e, s );
1791 662 : IF( tmp2 >= 0 )
1792 : {
1793 : BASOP_SATURATE_WARNING_OFF_EVS;
1794 662 : tmp2 = sub_sat( sqGain, shr_sat( tmp1, tmp2 ) );
1795 : BASOP_SATURATE_WARNING_ON_EVS;
1796 : }
1797 : ELSE
1798 : {
1799 0 : tmp2 = sub( shl( sqGain, s_max( -15, tmp2 ) ), tmp1 );
1800 : }
1801 :
1802 662 : IF( tmp2 < 0 )
1803 : {
1804 0 : sqGain = tmp1;
1805 0 : sqGain_e = s;
1806 :
1807 0 : tcx_scalar_quantization_fx( spectrum, *spectrum_e,
1808 : sqQ,
1809 : L_spec,
1810 : sqGain, sqGain_e,
1811 0 : hTcxCfg->sq_rounding,
1812 0 : hTcxEnc->memQuantZeros,
1813 : tcxonly );
1814 :
1815 0 : move16();
1816 0 : stop = 1;
1817 :
1818 0 : phm_cfg = NULL;
1819 0 : move16();
1820 0 : if ( PeriodicityIndex >= 0 )
1821 : {
1822 0 : phm_cfg = hm_cfg;
1823 0 : move16();
1824 : }
1825 0 : sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ,
1826 : L_spec,
1827 : prm_lastnz,
1828 : &nEncoded,
1829 : sqTargetBits,
1830 : &stop,
1831 : phm_cfg );
1832 : }
1833 :
1834 : /* Truncate spectrum (for CBR) */
1835 662 : IF( stop != 0 )
1836 : {
1837 63 : set16_fx( sqQ + nEncoded, 0, sub( L_spec, nEncoded ) );
1838 : }
1839 :
1840 : /* Save quantized Values */
1841 662 : tmp32 = L_deposit_l( 0 );
1842 430582 : FOR( i = 0; i < L_spec; i++ )
1843 : {
1844 429920 : spectrum[i] = L_mult( sqQ[i], 1 << ( 30 - SPEC_EXP_DEC ) );
1845 429920 : move32();
1846 : /* noise filling seed */
1847 429920 : tmp32 = L_macNs_co( tmp32, abs_s( sqQ[i] ), i, &Carry, &Overflow );
1848 : }
1849 662 : *spectrum_e = SPEC_EXP_DEC;
1850 662 : move16();
1851 :
1852 662 : nf_seed = extract_l( tmp32 );
1853 : }
1854 : ELSE /* low rates: new arithmetic coder */
1855 : {
1856 0 : AdaptLowFreqEmph_fx( spectrum, *spectrum_e,
1857 : NULL,
1858 : 0, 0,
1859 0 : hTcxEnc->tcx_lpc_shaped_ari,
1860 : gainlpc, gainlpc_e,
1861 : L_frame );
1862 :
1863 0 : prm_target = sqQ;
1864 0 : move16();
1865 0 : sqQ = prm_target + 1;
1866 0 : move16();
1867 0 : signs = hm_cfg->indexBuffer;
1868 0 : move16();
1869 :
1870 0 : LtpPitchLag = -1;
1871 0 : move16();
1872 :
1873 0 : IF( LT_16( hTcxEnc->tcxltp_pitch_int, st->L_frame ) )
1874 : {
1875 0 : tmp32 = L_shl( L_mult0( st->L_frame, st->pit_res_max ), 1 + kLtpHmFractionalResolution + 1 );
1876 0 : tmp1 = add( imult1616( hTcxEnc->tcxltp_pitch_int, st->pit_res_max ), hTcxEnc->tcxltp_pitch_fr );
1877 0 : LtpPitchLag = div_l( tmp32, tmp1 );
1878 : }
1879 :
1880 0 : tmp8 = 1;
1881 0 : move16();
1882 0 : if ( st->last_core == ACELP_CORE )
1883 : {
1884 0 : tmp8 = 0;
1885 0 : move16();
1886 : }
1887 :
1888 0 : tcx_arith_encode_envelope_fx(
1889 : spectrum,
1890 : spectrum_e,
1891 : signs,
1892 : L_frame,
1893 : L_spec,
1894 : st,
1895 : Aqind,
1896 : sqTargetBits,
1897 : sqQ,
1898 : tmp8,
1899 : prm_hm, /* HM parameter area */
1900 : LtpPitchLag,
1901 : &sqBits,
1902 : &signaling_bits,
1903 0 : &nf_seed, shr( st->bwidth, 1 ) /* equivalent to: (st->bwidth > WB)?1:0 */
1904 : );
1905 :
1906 0 : sqTargetBits = sub( sqTargetBits, signaling_bits );
1907 0 : *prm_target = sqTargetBits;
1908 0 : move16();
1909 : }
1910 :
1911 : /*-----------------------------------------------------------*
1912 : * Compute optimal TCX gain. *
1913 : *-----------------------------------------------------------*/
1914 : /* initialize LF deemphasis factors in xn_buf */
1915 662 : set16_fx( xn_buf16, 0x4000, L_spec );
1916 :
1917 662 : IF( tcxonly == 0 )
1918 : {
1919 :
1920 662 : AdaptLowFreqDeemph( spectrum, *spectrum_e,
1921 662 : hTcxEnc->tcx_lpc_shaped_ari,
1922 : gainlpc, gainlpc_e,
1923 : L_frame,
1924 : xn_buf16 /* LF deemphasis factors */
1925 : );
1926 : }
1927 :
1928 662 : tcx_get_gain( x_orig, x_orig_e,
1929 662 : spectrum, *spectrum_e,
1930 : L_spec,
1931 : &gain_tcx_opt, &gain_tcx_opt_e,
1932 : &ener, &ener_e );
1933 :
1934 662 : IF( gain_tcx_opt <= 0 )
1935 : {
1936 0 : gain_tcx_opt = sqGain;
1937 0 : move16();
1938 0 : gain_tcx_opt_e = sqGain_e;
1939 0 : move16();
1940 : }
1941 662 : gain_tcx = gain_tcx_opt;
1942 662 : move16();
1943 662 : gain_tcx_e = gain_tcx_opt_e;
1944 662 : move16();
1945 :
1946 : /* Save gains for FAC and Residual Q*/
1947 :
1948 : /*-----------------------------------------------------------*
1949 : * Quantize TCX gain *
1950 : *-----------------------------------------------------------*/
1951 662 : test();
1952 662 : IF( GE_32( st->total_brate, ACELP_13k20 ) && st->rf_mode == 0 )
1953 : {
1954 662 : QuantizeGain( L_spec, &gain_tcx, &gain_tcx_e, &prm[0] );
1955 : }
1956 :
1957 :
1958 : /*-----------------------------------------------------------*
1959 : * Residual Quantization *
1960 : *-----------------------------------------------------------*/
1961 :
1962 662 : IF( hTcxCfg->resq )
1963 : {
1964 :
1965 662 : resQTargetBits = sub( sqTargetBits, sqBits );
1966 :
1967 662 : IF( hTcxEnc->tcx_lpc_shaped_ari ) /* new arithmetic coder */
1968 : {
1969 : Word16 *prm_resq;
1970 :
1971 0 : prm_resq = sqQ + sqTargetBits - resQTargetBits;
1972 :
1973 0 : resQBits = tcx_ari_res_Q_spec_fx( x_orig, x_orig_e, signs, spectrum, *spectrum_e, L_spec, gain_tcx, gain_tcx_e,
1974 : prm_resq,
1975 : resQTargetBits,
1976 : resQBits,
1977 0 : hTcxCfg->sq_rounding,
1978 : xn_buf16 /* LF deemphasis factors */ );
1979 :
1980 : /* Transmit zeros when there bits remain after RESQ */
1981 0 : set16_fx( prm_resq + resQBits, 0, sub( resQTargetBits, resQBits ) );
1982 : }
1983 : ELSE /* old arithmetic coder */
1984 : {
1985 662 : move16();
1986 662 : tmpP16 = NULL;
1987 662 : if ( tcxonly == 0 )
1988 : {
1989 662 : move16();
1990 662 : tmpP16 = xn_buf16;
1991 : }
1992 :
1993 662 : resQBits = tcx_res_Q_gain_fx( gain_tcx_opt, gain_tcx_opt_e,
1994 : &gain_tcx, &gain_tcx_e,
1995 662 : &sqQ[L_spec],
1996 : resQTargetBits );
1997 :
1998 662 : resQBits = tcx_res_Q_spec_fx( x_orig, x_orig_e,
1999 662 : spectrum, *spectrum_e,
2000 : L_spec,
2001 : gain_tcx, gain_tcx_e,
2002 662 : &sqQ[L_spec],
2003 : resQTargetBits,
2004 : resQBits,
2005 662 : hTcxCfg->sq_rounding,
2006 : tmpP16 /* LF deemphasis factors */ );
2007 : }
2008 : }
2009 :
2010 :
2011 : /*-----------------------------------------------------------*
2012 : * ALFE tcx only bitrates *
2013 : *-----------------------------------------------------------*/
2014 :
2015 662 : IF( st->tcxonly != 0 )
2016 : {
2017 0 : test();
2018 0 : test();
2019 0 : IF( hTcxEnc->tcxltp != 0 && ( hTcxEnc->tcxltp_gain > 0 ) && fUseTns == 0 )
2020 : {
2021 :
2022 0 : PsychAdaptLowFreqDeemph( spectrum, gainlpc, gainlpc_e, NULL );
2023 : }
2024 : }
2025 :
2026 : /*-----------------------------------------------------------*
2027 : * TCX SNR for Analysis purposes *
2028 : *-----------------------------------------------------------*/
2029 :
2030 : {
2031 662 : maxNfCalcBw = s_min( noiseFillingSize, round_fx( L_shl( L_mult( hTcxEnc->measuredBwRatio, L_frame ), 1 ) ) );
2032 :
2033 : /*-----------------------------------------------------------*
2034 : * Estimate and quantize noise factor *
2035 : *-----------------------------------------------------------*/
2036 :
2037 662 : IF( GE_32( st->total_brate, HQ_96k ) )
2038 : {
2039 0 : fac_ns = 0;
2040 0 : move16();
2041 0 : prm[1] = 0;
2042 0 : move16();
2043 : }
2044 : ELSE
2045 : {
2046 : /* noise filling start bin */
2047 662 : i = shr( L_frame, 3 );
2048 662 : test();
2049 662 : IF( GE_32( st->total_brate, ACELP_13k20 ) && st->rf_mode == 0 )
2050 : {
2051 662 : i = idiv1616U( L_frame, 6 );
2052 : }
2053 :
2054 662 : IF( tcxonly )
2055 : {
2056 0 : tmp1 = 0;
2057 0 : move16();
2058 0 : test();
2059 0 : test();
2060 0 : if ( ( hTcxCfg->ctx_hm != 0 ) && ( st->last_core != ACELP_CORE ) && ( prm_hm[0] != 0 ) )
2061 : {
2062 0 : tmp1 = 10240 /*0.3125f Q15*/;
2063 0 : move16();
2064 : }
2065 0 : noiseTransWidth = HOLE_SIZE_FROM_LTP( s_max( hTcxEnc->tcxltp_gain, tmp1 ) );
2066 :
2067 0 : if ( EQ_16( L_frame, shr( st->L_frame, 1 ) ) )
2068 : {
2069 : /* minimum transition for noise filling in TCX-10 */
2070 0 : noiseTransWidth = 3;
2071 0 : move16();
2072 : }
2073 : }
2074 :
2075 662 : tcx_noise_factor_fx( x_orig, x_orig_e,
2076 : spectrum,
2077 : i,
2078 : maxNfCalcBw,
2079 : noiseTransWidth,
2080 : L_frame,
2081 : gain_tcx, gain_tcx_e,
2082 662 : hTcxEnc->noiseTiltFactor,
2083 : &fac_ns, &prm[NOISE_FILL_RANGES] );
2084 :
2085 : /* hysteresis for very tonal passages (more stationary noise filling level) */
2086 :
2087 662 : IF( EQ_16( prm[NOISE_FILL_RANGES], 1 ) )
2088 : {
2089 56 : hTcxEnc->noiseLevelMemory_cnt = add( 1, abs_s( hTcxEnc->noiseLevelMemory_cnt ) ); /* update counter */
2090 56 : move16();
2091 : }
2092 : ELSE
2093 : {
2094 606 : test();
2095 606 : IF( ( EQ_16( prm[NOISE_FILL_RANGES], 2 ) ) &&
2096 : ( GT_16( abs_s( hTcxEnc->noiseLevelMemory_cnt ), 5 ) ) )
2097 : {
2098 : /* reduce noise filling level by one step */
2099 3 : prm[NOISE_FILL_RANGES] = 1;
2100 3 : move16();
2101 3 : fac_ns = shr( 0x6000, NBITS_NOISE_FILL_LEVEL );
2102 :
2103 : /* signal that noise level is changed by inverting sign of level memory */
2104 3 : tmp1 = 5;
2105 3 : move16();
2106 3 : if ( hTcxEnc->noiseLevelMemory_cnt >= 0 )
2107 : {
2108 2 : tmp1 = sub( -1, hTcxEnc->noiseLevelMemory_cnt );
2109 : }
2110 3 : hTcxEnc->noiseLevelMemory_cnt = tmp1;
2111 3 : move16();
2112 : }
2113 : ELSE
2114 : {
2115 : /* reset memory since level is too different */
2116 603 : hTcxEnc->noiseLevelMemory_cnt = 0;
2117 603 : move16();
2118 : }
2119 : }
2120 :
2121 : } /* bitrate */
2122 : }
2123 :
2124 : /* Free encoder specific stack to use it below for the internal TCX decoder. */
2125 : }
2126 :
2127 : /*-----------------------------------------------------------*
2128 : * Internal TCX decoder *
2129 : *-----------------------------------------------------------*/
2130 : {
2131 : /* Overlay of a 16-bit buffer xn_buf16 with a 32-bit buffer xn_buf32 */
2132 : /* The size is determined by the requirements of the 16-bit buffer. */
2133 : Word32 xn_buf32[( L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX ) / 2];
2134 662 : Word16 *xn_buf16 = (Word16 *) xn_buf32;
2135 :
2136 : /*Enable internal TCX decoder to run always to update LPD memory for rate switching */
2137 :
2138 : IF( tcxonly == 0 )
2139 : {
2140 : }
2141 :
2142 : /*-----------------------------------------------------------*
2143 : * Noise Filling. *
2144 : *-----------------------------------------------------------*/
2145 :
2146 662 : test();
2147 : /* Replication of ACELP formant enhancement for low rates */
2148 662 : IF( LT_32( st->total_brate, ACELP_13k20 ) || st->rf_mode != 0 )
2149 : {
2150 0 : tcxFormantEnhancement( xn_buf16, gainlpc, gainlpc_e, spectrum, spectrum_e, L_frame, L_spec );
2151 : }
2152 :
2153 662 : IF( fac_ns > 0 )
2154 : {
2155 660 : tmp1 = 0;
2156 660 : move16();
2157 660 : test();
2158 660 : if ( GE_32( st->total_brate, ACELP_13k20 ) && st->rf_mode == 0 )
2159 : {
2160 660 : tmp1 = 1;
2161 660 : move16();
2162 : }
2163 :
2164 660 : i = tcxGetNoiseFillingTilt( A,
2165 : M,
2166 : L_frame,
2167 : tmp1,
2168 : &hTcxEnc->noiseTiltFactor );
2169 :
2170 660 : tcx_noise_filling( spectrum, *spectrum_e, nf_seed /* seed */, i, noiseFillingSize, noiseTransWidth, L_frame, hTcxEnc->noiseTiltFactor, fac_ns, NULL, st->element_mode );
2171 : }
2172 662 : test();
2173 662 : IF( LT_32( st->total_brate, ACELP_13k20 ) || st->rf_mode != 0 )
2174 : {
2175 : /* partially recompute global gain (energy part), taking noise filling and formant enhancement into account */
2176 0 : s = sub( getScaleFactor32( spectrum, L_spec ), 4 );
2177 0 : tmp32 = L_deposit_l( 1 );
2178 :
2179 0 : FOR( i = 0; i < L_spec; i++ )
2180 : {
2181 0 : tmp1 = round_fx( L_shl( spectrum[i], s ) );
2182 0 : tmp32 = L_mac0( tmp32, tmp1, tmp1 );
2183 : }
2184 :
2185 0 : tmp1 = BASOP_Util_Divide3232_Scale( ener, tmp32, &tmp2 );
2186 0 : tmp2 = add( tmp2, sub( ener_e, add( shl( sub( *spectrum_e, s ), 1 ), 1 ) ) );
2187 0 : tmp1 = Sqrt16( tmp1, &tmp2 );
2188 :
2189 0 : gain_tcx = mult( gain_tcx, tmp1 );
2190 0 : gain_tcx_e = add( gain_tcx_e, tmp2 );
2191 :
2192 0 : QuantizeGain( L_spec, &gain_tcx, &gain_tcx_e, &prm[0] );
2193 : }
2194 :
2195 : /*end of noise filling*/
2196 :
2197 : /*-----------------------------------------------------------*
2198 : * Noise shaping in frequency domain (1/Wz) *
2199 : *-----------------------------------------------------------*/
2200 :
2201 : /* LPC gains already available */
2202 662 : mdct_shaping( spectrum, L_frame, gainlpc, gainlpc_e );
2203 :
2204 : /*-----------------------------------------------------------*
2205 : * Apply gain *
2206 : *-----------------------------------------------------------*/
2207 662 : IF( st->hTcxCfg->coder_type == INACTIVE )
2208 : {
2209 12 : gain_tcx = mult_r( gain_tcx, hTcxCfg->na_scale );
2210 : }
2211 :
2212 430582 : FOR( i = 0; i < L_spec; i++ )
2213 : {
2214 429920 : spectrum[i] = Mpy_32_16_1( spectrum[i], gain_tcx ); // Q(31-(spectrum_e+gain_tcx_e))
2215 429920 : move32();
2216 : }
2217 662 : *spectrum_e = add( *spectrum_e, gain_tcx_e );
2218 662 : move16();
2219 :
2220 662 : stop = hTcxCfg->tcx_last_overlap_mode; /* backup last TCX overlap mode */
2221 662 : move16();
2222 :
2223 662 : test();
2224 662 : IF( ( EQ_16( L_frame, shr( st->L_frame, 1 ) ) ) && ( tcxonly != 0 ) )
2225 : {
2226 0 : Word16 L = L_frame;
2227 0 : move16();
2228 :
2229 0 : test();
2230 0 : test();
2231 0 : if ( ( ( hTcxCfg->fIsTNSAllowed != 0 ) && ( fUseTns != 0 ) ) || ( GT_16( L_spec, L_frame ) ) )
2232 : {
2233 0 : L = L_spec;
2234 0 : move16();
2235 : }
2236 :
2237 0 : tcxInvertWindowGrouping( hTcxCfg,
2238 : xn_buf32,
2239 : spectrum,
2240 : L,
2241 : fUseTns,
2242 0 : st->last_core,
2243 : stop,
2244 : frame_cnt,
2245 : 0 );
2246 : }
2247 :
2248 : /*-----------------------------------------------------------*
2249 : * Temporal Noise Shaping Synthesis *
2250 : *-----------------------------------------------------------*/
2251 :
2252 662 : IF( hTcxCfg->fIsTNSAllowed != 0 )
2253 : {
2254 402 : test();
2255 402 : SetTnsConfig( hTcxCfg, sub( L_frame_glob, st->L_frame ) == 0, ( st->last_core == ACELP_CORE ) && ( frame_cnt == 0 ) );
2256 :
2257 : /* Apply TNS to get the reconstructed signal */
2258 402 : IF( fUseTns != 0 )
2259 : {
2260 4 : ApplyTnsFilter( hTcxCfg->pCurrentTnsConfig, pTnsData, spectrum, 0 );
2261 :
2262 4 : test();
2263 4 : IF( ( EQ_16( L_frame, shr( st->L_frame, 1 ) ) ) && ( tcxonly != 0 ) )
2264 : {
2265 0 : test();
2266 0 : test();
2267 0 : test();
2268 0 : IF( ( hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) ||
2269 : ( ( hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) && ( frame_cnt == 0 ) && ( stop == 0 ) ) )
2270 : {
2271 0 : tmp1 = shr( L_spec, 1 );
2272 : /* undo rearrangement of LF sub-window lines for TNS synthesis filter */
2273 0 : assert( L_frame <= L_spec );
2274 0 : Copy32( spectrum + 8, xn_buf32, 8 );
2275 0 : Copy32( spectrum + 16, spectrum + 8, sub( tmp1, 8 ) );
2276 0 : Copy32( xn_buf32, spectrum + tmp1, 8 );
2277 : }
2278 : }
2279 : }
2280 : }
2281 :
2282 : {
2283 : /* normalize spectrum to minimize IMDCT noise */
2284 662 : s = getScaleFactor32( spectrum, L_frame );
2285 198774 : FOR( i = 0; i < L_frame; i++ )
2286 : {
2287 198112 : spectrum[i] = L_shl( spectrum[i], s ); // Q(31-(spectrum_e-s))
2288 198112 : move32();
2289 : }
2290 662 : *spectrum_e = sub( *spectrum_e, s );
2291 :
2292 : /*-----------------------------------------------------------*
2293 : * Compute inverse MDCT of spectrum[]. *
2294 : *-----------------------------------------------------------*/
2295 662 : test();
2296 662 : IF( ( EQ_16( L_frame, shr( st->L_frame, 1 ) ) ) && ( tcxonly != 0 ) )
2297 : {
2298 0 : IF( hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP )
2299 : {
2300 : Word16 win[( L_FRAME_PLUS + L_MDCT_OVLP_MAX ) / 2];
2301 : Word16 L_win, L_spec_TCX5, L_ola, w;
2302 :
2303 : /* minimum or half overlap, two transforms, grouping into one window */
2304 0 : L_win = shr( L_frame, 1 );
2305 0 : L_spec_TCX5 = shr( s_max( L_frame, L_spec ), 1 );
2306 0 : L_ola = hTcxCfg->tcx_mdct_window_half_length;
2307 0 : move16();
2308 0 : if ( EQ_16( hTcxCfg->tcx_last_overlap_mode, MIN_OVERLAP ) )
2309 : {
2310 0 : L_ola = hTcxCfg->tcx_mdct_window_min_length;
2311 0 : move16();
2312 : }
2313 :
2314 0 : set16_fx( win, 0, ( L_FRAME_PLUS + L_MDCT_OVLP_MAX ) / 2 );
2315 0 : set16_fx( xn_buf16, 0, add( tcx_offset, shr( L_ola, 1 ) ) ); /* zero left end of buffer */
2316 :
2317 0 : FOR( w = 0; w < 2; w++ )
2318 : {
2319 :
2320 0 : IF( EQ_16( hTcxCfg->tcx_last_overlap_mode, MIN_OVERLAP ) )
2321 : {
2322 0 : TCX_MDCT_Inverse( spectrum + L_mult0( w, L_spec_TCX5 ), sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ),
2323 0 : win, L_ola, sub( L_win, L_ola ), L_ola, st->element_mode );
2324 : }
2325 : ELSE
2326 : {
2327 0 : TCX_MDCT_Inverse( spectrum + L_mult0( w, L_spec_TCX5 ), sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ), win,
2328 0 : L_ola, sub( L_win, L_ola ), L_ola, st->element_mode );
2329 : }
2330 :
2331 0 : tmp1 = hTcxCfg->tcx_last_overlap_mode;
2332 0 : move16();
2333 0 : test();
2334 0 : test();
2335 0 : if ( ( w > 0 ) || ( ( w == 0 ) && ( EQ_16( stop, 2 ) ) ) )
2336 : {
2337 0 : tmp1 = MIN_OVERLAP;
2338 0 : move16();
2339 : }
2340 :
2341 0 : tmp2 = 0;
2342 0 : move16();
2343 0 : test();
2344 0 : if ( ( w == 0 ) && ( st->last_core == ACELP_CORE ) )
2345 : {
2346 0 : tmp2 = 1;
2347 0 : move16();
2348 : }
2349 :
2350 0 : tmp3 = st->last_core;
2351 0 : move16();
2352 0 : if ( w > 0 )
2353 : {
2354 0 : tmp3 = 1;
2355 0 : move16();
2356 : }
2357 :
2358 0 : tmp4 = 0;
2359 0 : move16();
2360 0 : if ( tcx_offset < 0 )
2361 : {
2362 0 : tmp4 = negate( tcx_offset );
2363 : }
2364 :
2365 0 : tcx_windowing_synthesis_current_frame( win,
2366 0 : hTcxCfg->tcx_aldo_window_2,
2367 0 : hTcxCfg->tcx_mdct_window_half,
2368 0 : hTcxCfg->tcx_mdct_window_minimum,
2369 : L_ola,
2370 0 : hTcxCfg->tcx_mdct_window_half_length,
2371 0 : hTcxCfg->tcx_mdct_window_min_length,
2372 : tmp2,
2373 : tmp1,
2374 : hTcxEnc->acelp_zir,
2375 0 : hTcxEnc->Txnq,
2376 : NULL,
2377 : Aq_old,
2378 0 : hTcxCfg->tcx_mdct_window_trans,
2379 : L_win,
2380 : tmp4,
2381 : tmp3,
2382 : 0,
2383 : 0 );
2384 :
2385 0 : tmp1 = add( tcx_offset, imult1616( w, L_win ) );
2386 0 : move16();
2387 0 : tmpP16 = xn_buf16 + sub( tmp1, shr( L_ola, 1 ) );
2388 :
2389 0 : IF( w > 0 )
2390 : {
2391 0 : tcx_windowing_synthesis_past_frame( tmpP16,
2392 0 : hTcxCfg->tcx_aldo_window_1_trunc,
2393 0 : hTcxCfg->tcx_mdct_window_half,
2394 0 : hTcxCfg->tcx_mdct_window_minimum,
2395 : L_ola,
2396 0 : hTcxCfg->tcx_mdct_window_half_length,
2397 0 : hTcxCfg->tcx_mdct_window_min_length,
2398 : 2 );
2399 : }
2400 : /* add part of current sub-window overlapping with previous window */
2401 0 : FOR( i = 0; i < L_ola; i++ )
2402 : {
2403 0 : tmpP16[i] = add_sat( tmpP16[i], win[i] );
2404 0 : move16();
2405 : }
2406 : /* copy new sub-window region not overlapping with previous window */
2407 0 : Copy( win + L_ola, xn_buf16 + add( tmp1, shr( L_ola, 1 ) ), L_win );
2408 : }
2409 : /* To assure that no garbage values are copied to hLPDmem->Txnq */
2410 0 : set16_fx( xn_buf16 + add( add( L_frame, tcx_offset ), shr( L_ola, 1 ) ),
2411 0 : 0, sub( sub( overlap, tcx_offset ), shr( L_ola, 1 ) ) );
2412 : }
2413 0 : ELSE IF( s_and( frame_cnt == 0, ( hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) ) )
2414 : {
2415 : /* special overlap attempt, two transforms, grouping into one window */
2416 : Word16 win[( L_FRAME_PLUS + L_MDCT_OVLP_MAX ) / 2];
2417 : Word16 L_win, L_spec_TCX5, L_ola, w;
2418 :
2419 0 : L_win = shr( L_frame, 1 );
2420 0 : L_spec_TCX5 = shr( s_max( L_frame, L_spec ), 1 );
2421 0 : L_ola = hTcxCfg->tcx_mdct_window_min_length;
2422 0 : move16();
2423 :
2424 0 : set16_fx( win, 0, ( L_FRAME_PLUS + L_MDCT_OVLP_MAX ) / 2 );
2425 :
2426 : /* Resize overlap (affect only asymmetric window)*/
2427 0 : overlap = st->hTcxCfg->tcx_mdct_window_delay;
2428 : /* 1st TCX-5 window, special MDCT with minimum overlap on right side */
2429 0 : TCX_MDCT_Inverse( spectrum, sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ),
2430 0 : win + L_win, 0, sub( L_win, shr( L_ola, 1 ) ), L_ola, st->element_mode );
2431 :
2432 : /* copy new sub-window region not overlapping with previous window */
2433 0 : Copy( win + L_win, xn_buf16 + shr( overlap, 1 ), add( L_win, shr( L_ola, 1 ) ) );
2434 :
2435 : /* 2nd TCX-5 window, regular MDCT with minimum overlap on both sides */
2436 :
2437 0 : TCX_MDCT_Inverse( spectrum + L_spec_TCX5, sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ),
2438 0 : win, L_ola, sub( L_win, L_ola ), L_ola, st->element_mode );
2439 :
2440 0 : tmp4 = 0;
2441 0 : move16();
2442 0 : if ( tcx_offset < 0 )
2443 : {
2444 0 : tmp4 = negate( tcx_offset );
2445 : }
2446 0 : tcx_windowing_synthesis_current_frame( win,
2447 0 : hTcxCfg->tcx_aldo_window_2,
2448 0 : hTcxCfg->tcx_mdct_window_half,
2449 0 : hTcxCfg->tcx_mdct_window_minimum,
2450 : L_ola,
2451 0 : hTcxCfg->tcx_mdct_window_half_length,
2452 0 : hTcxCfg->tcx_mdct_window_min_length,
2453 : 0, /* left_rect */
2454 : 2, /* left_mode */
2455 : hTcxEnc->acelp_zir,
2456 0 : hTcxEnc->Txnq,
2457 : NULL,
2458 : Aq_old,
2459 0 : hTcxCfg->tcx_mdct_window_trans,
2460 : L_win,
2461 : tmp4,
2462 : 1, /* not LPDmem->mode */
2463 : 0,
2464 : 0 );
2465 :
2466 :
2467 0 : tmpP16 = xn_buf16 + add( sub( L_win, shr( L_ola, 1 ) ), shr( overlap, 1 ) );
2468 :
2469 0 : tcx_windowing_synthesis_past_frame( tmpP16,
2470 0 : hTcxCfg->tcx_aldo_window_1_trunc,
2471 0 : hTcxCfg->tcx_mdct_window_half,
2472 0 : hTcxCfg->tcx_mdct_window_minimum,
2473 : L_ola,
2474 0 : hTcxCfg->tcx_mdct_window_half_length,
2475 0 : hTcxCfg->tcx_mdct_window_min_length,
2476 : 2 );
2477 :
2478 : /* add part of current sub-window overlapping with previous window */
2479 0 : FOR( i = 0; i < L_ola; i++ )
2480 : {
2481 0 : tmpP16[i] = add_sat( tmpP16[i], win[i] );
2482 0 : move16();
2483 : }
2484 :
2485 : /* copy new sub-window region not overlapping with previous window */
2486 0 : Copy( win + L_ola,
2487 0 : xn_buf16 + add( add( shr( overlap, 1 ), shr( L_ola, 1 ) ), L_win ),
2488 : L_win );
2489 :
2490 : /* extra folding-out on left side of win, for perfect reconstruction */
2491 0 : FOR( w = overlap / 2; w < overlap; w++ )
2492 : {
2493 0 : xn_buf16[overlap - 1 - w] = negate( xn_buf16[w] );
2494 0 : move16();
2495 : }
2496 :
2497 0 : tmp4 = 0;
2498 0 : move16();
2499 0 : if ( tcx_offset < 0 )
2500 : {
2501 0 : tmp4 = negate( tcx_offset );
2502 : }
2503 0 : tcx_windowing_synthesis_current_frame( xn_buf16,
2504 0 : hTcxCfg->tcx_aldo_window_2,
2505 0 : hTcxCfg->tcx_mdct_window_half,
2506 0 : hTcxCfg->tcx_mdct_window_minimum,
2507 : overlap,
2508 0 : hTcxCfg->tcx_mdct_window_half_length,
2509 0 : hTcxCfg->tcx_mdct_window_min_length,
2510 0 : st->last_core == ACELP_CORE,
2511 : 0,
2512 : hTcxEnc->acelp_zir,
2513 0 : hTcxEnc->Txnq,
2514 : NULL,
2515 : Aq_old,
2516 0 : hTcxCfg->tcx_mdct_window_trans,
2517 : L_win,
2518 : tmp4,
2519 0 : st->last_core,
2520 : 0,
2521 : 0 );
2522 : }
2523 : ELSE /* default, i.e. maximum overlap, single transform, no grouping */
2524 : {
2525 :
2526 0 : TCX_MDCT_Inverse( spectrum, sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ),
2527 0 : xn_buf16, overlap, sub( L_frame, overlap ), overlap, st->element_mode );
2528 :
2529 0 : tmp1 = stop;
2530 0 : move16();
2531 0 : test();
2532 0 : test();
2533 0 : if ( ( frame_cnt > 0 ) && ( stop == 0 ) && ( st->last_core != ACELP_CORE ) )
2534 : {
2535 0 : tmp1 = 2;
2536 0 : move16();
2537 : }
2538 :
2539 0 : tmp4 = 0;
2540 0 : move16();
2541 0 : if ( tcx_offset < 0 )
2542 : {
2543 0 : tmp4 = negate( tcx_offset );
2544 : }
2545 0 : tcx_windowing_synthesis_current_frame( xn_buf16,
2546 0 : hTcxCfg->tcx_aldo_window_2,
2547 0 : hTcxCfg->tcx_mdct_window_half,
2548 0 : hTcxCfg->tcx_mdct_window_minimum,
2549 : overlap, /*hTcxCfg->tcx_mdct_window_length*/
2550 0 : hTcxCfg->tcx_mdct_window_half_length,
2551 0 : hTcxCfg->tcx_mdct_window_min_length,
2552 0 : st->last_core == ACELP_CORE,
2553 : tmp1,
2554 : hTcxEnc->acelp_zir,
2555 0 : hTcxEnc->Txnq,
2556 : NULL,
2557 : Aq_old,
2558 0 : hTcxCfg->tcx_mdct_window_trans,
2559 0 : shr( L_frame_glob, 1 ),
2560 : tmp4,
2561 0 : st->last_core,
2562 : 0,
2563 : 0 );
2564 :
2565 : } /* tcx_last_overlap_mode > 0 */
2566 : }
2567 : ELSE /* frame is TCX-20 or not TCX-only */
2568 : {
2569 662 : IF( NE_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) )
2570 : {
2571 : Word32 tmp_buf[L_FRAME_PLUS];
2572 : Word16 Q;
2573 :
2574 : /* DCT */
2575 623 : Q = sub( 31, *spectrum_e );
2576 623 : edct_fx( spectrum, tmp_buf, L_frame, &Q );
2577 :
2578 : /* scale by sqrt(L / NORM_MDCT_FACTOR) */
2579 623 : tmp1 = mult_r( shl( L_frame, 4 ), 26214 /*128.f / NORM_MDCT_FACTOR Q15*/ ); /* 4Q11 */
2580 623 : tmp2 = 4;
2581 623 : move16();
2582 623 : tmp1 = Sqrt16( tmp1, &tmp2 );
2583 :
2584 184175 : FOR( i = 0; i < L_frame; i++ )
2585 : {
2586 183552 : tmp_buf[i] = Mpy_32_16_1( tmp_buf[i], tmp1 );
2587 183552 : move32();
2588 : }
2589 623 : Q = sub( Q, tmp2 );
2590 :
2591 :
2592 623 : window_ola_fx( tmp_buf,
2593 : xn_buf16,
2594 : &Q,
2595 623 : hTcxEnc->old_out_fx,
2596 : &hTcxEnc->Q_old_out,
2597 : L_frame,
2598 623 : hTcxCfg->tcx_last_overlap_mode,
2599 623 : hTcxCfg->tcx_curr_overlap_mode,
2600 : 0,
2601 : 0,
2602 : NULL );
2603 :
2604 : /* scale output */
2605 184175 : FOR( i = 0; i < L_frame; i++ )
2606 : {
2607 183552 : xn_buf16[i] = shr_o( xn_buf16[i], Q, &Overflow );
2608 183552 : move16();
2609 : }
2610 :
2611 623 : aldo = 1;
2612 623 : move16();
2613 : }
2614 : ELSE
2615 : {
2616 :
2617 39 : TCX_MDCT_Inverse( spectrum, sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ),
2618 39 : xn_buf16, overlap, sub( L_frame, overlap ), overlap, st->element_mode );
2619 :
2620 : /*-----------------------------------------------------------*
2621 : * Windowing, overlap and add *
2622 : *-----------------------------------------------------------*/
2623 :
2624 : /* Window current frame */
2625 39 : tmp4 = 0;
2626 39 : move16();
2627 39 : if ( tcx_offset < 0 )
2628 : {
2629 39 : tmp4 = negate( tcx_offset );
2630 : }
2631 78 : tcx_windowing_synthesis_current_frame( xn_buf16,
2632 39 : hTcxCfg->tcx_aldo_window_2,
2633 39 : hTcxCfg->tcx_mdct_window_half,
2634 39 : hTcxCfg->tcx_mdct_window_minimum,
2635 : overlap, /*hTcxCfg->tcx_mdct_window_length*/
2636 39 : hTcxCfg->tcx_mdct_window_half_length,
2637 39 : hTcxCfg->tcx_mdct_window_min_length,
2638 39 : st->last_core == ACELP_CORE,
2639 39 : hTcxCfg->tcx_last_overlap_mode, /*left mode*/
2640 : hTcxEnc->acelp_zir,
2641 39 : hTcxEnc->Txnq,
2642 : NULL,
2643 : Aq_old,
2644 39 : hTcxCfg->tcx_mdct_window_trans,
2645 39 : shr( L_frame_glob, 1 ),
2646 : tmp4,
2647 39 : st->last_core,
2648 : 0,
2649 : 0 );
2650 : }
2651 : } /* TCX-10 and TCX-only */
2652 :
2653 : /* Window and overlap-add past frame if past frame is TCX */
2654 662 : test();
2655 662 : test();
2656 662 : test();
2657 662 : IF( ( st->last_core > ACELP_CORE ) && ( ( ( EQ_16( L_frameTCX, shr( hTcxEnc->L_frameTCX, 1 ) ) ) && ( st->tcxonly != 0 ) ) || ( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) ) )
2658 : {
2659 :
2660 0 : IF( hTcxCfg->last_aldo != 0 )
2661 : {
2662 0 : tmp2 = add( hTcxEnc->Q_old_out, TCX_IMDCT_HEADROOM );
2663 :
2664 0 : tmp1 = sub( overlap, hTcxCfg->tcx_mdct_window_min_length );
2665 0 : FOR( i = 0; i < tmp1; i++ )
2666 : {
2667 0 : xn_buf16[i] = shl_sat( add_sat( xn_buf16[i], shr_sat( hTcxEnc->old_out_fx[i + nz], tmp2 ) ), TCX_IMDCT_HEADROOM );
2668 0 : move16();
2669 : }
2670 :
2671 : /* fade truncated ALDO window */
2672 0 : tmp1 = sub( overlap, shr( hTcxCfg->tcx_mdct_window_min_length, 1 ) );
2673 0 : FOR( ; i < tmp1; i++ )
2674 : {
2675 0 : tmp3 = mult_r( shr( hTcxEnc->old_out_fx[i + nz], tmp2 ), hTcxCfg->tcx_mdct_window_minimum[i - overlap + hTcxCfg->tcx_mdct_window_min_length].v.re );
2676 0 : xn_buf16[i] = shl_sat( add_sat( xn_buf16[i], tmp3 ), TCX_IMDCT_HEADROOM );
2677 0 : move16();
2678 : }
2679 0 : FOR( ; i < overlap; i++ )
2680 : {
2681 0 : tmp3 = mult_r( shr( hTcxEnc->old_out_fx[i + nz], tmp2 ), hTcxCfg->tcx_mdct_window_minimum[overlap - 1 - i].v.im );
2682 0 : xn_buf16[i] = shl_sat( add_sat( xn_buf16[i], tmp3 ), TCX_IMDCT_HEADROOM );
2683 0 : move16();
2684 : }
2685 :
2686 0 : FOR( ; i < L_frame; i++ )
2687 : {
2688 0 : xn_buf16[i] = shl_sat( xn_buf16[i], TCX_IMDCT_HEADROOM );
2689 0 : move16();
2690 : }
2691 : }
2692 : ELSE
2693 : {
2694 0 : test();
2695 0 : test();
2696 0 : test();
2697 0 : if ( ( frame_cnt > 0 ) && ( stop == 0 ) && ( hTcxCfg->tcx_curr_overlap_mode == 0 ) && ( st->last_core != ACELP_CORE ) )
2698 : {
2699 0 : stop = 2; /* use minimum overlap between the two TCX-10 windows */
2700 0 : move16();
2701 : }
2702 :
2703 0 : tmp1 = stop;
2704 0 : move16();
2705 0 : test();
2706 0 : if ( ( stop == 0 ) || ( EQ_16( hTcxCfg->tcx_last_overlap_mode, MIN_OVERLAP ) ) )
2707 : {
2708 0 : tmp1 = hTcxCfg->tcx_last_overlap_mode;
2709 0 : move16();
2710 : }
2711 :
2712 0 : tcx_windowing_synthesis_past_frame( hTcxEnc->Txnq, hTcxCfg->tcx_aldo_window_1_trunc, hTcxCfg->tcx_mdct_window_half,
2713 0 : hTcxCfg->tcx_mdct_window_minimum, overlap, hTcxCfg->tcx_mdct_window_half_length, hTcxCfg->tcx_mdct_window_min_length, tmp1 );
2714 :
2715 : BASOP_SATURATE_WARNING_OFF_EVS;
2716 0 : FOR( i = 0; i < overlap; i++ )
2717 : {
2718 0 : xn_buf16[i] = shl_sat( add( xn_buf16[i], hTcxEnc->Txnq[i] ), TCX_IMDCT_HEADROOM );
2719 0 : move16();
2720 : }
2721 :
2722 0 : IF( LT_16( i, L_frame ) )
2723 : {
2724 0 : FOR( ; i < L_frame; i++ )
2725 : {
2726 0 : xn_buf16[i] = shl_sat( xn_buf16[i], TCX_IMDCT_HEADROOM );
2727 0 : move16();
2728 : }
2729 : }
2730 : BASOP_SATURATE_WARNING_ON_EVS;
2731 : }
2732 : }
2733 : ELSE
2734 : {
2735 662 : IF( aldo == 0 )
2736 : {
2737 : BASOP_SATURATE_WARNING_OFF_EVS;
2738 14599 : FOR( i = 0; i < L_frame; i++ )
2739 : {
2740 14560 : xn_buf16[i] = shl_o( xn_buf16[i], TCX_IMDCT_HEADROOM, &Overflow );
2741 14560 : move16();
2742 : }
2743 : BASOP_SATURATE_WARNING_ON_EVS;
2744 : }
2745 : }
2746 :
2747 662 : test();
2748 662 : test();
2749 662 : test();
2750 662 : IF( ( aldo == 0 ) &&
2751 : ( ( EQ_16( L_frameTCX, shr( hTcxEnc->L_frameTCX, 1 ) ) && frame_cnt > 0 ) ||
2752 : NE_16( L_frameTCX, shr( hTcxEnc->L_frameTCX, 1 ) ) ) )
2753 : {
2754 : /*Compute windowed synthesis in case of switching to ALDO windows in next frame*/
2755 3315 : FOR( i = 0; i < nz; i++ )
2756 : {
2757 3276 : hTcxEnc->old_out_fx[i] = shr( xn_buf16[L_frame - nz + i], TCX_IMDCT_HEADROOM );
2758 3276 : move16();
2759 : }
2760 39 : Copy( xn_buf16 + L_frame, hTcxEnc->old_out_fx + nz, overlap );
2761 39 : set16_fx( hTcxEnc->old_out_fx + nz + overlap, 0, nz );
2762 :
2763 39 : tcx_windowing_synthesis_past_frame( hTcxEnc->old_out_fx + nz,
2764 39 : hTcxCfg->tcx_aldo_window_1_trunc,
2765 39 : hTcxCfg->tcx_mdct_window_half,
2766 39 : hTcxCfg->tcx_mdct_window_minimum,
2767 : overlap,
2768 39 : hTcxCfg->tcx_mdct_window_half_length,
2769 39 : hTcxCfg->tcx_mdct_window_min_length,
2770 39 : hTcxCfg->tcx_curr_overlap_mode );
2771 :
2772 : /* If current overlap mode = FULL_OVERLAP -> ALDO_WINDOW */
2773 39 : IF( EQ_16( hTcxCfg->tcx_curr_overlap_mode, FULL_OVERLAP ) )
2774 : {
2775 3315 : FOR( i = 0; i < nz; i++ )
2776 : {
2777 3276 : hTcxEnc->old_out_fx[nz + overlap + i] = shr( mult_r( xn_buf16[L_frame - 1 - i], hTcxCfg->tcx_aldo_window_1[nz - 1 - i] ), TCX_IMDCT_HEADROOM );
2778 3276 : move16();
2779 : }
2780 39 : hTcxCfg->tcx_curr_overlap_mode = ALDO_WINDOW;
2781 39 : move16();
2782 : }
2783 :
2784 39 : hTcxEnc->Q_old_out = -TCX_IMDCT_HEADROOM;
2785 39 : move16();
2786 : }
2787 662 : hTcxCfg->last_aldo = aldo;
2788 662 : move16();
2789 :
2790 : /* Update Txnq */
2791 662 : IF( hTcxCfg->last_aldo == 0 )
2792 : {
2793 39 : Copy( xn_buf16 + L_frame, hTcxEnc->Txnq, overlap );
2794 : }
2795 :
2796 :
2797 : /* Output */
2798 662 : Copy( xn_buf16 + shr( overlap, 1 ) - tcx_offset, synth, L_frame_glob );
2799 : }
2800 :
2801 : /* Free internal TCX decoder stack memory */
2802 : }
2803 :
2804 : /* Update L_frame_past */
2805 662 : st->L_frame_past = L_frame;
2806 662 : move16();
2807 662 : }
2808 :
2809 0 : static Word16 DecideTonalSideInfo_fx(
2810 : Word32 spectrum[], // Qx
2811 : const Word16 L_frame_glob,
2812 : Word32 SFM2 )
2813 : {
2814 : Word32 SFM, K, K2;
2815 : Word16 Tonal_SideInfo;
2816 :
2817 0 : SFM = SFM_Cal_fx( spectrum, s_min( 200, L_frame_glob ) );
2818 0 : test();
2819 0 : IF( LE_16( L_frame_glob, 256 ) )
2820 : {
2821 0 : K = 0x33333333;
2822 0 : move32();
2823 0 : K2 = 0xCCCCCCD;
2824 0 : move32();
2825 : }
2826 0 : ELSE IF( EQ_16( L_frame_glob, 320 ) || EQ_16( L_frame_glob, 512 ) )
2827 : {
2828 0 : K = 0x33333333;
2829 0 : move32();
2830 0 : K2 = 0xCCCCCCD;
2831 0 : move32();
2832 : }
2833 : ELSE /*FrameSize_Core == 640*/
2834 : {
2835 0 : K = 0x2CCCCCCD;
2836 0 : move32();
2837 0 : K2 = 0x51EB852;
2838 0 : move32();
2839 : }
2840 :
2841 :
2842 0 : Tonal_SideInfo = 0;
2843 0 : move16();
2844 0 : if ( LT_32( SFM, K ) )
2845 : {
2846 0 : Tonal_SideInfo = 1;
2847 0 : move16();
2848 : }
2849 0 : if ( LT_32( SFM2, K2 ) )
2850 : {
2851 0 : Tonal_SideInfo = 1;
2852 0 : move16();
2853 : }
2854 :
2855 0 : return Tonal_SideInfo;
2856 : }
2857 :
2858 861441 : void QuantizeTCXSpectrum_fx(
2859 : Encoder_State *st, /* i : state handle */
2860 : const Word16 frame_cnt, /* i : frame counter in the super_frame Q0 */
2861 : Word32 *x_orig_fx, /* i : shaped MDCT spectrum Q(31-x_orig_e)*/
2862 : Word16 x_orig_e, /* i : exp of shaped MDCT spectrum */
2863 : Word16 *gainlpc_fx, /* i : FDNS gains Q(15-gainlpc_e)*/
2864 : Word16 *gainlpc_e, /* i : exp of FDNS gains */
2865 : const Word16 *Aqind, /* i : frame-independent quantized coefficients (M+1) Q0 */
2866 : const Word16 tnsSize, /* i : number of tns parameters put into prm Q0 */
2867 : const Word16 nb_bits, /* i : bit budget Q0 */
2868 : const Word16 vad_hover_flag, /* i : VAD hangover flag Q0 */
2869 : Word16 *pL_frameTCX, /* o : full frame length Q0 */
2870 : Word16 *pL_frame, /* o : frame length Q0 */
2871 : Word16 *pL_spec, /* o : length of the coded spectrum Q0 */
2872 : Word16 *ptcx_offset, /* o : folding point offset relative to the end of the previous frame Q0 */
2873 : Word16 *pnoiseFillingBorder, /* o : noise filling border Q0 */
2874 : Word32 spectrum_fx[], /* o : quantized MDCT spectrum Q(31-spectrum_e)*/
2875 : Word16 *spectrum_e, /* o : exp of quantized MDCT spectrum */
2876 : CONTEXT_HM_CONFIG *hm_cfg, /* o : Context-based harmonic model configuration */
2877 : Word16 *hm_active, /* o : flag indicating if the harmonic model is active */
2878 : Word16 lf_deemph_fact_fx[], /* o : low frequency deemphasis factors Q14*/
2879 : Word16 *nf_seed, /* o : noise filling random seed Q0*/
2880 : Word32 *ener_fx, /* o : energy of the quantized spectrum Q(31-ener_e) */
2881 : Word16 *ener_e, /* o : exp of energy of the quantized spectrum */
2882 : Word16 *gain_tcx_fx, /* o : global gain Q(15-gain_tcx_e) */
2883 : Word16 *gain_tcx_e, /* o : exp of global gain */
2884 : Word16 prm[] /* o : tcx parameters Q0 */
2885 : )
2886 : {
2887 861441 : TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
2888 : Word16 i, L_frame, L_frameTCX, L_spec, tcx_offset;
2889 : Word16 noiseFillingBorder, LtpPitchLag, PeriodicityIndex;
2890 : Word16 lastnzCtxHm, lastnz;
2891 : Word16 stop;
2892 : Word16 nEncodedCtxHm, stopCtxHm, sqBitsCtxHm, Selector;
2893 : Word16 nEncoded, sqBits_noStop;
2894 : Word16 NumIndexBits, signaling_bits, sqTargetBits, sqBits, ctxHmBits, resQBits, resQTargetBits;
2895 : Word16 *prm_ltp, *prm_tns, *prm_hm, *prm_lastnz, *sqQ, *prm_target;
2896 : Word32 total_brate, tmp32;
2897 : Word16 RelativeScore_fx, sqGain_fx, sqGain_e, gain_tcx_opt_fx, gain_tcx_opt_e;
2898 : Word16 tmp1, tmp2, max_iter, minSqGain;
2899 : CONTEXT_HM_CONFIG *phm_cfg;
2900 861441 : Word16 att_fx = 0;
2901 861441 : move16();
2902 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
2903 861441 : Flag Overflow = 0;
2904 861441 : move16();
2905 861441 : Flag Carry = 0;
2906 861441 : move16();
2907 : #endif
2908 : /*-----------------------------------------------------------*
2909 : * Init *
2910 : *-----------------------------------------------------------*/
2911 :
2912 861441 : sqGain_fx = MAX_16;
2913 861441 : move16();
2914 861441 : sqGain_e = 0;
2915 861441 : move16();
2916 861441 : minSqGain = 0;
2917 861441 : move16();
2918 861441 : resQTargetBits = 0;
2919 861441 : move16();
2920 :
2921 861441 : NumIndexBits = 0;
2922 861441 : move16();
2923 861441 : sqBits = 0;
2924 861441 : move16();
2925 861441 : ctxHmBits = 0;
2926 861441 : move16();
2927 861441 : resQBits = 0;
2928 861441 : move16();
2929 861441 : prm_ltp = &prm[1 + NOISE_FILL_RANGES];
2930 861441 : prm_tns = prm_ltp + LTPSIZE;
2931 861441 : prm_hm = prm_tns + tnsSize;
2932 861441 : prm_lastnz = prm_hm + 2;
2933 861441 : sqQ = prm_hm + NPRM_CTX_HM;
2934 :
2935 861441 : IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) )
2936 : {
2937 623603 : total_brate = st->element_brate;
2938 : }
2939 : ELSE
2940 : {
2941 237838 : total_brate = st->total_brate;
2942 : }
2943 861441 : move32();
2944 : /*-----------------------------------------------------------*
2945 : * Init lengths *
2946 : *-----------------------------------------------------------*/
2947 :
2948 : /******************************************************************************************/
2949 :
2950 861441 : L_frame = st->L_frame;
2951 861441 : move16();
2952 861441 : L_frameTCX = hTcxEnc->L_frameTCX;
2953 861441 : move16();
2954 861441 : L_spec = st->hTcxCfg->tcx_coded_lines;
2955 861441 : move16();
2956 861441 : tcx_offset = st->hTcxCfg->tcx_offset;
2957 861441 : move16();
2958 :
2959 861441 : IF( EQ_16( st->core, TCX_10_CORE ) )
2960 : {
2961 31598 : L_frame = shr( L_frame, 1 );
2962 31598 : L_frameTCX = shr( L_frameTCX, 1 );
2963 31598 : L_spec = shr( L_spec, 1 );
2964 : }
2965 829843 : ELSE IF( st->last_core == ACELP_CORE )
2966 : {
2967 9214 : st->hTcxCfg->last_aldo = 0;
2968 9214 : move16();
2969 9214 : L_frame = add( L_frame, tcx_offset );
2970 9214 : L_frameTCX = add( L_frameTCX, st->hTcxCfg->tcx_offsetFB );
2971 9214 : L_spec = add( L_spec, shr( st->hTcxCfg->tcx_coded_lines, 2 ) );
2972 :
2973 9214 : IF( st->hTcxCfg->lfacNext < 0 )
2974 : {
2975 9214 : L_frame = sub( L_frame, st->hTcxCfg->lfacNext );
2976 9214 : L_frameTCX = sub( L_frameTCX, st->hTcxCfg->lfacNextFB );
2977 9214 : tcx_offset = st->hTcxCfg->lfacNext;
2978 9214 : move16();
2979 : }
2980 : ELSE
2981 : {
2982 0 : tcx_offset = 0;
2983 0 : move16();
2984 : }
2985 9214 : hTcxEnc->noiseLevelMemory_cnt = 0;
2986 9214 : move16();
2987 : }
2988 :
2989 861441 : *pL_frameTCX = L_frameTCX;
2990 861441 : move16();
2991 861441 : *pL_frame = L_frame;
2992 861441 : move16();
2993 861441 : *pL_spec = L_spec;
2994 861441 : move16();
2995 861441 : *ptcx_offset = tcx_offset;
2996 861441 : move16();
2997 :
2998 : /* target bitrate for SQ */
2999 861441 : sqTargetBits = sub( nb_bits, NBITS_TCX_GAIN + NBITS_NOISE_FILL_LEVEL );
3000 :
3001 861441 : IF( st->enablePlcWaveadjust )
3002 : {
3003 : Word16 L_frame_glob;
3004 0 : IF( EQ_16( st->core, TCX_20_CORE ) )
3005 : {
3006 0 : L_frame_glob = st->L_frame;
3007 0 : move16();
3008 : }
3009 : ELSE
3010 : {
3011 0 : L_frame_glob = shr( st->L_frame, 1 );
3012 : }
3013 0 : move16();
3014 0 : st->Tonal_SideInfo = DecideTonalSideInfo_fx( x_orig_fx, L_frame_glob, st->hTcxCfg->SFM2 );
3015 : }
3016 :
3017 : /* Start with the pre-shaped spectrum*/
3018 :
3019 : /*scaling buffer to Q31 if exp < 0 to avoid overflow while scaling constants*/
3020 861441 : IF( x_orig_e < 0 )
3021 : {
3022 706 : scale_sig32( x_orig_fx, L_spec, x_orig_e );
3023 706 : x_orig_e = 0;
3024 706 : move16();
3025 : }
3026 :
3027 861441 : Copy32( x_orig_fx, spectrum_fx, L_spec );
3028 861441 : *spectrum_e = x_orig_e;
3029 861441 : move16();
3030 :
3031 : /*-----------------------------------------------------------*
3032 : * Bandwidth Limitation *
3033 : *-----------------------------------------------------------*/
3034 :
3035 861441 : noiseFillingBorder = L_spec;
3036 861441 : move16();
3037 861441 : IF( st->igf )
3038 : {
3039 592081 : noiseFillingBorder = st->hIGFEnc->infoStartLine;
3040 592081 : move16();
3041 : }
3042 861441 : *pnoiseFillingBorder = noiseFillingBorder;
3043 861441 : move16();
3044 :
3045 861441 : IF( st->igf )
3046 : {
3047 88245345 : FOR( i = st->hIGFEnc->infoStopLine; i < s_max( L_frame, L_frameTCX ); i++ )
3048 : {
3049 87653264 : spectrum_fx[i] = 0;
3050 87653264 : move32();
3051 : }
3052 : }
3053 : ELSE
3054 : {
3055 14081360 : FOR( i = noiseFillingBorder; i < s_max( L_frame, L_frameTCX ); i++ )
3056 : {
3057 13812000 : spectrum_fx[i] = 0;
3058 13812000 : move32();
3059 : }
3060 : }
3061 :
3062 : /*-----------------------------------------------------------*
3063 : * Quantization *
3064 : *-----------------------------------------------------------*/
3065 :
3066 861441 : IF( !hTcxEnc->tcx_lpc_shaped_ari )
3067 : {
3068 : /* context based arithmetic coder */
3069 :
3070 : /* initialize signaling to default, i.e. context based AC is inactive */
3071 843946 : prm_hm[0] = 0;
3072 843946 : move16();
3073 843946 : prm_hm[1] = -1;
3074 843946 : move16();
3075 :
3076 : /* Fast estimation of the scalar quantizer step size */
3077 843946 : test();
3078 843946 : IF( st->hTcxCfg->ctx_hm && ( st->last_core != ACELP_CORE ) )
3079 180593 : {
3080 180593 : LtpPitchLag = -1;
3081 180593 : move16();
3082 :
3083 180593 : test();
3084 180593 : IF( ( st->tcxonly == 0 ) && ( LT_16( hTcxEnc->tcxltp_pitch_int, st->L_frame ) ) )
3085 : {
3086 50203 : tmp32 = L_shl( L_mult0( st->L_frame, st->pit_res_max ), 1 + kLtpHmFractionalResolution + 1 );
3087 50203 : tmp1 = add( imult1616( hTcxEnc->tcxltp_pitch_int, st->pit_res_max ), hTcxEnc->tcxltp_pitch_fr );
3088 50203 : LtpPitchLag = div_l( tmp32, tmp1 );
3089 : }
3090 :
3091 180593 : ctxHmBits = add( ctxHmBits, 1 ); /* ContextHM flag */
3092 180593 : sqTargetBits = sub( sqTargetBits, 1 ); /* ContextHM flag */
3093 :
3094 : Word16 LtpGain;
3095 180593 : IF( hTcxEnc->tcxltp )
3096 : {
3097 107580 : LtpGain = hTcxEnc->tcxltp_gain;
3098 : }
3099 : ELSE
3100 : {
3101 73013 : LtpGain = -MAX_16;
3102 : }
3103 180593 : move16();
3104 180593 : PeriodicityIndex = SearchPeriodicityIndex_fx( spectrum_fx, NULL, L_spec, sqTargetBits, LtpPitchLag, LtpGain, &RelativeScore_fx );
3105 :
3106 180593 : NumIndexBits = CountIndexBits( (Word16) GE_16( L_spec, (Word16) 256 ), PeriodicityIndex );
3107 :
3108 180593 : IF( st->element_mode > EVS_MONO )
3109 : {
3110 180593 : ConfigureContextHm( L_spec, sub( sqTargetBits, NumIndexBits ), PeriodicityIndex, LtpPitchLag, hm_cfg );
3111 : }
3112 : ELSE
3113 : {
3114 0 : ConfigureContextHm( L_spec, sqTargetBits, PeriodicityIndex, LtpPitchLag, hm_cfg );
3115 : }
3116 :
3117 : /* Quantize original spectrum */
3118 180593 : sqGain_fx = SQ_gain_ivas_fx( spectrum_fx, *spectrum_e, ( mult( hTcxEnc->tcx_target_bits_fac, shl( sqTargetBits, 1 ) ) ), L_spec, &sqGain_e );
3119 :
3120 180593 : tcx_scalar_quantization_ivas_fx( spectrum_fx, *spectrum_e, sqQ, L_spec, sqGain_fx, sqGain_e, st->hTcxCfg->sq_rounding, hTcxEnc->memQuantZeros, st->tcxonly );
3121 :
3122 : /* Estimate original bitrate */
3123 180593 : stop = 0;
3124 180593 : move16();
3125 180593 : IF( st->element_mode > EVS_MONO )
3126 : {
3127 180593 : sqBits = RCcontextMapping_encode2_estimate_no_mem_s17_LCS_fx( sqQ, L_spec, &lastnz, &nEncoded, sqTargetBits, &stop, 0, NULL );
3128 : }
3129 : ELSE
3130 : {
3131 0 : sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, &lastnz, &nEncoded, sqTargetBits, &stop, NULL );
3132 : }
3133 :
3134 : /* Estimate context mapped bitrate */
3135 180593 : stopCtxHm = 0;
3136 180593 : move16();
3137 :
3138 : /* Context Mapping */
3139 180593 : IF( st->element_mode > EVS_MONO )
3140 : {
3141 180593 : sqBitsCtxHm = RCcontextMapping_encode2_estimate_no_mem_s17_LCS_fx( sqQ, L_spec, &lastnzCtxHm, &nEncodedCtxHm, sqTargetBits - NumIndexBits, &stopCtxHm, 0, hm_cfg );
3142 : }
3143 : ELSE
3144 : {
3145 0 : sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, &lastnzCtxHm, &nEncodedCtxHm, sqTargetBits - NumIndexBits, &stopCtxHm, hm_cfg );
3146 : }
3147 :
3148 : /* Decide whether or not to use context mapping */
3149 180593 : Selector = sub( s_max( stop, sqBits ), ( add( s_max( stopCtxHm, sqBitsCtxHm ), NumIndexBits ) ) );
3150 :
3151 180593 : test();
3152 180593 : test();
3153 180593 : IF( GT_16( Selector, 2 ) || ( LE_16( abs_s( Selector ), 2 ) && LT_16( kCtxHmOlRSThr, RelativeScore_fx ) ) )
3154 : {
3155 : /* CtxHm is likely better */
3156 12381 : sqTargetBits = sub( sqTargetBits, NumIndexBits );
3157 12381 : ctxHmBits = add( ctxHmBits, NumIndexBits );
3158 12381 : prm_hm[0] = 1;
3159 12381 : move16();
3160 12381 : prm_hm[1] = PeriodicityIndex;
3161 12381 : move16();
3162 12381 : *prm_lastnz = lastnzCtxHm;
3163 12381 : move16();
3164 12381 : sqBits_noStop = sqBits = sqBitsCtxHm;
3165 12381 : move16();
3166 12381 : move16();
3167 12381 : nEncoded = nEncodedCtxHm;
3168 12381 : move16();
3169 12381 : stop = stopCtxHm;
3170 12381 : move16();
3171 : }
3172 : ELSE
3173 : {
3174 : /* Original is better or not much difference */
3175 168212 : prm_hm[0] = 0;
3176 168212 : move16();
3177 168212 : prm_hm[1] = PeriodicityIndex;
3178 168212 : move16();
3179 168212 : *prm_lastnz = lastnz;
3180 168212 : move16();
3181 168212 : PeriodicityIndex = -1;
3182 168212 : move16();
3183 :
3184 168212 : sqBits_noStop = sqBits;
3185 168212 : move16();
3186 : }
3187 :
3188 180593 : if ( stop != 0 )
3189 : {
3190 66650 : sqBits = stop;
3191 66650 : move16();
3192 : }
3193 : }
3194 : ELSE
3195 : {
3196 : /* no context hm*/
3197 663353 : PeriodicityIndex = -1;
3198 663353 : move16();
3199 :
3200 663353 : IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) )
3201 : {
3202 623603 : sqGain_fx = SQ_gain_estimate_fx( spectrum_fx, *spectrum_e, shl( mult( hTcxEnc->tcx_target_bits_fac, sqTargetBits ), 1 ), L_spec, &sqGain_e );
3203 : }
3204 : ELSE
3205 : {
3206 39750 : sqGain_fx = SQ_gain_ivas_fx( spectrum_fx, *spectrum_e, shl( mult( hTcxEnc->tcx_target_bits_fac, sqTargetBits ), 1 ), L_spec, &sqGain_e );
3207 : }
3208 : /* Quantize spectrum */
3209 663353 : tcx_scalar_quantization_ivas_fx( spectrum_fx, *spectrum_e, sqQ, L_spec, sqGain_fx, sqGain_e, st->hTcxCfg->sq_rounding, hTcxEnc->memQuantZeros, st->tcxonly );
3210 :
3211 : /* Estimate bitrate */
3212 663353 : stop = 0;
3213 663353 : move16();
3214 :
3215 663353 : IF( st->element_mode > EVS_MONO )
3216 : {
3217 663353 : sqBits_noStop = sqBits = RCcontextMapping_encode2_estimate_no_mem_s17_LCS_fx( sqQ, L_spec, prm_lastnz, &nEncoded, sqTargetBits, &stop, 0, NULL );
3218 663353 : move16();
3219 : }
3220 : ELSE
3221 : {
3222 0 : sqBits_noStop = sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, prm_lastnz, &nEncoded, sqTargetBits, &stop, NULL );
3223 0 : move16();
3224 : }
3225 :
3226 663353 : if ( stop != 0 )
3227 : {
3228 345812 : sqBits = stop;
3229 345812 : move16();
3230 : }
3231 : } /* end of if (ctx_hm) */
3232 :
3233 : /* Adjust correction factor */
3234 843946 : tmp1 = sqBits;
3235 843946 : move16();
3236 :
3237 843946 : if ( s_and( L_spec, sub( L_spec, 1 ) ) == 0 ) /* power-of-2 */
3238 : {
3239 0 : tmp1 = add( tmp1, 1 );
3240 : }
3241 :
3242 843946 : tmp1 = BASOP_Util_Divide1616_Scale( sqTargetBits, tmp1, &tmp2 );
3243 : BASOP_SATURATE_WARNING_OFF_EVS
3244 843946 : hTcxEnc->tcx_target_bits_fac = shl_o( mult( hTcxEnc->tcx_target_bits_fac, tmp1 ), tmp2, &Overflow );
3245 : BASOP_SATURATE_WARNING_ON_EVS
3246 :
3247 843946 : if ( GT_16( hTcxEnc->tcx_target_bits_fac, 20480 /*1.25 in Q14*/ ) )
3248 : {
3249 83210 : hTcxEnc->tcx_target_bits_fac = 20480;
3250 83210 : move16();
3251 : }
3252 843946 : if ( LT_16( hTcxEnc->tcx_target_bits_fac, 12288 /*.75 in Q14*/ ) )
3253 : {
3254 56003 : hTcxEnc->tcx_target_bits_fac = 12288;
3255 56003 : move16();
3256 : }
3257 :
3258 : /* Refine quantizer step size with a rate-control-loop (optional) */
3259 843946 : phm_cfg = NULL;
3260 843946 : move16();
3261 843946 : if ( PeriodicityIndex >= 0 )
3262 : {
3263 12381 : phm_cfg = hm_cfg;
3264 12381 : move16();
3265 : }
3266 :
3267 843946 : max_iter = 4;
3268 843946 : move16();
3269 843946 : if ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) )
3270 : {
3271 623603 : max_iter = 2;
3272 623603 : move16();
3273 : }
3274 843946 : sqBits = tcx_scalar_quantization_rateloop_ivas_fx( spectrum_fx, *spectrum_e, sqQ, L_spec, &sqGain_fx, &sqGain_e, st->hTcxCfg->sq_rounding, hTcxEnc->memQuantZeros, prm_lastnz, /* lastnz */ sqTargetBits, &nEncoded, &stop, sqBits_noStop, sqBits, st->hTcxCfg->tcxRateLoopOpt, st->tcxonly, phm_cfg, max_iter, st->element_mode );
3275 :
3276 843946 : IF( ctxHmBits > 0 )
3277 : {
3278 : /* Mapping tool is enabled */
3279 : /* Truncate spectrum */
3280 180593 : FOR( i = nEncoded; i < L_spec; i++ )
3281 : {
3282 179155 : IF( st->element_mode > EVS_MONO )
3283 : {
3284 179155 : break;
3285 : }
3286 : ELSE
3287 : {
3288 0 : sqQ[i] = 0;
3289 0 : move16();
3290 : }
3291 : }
3292 :
3293 180593 : IF( PeriodicityIndex >= 0 )
3294 : {
3295 : /* Mapping is used */
3296 : /* Estimate non-mapped bitrate */
3297 12381 : stopCtxHm = 1;
3298 12381 : move16();
3299 12381 : IF( st->element_mode > EVS_MONO )
3300 : {
3301 : /* Fix: Use updated value for target bits (sqTargetBits + NumIndexBits) before computing non-mapped estimate */
3302 12381 : sqBitsCtxHm = RCcontextMapping_encode2_estimate_no_mem_s17_LCS_fx( sqQ, L_spec, &lastnz, &nEncodedCtxHm, sqTargetBits + NumIndexBits, &stopCtxHm, 0, NULL );
3303 : }
3304 : ELSE
3305 : {
3306 0 : sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, &lastnz, &nEncodedCtxHm, sqTargetBits, &stopCtxHm, NULL );
3307 : }
3308 :
3309 : /* Decide whether or not to revert mapping */
3310 12381 : Selector = sub( sqBits, add( sqBitsCtxHm, NumIndexBits ) );
3311 :
3312 12381 : IF( st->element_mode > EVS_MONO )
3313 : {
3314 12381 : test();
3315 12381 : test();
3316 12381 : IF( ( stopCtxHm == 0 && Selector > 0 ) || stop ) /* If overflow occured with mapped, select non-mapped */
3317 : {
3318 : /* Non-mapped is better */
3319 475 : sqTargetBits = add( sqTargetBits, NumIndexBits );
3320 475 : ctxHmBits = sub( ctxHmBits, NumIndexBits );
3321 475 : prm_hm[0] = 0;
3322 475 : move16();
3323 475 : *prm_lastnz = lastnz;
3324 475 : move16();
3325 475 : PeriodicityIndex = -1;
3326 475 : move16();
3327 475 : sqBits_noStop = sqBits = sqBitsCtxHm;
3328 475 : move16();
3329 475 : move16();
3330 475 : nEncoded = nEncodedCtxHm;
3331 475 : move16();
3332 475 : stop = stopCtxHm;
3333 475 : move16();
3334 : }
3335 : }
3336 : ELSE
3337 : {
3338 0 : test();
3339 0 : IF( stopCtxHm == 0 && Selector > 0 )
3340 : {
3341 : /* Non-mapped is better */
3342 0 : sqTargetBits = add( sqTargetBits, NumIndexBits );
3343 0 : ctxHmBits = sub( ctxHmBits, NumIndexBits );
3344 0 : prm_hm[0] = 0;
3345 0 : move16();
3346 0 : *prm_lastnz = lastnz;
3347 0 : move16();
3348 0 : PeriodicityIndex = -1;
3349 0 : move16();
3350 0 : sqBits_noStop = sqBits = sqBitsCtxHm;
3351 0 : move16();
3352 0 : move16();
3353 0 : nEncoded = nEncodedCtxHm;
3354 0 : move16();
3355 0 : stop = stopCtxHm;
3356 0 : move16();
3357 : }
3358 : }
3359 : }
3360 : ELSE
3361 : {
3362 : /* Mapping is not used */
3363 168212 : IF( st->element_mode > EVS_MONO )
3364 : {
3365 : /* Truncate Spectrum */
3366 87615204 : FOR( i = nEncoded; i < L_spec; i++ )
3367 : {
3368 87446992 : sqQ[i] = 0;
3369 87446992 : move16();
3370 : }
3371 : }
3372 : /* Estimate mapped bitrate */
3373 168212 : stopCtxHm = 1;
3374 168212 : move16();
3375 168212 : IF( st->element_mode > EVS_MONO )
3376 : {
3377 168212 : sqBitsCtxHm = RCcontextMapping_encode2_estimate_no_mem_s17_LCS_fx( sqQ, L_spec, &lastnzCtxHm, &nEncodedCtxHm, sqTargetBits - NumIndexBits, &stopCtxHm, 0, hm_cfg );
3378 : }
3379 : ELSE
3380 : {
3381 0 : sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, &lastnzCtxHm, &nEncodedCtxHm, sqTargetBits - NumIndexBits, &stopCtxHm, hm_cfg );
3382 : }
3383 :
3384 : /* Decide whether or not to use mapping */
3385 168212 : Selector = sub( sqBits, add( sqBitsCtxHm, NumIndexBits ) );
3386 168212 : test();
3387 168212 : IF( stopCtxHm == 0 && Selector > 0 )
3388 : {
3389 : /* Mapped is better */
3390 710 : sqTargetBits = sub( sqTargetBits, NumIndexBits );
3391 710 : ctxHmBits = add( ctxHmBits, NumIndexBits );
3392 710 : prm_hm[0] = 1;
3393 710 : move16();
3394 710 : *prm_lastnz = lastnzCtxHm;
3395 710 : move16();
3396 710 : PeriodicityIndex = prm_hm[1];
3397 710 : move16();
3398 710 : sqBits_noStop = sqBits = sqBitsCtxHm;
3399 710 : move16();
3400 710 : move16();
3401 710 : nEncoded = nEncodedCtxHm;
3402 710 : move16();
3403 710 : stop = stopCtxHm;
3404 710 : move16();
3405 : }
3406 : }
3407 : }
3408 :
3409 : /* Limit low sqGain for avoiding saturation of the gain quantizer*/
3410 : /*(float) sqrt( (float) NORM_MDCT_FACTOR / (float) L_spec ) in Q14 */
3411 843946 : SWITCH( L_spec )
3412 : {
3413 0 : case 80:
3414 0 : minSqGain = 23170;
3415 0 : BREAK;
3416 0 : case 100:
3417 0 : minSqGain = 20724;
3418 0 : BREAK;
3419 2140 : case 160:
3420 2140 : minSqGain = 16384;
3421 2140 : BREAK;
3422 0 : case 200:
3423 0 : minSqGain = 14654;
3424 0 : BREAK;
3425 0 : case 240:
3426 0 : minSqGain = 13377;
3427 0 : BREAK;
3428 0 : case 300:
3429 0 : minSqGain = 11965;
3430 0 : BREAK;
3431 69557 : case 320:
3432 69557 : minSqGain = 11585;
3433 69557 : BREAK;
3434 415 : case 400:
3435 415 : minSqGain = 10362;
3436 415 : BREAK;
3437 21982 : case 480:
3438 21982 : minSqGain = 9459;
3439 21982 : BREAK;
3440 0 : case 600:
3441 0 : minSqGain = 8461;
3442 0 : BREAK;
3443 207815 : case 640:
3444 207815 : minSqGain = 8192;
3445 207815 : BREAK;
3446 3145 : case 800:
3447 3145 : minSqGain = 7327;
3448 3145 : BREAK;
3449 534884 : case 960:
3450 534884 : minSqGain = 6689;
3451 534884 : BREAK;
3452 4008 : case 1200:
3453 4008 : minSqGain = 5983;
3454 4008 : BREAK;
3455 0 : case 1440:
3456 0 : minSqGain = 5461;
3457 0 : BREAK;
3458 0 : case 1800:
3459 0 : minSqGain = 4885;
3460 0 : BREAK;
3461 0 : case 2048:
3462 0 : minSqGain = 4579;
3463 0 : BREAK;
3464 0 : default:
3465 0 : assert( 0 );
3466 : }
3467 843946 : move16();
3468 843946 : Word16 shift_tmp = s_max( sqGain_e, 1 );
3469 843946 : test();
3470 843946 : IF( LT_16( st->hTcxCfg->tcxRateLoopOpt, 3 ) && LT_16( shl( sqGain_fx, sub( sqGain_e, shift_tmp ) ), shl( minSqGain, sub( 1, shift_tmp ) ) ) )
3471 : {
3472 5003 : sqGain_fx = minSqGain;
3473 5003 : move16();
3474 5003 : sqGain_e = 1;
3475 5003 : move16();
3476 :
3477 5003 : tcx_scalar_quantization_ivas_fx( spectrum_fx, *spectrum_e, sqQ, L_spec, sqGain_fx, sqGain_e, st->hTcxCfg->sq_rounding, hTcxEnc->memQuantZeros, st->tcxonly );
3478 5003 : stop = 1;
3479 5003 : IF( st->element_mode > EVS_MONO )
3480 : {
3481 : /* Ensure non-mapped estimation is used for limiting low sqGain considering that this refinement occurs very rarely */
3482 5003 : PeriodicityIndex = -1;
3483 5003 : move16();
3484 5003 : IF( prm_hm[0] == 1 )
3485 : {
3486 0 : prm_hm[0] = 0;
3487 0 : move16();
3488 0 : sqTargetBits = add( sqTargetBits, NumIndexBits );
3489 0 : ctxHmBits = sub( ctxHmBits, NumIndexBits );
3490 : }
3491 5003 : sqBits = RCcontextMapping_encode2_estimate_no_mem_s17_LCS_fx( sqQ, L_spec, prm_lastnz, &nEncoded, sqTargetBits, &stop, 0, NULL );
3492 : }
3493 : ELSE
3494 : {
3495 0 : sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, prm_lastnz, &nEncoded, sqTargetBits, &stop, PeriodicityIndex >= 0 ? hm_cfg : NULL );
3496 : }
3497 : }
3498 :
3499 : /* Truncate spectrum (for CBR) */
3500 843946 : IF( stop )
3501 : {
3502 61823782 : FOR( i = nEncoded; i < L_spec; i++ )
3503 : {
3504 61702698 : sqQ[i] = 0;
3505 61702698 : move16();
3506 : }
3507 : }
3508 :
3509 : /* Save quantized Values */
3510 843946 : *nf_seed = 0;
3511 843946 : move16();
3512 687977786 : FOR( i = 0; i < L_spec; i++ )
3513 : {
3514 687133840 : spectrum_fx[i] = (Word32) sqQ[i];
3515 687133840 : move32();
3516 : /* noise filling seed */
3517 687133840 : *nf_seed = (Word16) L_add( *nf_seed, L_mult0( abs_s( sqQ[i] ), shl( i, 1 ) ) );
3518 687133840 : move16();
3519 : }
3520 :
3521 843946 : tmp32 = L_deposit_l( 0 );
3522 687977786 : FOR( i = 0; i < L_spec; i++ )
3523 : {
3524 687133840 : spectrum_fx[i] = L_mult( sqQ[i], 1 << ( 30 - SPEC_EXP_DEC ) );
3525 687133840 : move32();
3526 : /* noise filling seed */
3527 687133840 : tmp32 = L_macNs_co( tmp32, abs_s( sqQ[i] ), i, &Carry, &Overflow );
3528 : }
3529 843946 : *spectrum_e = SPEC_EXP_DEC;
3530 843946 : move16();
3531 :
3532 843946 : *nf_seed = extract_l( tmp32 );
3533 : }
3534 : ELSE
3535 : {
3536 : /* low rates: envelope based arithmetic coder */
3537 :
3538 17495 : AdaptLowFreqEmph_fx( spectrum_fx, *spectrum_e, NULL, 0, 0, 1, gainlpc_fx, gainlpc_e, L_frame );
3539 :
3540 17495 : prm_target = sqQ;
3541 17495 : sqQ = prm_target + 1;
3542 :
3543 17495 : LtpPitchLag = -1;
3544 17495 : move16();
3545 :
3546 17495 : IF( LT_16( hTcxEnc->tcxltp_pitch_int, st->L_frame ) )
3547 : {
3548 7680 : tmp32 = L_shl( L_mult0( st->L_frame, st->pit_res_max ), 1 + kLtpHmFractionalResolution + 1 );
3549 7680 : tmp1 = add( imult1616( hTcxEnc->tcxltp_pitch_int, st->pit_res_max ), hTcxEnc->tcxltp_pitch_fr );
3550 7680 : LtpPitchLag = div_l( tmp32, tmp1 );
3551 : }
3552 :
3553 17495 : Word8 tmp8 = 1;
3554 17495 : move16();
3555 17495 : if ( st->last_core == ACELP_CORE )
3556 : {
3557 1646 : tmp8 = 0;
3558 1646 : move16();
3559 : }
3560 17495 : Word16 low_complexiety = 0;
3561 17495 : move16();
3562 17495 : if ( GT_16( st->bwidth, WB ) )
3563 : {
3564 16193 : low_complexiety = 1;
3565 16193 : move16();
3566 : }
3567 17495 : tcx_arith_encode_envelope_ivas_fx( spectrum_fx, spectrum_e, hm_cfg->indexBuffer, L_frame, L_spec, st, Aqind, sqTargetBits, sqQ, tmp8, prm_hm, /* HM parameter area */ LtpPitchLag, &sqBits, &signaling_bits, low_complexiety );
3568 :
3569 17495 : sqTargetBits = sub( sqTargetBits, signaling_bits );
3570 17495 : *prm_target = sqTargetBits;
3571 17495 : move16();
3572 :
3573 : /* Noise filling seed */
3574 17495 : Word64 seed = 0;
3575 17495 : move64();
3576 3659347 : FOR( i = 0; i < noiseFillingBorder; ++i )
3577 : {
3578 : /* *nf_seed += (int16_t) ( abs( (int16_t) spectrum[i] ) * i * 2 ); */
3579 3641852 : seed = W_mac_32_32( seed, L_abs( spectrum_fx[i] ), i ); // exp: spectrum_e
3580 : }
3581 17495 : *nf_seed = extract_l( W_extract_l( W_shr( seed, sub( 31, *spectrum_e ) ) ) ); // Q0
3582 17495 : move16();
3583 : }
3584 :
3585 861441 : *hm_active = prm_hm[0];
3586 861441 : move16();
3587 :
3588 : /*-----------------------------------------------------------*
3589 : * Compute optimal TCX gain. *
3590 : *-----------------------------------------------------------*/
3591 :
3592 861441 : IF( lf_deemph_fact_fx != NULL )
3593 : {
3594 : /* initialize LF deemphasis factors in lf_deemph_fact */
3595 198886318 : FOR( i = 0; i < L_spec; i++ )
3596 : {
3597 198648480 : lf_deemph_fact_fx[i] = ONE_IN_Q14;
3598 198648480 : move16();
3599 : }
3600 : }
3601 :
3602 861441 : IF( !st->tcxonly )
3603 : {
3604 128905 : AdaptLowFreqDeemph( spectrum_fx, *spectrum_e, hTcxEnc->tcx_lpc_shaped_ari, gainlpc_fx, gainlpc_e, L_frame, lf_deemph_fact_fx );
3605 : }
3606 :
3607 861441 : assert( x_orig_fx != spectrum_fx );
3608 :
3609 861441 : tcx_get_gain( x_orig_fx, x_orig_e, spectrum_fx, *spectrum_e, L_spec, &gain_tcx_opt_fx, &gain_tcx_opt_e, ener_fx, ener_e );
3610 :
3611 861441 : IF( gain_tcx_opt_fx <= 0 )
3612 : {
3613 2289 : gain_tcx_opt_fx = sqGain_fx;
3614 2289 : move16();
3615 2289 : gain_tcx_opt_e = sqGain_e;
3616 2289 : move16();
3617 : }
3618 861441 : *gain_tcx_fx = gain_tcx_opt_fx;
3619 861441 : move16();
3620 861441 : *gain_tcx_e = gain_tcx_opt_e;
3621 861441 : move16();
3622 :
3623 861441 : test();
3624 861441 : IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) )
3625 : {
3626 14576 : calculate_hangover_attenuation_gain_ivas_fx( st, &att_fx, vad_hover_flag );
3627 14576 : *gain_tcx_fx = mult( *gain_tcx_fx, att_fx );
3628 14576 : move16();
3629 : }
3630 :
3631 : /*-----------------------------------------------------------*
3632 : * Quantize TCX gain *
3633 : *-----------------------------------------------------------*/
3634 :
3635 : /* gain quantization here in case of VBR unvoiced coding; fixes problems of uninitialized global gain values */
3636 861441 : test();
3637 861441 : IF( GE_32( total_brate, ACELP_13k20 ) && st->rf_mode == 0 )
3638 : {
3639 828195 : QuantizeGain( L_spec, gain_tcx_fx, gain_tcx_e, &prm[0] );
3640 : }
3641 :
3642 : /*-----------------------------------------------------------*
3643 : * Residual Quantization *
3644 : *-----------------------------------------------------------*/
3645 :
3646 861441 : IF( st->hTcxCfg->resq )
3647 : {
3648 390356 : resQTargetBits = sub( sqTargetBits, sqBits );
3649 :
3650 390356 : IF( hTcxEnc->tcx_lpc_shaped_ari )
3651 : {
3652 : /* envelope based arithmetic coder */
3653 : Word16 *prm_resq;
3654 :
3655 17495 : prm_resq = sqQ + sub( sqTargetBits, resQTargetBits );
3656 :
3657 17495 : resQBits = tcx_ari_res_Q_spec_ivas_fx( x_orig_fx, x_orig_e, hm_cfg->indexBuffer, spectrum_fx, *spectrum_e, L_spec, *gain_tcx_fx, *gain_tcx_e, prm_resq, resQTargetBits, resQBits, st->hTcxCfg->sq_rounding, lf_deemph_fact_fx );
3658 :
3659 : /* Transmit zeros when there bits remain after RESQ */
3660 18717 : FOR( i = resQBits; i < resQTargetBits; ++i )
3661 : {
3662 1222 : prm_resq[i] = 0;
3663 1222 : move16();
3664 : }
3665 : }
3666 : ELSE
3667 : {
3668 : /* context based arithmetic coder */
3669 372861 : resQBits = tcx_res_Q_gain_fx( gain_tcx_opt_fx, gain_tcx_opt_e, gain_tcx_fx, gain_tcx_e, sqQ + L_spec, resQTargetBits );
3670 372861 : IF( st->tcxonly )
3671 : {
3672 261451 : resQBits = tcx_res_Q_spec_ivas_fx( x_orig_fx, x_orig_e, spectrum_fx, *spectrum_e, L_spec, *gain_tcx_fx, *gain_tcx_e, sqQ + L_spec, resQTargetBits, resQBits, st->hTcxCfg->sq_rounding, NULL );
3673 : }
3674 : ELSE
3675 : {
3676 111410 : resQBits = tcx_res_Q_spec_ivas_fx( x_orig_fx, x_orig_e, spectrum_fx, *spectrum_e, L_spec, *gain_tcx_fx, *gain_tcx_e, sqQ + L_spec, resQTargetBits, resQBits, st->hTcxCfg->sq_rounding, lf_deemph_fact_fx );
3677 : }
3678 : }
3679 : }
3680 :
3681 861441 : tmp1 = norm_s( *gain_tcx_fx );
3682 861441 : *gain_tcx_fx = shl( *gain_tcx_fx, tmp1 );
3683 861441 : move16();
3684 861441 : *gain_tcx_e = sub( *gain_tcx_e, tmp1 );
3685 861441 : move16();
3686 :
3687 : /*-----------------------------------------------------------*
3688 : * ALFE tcx only bitrates *
3689 : *-----------------------------------------------------------*/
3690 :
3691 861441 : IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) )
3692 : {
3693 237838 : IF( st->tcxonly )
3694 : {
3695 108933 : test();
3696 108933 : test();
3697 108933 : IF( hTcxEnc->tcxltp && ( hTcxEnc->tcxltp_gain > 0 ) && !hTcxEnc->fUseTns[frame_cnt] )
3698 : {
3699 3726 : PsychAdaptLowFreqDeemph( spectrum_fx, gainlpc_fx, gainlpc_e, NULL );
3700 : }
3701 : }
3702 : }
3703 :
3704 861441 : return;
3705 : }
3706 :
3707 662 : void coder_tcx_fx(
3708 : Word16 n,
3709 : TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
3710 : Word16 A[], /* input: quantized coefficients NxAz_q[M+1] */
3711 : Word16 Aqind[], /* input: frame-independent quantized coefficients (M+1) */
3712 : Word16 synth[], /*Qx*/
3713 : Word16 L_frame_glob, /* input: frame length */
3714 : Word16 L_frameTCX_glob,
3715 : Word16 L_spec,
3716 : Word16 nb_bits, /*input: bit budget*/
3717 : Word8 tcxonly, /*input: only TCX flag*/
3718 : Word32 spectrum[], /* i/o: MDCT spectrum Q(31-spectrum_e)*/
3719 : Word16 *spectrum_e, /* i/o: MDCT spectrum exponent */
3720 : Word16 prm[], /* output: tcx parameters */
3721 : Encoder_State *st,
3722 : CONTEXT_HM_CONFIG *hm_cfg )
3723 : {
3724 : Word16 L_frame;
3725 : Word16 left_overlap, right_overlap;
3726 : Word16 tnsSize; /* number of tns parameters put into prm */
3727 : Word16 tnsBits; /* number of tns bits in the frame */
3728 : Word16 ltpBits;
3729 : Word16 gainlpc[FDNS_NPTS], gainlpc_e[FDNS_NPTS];
3730 : Word16 win[N_MAX + L_MDCT_OVLP_MAX];
3731 : Word32 powerSpec[N_MAX];
3732 : Word16 powerSpec_e;
3733 : Word16 winMDST[N_MAX + L_MDCT_OVLP_MAX];
3734 : Word16 *pWinMDST;
3735 : Word16 left_overlap_mode, right_overlap_mode;
3736 662 : TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
3737 :
3738 662 : left_overlap = right_overlap = -1;
3739 662 : move16();
3740 662 : move16();
3741 662 : tnsSize = 0;
3742 662 : move16();
3743 662 : tnsBits = 0;
3744 662 : move16();
3745 662 : ltpBits = 0;
3746 662 : move16();
3747 :
3748 662 : L_frame = L_frameTCX_glob;
3749 662 : move16();
3750 :
3751 : /*-----------------------------------------------------------*
3752 : * Windowing *
3753 : *-----------------------------------------------------------*/
3754 662 : IF( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) )
3755 : {
3756 :
3757 39 : WindowSignal( hTcxCfg, hTcxCfg->tcx_offsetFB, hTcxCfg->tcx_last_overlap_mode, hTcxCfg->tcx_curr_overlap_mode, &left_overlap, &right_overlap,
3758 39 : hTcxEnc->speech_TCX, &L_frame, win, 1, 1 );
3759 :
3760 : /*-----------------------------------------------------------*
3761 : * Compute MDCT *
3762 : *-----------------------------------------------------------*/
3763 :
3764 39 : *spectrum_e = 16;
3765 39 : move16();
3766 39 : TCX_MDCT( win, spectrum, spectrum_e, left_overlap, sub( L_frame, shr( add( left_overlap, right_overlap ), 1 ) ), right_overlap, st->element_mode );
3767 : }
3768 : ELSE
3769 : {
3770 : Word32 tmp_buf[L_FRAME_PLUS];
3771 : Word16 Q, tmp1, tmp2, i;
3772 :
3773 623 : Q = 0;
3774 623 : move16();
3775 :
3776 623 : wtda_fx( hTcxEnc->new_speech_TCX, &Q, tmp_buf, NULL, NULL, hTcxCfg->tcx_last_overlap_mode, hTcxCfg->tcx_curr_overlap_mode, L_frame );
3777 :
3778 623 : left_overlap_mode = hTcxCfg->tcx_last_overlap_mode;
3779 623 : move16();
3780 623 : if ( EQ_16( left_overlap_mode, ALDO_WINDOW ) )
3781 : {
3782 615 : left_overlap_mode = FULL_OVERLAP;
3783 615 : move16();
3784 : }
3785 623 : right_overlap_mode = hTcxCfg->tcx_curr_overlap_mode;
3786 623 : move16();
3787 623 : if ( EQ_16( right_overlap_mode, ALDO_WINDOW ) )
3788 : {
3789 613 : right_overlap_mode = FULL_OVERLAP;
3790 613 : move16();
3791 : }
3792 :
3793 623 : WindowSignal( hTcxCfg, hTcxCfg->tcx_offsetFB, left_overlap_mode, right_overlap_mode, &left_overlap, &right_overlap, hTcxEnc->speech_TCX, &L_frame, winMDST, 1, 1 );
3794 :
3795 : /* scale by NORM_MDCT_FACTOR / L */
3796 623 : tmp1 = mult_r( shl( L_frame, 4 ), 26214 /*128.f / NORM_MDCT_FACTOR Q15*/ ); /* 4Q11 */
3797 623 : tmp2 = 4;
3798 623 : move16();
3799 623 : tmp1 = ISqrt16( tmp1, &tmp2 );
3800 :
3801 519663 : FOR( i = 0; i < L_frame; i++ )
3802 : {
3803 519040 : tmp_buf[i] = Mpy_32_16_1( tmp_buf[i], tmp1 );
3804 519040 : move32();
3805 : }
3806 623 : Q = sub( Q, tmp2 );
3807 :
3808 : /* DCT */
3809 623 : edct_fx( tmp_buf, spectrum, L_frame, &Q );
3810 623 : *spectrum_e = sub( 31, Q );
3811 623 : move16();
3812 : }
3813 :
3814 :
3815 : /*-----------------------------------------------------------*
3816 : * Attenuate upper end of NB spectrum, *
3817 : * to simulate ACELP behavior *
3818 : *-----------------------------------------------------------*/
3819 :
3820 662 : IF( st->narrowBand != 0 )
3821 : {
3822 0 : attenuateNbSpectrum_fx( L_frame, spectrum );
3823 : }
3824 :
3825 : /*-----------------------------------------------------------*
3826 : * Compute noise-measure flags for spectrum filling *
3827 : * and quantization (0: tonal, 1: noise-like). *
3828 : * Detect low pass if present. *
3829 : *-----------------------------------------------------------*/
3830 :
3831 662 : pWinMDST = winMDST;
3832 662 : move16();
3833 662 : if ( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) )
3834 : {
3835 39 : pWinMDST = win;
3836 39 : move16();
3837 : }
3838 :
3839 662 : AnalyzePowerSpectrum_fx( st,
3840 662 : round_fx( L_shl( Mpy_32_16_1( L_mult0( L_frame, st->L_frame ) /*Q0*/,
3841 662 : getInvFrameLen( hTcxEnc->L_frameTCX ) /*Q21*/ ) /*Q6*/,
3842 : 16 - 6 ) ),
3843 : L_frame,
3844 : left_overlap, right_overlap,
3845 662 : spectrum, *spectrum_e,
3846 : pWinMDST,
3847 : powerSpec, &powerSpec_e );
3848 662 : IF( hTcxCfg->fIsTNSAllowed != 0 )
3849 : {
3850 :
3851 402 : SetTnsConfig( hTcxCfg, sub( L_frame_glob, st->L_frame ) == 0, st->last_core == 0 );
3852 :
3853 402 : TNSAnalysis_fx( hTcxCfg, L_frame, L_spec, TCX_20, st->last_core == 0, spectrum, hTcxEnc->tnsData, hTcxEnc->fUseTns, &st->hIGFEnc->tns_predictionGain );
3854 : }
3855 : ELSE
3856 : {
3857 260 : hTcxEnc->fUseTns[0] = hTcxEnc->fUseTns[1] = 0;
3858 260 : move16();
3859 260 : move16();
3860 : }
3861 :
3862 662 : IF( st->igf )
3863 : {
3864 662 : ProcessIGF_fx( st->hIGFEnc, st, spectrum, spectrum_e, powerSpec, &powerSpec_e, 1, hTcxEnc->fUseTns[0], ( st->last_core == ACELP_CORE ), 0 );
3865 : }
3866 :
3867 662 : ShapeSpectrum_fx( hTcxCfg, A, gainlpc, gainlpc_e,
3868 : L_frame_glob,
3869 : L_spec,
3870 : spectrum,
3871 662 : hTcxEnc->fUseTns[0],
3872 : st );
3873 662 : if ( st->igf )
3874 : {
3875 662 : nb_bits = sub( nb_bits, st->hIGFEnc->infoTotalBitsPerFrameWritten );
3876 : }
3877 662 : IF( hTcxCfg->fIsTNSAllowed != 0 )
3878 : {
3879 402 : EncodeTnsData_fx( hTcxCfg->pCurrentTnsConfig, hTcxEnc->tnsData, prm + 1 + NOISE_FILL_RANGES + LTPSIZE, &tnsSize, &tnsBits );
3880 : }
3881 :
3882 662 : QuantizeSpectrum_fx( hTcxCfg,
3883 : A,
3884 : Aqind,
3885 : gainlpc, gainlpc_e,
3886 : synth,
3887 : L_frame_glob,
3888 : L_frameTCX_glob,
3889 : L_spec,
3890 662 : sub( sub( nb_bits, tnsBits ), ltpBits ),
3891 : tcxonly,
3892 : spectrum, spectrum_e,
3893 662 : hTcxEnc->tnsData,
3894 662 : hTcxEnc->fUseTns[0],
3895 : tnsSize,
3896 : prm,
3897 : n,
3898 : st,
3899 : hm_cfg );
3900 662 : }
3901 :
3902 :
3903 : /*-------------------------------------------------------------------*
3904 : * coder_tcx_post_fx()
3905 : *
3906 : *
3907 : *-------------------------------------------------------------------*/
3908 :
3909 662 : void coder_tcx_post_fx(
3910 : Encoder_State *st,
3911 : LPD_state *LPDmem,
3912 : TCX_CONFIG_HANDLE hTcxCfg,
3913 : /* i : configuration of TCX */ Word16 *synth,
3914 : const Word16 *A,
3915 : const Word16 *Ai,
3916 : Word16 *wsig,
3917 : Word16 Q_new,
3918 : Word16 shift )
3919 : {
3920 : Word16 xn_buf[L_FRAME_MAX];
3921 :
3922 : /* TCX output */
3923 662 : Copy( synth, xn_buf, st->L_frame );
3924 :
3925 :
3926 : /*-----------------------------------------------------------*
3927 : * Memory update *
3928 : *-----------------------------------------------------------*/
3929 :
3930 : /* Update LPDmem (Txnq,syn,syn_pe,old_exc,wsyn,Ai,Aq) */
3931 662 : tcx_encoder_memory_update_fx( wsig, xn_buf, st->L_frame, Ai, A, hTcxCfg->preemph_fac, LPDmem, st, synth, Q_new, shift );
3932 :
3933 662 : return;
3934 : }
3935 235779 : void coder_tcx_post_ivas_fx(
3936 : Encoder_State *st,
3937 : LPD_state *LPDmem,
3938 : TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
3939 : Word16 *synth,
3940 : const Word16 *A,
3941 : const Word16 *Ai,
3942 : Word16 *wsig,
3943 : Word16 Q_new )
3944 : {
3945 : Word16 xn_buf[L_FRAME_MAX];
3946 :
3947 : /* TCX output */
3948 235779 : Copy( synth, xn_buf, st->L_frame );
3949 :
3950 :
3951 : /*-----------------------------------------------------------*
3952 : * Memory update *
3953 : *-----------------------------------------------------------*/
3954 :
3955 : /* Update LPDmem (Txnq,syn,syn_pe,old_exc,wsyn,Ai,Aq) */
3956 235779 : tcx_encoder_memory_update_ivas_fx( wsig, xn_buf, st->L_frame, Ai, A, hTcxCfg->preemph_fac, LPDmem, st, synth, Q_new );
3957 :
3958 235779 : return;
3959 : }
3960 :
3961 :
3962 : /*-------------------------------------------------------------------*
3963 : * InternalTCXDecoder_fx()
3964 : *
3965 : *
3966 : *-------------------------------------------------------------------*/
3967 :
3968 237838 : void InternalTCXDecoder_fx(
3969 : Encoder_State *st, /* i/o: state handle */
3970 : const Word16 frame_cnt, /* i : frame counter in the super_frame */
3971 : const Word16 L_frameTCX, /* i : full frame length */
3972 : const Word16 L_frame, /* i : frame length */
3973 : const Word16 L_spec, /* i : length of the coded spectrum */
3974 : const Word16 tcx_offset, /* i : folding point offset relative to the end of the previous frame */
3975 : const Word16 noiseFillingBorder, /* i : noise filling border */
3976 : const Word32 *x_quant_fx, /* i : quantized spectrum, exponent same as spectrum_e */
3977 : const Word32 ener_fx, /* i : energy of the quantized spectrum Q(31-ener_e) */
3978 : const Word16 ener_e, /* i : exponent of energy of the quantized spectrum */
3979 : Word16 lf_deemph_fact_fx[], /* i/o: low frequency deemphasis factors */
3980 : const Word16 fac_ns_fx, /* i : noise filling level, Q15 */
3981 : const Word16 nf_seed, /* i : noise filling random seed, Q0 */
3982 : const Word16 *A_fx, /* i : LPC representation of the FDNS gains, Q = 14 - norm_s(A_fx[0]) */
3983 : Word16 gainlpc_fx[], /* i/o: FDNS gains Q(15-gainlpc_e) */
3984 : Word16 gainlpc_e[], /* i/o: FDNS gains exponents */
3985 : const Word16 hm_active, /* i : flag indicating if the harmonic model is active */
3986 : Word16 gain_tcx_fx, /* i/o: global gain / quantized global gain Q(15-gain_tcx_e) */
3987 : Word16 *gain_tcx_e, /* i/o: global gain / quantized global gain exponent */
3988 : Word32 spectrum_fx[], /* o : dequantized spectrum Q(31-spectrum_e) */
3989 : Word16 *spectrum_e, /* o : exponent of dequantized spectrum */
3990 : Word16 synth[], /* o : time domain signal */
3991 : Word16 *gain_tcx_q /* o : quantized global gain (at low bitrates), Q0 */
3992 : )
3993 : {
3994 237838 : TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
3995 : Word16 i, iStart, noiseTransWidth;
3996 : Word16 tcx_last_overlap_mode, overlap;
3997 : Word16 nz; /* non-zero length in ALDO window*/
3998 : Word16 aldo; /* ALDO flag in current frame*/
3999 : Word16 tmp1, tmp2, tmp3, tmp4, s;
4000 : Word16 *tmpP16;
4001 : Word16 q_spec, len;
4002 : Word32 tmp32;
4003 : Word32 xn_buf32[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX];
4004 : Word16 Aq_old_fx[M + 1];
4005 : Word32 sns_interpolated_scalefactors_fx[FDNS_NPTS], A_fx32[M + 1];
4006 237838 : Word16 *xn_buf16 = (Word16 *) xn_buf32;
4007 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
4008 237838 : Flag Overflow = 0;
4009 237838 : move32();
4010 : #endif
4011 :
4012 237838 : Copy32( x_quant_fx, spectrum_fx, s_max( L_frame, L_spec ) );
4013 :
4014 : /* Replication of ACELP formant enhancement for low rates */
4015 237838 : test();
4016 237838 : IF( st->total_brate < ACELP_13k20 || st->rf_mode )
4017 : {
4018 33246 : tcxFormantEnhancement( lf_deemph_fact_fx, gainlpc_fx, gainlpc_e, spectrum_fx, spectrum_e, L_frame, L_spec );
4019 : }
4020 :
4021 : /*-----------------------------------------------------------*
4022 : * Noise Filling. *
4023 : *-----------------------------------------------------------*/
4024 :
4025 237838 : IF( fac_ns_fx > 0 )
4026 : {
4027 219199 : tmp1 = 0;
4028 219199 : move16();
4029 219199 : test();
4030 219199 : if ( GE_32( st->total_brate, ACELP_13k20 ) && st->rf_mode == 0 )
4031 : {
4032 186131 : tmp1 = 1;
4033 186131 : move16();
4034 : }
4035 219199 : iStart = tcxGetNoiseFillingTilt( A_fx, M, L_frame, tmp1, &hTcxEnc->noiseTiltFactor );
4036 :
4037 219199 : tmp1 = 0;
4038 219199 : move16();
4039 219199 : test();
4040 219199 : test();
4041 219199 : if ( st->hTcxCfg->ctx_hm && st->last_core != ACELP_CORE && hm_active )
4042 : {
4043 12551 : tmp1 = 1;
4044 12551 : move16();
4045 : }
4046 219199 : noiseTransWidth = GetTransWidth_ivas_fx( st->tcxonly, (Word16) EQ_16( L_frame, shr( st->L_frame, 1 ) ), hTcxEnc->tcxltp_gain, tmp1 );
4047 219199 : assert( st->element_mode != IVAS_CPE_MDCT );
4048 219199 : tcx_noise_filling( spectrum_fx, *spectrum_e, nf_seed, iStart, noiseFillingBorder, noiseTransWidth, L_frame, hTcxEnc->noiseTiltFactor, fac_ns_fx, NULL, st->element_mode );
4049 : }
4050 :
4051 237838 : test();
4052 237838 : IF( LT_32( st->total_brate, ACELP_13k20 ) || st->rf_mode != 0 )
4053 : {
4054 : /* partially recompute global gain (energy part), taking noise filling and formant enhancement into account */
4055 33246 : s = sub( getScaleFactor32( spectrum_fx, L_spec ), 4 );
4056 33246 : tmp32 = L_deposit_l( 1 );
4057 :
4058 21439406 : FOR( i = 0; i < L_spec; i++ )
4059 : {
4060 21406160 : tmp1 = round_fx( L_shl( spectrum_fx[i], s ) );
4061 21406160 : tmp32 = L_mac0( tmp32, tmp1, tmp1 );
4062 : }
4063 :
4064 33246 : tmp1 = BASOP_Util_Divide3232_Scale( ener_fx, tmp32, &tmp2 );
4065 33246 : tmp2 = add( tmp2, sub( ener_e, add( shl( sub( *spectrum_e, s ), 1 ), 1 ) ) );
4066 33246 : tmp1 = Sqrt16( tmp1, &tmp2 );
4067 :
4068 33246 : gain_tcx_fx = mult( gain_tcx_fx, tmp1 ); // Q(15-(gain_tcx_e+tmp2))
4069 33246 : *gain_tcx_e = add( *gain_tcx_e, tmp2 );
4070 33246 : move16();
4071 :
4072 33246 : QuantizeGain( L_spec, &gain_tcx_fx, gain_tcx_e, gain_tcx_q );
4073 : }
4074 :
4075 : /*end of noise filling*/
4076 :
4077 : /*-----------------------------------------------------------*
4078 : * Noise shaping in frequency domain (1/Wz) *
4079 : *-----------------------------------------------------------*/
4080 :
4081 237838 : IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) )
4082 : {
4083 0 : Copy_Scale_sig_16_32_DEPREC( A_fx, A_fx32, M + 1, add( norm_s( A_fx[0] ), 2 ) ); // Copying the Word16 A_fx buffer to a temporary Word32 buffer in Q16
4084 :
4085 0 : q_spec = sub( 31, *spectrum_e );
4086 0 : sns_interpolate_scalefactors_fx( sns_interpolated_scalefactors_fx, A_fx32, DEC );
4087 0 : sns_shape_spectrum_fx( spectrum_fx, &q_spec, st->hTcxCfg->psychParamsCurrent, sns_interpolated_scalefactors_fx, Q16, L_frame, &len );
4088 :
4089 0 : test();
4090 0 : test();
4091 0 : IF( NE_16( len, L_frame ) && LT_16( q_spec, sub( 31, *spectrum_e ) ) )
4092 : {
4093 0 : scale_sig32( spectrum_fx + len, sub( L_frame, len ), sub( q_spec, sub( 15, *spectrum_e ) ) ); // q_spec
4094 : }
4095 0 : ELSE IF( NE_16( len, L_frame ) && GT_16( q_spec, sub( 31, *spectrum_e ) ) )
4096 : {
4097 0 : scale_sig32( spectrum_fx, len, sub( sub( 15, *spectrum_e ), q_spec ) ); // Q(31-spectrum_e)
4098 0 : q_spec = sub( 31, *spectrum_e );
4099 : }
4100 0 : *spectrum_e = sub( 31, q_spec );
4101 0 : move16();
4102 : }
4103 : ELSE
4104 : {
4105 237838 : mdct_noiseShaping_ivas_fx( spectrum_fx, spectrum_e, L_frame, gainlpc_fx, gainlpc_e );
4106 : }
4107 : /*-----------------------------------------------------------*
4108 : * Apply gain *
4109 : *-----------------------------------------------------------*/
4110 :
4111 237838 : IF( st->hTcxCfg->coder_type == INACTIVE )
4112 : {
4113 13351 : gain_tcx_fx = mult_r( gain_tcx_fx, st->hTcxCfg->na_scale );
4114 : }
4115 :
4116 198886318 : FOR( i = 0; i < L_spec; i++ )
4117 : {
4118 198648480 : spectrum_fx[i] = Mpy_32_16_1( spectrum_fx[i], gain_tcx_fx );
4119 198648480 : move32();
4120 : }
4121 237838 : *spectrum_e = add( *spectrum_e, *gain_tcx_e );
4122 237838 : move16();
4123 :
4124 237838 : tcx_last_overlap_mode = st->hTcxCfg->tcx_last_overlap_mode; /* backup last TCX overlap mode */
4125 237838 : move16();
4126 :
4127 237838 : test();
4128 237838 : IF( ( EQ_16( L_frame, shr( st->L_frame, 1 ) ) ) && ( st->tcxonly != 0 ) )
4129 : {
4130 4118 : Word16 L = L_frame;
4131 4118 : move16();
4132 :
4133 4118 : test();
4134 4118 : test();
4135 4118 : if ( ( ( st->hTcxCfg->fIsTNSAllowed != 0 ) && ( hTcxEnc->fUseTns[frame_cnt] != 0 ) ) || ( GT_16( L_spec, L_frame ) ) )
4136 : {
4137 4018 : L = L_spec;
4138 4018 : move16();
4139 : }
4140 :
4141 4118 : tcxInvertWindowGrouping( st->hTcxCfg,
4142 : xn_buf32,
4143 : spectrum_fx,
4144 : L,
4145 4118 : hTcxEnc->fUseTns[frame_cnt],
4146 4118 : st->last_core,
4147 : tcx_last_overlap_mode,
4148 : frame_cnt,
4149 : 0 );
4150 : }
4151 :
4152 : /*-----------------------------------------------------------*
4153 : * Temporal Noise Shaping Synthesis *
4154 : *-----------------------------------------------------------*/
4155 :
4156 237838 : IF( st->hTcxCfg->fIsTNSAllowed )
4157 : {
4158 161707 : test();
4159 161707 : SetTnsConfig( st->hTcxCfg, (Word16) EQ_16( st->core, TCX_20_CORE ), ( st->last_core == ACELP_CORE ) && ( frame_cnt == 0 ) );
4160 :
4161 : /* Apply TNS to get the reconstructed signal */
4162 161707 : IF( hTcxEnc->fUseTns[frame_cnt] != 0 )
4163 : {
4164 17613 : ApplyTnsFilter( st->hTcxCfg->pCurrentTnsConfig, &hTcxEnc->tnsData[frame_cnt], spectrum_fx, 0 );
4165 :
4166 17613 : test();
4167 17613 : IF( ( EQ_16( L_frame, shr( st->L_frame, 1 ) ) ) && ( st->tcxonly != 0 ) )
4168 : {
4169 2365 : test();
4170 2365 : test();
4171 2365 : test();
4172 2365 : IF( ( st->hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP ) ||
4173 : ( ( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) && ( frame_cnt == 0 ) && ( tcx_last_overlap_mode == 0 ) ) )
4174 : {
4175 1717 : const Word16 L_win = shr( L_spec, 1 );
4176 : /* undo rearrangement of LF sub-window lines for TNS synthesis filter */
4177 1717 : IF( GT_16( L_frame, L_spec ) )
4178 : {
4179 0 : assert( 0 );
4180 : }
4181 : ELSE
4182 : {
4183 1717 : Copy32( spectrum_fx + 8, xn_buf32, L_win );
4184 1717 : Copy32( xn_buf32, spectrum_fx + L_win, 8 );
4185 1717 : Copy32( xn_buf32 + 8, spectrum_fx + 8, L_win - 8 );
4186 : }
4187 : }
4188 : }
4189 : }
4190 : }
4191 :
4192 :
4193 : /*-----------------------------------------------------------*
4194 : * Compute inverse MDCT of spectrum[]. *
4195 : *-----------------------------------------------------------*/
4196 :
4197 237838 : E_LPC_f_lsp_a_conversion( st->lsp_old_fx, Aq_old_fx, M );
4198 237838 : overlap = st->hTcxCfg->tcx_mdct_window_length;
4199 237838 : nz = NS2SA_FX2( st->sr_core, N_ZERO_MDCT_NS );
4200 237838 : aldo = 0;
4201 237838 : move16();
4202 237838 : move16();
4203 :
4204 : /* normalize spectrum to minimize IMDCT noise */
4205 237838 : s = getScaleFactor32( spectrum_fx, L_frame );
4206 105894286 : FOR( i = 0; i < L_frame; i++ )
4207 : {
4208 105656448 : spectrum_fx[i] = L_shl( spectrum_fx[i], s );
4209 105656448 : move32();
4210 : }
4211 237838 : *spectrum_e = sub( *spectrum_e, s );
4212 237838 : move16();
4213 :
4214 237838 : test();
4215 237838 : IF( ( EQ_16( L_frame, shr( st->L_frame, 1 ) ) ) && ( st->tcxonly != 0 ) )
4216 : {
4217 4118 : IF( st->hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP )
4218 : {
4219 : Word16 win[( L_FRAME_PLUS + L_MDCT_OVLP_MAX ) / 2];
4220 : Word16 L_win, L_spec_TCX5, L_ola, w;
4221 :
4222 : /* minimum or half overlap, two transforms, grouping into one window */
4223 1601 : L_win = shr( L_frame, 1 );
4224 1601 : L_spec_TCX5 = shr( s_max( L_frame, L_spec ), 1 );
4225 1601 : L_ola = st->hTcxCfg->tcx_mdct_window_half_length;
4226 1601 : move16();
4227 1601 : if ( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, MIN_OVERLAP ) )
4228 : {
4229 770 : L_ola = st->hTcxCfg->tcx_mdct_window_min_length;
4230 770 : move16();
4231 : }
4232 :
4233 1601 : set16_fx( win, 0, ( L_FRAME_PLUS + L_MDCT_OVLP_MAX ) / 2 );
4234 1601 : set16_fx( xn_buf16, 0, add( tcx_offset, shr( L_ola, 1 ) ) ); /* zero left end of buffer */
4235 :
4236 4803 : FOR( w = 0; w < 2; w++ )
4237 : {
4238 :
4239 3202 : IF( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, MIN_OVERLAP ) )
4240 : {
4241 1540 : TCX_MDCT_Inverse( spectrum_fx + L_mult0( w, L_spec_TCX5 ), sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ),
4242 1540 : win, L_ola, sub( L_win, L_ola ), L_ola, st->element_mode );
4243 : }
4244 : ELSE
4245 : {
4246 1662 : TCX_MDCT_Inverse( spectrum_fx + L_mult0( w, L_spec_TCX5 ), sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ), win,
4247 1662 : L_ola, sub( L_win, L_ola ), L_ola, st->element_mode );
4248 : }
4249 :
4250 3202 : tmp1 = st->hTcxCfg->tcx_last_overlap_mode;
4251 3202 : move16();
4252 3202 : test();
4253 3202 : test();
4254 3202 : if ( ( w > 0 ) || ( ( w == 0 ) && ( EQ_16( tcx_last_overlap_mode, 2 ) ) ) )
4255 : {
4256 1942 : tmp1 = MIN_OVERLAP;
4257 1942 : move16();
4258 : }
4259 :
4260 3202 : tmp2 = 0;
4261 3202 : move16();
4262 3202 : test();
4263 3202 : if ( ( w == 0 ) && ( st->last_core == ACELP_CORE ) )
4264 : {
4265 0 : tmp2 = 1;
4266 0 : move16();
4267 : }
4268 :
4269 3202 : tmp3 = st->last_core;
4270 3202 : move16();
4271 3202 : if ( w > 0 )
4272 : {
4273 1601 : tmp3 = 1;
4274 1601 : move16();
4275 : }
4276 :
4277 3202 : tmp4 = 0;
4278 3202 : move16();
4279 3202 : if ( tcx_offset < 0 )
4280 : {
4281 0 : tmp4 = negate( tcx_offset );
4282 : }
4283 :
4284 3202 : tcx_windowing_synthesis_current_frame( win,
4285 3202 : st->hTcxCfg->tcx_aldo_window_2,
4286 3202 : st->hTcxCfg->tcx_mdct_window_half,
4287 3202 : st->hTcxCfg->tcx_mdct_window_minimum,
4288 : L_ola,
4289 3202 : st->hTcxCfg->tcx_mdct_window_half_length,
4290 3202 : st->hTcxCfg->tcx_mdct_window_min_length,
4291 : tmp2,
4292 : tmp1,
4293 : hTcxEnc->acelp_zir,
4294 3202 : hTcxEnc->Txnq,
4295 : NULL,
4296 : Aq_old_fx,
4297 3202 : st->hTcxCfg->tcx_mdct_window_trans,
4298 : L_win,
4299 : tmp4,
4300 : tmp3,
4301 : 0,
4302 : 0 );
4303 :
4304 3202 : tmp1 = add( tcx_offset, imult1616( w, L_win ) );
4305 3202 : move16();
4306 3202 : tmpP16 = xn_buf16 + sub( tmp1, shr( L_ola, 1 ) );
4307 :
4308 3202 : IF( w > 0 )
4309 : {
4310 1601 : tcx_windowing_synthesis_past_frame( tmpP16,
4311 1601 : st->hTcxCfg->tcx_aldo_window_1_trunc,
4312 1601 : st->hTcxCfg->tcx_mdct_window_half,
4313 1601 : st->hTcxCfg->tcx_mdct_window_minimum,
4314 : L_ola,
4315 1601 : st->hTcxCfg->tcx_mdct_window_half_length,
4316 1601 : st->hTcxCfg->tcx_mdct_window_min_length,
4317 : 2 );
4318 : }
4319 : /* add part of current sub-window overlapping with previous window */
4320 263522 : FOR( i = 0; i < L_ola; i++ )
4321 : {
4322 260320 : tmpP16[i] = add_sat( tmpP16[i], win[i] );
4323 260320 : move16();
4324 : }
4325 : /* copy new sub-window region not overlapping with previous window */
4326 3202 : Copy( win + L_ola, xn_buf16 + add( tmp1, shr( L_ola, 1 ) ), L_win );
4327 : }
4328 : /* To assure that no garbage values are copied to hLPDmem->Txnq */
4329 1601 : set16_fx( xn_buf16 + add( add( L_frame, tcx_offset ), shr( L_ola, 1 ) ),
4330 1601 : 0, sub( sub( overlap, tcx_offset ), shr( L_ola, 1 ) ) );
4331 : }
4332 2517 : ELSE IF( s_and( frame_cnt == 0, ( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) ) )
4333 : {
4334 : /* special overlap attempt, two transforms, grouping into one window */
4335 : Word16 win[( L_FRAME_PLUS + L_MDCT_OVLP_MAX ) / 2];
4336 : Word16 L_win, L_spec_TCX5, L_ola, w;
4337 :
4338 596 : L_win = shr( L_frame, 1 );
4339 596 : L_spec_TCX5 = shr( s_max( L_frame, L_spec ), 1 );
4340 596 : L_ola = st->hTcxCfg->tcx_mdct_window_min_length;
4341 596 : move16();
4342 :
4343 596 : set16_fx( win, 0, ( L_FRAME_PLUS + L_MDCT_OVLP_MAX ) / 2 );
4344 :
4345 : /* Resize overlap (affect only asymmetric window)*/
4346 596 : overlap = st->hTcxCfg->tcx_mdct_window_delay;
4347 : /* 1st TCX-5 window, special MDCT with minimum overlap on right side */
4348 596 : TCX_MDCT_Inverse( spectrum_fx, sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ),
4349 596 : win + L_win, 0, sub( L_win, shr( L_ola, 1 ) ), L_ola, st->element_mode );
4350 :
4351 : /* copy new sub-window region not overlapping with previous window */
4352 596 : Copy( win + L_win, xn_buf16 + shr( overlap, 1 ), add( L_win, shr( L_ola, 1 ) ) );
4353 :
4354 : /* 2nd TCX-5 window, regular MDCT with minimum overlap on both sides */
4355 :
4356 596 : TCX_MDCT_Inverse( spectrum_fx + L_spec_TCX5, sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ),
4357 596 : win, L_ola, sub( L_win, L_ola ), L_ola, st->element_mode );
4358 :
4359 596 : tmp4 = 0;
4360 596 : move16();
4361 596 : if ( tcx_offset < 0 )
4362 : {
4363 0 : tmp4 = negate( tcx_offset );
4364 : }
4365 596 : tcx_windowing_synthesis_current_frame( win,
4366 596 : st->hTcxCfg->tcx_aldo_window_2,
4367 596 : st->hTcxCfg->tcx_mdct_window_half,
4368 596 : st->hTcxCfg->tcx_mdct_window_minimum,
4369 : L_ola,
4370 596 : st->hTcxCfg->tcx_mdct_window_half_length,
4371 596 : st->hTcxCfg->tcx_mdct_window_min_length,
4372 : 0, /* left_rect */
4373 : 2, /* left_mode */
4374 : hTcxEnc->acelp_zir,
4375 596 : hTcxEnc->Txnq,
4376 : NULL,
4377 : Aq_old_fx,
4378 596 : st->hTcxCfg->tcx_mdct_window_trans,
4379 : L_win,
4380 : tmp4,
4381 : 1, /* not LPDmem->mode */
4382 : 0,
4383 : 0 );
4384 :
4385 :
4386 596 : tmpP16 = xn_buf16 + add( sub( L_win, shr( L_ola, 1 ) ), shr( overlap, 1 ) );
4387 :
4388 596 : tcx_windowing_synthesis_past_frame( tmpP16,
4389 596 : st->hTcxCfg->tcx_aldo_window_1_trunc,
4390 596 : st->hTcxCfg->tcx_mdct_window_half,
4391 596 : st->hTcxCfg->tcx_mdct_window_minimum,
4392 : L_ola,
4393 596 : st->hTcxCfg->tcx_mdct_window_half_length,
4394 596 : st->hTcxCfg->tcx_mdct_window_min_length,
4395 : 2 );
4396 :
4397 : /* add part of current sub-window overlapping with previous window */
4398 24316 : FOR( i = 0; i < L_ola; i++ )
4399 : {
4400 23720 : tmpP16[i] = add_sat( tmpP16[i], win[i] );
4401 23720 : move16();
4402 : }
4403 :
4404 : /* copy new sub-window region not overlapping with previous window */
4405 1192 : Copy( win + L_ola,
4406 596 : xn_buf16 + add( add( shr( overlap, 1 ), shr( L_ola, 1 ) ), L_win ),
4407 : L_win );
4408 :
4409 : /* extra folding-out on left side of win, for perfect reconstruction */
4410 83616 : FOR( w = shr( overlap, 1 ); w < overlap; w++ )
4411 : {
4412 83020 : xn_buf16[overlap - 1 - w] = negate( xn_buf16[w] );
4413 83020 : move16();
4414 : }
4415 :
4416 596 : tmp4 = 0;
4417 596 : move16();
4418 596 : if ( tcx_offset < 0 )
4419 : {
4420 0 : tmp4 = negate( tcx_offset );
4421 : }
4422 596 : tcx_windowing_synthesis_current_frame( xn_buf16,
4423 596 : st->hTcxCfg->tcx_aldo_window_2,
4424 596 : st->hTcxCfg->tcx_mdct_window_half,
4425 596 : st->hTcxCfg->tcx_mdct_window_minimum,
4426 : overlap,
4427 596 : st->hTcxCfg->tcx_mdct_window_half_length,
4428 596 : st->hTcxCfg->tcx_mdct_window_min_length,
4429 596 : st->last_core == ACELP_CORE,
4430 : 0,
4431 : hTcxEnc->acelp_zir,
4432 596 : hTcxEnc->Txnq,
4433 : NULL,
4434 : Aq_old_fx,
4435 596 : st->hTcxCfg->tcx_mdct_window_trans,
4436 : L_win,
4437 : tmp4,
4438 596 : st->last_core,
4439 : 0,
4440 : 0 );
4441 : }
4442 : ELSE /* default, i.e. maximum overlap, single transform, no grouping */
4443 : {
4444 :
4445 1921 : TCX_MDCT_Inverse( spectrum_fx, sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ),
4446 1921 : xn_buf16, overlap, sub( L_frame, overlap ), overlap, st->element_mode );
4447 :
4448 1921 : tmp1 = tcx_last_overlap_mode;
4449 1921 : move16();
4450 1921 : test();
4451 1921 : test();
4452 1921 : if ( ( frame_cnt > 0 ) && ( tcx_last_overlap_mode == 0 ) && ( st->last_core != ACELP_CORE ) )
4453 : {
4454 596 : tmp1 = 2;
4455 596 : move16();
4456 : }
4457 :
4458 1921 : tmp4 = 0;
4459 1921 : move16();
4460 1921 : if ( tcx_offset < 0 )
4461 : {
4462 0 : tmp4 = negate( tcx_offset );
4463 : }
4464 3842 : tcx_windowing_synthesis_current_frame( xn_buf16,
4465 1921 : st->hTcxCfg->tcx_aldo_window_2,
4466 1921 : st->hTcxCfg->tcx_mdct_window_half,
4467 1921 : st->hTcxCfg->tcx_mdct_window_minimum,
4468 : overlap, /*hTcxCfg->tcx_mdct_window_length*/
4469 1921 : st->hTcxCfg->tcx_mdct_window_half_length,
4470 1921 : st->hTcxCfg->tcx_mdct_window_min_length,
4471 1921 : st->last_core == ACELP_CORE,
4472 : tmp1,
4473 : hTcxEnc->acelp_zir,
4474 1921 : hTcxEnc->Txnq,
4475 : NULL,
4476 : Aq_old_fx,
4477 1921 : st->hTcxCfg->tcx_mdct_window_trans,
4478 1921 : shr( st->L_frame, 2 ),
4479 : tmp4,
4480 1921 : st->last_core,
4481 : 0,
4482 : 0 );
4483 :
4484 : } /* tcx_last_overlap_mode > 0 */
4485 : }
4486 : ELSE /* frame is TCX-20 or not TCX-only */
4487 : {
4488 233720 : IF( NE_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) )
4489 : {
4490 : Word32 tmp_buf[L_FRAME_PLUS];
4491 : Word16 Q;
4492 :
4493 : /* DCT */
4494 225864 : Q = sub( 31, *spectrum_e );
4495 225864 : edct_ivas_fx( spectrum_fx, tmp_buf, L_frame, &Q );
4496 :
4497 : /* scale by sqrt(L / NORM_MDCT_FACTOR) */
4498 225864 : tmp1 = mult_r( shl( L_frame, 4 ), 26214 /*128.f / NORM_MDCT_FACTOR Q15*/ ); /* 4Q11 */
4499 225864 : tmp2 = 4;
4500 225864 : move16();
4501 225864 : tmp1 = Sqrt16( tmp1, &tmp2 );
4502 :
4503 101608072 : FOR( i = 0; i < L_frame; i++ )
4504 : {
4505 101382208 : tmp_buf[i] = Mpy_32_16_1( tmp_buf[i], tmp1 );
4506 101382208 : move32();
4507 : }
4508 225864 : Q = sub( Q, tmp2 );
4509 :
4510 :
4511 225864 : window_ola_fx( tmp_buf,
4512 : xn_buf16,
4513 : &Q,
4514 225864 : hTcxEnc->old_out_fx,
4515 : &hTcxEnc->Q_old_out,
4516 : L_frame,
4517 225864 : st->hTcxCfg->tcx_last_overlap_mode,
4518 225864 : st->hTcxCfg->tcx_curr_overlap_mode,
4519 : 0,
4520 : 0,
4521 : NULL );
4522 :
4523 : /* scale output */
4524 101608072 : FOR( i = 0; i < L_frame; i++ )
4525 : {
4526 101382208 : xn_buf16[i] = shr_o( xn_buf16[i], Q, &Overflow );
4527 101382208 : move16();
4528 : }
4529 :
4530 225864 : aldo = 1;
4531 225864 : move16();
4532 : }
4533 : ELSE
4534 : {
4535 :
4536 7856 : TCX_MDCT_Inverse( spectrum_fx, sub( *spectrum_e, TCX_IMDCT_SCALE + TCX_IMDCT_HEADROOM ),
4537 7856 : xn_buf16, overlap, sub( L_frame, overlap ), overlap, st->element_mode );
4538 :
4539 : /*-----------------------------------------------------------*
4540 : * Windowing, overlap and add *
4541 : *-----------------------------------------------------------*/
4542 :
4543 : /* Window current frame */
4544 7856 : tmp4 = 0;
4545 7856 : move16();
4546 7856 : if ( tcx_offset < 0 )
4547 : {
4548 7856 : tmp4 = negate( tcx_offset );
4549 : }
4550 15712 : tcx_windowing_synthesis_current_frame( xn_buf16,
4551 7856 : st->hTcxCfg->tcx_aldo_window_2,
4552 7856 : st->hTcxCfg->tcx_mdct_window_half,
4553 7856 : st->hTcxCfg->tcx_mdct_window_minimum,
4554 : overlap, /*hTcxCfg->tcx_mdct_window_length*/
4555 7856 : st->hTcxCfg->tcx_mdct_window_half_length,
4556 7856 : st->hTcxCfg->tcx_mdct_window_min_length,
4557 7856 : st->last_core == ACELP_CORE,
4558 7856 : st->hTcxCfg->tcx_last_overlap_mode, /*left mode*/
4559 : hTcxEnc->acelp_zir,
4560 7856 : hTcxEnc->Txnq,
4561 : NULL,
4562 : Aq_old_fx,
4563 7856 : st->hTcxCfg->tcx_mdct_window_trans,
4564 7856 : shr( st->L_frame, 1 ),
4565 : tmp4,
4566 7856 : st->last_core,
4567 : 0,
4568 : 0 );
4569 : }
4570 : } /* TCX-10 and TCX-only */
4571 :
4572 : /* Window and overlap-add past frame if past frame is TCX */
4573 237838 : test();
4574 237838 : test();
4575 237838 : test();
4576 237838 : IF( ( st->last_core > ACELP_CORE ) && ( ( ( EQ_16( L_frameTCX, shr( hTcxEnc->L_frameTCX, 1 ) ) ) && ( st->tcxonly != 0 ) ) || ( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) ) )
4577 : {
4578 :
4579 4118 : IF( st->hTcxCfg->last_aldo != 0 )
4580 : {
4581 1922 : tmp2 = add( hTcxEnc->Q_old_out, TCX_IMDCT_HEADROOM );
4582 :
4583 1922 : tmp1 = sub( overlap, st->hTcxCfg->tcx_mdct_window_min_length );
4584 461522 : FOR( i = 0; i < tmp1; i++ )
4585 : {
4586 459600 : xn_buf16[i] = shl_sat( add_sat( xn_buf16[i], shr_sat( hTcxEnc->old_out_fx[i + nz], tmp2 ) ), TCX_IMDCT_HEADROOM );
4587 459600 : move16();
4588 : }
4589 :
4590 : /* fade truncated ALDO window */
4591 1922 : tmp1 = sub( overlap, shr( st->hTcxCfg->tcx_mdct_window_min_length, 1 ) );
4592 40222 : FOR( ; i < tmp1; i++ )
4593 : {
4594 38300 : tmp3 = mult_r( shr( hTcxEnc->old_out_fx[i + nz], tmp2 ), st->hTcxCfg->tcx_mdct_window_minimum[i - overlap + st->hTcxCfg->tcx_mdct_window_min_length].v.re );
4595 38300 : xn_buf16[i] = shl_sat( add_sat( xn_buf16[i], tmp3 ), TCX_IMDCT_HEADROOM );
4596 38300 : move16();
4597 : }
4598 40222 : FOR( ; i < overlap; i++ )
4599 : {
4600 38300 : tmp3 = mult_r( shr( hTcxEnc->old_out_fx[i + nz], tmp2 ), st->hTcxCfg->tcx_mdct_window_minimum[overlap - 1 - i].v.im );
4601 38300 : xn_buf16[i] = shl_sat( add_sat( xn_buf16[i], tmp3 ), TCX_IMDCT_HEADROOM );
4602 38300 : move16();
4603 : }
4604 :
4605 78522 : FOR( ; i < L_frame; i++ )
4606 : {
4607 76600 : xn_buf16[i] = shl_sat( xn_buf16[i], TCX_IMDCT_HEADROOM );
4608 76600 : move16();
4609 : }
4610 : }
4611 : ELSE
4612 : {
4613 2196 : test();
4614 2196 : test();
4615 2196 : test();
4616 2196 : if ( ( frame_cnt > 0 ) && ( tcx_last_overlap_mode == 0 ) && ( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) && ( st->last_core != ACELP_CORE ) )
4617 : {
4618 596 : tcx_last_overlap_mode = 2; /* use minimum overlap between the two TCX-10 windows */
4619 596 : move16();
4620 : }
4621 :
4622 2196 : tmp1 = tcx_last_overlap_mode;
4623 2196 : move16();
4624 2196 : test();
4625 2196 : if ( ( tcx_last_overlap_mode == 0 ) || ( EQ_16( st->hTcxCfg->tcx_last_overlap_mode, MIN_OVERLAP ) ) )
4626 : {
4627 1056 : tmp1 = st->hTcxCfg->tcx_last_overlap_mode;
4628 1056 : move16();
4629 : }
4630 :
4631 2196 : tcx_windowing_synthesis_past_frame( hTcxEnc->Txnq, st->hTcxCfg->tcx_aldo_window_1_trunc, st->hTcxCfg->tcx_mdct_window_half,
4632 2196 : st->hTcxCfg->tcx_mdct_window_minimum, overlap, st->hTcxCfg->tcx_mdct_window_half_length, st->hTcxCfg->tcx_mdct_window_min_length, tmp1 );
4633 :
4634 : BASOP_SATURATE_WARNING_OFF_EVS;
4635 615116 : FOR( i = 0; i < overlap; i++ )
4636 : {
4637 612920 : xn_buf16[i] = shl_sat( add( xn_buf16[i], hTcxEnc->Txnq[i] ), TCX_IMDCT_HEADROOM );
4638 612920 : move16();
4639 : }
4640 :
4641 2196 : IF( LT_16( i, L_frame ) )
4642 : {
4643 89756 : FOR( ; i < L_frame; i++ )
4644 : {
4645 87560 : xn_buf16[i] = shl_sat( xn_buf16[i], TCX_IMDCT_HEADROOM );
4646 87560 : move16();
4647 : }
4648 : }
4649 : BASOP_SATURATE_WARNING_ON_EVS;
4650 : }
4651 : }
4652 : ELSE
4653 : {
4654 233720 : IF( aldo == 0 )
4655 : {
4656 : BASOP_SATURATE_WARNING_OFF_EVS;
4657 2968816 : FOR( i = 0; i < L_frame; i++ )
4658 : {
4659 2960960 : xn_buf16[i] = shl_o( xn_buf16[i], TCX_IMDCT_HEADROOM, &Overflow );
4660 2960960 : move16();
4661 : }
4662 : BASOP_SATURATE_WARNING_ON_EVS;
4663 : }
4664 : }
4665 :
4666 237838 : test();
4667 237838 : test();
4668 237838 : test();
4669 237838 : IF( ( aldo == 0 ) &&
4670 : ( ( EQ_16( L_frameTCX, shr( hTcxEnc->L_frameTCX, 1 ) ) && frame_cnt > 0 ) ||
4671 : NE_16( L_frameTCX, shr( hTcxEnc->L_frameTCX, 1 ) ) ) )
4672 : {
4673 : /*Compute windowed synthesis in case of switching to ALDO windows in next frame*/
4674 1045491 : FOR( i = 0; i < nz; i++ )
4675 : {
4676 1035576 : hTcxEnc->old_out_fx[i] = shr( xn_buf16[L_frame - nz + i], TCX_IMDCT_HEADROOM );
4677 1035576 : move16();
4678 : }
4679 9915 : Copy( xn_buf16 + L_frame, hTcxEnc->old_out_fx + nz, overlap );
4680 9915 : set16_fx( hTcxEnc->old_out_fx + nz + overlap, 0, nz );
4681 :
4682 9915 : tcx_windowing_synthesis_past_frame( hTcxEnc->old_out_fx + nz,
4683 9915 : st->hTcxCfg->tcx_aldo_window_1_trunc,
4684 9915 : st->hTcxCfg->tcx_mdct_window_half,
4685 9915 : st->hTcxCfg->tcx_mdct_window_minimum,
4686 : overlap,
4687 9915 : st->hTcxCfg->tcx_mdct_window_half_length,
4688 9915 : st->hTcxCfg->tcx_mdct_window_min_length,
4689 9915 : st->hTcxCfg->tcx_curr_overlap_mode );
4690 :
4691 : /* If current overlap mode = FULL_OVERLAP -> ALDO_WINDOW */
4692 9915 : IF( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP )
4693 : {
4694 855515 : FOR( i = 0; i < nz; i++ )
4695 : {
4696 846684 : hTcxEnc->old_out_fx[nz + overlap + i] = shr( mult_r( xn_buf16[L_frame - 1 - i], st->hTcxCfg->tcx_aldo_window_1[nz - 1 - i] ), TCX_IMDCT_HEADROOM );
4697 846684 : move16();
4698 : }
4699 : }
4700 :
4701 9915 : hTcxEnc->Q_old_out = -TCX_IMDCT_HEADROOM;
4702 9915 : move16();
4703 : }
4704 237838 : st->hTcxCfg->last_aldo = aldo;
4705 237838 : move16();
4706 :
4707 : /* Update Txnq */
4708 237838 : IF( st->hTcxCfg->last_aldo == 0 )
4709 : {
4710 11974 : Copy( xn_buf16 + L_frame, hTcxEnc->Txnq, overlap );
4711 : }
4712 :
4713 237838 : tmp1 = L_frame;
4714 237838 : move16();
4715 237838 : if ( EQ_16( st->core, TCX_20_CORE ) )
4716 : {
4717 233720 : tmp1 = st->L_frame;
4718 233720 : move16();
4719 : }
4720 :
4721 : /* Output */
4722 237838 : Copy( xn_buf16 + shr( overlap, 1 ) - tcx_offset, synth, tmp1 );
4723 :
4724 237838 : return;
4725 : }
4726 :
4727 :
4728 686098 : void TNSAnalysisStereo_fx(
4729 : Encoder_State **sts, /* i : encoder state handle */
4730 : Word32 *mdst_spectrum_fx[CPE_CHANNELS][NB_DIV], /* o : MDST spectrum Qx*/
4731 : const Word16 bWhitenedDomain, /* i : whitened domain flag Q0*/
4732 : Word16 tnsSize[CPE_CHANNELS][NB_DIV], /* i : number of tns parameters put into prm Q0*/
4733 : Word16 tnsBits[CPE_CHANNELS][NB_DIV], /* i : number of tns bits in the frame Q0*/
4734 : Word16 param_core[][NB_DIV * NPRM_DIV], /* o : TNS parameters Q0*/
4735 : const Word16 mct_on /* i : flag mct block (1) or stereo (0) Q0*/
4736 : )
4737 : {
4738 : Word16 ch, k, L_spec, L_frame, nSubframes, iFilter;
4739 : Word32 *spectrum_fx, sum;
4740 686098 : Encoder_State *st = NULL;
4741 686098 : TCX_ENC_HANDLE hTcxEnc = NULL;
4742 : Word16 individual_decision[NB_DIV];
4743 686098 : Word32 maxPredictionGain_fx = 0, meanPredictionGain_fx;
4744 686098 : move32();
4745 686098 : Word16 maxPredictionGain_e = 0, meanPredictionGain_e;
4746 686098 : move16();
4747 686098 : Word16 sum_e = 0;
4748 686098 : move16();
4749 686098 : individual_decision[0] = 0;
4750 686098 : move16();
4751 686098 : individual_decision[1] = 0;
4752 686098 : move16();
4753 686098 : L_spec = -1;
4754 686098 : move16();
4755 686098 : L_frame = -1;
4756 686098 : move16();
4757 :
4758 : /* TNS filter analysis, loop over channels */
4759 2058294 : FOR( ch = 0; ch < CPE_CHANNELS; ch++ )
4760 : {
4761 1372196 : st = sts[ch];
4762 1372196 : IF( EQ_16( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
4763 : {
4764 139021 : CONTINUE;
4765 : }
4766 :
4767 1233175 : hTcxEnc = st->hTcxEnc;
4768 :
4769 1233175 : IF( EQ_16( hTcxEnc->tcxMode, TCX_20 ) )
4770 : {
4771 1205695 : nSubframes = 1;
4772 : }
4773 : ELSE
4774 : {
4775 27480 : nSubframes = NB_DIV;
4776 : }
4777 1233175 : move16();
4778 :
4779 2493830 : FOR( k = 0; k < nSubframes; k++ )
4780 : {
4781 : /* reset tns on whitened domain flag */
4782 1260655 : IF( !bWhitenedDomain )
4783 : {
4784 637199 : hTcxEnc->bTnsOnWhithenedSpectra[k] = 0;
4785 637199 : move16();
4786 637199 : hTcxEnc->fUseTns[k] = 0;
4787 637199 : move16();
4788 : }
4789 1260655 : test();
4790 1260655 : test();
4791 1260655 : IF( st->hTcxCfg->fIsTNSAllowed && ( !bWhitenedDomain || hTcxEnc->bTnsOnWhithenedSpectra[k] ) )
4792 : {
4793 1239909 : spectrum_fx = hTcxEnc->spectrum_fx[k];
4794 :
4795 1239909 : L_frame = hTcxEnc->L_frameTCX;
4796 1239909 : move16();
4797 1239909 : st->hTcxCfg->pCurrentTnsConfig = &st->hTcxCfg->tnsConfig[hTcxEnc->transform_type[k] == TCX_20][( k == 0 ) && ( st->last_core == ACELP_CORE )];
4798 1239909 : L_spec = st->hTcxCfg->pCurrentTnsConfig->iFilterBorders[0];
4799 1239909 : move16();
4800 : /*-----------------------------------------------------------*
4801 : * Temporal Noise Shaping analysis *
4802 : *-----------------------------------------------------------*/
4803 :
4804 1239909 : IF( EQ_16( hTcxEnc->transform_type[k], TCX_5 ) )
4805 : {
4806 : /* rearrange LF sub-window lines prior to TNS analysis & filtering */
4807 14213 : tcx5TnsGrouping_fx( shr( L_frame, 2 ), shr( L_spec, 1 ), spectrum_fx );
4808 : }
4809 :
4810 : /* WMOPS: All initializations are either for safety or static (tables) and thus not to be counted */
4811 :
4812 1239909 : ResetTnsData( &hTcxEnc->tnsData[k] );
4813 1239909 : IF( st->hTcxCfg->pCurrentTnsConfig->maxOrder <= 0 )
4814 : {
4815 0 : BREAK;
4816 : }
4817 :
4818 1239909 : CalculateTnsFilt_fx( st->hTcxCfg->pCurrentTnsConfig, spectrum_fx, hTcxEnc->spectrum_e[k], &hTcxEnc->tnsData[k] );
4819 : }
4820 : }
4821 : }
4822 :
4823 686098 : IF( !mct_on )
4824 : {
4825 : /* TNS decision */
4826 : /* if framing differs between channels, keep the filter decision per channel */
4827 163762 : test();
4828 163762 : test();
4829 163762 : IF( ( NE_16( sts[0]->hTcxEnc->transform_type[0], sts[1]->hTcxEnc->transform_type[0] ) &&
4830 : NE_16( sts[0]->hTcxEnc->transform_type[1], sts[1]->hTcxEnc->transform_type[1] ) ) ||
4831 : NE_16( sts[0]->hTcxCfg->fIsTNSAllowed, sts[1]->hTcxCfg->fIsTNSAllowed ) )
4832 : {
4833 1196 : individual_decision[0] = individual_decision[1] = 1;
4834 1196 : move16();
4835 1196 : move16();
4836 : }
4837 162566 : ELSE IF( bWhitenedDomain )
4838 : {
4839 81283 : IF( EQ_16( sts[0]->hTcxEnc->tcxMode, TCX_20 ) )
4840 : {
4841 79539 : nSubframes = 1;
4842 : }
4843 : ELSE
4844 : {
4845 1744 : nSubframes = NB_DIV;
4846 : }
4847 81283 : move16();
4848 164310 : FOR( k = 0; k < nSubframes; k++ )
4849 : {
4850 83027 : IF( NE_16( sts[0]->hTcxEnc->bTnsOnWhithenedSpectra[k], sts[1]->hTcxEnc->bTnsOnWhithenedSpectra[k] ) )
4851 : {
4852 389 : individual_decision[k] = 1;
4853 389 : move16();
4854 : }
4855 : }
4856 : }
4857 :
4858 : /* framing equal, check for similar filters, if very similar (also indicator for and M signal),
4859 : * use at least the same decision, maybe use the same filter
4860 : */
4861 : {
4862 : Word8 isTCX10;
4863 :
4864 163762 : IF( EQ_16( sts[0]->hTcxEnc->tcxMode, TCX_20 ) )
4865 : {
4866 159706 : nSubframes = 1;
4867 159706 : isTCX10 = 0;
4868 : }
4869 : ELSE
4870 : {
4871 4056 : nSubframes = NB_DIV;
4872 4056 : isTCX10 = 1;
4873 : }
4874 163762 : move16();
4875 163762 : move16();
4876 331580 : FOR( k = 0; k < nSubframes; k++ )
4877 : {
4878 167818 : test();
4879 167818 : test();
4880 167818 : test();
4881 167818 : IF( sts[0]->hTcxCfg->fIsTNSAllowed && NE_16( individual_decision[k], 1 ) && ( !bWhitenedDomain || sts[0]->hTcxEnc->bTnsOnWhithenedSpectra[k] ) )
4882 : {
4883 163360 : Word32 maxPredGain_fx = -ONE_IN_Q31;
4884 163360 : move32();
4885 163360 : Word16 maxPredGain_e = 0;
4886 163360 : move16();
4887 163360 : sts[0]->hTcxCfg->pCurrentTnsConfig = &sts[0]->hTcxCfg->tnsConfig[sts[0]->hTcxEnc->transform_type[k] == TCX_20][( k == 0 ) && ( sts[0]->last_core == ACELP_CORE )];
4888 163360 : sts[1]->hTcxCfg->pCurrentTnsConfig = &sts[1]->hTcxCfg->tnsConfig[sts[1]->hTcxEnc->transform_type[k] == TCX_20][( k == 0 ) && ( sts[1]->last_core == ACELP_CORE )];
4889 :
4890 469576 : FOR( iFilter = sts[0]->hTcxCfg->pCurrentTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter-- )
4891 : {
4892 : STnsFilter *pFilter[2];
4893 : struct TnsParameters const *pTnsParameters[2];
4894 306216 : pFilter[0] = sts[0]->hTcxEnc->tnsData[k].filter + iFilter;
4895 306216 : pTnsParameters[0] = sts[0]->hTcxCfg->pCurrentTnsConfig->pTnsParameters + iFilter;
4896 306216 : pFilter[1] = sts[1]->hTcxEnc->tnsData[k].filter + iFilter;
4897 306216 : pTnsParameters[1] = sts[1]->hTcxCfg->pCurrentTnsConfig->pTnsParameters + iFilter;
4898 :
4899 : /* if prediction gain and avgSqrCoef are both close we are pretty sure the filters are quite similar, use the avg of
4900 : * both filters for the decision
4901 : */
4902 :
4903 306216 : meanPredictionGain_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( pFilter[0]->predictionGain32, 16384 /*0.5f Q15*/ ), pFilter[0]->predictionGain_e, Mpy_32_16_1( pFilter[1]->predictionGain32, 16384 /*0.5f Q15*/ ), pFilter[1]->predictionGain_e, &meanPredictionGain_e ); // meanPredictionGain_e
4904 :
4905 : /* maxPredictionGain = max( maxPredictionGain, meanPredictionGain );*/
4906 306216 : IF( GT_32( meanPredictionGain_fx, L_shl_sat( maxPredictionGain_fx, sub( maxPredictionGain_e, meanPredictionGain_e ) ) ) ) /* exp: meanPredictionGain_e */
4907 : {
4908 203648 : maxPredictionGain_fx = meanPredictionGain_fx;
4909 203648 : maxPredictionGain_e = meanPredictionGain_e;
4910 203648 : move32();
4911 203648 : move16();
4912 : }
4913 :
4914 306216 : test();
4915 306216 : test();
4916 306216 : test();
4917 306216 : IF( GT_32( pFilter[0]->predictionGain32, L_shl_sat( L_deposit_h( pTnsParameters[0]->minPredictionGain ), sub( PRED_GAIN_E, pFilter[0]->predictionGain_e ) ) ) && LT_32( sts[0]->element_brate, IVAS_80k ) &&
4918 : GT_32( pFilter[1]->predictionGain32, L_shl_sat( L_deposit_h( pTnsParameters[1]->minPredictionGain ), sub( PRED_GAIN_E, pFilter[1]->predictionGain_e ) ) ) && EQ_16( sts[0]->hTcxEnc->tnsData[k].nFilters, sts[1]->hTcxEnc->tnsData[k].nFilters ) )
4919 : {
4920 4783 : pFilter[0]->predictionGain32 = pFilter[1]->predictionGain32 = meanPredictionGain_fx; /* more TNS filter sync at 48kbps */
4921 4783 : move32();
4922 4783 : move32();
4923 4783 : pFilter[0]->predictionGain_e = pFilter[1]->predictionGain_e = meanPredictionGain_e; /* more TNS filter sync at 48kbps */
4924 4783 : move16();
4925 4783 : move16();
4926 4783 : pFilter[0]->predictionGain = pFilter[1]->predictionGain = shl_sat( extract_h( meanPredictionGain_fx ), sub( meanPredictionGain_e, PRED_GAIN_E ) ); /* Q7 */
4927 4783 : move16();
4928 : }
4929 306216 : sum_e = s_max( pFilter[0]->predictionGain_e, pFilter[1]->predictionGain_e );
4930 306216 : sum = L_abs( L_sub_sat( L_shl( pFilter[0]->predictionGain32, sub( pFilter[0]->predictionGain_e, sum_e ) ), L_shl( pFilter[1]->predictionGain32, sub( pFilter[1]->predictionGain_e, sum_e ) ) ) ); // sum_e
4931 :
4932 306216 : IF( LT_32( L_shl_sat( sum, sub( sum_e, meanPredictionGain_e ) ), Mpy_32_16_1( meanPredictionGain_fx, SIMILAR_TNS_THRESHOLD_FX_IN_Q15 ) ) &&
4933 : ( EQ_16( sts[0]->hTcxEnc->tnsData[k].nFilters, sts[1]->hTcxEnc->tnsData[k].nFilters ) ) )
4934 202780 : {
4935 :
4936 202780 : Word16 maxAvgSqrCoef_fx = s_max( pFilter[0]->avgSqrCoef, pFilter[1]->avgSqrCoef ); // Q15
4937 202780 : Word16 meanLtpGain_fx = add( shr( sts[0]->hTcxEnc->tcxltp_gain, 1 ), shr( sts[1]->hTcxEnc->tcxltp_gain, 1 ) );
4938 :
4939 : /* maxPredGain_fx = L_max( maxPredGain_fx, meanPredictionGain_fx ); */
4940 202780 : IF( GT_32( meanPredictionGain_fx, L_shl_sat( maxPredGain_fx, sub( maxPredGain_e, maxPredictionGain_e ) ) ) ) /* exp: meanPredictionGain_e */
4941 : {
4942 153265 : maxPredGain_fx = meanPredictionGain_fx;
4943 153265 : maxPredGain_e = meanPredictionGain_e;
4944 153265 : move32();
4945 153265 : move16();
4946 : }
4947 :
4948 202780 : test();
4949 202780 : test();
4950 202780 : IF( GT_32( meanPredictionGain_fx, L_shl_sat( L_deposit_h( pTnsParameters[0]->minPredictionGain ), sub( PRED_GAIN_E, meanPredictionGain_e ) ) ) || GT_16( maxAvgSqrCoef_fx, pTnsParameters[0]->minAvgSqrCoef ) )
4951 : {
4952 7187 : test();
4953 7187 : test();
4954 7187 : test();
4955 7187 : IF( sts[0]->hTcxEnc->tnsData[k].nFilters > 0 || sts[1]->hTcxEnc->tnsData[k].nFilters > 0 || isTCX10 || LT_16( meanLtpGain_fx, 19660 /* 0.6 in Q15*/ ) )
4956 : {
4957 :
4958 6536 : sts[0]->hTcxEnc->tnsData[k].nFilters = add( sts[0]->hTcxEnc->tnsData[k].nFilters, 1 );
4959 6536 : move16();
4960 : /* When order parameter is evaluated as 0 and change in precision causes the flow to reach here,
4961 : this may result in crash later. Changing the filter type here so the order is taken here in further section */
4962 6536 : IF( pFilter[0]->order != 0 )
4963 : {
4964 6536 : pFilter[0]->filterType = TNS_FILTER_ON;
4965 6536 : move16();
4966 : }
4967 : ELSE
4968 : {
4969 0 : pFilter[0]->filterType = TNS_FILTER_ON_ZERO;
4970 0 : move16();
4971 : }
4972 6536 : sts[1]->hTcxEnc->tnsData[k].nFilters = add( sts[1]->hTcxEnc->tnsData[k].nFilters, 1 );
4973 6536 : move16();
4974 6536 : IF( pFilter[1]->order != 0 )
4975 : {
4976 6536 : pFilter[1]->filterType = TNS_FILTER_ON;
4977 6536 : move16();
4978 : }
4979 : ELSE
4980 : {
4981 0 : pFilter[1]->filterType = TNS_FILTER_ON_ZERO;
4982 0 : move16();
4983 : }
4984 : }
4985 : ELSE
4986 : {
4987 : Word16 maxEnergyChange_fx;
4988 651 : maxEnergyChange_fx = mac_r( L_mult( GetTCXMaxenergyChange_ivas_fx( sts[0]->hTranDet, isTCX10, NSUBBLOCKS, 3 ), 16384 ), GetTCXMaxenergyChange_ivas_fx( sts[1]->hTranDet, isTCX10, NSUBBLOCKS, 3 ), 16384 );
4989 :
4990 651 : IF( GE_16( maxEnergyChange_fx, shl( pTnsParameters[0]->minEnergyChange, Q3 - Q7 ) ) )
4991 : {
4992 641 : sts[0]->hTcxEnc->tnsData[k].nFilters = add( sts[0]->hTcxEnc->tnsData[k].nFilters, 1 );
4993 641 : move16();
4994 : /* When order parameter is evaluated as 0 and change in precision causes the flow to reach here,
4995 : this may result in crash later. Changing the filter type here so the order is taken here in further section */
4996 641 : IF( pFilter[0]->order != 0 )
4997 : {
4998 641 : pFilter[0]->filterType = TNS_FILTER_ON;
4999 641 : move16();
5000 : }
5001 : ELSE
5002 : {
5003 0 : pFilter[0]->filterType = TNS_FILTER_ON_ZERO;
5004 0 : move16();
5005 : }
5006 641 : sts[1]->hTcxEnc->tnsData[k].nFilters = add( sts[1]->hTcxEnc->tnsData[k].nFilters, 1 );
5007 641 : move16();
5008 641 : IF( pFilter[1]->order != 0 )
5009 : {
5010 641 : pFilter[1]->filterType = TNS_FILTER_ON;
5011 641 : move16();
5012 : }
5013 : ELSE
5014 : {
5015 0 : pFilter[1]->filterType = TNS_FILTER_ON_ZERO;
5016 0 : move16();
5017 : }
5018 : }
5019 : ELSE
5020 : {
5021 10 : pFilter[0]->filterType = TNS_FILTER_OFF;
5022 10 : move16();
5023 10 : pFilter[1]->filterType = TNS_FILTER_OFF;
5024 10 : move16();
5025 : }
5026 : }
5027 : }
5028 195593 : ELSE IF( sts[0]->hTcxEnc->tnsData[k].nFilters > 0 && sts[1]->hTcxEnc->tnsData[k].nFilters > 0 ) /* If a previous filter is turned on */
5029 : {
5030 239 : pFilter[0]->filterType = TNS_FILTER_ON_ZERO;
5031 239 : pFilter[1]->filterType = TNS_FILTER_ON_ZERO;
5032 239 : move16();
5033 239 : move16();
5034 239 : sts[0]->hTcxEnc->tnsData[k].nFilters = add( sts[0]->hTcxEnc->tnsData[k].nFilters, 1 );
5035 239 : move16();
5036 239 : sts[1]->hTcxEnc->tnsData[k].nFilters = add( sts[1]->hTcxEnc->tnsData[k].nFilters, 1 );
5037 239 : move16();
5038 : }
5039 195354 : ELSE IF( NE_16( sts[0]->hTcxEnc->tnsData[k].nFilters, sts[1]->hTcxEnc->tnsData[k].nFilters ) ) /* sanity check */
5040 : {
5041 0 : assert( 0 );
5042 : }
5043 : ELSE
5044 : {
5045 195354 : pFilter[0]->filterType = TNS_FILTER_OFF;
5046 195354 : move16();
5047 195354 : pFilter[1]->filterType = TNS_FILTER_OFF;
5048 195354 : move16();
5049 : }
5050 :
5051 202780 : test();
5052 202780 : test();
5053 202780 : IF( EQ_16( pFilter[0]->filterType, TNS_FILTER_ON ) && EQ_16( pFilter[1]->filterType, TNS_FILTER_ON ) && LT_32( sts[0]->element_brate, IVAS_80k ) )
5054 : {
5055 6071 : Word16 tmpIntValue = 0;
5056 6071 : move16();
5057 : Word16 tmpCoeff[TNS_MAX_FILTER_ORDER];
5058 6071 : Word16 i, maxOrder = s_max( pFilter[0]->order, pFilter[1]->order );
5059 :
5060 6071 : set16_fx( tmpCoeff, 0, TNS_MAX_FILTER_ORDER );
5061 45967 : FOR( i = 0; i < maxOrder; i++ )
5062 : {
5063 39896 : tmpIntValue = s_max( tmpIntValue, abs_s( sub( pFilter[0]->coefIndex[i], pFilter[1]->coefIndex[i] ) ) );
5064 : }
5065 :
5066 6071 : IF( EQ_16( tmpIntValue, 1 ) ) /* the TNS coefficients are sufficiently similar to equalize the two filters */
5067 : {
5068 27028 : FOR( i = maxOrder - 1; i >= 0; i-- )
5069 : {
5070 23467 : IF( LT_16( abs_s( pFilter[0]->coefIndex[i] ), abs_s( pFilter[1]->coefIndex[i] ) ) )
5071 : {
5072 4534 : tmpCoeff[i] = pFilter[0]->coefIndex[i];
5073 : }
5074 : ELSE
5075 : {
5076 18933 : tmpCoeff[i] = pFilter[1]->coefIndex[i];
5077 : }
5078 23467 : move16();
5079 23467 : IF( ( tmpIntValue > 0 ) && ( tmpCoeff[i] == 0 ) )
5080 : {
5081 5772 : maxOrder = sub( maxOrder, 1 );
5082 : }
5083 : ELSE
5084 : {
5085 17695 : tmpIntValue = 0;
5086 17695 : move16();
5087 : }
5088 : }
5089 : /* make sure that maxOrder is non zero and not all coefficients are zero (could happen in rare cases) */
5090 3561 : IF( maxOrder > 0 )
5091 : {
5092 32049 : FOR( i = TNS_MAX_FILTER_ORDER - 1; i >= 0; i-- )
5093 : {
5094 28488 : pFilter[0]->coefIndex[i] = pFilter[1]->coefIndex[i] = tmpCoeff[i];
5095 28488 : move16();
5096 28488 : move16();
5097 : }
5098 :
5099 3561 : pFilter[0]->order = pFilter[1]->order = maxOrder;
5100 3561 : move16();
5101 3561 : move16();
5102 : }
5103 : }
5104 : }
5105 : }
5106 : ELSE
5107 : {
5108 103436 : individual_decision[k] = 1;
5109 103436 : move16();
5110 : }
5111 : }
5112 :
5113 163360 : IF( individual_decision[k] == 0 )
5114 : {
5115 80425 : IF( ( sts[0]->hTcxEnc->tnsData[k].nFilters > 0 ) )
5116 : {
5117 3427 : sts[0]->hTcxEnc->fUseTns[k] = 1;
5118 : }
5119 : ELSE
5120 : {
5121 76998 : sts[0]->hTcxEnc->fUseTns[k] = 0;
5122 : }
5123 80425 : move16();
5124 :
5125 80425 : IF( ( sts[1]->hTcxEnc->tnsData[k].nFilters > 0 ) )
5126 : {
5127 3427 : sts[1]->hTcxEnc->fUseTns[k] = 1;
5128 : }
5129 : ELSE
5130 : {
5131 76998 : sts[1]->hTcxEnc->fUseTns[k] = 0;
5132 : }
5133 80425 : move16();
5134 : }
5135 : ELSE
5136 : {
5137 82935 : sts[0]->hTcxEnc->tnsData[k].nFilters = 0;
5138 82935 : move16();
5139 82935 : sts[1]->hTcxEnc->tnsData[k].nFilters = 0;
5140 82935 : move16();
5141 82935 : sts[0]->hTcxEnc->fUseTns[k] = 0;
5142 82935 : move16();
5143 82935 : sts[1]->hTcxEnc->fUseTns[k] = 0;
5144 82935 : move16();
5145 241761 : FOR( iFilter = sts[0]->hTcxCfg->pCurrentTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter-- )
5146 : {
5147 158826 : sts[0]->hTcxEnc->tnsData[k].filter[iFilter].filterType = TNS_FILTER_OFF;
5148 158826 : move16();
5149 158826 : sts[1]->hTcxEnc->tnsData[k].filter[iFilter].filterType = TNS_FILTER_OFF;
5150 158826 : move16();
5151 : }
5152 : }
5153 :
5154 163360 : test();
5155 163360 : test();
5156 163360 : test();
5157 163360 : IF( !bWhitenedDomain && individual_decision[k] == 0 &&
5158 : LT_32( L_shl_sat( maxPredGain_fx, sub( maxPredGain_e, PRED_GAIN_E ) ), TNS_GAIN_THRESHOLD_FOR_WHITE_FX_IN_Q23 ) &&
5159 : NE_16( sts[0]->hTcxEnc->transform_type[k], TCX_5 ) )
5160 : {
5161 39340 : sts[0]->hTcxEnc->bTnsOnWhithenedSpectra[k] = 1;
5162 39340 : move16();
5163 39340 : sts[1]->hTcxEnc->bTnsOnWhithenedSpectra[k] = 1;
5164 39340 : move16();
5165 39340 : sts[0]->hTcxEnc->tnsData[k].nFilters = 0;
5166 39340 : move16();
5167 39340 : sts[1]->hTcxEnc->tnsData[k].nFilters = 0;
5168 39340 : move16();
5169 39340 : sts[0]->hTcxEnc->fUseTns[k] = 0;
5170 39340 : move16();
5171 39340 : sts[1]->hTcxEnc->fUseTns[k] = 0;
5172 39340 : move16();
5173 111455 : FOR( iFilter = sts[0]->hTcxCfg->pCurrentTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter-- )
5174 : {
5175 72115 : ClearTnsFilterCoefficients( sts[0]->hTcxEnc->tnsData[k].filter + iFilter );
5176 72115 : ClearTnsFilterCoefficients( sts[1]->hTcxEnc->tnsData[k].filter + iFilter );
5177 : }
5178 : }
5179 :
5180 : /* maxPredictionGain_fx = L_max( maxPredictionGain_fx, maxPredGain_fx ); */
5181 163360 : IF( GT_32( maxPredGain_fx, L_shl_sat( maxPredictionGain_fx, sub( maxPredictionGain_e, maxPredGain_e ) ) ) ) /* exp: maxPredGain_e */
5182 : {
5183 0 : maxPredictionGain_fx = maxPredGain_fx;
5184 0 : maxPredictionGain_e = maxPredGain_e;
5185 0 : move32();
5186 0 : move16();
5187 : }
5188 : }
5189 : }
5190 : }
5191 : }
5192 :
5193 : /* individual decision for each channel */
5194 2058294 : FOR( ch = 0; ch < CPE_CHANNELS; ch++ )
5195 : {
5196 1372196 : IF( EQ_32( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
5197 : {
5198 139021 : CONTINUE;
5199 : }
5200 :
5201 : Word8 isTCX10;
5202 :
5203 1233175 : IF( EQ_16( sts[ch]->hTcxEnc->tcxMode, TCX_20 ) )
5204 : {
5205 1205695 : nSubframes = 1;
5206 1205695 : isTCX10 = 0;
5207 : }
5208 : ELSE
5209 : {
5210 27480 : nSubframes = NB_DIV;
5211 27480 : isTCX10 = 1;
5212 : }
5213 1233175 : move16();
5214 1233175 : move16();
5215 :
5216 2493830 : FOR( k = 0; k < nSubframes; k++ )
5217 : {
5218 1260655 : test();
5219 1260655 : test();
5220 1260655 : test();
5221 1260655 : test();
5222 1260655 : IF( sts[ch]->hTcxCfg->fIsTNSAllowed && ( individual_decision[k] || mct_on ) &&
5223 : ( !bWhitenedDomain || sts[ch]->hTcxEnc->bTnsOnWhithenedSpectra[k] ) )
5224 : {
5225 1079059 : Word32 maxPredGain_fx = -ONE_IN_Q31; // Q31
5226 1079059 : move32();
5227 1079059 : Word16 maxPredGain_e = 0;
5228 1079059 : move16();
5229 1079059 : sts[ch]->hTcxCfg->pCurrentTnsConfig = &sts[ch]->hTcxCfg->tnsConfig[sts[ch]->hTcxEnc->transform_type[k] == TCX_20][( k == 0 ) && ( sts[ch]->last_core == ACELP_CORE )];
5230 :
5231 3155282 : FOR( iFilter = sts[ch]->hTcxCfg->pCurrentTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter-- )
5232 : {
5233 : STnsFilter *pFilter;
5234 : struct TnsParameters const *pTnsParameters;
5235 2076223 : pFilter = sts[ch]->hTcxEnc->tnsData[k].filter + iFilter;
5236 2076223 : pTnsParameters = sts[ch]->hTcxCfg->pCurrentTnsConfig->pTnsParameters + iFilter;
5237 :
5238 : // maxPredGain_fx = L_max( maxPredGain_fx, pFilter->predictionGain32 );
5239 2076223 : IF( GT_32( pFilter->predictionGain32, L_shl_sat( maxPredGain_fx, sub( maxPredGain_e, pFilter->predictionGain_e ) ) ) ) /* pFilter->predictionGain_e */
5240 : {
5241 1414420 : maxPredGain_fx = pFilter->predictionGain32;
5242 1414420 : maxPredGain_e = pFilter->predictionGain_e;
5243 1414420 : move32();
5244 1414420 : move16();
5245 : }
5246 :
5247 2076223 : test();
5248 2076223 : IF( GT_32( pFilter->predictionGain32, L_shl_sat( L_deposit_h( pTnsParameters->minPredictionGain ), sub( PRED_GAIN_E, pFilter->predictionGain_e ) ) ) || GT_16( pFilter->avgSqrCoef, pTnsParameters->minAvgSqrCoef ) )
5249 : {
5250 128940 : test();
5251 128940 : test();
5252 128940 : IF( sts[ch]->hTcxEnc->tnsData[k].nFilters > 0 || isTCX10 || LT_16( sts[ch]->hTcxEnc->tcxltp_gain, 19660 /*.6f in Q15*/ ) )
5253 : {
5254 110837 : sts[ch]->hTcxEnc->tnsData[k].nFilters = add( sts[ch]->hTcxEnc->tnsData[k].nFilters, 1 );
5255 110837 : move16();
5256 : /* When order parameter is evaluated as 0 and change in precision causes the flow to reach here,
5257 : this may result in crash later. Changing the filter type here so the order is taken here in further section */
5258 110837 : IF( pFilter->order != 0 )
5259 : {
5260 110837 : pFilter->filterType = TNS_FILTER_ON;
5261 110837 : move16();
5262 : }
5263 : ELSE
5264 : {
5265 0 : pFilter->filterType = TNS_FILTER_ON_ZERO;
5266 0 : move16();
5267 : }
5268 : }
5269 : ELSE
5270 : {
5271 18103 : Word16 maxEnergyChange_fx = GetTCXMaxenergyChange_ivas_fx( sts[ch]->hTranDet, isTCX10, NSUBBLOCKS, 3 );
5272 :
5273 18103 : IF( GE_16( maxEnergyChange_fx, shl( pTnsParameters->minEnergyChange, Q3 - Q7 ) ) )
5274 : {
5275 17093 : sts[ch]->hTcxEnc->tnsData[k].nFilters = add( sts[ch]->hTcxEnc->tnsData[k].nFilters, 1 );
5276 17093 : move16();
5277 : /* When order parameter is evaluated as 0 and change in precision causes the flow to reach here,
5278 : this may result in crash later. Changing the filter type here so the order is taken here in further section */
5279 17093 : IF( pFilter->order != 0 )
5280 : {
5281 17093 : pFilter->filterType = TNS_FILTER_ON;
5282 17093 : move16();
5283 : }
5284 : ELSE
5285 : {
5286 0 : pFilter->filterType = TNS_FILTER_ON_ZERO;
5287 0 : move16();
5288 : }
5289 : }
5290 : ELSE
5291 : {
5292 1010 : pFilter->filterType = TNS_FILTER_OFF;
5293 1010 : move16();
5294 : }
5295 : }
5296 : }
5297 1947283 : ELSE IF( sts[ch]->hTcxEnc->tnsData[k].nFilters > 0 ) /* If a previous filter is turned on */
5298 : {
5299 11926 : pFilter->filterType = TNS_FILTER_ON_ZERO;
5300 11926 : move16();
5301 11926 : sts[ch]->hTcxEnc->tnsData[k].nFilters = add( sts[ch]->hTcxEnc->tnsData[k].nFilters, 1 );
5302 11926 : move16();
5303 : }
5304 : ELSE
5305 : {
5306 1935357 : pFilter->filterType = TNS_FILTER_OFF;
5307 1935357 : move16();
5308 : }
5309 : }
5310 :
5311 1079059 : sts[ch]->hTcxEnc->fUseTns[k] = 0;
5312 1079059 : move16();
5313 1079059 : if ( sts[ch]->hTcxEnc->tnsData[k].nFilters > 0 )
5314 : {
5315 117933 : sts[ch]->hTcxEnc->fUseTns[k] = 1;
5316 117933 : move16();
5317 : }
5318 :
5319 1079059 : test();
5320 1079059 : test();
5321 1079059 : IF( !bWhitenedDomain && LT_32( L_shl_sat( maxPredGain_fx, sub( maxPredGain_e, PRED_GAIN_E ) ), TNS_GAIN_THRESHOLD_FOR_WHITE_FX_IN_Q23 ) && NE_16( sts[ch]->hTcxEnc->transform_type[k], TCX_5 ) )
5322 : {
5323 537773 : sts[ch]->hTcxEnc->fUseTns[k] = 0;
5324 537773 : move16();
5325 537773 : sts[ch]->hTcxEnc->bTnsOnWhithenedSpectra[k] = 1;
5326 537773 : move16();
5327 537773 : sts[ch]->hTcxEnc->tnsData[k].nFilters = 0;
5328 537773 : move16();
5329 1571413 : FOR( iFilter = sts[ch]->hTcxCfg->pCurrentTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter-- )
5330 : {
5331 1033640 : ClearTnsFilterCoefficients( sts[ch]->hTcxEnc->tnsData[k].filter + iFilter );
5332 1033640 : sts[ch]->hTcxEnc->tnsData[k].filter[iFilter].filterType = TNS_FILTER_OFF;
5333 1033640 : move16();
5334 : }
5335 : }
5336 :
5337 : // maxPredictionGain_fx = L_max( maxPredictionGain_fx, maxPredGain_fx );
5338 1079059 : IF( GT_32( maxPredGain_fx, L_shl_sat( maxPredictionGain_fx, sub( maxPredictionGain_e, maxPredGain_e ) ) ) ) /* maxPredGain_e */
5339 : {
5340 778574 : maxPredictionGain_fx = maxPredGain_fx;
5341 778574 : maxPredictionGain_e = maxPredGain_e;
5342 778574 : move32();
5343 778574 : move16();
5344 : }
5345 : }
5346 : }
5347 : }
5348 :
5349 :
5350 : /* we have the decision, set filter data accordingly */
5351 2058294 : FOR( ch = 0; ch < CPE_CHANNELS; ch++ )
5352 : {
5353 1372196 : IF( EQ_16( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
5354 : {
5355 139021 : CONTINUE;
5356 : }
5357 :
5358 1233175 : IF( EQ_16( sts[ch]->hTcxEnc->tcxMode, TCX_20 ) )
5359 : {
5360 1205695 : nSubframes = 1;
5361 : }
5362 : ELSE
5363 : {
5364 27480 : nSubframes = NB_DIV;
5365 : }
5366 1233175 : move16();
5367 2493830 : FOR( k = 0; k < nSubframes; k++ )
5368 : {
5369 1260655 : test();
5370 1260655 : test();
5371 1260655 : IF( sts[ch]->hTcxCfg->fIsTNSAllowed && ( !bWhitenedDomain || sts[ch]->hTcxEnc->bTnsOnWhithenedSpectra[k] ) )
5372 : {
5373 1239909 : sts[ch]->hTcxCfg->pCurrentTnsConfig = &sts[ch]->hTcxCfg->tnsConfig[sts[ch]->hTcxEnc->transform_type[k] == TCX_20][( k == 0 ) && ( sts[ch]->last_core == ACELP_CORE )];
5374 :
5375 3610912 : FOR( iFilter = sts[ch]->hTcxCfg->pCurrentTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter-- )
5376 : {
5377 : STnsFilter *pFilter;
5378 2371003 : pFilter = sts[ch]->hTcxEnc->tnsData[k].filter + iFilter;
5379 2371003 : SWITCH( pFilter->filterType )
5380 : {
5381 2280966 : case TNS_FILTER_OFF:
5382 2280966 : ClearTnsFilterCoefficients( sts[ch]->hTcxEnc->tnsData[k].filter + iFilter );
5383 2280966 : BREAK;
5384 9100 : case TNS_FILTER_ON_ZERO:
5385 : /* Since TNS filter of order 0 is not allowed we have to signal in the stream filter of order 1 with the 0th coefficient equal to 0 */
5386 9100 : ClearTnsFilterCoefficients( pFilter );
5387 9100 : pFilter->order = 1;
5388 9100 : move16();
5389 9100 : BREAK;
5390 : }
5391 2371003 : }
5392 : }
5393 : }
5394 : }
5395 :
5396 : /* Apply filters, loop over channels */
5397 2058294 : FOR( ch = 0; ch < CPE_CHANNELS; ch++ )
5398 : {
5399 1372196 : st = sts[ch];
5400 1372196 : IF( EQ_32( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) )
5401 : {
5402 139021 : CONTINUE;
5403 : }
5404 :
5405 1233175 : IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) )
5406 : {
5407 1205695 : nSubframes = 1;
5408 : }
5409 : ELSE
5410 : {
5411 27480 : nSubframes = NB_DIV;
5412 : }
5413 1233175 : move16();
5414 :
5415 2493830 : FOR( k = 0; k < nSubframes; k++ )
5416 : {
5417 1260655 : test();
5418 1260655 : test();
5419 1260655 : test();
5420 1260655 : test();
5421 1260655 : test();
5422 1260655 : IF( bWhitenedDomain && ( ch > 0 ) && /* test for identical TNS filter data in both channels */
5423 : sts[0]->hTcxCfg->fIsTNSAllowed && sts[0]->hTcxEnc->fUseTns[k] &&
5424 : sts[1]->hTcxCfg->fIsTNSAllowed && sts[1]->hTcxEnc->fUseTns[k] )
5425 : {
5426 18361 : Word16 equalFilterData = 0;
5427 18361 : move16();
5428 18361 : test();
5429 18361 : test();
5430 36707 : if ( EQ_16( sts[0]->hTcxCfg->pCurrentTnsConfig->nMaxFilters, sts[1]->hTcxCfg->pCurrentTnsConfig->nMaxFilters ) &&
5431 34411 : EQ_16( sts[0]->hTcxEnc->bTnsOnWhithenedSpectra[k], sts[1]->hTcxEnc->bTnsOnWhithenedSpectra[k] ) &&
5432 16065 : EQ_16( sts[0]->hTcxEnc->tnsData[k].nFilters, sts[1]->hTcxEnc->tnsData[k].nFilters ) )
5433 : {
5434 14681 : equalFilterData = 1;
5435 14681 : move16();
5436 : }
5437 :
5438 18361 : IF( equalFilterData )
5439 : {
5440 30360 : FOR( iFilter = st->hTcxCfg->pCurrentTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter-- )
5441 : {
5442 26193 : const Word16 *pDataCh0 = (const Word16 *) &sts[0]->hTcxEnc->tnsData[k].filter[iFilter];
5443 26193 : const Word16 *pDataCh1 = (const Word16 *) &sts[1]->hTcxEnc->tnsData[k].filter[iFilter];
5444 26193 : Word16 i = 2 + TNS_MAX_FILTER_ORDER; /* excl. informative float data. Portable? */
5445 :
5446 26193 : move16();
5447 26193 : test();
5448 221461 : WHILE( ( i >= 0 ) && EQ_16( pDataCh0[i], pDataCh1[i] ) )
5449 : {
5450 195268 : test();
5451 195268 : i = sub( i, 1 );
5452 : }
5453 26193 : IF( i >= 0 )
5454 : {
5455 10514 : equalFilterData = 0;
5456 10514 : move16();
5457 10514 : BREAK;
5458 : }
5459 : }
5460 14681 : IF( equalFilterData )
5461 : {
5462 4167 : st->hTcxEnc->tnsData[k].nFilters = i_mult( st->hTcxEnc->tnsData[k].nFilters, -1 ); /* signals common TNS */
5463 4167 : move16();
5464 : }
5465 : }
5466 : }
5467 1260655 : test();
5468 1260655 : test();
5469 1260655 : IF( st->hTcxCfg->fIsTNSAllowed && ( !bWhitenedDomain || st->hTcxEnc->bTnsOnWhithenedSpectra[k] ) )
5470 : {
5471 1239909 : L_spec = st->hTcxCfg->pCurrentTnsConfig->iFilterBorders[0];
5472 1239909 : move16();
5473 1239909 : spectrum_fx = st->hTcxEnc->spectrum_fx[k];
5474 : /* If TNS should be used then get the residual after applying it inplace in the spectrum */
5475 1239909 : IF( st->hTcxEnc->fUseTns[k] )
5476 : {
5477 69828 : st->hTcxCfg->pCurrentTnsConfig = &st->hTcxCfg->tnsConfig[st->hTcxEnc->transform_type[k] == TCX_20][( k == 0 ) && ( st->last_core == ACELP_CORE )];
5478 :
5479 69828 : ApplyTnsFilter( st->hTcxCfg->pCurrentTnsConfig, &st->hTcxEnc->tnsData[k], spectrum_fx, 1 );
5480 : }
5481 :
5482 1239909 : IF( EQ_16( st->hTcxEnc->transform_type[k], TCX_5 ) )
5483 : {
5484 14213 : tcx5TnsUngrouping_fx( shr( L_frame, 2 ), shr( L_spec, 1 ), st->hTcxEnc->spectrum_fx[k], ENC );
5485 : }
5486 :
5487 1239909 : st->hTcxEnc->tnsData[k].tnsOnWhitenedSpectra = st->hTcxEnc->bTnsOnWhithenedSpectra[k];
5488 1239909 : move16();
5489 1239909 : EncodeTnsData_ivas_fx( st->hTcxCfg->pCurrentTnsConfig, &st->hTcxEnc->tnsData[k], param_core[ch] + k * NPRM_DIV + 1 + NOISE_FILL_RANGES + LTPSIZE, tnsSize[ch] + k, tnsBits[ch] + k );
5490 : }
5491 :
5492 1260655 : IF( EQ_16( st->hTcxEnc->transform_type[k], TCX_5 ) )
5493 : {
5494 28426 : tcx5SpectrumInterleaving_fx( st->hTcxCfg->tcx5SizeFB, st->hTcxEnc->spectrum_fx[k] );
5495 28426 : tcx5SpectrumInterleaving_fx( st->hTcxCfg->tcx5SizeFB, mdst_spectrum_fx[ch][k] );
5496 : }
5497 : }
5498 : }
5499 686098 : return;
5500 : }
|