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 :
34 : #include <stdint.h>
35 : #include <math.h>
36 : #include <assert.h>
37 : #include "options.h"
38 : #include "prot_fx.h"
39 : #include "rom_com.h"
40 : #include "wmc_auto.h"
41 : #include "ivas_prot_fx.h"
42 : #include "basop_util.h"
43 :
44 : /*------------------------------------------------------------------------------------------*
45 : * Local constants
46 : *------------------------------------------------------------------------------------------*/
47 :
48 : #define AGC_MIN_DELTA_FX 1 // q31
49 : #define TWO_IN_Q29 1073741824
50 : #define ONE_MINUS_M_DELTA_PROD_FLT_FC 1073741824 // Q15
51 :
52 : static Word16 ceil_fx( Word16 inp, Word16 Q );
53 : static Word32 pow32_fx( Word16 inp, Word16 indx );
54 : static Word16 BASOP_Util_Cmp_Mant32Exp_sat( Word32 a_m, Word16 a_e, Word32 b_m, Word16 b_e );
55 307 : static Word16 ceil_fx( Word16 inp, Word16 Q )
56 : {
57 : Word16 ret;
58 : Word32 ret_32;
59 307 : IF( inp > 0 )
60 : {
61 307 : IF( EQ_16( Q, 15 ) )
62 : {
63 282 : return 1;
64 : }
65 : ELSE
66 : {
67 25 : ret_32 = L_add( inp, sub( shl( 1, Q ), 1 ) ); //(inp+(pow(2,q)-1))/pow(2,q)//
68 25 : ret_32 = L_shr( ret_32, Q );
69 25 : return extract_l( ret_32 );
70 : }
71 : }
72 : ELSE
73 : {
74 0 : ret = negate( shr( abs_s( inp ), Q ) );
75 : }
76 :
77 0 : return ret;
78 : }
79 :
80 109837500 : Word16 BASOP_Util_Cmp_Mant32Exp_sat /*!< o: flag: result of comparison */
81 : /* 0, if a == b */
82 : /* 1, if a > b */
83 : /* -1, if a < b */
84 : ( Word32 a_m, /*!< i: Mantissa of 1st operand a */
85 : Word16 a_e, /*!< i: Exponent of 1st operand a */
86 : Word32 b_m, /*!< i: Mantissa of 2nd operand b */
87 : Word16 b_e ) /*!< i: Exponent of 2nd operand b */
88 :
89 : {
90 : Word32 diff_m;
91 : Word16 diff_e, shift, result;
92 :
93 :
94 : /*
95 : This function compares two input parameters, both represented by a 32-bit mantissa and a 16-bit exponent.
96 : If both values are identical, 0 is returned.
97 : If a is greater b, 1 is returned.
98 : If a is less than b, -1 is returned.
99 : */
100 :
101 : /* Check, if both mantissa and exponents are identical, when normalized: return 0 */
102 109837500 : shift = norm_l( a_m );
103 109837500 : IF( shift )
104 109737354 : a_m = L_shl( a_m, shift );
105 109837500 : IF( shift )
106 109737354 : a_e = sub( a_e, shift );
107 :
108 109837500 : shift = norm_l( b_m );
109 109837500 : IF( shift )
110 79280545 : b_m = L_shl( b_m, shift );
111 109837500 : IF( shift )
112 79280545 : b_e = sub( b_e, shift );
113 :
114 : /* align exponent, if any mantissa is zero */
115 109837500 : if ( !a_m )
116 : {
117 89984 : a_e = b_e;
118 89984 : move16();
119 : }
120 109837500 : if ( !b_m )
121 : {
122 69509 : b_e = a_e;
123 69509 : move16();
124 : }
125 :
126 : BASOP_SATURATE_WARNING_OFF_EVS
127 109837500 : diff_m = L_sub_sat( a_m, b_m );
128 : BASOP_SATURATE_WARNING_ON_EVS
129 109837500 : diff_e = sub( a_e, b_e );
130 :
131 109837500 : test();
132 109837500 : IF( diff_m == 0 && diff_e == 0 )
133 : {
134 48438 : return 0;
135 : }
136 :
137 : /* Check sign, exponent and mantissa to identify, whether a is greater b or not */
138 109789062 : result = -1; // sub( 0, 1 );
139 109789062 : move16();
140 :
141 109789062 : IF( a_m >= 0 )
142 : {
143 : /* a is positive */
144 64238519 : if ( b_m < 0 )
145 : {
146 0 : result = 1;
147 0 : move16();
148 : }
149 :
150 64238519 : test();
151 64238519 : test();
152 64238519 : test();
153 64238519 : if ( ( b_m >= 0 ) && ( ( diff_e > 0 ) || ( diff_e == 0 && diff_m > 0 ) ) )
154 : {
155 1046519 : result = 1;
156 1046519 : move16();
157 : }
158 : }
159 : ELSE
160 : {
161 : /* a is negative */
162 45550543 : test();
163 45550543 : test();
164 45550543 : test();
165 45550543 : if ( ( b_m < 0 ) && ( ( diff_e < 0 ) || ( diff_e == 0 && diff_m > 0 ) ) )
166 : {
167 132 : result = 1;
168 132 : move16();
169 : }
170 : }
171 109789062 : return result;
172 : }
173 :
174 3466817 : Word32 pow32_fx( Word16 inp, Word16 indx )
175 : {
176 : Word32 temp_1, temp_2;
177 3466817 : IF( EQ_16( indx, 1 ) )
178 : {
179 386178 : return L_deposit_h( inp );
180 : }
181 3080639 : ELSE IF( indx == 0 )
182 : {
183 3080639 : return ONE_IN_Q31;
184 : }
185 : ELSE
186 : {
187 0 : temp_1 = L_mult( inp, inp ); // Q31
188 0 : temp_2 = temp_1;
189 0 : move32();
190 0 : FOR( Word16 i = 0; i < ( indx >> 1 ); i++ )
191 : {
192 0 : temp_1 = Mpy_32_32( temp_1, temp_1 ); // Q31
193 : }
194 0 : IF( s_and( indx, 1 ) )
195 : {
196 0 : temp_1 = Mpy_32_32( temp_2, temp_1 ); // Q31
197 : }
198 : }
199 0 : return temp_1;
200 : }
201 :
202 :
203 : /*-----------------------------------------------------------------------------------------*
204 : * Function ivas_agc_enc_get_flag()
205 : *
206 : * This function determines if AGC is enabled or disabled.
207 : *-----------------------------------------------------------------------------------------*/
208 :
209 : /*! r: AGC enable flag */
210 3419 : Word16 ivas_agc_enc_get_flag(
211 : const Word16 nchan_transport /* i : number of transport channels Q0*/
212 : )
213 : {
214 : Word16 agc_flag;
215 :
216 : /* AGC is enabled only if there is one transport channel. */
217 3419 : agc_flag = 0;
218 3419 : move16();
219 3419 : if ( EQ_16( nchan_transport, 1 ) )
220 : {
221 1217 : agc_flag = 1;
222 1217 : move16();
223 : }
224 :
225 3419 : return agc_flag;
226 : }
227 :
228 :
229 : /*-----------------------------------------------------------------------------------------*
230 : * Function ivas_agc_enc_init()
231 : *
232 : * AGC encoder initialization
233 : *-----------------------------------------------------------------------------------------*/
234 :
235 540 : static void ivas_agc_enc_init_fx(
236 : ivas_agc_enc_state_t *hAgcEnc,
237 : const Word16 input_frame, /* Q0 */
238 : const Word16 nchan_inp, /* Q0 */
239 : const Word16 delay /* Q0 */
240 : )
241 : {
242 : Word16 i;
243 540 : ivas_agc_enc_chan_state_t *ptrG = hAgcEnc->gain_state;
244 540 : ivas_agc_chan_data_t *ptr = hAgcEnc->gain_data;
245 :
246 540 : hAgcEnc->agc_com.in_delay = delay; /* Q0 */
247 540 : move16();
248 540 : hAgcEnc->agc_com.num_coeff = FOA_CHANNELS;
249 540 : move16();
250 :
251 540 : ivas_agc_calcGainParams_fx( &hAgcEnc->agc_com.absEmin, &hAgcEnc->agc_com.betaE, &hAgcEnc->agc_com.maxAttExp, hAgcEnc->agc_com.num_coeff );
252 :
253 540 : ivas_agc_initWindowFunc_fx( hAgcEnc->agc_com.winFunc_fx, sub( input_frame, hAgcEnc->agc_com.in_delay ) );
254 :
255 540 : hAgcEnc->minDelta_fx = AGC_MIN_DELTA_FX;
256 540 : move32();
257 540 : hAgcEnc->smFact_fx = 214748368; // q31
258 540 : move32();
259 :
260 2700 : FOR( i = 0; i < nchan_inp; i++ )
261 : {
262 : /* gain_state */
263 2160 : ptrG->lastExp = 0;
264 2160 : move16();
265 2160 : ptrG->prevExp = 0;
266 2160 : move16();
267 2160 : ptrG->lastGain_fx = ONE_IN_Q31;
268 2160 : move32();
269 2160 : ptrG->q_lastGain_fx = Q31;
270 2160 : move16();
271 2160 : ptrG->lastMaxAbs_fx = 0;
272 2160 : move32();
273 2160 : ptrG->q_lastMaxAbs_fx = Q31;
274 2160 : move16();
275 2160 : ptrG->gainExpVal = 0;
276 2160 : move16();
277 2160 : ptrG->MaxAbsVal_del_fx = 0;
278 2160 : move32();
279 2160 : ptrG->q_MaxAbsVal_del_fx = Q31;
280 2160 : move16();
281 2160 : ptrG->MaxAbsValIdx_del = 0;
282 2160 : move32();
283 2160 : ptrG++;
284 :
285 : /* gain_data */
286 2160 : ptr->absGainExp = hAgcEnc->agc_com.absEmin; /* Q0 */
287 2160 : move16();
288 2160 : ptr->absGainExpCurr = hAgcEnc->agc_com.absEmin; /* Q0 */
289 2160 : move16();
290 2160 : ptr++;
291 : }
292 :
293 540 : return;
294 : }
295 :
296 :
297 : /*-------------------------------------------------------------------------
298 : * ivas_spar_agc_enc_open()
299 : *
300 : * Allocate and initialize SPAR AGC encoder handle
301 : *------------------------------------------------------------------------*/
302 :
303 540 : ivas_error ivas_spar_agc_enc_open_fx(
304 : ivas_agc_enc_state_t **hAgcEnc, /* i/o: SPAR AGC encoder handle */
305 : const Word32 input_Fs, /* i : input sampling rate Q0*/
306 : const Word16 nchan_inp /* i : number of input channels Q0*/
307 : )
308 : {
309 : ivas_agc_enc_state_t *hAgc;
310 : Word16 input_frame, delay;
311 :
312 540 : IF( ( hAgc = (ivas_agc_enc_state_t *) malloc( sizeof( ivas_agc_enc_state_t ) ) ) == NULL )
313 : {
314 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR AGC encoder" );
315 : }
316 :
317 540 : input_frame = extract_l( Mpy_32_16_1( input_Fs, INV_FRAME_PER_SEC_Q15 ) ); /* Q0 */
318 540 : delay = NS2SA_FX2( input_Fs, ( IVAS_ENC_DELAY_NS + IVAS_DEC_DELAY_NS ) );
319 :
320 540 : IF( ( hAgc->agc_com.winFunc_fx = (Word16 *) malloc( sizeof( Word16 ) * ( input_frame - delay ) ) ) == NULL )
321 : {
322 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR AGC encoder" );
323 : }
324 :
325 540 : IF( ( hAgc->gain_state = (ivas_agc_enc_chan_state_t *) malloc( sizeof( ivas_agc_enc_chan_state_t ) * nchan_inp ) ) == NULL )
326 : {
327 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR AGC encoder" );
328 : }
329 :
330 540 : IF( ( hAgc->gain_data = (ivas_agc_chan_data_t *) malloc( sizeof( ivas_agc_chan_data_t ) * nchan_inp ) ) == NULL )
331 : {
332 0 : return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SPAR AGC encoder" );
333 : }
334 :
335 540 : ivas_agc_enc_init_fx( hAgc, input_frame, nchan_inp, delay );
336 :
337 540 : *hAgcEnc = hAgc;
338 :
339 540 : return IVAS_ERR_OK;
340 : }
341 :
342 :
343 : /*-------------------------------------------------------------------------
344 : * ivas_spar_agc_enc_close()
345 : *
346 : * Deallocate SPAR AGC encoder handle
347 : *------------------------------------------------------------------------*/
348 :
349 1558 : void ivas_spar_agc_enc_close_fx(
350 : ivas_agc_enc_state_t **hAgcEnc /* i/o: SPAR AGC encoder handle */
351 : )
352 : {
353 : ivas_agc_enc_state_t *hAgc;
354 :
355 1558 : test();
356 1558 : IF( hAgcEnc == NULL || *hAgcEnc == NULL )
357 : {
358 1018 : return;
359 : }
360 :
361 540 : hAgc = *hAgcEnc;
362 :
363 540 : free( hAgc->agc_com.winFunc_fx );
364 540 : hAgc->agc_com.winFunc_fx = NULL;
365 :
366 540 : free( hAgc->gain_state );
367 540 : hAgc->gain_state = NULL;
368 :
369 540 : free( hAgc->gain_data );
370 540 : hAgc->gain_data = NULL;
371 :
372 540 : free( *hAgcEnc );
373 540 : *hAgcEnc = NULL;
374 :
375 540 : return;
376 : }
377 :
378 :
379 : /*-----------------------------------------------------------------------------------------*
380 : * Function ivas_agc_enc_process()
381 : *
382 : * AGC encoder
383 : *-----------------------------------------------------------------------------------------*/
384 :
385 42018 : void ivas_agc_enc_process_fx(
386 : ivas_agc_enc_state_t *hAgcEnc, /* i/o: AGC encoder handle */
387 : BSTR_ENC_HANDLE hMetaData, /* i/o: MetaData handle */
388 : Word32 **ppPcm_in, /* i : input audio channels q_ppPcm*/
389 : Word32 **ppPcm_out, /* o : output audio channels q_ppPcm*/
390 : const Word16 n_channels, /* i : number of channels Q0*/
391 : const ENCODER_CONFIG_HANDLE hEncoderConfig, /* i : configuration structure */
392 : Word16 *q_ppPcm )
393 : {
394 : Word16 i, j, idx, input_frame, offset;
395 : Word16 per_ch_bit[FOA_CHANNELS], AGC_flag;
396 42018 : Word16 extendedExpVal = FALSE;
397 42018 : move16();
398 : Word16 isGainAdjusted;
399 : Word16 q_predMaxAbsVal, q_MaxAbsVal;
400 42018 : ivas_agc_enc_state_t *pState = hAgcEnc;
401 :
402 42018 : input_frame = extract_l( Mpy_32_16_1( hEncoderConfig->input_Fs, INV_FRAME_PER_SEC_Q15 ) ); /* Q0 */
403 42018 : offset = sub( input_frame, pState->agc_com.in_delay ); /* Q0 */
404 :
405 42018 : AGC_flag = 0;
406 42018 : move16();
407 :
408 84036 : FOR( i = 0; i < n_channels; i++ )
409 : {
410 42018 : Word16 q_pcm = q_ppPcm[i];
411 42018 : move16();
412 : Word32 sampleAbsVal;
413 42018 : Word16 isClipped = FALSE;
414 42018 : move16();
415 42018 : Word16 clippedIdx = 0;
416 42018 : move16();
417 42018 : Word16 MaxAbsValIdx = 0;
418 42018 : move16();
419 : Word16 q_sampleAbsVal, gain_norm;
420 42018 : Word32 MaxAbsVal = pState->gain_state[i].MaxAbsVal_del_fx;
421 42018 : move32();
422 42018 : Word32 predMaxAbsVal = L_abs( ppPcm_in[i][offset] );
423 42018 : q_predMaxAbsVal = q_ppPcm[i];
424 42018 : move16();
425 42018 : q_MaxAbsVal = pState->gain_state[i].q_MaxAbsVal_del_fx;
426 42018 : move16();
427 :
428 42018 : IF( LT_16( pState->gain_state[i].q_lastGain_fx, Q31 ) )
429 : {
430 282 : gain_norm = norm_l( L_abs( pState->gain_state[i].lastGain_fx ) );
431 282 : pState->gain_state[i].lastGain_fx = L_shl( pState->gain_state[i].lastGain_fx, gain_norm ); /* pState->gain_state[i].q_lastGain_fx + gain_norm */
432 282 : move32();
433 282 : pState->gain_state[i].q_lastGain_fx = add( pState->gain_state[i].q_lastGain_fx, gain_norm );
434 282 : move16();
435 : }
436 30601058 : FOR( j = 0; j < input_frame; j++ )
437 : {
438 30559040 : sampleAbsVal = L_abs( ppPcm_in[i][j] ); /* q_ppPcm */
439 30559040 : q_sampleAbsVal = q_ppPcm[i];
440 30559040 : move16();
441 :
442 30559040 : IF( EQ_16( BASOP_Util_Cmp_Mant32Exp_sat( sampleAbsVal, sub( Q31, q_sampleAbsVal ), MaxAbsVal, sub( Q31, q_MaxAbsVal ) ), 1 ) )
443 : {
444 239841 : MaxAbsVal = sampleAbsVal; /* q_sampleAbsVal */
445 239841 : move32();
446 239841 : q_MaxAbsVal = q_sampleAbsVal;
447 239841 : move16();
448 239841 : MaxAbsValIdx = j;
449 239841 : move16();
450 : }
451 :
452 30559040 : IF( GT_16( j, offset ) )
453 : {
454 18293406 : IF( EQ_16( BASOP_Util_Cmp_Mant32Exp_sat( sampleAbsVal, sub( Q31, q_sampleAbsVal ), predMaxAbsVal, sub( Q31, q_predMaxAbsVal ) ), 1 ) )
455 : {
456 802497 : predMaxAbsVal = sampleAbsVal; /* q_sampleAbsVal */
457 802497 : move32();
458 802497 : q_predMaxAbsVal = q_sampleAbsVal;
459 802497 : move16();
460 : }
461 : }
462 :
463 30559040 : ppPcm_out[i][j] = Mpy_32_32( ppPcm_in[i][j], pState->gain_state[i].lastGain_fx ); /* q_ppPcm + State->gain_state[i].q_lastGain_fx - 31 */
464 30559040 : move32();
465 30559040 : q_pcm = add( q_ppPcm[i], sub( pState->gain_state[i].q_lastGain_fx, Q31 ) );
466 30559040 : IF( !isClipped )
467 : {
468 30482657 : Word16 comp_flag_1 = 0;
469 30482657 : move16();
470 30482657 : comp_flag_1 = BASOP_Util_Cmp_Mant32Exp_sat( ppPcm_in[i][j], sub( Q31, q_pcm ), ONE_MINUS_M_DELTA_PROD_FLT_FC, Q16 );
471 30482657 : IF( EQ_16( comp_flag_1, 1 ) )
472 : {
473 175 : comp_flag_1 = 1;
474 175 : move16();
475 : }
476 : ELSE
477 : {
478 30482482 : comp_flag_1 = 0;
479 30482482 : move16();
480 : }
481 30482657 : Word16 comp_flag_2 = BASOP_Util_Cmp_Mant32Exp_sat( MIN16B_FLT_FX_IN_Q15, Q16, ppPcm_in[i][j], sub( Q31, q_pcm ) );
482 30482657 : IF( EQ_16( comp_flag_2, 1 ) )
483 : {
484 132 : comp_flag_2 = 1;
485 132 : move16();
486 : }
487 : ELSE
488 : {
489 30482525 : comp_flag_2 = 0;
490 30482525 : move16();
491 : }
492 30482657 : test();
493 30482657 : IF( ( comp_flag_1 ) || ( comp_flag_2 ) )
494 : {
495 307 : clippedIdx = j;
496 307 : move16();
497 307 : isClipped = TRUE;
498 307 : move16();
499 : }
500 : }
501 : }
502 :
503 42018 : pState->gain_state[i].MaxAbsVal_del_fx = predMaxAbsVal; /* q_predMaxAbsVal */
504 42018 : move32();
505 42018 : pState->gain_state[i].q_MaxAbsVal_del_fx = q_predMaxAbsVal;
506 42018 : move16();
507 :
508 42018 : isGainAdjusted = FALSE;
509 42018 : move16();
510 42018 : IF( !isClipped )
511 : {
512 : // CHECK THIS PART AGAIN MaxAbsVal < FLT_MIN
513 41711 : Word16 flag = 0;
514 41711 : move16();
515 41711 : if ( MaxAbsVal <= 0 )
516 : {
517 29 : flag = 1;
518 29 : move16();
519 : }
520 41711 : test();
521 41711 : IF( ( pState->gain_state[i].lastExp == 0 ) || ( flag ) )
522 : {
523 36630 : pState->gain_state[i].gainExpVal = 0;
524 36630 : move16();
525 36630 : pState->gain_state[i].prevExp = pState->gain_state[i].lastExp;
526 36630 : move16();
527 36630 : isGainAdjusted = TRUE;
528 36630 : move16();
529 : }
530 : ELSE
531 : {
532 : Word32 smoothedMaxAbsVal, maxGain;
533 : Word16 q_smoothedMaxAbsVal, q_maxGain;
534 : Word32 temp1, temp2;
535 5081 : Word16 Comp_flag, q_temp, e_result = 0;
536 5081 : temp1 = Mpy_32_32( pState->smFact_fx, MaxAbsVal ); // q_MaxAbsVal
537 5081 : temp2 = Mpy_32_32( ( L_sub( ONE_IN_Q31, pState->smFact_fx ) ), pState->gain_state[i].lastMaxAbs_fx ); // q_lastMaxAbs_fx
538 :
539 5081 : smoothedMaxAbsVal = BASOP_Util_Add_Mant32Exp( temp1, sub( Q31, q_MaxAbsVal ), temp2, sub( Q31, pState->gain_state[i].q_lastMaxAbs_fx ), &e_result ); /* exp(e_result) */
540 5081 : q_smoothedMaxAbsVal = sub( Q31, e_result );
541 :
542 5081 : pState->gain_state[i].lastMaxAbs_fx = smoothedMaxAbsVal; /* q_smoothedMaxAbsVal */
543 5081 : move32();
544 5081 : pState->gain_state[i].q_lastMaxAbs_fx = q_smoothedMaxAbsVal;
545 5081 : move16();
546 :
547 5081 : Comp_flag = BASOP_Util_Cmp_Mant32Exp_sat( smoothedMaxAbsVal, sub( Q31, q_smoothedMaxAbsVal ), MaxAbsVal, sub( Q31, q_MaxAbsVal ) );
548 5081 : IF( EQ_16( Comp_flag, 1 ) )
549 : {
550 3724 : temp1 = smoothedMaxAbsVal; /* q_smoothedMaxAbsVal */
551 3724 : move32();
552 3724 : q_temp = q_smoothedMaxAbsVal;
553 3724 : move16();
554 : }
555 : ELSE
556 : {
557 1357 : temp1 = MaxAbsVal;
558 1357 : move32();
559 1357 : q_temp = q_MaxAbsVal;
560 1357 : move16();
561 : }
562 5081 : temp1 = Mpy_32_32( temp1, TWO_IN_Q29 ); /* q_temp + 29 - 31 */
563 5081 : q_temp = add( q_temp, Q29 - Q31 );
564 5081 : maxGain = Mpy_32_32( temp1, pState->gain_state[i].lastGain_fx ); /* q_temp + pState->gain_state[i].q_lastGain_fx - 31 */
565 5081 : q_maxGain = add( q_temp, sub( pState->gain_state[i].q_lastGain_fx, Q31 ) );
566 :
567 5081 : temp2 = ONE_MINUS_M_DELTA_PROD_FLT_FC; // Q15
568 5081 : move16();
569 5081 : Comp_flag = BASOP_Util_Cmp_Mant32Exp_sat( temp2, Q16, maxGain, sub( Q31, q_maxGain ) );
570 5081 : IF( EQ_16( Comp_flag, 1 ) )
571 : {
572 282 : pState->gain_state[i].gainExpVal = -1;
573 282 : move16();
574 : }
575 : ELSE
576 : {
577 4799 : pState->gain_state[i].gainExpVal = 0;
578 4799 : move16();
579 : }
580 : }
581 : }
582 : ELSE
583 : {
584 307 : pState->gain_state[i].lastMaxAbs_fx = MaxAbsVal; /* q_MaxAbsVal */
585 307 : move32();
586 307 : pState->gain_state[i].q_lastMaxAbs_fx = q_MaxAbsVal;
587 307 : move16();
588 : }
589 :
590 42018 : IF( !isGainAdjusted )
591 : {
592 5388 : Word32 actualMaxAbsVal = 0;
593 5388 : move16();
594 : Word16 currMaxAttExp, q_actualMaxAbsVal;
595 :
596 5388 : currMaxAttExp = s_min( ( add( pState->gain_state[i].lastExp, pState->agc_com.absEmin ) ), pState->agc_com.maxAttExp );
597 5388 : extendedExpVal = FALSE;
598 5388 : move16();
599 :
600 5388 : IF( isClipped )
601 : {
602 307 : Word16 isCompensated = FALSE;
603 : Word32 temp1, temp2;
604 307 : actualMaxAbsVal = Mpy_32_32( pState->gain_state[i].lastMaxAbs_fx, pState->gain_state[i].lastGain_fx ); // QlastGain_fx
605 307 : q_actualMaxAbsVal = add( pState->gain_state[i].q_lastMaxAbs_fx, sub( pState->gain_state[i].q_lastGain_fx, Q31 ) );
606 307 : idx = s_min( sub( offset, 1 ), MaxAbsValIdx ); /* Q0 */
607 :
608 307 : q_actualMaxAbsVal = add( q_actualMaxAbsVal, norm_l( actualMaxAbsVal ) );
609 307 : temp1 = L_shl( actualMaxAbsVal, norm_l( actualMaxAbsVal ) );
610 307 : temp1 = BASOP_Util_Log2( temp1 ); // Q25
611 307 : temp1 = L_add( temp1, L_shl( sub( Q31, q_actualMaxAbsVal ), 25 ) ); // Q25
612 307 : temp1 = L_negate( L_add( temp1, LOG2_MDFT_NORM_SCALING_FX ) ); // Q25
613 307 : temp2 = BASOP_Util_Log2( L_deposit_h( pState->agc_com.winFunc_fx[idx] ) ); // Q25
614 : Word16 temp_16, div_e;
615 307 : IF( temp2 == 0 )
616 : {
617 0 : temp_16 = 0;
618 0 : move16();
619 : }
620 : ELSE
621 : {
622 307 : temp_16 = BASOP_Util_Divide3232_Scale( temp1, temp2, &div_e ); /* exp(div_e) */
623 307 : IF( div_e < 0 )
624 : {
625 248 : temp_16 = shr( temp_16, abs_s( div_e ) );
626 248 : div_e = 0;
627 248 : move16();
628 : }
629 307 : temp_16 = ceil_fx( temp_16, sub( Q15, div_e ) ); /* Q0 */
630 : }
631 307 : pState->gain_state[i].gainExpVal = temp_16; /* Q0 */
632 307 : move16();
633 :
634 614 : WHILE( !isCompensated )
635 : {
636 : Word32 tmpSignal;
637 : Word16 q_tmpSignal;
638 307 : isCompensated = TRUE;
639 307 : Word16 tmp_1, q_tmp_2 = 31, e_div;
640 307 : move16();
641 307 : Word32 tmp_2 = ONE_IN_Q31;
642 307 : move16();
643 307 : tmp_1 = pState->gain_state[i].gainExpVal; /* Q0 */
644 307 : move16();
645 5096 : FOR( idx = clippedIdx; idx <= MaxAbsValIdx; idx++ )
646 : {
647 4789 : IF( GE_16( idx, offset ) )
648 : {
649 282 : idx = MaxAbsValIdx;
650 282 : move16();
651 282 : IF( tmp_1 < 0 )
652 : {
653 0 : tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[offset - 1], ( negate( tmp_1 ) ) ); /* Q31 */
654 0 : IF( tmp_2 < 0 )
655 : {
656 0 : tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, L_negate( tmp_2 ), &e_div ) ); /* exp(e_div) */
657 0 : tmp_2 = L_negate( tmp_2 );
658 : }
659 : ELSE
660 : {
661 0 : tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, tmp_2, &e_div ) ); /* exp(e_div) */
662 : }
663 0 : q_tmp_2 = sub( Q31, e_div );
664 : }
665 : ELSE
666 : {
667 282 : tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[offset - 1], tmp_1 ); /* Q31 */
668 282 : q_tmp_2 = Q31;
669 282 : move16();
670 : }
671 : }
672 : ELSE
673 : {
674 4507 : IF( tmp_1 < 0 )
675 : {
676 0 : tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[idx], ( negate( tmp_1 ) ) ); /* Q31 */
677 0 : IF( tmp_2 < 0 )
678 : {
679 0 : tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, L_negate( tmp_2 ), &e_div ) ); /* exp(e_div) */
680 0 : tmp_2 = L_negate( tmp_2 );
681 : }
682 : ELSE
683 : {
684 0 : tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, tmp_2, &e_div ) ); /* exp(e_div) */
685 : }
686 0 : q_tmp_2 = sub( Q31, e_div );
687 : }
688 : ELSE
689 : {
690 4507 : tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[idx], tmp_1 );
691 4507 : q_tmp_2 = Q31;
692 4507 : move16();
693 : }
694 : }
695 :
696 4789 : tmpSignal = Mpy_32_32( ppPcm_out[i][idx], tmp_2 ); /* q_pcm + q_tmp_2 - 31 */
697 4789 : q_tmpSignal = add( q_pcm, sub( q_tmp_2, 31 ) );
698 :
699 4789 : Word16 comp_flag_1 = BASOP_Util_Cmp_Mant32Exp_sat( tmpSignal, sub( Q31, q_tmpSignal ), ONE_MINUS_M_DELTA_PROD_FLT_FC, Q16 );
700 4789 : IF( EQ_16( comp_flag_1, 1 ) )
701 : {
702 0 : comp_flag_1 = 1;
703 0 : move16();
704 : }
705 : ELSE
706 : {
707 4789 : comp_flag_1 = 0;
708 4789 : move16();
709 : }
710 :
711 4789 : Word16 comp_flag_2 = BASOP_Util_Cmp_Mant32Exp_sat( MIN16B_FLT_FX_IN_Q15, Q16, tmpSignal, sub( Q31, q_tmpSignal ) );
712 4789 : IF( EQ_16( comp_flag_2, 1 ) )
713 : {
714 0 : comp_flag_2 = 1;
715 0 : move16();
716 : }
717 : ELSE
718 : {
719 4789 : comp_flag_2 = 0;
720 4789 : move16();
721 : }
722 4789 : test();
723 4789 : IF( ( comp_flag_1 ) || ( comp_flag_2 ) )
724 : {
725 0 : isCompensated = FALSE;
726 0 : move16();
727 0 : BREAK;
728 : }
729 : }
730 307 : IF( !isCompensated )
731 : {
732 0 : pState->gain_state[i].gainExpVal = add( pState->gain_state[i].gainExpVal, 1 ); /* Q0 */
733 0 : move16();
734 : }
735 :
736 307 : IF( GT_16( pState->gain_state[i].gainExpVal, currMaxAttExp ) )
737 : {
738 0 : pState->gain_state[i].gainExpVal = s_min( pState->gain_state[i].gainExpVal, currMaxAttExp ); /* Q0 */
739 0 : move16();
740 0 : BREAK;
741 : }
742 : }
743 : }
744 :
745 5388 : Word16 q_pcm_tmp = q_pcm;
746 3462028 : FOR( idx = 0; idx < input_frame; idx++ )
747 : {
748 : Word16 tmp_1, q_tmp_2, e_div;
749 : Word32 tmp_2;
750 3456640 : tmp_1 = pState->gain_state[i].gainExpVal; /* Q0 */
751 3456640 : move16();
752 :
753 3456640 : IF( GT_16( offset, idx ) )
754 : {
755 1382656 : IF( tmp_1 < 0 )
756 : {
757 72960 : tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[idx], ( negate( tmp_1 ) ) );
758 72960 : IF( tmp_2 < 0 )
759 : {
760 0 : tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, L_negate( tmp_2 ), &e_div ) ); /* exp(e_div) */
761 0 : tmp_2 = L_negate( tmp_2 );
762 : }
763 : ELSE
764 : {
765 72960 : tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, tmp_2, &e_div ) ); /* exp(e_div) */
766 : }
767 72960 : q_tmp_2 = sub( Q31, e_div );
768 : }
769 : ELSE
770 : {
771 1309696 : tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[idx], tmp_1 ); /* Q31 */
772 1309696 : q_tmp_2 = Q31;
773 1309696 : move16();
774 : }
775 : }
776 : ELSE
777 : {
778 2073984 : IF( tmp_1 < 0 )
779 : {
780 109440 : tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[offset - 1], ( negate( tmp_1 ) ) ); /* Q31 */
781 109440 : IF( tmp_2 < 0 )
782 : {
783 0 : tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, L_negate( tmp_2 ), &e_div ) ); /* exp(e_div) */
784 0 : tmp_2 = L_negate( tmp_2 );
785 : }
786 : ELSE
787 : {
788 109440 : tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, tmp_2, &e_div ) ); /* exp(e_div) */
789 : }
790 109440 : q_tmp_2 = sub( Q31, e_div );
791 : }
792 : ELSE
793 : {
794 1964544 : tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[offset - 1], tmp_1 ); /* Q31 */
795 1964544 : q_tmp_2 = Q31;
796 1964544 : move16();
797 : }
798 : }
799 : // gain = tmp_2;
800 3456640 : ppPcm_out[i][idx] = Mpy_32_32( ppPcm_out[i][idx], tmp_2 ); // Q remains same
801 3456640 : move32();
802 3456640 : q_pcm = add( q_pcm_tmp, sub( q_tmp_2, Q31 ) );
803 : }
804 :
805 :
806 : Word16 tmp_1, q_tmp_2, e_div;
807 : Word32 tmp_2;
808 5388 : tmp_1 = pState->gain_state[i].gainExpVal; /* Q0 */
809 5388 : move16();
810 5388 : IF( tmp_1 < 0 )
811 : {
812 282 : tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[offset - 1], ( negate( tmp_1 ) ) ); /* Q31 */
813 282 : IF( tmp_2 < 0 )
814 : {
815 0 : tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, L_negate( tmp_2 ), &e_div ) ); /* exp(e_div) */
816 0 : tmp_2 = L_negate( tmp_2 );
817 : }
818 : ELSE
819 : {
820 282 : tmp_2 = L_deposit_h( BASOP_Util_Divide3232_Scale( ONE_IN_Q31, tmp_2, &e_div ) ); /* exp(e_div) */
821 : }
822 282 : q_tmp_2 = sub( Q31, e_div );
823 : }
824 : ELSE
825 : {
826 5106 : tmp_2 = pow32_fx( pState->agc_com.winFunc_fx[offset - 1], tmp_1 ); /* Q31 */
827 5106 : q_tmp_2 = Q31;
828 5106 : move16();
829 : }
830 5388 : pState->gain_state[i].lastGain_fx = Mpy_32_32( pState->gain_state[i].lastGain_fx, tmp_2 ); /* pState->gain_state[i].q_lastGain_fx + q_tmp_2 - 31 */
831 5388 : move32();
832 5388 : pState->gain_state[i].q_lastGain_fx = add( pState->gain_state[i].q_lastGain_fx, sub( q_tmp_2, Q31 ) );
833 5388 : move16();
834 :
835 : /*safety check starts*/
836 5388 : if ( EQ_16( pState->gain_state[i].gainExpVal, add( pState->agc_com.maxAttExp, 1 ) ) )
837 : {
838 0 : extendedExpVal = TRUE;
839 0 : move16();
840 : }
841 : /*safety check ends*/
842 :
843 5388 : pState->gain_state[i].prevExp = pState->gain_state[i].lastExp;
844 5388 : move16();
845 :
846 5388 : pState->gain_state[i].lastExp = sub( pState->gain_state[i].lastExp, pState->gain_state[i].gainExpVal );
847 5388 : move16();
848 5388 : if ( extendedExpVal )
849 : {
850 0 : pState->gain_state[i].gainExpVal = -1;
851 0 : move16();
852 : }
853 : }
854 :
855 42018 : pState->gain_data[i].absGainExp = add( pState->gain_state[i].prevExp, pState->agc_com.absEmin );
856 42018 : move16();
857 :
858 42018 : IF( extendedExpVal )
859 : {
860 0 : IF( pState->gain_state[i].gainExpVal <= 0 )
861 : {
862 0 : pState->gain_state[i].gainExpVal = add( pState->agc_com.maxAttExp, 1 ); /* Q0 */
863 0 : move16();
864 : }
865 : }
866 42018 : pState->gain_data[i].absGainExpCurr = sub( pState->gain_data[i].absGainExp, pState->gain_state[i].gainExpVal ); /* Q0 */
867 42018 : move16();
868 :
869 42018 : test();
870 42018 : IF( GT_16( pState->gain_data[i].absGainExpCurr, pState->agc_com.absEmin ) || ( pState->gain_data[i].absGainExpCurr < 0 ) )
871 : {
872 0 : assert( 0 );
873 : }
874 :
875 42018 : IF( EQ_16( pState->gain_data[i].absGainExpCurr, pState->agc_com.absEmin ) )
876 : {
877 36737 : per_ch_bit[i] = 0;
878 36737 : move16();
879 : }
880 : ELSE
881 : {
882 5281 : per_ch_bit[i] = 1;
883 5281 : move16();
884 5281 : AGC_flag = 1;
885 5281 : move16();
886 : }
887 42018 : q_ppPcm[i] = q_pcm;
888 42018 : move16();
889 : }
890 :
891 42018 : push_next_indice( hMetaData, AGC_flag, 1 );
892 : /* encode AGC parameters */
893 42018 : IF( EQ_16( AGC_flag, 1 ) )
894 : {
895 5281 : IF( GT_16( n_channels, 1 ) )
896 : {
897 0 : FOR( i = 0; i < n_channels; i++ )
898 : {
899 0 : push_next_indice( hMetaData, per_ch_bit[i], 1 );
900 : }
901 : }
902 5281 : assert( AGC_BITS_PER_CH == ( pState->agc_com.betaE + 1 ) );
903 :
904 10562 : FOR( i = 0; i < n_channels; i++ )
905 : {
906 5281 : IF( EQ_16( per_ch_bit[i], 1 ) )
907 : {
908 5281 : push_next_indice( hMetaData, (UWord16) pState->gain_data[i].absGainExpCurr, (Word16) pState->agc_com.betaE );
909 : }
910 : }
911 : }
912 :
913 42018 : return;
914 : }
|