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 : /* Double check cost function calculation */
34 :
35 : #include <stdlib.h>
36 : #include "options.h"
37 : #include <math.h>
38 : #include "prot_fx.h"
39 : #include "isar_lcld_prot.h"
40 : #include "isar_rom_lcld_tables.h"
41 : #include "wmc_auto.h"
42 : #include "prot_fx.h"
43 : #include "basop_util.h"
44 : #include "enh64.h"
45 :
46 :
47 : /*-------------------------------------------------------------------*
48 : * Local ROM tables
49 : *
50 : *
51 : *-------------------------------------------------------------------*/
52 :
53 : Word32 Inv_grp_length[17] = {
54 : // Q31
55 : 0,
56 : 2147483647,
57 : 1073741823,
58 : 715827882,
59 : 536870911,
60 : 429496729,
61 : 357913941,
62 : 306783378,
63 : 268435455,
64 : 238609294,
65 : 214748364,
66 : 195225786,
67 : 178956970,
68 : 165191049,
69 : 153391689,
70 : 143165576,
71 : 134217727,
72 :
73 : };
74 :
75 : static const Word32 c_afThreshQuiet48_fx[23] = {
76 : // Q23
77 : -705191424,
78 : -705191424,
79 : -705191424,
80 : -705191424,
81 : -705191424,
82 : -705191424,
83 : -705191424,
84 : -705191424,
85 : -703021824,
86 : -694920256,
87 : -685375488,
88 : -662531840,
89 : -646432768,
90 : -636262784,
91 : -627448000,
92 : -618652544,
93 : -598245120,
94 : -575579520,
95 : -550540736,
96 : -508787360,
97 : -264583456,
98 : -161516096,
99 : -158042848,
100 : };
101 : static const Word32 c_fiDefaultTheta48_fx[MAX_BANDS_48] = {
102 : // Q31
103 : 939524096,
104 : 939524096,
105 : 805306368,
106 : 671088640,
107 : 671088640,
108 : 536870912,
109 : 536870912,
110 : 536870912,
111 : 536870912,
112 : 536870912,
113 : 536870912,
114 : 536870912,
115 : 536870912,
116 : 536870912,
117 : 536870912,
118 : 536870912,
119 : 536870912,
120 : 536870912,
121 : 536870912,
122 : 536870912,
123 : 536870912,
124 : 536870912,
125 : 536870912,
126 : };
127 : typedef struct GMNODE
128 : {
129 : Word32 iGroupStart;
130 : Word32 iGroupLength;
131 : Word32 *pfMergedEnergydB_fx;
132 : Word32 *piQRMSEnvelope;
133 :
134 : Word32 iGroupRMSEnvelopeCost;
135 : Word32 fGroupSNRPenalty_fx;
136 : Word16 fGroupSNRPenalty_exp;
137 : struct GMNODE *psNext;
138 : } GMNode;
139 :
140 : struct RMS_ENVELOPE_GROUPING
141 : {
142 : Word32 iNumBlocks;
143 : Word32 iMaxGroups;
144 : Word32 **ppfWeight_man;
145 : Word16 **ppfWeight_exp;
146 : Word32 **ppfBandEnergy_man;
147 : Word16 **ppfBandEnergy_exp;
148 : Word32 **ppfBandEnergydB_fx;
149 : // Word32 **ppfWeight_fx;
150 : GMNode *psGMNodes;
151 : };
152 :
153 :
154 : /*-------------------------------------------------------------------*
155 : * Function CreateRMSEnvelopeGrouping()
156 : *
157 : *
158 : *-------------------------------------------------------------------*/
159 :
160 0 : RMSEnvelopeGrouping *CreateRMSEnvelopeGrouping(
161 : const Word32 iNumBlocks )
162 : {
163 : Word32 n;
164 :
165 : RMSEnvelopeGrouping *psRMSEnvelopeGrouping;
166 :
167 0 : psRMSEnvelopeGrouping = (RMSEnvelopeGrouping *) malloc( sizeof( RMSEnvelopeGrouping ) );
168 0 : psRMSEnvelopeGrouping->iNumBlocks = iNumBlocks;
169 :
170 0 : psRMSEnvelopeGrouping->iMaxGroups = iNumBlocks >> 1;
171 0 : psRMSEnvelopeGrouping->ppfBandEnergy_man = (Word32 **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( Word32 * ) );
172 0 : psRMSEnvelopeGrouping->ppfBandEnergy_exp = (Word16 **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( Word16 * ) );
173 0 : psRMSEnvelopeGrouping->ppfBandEnergydB_fx = (Word32 **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( Word32 * ) );
174 0 : psRMSEnvelopeGrouping->ppfWeight_man = (Word32 **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( Word32 * ) );
175 0 : psRMSEnvelopeGrouping->ppfWeight_exp = (Word16 **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( Word16 * ) );
176 :
177 0 : FOR( n = 0; n < psRMSEnvelopeGrouping->iNumBlocks; n++ )
178 : {
179 0 : psRMSEnvelopeGrouping->ppfBandEnergy_man[n] = (Word32 *) malloc( MAX_BANDS * 2 * sizeof( Word32 ) ); /* 2 for stereo joint group calc */
180 0 : psRMSEnvelopeGrouping->ppfBandEnergy_exp[n] = (Word16 *) malloc( MAX_BANDS * 2 * sizeof( Word16 ) ); /* 2 for stereo joint group calc */
181 0 : psRMSEnvelopeGrouping->ppfBandEnergydB_fx[n] = (Word32 *) malloc( MAX_BANDS * 2 * sizeof( Word32 ) );
182 0 : psRMSEnvelopeGrouping->ppfWeight_man[n] = (Word32 *) malloc( MAX_BANDS * 2 * sizeof( Word32 ) );
183 0 : psRMSEnvelopeGrouping->ppfWeight_exp[n] = (Word16 *) malloc( MAX_BANDS * 2 * sizeof( Word16 ) );
184 : }
185 :
186 0 : psRMSEnvelopeGrouping->psGMNodes = (GMNode *) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( GMNode ) );
187 :
188 0 : for ( n = 0; n < psRMSEnvelopeGrouping->iNumBlocks; n++ )
189 : {
190 0 : psRMSEnvelopeGrouping->psGMNodes[n].pfMergedEnergydB_fx = (Word32 *) malloc( MAX_BANDS * 2 * sizeof( Word32 ) );
191 0 : psRMSEnvelopeGrouping->psGMNodes[n].piQRMSEnvelope = (Word32 *) malloc( MAX_BANDS * 2 * sizeof( Word32 ) );
192 0 : psRMSEnvelopeGrouping->psGMNodes[n].iGroupRMSEnvelopeCost = -1;
193 0 : psRMSEnvelopeGrouping->psGMNodes[n].fGroupSNRPenalty_fx = L_negate( ONE_IN_Q30 );
194 0 : psRMSEnvelopeGrouping->psGMNodes[n].fGroupSNRPenalty_exp = 1;
195 : }
196 :
197 0 : return psRMSEnvelopeGrouping;
198 : }
199 :
200 :
201 : /*-------------------------------------------------------------------*
202 : * Function DeleteRMSEnvelopeGrouping()
203 : *
204 : *
205 : *-------------------------------------------------------------------*/
206 :
207 0 : void DeleteRMSEnvelopeGrouping(
208 : RMSEnvelopeGrouping *psRMSEnvelopeGrouping )
209 : {
210 : Word32 n;
211 :
212 0 : FOR( n = 0; n < psRMSEnvelopeGrouping->iNumBlocks; n++ )
213 : {
214 0 : free( psRMSEnvelopeGrouping->ppfBandEnergy_man[n] );
215 0 : free( psRMSEnvelopeGrouping->ppfBandEnergy_exp[n] );
216 0 : free( psRMSEnvelopeGrouping->ppfBandEnergydB_fx[n] );
217 0 : free( psRMSEnvelopeGrouping->ppfWeight_man[n] );
218 0 : free( psRMSEnvelopeGrouping->ppfWeight_exp[n] );
219 : }
220 0 : free( psRMSEnvelopeGrouping->ppfBandEnergy_man );
221 0 : free( psRMSEnvelopeGrouping->ppfBandEnergy_exp );
222 0 : free( psRMSEnvelopeGrouping->ppfBandEnergydB_fx );
223 0 : free( psRMSEnvelopeGrouping->ppfWeight_man );
224 0 : free( psRMSEnvelopeGrouping->ppfWeight_exp );
225 :
226 0 : FOR( n = 0; n < psRMSEnvelopeGrouping->iNumBlocks; n++ )
227 : {
228 0 : free( psRMSEnvelopeGrouping->psGMNodes[n].pfMergedEnergydB_fx );
229 0 : free( psRMSEnvelopeGrouping->psGMNodes[n].piQRMSEnvelope );
230 : }
231 0 : free( psRMSEnvelopeGrouping->psGMNodes );
232 :
233 0 : free( psRMSEnvelopeGrouping );
234 :
235 0 : return;
236 : }
237 :
238 :
239 : /*-------------------------------------------------------------------*
240 : * Function ComputeBandEnergy()
241 : *
242 : *
243 : *-------------------------------------------------------------------*/
244 :
245 0 : static void ComputeBandEnergy(
246 : const Word32 iChannels,
247 : const Word32 iNumBlocks,
248 : const Word32 iNumBands,
249 : const Word32 *piBandwidths,
250 : Word32 ***pppfReal_fx,
251 : Word32 ***pppfImag_fx,
252 : Word32 **ppfBandEnergy_man,
253 : Word16 **ppfBandEnergy_exp,
254 : Word32 **ppfBandEnergydB_fx,
255 : Word32 **ppfWeight_man,
256 : Word16 **ppfWeight_exp,
257 : Word16 q_final )
258 : {
259 : Word32 n;
260 0 : Word32 constant = 1616142483; // Q29 of(1/log2(10))*10
261 : Word32 const_comp3, const_comp1;
262 0 : Word16 exp3 = 0, exp1 = 0, Flag1, Flag2, Flag3;
263 : Word16 div_exp;
264 : /*For 0.33f*/
265 0 : const_comp3 = 1417339264;
266 0 : move32();
267 0 : exp3 = -1;
268 0 : move16();
269 : // f2me( 0.33, &const_comp3, &exp3 );//
270 : // f2me( 1.0, &const_comp1, &exp1 );//
271 : /*For 1.0f*/
272 : Word32 mul_32;
273 : Word16 mul_exp;
274 0 : const_comp1 = 1073741824;
275 0 : move32();
276 0 : exp1 = 1;
277 0 : move16();
278 0 : FOR( n = 0; n < iChannels; n++ )
279 : {
280 : Word32 k;
281 : Word32 iChanOffset;
282 :
283 0 : iChanOffset = L_mult0( extract_l( n ), extract_l( iNumBands ) );
284 0 : FOR( k = 0; k < iNumBlocks; k++ )
285 : {
286 : Word32 b;
287 : Word32 iFBOffset;
288 0 : Word32 fMaxWeight_fx = 0;
289 0 : move32();
290 0 : Word16 fMaxWeight_exp = 0;
291 0 : move16();
292 0 : iFBOffset = 0;
293 0 : move32();
294 0 : FOR( b = 0; b < iNumBands; b++ )
295 : {
296 : Word32 m;
297 : Word16 fEnergy_exp;
298 : Word32 fEnergy_fx, fWeight_temp;
299 : Word16 shift_value;
300 : Word32 fEnergy_log_fx, fEnergy_log_fx1;
301 0 : fEnergy_exp = 0;
302 0 : move16();
303 : /*For 1e-12f in Q63*/
304 : Word32 fWeight_fx;
305 : Word64 Wmult_value;
306 0 : Word16 exp_pow = 0;
307 0 : move16();
308 0 : Word16 guard_bits = find_guarded_bits_fx( piBandwidths[b] + 1 );
309 : // fEnergy_f64 = W_shr( fEnergy_f64, ( 63 - ( 2 * ( q_final - guard_bits ) + 1 ) ) );
310 0 : fEnergy_fx = 1180591616;
311 0 : fEnergy_exp = -39;
312 0 : FOR( m = 0; m < piBandwidths[b]; m++ )
313 : {
314 0 : Wmult_value = W_add( W_mult_32_32( L_shr( pppfReal_fx[n][k][iFBOffset], guard_bits ), L_shr( pppfReal_fx[n][k][iFBOffset], guard_bits ) ), W_mult_32_32( L_shr( pppfImag_fx[n][k][iFBOffset], guard_bits ), L_shr( pppfImag_fx[n][k][iFBOffset], guard_bits ) ) );
315 0 : shift_value = W_norm( Wmult_value );
316 0 : mul_32 = W_extract_h( W_shl( Wmult_value, shift_value ) );
317 0 : mul_exp = 31 - ( 2 * ( q_final - guard_bits ) + 1 + shift_value - 32 );
318 0 : fEnergy_fx = BASOP_Util_Add_Mant32Exp( fEnergy_fx, fEnergy_exp, mul_32, mul_exp, &fEnergy_exp ); // Some large number to prevent clipping
319 0 : iFBOffset++;
320 : }
321 0 : IF( EQ_32( fEnergy_fx, 0 ) )
322 : {
323 : // f2me( 1e-12f, &fEnergy_fx, &fEnergy_exp ); //
324 0 : fEnergy_fx = 1180591616;
325 0 : fEnergy_exp = -39;
326 0 : fEnergy_fx = Mpy_32_32( fEnergy_fx, Inv_grp_length[piBandwidths[b]] ); // Correction removed normalization by 2
327 0 : ppfBandEnergy_man[k][iChanOffset + b] = fEnergy_fx;
328 0 : move32();
329 0 : ppfBandEnergy_exp[k][iChanOffset + b] = fEnergy_exp;
330 0 : move16();
331 0 : fEnergy_fx = Mpy_32_32( fEnergy_fx, Inv_grp_length[piBandwidths[b]] ); // Correction removed normalization by 2
332 0 : ppfBandEnergy_man[k][iChanOffset + b] = fEnergy_fx;
333 0 : move32();
334 0 : ppfBandEnergy_exp[k][iChanOffset + b] = fEnergy_exp;
335 0 : move16();
336 0 : fEnergy_log_fx1 = -1006632960; // Q23
337 0 : fWeight_fx = 403727488; // Q31
338 0 : exp_pow = 0;
339 : }
340 : ELSE
341 : {
342 0 : fEnergy_fx = Mpy_32_32( fEnergy_fx, Inv_grp_length[piBandwidths[b]] ); // Correction removed normalization by 2
343 0 : ppfBandEnergy_man[k][iChanOffset + b] = fEnergy_fx;
344 0 : move32();
345 0 : ppfBandEnergy_exp[k][iChanOffset + b] = fEnergy_exp;
346 0 : move16();
347 0 : fEnergy_fx = BASOP_Util_Log2( fEnergy_fx );
348 0 : move32();
349 0 : fEnergy_log_fx = L_add( fEnergy_fx, L_shl( L_deposit_l( fEnergy_exp ), WORD32_BITS - 1 - LD_DATA_SCALE ) ); /*Q25*/ // log2f( fEnergy )
350 0 : fEnergy_log_fx1 = Mpy_32_32( fEnergy_log_fx, constant );
351 0 : fEnergy_log_fx = L_sub( fEnergy_log_fx1, c_afThreshQuiet48_fx[b] ); // Q23 of ( 10.0f * log10f( fEnergy ) - c_afThreshQuiet48[b] ) )
352 0 : fWeight_fx = Mpy_32_32( 48509336, fEnergy_log_fx ); // 0.0068f*3.3219 in Q31, result in Q23
353 0 : fWeight_temp = BASOP_util_Pow2( fWeight_fx, 8, &exp_pow );
354 0 : fWeight_fx = Mpy_32_32( 708669604, fWeight_temp ); // 708669604 = Q31 0f 0.33
355 : }
356 0 : Flag1 = BASOP_Util_Cmp_Mant32Exp( fWeight_fx, exp_pow, const_comp3, exp3 );
357 0 : IF( NE_16( Flag1, 1 ) )
358 : {
359 0 : fWeight_fx = const_comp3;
360 0 : move32();
361 0 : exp_pow = exp3;
362 0 : move16();
363 : }
364 0 : Flag2 = BASOP_Util_Cmp_Mant32Exp( const_comp1, exp1, fWeight_fx, exp_pow );
365 0 : IF( NE_16( Flag2, 1 ) )
366 : {
367 0 : fWeight_fx = const_comp1;
368 0 : move32();
369 0 : exp_pow = exp1;
370 0 : move16();
371 : }
372 0 : Flag3 = BASOP_Util_Cmp_Mant32Exp( fMaxWeight_fx, fMaxWeight_exp, fWeight_fx, exp_pow );
373 0 : IF( NE_16( Flag3, 1 ) )
374 : {
375 0 : fMaxWeight_fx = fWeight_fx;
376 0 : move32();
377 0 : fMaxWeight_exp = exp_pow;
378 0 : move16();
379 : }
380 : #ifdef APPLY_TEMPORAL_SMOOTHING
381 : if ( k > 0 )
382 : {
383 : float fSmoothEnergy;
384 : fSmoothEnergy = 0.7f * ppfBandEnergy[k - 1][iChanOffset + b] + 0.3f * fEnergy;
385 :
386 : fEnergy = ( fEnergy > fSmoothEnergy ) ? fEnergy : fSmoothEnergy;
387 : }
388 : #endif
389 0 : ppfWeight_man[k][iChanOffset + b] = fWeight_fx;
390 0 : ppfWeight_exp[k][iChanOffset + b] = exp_pow;
391 0 : ppfBandEnergydB_fx[k][iChanOffset + b] = fEnergy_log_fx1; // Q23
392 : }
393 0 : FOR( b = 0; b < iNumBands; b++ )
394 : {
395 0 : ppfWeight_man[k][iChanOffset + b] = L_deposit_h( BASOP_Util_Divide3232_Scale( ppfWeight_man[k][iChanOffset + b], fMaxWeight_fx, &div_exp ) );
396 0 : ppfWeight_exp[k][iChanOffset + b] = div_exp + ppfWeight_exp[k][iChanOffset + b] - fMaxWeight_exp;
397 : }
398 : }
399 : }
400 :
401 0 : return;
402 : }
403 :
404 :
405 : /*-------------------------------------------------------------------*
406 : * Function ComputeMergeRMS()
407 : *
408 : *
409 : *-------------------------------------------------------------------*/
410 :
411 0 : static void ComputeMergeRMS(
412 : const Word32 iNumBands,
413 : const Word32 iStartBlock,
414 : const Word32 iGroupLength,
415 : Word32 *pfMergedEnergydB,
416 : Word32 *piQRMSEnvelope,
417 : Word32 **ppfBandEnergy_man,
418 : Word16 **ppfBandEnergy_exp )
419 : {
420 : Word32 b;
421 0 : Word32 constant = 1616142483; // Q29 of(1/log2(10))*10 // Note epsolon was added when computing BandEnergy;
422 0 : move32();
423 : Word32 fGroupEnergy32_fx;
424 :
425 0 : FOR( b = 0; b < iNumBands; b++ )
426 : {
427 : Word32 n;
428 0 : Word32 fGroupEnergy_fx = 0;
429 0 : move32();
430 0 : Word16 fGroupEnergy_exp = 0;
431 0 : move16();
432 : Word32 fRMSEnvelope_fx;
433 : Word32 iQRMSEnvelope_fx;
434 0 : FOR( n = iStartBlock; n < ( iStartBlock + iGroupLength ); n++ )
435 : {
436 0 : fGroupEnergy_fx = BASOP_Util_Add_Mant32Exp( ppfBandEnergy_man[n][b], ppfBandEnergy_exp[n][b], fGroupEnergy_fx, fGroupEnergy_exp, &fGroupEnergy_exp );
437 : }
438 0 : fGroupEnergy_fx = Mpy_32_32( fGroupEnergy_fx, Inv_grp_length[iGroupLength] ); // Division by iGroupLength
439 0 : move32();
440 0 : IF( NE_32( fGroupEnergy_fx, 0 ) )
441 : {
442 0 : fRMSEnvelope_fx = BASOP_Util_Log2( fGroupEnergy_fx );
443 0 : move32();
444 0 : fRMSEnvelope_fx = L_add( fRMSEnvelope_fx, L_shl( L_deposit_l( fGroupEnergy_exp ), WORD32_BITS - 1 - LD_DATA_SCALE ) ); /*Q25*/
445 : }
446 : ELSE
447 : {
448 0 : fRMSEnvelope_fx = 0;
449 0 : fGroupEnergy_exp = 0;
450 : }
451 0 : iQRMSEnvelope_fx = ( fRMSEnvelope_fx > 0 ) ? L_add( fRMSEnvelope_fx, ONE_IN_Q24 ) : L_negate( L_add( L_negate( fRMSEnvelope_fx ), ONE_IN_Q24 ) );
452 0 : iQRMSEnvelope_fx = L_shr( iQRMSEnvelope_fx, 25 );
453 :
454 0 : fGroupEnergy32_fx = fRMSEnvelope_fx; /*Q25*/ // BASOP_Util_Log2( fGroupEnergy_fx );
455 0 : fGroupEnergy32_fx = Mpy_32_32( fGroupEnergy32_fx, constant ); // Q23
456 0 : pfMergedEnergydB[b] = fGroupEnergy32_fx; // Q23
457 0 : piQRMSEnvelope[b] = iQRMSEnvelope_fx; // Q25
458 : }
459 :
460 0 : return;
461 : }
462 :
463 :
464 : /*-------------------------------------------------------------------*
465 : * Function ComputeRMSEnvelopeBits()
466 : *
467 : *
468 : *-------------------------------------------------------------------*/
469 :
470 0 : static Word32 ComputeRMSEnvelopeBits(
471 : const Word32 iChannels,
472 : const Word32 iNumBands,
473 : const Word32 *piQRMSEnevelope )
474 : {
475 : Word32 n;
476 0 : Word32 iRMSEnvelopeBits = 0;
477 0 : move32();
478 0 : Word32 iChanOffset = 0;
479 0 : move32();
480 :
481 0 : FOR( n = 0; n < iChannels; n++ )
482 : {
483 : Word32 b;
484 : Word32 iLastRMSVal;
485 :
486 0 : iRMSEnvelopeBits = L_add( iRMSEnvelopeBits, ENV0_BITS );
487 0 : iLastRMSVal = piQRMSEnevelope[iChanOffset];
488 0 : move32();
489 0 : FOR( b = 1; b < iNumBands; b++ )
490 : {
491 : Word32 iDelta;
492 :
493 0 : iDelta = L_sub( piQRMSEnevelope[iChanOffset + b], iLastRMSVal );
494 0 : iDelta = ( iDelta > ENV_DELTA_MIN ) ? iDelta : ENV_DELTA_MIN;
495 0 : iDelta = ( iDelta < ENV_DELTA_MAX ) ? iDelta : ENV_DELTA_MAX;
496 0 : iDelta = L_sub( iDelta, ENV_DELTA_MIN );
497 0 : iRMSEnvelopeBits = L_add( iRMSEnvelopeBits, c_aaiRMSEnvHuffEnc[iDelta][0] );
498 :
499 0 : iLastRMSVal = piQRMSEnevelope[iChanOffset + b];
500 0 : move32();
501 : }
502 :
503 0 : iChanOffset = L_add( iChanOffset, iNumBands );
504 : }
505 :
506 0 : return iRMSEnvelopeBits;
507 : }
508 :
509 :
510 : /*-------------------------------------------------------------------*
511 : * Function ComputeSNRPenalty()
512 : *
513 : *
514 : *-------------------------------------------------------------------*/
515 :
516 0 : static Word32 ComputeSNRPenalty(
517 : const Word32 iChannels,
518 : const Word32 iNumBands,
519 : const Word32 *piBandwidths,
520 : const Word32 iStartBlock,
521 : const Word32 iGroupLength,
522 : Word32 **ppfBandEnergy_dB_fx,
523 : const Word32 *piRMSEnvelope,
524 : Word16 *fSNRPenalty_exp )
525 : {
526 : Word32 n;
527 : Word32 iChanOffset;
528 : Word32 temp;
529 0 : Word32 fSNRPenalty_fx = 0;
530 0 : move32();
531 0 : Word32 fSNRPenaltyconst_fx = 0;
532 0 : move32();
533 : Word32 mul_temp;
534 0 : Word16 fSNRPenaltycnst_exp = 0, exp = 0;
535 :
536 0 : fSNRPenaltyconst_fx = 1250000000;
537 0 : fSNRPenaltycnst_exp = 34;
538 0 : iChanOffset = 0;
539 0 : move32();
540 0 : FOR( n = 0; n < iChannels; n++ )
541 : {
542 : Word32 b;
543 0 : FOR( b = 0; b < iNumBands; b++ )
544 : {
545 : Word32 k;
546 : Word32 fRMSVal_fx;
547 : Word32 RMS_value_fx;
548 : // RMS_value = piRMSEnvelope[iChanOffset + b];
549 0 : RMS_value_fx = L_shl( piRMSEnvelope[iChanOffset + b], 25 );
550 0 : move32();
551 : // fRMSVal = 3.0103f * (float) RMS_value;
552 0 : fRMSVal_fx = Mpy_32_32( 1616142506, RMS_value_fx ); // Q23
553 0 : move32();
554 0 : FOR( k = iStartBlock; k < ( iStartBlock + iGroupLength ); k++ )
555 : {
556 : Word32 fDeltadB_fx;
557 0 : fDeltadB_fx = L_sub( fRMSVal_fx, ppfBandEnergy_dB_fx[k][iChanOffset + b] );
558 0 : IF( LT_32( fDeltadB_fx, -75756680 ) )
559 : {
560 0 : fSNRPenalty_fx = BASOP_Util_Add_Mant32Exp( fSNRPenalty_fx, *fSNRPenalty_exp, fSNRPenaltyconst_fx, fSNRPenaltycnst_exp, fSNRPenalty_exp ); // Some large number to prevent clipping
561 : }
562 : ELSE
563 : {
564 0 : mul_temp = L_abs( L_sub( Mpy_32_32( c_fiDefaultTheta48_fx[b], fDeltadB_fx ), fDeltadB_fx ) );
565 0 : temp = Mpy_32_32( mul_temp, Mpy_32_32( 715827883, L_shl( piBandwidths[b], 27 ) ) ); // Q27+23 -31=19
566 0 : exp = Q12; // Q31 - Q19
567 0 : fSNRPenalty_fx = BASOP_Util_Add_Mant32Exp( fSNRPenalty_fx, *fSNRPenalty_exp, temp, exp, fSNRPenalty_exp );
568 : }
569 : }
570 : }
571 :
572 0 : iChanOffset = L_add( iChanOffset, iNumBands );
573 : }
574 :
575 0 : return fSNRPenalty_fx;
576 : }
577 :
578 :
579 : /*-------------------------------------------------------------------*
580 : * Function TryMerge2()
581 : *
582 : *
583 : *-------------------------------------------------------------------*/
584 :
585 0 : static Word32 TryMerge2(
586 : const Word32 iChannels,
587 : const Word32 iNumBands,
588 : const Word32 *piBandwidths,
589 : Word32 **ppfBandEnergy_man,
590 : Word16 **ppfBandEnergy_exp,
591 : Word32 **ppfBandEnergydB_fx,
592 : GMNode *psGMNode1,
593 : GMNode *psGMNode2,
594 : Word16 *fMergedCost_exp )
595 : {
596 : Word32 iRMSEnvBits1;
597 : Word32 iRMSEnvBits2;
598 : Word32 iRMSEnvBitsMerged;
599 0 : Word32 temp = 0;
600 0 : move32();
601 0 : Word16 temp_exp = 0;
602 0 : move16();
603 0 : Word32 fMergedCost_fx = 0;
604 0 : move32();
605 : Word32 RMSEnvBits_fx;
606 : Word32 fSNRPenalty1_fx;
607 : Word32 fSNRPenalty2_fx;
608 : Word32 fSNRPenaltyMerged_fx;
609 0 : Word16 fSNRPenalty1_exp = 0;
610 0 : move16();
611 0 : Word16 fSNRPenalty2_exp = 0;
612 0 : move16();
613 0 : Word16 fSNRPenaltyMerged_exp = 0;
614 0 : move16();
615 0 : Word32 one_in_mant = L_negate( ONE_IN_Q30 );
616 0 : Word16 one_in_exp = 1;
617 0 : move16();
618 0 : *fMergedCost_exp = 0;
619 0 : move16();
620 0 : Word16 flag = 0;
621 0 : move16();
622 :
623 0 : IF( EQ_32( psGMNode1->fGroupSNRPenalty_fx, one_in_mant ) && EQ_16( psGMNode1->fGroupSNRPenalty_exp, one_in_exp ) )
624 : {
625 0 : flag = 1;
626 0 : move16();
627 : }
628 :
629 : /* First compute current RMS Envelope for each group */
630 0 : IF( EQ_32( psGMNode1->iGroupRMSEnvelopeCost, -1 ) || flag )
631 : {
632 0 : ComputeMergeRMS( iNumBands * iChannels, psGMNode1->iGroupStart, psGMNode1->iGroupLength, psGMNode1->pfMergedEnergydB_fx, psGMNode1->piQRMSEnvelope, ppfBandEnergy_man, ppfBandEnergy_exp );
633 0 : iRMSEnvBits1 = ComputeRMSEnvelopeBits( iChannels, iNumBands, psGMNode1->piQRMSEnvelope );
634 0 : fSNRPenalty1_fx = ComputeSNRPenalty( iChannels, iNumBands, piBandwidths, psGMNode1->iGroupStart, psGMNode1->iGroupLength, ppfBandEnergydB_fx, psGMNode1->piQRMSEnvelope, &fSNRPenalty1_exp );
635 0 : psGMNode1->iGroupRMSEnvelopeCost = iRMSEnvBits1;
636 0 : move32();
637 0 : psGMNode1->fGroupSNRPenalty_fx = fSNRPenalty1_fx;
638 0 : move32();
639 0 : psGMNode1->fGroupSNRPenalty_exp = fSNRPenalty1_exp;
640 0 : move16();
641 : }
642 : ELSE
643 : {
644 0 : iRMSEnvBits1 = psGMNode1->iGroupRMSEnvelopeCost;
645 0 : move32();
646 0 : fSNRPenalty1_fx = psGMNode1->fGroupSNRPenalty_fx;
647 0 : move32();
648 0 : fSNRPenalty1_exp = psGMNode1->fGroupSNRPenalty_exp;
649 0 : move16();
650 : }
651 0 : IF( EQ_32( psGMNode2->fGroupSNRPenalty_fx, one_in_mant ) && EQ_16( psGMNode2->fGroupSNRPenalty_exp, one_in_exp ) )
652 : {
653 0 : flag = 1;
654 0 : move16();
655 : }
656 :
657 0 : IF( EQ_32( psGMNode2->iGroupRMSEnvelopeCost, -1 ) || flag )
658 : {
659 :
660 0 : ComputeMergeRMS( iNumBands * iChannels, psGMNode2->iGroupStart, psGMNode2->iGroupLength, psGMNode2->pfMergedEnergydB_fx, psGMNode2->piQRMSEnvelope, ppfBandEnergy_man, ppfBandEnergy_exp );
661 0 : iRMSEnvBits2 = ComputeRMSEnvelopeBits( iChannels, iNumBands, psGMNode2->piQRMSEnvelope );
662 0 : fSNRPenalty2_fx = ComputeSNRPenalty( iChannels, iNumBands, piBandwidths, psGMNode2->iGroupStart, psGMNode2->iGroupLength, ppfBandEnergydB_fx, psGMNode2->piQRMSEnvelope, &fSNRPenalty2_exp );
663 0 : psGMNode2->iGroupRMSEnvelopeCost = iRMSEnvBits2;
664 0 : move32();
665 0 : psGMNode2->fGroupSNRPenalty_fx = fSNRPenalty2_fx;
666 0 : move32();
667 0 : psGMNode2->fGroupSNRPenalty_exp = fSNRPenalty2_exp;
668 0 : move16();
669 : }
670 : ELSE
671 : {
672 0 : iRMSEnvBits2 = psGMNode2->iGroupRMSEnvelopeCost;
673 0 : move32();
674 0 : fSNRPenalty2_fx = psGMNode2->fGroupSNRPenalty_fx;
675 0 : move32();
676 0 : fSNRPenalty2_exp = psGMNode2->fGroupSNRPenalty_exp;
677 0 : move16();
678 : }
679 :
680 0 : ComputeMergeRMS( iNumBands * iChannels, psGMNode1->iGroupStart, psGMNode1->iGroupLength + psGMNode2->iGroupLength, psGMNode1->pfMergedEnergydB_fx, psGMNode1->piQRMSEnvelope, ppfBandEnergy_man, ppfBandEnergy_exp );
681 :
682 : /* Compute the RMS Envelope cost for merged group */
683 0 : iRMSEnvBitsMerged = ComputeRMSEnvelopeBits( iChannels, iNumBands, psGMNode1->piQRMSEnvelope );
684 : // fSNRPenalty_exp = 0;
685 : /* Compute an approximation of the bit cost based on SNR increase/decrease due to merging */
686 0 : fSNRPenaltyMerged_fx = ComputeSNRPenalty( iChannels, iNumBands, piBandwidths, psGMNode1->iGroupStart, psGMNode1->iGroupLength + psGMNode2->iGroupLength, ppfBandEnergydB_fx, psGMNode1->piQRMSEnvelope, &fSNRPenaltyMerged_exp );
687 0 : RMSEnvBits_fx = L_sub( L_sub( iRMSEnvBitsMerged, iRMSEnvBits1 ), iRMSEnvBits2 );
688 0 : RMSEnvBits_fx = L_shl( RMSEnvBits_fx, 10 ); // Converting to Q10
689 0 : temp = BASOP_Util_Add_Mant32Exp( fSNRPenaltyMerged_fx, fSNRPenaltyMerged_exp, L_negate( fSNRPenalty1_fx ), fSNRPenalty1_exp, &temp_exp );
690 0 : fMergedCost_fx = BASOP_Util_Add_Mant32Exp( temp, temp_exp, L_negate( fSNRPenalty2_fx ), fSNRPenalty2_exp, fMergedCost_exp );
691 0 : fMergedCost_fx = BASOP_Util_Add_Mant32Exp( fMergedCost_fx, *fMergedCost_exp, RMSEnvBits_fx, 21, fMergedCost_exp );
692 : // fMergedCost = fSNRPenaltyMerged - fSNRPenalty1 - fSNRPenalty2 + (float) iRMSEnvBitsMerged - (float) iRMSEnvBits1 - (float) iRMSEnvBits2;
693 :
694 0 : return fMergedCost_fx;
695 : }
696 :
697 :
698 : /*-------------------------------------------------------------------*
699 : * Function ComputeGreedyGroups3()
700 : *
701 : *
702 : *-------------------------------------------------------------------*/
703 :
704 0 : static void ComputeGreedyGroups3(
705 : RMSEnvelopeGrouping *psRMSEnvelopeGrouping,
706 : const Word32 iChannels,
707 : const Word32 iNumBands,
708 : const Word32 *piBandwidths,
709 : const Word32 iMaxGroups )
710 : {
711 :
712 0 : Word32 iDone = 0;
713 0 : Word32 iNumGroups = psRMSEnvelopeGrouping->iMaxGroups;
714 0 : WHILE( EQ_32( iDone, 0 ) )
715 : {
716 : GMNode *psGMNode;
717 : GMNode *psBestGMNode;
718 : /* Instead of 1e20f*/
719 0 : Word32 fBestMergeCost_fx = 1455191552; // mantissa of 1e20f
720 0 : move32();
721 0 : Word16 fBestMergeCost_exp = 67; // exp of 1e20f
722 0 : move16();
723 0 : Word16 Flag = 0;
724 0 : move16();
725 0 : psGMNode = &psRMSEnvelopeGrouping->psGMNodes[0];
726 0 : psBestGMNode = NULL;
727 0 : WHILE( psGMNode->psNext != NULL )
728 : {
729 0 : Word32 fMergeCost_fx = 0;
730 0 : move32();
731 0 : Word16 fMergeCost_exp = 0;
732 0 : move16();
733 0 : fMergeCost_fx = TryMerge2( iChannels, iNumBands, piBandwidths, psRMSEnvelopeGrouping->ppfBandEnergy_man, psRMSEnvelopeGrouping->ppfBandEnergy_exp, psRMSEnvelopeGrouping->ppfBandEnergydB_fx, psGMNode, psGMNode->psNext, &fMergeCost_exp );
734 0 : IF( LT_32( fMergeCost_fx, 0 ) && ( GT_32( fBestMergeCost_fx, 0 ) ) )
735 : {
736 :
737 0 : Flag = 1;
738 0 : move16();
739 : }
740 0 : ELSE IF( ( GT_32( fMergeCost_fx, 0 ) && ( LT_32( fBestMergeCost_fx, 0 ) ) ) )
741 : {
742 0 : Flag = -1;
743 0 : move16();
744 : }
745 : ELSE
746 : {
747 0 : Flag = BASOP_Util_Cmp_Mant32Exp( fBestMergeCost_fx, fBestMergeCost_exp, fMergeCost_fx, fMergeCost_exp );
748 : }
749 0 : IF( EQ_32( Flag, 1 ) )
750 : {
751 0 : fBestMergeCost_fx = fMergeCost_fx;
752 0 : move32();
753 0 : fBestMergeCost_exp = fMergeCost_exp;
754 0 : move16();
755 0 : psBestGMNode = psGMNode;
756 : }
757 :
758 0 : psGMNode = psGMNode->psNext;
759 : }
760 :
761 0 : IF( ( GT_32( fBestMergeCost_fx, 0 ) && ( LE_32( iNumGroups, iMaxGroups ) ) ) )
762 : {
763 0 : iDone++;
764 : }
765 0 : ELSE IF( ( psBestGMNode != NULL ) && ( psBestGMNode->psNext != NULL ) )
766 : {
767 0 : psBestGMNode->iGroupLength = L_add( psBestGMNode->psNext->iGroupLength, psBestGMNode->iGroupLength );
768 0 : psBestGMNode->fGroupSNRPenalty_fx = L_negate( ONE_IN_Q30 );
769 0 : psBestGMNode->fGroupSNRPenalty_exp = 1;
770 0 : move16();
771 0 : psBestGMNode->psNext = psBestGMNode->psNext->psNext;
772 0 : iNumGroups--;
773 : }
774 : ELSE
775 : {
776 0 : iDone++; // This only catches a problem
777 : }
778 : }
779 :
780 0 : return;
781 : }
782 :
783 :
784 : /*-------------------------------------------------------------------*
785 : * Function ComputeRMSEnvelope()
786 : *
787 : *
788 : *-------------------------------------------------------------------*/
789 :
790 0 : static void ComputeRMSEnvelope(
791 : const Word32 iChannels,
792 : const Word32 iNumBands,
793 : const Word32 iNumGroups,
794 : const Word32 *piGroupLengths,
795 : Word32 **ppfBandEnergy_man,
796 : Word16 **ppfBandEnergy_exp,
797 : Word32 ***pppiRMSEnvelope )
798 : {
799 : Word32 n;
800 : Word32 fGroupEnergy_fx;
801 : Word16 fGroupEnergy_exp;
802 : Word32 temp;
803 :
804 0 : FOR( n = 0; n < iChannels; n++ )
805 : {
806 : Word32 b;
807 : Word32 iChanOffset;
808 :
809 0 : iChanOffset = L_mult0( extract_l( n ), extract_l( iNumBands ) );
810 :
811 0 : FOR( b = 0; b < iNumBands; b++ )
812 : {
813 : Word32 k;
814 : Word32 iBlockOffset;
815 0 : iBlockOffset = 0;
816 0 : FOR( k = 0; k < iNumGroups; k++ )
817 : {
818 : Word32 m;
819 0 : fGroupEnergy_exp = 0;
820 0 : move16();
821 0 : fGroupEnergy_fx = 0;
822 0 : move32();
823 0 : FOR( m = 0; m < piGroupLengths[k]; m++ )
824 : {
825 0 : fGroupEnergy_fx = BASOP_Util_Add_Mant32Exp( ppfBandEnergy_man[iBlockOffset][b + iChanOffset], ppfBandEnergy_exp[iBlockOffset][b + iChanOffset], fGroupEnergy_fx, fGroupEnergy_exp, &fGroupEnergy_exp );
826 0 : iBlockOffset++;
827 : }
828 0 : fGroupEnergy_fx = Mpy_32_32( fGroupEnergy_fx, Inv_grp_length[piGroupLengths[k]] ); // Division by iGroupLength
829 0 : fGroupEnergy_fx = BASOP_Util_Log2( fGroupEnergy_fx );
830 0 : move32();
831 0 : fGroupEnergy_fx = L_add( fGroupEnergy_fx, L_shl( L_deposit_l( fGroupEnergy_exp ), WORD32_BITS - 1 - LD_DATA_SCALE ) ); /*Q25*/
832 0 : temp = ( fGroupEnergy_fx > 0 ) ? L_add( fGroupEnergy_fx, ONE_IN_Q24 ) : L_negate( L_add( L_negate( fGroupEnergy_fx ), ONE_IN_Q24 ) ); // Q25
833 0 : temp = L_shr( temp, 25 );
834 0 : temp = ( temp > ENV_MIN ) ? temp : ENV_MIN;
835 0 : temp = ( temp < ENV_MAX ) ? temp : ENV_MAX;
836 0 : pppiRMSEnvelope[n][k][b] = temp;
837 : }
838 : }
839 : }
840 :
841 0 : return;
842 : }
843 :
844 :
845 : /*-------------------------------------------------------------------*
846 : * Function LimitRMSEnvelope()
847 : *
848 : *
849 : *-------------------------------------------------------------------*/
850 :
851 0 : static void LimitRMSEnvelope(
852 : const Word32 iBandCount,
853 : const Word32 iRMSDeltaMax,
854 : const Word32 iRMSDeltaMin,
855 : Word32 *piRMSEnvelope )
856 : {
857 : Word32 iBand;
858 : Word32 iLastSCF;
859 :
860 : /* Increase low envelope values to ensure that the scale factors traces the large values correctly (checking for max deltas) */
861 0 : iLastSCF = piRMSEnvelope[iBandCount - 1];
862 0 : move32();
863 0 : for ( iBand = iBandCount - 2; iBand > -1; iBand-- )
864 : {
865 : Word32 iDelta;
866 :
867 0 : iDelta = L_sub( iLastSCF, piRMSEnvelope[iBand] );
868 :
869 0 : IF( GT_32( iDelta, iRMSDeltaMax ) )
870 : {
871 : #ifdef DEBUG_VERBOSE
872 : printf( "WARNING RMS envelope delta limited\n" );
873 : #endif
874 0 : piRMSEnvelope[iBand] = L_add( L_sub( iDelta, iRMSDeltaMax ), piRMSEnvelope[iBand] );
875 : }
876 :
877 0 : iLastSCF = piRMSEnvelope[iBand];
878 0 : move32();
879 : }
880 :
881 : /* Increase low envelope values to ensure that the envelope traces the large values correctly (checking for min deltas)*/
882 0 : iLastSCF = piRMSEnvelope[0];
883 0 : FOR( iBand = 1; iBand < iBandCount; iBand++ )
884 : {
885 : Word32 iDelta;
886 :
887 0 : iDelta = L_sub( piRMSEnvelope[iBand], iLastSCF );
888 :
889 0 : IF( LT_32( iDelta, iRMSDeltaMin ) )
890 : {
891 : #ifdef DEBUG_VERBOSE
892 : printf( "WARNING RMS envelope delta limited\n" );
893 : #endif
894 0 : piRMSEnvelope[iBand] = L_add( piRMSEnvelope[iBand], L_sub( iRMSDeltaMin, iDelta ) );
895 : }
896 :
897 0 : iLastSCF = piRMSEnvelope[iBand];
898 0 : move32();
899 : }
900 :
901 0 : return;
902 : }
903 :
904 :
905 : /*-------------------------------------------------------------------*
906 : * Function ComputeEnvelopeGrouping()
907 : *
908 : *
909 : *-------------------------------------------------------------------*/
910 :
911 0 : void ComputeEnvelopeGrouping(
912 : RMSEnvelopeGrouping *psRMSEnvelopeGrouping,
913 : const Word32 iChannels,
914 : const Word32 iNumBands,
915 : const Word32 *piBandwidths,
916 : Word32 ***pppfReal_fx,
917 : Word32 ***pppfImag_fx,
918 : Word32 *piNumGroups,
919 : Word32 *piGroupLengths,
920 : Word32 ***pppiRMSEnvelope,
921 : Word16 q_final )
922 : {
923 : Word32 n;
924 : GMNode *psGMNode;
925 :
926 : /* Compute Band Energies */
927 0 : ComputeBandEnergy( iChannels, psRMSEnvelopeGrouping->iNumBlocks, iNumBands, piBandwidths, pppfReal_fx, pppfImag_fx, psRMSEnvelopeGrouping->ppfBandEnergy_man, psRMSEnvelopeGrouping->ppfBandEnergy_exp, psRMSEnvelopeGrouping->ppfBandEnergydB_fx, psRMSEnvelopeGrouping->ppfWeight_man, psRMSEnvelopeGrouping->ppfWeight_exp, q_final );
928 : /* Init GMNodes */
929 0 : psRMSEnvelopeGrouping->psGMNodes[0].iGroupStart = 0;
930 0 : move32();
931 0 : psRMSEnvelopeGrouping->psGMNodes[0].iGroupLength = 2;
932 0 : move32();
933 0 : psRMSEnvelopeGrouping->psGMNodes[0].psNext = NULL;
934 0 : psRMSEnvelopeGrouping->psGMNodes[0].iGroupRMSEnvelopeCost = -1;
935 0 : move32();
936 0 : psRMSEnvelopeGrouping->psGMNodes[0].fGroupSNRPenalty_fx = L_negate( ONE_IN_Q30 );
937 0 : psRMSEnvelopeGrouping->psGMNodes[0].fGroupSNRPenalty_exp = 1;
938 0 : move16();
939 0 : FOR( n = 1; n < psRMSEnvelopeGrouping->iMaxGroups; n++ )
940 : {
941 0 : psRMSEnvelopeGrouping->psGMNodes[n - 1].psNext = &psRMSEnvelopeGrouping->psGMNodes[n];
942 0 : psRMSEnvelopeGrouping->psGMNodes[n].iGroupStart = L_shl( n, 1 );
943 0 : move32();
944 0 : psRMSEnvelopeGrouping->psGMNodes[n].iGroupLength = 2;
945 0 : move32();
946 0 : psRMSEnvelopeGrouping->psGMNodes[n].iGroupRMSEnvelopeCost = -1;
947 0 : move32();
948 0 : psRMSEnvelopeGrouping->psGMNodes[n].fGroupSNRPenalty_fx = L_negate( ONE_IN_Q30 );
949 0 : psRMSEnvelopeGrouping->psGMNodes[n].fGroupSNRPenalty_exp = 1;
950 0 : move16();
951 0 : psRMSEnvelopeGrouping->psGMNodes[n].psNext = NULL;
952 : }
953 : /* Perform grouping via Greedy Merge */
954 : /* Allows control over max groups can call using 16 if want same as previous call */
955 0 : ComputeGreedyGroups3( psRMSEnvelopeGrouping, iChannels, iNumBands, piBandwidths, psRMSEnvelopeGrouping->iNumBlocks );
956 : /* Calc Groups from Merge Results */
957 0 : *piNumGroups = 0;
958 0 : move32();
959 0 : psGMNode = &psRMSEnvelopeGrouping->psGMNodes[0];
960 0 : WHILE( psGMNode != NULL )
961 : {
962 0 : piGroupLengths[*piNumGroups] = psGMNode->iGroupLength;
963 0 : move32();
964 0 : *piNumGroups = L_add( *piNumGroups, 1 );
965 0 : psGMNode = psGMNode->psNext;
966 : }
967 : /* Compute RMS Envelope given group lengths */
968 0 : ComputeRMSEnvelope( iChannels, iNumBands, *piNumGroups, piGroupLengths, psRMSEnvelopeGrouping->ppfBandEnergy_man, psRMSEnvelopeGrouping->ppfBandEnergy_exp, pppiRMSEnvelope );
969 :
970 : /* Envelope Tenting */
971 0 : FOR( n = 0; n < iChannels; n++ )
972 : {
973 : Word32 k;
974 0 : FOR( k = 0; k < *piNumGroups; k++ )
975 : {
976 0 : LimitRMSEnvelope( iNumBands, ENV_DELTA_MAX, ENV_DELTA_MIN, pppiRMSEnvelope[n][k] );
977 : }
978 : }
979 :
980 0 : return;
981 : }
|