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