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