Line data Source code
1 : /*====================================================================================
2 : EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
3 : ====================================================================================*/
4 :
5 : #include <assert.h>
6 : #include <stdint.h>
7 : #include "options.h"
8 : #include "basop_util.h"
9 : #include "options.h"
10 : #include "rom_basop_util.h"
11 : #include "rom_com.h"
12 : #include "prot_fx.h"
13 : #include "prot_fx_enc.h"
14 : #include "ivas_prot_fx.h"
15 :
16 : #define FFT_SCALING_512 1073741824 // Q22
17 : #define FFT_SCALING_640 1342177280 // Q22
18 :
19 : #define DELTA_SHIFT 2
20 : #define DELTA_SHIFT_LD64 67108864l /*DELTA_SHIFT/64.0 Q31*/
21 : #define CNG_HS 4 /* 4 bit headroom for dot product */
22 : #define CNG_S 6 /* 1 sign bit, 6 bit integer part, 9 bit frational part for input and output data */
23 :
24 : /*-------------------------------------------------------------------
25 : * Local function prototypes
26 : *-------------------------------------------------------------------*/
27 : static void getmidbands( const Word16 *part, const Word16 npart, Word16 *midband, Word16 *psize, Word16 *psize_norm, Word16 *psize_norm_exp, Word16 *psize_inv );
28 :
29 :
30 : /*-------------------------------------------------------------------
31 : * createFdCngCom()
32 : *
33 : * Create an instance of type FD_CNG_COM
34 : *-------------------------------------------------------------------*/
35 6910 : ivas_error createFdCngCom_fx(
36 : HANDLE_FD_CNG_COM *hFdCngCom /* i/o: FD_CNG structure containing all buffers and variables */
37 : )
38 : {
39 : HANDLE_FD_CNG_COM hs;
40 :
41 : /* Allocate memory */
42 6910 : hs = (HANDLE_FD_CNG_COM) malloc( sizeof( FD_CNG_COM ) );
43 :
44 6910 : if ( hs == NULL )
45 : {
46 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FD CNG COM" );
47 : }
48 :
49 6910 : *hFdCngCom = hs;
50 :
51 6910 : return IVAS_ERR_OK;
52 : }
53 : /*-------------------------------------------------------------------
54 : * initFdCngCom()
55 : *
56 : *
57 : *-------------------------------------------------------------------*/
58 :
59 6427 : void ivas_initFdCngCom_fx( HANDLE_FD_CNG_COM hFdCngCom, Word16 scale )
60 : {
61 : /* Calculate CLDFB scaling factor */
62 : /* shl(i_mult2(scale, scale), 3) does not fit in 16 bit */
63 : /*hFdCngCom->scalingFactor = div_s(1, shl(i_mult2(scale, scale), 3));*/
64 6427 : assert( 2048 /*1.0/(1<<4) Q15*/ < mult( scale, scale ) );
65 : /* Exponent invScalingFactor: -16 = -(2*7 (scale) + 2 (8.0) */
66 6427 : hFdCngCom->invScalingFactor = shl( mult( scale, scale ), 1 );
67 : /* Exponent scalingFactor: -15 = -(2*7 (scale) + 2 (8.0) - 1 (1.0)) */
68 6427 : hFdCngCom->scalingFactor = div_s( 0x4000, hFdCngCom->invScalingFactor );
69 :
70 : /* Initialize the overlap-add */
71 6427 : set16_fx( hFdCngCom->timeDomainBuffer, 0, L_FRAME16k );
72 6427 : hFdCngCom->olapBufferAna = NULL;
73 6427 : set16_fx( hFdCngCom->olapBufferAna_fx, 0, FFTLEN );
74 :
75 6427 : move16();
76 6427 : set16_fx( hFdCngCom->olapBufferSynth, 0, FFTLEN );
77 6427 : hFdCngCom->olapBufferSynth2 = NULL;
78 6427 : move16();
79 :
80 : /* Initialize the comfort noise generation */
81 6427 : set32_fx( hFdCngCom->fftBuffer, 0, FFTLEN );
82 6427 : set32_fx( hFdCngCom->cngNoiseLevel, 0, FFTCLDFBLEN );
83 6427 : set16_fx( &hFdCngCom->cngNoiseLevelExp, 0, 1 );
84 :
85 : /* Initialize quantizer */
86 6427 : set32_fx( hFdCngCom->sidNoiseEst, 0, NPART );
87 6427 : set16_fx( &hFdCngCom->sidNoiseEstExp, 0, 1 );
88 6427 : set16_fx( hFdCngCom->A_cng, 0, M + 1 );
89 6427 : hFdCngCom->A_cng[0] = 4096 /*1.f Q12*/; /* 3Q12 */
90 6427 : move16();
91 :
92 : /* Set some counters and flags */
93 6427 : hFdCngCom->inactive_frame_counter = 0; /* Either SID or zero frames */
94 6427 : move16();
95 6427 : hFdCngCom->active_frame_counter = 0;
96 6427 : move16();
97 6427 : hFdCngCom->frame_type_previous = ACTIVE_FRAME;
98 6427 : move16();
99 6427 : hFdCngCom->flag_noisy_speech = 0;
100 6427 : move16();
101 6427 : hFdCngCom->likelihood_noisy_speech = 0;
102 6427 : move16();
103 6427 : hFdCngCom->numCoreBands = 0;
104 6427 : move16();
105 6427 : hFdCngCom->stopBand = 0;
106 6427 : move16();
107 6427 : hFdCngCom->startBand = 0;
108 6427 : move16();
109 6427 : hFdCngCom->stopFFTbin = 0;
110 6427 : move16();
111 6427 : hFdCngCom->frameSize = 0;
112 6427 : move16();
113 6427 : hFdCngCom->fftlen = 0;
114 6427 : move16();
115 6427 : hFdCngCom->seed = 0;
116 6427 : move16();
117 6427 : hFdCngCom->seed2 = 1;
118 6427 : move16();
119 6427 : hFdCngCom->seed3 = 2;
120 6427 : move16();
121 6427 : hFdCngCom->CngBitrate = -1;
122 6427 : move16();
123 6427 : hFdCngCom->olapBufferSynth_exp = 0;
124 6427 : move16();
125 :
126 : /* Initialize noise estimation algorithm */
127 6427 : set32_fx( hFdCngCom->periodog, 0, PERIODOGLEN );
128 6427 : mhvals( MSNUMSUBFR * MSSUBFRLEN, &( hFdCngCom->msM_win ) );
129 6427 : mhvals( MSSUBFRLEN, &( hFdCngCom->msM_subwin ) );
130 6427 : set32_fx( hFdCngCom->msPeriodogSum, 0, 2 );
131 6427 : hFdCngCom->msPeriodogSum_exp[0] = 0;
132 6427 : move16();
133 6427 : hFdCngCom->msPeriodogSum_exp[1] = 0;
134 6427 : move16();
135 6427 : set32_fx( hFdCngCom->msPsdSum, 0, 2 );
136 6427 : set16_fx( hFdCngCom->msSlope, 0, 2 );
137 6427 : set32_fx( hFdCngCom->msQeqInvAv, 0, 2 );
138 6427 : hFdCngCom->msQeqInvAv_exp[0] = 0;
139 6427 : move16();
140 6427 : hFdCngCom->msQeqInvAv_exp[1] = 0;
141 6427 : move16();
142 6427 : hFdCngCom->msFrCnt_init_counter = 0;
143 6427 : move16();
144 6427 : hFdCngCom->msFrCnt_init_thresh = 1;
145 6427 : move16();
146 6427 : hFdCngCom->init_old = 0;
147 6427 : move16();
148 6427 : hFdCngCom->offsetflag = 0;
149 6427 : move16();
150 6427 : hFdCngCom->msFrCnt = MSSUBFRLEN;
151 6427 : move16();
152 6427 : hFdCngCom->msMinBufferPtr = 0;
153 6427 : move16();
154 6427 : hFdCngCom->msAlphaCor[0] = 644245120l /*0.3f Q31*/;
155 6427 : move16();
156 6427 : hFdCngCom->msAlphaCor[1] = 644245120l /*0.3f Q31*/;
157 6427 : move16();
158 6427 : set16_fx( hFdCngCom->psize, 0, NPART );
159 : /* Initialize exponents */
160 6427 : hFdCngCom->exp_cldfb_periodog = 0;
161 6427 : move16();
162 :
163 6427 : hFdCngCom->coherence_fx = 16384; /* 0.5 in Q15 */
164 6427 : move16();
165 :
166 6427 : set32_fx( hFdCngCom->olapBufferSynth_fx, 0, FFTLEN );
167 6427 : set32_fx( hFdCngCom->olapBufferSynth2_fx, 0, FFTLEN );
168 6427 : set32_fx( hFdCngCom->exc_cng_32fx, 0, L_FRAME16k );
169 6427 : set16_fx( hFdCngCom->exc_cng, 0, L_FRAME16k );
170 :
171 6427 : return;
172 : }
173 483 : void initFdCngCom( HANDLE_FD_CNG_COM hFdCngCom, Word16 scale )
174 : {
175 : /* Calculate CLDFB scaling factor */
176 : /* shl(i_mult2(scale, scale), 3) does not fit in 16 bit */
177 : /*hFdCngCom->scalingFactor = div_s(1, shl(i_mult2(scale, scale), 3));*/
178 483 : assert( 2048 /*1.0/(1<<4) Q15*/ < mult( scale, scale ) );
179 : /* Exponent invScalingFactor: -16 = -(2*7 (scale) + 2 (8.0) */
180 483 : hFdCngCom->invScalingFactor = shl( mult( scale, scale ), 1 );
181 483 : move16();
182 : /* Exponent scalingFactor: -15 = -(2*7 (scale) + 2 (8.0) - 1 (1.0)) */
183 483 : hFdCngCom->scalingFactor = div_s( 0x4000, hFdCngCom->invScalingFactor );
184 483 : move16();
185 :
186 : /* Initialize the overlap-add */
187 483 : set16_fx( hFdCngCom->timeDomainBuffer, 0, L_FRAME16k );
188 483 : hFdCngCom->olapBufferAna = NULL;
189 483 : set16_fx( hFdCngCom->olapBufferAna_fx, 0, FFTLEN );
190 :
191 483 : set16_fx( hFdCngCom->olapBufferSynth, 0, FFTLEN );
192 483 : hFdCngCom->olapBufferSynth2 = NULL;
193 :
194 : /* Initialize the comfort noise generation */
195 483 : set32_fx( hFdCngCom->fftBuffer, 0, FFTLEN );
196 483 : set32_fx( hFdCngCom->cngNoiseLevel, 0, FFTCLDFBLEN );
197 483 : set16_fx( &hFdCngCom->cngNoiseLevelExp, 0, 1 );
198 :
199 : /* Initialize quantizer */
200 483 : set32_fx( hFdCngCom->sidNoiseEst, 0, NPART );
201 483 : set16_fx( &hFdCngCom->sidNoiseEstExp, 0, 1 );
202 483 : set16_fx( hFdCngCom->A_cng, 0, M + 1 );
203 483 : hFdCngCom->A_cng[0] = 4096 /*1.f Q12*/; /* 3Q12 */
204 483 : move16();
205 :
206 : /* Set some counters and flags */
207 483 : hFdCngCom->inactive_frame_counter = 0; /* Either SID or zero frames */
208 483 : move16();
209 483 : hFdCngCom->active_frame_counter = 0;
210 483 : move16();
211 483 : hFdCngCom->frame_type_previous = ACTIVE_FRAME;
212 483 : move16();
213 483 : hFdCngCom->flag_noisy_speech = 0;
214 483 : move16();
215 483 : hFdCngCom->likelihood_noisy_speech = 0;
216 483 : move16();
217 483 : hFdCngCom->numCoreBands = 0;
218 483 : move16();
219 483 : hFdCngCom->stopBand = 0;
220 483 : move16();
221 483 : hFdCngCom->startBand = 0;
222 483 : move16();
223 483 : hFdCngCom->stopFFTbin = 0;
224 483 : move16();
225 483 : hFdCngCom->frameSize = 0;
226 483 : move16();
227 483 : hFdCngCom->fftlen = 0;
228 483 : move16();
229 483 : hFdCngCom->seed = 0;
230 483 : move16();
231 : // hFdCngCom->seed2 = 1;
232 : // move16();
233 : // hFdCngCom->seed3 = 2;
234 : // move16();
235 483 : hFdCngCom->CngBitrate = -1;
236 483 : move16();
237 :
238 : /* Initialize noise estimation algorithm */
239 483 : set32_fx( hFdCngCom->periodog, 0, PERIODOGLEN );
240 483 : mhvals( MSNUMSUBFR * MSSUBFRLEN, &( hFdCngCom->msM_win ) );
241 483 : mhvals( MSSUBFRLEN, &( hFdCngCom->msM_subwin ) );
242 483 : set32_fx( hFdCngCom->msPeriodogSum, 0, 2 );
243 483 : hFdCngCom->msPeriodogSum_exp[0] = 0;
244 483 : move16();
245 483 : hFdCngCom->msPeriodogSum_exp[1] = 0;
246 483 : move16();
247 483 : set32_fx( hFdCngCom->msPsdSum, 0, 2 );
248 483 : set16_fx( hFdCngCom->msSlope, 0, 2 );
249 483 : set32_fx( hFdCngCom->msQeqInvAv, 0, 2 );
250 483 : hFdCngCom->msQeqInvAv_exp[0] = 0;
251 483 : move16();
252 483 : hFdCngCom->msQeqInvAv_exp[1] = 0;
253 483 : move16();
254 483 : hFdCngCom->msFrCnt_init_counter = 0;
255 483 : move16();
256 483 : hFdCngCom->msFrCnt_init_thresh = 1;
257 483 : move16();
258 483 : hFdCngCom->init_old = 0;
259 483 : move16();
260 483 : hFdCngCom->offsetflag = 0;
261 483 : move16();
262 483 : hFdCngCom->msFrCnt = MSSUBFRLEN;
263 483 : move16();
264 483 : hFdCngCom->msMinBufferPtr = 0;
265 483 : move16();
266 483 : hFdCngCom->msAlphaCor[0] = 644245120l /*0.3f Q31*/;
267 483 : move16();
268 483 : hFdCngCom->msAlphaCor[1] = 644245120l /*0.3f Q31*/;
269 483 : move16();
270 483 : set16_fx( hFdCngCom->psize, 0, NPART );
271 : /* Initialize exponents */
272 483 : hFdCngCom->exp_cldfb_periodog = 0;
273 483 : move16();
274 :
275 483 : return;
276 : }
277 :
278 : /*-------------------------------------------------------------------
279 : * deleteFdCngCom()
280 : *
281 : * Delete an instance of type FD_CNG_COM
282 : *-------------------------------------------------------------------*/
283 6910 : void deleteFdCngCom_fx( HANDLE_FD_CNG_COM *hFdCngCom ) /* i/o: Contains the variables related to the CLDFB-based CNG process */
284 : {
285 : HANDLE_FD_CNG_COM hsCom;
286 6910 : hsCom = *hFdCngCom;
287 6910 : move16();
288 6910 : IF( hsCom != NULL )
289 : {
290 6910 : free( hsCom );
291 6910 : *hFdCngCom = NULL;
292 6910 : move16();
293 : }
294 6910 : }
295 :
296 : /*-------------------------------------------------------------------
297 : * initPartitions()
298 : *
299 : * Initialize the spectral partitioning
300 : *-------------------------------------------------------------------*/
301 1096668 : void initPartitions(
302 : const Word16 *part_in,
303 : const Word16 npart_in,
304 : const Word16 startBand,
305 : const Word16 stopBand,
306 : Word16 *part_out,
307 : Word16 *npart_out,
308 : Word16 *midband,
309 : Word16 *psize,
310 : Word16 *psize_norm,
311 : Word16 *psize_norm_exp,
312 : Word16 *psize_inv,
313 : const Word16 stopBandFR )
314 : {
315 : Word16 i, j, len_out, tmp16;
316 :
317 :
318 1096668 : IF( part_in != NULL )
319 : {
320 1096668 : len_out = 0;
321 1096668 : move16();
322 1096668 : IF( GT_16( stopBandFR, startBand ) )
323 : {
324 530341 : len_out = sub( stopBandFR, startBand );
325 20683299 : FOR( i = 0; i < len_out; i++ )
326 : {
327 20152958 : part_out[i] = i;
328 20152958 : move16();
329 : }
330 : }
331 35357043 : FOR( j = 0; j < npart_in; j++ )
332 : {
333 34260403 : IF( GE_16( part_in[j], stopBand ) )
334 : {
335 28 : BREAK;
336 : }
337 34260375 : tmp16 = sub( part_in[j], startBand );
338 34260375 : test();
339 34260375 : if ( GE_16( part_in[j], stopBandFR ) && tmp16 >= 0 )
340 : {
341 25774919 : part_out[len_out++] = tmp16;
342 25774919 : move16();
343 : }
344 : }
345 : }
346 : ELSE
347 : {
348 0 : len_out = sub( stopBand, startBand );
349 0 : FOR( i = 0; i < len_out; i++ )
350 : {
351 0 : part_out[i] = i;
352 0 : move16();
353 : }
354 : }
355 :
356 1096668 : *npart_out = len_out;
357 1096668 : move16();
358 1096668 : getmidbands( part_out, len_out, midband, psize, psize_norm, psize_norm_exp, psize_inv );
359 1096668 : }
360 :
361 :
362 : /*-------------------------------------------------------------------
363 : * compress_range()
364 : *
365 : * Apply some dynamic range compression based on the log
366 : *-------------------------------------------------------------------*/
367 166385 : void compress_range(
368 : Word32 *in, // Q(31 - in_exp)
369 : Word16 in_exp,
370 : Word16 *out,
371 : const Word16 len )
372 : {
373 : Word16 i;
374 : Word32 in_s;
375 : Word32 one_s;
376 : Word32 in_exp32;
377 : Word32 L_tmp;
378 :
379 :
380 : /* out = log2( 1 + in ) */
381 166385 : IF( in_exp >= 0 )
382 : {
383 143468 : one_s = L_shr( 1073741824l /*0.5 Q31*/, in_exp ); // Q(31 - in_exp)
384 143468 : in_exp32 = L_shl( L_deposit_l( add( in_exp, 1 ) ), WORD32_BITS - 1 - LD_DATA_SCALE );
385 4775879 : FOR( i = 0; i < len; i++ )
386 : {
387 4632411 : in_s = L_add( L_shr( in[i], 1 ), one_s ); // Q(31 - in_exp)
388 4632411 : L_tmp = L_add( BASOP_Util_Log2( in_s ), in_exp32 );
389 4632411 : if ( in_s == 0 )
390 : {
391 42339 : out[i] = 0;
392 42339 : move16();
393 : }
394 4632411 : if ( in_s != 0 )
395 : {
396 4590072 : out[i] = extract_h( L_tmp );
397 4590072 : move16();
398 : }
399 4632411 : if ( out[i] == 0 )
400 : {
401 142942 : out[i] = 1;
402 142942 : move16();
403 : }
404 : }
405 : }
406 : ELSE
407 : {
408 22917 : in_exp = sub( in_exp, 1 );
409 22917 : in_exp32 = L_shl( L_deposit_l( 1 ), WORD32_BITS - 1 - LD_DATA_SCALE );
410 911073 : FOR( i = 0; i < len; i++ )
411 : {
412 888156 : L_tmp = L_add( BASOP_Util_Log2( L_add( L_shl( in[i], in_exp ), 1073741824l /*0.5 Q31*/ ) ), in_exp32 );
413 888156 : if ( in[i] == 0 )
414 : {
415 15776 : out[i] = 0;
416 15776 : move16();
417 : }
418 888156 : if ( in[i] != 0 )
419 : {
420 872380 : out[i] = extract_h( L_tmp );
421 872380 : move16();
422 : }
423 888156 : if ( out[i] == 0 )
424 : {
425 247339 : out[i] = 1;
426 247339 : move16();
427 : }
428 : }
429 : }
430 166385 : }
431 :
432 : /*-------------------------------------------------------------------
433 : * expand_range()
434 : *
435 : * Apply some dynamic range expansion to undo the compression
436 : *-------------------------------------------------------------------*/
437 3115 : void expand_range(
438 : Word16 *in, // Q15
439 : Word32 *out, // Q(31 - out_exp)
440 : Word16 *out_exp,
441 : const Word16 len )
442 : {
443 : Word16 i;
444 : Word16 s;
445 : Word16 tmp;
446 : Word32 one_s, tmp32;
447 : Word16 maxVal;
448 : Word16 maxVal2;
449 :
450 :
451 3115 : maxVal = 0;
452 3115 : move16();
453 78437 : FOR( i = 0; i < len; i++ )
454 : {
455 75322 : maxVal = s_max( maxVal, in[i] ); // Q15
456 : }
457 :
458 3115 : maxVal2 = maxVal;
459 3115 : move16();
460 3115 : s = 0;
461 3115 : move16();
462 40866 : WHILE( maxVal >= 0 )
463 : {
464 37751 : maxVal = sub( maxVal, 512 /*0.015625 Q15*/ ); // Q15
465 37751 : s = add( s, 1 );
466 : }
467 3115 : tmp = sub( maxVal2, maxVal );
468 :
469 3115 : one_s = L_shr( 1073741824l /*0.5 Q31*/, sub( s, 1 ) ); // Q(31 - sub( s, 1 ))
470 3115 : tmp32 = L_shr( 726941l /*0.0003385080526823181 Q31*/, s );
471 : /* out = (2^(in) - 1) */
472 78437 : FOR( i = 0; i < len; i++ )
473 : {
474 75322 : out[i] = L_sub( BASOP_Util_InvLog2( L_deposit_h( sub( in[i], tmp ) ) ), one_s );
475 75322 : move32();
476 75322 : if ( out[i] == 0 )
477 : {
478 57 : out[i] = tmp32;
479 57 : move32();
480 : }
481 : }
482 3115 : *out_exp = s;
483 3115 : move16();
484 3115 : }
485 :
486 163270 : void expand_range_fx(
487 : Word32 *in, // Q25
488 : Word32 *out, // exp:out_exp
489 : Word16 *out_exp,
490 : const Word16 len )
491 : {
492 : Word16 i, tmp_e;
493 : Word32 maxVal, tmp32;
494 : Word16 maxOutExp;
495 :
496 163270 : const Word32 low_lim = 726940; /* 0.0003385080526823181f in Q31 */
497 163270 : move32();
498 :
499 : /* Find max possible output exponent. */
500 163270 : maxVal = 0;
501 163270 : move32();
502 5608515 : FOR( i = 0; i < len; i++ )
503 : {
504 5445245 : maxVal = L_max( maxVal, in[i] );
505 : }
506 163270 : tmp32 = BASOP_util_Pow2( maxVal, Q31 - Q25, &tmp_e );
507 163270 : maxOutExp = tmp_e;
508 163270 : move16();
509 :
510 : /* out = (2^(in) - 1) */
511 5608515 : FOR( i = 0; i < len; i++ )
512 : {
513 5445245 : tmp32 = BASOP_util_Pow2( in[i], Q31 - Q25, &tmp_e ); // 2^x
514 5445245 : tmp32 = L_sub( tmp32, L_shl( 1, sub( 31, tmp_e ) ) ); // 2^x - 1
515 5445245 : tmp32 = L_shr( tmp32, sub( maxOutExp, tmp_e ) ); // make exp same as maxExpOut
516 :
517 5445245 : out[i] = tmp32;
518 5445245 : move32();
519 :
520 5445245 : Word32 tmp_low_lim = L_shr( low_lim, maxOutExp );
521 5445245 : if ( LT_32( out[i], tmp_low_lim ) )
522 : {
523 16870 : out[i] = tmp_low_lim;
524 16870 : move32();
525 : }
526 : }
527 :
528 163270 : *out_exp = maxOutExp;
529 163270 : move16();
530 :
531 163270 : return;
532 : }
533 :
534 : /*-------------------------------------------------------------------
535 : * expand_range_var_e()
536 : *
537 : * Apply some dynamic range expansion to undo the compression. Similar
538 : * to expand_range but has variable input exponent.
539 : *
540 : *-------------------------------------------------------------------*/
541 0 : void expand_range_var_exp(
542 : Word16 *in,
543 : Word16 in_exp,
544 : Word32 *out,
545 : Word16 *out_exp,
546 : const Word16 len )
547 : {
548 : Word16 i, tmp_e;
549 : Word32 tmp32;
550 : Word16 maxVal, maxOutExp;
551 :
552 0 : const Word32 low_lim = 726940; /* 0.0003385080526823181f in Q31 */
553 0 : move32();
554 :
555 : /* Find max possible output exponent. */
556 0 : maxVal = 0;
557 0 : move16();
558 0 : FOR( i = 0; i < len; i++ )
559 : {
560 0 : maxVal = s_max( maxVal, in[i] );
561 : }
562 0 : tmp32 = BASOP_util_Pow2( L_deposit_h( maxVal ), in_exp, &tmp_e );
563 0 : maxOutExp = tmp_e;
564 0 : move16();
565 :
566 : /* out = (2^(in) - 1) */
567 0 : FOR( i = 0; i < len; i++ )
568 : {
569 0 : tmp32 = BASOP_util_Pow2( L_deposit_h( in[i] ), in_exp, &tmp_e ); // 2^x
570 0 : tmp32 = L_sub( tmp32, L_shl( 1, sub( 31, tmp_e ) ) ); // 2^x - 1
571 0 : tmp32 = L_shr( tmp32, sub( maxOutExp, tmp_e ) ); // make exp same as maxExpOut
572 :
573 0 : out[i] = tmp32;
574 0 : move32();
575 :
576 0 : Word32 tmp_low_lim = L_shr( low_lim, maxOutExp );
577 0 : if ( LT_32( out[i], tmp_low_lim ) )
578 : {
579 0 : out[i] = tmp_low_lim;
580 0 : move32();
581 : }
582 : }
583 :
584 0 : *out_exp = maxOutExp;
585 0 : move16();
586 :
587 0 : return;
588 : }
589 :
590 : /*-------------------------------------------------------------------
591 : * minimum_statistics()
592 : *
593 : * Noise estimation using Minimum Statistics (MS)
594 : *-------------------------------------------------------------------*/
595 :
596 3115 : void minimum_statistics(
597 : Word16 len, /* i : Total number of partitions (CLDFB or FFT) */
598 : Word16 lenFFT, /* i : Number of FFT partitions */
599 : Word16 *psize, /* i : Partition sizes, fractional */
600 : Word16 *msPeriodog, /* i : Periodogram (energies) */
601 : Word16 *msNoiseFloor, /* i/o: Noise floors (energies) */
602 : Word16 *msNoiseEst, /* i/o: Noise estimates (energies) */
603 : Word32 *msAlpha, /* i/o: Forgetting factors */
604 : Word16 *msPsd, /* i/o: Power Spectral Density (smoothed periodogram => energies) */
605 : Word16 *msPsdFirstMoment, /* i/o: PSD statistics of 1st order (energy means) */
606 : Word32 *msPsdSecondMoment, /* i/o: PSD statistics of 2nd order (energy variances) */
607 : Word32 *msMinBuf, /* i/o: Buffer of minima (energies) */
608 : Word32 *msBminWin, /* o : Bias correction factors */
609 : Word32 *msBminSubWin, /* o : Bias correction factors */
610 : Word32 *msCurrentMin, /* i/o: Local minima (energies) */
611 : Word32 *msCurrentMinOut, /* i/o: Local minima (energies) */
612 : Word32 *msCurrentMinSubWindow, /* i/o: Local minima (energies) */
613 : Word16 *msLocalMinFlag, /* i : Binary flag */
614 : Word16 *msNewMinFlag, /* i : Binary flag */
615 : Word16 *msPeriodogBuf, /* i/o: Buffer of periodograms (energies) */
616 : Word16 *msPeriodogBufPtr, /* i/o: Counter */
617 : HANDLE_FD_CNG_COM hFdCngCom /* i/o: FD_CNG structure containing all buffers and variables */
618 : )
619 : {
620 : Word16 i, j, k, s, s1, s2, s3;
621 : Word16 len2;
622 : Word16 current_len;
623 : Word16 start, stop, cnt;
624 : Word16 totsize;
625 : Word16 inv_totsize;
626 :
627 : Word32 tmp, tmp0, tmp1;
628 : Word32 scalar, scalar2, scalar3;
629 : Word32 snr;
630 : Word32 msAlphaHatMin2;
631 : Word32 BminCorr;
632 : Word32 QeqInvAv;
633 : Word32 *ptr;
634 : Word32 *msPsdSum;
635 : Word32 *msPeriodogSum;
636 :
637 : Word16 tmp16, tmp16_1;
638 : Word16 beta;
639 : Word16 slope;
640 : Word16 QeqInv;
641 : Word16 scalar16;
642 : Word16 scalar216;
643 : Word16 scalar316;
644 : Word16 msM_win;
645 : Word16 msM_subwin;
646 : Word16 msAlphaCorAlpha;
647 : Word16 msAlphaCorAlpha2;
648 : Word16 msPeriodogSum16;
649 : Word16 msNoiseFloor16;
650 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
651 3115 : Flag Overflow = 0;
652 3115 : move32();
653 : #endif
654 :
655 :
656 3115 : len2 = i_mult( MSNUMSUBFR, len );
657 :
658 3115 : msM_win = hFdCngCom->msM_win;
659 3115 : move16();
660 3115 : msM_subwin = hFdCngCom->msM_subwin;
661 3115 : move16();
662 :
663 3115 : msAlphaCorAlpha = MSALPHACORALPHA;
664 3115 : move16();
665 3115 : msAlphaCorAlpha2 = MSALPHACORALPHA2;
666 3115 : move16();
667 :
668 3115 : msPsdSum = hFdCngCom->msPsdSum;
669 3115 : msPeriodogSum = hFdCngCom->msPeriodogSum;
670 :
671 : /* No minimum statistics at initialization */
672 3115 : IF( LT_16( hFdCngCom->msFrCnt_init_counter, hFdCngCom->msFrCnt_init_thresh ) )
673 : {
674 18 : Copy( msPeriodog, msPsd, len ); /* 6Q9 */
675 18 : Copy( msPeriodog, msNoiseFloor, len ); /* 6Q9 */
676 18 : Copy( msPeriodog, msNoiseEst, len ); /* 6Q9 */
677 18 : Copy( msPeriodog, msPsdFirstMoment, len ); /* 6Q9 */
678 :
679 18 : set32_fx( msPsdSecondMoment, 0l /*0.0 Q31*/, len );
680 18 : msPeriodogSum[0] = dotp_s_fx( msPeriodog, psize, lenFFT, CNG_HS );
681 18 : move32();
682 18 : msPsdSum[0] = msPeriodogSum[0]; /* 16Q15 */
683 18 : move32();
684 :
685 18 : IF( LT_16( lenFFT, len ) )
686 : {
687 12 : msPeriodogSum[1] = dotp_s_fx( msPeriodog + lenFFT, psize + lenFFT, sub( len, lenFFT ), CNG_HS );
688 12 : move32();
689 12 : msPsdSum[1] = msPeriodogSum[1]; /* 16Q15 */
690 12 : move32();
691 : }
692 :
693 : /* Increment frame counter at initialization */
694 : /* Some frames are sometimes zero at initialization => ignore them */
695 18 : IF( LT_16( msPeriodog[0], hFdCngCom->init_old ) )
696 : {
697 5 : set32_fx( msCurrentMinOut, 2147483647l /*1.0 Q31*/, len ); /* 16Q15 */
698 5 : set32_fx( msCurrentMin, 2147483647l /*1.0 Q31*/, len ); /* 16Q15 */
699 5 : set32_fx( msMinBuf, 2147483647l /*1.0 Q31*/, len2 ); /* 16Q15 */
700 5 : set32_fx( msCurrentMinSubWindow, 2147483647l /*1.0 Q31*/, len ); /* 16Q15 */
701 :
702 5 : hFdCngCom->msFrCnt_init_counter = add( hFdCngCom->msFrCnt_init_counter, 1 );
703 5 : move16();
704 : }
705 18 : hFdCngCom->init_old = msPeriodog[0]; /* 6Q9 */
706 18 : move16();
707 : }
708 : ELSE
709 : {
710 : /* Consider the FFT and CLDFB bands separately
711 : - first iteration for FFT bins,
712 : - second one for CLDFB bands in SWB mode */
713 3097 : cnt = 0;
714 3097 : move16();
715 3097 : start = 0;
716 3097 : move16();
717 3097 : stop = lenFFT;
718 3097 : move16();
719 3097 : totsize = sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand );
720 9282 : WHILE( GT_16( stop, start ) )
721 : {
722 6185 : current_len = sub( stop, start );
723 :
724 : /* Compute smoothed correction factor for PSD smoothing */
725 :
726 : /* msPeriodogSum[cnt] with format 16Q15 */
727 6185 : msPeriodogSum[cnt] = dotp_s_fx( msPeriodog + start, psize + start, current_len, CNG_HS );
728 6185 : move32();
729 :
730 6185 : IF( msPeriodogSum[cnt] == 0 )
731 : {
732 0 : hFdCngCom->msAlphaCor[cnt] = Mpy_32_16_1( hFdCngCom->msAlphaCor[cnt], msAlphaCorAlpha );
733 0 : move32();
734 : }
735 : ELSE
736 : {
737 : /* calculate scalar with normalized msPeriodogSum[cnt], exponent -2*s1 */
738 6185 : s1 = norm_l( msPeriodogSum[cnt] );
739 6185 : msPeriodogSum16 = round_fx_sat( L_shl_sat( msPeriodogSum[cnt], s1 ) );
740 6185 : scalar = L_mult( msPeriodogSum16, msPeriodogSum16 );
741 :
742 : /* calculate difference, both elements in 16Q15 format, use absolute value
743 : to avoid -1.0 x -1.0 multiplications later */
744 6185 : scalar2 = L_abs( L_sub( msPsdSum[cnt], msPeriodogSum[cnt] ) );
745 :
746 6185 : s2 = WORD32_BITS - 1;
747 6185 : move16();
748 6185 : if ( scalar2 != 0 )
749 : {
750 : /* use absolute value to avoid -1.0 x -1.0 multiplications */
751 6184 : s2 = norm_l( scalar2 );
752 : }
753 6185 : scalar216 = round_fx_o( L_shl_o( scalar2, s2, &Overflow ), &Overflow );
754 6185 : scalar2 = L_mult( scalar216, scalar216 );
755 :
756 : /* find common exponent */
757 6185 : tmp16_1 = sub( s1, s2 );
758 6185 : tmp16 = s_min( shl( abs_s( tmp16_1 ), 1 ), WORD32_BITS - 1 );
759 6185 : if ( tmp16_1 < 0 )
760 : {
761 5341 : scalar2 = L_shr( scalar2, tmp16 );
762 : }
763 6185 : if ( tmp16_1 > 0 )
764 : {
765 315 : scalar = L_shr( scalar, tmp16 );
766 : }
767 :
768 :
769 : /* add scalar and scalar2, avoid overflows */
770 6185 : scalar = L_shr( scalar, 1 );
771 6185 : scalar2 = L_shr( scalar2, 1 );
772 6185 : scalar3 = L_add( scalar, scalar2 );
773 :
774 : /* calculate division */
775 6185 : scalar16 = BASOP_Util_Divide3232_uu_1616_Scale( scalar, scalar3, &s3 );
776 6185 : s3 = s_max( s3, -( WORD16_BITS - 1 ) );
777 6185 : scalar16 = shl( scalar16, s3 );
778 6185 : scalar16 = s_max( scalar16, MSALPHACORMAX );
779 :
780 6185 : hFdCngCom->msAlphaCor[cnt] = L_add( Mpy_32_16_1( hFdCngCom->msAlphaCor[cnt], msAlphaCorAlpha ),
781 : L_mult( scalar16, msAlphaCorAlpha2 ) );
782 6185 : move32();
783 : }
784 :
785 : /* Compute SNR */
786 :
787 : /* msPeriodogSum[cnt] with format 16Q15 */
788 6185 : snr = dotp_s_fx( msNoiseFloor + start, psize + start, current_len, CNG_HS );
789 :
790 6185 : IF( GT_32( L_shr( Mpy_32_16_1( msPsdSum[cnt], 18431 /*0.56246299817 Q15*/ ), 13 ), snr ) )
791 : {
792 0 : tmp0 = BASOP_Util_Log2( msPsdSum[cnt] );
793 0 : tmp1 = BASOP_Util_Log2( snr );
794 0 : tmp1 = L_sub( tmp0, tmp1 );
795 0 : tmp1 = Mpy_32_16_1( tmp1, MSSNREXP );
796 0 : msAlphaHatMin2 = BASOP_Util_InvLog2( tmp1 );
797 : }
798 : ELSE
799 : {
800 6185 : msAlphaHatMin2 = MSALPHAHATMIN;
801 6185 : move32();
802 : }
803 6185 : scalar = Mpy_32_16_1( hFdCngCom->msAlphaCor[cnt], MSALPHAMAX );
804 :
805 80848 : FOR( j = start; j < stop; j++ )
806 : {
807 : /* Compute optimal smoothing parameter for PSD estimation */
808 74663 : test();
809 74663 : IF( ( scalar == 0 ) || ( msNoiseFloor[j] == 0 ) )
810 : {
811 0 : msAlpha[j] = msAlphaHatMin2;
812 0 : move32();
813 : }
814 : ELSE
815 : {
816 : /* calculate scalar2 with normalized msNoiseFloor[j], exponent -2*s1 */
817 74663 : s1 = WORD16_BITS - 1;
818 74663 : move16();
819 74663 : if ( msNoiseFloor[j] != 0 )
820 : {
821 74663 : s1 = norm_s( msNoiseFloor[j] );
822 : }
823 74663 : msNoiseFloor16 = shl( msNoiseFloor[j], s1 );
824 74663 : scalar2 = L_mult( msNoiseFloor16, msNoiseFloor16 );
825 :
826 : /* calculate difference, both elements in 6Q9 format, use absolute value
827 : to avoid -1.0 x -1.0 multiplications later */
828 74663 : scalar316 = abs_s( sub( msPsd[j], msNoiseFloor[j] ) );
829 :
830 74663 : s2 = WORD16_BITS - 1;
831 74663 : move16();
832 74663 : if ( scalar316 != 0 )
833 : {
834 : /* use absolute value to avoid -1.0 x -1.0 multiplications */
835 74086 : s2 = norm_s( scalar316 );
836 : }
837 74663 : scalar316 = shl( scalar316, s2 );
838 74663 : scalar3 = L_mult( scalar316, scalar316 );
839 :
840 : /* find common exponent */
841 74663 : tmp16_1 = sub( s1, s2 );
842 74663 : tmp16 = s_min( shl( abs_s( tmp16_1 ), 1 ), WORD32_BITS - 1 );
843 74663 : if ( tmp16_1 < 0 )
844 : {
845 34063 : scalar3 = L_shr( scalar3, tmp16 );
846 : }
847 74663 : if ( tmp16_1 > 0 )
848 : {
849 36179 : scalar2 = L_shr( scalar2, tmp16 );
850 : }
851 :
852 : /* add scalar2 and scalar3, avoid overflows */
853 74663 : scalar2 = L_shr( scalar2, 1 );
854 74663 : scalar3 = L_shr( scalar3, 1 );
855 74663 : scalar3 = L_add( scalar2, scalar3 );
856 :
857 : /* calculate division */
858 74663 : tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( scalar2, scalar3, &s3 );
859 74663 : scalar2 = Mpy_32_16_1( scalar, tmp16 );
860 74663 : s3 = s_max( s3, -( WORD32_BITS - 1 ) );
861 74663 : scalar2 = L_shl( scalar2, s3 );
862 74663 : msAlpha[j] = L_max( scalar2, msAlphaHatMin2 );
863 74663 : move32();
864 : }
865 :
866 : /* Compute the PSD (smoothed periodogram) in each band */
867 74663 : msPsd[j] = round_fx( L_add( Mpy_32_16_1( msAlpha[j], msPsd[j] ),
868 74663 : Mpy_32_16_1( L_sub( 2147483647l /*1.0 Q31*/, msAlpha[j] ), msPeriodog[j] ) ) );
869 74663 : move16();
870 : }
871 6185 : msPsdSum[cnt] = dotp_s_fx( msPsd + start, psize + start, current_len, CNG_HS );
872 6185 : move32();
873 :
874 6185 : QeqInvAv = 0l /*0.0 Q31*/;
875 6185 : move32();
876 :
877 : /* scalar: 7Q24 format */
878 6185 : tmp = 1191182336l /*(float)(MSNUMSUBFR*MSSUBFRLEN)-1.0 Q24*/;
879 6185 : move32();
880 6185 : scalar = L_sub( tmp, L_mult( round_fx( tmp ), msM_win ) );
881 :
882 : /* scalar2: 4Q27 format */
883 6185 : tmp = 1476395008l /*(float)MSSUBFRLEN-1.0 Q27*/;
884 6185 : move32();
885 6185 : scalar2 = L_sub( tmp, L_mult( round_fx( tmp ), msM_subwin ) );
886 :
887 80848 : FOR( j = start; j < stop; j++ )
888 : {
889 : /* Compute variance of PSD */
890 74663 : tmp = L_min( msAlpha[j], MSBETAMAX_SQRT );
891 :
892 74663 : s1 = WORD32_BITS - 1;
893 74663 : move16();
894 74663 : if ( tmp != 0 )
895 : {
896 74663 : s1 = norm_l( tmp );
897 : }
898 74663 : s2 = shl( s1, 1 );
899 :
900 74663 : s2 = s_min( s2, WORD32_BITS - 1 );
901 :
902 : /* beta: scaled by s2 */
903 74663 : tmp16 = round_fx_o( L_shl_o( tmp, s1, &Overflow ), &Overflow );
904 74663 : beta = mult_r( tmp16, tmp16 );
905 :
906 : /* scalar3: scaled by s3 */
907 74663 : scalar3 = L_sub( L_deposit_l( msPsd[j] ), L_deposit_l( msPsdFirstMoment[j] ) );
908 74663 : s3 = norm_l( scalar3 );
909 74663 : scalar3 = L_shl( scalar3, s3 );
910 :
911 : /* msPsdFirstMoment: 6Q9 */
912 74663 : tmp = L_msu( L_mult( beta, msPsdFirstMoment[j] ), beta, msPsd[j] );
913 74663 : msPsdFirstMoment[j] = add( round_fx( L_shr( tmp, s2 ) ), msPsd[j] );
914 74663 : move16();
915 :
916 : /* msPsdSecondMoment: 12Q19 */
917 74663 : tmp0 = L_shr( Mpy_32_16_r( msPsdSecondMoment[j], beta ), s2 );
918 74663 : tmp1 = Mpy_32_32( scalar3, scalar3 );
919 74663 : tmp1 = L_shr( L_sub( tmp1, L_shr( Mpy_32_16_r( tmp1, beta ), s2 ) ), sub( shl( s3, 1 ), 32 ) );
920 74663 : msPsdSecondMoment[j] = L_add( tmp0, tmp1 );
921 74663 : move32();
922 :
923 : /* Compute inverse of amount of degrees of freedom */
924 74663 : QeqInv = MSQEQINVMAX;
925 74663 : move16();
926 :
927 74663 : IF( msNoiseFloor[j] != 0 /*0.0 Q15*/ )
928 : {
929 74663 : tmp = L_mult( msNoiseFloor[j], msNoiseFloor[j] );
930 74663 : tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( msPsdSecondMoment[j], tmp, &s );
931 : /* consider factor of 2 */
932 74663 : s = s_min( s_max( sub( s, 1 ), -( WORD16_BITS - 1 ) ), ( WORD16_BITS - 1 ) );
933 74663 : if ( s < 0 )
934 : {
935 46046 : QeqInv = shl( tmp16, s );
936 : }
937 74663 : QeqInv = s_min( QeqInv, MSQEQINVMAX );
938 : }
939 74663 : QeqInvAv = L_add( QeqInvAv, L_mult( QeqInv, psize[j] ) );
940 :
941 : /* Compute bias correction Bmin */
942 74663 : tmp0 = Mpy_32_16_1( scalar, QeqInv );
943 74663 : tmp1 = L_sub( 1073741824l /*0.5 Q31*/, L_mult( msM_win, QeqInv ) );
944 74663 : tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( tmp0, tmp1, &s );
945 74663 : msBminWin[j] = L_add( 134217728l /*1.0 Q27*/, L_shl( L_deposit_h( tmp16 ), add( s, 7 - 4 ) ) );
946 74663 : move32();
947 :
948 74663 : tmp0 = Mpy_32_16_1( scalar2, QeqInv );
949 74663 : tmp1 = L_sub( 1073741824l /*0.5 Q31*/, L_mult( msM_subwin, QeqInv ) );
950 74663 : tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( tmp0, tmp1, &s );
951 74663 : msBminSubWin[j] = L_add( 134217728l /*1.0 Q27*/, L_shl( L_deposit_h( tmp16 ), s ) );
952 74663 : move32();
953 : }
954 :
955 6185 : inv_totsize = BASOP_Util_Divide3232_uu_1616_Scale( 1, totsize, &s );
956 6185 : QeqInvAv = Mpy_32_16_1( QeqInvAv, inv_totsize );
957 6185 : QeqInvAv = L_shl( QeqInvAv, s );
958 6185 : hFdCngCom->msQeqInvAv[cnt] = QeqInvAv;
959 6185 : move32();
960 :
961 : /* New minimum? */
962 :
963 : /* exponent QeqInvAv: CNG_S, exponent MSAV: (4>>1) */
964 6185 : s = CNG_S + 2 * MSAV_EXP;
965 6185 : move16();
966 6185 : BminCorr = Mpy_32_16_1( Sqrt32( QeqInvAv, &s ), MSAV );
967 6185 : BminCorr = L_shl( BminCorr, sub( s, 1 ) );
968 :
969 : /* exponent BminCorr: 1 */
970 6185 : BminCorr = L_add( BminCorr, 1073741824l /*0.5 Q31*/ );
971 :
972 80848 : FOR( j = start; j < stop; j++ )
973 : {
974 : /* exponent scalar: CNG_S+1 */
975 74663 : scalar = Mpy_32_16_1( BminCorr, msPsd[j] );
976 :
977 : /* exponent scalar2: CNG_S+1+4 */
978 74663 : scalar2 = Mpy_32_32( scalar, msBminWin[j] );
979 :
980 74663 : msNewMinFlag[j] = 0;
981 74663 : move16();
982 74663 : IF( LT_32( scalar2, msCurrentMin[j] ) /*0.0 Q31*/ )
983 : {
984 29393 : msNewMinFlag[j] = 1;
985 29393 : move16();
986 : /* exponent msCurrentMin[j]: CNG_S+1+4 */
987 29393 : msCurrentMin[j] = scalar2;
988 29393 : move32();
989 : /* exponent msCurrentMinSubWindow[j]: CNG_S */
990 : BASOP_SATURATE_WARNING_OFF_EVS;
991 29393 : msCurrentMinSubWindow[j] = L_shl_o( Mpy_32_32( scalar, msBminSubWin[j] ), 5, &Overflow );
992 29393 : move32();
993 : BASOP_SATURATE_WARNING_ON_EVS;
994 : }
995 : }
996 :
997 : /* This is used later to identify local minima */
998 6185 : IF( GE_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
999 : {
1000 1899 : FOR( i = 0; i < 3; i++ )
1001 : {
1002 1482 : IF( LT_32( hFdCngCom->msQeqInvAv[cnt], L_shr( L_deposit_h( msQeqInvAv_thresh[i] ), CNG_S ) ) /*0.0 Q31*/ )
1003 : {
1004 103 : BREAK;
1005 : }
1006 : }
1007 : /* format 1Q30 */
1008 520 : hFdCngCom->msSlope[cnt] = msNoiseSlopeMax[i];
1009 520 : move32();
1010 : }
1011 :
1012 : /* Consider the FFT and CLDFB bands separately */
1013 6185 : start = stop;
1014 6185 : move16();
1015 6185 : stop = len;
1016 6185 : move16();
1017 6185 : totsize = sub( hFdCngCom->stopBand, hFdCngCom->stopFFTbin );
1018 6185 : cnt = add( cnt, 1 );
1019 : } /*while (stop > start)*/
1020 :
1021 : /* Update minimum between sub windows */
1022 3097 : test();
1023 3097 : IF( GT_16( hFdCngCom->msFrCnt, 1 ) && LT_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
1024 : {
1025 64560 : FOR( j = 0; j < len; j++ )
1026 : {
1027 61985 : if ( msNewMinFlag[j] > 0 )
1028 : {
1029 21487 : msLocalMinFlag[j] = 1;
1030 21487 : move16();
1031 : }
1032 61985 : if ( LT_32( msCurrentMinSubWindow[j], msCurrentMinOut[j] ) /*0.0 Q31*/ )
1033 : {
1034 : /* msCurrentMinOut[j] scaled with CNG_S */
1035 6040 : msCurrentMinOut[j] = msCurrentMinSubWindow[j];
1036 6040 : move32();
1037 : }
1038 : }
1039 : /* Get the current noise floor */
1040 2575 : Copy_Scale_sig_32_16( msCurrentMinOut, msNoiseFloor, len, -16 );
1041 : }
1042 : ELSE /* sub window complete */
1043 : {
1044 522 : IF( GE_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
1045 : {
1046 : /* Collect buffers */
1047 261 : Copy32( msCurrentMinSubWindow, msMinBuf + len * hFdCngCom->msMinBufferPtr, len );
1048 :
1049 : /* Compute minimum among all buffers */
1050 261 : Copy32( msMinBuf, msCurrentMinOut, len );
1051 261 : ptr = msMinBuf + len;
1052 1566 : FOR( i = 1; i < MSNUMSUBFR; i++ )
1053 : {
1054 33000 : FOR( j = 0; j < len; j++ )
1055 : {
1056 31695 : if ( LT_32( *ptr, msCurrentMinOut[j] ) /*0.0 Q31*/ )
1057 : {
1058 8983 : msCurrentMinOut[j] = *ptr;
1059 8983 : move32();
1060 : }
1061 31695 : ptr++;
1062 : }
1063 : }
1064 :
1065 : /* Take over local minima */
1066 261 : slope = hFdCngCom->msSlope[0];
1067 261 : move16();
1068 6600 : FOR( j = 0; j < len; j++ )
1069 : {
1070 6339 : if ( EQ_16( j, lenFFT ) )
1071 : {
1072 259 : slope = hFdCngCom->msSlope[1];
1073 259 : move16();
1074 : }
1075 6339 : test();
1076 6339 : test();
1077 6339 : test();
1078 6339 : IF( ( msLocalMinFlag[j] != 0 ) && ( msNewMinFlag[j] == 0 ) && ( LT_32( L_shr( msCurrentMinSubWindow[j], 1 ), Mpy_32_16_1( msCurrentMinOut[j], slope ) ) /*0.0 Q31*/ ) && ( GT_32( msCurrentMinSubWindow[j], msCurrentMinOut[j] ) /*0.0 Q31*/ ) )
1079 : {
1080 235 : msCurrentMinOut[j] = msCurrentMinSubWindow[j];
1081 235 : move32();
1082 235 : i = j;
1083 235 : move16();
1084 1645 : FOR( k = 0; k < MSNUMSUBFR; k++ )
1085 : {
1086 1410 : msMinBuf[i] = msCurrentMinOut[j];
1087 1410 : move32();
1088 1410 : i = add( i, len );
1089 : }
1090 : }
1091 : }
1092 :
1093 : /* Reset */
1094 261 : set16_fx( msLocalMinFlag, 0, len );
1095 261 : set32_fx( msCurrentMin, 2147483647l /*1.0 Q31*/, len );
1096 :
1097 : /* Get the current noise floor */
1098 261 : Copy_Scale_sig_32_16( msCurrentMinOut, msNoiseFloor, len, -16 );
1099 : }
1100 : }
1101 :
1102 :
1103 : /* Detect sudden offsets based on the FFT bins (core bandwidth) */
1104 3097 : IF( GT_32( Mpy_32_16_1( msPsdSum[0], 655 /*0.02 Q15*/ ), msPeriodogSum[0] ) /*0.0 Q31*/ )
1105 : {
1106 0 : IF( hFdCngCom->offsetflag > 0 )
1107 : {
1108 0 : Copy( msPeriodog, msPsd, len );
1109 0 : FOR( j = 0; j < len; j++ )
1110 : {
1111 0 : msCurrentMinOut[j] = L_deposit_h( msPeriodog[j] );
1112 0 : move32();
1113 : }
1114 0 : set32_fx( hFdCngCom->msAlphaCor, 2147483647l /*1.0 Q31*/, cnt );
1115 0 : set32_fx( msAlpha, 0l /*0.0 Q31*/, len );
1116 0 : Copy( msPeriodog, msPsdFirstMoment, len );
1117 0 : set32_fx( msPsdSecondMoment, 0l /*0.0 Q31*/, len );
1118 :
1119 0 : msPsdSum[0] = dotp_s_fx( msPeriodog, psize, lenFFT, CNG_HS );
1120 0 : move32();
1121 0 : IF( LT_16( lenFFT, len ) )
1122 : {
1123 0 : msPsdSum[1] = dotp_s_fx( msPeriodog + lenFFT, psize + lenFFT, sub( len, lenFFT ), CNG_HS );
1124 0 : move32();
1125 : }
1126 : }
1127 0 : hFdCngCom->offsetflag = 1;
1128 0 : move16();
1129 : }
1130 : ELSE
1131 : {
1132 3097 : hFdCngCom->offsetflag = 0;
1133 3097 : move16();
1134 : }
1135 :
1136 :
1137 : /* Increment frame counter */
1138 3097 : IF( EQ_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
1139 : {
1140 261 : hFdCngCom->msFrCnt = 1;
1141 261 : move16();
1142 261 : hFdCngCom->msMinBufferPtr = add( hFdCngCom->msMinBufferPtr, 1 );
1143 261 : move16();
1144 261 : if ( EQ_16( hFdCngCom->msMinBufferPtr, MSNUMSUBFR ) )
1145 : {
1146 41 : hFdCngCom->msMinBufferPtr = 0;
1147 41 : move16();
1148 : }
1149 : }
1150 : ELSE
1151 : {
1152 2836 : hFdCngCom->msFrCnt = add( hFdCngCom->msFrCnt, 1 );
1153 : }
1154 :
1155 : /* Smooth noise estimate during CNG phases */
1156 77760 : FOR( j = 0; j < len; j++ )
1157 : {
1158 74663 : msNoiseEst[j] = round_fx( L_mac( L_mult( 31130 /*0.95 Q15*/, msNoiseEst[j] ), 1638 /*0.05 Q15*/, msNoiseFloor[j] ) );
1159 74663 : move16();
1160 : }
1161 : }
1162 : /* Collect buffers */
1163 3115 : Copy( msPeriodog, msPeriodogBuf + len * ( *msPeriodogBufPtr ), len );
1164 :
1165 3115 : *msPeriodogBufPtr = add( *msPeriodogBufPtr, 1 );
1166 3115 : move16();
1167 3115 : if ( EQ_16( *msPeriodogBufPtr, MSBUFLEN ) )
1168 : {
1169 622 : ( *msPeriodogBufPtr ) = 0;
1170 622 : move16();
1171 : }
1172 :
1173 : /* Upper limit the noise floors with the averaged input energy */
1174 78437 : FOR( j = 0; j < len; j++ )
1175 : {
1176 75322 : scalar = L_mult( msPeriodogBuf[j], 6554 /*1.0/MSBUFLEN Q15*/ );
1177 :
1178 376610 : FOR( i = j + len; i < MSBUFLEN * len; i += len )
1179 : {
1180 301288 : scalar = L_mac( scalar, msPeriodogBuf[i], 6554 /*1.0/MSBUFLEN Q15*/ );
1181 : }
1182 75322 : scalar16 = round_fx( scalar );
1183 75322 : if ( GT_16( msNoiseEst[j], scalar16 ) /*0.0 Q15*/ )
1184 : {
1185 12561 : msNoiseEst[j] = scalar16;
1186 12561 : move16();
1187 : }
1188 :
1189 75322 : assert( msNoiseEst[j] >= 0 /*0.0 Q15*/ );
1190 : }
1191 3115 : }
1192 :
1193 163270 : void minimum_statistics_fx(
1194 : Word16 len, /* i : Total number of partitions (CLDFB or FFT) */
1195 : Word16 lenFFT, /* i : Number of FFT partitions */
1196 : Word16 *psize, /* i : Partition sizes, fractional Q9*/
1197 : Word16 *msPeriodog, /* i : Periodogram (energies) */
1198 : Word32 *msNoiseFloor, /* i/o: Noise floors (energies) Q25*/
1199 : Word32 *msNoiseEst, /* i/o: Noise estimates (energies) Q25*/
1200 : Word32 *msAlpha, /* i/o: Forgetting factors */
1201 : Word16 *msPsd, /* i/o: Power Spectral Density (smoothed periodogram => energies) */
1202 : Word16 *msPsdFirstMoment, /* i/o: PSD statistics of 1st order (energy means) */
1203 : Word32 *msPsdSecondMoment, /* i/o: PSD statistics of 2nd order (energy variances) */
1204 : Word32 *msMinBuf, /* i/o: Buffer of minima (energies) */
1205 : Word32 *msBminWin, /* o : Bias correction factors */
1206 : Word32 *msBminSubWin, /* o : Bias correction factors */
1207 : Word32 *msCurrentMin, /* i/o: Local minima (energies) */
1208 : Word32 *msCurrentMinOut, /* i/o: Local minima (energies) */
1209 : Word32 *msCurrentMinSubWindow, /* i/o: Local minima (energies) */
1210 : Word16 *msLocalMinFlag, /* i : Binary flag */
1211 : Word16 *msNewMinFlag, /* i : Binary flag */
1212 : Word16 *msPeriodogBuf, /* i/o: Buffer of periodograms (energies) */
1213 : Word16 *msPeriodogBufPtr, /* i/o: Counter */
1214 : HANDLE_FD_CNG_COM hFdCngCom, /* i/o: FD_CNG structure containing all buffers and variables */
1215 : const Word16 enc_dec, /* i : encoder/decoder indicator */
1216 : const Word16 element_mode /* i : IVAS element mode type */
1217 : )
1218 : {
1219 : Word16 i, j, k, s, s1, s2, s3;
1220 : Word16 len2;
1221 : Word16 current_len;
1222 : Word16 start, stop, cnt;
1223 : Word16 totsize;
1224 : Word16 inv_totsize;
1225 :
1226 : Word32 tmp, tmp0, tmp1;
1227 : Word32 scalar, scalar2, scalar3;
1228 : Word32 snr;
1229 : Word32 msAlphaHatMin2;
1230 : Word32 BminCorr;
1231 : Word32 QeqInvAv;
1232 : Word32 *ptr;
1233 : Word32 *msPsdSum;
1234 : Word32 *msPeriodogSum;
1235 :
1236 : Word16 tmp16, tmp16_1;
1237 : Word16 beta;
1238 : Word16 slope;
1239 : Word16 QeqInv;
1240 : Word16 scalar16;
1241 : Word16 scalar216;
1242 : Word16 scalar316;
1243 : Word16 msM_win;
1244 : Word16 msM_subwin;
1245 : Word16 msAlphaCorAlpha;
1246 : Word16 msAlphaCorAlpha2;
1247 : Word16 msPeriodogSum16;
1248 : Word16 msNoiseFloor16;
1249 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
1250 163270 : Flag Overflow = 0;
1251 163270 : move32();
1252 : #endif
1253 :
1254 :
1255 163270 : len2 = i_mult( MSNUMSUBFR, len );
1256 :
1257 163270 : msM_win = hFdCngCom->msM_win;
1258 163270 : move16();
1259 163270 : msM_subwin = hFdCngCom->msM_subwin;
1260 163270 : move16();
1261 :
1262 163270 : msAlphaCorAlpha = MSALPHACORALPHA;
1263 163270 : move16();
1264 163270 : msAlphaCorAlpha2 = MSALPHACORALPHA2;
1265 163270 : move16();
1266 :
1267 163270 : msPsdSum = hFdCngCom->msPsdSum;
1268 163270 : msPeriodogSum = hFdCngCom->msPeriodogSum;
1269 :
1270 : /* No minimum statistics at initialization */
1271 163270 : IF( LT_16( hFdCngCom->msFrCnt_init_counter, hFdCngCom->msFrCnt_init_thresh ) )
1272 : {
1273 6404 : Copy( msPeriodog, msPsd, len ); /* 6Q9 */
1274 6404 : Copy_Scale_sig_16_32_no_sat( msPeriodog, msNoiseFloor, len, Q16 ); /* Q25 */
1275 6404 : Copy_Scale_sig_16_32_no_sat( msPeriodog, msNoiseEst, len, Q16 ); /* Q25 */
1276 6404 : Copy( msPeriodog, msPsdFirstMoment, len ); /* 6Q9 */
1277 :
1278 6404 : set32_fx( msPsdSecondMoment, 0l /*0.0 Q31*/, len );
1279 6404 : msPeriodogSum[0] = dotp_s_fx( msPeriodog, psize, lenFFT, CNG_HS );
1280 6404 : move32();
1281 6404 : msPsdSum[0] = msPeriodogSum[0]; /* 16Q15 */
1282 6404 : move32();
1283 :
1284 6404 : IF( LT_16( lenFFT, len ) )
1285 : {
1286 2571 : msPeriodogSum[1] = dotp_s_fx( msPeriodog + lenFFT, psize + lenFFT, sub( len, lenFFT ), CNG_HS );
1287 2571 : move32();
1288 2571 : msPsdSum[1] = msPeriodogSum[1]; /* 16Q15 */
1289 2571 : move32();
1290 : }
1291 :
1292 : /* Increment frame counter at initialization */
1293 : /* Some frames are sometimes zero at initialization => ignore them */
1294 6404 : IF( LT_16( msPeriodog[0], hFdCngCom->init_old ) )
1295 : {
1296 1476 : set32_fx( msCurrentMinOut, 2147483647l /*1.0 Q31*/, len ); /* 16Q15 */
1297 1476 : set32_fx( msCurrentMin, 2147483647l /*1.0 Q31*/, len ); /* 16Q15 */
1298 1476 : set32_fx( msMinBuf, 2147483647l /*1.0 Q31*/, len2 ); /* 16Q15 */
1299 1476 : set32_fx( msCurrentMinSubWindow, 2147483647l /*1.0 Q31*/, len ); /* 16Q15 */
1300 :
1301 1476 : hFdCngCom->msFrCnt_init_counter = add( hFdCngCom->msFrCnt_init_counter, 1 );
1302 1476 : move16();
1303 : }
1304 6404 : hFdCngCom->init_old = msPeriodog[0]; /* 6Q9 */
1305 6404 : move16();
1306 : }
1307 : ELSE
1308 : {
1309 : /* Consider the FFT and CLDFB bands separately
1310 : - first iteration for FFT bins,
1311 : - second one for CLDFB bands in SWB mode */
1312 156866 : cnt = 0;
1313 156866 : move16();
1314 156866 : start = 0;
1315 156866 : move16();
1316 156866 : stop = lenFFT;
1317 156866 : move16();
1318 156866 : totsize = sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand );
1319 432293 : WHILE( GT_16( stop, start ) )
1320 : {
1321 275427 : current_len = sub( stop, start );
1322 :
1323 : /* Compute smoothed correction factor for PSD smoothing */
1324 :
1325 : /* msPeriodogSum[cnt] with format 16Q15 */
1326 275427 : msPeriodogSum[cnt] = dotp_s_fx( msPeriodog + start, psize + start, current_len, CNG_HS );
1327 275427 : move32();
1328 :
1329 275427 : IF( msPeriodogSum[cnt] == 0 )
1330 : {
1331 0 : hFdCngCom->msAlphaCor[cnt] = Mpy_32_16_1( hFdCngCom->msAlphaCor[cnt], msAlphaCorAlpha );
1332 0 : move32();
1333 : }
1334 : ELSE
1335 : {
1336 : /* calculate scalar with normalized msPeriodogSum[cnt], exponent -2*s1 */
1337 275427 : s1 = norm_l( msPeriodogSum[cnt] );
1338 275427 : msPeriodogSum16 = round_fx_sat( L_shl( msPeriodogSum[cnt], s1 ) );
1339 275427 : scalar = L_mult( msPeriodogSum16, msPeriodogSum16 );
1340 :
1341 : /* calculate difference, both elements in 16Q15 format, use absolute value
1342 : to avoid -1.0 x -1.0 multiplications later */
1343 275427 : scalar2 = L_abs( L_sub( msPsdSum[cnt], msPeriodogSum[cnt] ) );
1344 :
1345 275427 : s2 = WORD32_BITS - 1;
1346 275427 : move16();
1347 275427 : if ( scalar2 != 0 )
1348 : {
1349 : /* use absolute value to avoid -1.0 x -1.0 multiplications */
1350 248819 : s2 = norm_l( scalar2 );
1351 : }
1352 275427 : scalar216 = round_fx_o( L_shl_o( scalar2, s2, &Overflow ), &Overflow );
1353 275427 : scalar2 = L_mult( scalar216, scalar216 );
1354 :
1355 : /* find common exponent */
1356 275427 : tmp16_1 = sub( s1, s2 );
1357 275427 : tmp16 = s_min( shl( abs_s( tmp16_1 ), 1 ), WORD32_BITS - 1 );
1358 275427 : if ( tmp16_1 < 0 )
1359 : {
1360 254517 : scalar2 = L_shr( scalar2, tmp16 );
1361 : }
1362 275427 : if ( tmp16_1 > 0 )
1363 : {
1364 8197 : scalar = L_shr( scalar, tmp16 );
1365 : }
1366 :
1367 :
1368 : /* add scalar and scalar2, avoid overflows */
1369 275427 : scalar = L_shr( scalar, 1 );
1370 275427 : scalar2 = L_shr( scalar2, 1 );
1371 275427 : scalar3 = L_add( scalar, scalar2 );
1372 :
1373 : /* calculate division */
1374 275427 : scalar16 = BASOP_Util_Divide3232_uu_1616_Scale( scalar, scalar3, &s3 );
1375 275427 : s3 = s_max( s3, -( WORD16_BITS - 1 ) );
1376 275427 : scalar16 = shl( scalar16, s3 );
1377 275427 : scalar16 = s_max( scalar16, MSALPHACORMAX );
1378 :
1379 275427 : hFdCngCom->msAlphaCor[cnt] = Madd_32_16( L_mult( scalar16, msAlphaCorAlpha2 ), hFdCngCom->msAlphaCor[cnt], msAlphaCorAlpha );
1380 275427 : move32();
1381 : }
1382 :
1383 : /* Compute SNR */
1384 :
1385 : /* msPeriodogSum[cnt] with format 16Q15 */
1386 : Word16 msNoiseFloor16tmp[NPART_SHAPING];
1387 275427 : IF( enc_dec == ENC )
1388 : {
1389 237122 : Copy_Scale_sig32_16( msNoiseFloor, msNoiseFloor16tmp, NPART, 0 );
1390 : }
1391 : ELSE
1392 : {
1393 38305 : Copy_Scale_sig32_16( msNoiseFloor, msNoiseFloor16tmp, NPART_SHAPING, 0 );
1394 : }
1395 275427 : snr = dotp_s_fx( &msNoiseFloor16tmp[start], psize + start, current_len, CNG_HS );
1396 :
1397 275427 : IF( GT_32( L_shr( Mpy_32_16_1( msPsdSum[cnt], 18431 /*0.56246299817 Q15*/ ), 13 ), snr ) )
1398 : {
1399 0 : tmp0 = BASOP_Util_Log2( msPsdSum[cnt] );
1400 0 : tmp1 = BASOP_Util_Log2( snr );
1401 0 : tmp1 = L_sub( tmp0, tmp1 );
1402 0 : tmp1 = Mpy_32_16_1( tmp1, MSSNREXP );
1403 0 : msAlphaHatMin2 = BASOP_Util_InvLog2( tmp1 );
1404 : }
1405 : ELSE
1406 : {
1407 275427 : msAlphaHatMin2 = MSALPHAHATMIN;
1408 275427 : move32();
1409 : }
1410 275427 : scalar = Mpy_32_16_1( hFdCngCom->msAlphaCor[cnt], MSALPHAMAX );
1411 :
1412 5424166 : FOR( j = start; j < stop; j++ )
1413 : {
1414 : /* Compute optimal smoothing parameter for PSD estimation */
1415 5148739 : test();
1416 5148739 : IF( ( scalar == 0 ) || ( msNoiseFloor[j] == 0 ) )
1417 : {
1418 80 : msAlpha[j] = msAlphaHatMin2;
1419 80 : move32();
1420 : }
1421 : ELSE
1422 : {
1423 : /* calculate scalar2 with normalized msNoiseFloor[j], exponent -2*s1 */
1424 5148659 : s1 = WORD16_BITS - 1;
1425 5148659 : move16();
1426 5148659 : if ( msNoiseFloor16tmp[j] != 0 )
1427 : {
1428 5148659 : s1 = norm_s( msNoiseFloor16tmp[j] );
1429 : }
1430 5148659 : msNoiseFloor16 = shl( msNoiseFloor16tmp[j], s1 );
1431 5148659 : scalar2 = L_mult( msNoiseFloor16, msNoiseFloor16 );
1432 :
1433 : /* calculate difference, both elements in 6Q9 format, use absolute value
1434 : to avoid -1.0 x -1.0 multiplications later */
1435 5148659 : scalar316 = abs_s( sub( msPsd[j], msNoiseFloor16tmp[j] ) );
1436 :
1437 5148659 : s2 = WORD16_BITS - 1;
1438 5148659 : move16();
1439 5148659 : if ( scalar316 != 0 )
1440 : {
1441 : /* use absolute value to avoid -1.0 x -1.0 multiplications */
1442 4398015 : s2 = norm_s( scalar316 );
1443 : }
1444 5148659 : scalar316 = shl( scalar316, s2 );
1445 5148659 : scalar3 = L_mult( scalar316, scalar316 );
1446 :
1447 : /* find common exponent */
1448 5148659 : tmp16_1 = sub( s1, s2 );
1449 5148659 : tmp16 = s_min( shl( abs_s( tmp16_1 ), 1 ), WORD32_BITS - 1 );
1450 5148659 : if ( tmp16_1 < 0 )
1451 : {
1452 4286887 : scalar3 = L_shr( scalar3, tmp16 );
1453 : }
1454 5148659 : if ( tmp16_1 > 0 )
1455 : {
1456 642457 : scalar2 = L_shr( scalar2, tmp16 );
1457 : }
1458 :
1459 : /* add scalar2 and scalar3, avoid overflows */
1460 5148659 : scalar2 = L_shr( scalar2, 1 );
1461 5148659 : scalar3 = L_shr( scalar3, 1 );
1462 5148659 : scalar3 = L_add( scalar2, scalar3 );
1463 :
1464 : /* calculate division */
1465 5148659 : tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( scalar2, scalar3, &s3 );
1466 5148659 : scalar2 = Mpy_32_16_1( scalar, tmp16 );
1467 5148659 : s3 = s_max( s3, -( WORD32_BITS - 1 ) );
1468 5148659 : scalar2 = L_shl( scalar2, s3 );
1469 5148659 : msAlpha[j] = L_max( scalar2, msAlphaHatMin2 );
1470 5148659 : move32();
1471 : }
1472 :
1473 : /* Compute the PSD (smoothed periodogram) in each band */
1474 5148739 : msPsd[j] = round_fx( Madd_32_16( Mpy_32_16_1( msAlpha[j], msPsd[j] ), L_sub( 2147483647l /*1.0 Q31*/, msAlpha[j] ), msPeriodog[j] ) );
1475 5148739 : move16();
1476 : }
1477 275427 : msPsdSum[cnt] = dotp_s_fx( msPsd + start, psize + start, current_len, CNG_HS );
1478 275427 : move32();
1479 :
1480 275427 : QeqInvAv = 0l /*0.0 Q31*/;
1481 275427 : move32();
1482 :
1483 : /* scalar: 7Q24 format */
1484 275427 : tmp = 1191182336l /*(float)(MSNUMSUBFR*MSSUBFRLEN)-1.0 Q24*/;
1485 275427 : move32();
1486 275427 : scalar = L_sub( tmp, L_mult( round_fx( tmp ), msM_win ) );
1487 :
1488 : /* scalar2: 4Q27 format */
1489 275427 : tmp = 1476395008l /*(float)MSSUBFRLEN-1.0 Q27*/;
1490 275427 : move32();
1491 275427 : scalar2 = L_sub( tmp, L_mult( round_fx( tmp ), msM_subwin ) );
1492 :
1493 5424166 : FOR( j = start; j < stop; j++ )
1494 : {
1495 : /* Compute variance of PSD */
1496 5148739 : tmp = L_min( msAlpha[j], MSBETAMAX_SQRT );
1497 :
1498 5148739 : s1 = WORD32_BITS - 1;
1499 5148739 : move16();
1500 5148739 : if ( tmp != 0 )
1501 : {
1502 5148739 : s1 = norm_l( tmp );
1503 : }
1504 5148739 : s2 = shl( s1, 1 );
1505 :
1506 5148739 : s2 = s_min( s2, WORD32_BITS - 1 );
1507 :
1508 : /* beta: scaled by s2 */
1509 5148739 : tmp16 = round_fx_o( L_shl_o( tmp, s1, &Overflow ), &Overflow );
1510 5148739 : beta = mult_r( tmp16, tmp16 );
1511 :
1512 : /* scalar3: scaled by s3 */
1513 5148739 : scalar3 = L_sub( L_deposit_l( msPsd[j] ), L_deposit_l( msPsdFirstMoment[j] ) );
1514 5148739 : s3 = norm_l( scalar3 );
1515 5148739 : scalar3 = L_shl( scalar3, s3 );
1516 :
1517 : /* msPsdFirstMoment: 6Q9 */
1518 5148739 : tmp = L_msu( L_mult( beta, msPsdFirstMoment[j] ), beta, msPsd[j] );
1519 5148739 : msPsdFirstMoment[j] = add( round_fx( L_shr( tmp, s2 ) ), msPsd[j] );
1520 5148739 : move16();
1521 :
1522 : /* msPsdSecondMoment: 12Q19 */
1523 5148739 : tmp0 = L_shr( Mpy_32_16_r( msPsdSecondMoment[j], beta ), s2 );
1524 5148739 : tmp1 = Mpy_32_32( scalar3, scalar3 );
1525 5148739 : tmp1 = L_shr( L_sub( tmp1, L_shr( Mpy_32_16_r( tmp1, beta ), s2 ) ), sub( shl( s3, 1 ), 32 ) );
1526 5148739 : msPsdSecondMoment[j] = L_add( tmp0, tmp1 );
1527 5148739 : move32();
1528 :
1529 : /* Compute inverse of amount of degrees of freedom */
1530 5148739 : QeqInv = MSQEQINVMAX;
1531 5148739 : move16();
1532 :
1533 5148739 : IF( msNoiseFloor[j] != 0 /*0.0 Q15*/ )
1534 : {
1535 5148659 : tmp = Mpy_32_32( msNoiseFloor[j], msNoiseFloor[j] );
1536 5148659 : tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( msPsdSecondMoment[j], tmp, &s );
1537 : /* consider factor of 2 */
1538 5148659 : s = s_min( s_max( sub( s, 1 ), -( WORD16_BITS - 1 ) ), ( WORD16_BITS - 1 ) );
1539 5148659 : if ( s < 0 )
1540 : {
1541 4567802 : QeqInv = shl( tmp16, s );
1542 : }
1543 5148659 : QeqInv = s_min( QeqInv, MSQEQINVMAX );
1544 : }
1545 5148739 : QeqInvAv = L_add( QeqInvAv, L_mult( QeqInv, psize[j] ) );
1546 :
1547 : /* Compute bias correction Bmin */
1548 5148739 : tmp0 = Mpy_32_16_1( scalar, QeqInv );
1549 5148739 : tmp1 = L_msu( 1073741824l /*0.5 Q31*/, msM_win, QeqInv );
1550 5148739 : tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( tmp0, tmp1, &s );
1551 5148739 : msBminWin[j] = L_add( 134217728l /*1.0 Q27*/, L_shl( L_deposit_h( tmp16 ), add( s, 7 - 4 ) ) );
1552 5148739 : move32();
1553 :
1554 5148739 : tmp0 = Mpy_32_16_1( scalar2, QeqInv );
1555 5148739 : tmp1 = L_msu( 1073741824l /*0.5 Q31*/, msM_subwin, QeqInv );
1556 5148739 : tmp16 = BASOP_Util_Divide3232_uu_1616_Scale( tmp0, tmp1, &s );
1557 5148739 : msBminSubWin[j] = L_add( 134217728l /*1.0 Q27*/, L_shl( L_deposit_h( tmp16 ), s ) );
1558 5148739 : move32();
1559 : }
1560 :
1561 275427 : inv_totsize = BASOP_Util_Divide3232_uu_1616_Scale( 1, totsize, &s );
1562 275427 : QeqInvAv = Mpy_32_16_1( QeqInvAv, inv_totsize );
1563 275427 : QeqInvAv = L_shl( QeqInvAv, s );
1564 275427 : hFdCngCom->msQeqInvAv[cnt] = QeqInvAv;
1565 275427 : move32();
1566 :
1567 : /* New minimum? */
1568 :
1569 : /* exponent QeqInvAv: CNG_S, exponent MSAV: (4>>1) */
1570 275427 : s = CNG_S + 2 * MSAV_EXP;
1571 275427 : move16();
1572 275427 : BminCorr = Mpy_32_16_1( Sqrt32( QeqInvAv, &s ), MSAV );
1573 275427 : BminCorr = L_shl( BminCorr, sub( s, 1 ) );
1574 :
1575 : /* exponent BminCorr: 1 */
1576 275427 : BminCorr = L_add( BminCorr, 1073741824l /*0.5 Q31*/ );
1577 :
1578 5424166 : FOR( j = start; j < stop; j++ )
1579 : {
1580 : /* exponent scalar: CNG_S+1 */
1581 5148739 : scalar = Mpy_32_16_1( BminCorr, msPsd[j] );
1582 :
1583 : /* exponent scalar2: CNG_S+1+4 */
1584 5148739 : scalar2 = Mpy_32_32( scalar, msBminWin[j] );
1585 :
1586 5148739 : msNewMinFlag[j] = 0;
1587 5148739 : move16();
1588 5148739 : IF( LT_32( scalar2, msCurrentMin[j] ) /*0.0 Q31*/ )
1589 : {
1590 1995927 : msNewMinFlag[j] = 1;
1591 1995927 : move16();
1592 : /* exponent msCurrentMin[j]: CNG_S+1+4 */
1593 1995927 : msCurrentMin[j] = scalar2;
1594 1995927 : move32();
1595 : /* exponent msCurrentMinSubWindow[j]: CNG_S */
1596 : BASOP_SATURATE_WARNING_OFF_EVS;
1597 1995927 : msCurrentMinSubWindow[j] = L_shl_o( Mpy_32_32( scalar, msBminSubWin[j] ), 5, &Overflow );
1598 1995927 : move32();
1599 : BASOP_SATURATE_WARNING_ON_EVS;
1600 : }
1601 : }
1602 :
1603 : /* This is used later to identify local minima */
1604 275427 : IF( GE_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
1605 : {
1606 55314 : FOR( i = 0; i < 3; i++ )
1607 : {
1608 47026 : IF( LT_32( hFdCngCom->msQeqInvAv[cnt], L_shr( L_deposit_h( msQeqInvAv_thresh[i] ), CNG_S ) ) /*0.0 Q31*/ )
1609 : {
1610 15447 : BREAK;
1611 : }
1612 : }
1613 : /* format 1Q30 */
1614 23735 : hFdCngCom->msSlope[cnt] = msNoiseSlopeMax[i];
1615 23735 : move32();
1616 : }
1617 :
1618 : /* Consider the FFT and CLDFB bands separately */
1619 275427 : start = stop;
1620 275427 : move16();
1621 275427 : stop = len;
1622 275427 : move16();
1623 275427 : totsize = sub( hFdCngCom->stopBand, hFdCngCom->stopFFTbin );
1624 275427 : cnt = add( cnt, 1 );
1625 : } /*while (stop > start)*/
1626 :
1627 : /* Update minimum between sub windows */
1628 156866 : test();
1629 156866 : IF( GT_16( hFdCngCom->msFrCnt, 1 ) && LT_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
1630 : {
1631 4372055 : FOR( j = 0; j < len; j++ )
1632 : {
1633 4242373 : if ( msNewMinFlag[j] > 0 )
1634 : {
1635 1411231 : msLocalMinFlag[j] = 1;
1636 1411231 : move16();
1637 : }
1638 4242373 : if ( LT_32( msCurrentMinSubWindow[j], msCurrentMinOut[j] ) /*0.0 Q31*/ )
1639 : {
1640 : /* msCurrentMinOut[j] scaled with CNG_S */
1641 537895 : msCurrentMinOut[j] = msCurrentMinSubWindow[j];
1642 537895 : move32();
1643 : }
1644 : }
1645 : /* Get the current noise floor */
1646 129682 : Copy32( msCurrentMinOut, msNoiseFloor, len );
1647 : }
1648 : ELSE /* sub window complete */
1649 : {
1650 27184 : IF( GE_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
1651 : {
1652 : /* Collect buffers */
1653 13638 : Copy32( msCurrentMinSubWindow, msMinBuf + len * hFdCngCom->msMinBufferPtr, len );
1654 :
1655 : /* Compute minimum among all buffers */
1656 13638 : Copy32( msMinBuf, msCurrentMinOut, len );
1657 13638 : ptr = msMinBuf + len;
1658 81828 : FOR( i = 1; i < MSNUMSUBFR; i++ )
1659 : {
1660 2346405 : FOR( j = 0; j < len; j++ )
1661 : {
1662 2278215 : if ( LT_32( *ptr, msCurrentMinOut[j] ) /*0.0 Q31*/ )
1663 : {
1664 522309 : msCurrentMinOut[j] = *ptr;
1665 522309 : move32();
1666 : }
1667 2278215 : ptr++;
1668 : }
1669 : }
1670 :
1671 : /* Take over local minima */
1672 13638 : slope = hFdCngCom->msSlope[0];
1673 13638 : move16();
1674 469281 : FOR( j = 0; j < len; j++ )
1675 : {
1676 455643 : if ( EQ_16( j, lenFFT ) )
1677 : {
1678 10097 : slope = hFdCngCom->msSlope[1];
1679 10097 : move16();
1680 : }
1681 455643 : test();
1682 455643 : test();
1683 455643 : test();
1684 455643 : IF( ( msLocalMinFlag[j] != 0 ) && ( msNewMinFlag[j] == 0 ) && ( LT_32( L_shr( msCurrentMinSubWindow[j], 1 ), Mpy_32_16_1( msCurrentMinOut[j], slope ) ) /*0.0 Q31*/ ) && ( GT_32( msCurrentMinSubWindow[j], msCurrentMinOut[j] ) /*0.0 Q31*/ ) )
1685 : {
1686 60048 : msCurrentMinOut[j] = msCurrentMinSubWindow[j];
1687 60048 : move32();
1688 60048 : i = j;
1689 60048 : move16();
1690 420336 : FOR( k = 0; k < MSNUMSUBFR; k++ )
1691 : {
1692 360288 : msMinBuf[i] = msCurrentMinOut[j];
1693 360288 : move32();
1694 360288 : i = add( i, len );
1695 : }
1696 : }
1697 : }
1698 :
1699 : /* Reset */
1700 13638 : set16_fx( msLocalMinFlag, 0, len );
1701 13638 : set32_fx( msCurrentMin, 2147483647l /*1.0 Q31*/, len );
1702 :
1703 : /* Get the current noise floor */
1704 13638 : Copy32( msCurrentMinOut, msNoiseFloor, len );
1705 : }
1706 : }
1707 :
1708 :
1709 : /* Detect sudden offsets based on the FFT bins (core bandwidth) */
1710 156866 : IF( GT_32( Mpy_32_16_1( msPsdSum[0], 655 /*0.02 Q15*/ ), msPeriodogSum[0] ) /*0.0 Q31*/ )
1711 : {
1712 155 : IF( hFdCngCom->offsetflag > 0 )
1713 : {
1714 65 : Copy( msPeriodog, msPsd, len );
1715 3480 : FOR( j = 0; j < len; j++ )
1716 : {
1717 3415 : msCurrentMinOut[j] = L_deposit_h( msPeriodog[j] );
1718 3415 : move32();
1719 : }
1720 65 : set32_fx( hFdCngCom->msAlphaCor, 2147483647l /*1.0 Q31*/, cnt );
1721 65 : set32_fx( msAlpha, 0l /*0.0 Q31*/, len );
1722 65 : Copy( msPeriodog, msPsdFirstMoment, len );
1723 65 : set32_fx( msPsdSecondMoment, 0l /*0.0 Q31*/, len );
1724 :
1725 65 : msPsdSum[0] = dotp_s_fx( msPeriodog, psize, lenFFT, CNG_HS );
1726 65 : move32();
1727 65 : IF( LT_16( lenFFT, len ) )
1728 : {
1729 15 : msPsdSum[1] = dotp_s_fx( msPeriodog + lenFFT, psize + lenFFT, sub( len, lenFFT ), CNG_HS );
1730 15 : move32();
1731 : }
1732 : }
1733 155 : hFdCngCom->offsetflag = 1;
1734 155 : move16();
1735 : }
1736 : ELSE
1737 : {
1738 156711 : hFdCngCom->offsetflag = 0;
1739 156711 : move16();
1740 : }
1741 :
1742 :
1743 : /* Increment frame counter */
1744 156866 : IF( EQ_16( hFdCngCom->msFrCnt, MSSUBFRLEN ) )
1745 : {
1746 13638 : hFdCngCom->msFrCnt = 1;
1747 13638 : move16();
1748 13638 : hFdCngCom->msMinBufferPtr = add( hFdCngCom->msMinBufferPtr, 1 );
1749 13638 : move16();
1750 13638 : if ( EQ_16( hFdCngCom->msMinBufferPtr, MSNUMSUBFR ) )
1751 : {
1752 1919 : hFdCngCom->msMinBufferPtr = 0;
1753 1919 : move16();
1754 : }
1755 : }
1756 : ELSE
1757 : {
1758 143228 : hFdCngCom->msFrCnt = add( hFdCngCom->msFrCnt, 1 );
1759 143228 : move16();
1760 : }
1761 : Word64 tmp64;
1762 : /* Smooth noise estimate during CNG phases */
1763 5305605 : FOR( j = 0; j < len; j++ )
1764 : {
1765 5148739 : tmp64 = W_add( W_mult_32_16( msNoiseEst[j], 31130 /*0.95 Q15*/ ), W_mult_32_16( msNoiseFloor[j], 1638 /*0.05 Q15*/ ) );
1766 5148739 : msNoiseEst[j] = W_extract_h( W_shl( tmp64, 16 ) ); // Q25
1767 5148739 : move32();
1768 : }
1769 : }
1770 163270 : IF( EQ_16( enc_dec, DEC ) && EQ_16( element_mode, IVAS_CPE_TD ) )
1771 : {
1772 : // v_multc(msNoiseEst, 1.4125f, msNoiseEst, NPART_SHAPING);
1773 0 : v_multc_att32( msNoiseEst, 23142, msNoiseEst, NPART_SHAPING );
1774 : }
1775 : /* Collect buffers */
1776 163270 : Copy( msPeriodog, msPeriodogBuf + len * ( *msPeriodogBufPtr ), len );
1777 :
1778 163270 : *msPeriodogBufPtr = add( *msPeriodogBufPtr, 1 );
1779 163270 : move16();
1780 163270 : if ( EQ_16( *msPeriodogBufPtr, MSBUFLEN ) )
1781 : {
1782 32289 : ( *msPeriodogBufPtr ) = 0;
1783 32289 : move16();
1784 : }
1785 :
1786 : /* Upper limit the noise floors with the averaged input energy */
1787 5608515 : FOR( j = 0; j < len; j++ )
1788 : {
1789 5445245 : scalar = L_mult( msPeriodogBuf[j], 6554 /*1.0/MSBUFLEN Q15*/ );
1790 :
1791 27226225 : FOR( i = j + len; i < MSBUFLEN * len; i += len )
1792 : {
1793 21780980 : scalar = L_mac( scalar, msPeriodogBuf[i], 6554 /*1.0/MSBUFLEN Q15*/ );
1794 : }
1795 5445245 : if ( GT_32( msNoiseEst[j], scalar ) /*0.0 Q15*/ )
1796 : {
1797 1369476 : msNoiseEst[j] = scalar;
1798 1369476 : move32();
1799 : }
1800 :
1801 5445245 : assert( msNoiseEst[j] >= 0 /*0.0 Q15*/ );
1802 : }
1803 163270 : }
1804 : /*-------------------------------------------------------------------
1805 : * apply_scale()
1806 : *
1807 : * Apply bitrate-dependent scale
1808 : *-------------------------------------------------------------------*/
1809 31442 : void apply_scale(
1810 : Word32 *scale, /* o : scalefactor */
1811 : const Word16 bwmode, /* i : audio bandwidth */
1812 : const Word32 bitrate, /* i : Bit rate */
1813 : const SCALE_SETUP *scaleTable, /* i : Scale table Q7 */
1814 : const Word16 scaleTableSize /* i : Size of scale table */
1815 : )
1816 : {
1817 : Word16 i;
1818 : // PMT("Verifiy if the basop ued are ok for stereo too")
1819 294492 : FOR( i = 0; i < scaleTableSize; i++ )
1820 : {
1821 294492 : cast16();
1822 294492 : IF( s_and( (Word16) EQ_16( bwmode, (Word16) scaleTable[i].bwmode ),
1823 : s_and( L_sub( bitrate, scaleTable[i].bitrateFrom ) >= 0,
1824 : L_sub( bitrate, scaleTable[i].bitrateTo ) < 0 ) ) )
1825 : {
1826 31442 : BREAK;
1827 : }
1828 : }
1829 :
1830 : {
1831 31442 : *scale = L_add( *scale, L_deposit_h( scaleTable[i].scale ) );
1832 31442 : move32();
1833 : }
1834 31442 : }
1835 :
1836 : /*-------------------------------------------------------------------
1837 : * apply_scale_ind()
1838 : *
1839 : * Apply bitrate-dependent scale
1840 : * returns index of scaleTable
1841 : *-------------------------------------------------------------------*/
1842 0 : Word16 apply_scale_ind(
1843 : Word32 *scale, /* o : scalefactor */
1844 : const Word16 bwmode, /* i : audio bandwidth */
1845 : const Word32 bitrate, /* i : Bit rate */
1846 : const SCALE_SETUP *scaleTable, /* i : Scale table */
1847 : const Word16 scaleTableSize /* i : Size of scale table */
1848 : )
1849 : {
1850 : Word16 i;
1851 : // PMT("Verifiy if the basop ued are ok for stereo too")
1852 0 : FOR( i = 0; i < scaleTableSize; i++ )
1853 : {
1854 0 : cast16();
1855 0 : IF( s_and( (Word16) EQ_16( bwmode, (Word16) scaleTable[i].bwmode ),
1856 : s_and( L_sub( bitrate, scaleTable[i].bitrateFrom ) >= 0,
1857 : L_sub( bitrate, scaleTable[i].bitrateTo ) < 0 ) ) )
1858 : {
1859 0 : BREAK;
1860 : }
1861 : }
1862 :
1863 : {
1864 0 : *scale = L_add( *scale, L_deposit_h( scaleTable[i].scale ) );
1865 0 : move32();
1866 : }
1867 0 : return i;
1868 : }
1869 :
1870 168084 : void apply_scale_ivas_fx(
1871 : Word32 *scale, /* o : scalefactor */
1872 : const Word16 bwmode, /* i : audio bandwidth */
1873 : const Word32 bitrate, /* i : Bit rate */
1874 : const SCALE_SETUP *scaleTable, /* i : Scale table Q7 */
1875 : const Word16 scaleTableSize, /* i : Size of scale table */
1876 : Word16 *index )
1877 : {
1878 : Word16 i;
1879 : // PMT("Verifiy if the basop ued are ok for stereo too")
1880 1772256 : FOR( i = 0; i < scaleTableSize; i++ )
1881 : {
1882 1772256 : cast16();
1883 1772256 : IF( s_and( (Word16) EQ_16( bwmode, (Word16) scaleTable[i].bwmode ),
1884 : s_and( L_sub( bitrate, scaleTable[i].bitrateFrom ) >= 0,
1885 : L_sub( bitrate, scaleTable[i].bitrateTo ) < 0 ) ) )
1886 : {
1887 168084 : BREAK;
1888 : }
1889 : }
1890 168084 : assert( i < scaleTableSize );
1891 :
1892 168084 : *scale = L_add( *scale, L_deposit_h( scaleTable[i].scale ) );
1893 168084 : move32();
1894 168084 : *index = i;
1895 168084 : move16();
1896 168084 : }
1897 : /*-------------------------------------------------------------------
1898 : * bandcombinepow()
1899 : *
1900 : * Compute the power for each partition
1901 : *-------------------------------------------------------------------*/
1902 175661 : void bandcombinepow(
1903 : const Word32 *bandpow, /* i : Power for each band */
1904 : const Word16 exp_bandpow, /* i : exponent of bandpow */
1905 : const Word16 nband, /* i : Number of bands */
1906 : Word16 *part, /* i : Partition upper boundaries (band indices starting from 0) */
1907 : const Word16 npart, /* i : Number of partitions */
1908 : const Word16 *psize_inv, /* i : Inverse partition sizes */
1909 : Word32 *partpow, /* o : Power for each partition */
1910 : Word16 *exp_partpow )
1911 : {
1912 :
1913 : Word16 i, p;
1914 : Word32 temp;
1915 : Word16 smin, len, prev_part;
1916 : Word16 facTabExp[NPART_SHAPING];
1917 :
1918 :
1919 175661 : IF( EQ_16( nband, npart ) )
1920 : {
1921 0 : Copy32( bandpow, partpow, nband ); // Q(31 - exp_bandpow)
1922 0 : smin = 0;
1923 0 : move16();
1924 : }
1925 : ELSE
1926 : {
1927 : /* Compute the power in each partition */
1928 175661 : prev_part = -1;
1929 175661 : move16();
1930 3625691 : FOR( p = 0; p < npart; p++ )
1931 : {
1932 3450030 : len = sub( part[p], prev_part );
1933 3450030 : facTabExp[p] = getScaleFactor32( &bandpow[prev_part + 1], len );
1934 3450030 : move16();
1935 3450030 : prev_part = part[p];
1936 3450030 : move16();
1937 : }
1938 :
1939 175661 : smin = WORD32_BITS - 1;
1940 175661 : move16();
1941 3625691 : FOR( p = 0; p < npart; p++ )
1942 : {
1943 3450030 : smin = s_min( smin, facTabExp[p] );
1944 : }
1945 :
1946 175661 : i = 0;
1947 175661 : move16();
1948 3625691 : FOR( p = 0; p < npart; p++ )
1949 : {
1950 : /* Arithmetic averaging of power for all bins in partition */
1951 3450030 : temp = 0;
1952 3450030 : move32();
1953 20923620 : FOR( ; i <= part[p]; i++ )
1954 : {
1955 17473590 : temp = L_add( temp, Mpy_32_16_1( L_shl( bandpow[i], facTabExp[p] ), psize_inv[p] ) );
1956 : }
1957 3450030 : partpow[p] = L_shr( temp, sub( facTabExp[p], smin ) );
1958 3450030 : move32();
1959 : }
1960 : }
1961 :
1962 175661 : *exp_partpow = sub( exp_bandpow, smin );
1963 175661 : move16();
1964 175661 : }
1965 :
1966 : /*-------------------------------------------------------------------
1967 : * scalebands()
1968 : *
1969 : * Scale partitions (with smoothing)
1970 : *-------------------------------------------------------------------*/
1971 5885 : void scalebands(
1972 : const Word32 *partpow, /* i : Power for each partition Qx*/
1973 : Word16 *part, /* i : Partition upper boundaries (band indices starting from 0) */
1974 : const Word16 npart, /* i : Number of partitions */
1975 : Word16 *midband, /* i : Central band of each partition */
1976 : const Word16 nFFTpart, /* i : Number of FFT partitions */
1977 : const Word16 nband, /* i : Number of bands */
1978 : Word32 *bandpow, /* o : Power for each band Qx*/
1979 : const Word16 flag_fft_en )
1980 : {
1981 : Word16 i, j, s, s1, nint, delta, delta_cmp, delta_s;
1982 : Word16 startBand, startPart, stopPart, stopPartM1;
1983 : Word32 tmp, val, partpowLD64, partpowLD64M1;
1984 :
1985 :
1986 5885 : j = 0;
1987 5885 : move16();
1988 5885 : delta = 0;
1989 5885 : move16();
1990 5885 : partpowLD64M1 = 0L; /* to avoid compilation warnings */
1991 5885 : move32();
1992 :
1993 : /* Interpolate the bin/band-wise levels from the partition levels */
1994 5885 : IF( EQ_16( nband, npart ) )
1995 : {
1996 0 : Copy32( partpow, bandpow, npart );
1997 : }
1998 : ELSE
1999 : {
2000 5885 : startBand = 0;
2001 5885 : move16();
2002 5885 : startPart = 0;
2003 5885 : move16();
2004 5885 : stopPart = nFFTpart;
2005 5885 : move16();
2006 :
2007 16475 : WHILE( startBand < nband )
2008 : {
2009 10590 : stopPartM1 = sub( stopPart, 1 );
2010 10590 : test();
2011 10590 : IF( ( flag_fft_en != 0 ) || ( GE_16( startPart, nFFTpart ) ) )
2012 : {
2013 : /* first half partition */
2014 10590 : j = startPart;
2015 10590 : move16();
2016 :
2017 40191 : FOR( i = startBand; i <= midband[j]; i++ )
2018 : {
2019 29601 : bandpow[i] = partpow[j];
2020 29601 : move32();
2021 : }
2022 10590 : j = add( j, 1 );
2023 :
2024 : /* inner partitions */
2025 10590 : IF( LT_16( j, stopPart ) )
2026 : {
2027 10275 : partpowLD64M1 = BASOP_Util_Log2( partpow[j - 1] );
2028 : }
2029 :
2030 : /* Debug values to check this variable is set. */
2031 10590 : delta = 0x4000; // 1.Q14
2032 10590 : move16();
2033 10590 : delta_cmp = 0x4000; // 1.Q14
2034 10590 : move16();
2035 10590 : s1 = 1;
2036 10590 : move16();
2037 10590 : s = 1;
2038 10590 : move16();
2039 :
2040 137360 : FOR( ; j < stopPart; j++ )
2041 : {
2042 126770 : nint = sub( midband[j], midband[j - 1] );
2043 :
2044 : /* log-linear interpolation */
2045 126770 : partpowLD64 = BASOP_Util_Log2( partpow[j] );
2046 126770 : tmp = L_sub( partpowLD64, partpowLD64M1 );
2047 126770 : tmp = Mpy_32_16_1( tmp, getNormReciprocalWord16( nint ) );
2048 :
2049 : /* scale logarithmic value */
2050 126770 : tmp = L_sub( tmp, DELTA_SHIFT_LD64 );
2051 126770 : delta_s = DELTA_SHIFT;
2052 126770 : move16();
2053 :
2054 126818 : WHILE( tmp > 0 )
2055 : {
2056 48 : tmp = L_sub( tmp, 33554432l /*0.015625 Q31*/ ); // Q31
2057 48 : delta_s = add( delta_s, 1 );
2058 : }
2059 126770 : delta_cmp = shl( 1, s_max( -15, sub( WORD16_BITS - 1, delta_s ) ) );
2060 :
2061 126770 : tmp = BASOP_Util_InvLog2( tmp );
2062 126770 : s = norm_l( tmp );
2063 126770 : s1 = sub( delta_s, s );
2064 :
2065 126770 : delta = round_fx_sat( L_shl_sat( tmp, s ) ); // Q(14+s)
2066 : /* Choose scale such that the interpolation start and end point both are representable and add 1 additional bit hr. */
2067 126770 : delta_s = sub( s_min( norm_l( partpow[j - 1] ), norm_l( partpow[j] ) ), 1 );
2068 126770 : val = L_shl( partpow[j - 1], delta_s );
2069 1610079 : FOR( ; i < midband[j]; i++ )
2070 : {
2071 1483309 : val = L_shl( Mpy_32_16_1( val, delta ), s1 );
2072 1483309 : bandpow[i] = L_shr( val, delta_s );
2073 1483309 : move32();
2074 : }
2075 126770 : bandpow[i++] = partpow[j];
2076 126770 : move32();
2077 126770 : partpowLD64M1 = partpowLD64;
2078 126770 : move32();
2079 : }
2080 :
2081 10590 : IF( GT_16( shr( delta, s ), delta_cmp ) )
2082 : {
2083 2553 : delta = 0x4000; // 1.Q14
2084 2553 : move16();
2085 2553 : s1 = 1;
2086 2553 : move16();
2087 : }
2088 :
2089 : /* last half partition */
2090 10590 : val = partpow[stopPartM1]; // Qx
2091 10590 : move32();
2092 192104 : FOR( ; i <= part[stopPartM1]; i++ )
2093 : {
2094 181514 : val = L_shl( Mpy_32_16_1( val, delta ), s1 );
2095 181514 : bandpow[i] = val; // Qx
2096 181514 : move32();
2097 : }
2098 : }
2099 10590 : startBand = add( part[stopPartM1], 1 );
2100 10590 : startPart = stopPart;
2101 10590 : move16();
2102 10590 : stopPart = npart;
2103 10590 : move16();
2104 : }
2105 : }
2106 5885 : }
2107 :
2108 96040 : void scalebands_fx(
2109 : const Word32 *partpow, /* i : Power for each partition Qx*/
2110 : Word16 *part, /* i : Partition upper boundaries (band indices starting from 0) */
2111 : const Word16 npart, /* i : Number of partitions */
2112 : Word16 *midband, /* i : Central band of each partition */
2113 : const Word16 nFFTpart, /* i : Number of FFT partitions */
2114 : const Word16 nband, /* i : Number of bands */
2115 : Word32 *bandpow, /* o : Power for each band Qx*/
2116 : const Word16 flag_fft_en )
2117 : {
2118 : Word16 i, j, s, s1, nint, delta, delta_cmp, delta_s;
2119 : Word16 startBand, startPart, stopPart, stopPartM1;
2120 : Word32 tmp, val, partpowLD64, partpowLD64M1;
2121 :
2122 :
2123 96040 : j = 0;
2124 96040 : move16();
2125 96040 : delta = 0;
2126 96040 : move16();
2127 96040 : partpowLD64M1 = 0L; /* to avoid compilation warnings */
2128 96040 : move32();
2129 :
2130 : /* Interpolate the bin/band-wise levels from the partition levels */
2131 96040 : IF( EQ_16( nband, npart ) )
2132 : {
2133 0 : Copy32( partpow, bandpow, npart );
2134 : }
2135 : ELSE
2136 : {
2137 96040 : startBand = 0;
2138 96040 : move16();
2139 96040 : startPart = 0;
2140 96040 : move16();
2141 96040 : stopPart = nFFTpart;
2142 96040 : move16();
2143 :
2144 194097 : WHILE( LT_16( startBand, nband ) )
2145 : {
2146 98057 : stopPartM1 = sub( stopPart, 1 );
2147 98057 : test();
2148 98057 : IF( ( flag_fft_en != 0 ) || ( GE_16( startPart, nFFTpart ) ) )
2149 : {
2150 : /* first half partition */
2151 96062 : j = startPart;
2152 96062 : move16();
2153 :
2154 195374 : FOR( i = startBand; i <= midband[j]; i++ )
2155 : {
2156 99312 : bandpow[i] = partpow[j]; // Qx
2157 99312 : move32();
2158 : }
2159 96062 : j = add( j, 1 );
2160 :
2161 : /* inner partitions */
2162 96062 : IF( j < stopPart )
2163 : {
2164 95837 : partpowLD64M1 = BASOP_Util_Log2( L_add( partpow[j - 1], DELTA_FX ) );
2165 : }
2166 :
2167 : /* Debug values to check this variable is set. */
2168 96062 : delta = 0x4000; // 1.Q14
2169 96062 : move16();
2170 96062 : delta_cmp = 0x4000; // 1.Q14
2171 96062 : move16();
2172 96062 : s1 = 1;
2173 96062 : move16();
2174 96062 : s = 1;
2175 96062 : move16();
2176 :
2177 5783865 : FOR( ; j < stopPart; j++ )
2178 : {
2179 5687803 : nint = sub( midband[j], midband[j - 1] );
2180 :
2181 : /* log-linear interpolation */
2182 5687803 : IF( NE_32( partpow[j], MAX_32 ) )
2183 : {
2184 5687803 : partpowLD64 = BASOP_Util_Log2( L_add( partpow[j], DELTA_FX ) );
2185 : }
2186 : ELSE
2187 : {
2188 0 : partpowLD64 = BASOP_Util_Log2( partpow[j] );
2189 : }
2190 5687803 : tmp = L_sub( partpowLD64, partpowLD64M1 );
2191 5687803 : tmp = Mpy_32_16_1( tmp, getNormReciprocalWord16( nint ) );
2192 :
2193 : /* scale logarithmic value */
2194 5687803 : tmp = L_sub( tmp, DELTA_SHIFT_LD64 );
2195 5687803 : delta_s = DELTA_SHIFT;
2196 5687803 : move16();
2197 :
2198 5841011 : WHILE( tmp > 0 )
2199 : {
2200 153208 : tmp = L_sub( tmp, 33554432l /*0.015625 Q31*/ ); // Q31
2201 153208 : delta_s = add( delta_s, 1 );
2202 : }
2203 5687803 : delta_cmp = shl( 1, s_max( -15, sub( WORD16_BITS - 1, delta_s ) ) );
2204 :
2205 5687803 : tmp = BASOP_Util_InvLog2( tmp );
2206 5687803 : s = norm_l( tmp );
2207 5687803 : s1 = sub( delta_s, s );
2208 :
2209 5687803 : delta = round_fx_sat( L_shl_sat( tmp, s ) ); // Q(14+s)
2210 : /* Choose scale such that the interpolation start and end point both are representable and add 1 additional bit hr. */
2211 5687803 : delta_s = sub( s_min( norm_l( partpow[j - 1] ), norm_l( partpow[j] ) ), 1 );
2212 5687803 : val = L_shl( partpow[j - 1], delta_s );
2213 26345313 : FOR( ; i < midband[j]; i++ )
2214 : {
2215 20657510 : val = L_shl( Mpy_32_16_1( val, delta ), s1 );
2216 20657510 : bandpow[i] = L_shr( val, delta_s );
2217 20657510 : move32();
2218 : }
2219 5687803 : bandpow[i++] = partpow[j]; // Qx
2220 5687803 : move32();
2221 5687803 : partpowLD64M1 = partpowLD64;
2222 5687803 : move32();
2223 : }
2224 :
2225 96062 : IF( GT_16( shr( delta, s ), delta_cmp ) )
2226 : {
2227 11551 : delta = 0x4000; // 1.Q14
2228 11551 : move16();
2229 11551 : s1 = 1;
2230 11551 : move16();
2231 : }
2232 :
2233 : /* last half partition */
2234 96062 : val = partpow[stopPartM1]; // Qx
2235 96062 : move32();
2236 833624 : FOR( ; i <= part[stopPartM1]; i++ )
2237 : {
2238 737562 : test();
2239 737562 : IF( val != 0 && delta != 0 )
2240 : {
2241 514527 : val = L_shl( Mpy_32_16_1( val, delta ), s1 );
2242 514527 : IF( val == 0 )
2243 : {
2244 3172 : val = 1;
2245 3172 : move32();
2246 : }
2247 : }
2248 : ELSE
2249 : {
2250 223035 : val = 0;
2251 223035 : move32();
2252 : }
2253 737562 : bandpow[i] = val; // Qx
2254 737562 : move32();
2255 : }
2256 : }
2257 98057 : startBand = add( part[stopPartM1], 1 );
2258 98057 : startPart = stopPart;
2259 98057 : move16();
2260 98057 : stopPart = npart;
2261 98057 : move16();
2262 : }
2263 : }
2264 96040 : }
2265 :
2266 : /*-------------------------------------------------------------------
2267 : * getmidbands()
2268 : *
2269 : * Get central band for each partition
2270 : *-------------------------------------------------------------------*/
2271 1096668 : static void getmidbands(
2272 : const Word16 *part, /* i : Partition upper boundaries (band indices starting from 0) */
2273 : const Word16 npart, /* i : Number of partitions */
2274 : Word16 *midband, /* o : Central band of each partition */
2275 : Word16 *psize, /* o : Partition sizes */
2276 : Word16 *psize_norm, /* o : Partition sizes, fractional values */
2277 : Word16 *psize_norm_exp, /* o : Exponent for fractional partition sizes */
2278 : Word16 *psize_inv /* o : Inverse of partition sizes */
2279 : )
2280 : {
2281 : Word16 j, max_psize, shift;
2282 : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
2283 1096668 : Flag Overflow = 0;
2284 1096668 : move32();
2285 : #endif
2286 :
2287 :
2288 1096668 : max_psize = psize[0];
2289 1096668 : move16();
2290 1096668 : /* first half partition */ move16();
2291 1096668 : midband[0] = part[0];
2292 1096668 : move16();
2293 1096668 : psize[0] = add( part[0], 1 );
2294 1096668 : move16();
2295 1096668 : psize_inv[0] = getNormReciprocalWord16( psize[0] );
2296 1096668 : move16();
2297 : /* inner partitions */
2298 45927877 : FOR( j = 1; j < npart; j++ )
2299 : {
2300 44831209 : midband[j] = shr( add( add( part[j - 1], 1 ), part[j] ), 1 );
2301 44831209 : move16();
2302 44831209 : psize[j] = sub( part[j], part[j - 1] );
2303 44831209 : move16();
2304 44831209 : psize_inv[j] = getNormReciprocalWord16( psize[j] );
2305 44831209 : move16();
2306 44831209 : if ( GT_16( psize[j], max_psize ) )
2307 : {
2308 13666532 : max_psize = psize[j];
2309 13666532 : move16();
2310 : }
2311 : }
2312 :
2313 1096668 : shift = 9;
2314 1096668 : move16();
2315 1096668 : *psize_norm_exp = sub( 15, shift );
2316 1096668 : move16();
2317 47024545 : FOR( j = 0; j < npart; j++ )
2318 : {
2319 45927877 : psize_norm[j] = shl_o( psize[j], shift, &Overflow ); // Q(15 - psize_norm_exp)
2320 45927877 : move16();
2321 : }
2322 : /* minimum_statistics needs fixed exponent of 6 */
2323 1096668 : assert( norm_s( -max_psize ) >= 9 );
2324 1096668 : }
2325 :
2326 : /*-------------------------------------------------------------------
2327 : * AnalysisSTFT()
2328 : *
2329 : * STFT analysis filterbank
2330 : *-------------------------------------------------------------------*/
2331 :
2332 15 : void AnalysisSTFT(
2333 : const Word16 *timeDomainInput, /* i : pointer to time signal Q(Q)*/
2334 : Word16 Q,
2335 : Word32 *fftBuffer, /* o : FFT bins */
2336 : Word16 *fftBuffer_exp, /* i : exponent of FFT bins */
2337 : HANDLE_FD_CNG_COM hFdCngCom /* i/o: FD_CNG structure containing all buffers and variables */
2338 : )
2339 : {
2340 : Word16 i, len;
2341 : Word16 len2;
2342 : const PWord16 *olapWin;
2343 : Word16 *olapBuffer;
2344 :
2345 :
2346 15 : assert( ( hFdCngCom->fftlen >> 1 ) == hFdCngCom->frameSize );
2347 :
2348 : /* pointer inititialization */
2349 15 : assert( hFdCngCom->olapBufferAna != NULL );
2350 15 : olapBuffer = hFdCngCom->olapBufferAna;
2351 15 : olapWin = hFdCngCom->olapWinAna;
2352 :
2353 : /* olapWin factor is scaled with one bit */
2354 15 : *fftBuffer_exp = 1;
2355 15 : move16();
2356 15 : len = sub( hFdCngCom->fftlen, hFdCngCom->frameSize );
2357 15 : assert( len <= 320 ); /* see size of olapBuffer */
2358 :
2359 : /* Window the signal */
2360 15 : len2 = shr( len, 1 );
2361 2191 : FOR( i = 0; i < len2; i++ )
2362 : {
2363 2176 : move32();
2364 2176 : move32();
2365 2176 : fftBuffer[i] = L_mult( olapBuffer[i], mult_r( olapWin[i].v.im, 23170 /*1.4142135623730950488016887242097 Q14*/ ) );
2366 2176 : fftBuffer[i + len2] = L_mult( olapBuffer[i + len2], mult_r( olapWin[len2 - 1 - i].v.re, 23170 /*1.4142135623730950488016887242097 Q14*/ ) );
2367 : }
2368 15 : len2 = shr( hFdCngCom->frameSize, 1 );
2369 2191 : FOR( i = 0; i < len2; i++ )
2370 : {
2371 2176 : move32();
2372 2176 : move32();
2373 2176 : fftBuffer[i + len] = L_mult( shr_sat( timeDomainInput[i], Q ), mult_r( olapWin[i].v.re, 23170 /*1.4142135623730950488016887242097 Q14*/ ) );
2374 2176 : fftBuffer[i + len + len2] = L_mult( shr_sat( timeDomainInput[i + len2], Q ), mult_r( olapWin[len2 - 1 - i].v.im, 23170 /*1.4142135623730950488016887242097 Q14*/ ) );
2375 : }
2376 :
2377 : /* Perform FFT */
2378 15 : BASOP_rfft( fftBuffer, hFdCngCom->fftlen, fftBuffer_exp, -1 );
2379 :
2380 4367 : FOR( i = 0; i < len; i++ )
2381 : {
2382 4352 : olapBuffer[i] = shr_sat( timeDomainInput[sub( hFdCngCom->frameSize, len ) + i], Q );
2383 4352 : move16();
2384 : }
2385 15 : }
2386 :
2387 : /*-------------------------------------------------------------------
2388 : * AnalysisSTFT_fx()
2389 : *
2390 : * STFT analysis filterbank
2391 : *-------------------------------------------------------------------*/
2392 87961 : void AnalysisSTFT_fx(
2393 : const Word16 *timeDomainInput, // Q(Q)
2394 : Word16 Q,
2395 : Word32 *fftBuffer, /* o : FFT bins */
2396 : Word16 *fftBuffer_exp, /* i : exponent of FFT bins */
2397 : HANDLE_FD_CNG_COM hFdCngCom /* i/o: FD_CNG structure containing all buffers and variables */
2398 : )
2399 : {
2400 : Word16 i, len;
2401 : const Word32 *olapWin;
2402 : Word16 *olapBuffer;
2403 :
2404 87961 : assert( ( hFdCngCom->fftlen >> 1 ) == hFdCngCom->frameSize );
2405 :
2406 : /* pointer inititialization */
2407 87961 : assert( hFdCngCom->olapBufferAna != NULL );
2408 87961 : olapBuffer = hFdCngCom->olapBufferAna_fx;
2409 87961 : olapWin = hFdCngCom->olapWinAna_fx;
2410 :
2411 : /* olapWin factor is scaled with one bit */
2412 87961 : *fftBuffer_exp = 1;
2413 87961 : move16();
2414 87961 : len = sub( hFdCngCom->fftlen, hFdCngCom->frameSize );
2415 87961 : assert( len <= 320 ); /* see size of olapBuffer */
2416 :
2417 : /* Window the signal */
2418 87961 : Copy( olapBuffer + hFdCngCom->frameSize, olapBuffer, len );
2419 :
2420 25480345 : FOR( i = 0; i < hFdCngCom->frameSize; i++ )
2421 : {
2422 25392384 : olapBuffer[i + len] = shr_sat( timeDomainInput[i], Q ); // Values above MAX_16 seen with 10dB tests in float code
2423 25392384 : move16();
2424 : }
2425 :
2426 : /* Window the signal */
2427 87961 : v_L_mult_3216( olapWin, olapBuffer, fftBuffer, hFdCngCom->fftlen );
2428 :
2429 50872729 : FOR( i = 0; i < hFdCngCom->fftlen; i++ )
2430 : {
2431 50784768 : fftBuffer[i] = L_shr( fftBuffer[i], 11 );
2432 50784768 : move32();
2433 : }
2434 87961 : *fftBuffer_exp = WORD16_BITS + 11;
2435 87961 : move16();
2436 :
2437 : /* Perform FFT */
2438 87961 : RFFTN_fx( fftBuffer, hFdCngCom->fftSineTab_fx, hFdCngCom->fftlen, -1 );
2439 :
2440 :
2441 87961 : return;
2442 : }
2443 :
2444 : /*-------------------------------------------------------------------
2445 : * SynthesisSTFT_enc_ivas_fx()
2446 : *
2447 : * STFT synthesis filterbank
2448 : *-------------------------------------------------------------------*/
2449 :
2450 11704 : void SynthesisSTFT_enc_ivas_fx(
2451 : Word32 *fftBuffer, /* i : pointer to FFT bins */
2452 : Word16 fftBufferExp, /* i : exponent of FFT bins */
2453 : Word16 *timeDomainOutput, /* o : pointer to time domain signal */
2454 : Word16 *olapBuffer, /* i/o : pointer to overlap buffer */
2455 : const PWord16 *olapWin, /* i : pointer to overlap window */
2456 : Word16 tcx_transition,
2457 : HANDLE_FD_CNG_COM hFdCngCom, /* i/o : pointer to FD_CNG structure containing all buffers and variables */
2458 : Word16 gen_exc,
2459 : Word16 *Q_new, /* i : Q of generated exc_cng */
2460 : const Word16 element_mode, /* i : element mode */
2461 : const Word16 nchan_out /* i : number of output channels */
2462 : )
2463 : {
2464 : Word16 i, len, scale, tmp;
2465 : Word16 len2, len3, len4;
2466 : Word16 buf[M + 1 + L_FRAME16k];
2467 :
2468 :
2469 : /* Perform IFFT */
2470 11704 : scale = 0;
2471 11704 : move16();
2472 11704 : BASOP_rfft( fftBuffer, hFdCngCom->fftlen, &scale, 1 );
2473 11704 : fftBufferExp = add( fftBufferExp, scale );
2474 11704 : hFdCngCom->fftBuffer_exp = fftBufferExp;
2475 11704 : move16();
2476 :
2477 11704 : fftBufferExp = add( fftBufferExp, hFdCngCom->fftlenShift );
2478 :
2479 : /* Perform overlap-add */
2480 : /* Handle overlap in P/S domain for stereo */
2481 11704 : test();
2482 11704 : test();
2483 11704 : IF( ( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_DFT ) ) && EQ_16( nchan_out, 2 ) )
2484 : {
2485 0 : Copy( olapBuffer + 3 * hFdCngCom->frameSize / 4 - ( M + 1 ), buf, hFdCngCom->frameSize + M + 1 );
2486 0 : set16_fx( olapBuffer, 0, hFdCngCom->fftlen );
2487 : }
2488 : ELSE
2489 : {
2490 11704 : Copy( olapBuffer + hFdCngCom->frameSize, olapBuffer, hFdCngCom->frameSize );
2491 11704 : set16_fx( olapBuffer + hFdCngCom->frameSize, 0, hFdCngCom->frameSize );
2492 : }
2493 11704 : len2 = shr( hFdCngCom->fftlen, 2 );
2494 11704 : len4 = shr( hFdCngCom->fftlen, 3 );
2495 11704 : len3 = add( len2, len4 );
2496 11704 : len = add( hFdCngCom->frameSize, len4 );
2497 11704 : IF( tcx_transition )
2498 : {
2499 222810 : FOR( i = 0; i < len; i++ )
2500 : {
2501 222160 : olapBuffer[i] = round_fx_sat( L_shl_sat( fftBuffer[i], sub( fftBufferExp, 15 ) ) ); // Q(15 - fftBufferExp)
2502 222160 : move16();
2503 : }
2504 : }
2505 : ELSE
2506 : {
2507 805694 : FOR( i = 0; i < len4; i++ )
2508 : {
2509 794640 : olapBuffer[i + 1 * len4] = add_sat( olapBuffer[i + 1 * len4], mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 1 * len4], sub( fftBufferExp, 15 ) ) ), olapWin[i].v.im ) );
2510 794640 : move16();
2511 794640 : olapBuffer[i + 2 * len4] = add_sat( olapBuffer[i + 2 * len4], mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 2 * len4], sub( fftBufferExp, 15 ) ) ), olapWin[len4 - 1 - i].v.re ) );
2512 794640 : move16();
2513 : }
2514 1600334 : FOR( i = len3; i < len; i++ )
2515 : {
2516 1589280 : olapBuffer[i] = round_fx_sat( L_shl_sat( fftBuffer[i], sub( fftBufferExp, 15 ) ) ); // Q(15 - fftBufferExp)
2517 1589280 : move16();
2518 : }
2519 : }
2520 :
2521 850776 : FOR( i = 0; i < len4; i++ )
2522 : {
2523 839072 : olapBuffer[i + 5 * len4] = mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 5 * len4], sub( fftBufferExp, 15 ) ) ), olapWin[i].v.re );
2524 839072 : move16();
2525 839072 : olapBuffer[i + 6 * len4] = mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 6 * len4], sub( fftBufferExp, 15 ) ) ), olapWin[len4 - 1 - i].v.im );
2526 839072 : move16();
2527 : }
2528 :
2529 11704 : len = add( len, len2 );
2530 850776 : FOR( i = len; i < hFdCngCom->fftlen; i++ )
2531 : {
2532 839072 : olapBuffer[i] = 0;
2533 839072 : move16();
2534 : }
2535 :
2536 : /* Get time-domain signal */
2537 3367992 : FOR( i = 0; i < hFdCngCom->frameSize; i++ )
2538 : {
2539 3356288 : timeDomainOutput[i] = mult_r( olapBuffer[i + len4], hFdCngCom->fftlenFac );
2540 3356288 : move16();
2541 : }
2542 : /* Generate excitation */
2543 11704 : test();
2544 11704 : test();
2545 11704 : IF( ( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_DFT ) ) && EQ_16( nchan_out, 2 ) )
2546 : {
2547 0 : FOR( i = 0; i < hFdCngCom->frameSize / 2; i++ )
2548 : {
2549 0 : buf[i + ( M + 1 )] = add( buf[i + ( M + 1 )], olapBuffer[i + hFdCngCom->frameSize / 4] );
2550 0 : move16();
2551 : }
2552 :
2553 0 : FOR( i = 0; i < M + 1 + hFdCngCom->frameSize; i++ )
2554 : {
2555 0 : buf[i] = mult_r( buf[i], hFdCngCom->fftlenFac );
2556 0 : move16();
2557 : }
2558 : }
2559 : ELSE
2560 : {
2561 3566960 : FOR( i = 0; i < M + 1 + hFdCngCom->frameSize; i++ )
2562 : {
2563 3555256 : buf[i] = mult_r( olapBuffer[i + len4 - M - 1], hFdCngCom->fftlenFac );
2564 3555256 : move16();
2565 : }
2566 11704 : tmp = buf[0];
2567 11704 : move16();
2568 : }
2569 11704 : IF( EQ_16( gen_exc, 1 ) )
2570 : {
2571 :
2572 11704 : E_UTIL_f_preemph2( sub( *Q_new, 1 ), buf + 1, PREEMPH_FAC, M + hFdCngCom->frameSize, &tmp );
2573 11704 : Residu3_fx( hFdCngCom->A_cng, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize, 1 );
2574 : }
2575 11704 : IF( EQ_16( gen_exc, 2 ) )
2576 : {
2577 0 : *Q_new = E_UTIL_f_preemph3( buf + 1, PREEMPH_FAC, M + hFdCngCom->frameSize, &tmp, 1 );
2578 0 : move16();
2579 0 : Residu3_fx( hFdCngCom->A_cng, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize, 1 );
2580 : }
2581 11704 : }
2582 :
2583 : /*-------------------------------------------------------------------
2584 : * SynthesisSTFT()
2585 : *
2586 : * STFT synthesis filterbank
2587 : *-------------------------------------------------------------------*/
2588 :
2589 1023 : void SynthesisSTFT(
2590 : Word32 *fftBuffer, /* i : pointer to FFT bins */
2591 : Word16 fftBufferExp, /* i : exponent of FFT bins */
2592 : Word16 *timeDomainOutput, /* o : pointer to time domain signal Qx*/
2593 : Word16 *olapBuffer, /* i/o : pointer to overlap buffer */
2594 : const PWord16 *olapWin, /* i : pointer to overlap window */
2595 : Word16 tcx_transition,
2596 : HANDLE_FD_CNG_COM hFdCngCom, /* i/o : pointer to FD_CNG structure containing all buffers and variables */
2597 : Word16 gen_exc,
2598 : Word16 *Q_new,
2599 : const Word16 element_mode, /* i : element mode */
2600 : const Word16 nchan_out /* i : number of output channels */
2601 : )
2602 : {
2603 : Word16 i, len, scale, tmp;
2604 : Word16 len2, len3, len4;
2605 : Word16 buf[M + 1 + L_FRAME16k];
2606 :
2607 :
2608 : /* Perform IFFT */
2609 1023 : scale = 0;
2610 1023 : move16();
2611 1023 : BASOP_rfft( fftBuffer, hFdCngCom->fftlen, &scale, 1 );
2612 1023 : fftBufferExp = add( fftBufferExp, scale );
2613 1023 : hFdCngCom->fftBuffer_exp = fftBufferExp;
2614 1023 : move16();
2615 :
2616 1023 : fftBufferExp = add( fftBufferExp, hFdCngCom->fftlenShift );
2617 :
2618 : /* Perform overlap-add */
2619 : /* Handle overlap in P/S domain for stereo */
2620 1023 : IF( ( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_DFT ) ) && EQ_16( nchan_out, 2 ) )
2621 : {
2622 0 : Copy( olapBuffer + 3 * hFdCngCom->frameSize / 4 - ( M + 1 ), buf, hFdCngCom->frameSize + M + 1 );
2623 0 : set16_fx( olapBuffer, 0, hFdCngCom->fftlen );
2624 : }
2625 : ELSE
2626 : {
2627 1023 : Copy( olapBuffer + hFdCngCom->frameSize, olapBuffer, hFdCngCom->frameSize );
2628 1023 : set16_fx( olapBuffer + hFdCngCom->frameSize, 0, hFdCngCom->frameSize );
2629 : }
2630 1023 : len2 = shr( hFdCngCom->fftlen, 2 );
2631 1023 : len4 = shr( hFdCngCom->fftlen, 3 );
2632 1023 : len3 = add( len2, len4 );
2633 1023 : len = add( hFdCngCom->frameSize, len4 );
2634 1023 : IF( tcx_transition )
2635 : {
2636 0 : FOR( i = 0; i < len; i++ )
2637 : {
2638 0 : olapBuffer[i] = round_fx_sat( L_shl_sat( fftBuffer[i], fftBufferExp - 15 ) ); // Q(15 - fftBufferExp)
2639 0 : move16();
2640 : }
2641 : }
2642 : ELSE
2643 : {
2644 66495 : FOR( i = 0; i < len4; i++ )
2645 : {
2646 65472 : olapBuffer[i + 1 * len4] = add_sat( olapBuffer[i + 1 * len4], mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 1 * len4], fftBufferExp - 15 ) ), olapWin[i].v.im ) );
2647 65472 : move16();
2648 65472 : olapBuffer[i + 2 * len4] = add_sat( olapBuffer[i + 2 * len4], mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 2 * len4], fftBufferExp - 15 ) ), olapWin[len4 - 1 - i].v.re ) );
2649 65472 : move16();
2650 : }
2651 131967 : FOR( i = len3; i < len; i++ )
2652 : {
2653 130944 : olapBuffer[i] = round_fx_sat( L_shl_sat( fftBuffer[i], fftBufferExp - 15 ) );
2654 : }
2655 : }
2656 :
2657 66495 : FOR( i = 0; i < len4; i++ )
2658 : {
2659 65472 : olapBuffer[i + 5 * len4] = mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 5 * len4], fftBufferExp - 15 ) ), olapWin[i].v.re );
2660 65472 : move16();
2661 65472 : olapBuffer[i + 6 * len4] = mult_r( round_fx_sat( L_shl_sat( fftBuffer[i + 6 * len4], fftBufferExp - 15 ) ), olapWin[len4 - 1 - i].v.im );
2662 65472 : move16();
2663 : }
2664 :
2665 1023 : len = add( len, len2 );
2666 66495 : FOR( i = len; i < hFdCngCom->fftlen; i++ )
2667 : {
2668 65472 : olapBuffer[i] = 0;
2669 65472 : move16();
2670 : }
2671 :
2672 : /* Get time-domain signal */
2673 262911 : FOR( i = 0; i < hFdCngCom->frameSize; i++ )
2674 : {
2675 261888 : timeDomainOutput[i] = mult_r( olapBuffer[i + len4], hFdCngCom->fftlenFac );
2676 261888 : move16();
2677 : }
2678 : /* Generate excitation */
2679 : {
2680 280302 : FOR( i = 0; i < M + 1 + hFdCngCom->frameSize; i++ )
2681 : {
2682 279279 : buf[i] = mult_r( olapBuffer[i + len4 - M - 1], hFdCngCom->fftlenFac );
2683 279279 : move16();
2684 : }
2685 1023 : tmp = buf[0];
2686 : }
2687 1023 : IF( EQ_16( gen_exc, 1 ) )
2688 : {
2689 :
2690 0 : E_UTIL_f_preemph2( *Q_new - 1, buf + 1, PREEMPH_FAC, M + hFdCngCom->frameSize, &tmp );
2691 0 : Residu3_fx( hFdCngCom->A_cng, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize, 1 );
2692 : }
2693 1023 : IF( EQ_16( gen_exc, 2 ) )
2694 : {
2695 0 : *Q_new = E_UTIL_f_preemph3( buf + 1, PREEMPH_FAC, M + hFdCngCom->frameSize, &tmp, 1 );
2696 0 : Residu3_fx( hFdCngCom->A_cng, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize, 1 );
2697 : }
2698 1023 : }
2699 :
2700 18381 : void SynthesisSTFT_ivas_fx(
2701 : Word32 *fftBuffer, /* i : pointer to FFT bins */
2702 : Word16 fftBufferExp, /* i : exponent of FFT bins */
2703 : Word16 *timeDomainOutput, /* o : pointer to time domain signal Qx*/
2704 : Word16 *olapBuffer, /* i/o : pointer to overlap buffer */
2705 : const PWord16 *olapWin, /* i : pointer to overlap window */
2706 : Word16 tcx_transition,
2707 : HANDLE_FD_CNG_COM hFdCngCom, /* i/o : pointer to FD_CNG structure containing all buffers and variables */
2708 : Word16 gen_exc,
2709 : Word16 *Q_new,
2710 : const Word16 element_mode, /* i : element mode */
2711 : const Word16 nchan_out /* i : number of output channels */
2712 : )
2713 : {
2714 : Word16 i, len, scale, tmp, sft, exp, tmp1;
2715 : Word16 len2, len3, len4;
2716 : Word16 buf[M + 1 + L_FRAME16k];
2717 : Word32 L_olapBuffer[FFTLEN];
2718 :
2719 :
2720 : /* Perform IFFT */
2721 18381 : scale = 0;
2722 18381 : move16();
2723 18381 : BASOP_rfft( fftBuffer, hFdCngCom->fftlen, &scale, 1 );
2724 18381 : fftBufferExp = add( fftBufferExp, scale );
2725 18381 : hFdCngCom->fftBuffer_exp = fftBufferExp;
2726 18381 : move16();
2727 :
2728 18381 : sft = getScaleFactor32( fftBuffer, hFdCngCom->fftlen );
2729 18381 : scale_sig32( fftBuffer, hFdCngCom->fftlen, sft );
2730 18381 : fftBufferExp = sub( fftBufferExp, sft );
2731 18381 : hFdCngCom->fftBuffer_exp = fftBufferExp;
2732 18381 : move16();
2733 :
2734 18381 : fftBufferExp = add( fftBufferExp, hFdCngCom->fftlenShift );
2735 :
2736 : /* Perform overlap-add */
2737 : /* Handle overlap in P/S domain for stereo */
2738 18381 : test();
2739 18381 : test();
2740 18381 : IF( ( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_DFT ) ) && EQ_16( nchan_out, 2 ) )
2741 : {
2742 0 : Copy( olapBuffer + 3 * hFdCngCom->frameSize / 4 - ( M + 1 ), buf, hFdCngCom->frameSize + M + 1 );
2743 0 : set16_fx( olapBuffer, 0, hFdCngCom->fftlen );
2744 : }
2745 : ELSE
2746 : {
2747 18381 : Copy_Scale_sig_16_32_no_sat( olapBuffer + hFdCngCom->frameSize, L_olapBuffer, hFdCngCom->frameSize, add( sub( hFdCngCom->olapBufferSynth_exp, sub( 15, hFdCngCom->fftlenShift ) ), 16 ) ); /* exp: hFdCngCom->olapBufferSynth_exp -> (15 - fftlenShift) */
2748 18381 : set16_fx( olapBuffer + hFdCngCom->frameSize, 0, hFdCngCom->frameSize );
2749 : }
2750 18381 : len2 = shr( hFdCngCom->fftlen, 2 );
2751 18381 : len4 = shr( hFdCngCom->fftlen, 3 );
2752 18381 : len3 = add( len2, len4 );
2753 18381 : len = add( hFdCngCom->frameSize, len4 );
2754 18381 : tmp1 = sub( fftBufferExp, 15 );
2755 18381 : IF( tcx_transition )
2756 : {
2757 606892 : FOR( i = 0; i < len; i++ )
2758 : {
2759 605120 : L_olapBuffer[i] = L_shl_sat( fftBuffer[i], tmp1 ); /* Q(31 - (15 - fftlenShift) ) */
2760 605120 : move32();
2761 : }
2762 : }
2763 : ELSE
2764 : {
2765 1256353 : FOR( i = 0; i < len4; i++ )
2766 : {
2767 1239744 : L_olapBuffer[i + 1 * len4] = Madd_32_16( L_olapBuffer[i + 1 * len4], L_shl_sat( fftBuffer[i + 1 * len4], tmp1 ), olapWin[i].v.im ); /* Q(31 - (15 - fftlenShift) ) */
2768 1239744 : move32();
2769 1239744 : L_olapBuffer[i + 2 * len4] = Madd_32_16( L_olapBuffer[i + 2 * len4], L_shl_sat( fftBuffer[i + 2 * len4], tmp1 ), olapWin[len4 - 1 - i].v.re ); /* Q(31 - (15 - fftlenShift) ) */
2770 1239744 : move32();
2771 : }
2772 2496097 : FOR( i = len3; i < len; i++ )
2773 : {
2774 2479488 : L_olapBuffer[i] = L_shl_sat( fftBuffer[i], tmp1 ); /* Q(31 - (15 - fftlenShift) ) */
2775 2479488 : move32();
2776 : }
2777 : }
2778 :
2779 1379149 : FOR( i = 0; i < len4; i++ )
2780 : {
2781 1360768 : L_olapBuffer[i + 5 * len4] = Mpy_32_16_1( L_shl_sat( fftBuffer[i + 5 * len4], tmp1 ), olapWin[i].v.re ); /* Q(31 - (15 - fftlenShift) ) */
2782 1360768 : move32();
2783 1360768 : L_olapBuffer[i + 6 * len4] = Mpy_32_16_1( L_shl_sat( fftBuffer[i + 6 * len4], tmp1 ), olapWin[len4 - 1 - i].v.im ); /* Q(31 - (15 - fftlenShift) ) */
2784 1360768 : move32();
2785 : }
2786 :
2787 18381 : len = add( len, len2 );
2788 1379149 : FOR( i = len; i < hFdCngCom->fftlen; i++ )
2789 : {
2790 1360768 : L_olapBuffer[i] = 0;
2791 1360768 : move32();
2792 : }
2793 :
2794 18381 : sft = L_norm_arr( L_olapBuffer, hFdCngCom->fftlen );
2795 18381 : IF( NE_16( sft, 31 ) )
2796 : {
2797 17096 : Copy_Scale_sig32_16( L_olapBuffer, olapBuffer, hFdCngCom->fftlen, sft );
2798 17096 : hFdCngCom->olapBufferSynth_exp = sub( sub( 15, hFdCngCom->fftlenShift ), sft );
2799 17096 : move16();
2800 : }
2801 :
2802 : /* Get time-domain signal */
2803 5461453 : FOR( i = 0; i < hFdCngCom->frameSize; i++ )
2804 : {
2805 5443072 : timeDomainOutput[i] = mult_r( olapBuffer[i + len4], hFdCngCom->fftlenFac );
2806 5443072 : move16();
2807 : }
2808 : /* Generate excitation */
2809 : {
2810 5773930 : FOR( i = 0; i < M + 1 + hFdCngCom->frameSize; i++ )
2811 : {
2812 5755549 : buf[i] = mult_r( olapBuffer[i + len4 - M - 1], hFdCngCom->fftlenFac );
2813 5755549 : move16();
2814 : }
2815 18381 : exp = add( hFdCngCom->olapBufferSynth_exp, hFdCngCom->fftlenShift );
2816 18381 : tmp = buf[0];
2817 : }
2818 18381 : IF( EQ_16( gen_exc, 1 ) )
2819 : {
2820 18381 : E_UTIL_f_preemph2( 0, buf + 1, PREEMPH_FAC, add( M, hFdCngCom->frameSize ), &tmp );
2821 18381 : Residu3_fx( hFdCngCom->A_cng, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize, 0 );
2822 18381 : *Q_new = sub( 15, exp );
2823 18381 : move16();
2824 : }
2825 18381 : IF( EQ_16( gen_exc, 2 ) )
2826 : {
2827 0 : *Q_new = E_UTIL_f_preemph3( buf + 1, PREEMPH_FAC, add( M, hFdCngCom->frameSize ), &tmp, 0 );
2828 0 : move16();
2829 0 : Residu3_fx( hFdCngCom->A_cng, buf + 1 + M, hFdCngCom->exc_cng, hFdCngCom->frameSize, negate( *Q_new ) );
2830 0 : *Q_new = sub( 15, exp );
2831 0 : move16();
2832 : }
2833 18381 : }
2834 :
2835 : /**************************************************************************************
2836 : * Compute some values used in the bias correction of the minimum statistics algorithm *
2837 : **************************************************************************************/
2838 13820 : void mhvals(
2839 : const Word16 d,
2840 : Word16 *m /*, Word16 * h*/
2841 : )
2842 : {
2843 : Word16 i, j;
2844 13820 : Word16 len = SIZE_SCALE_TABLE_CN;
2845 13820 : move16();
2846 :
2847 :
2848 13820 : assert( d == 72 || d == 12 ); /* function only tested for d==72 and d==12) */
2849 13820 : i = 0;
2850 13820 : move16();
2851 117470 : FOR( i = 0; i < len; i++ )
2852 : {
2853 117470 : IF( LE_16( d, d_array[i] ) )
2854 : {
2855 13820 : BREAK;
2856 : }
2857 : }
2858 13820 : IF( EQ_16( i, len ) )
2859 : {
2860 0 : i = sub( len, 1 );
2861 0 : j = i;
2862 0 : move16();
2863 : }
2864 : ELSE
2865 : {
2866 13820 : j = sub( i, 1 );
2867 : }
2868 13820 : IF( EQ_16( d, d_array[i] ) )
2869 : {
2870 0 : *m = m_array[i];
2871 0 : move16();
2872 : }
2873 : ELSE
2874 : {
2875 : Word32 qi_m, qj_m, q_m, tmp1_m, tmp2_m;
2876 : Word16 qi_e, qj_e, q_e, tmp1_e, tmp2_e, tmp1_w16_m, tmp1_w16_e, shift;
2877 :
2878 :
2879 : /* d_array has exponent 15 */
2880 13820 : qj_e = 15;
2881 13820 : move16();
2882 13820 : qj_m = L_deposit_h( d_array[i - 1] );
2883 :
2884 13820 : qi_e = 15;
2885 13820 : move16();
2886 13820 : qi_m = L_deposit_h( d_array[i] );
2887 :
2888 13820 : q_e = 15;
2889 13820 : move16();
2890 13820 : q_m = L_deposit_h( d );
2891 :
2892 13820 : qj_m = Sqrt32( qj_m, &qj_e );
2893 13820 : qi_m = Sqrt32( qi_m, &qi_e );
2894 13820 : q_m = Sqrt32( q_m, &q_e );
2895 :
2896 13820 : tmp1_m = Mpy_32_32( qi_m, qj_m );
2897 13820 : tmp1_e = add( qi_e, qj_e );
2898 13820 : tmp1_m = L_deposit_h( BASOP_Util_Divide3232_Scale( tmp1_m, q_m, &shift ) );
2899 13820 : tmp1_e = sub( tmp1_e, q_e );
2900 13820 : tmp1_e = add( tmp1_e, shift );
2901 13820 : tmp1_m = BASOP_Util_Add_Mant32Exp( tmp1_m, tmp1_e, L_negate( qj_m ), qj_e, &tmp1_e );
2902 :
2903 13820 : tmp2_m = BASOP_Util_Add_Mant32Exp( qi_m, qi_e, L_negate( qj_m ), qj_e, &tmp2_e );
2904 13820 : tmp1_w16_m = round_fx( tmp2_m );
2905 13820 : tmp1_w16_e = tmp2_e;
2906 13820 : move16();
2907 13820 : BASOP_Util_Divide_MantExp( sub( m_array[j], m_array[i] ), 0, tmp1_w16_m, tmp1_w16_e, &tmp1_w16_m, &tmp1_w16_e );
2908 :
2909 13820 : tmp2_m = Mpy_32_16_1( tmp1_m, tmp1_w16_m );
2910 13820 : tmp2_e = add( tmp1_e, tmp1_w16_e );
2911 :
2912 13820 : tmp2_m = BASOP_Util_Add_Mant32Exp( tmp2_m, tmp2_e, L_deposit_h( m_array[i] ), 0, &tmp2_e );
2913 13820 : assert( tmp2_e == 0 );
2914 13820 : *m = extract_h( tmp2_m );
2915 13820 : move32();
2916 : }
2917 13820 : }
2918 :
2919 : /*-------------------------------------------------------------------
2920 : * rand_gauss()
2921 : *
2922 : * Random generator with Gaussian distribution with mean 0 and std 1
2923 : * Returns:
2924 : * random signal format Q3.29
2925 : *-------------------------------------------------------------------*/
2926 46935923 : Word32 rand_gauss( Word16 *seed )
2927 : {
2928 : Word32 temp;
2929 : Word16 loc_seed;
2930 :
2931 : /* This unrolled version reduces the cycles from 17 to 10 */
2932 46935923 : loc_seed = extract_l( L_mac0( 13849, *seed, 31821 ) );
2933 46935923 : temp = L_deposit_l( loc_seed );
2934 :
2935 46935923 : loc_seed = extract_l( L_mac0( 13849, loc_seed, 31821 ) );
2936 46935923 : temp = L_msu0( temp, loc_seed, -1 );
2937 :
2938 46935923 : loc_seed = extract_l( L_mac0( 13849, loc_seed, 31821 ) );
2939 46935923 : temp = L_msu0( temp, loc_seed, -1 );
2940 :
2941 46935923 : *seed = loc_seed;
2942 46935923 : move16();
2943 46935923 : return L_shl( temp, WORD16_BITS - CNG_RAND_GAUSS_SHIFT );
2944 : }
2945 :
2946 : /*-------------------------------------------------------------------
2947 : * lpc_from_spectrum()
2948 : *
2949 : *
2950 : *-------------------------------------------------------------------*/
2951 :
2952 6605 : void lpc_from_spectrum(
2953 : HANDLE_FD_CNG_COM hFdCngCom,
2954 : const Word16 start, /*i : start band*/
2955 : const Word16 stop, /*i : stop band*/
2956 : const Word16 preemph_fac /*i : preemphase factor format Q1.15*/
2957 : )
2958 : {
2959 : Word16 i, s1, s2, s3, fftlen2, scale, fftlen4, fftlen8, len, step, preemph_fac2;
2960 : Word32 maxVal, r[32], fftBuffer[FFTLEN], *ptr, *pti, nf;
2961 : Word16 tmp, r_h[32], r_l[32];
2962 : const PWord16 *table;
2963 :
2964 6605 : Word32 *powspec = hFdCngCom->cngNoiseLevel; /*i : pointer to noise levels format Q5.27*/
2965 6605 : Word16 powspec_exp = hFdCngCom->cngNoiseLevelExp;
2966 6605 : move16();
2967 6605 : Word16 fftlen = hFdCngCom->fftlen; /*i : size of fft*/
2968 6605 : Word16 *A = hFdCngCom->A_cng; /*o : lpc coefficients format Q3.12*/
2969 6605 : move16();
2970 6605 : Word16 lpcorder = M;
2971 6605 : move16();
2972 :
2973 6605 : scale = 0;
2974 6605 : move16();
2975 6605 : fftlen2 = shr( fftlen, 1 );
2976 6605 : fftlen4 = shr( fftlen, 2 );
2977 6605 : fftlen8 = shr( fftlen, 3 );
2978 :
2979 : /* Power Spectrum */
2980 6605 : maxVal = 0;
2981 6605 : move32();
2982 6605 : len = sub( stop, start );
2983 1947635 : FOR( i = 0; i < len; i++ )
2984 : {
2985 1941030 : maxVal = L_max( maxVal, L_abs( powspec[i] ) );
2986 : }
2987 6605 : s1 = norm_l( maxVal );
2988 6605 : nf = L_shr_r_sat( 1099511680l /*1e-3f Q40*/, add( sub( powspec_exp, s1 ), 9 ) );
2989 6605 : ptr = fftBuffer;
2990 6605 : pti = fftBuffer + 1;
2991 :
2992 19815 : FOR( i = 0; i < start; i++ )
2993 : {
2994 13210 : *ptr = nf;
2995 13210 : move32();
2996 13210 : *pti = L_deposit_l( 0 );
2997 13210 : move32();
2998 13210 : ptr += 2;
2999 13210 : pti += 2;
3000 : }
3001 :
3002 1947635 : FOR( ; i < stop; i++ )
3003 : {
3004 1941030 : *ptr = L_max( nf, L_shl( powspec[i - start], s1 ) );
3005 1941030 : move32();
3006 1941030 : *pti = L_deposit_l( 0 );
3007 1941030 : move32();
3008 1941030 : ptr += 2;
3009 1941030 : pti += 2;
3010 : }
3011 :
3012 6797 : FOR( ; i < fftlen2; i++ )
3013 : {
3014 192 : *ptr = nf;
3015 192 : move32();
3016 192 : *pti = L_deposit_l( 0 );
3017 192 : move32();
3018 192 : ptr += 2;
3019 192 : pti += 2;
3020 : }
3021 :
3022 6605 : fftBuffer[1] = nf;
3023 6605 : move32();
3024 :
3025 : /* Pre-emphasis */
3026 :
3027 6605 : BASOP_getTables( &table, NULL, &step, fftlen4 );
3028 6605 : tmp = round_fx( L_shr( L_add( 0x40000000, L_mult0( preemph_fac, preemph_fac ) ), 1 ) );
3029 6605 : preemph_fac2 = shr( preemph_fac, 1 );
3030 6605 : ptr = fftBuffer;
3031 6605 : *ptr = Mpy_32_16_1( *ptr, sub( tmp, preemph_fac2 ) );
3032 6605 : move32();
3033 6605 : ptr += 2;
3034 488608 : FOR( i = 1; i < fftlen8; i++ )
3035 : {
3036 482003 : move32();
3037 482003 : *ptr = Mpy_32_16_1( *ptr, sub( tmp, mult_r( preemph_fac2, add( shr( table[i - 1].v.re, 1 ), shr( table[i].v.re, 1 ) ) ) ) );
3038 482003 : ptr += 2;
3039 : }
3040 6605 : move32();
3041 6605 : *ptr = Mpy_32_16_1( *ptr, sub( tmp, mult_r( preemph_fac2, add( shr( table[fftlen8 - 1].v.re, 1 ), shr( table[fftlen8 - 1].v.im, 1 ) ) ) ) );
3042 6605 : ptr += 2;
3043 488608 : FOR( i = 1; i < fftlen8; i++ )
3044 : {
3045 482003 : move32();
3046 482003 : *ptr = Mpy_32_16_1( *ptr, sub( tmp, mult_r( preemph_fac2, add( shr( table[fftlen8 - i - 1].v.im, 1 ), shr( table[fftlen8 - i].v.im, 1 ) ) ) ) );
3047 482003 : ptr += 2;
3048 : }
3049 6605 : move32();
3050 6605 : *ptr = Mpy_32_16_1( *ptr, tmp );
3051 6605 : ptr += 2;
3052 488608 : FOR( i = 1; i < fftlen8; i++ )
3053 : {
3054 482003 : move32();
3055 482003 : *ptr = Mpy_32_16_1( *ptr, add( tmp, mult_r( preemph_fac2, add( shr( table[i - 1].v.im, 1 ), shr( table[i].v.im, 1 ) ) ) ) );
3056 482003 : ptr += 2;
3057 : }
3058 6605 : move32();
3059 6605 : *ptr = Mpy_32_16_1( *ptr, add( tmp, mult_r( preemph_fac2, add( shr( table[fftlen8 - 1].v.re, 1 ), shr( table[fftlen8 - 1].v.im, 1 ) ) ) ) );
3060 6605 : ptr += 2;
3061 488608 : FOR( i = 1; i < fftlen8; i++ )
3062 : {
3063 482003 : move32();
3064 482003 : *ptr = Mpy_32_16_1( *ptr, add( tmp, mult_r( preemph_fac2, add( shr( table[fftlen8 - i - 1].v.re, 1 ), shr( table[fftlen8 - i].v.re, 1 ) ) ) ) );
3065 482003 : ptr += 2;
3066 : }
3067 6605 : move32();
3068 6605 : fftBuffer[1] = Mpy_32_16_1( fftBuffer[1], add( tmp, preemph_fac2 ) );
3069 6605 : maxVal = 0;
3070 6605 : move32();
3071 3915469 : FOR( i = 0; i < fftlen; i++ )
3072 : {
3073 3908864 : maxVal = L_max( maxVal, L_abs( fftBuffer[i] ) );
3074 : }
3075 6605 : s2 = norm_l( maxVal );
3076 3915469 : FOR( i = 0; i < fftlen; i++ )
3077 : {
3078 3908864 : fftBuffer[i] = L_shl( fftBuffer[i], s2 );
3079 3908864 : move32();
3080 : }
3081 :
3082 : /* Autocorrelation */
3083 :
3084 6605 : BASOP_rfft( fftBuffer, fftlen, &scale, 1 );
3085 :
3086 6605 : s3 = getScaleFactor32( fftBuffer, add( lpcorder, 1 ) );
3087 :
3088 118890 : FOR( i = 0; i <= lpcorder; i++ )
3089 : {
3090 112285 : r[i] = L_shl( fftBuffer[i], s3 );
3091 112285 : move32();
3092 : }
3093 :
3094 6605 : r[0] = Mpy_32_32( r[0], 1074278656l /*1.0005f Q30*/ );
3095 6605 : move32();
3096 112285 : FOR( i = 1; i <= lpcorder; i++ )
3097 : {
3098 105680 : r[i] = Mpy_32_32( r[i], 1073741824l /*1.f Q30*/ );
3099 105680 : move32();
3100 : }
3101 6605 : s3 = getScaleFactor32( r, add( lpcorder, 1 ) );
3102 :
3103 118890 : FOR( i = 0; i <= lpcorder; i++ )
3104 : {
3105 112285 : r[i] = L_shl( r[i], s3 );
3106 112285 : move32();
3107 : }
3108 :
3109 118890 : FOR( i = 0; i <= lpcorder; i++ )
3110 : {
3111 112285 : L_Extract( r[i], &r_h[i], &r_l[i] );
3112 : }
3113 :
3114 : /* LPC */
3115 :
3116 6605 : E_LPC_lev_dur( r_h, r_l, A, NULL, lpcorder, NULL );
3117 6605 : }
3118 :
3119 : /*
3120 : msvq_decoder
3121 :
3122 : Parameters:
3123 :
3124 : cb i : Codebook (indexed cb[stages][levels][p]) format Q9.7
3125 : stages i : Number of stages
3126 : N i : Vector dimension
3127 : maxN i : Codebook vector dimension
3128 : Idx o : Indices
3129 : uq[] i : Quantized vector format Q9.7
3130 :
3131 :
3132 : Function:
3133 : multi stage vector dequantisation
3134 :
3135 : Returns:
3136 : void
3137 : */
3138 0 : void msvq_decoder(
3139 : const Word16 *const cb[], /* i : Codebook (indexed cb[*stages][levels][p]) */
3140 : const Word16 stages, /* i : Number of stages */
3141 : const Word16 N, /* i : Vector dimension */
3142 : const Word16 maxN, /* i : Codebook vector dimension */
3143 : const Word16 Idx[], /* i : Indices */
3144 : Word16 *uq /* o : quantized vector */
3145 : )
3146 : {
3147 : Word16 s, i, offset;
3148 :
3149 : // PMT("msvq_decoder Not verified")
3150 :
3151 0 : offset = i_mult( Idx[0], maxN );
3152 0 : FOR( i = 0; i < N; i++ )
3153 : {
3154 0 : uq[i] = cb[0][offset + i];
3155 0 : move16();
3156 : }
3157 :
3158 0 : FOR( s = 1; s < stages; s++ )
3159 : {
3160 0 : offset = i_mult( Idx[s], maxN );
3161 :
3162 0 : FOR( i = 0; i < N; i++ )
3163 : {
3164 0 : uq[i] = add( uq[i], cb[s][offset + i] );
3165 0 : move16();
3166 : }
3167 : }
3168 0 : }
3169 : /*-------------------------------------------------------------------
3170 : * FdCng_exc()
3171 : *
3172 : * Generate FD-CNG as LP excitation
3173 : *-------------------------------------------------------------------*/
3174 :
3175 30085 : void FdCng_exc(
3176 : HANDLE_FD_CNG_COM hFdCngCom,
3177 : Word16 *CNG_mode,
3178 : Word16 L_frame,
3179 : Word16 *lsp_old,
3180 : Word16 first_CNG,
3181 : Word16 *lspCNG,
3182 : Word16 *Aq, /* o: LPC coeffs Q12*/
3183 : Word16 *lsp_new, /* o: lsp Q15 */
3184 : Word16 *lsf_new, /* o: lsf Qlog2(2.56) */
3185 : Word16 *exc, /* o: LP excitation Q12 */
3186 : Word16 *exc2, /* o: LP excitation Q12 */
3187 : Word16 *bwe_exc /* o: LP excitation for BWE Q12*/
3188 : )
3189 : {
3190 : Word16 i;
3191 :
3192 30085 : *CNG_mode = -1;
3193 30085 : move16();
3194 :
3195 167575 : FOR( i = 0; i < L_frame / L_SUBFR; i++ )
3196 : {
3197 137490 : Copy( hFdCngCom->A_cng, Aq + i * ( M + 1 ), M + 1 );
3198 : }
3199 :
3200 30085 : E_LPC_a_lsp_conversion( Aq, lsp_new, lsp_old, M );
3201 :
3202 30085 : IF( first_CNG == 0 )
3203 : {
3204 11250 : Copy( lsp_old, lspCNG, M );
3205 : }
3206 511445 : FOR( i = 0; i < M; i++ )
3207 : {
3208 : /* AR low-pass filter */
3209 481360 : lspCNG[i] = mac_r( L_mult( CNG_ISF_FACT_FX, lspCNG[i] ), 32768 - CNG_ISF_FACT_FX, lsp_new[i] );
3210 481360 : move16(); /* Q15 (15+15+1-16) */
3211 : }
3212 :
3213 30085 : IF( EQ_16( L_frame, L_FRAME16k ) )
3214 : {
3215 17150 : lsp2lsf_fx( lsp_new, lsf_new, M, INT_FS_16k_FX );
3216 : }
3217 : ELSE
3218 : {
3219 12935 : E_LPC_lsp_lsf_conversion( lsp_new, lsf_new, M );
3220 : }
3221 30085 : Copy( hFdCngCom->exc_cng, exc, L_frame );
3222 30085 : Copy( hFdCngCom->exc_cng, exc2, L_frame );
3223 30085 : IF( bwe_exc != NULL )
3224 : {
3225 22862 : IF( EQ_16( L_frame, L_FRAME ) )
3226 : {
3227 12935 : interp_code_5over2_fx( exc2, bwe_exc, L_frame );
3228 : }
3229 : ELSE
3230 : {
3231 9927 : interp_code_4over2_fx( exc2, bwe_exc, L_frame );
3232 : }
3233 : }
3234 30085 : }
3235 :
3236 : /*-------------------------------------------------------------------
3237 : * SynthesisSTFT_fx()
3238 : *
3239 : * STFT synthesis filterbank
3240 : *-------------------------------------------------------------------*/
3241 :
3242 59366 : void SynthesisSTFT_fx(
3243 : Word32 *fftBuffer,
3244 : /* i : FFT bins */ // Q15
3245 : Word32 *timeDomainOutput,
3246 : Word32 *olapBuffer, // Qin
3247 : const Word16 *olapWin,
3248 : const Word16 tcx_transition,
3249 : HANDLE_FD_CNG_COM hFdCngCom, /* i/o: FD_CNG structure containing all buffers and variables */
3250 : const Word16 element_mode, /* i : element mode */
3251 : const Word16 nchan_out /* i : number of output channels */
3252 : )
3253 : {
3254 : Word16 i;
3255 : Word32 buf_fx[M + 1 + 320], tmp_fx;
3256 :
3257 : /* Perform IFFT */
3258 59366 : RFFTN_fx( fftBuffer, hFdCngCom->fftSineTab_fx, hFdCngCom->fftlen, 1 );
3259 :
3260 : /* Handle overlap in P/S domain for stereo */
3261 59366 : test();
3262 59366 : test();
3263 59366 : IF( ( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_DFT ) ) && EQ_16( nchan_out, 2 ) )
3264 : {
3265 876 : Copy32( olapBuffer + sub( i_mult( 3, shr( hFdCngCom->frameSize, 2 ) ), ( M + 1 ) ), buf_fx, add( hFdCngCom->frameSize, M + 1 ) ); // Qin
3266 876 : set32_fx( olapBuffer, 0, hFdCngCom->fftlen );
3267 : }
3268 : ELSE
3269 : {
3270 58490 : Copy32( olapBuffer + hFdCngCom->frameSize, olapBuffer, hFdCngCom->frameSize );
3271 58490 : set32_fx( olapBuffer + hFdCngCom->frameSize, 0, hFdCngCom->frameSize ); /*olapBuffer, fftBuffer, olapWin*/
3272 : }
3273 :
3274 59366 : IF( tcx_transition )
3275 : {
3276 0 : FOR( i = 0; i < ( 5 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
3277 : {
3278 0 : olapBuffer[i] = fftBuffer[i]; // Q15
3279 0 : move32();
3280 : }
3281 : }
3282 : ELSE
3283 : {
3284 8535718 : FOR( i = hFdCngCom->frameSize / 4; i < ( 3 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
3285 : {
3286 8476352 : olapBuffer[i] = L_add( olapBuffer[i], Mpy_32_16_1( fftBuffer[i], olapWin[( i - ( hFdCngCom->frameSize >> 2 ) )] ) );
3287 8476352 : move32();
3288 : }
3289 8535718 : FOR( ; i < ( 5 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
3290 : {
3291 8476352 : olapBuffer[i] = fftBuffer[i];
3292 8476352 : move32();
3293 : }
3294 : }
3295 8535718 : FOR( ; i < ( 7 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
3296 : {
3297 8476352 : olapBuffer[i] = Mpy_32_16_1( fftBuffer[i], olapWin[( i - ( 3 * ( hFdCngCom->frameSize >> 2 ) ) )] );
3298 8476352 : move32();
3299 : }
3300 :
3301 4297542 : FOR( ; i < hFdCngCom->fftlen; i++ )
3302 : {
3303 4238176 : olapBuffer[i] = 0;
3304 4238176 : move32();
3305 : }
3306 :
3307 59366 : Word32 fftScale = 0;
3308 59366 : SWITCH( hFdCngCom->fftlen )
3309 : {
3310 27422 : case 640:
3311 27422 : fftScale = FFT_SCALING_640;
3312 27422 : move32();
3313 27422 : BREAK;
3314 31944 : case 512:
3315 31944 : fftScale = FFT_SCALING_512;
3316 31944 : move32();
3317 31944 : BREAK;
3318 0 : default:
3319 0 : assert( !"Not supported FFT length!" );
3320 : }
3321 : /* Get time-domain signal */
3322 : // v_multc(olapBuffer + hFdCngCom->frameSize / 4, (float)(hFdCngCom->fftlen / 2), timeDomainOutput, hFdCngCom->frameSize);
3323 59366 : v_multc_fixed( olapBuffer + hFdCngCom->frameSize / 4, fftScale, timeDomainOutput, hFdCngCom->frameSize ); // Q_in - 9
3324 : /* Get excitation */
3325 59366 : test();
3326 59366 : test();
3327 59366 : IF( ( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_DFT ) ) && EQ_16( nchan_out, 2 ) )
3328 : {
3329 113004 : FOR( i = 0; i < hFdCngCom->frameSize / 2; i++ )
3330 : {
3331 112128 : buf_fx[i + ( M + 1 )] = L_add( buf_fx[i + ( M + 1 )], olapBuffer[( i + ( hFdCngCom->frameSize >> 2 ) )] );
3332 112128 : move32();
3333 : }
3334 : // v_multc(buf, (float)(hFdCngCom->fftlen / 2), buf, M + 1 + hFdCngCom->frameSize);
3335 876 : v_multc_fixed( buf_fx, fftScale, buf_fx, add( M + 1, hFdCngCom->frameSize ) );
3336 : }
3337 : ELSE
3338 : {
3339 : // v_multc(olapBuffer + hFdCngCom->frameSize / 4 - (M + 1), (float)(hFdCngCom->fftlen / 2), buf, M + 1 + hFdCngCom->frameSize);
3340 58490 : v_multc_fixed( olapBuffer + sub( shr( hFdCngCom->frameSize, 2 ), ( M + 1 ) ), fftScale, buf_fx, add( M + 1, hFdCngCom->frameSize ) );
3341 : }
3342 :
3343 59366 : tmp_fx = buf_fx[0];
3344 59366 : move32();
3345 : // preemph(buf + 1, PREEMPH_FAC_FLT, M + hFdCngCom->frameSize, &tmp);
3346 59366 : preemph_ivas_fx( buf_fx + 1, PREEMPH_FAC, add( M, hFdCngCom->frameSize ), &tmp_fx );
3347 : // residu(hFdCngCom->A_cng_flt, M, buf + 1 + M, hFdCngCom->exc_cng_flt, hFdCngCom->frameSize);
3348 :
3349 : // residu_ivas_fx( hFdCngCom->A_cng, Q13, M, buf_fx + 1 + M, hFdCngCom->exc_cng_32fx, hFdCngCom->frameSize );
3350 59366 : residu_ivas_fx( hFdCngCom->A_cng, ( 15 - norm_s( hFdCngCom->A_cng[0] - 1 ) ), M, buf_fx + 1 + M, hFdCngCom->exc_cng_32fx, hFdCngCom->frameSize );
3351 :
3352 59366 : return;
3353 : }
3354 :
3355 4095 : void SynthesisSTFT_dirac_fx(
3356 : Word32 *fftBuffer,
3357 : /* i : FFT bins */ // hFdCngCom->fftBuffer_exp
3358 : Word32 *timeDomainOutput,
3359 : Word32 *olapBuffer, // Q_in
3360 : const Word16 *olapWin,
3361 : const Word16 samples_out,
3362 : HANDLE_FD_CNG_COM hFdCngCom /* i/o: FD_CNG structure containing all buffers and variables */
3363 : )
3364 : {
3365 : Word16 i;
3366 : Word32 buf[M + 1 + 320], tmp;
3367 :
3368 : /* Perform IFFT */
3369 4095 : RFFTN_fx( fftBuffer, hFdCngCom->fftSineTab_fx, hFdCngCom->fftlen, 1 );
3370 :
3371 : /* Handle overlap in P/S domain for stereo */
3372 4095 : Copy32( olapBuffer + hFdCngCom->frameSize, olapBuffer, hFdCngCom->frameSize );
3373 4095 : set32_fx( olapBuffer + hFdCngCom->frameSize, 0, hFdCngCom->frameSize ); /*olapBuffer, fftBuffer, olapWin*/
3374 :
3375 611711 : FOR( i = ( hFdCngCom->frameSize >> 2 ); i < ( 3 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
3376 : {
3377 607616 : olapBuffer[i] = L_add( olapBuffer[i], Mpy_32_16_1( fftBuffer[i], olapWin[( i - ( hFdCngCom->frameSize >> 2 ) )] ) );
3378 607616 : move32();
3379 : }
3380 611711 : FOR( ; i < ( 5 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
3381 : {
3382 607616 : olapBuffer[i] = fftBuffer[i];
3383 607616 : move32();
3384 : }
3385 :
3386 611711 : FOR( ; i < ( 7 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
3387 : {
3388 607616 : olapBuffer[i] = fftBuffer[i];
3389 607616 : move32();
3390 : }
3391 :
3392 307903 : FOR( ; i < hFdCngCom->fftlen; i++ )
3393 : {
3394 303808 : olapBuffer[i] = 0;
3395 303808 : move32();
3396 : }
3397 :
3398 4095 : Word32 fftScale = 0;
3399 4095 : move32();
3400 4095 : SWITCH( hFdCngCom->fftlen )
3401 : {
3402 2608 : case 640:
3403 2608 : fftScale = FFT_SCALING_640;
3404 2608 : move32();
3405 2608 : break;
3406 1487 : case 512:
3407 1487 : fftScale = FFT_SCALING_512;
3408 1487 : move32();
3409 1487 : break;
3410 0 : default:
3411 0 : assert( !"Not supported FFT length!" );
3412 : }
3413 :
3414 : /* Get time-domain signal */
3415 4095 : v_multc_fixed( olapBuffer + shr( hFdCngCom->frameSize, 2 ), fftScale, timeDomainOutput, samples_out ); // Q_in - 9
3416 :
3417 : /* Get excitation */
3418 4095 : v_multc_fixed( olapBuffer + sub( shr( hFdCngCom->frameSize, 2 ), ( M + 1 ) ), fftScale, buf, add( M + 1, hFdCngCom->frameSize ) );
3419 4095 : tmp = buf[0];
3420 4095 : move32();
3421 4095 : preemph_ivas_fx( buf + 1, PREEMPH_FAC, M + hFdCngCom->frameSize, &tmp );
3422 : // residu_ivas_fx( hFdCngCom->A_cng, Q13, M, buf + 1 + M, hFdCngCom->exc_cng_32fx, hFdCngCom->frameSize );
3423 4095 : residu_ivas_fx( hFdCngCom->A_cng, sub( 15, norm_s( hFdCngCom->A_cng[0] - 1 ) ), M, buf + 1 + M, hFdCngCom->exc_cng_32fx, hFdCngCom->frameSize );
3424 :
3425 : /* update and window olapBuf if we have a output frame that is shorter than the default frame size...*/
3426 4095 : IF( LT_16( samples_out, hFdCngCom->frameSize ) )
3427 : {
3428 0 : Copy32( olapBuffer + samples_out, olapBuffer + hFdCngCom->frameSize, i_mult( 3, shr( hFdCngCom->frameSize, 2 ) ) );
3429 : }
3430 611711 : FOR( i = ( 5 * ( hFdCngCom->frameSize >> 2 ) ); i < ( 7 * ( hFdCngCom->frameSize >> 2 ) ); i++ )
3431 : {
3432 607616 : olapBuffer[i] = Mpy_32_16_1( olapBuffer[i], olapWin[( i - ( 3 * ( hFdCngCom->frameSize >> 2 ) ) )] );
3433 607616 : move32();
3434 : }
3435 :
3436 4095 : return;
3437 : }
3438 :
3439 46742858 : Word32 rand_gauss_fx(
3440 : Word32 *x,
3441 : Word16 *seed,
3442 : Word16 q )
3443 : {
3444 : Word32 temp;
3445 :
3446 46742858 : temp = own_random( seed );
3447 46742858 : temp = L_add( temp, own_random( seed ) );
3448 46742858 : temp = L_add( temp, own_random( seed ) );
3449 46742858 : temp = L_shr( temp, sub( 15, q ) );
3450 :
3451 46742858 : *x = temp;
3452 46742858 : move32();
3453 :
3454 46742858 : return temp;
3455 : }
3456 :
3457 : /*-------------------------------------------------------------------
3458 : * rand_gauss_fix()
3459 : *
3460 : * Random generator with Gaussian distribution with mean 0 and std 1
3461 : *-------------------------------------------------------------------*/
3462 :
3463 50111712 : Word16 rand_gauss_fix(
3464 : Word16 *x,
3465 : Word16 *seed )
3466 : {
3467 : Word32 temp;
3468 :
3469 50111712 : temp = shr( own_random( seed ), Q2 );
3470 50111712 : temp = L_add( temp, shr( own_random( seed ), Q2 ) );
3471 50111712 : temp = L_add( temp, shr( own_random( seed ), Q2 ) );
3472 :
3473 50111712 : *x = (Word16) temp;
3474 50111712 : move32();
3475 :
3476 50111712 : return (Word16) temp;
3477 : }
|