• 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. Multrus
98 
99    Description: PS Wrapper, Downmix
100 
101 *******************************************************************************/
102 
103 #include "ps_main.h"
104 
105 /* Includes ******************************************************************/
106 #include "ps_bitenc.h"
107 #include "sbrenc_ram.h"
108 
109 /*--------------- function declarations --------------------*/
110 static void psFindBestScaling(
111     HANDLE_PARAMETRIC_STEREO hParametricStereo,
112     FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2],
113     UCHAR *dynBandScale, FIXP_DBL *maxBandValue, SCHAR *dmxScale);
114 
115 /*------------- function definitions ----------------*/
PSEnc_Create(HANDLE_PARAMETRIC_STEREO * phParametricStereo)116 FDK_PSENC_ERROR PSEnc_Create(HANDLE_PARAMETRIC_STEREO *phParametricStereo) {
117   FDK_PSENC_ERROR error = PSENC_OK;
118   HANDLE_PARAMETRIC_STEREO hParametricStereo = NULL;
119 
120   if (phParametricStereo == NULL) {
121     error = PSENC_INVALID_HANDLE;
122   } else {
123     int i;
124 
125     if (NULL == (hParametricStereo = GetRam_ParamStereo())) {
126       error = PSENC_MEMORY_ERROR;
127       goto bail;
128     }
129     FDKmemclear(hParametricStereo, sizeof(PARAMETRIC_STEREO));
130 
131     if (PSENC_OK !=
132         (error = FDKsbrEnc_CreatePSEncode(&hParametricStereo->hPsEncode))) {
133       error = PSENC_MEMORY_ERROR;
134       goto bail;
135     }
136 
137     for (i = 0; i < MAX_PS_CHANNELS; i++) {
138       if (FDKhybridAnalysisOpen(
139               &hParametricStereo->fdkHybAnaFilter[i],
140               hParametricStereo->__staticHybAnaStatesLF[i],
141               sizeof(hParametricStereo->__staticHybAnaStatesLF[i]),
142               hParametricStereo->__staticHybAnaStatesHF[i],
143               sizeof(hParametricStereo->__staticHybAnaStatesHF[i])) != 0) {
144         error = PSENC_MEMORY_ERROR;
145         goto bail;
146       }
147     }
148   }
149 
150 bail:
151   if (phParametricStereo != NULL) {
152     *phParametricStereo = hParametricStereo; /* return allocated handle */
153   }
154 
155   if (error != PSENC_OK) {
156     PSEnc_Destroy(phParametricStereo);
157   }
158   return error;
159 }
160 
PSEnc_Init(HANDLE_PARAMETRIC_STEREO hParametricStereo,const HANDLE_PSENC_CONFIG hPsEncConfig,INT noQmfSlots,INT noQmfBands,UCHAR * dynamic_RAM)161 FDK_PSENC_ERROR PSEnc_Init(HANDLE_PARAMETRIC_STEREO hParametricStereo,
162                            const HANDLE_PSENC_CONFIG hPsEncConfig,
163                            INT noQmfSlots, INT noQmfBands, UCHAR *dynamic_RAM) {
164   FDK_PSENC_ERROR error = PSENC_OK;
165 
166   if ((NULL == hParametricStereo) || (NULL == hPsEncConfig)) {
167     error = PSENC_INVALID_HANDLE;
168   } else {
169     int ch, i;
170 
171     hParametricStereo->initPS = 1;
172     hParametricStereo->noQmfSlots = noQmfSlots;
173     hParametricStereo->noQmfBands = noQmfBands;
174 
175     /* clear delay lines */
176     FDKmemclear(hParametricStereo->qmfDelayLines,
177                 sizeof(hParametricStereo->qmfDelayLines));
178 
179     hParametricStereo->qmfDelayScale = FRACT_BITS - 1;
180 
181     /* create configuration for hybrid filter bank */
182     for (ch = 0; ch < MAX_PS_CHANNELS; ch++) {
183       FDKhybridAnalysisInit(&hParametricStereo->fdkHybAnaFilter[ch],
184                             THREE_TO_TEN, 64, 64, 1);
185     } /* ch */
186 
187     FDKhybridSynthesisInit(&hParametricStereo->fdkHybSynFilter, THREE_TO_TEN,
188                            64, 64);
189 
190     /* determine average delay */
191     hParametricStereo->psDelay =
192         (HYBRID_FILTER_DELAY * hParametricStereo->noQmfBands);
193 
194     if ((hPsEncConfig->maxEnvelopes < PSENC_NENV_1) ||
195         (hPsEncConfig->maxEnvelopes > PSENC_NENV_MAX)) {
196       hPsEncConfig->maxEnvelopes = PSENC_NENV_DEFAULT;
197     }
198     hParametricStereo->maxEnvelopes = hPsEncConfig->maxEnvelopes;
199 
200     if (PSENC_OK !=
201         (error = FDKsbrEnc_InitPSEncode(
202              hParametricStereo->hPsEncode, (PS_BANDS)hPsEncConfig->nStereoBands,
203              hPsEncConfig->iidQuantErrorThreshold))) {
204       goto bail;
205     }
206 
207     for (ch = 0; ch < MAX_PS_CHANNELS; ch++) {
208       FIXP_DBL *pDynReal = GetRam_Sbr_envRBuffer(ch, dynamic_RAM);
209       FIXP_DBL *pDynImag = GetRam_Sbr_envIBuffer(ch, dynamic_RAM);
210 
211       for (i = 0; i < HYBRID_FRAMESIZE; i++) {
212         hParametricStereo->pHybridData[i + HYBRID_READ_OFFSET][ch][0] =
213             &pDynReal[i * MAX_HYBRID_BANDS];
214         hParametricStereo->pHybridData[i + HYBRID_READ_OFFSET][ch][1] =
215             &pDynImag[i * MAX_HYBRID_BANDS];
216         ;
217       }
218 
219       for (i = 0; i < HYBRID_READ_OFFSET; i++) {
220         hParametricStereo->pHybridData[i][ch][0] =
221             hParametricStereo->__staticHybridData[i][ch][0];
222         hParametricStereo->pHybridData[i][ch][1] =
223             hParametricStereo->__staticHybridData[i][ch][1];
224       }
225     } /* ch */
226 
227     /* clear static hybrid buffer */
228     FDKmemclear(hParametricStereo->__staticHybridData,
229                 sizeof(hParametricStereo->__staticHybridData));
230 
231     /* clear bs buffer */
232     FDKmemclear(hParametricStereo->psOut, sizeof(hParametricStereo->psOut));
233 
234     hParametricStereo->psOut[0].enablePSHeader =
235         1; /* write ps header in first frame */
236 
237     /* clear scaling buffer */
238     FDKmemclear(hParametricStereo->dynBandScale, sizeof(UCHAR) * PS_MAX_BANDS);
239     FDKmemclear(hParametricStereo->maxBandValue,
240                 sizeof(FIXP_DBL) * PS_MAX_BANDS);
241 
242   } /* valid handle */
243 bail:
244   return error;
245 }
246 
PSEnc_Destroy(HANDLE_PARAMETRIC_STEREO * phParametricStereo)247 FDK_PSENC_ERROR PSEnc_Destroy(HANDLE_PARAMETRIC_STEREO *phParametricStereo) {
248   FDK_PSENC_ERROR error = PSENC_OK;
249 
250   if (NULL != phParametricStereo) {
251     HANDLE_PARAMETRIC_STEREO hParametricStereo = *phParametricStereo;
252     if (hParametricStereo != NULL) {
253       FDKsbrEnc_DestroyPSEncode(&hParametricStereo->hPsEncode);
254       FreeRam_ParamStereo(phParametricStereo);
255     }
256   }
257 
258   return error;
259 }
260 
ExtractPSParameters(HANDLE_PARAMETRIC_STEREO hParametricStereo,const int sendHeader,FIXP_DBL * hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2])261 static FDK_PSENC_ERROR ExtractPSParameters(
262     HANDLE_PARAMETRIC_STEREO hParametricStereo, const int sendHeader,
263     FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2]) {
264   FDK_PSENC_ERROR error = PSENC_OK;
265 
266   if (hParametricStereo == NULL) {
267     error = PSENC_INVALID_HANDLE;
268   } else {
269     /* call ps encode function */
270     if (hParametricStereo->initPS) {
271       hParametricStereo->psOut[1] = hParametricStereo->psOut[0];
272     }
273     hParametricStereo->psOut[0] = hParametricStereo->psOut[1];
274 
275     if (PSENC_OK !=
276         (error = FDKsbrEnc_PSEncode(
277              hParametricStereo->hPsEncode, &hParametricStereo->psOut[1],
278              hParametricStereo->dynBandScale, hParametricStereo->maxEnvelopes,
279              hybridData, hParametricStereo->noQmfSlots, sendHeader))) {
280       goto bail;
281     }
282 
283     if (hParametricStereo->initPS) {
284       hParametricStereo->psOut[0] = hParametricStereo->psOut[1];
285       hParametricStereo->initPS = 0;
286     }
287   }
288 bail:
289   return error;
290 }
291 
DownmixPSQmfData(HANDLE_PARAMETRIC_STEREO hParametricStereo,HANDLE_QMF_FILTER_BANK sbrSynthQmf,FIXP_DBL ** RESTRICT mixRealQmfData,FIXP_DBL ** RESTRICT mixImagQmfData,INT_PCM * downsampledOutSignal,const UINT downsampledOutSignalBufSize,FIXP_DBL * hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2],const INT noQmfSlots,const INT psQmfScale[MAX_PS_CHANNELS],SCHAR * qmfScale)292 static FDK_PSENC_ERROR DownmixPSQmfData(
293     HANDLE_PARAMETRIC_STEREO hParametricStereo,
294     HANDLE_QMF_FILTER_BANK sbrSynthQmf, FIXP_DBL **RESTRICT mixRealQmfData,
295     FIXP_DBL **RESTRICT mixImagQmfData, INT_PCM *downsampledOutSignal,
296     const UINT downsampledOutSignalBufSize,
297     FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2],
298     const INT noQmfSlots, const INT psQmfScale[MAX_PS_CHANNELS],
299     SCHAR *qmfScale) {
300   FDK_PSENC_ERROR error = PSENC_OK;
301 
302   if (hParametricStereo == NULL) {
303     error = PSENC_INVALID_HANDLE;
304   } else {
305     int n, k;
306     C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, 2 * 64)
307 
308     /* define scalings */
309     int dynQmfScale = fixMax(
310         0, hParametricStereo->dmxScale -
311                1); /* scale one bit more for addition of left and right */
312     int downmixScale = psQmfScale[0] - dynQmfScale;
313     const FIXP_DBL maxStereoScaleFactor = MAXVAL_DBL; /* 2.f/2.f */
314 
315     for (n = 0; n < noQmfSlots; n++) {
316       FIXP_DBL tmpHybrid[2][MAX_HYBRID_BANDS];
317 
318       for (k = 0; k < 71; k++) {
319         int dynScale, sc; /* scaling */
320         FIXP_DBL tmpLeftReal, tmpRightReal, tmpLeftImag, tmpRightImag;
321         FIXP_DBL tmpScaleFactor, stereoScaleFactor;
322 
323         tmpLeftReal = hybridData[n][0][0][k];
324         tmpLeftImag = hybridData[n][0][1][k];
325         tmpRightReal = hybridData[n][1][0][k];
326         tmpRightImag = hybridData[n][1][1][k];
327 
328         sc = fixMax(
329             0, CntLeadingZeros(fixMax(
330                    fixMax(fixp_abs(tmpLeftReal), fixp_abs(tmpLeftImag)),
331                    fixMax(fixp_abs(tmpRightReal), fixp_abs(tmpRightImag)))) -
332                    2);
333 
334         tmpLeftReal <<= sc;
335         tmpLeftImag <<= sc;
336         tmpRightReal <<= sc;
337         tmpRightImag <<= sc;
338         dynScale = fixMin(sc - dynQmfScale, DFRACT_BITS - 1);
339 
340         /* calc stereo scale factor to avoid loss of energy in bands */
341         /* stereo scale factor = min(2.0f, sqrt( (abs(l(k, n)^2 + abs(r(k, n)^2
342          * )))/(0.5f*abs(l(k, n) + r(k, n))) )) */
343         stereoScaleFactor = fPow2Div2(tmpLeftReal) + fPow2Div2(tmpLeftImag) +
344                             fPow2Div2(tmpRightReal) + fPow2Div2(tmpRightImag);
345 
346         /* might be that tmpScaleFactor becomes negative, so fabs(.) */
347         tmpScaleFactor =
348             fixp_abs(stereoScaleFactor + fMult(tmpLeftReal, tmpRightReal) +
349                      fMult(tmpLeftImag, tmpRightImag));
350 
351         /* min(2.0f, sqrt(stereoScaleFactor/(0.5f*tmpScaleFactor)))  */
352         if ((stereoScaleFactor >> 1) <
353             fMult(maxStereoScaleFactor, tmpScaleFactor)) {
354           int sc_num = CountLeadingBits(stereoScaleFactor);
355           int sc_denum = CountLeadingBits(tmpScaleFactor);
356           sc = -(sc_num - sc_denum);
357 
358           tmpScaleFactor = schur_div((stereoScaleFactor << (sc_num)) >> 1,
359                                      tmpScaleFactor << sc_denum, 16);
360 
361           /* prevent odd scaling for next sqrt calculation */
362           if (sc & 0x1) {
363             sc++;
364             tmpScaleFactor >>= 1;
365           }
366           stereoScaleFactor = sqrtFixp(tmpScaleFactor);
367           stereoScaleFactor <<= (sc >> 1);
368         } else {
369           stereoScaleFactor = maxStereoScaleFactor;
370         }
371 
372         /* write data to hybrid output */
373         tmpHybrid[0][k] = fMultDiv2(stereoScaleFactor,
374                                     (FIXP_DBL)(tmpLeftReal + tmpRightReal)) >>
375                           dynScale;
376         tmpHybrid[1][k] = fMultDiv2(stereoScaleFactor,
377                                     (FIXP_DBL)(tmpLeftImag + tmpRightImag)) >>
378                           dynScale;
379 
380       } /* hybrid bands - k */
381 
382       FDKhybridSynthesisApply(&hParametricStereo->fdkHybSynFilter, tmpHybrid[0],
383                               tmpHybrid[1], mixRealQmfData[n],
384                               mixImagQmfData[n]);
385 
386       qmfSynthesisFilteringSlot(
387           sbrSynthQmf, mixRealQmfData[n], mixImagQmfData[n], downmixScale - 7,
388           downmixScale - 7,
389           downsampledOutSignal + (n * sbrSynthQmf->no_channels), 1,
390           pWorkBuffer);
391 
392     } /* slots */
393 
394     *qmfScale = -downmixScale + 7;
395 
396     C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, 2 * 64)
397 
398     {
399       const INT noQmfSlots2 = hParametricStereo->noQmfSlots >> 1;
400       const int noQmfBands = hParametricStereo->noQmfBands;
401 
402       INT scale, i, j, slotOffset;
403 
404       FIXP_DBL tmp[2][64];
405 
406       for (i = 0; i < noQmfSlots2; i++) {
407         FDKmemcpy(tmp[0], hParametricStereo->qmfDelayLines[0][i],
408                   noQmfBands * sizeof(FIXP_DBL));
409         FDKmemcpy(tmp[1], hParametricStereo->qmfDelayLines[1][i],
410                   noQmfBands * sizeof(FIXP_DBL));
411 
412         FDKmemcpy(hParametricStereo->qmfDelayLines[0][i],
413                   mixRealQmfData[i + noQmfSlots2],
414                   noQmfBands * sizeof(FIXP_DBL));
415         FDKmemcpy(hParametricStereo->qmfDelayLines[1][i],
416                   mixImagQmfData[i + noQmfSlots2],
417                   noQmfBands * sizeof(FIXP_DBL));
418 
419         FDKmemcpy(mixRealQmfData[i + noQmfSlots2], mixRealQmfData[i],
420                   noQmfBands * sizeof(FIXP_DBL));
421         FDKmemcpy(mixImagQmfData[i + noQmfSlots2], mixImagQmfData[i],
422                   noQmfBands * sizeof(FIXP_DBL));
423 
424         FDKmemcpy(mixRealQmfData[i], tmp[0], noQmfBands * sizeof(FIXP_DBL));
425         FDKmemcpy(mixImagQmfData[i], tmp[1], noQmfBands * sizeof(FIXP_DBL));
426       }
427 
428       if (hParametricStereo->qmfDelayScale > *qmfScale) {
429         scale = hParametricStereo->qmfDelayScale - *qmfScale;
430         slotOffset = 0;
431       } else {
432         scale = *qmfScale - hParametricStereo->qmfDelayScale;
433         slotOffset = noQmfSlots2;
434       }
435 
436       for (i = 0; i < noQmfSlots2; i++) {
437         for (j = 0; j < noQmfBands; j++) {
438           mixRealQmfData[i + slotOffset][j] >>= scale;
439           mixImagQmfData[i + slotOffset][j] >>= scale;
440         }
441       }
442 
443       scale = *qmfScale;
444       *qmfScale = fMin(*qmfScale, hParametricStereo->qmfDelayScale);
445       hParametricStereo->qmfDelayScale = scale;
446     }
447 
448   } /* valid handle */
449 
450   return error;
451 }
452 
FDKsbrEnc_PSEnc_WritePSData(HANDLE_PARAMETRIC_STEREO hParametricStereo,HANDLE_FDK_BITSTREAM hBitstream)453 INT FDKsbrEnc_PSEnc_WritePSData(HANDLE_PARAMETRIC_STEREO hParametricStereo,
454                                 HANDLE_FDK_BITSTREAM hBitstream) {
455   return (
456       (hParametricStereo != NULL)
457           ? FDKsbrEnc_WritePSBitstream(&hParametricStereo->psOut[0], hBitstream)
458           : 0);
459 }
460 
FDKsbrEnc_PSEnc_ParametricStereoProcessing(HANDLE_PARAMETRIC_STEREO hParametricStereo,INT_PCM * samples[2],UINT samplesBufSize,QMF_FILTER_BANK ** hQmfAnalysis,FIXP_DBL ** RESTRICT downmixedRealQmfData,FIXP_DBL ** RESTRICT downmixedImagQmfData,INT_PCM * downsampledOutSignal,HANDLE_QMF_FILTER_BANK sbrSynthQmf,SCHAR * qmfScale,const int sendHeader)461 FDK_PSENC_ERROR FDKsbrEnc_PSEnc_ParametricStereoProcessing(
462     HANDLE_PARAMETRIC_STEREO hParametricStereo, INT_PCM *samples[2],
463     UINT samplesBufSize, QMF_FILTER_BANK **hQmfAnalysis,
464     FIXP_DBL **RESTRICT downmixedRealQmfData,
465     FIXP_DBL **RESTRICT downmixedImagQmfData, INT_PCM *downsampledOutSignal,
466     HANDLE_QMF_FILTER_BANK sbrSynthQmf, SCHAR *qmfScale, const int sendHeader) {
467   FDK_PSENC_ERROR error = PSENC_OK;
468   INT psQmfScale[MAX_PS_CHANNELS] = {0};
469   int psCh, i;
470   C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, 4 * 64)
471 
472   for (psCh = 0; psCh < MAX_PS_CHANNELS; psCh++) {
473     for (i = 0; i < hQmfAnalysis[psCh]->no_col; i++) {
474       qmfAnalysisFilteringSlot(
475           hQmfAnalysis[psCh], &pWorkBuffer[2 * 64], /* qmfReal[64] */
476           &pWorkBuffer[3 * 64],                     /* qmfImag[64] */
477           samples[psCh] + i * hQmfAnalysis[psCh]->no_channels, 1,
478           &pWorkBuffer[0 * 64] /* qmf workbuffer 2*64 */
479       );
480 
481       FDKhybridAnalysisApply(
482           &hParametricStereo->fdkHybAnaFilter[psCh],
483           &pWorkBuffer[2 * 64], /* qmfReal[64] */
484           &pWorkBuffer[3 * 64], /* qmfImag[64] */
485           hParametricStereo->pHybridData[i + HYBRID_READ_OFFSET][psCh][0],
486           hParametricStereo->pHybridData[i + HYBRID_READ_OFFSET][psCh][1]);
487 
488     } /* no_col loop  i  */
489 
490     psQmfScale[psCh] = hQmfAnalysis[psCh]->outScalefactor;
491 
492   } /* for psCh */
493 
494   C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, 4 * 64)
495 
496   /* find best scaling in new QMF and Hybrid data */
497   psFindBestScaling(
498       hParametricStereo, &hParametricStereo->pHybridData[HYBRID_READ_OFFSET],
499       hParametricStereo->dynBandScale, hParametricStereo->maxBandValue,
500       &hParametricStereo->dmxScale);
501 
502   /* extract the ps parameters */
503   if (PSENC_OK !=
504       (error = ExtractPSParameters(hParametricStereo, sendHeader,
505                                    &hParametricStereo->pHybridData[0]))) {
506     goto bail;
507   }
508 
509   /* save hybrid date for next frame */
510   for (i = 0; i < HYBRID_READ_OFFSET; i++) {
511     FDKmemcpy(
512         hParametricStereo->pHybridData[i][0][0],
513         hParametricStereo->pHybridData[hParametricStereo->noQmfSlots + i][0][0],
514         MAX_HYBRID_BANDS * sizeof(FIXP_DBL)); /* left, real */
515     FDKmemcpy(
516         hParametricStereo->pHybridData[i][0][1],
517         hParametricStereo->pHybridData[hParametricStereo->noQmfSlots + i][0][1],
518         MAX_HYBRID_BANDS * sizeof(FIXP_DBL)); /* left, imag */
519     FDKmemcpy(
520         hParametricStereo->pHybridData[i][1][0],
521         hParametricStereo->pHybridData[hParametricStereo->noQmfSlots + i][1][0],
522         MAX_HYBRID_BANDS * sizeof(FIXP_DBL)); /* right, real */
523     FDKmemcpy(
524         hParametricStereo->pHybridData[i][1][1],
525         hParametricStereo->pHybridData[hParametricStereo->noQmfSlots + i][1][1],
526         MAX_HYBRID_BANDS * sizeof(FIXP_DBL)); /* right, imag */
527   }
528 
529   /* downmix and hybrid synthesis */
530   if (PSENC_OK !=
531       (error = DownmixPSQmfData(
532            hParametricStereo, sbrSynthQmf, downmixedRealQmfData,
533            downmixedImagQmfData, downsampledOutSignal, samplesBufSize,
534            &hParametricStereo->pHybridData[HYBRID_READ_OFFSET],
535            hParametricStereo->noQmfSlots, psQmfScale, qmfScale))) {
536     goto bail;
537   }
538 
539 bail:
540 
541   return error;
542 }
543 
psFindBestScaling(HANDLE_PARAMETRIC_STEREO hParametricStereo,FIXP_DBL * hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2],UCHAR * dynBandScale,FIXP_DBL * maxBandValue,SCHAR * dmxScale)544 static void psFindBestScaling(
545     HANDLE_PARAMETRIC_STEREO hParametricStereo,
546     FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2],
547     UCHAR *dynBandScale, FIXP_DBL *maxBandValue, SCHAR *dmxScale) {
548   HANDLE_PS_ENCODE hPsEncode = hParametricStereo->hPsEncode;
549 
550   INT group, bin, col, band;
551   const INT frameSize = hParametricStereo->noQmfSlots;
552   const INT psBands = (INT)hPsEncode->psEncMode;
553   const INT nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups;
554 
555   /* group wise scaling */
556   FIXP_DBL maxVal[2][PS_MAX_BANDS];
557   FIXP_DBL maxValue = FL2FXCONST_DBL(0.f);
558 
559   FDKmemclear(maxVal, sizeof(maxVal));
560 
561   /* start with hybrid data */
562   for (group = 0; group < nIidGroups; group++) {
563     /* Translate group to bin */
564     bin = hPsEncode->subband2parameterIndex[group];
565 
566     /* Translate from 20 bins to 10 bins */
567     if (hPsEncode->psEncMode == PS_BANDS_COARSE) {
568       bin >>= 1;
569     }
570 
571     /* QMF downmix scaling */
572     for (col = 0; col < frameSize; col++) {
573       int i, section = (col < frameSize - HYBRID_READ_OFFSET) ? 0 : 1;
574       FIXP_DBL tmp = maxVal[section][bin];
575       for (i = hPsEncode->iidGroupBorders[group];
576            i < hPsEncode->iidGroupBorders[group + 1]; i++) {
577         tmp = fixMax(tmp, (FIXP_DBL)fixp_abs(hybridData[col][0][0][i]));
578         tmp = fixMax(tmp, (FIXP_DBL)fixp_abs(hybridData[col][0][1][i]));
579         tmp = fixMax(tmp, (FIXP_DBL)fixp_abs(hybridData[col][1][0][i]));
580         tmp = fixMax(tmp, (FIXP_DBL)fixp_abs(hybridData[col][1][1][i]));
581       }
582       maxVal[section][bin] = tmp;
583     }
584   } /* nIidGroups */
585 
586   /* convert maxSpec to maxScaling, find scaling space */
587   for (band = 0; band < psBands; band++) {
588 #ifndef MULT_16x16
589     dynBandScale[band] =
590         CountLeadingBits(fixMax(maxVal[0][band], maxBandValue[band]));
591 #else
592     dynBandScale[band] = fixMax(
593         0, CountLeadingBits(fixMax(maxVal[0][band], maxBandValue[band])) -
594                FRACT_BITS);
595 #endif
596     maxValue = fixMax(maxValue, fixMax(maxVal[0][band], maxVal[1][band]));
597     maxBandValue[band] = fixMax(maxVal[0][band], maxVal[1][band]);
598   }
599 
600     /* calculate maximal scaling for QMF downmix */
601 #ifndef MULT_16x16
602   *dmxScale = fixMin(DFRACT_BITS, CountLeadingBits(maxValue));
603 #else
604   *dmxScale = fixMax(0, fixMin(FRACT_BITS, CountLeadingBits((maxValue))));
605 #endif
606 }
607