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