Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : #include <stdlib.h>
34 : #include "options.h"
35 : #include <math.h>
36 : #include "prot.h"
37 : #include "isar_lcld_prot.h"
38 : #include "isar_rom_lcld_tables.h"
39 : #include "wmc_auto.h"
40 :
41 :
42 : /*-------------------------------------------------------------------*
43 : * Local ROM tables
44 : *
45 : *
46 : *-------------------------------------------------------------------*/
47 :
48 : static const float c_afThreshQuiet48[23] = {
49 : -8.40653699e+01f,
50 : -8.40653699e+01f,
51 : -8.40653699e+01f,
52 : -8.40653699e+01f,
53 : -8.40653699e+01f,
54 : -8.40653699e+01f,
55 : -8.40653699e+01f,
56 : -8.40653699e+01f,
57 : -8.38067304e+01f,
58 : -8.28409495e+01f,
59 : -8.17031225e+01f,
60 : -7.89799501e+01f,
61 : -7.70607916e+01f,
62 : -7.58484320e+01f,
63 : -7.47976303e+01f,
64 : -7.37491303e+01f,
65 : -7.13163746e+01f,
66 : -6.86144293e+01f,
67 : -6.56295695e+01f,
68 : -6.06521800e+01f,
69 : -3.15408065e+01f,
70 : -1.92542188e+01f,
71 : -1.88401753e+01f,
72 : };
73 :
74 : static const float c_fiDefaultTheta48[MAX_BANDS_48] = {
75 : 0.4375,
76 : 0.4375,
77 : 0.375,
78 : 0.3125,
79 : 0.3125,
80 : 0.25,
81 : 0.25,
82 : 0.25,
83 : 0.25,
84 : 0.25,
85 : 0.25,
86 : 0.25,
87 : 0.25,
88 : 0.25,
89 : 0.25,
90 : 0.25,
91 : 0.25,
92 : 0.25,
93 : 0.25,
94 : 0.25,
95 : 0.25,
96 : 0.25,
97 : 0.25,
98 : };
99 :
100 : typedef struct GMNODE
101 : {
102 : int32_t iGroupStart;
103 : int32_t iGroupLength;
104 : float *pfMergedEnergydB;
105 : int32_t *piQRMSEnvelope;
106 :
107 : int32_t iGroupRMSEnvelopeCost;
108 : float fGroupSNRPenalty;
109 :
110 : struct GMNODE *psNext;
111 : } GMNode;
112 :
113 : struct RMS_ENVELOPE_GROUPING
114 : {
115 : int32_t iNumBlocks;
116 : int32_t iMaxGroups;
117 : float **ppfBandEnergy;
118 : float **ppfBandEnergydB;
119 : float **ppfWeight;
120 : GMNode *psGMNodes;
121 : };
122 :
123 :
124 : /*-------------------------------------------------------------------*
125 : * Function CreateRMSEnvelopeGrouping()
126 : *
127 : *
128 : *-------------------------------------------------------------------*/
129 :
130 0 : RMSEnvelopeGrouping *CreateRMSEnvelopeGrouping(
131 : const int32_t iNumBlocks )
132 : {
133 : int32_t n;
134 :
135 : RMSEnvelopeGrouping *psRMSEnvelopeGrouping;
136 :
137 0 : psRMSEnvelopeGrouping = (RMSEnvelopeGrouping *) malloc( sizeof( RMSEnvelopeGrouping ) );
138 0 : psRMSEnvelopeGrouping->iNumBlocks = iNumBlocks;
139 :
140 0 : psRMSEnvelopeGrouping->iMaxGroups = iNumBlocks >> 1;
141 :
142 0 : psRMSEnvelopeGrouping->ppfBandEnergy = (float **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( float * ) );
143 0 : psRMSEnvelopeGrouping->ppfBandEnergydB = (float **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( float * ) );
144 0 : psRMSEnvelopeGrouping->ppfWeight = (float **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( float * ) );
145 0 : for ( n = 0; n < psRMSEnvelopeGrouping->iNumBlocks; n++ )
146 : {
147 0 : psRMSEnvelopeGrouping->ppfBandEnergy[n] = (float *) malloc( MAX_BANDS * 2 * sizeof( float ) ); /* 2 for stereo joint group calc */
148 0 : psRMSEnvelopeGrouping->ppfBandEnergydB[n] = (float *) malloc( MAX_BANDS * 2 * sizeof( float ) );
149 0 : psRMSEnvelopeGrouping->ppfWeight[n] = (float *) malloc( MAX_BANDS * 2 * sizeof( float ) );
150 : }
151 :
152 0 : psRMSEnvelopeGrouping->psGMNodes = (GMNode *) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( GMNode ) );
153 0 : for ( n = 0; n < psRMSEnvelopeGrouping->iNumBlocks; n++ )
154 : {
155 0 : psRMSEnvelopeGrouping->psGMNodes[n].pfMergedEnergydB = (float *) malloc( MAX_BANDS * 2 * sizeof( float ) );
156 0 : psRMSEnvelopeGrouping->psGMNodes[n].piQRMSEnvelope = (int32_t *) malloc( MAX_BANDS * 2 * sizeof( int32_t ) );
157 0 : psRMSEnvelopeGrouping->psGMNodes[n].iGroupRMSEnvelopeCost = -1;
158 0 : psRMSEnvelopeGrouping->psGMNodes[n].fGroupSNRPenalty = -1.0;
159 : }
160 :
161 0 : return psRMSEnvelopeGrouping;
162 : }
163 :
164 :
165 : /*-------------------------------------------------------------------*
166 : * Function DeleteRMSEnvelopeGrouping()
167 : *
168 : *
169 : *-------------------------------------------------------------------*/
170 :
171 0 : void DeleteRMSEnvelopeGrouping(
172 : RMSEnvelopeGrouping *psRMSEnvelopeGrouping )
173 : {
174 : int32_t n;
175 :
176 0 : for ( n = 0; n < psRMSEnvelopeGrouping->iNumBlocks; n++ )
177 : {
178 0 : free( psRMSEnvelopeGrouping->ppfBandEnergy[n] );
179 0 : free( psRMSEnvelopeGrouping->ppfBandEnergydB[n] );
180 0 : free( psRMSEnvelopeGrouping->ppfWeight[n] );
181 : }
182 0 : free( psRMSEnvelopeGrouping->ppfBandEnergy );
183 0 : free( psRMSEnvelopeGrouping->ppfBandEnergydB );
184 0 : free( psRMSEnvelopeGrouping->ppfWeight );
185 :
186 0 : for ( n = 0; n < psRMSEnvelopeGrouping->iNumBlocks; n++ )
187 : {
188 0 : free( psRMSEnvelopeGrouping->psGMNodes[n].pfMergedEnergydB );
189 0 : free( psRMSEnvelopeGrouping->psGMNodes[n].piQRMSEnvelope );
190 : }
191 0 : free( psRMSEnvelopeGrouping->psGMNodes );
192 :
193 0 : free( psRMSEnvelopeGrouping );
194 :
195 0 : return;
196 : }
197 :
198 :
199 : /*-------------------------------------------------------------------*
200 : * Function ComputeBandEnergy()
201 : *
202 : *
203 : *-------------------------------------------------------------------*/
204 :
205 0 : static void ComputeBandEnergy(
206 : const int32_t iChannels,
207 : const int32_t iNumBlocks,
208 : const int32_t iNumBands,
209 : const int32_t *piBandwidths,
210 : float ***pppfReal,
211 : float ***pppfImag,
212 : float **ppfBandEnergy,
213 : float **ppfBandEnergydB,
214 : float **ppfWeight )
215 : {
216 : int32_t n;
217 :
218 0 : for ( n = 0; n < iChannels; n++ )
219 : {
220 : int32_t k;
221 : int32_t iChanOffset;
222 :
223 0 : iChanOffset = n * iNumBands;
224 0 : for ( k = 0; k < iNumBlocks; k++ )
225 : {
226 : int32_t b;
227 : int32_t iFBOffset;
228 : float fMaxWeight;
229 :
230 0 : iFBOffset = 0;
231 0 : fMaxWeight = 0.0f;
232 0 : for ( b = 0; b < iNumBands; b++ )
233 : {
234 : int32_t m;
235 0 : float fEnergy = 1e-12f;
236 : float fWeight;
237 :
238 0 : for ( m = 0; m < piBandwidths[b]; m++ )
239 : {
240 0 : fEnergy += ( pppfReal[n][k][iFBOffset] * pppfReal[n][k][iFBOffset] + pppfImag[n][k][iFBOffset] * pppfImag[n][k][iFBOffset] );
241 0 : iFBOffset++;
242 : }
243 0 : fEnergy /= (float) ( piBandwidths[b] ); /* Correction removed normalization by 2*/
244 0 : ppfBandEnergy[k][iChanOffset + b] = fEnergy;
245 :
246 0 : fWeight = 0.33f * powf( 10.0f, 0.0068f * ( 10.0f * log10f( fEnergy ) - c_afThreshQuiet48[b] ) );
247 0 : fWeight = ( fWeight > 0.33f ) ? fWeight : 0.33f;
248 0 : fWeight = ( fWeight < 1.0f ) ? fWeight : 1.0f;
249 0 : fMaxWeight = ( fMaxWeight > fWeight ) ? fMaxWeight : fWeight;
250 0 : ppfWeight[k][iChanOffset + b] = fWeight;
251 :
252 : #ifdef APPLY_TEMPORAL_SMOOTHING
253 : if ( k > 0 )
254 : {
255 : float fSmoothEnergy;
256 : fSmoothEnergy = 0.7f * ppfBandEnergy[k - 1][iChanOffset + b] + 0.3f * fEnergy;
257 :
258 : fEnergy = ( fEnergy > fSmoothEnergy ) ? fEnergy : fSmoothEnergy;
259 : }
260 : #endif
261 0 : fEnergy = 10.0f * log10f( fEnergy );
262 0 : ppfBandEnergydB[k][iChanOffset + b] = fEnergy;
263 : }
264 0 : for ( b = 0; b < iNumBands; b++ )
265 : {
266 0 : ppfWeight[k][iChanOffset + b] /= fMaxWeight;
267 : }
268 : }
269 : }
270 :
271 0 : return;
272 : }
273 :
274 : /*-------------------------------------------------------------------*
275 : * Function ComputeMergeRMS()
276 : *
277 : *
278 : *-------------------------------------------------------------------*/
279 :
280 0 : static void ComputeMergeRMS(
281 : const int32_t iNumBands,
282 : const int32_t iStartBlock,
283 : const int32_t iGroupLength,
284 : float **ppfBandEnergy,
285 : float *pfMergedEnergydB,
286 : int32_t *piQRMSEnvelope )
287 : {
288 : int32_t b;
289 0 : float fInvGroupSize = 1.0f / (float) iGroupLength;
290 :
291 0 : for ( b = 0; b < iNumBands; b++ )
292 : {
293 : int32_t n;
294 : float fGroupEnergy;
295 : float fRMSEnvelope;
296 : int32_t iQRMSEnvelope;
297 :
298 0 : fGroupEnergy = 0.0;
299 0 : for ( n = iStartBlock; n < ( iStartBlock + iGroupLength ); n++ )
300 : {
301 0 : fGroupEnergy += ppfBandEnergy[n][b];
302 : }
303 0 : fGroupEnergy *= fInvGroupSize;
304 :
305 0 : fRMSEnvelope = log2f( fGroupEnergy );
306 0 : iQRMSEnvelope = ( fRMSEnvelope > 0.0 ) ? (int32_t) ( fRMSEnvelope + 0.5 ) : (int32_t) ( fRMSEnvelope - 0.5 );
307 :
308 0 : fGroupEnergy = 10.0f * log10f( fGroupEnergy ); /* Note epsilon was added when computing BandEnergy;*/
309 :
310 0 : pfMergedEnergydB[b] = fGroupEnergy;
311 0 : piQRMSEnvelope[b] = iQRMSEnvelope;
312 : }
313 :
314 0 : return;
315 : }
316 :
317 :
318 : /*-------------------------------------------------------------------*
319 : * Function ComputeRMSEnvelopeBits()
320 : *
321 : *
322 : *-------------------------------------------------------------------*/
323 :
324 0 : static int32_t ComputeRMSEnvelopeBits(
325 : const int32_t iChannels,
326 : const int32_t iNumBands,
327 : const int32_t *piQRMSEnevelope )
328 : {
329 : int32_t n;
330 0 : int32_t iRMSEnvelopeBits = 0;
331 0 : int32_t iChanOffset = 0;
332 :
333 0 : for ( n = 0; n < iChannels; n++ )
334 : {
335 : int32_t b;
336 : int32_t iLastRMSVal;
337 :
338 0 : iRMSEnvelopeBits += ENV0_BITS;
339 0 : iLastRMSVal = piQRMSEnevelope[iChanOffset];
340 0 : for ( b = 1; b < iNumBands; b++ )
341 : {
342 : int32_t iDelta;
343 :
344 0 : iDelta = piQRMSEnevelope[iChanOffset + b] - iLastRMSVal;
345 0 : iDelta = ( iDelta > ENV_DELTA_MIN ) ? iDelta : ENV_DELTA_MIN;
346 0 : iDelta = ( iDelta < ENV_DELTA_MAX ) ? iDelta : ENV_DELTA_MAX;
347 0 : iDelta -= ENV_DELTA_MIN;
348 0 : iRMSEnvelopeBits += c_aaiRMSEnvHuffEnc[iDelta][0];
349 :
350 0 : iLastRMSVal = piQRMSEnevelope[iChanOffset + b];
351 : }
352 :
353 0 : iChanOffset += iNumBands;
354 : }
355 :
356 0 : return iRMSEnvelopeBits;
357 : }
358 :
359 :
360 : /*-------------------------------------------------------------------*
361 : * Function ComputeSNRPenalty()
362 : *
363 : *
364 : *-------------------------------------------------------------------*/
365 :
366 0 : static float ComputeSNRPenalty(
367 : const int32_t iChannels,
368 : const int32_t iNumBands,
369 : const int32_t *piBandwidths,
370 : const int32_t iStartBlock,
371 : const int32_t iGroupLength,
372 : float **ppfBandEnergydB,
373 : const int32_t *piRMSEnvelope )
374 : {
375 : int32_t n;
376 : int32_t iChanOffset;
377 0 : float fSNRPenalty = 0.0;
378 :
379 0 : iChanOffset = 0;
380 0 : for ( n = 0; n < iChannels; n++ )
381 : {
382 : int32_t b;
383 0 : for ( b = 0; b < iNumBands; b++ )
384 : {
385 : int32_t k;
386 : float fRMSVal;
387 :
388 0 : fRMSVal = 3.0103f * (float) piRMSEnvelope[iChanOffset + b];
389 :
390 0 : for ( k = iStartBlock; k < ( iStartBlock + iGroupLength ); k++ )
391 : {
392 : float fDeltadB;
393 :
394 0 : fDeltadB = fRMSVal - ppfBandEnergydB[k][iChanOffset + b];
395 0 : if ( fDeltadB < -9.0309f )
396 : {
397 0 : fSNRPenalty += 1e10f; /* Some large number to prevent clipping*/
398 : }
399 : else /*if(fDeltadB < 0.0)*/
400 : {
401 0 : fSNRPenalty += fabsf( c_fiDefaultTheta48[b] * fDeltadB - fDeltadB ) * 2.0f * (float) piBandwidths[b] / 6.0f;
402 : }
403 : }
404 : }
405 :
406 0 : iChanOffset += iNumBands;
407 : }
408 :
409 0 : return fSNRPenalty;
410 : }
411 :
412 :
413 : /*-------------------------------------------------------------------*
414 : * Function TryMerge2()
415 : *
416 : *
417 : *-------------------------------------------------------------------*/
418 :
419 0 : static float TryMerge2(
420 : const int32_t iChannels,
421 : const int32_t iNumBands,
422 : const int32_t *piBandwidths,
423 : float **ppfBandEnergy,
424 : float **ppfBandEnergydB,
425 : GMNode *psGMNode1,
426 : GMNode *psGMNode2 )
427 : {
428 : int32_t iRMSEnvBits1;
429 : int32_t iRMSEnvBits2;
430 : int32_t iRMSEnvBitsMerged;
431 : float fSNRPenalty1;
432 : float fSNRPenalty2;
433 : float fSNRPenaltyMerged;
434 0 : float fMergedCost = 0.0;
435 :
436 : /* First compute current RMS Envelope for each group */
437 0 : if ( psGMNode1->iGroupRMSEnvelopeCost == -1 || psGMNode1->fGroupSNRPenalty == -1.0 )
438 : {
439 0 : ComputeMergeRMS( iNumBands * iChannels, psGMNode1->iGroupStart, psGMNode1->iGroupLength, ppfBandEnergy, psGMNode1->pfMergedEnergydB, psGMNode1->piQRMSEnvelope );
440 :
441 0 : iRMSEnvBits1 = ComputeRMSEnvelopeBits( iChannels, iNumBands, psGMNode1->piQRMSEnvelope );
442 :
443 0 : fSNRPenalty1 = ComputeSNRPenalty( iChannels, iNumBands, piBandwidths, psGMNode1->iGroupStart, psGMNode1->iGroupLength, ppfBandEnergydB, psGMNode1->piQRMSEnvelope );
444 :
445 0 : psGMNode1->iGroupRMSEnvelopeCost = iRMSEnvBits1;
446 0 : psGMNode1->fGroupSNRPenalty = fSNRPenalty1;
447 : }
448 : else
449 : {
450 0 : iRMSEnvBits1 = psGMNode1->iGroupRMSEnvelopeCost;
451 0 : fSNRPenalty1 = psGMNode1->fGroupSNRPenalty;
452 : }
453 :
454 0 : if ( psGMNode2->iGroupRMSEnvelopeCost == -1 || psGMNode2->fGroupSNRPenalty == -1.0 )
455 : {
456 0 : ComputeMergeRMS( iNumBands * iChannels, psGMNode2->iGroupStart, psGMNode2->iGroupLength, ppfBandEnergy, psGMNode2->pfMergedEnergydB, psGMNode2->piQRMSEnvelope );
457 :
458 0 : iRMSEnvBits2 = ComputeRMSEnvelopeBits( iChannels, iNumBands, psGMNode2->piQRMSEnvelope );
459 :
460 0 : fSNRPenalty2 = ComputeSNRPenalty( iChannels, iNumBands, piBandwidths, psGMNode2->iGroupStart, psGMNode2->iGroupLength, ppfBandEnergydB, psGMNode2->piQRMSEnvelope );
461 :
462 0 : psGMNode2->iGroupRMSEnvelopeCost = iRMSEnvBits2;
463 0 : psGMNode2->fGroupSNRPenalty = fSNRPenalty2;
464 : }
465 : else
466 : {
467 0 : iRMSEnvBits2 = psGMNode2->iGroupRMSEnvelopeCost;
468 0 : fSNRPenalty2 = psGMNode2->fGroupSNRPenalty;
469 : }
470 :
471 : /* Compute the merged group */
472 0 : ComputeMergeRMS( iNumBands * iChannels, psGMNode1->iGroupStart, psGMNode1->iGroupLength + psGMNode2->iGroupLength, ppfBandEnergy, psGMNode1->pfMergedEnergydB, psGMNode1->piQRMSEnvelope );
473 :
474 : /* Compute the RMS Envelope cost for merged group */
475 0 : iRMSEnvBitsMerged = ComputeRMSEnvelopeBits( iChannels, iNumBands, psGMNode1->piQRMSEnvelope );
476 :
477 : /* Compute an approximation of the bit cost based on SNR increase/decrease due to merging */
478 0 : fSNRPenaltyMerged = ComputeSNRPenalty( iChannels, iNumBands, piBandwidths, psGMNode1->iGroupStart, psGMNode1->iGroupLength + psGMNode2->iGroupLength, ppfBandEnergydB, psGMNode1->piQRMSEnvelope );
479 :
480 0 : fMergedCost = fSNRPenaltyMerged - fSNRPenalty1 - fSNRPenalty2 + (float) iRMSEnvBitsMerged - (float) iRMSEnvBits1 - (float) iRMSEnvBits2;
481 :
482 0 : return fMergedCost;
483 : }
484 :
485 : /*-------------------------------------------------------------------*
486 : * Function ComputeGreedyGroups3()
487 : *
488 : *
489 : *-------------------------------------------------------------------*/
490 :
491 0 : static void ComputeGreedyGroups3(
492 : RMSEnvelopeGrouping *psRMSEnvelopeGrouping,
493 : const int32_t iChannels,
494 : const int32_t iNumBands,
495 : const int32_t *piBandwidths,
496 : const int32_t iMaxGroups )
497 : {
498 :
499 0 : int32_t iDone = 0;
500 0 : int32_t iNumGroups = psRMSEnvelopeGrouping->iMaxGroups;
501 :
502 0 : while ( iDone == 0 )
503 : {
504 : GMNode *psGMNode;
505 : GMNode *psBestGMNode;
506 : float fBestMergeCost;
507 :
508 0 : fBestMergeCost = 1e20f;
509 0 : psGMNode = &psRMSEnvelopeGrouping->psGMNodes[0];
510 0 : psBestGMNode = NULL;
511 0 : while ( psGMNode->psNext != NULL )
512 : {
513 : float fMergeCost;
514 :
515 0 : fMergeCost = TryMerge2( iChannels, iNumBands, piBandwidths, psRMSEnvelopeGrouping->ppfBandEnergy, psRMSEnvelopeGrouping->ppfBandEnergydB, psGMNode, psGMNode->psNext );
516 :
517 0 : if ( fMergeCost < fBestMergeCost )
518 : {
519 0 : fBestMergeCost = fMergeCost;
520 0 : psBestGMNode = psGMNode;
521 : }
522 :
523 0 : psGMNode = psGMNode->psNext;
524 : }
525 :
526 0 : if ( fBestMergeCost > 0.0 && iNumGroups <= iMaxGroups )
527 : {
528 0 : iDone++;
529 : }
530 0 : else if ( psBestGMNode != NULL && psBestGMNode->psNext != NULL )
531 : {
532 0 : psBestGMNode->iGroupLength += psBestGMNode->psNext->iGroupLength;
533 0 : psBestGMNode->iGroupRMSEnvelopeCost = -1;
534 0 : psBestGMNode->fGroupSNRPenalty = -1.0;
535 0 : psBestGMNode->psNext = psBestGMNode->psNext->psNext;
536 0 : iNumGroups--;
537 : }
538 : else
539 : {
540 0 : iDone++; /* This only catches a problem*/
541 : }
542 : }
543 :
544 0 : return;
545 : }
546 :
547 :
548 : /*-------------------------------------------------------------------*
549 : * Function ComputeRMSEnvelope()
550 : *
551 : *
552 : *-------------------------------------------------------------------*/
553 :
554 0 : static void ComputeRMSEnvelope(
555 : const int32_t iChannels,
556 : const int32_t iNumBands,
557 : const int32_t iNumGroups,
558 : const int32_t *piGroupLengths,
559 : float **ppfBandEnergy,
560 : int32_t ***pppiRMSEnvelope )
561 : {
562 : int32_t n;
563 :
564 0 : for ( n = 0; n < iChannels; n++ )
565 : {
566 : int32_t b;
567 : int32_t iChanOffset;
568 :
569 0 : iChanOffset = n * iNumBands;
570 0 : for ( b = 0; b < iNumBands; b++ )
571 : {
572 : int32_t k;
573 : int32_t iBlockOffset;
574 :
575 0 : iBlockOffset = 0;
576 0 : for ( k = 0; k < iNumGroups; k++ )
577 : {
578 : int32_t m;
579 : float fGroupEnergy;
580 0 : fGroupEnergy = 0.0;
581 0 : for ( m = 0; m < piGroupLengths[k]; m++ )
582 : {
583 0 : fGroupEnergy += ppfBandEnergy[iBlockOffset][b + iChanOffset];
584 0 : iBlockOffset++;
585 : }
586 0 : fGroupEnergy /= (float) piGroupLengths[k];
587 :
588 0 : fGroupEnergy = log2f( fGroupEnergy );
589 0 : pppiRMSEnvelope[n][k][b] = ( fGroupEnergy > 0.0 ) ? (int32_t) ( fGroupEnergy + 0.5 ) : (int32_t) ( fGroupEnergy - 0.5 );
590 0 : pppiRMSEnvelope[n][k][b] = ( pppiRMSEnvelope[n][k][b] > ENV_MIN ) ? pppiRMSEnvelope[n][k][b] : ENV_MIN;
591 0 : pppiRMSEnvelope[n][k][b] = ( pppiRMSEnvelope[n][k][b] < ENV_MAX ) ? pppiRMSEnvelope[n][k][b] : ENV_MAX;
592 : }
593 : }
594 : }
595 :
596 0 : return;
597 : }
598 :
599 :
600 : /*-------------------------------------------------------------------*
601 : * Function LimitRMSEnvelope()
602 : *
603 : *
604 : *-------------------------------------------------------------------*/
605 :
606 0 : static void LimitRMSEnvelope(
607 : const int32_t iBandCount,
608 : const int32_t iRMSDeltaMax,
609 : const int32_t iRMSDeltaMin,
610 : int32_t *piRMSEnvelope )
611 : {
612 : int32_t iBand;
613 : int32_t iLastSCF;
614 :
615 : /* Increase low envelope values to ensure that the scale factors traces the large values correctly (checking for max deltas) */
616 0 : iLastSCF = piRMSEnvelope[iBandCount - 1];
617 0 : for ( iBand = iBandCount - 2; iBand > -1; iBand-- )
618 : {
619 : int32_t iDelta;
620 :
621 0 : iDelta = iLastSCF - piRMSEnvelope[iBand];
622 :
623 0 : if ( iDelta > iRMSDeltaMax )
624 : {
625 : #ifdef DEBUG_VERBOSE
626 : printf( "WARNING RMS envelope delta limited\n" );
627 : #endif
628 0 : piRMSEnvelope[iBand] += ( iDelta - iRMSDeltaMax );
629 : }
630 :
631 0 : iLastSCF = piRMSEnvelope[iBand];
632 : }
633 :
634 : /* Increase low envelope values to ensure that the envelope traces the large values correctly (checking for min deltas)*/
635 0 : iLastSCF = piRMSEnvelope[0];
636 0 : for ( iBand = 1; iBand < iBandCount; iBand++ )
637 : {
638 : int32_t iDelta;
639 :
640 0 : iDelta = piRMSEnvelope[iBand] - iLastSCF;
641 :
642 0 : if ( iDelta < iRMSDeltaMin )
643 : {
644 : #ifdef DEBUG_VERBOSE
645 : printf( "WARNING RMS envelope delta limited\n" );
646 : #endif
647 0 : piRMSEnvelope[iBand] += ( iRMSDeltaMin - iDelta );
648 : }
649 :
650 0 : iLastSCF = piRMSEnvelope[iBand];
651 : }
652 :
653 0 : return;
654 : }
655 :
656 :
657 : /*-------------------------------------------------------------------*
658 : * Function ComputeEnvelopeGrouping()
659 : *
660 : *
661 : *-------------------------------------------------------------------*/
662 :
663 0 : void ComputeEnvelopeGrouping(
664 : RMSEnvelopeGrouping *psRMSEnvelopeGrouping,
665 : const int32_t iChannels,
666 : const int32_t iNumBands,
667 : const int32_t *piBandwidths,
668 : float ***pppfReal,
669 : float ***pppfImag,
670 : int32_t *piNumGroups,
671 : int32_t *piGroupLengths,
672 : int32_t ***pppiRMSEnvelope )
673 : {
674 : int32_t n;
675 : GMNode *psGMNode;
676 :
677 : /* Compute Band Energies */
678 0 : ComputeBandEnergy( iChannels, psRMSEnvelopeGrouping->iNumBlocks, iNumBands, piBandwidths, pppfReal, pppfImag, psRMSEnvelopeGrouping->ppfBandEnergy, psRMSEnvelopeGrouping->ppfBandEnergydB, psRMSEnvelopeGrouping->ppfWeight );
679 :
680 : /* Init GMNodes */
681 0 : psRMSEnvelopeGrouping->psGMNodes[0].iGroupStart = 0;
682 0 : psRMSEnvelopeGrouping->psGMNodes[0].iGroupLength = 2;
683 0 : psRMSEnvelopeGrouping->psGMNodes[0].psNext = NULL;
684 0 : psRMSEnvelopeGrouping->psGMNodes[0].iGroupRMSEnvelopeCost = -1;
685 0 : psRMSEnvelopeGrouping->psGMNodes[0].fGroupSNRPenalty = -1.0f;
686 :
687 0 : for ( n = 1; n < psRMSEnvelopeGrouping->iMaxGroups; n++ )
688 : {
689 0 : psRMSEnvelopeGrouping->psGMNodes[n - 1].psNext = &psRMSEnvelopeGrouping->psGMNodes[n];
690 0 : psRMSEnvelopeGrouping->psGMNodes[n].iGroupStart = n * 2;
691 0 : psRMSEnvelopeGrouping->psGMNodes[n].iGroupLength = 2;
692 0 : psRMSEnvelopeGrouping->psGMNodes[n].iGroupRMSEnvelopeCost = -1;
693 0 : psRMSEnvelopeGrouping->psGMNodes[n].fGroupSNRPenalty = -1.0;
694 0 : psRMSEnvelopeGrouping->psGMNodes[n].psNext = NULL;
695 : }
696 :
697 : /* Perform grouping via Greedy Merge */
698 : /* Allows control over max groups can call using 16 if want same as previous call */
699 0 : ComputeGreedyGroups3( psRMSEnvelopeGrouping, iChannels, iNumBands, piBandwidths, psRMSEnvelopeGrouping->iNumBlocks );
700 :
701 : /* Calc Groups from Merge Results */
702 0 : *piNumGroups = 0;
703 0 : psGMNode = &psRMSEnvelopeGrouping->psGMNodes[0];
704 0 : while ( psGMNode != NULL )
705 : {
706 0 : piGroupLengths[*piNumGroups] = psGMNode->iGroupLength;
707 0 : *piNumGroups += 1;
708 0 : psGMNode = psGMNode->psNext;
709 : }
710 :
711 : /* Compute RMS Envelope given group lengths */
712 0 : ComputeRMSEnvelope( iChannels, iNumBands, *piNumGroups, piGroupLengths, psRMSEnvelopeGrouping->ppfBandEnergy, pppiRMSEnvelope );
713 :
714 : /* Envelope Tenting */
715 0 : for ( n = 0; n < iChannels; n++ )
716 : {
717 : int32_t k;
718 0 : for ( k = 0; k < *piNumGroups; k++ )
719 : {
720 0 : LimitRMSEnvelope( iNumBands, ENV_DELTA_MAX, ENV_DELTA_MIN, pppiRMSEnvelope[n][k] );
721 : }
722 : }
723 :
724 0 : return;
725 : }
|