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