Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : #include <stdint.h>
34 : #include "options.h"
35 : #include <math.h>
36 : #include "cnst.h"
37 : #include "prot_fx.h"
38 : #include "ivas_cnst.h"
39 : #include "ivas_rom_com.h"
40 : #include "wmc_auto.h"
41 : #include "ivas_prot_fx.h"
42 : #include "ivas_rom_com_fx.h"
43 :
44 : /*-------------------------------------------------------------------
45 : * Local constants
46 : *-------------------------------------------------------------------*/
47 :
48 : #define A_GFILT_FX ( Word16 )( 0x6666 ) /* LP-filter coefficient for coherence and sidegain */
49 : #define ONE_MINUS_A_GFILT_FX ( Word16 )( 0x199A ) /* LP-filter coefficient for coherence and sidegain */
50 : #define SKIP_XFADE_FRAMES 2
51 :
52 : /* DTX/CNG */
53 : #define MAX_K 50
54 : #define ONE_BY_MAX_K ( Word16 )( 0x028F )
55 : #define STEREO_TD_PS_CORR_FILT_FX 1717986918
56 : #define STEREO_TD_PS_CORR_FILT_Q31 1717986944
57 : #define ONE_MINUS_STEREO_TD_PS_CORR_FILT_Q31 429496704
58 : #define MAX_XFADE_FX 50
59 : #define CM_INIT 50
60 : #define CORR_INIT 8
61 : #define SID_INIT 6
62 : #define STEREO_CNA_LR_CORR_LT_FILT_FX 2040109440 /* long-term averaging factor for L/R correlation estimation in stereo CNA */
63 : #define STEREO_CNA_ILD_LT_FILT_FX 1932735283 /* long-term averaging factor for ILD estimation in stereo CNA */
64 :
65 : /*-------------------------------------------------------------------
66 : * stereo_dft_dec_sid_coh()
67 : *
68 : * Decode coherence vector
69 : *-------------------------------------------------------------------*/
70 :
71 : /*-------------------------------------------------------------------
72 : * stereo_dft_generate_comfort_noise_fx()
73 : *
74 : * Generate the comfort noise based on the target noise level for the CLDFB part
75 : *-------------------------------------------------------------------*/
76 :
77 10940 : static void stereo_dft_generate_comfort_noise_fx(
78 : STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: DFT Stereo decoder handle */
79 : STEREO_CNG_DEC_HANDLE hStereoCng, /* i/o: Stereo CNG data structure */
80 : const Word16 last_element_mode, /* i : last element mode Q0*/
81 : Decoder_State *st, /* i/o: Core coder decoder state */
82 : Word32 DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i/o: DFT buffers q_dft*/
83 : Decoder_State *st1, /* i/o: Core coder decoder state secondary channel */
84 : const Word16 targetGain, /* i : ICA target gain Q13*/
85 : const Word16 chan, /* i : channel number Q0*/
86 : const Word16 output_frame, /* i : output frame size Q0*/
87 : Word16 q_dft /* i : Q of DFT */
88 : )
89 : {
90 : Word16 i, j, k;
91 : Word32 *ptr_level, *ptr_shb, *ptr_r, *ptr_i;
92 : HANDLE_FD_CNG_COM hFdCngCom;
93 : Word16 numSlots;
94 : Word16 scale, inv_scale, tmp_16;
95 : Word32 lp_noise;
96 : Word16 lp_noise_e;
97 : Word32 tmp, enr;
98 : Word16 q_enr;
99 : Word32 shb_shape[L_FRAME16k];
100 : Word16 q_shb_shape;
101 : Word32 *ptr0, *ptr1, *ptr2;
102 : Word16 dmpf[M + 2], Atmp[M + 2];
103 : Word32 cngNoiseLevel_upd[L_FRAME16k], cngNoiseLevel_hist[L_FRAME16k - 2];
104 : Word16 e_norm_temp[L_FRAME16k];
105 : Word32 *ptr_tmp, *ptr_cng;
106 : Word64 E0, E1;
107 : Word16 E0_e, E1_e;
108 : Word16 b, q_cngNoiseLevel_upd, q_cngNoiseLevel;
109 : Word32 *pSideGain;
110 : Word16 gamma;
111 : Word16 c, c_e;
112 : Word16 scaleMS;
113 : Word16 scaleAvg, scaleAvg_e;
114 : Word16 LR_ratio; /* Q15 */
115 : Word32 factor;
116 : Word16 alpha;
117 : Word32 ftmp;
118 : Word16 trigo_dec[STEREO_DFT32MS_N_16k / 2 + 1];
119 : const Word16 *pTrigo;
120 : Word16 trigo_step;
121 : Word32 tmp32_1, tmp32_2;
122 : Word16 q_div, q_sqrt1, q_sqrt2, q_sqrt, sqrt_res;
123 : Word16 q_shift, q_shift_1, q_shift_2, min_q;
124 :
125 10940 : hFdCngCom = st->hFdCngDec->hFdCngCom;
126 :
127 10940 : push_wmops( "DFT_CNG" );
128 :
129 10940 : set16_fx( dmpf, 0, M + 2 );
130 10940 : set16_fx( Atmp, 0, M + 2 );
131 :
132 10940 : set_zero_fx( DFT[chan], STEREO_DFT_BUF_MAX );
133 10940 : set32_fx( cngNoiseLevel_upd, 0, L_FRAME16k );
134 :
135 10940 : enr = 0; /* Eliminates compiler warning. They are always set before they are used */
136 10940 : move32();
137 10940 : q_enr = 0;
138 10940 : move16();
139 10940 : E0 = 0;
140 10940 : move64();
141 10940 : E0_e = 0;
142 10940 : move16();
143 10940 : E1 = 0;
144 10940 : move64();
145 10940 : E1_e = 0;
146 10940 : move16();
147 10940 : lp_noise = 0;
148 10940 : move32();
149 10940 : lp_noise_e = 0;
150 10940 : move16();
151 10940 : q_shb_shape = 0;
152 10940 : move16();
153 :
154 10940 : IF( chan == 0 )
155 : {
156 5470 : pSideGain = hStereoDft->side_gain_fx + STEREO_DFT_NBDIV * STEREO_DFT_BAND_MAX; /* Q31 */
157 37322 : FOR( b = 0; b < hStereoDft->nbands; b++ )
158 : {
159 31852 : IF( hStereoCng->xfade_frame_counter == 0 )
160 : {
161 646 : hStereoDft->g_state_fx[b] = extract_h( *pSideGain++ ); /* Q15 */
162 646 : move16();
163 : }
164 : ELSE
165 : {
166 31206 : hStereoDft->g_state_fx[b] = add( mult( ONE_MINUS_A_GFILT_FX, extract_h( *pSideGain++ ) ), mult( A_GFILT_FX, hStereoDft->g_state_fx[b] ) ); /* Q15 */
167 31206 : move16();
168 : }
169 :
170 31852 : test();
171 31852 : IF( hStereoCng->first_SID )
172 : {
173 86 : IF( hStereoCng->first_SID_after_TD )
174 : {
175 0 : hStereoCng->cm_fx[b] = extract_h( Mpy_32_32( hStereoCng->c_LR_LT_fx, hStereoCng->c_LR_LT_fx ) ); /* Q15 */
176 0 : move16();
177 : }
178 : ELSE
179 : {
180 86 : hStereoCng->cm_fx[b] = hStereoCng->coh_fx[b]; /* Q15 */
181 86 : move16();
182 : }
183 : }
184 31766 : ELSE IF( LT_16( hStereoCng->nr_dft_frames, CM_INIT ) && LT_16( hStereoCng->nr_sid_frames, SID_INIT ) )
185 : {
186 0 : IF( GT_16( hStereoCng->nr_corr_frames, CORR_INIT ) )
187 : {
188 0 : hStereoCng->cm_fx[b] = extract_h( Mpy_32_32( hStereoCng->c_LR_LT_fx, hStereoCng->c_LR_LT_fx ) ); /* Q15 */
189 0 : move16();
190 : }
191 : ELSE
192 : {
193 0 : hStereoCng->cm_fx[b] = add( mult( ONE_MINUS_A_GFILT_FX, hStereoCng->coh_fx[b] ), mult( A_GFILT_FX, hStereoCng->cm_fx[b] ) ); /* Q15 */
194 0 : move16();
195 : }
196 : }
197 : ELSE
198 : {
199 31766 : hStereoCng->cm_fx[b] = add( mult( ONE_MINUS_A_GFILT_FX, hStereoCng->coh_fx[b] ), mult( A_GFILT_FX, hStereoCng->cm_fx[b] ) ); /* Q15 */
200 31766 : move16();
201 : }
202 : }
203 :
204 5470 : IF( hStereoCng->first_SID_after_TD )
205 : {
206 14 : scaleAvg = 0;
207 14 : move16();
208 14 : scaleAvg_e = 15;
209 14 : move16();
210 93 : FOR( b = 0; b < hStereoDft->nbands; b++ )
211 : {
212 79 : IF( LT_16( hStereoCng->cm_fx[b], 0x7333 ) )
213 : {
214 79 : gamma = hStereoCng->cm_fx[b]; /* Q15 */
215 79 : move16();
216 79 : gamma = BASOP_Util_Divide1616_Scale( gamma, sub( 32767, gamma ), &q_div ); /* e(q_div) */
217 79 : q_sqrt2 = add( q_div, 16 );
218 79 : tmp32_1 = BASOP_Util_Add_Mant32Exp( gamma, add( q_div, 16 ), sub( 32767, mult_r( hStereoDft->g_state_fx[b], hStereoDft->g_state_fx[b] ) ), 16, &q_sqrt1 ); /* e(q_sqrt1) */
219 79 : tmp32_1 = Sqrt32( tmp32_1, &q_sqrt1 ); /* e(q_sqrt1) */
220 79 : tmp32_2 = Sqrt32( gamma, &q_sqrt2 ); /* e(q_sqrt2) */
221 79 : tmp32_1 = BASOP_Util_Add_Mant32Exp( tmp32_1, q_sqrt1, L_negate( tmp32_2 ), q_sqrt2, &q_sqrt1 ); /* e(q_sqrt1) */
222 79 : gamma = extract_h( L_shl( tmp32_1, q_sqrt1 ) ); /* Q15 */
223 : }
224 : ELSE
225 : {
226 0 : gamma = 0;
227 0 : move16();
228 : }
229 :
230 79 : LR_ratio = extract_h( tdm_ratio_tabl_fx[hStereoCng->last_tdm_idx] ); /* Q15 */
231 237 : c = BASOP_Util_Divide3232_Scale(
232 79 : L_add( L_mult( add( ONE_IN_Q13, shr( hStereoDft->g_state_fx[b], 2 ) ),
233 79 : add( ONE_IN_Q13, shr( hStereoDft->g_state_fx[b], 2 ) ) ),
234 : L_shr( L_mult( gamma, gamma ), 4 ) ),
235 79 : L_add( L_mult( sub( ONE_IN_Q13, shr( hStereoDft->g_state_fx[b], 2 ) ),
236 79 : sub( ONE_IN_Q13, shr( hStereoDft->g_state_fx[b], 2 ) ) ),
237 : L_shr( L_mult( gamma, gamma ), 4 ) ),
238 : &c_e );
239 79 : q_sqrt = c_e;
240 79 : move16();
241 79 : sqrt_res = Sqrt16( mult( c, hStereoCng->cm_fx[b] ), &q_sqrt );
242 79 : tmp32_1 = L_add( L_add( L_shl( 1, sub( Q15, c_e ) ), c ), L_shl( L_deposit_l( sqrt_res ), sub( add( q_sqrt, 1 ), c_e ) ) ); /* Q(15 - c_e) */ /* +1 to account for multiplication with 2 */
243 79 : move16();
244 : // scaleMS = (1 + c + 2 * sqrtf(c * hStereoCng->cm[b])) / (4 * (c * LR_ratio * LR_ratio + (1 - LR_ratio) * (1 - LR_ratio) * targetGain * targetGain + 2 * LR_ratio * (1 - LR_ratio) * targetGain * sqrtf(c * hStereoCng->cm[b])));
245 79 : sqrt_res = Sqrt16( mult( c, hStereoCng->cm_fx[b] ), &q_sqrt );
246 79 : tmp32_2 = L_deposit_l( mult( c, mult( LR_ratio, LR_ratio ) ) ); /* Q(15 - c_e) */
247 : /* (1 - LR_ratio) * (1 - LR_ratio) * targetGain * targetGain */
248 79 : tmp32_2 = L_add( tmp32_2, L_shl( mult( mult( sub( MAX_16, LR_ratio ), sub( MAX_16, LR_ratio ) ), mult( targetGain, targetGain ) ), sub( Q4, c_e ) ) ); /* Q(15 - c_e) */
249 : /* 2 * LR_ratio * (1 - LR_ratio) * targetGain * sqrtf(c * hStereoCng->cm[b]) */
250 79 : tmp32_2 = L_add( tmp32_2, L_shl( L_deposit_l( mult( mult( LR_ratio, sub( MAX_16, LR_ratio ) ), mult( targetGain, sqrt_res ) ) ), sub( add( q_sqrt, 3 ), c_e ) ) ); /* Q(15 - c_e) */ /* +1 to account for multiplication with 2 */
251 79 : tmp32_2 = L_shl( tmp32_2, 2 );
252 79 : scaleMS = BASOP_Util_Divide3232_Scale( tmp32_1, tmp32_2, &c_e );
253 79 : q_sqrt = c_e;
254 79 : move16();
255 79 : scaleMS = Sqrt16( scaleMS, &q_sqrt );
256 79 : scaleAvg_e = BASOP_Util_Add_MantExp( scaleAvg, scaleAvg_e, scaleMS, q_sqrt, &scaleAvg );
257 : }
258 14 : scaleAvg = BASOP_Util_Divide1616_Scale( scaleAvg, hStereoDft->nbands, &c_e );
259 14 : c_e = sub( add( c_e, scaleAvg_e ), 15 );
260 14 : hStereoDft->scale_fx = shl_sat( scaleAvg, c_e );
261 14 : move16();
262 : }
263 : }
264 :
265 10940 : IF( st->cng_type == LP_CNG )
266 : {
267 2474 : set32_fx( cngNoiseLevel_upd, 0, st->L_frame );
268 :
269 : /* Deemphasis */
270 2474 : dmpf[0] = MAX_16;
271 2474 : move16();
272 2474 : dmpf[1] = negate( st->preemph_fac );
273 2474 : move16();
274 2474 : Copy( st->Aq_cng, Atmp, M + 1 );
275 2474 : conv_fx_32( Atmp, dmpf, cngNoiseLevel_upd, M + 2 );
276 :
277 2474 : IF( EQ_16( st->L_frame, L_FRAME ) )
278 : {
279 710 : pTrigo = hStereoDft->dft_trigo_12k8_fx; /* Q15 */
280 710 : trigo_step = STEREO_DFT_TRIGO_SRATE_12k8_STEP * STEREO_DFT_TRIGO_DEC_STEP;
281 710 : move16();
282 : }
283 : ELSE
284 : {
285 1764 : pTrigo = hStereoDft->dft_trigo_16k_fx; /* Q15 */
286 1764 : trigo_step = STEREO_DFT_TRIGO_SRATE_16k_STEP * STEREO_DFT_TRIGO_DEC_STEP;
287 1764 : move16();
288 : }
289 :
290 189034 : FOR( i = 0; i < st->L_frame / 4; i++ )
291 : {
292 186560 : trigo_dec[i] = pTrigo[i * trigo_step]; /* Q15 */
293 186560 : move16();
294 186560 : trigo_dec[st->L_frame / 2 - i] = pTrigo[i * trigo_step]; /* Q15 */
295 186560 : move16();
296 : }
297 2474 : trigo_dec[st->L_frame / 4] = pTrigo[st->L_frame / 4 * trigo_step]; /* Q15 */
298 2474 : move16();
299 :
300 2474 : Word16 rshift_cng = sub( find_guarded_bits_fx( st->L_frame ), getScaleFactor32( cngNoiseLevel_upd, st->L_frame ) );
301 2474 : v_shr_32( cngNoiseLevel_upd, cngNoiseLevel_upd, st->L_frame, rshift_cng );
302 2474 : q_cngNoiseLevel_upd = sub( Q30, rshift_cng );
303 :
304 2474 : rfft_fx( cngNoiseLevel_upd, trigo_dec, st->L_frame, -1 );
305 :
306 2474 : Word16 shift = sub( getScaleFactor32( cngNoiseLevel_upd, st->L_frame ), 1 );
307 2474 : scale_sig32( cngNoiseLevel_upd, st->L_frame, shift );
308 2474 : q_cngNoiseLevel_upd = add( q_cngNoiseLevel_upd, shift );
309 2474 : set16_fx( e_norm_temp, q_cngNoiseLevel_upd, st->L_frame );
310 :
311 : /* Compute 1/|A| */
312 2474 : ptr0 = cngNoiseLevel_upd;
313 2474 : ptr1 = ptr0 + 2;
314 2474 : ptr2 = ptr1 + 1;
315 2474 : assert( st->lp_ener_fx > 0 );
316 :
317 : // lp_ener_fx will be in Q6 at this point.
318 : // So applying appropriate left shift on the denominator.
319 2474 : factor = L_shr( BASOP_Util_Divide3232_Scale_newton( st->lp_ener_fx, L_shl( st->L_frame, Q6 ), &q_div ), 1 ); /* fixed factor in the loop below */ /* q_div */
320 2474 : factor = Sqrt32( factor, &q_div );
321 2474 : q_div = add( q_div, 1 );
322 :
323 : Word16 q_tmp;
324 373120 : FOR( i = 0; i < st->L_frame / 2 - 1; i++ )
325 : {
326 370646 : ftmp = Madd_32_32( Mpy_32_32( *ptr1, *ptr1 ), *ptr2, *ptr2 ); /* q_cngNoiseLevel_upd */
327 370646 : assert( ftmp > 0 );
328 370646 : q_sqrt = sub( 62, shl( q_cngNoiseLevel_upd, 1 ) );
329 370646 : IF( ftmp == 0 )
330 : {
331 0 : ftmp = EPSILLON_FX;
332 0 : move32();
333 0 : q_sqrt = s_max( 0, q_sqrt );
334 : }
335 370646 : tmp = ISqrt32( ftmp, &q_sqrt );
336 370646 : e_norm_temp[i] = sub( 31, add( q_sqrt, q_div ) );
337 370646 : move16();
338 370646 : *ptr0++ = Mpy_32_32( factor, tmp ); /* 2 * q_div + q_sqrt - 31 */
339 370646 : move32();
340 370646 : ptr1 += 2;
341 370646 : ptr2 += 2;
342 : }
343 :
344 373120 : FOR( i = 0; i < st->L_frame / 2 - 1; i++ )
345 : {
346 370646 : q_cngNoiseLevel_upd = s_min( q_cngNoiseLevel_upd, add( e_norm_temp[i], norm_l( cngNoiseLevel_upd[i] ) ) );
347 : }
348 748714 : FOR( i = 0; i < st->L_frame; i++ )
349 : {
350 746240 : cngNoiseLevel_upd[i] = L_shl( cngNoiseLevel_upd[i], sub( q_cngNoiseLevel_upd, e_norm_temp[i] ) );
351 746240 : move32();
352 : }
353 :
354 2474 : IF( sub( s_min( output_frame, L_FRAME32k ), hFdCngCom->stopFFTbin ) > 0 )
355 : {
356 : /* Transform shb LP spectrum */
357 2120 : set32_fx( shb_shape, 0, L_FRAME16k );
358 2120 : Copy_Scale_sig_16_32_DEPREC( st->hTdCngDec->shb_lpcCNG_fx, shb_shape, LPC_SHB_ORDER + 1, Q15 ); // Q30
359 :
360 2120 : IF( NE_16( st->L_frame, L_FRAME16k ) )
361 : {
362 710 : pTrigo = hStereoDft->dft_trigo_16k_fx; /* Q15 */
363 710 : trigo_step = STEREO_DFT_TRIGO_SRATE_16k_STEP * STEREO_DFT_TRIGO_DEC_STEP;
364 710 : move16();
365 :
366 57510 : FOR( i = 0; i < L_FRAME16k / 4; i++ )
367 : {
368 56800 : trigo_dec[i] = pTrigo[i * trigo_step]; /* Q15 */
369 56800 : move16();
370 56800 : trigo_dec[L_FRAME16k / 2 - i] = pTrigo[i * trigo_step]; /* Q15 */
371 56800 : move16();
372 : }
373 710 : trigo_dec[L_FRAME16k / 4] = pTrigo[L_FRAME16k / 4 * trigo_step]; /* Q15 */
374 710 : move16();
375 : }
376 :
377 2120 : Word16 rshift_shb = sub( find_guarded_bits_fx( L_FRAME16k ), getScaleFactor32( shb_shape, L_FRAME16k ) );
378 2120 : v_shr_32( shb_shape, shb_shape, L_FRAME16k, rshift_shb );
379 2120 : q_shb_shape = sub( Q30, rshift_shb );
380 :
381 2120 : rfft_fx( shb_shape, trigo_dec, L_FRAME16k, -1 );
382 :
383 2120 : shift = sub( getScaleFactor32( shb_shape, L_FRAME16k ), 1 );
384 2120 : scale_sig32( shb_shape, L_FRAME16k, shift ); /* q_shb_shape + shift */
385 2120 : q_shb_shape = add( q_shb_shape, shift );
386 :
387 : /* Compute 1/|A| */
388 2120 : enr = Madd_32_32( Mpy_32_32( shb_shape[0], shb_shape[0] ), shb_shape[1], shb_shape[1] ); /* 62 - 2*q_shb_shape */
389 2120 : q_enr = sub( 62, shl( q_shb_shape, 1 ) );
390 2120 : ptr0 = shb_shape;
391 2120 : ptr1 = ptr0 + 2;
392 2120 : ptr2 = ptr1 + 1;
393 2120 : set16_fx( e_norm_temp, q_shb_shape, L_FRAME16k );
394 :
395 339200 : FOR( i = 0; i < L_FRAME16k / 2 - 1; i++ )
396 : {
397 337080 : ftmp = Madd_32_32( Mpy_32_32( *ptr1, *ptr1 ), *ptr2, *ptr2 ); /* 2*q_shape - 31 */
398 337080 : q_tmp = sub( shl( q_shb_shape, 1 ), 31 );
399 337080 : assert( ftmp > 0 );
400 337080 : q_div = 0;
401 337080 : move16();
402 337080 : ftmp = BASOP_Util_Divide3232_Scale_newton( L_shl( 1, q_tmp ), ftmp, &q_div ); /* q_div */
403 : /* in float:
404 : both a = "div"=(1/(x^2+y^2) and sqrt(a) is used and summed up in the same loop.
405 :
406 : in BASOP:
407 : sum up using inv_sqrt( *ptr1 * *ptr1 + *ptr2 * *ptr2 ), in this loop
408 : and then sum up enr = sum( *ptr0 * *ptr0 ), in a subsequent MAC loop */
409 337080 : enr = BASOP_Util_Add_Mant32Exp( enr, q_enr, ftmp, q_div, &q_enr ); /* q_enr */
410 337080 : tmp32_1 = Sqrt32( ftmp, &q_div ); /* q_div */
411 337080 : *ptr0++ = tmp32_1;
412 337080 : move32();
413 337080 : e_norm_temp[i] = sub( 31, q_div );
414 337080 : move16();
415 337080 : ptr1 += 2;
416 337080 : ptr2 += 2;
417 : }
418 2120 : q_shb_shape = MAX_16;
419 2120 : move16();
420 :
421 680520 : FOR( i = 0; i < L_FRAME16k; i++ )
422 : {
423 678400 : q_shb_shape = s_min( q_shb_shape, add( e_norm_temp[i], norm_l( shb_shape[i] ) ) );
424 : }
425 680520 : FOR( i = 0; i < L_FRAME16k; i++ )
426 : {
427 678400 : shb_shape[i] = L_shl( shb_shape[i], sub( q_shb_shape, e_norm_temp[i] ) ); /* q_shb_shape */
428 678400 : move32();
429 : }
430 : }
431 :
432 : /* Update CNG noise level from MS noise estimation */
433 2474 : Copy32( st->hFdCngDec->bandNoiseShape, cngNoiseLevel_hist, sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand ) ); /* exp(bandNoiseShape_exp)*/
434 2474 : ptr_cng = cngNoiseLevel_hist;
435 373120 : FOR( i = 0; i < ( st->last_L_frame - hFdCngCom->startBand ) / 2; i++ )
436 : {
437 370646 : tmp = L_shr( *( cngNoiseLevel_hist + shl( i, 1 ) ), 1 );
438 370646 : move32();
439 370646 : tmp = L_add( tmp, L_shr( *( cngNoiseLevel_hist + add( shl( i, 1 ), 1 ) ), 1 ) ); /* exp(bandNoiseShape_exp)*/
440 370646 : *ptr_cng++ = tmp;
441 370646 : move32();
442 : }
443 :
444 2474 : test();
445 2474 : test();
446 2474 : test();
447 2474 : IF( EQ_16( last_element_mode, IVAS_CPE_TD ) && ( chan == 0 ) && ( hStereoCng->xfade_frame_counter == 0 ) && GE_16( hFdCngCom->msFrCnt_init_counter, hFdCngCom->msFrCnt_init_thresh ) )
448 : {
449 7 : ptr_cng = cngNoiseLevel_hist + hFdCngCom->startBand;
450 7 : ptr_tmp = cngNoiseLevel_upd + hFdCngCom->startBand;
451 : Word32 temppp;
452 7 : Word16 shift_g = shr( find_guarded_bits_fx( shr( sub( st->last_L_frame, hFdCngCom->startBand ), 1 ) ), 1 );
453 1120 : FOR( i = 0; i < ( st->last_L_frame - hFdCngCom->startBand ) / 2; i++ )
454 : {
455 1113 : E0 = W_add( E0, *ptr_cng++ ); /* exp(bandNoiseShape_exp - E0_e) */
456 1113 : temppp = L_shr( ( *ptr_tmp ), shift_g );
457 1113 : E1 = W_mac_32_32( E1, temppp, temppp ); /* 2*(q_cngNoiseLevel_upd - shift_g) + 1*/
458 1113 : ptr_tmp++;
459 : }
460 7 : E0_e = W_norm( E0 );
461 7 : E0 = W_shl( E0, E0_e );
462 7 : E0_e = add( sub( st->hFdCngDec->bandNoiseShape_exp, E0_e ), 32 );
463 7 : E1_e = W_norm( E1 );
464 7 : E1 = W_shl( E1, E1_e );
465 7 : E1_e = sub( 63, add( E1_e, add( shl( sub( q_cngNoiseLevel_upd, shift_g ), 1 ), 1 ) ) );
466 :
467 7 : IF( BASOP_Util_Cmp_Mant32Exp( W_extract_h( E0 ), E0_e, W_extract_h( E1 ), E1_e ) < 0 )
468 : {
469 7 : tmp_16 = BASOP_Util_Divide3232_Scale( W_extract_h( E0 ), W_extract_h( E1 ), &q_div ); /* q_div + E0_e - E1_e */
470 7 : q_div = add( q_div, sub( E0_e, E1_e ) );
471 7 : tmp_16 = Sqrt16( tmp_16, &q_div );
472 7 : tmp_16 = shl( tmp_16, q_div );
473 7 : hStereoCng->xfade_length = sub( MAX_XFADE_FX, extract_l( L_shr( imult3216( MAX_XFADE_FX, tmp_16 ), Q15 ) ) ); /* Q0 */
474 7 : move16();
475 : }
476 : ELSE
477 : {
478 0 : tmp_16 = BASOP_Util_Divide3232_Scale( W_extract_h( E1 ), W_extract_h( E0 ), &q_div ); /* q_div + E0_e - E1_e */
479 0 : q_div = add( q_div, sub( E1_e, E0_e ) );
480 0 : tmp_16 = Sqrt16( tmp_16, &q_div );
481 0 : tmp_16 = shl( tmp_16, q_div );
482 0 : hStereoCng->xfade_length = sub( MAX_XFADE_FX, extract_l( L_shr( imult3216( MAX_XFADE_FX, tmp_16 ), Q15 ) ) ); /* Q0 */
483 0 : move16();
484 : }
485 : }
486 :
487 2474 : IF( LT_16( hStereoCng->xfade_frame_counter, hStereoCng->xfade_length ) )
488 : {
489 74 : ptr_cng = cngNoiseLevel_hist + hFdCngCom->startBand;
490 74 : ptr_tmp = cngNoiseLevel_upd + hFdCngCom->startBand;
491 11840 : FOR( i = 0; i < ( st->last_L_frame - hFdCngCom->startBand ) / 2; i++ )
492 : {
493 11766 : q_sqrt = st->hFdCngDec->bandNoiseShape_exp;
494 11766 : move16();
495 11766 : tmp_16 = BASOP_Util_Divide1616_Scale( hStereoCng->xfade_frame_counter, hStereoCng->xfade_length, &q_div ); /* Q0 */
496 11766 : tmp_16 = shl( tmp_16, q_div );
497 11766 : tmp = Sqrt32( *ptr_cng++, &q_sqrt );
498 11766 : tmp = L_shl( tmp, sub( add( q_cngNoiseLevel_upd, q_sqrt ), 31 ) );
499 11766 : *ptr_tmp = L_add( Mpy_32_16_1( *ptr_tmp, tmp_16 ), Mpy_32_16_1( Mpy_32_16_1( tmp, sub( MAX_16, tmp_16 ) ), hStereoDft->scale_fx ) ); /* q_cngNoiseLevel_upd + q_div */
500 11766 : move32();
501 11766 : ptr_tmp++;
502 : }
503 : }
504 :
505 7422 : FOR( k = 0; k < STEREO_DFT_NBDIV; k++ )
506 : {
507 : /* low band */
508 4948 : ptr_level = cngNoiseLevel_upd; // Q(q_cngNoiseLevel_upd)
509 4948 : ptr_r = DFT[chan] + add( hFdCngCom->startBand, i_mult( k, STEREO_DFT32MS_N_MAX ) ); // Q(q_dft)
510 4948 : ptr_i = ptr_r + 1;
511 4948 : scale = shr( output_frame, 1 );
512 :
513 746240 : FOR( i = 0; i < ( hFdCngCom->stopFFTbin - hFdCngCom->startBand ) / 2; i++ )
514 : {
515 : /* Real part in FFT bins */
516 741292 : rand_gauss_fx( ptr_r, &st->hTdCngDec->cng_seed, q_dft );
517 741292 : tmp32_1 = Mpy_32_16_1( *ptr_level, scale ); // Q(q_cngNoiseLevel_upd - 15)
518 741292 : q_shift = norm_l( tmp32_1 );
519 741292 : if ( GT_16( q_shift, sub( 46, q_cngNoiseLevel_upd ) ) )
520 : {
521 352 : q_shift = sub( 46, q_cngNoiseLevel_upd );
522 : }
523 741292 : tmp32_1 = L_shl( tmp32_1, q_shift );
524 741292 : q_shift = sub( sub( 46, q_cngNoiseLevel_upd ), q_shift );
525 :
526 741292 : ( *ptr_r ) = L_shl( Mpy_32_32( ( *ptr_r ), tmp32_1 ), q_shift ); /* q_dft */
527 741292 : move32();
528 741292 : ptr_r += 2;
529 :
530 : /* Imaginary part in FFT bins */
531 741292 : rand_gauss_fx( ptr_i, &st->hTdCngDec->cng_seed, q_dft );
532 741292 : ( *ptr_i ) = L_shl( Mpy_32_32( ( *ptr_i ), tmp32_1 ), q_shift ); /* q_dft */
533 741292 : move32();
534 741292 : ptr_i += 2;
535 741292 : ptr_level++;
536 : }
537 :
538 4948 : IF( sub( s_min( output_frame, L_FRAME32k ), hFdCngCom->stopFFTbin ) > 0 )
539 : {
540 : Word32 scale_32;
541 : Word16 q_res;
542 : /* high band generation, flipped spectrum */
543 4240 : assert( enr != 0 );
544 : // 10 ^ (0.1 * st->hTdCngDec->shb_cng_gain)
545 : // Above expression equivalent to 2 ^ (3.321928094 * 0.1 * st->hTdCngDec->shb_cng_gain)
546 : // 3.321928094 * 0.1 = 0.3321928094
547 : // st->hTdCngDec->shb_cng_gain_fx_32 Q is 11
548 4240 : scale_32 = BASOP_util_Pow2( Mpy_32_16_1( st->hTdCngDec->shb_cng_gain_fx_32, (Word16) 0x2A85 ), Q31 - Q11, &q_res );
549 : // Q of scale_32 is Q31 - q_res, Q of enr is
550 : // scale_32 = L_shl(scale_32, sub( q_enr, sub(Q31, q_res)));
551 4240 : q_div = 0;
552 4240 : move16();
553 4240 : scale = BASOP_Util_Divide3232_Scale( scale_32, enr, &q_div );
554 : // q_res = add(q_div, sub( q_enr, sub(Q31, q_res))); move16();
555 4240 : q_res = add( sub( q_res, q_enr ), q_div );
556 : // q_div = sub(Q15, q_res); move16();
557 4240 : q_div = q_res;
558 4240 : move16();
559 4240 : inv_scale = ISqrt16( scale, &q_res );
560 4240 : scale = Sqrt16( scale, &q_div );
561 4240 : ptr_shb = shb_shape + ( L_FRAME16k / 2 - 1 );
562 : /* Averaging for Nyquist frequency */
563 : Word16 q1, q2;
564 4240 : tmp32_1 = Mpy_32_16_1( cngNoiseLevel_upd[( hFdCngCom->stopFFTbin - hFdCngCom->startBand ) / 2 - 1], inv_scale ); /* q_cngNoiseLevel_upd + 1 - q_res */
565 4240 : tmp32_2 = *( ptr_shb - 1 ); /* q_shb_shape */
566 4240 : move32();
567 4240 : q1 = sub( add( q_cngNoiseLevel_upd, 1 ), q_res );
568 4240 : q2 = q_shb_shape;
569 4240 : move16();
570 4240 : *ptr_shb = BASOP_Util_Add_Mant32Exp( tmp32_1, sub( Q31, q1 ), tmp32_2, sub( Q31, q2 ), &q_tmp );
571 4240 : move32();
572 4240 : q_tmp = sub( q_tmp, 1 );
573 4240 : IF( LT_16( sub( Q31, q_tmp ), q_shb_shape ) )
574 : {
575 216 : scale_sig32( shb_shape, L_FRAME16k, sub( sub( Q31, q_tmp ), q_shb_shape ) ); /* Q31 - q_tmp */
576 216 : q_shb_shape = sub( Q31, q_tmp );
577 : }
578 :
579 4240 : *ptr_shb = L_shl( *ptr_shb, sub( q_shb_shape, sub( Q31, q_tmp ) ) ); /* Q31 - q_tmp */
580 4240 : move32();
581 :
582 : // *ptr_shb = 0.5f * ( cngNoiseLevel_upd[( hFdCngCom->stopFFTbin - hFdCngCom->startBand ) / 2 - 1] / scale + *( ptr_shb - 1 ) );
583 :
584 4240 : ptr_r = DFT[chan] + add( hFdCngCom->stopFFTbin, i_mult( k, STEREO_DFT32MS_N_MAX ) ); /* q_dft */
585 4240 : ptr_i = ptr_r + 1;
586 :
587 4240 : Word16 len = shr( ( sub( s_min( output_frame, i_mult( hFdCngCom->regularStopBand, 16 ) ), hFdCngCom->stopFFTbin ) ), 1 );
588 517360 : FOR( i = 0; i < len; i++ )
589 : {
590 : /* Real part in FFT bins */
591 513120 : rand_gauss_fx( ptr_r, &st->hTdCngDec->cng_seed, q_dft );
592 513120 : tmp32_1 = *ptr_shb;
593 513120 : move32();
594 513120 : q_shift = norm_l( tmp32_1 );
595 513120 : IF( GT_16( q_shift, sub( 31, q_shb_shape ) ) )
596 : {
597 23900 : q_shift = sub( 31, q_shb_shape );
598 : }
599 513120 : tmp32_1 = L_shl( tmp32_1, q_shift );
600 513120 : q_shift = sub( sub( 31, q_shb_shape ), q_shift );
601 :
602 513120 : ( *ptr_r ) = L_shl( Mpy_32_32( ( *ptr_r ), tmp32_1 ), q_shift );
603 513120 : move32();
604 513120 : ptr_r += 2;
605 : /* Imaginary part in FFT bins */
606 513120 : rand_gauss_fx( ptr_i, &st->hTdCngDec->cng_seed, q_dft );
607 513120 : ( *ptr_i ) = L_shl( Mpy_32_32( ( *ptr_i ), tmp32_1 ), q_shift ); /* q_dft + q_shift */
608 513120 : move32();
609 513120 : ptr_i += 2;
610 513120 : ptr_shb--;
611 : }
612 :
613 : /* rescale */
614 4240 : tmp32_1 = L_mult0( scale, shr( output_frame, 1 ) );
615 4240 : q_shift = norm_l( tmp32_1 );
616 4240 : IF( GT_16( q_shift, add( Q16, q_div ) ) )
617 : {
618 400 : q_shift = add( Q16, q_div );
619 : }
620 4240 : tmp32_1 = L_shl( tmp32_1, q_shift );
621 4240 : q_shift = sub( add( Q16, q_div ), q_shift );
622 :
623 4240 : ptr_r = DFT[chan] + add( hFdCngCom->stopFFTbin, i_mult( k, STEREO_DFT32MS_N_MAX ) ); /* q_dft */
624 4240 : ptr_i = ptr_r + 1;
625 4240 : tmp = shr( sub( s_min( output_frame, i_mult( hFdCngCom->regularStopBand, 16 ) ), hFdCngCom->stopFFTbin ), 1 );
626 517360 : FOR( i = 0; i < tmp; i++ )
627 : {
628 513120 : ( *ptr_r ) = L_shl( Mpy_32_32( ( *ptr_r ), tmp32_1 ), q_shift ); /* q_dft + q_shift */
629 513120 : move32();
630 513120 : ( *ptr_i ) = L_shl( Mpy_32_32( ( *ptr_i ), tmp32_1 ), q_shift ); /* q_dft + q_shift */
631 513120 : move32();
632 513120 : ptr_r += 2;
633 513120 : ptr_i += 2;
634 : }
635 : }
636 : }
637 :
638 : /* Expand cngNoiseLevel_flt from 0-159 to 0-318, compute noise level */
639 2474 : lp_noise = 0;
640 2474 : move32();
641 2474 : lp_noise_e = 0;
642 2474 : move16();
643 2474 : ptr_level = hFdCngCom->cngNoiseLevel + sub( hFdCngCom->stopFFTbin, add( hFdCngCom->startBand, 1 ) ); /* q_cngNoiseLevel */
644 2474 : ptr_tmp = cngNoiseLevel_upd + sub( shr( sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand ), 1 ), 1 ); /* q_cngNoiseLevel_upd */
645 :
646 2474 : q_tmp = s_max( hFdCngCom->cngNoiseLevelExp, shl( sub( Q31, q_cngNoiseLevel_upd ), 1 ) );
647 2474 : scale_sig32( hFdCngCom->cngNoiseLevel, FFTCLDFBLEN, sub( hFdCngCom->cngNoiseLevelExp, q_tmp ) ); /* q_tmp */
648 2474 : hFdCngCom->cngNoiseLevelExp = q_tmp;
649 2474 : move16();
650 :
651 373120 : FOR( i = 0; i < ( hFdCngCom->stopFFTbin - hFdCngCom->startBand ) / 2; i++ )
652 : {
653 370646 : *ptr_level-- = L_shl( Mpy_32_32( *ptr_tmp, *ptr_tmp ), sub( shl( sub( Q31, q_cngNoiseLevel_upd ), 1 ), hFdCngCom->cngNoiseLevelExp ) ); /* q_cngNoiseLevel */
654 370646 : move32();
655 370646 : ptr_tmp--;
656 370646 : *ptr_level = *( ptr_level + 1 );
657 370646 : move32();
658 370646 : lp_noise = BASOP_Util_Add_Mant32Exp( lp_noise, lp_noise_e, *ptr_level--, add( hFdCngCom->cngNoiseLevelExp, 1 ), &lp_noise_e );
659 : }
660 : }
661 : ELSE
662 : {
663 : /* FD-CNG */
664 8466 : IF( !LT_16( hFdCngCom->msFrCnt_init_counter, hFdCngCom->msFrCnt_init_thresh ) )
665 : {
666 8466 : test();
667 8466 : test();
668 8466 : IF( LE_16( hStereoCng->xfade_frame_counter, (Word16) MAX_K ) && EQ_16( hStereoCng->last_act_element_mode, IVAS_CPE_TD ) && ( chan == 0 ) )
669 : {
670 : /* Fade MS -> SID/MS */
671 59 : j = 0;
672 59 : move16();
673 1180 : FOR( k = 0; k < ( hFdCngCom->nFFTpart - 2 ); k++ )
674 : {
675 1121 : factor = BASOP_Util_Divide3232_Scale_newton( L_add( hFdCngCom->sidNoiseEstLp[k], DELTA_FX ), L_add( st->hFdCngDec->partNoiseShape[k], DELTA_FX ), &q_div ); /* q_div */
676 1121 : q_div = add( q_div, sub( hFdCngCom->sidNoiseEstExp, st->hFdCngDec->partNoiseShape_exp ) );
677 1121 : IF( q_div < 0 )
678 : {
679 0 : factor = L_shl( factor, q_div ); // Q31
680 0 : q_div = 0;
681 0 : move16();
682 : }
683 1121 : factor = L_min( L_add( L_shl( hStereoDft->scale_fx, sub( 16, q_div ) ), W_extract_l( W_mult0_32_32( Mpy_32_16_1( L_sub( factor, L_shl( hStereoDft->scale_fx, sub( 16, q_div ) ) ), ONE_BY_MAX_K ), hStereoCng->xfade_frame_counter ) ) ), factor ); /* q_div */
684 13570 : FOR( ; j <= hFdCngCom->part[k]; j++ )
685 : {
686 : /* NOTE: saturation is added here as part of issue 1218 fix. After rescaling the fdcng noise estimation buffers, due to slight precision loss, values may slightly overflow */
687 12449 : hFdCngCom->cngNoiseLevel[j] = L_shl_sat( Mpy_32_32( st->hFdCngDec->bandNoiseShape[j], factor ), q_div ); /* exp(st->hFdCngDec->bandNoiseShape_exp) */
688 12449 : move32();
689 : }
690 : }
691 59 : hFdCngCom->cngNoiseLevelExp = st->hFdCngDec->bandNoiseShape_exp;
692 59 : move16();
693 : }
694 : }
695 8466 : scale = shr( output_frame, 1 );
696 8466 : numSlots = shr( hFdCngCom->numSlots, 1 );
697 25398 : FOR( k = 0; k < STEREO_DFT_NBDIV; k++ )
698 : {
699 16932 : ptr_level = hFdCngCom->cngNoiseLevel;
700 16932 : ptr_r = DFT[chan] + add( hFdCngCom->startBand, i_mult( k, STEREO_DFT32MS_N_MAX ) ); /* qDFT */
701 16932 : ptr_i = ptr_r + 1;
702 16932 : q_cngNoiseLevel = sub( Q31, hFdCngCom->cngNoiseLevelExp );
703 2436736 : FOR( i = 0; i < ( hFdCngCom->stopFFTbin - hFdCngCom->startBand ) / 2; i++ )
704 : {
705 : /* Real part in FFT bins */
706 2419804 : tmp = L_shr( *ptr_level++, 1 );
707 2419804 : tmp = L_add( tmp, L_shr( *ptr_level++, 1 ) );
708 2419804 : rand_gauss_fx( ptr_r, &st->hTdCngDec->cng_seed, q_dft );
709 2419804 : q_sqrt = sub( Q31, q_cngNoiseLevel );
710 2419804 : tmp = Sqrt32( tmp, &q_sqrt );
711 2419804 : *( ptr_r ) = imult3216( Mpy_32_32( *( ptr_r ), tmp ), scale ); /* qDFT */
712 2419804 : move32();
713 2419804 : ( *ptr_r ) = L_shl( ( *ptr_r ), q_sqrt ); /* qDFT */
714 2419804 : move32();
715 2419804 : ptr_r += 2;
716 : /* Imaginary part in FFT bins */
717 2419804 : rand_gauss_fx( ptr_i, &st->hTdCngDec->cng_seed, q_dft );
718 2419804 : ( *ptr_i ) = L_shl( imult3216( Mpy_32_32( ( *ptr_i ), tmp ), scale ), q_sqrt ); /* qDFT */
719 2419804 : move32();
720 2419804 : ptr_i += 2;
721 : }
722 16932 : ptr_level = hFdCngCom->cngNoiseLevel + sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand );
723 16932 : ptr_r = DFT[chan] + add( hFdCngCom->stopFFTbin, i_mult( k, STEREO_DFT32MS_N_MAX ) ); /* qDFT */
724 16932 : ptr_i = ptr_r + 1;
725 249380 : FOR( j = hFdCngCom->numCoreBands; j < hFdCngCom->regularStopBand; j++ )
726 : {
727 2092032 : FOR( i = 0; i < numSlots; i++ )
728 : {
729 : /* Real part in FFT bins */
730 1859584 : rand_gauss_fx( ptr_r, &st->hTdCngDec->cng_seed, q_dft );
731 1859584 : q_sqrt = sub( Q31, q_cngNoiseLevel );
732 1859584 : tmp = Sqrt32( *ptr_level, &q_sqrt );
733 1859584 : tmp = Mpy_32_16_1( tmp, scale ); // 15 + q_sqrt
734 1859584 : ( *ptr_r ) = Mpy_32_32( *ptr_r, tmp ); // q_dft + 15 + q_sqrt - 31
735 1859584 : ( *ptr_r ) = L_shl_sat( ( *ptr_r ), add( 15, q_sqrt ) );
736 1859584 : move32();
737 1859584 : ptr_r += 2;
738 : /* Imaginary part in FFT bins */
739 1859584 : rand_gauss_fx( ptr_i, &st->hTdCngDec->cng_seed, q_dft );
740 1859584 : ( *ptr_i ) = Mpy_32_32( *ptr_i, tmp ); // q_dft + 15 + q_sqrt - 31
741 1859584 : ( *ptr_i ) = L_shl_sat( ( *ptr_i ), add( 15, q_sqrt ) );
742 1859584 : move32();
743 1859584 : ptr_i += 2;
744 : }
745 232448 : ptr_level++;
746 : }
747 : }
748 :
749 : /* Compute noise level */
750 8466 : lp_noise = 0;
751 8466 : move32();
752 8466 : lp_noise_e = 0;
753 8466 : move16();
754 8466 : ptr_level = hFdCngCom->cngNoiseLevel;
755 2428270 : FOR( i = 0; i < hFdCngCom->stopFFTbin - hFdCngCom->startBand; i++ )
756 : {
757 : // lp_noise = L_add( lp_noise, *ptr_level++ );
758 2419804 : lp_noise = BASOP_Util_Add_Mant32Exp( lp_noise, lp_noise_e, *ptr_level++, hFdCngCom->cngNoiseLevelExp, &lp_noise_e );
759 : }
760 : }
761 :
762 10940 : test();
763 10940 : IF( EQ_16( hStereoCng->last_act_element_mode, IVAS_CPE_TD ) && ( chan > 0 ) )
764 96 : {
765 96 : Word32 log_lp_noise = L_add( L_shl( lp_noise_e, Q25 ), BASOP_Util_Log2( L_add( lp_noise, DELTA_FX ) ) ); /* Q25 */
766 : // log10(x) is computed as log2(x) * log10(2)
767 : // log_lp_noise at this stage is in Q25. where as the structure value is in Q23
768 : // Hence the 16-bit constant log10(2) will be stored in Q13
769 96 : log_lp_noise = Mpy_32_16_1( log_lp_noise, 2466 /* log10(2) in Q13 */ ); /* Q23 */
770 96 : st1->lp_noise = L_add( Mpy_32_16_1( st1->lp_noise, 29491 /* 0.9f in Q15 */ ), log_lp_noise ); /* Q23 */
771 96 : move32();
772 : }
773 10844 : ELSE IF( ( chan == 0 ) )
774 : {
775 5470 : Word16 q_lp_noise = 0; // st->hFdCngDec->q_lp_noise; // to be populated appropriately.
776 5470 : move16();
777 5470 : Word32 log_lp_noise = L_add( L_shl( lp_noise_e, Q25 ), BASOP_Util_Log2( L_add( lp_noise, DELTA_FX ) ) ); /* Q25 */
778 : // log10(x) is computed as log2(x) * log10(2)
779 : // log_lp_noise at this stage is in Q25. where as the structure value is in Q23
780 : // Hence the 16-bit constant log10(2) will be stored in Q13
781 5470 : log_lp_noise = Mpy_32_16_1( log_lp_noise, 2466 /* log10(2) in Q13 */ ); /* Q23 */
782 5470 : st->hFdCngDec->lp_noise = L_add( Mpy_32_16_1( st->hFdCngDec->lp_noise, 29491 /* 0.9f in Q15 */ ), log_lp_noise ); /* Q23 */
783 5470 : move32();
784 5470 : st->lp_noise = st->hFdCngDec->lp_noise; /* Q23 */
785 5470 : move32();
786 5470 : st->hFdCngDec->hFdCngCom->flag_noisy_speech = extract_l( LT_32( L_shr( L_sub( st->hFdCngDec->lp_speech, st->hFdCngDec->lp_noise ), q_lp_noise ), 28 ) ); /* Q0 */
787 5470 : move16();
788 5470 : st->hFdCngDec->hFdCngCom->likelihood_noisy_speech = add( mult_r( 32440 /* 0.99 in Q15 */, st->hFdCngDec->hFdCngCom->likelihood_noisy_speech ),
789 5470 : mult_r( 328 /* 0.01 in Q15 */, st->hFdCngDec->hFdCngCom->flag_noisy_speech ) ); /* Q15 */
790 5470 : move16();
791 : }
792 :
793 10940 : test();
794 10940 : IF( ( chan == 0 ) && LE_32( st->core_brate, SID_2k40 ) )
795 : {
796 : /* update smoothed periodogram used by stereo CNA in SID and NO_DATA frames from cngNoiseLevel_flt */
797 5470 : q_shift_1 = L_norm_arr( st->hFdCngDec->smoothed_psd_fx, L_FRAME16k );
798 5470 : q_shift_2 = L_norm_arr( hFdCngCom->cngNoiseLevel, FFTCLDFBLEN );
799 :
800 5470 : min_q = sub( s_min( add( q_shift_1, sub( Q31, st->hFdCngDec->smoothed_psd_exp ) ), add( q_shift_2, sub( Q31, hFdCngCom->cngNoiseLevelExp ) ) ), 1 /* Guard bit */ );
801 :
802 5470 : scale_sig32( st->hFdCngDec->smoothed_psd_fx, L_FRAME16k, sub( min_q, sub( Q31, st->hFdCngDec->smoothed_psd_exp ) ) ); /* Q31 - st->hFdCngDec->smoothed_psd_exp */
803 5470 : st->hFdCngDec->smoothed_psd_exp = sub( Q31, min_q );
804 5470 : move16();
805 5470 : scale_sig32( hFdCngCom->cngNoiseLevel, FFTCLDFBLEN, sub( min_q, sub( Q31, hFdCngCom->cngNoiseLevelExp ) ) ); /* Q31 - hFdCngCom->cngNoiseLevelExp */
806 5470 : hFdCngCom->cngNoiseLevelExp = st->hFdCngDec->smoothed_psd_exp;
807 5470 : move16();
808 :
809 1586018 : FOR( i = hFdCngCom->startBand; i < hFdCngCom->stopFFTbin; i++ )
810 : {
811 1580548 : ftmp = hFdCngCom->cngNoiseLevel[i - hFdCngCom->startBand];
812 1580548 : move32();
813 1580548 : IF( !st->hFdCngDec->first_cna_noise_updated )
814 : {
815 : /* very first update */
816 2606 : alpha = 0;
817 2606 : move16();
818 : }
819 : ELSE
820 : {
821 1577942 : alpha = (Word16) ( 0x799A );
822 1577942 : move16();
823 1577942 : test();
824 1577942 : IF( ( st->hFdCngDec->smoothed_psd_fx[i] > 0 ) && GT_32( Mpy_32_16_1( ftmp, (Word16) 0x3333 ), st->hFdCngDec->smoothed_psd_fx[i] ) )
825 : {
826 : /* prevent abrupt upward update steps */
827 105819 : ftmp = L_add( L_shl( st->hFdCngDec->smoothed_psd_fx[i], 1 ), L_shr( st->hFdCngDec->smoothed_psd_fx[i], 1 ) ); /* st->hFdCngDec->smoothed_psd_exp */
828 105819 : move16();
829 : }
830 1472123 : ELSE IF( LT_32( ftmp, st->hFdCngDec->smoothed_psd_fx[i] ) )
831 : {
832 : /* faster downward updates */
833 323320 : alpha = (Word16) ( 0x599A );
834 323320 : move16();
835 : }
836 : }
837 :
838 : /* smoothing */
839 1580548 : st->hFdCngDec->smoothed_psd_fx[i] = L_add( Mpy_32_16_1( st->hFdCngDec->smoothed_psd_fx[i], alpha ), Mpy_32_16_1( ftmp, sub( MAX_16, alpha ) ) ); /* st->hFdCngDec->smoothed_psd_exp */
840 1580548 : move32();
841 : }
842 :
843 : /* update msNoiseEst in SID and NO_DATA frames */
844 5470 : bandcombinepow( &st->hFdCngDec->smoothed_psd_fx[hFdCngCom->startBand], st->hFdCngDec->smoothed_psd_exp, sub( hFdCngCom->stopFFTbin, hFdCngCom->startBand ), st->hFdCngDec->part_shaping, st->hFdCngDec->nFFTpart_shaping, st->hFdCngDec->psize_inv_shaping, st->hFdCngDec->msNoiseEst, &st->hFdCngDec->msNoiseEst_exp );
845 :
846 : Word32 max_l;
847 5470 : maximum_32_fx( st->hFdCngDec->msNoiseEst, NPART_SHAPING, &max_l );
848 5470 : IF( max_l )
849 : {
850 5470 : q_shift = sub( norm_l( max_l ), 2 );
851 5470 : scale_sig32( st->hFdCngDec->msNoiseEst, NPART_SHAPING, q_shift ); /* st->hFdCngDec->msNoiseEst_exp - q_shift */
852 5470 : st->hFdCngDec->msNoiseEst_exp = sub( st->hFdCngDec->msNoiseEst_exp, q_shift );
853 5470 : move16();
854 : }
855 5470 : st->hFdCngDec->first_cna_noise_updated = 1;
856 5470 : move16();
857 5470 : Copy32( st->hFdCngDec->msNoiseEst, st->hFdCngDec->msPeriodog_ST_fx, st->hFdCngDec->nFFTpart_shaping ); /* st->hFdCngDec->msNoiseEst_exp - q_shift */
858 5470 : st->hFdCngDec->msPeriodog_ST_exp = st->hFdCngDec->msNoiseEst_exp;
859 5470 : st->hFdCngDec->ms_last_inactive_bwidth = st->bwidth; /* Q0 */
860 5470 : move16();
861 : }
862 :
863 10940 : pop_wmops();
864 10940 : return;
865 : }
866 :
867 : /*-------------------------------------------------------------------
868 : * stereo_dtf_cng()
869 : *
870 : * DFT stereo CNG
871 : *-------------------------------------------------------------------*/
872 42046 : void stereo_dtf_cng_fx(
873 : CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
874 : const Word32 ivas_total_brate, /* i : IVAS total bitrate Q0*/
875 : Word32 DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i/o: DFT buffers q_dft*/
876 : const Word16 output_frame, /* i : output frame size Q0*/
877 : Word16 q_dft /* i : Q factor of the DFT data */
878 : )
879 : {
880 : Decoder_State **sts;
881 : Word16 n;
882 :
883 42046 : sts = hCPE->hCoreCoder;
884 :
885 42046 : IF( hCPE->hStereoCng != NULL )
886 : {
887 42046 : IF( LT_16( hCPE->hStereoCng->nr_dft_frames, CM_INIT ) )
888 : {
889 5605 : hCPE->hStereoCng->nr_dft_frames = add( hCPE->hStereoCng->nr_dft_frames, 1 ); /* Q0 */
890 5605 : move16();
891 : }
892 :
893 42046 : IF( LE_32( ivas_total_brate, IVAS_SID_5k2 ) )
894 : {
895 5470 : test();
896 5470 : IF( LT_16( hCPE->hStereoCng->nr_sid_frames, SID_INIT ) && EQ_32( ivas_total_brate, IVAS_SID_5k2 ) )
897 : {
898 90 : hCPE->hStereoCng->nr_sid_frames = add( hCPE->hStereoCng->nr_sid_frames, 1 ); /* Q0 */
899 90 : move16();
900 : }
901 :
902 16410 : FOR( n = 0; n < CPE_CHANNELS; n++ )
903 : {
904 10940 : stereo_dft_generate_comfort_noise_fx( hCPE->hStereoDft, hCPE->hStereoCng, hCPE->last_element_mode, sts[0], DFT, sts[1], extract_h( hCPE->hStereoTCA->targetGain_fx ), n, output_frame, q_dft );
905 : }
906 : }
907 : }
908 :
909 42046 : return;
910 : }
911 :
912 :
913 : /*-------------------------------------------------------------------
914 : * stereo_cng_dec_update()
915 : *
916 : * Update counters used for TD->DFT-CNG cross fade and stereo SID parameters
917 : *-------------------------------------------------------------------*/
918 :
919 62798 : void stereo_cng_dec_update(
920 : CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
921 : const Word32 ivas_total_brate /* i : IVAS total bitrate Q0*/
922 : )
923 : {
924 62798 : IF( GT_32( hCPE->hCoreCoder[0]->core_brate, SID_2k40 ) )
925 : {
926 52447 : hCPE->hStereoCng->last_act_element_mode = hCPE->element_mode;
927 52447 : move16();
928 52447 : IF( GT_16( hCPE->hStereoCng->active_frame_counter, SKIP_XFADE_FRAMES ) )
929 : {
930 49613 : hCPE->hStereoCng->xfade_frame_counter = 0;
931 49613 : move16();
932 49613 : hCPE->hStereoCng->xfade_length = 0;
933 49613 : move16();
934 : }
935 52447 : IF( LT_16( hCPE->hStereoCng->active_frame_counter, MAX_FRAME_COUNTER ) )
936 : {
937 33860 : hCPE->hStereoCng->active_frame_counter = add( hCPE->hStereoCng->active_frame_counter, 1 ); /* Q0 */
938 33860 : move16();
939 : }
940 : }
941 : ELSE
942 : {
943 10351 : hCPE->hStereoCng->active_frame_counter = 0;
944 10351 : move16();
945 10351 : IF( LT_16( hCPE->hStereoCng->xfade_frame_counter, MAX_FRAME_COUNTER ) )
946 : {
947 10351 : hCPE->hStereoCng->xfade_frame_counter = add( hCPE->hStereoCng->xfade_frame_counter, 1 ); /* Q0 */
948 10351 : move16();
949 : }
950 : }
951 :
952 62798 : IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) )
953 : {
954 59047 : test();
955 59047 : IF( EQ_32( ivas_total_brate, IVAS_SID_5k2 ) || ( ivas_total_brate == FRAME_NO_DATA ) )
956 : {
957 10351 : hCPE->hStereoCng->prev_sid_nodata = 1;
958 10351 : move16();
959 : }
960 : ELSE
961 : {
962 48696 : hCPE->hStereoCng->prev_sid_nodata = 0;
963 48696 : move16();
964 : }
965 : }
966 :
967 62798 : hCPE->hCoreCoder[0]->hFdCngDec->hFdCngCom->active_frame_counter = hCPE->hStereoCng->active_frame_counter; /* Q0 */
968 62798 : move16();
969 :
970 62798 : return;
971 : }
972 :
973 :
974 : /*-------------------------------------------------------------------*
975 : * Function stereo_cng_compute_PScorr()
976 : *
977 : * CNA for TD stereo, compute PS correlation
978 : *-------------------------------------------------------------------*/
979 3751 : void stereo_cng_compute_PScorr_fx(
980 : Word32 output_fx0[], /* i : Output signal Qx = 1 temp*/
981 : Word32 output_fx1[], /* i : Output signal Qx*/
982 : Word16 *output_Q,
983 : Word32 *c_PS_LT_fx,
984 : Word16 Q_c_PS_LT_fx,
985 : const Word16 L_frame_0, /* i : L_frame channel 0 Q0*/
986 : const Word16 L_frame_1 /* i : L_frame channel 1 Q0*/
987 : )
988 : {
989 : Word16 i;
990 3751 : Word32 enrP_fx = 0, enrS_fx = 0, dotPS_fx = 0, c_PS_fx;
991 3751 : move32();
992 3751 : move32();
993 3751 : move32();
994 : Word32 outputResamp_fx[L_FRAME16k];
995 : Word32 *outputPptr_fx, *outputSptr_fx;
996 3751 : Word16 outputPptr_Q = 0, outputSptr_Q = 0;
997 3751 : move16();
998 3751 : move16();
999 3751 : Word32 tmp1 = 0, tmp2 = 0, tmp3 = 0;
1000 3751 : move32();
1001 3751 : move32();
1002 3751 : move32();
1003 :
1004 3751 : IF( GT_16( L_frame_0, L_frame_1 ) )
1005 : {
1006 2082 : outputPptr_fx = output_fx0;
1007 2082 : L_lerp_fx( output_fx1, outputResamp_fx, L_frame_0, L_frame_1, output_Q );
1008 2082 : outputPptr_Q = *output_Q;
1009 2082 : move16();
1010 2082 : outputSptr_fx = outputResamp_fx;
1011 2082 : outputSptr_Q = 1;
1012 2082 : move16();
1013 : }
1014 1669 : ELSE IF( GT_16( L_frame_1, L_frame_0 ) )
1015 : {
1016 0 : outputSptr_fx = output_fx1;
1017 0 : L_lerp_fx( output_fx0, outputResamp_fx, L_frame_1, L_frame_0, output_Q );
1018 0 : outputSptr_Q = *output_Q;
1019 0 : move16();
1020 0 : outputPptr_fx = outputResamp_fx;
1021 0 : outputPptr_Q = 1;
1022 0 : move16();
1023 : }
1024 : ELSE
1025 : {
1026 1669 : outputPptr_fx = output_fx0;
1027 1669 : outputSptr_fx = output_fx1;
1028 1669 : outputPptr_Q = *output_Q;
1029 1669 : move16();
1030 1669 : outputSptr_Q = *output_Q;
1031 1669 : move16();
1032 : }
1033 :
1034 3751 : Word16 guard_bits = find_guarded_bits_fx( L_frame_0 );
1035 :
1036 1097255 : FOR( i = 0; i < L_frame_0; i++ )
1037 : {
1038 1093504 : tmp1 = Mpy_32_32( *outputPptr_fx, *outputPptr_fx ); // 2*outputPptr_Q - 31
1039 1093504 : tmp1 = L_shr( tmp1, guard_bits ); // 2*outputPptr_Q - 31 - guard_bits
1040 1093504 : enrP_fx = L_add( enrP_fx, tmp1 );
1041 1093504 : tmp2 = Mpy_32_32( *outputSptr_fx, *outputSptr_fx ); // 2*outputSptr_Q - 31
1042 1093504 : tmp2 = L_shr( tmp2, guard_bits ); // 2 * outputSptr_Q - 31 - guard_bits
1043 1093504 : enrS_fx = L_add( enrS_fx, tmp2 );
1044 :
1045 1093504 : tmp3 = Mpy_32_32( *outputPptr_fx++, *outputSptr_fx++ ); // outputSptr_Q + outputPptr_Q - 31
1046 1093504 : tmp3 = L_shr( tmp3, add( guard_bits, 1 ) ); // outputSptr_Q + outputPptr_Q - 31 - guard_bits
1047 1093504 : dotPS_fx = L_add( dotPS_fx, tmp3 );
1048 : }
1049 :
1050 3751 : Word32 Var1 = Mpy_32_32( enrP_fx, enrS_fx ); // 2*( outputPptr_Q - 31 - guard_bits + outputSptr_Q - 31 - guard_bits )
1051 3751 : Word16 exp = sub( 31, shl( add( sub( sub( outputPptr_Q, 31 ), guard_bits ), sub( sub( outputSptr_Q, 31 ), guard_bits ) ), 1 ) );
1052 :
1053 3751 : if ( Var1 == 0 )
1054 : {
1055 3712 : Var1 = 1;
1056 3712 : move32();
1057 : }
1058 :
1059 : Word32 Var2, Var3;
1060 3751 : Var2 = ISqrt32( Var1, &exp );
1061 3751 : Var3 = L_add( dotPS_fx, 1 ); /*adding one in order to make temp non-zero. q = Q_outputSptr + Q_outputPptr - guard_bits*/
1062 3751 : c_PS_fx = Mpy_32_32( Var3, Var2 ); /* outputSptr_Q + outputPptr_Q - guard_bits - exp */
1063 :
1064 3751 : Word16 c_PS_fx_Q = add( outputSptr_Q, sub( sub( sub( outputPptr_Q, guard_bits ), exp ), 31 ) );
1065 3751 : Word32 a = 0, b = 0;
1066 3751 : move32();
1067 3751 : move32();
1068 3751 : Word16 a_q = 0, b_q = 0, ab_q = 0;
1069 3751 : move16();
1070 3751 : move16();
1071 3751 : move16();
1072 :
1073 3751 : a = Mpy_32_32( c_PS_fx, ONE_MINUS_STEREO_TD_PS_CORR_FILT_Q31 ); // Q(c_PS_fx_Q)
1074 3751 : a_q = c_PS_fx_Q;
1075 3751 : move16();
1076 3751 : b = Mpy_32_32( STEREO_TD_PS_CORR_FILT_Q31, *c_PS_LT_fx ); // Q(Q_c_PS_LT_fx)
1077 3751 : b_q = Q_c_PS_LT_fx;
1078 3751 : move16();
1079 :
1080 3751 : IF( GT_16( a_q, b_q ) )
1081 : {
1082 3751 : ab_q = sub( a_q, b_q );
1083 3751 : *c_PS_LT_fx = L_add( L_shr( a, ab_q ), b );
1084 3751 : move32();
1085 3751 : Q_c_PS_LT_fx = b_q;
1086 3751 : move16();
1087 : }
1088 0 : ELSE IF( LT_16( b_q, a_q ) )
1089 : {
1090 0 : ab_q = sub( b_q, a_q );
1091 0 : *c_PS_LT_fx = L_add( a, L_shr( b, ab_q ) );
1092 0 : move32();
1093 0 : Q_c_PS_LT_fx = a_q;
1094 0 : move16();
1095 : }
1096 :
1097 3751 : return;
1098 : }
1099 :
1100 :
1101 : /*-------------------------------------------------------------------*
1102 : * Function stereo_cng_compute_LRcorr()
1103 : *
1104 : * CNA for TD stereo, compute LR correlation
1105 : *-------------------------------------------------------------------*/
1106 :
1107 3751 : static void stereo_cng_compute_LRcorr_fx(
1108 : CPE_DEC_HANDLE hCPE, /* i/o: CPE handle */
1109 : Word32 *output_fx[CPE_CHANNELS], /* i : Output signal OUTPUT_Q*/
1110 : const Word16 output_frame, /* i : Output frame length Q0*/
1111 : const Word16 tdm_ratio_idx /* i : TDM ratio index Q0*/
1112 : )
1113 : {
1114 : Word16 i;
1115 : Word32 c_LR_fx, c_fx, tmp_fx, sc_fx;
1116 : Word16 c_q;
1117 : Word64 enrL_fx, enrR_fx, dotLR_fx;
1118 : Word32 beta_fx;
1119 : Word16 enrL_q, enrR_q, dotLR_q;
1120 : Word16 enrL_inv_q, enrR_inv_q;
1121 : Word16 sc_q;
1122 : Word16 headroom_left_enrL, headroom_left_enrR, headroom_left_dotLR;
1123 : Word32 temp_x_inv, temp_y_inv, energy_xy_fx;
1124 : Word16 res_q;
1125 : Word32 numer_1, numer_2, numer_3, num;
1126 : Word16 numer_1_q, numer_2_q, numer_3_q, num_q;
1127 : Word32 denom_1, denom_2, denom_3, denom;
1128 : Word16 denom_1_q, denom_2_q, denom_3_q, denom_q;
1129 : Word32 beta_sqr, one_minus_beta_sqr;
1130 3751 : beta_fx = tdm_ratio_tabl_fx[tdm_ratio_idx];
1131 3751 : move32();
1132 :
1133 3751 : enrL_fx = 0;
1134 3751 : move64();
1135 3751 : enrR_fx = 0;
1136 3751 : move64();
1137 3751 : dotLR_fx = 0;
1138 3751 : move64();
1139 :
1140 2406951 : FOR( i = 0; i < output_frame; i++ )
1141 : {
1142 2403200 : enrL_fx = W_add( enrL_fx, W_mult0_32_32( output_fx[0][i], output_fx[0][i] ) ); /* 2 * OUTPUT_Q */
1143 2403200 : enrR_fx = W_add( enrR_fx, W_mult0_32_32( output_fx[1][i], output_fx[1][i] ) ); /* 2 * OUTPUT_Q */
1144 2403200 : dotLR_fx = W_add( dotLR_fx, W_mult0_32_32( output_fx[0][i], output_fx[1][i] ) ); /* 2 * OUTPUT_Q */
1145 : }
1146 3751 : dotLR_fx = W_add( dotLR_fx, EPSILON_FX_SMALL );
1147 3751 : if ( dotLR_fx < 0 )
1148 : {
1149 669 : dotLR_fx = W_neg( dotLR_fx );
1150 : }
1151 3751 : enrL_fx = W_add( enrL_fx, EPSILON_FX_SMALL );
1152 3751 : enrR_fx = W_add( enrR_fx, EPSILON_FX_SMALL );
1153 :
1154 3751 : headroom_left_enrL = W_norm( enrL_fx );
1155 3751 : headroom_left_enrR = W_norm( enrR_fx );
1156 :
1157 : {
1158 :
1159 3751 : IF( LT_16( headroom_left_enrL, 32 ) )
1160 : {
1161 3587 : enrL_fx = W_shr( enrL_fx, sub( 32, headroom_left_enrL ) );
1162 3587 : enrL_q = sub( 31, sub( ( 2 * OUTPUT_Q ), sub( 32, headroom_left_enrL ) ) );
1163 : }
1164 : ELSE
1165 : {
1166 164 : enrL_q = sub( 31, ( 2 * OUTPUT_Q ) );
1167 : }
1168 3751 : IF( LT_16( headroom_left_enrR, 32 ) )
1169 : {
1170 3692 : enrR_fx = W_shr( enrR_fx, sub( 32, headroom_left_enrR ) );
1171 3692 : enrR_q = sub( 31, sub( ( 2 * OUTPUT_Q ), sub( 32, headroom_left_enrR ) ) );
1172 : }
1173 : ELSE
1174 : {
1175 59 : enrR_q = sub( 31, ( 2 * OUTPUT_Q ) );
1176 : }
1177 :
1178 3751 : enrL_inv_q = enrL_q;
1179 3751 : move16();
1180 3751 : enrR_inv_q = enrR_q;
1181 3751 : move16();
1182 :
1183 3751 : temp_x_inv = ISqrt32( W_extract_l( enrL_fx ), &enrL_inv_q );
1184 3751 : temp_y_inv = ISqrt32( W_extract_l( enrR_fx ), &enrR_inv_q );
1185 3751 : energy_xy_fx = Mpy_32_32( temp_x_inv, temp_y_inv ); /* enrL_inv_q + enrR_inv_q - 31 */
1186 3751 : res_q = add( enrL_inv_q, enrR_inv_q );
1187 3751 : headroom_left_dotLR = W_norm( dotLR_fx );
1188 3751 : dotLR_q = OUTPUT_Q * 2;
1189 3751 : move16();
1190 3751 : IF( LT_16( headroom_left_dotLR, 32 ) )
1191 : {
1192 3643 : dotLR_fx = W_shr( dotLR_fx, sub( 32, headroom_left_dotLR ) );
1193 3643 : dotLR_q = sub( dotLR_q, sub( 32, headroom_left_dotLR ) );
1194 : }
1195 3751 : dotLR_fx = Mpy_32_32( W_extract_l( dotLR_fx ), energy_xy_fx );
1196 3751 : dotLR_q = add( dotLR_q, sub( sub( 31, res_q ), 31 ) );
1197 3751 : dotLR_fx = W_shl( dotLR_fx, sub( 31, dotLR_q ) );
1198 : }
1199 3751 : c_LR_fx = extract_h( W_extract_l( dotLR_fx ) );
1200 :
1201 3751 : Word16 div_q = 0;
1202 3751 : move16();
1203 3751 : c_fx = BASOP_Util_Divide3232_Scale( W_extract_l( enrL_fx ), W_extract_l( enrR_fx ), &div_q ); /* div_q */
1204 3751 : c_q = add( sub( 15, div_q ), sub( enrR_q, enrL_q ) );
1205 :
1206 3751 : hCPE->hStereoTD->c_LR_LT_fx = L_add( Mpy_32_32( STEREO_TD_PS_CORR_FILT_FX, hCPE->hStereoTD->c_LR_LT_fx ),
1207 3751 : Mpy_32_32( L_sub( ONE_IN_Q31, STEREO_TD_PS_CORR_FILT_FX ), L_deposit_h( extract_l( c_LR_fx ) ) ) ); /* Q31 */
1208 3751 : move32();
1209 3751 : hCPE->hStereoCng->c_LR_LT_fx = hCPE->hStereoTD->c_LR_LT_fx; /* Q31 */
1210 3751 : move32();
1211 :
1212 3751 : Word16 sqrt_q = sub( 31, c_q );
1213 3751 : Word32 sqrt_res = Sqrt32( c_fx, &sqrt_q );
1214 3751 : tmp_fx = Mpy_32_32( beta_fx, L_sub( ONE_IN_Q31, beta_fx ) );
1215 3751 : tmp_fx = Mpy_32_32( tmp_fx, hCPE->hStereoTD->c_LR_LT_fx );
1216 3751 : tmp_fx = Mpy_32_32( tmp_fx, sqrt_res );
1217 3751 : Word16 tmp_q = sub( sub( 31, sqrt_q ), 1 ); // *2 handled with q reduction
1218 :
1219 3751 : beta_sqr = Mpy_32_32( beta_fx, beta_fx ); /* Q31 */
1220 3751 : one_minus_beta_sqr = Mpy_32_32( L_sub( ONE_IN_Q31, beta_fx ), L_sub( ONE_IN_Q31, beta_fx ) ); /* Q31 */
1221 :
1222 3751 : numer_1 = Mpy_32_16_1( one_minus_beta_sqr, extract_l( c_fx ) ); // c_q+31-15
1223 3751 : numer_1_q = add( c_q, 31 - 15 );
1224 3751 : numer_2 = beta_sqr; // 31
1225 3751 : move32();
1226 3751 : numer_2_q = 31;
1227 3751 : move16();
1228 3751 : numer_3 = tmp_fx; // tmp_q
1229 3751 : move32();
1230 3751 : numer_3_q = tmp_q;
1231 3751 : move16();
1232 3751 : num_q = 31;
1233 3751 : move16();
1234 :
1235 3751 : num_q = s_min( num_q, numer_1_q );
1236 :
1237 3751 : num_q = s_min( num_q, numer_2_q );
1238 :
1239 3751 : num_q = s_min( num_q, numer_3_q );
1240 :
1241 3751 : denom_1 = Mpy_32_16_1( beta_sqr, extract_l( c_fx ) ); // c_q+31-15;
1242 3751 : denom_1_q = add( c_q, 31 - 15 );
1243 3751 : denom_2 = one_minus_beta_sqr; // 31
1244 3751 : move32();
1245 3751 : denom_2_q = 31;
1246 3751 : move16();
1247 3751 : denom_3 = tmp_fx; // tmp_q
1248 3751 : move32();
1249 3751 : denom_3_q = tmp_q;
1250 3751 : move16();
1251 3751 : denom_q = 31;
1252 3751 : move16();
1253 :
1254 3751 : denom_q = s_min( denom_q, denom_1_q );
1255 :
1256 3751 : denom_q = s_min( denom_q, denom_2_q );
1257 :
1258 3751 : denom_q = s_min( denom_q, denom_3_q );
1259 :
1260 3751 : num = L_add( L_add( L_shr( numer_1, sub( numer_1_q, num_q ) ), L_sub( L_shr( numer_2, sub( numer_2_q, num_q ) ), L_shr( numer_3, sub( numer_3_q, num_q ) ) ) ), DELTA_FX ); /* num_q */
1261 3751 : denom = L_add( L_add( L_shr( denom_1, sub( denom_1_q, denom_q ) ), L_add( L_shr( denom_2, sub( denom_2_q, denom_q ) ), L_shr( denom_3, sub( denom_3_q, denom_q ) ) ) ), DELTA_FX ); /* denom_q */
1262 3751 : Word16 q = 0;
1263 3751 : move16();
1264 3751 : sc_fx = BASOP_Util_Divide3232_Scale( num, denom, &q );
1265 3751 : sc_q = sub( sub( 15, sub( num_q, denom_q ) ), q );
1266 3751 : Word32 sc_thr = L_shr( sc_fx, sc_q );
1267 3751 : IF( GT_32( sc_thr, 4 ) )
1268 : {
1269 547 : sc_fx = MAX_WORD16;
1270 547 : move32();
1271 : }
1272 : ELSE
1273 : {
1274 3204 : sc_fx = L_shr( sc_fx, sub( sc_q, 13 ) );
1275 : }
1276 3751 : sqrt_q = 2;
1277 3751 : move16();
1278 3751 : sqrt_res = Sqrt32( L_shl_sat( sc_fx, 16 ), &sqrt_q );
1279 3751 : IF( sqrt_q < 0 )
1280 : {
1281 680 : sqrt_res = L_shr( sqrt_res, ( -sqrt_q ) );
1282 680 : sqrt_q = 0;
1283 680 : move16();
1284 : }
1285 3751 : hCPE->hStereoTD->SP_ratio_LT_fx = L_add_sat( Mpy_32_32( 1932735283, hCPE->hStereoTD->SP_ratio_LT_fx ),
1286 : L_shl_sat( Mpy_32_32( 214748364, sqrt_res ), sqrt_q ) ); /* sqrt_q */
1287 3751 : move32();
1288 :
1289 3751 : IF( LT_16( hCPE->hStereoCng->nr_corr_frames, CM_INIT ) )
1290 : {
1291 1757 : hCPE->hStereoCng->nr_corr_frames = add( hCPE->hStereoCng->nr_corr_frames, 1 ); /* Q0 */
1292 1757 : move16();
1293 : }
1294 :
1295 3751 : hCPE->hStereoCng->nr_dft_frames = 0;
1296 3751 : move16();
1297 :
1298 3751 : return;
1299 : }
1300 :
1301 :
1302 : /*-------------------------------------------------------------------*
1303 : * FindEmEs()
1304 : *
1305 : * Find the energie ratio between the mono and the side
1306 : *-------------------------------------------------------------------*/
1307 :
1308 :
1309 40452 : static void FindEmEs_fx(
1310 : const Word32 *ch1_fx, /* i : Left channel OUTPUT_Q*/
1311 : const Word32 *ch2_fx, /* i : right channel OUTPUT_Q*/
1312 : const Word16 len, /* i : length Q0*/
1313 : Word32 *lt_es_em_fx /* i/o: LT energy ratio Q24*/
1314 : )
1315 : {
1316 : Word16 i;
1317 : Word32 mono_i_fx;
1318 : Word32 es_em_fx;
1319 : Word32 side_i_fx;
1320 : Word64 ener_fx, ener_side_fx;
1321 : Word16 headroom_left_ener_fx, headroom_left_ener_side_fx;
1322 : Word16 ener_q, ener_side_q;
1323 40452 : ener_fx = 1;
1324 40452 : move64();
1325 40452 : ener_side_fx = 1;
1326 40452 : move64();
1327 : Word32 square_res, log_res, division_res;
1328 40452 : Word16 temp_q = 0;
1329 40452 : move16();
1330 26006532 : FOR( i = 0; i < len; i++ )
1331 : {
1332 25966080 : mono_i_fx = L_add( L_shr( ch1_fx[i], 1 ), L_shr( ch2_fx[i], 1 ) );
1333 25966080 : ener_fx = W_add( ener_fx, W_mult0_32_32( mono_i_fx, mono_i_fx ) ); /* 2 * OUTPUT_Q */
1334 25966080 : side_i_fx = L_sub( L_shr( ch1_fx[i], 1 ), L_shr( ch2_fx[i], 1 ) );
1335 25966080 : ener_side_fx = W_add( ener_side_fx, W_mult0_32_32( side_i_fx, side_i_fx ) ); /* 2 * OUTPUT_Q */
1336 : }
1337 40452 : headroom_left_ener_fx = W_norm( ener_fx );
1338 40452 : headroom_left_ener_side_fx = W_norm( ener_side_fx );
1339 :
1340 40452 : IF( LT_16( headroom_left_ener_fx, 32 ) )
1341 : {
1342 39065 : ener_fx = W_shr( ener_fx, sub( 32, headroom_left_ener_fx ) ); /* 2 * OUTPUT_Q - 32 * headroom_left_ener_fx */
1343 39065 : ener_q = sub( ( 2 * OUTPUT_Q ), sub( 32, headroom_left_ener_fx ) );
1344 : }
1345 : ELSE
1346 : {
1347 1387 : ener_q = ( 2 * OUTPUT_Q );
1348 1387 : move16();
1349 : }
1350 40452 : IF( LT_16( headroom_left_ener_side_fx, 32 ) )
1351 : {
1352 37909 : ener_side_fx = W_shr( ener_side_fx, sub( 32, headroom_left_ener_side_fx ) ); /* 2 * OUTPUT_Q - 32 * headroom_left_ener_fx */
1353 37909 : ener_side_q = sub( ( 2 * OUTPUT_Q ), sub( 32, headroom_left_ener_side_fx ) );
1354 : }
1355 : ELSE
1356 : {
1357 2543 : ener_side_q = ( 2 * OUTPUT_Q );
1358 2543 : move16();
1359 : }
1360 :
1361 : /**es_em = 10 * ( log10( sqrt( ener_side / len ) ) - log10( sqrt( ener / len ) ) ); */
1362 40452 : division_res = BASOP_Util_Divide3232_Scale( W_extract_l( ener_side_fx ), W_extract_l( ener_fx ), &temp_q );
1363 40452 : temp_q = sub( temp_q, sub( ener_side_q, ener_q ) );
1364 40452 : square_res = Sqrt32( L_deposit_h( extract_l( division_res ) ), &temp_q ); /* temp_q */
1365 40452 : IF( temp_q < 0 )
1366 : {
1367 19803 : square_res = L_shr( square_res, ( -temp_q ) );
1368 19803 : temp_q = 0;
1369 19803 : move16();
1370 : }
1371 40452 : log_res = BASOP_Util_Log2( square_res );
1372 40452 : es_em_fx = Mpy_32_32( log_res, 1616107501 ); // 25+30-31
1373 : /* long-term estimate */
1374 40452 : *lt_es_em_fx = L_add( Mpy_32_32( 858993459, *lt_es_em_fx ), Mpy_32_32( 1288490188, es_em_fx ) ); /* Q24 */
1375 40452 : move32();
1376 40452 : return;
1377 : }
1378 :
1379 :
1380 : /*-------------------------------------------------------------------*
1381 : * Function stereo_cna_update_params()
1382 : *
1383 : * compute LR correlation and update long-term parameters for stereo CNA
1384 : *-------------------------------------------------------------------*/
1385 :
1386 145402 : void stereo_cna_update_params_fx(
1387 : CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
1388 : Word32 *output_fx[CPE_CHANNELS], /* i : Output signal OUTPUT_Q*/
1389 : const Word16 output_frame, /* i : Output frame length Q0*/
1390 : const Word16 tdm_ratio_idx /* i : TDM ratio index Q0*/
1391 : )
1392 : {
1393 : Word16 i;
1394 : Word64 enrL_fx, enrR_fx, dotLR_fx;
1395 : Word32 c_fx, c_LR_fx, c_ILD_fx;
1396 : Decoder_State **sts;
1397 : HANDLE_FD_CNG_DEC hFdCngDec;
1398 : Word16 dotLR_fx_q;
1399 : Word32 temp_x_inv, temp_y_inv, energy_xy_fx;
1400 : Word16 headroom_left_x, headroom_left_y;
1401 : Word16 headroom_left_dotLR_fx;
1402 : Word16 x_q, y_q, c_q;
1403 : Word16 x_inv_q, y_inv_q;
1404 : Word16 temp_res_q;
1405 145402 : sts = hCPE->hCoreCoder;
1406 :
1407 145402 : hFdCngDec = sts[0]->hFdCngDec;
1408 :
1409 145402 : IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) )
1410 : {
1411 59047 : IF( GT_16( hCPE->nchan_out, 1 ) )
1412 : {
1413 36701 : FindEmEs_fx( output_fx[0], output_fx[1], output_frame, &hCPE->lt_es_em_fx );
1414 : }
1415 : ELSE
1416 : {
1417 22346 : hCPE->lt_es_em_fx = 0;
1418 22346 : move32();
1419 : }
1420 : }
1421 86355 : ELSE IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) )
1422 : {
1423 3751 : FindEmEs_fx( output_fx[0], output_fx[1], output_frame, &hCPE->lt_es_em_fx );
1424 :
1425 :
1426 3751 : hCPE->hStereoCng->first_SID_after_TD = 1; /* Q0 */
1427 3751 : move16();
1428 3751 : stereo_cng_compute_LRcorr_fx( hCPE, output_fx, output_frame, tdm_ratio_idx );
1429 : }
1430 : ELSE
1431 : {
1432 82604 : return;
1433 : }
1434 :
1435 62798 : enrL_fx = 0;
1436 62798 : move64();
1437 62798 : enrR_fx = 0;
1438 62798 : move64();
1439 62798 : dotLR_fx = 0;
1440 62798 : move64();
1441 :
1442 62798 : test();
1443 62798 : test();
1444 62798 : test();
1445 62798 : IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) || ( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) && GT_32( sts[0]->core_brate, SID_2k40 ) && ( sts[0]->VAD == 0 ) ) )
1446 : {
1447 6853 : IF( EQ_16( hCPE->nchan_out, 1 ) )
1448 : {
1449 : #ifdef OPT_STEREO_32KBPS_V1
1450 2851 : c_LR_fx = MAX_32;
1451 : #else /* OPT_STEREO_32KBPS_V1 */
1452 : c_LR_fx = MAX_WORD16;
1453 : #endif /* OPT_STEREO_32KBPS_V1 */
1454 2851 : move32();
1455 2851 : c_ILD_fx = 0;
1456 2851 : move32();
1457 : }
1458 : ELSE
1459 : {
1460 2730722 : FOR( i = 0; i < output_frame; i++ )
1461 : {
1462 2726720 : enrL_fx = W_add( enrL_fx, W_mult0_32_32( output_fx[0][i], output_fx[0][i] ) ); /* 2 * OUTPUT_Q */
1463 2726720 : enrR_fx = W_add( enrR_fx, W_mult0_32_32( output_fx[1][i], output_fx[1][i] ) ); /* 2 * OUTPUT_Q */
1464 2726720 : dotLR_fx = W_add( dotLR_fx, W_mult0_32_32( output_fx[0][i], output_fx[1][i] ) ); /* 2 * OUTPUT_Q */
1465 : }
1466 4002 : dotLR_fx = W_add( dotLR_fx, EPSILON_FX_SMALL );
1467 4002 : if ( dotLR_fx < 0 )
1468 : {
1469 743 : dotLR_fx = W_neg( dotLR_fx );
1470 : }
1471 4002 : enrL_fx = W_add( enrL_fx, EPSILON_FX_SMALL );
1472 4002 : enrR_fx = W_add( enrR_fx, EPSILON_FX_SMALL );
1473 4002 : headroom_left_x = W_norm( enrL_fx );
1474 4002 : headroom_left_y = W_norm( enrR_fx );
1475 :
1476 4002 : IF( LT_16( headroom_left_x, 32 ) )
1477 : {
1478 3877 : enrL_fx = W_shr( enrL_fx, sub( 32, headroom_left_x ) ); /* 2 * OUTPUT_Q - 32 * headroom_left_x */
1479 3877 : x_q = sub( 31, sub( ( 2 * OUTPUT_Q ), sub( 32, headroom_left_x ) ) );
1480 : }
1481 : ELSE
1482 : {
1483 125 : x_q = sub( 31, ( 2 * OUTPUT_Q ) );
1484 : }
1485 4002 : IF( LT_16( headroom_left_y, 32 ) )
1486 : {
1487 3959 : enrR_fx = W_shr( enrR_fx, sub( 32, headroom_left_y ) ); /* 2 * OUTPUT_Q - 32 * headroom_left_x */
1488 3959 : y_q = sub( 31, sub( ( 2 * OUTPUT_Q ), sub( 32, headroom_left_y ) ) );
1489 : }
1490 : ELSE
1491 : {
1492 43 : y_q = sub( 31, ( 2 * OUTPUT_Q ) );
1493 : }
1494 :
1495 4002 : x_inv_q = x_q;
1496 4002 : move16();
1497 4002 : y_inv_q = y_q;
1498 4002 : move16();
1499 :
1500 4002 : temp_x_inv = ISqrt32( W_extract_l( enrL_fx ), &x_inv_q );
1501 4002 : temp_y_inv = ISqrt32( W_extract_l( enrR_fx ), &y_inv_q );
1502 4002 : energy_xy_fx = Mpy_32_32( temp_x_inv, temp_y_inv ); /* x_inv_q + y_inv_q */
1503 4002 : temp_res_q = add( x_inv_q, y_inv_q );
1504 4002 : headroom_left_dotLR_fx = W_norm( dotLR_fx );
1505 4002 : dotLR_fx_q = OUTPUT_Q * 2;
1506 4002 : move16();
1507 4002 : IF( LT_16( headroom_left_dotLR_fx, 32 ) )
1508 : {
1509 3922 : dotLR_fx = W_shr( dotLR_fx, sub( 32, headroom_left_dotLR_fx ) ); /* dotLR_fx_q - (32 * headroom_left_dotLR_fx) */
1510 3922 : dotLR_fx_q = sub( dotLR_fx_q, sub( 32, headroom_left_dotLR_fx ) );
1511 : }
1512 4002 : dotLR_fx = Mpy_32_32( W_extract_l( dotLR_fx ), energy_xy_fx ); /* dotLR_fx_q + ((31 - temp_res_q) - 31)) */
1513 4002 : dotLR_fx_q = add( dotLR_fx_q, sub( sub( 31, temp_res_q ), 31 ) );
1514 4002 : dotLR_fx = W_deposit32_l( L_shl_sat( W_extract_l( dotLR_fx ), sub( 31, dotLR_fx_q ) ) ); /* Q31 */
1515 : /* estimate L/R correlation factor and ILD in time domain */
1516 : #ifdef OPT_STEREO_32KBPS_V1
1517 4002 : c_LR_fx = W_extract_l( dotLR_fx ); /* Q31 */
1518 : #else /* OPT_STEREO_32KBPS_V1 */
1519 : c_LR_fx = extract_h( W_extract_l( dotLR_fx ) ); /* Q15 */
1520 : #endif /* OPT_STEREO_32KBPS_V1 */
1521 :
1522 4002 : temp_res_q = 0;
1523 4002 : move16();
1524 4002 : c_fx = BASOP_Util_Divide3232_Scale( W_extract_l( enrL_fx ), W_extract_l( enrR_fx ), &temp_res_q );
1525 4002 : c_q = add( sub( 15, temp_res_q ), sub( y_q, x_q ) );
1526 :
1527 : Word32 one_in_c_q;
1528 4002 : IF( GT_16( c_q, 31 ) )
1529 : {
1530 69 : c_q = 31;
1531 69 : move16();
1532 69 : c_fx = L_shr_sat( c_fx, sub( c_q, 31 ) ); /* Q31 */
1533 69 : one_in_c_q = ONE_IN_Q31;
1534 69 : move32();
1535 : }
1536 : ELSE
1537 : {
1538 3933 : one_in_c_q = L_shl_sat( 1, c_q );
1539 : }
1540 :
1541 4002 : Word32 num_c_fx = L_sub_sat( c_fx, one_in_c_q );
1542 4002 : Word32 denom_c_fx = L_add_sat( c_fx, one_in_c_q );
1543 4002 : Word16 num_c_headroom = norm_l( L_sub_sat( c_fx, one_in_c_q ) );
1544 4002 : Word16 denom_c_headroom = norm_l( L_add_sat( c_fx, one_in_c_q ) );
1545 4002 : Word16 min_headroom_left = s_min( num_c_headroom, denom_c_headroom );
1546 4002 : move16();
1547 4002 : temp_res_q = 0;
1548 4002 : move16();
1549 4002 : c_ILD_fx = BASOP_Util_Divide3232_Scale( L_shl_sat( num_c_fx, min_headroom_left ), L_shl_sat( denom_c_fx, min_headroom_left ), &temp_res_q ); /* temp_res_q */
1550 4002 : IF( temp_res_q < 0 )
1551 : {
1552 1974 : c_ILD_fx = L_shr( c_ILD_fx, negate( temp_res_q ) );
1553 : }
1554 : }
1555 :
1556 : /* update of long-term ILD and LR correlation factors for stereo CNA */
1557 6853 : IF( !hFdCngDec->first_cna_noise_updated )
1558 : {
1559 : #ifdef OPT_STEREO_32KBPS_V1
1560 2543 : hFdCngDec->cna_LR_LT_fx = extract_h( c_LR_fx );
1561 : #else /* OPT_STEREO_32KBPS_V1 */
1562 : hFdCngDec->cna_LR_LT_fx = extract_l( c_LR_fx );
1563 : #endif /* OPT_STEREO_32KBPS_V1 */
1564 2543 : move16();
1565 2543 : hFdCngDec->cna_ILD_LT_fx = extract_l( c_ILD_fx );
1566 2543 : move16();
1567 : }
1568 : ELSE
1569 : {
1570 : #ifdef OPT_STEREO_32KBPS_V1
1571 4310 : hFdCngDec->cna_LR_LT_fx = extract_h( L_add_sat( Mpy_32_16_1( STEREO_CNA_LR_CORR_LT_FILT_FX, hFdCngDec->cna_LR_LT_fx ),
1572 : Mpy_32_32( ONE_IN_Q31 - STEREO_CNA_LR_CORR_LT_FILT_FX, c_LR_fx ) ) ); /* Q31 */
1573 : #else /* OPT_STEREO_32KBPS_V1 */
1574 : hFdCngDec->cna_LR_LT_fx = extract_h( L_add_sat( Mpy_32_16_1( STEREO_CNA_LR_CORR_LT_FILT_FX, hFdCngDec->cna_LR_LT_fx ),
1575 : Mpy_32_16_1( L_sub( ONE_IN_Q31, STEREO_CNA_LR_CORR_LT_FILT_FX ), extract_l( c_LR_fx ) ) ) ); /* Q31 */
1576 : #endif /* OPT_STEREO_32KBPS_V1 */
1577 4310 : move16();
1578 :
1579 4310 : hFdCngDec->cna_ILD_LT_fx = extract_h( L_add_sat( Mpy_32_16_1( STEREO_CNA_ILD_LT_FILT_FX, hFdCngDec->cna_ILD_LT_fx ),
1580 4310 : Mpy_32_16_1( L_sub( ONE_IN_Q31, STEREO_CNA_ILD_LT_FILT_FX ), extract_l( c_ILD_fx ) ) ) ); /* Q31 */
1581 4310 : move16();
1582 : }
1583 :
1584 6853 : set16_fx( hFdCngDec->cna_g_state_fx, hFdCngDec->cna_ILD_LT_fx, hFdCngDec->cna_nbands );
1585 6853 : set16_fx( hFdCngDec->cna_cm_fx, hFdCngDec->cna_LR_LT_fx, hFdCngDec->cna_nbands );
1586 : }
1587 :
1588 :
1589 : /* Soft VAD for stereo CNA */
1590 62798 : test();
1591 62798 : IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) || EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) )
1592 : {
1593 62798 : IF( !hFdCngDec->first_cna_noise_updated )
1594 : {
1595 31174 : hFdCngDec->cna_act_fact_fx = 0;
1596 31174 : move16();
1597 : }
1598 : ELSE
1599 : {
1600 31624 : IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) )
1601 : {
1602 : /* quickly decrease in TD stereo mode */
1603 1686 : hFdCngDec->cna_act_fact_fx = extract_h( Mpy_32_16_1( 1503238553, hFdCngDec->cna_act_fact_fx ) ); /* Q15 */
1604 1686 : move16();
1605 : }
1606 29938 : ELSE IF( GT_32( L_mult0( sts[0]->VAD, MAX_WORD16 ), hFdCngDec->cna_act_fact_fx ) ) // VAD is one bit
1607 : {
1608 : /* quickly increase during active frames in DFT stereo mode */
1609 16977 : hFdCngDec->cna_act_fact_fx = extract_h( L_add( Mpy_32_16_1( 1503238553, hFdCngDec->cna_act_fact_fx ), ( 644245094 * sts[0]->VAD ) ) ); /* Q15 */
1610 16977 : move16();
1611 : }
1612 : ELSE
1613 : {
1614 : /* slowly decrease during inactive frames in DFT stereo mode */
1615 12961 : hFdCngDec->cna_act_fact_fx = extract_h( L_add( Mpy_32_16_1( 2040109440, hFdCngDec->cna_act_fact_fx ), ( 107374184 * sts[0]->VAD ) ) ); /* Q15 */
1616 12961 : move16();
1617 : }
1618 : }
1619 : }
1620 :
1621 62798 : return;
1622 : }
1623 :
1624 :
1625 : /*-------------------------------------------------------------------
1626 : * stereo_cng_init_dec()
1627 : *
1628 : * Initialized stereo CNG
1629 : *-------------------------------------------------------------------*/
1630 :
1631 764 : void stereo_cng_init_dec_fx(
1632 : STEREO_CNG_DEC_HANDLE hStereoCng, /* i/o: stereo CNG decoder structure */
1633 : const Word16 *frameSize /* i : pointer to frameSize of channel 0 to be used for channel 1 Q0*/
1634 : )
1635 : {
1636 764 : hStereoCng->prev_sid_nodata = 0;
1637 764 : move16();
1638 764 : set16_fx( hStereoCng->coh_fx, 8192 /*0.5 in Q14*/, STEREO_DFT_BAND_MAX + 1 );
1639 764 : set16_fx( hStereoCng->cm_fx, 0, STEREO_DFT_BAND_MAX );
1640 764 : hStereoCng->first_SID = 1;
1641 764 : move16();
1642 764 : hStereoCng->first_SID_after_TD = 0;
1643 764 : move16();
1644 764 : hStereoCng->active_frame_counter = 0;
1645 764 : move16();
1646 764 : hStereoCng->xfade_frame_counter = 0;
1647 764 : move16();
1648 764 : hStereoCng->xfade_length = 0;
1649 764 : move16();
1650 764 : hStereoCng->nr_dft_frames = 0;
1651 764 : move16();
1652 764 : hStereoCng->nr_corr_frames = 0;
1653 764 : move16();
1654 764 : hStereoCng->nr_sid_frames = 0;
1655 764 : move16();
1656 764 : set16_fx( hStereoCng->olapBufferSynth22_fx, 0, FFTLEN );
1657 764 : hStereoCng->flag_cna_fade = 0;
1658 764 : move16();
1659 764 : set16_fx( hStereoCng->maskingNoiseS_fx, 0, L_FRAME16k );
1660 764 : hStereoCng->enableSecCNA = 0;
1661 764 : move16();
1662 764 : hStereoCng->c_PS_LT_fx = 16384; /* 0.5 in Q15 */
1663 764 : move16();
1664 764 : hStereoCng->frameSize = frameSize;
1665 764 : hStereoCng->last_act_element_mode = IVAS_CPE_DFT;
1666 764 : move16();
1667 :
1668 764 : return;
1669 : }
|