• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* -----------------------------------------------------------------------------------------------------------
3 Software License for The Fraunhofer FDK AAC Codec Library for Android
4 
5 � Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V.
6   All rights reserved.
7 
8  1.    INTRODUCTION
9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
12 
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
16 of the MPEG specifications.
17 
18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
24 
25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
27 applications information and documentation.
28 
29 2.    COPYRIGHT LICENSE
30 
31 Redistribution and use in source and binary forms, with or without modification, are permitted without
32 payment of copyright license fees provided that you satisfy the following conditions:
33 
34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
35 your modifications thereto in source code form.
36 
37 You must retain the complete text of this software license in the documentation and/or other materials
38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
40 modifications thereto to recipients of copies in binary form.
41 
42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43 prior written permission.
44 
45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
46 software or your modifications thereto.
47 
48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
49 and the date of any change. For modified versions of the FDK AAC Codec, the term
50 "Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
51 "Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
52 
53 3.    NO PATENT LICENSE
54 
55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
57 respect to this software.
58 
59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60 by appropriate patent licenses.
61 
62 4.    DISCLAIMER
63 
64 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
65 "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
69 or business interruption, however caused and on any theory of liability, whether in contract, strict
70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
71 advised of the possibility of such damage.
72 
73 5.    CONTACT INFORMATION
74 
75 Fraunhofer Institute for Integrated Circuits IIS
76 Attention: Audio and Multimedia Departments - FDK AAC LL
77 Am Wolfsmantel 33
78 91058 Erlangen, Germany
79 
80 www.iis.fraunhofer.de/amm
81 amm-info@iis.fraunhofer.de
82 ----------------------------------------------------------------------------------------------------------- */
83 
84 /*****************************  MPEG Audio Encoder  ***************************
85 
86    Initial Authors:      M. Neuendorf, N. Rettelbach, M. Multrus
87    Contents/Description: PS parameter extraction, encoding
88 
89 ******************************************************************************/
90 /*!
91   \file
92   \brief  PS parameter extraction, encoding functions
93 */
94 
95 #include "ps_main.h"
96 
97 
98 #include "sbr_ram.h"
99 #include "ps_encode.h"
100 
101 #include "qmf.h"
102 
103 #include "ps_const.h"
104 #include "sbr_misc.h"
105 
106 #include "genericStds.h"
107 
FDKsbrEnc_addFIXP_DBL(const FIXP_DBL * X,const FIXP_DBL * Y,FIXP_DBL * Z,INT n)108 inline void FDKsbrEnc_addFIXP_DBL(const FIXP_DBL *X, const FIXP_DBL *Y, FIXP_DBL *Z, INT n)
109 {
110   for (INT i=0; i<n; i++)
111     Z[i] = (X[i]>>1) + (Y[i]>>1);
112 }
113 
114 #define LOG10_2_10             3.01029995664f /* 10.0f*log10(2.f) */
115 
116 static const INT iidGroupBordersLoRes[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES + 1] =
117 {
118   0, 1, 2, 3, 4, 5,    /* 6 subqmf subbands - 0th qmf subband */
119   6, 7,                /* 2 subqmf subbands - 1st qmf subband */
120   8, 9,                /* 2 subqmf subbands - 2nd qmf subband */
121   10, 11, 12, 13, 14, 15, 16, 18, 21, 25, 30, 42, 71
122 };
123 
124 static const UCHAR iidGroupWidthLdLoRes[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES] =
125 {
126   0, 0, 0, 0, 0, 0,
127   0, 0,
128   0, 0,
129   0, 0, 0, 0, 0, 0, 1, 2, 2, 3, 4, 5
130 };
131 
132 
133 static const INT subband2parameter20[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES] =
134 {
135   1, 0, 0, 1, 2, 3,   /* 6 subqmf subbands - 0th qmf subband */
136   4, 5,               /* 2 subqmf subbands - 1st qmf subband */
137   6, 7,               /* 2 subqmf subbands - 2nd qmf subband */
138   8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
139 };
140 
141 
142 typedef enum {
143   MAX_TIME_DIFF_FRAMES = 20,
144   MAX_PS_NOHEADER_CNT  = 10,
145   MAX_NOENV_CNT        = 10,
146   DO_NOT_USE_THIS_MODE = 0x7FFFFF
147 } __PS_CONSTANTS;
148 
149 
150 
151 static const FIXP_DBL iidQuant_fx[15] = {
152   0xce000000, 0xdc000000, 0xe4000000, 0xec000000, 0xf2000000, 0xf8000000, 0xfc000000, 0x00000000,
153   0x04000000, 0x08000000, 0x0e000000, 0x14000000, 0x1c000000, 0x24000000, 0x32000000
154 };
155 
156 static const FIXP_DBL iidQuantFine_fx[31] = {
157   0x9c000001, 0xa6000001, 0xb0000001, 0xba000001, 0xc4000000, 0xce000000, 0xd4000000, 0xda000000,
158   0xe0000000, 0xe6000000, 0xec000000, 0xf0000000, 0xf4000000, 0xf8000000, 0xfc000000, 0x00000000,
159   0x04000000, 0x08000000, 0x0c000000, 0x10000000, 0x14000000, 0x1a000000, 0x20000000, 0x26000000,
160   0x2c000000, 0x32000000, 0x3c000000, 0x45ffffff, 0x4fffffff, 0x59ffffff, 0x63ffffff
161 };
162 
163 
164 
165 static const FIXP_DBL iccQuant[8] = {
166   0x7fffffff, 0x77ef9d7f, 0x6babc97f, 0x4ceaf27f, 0x2f0ed3c0, 0x00000000, 0xb49ba601, 0x80000000
167 };
168 
InitPSData(HANDLE_PS_DATA hPsData)169 static FDK_PSENC_ERROR InitPSData(
170         HANDLE_PS_DATA            hPsData
171         )
172 {
173   FDK_PSENC_ERROR error = PSENC_OK;
174 
175   if(hPsData == NULL) {
176     error = PSENC_INVALID_HANDLE;
177   }
178   else {
179     int i, env;
180     FDKmemclear(hPsData,sizeof(PS_DATA));
181 
182     for (i=0; i<PS_MAX_BANDS; i++) {
183       hPsData->iidIdxLast[i] = 0;
184       hPsData->iccIdxLast[i] = 0;
185     }
186 
187     hPsData->iidEnable    = hPsData->iidEnableLast = 0;
188     hPsData->iccEnable    = hPsData->iccEnableLast = 0;
189     hPsData->iidQuantMode = hPsData->iidQuantModeLast = PS_IID_RES_COARSE;
190     hPsData->iccQuantMode = hPsData->iccQuantModeLast = PS_ICC_ROT_A;
191 
192     for(env=0; env<PS_MAX_ENVELOPES; env++) {
193       hPsData->iccDiffMode[env] = PS_DELTA_FREQ;
194       hPsData->iccDiffMode[env] = PS_DELTA_FREQ;
195 
196       for (i=0; i<PS_MAX_BANDS; i++) {
197         hPsData->iidIdx[env][i] = 0;
198         hPsData->iccIdx[env][i] = 0;
199       }
200     }
201 
202     hPsData->nEnvelopesLast = 0;
203 
204     hPsData->headerCnt  = MAX_PS_NOHEADER_CNT;
205     hPsData->iidTimeCnt = MAX_TIME_DIFF_FRAMES;
206     hPsData->iccTimeCnt = MAX_TIME_DIFF_FRAMES;
207     hPsData->noEnvCnt   = MAX_NOENV_CNT;
208   }
209 
210   return error;
211 }
212 
quantizeCoef(const FIXP_DBL * RESTRICT input,const INT nBands,const FIXP_DBL * RESTRICT quantTable,const INT idxOffset,const INT nQuantSteps,INT * RESTRICT quantOut)213 static FIXP_DBL quantizeCoef( const FIXP_DBL *RESTRICT input,
214                               const INT       nBands,
215                               const FIXP_DBL *RESTRICT quantTable,
216                               const INT       idxOffset,
217                               const INT       nQuantSteps,
218                               INT            *RESTRICT quantOut)
219 {
220   INT idx, band;
221   FIXP_DBL quantErr = FL2FXCONST_DBL(0.f);
222 
223   for (band=0; band<nBands;band++) {
224     for(idx=0; idx<nQuantSteps-1; idx++){
225       if( fixp_abs((input[band]>>1)-(quantTable[idx+1]>>1)) >
226           fixp_abs((input[band]>>1)-(quantTable[idx]>>1)) )
227       {
228         break;
229       }
230     }
231     quantErr      += (fixp_abs(input[band]-quantTable[idx])>>PS_QUANT_SCALE);   /* don't scale before subtraction; diff smaller (64-25)/64 */
232     quantOut[band] = idx - idxOffset;
233   }
234 
235   return quantErr;
236 }
237 
getICCMode(const INT nBands,const INT rotType)238 static INT getICCMode(const INT nBands,
239                       const INT rotType)
240 {
241   INT mode = 0;
242 
243   switch(nBands) {
244   case PS_BANDS_COARSE:
245     mode = PS_RES_COARSE;
246     break;
247   case PS_BANDS_MID:
248     mode = PS_RES_MID;
249     break;
250   default:
251     mode = 0;
252   }
253   if(rotType==PS_ICC_ROT_B){
254     mode += 3;
255   }
256 
257   return mode;
258 }
259 
260 
getIIDMode(const INT nBands,const INT iidRes)261 static INT getIIDMode(const INT nBands,
262                       const INT iidRes)
263 {
264   INT mode = 0;
265 
266   switch(nBands) {
267   case PS_BANDS_COARSE:
268     mode = PS_RES_COARSE;
269     break;
270   case PS_BANDS_MID:
271     mode = PS_RES_MID;
272     break;
273   default:
274     mode = 0;
275     break;
276   }
277 
278   if(iidRes == PS_IID_RES_FINE){
279     mode += 3;
280   }
281 
282   return mode;
283 }
284 
285 
envelopeReducible(FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS],FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS],INT psBands,INT nEnvelopes)286 static INT envelopeReducible(FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS],
287                              FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS],
288                              INT psBands,
289                              INT nEnvelopes)
290 {
291   #define THRESH_SCALE     7
292 
293   INT reducible = 1; /* true */
294   INT e = 0, b = 0;
295   FIXP_DBL dIid = FL2FXCONST_DBL(0.f);
296   FIXP_DBL dIcc = FL2FXCONST_DBL(0.f);
297 
298   FIXP_DBL iidErrThreshold, iccErrThreshold;
299   FIXP_DBL iidMeanError, iccMeanError;
300 
301   /* square values to prevent sqrt,
302      multiply bands to prevent division; bands shifted DFRACT_BITS instead (DFRACT_BITS-1) because fMultDiv2 used*/
303   iidErrThreshold = fMultDiv2 ( FL2FXCONST_DBL(6.5f*6.5f/(IID_SCALE_FT*IID_SCALE_FT)), (FIXP_DBL)(psBands<<((DFRACT_BITS)-THRESH_SCALE)) );
304   iccErrThreshold = fMultDiv2 ( FL2FXCONST_DBL(0.75f*0.75f),                           (FIXP_DBL)(psBands<<((DFRACT_BITS)-THRESH_SCALE)) );
305 
306   if (nEnvelopes <= 1) {
307     reducible = 0;
308   } else {
309 
310     /* mean error criterion */
311     for (e=0; (e < nEnvelopes/2) && (reducible!=0 ) ; e++) {
312       iidMeanError = iccMeanError = FL2FXCONST_DBL(0.f);
313       for(b=0; b<psBands; b++) {
314         dIid = (iid[2*e][b]>>1) - (iid[2*e+1][b]>>1);   /* scale 1 bit; squared -> 2 bit */
315         dIcc = (icc[2*e][b]>>1) - (icc[2*e+1][b]>>1);
316         iidMeanError += fPow2Div2(dIid)>>(5-1);    /* + (bands=20) scale = 5 */
317         iccMeanError += fPow2Div2(dIcc)>>(5-1);
318       }                                                 /* --> scaling = 7 bit = THRESH_SCALE !! */
319 
320       /* instead sqrt values are squared!
321          instead of division, multiply threshold with psBands
322          scaling necessary!! */
323 
324       /* quit as soon as threshold is reached */
325       if ( (iidMeanError > (iidErrThreshold)) ||
326            (iccMeanError > (iccErrThreshold)) ) {
327         reducible = 0;
328       }
329     }
330   } /* nEnvelopes != 1 */
331 
332   return reducible;
333 }
334 
335 
processIidData(PS_DATA * psData,FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS],const INT psBands,const INT nEnvelopes,const FIXP_DBL quantErrorThreshold)336 static void processIidData(PS_DATA       *psData,
337                            FIXP_DBL       iid[PS_MAX_ENVELOPES][PS_MAX_BANDS],
338                            const INT      psBands,
339                            const INT      nEnvelopes,
340                            const FIXP_DBL quantErrorThreshold)
341 {
342   INT iidIdxFine  [PS_MAX_ENVELOPES][PS_MAX_BANDS];
343   INT iidIdxCoarse[PS_MAX_ENVELOPES][PS_MAX_BANDS];
344 
345   FIXP_DBL errIID = FL2FXCONST_DBL(0.f);
346   FIXP_DBL errIIDFine = FL2FXCONST_DBL(0.f);
347   INT   bitsIidFreq = 0;
348   INT   bitsIidTime = 0;
349   INT   bitsFineTot = 0;
350   INT   bitsCoarseTot = 0;
351   INT   error = 0;
352   INT   env, band;
353   INT   diffMode[PS_MAX_ENVELOPES], diffModeFine[PS_MAX_ENVELOPES];
354   INT loudnDiff = 0;
355   INT iidTransmit = 0;
356 
357   bitsIidFreq = bitsIidTime = 0;
358 
359   /* Quantize IID coefficients */
360   for(env=0;env<nEnvelopes; env++) {
361     errIID     += quantizeCoef(iid[env], psBands, iidQuant_fx,      7, 15, iidIdxCoarse[env]);
362     errIIDFine += quantizeCoef(iid[env], psBands, iidQuantFine_fx, 15, 31, iidIdxFine[env]);
363   }
364 
365   /* normalize error to number of envelopes, ps bands
366      errIID /= psBands*nEnvelopes;
367      errIIDFine /= psBands*nEnvelopes; */
368 
369 
370   /* Check if IID coefficients should be used in this frame */
371   psData->iidEnable = 0;
372   for(env=0;env<nEnvelopes; env++) {
373     for(band=0;band<psBands;band++) {
374       loudnDiff   += fixp_abs(iidIdxCoarse[env][band]);
375       iidTransmit ++;
376     }
377   }
378 
379   if(loudnDiff > fMultI(FL2FXCONST_DBL(0.7f),iidTransmit)){    /* 0.7f empiric value */
380     psData->iidEnable = 1;
381   }
382 
383   /* if iid not active -> RESET data */
384   if(psData->iidEnable==0) {
385     psData->iidTimeCnt = MAX_TIME_DIFF_FRAMES;
386     for(env=0;env<nEnvelopes; env++) {
387       psData->iidDiffMode[env] = PS_DELTA_FREQ;
388       FDKmemclear(psData->iidIdx[env], sizeof(INT)*psBands);
389     }
390     return;
391   }
392 
393   /* count COARSE quantization bits for first envelope*/
394   bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[0], NULL, psBands, PS_IID_RES_COARSE, PS_DELTA_FREQ, &error);
395 
396   if( (psData->iidTimeCnt>=MAX_TIME_DIFF_FRAMES) || (psData->iidQuantModeLast==PS_IID_RES_FINE) ) {
397     bitsIidTime     = DO_NOT_USE_THIS_MODE;
398   }
399   else {
400     bitsIidTime     = FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[0], psData->iidIdxLast, psBands, PS_IID_RES_COARSE, PS_DELTA_TIME, &error);
401   }
402 
403   /* decision DELTA_FREQ vs DELTA_TIME */
404   if(bitsIidTime>bitsIidFreq) {
405     diffMode[0]   = PS_DELTA_FREQ;
406     bitsCoarseTot = bitsIidFreq;
407   }
408   else {
409     diffMode[0]   = PS_DELTA_TIME;
410     bitsCoarseTot = bitsIidTime;
411   }
412 
413   /* count COARSE quantization bits for following envelopes*/
414   for(env=1;env<nEnvelopes; env++) {
415     bitsIidFreq  = FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[env], NULL,                psBands, PS_IID_RES_COARSE, PS_DELTA_FREQ, &error);
416     bitsIidTime  = FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[env], iidIdxCoarse[env-1], psBands, PS_IID_RES_COARSE, PS_DELTA_TIME, &error);
417 
418     /* decision DELTA_FREQ vs DELTA_TIME */
419     if(bitsIidTime>bitsIidFreq) {
420       diffMode[env]  = PS_DELTA_FREQ;
421       bitsCoarseTot += bitsIidFreq;
422     }
423     else {
424       diffMode[env]  = PS_DELTA_TIME;
425       bitsCoarseTot += bitsIidTime;
426     }
427   }
428 
429 
430   /* count FINE quantization bits for first envelope*/
431   bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxFine[0],   NULL, psBands, PS_IID_RES_FINE,   PS_DELTA_FREQ, &error);
432 
433   if( (psData->iidTimeCnt>=MAX_TIME_DIFF_FRAMES) || (psData->iidQuantModeLast==PS_IID_RES_COARSE) ) {
434     bitsIidTime = DO_NOT_USE_THIS_MODE;
435   }
436   else {
437     bitsIidTime = FDKsbrEnc_EncodeIid(NULL, iidIdxFine[0],  psData->iidIdxLast, psBands, PS_IID_RES_FINE, PS_DELTA_TIME, &error);
438   }
439 
440   /* decision DELTA_FREQ vs DELTA_TIME */
441   if(bitsIidTime>bitsIidFreq) {
442     diffModeFine[0]   = PS_DELTA_FREQ;
443     bitsFineTot       = bitsIidFreq;
444   }
445   else {
446     diffModeFine[0]   = PS_DELTA_TIME;
447     bitsFineTot       = bitsIidTime;
448   }
449 
450   /* count FINE quantization bits for following envelopes*/
451   for(env=1;env<nEnvelopes; env++) {
452     bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxFine[env],   NULL,              psBands, PS_IID_RES_FINE, PS_DELTA_FREQ, &error);
453     bitsIidTime = FDKsbrEnc_EncodeIid(NULL, iidIdxFine[env],   iidIdxFine[env-1], psBands, PS_IID_RES_FINE, PS_DELTA_TIME, &error);
454 
455     /* decision DELTA_FREQ vs DELTA_TIME */
456     if(bitsIidTime>bitsIidFreq) {
457       diffModeFine[env]  = PS_DELTA_FREQ;
458       bitsFineTot += bitsIidFreq;
459     }
460     else {
461       diffModeFine[env]  = PS_DELTA_TIME;
462       bitsFineTot       += bitsIidTime;
463     }
464   }
465 
466   if(bitsFineTot == bitsCoarseTot){
467     /* if same number of bits is needed, use the quantization with lower error */
468     if(errIIDFine < errIID){
469       bitsCoarseTot = DO_NOT_USE_THIS_MODE;
470     } else {
471       bitsFineTot = DO_NOT_USE_THIS_MODE;
472     }
473   } else {
474     /* const FIXP_DBL minThreshold = FL2FXCONST_DBL(0.2f/(IID_SCALE_FT*PS_QUANT_SCALE_FT)*(psBands*nEnvelopes)); */
475     const FIXP_DBL minThreshold = (FIXP_DBL)((LONG)0x00019999 * (psBands*nEnvelopes));
476 
477     /* decision RES_FINE vs RES_COARSE                 */
478     /* test if errIIDFine*quantErrorThreshold < errIID */
479     /* shiftVal 2 comes from scaling of quantErrorThreshold */
480     if(fixMax(((errIIDFine>>1)+(minThreshold>>1))>>1, fMult(quantErrorThreshold,errIIDFine)) < (errIID>>2) ) {
481       bitsCoarseTot = DO_NOT_USE_THIS_MODE;
482     }
483     else if(fixMax(((errIID>>1)+(minThreshold>>1))>>1, fMult(quantErrorThreshold,errIID)) < (errIIDFine>>2) ) {
484       bitsFineTot = DO_NOT_USE_THIS_MODE;
485     }
486   }
487 
488   /* decision RES_FINE vs RES_COARSE */
489   if(bitsFineTot<bitsCoarseTot) {
490     psData->iidQuantMode = PS_IID_RES_FINE;
491     for(env=0;env<nEnvelopes; env++) {
492       psData->iidDiffMode[env] = diffModeFine[env];
493       FDKmemcpy(psData->iidIdx[env], iidIdxFine[env], psBands*sizeof(INT));
494     }
495   }
496   else {
497     psData->iidQuantMode = PS_IID_RES_COARSE;
498     for(env=0;env<nEnvelopes; env++) {
499       psData->iidDiffMode[env] = diffMode[env];
500       FDKmemcpy(psData->iidIdx[env], iidIdxCoarse[env], psBands*sizeof(INT));
501     }
502   }
503 
504   /* Count DELTA_TIME encoding streaks */
505   for(env=0;env<nEnvelopes; env++) {
506     if(psData->iidDiffMode[env]==PS_DELTA_TIME)
507       psData->iidTimeCnt++;
508     else
509       psData->iidTimeCnt=0;
510   }
511 }
512 
513 
similarIid(PS_DATA * psData,const INT psBands,const INT nEnvelopes)514 static INT similarIid(PS_DATA   *psData,
515                       const INT  psBands,
516                       const INT  nEnvelopes)
517 {
518   const INT diffThr = (psData->iidQuantMode == PS_IID_RES_COARSE) ? 2 : 3;
519   const INT sumDiffThr = diffThr * psBands/4;
520   INT similar = 0;
521   INT diff    = 0;
522   INT sumDiff = 0;
523   INT env = 0;
524   INT b   = 0;
525   if ((nEnvelopes == psData->nEnvelopesLast) && (nEnvelopes==1)) {
526     similar = 1;
527     for (env=0; env<nEnvelopes; env++) {
528       sumDiff = 0;
529       b = 0;
530       do {
531         diff = fixp_abs(psData->iidIdx[env][b] - psData->iidIdxLast[b]);
532         sumDiff += diff;
533         if ( (diff > diffThr) /* more than x quantization steps in any band */
534              || (sumDiff > sumDiffThr) ) {  /* more than x quantisations steps overall difference */
535           similar = 0;
536         }
537         b++;
538       } while ((b<psBands) && (similar>0));
539     }
540   } /* nEnvelopes==1  */
541 
542   return similar;
543 }
544 
545 
similarIcc(PS_DATA * psData,const INT psBands,const INT nEnvelopes)546 static INT similarIcc(PS_DATA *psData,
547                       const INT    psBands,
548                       const INT    nEnvelopes)
549 {
550   const INT diffThr = 2;
551   const INT sumDiffThr = diffThr * psBands/4;
552   INT similar = 0;
553   INT diff    = 0;
554   INT sumDiff = 0;
555   INT env = 0;
556   INT b   = 0;
557   if ((nEnvelopes == psData->nEnvelopesLast) && (nEnvelopes==1)) {
558     similar = 1;
559     for (env=0; env<nEnvelopes; env++) {
560       sumDiff = 0;
561       b = 0;
562       do {
563         diff = fixp_abs(psData->iccIdx[env][b] - psData->iccIdxLast[b]);
564         sumDiff += diff;
565         if ( (diff > diffThr) /* more than x quantisation step in any band */
566              || (sumDiff > sumDiffThr) ) {  /* more than x quantisations steps overall difference */
567           similar = 0;
568         }
569         b++;
570       } while ((b<psBands) && (similar>0));
571     }
572   } /* nEnvelopes==1  */
573 
574   return similar;
575 }
576 
processIccData(PS_DATA * psData,FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS],const INT psBands,const INT nEnvelopes)577 static void processIccData(PS_DATA   *psData,
578                            FIXP_DBL   icc[PS_MAX_ENVELOPES][PS_MAX_BANDS], /* const input values: unable to declare as const, since it does not poINT to const memory */
579                            const INT  psBands,
580                            const INT  nEnvelopes)
581 {
582   FIXP_DBL errICC = FL2FXCONST_DBL(0.f);
583   INT   env, band;
584   INT   bitsIccFreq, bitsIccTime;
585   INT   error = 0;
586   INT   inCoherence=0, iccTransmit=0;
587   INT  *iccIdxLast;
588 
589   iccIdxLast = psData->iccIdxLast;
590 
591   /* Quantize ICC coefficients */
592   for(env=0;env<nEnvelopes; env++) {
593     errICC += quantizeCoef(icc[env], psBands, iccQuant, 0, 8, psData->iccIdx[env]);
594   }
595 
596   /* Check if ICC coefficients should be used */
597   psData->iccEnable = 0;
598   for(env=0;env<nEnvelopes; env++) {
599     for(band=0;band<psBands;band++) {
600       inCoherence += psData->iccIdx[env][band];
601       iccTransmit ++;
602     }
603   }
604   if(inCoherence > fMultI(FL2FXCONST_DBL(0.5f),iccTransmit)){   /* 0.5f empiric value */
605     psData->iccEnable = 1;
606   }
607 
608   if(psData->iccEnable==0) {
609     psData->iccTimeCnt = MAX_TIME_DIFF_FRAMES;
610     for(env=0;env<nEnvelopes; env++) {
611       psData->iccDiffMode[env] = PS_DELTA_FREQ;
612       FDKmemclear(psData->iccIdx[env], sizeof(INT)*psBands);
613     }
614     return;
615   }
616 
617   for(env=0;env<nEnvelopes; env++) {
618     bitsIccFreq  = FDKsbrEnc_EncodeIcc(NULL, psData->iccIdx[env],   NULL,       psBands, PS_DELTA_FREQ, &error);
619 
620     if(psData->iccTimeCnt<MAX_TIME_DIFF_FRAMES) {
621       bitsIccTime  = FDKsbrEnc_EncodeIcc(NULL, psData->iccIdx[env], iccIdxLast, psBands, PS_DELTA_TIME, &error);
622     }
623     else {
624       bitsIccTime  = DO_NOT_USE_THIS_MODE;
625     }
626 
627     if(bitsIccFreq>bitsIccTime) {
628       psData->iccDiffMode[env] = PS_DELTA_TIME;
629       psData->iccTimeCnt++;
630     }
631     else {
632       psData->iccDiffMode[env] = PS_DELTA_FREQ;
633       psData->iccTimeCnt=0;
634     }
635     iccIdxLast = psData->iccIdx[env];
636   }
637 }
638 
calculateIID(FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS],FIXP_DBL ldPwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS],FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS],INT nEnvelopes,INT psBands)639 static void calculateIID(FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS],
640                          FIXP_DBL ldPwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS],
641                          FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS],
642                          INT   nEnvelopes,
643                          INT   psBands)
644 {
645   INT i=0;
646   INT env=0;
647   for(env=0; env<nEnvelopes;env++) {
648     for (i=0; i<psBands; i++) {
649 
650       /* iid[env][i] = 10.0f*(float)log10(pwrL[env][i]/pwrR[env][i]);
651       */
652       FIXP_DBL IID = fMultDiv2( FL2FXCONST_DBL(LOG10_2_10/IID_SCALE_FT), (ldPwrL[env][i]-ldPwrR[env][i]) );
653 
654       IID = fixMin( IID, (FIXP_DBL)(MAXVAL_DBL>>(LD_DATA_SHIFT+1)) );
655       IID = fixMax( IID, (FIXP_DBL)(MINVAL_DBL>>(LD_DATA_SHIFT+1)) );
656       iid[env][i] = IID << (LD_DATA_SHIFT+1);
657     }
658   }
659 }
660 
calculateICC(FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS],FIXP_DBL ldPwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS],FIXP_DBL pwrCr[PS_MAX_ENVELOPES][PS_MAX_BANDS],FIXP_DBL pwrCi[PS_MAX_ENVELOPES][PS_MAX_BANDS],FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS],INT nEnvelopes,INT psBands)661 static void calculateICC(FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS],
662                          FIXP_DBL ldPwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS],
663                          FIXP_DBL pwrCr[PS_MAX_ENVELOPES][PS_MAX_BANDS],
664                          FIXP_DBL pwrCi[PS_MAX_ENVELOPES][PS_MAX_BANDS],
665                          FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS],
666                          INT   nEnvelopes,
667                          INT   psBands)
668 {
669   INT i = 0;
670   INT env = 0;
671   INT border = psBands;
672 
673   switch (psBands) {
674   case PS_BANDS_COARSE:
675     border = 5;
676     break;
677   case PS_BANDS_MID:
678     border = 11;
679     break;
680   default:
681     break;
682   }
683 
684   for(env=0; env<nEnvelopes;env++) {
685     for (i=0; i<border; i++) {
686 
687       /* icc[env][i] = min( pwrCr[env][i] / (float) sqrt(pwrL[env][i] * pwrR[env][i]) , 1.f);
688       */
689       FIXP_DBL ICC, invNrg = CalcInvLdData ( -((ldPwrL[env][i]>>1) + (ldPwrR[env][i]>>1) + (FIXP_DBL)1) );
690       INT      scale, invScale = CountLeadingBits(invNrg);
691 
692       scale = (DFRACT_BITS-1) - invScale;
693       ICC = fMult(pwrCr[env][i], invNrg<<invScale) ;
694       icc[env][i] = SATURATE_LEFT_SHIFT(ICC, scale, DFRACT_BITS);
695     }
696 
697     for (; i<psBands; i++) {
698       INT sc1, sc2;
699       FIXP_DBL cNrgR, cNrgI, ICC;
700 
701       sc1 = CountLeadingBits( fixMax(fixp_abs(pwrCr[env][i]),fixp_abs(pwrCi[env][i])) ) ;
702       cNrgR = fPow2Div2((pwrCr[env][i]<<sc1));       /* squared nrg's expect explicit scaling */
703       cNrgI = fPow2Div2((pwrCi[env][i]<<sc1));
704 
705       ICC = CalcInvLdData( (CalcLdData((cNrgR + cNrgI)>>1)>>1) - (FIXP_DBL)((sc1-1)<<(DFRACT_BITS-1-LD_DATA_SHIFT)) );
706 
707       FIXP_DBL invNrg = CalcInvLdData ( -((ldPwrL[env][i]>>1) + (ldPwrR[env][i]>>1) + (FIXP_DBL)1) );
708       sc1 = CountLeadingBits(invNrg);
709       invNrg <<= sc1;
710 
711       sc2 = CountLeadingBits(ICC);
712       ICC = fMult(ICC<<sc2,invNrg);
713 
714       sc1 = ( (DFRACT_BITS-1) - sc1 - sc2 );
715       if (sc1 < 0) {
716           ICC >>= -sc1;
717       }
718       else {
719           if (ICC >= ((FIXP_DBL)MAXVAL_DBL>>sc1) )
720               ICC = (FIXP_DBL)MAXVAL_DBL;
721           else
722               ICC <<= sc1;
723       }
724 
725       icc[env][i] = ICC;
726     }
727   }
728 }
729 
FDKsbrEnc_initPsBandNrgScale(HANDLE_PS_ENCODE hPsEncode)730 void FDKsbrEnc_initPsBandNrgScale(HANDLE_PS_ENCODE hPsEncode)
731 {
732   INT group, bin;
733   INT nIidGroups   = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups;
734 
735   FDKmemclear(hPsEncode->psBandNrgScale, PS_MAX_BANDS*sizeof(SCHAR));
736 
737   for (group=0; group < nIidGroups; group++) {
738     /* Translate group to bin */
739     bin = hPsEncode->subband2parameterIndex[group];
740 
741     /* Translate from 20 bins to 10 bins */
742     if (hPsEncode->psEncMode == PS_BANDS_COARSE) {
743       bin = bin>>1;
744     }
745 
746     hPsEncode->psBandNrgScale[bin] = (hPsEncode->psBandNrgScale[bin]==0)
747                           ? (hPsEncode->iidGroupWidthLd[group] + 5)
748                           : (fixMax(hPsEncode->iidGroupWidthLd[group],hPsEncode->psBandNrgScale[bin]) + 1) ;
749 
750   }
751 }
752 
FDKsbrEnc_CreatePSEncode(HANDLE_PS_ENCODE * phPsEncode)753 FDK_PSENC_ERROR FDKsbrEnc_CreatePSEncode(
754         HANDLE_PS_ENCODE         *phPsEncode
755         )
756 {
757   FDK_PSENC_ERROR error = PSENC_OK;
758 
759   if (phPsEncode==NULL) {
760     error = PSENC_INVALID_HANDLE;
761   }
762   else {
763     HANDLE_PS_ENCODE hPsEncode = NULL;
764     if (NULL==(hPsEncode = GetRam_PsEncode())) {
765       error = PSENC_MEMORY_ERROR;
766       goto bail;
767     }
768     FDKmemclear(hPsEncode,sizeof(PS_ENCODE));
769     *phPsEncode = hPsEncode; /* return allocated handle */
770   }
771 bail:
772   return error;
773 }
774 
FDKsbrEnc_InitPSEncode(HANDLE_PS_ENCODE hPsEncode,const PS_BANDS psEncMode,const FIXP_DBL iidQuantErrorThreshold)775 FDK_PSENC_ERROR FDKsbrEnc_InitPSEncode(
776         HANDLE_PS_ENCODE          hPsEncode,
777         const PS_BANDS            psEncMode,
778         const FIXP_DBL            iidQuantErrorThreshold
779         )
780 {
781   FDK_PSENC_ERROR error = PSENC_OK;
782 
783   if (NULL==hPsEncode) {
784     error = PSENC_INVALID_HANDLE;
785   }
786   else {
787     if (PSENC_OK != (InitPSData(&hPsEncode->psData))) {
788       goto bail;
789     }
790 
791     switch(psEncMode){
792       case PS_BANDS_COARSE:
793       case PS_BANDS_MID:
794         hPsEncode->nQmfIidGroups    = QMF_GROUPS_LO_RES;
795         hPsEncode->nSubQmfIidGroups = SUBQMF_GROUPS_LO_RES;
796         FDKmemcpy(hPsEncode->iidGroupBorders,        iidGroupBordersLoRes, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups + 1)*sizeof(INT));
797         FDKmemcpy(hPsEncode->subband2parameterIndex, subband2parameter20,  (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups)    *sizeof(INT));
798         FDKmemcpy(hPsEncode->iidGroupWidthLd,        iidGroupWidthLdLoRes, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups)    *sizeof(UCHAR));
799         break;
800       default:
801         error = PSENC_INIT_ERROR;
802         goto bail;
803     }
804 
805     hPsEncode->psEncMode = psEncMode;
806     hPsEncode->iidQuantErrorThreshold = iidQuantErrorThreshold;
807     FDKsbrEnc_initPsBandNrgScale(hPsEncode);
808   }
809 bail:
810   return error;
811 }
812 
813 
FDKsbrEnc_DestroyPSEncode(HANDLE_PS_ENCODE * phPsEncode)814 FDK_PSENC_ERROR FDKsbrEnc_DestroyPSEncode(
815         HANDLE_PS_ENCODE         *phPsEncode
816         )
817 {
818   FDK_PSENC_ERROR error = PSENC_OK;
819 
820   if (NULL !=phPsEncode) {
821     FreeRam_PsEncode(phPsEncode);
822   }
823 
824   return error;
825 }
826 
827 typedef struct {
828   FIXP_DBL pwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS];
829   FIXP_DBL pwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS];
830   FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS];
831   FIXP_DBL ldPwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS];
832   FIXP_DBL pwrCr[PS_MAX_ENVELOPES][PS_MAX_BANDS];
833   FIXP_DBL pwrCi[PS_MAX_ENVELOPES][PS_MAX_BANDS];
834 
835 } PS_PWR_DATA;
836 
837 
FDKsbrEnc_PSEncode(HANDLE_PS_ENCODE hPsEncode,HANDLE_PS_OUT hPsOut,UCHAR * dynBandScale,UINT maxEnvelopes,FIXP_DBL * hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2],const INT frameSize,const INT sendHeader)838 FDK_PSENC_ERROR FDKsbrEnc_PSEncode(
839         HANDLE_PS_ENCODE          hPsEncode,
840         HANDLE_PS_OUT             hPsOut,
841         UCHAR                    *dynBandScale,
842         UINT                      maxEnvelopes,
843         FIXP_DBL                 *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2],
844         const INT                 frameSize,
845         const INT                 sendHeader
846         )
847 {
848   FDK_PSENC_ERROR error = PSENC_OK;
849 
850   HANDLE_PS_DATA hPsData = &hPsEncode->psData;
851   FIXP_DBL iid [PS_MAX_ENVELOPES][PS_MAX_BANDS];
852   FIXP_DBL icc [PS_MAX_ENVELOPES][PS_MAX_BANDS];
853   int envBorder[PS_MAX_ENVELOPES+1];
854 
855   int group, bin, col, subband, band;
856   int i = 0;
857 
858   int env = 0;
859   int psBands      = (int) hPsEncode->psEncMode;
860   int nIidGroups   = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups;
861   int nEnvelopes   = fixMin(maxEnvelopes, (UINT)PS_MAX_ENVELOPES);
862 
863   C_ALLOC_SCRATCH_START(pwrData, PS_PWR_DATA, 1);
864 
865   for(env=0; env<nEnvelopes+1;env++) {
866     envBorder[env] = fMultI(GetInvInt(nEnvelopes),frameSize*env);
867   }
868 
869   for(env=0; env<nEnvelopes;env++) {
870 
871     /* clear energy array */
872     for (band=0; band<psBands; band++) {
873       pwrData->pwrL[env][band] = pwrData->pwrR[env][band] = pwrData->pwrCr[env][band] = pwrData->pwrCi[env][band] = FIXP_DBL(1);
874     }
875 
876     /**** calculate energies and correlation ****/
877 
878     /* start with hybrid data */
879     for (group=0; group < nIidGroups; group++) {
880       /* Translate group to bin */
881       bin = hPsEncode->subband2parameterIndex[group];
882 
883       /* Translate from 20 bins to 10 bins */
884       if (hPsEncode->psEncMode == PS_BANDS_COARSE) {
885         bin >>= 1;
886       }
887 
888       /* determine group border */
889       int bScale = hPsEncode->psBandNrgScale[bin];
890 
891       FIXP_DBL pwrL_env_bin = pwrData->pwrL[env][bin];
892       FIXP_DBL pwrR_env_bin = pwrData->pwrR[env][bin];
893       FIXP_DBL pwrCr_env_bin = pwrData->pwrCr[env][bin];
894       FIXP_DBL pwrCi_env_bin = pwrData->pwrCi[env][bin];
895 
896       int scale = (int)dynBandScale[bin];
897       for (col=envBorder[env]; col<envBorder[env+1]; col++) {
898         for (subband = hPsEncode->iidGroupBorders[group]; subband < hPsEncode->iidGroupBorders[group+1]; subband++) {
899           FIXP_QMF l_real = (hybridData[col][0][0][subband]) << scale;
900           FIXP_QMF l_imag = (hybridData[col][0][1][subband]) << scale;
901           FIXP_QMF r_real = (hybridData[col][1][0][subband]) << scale;
902           FIXP_QMF r_imag = (hybridData[col][1][1][subband]) << scale;
903 
904           pwrL_env_bin  += (fPow2Div2(l_real) + fPow2Div2(l_imag)) >> bScale;
905           pwrR_env_bin  += (fPow2Div2(r_real) + fPow2Div2(r_imag)) >> bScale;
906           pwrCr_env_bin += (fMultDiv2(l_real, r_real) + fMultDiv2(l_imag, r_imag)) >> bScale;
907           pwrCi_env_bin += (fMultDiv2(r_real, l_imag) - fMultDiv2(l_real, r_imag)) >> bScale;
908         }
909       }
910       /* assure, nrg's of left and right channel are not negative; necessary on 16 bit multiply units */
911       pwrData->pwrL[env][bin] = fixMax((FIXP_DBL)0,pwrL_env_bin);
912       pwrData->pwrR[env][bin] = fixMax((FIXP_DBL)0,pwrR_env_bin);
913 
914       pwrData->pwrCr[env][bin] = pwrCr_env_bin;
915       pwrData->pwrCi[env][bin] = pwrCi_env_bin;
916 
917     } /* nIidGroups */
918 
919     /* calc logarithmic energy */
920     LdDataVector(pwrData->pwrL[env], pwrData->ldPwrL[env], psBands);
921     LdDataVector(pwrData->pwrR[env], pwrData->ldPwrR[env], psBands);
922 
923   } /* nEnvelopes */
924 
925   /* calculate iid and icc */
926   calculateIID(pwrData->ldPwrL, pwrData->ldPwrR, iid, nEnvelopes, psBands);
927   calculateICC(pwrData->ldPwrL, pwrData->ldPwrR, pwrData->pwrCr, pwrData->pwrCi, icc, nEnvelopes, psBands);
928 
929   /*** Envelope Reduction ***/
930   while (envelopeReducible(iid,icc,psBands,nEnvelopes)) {
931     int e=0;
932     /* sum energies of two neighboring envelopes */
933     nEnvelopes >>= 1;
934     for (e=0; e<nEnvelopes; e++) {
935       FDKsbrEnc_addFIXP_DBL(pwrData->pwrL[2*e], pwrData->pwrL[2*e+1], pwrData->pwrL[e], psBands);
936       FDKsbrEnc_addFIXP_DBL(pwrData->pwrR[2*e], pwrData->pwrR[2*e+1], pwrData->pwrR[e], psBands);
937       FDKsbrEnc_addFIXP_DBL(pwrData->pwrCr[2*e],pwrData->pwrCr[2*e+1],pwrData->pwrCr[e],psBands);
938       FDKsbrEnc_addFIXP_DBL(pwrData->pwrCi[2*e],pwrData->pwrCi[2*e+1],pwrData->pwrCi[e],psBands);
939 
940       /* calc logarithmic energy */
941       LdDataVector(pwrData->pwrL[e], pwrData->ldPwrL[e], psBands);
942       LdDataVector(pwrData->pwrR[e], pwrData->ldPwrR[e], psBands);
943 
944       /* reduce number of envelopes and adjust borders */
945       envBorder[e] = envBorder[2*e];
946     }
947     envBorder[nEnvelopes] = envBorder[2*nEnvelopes];
948 
949     /* re-calculate iid and icc */
950     calculateIID(pwrData->ldPwrL, pwrData->ldPwrR, iid, nEnvelopes, psBands);
951     calculateICC(pwrData->ldPwrL, pwrData->ldPwrR, pwrData->pwrCr, pwrData->pwrCi, icc, nEnvelopes, psBands);
952   }
953 
954 
955   /*  */
956   if(sendHeader) {
957     hPsData->headerCnt  = MAX_PS_NOHEADER_CNT;
958     hPsData->iidTimeCnt = MAX_TIME_DIFF_FRAMES;
959     hPsData->iccTimeCnt = MAX_TIME_DIFF_FRAMES;
960     hPsData->noEnvCnt   = MAX_NOENV_CNT;
961   }
962 
963   /*** Parameter processing, quantisation etc ***/
964   processIidData(hPsData, iid, psBands, nEnvelopes, hPsEncode->iidQuantErrorThreshold);
965   processIccData(hPsData, icc, psBands, nEnvelopes);
966 
967 
968   /*** Initialize output struct ***/
969 
970   /* PS Header on/off ? */
971   if( (hPsData->headerCnt<MAX_PS_NOHEADER_CNT)
972        && ( (hPsData->iidQuantMode == hPsData->iidQuantModeLast) && (hPsData->iccQuantMode == hPsData->iccQuantModeLast) )
973        && ( (hPsData->iidEnable    == hPsData->iidEnableLast)    && (hPsData->iccEnable    == hPsData->iccEnableLast)  ) ) {
974     hPsOut->enablePSHeader = 0;
975   }
976   else {
977     hPsOut->enablePSHeader = 1;
978     hPsData->headerCnt = 0;
979   }
980 
981   /* nEnvelopes = 0 ? */
982   if ( (hPsData->noEnvCnt < MAX_NOENV_CNT)
983        && (similarIid(hPsData, psBands, nEnvelopes))
984        && (similarIcc(hPsData, psBands, nEnvelopes)) ) {
985     hPsOut->nEnvelopes = nEnvelopes = 0;
986     hPsData->noEnvCnt++;
987   } else {
988     hPsData->noEnvCnt = 0;
989   }
990 
991 
992   if (nEnvelopes>0) {
993 
994     hPsOut->enableIID      = hPsData->iidEnable;
995     hPsOut->iidMode        = getIIDMode(psBands, hPsData->iidQuantMode);
996 
997     hPsOut->enableICC      = hPsData->iccEnable;
998     hPsOut->iccMode        = getICCMode(psBands, hPsData->iccQuantMode);
999 
1000     hPsOut->enableIpdOpd  = 0;
1001     hPsOut->frameClass    = 0;
1002     hPsOut->nEnvelopes    = nEnvelopes;
1003 
1004     for(env=0; env<nEnvelopes; env++) {
1005       hPsOut->frameBorder[env] = envBorder[env+1];
1006     }
1007 
1008     for(env=0; env<hPsOut->nEnvelopes; env++) {
1009       hPsOut->deltaIID[env] = (PS_DELTA)hPsData->iidDiffMode[env];
1010 
1011       for(band=0; band<psBands; band++) {
1012         hPsOut->iid[env][band] = hPsData->iidIdx[env][band];
1013       }
1014     }
1015 
1016     for(env=0; env<hPsOut->nEnvelopes; env++) {
1017       hPsOut->deltaICC[env] = (PS_DELTA)hPsData->iccDiffMode[env];
1018       for(band=0; band<psBands; band++) {
1019         hPsOut->icc[env][band] = hPsData->iccIdx[env][band];
1020       }
1021     }
1022 
1023     /* IPD OPD not supported right now */
1024     FDKmemclear(hPsOut->ipd, PS_MAX_ENVELOPES*PS_MAX_BANDS*sizeof(PS_DELTA));
1025     for(env=0; env<PS_MAX_ENVELOPES; env++) {
1026       hPsOut->deltaIPD[env] = PS_DELTA_FREQ;
1027       hPsOut->deltaOPD[env] = PS_DELTA_FREQ;
1028     }
1029 
1030     FDKmemclear(hPsOut->ipdLast, PS_MAX_BANDS*sizeof(INT));
1031     FDKmemclear(hPsOut->opdLast, PS_MAX_BANDS*sizeof(INT));
1032 
1033     for(band=0; band<PS_MAX_BANDS; band++) {
1034       hPsOut->iidLast[band] = hPsData->iidIdxLast[band];
1035       hPsOut->iccLast[band] = hPsData->iccIdxLast[band];
1036     }
1037 
1038     /* save iids and iccs for differential time coding in the next frame */
1039     hPsData->nEnvelopesLast   = nEnvelopes;
1040     hPsData->iidEnableLast    = hPsData->iidEnable;
1041     hPsData->iccEnableLast    = hPsData->iccEnable;
1042     hPsData->iidQuantModeLast = hPsData->iidQuantMode;
1043     hPsData->iccQuantModeLast = hPsData->iccQuantMode;
1044     for (i=0; i<psBands; i++) {
1045       hPsData->iidIdxLast[i] = hPsData->iidIdx[nEnvelopes-1][i];
1046       hPsData->iccIdxLast[i] = hPsData->iccIdx[nEnvelopes-1][i];
1047     }
1048   } /* Envelope > 0 */
1049 
1050   C_ALLOC_SCRATCH_END(pwrData, PS_PWR_DATA, 1)
1051 
1052   return error;
1053 }
1054 
1055