1 /* ----------------------------------------------------------------------------- 2 Software License for The Fraunhofer FDK AAC Codec Library for Android 3 4 Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Frderung 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 (at) 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 ----------------*/ 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 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 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 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 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 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 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 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