• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* -----------------------------------------------------------------------------------------------------------
3 Software License for The Fraunhofer FDK AAC Codec Library for Android
4 
5 � Copyright  1995 - 2012 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     /* clear scaling buffer */
231     FDKmemclear(hParametricStereo->dynBandScale, sizeof(UCHAR)*PS_MAX_BANDS);
232     FDKmemclear(hParametricStereo->maxBandValue, sizeof(FIXP_QMF)*PS_MAX_BANDS);
233 
234   } /* valid handle */
235 bail:
236   return error;
237 }
238 
239 
PSEnc_Destroy(HANDLE_PARAMETRIC_STEREO * phParametricStereo)240 FDK_PSENC_ERROR PSEnc_Destroy(
241         HANDLE_PARAMETRIC_STEREO *phParametricStereo
242         )
243 {
244   FDK_PSENC_ERROR error = PSENC_OK;
245 
246   if (NULL!=phParametricStereo) {
247     HANDLE_PARAMETRIC_STEREO hParametricStereo = *phParametricStereo;
248     if(hParametricStereo != NULL){
249       FDKsbrEnc_DestroyPSEncode(&hParametricStereo->hPsEncode);
250       FreeRam_ParamStereo(phParametricStereo);
251     }
252   }
253 
254   return error;
255 }
256 
ExtractPSParameters(HANDLE_PARAMETRIC_STEREO hParametricStereo,const int sendHeader,FIXP_DBL * hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2])257 static FDK_PSENC_ERROR ExtractPSParameters(
258         HANDLE_PARAMETRIC_STEREO  hParametricStereo,
259         const int                 sendHeader,
260         FIXP_DBL                 *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2]
261         )
262 {
263   FDK_PSENC_ERROR error = PSENC_OK;
264 
265   if (hParametricStereo == NULL) {
266     error = PSENC_INVALID_HANDLE;
267   }
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 != (error = FDKsbrEnc_PSEncode(
276             hParametricStereo->hPsEncode,
277            &hParametricStereo->psOut[1],
278             hParametricStereo->dynBandScale,
279             hParametricStereo->maxEnvelopes,
280             hybridData,
281             hParametricStereo->noQmfSlots,
282             sendHeader)))
283     {
284       goto bail;
285     }
286 
287     if (hParametricStereo->initPS) {
288       hParametricStereo->psOut[0] = hParametricStereo->psOut[1];
289       hParametricStereo->initPS = 0;
290     }
291   }
292 bail:
293   return error;
294 }
295 
296 
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)297 static FDK_PSENC_ERROR DownmixPSQmfData(
298        HANDLE_PARAMETRIC_STEREO  hParametricStereo,
299        HANDLE_QMF_FILTER_BANK    sbrSynthQmf,
300        FIXP_QMF       **RESTRICT mixRealQmfData,
301        FIXP_QMF       **RESTRICT mixImagQmfData,
302        INT_PCM                  *downsampledOutSignal,
303        FIXP_DBL                 *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2],
304        const INT                 noQmfSlots,
305        const INT                 psQmfScale[MAX_PS_CHANNELS],
306        SCHAR                    *qmfScale
307        )
308 {
309   FDK_PSENC_ERROR error = PSENC_OK;
310 
311   if(hParametricStereo == NULL){
312     error = PSENC_INVALID_HANDLE;
313   }
314   else {
315     int n, k;
316     C_ALLOC_SCRATCH_START(pWorkBuffer, FIXP_QMF, QMF_CHANNELS*2);
317 
318     /* define scalings */
319     int dynQmfScale = fixMax(0, hParametricStereo->dmxScale-1); /* scale one bit more for addition of left and right */
320     int downmixScale = psQmfScale[0] - dynQmfScale;
321     const FIXP_DBL maxStereoScaleFactor = MAXVAL_DBL; /* 2.f/2.f */
322 
323     for (n = 0; n<noQmfSlots; n++) {
324 
325       FIXP_DBL tmpHybrid[2][MAX_HYBRID_BANDS];
326 
327       for(k = 0; k<71; k++){
328           int dynScale, sc; /* scaling */
329           FIXP_QMF tmpLeftReal, tmpRightReal, tmpLeftImag, tmpRightImag;
330           FIXP_DBL tmpScaleFactor, stereoScaleFactor;
331 
332           tmpLeftReal  = hybridData[n][0][0][k];
333           tmpLeftImag  = hybridData[n][0][1][k];
334           tmpRightReal = hybridData[n][1][0][k];
335           tmpRightImag = hybridData[n][1][1][k];
336 
337           sc = fixMax(0,CntLeadingZeros( fixMax(fixMax(fixp_abs(tmpLeftReal),fixp_abs(tmpLeftImag)),fixMax(fixp_abs(tmpRightReal),fixp_abs(tmpRightImag))) )-2);
338 
339           tmpLeftReal  <<= sc; tmpLeftImag  <<= sc;
340           tmpRightReal <<= sc; tmpRightImag <<= sc;
341           dynScale = fixMin(sc-dynQmfScale,DFRACT_BITS-1);
342 
343           /* calc stereo scale factor to avoid loss of energy in bands                                                 */
344           /* 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))) )) */
345           stereoScaleFactor = fPow2Div2(tmpLeftReal)  + fPow2Div2(tmpLeftImag)
346                             + fPow2Div2(tmpRightReal) + fPow2Div2(tmpRightImag) ;
347 
348           /* might be that tmpScaleFactor becomes negative, so fabs(.) */
349           tmpScaleFactor    = fixp_abs(stereoScaleFactor + fMult(tmpLeftReal,tmpRightReal) + fMult(tmpLeftImag,tmpRightImag));
350 
351           /* min(2.0f, sqrt(stereoScaleFactor/(0.5f*tmpScaleFactor)))  */
352           if ( (stereoScaleFactor>>1) < fMult(maxStereoScaleFactor,tmpScaleFactor) ) {
353 
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,
360                                           16) ;
361 
362               /* prevent odd scaling for next sqrt calculation */
363               if (sc&0x1) {
364                 sc++;
365                 tmpScaleFactor>>=1;
366               }
367               stereoScaleFactor = sqrtFixp(tmpScaleFactor);
368               stereoScaleFactor <<= (sc>>1);
369           }
370           else {
371               stereoScaleFactor = maxStereoScaleFactor;
372           }
373 
374           /* write data to hybrid output */
375           tmpHybrid[0][k] = fMultDiv2(stereoScaleFactor, (FIXP_QMF)(tmpLeftReal + tmpRightReal))>>dynScale;
376           tmpHybrid[1][k] = fMultDiv2(stereoScaleFactor, (FIXP_QMF)(tmpLeftImag + tmpRightImag))>>dynScale;
377 
378       } /* hybrid bands - k */
379 
380       FDKhybridSynthesisApply(
381             &hParametricStereo->fdkHybSynFilter,
382              tmpHybrid[0],
383              tmpHybrid[1],
384              mixRealQmfData[n],
385              mixImagQmfData[n]);
386 
387       qmfSynthesisFilteringSlot(
388             sbrSynthQmf,
389             mixRealQmfData[n],
390             mixImagQmfData[n],
391             downmixScale-7,
392             downmixScale-7,
393             downsampledOutSignal+(n*sbrSynthQmf->no_channels),
394             1,
395             pWorkBuffer);
396 
397     } /* slots */
398 
399     *qmfScale = -downmixScale + 7;
400 
401     C_ALLOC_SCRATCH_END(pWorkBuffer, FIXP_QMF, QMF_CHANNELS*2);
402 
403 
404   {
405     const INT noQmfSlots2 = hParametricStereo->noQmfSlots>>1;
406     const int noQmfBands  = hParametricStereo->noQmfBands;
407 
408     INT scale, i, j, slotOffset;
409 
410     FIXP_QMF tmp[2][QMF_CHANNELS];
411 
412     for (i=0; i<noQmfSlots2; i++) {
413       FDKmemcpy(tmp[0], hParametricStereo->qmfDelayLines[0][i], noQmfBands*sizeof(FIXP_QMF));
414       FDKmemcpy(tmp[1], hParametricStereo->qmfDelayLines[1][i], noQmfBands*sizeof(FIXP_QMF));
415 
416       FDKmemcpy(hParametricStereo->qmfDelayLines[0][i], mixRealQmfData[i+noQmfSlots2], noQmfBands*sizeof(FIXP_QMF));
417       FDKmemcpy(hParametricStereo->qmfDelayLines[1][i], mixImagQmfData[i+noQmfSlots2], noQmfBands*sizeof(FIXP_QMF));
418 
419       FDKmemcpy(mixRealQmfData[i+noQmfSlots2], mixRealQmfData[i], noQmfBands*sizeof(FIXP_QMF));
420       FDKmemcpy(mixImagQmfData[i+noQmfSlots2], mixImagQmfData[i], noQmfBands*sizeof(FIXP_QMF));
421 
422       FDKmemcpy(mixRealQmfData[i], tmp[0], noQmfBands*sizeof(FIXP_QMF));
423       FDKmemcpy(mixImagQmfData[i], tmp[1], noQmfBands*sizeof(FIXP_QMF));
424     }
425 
426     if (hParametricStereo->qmfDelayScale > *qmfScale) {
427       scale = hParametricStereo->qmfDelayScale - *qmfScale;
428       slotOffset = 0;
429     }
430     else {
431       scale = *qmfScale - hParametricStereo->qmfDelayScale;
432       slotOffset = noQmfSlots2;
433     }
434 
435     for (i=0; i<noQmfSlots2; i++) {
436       for (j=0; j<noQmfBands; j++) {
437         mixRealQmfData[i+slotOffset][j] >>= scale;
438         mixImagQmfData[i+slotOffset][j] >>= scale;
439       }
440     }
441 
442     scale = *qmfScale;
443     *qmfScale = FDKmin(*qmfScale, hParametricStereo->qmfDelayScale);
444     hParametricStereo->qmfDelayScale = scale;
445   }
446 
447   } /* valid handle */
448 
449   return error;
450 }
451 
452 
FDKsbrEnc_PSEnc_WritePSData(HANDLE_PARAMETRIC_STEREO hParametricStereo,HANDLE_FDK_BITSTREAM hBitstream)453 INT FDKsbrEnc_PSEnc_WritePSData(
454         HANDLE_PARAMETRIC_STEREO  hParametricStereo,
455         HANDLE_FDK_BITSTREAM      hBitstream
456         )
457 {
458   return ( (hParametricStereo!=NULL) ? FDKsbrEnc_WritePSBitstream(&hParametricStereo->psOut[0], hBitstream) : 0 );
459 }
460 
461 
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)462 FDK_PSENC_ERROR FDKsbrEnc_PSEnc_ParametricStereoProcessing(
463         HANDLE_PARAMETRIC_STEREO  hParametricStereo,
464         INT_PCM                  *samples[2],
465         UINT                      timeInStride,
466         QMF_FILTER_BANK         **hQmfAnalysis,
467         FIXP_QMF **RESTRICT       downmixedRealQmfData,
468         FIXP_QMF **RESTRICT       downmixedImagQmfData,
469         INT_PCM                  *downsampledOutSignal,
470         HANDLE_QMF_FILTER_BANK    sbrSynthQmf,
471         SCHAR                    *qmfScale,
472         const int                 sendHeader
473         )
474 {
475   FDK_PSENC_ERROR error = PSENC_OK;
476   INT noQmfBands  = hParametricStereo->noQmfBands;
477   INT psQmfScale[MAX_PS_CHANNELS] = {0};
478   int psCh, i;
479   C_ALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, QMF_CHANNELS*4);
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_ALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, QMF_CHANNELS*4);
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