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