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