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 /*********************** MPEG surround decoder library ************************* 96 97 Author(s): 98 99 Description: SAC Processing 100 101 *******************************************************************************/ 102 103 /* data structures and interfaces for spatial audio reference software */ 104 #include "sac_process.h" 105 106 #include "sac_bitdec.h" 107 #include "sac_calcM1andM2.h" 108 #include "sac_smoothing.h" 109 #include "sac_rom.h" 110 111 #include "sac_dec_errorcodes.h" 112 113 #include "FDK_trigFcts.h" 114 #include "FDK_decorrelate.h" 115 116 /** 117 * \brief Linear interpolation between two parameter values. 118 * a*alpha + b*(1-alpha) 119 * = a*alpha + b - b*alpha 120 * 121 * \param alpha Weighting factor. 122 * \param a Parameter a. 123 * \param b Parameter b. 124 * 125 * \return Interpolated parameter value. 126 */ 127 FDK_INLINE FIXP_DBL interpolateParameter(const FIXP_SGL alpha, const FIXP_DBL a, 128 const FIXP_DBL b) { 129 return (b - fMult(alpha, b) + fMult(alpha, a)); 130 } 131 132 /** 133 * \brief Map MPEG Surround channel indices to MPEG 4 PCE like channel indices. 134 * \param self Spatial decoder handle. 135 * \param ch MPEG Surround channel index. 136 * \return MPEG 4 PCE style channel index, corresponding to the given MPEG 137 * Surround channel index. 138 */ 139 static UINT mapChannel(spatialDec *self, UINT ch) { 140 static const UCHAR chanelIdx[][8] = { 141 {0, 1, 2, 3, 4, 5, 6, 7}, /* binaural, TREE_212, arbitrary tree */ 142 }; 143 144 int idx = 0; 145 146 return (chanelIdx[idx][ch]); 147 } 148 149 FIXP_DBL getChGain(spatialDec *self, UINT ch, INT *scale) { 150 /* init no gain modifier */ 151 FIXP_DBL gain = 0x80000000; 152 *scale = 0; 153 154 if ((!isTwoChMode(self->upmixType)) && 155 (self->upmixType != UPMIXTYPE_BYPASS)) { 156 if ((ch == 0) || (ch == 1) || (ch == 2)) { 157 /* no modifier */ 158 } 159 } 160 161 return gain; 162 } 163 164 SACDEC_ERROR SpatialDecQMFAnalysis(spatialDec *self, const PCM_MPS *inData, 165 const INT ts, const INT bypassMode, 166 FIXP_DBL **qmfReal, FIXP_DBL **qmfImag, 167 const int numInputChannels) { 168 SACDEC_ERROR err = MPS_OK; 169 int ch, offset; 170 171 offset = self->pQmfDomain->globalConf.nBandsSynthesis * 172 self->pQmfDomain->globalConf.nQmfTimeSlots; 173 174 { 175 for (ch = 0; ch < numInputChannels; ch++) { 176 const PCM_MPS *inSamples = 177 &inData[ts * self->pQmfDomain->globalConf.nBandsAnalysis]; 178 FIXP_DBL *pQmfRealAnalysis = qmfReal[ch]; /* no delay in blind mode */ 179 FIXP_DBL *pQmfImagAnalysis = qmfImag[ch]; 180 181 CalculateSpaceAnalysisQmf(&self->pQmfDomain->QmfDomainIn[ch].fb, 182 inSamples + (ch * offset), pQmfRealAnalysis, 183 pQmfImagAnalysis); 184 185 if (!isTwoChMode(self->upmixType) && !bypassMode) { 186 int i; 187 for (i = 0; i < self->qmfBands; i++) { 188 qmfReal[ch][i] = fMult(qmfReal[ch][i], self->clipProtectGain__FDK); 189 qmfImag[ch][i] = fMult(qmfImag[ch][i], self->clipProtectGain__FDK); 190 } 191 } 192 } 193 } 194 195 self->qmfInputDelayBufPos = 196 (self->qmfInputDelayBufPos + 1) % self->pc_filterdelay; 197 198 return err; 199 } 200 201 SACDEC_ERROR SpatialDecFeedQMF(spatialDec *self, FIXP_DBL **qmfInDataReal, 202 FIXP_DBL **qmfInDataImag, const INT ts, 203 const INT bypassMode, FIXP_DBL **qmfReal__FDK, 204 FIXP_DBL **qmfImag__FDK, 205 const INT numInputChannels) { 206 SACDEC_ERROR err = MPS_OK; 207 int ch; 208 209 { 210 for (ch = 0; ch < numInputChannels; ch++) { 211 FIXP_DBL *pQmfRealAnalysis = 212 qmfReal__FDK[ch]; /* no delay in blind mode */ 213 FIXP_DBL *pQmfImagAnalysis = qmfImag__FDK[ch]; 214 215 /* Write Input data to pQmfRealAnalysis. */ 216 if (self->bShareDelayWithSBR) { 217 FDK_QmfDomain_GetSlot( 218 &self->pQmfDomain->QmfDomainIn[ch], ts + HYBRID_FILTER_DELAY, 0, 219 MAX_QMF_BANDS_TO_HYBRID, pQmfRealAnalysis, pQmfImagAnalysis, 15); 220 FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, 221 MAX_QMF_BANDS_TO_HYBRID, self->qmfBands, 222 pQmfRealAnalysis, pQmfImagAnalysis, 15); 223 } else { 224 FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, 0, 225 self->qmfBands, pQmfRealAnalysis, 226 pQmfImagAnalysis, 15); 227 } 228 if (ts == self->pQmfDomain->globalConf.nQmfTimeSlots - 1) { 229 /* Is currently also needed in case we dont have any overlap. We need to 230 * save lb_scale to ov_lb_scale */ 231 FDK_QmfDomain_SaveOverlap(&self->pQmfDomain->QmfDomainIn[ch], 0); 232 } 233 234 /* Apply clip protection to output. */ 235 if (!isTwoChMode(self->upmixType) && !bypassMode) { 236 int i; 237 for (i = 0; i < self->qmfBands; i++) { 238 qmfReal__FDK[ch][i] = 239 fMult(qmfReal__FDK[ch][i], self->clipProtectGain__FDK); 240 qmfImag__FDK[ch][i] = 241 fMult(qmfImag__FDK[ch][i], self->clipProtectGain__FDK); 242 } 243 } 244 245 } /* End of loop over numInputChannels */ 246 } 247 248 self->qmfInputDelayBufPos = 249 (self->qmfInputDelayBufPos + 1) % self->pc_filterdelay; 250 251 return err; 252 } 253 254 /******************************************************************************* 255 Functionname: SpatialDecHybridAnalysis 256 ******************************************************************************* 257 258 Description: 259 260 Arguments: 261 262 Input: 263 float** pointers[4] leftReal, leftIm, rightReal, rightIm 264 265 Output: 266 float self->qmfInputReal[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_QMF_BANDS]; 267 float self->qmfInputImag[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_QMF_BANDS]; 268 269 float 270 self->hybInputReal[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_HYBRID_BANDS]; float 271 self->hybInputImag[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_HYBRID_BANDS]; 272 273 274 *******************************************************************************/ 275 SACDEC_ERROR SpatialDecHybridAnalysis(spatialDec *self, FIXP_DBL **qmfInputReal, 276 FIXP_DBL **qmfInputImag, 277 FIXP_DBL **hybOutputReal, 278 FIXP_DBL **hybOutputImag, const INT ts, 279 const INT numInputChannels) { 280 SACDEC_ERROR err = MPS_OK; 281 int ch; 282 283 for (ch = 0; ch < numInputChannels; 284 ch++) /* hybrid filtering for down-mix signals */ 285 { 286 if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) { 287 int k; 288 /* No hybrid filtering. Just copy the QMF data. */ 289 for (k = 0; k < self->hybridBands; k += 1) { 290 hybOutputReal[ch][k] = qmfInputReal[ch][k]; 291 hybOutputImag[ch][k] = qmfInputImag[ch][k]; 292 } 293 } else { 294 self->hybridAnalysis[ch].hfMode = self->bShareDelayWithSBR; 295 296 if (self->stereoConfigIndex == 3) 297 FDK_ASSERT(self->hybridAnalysis[ch].hfMode == 0); 298 FDKhybridAnalysisApply(&self->hybridAnalysis[ch], qmfInputReal[ch], 299 qmfInputImag[ch], hybOutputReal[ch], 300 hybOutputImag[ch]); 301 } 302 } 303 304 if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC) && 305 self->residualCoding) { 306 self->hybridAnalysis[numInputChannels].hfMode = 0; 307 FDKhybridAnalysisApply( 308 &self->hybridAnalysis[numInputChannels], 309 self->qmfResidualReal__FDK[0][0], self->qmfResidualImag__FDK[0][0], 310 self->hybResidualReal__FDK[0], self->hybResidualImag__FDK[0]); 311 } 312 313 return err; 314 } 315 316 SACDEC_ERROR SpatialDecCreateX(spatialDec *self, FIXP_DBL **hybInputReal, 317 FIXP_DBL **hybInputImag, FIXP_DBL **pxReal, 318 FIXP_DBL **pxImag) { 319 SACDEC_ERROR err = MPS_OK; 320 int row; 321 322 /* Creating wDry */ 323 for (row = 0; row < self->numInputChannels; row++) { 324 /* pointer to direct signals */ 325 pxReal[row] = hybInputReal[row]; 326 pxImag[row] = hybInputImag[row]; 327 } 328 329 return err; 330 } 331 332 static void M2ParamToKernelMult(FIXP_SGL *RESTRICT pKernel, 333 FIXP_DBL *RESTRICT Mparam, 334 FIXP_DBL *RESTRICT MparamPrev, 335 int *RESTRICT pWidth, FIXP_SGL alpha__FDK, 336 int nBands) { 337 int pb; 338 339 for (pb = 0; pb < nBands; pb++) { 340 FIXP_SGL tmp = FX_DBL2FX_SGL( 341 interpolateParameter(alpha__FDK, Mparam[pb], MparamPrev[pb])); 342 343 int i = pWidth[pb]; 344 if (i & 1) *pKernel++ = tmp; 345 if (i & 2) { 346 *pKernel++ = tmp; 347 *pKernel++ = tmp; 348 } 349 for (i >>= 2; i--;) { 350 *pKernel++ = tmp; 351 *pKernel++ = tmp; 352 *pKernel++ = tmp; 353 *pKernel++ = tmp; 354 } 355 } 356 } 357 358 SACDEC_ERROR SpatialDecApplyM1_CreateW_Mode212( 359 spatialDec *self, const SPATIAL_BS_FRAME *frame, FIXP_DBL **xReal, 360 FIXP_DBL **xImag, FIXP_DBL **vReal, FIXP_DBL **vImag) { 361 SACDEC_ERROR err = MPS_OK; 362 int res; 363 FIXP_DBL *decorrInReal = vReal[0]; 364 FIXP_DBL *decorrInImag = vImag[0]; 365 366 /* M1 does not do anything in 212 mode, so use simplified processing */ 367 FDK_ASSERT(self->numVChannels == 2); 368 FDK_ASSERT(self->numDirektSignals == 1); 369 FDK_ASSERT(self->numDecorSignals == 1); 370 FDKmemcpy(vReal[0], xReal[0], self->hybridBands * sizeof(FIXP_DBL)); 371 FDKmemcpy(vImag[0], xImag[0], self->hybridBands * sizeof(FIXP_DBL)); 372 373 if (isTsdActive(frame->TsdData)) { 374 /* Generate v_{x,nonTr} as input for allpass based decorrelator */ 375 TsdGenerateNonTr(self->hybridBands, frame->TsdData, self->TsdTs, vReal[0], 376 vImag[0], vReal[1], vImag[1], &decorrInReal, 377 &decorrInImag); 378 } 379 /* - Decorrelate */ 380 res = SpatialDecGetResidualIndex(self, 1); 381 if (FDKdecorrelateApply(&self->apDecor[0], decorrInReal, decorrInImag, 382 vReal[1], vImag[1], 383 self->param2hyb[self->residualBands[res]])) { 384 return MPS_NOTOK; 385 } 386 if (isTsdActive(frame->TsdData)) { 387 /* Generate v_{x,Tr}, apply transient decorrelator and add to allpass based 388 * decorrelator output */ 389 TsdApply(self->hybridBands, frame->TsdData, &self->TsdTs, 390 vReal[0], /* input: v_x */ 391 vImag[0], 392 vReal[1], /* input: d_{x,nonTr}; output: d_{x,nonTr} + d_{x,Tr} */ 393 vImag[1]); 394 } 395 396 /* Write residual signal in approriate parameter bands */ 397 if (self->residualBands[res] > 0) { 398 int stopBand = self->param2hyb[self->residualBands[res]]; 399 FDKmemcpy(vReal[1], self->hybResidualReal__FDK[res], 400 fixMin(stopBand, self->hybridBands) * sizeof(FIXP_DBL)); 401 FDKmemcpy(vImag[1], self->hybResidualImag__FDK[res], 402 fixMin(stopBand, self->hybridBands) * sizeof(FIXP_DBL)); 403 } /* (self->residualBands[res]>0) */ 404 405 return err; 406 } 407 408 SACDEC_ERROR SpatialDecApplyM2_Mode212(spatialDec *self, INT ps, 409 const FIXP_SGL alpha, FIXP_DBL **wReal, 410 FIXP_DBL **wImag, 411 FIXP_DBL **hybOutputRealDry, 412 FIXP_DBL **hybOutputImagDry) { 413 SACDEC_ERROR err = MPS_OK; 414 INT row; 415 416 INT *pWidth = self->kernels_width; 417 /* for stereoConfigIndex == 3 case hybridBands is < 71 */ 418 INT pb_max = self->kernels[self->hybridBands - 1] + 1; 419 INT max_row = self->numOutputChannels; 420 421 INT M2_exp = 0; 422 if (self->residualCoding) M2_exp = 3; 423 424 for (row = 0; row < max_row; row++) // 2 times 425 { 426 FIXP_DBL *Mparam0 = self->M2Real__FDK[row][0]; 427 FIXP_DBL *Mparam1 = self->M2Real__FDK[row][1]; 428 FIXP_DBL *MparamPrev0 = self->M2RealPrev__FDK[row][0]; 429 FIXP_DBL *MparamPrev1 = self->M2RealPrev__FDK[row][1]; 430 431 FIXP_DBL *RESTRICT pHybOutRealDry = hybOutputRealDry[row]; 432 FIXP_DBL *RESTRICT pHybOutImagDry = hybOutputImagDry[row]; 433 434 FIXP_DBL *RESTRICT pWReal0 = wReal[0]; 435 FIXP_DBL *RESTRICT pWReal1 = wReal[1]; 436 FIXP_DBL *RESTRICT pWImag0 = wImag[0]; 437 FIXP_DBL *RESTRICT pWImag1 = wImag[1]; 438 for (INT pb = 0; pb < pb_max; pb++) { 439 FIXP_DBL tmp0, tmp1; 440 441 tmp0 = interpolateParameter(alpha, Mparam0[pb], MparamPrev0[pb]); 442 tmp1 = interpolateParameter(alpha, Mparam1[pb], MparamPrev1[pb]); 443 444 INT i = pWidth[pb]; 445 446 do // about 3-4 times 447 { 448 FIXP_DBL var0, var1, real, imag; 449 450 var0 = *pWReal0++; 451 var1 = *pWReal1++; 452 real = fMultDiv2(var0, tmp0); 453 var0 = *pWImag0++; 454 real = fMultAddDiv2(real, var1, tmp1); 455 var1 = *pWImag1++; 456 imag = fMultDiv2(var0, tmp0); 457 *pHybOutRealDry++ = real << (1 + M2_exp); 458 imag = fMultAddDiv2(imag, var1, tmp1); 459 *pHybOutImagDry++ = imag << (1 + M2_exp); 460 } while (--i != 0); 461 } 462 } 463 return err; 464 } 465 466 SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding( 467 spatialDec *self, INT ps, const FIXP_SGL alpha, FIXP_DBL **wReal, 468 FIXP_DBL **wImag, FIXP_DBL **hybOutputRealDry, 469 FIXP_DBL **hybOutputImagDry) { 470 SACDEC_ERROR err = MPS_OK; 471 INT row; 472 INT scale_param_m2; 473 INT *pWidth = self->kernels_width; 474 INT pb_max = self->kernels[self->hybridBands - 1] + 1; 475 476 scale_param_m2 = SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2; 477 478 for (row = 0; row < self->numM2rows; row++) { 479 INT qs, pb; 480 481 FIXP_DBL *RESTRICT pWReal0 = wReal[0]; 482 FIXP_DBL *RESTRICT pWImag0 = wImag[0]; 483 FIXP_DBL *RESTRICT pWReal1 = wReal[1]; 484 FIXP_DBL *RESTRICT pWImag1 = wImag[1]; 485 486 FIXP_DBL *MReal0 = self->M2Real__FDK[row][0]; 487 FIXP_DBL *MImag0 = self->M2Imag__FDK[row][0]; 488 FIXP_DBL *MReal1 = self->M2Real__FDK[row][1]; 489 FIXP_DBL *MRealPrev0 = self->M2RealPrev__FDK[row][0]; 490 FIXP_DBL *MImagPrev0 = self->M2ImagPrev__FDK[row][0]; 491 FIXP_DBL *MRealPrev1 = self->M2RealPrev__FDK[row][1]; 492 493 FIXP_DBL *RESTRICT pHybOutRealDry = hybOutputRealDry[row]; 494 FIXP_DBL *RESTRICT pHybOutImagDry = hybOutputImagDry[row]; 495 496 FDK_ASSERT(!(self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD)); 497 FDK_ASSERT((pWidth[0] + pWidth[1]) >= 3); 498 499 for (pb = 0, qs = 3; pb < 2; pb++) { 500 INT s; 501 FIXP_DBL maxVal; 502 FIXP_SGL mReal1; 503 FIXP_SGL mReal0, mImag0; 504 FIXP_DBL iReal0, iImag0, iReal1; 505 506 iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]); 507 iImag0 = -interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]); 508 iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]); 509 510 maxVal = fAbs(iReal0) | fAbs(iImag0); 511 maxVal |= fAbs(iReal1); 512 513 s = fMax(CntLeadingZeros(maxVal) - 1, 0); 514 s = fMin(s, scale_param_m2); 515 516 mReal0 = FX_DBL2FX_SGL(iReal0 << s); 517 mImag0 = FX_DBL2FX_SGL(iImag0 << s); 518 mReal1 = FX_DBL2FX_SGL(iReal1 << s); 519 520 s = scale_param_m2 - s; 521 522 INT i = pWidth[pb]; 523 524 do { 525 FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1; 526 527 wReal0 = *pWReal0++; 528 wImag0 = *pWImag0++; 529 wReal1 = *pWReal1++; 530 wImag1 = *pWImag1++; 531 532 cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0); 533 534 *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s; 535 *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s; 536 537 if (qs > 0) { 538 mImag0 = -mImag0; 539 qs--; 540 } 541 } while (--i != 0); 542 } 543 544 for (; pb < pb_max; pb++) { 545 INT s; 546 FIXP_DBL maxVal; 547 FIXP_SGL mReal1; 548 FIXP_SGL mReal0, mImag0; 549 FIXP_DBL iReal0, iImag0, iReal1; 550 551 iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]); 552 iImag0 = interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]); 553 iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]); 554 555 maxVal = fAbs(iReal0) | fAbs(iImag0); 556 maxVal |= fAbs(iReal1); 557 558 s = fMax(CntLeadingZeros(maxVal) - 1, 0); 559 s = fMin(s, scale_param_m2); 560 561 mReal0 = FX_DBL2FX_SGL(iReal0 << s); 562 mImag0 = FX_DBL2FX_SGL(iImag0 << s); 563 mReal1 = FX_DBL2FX_SGL(iReal1 << s); 564 565 s = scale_param_m2 - s; 566 567 INT i = pWidth[pb]; 568 569 do { 570 FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1; 571 572 wReal0 = *pWReal0++; 573 wImag0 = *pWImag0++; 574 wReal1 = *pWReal1++; 575 wImag1 = *pWImag1++; 576 577 cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0); 578 579 *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s; 580 *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s; 581 } while (--i != 0); 582 } 583 } 584 585 return err; 586 } 587 588 SACDEC_ERROR SpatialDecApplyM2(spatialDec *self, INT ps, const FIXP_SGL alpha, 589 FIXP_DBL **wReal, FIXP_DBL **wImag, 590 FIXP_DBL **hybOutputRealDry, 591 FIXP_DBL **hybOutputImagDry, 592 FIXP_DBL **hybOutputRealWet, 593 FIXP_DBL **hybOutputImagWet) { 594 SACDEC_ERROR err = MPS_OK; 595 596 { 597 int qs, row, col; 598 int complexHybBands; 599 int complexParBands; 600 int scale_param_m2 = 0; 601 int toolsDisabled; 602 603 UCHAR activParamBands; 604 FIXP_DBL *RESTRICT pWReal, *RESTRICT pWImag, *RESTRICT pHybOutRealDry, 605 *RESTRICT pHybOutImagDry, *RESTRICT pHybOutRealWet, 606 *RESTRICT pHybOutImagWet; 607 C_ALLOC_SCRATCH_START(pKernel, FIXP_SGL, MAX_HYBRID_BANDS); 608 609 /* The wet signal is added to the dry signal directly in applyM2 if GES and 610 * STP are disabled */ 611 toolsDisabled = 612 ((self->tempShapeConfig == 1) || (self->tempShapeConfig == 2)) ? 0 : 1; 613 614 { 615 complexHybBands = self->hybridBands; 616 complexParBands = self->numParameterBands; 617 } 618 619 FDKmemclear(hybOutputImagDry[0], 620 self->createParams.maxNumOutputChannels * 621 self->createParams.maxNumCmplxHybBands * sizeof(FIXP_DBL)); 622 FDKmemclear(hybOutputRealDry[0], self->createParams.maxNumOutputChannels * 623 self->createParams.maxNumHybridBands * 624 sizeof(FIXP_DBL)); 625 626 if (!toolsDisabled) { 627 FDKmemclear(hybOutputRealWet[0], 628 self->createParams.maxNumOutputChannels * 629 self->createParams.maxNumHybridBands * sizeof(FIXP_DBL)); 630 FDKmemclear(hybOutputImagWet[0], 631 self->createParams.maxNumOutputChannels * 632 self->createParams.maxNumCmplxHybBands * 633 sizeof(FIXP_DBL)); 634 } 635 636 if (self->phaseCoding == 3) { 637 /* + SCALE_DATA_APPLY_M2 to compensate for Div2 below ?! */ 638 scale_param_m2 = SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2; 639 } 640 641 for (row = 0; row < self->numM2rows; row++) { 642 pHybOutRealDry = hybOutputRealDry[row]; 643 pHybOutImagDry = hybOutputImagDry[row]; 644 645 if (toolsDisabled) { 646 pHybOutRealWet = hybOutputRealDry[row]; 647 pHybOutImagWet = hybOutputImagDry[row]; 648 } else { 649 pHybOutRealWet = hybOutputRealWet[row]; 650 pHybOutImagWet = hybOutputImagWet[row]; 651 } 652 653 for (col = 0; col < self->numDirektSignals; col++) { 654 if (self->pActivM2ParamBands == 655 0) { /* default setting, calculate all rows and columns */ 656 activParamBands = 1; 657 } else { 658 if (self->pActivM2ParamBands[MAX_M2_INPUT * row + 659 col]) /* table with activ and inactiv 660 bands exists for current 661 configuration */ 662 activParamBands = 1; 663 else 664 activParamBands = 0; 665 } 666 if (activParamBands) { 667 pWReal = wReal[col]; 668 pWImag = wImag[col]; 669 670 M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col], 671 self->M2RealPrev__FDK[row][col], 672 self->kernels_width, alpha, 673 self->numParameterBands); 674 675 if (1 && (self->phaseCoding != 3)) { 676 /* direct signals */ 677 { 678 /* only one sample will be assigned to each row, hence 679 * accumulation is not neccessary; that is valid for all 680 * configurations */ 681 for (qs = 0; qs < complexHybBands; qs++) { 682 pHybOutRealDry[qs] = fMult(pWReal[qs], pKernel[qs]); 683 pHybOutImagDry[qs] = fMult(pWImag[qs], pKernel[qs]); 684 } 685 } 686 } else { /* isBinauralMode(self->upmixType) */ 687 688 for (qs = 0; qs < complexHybBands; qs++) { 689 pHybOutRealDry[qs] += fMultDiv2(pWReal[qs], pKernel[qs]) 690 << (scale_param_m2); 691 pHybOutImagDry[qs] += fMultDiv2(pWImag[qs], pKernel[qs]) 692 << (scale_param_m2); 693 } 694 695 M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col], 696 self->M2ImagPrev__FDK[row][col], 697 self->kernels_width, alpha, complexParBands); 698 699 /* direct signals sign is -1 for qs = 0,2 */ 700 pHybOutRealDry[0] += fMultDiv2(pWImag[0], pKernel[0]) 701 << (scale_param_m2); 702 pHybOutImagDry[0] -= fMultDiv2(pWReal[0], pKernel[0]) 703 << (scale_param_m2); 704 705 pHybOutRealDry[2] += fMultDiv2(pWImag[2], pKernel[2]) 706 << (scale_param_m2); 707 pHybOutImagDry[2] -= fMultDiv2(pWReal[2], pKernel[2]) 708 << (scale_param_m2); 709 710 /* direct signals sign is +1 for qs = 1,3,4,5,...,complexHybBands */ 711 pHybOutRealDry[1] -= fMultDiv2(pWImag[1], pKernel[1]) 712 << (scale_param_m2); 713 pHybOutImagDry[1] += fMultDiv2(pWReal[1], pKernel[1]) 714 << (scale_param_m2); 715 716 for (qs = 3; qs < complexHybBands; qs++) { 717 pHybOutRealDry[qs] -= fMultDiv2(pWImag[qs], pKernel[qs]) 718 << (scale_param_m2); 719 pHybOutImagDry[qs] += fMultDiv2(pWReal[qs], pKernel[qs]) 720 << (scale_param_m2); 721 } 722 } /* self->upmixType */ 723 } /* if (activParamBands) */ 724 } /* self->numDirektSignals */ 725 726 for (; col < self->numVChannels; col++) { 727 if (self->pActivM2ParamBands == 728 0) { /* default setting, calculate all rows and columns */ 729 activParamBands = 1; 730 } else { 731 if (self->pActivM2ParamBands[MAX_M2_INPUT * row + 732 col]) /* table with activ and inactiv 733 bands exists for current 734 configuration */ 735 activParamBands = 1; 736 else 737 activParamBands = 0; 738 } 739 740 if (activParamBands) { 741 int resBandIndex; 742 int resHybIndex; 743 744 resBandIndex = 745 self->residualBands[SpatialDecGetResidualIndex(self, col)]; 746 resHybIndex = self->param2hyb[resBandIndex]; 747 748 pWReal = wReal[col]; 749 pWImag = wImag[col]; 750 751 M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col], 752 self->M2RealPrev__FDK[row][col], 753 self->kernels_width, alpha, 754 self->numParameterBands); 755 756 if (1 && (self->phaseCoding != 3)) { 757 /* residual signals */ 758 for (qs = 0; qs < resHybIndex; qs++) { 759 pHybOutRealDry[qs] += fMult(pWReal[qs], pKernel[qs]); 760 pHybOutImagDry[qs] += fMult(pWImag[qs], pKernel[qs]); 761 } 762 /* decor signals */ 763 for (; qs < complexHybBands; qs++) { 764 pHybOutRealWet[qs] += fMult(pWReal[qs], pKernel[qs]); 765 pHybOutImagWet[qs] += fMult(pWImag[qs], pKernel[qs]); 766 } 767 } else { /* self->upmixType */ 768 /* residual signals */ 769 FIXP_DBL *RESTRICT pHybOutReal; 770 FIXP_DBL *RESTRICT pHybOutImag; 771 772 for (qs = 0; qs < resHybIndex; qs++) { 773 pHybOutRealDry[qs] += fMultDiv2(pWReal[qs], pKernel[qs]) 774 << (scale_param_m2); 775 pHybOutImagDry[qs] += fMultDiv2(pWImag[qs], pKernel[qs]) 776 << (scale_param_m2); 777 } 778 /* decor signals */ 779 for (; qs < complexHybBands; qs++) { 780 pHybOutRealWet[qs] += fMultDiv2(pWReal[qs], pKernel[qs]) 781 << (scale_param_m2); 782 pHybOutImagWet[qs] += fMultDiv2(pWImag[qs], pKernel[qs]) 783 << (scale_param_m2); 784 } 785 786 M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col], 787 self->M2ImagPrev__FDK[row][col], 788 self->kernels_width, alpha, complexParBands); 789 790 /* direct signals sign is -1 for qs = 0,2 */ 791 /* direct signals sign is +1 for qs = 1,3.. */ 792 if (toolsDisabled) { 793 pHybOutRealDry[0] += fMultDiv2(pWImag[0], pKernel[0]) 794 << (scale_param_m2); 795 pHybOutImagDry[0] -= fMultDiv2(pWReal[0], pKernel[0]) 796 << (scale_param_m2); 797 798 pHybOutRealDry[1] -= fMultDiv2(pWImag[1], pKernel[1]) 799 << (scale_param_m2); 800 pHybOutImagDry[1] += fMultDiv2(pWReal[1], pKernel[1]) 801 << (scale_param_m2); 802 803 pHybOutRealDry[2] += fMultDiv2(pWImag[2], pKernel[2]) 804 << (scale_param_m2); 805 pHybOutImagDry[2] -= fMultDiv2(pWReal[2], pKernel[2]) 806 << (scale_param_m2); 807 } else { 808 pHybOutReal = &pHybOutRealDry[0]; 809 pHybOutImag = &pHybOutImagDry[0]; 810 if (0 == resHybIndex) { 811 pHybOutReal = &pHybOutRealWet[0]; 812 pHybOutImag = &pHybOutImagWet[0]; 813 } 814 pHybOutReal[0] += fMultDiv2(pWImag[0], pKernel[0]) 815 << (scale_param_m2); 816 pHybOutImag[0] -= fMultDiv2(pWReal[0], pKernel[0]) 817 << (scale_param_m2); 818 819 if (1 == resHybIndex) { 820 pHybOutReal = &pHybOutRealWet[0]; 821 pHybOutImag = &pHybOutImagWet[0]; 822 } 823 pHybOutReal[1] -= fMultDiv2(pWImag[1], pKernel[1]) 824 << (scale_param_m2); 825 pHybOutImag[1] += fMultDiv2(pWReal[1], pKernel[1]) 826 << (scale_param_m2); 827 828 if (2 == resHybIndex) { 829 pHybOutReal = &pHybOutRealWet[0]; 830 pHybOutImag = &pHybOutImagWet[0]; 831 } 832 pHybOutReal[2] += fMultDiv2(pWImag[2], pKernel[2]) 833 << (scale_param_m2); 834 pHybOutImag[2] -= fMultDiv2(pWReal[2], pKernel[2]) 835 << (scale_param_m2); 836 } 837 838 for (qs = 3; qs < resHybIndex; qs++) { 839 pHybOutRealDry[qs] -= fMultDiv2(pWImag[qs], pKernel[qs]) 840 << (scale_param_m2); 841 pHybOutImagDry[qs] += fMultDiv2(pWReal[qs], pKernel[qs]) 842 << (scale_param_m2); 843 } 844 /* decor signals */ 845 for (; qs < complexHybBands; qs++) { 846 pHybOutRealWet[qs] -= fMultDiv2(pWImag[qs], pKernel[qs]) 847 << (scale_param_m2); 848 pHybOutImagWet[qs] += fMultDiv2(pWReal[qs], pKernel[qs]) 849 << (scale_param_m2); 850 } 851 } /* self->upmixType */ 852 } /* if (activParamBands) { */ 853 } /* self->numVChannels */ 854 } 855 856 C_ALLOC_SCRATCH_END(pKernel, FIXP_SGL, MAX_HYBRID_BANDS); 857 } 858 859 return err; 860 } 861 862 SACDEC_ERROR SpatialDecSynthesis(spatialDec *self, const INT ts, 863 FIXP_DBL **hybOutputReal, 864 FIXP_DBL **hybOutputImag, PCM_MPS *timeOut, 865 const INT numInputChannels, 866 const FDK_channelMapDescr *const mapDescr) { 867 SACDEC_ERROR err = MPS_OK; 868 869 int ch; 870 int stride, offset; 871 872 stride = self->numOutputChannelsAT; 873 offset = 1; 874 875 PCM_MPS *pTimeOut__FDK = 876 &timeOut[stride * self->pQmfDomain->globalConf.nBandsSynthesis * ts]; 877 C_ALLOC_SCRATCH_START(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS); 878 C_ALLOC_SCRATCH_START(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS); 879 880 for (ch = 0; ch < self->numOutputChannelsAT; ch++) { 881 if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) { 882 int k; 883 /* No hybrid filtering. Just copy the QMF data. */ 884 for (k = 0; k < self->hybridBands; k += 1) { 885 pQmfReal[k] = hybOutputReal[ch][k]; 886 pQmfImag[k] = hybOutputImag[ch][k]; 887 } 888 } else { 889 FDKhybridSynthesisApply(&self->hybridSynthesis[ch], hybOutputReal[ch], 890 hybOutputImag[ch], pQmfReal, pQmfImag); 891 } 892 893 /* Map channel indices from MPEG Surround -> PCE style -> channelMapping[] 894 */ 895 FDK_ASSERT(self->numOutputChannelsAT <= 6); 896 int outCh = FDK_chMapDescr_getMapValue(mapDescr, mapChannel(self, ch), 897 self->numOutputChannelsAT); 898 899 { 900 if (self->stereoConfigIndex == 3) { 901 /* MPS -> SBR */ 902 int i; 903 FIXP_DBL *pWorkBufReal, *pWorkBufImag; 904 FDK_ASSERT((self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_m == 905 (FIXP_DBL)0x80000000) && 906 (self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_e == 0)); 907 FDK_QmfDomain_GetWorkBuffer(&self->pQmfDomain->QmfDomainIn[outCh], ts, 908 &pWorkBufReal, &pWorkBufImag); 909 FDK_ASSERT(self->qmfBands <= 910 self->pQmfDomain->QmfDomainIn[outCh].workBuf_nBands); 911 for (i = 0; i < self->qmfBands; i++) { 912 pWorkBufReal[i] = pQmfReal[i]; 913 pWorkBufImag[i] = pQmfImag[i]; 914 } 915 self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale = 916 -7; /*-ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK;*/ 917 self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -= 918 self->pQmfDomain->QmfDomainIn[outCh].fb.filterScale; 919 self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -= 920 self->clipProtectGainSF__FDK; 921 922 } else { 923 /* Call the QMF synthesis for dry. */ 924 err = CalculateSpaceSynthesisQmf(&self->pQmfDomain->QmfDomainOut[outCh], 925 pQmfReal, pQmfImag, stride, 926 pTimeOut__FDK + (offset * outCh)); 927 } 928 if (err != MPS_OK) goto bail; 929 } 930 } /* ch loop */ 931 932 bail: 933 C_ALLOC_SCRATCH_END(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS); 934 C_ALLOC_SCRATCH_END(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS); 935 936 return err; 937 } 938 939 void SpatialDecBufferMatrices(spatialDec *self) { 940 int row, col; 941 int complexParBands; 942 complexParBands = self->numParameterBands; 943 944 /* 945 buffer matrices M2 946 */ 947 for (row = 0; row < self->numM2rows; row++) { 948 for (col = 0; col < self->numVChannels; col++) { 949 FDKmemcpy(self->M2RealPrev__FDK[row][col], self->M2Real__FDK[row][col], 950 self->numParameterBands * sizeof(FIXP_DBL)); 951 if (0 || (self->phaseCoding == 3)) { 952 FDKmemcpy(self->M2ImagPrev__FDK[row][col], self->M2Imag__FDK[row][col], 953 complexParBands * sizeof(FIXP_DBL)); 954 } 955 } 956 } 957 958 /* buffer phase */ 959 FDKmemcpy(self->PhasePrevLeft__FDK, self->PhaseLeft__FDK, 960 self->numParameterBands * sizeof(FIXP_DBL)); 961 FDKmemcpy(self->PhasePrevRight__FDK, self->PhaseRight__FDK, 962 self->numParameterBands * sizeof(FIXP_DBL)); 963 } 964 965 #define PHASE_SCALE 2 966 967 #ifndef P_PI 968 #define P_PI 3.1415926535897932 969 #endif 970 971 /* For better precision, PI (pi_x2) is already doubled */ 972 static FIXP_DBL interp_angle__FDK(FIXP_DBL angle1, FIXP_DBL angle2, 973 FIXP_SGL alpha, FIXP_DBL pi_x2) { 974 if (angle2 - angle1 > (pi_x2 >> 1)) angle2 -= pi_x2; 975 976 if (angle1 - angle2 > (pi_x2 >> 1)) angle1 -= pi_x2; 977 978 return interpolateParameter(alpha, angle2, angle1); 979 } 980 981 /* 982 * 983 */ 984 void SpatialDecApplyPhase(spatialDec *self, FIXP_SGL alpha__FDK, 985 int lastSlotOfParamSet) { 986 int pb, qs; 987 FIXP_DBL ppb[MAX_PARAMETER_BANDS * 988 4]; /* left real, imag - right real, imag interleaved */ 989 990 const FIXP_DBL pi_x2 = PIx2__IPD; 991 for (pb = 0; pb < self->numParameterBands; pb++) { 992 FIXP_DBL pl, pr; 993 994 pl = interp_angle__FDK(self->PhasePrevLeft__FDK[pb], 995 self->PhaseLeft__FDK[pb], alpha__FDK, pi_x2); 996 pr = interp_angle__FDK(self->PhasePrevRight__FDK[pb], 997 self->PhaseRight__FDK[pb], alpha__FDK, pi_x2); 998 999 inline_fixp_cos_sin(pl, pr, IPD_SCALE, &ppb[4 * pb]); 1000 } 1001 1002 /* sign is -1 for qs = 0,2 and +1 for qs = 1 */ 1003 1004 const SCHAR *kernels = &self->kernels[0]; 1005 1006 FIXP_DBL *Dry_real0 = &self->hybOutputRealDry__FDK[0][0]; 1007 FIXP_DBL *Dry_imag0 = &self->hybOutputImagDry__FDK[0][0]; 1008 FIXP_DBL *Dry_real1 = &self->hybOutputRealDry__FDK[1][0]; 1009 FIXP_DBL *Dry_imag1 = &self->hybOutputImagDry__FDK[1][0]; 1010 1011 for (qs = 2; qs >= 0; qs--) { 1012 FIXP_DBL out_re, out_im; 1013 1014 pb = *kernels++; 1015 if (qs == 1) /* sign[qs] >= 0 */ 1016 { 1017 cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0], 1018 ppb[4 * pb + 1]); 1019 out_re <<= PHASE_SCALE - 1; 1020 out_im <<= PHASE_SCALE - 1; 1021 *Dry_real0++ = out_re; 1022 *Dry_imag0++ = out_im; 1023 1024 cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2], 1025 ppb[4 * pb + 3]); 1026 out_re <<= PHASE_SCALE - 1; 1027 out_im <<= PHASE_SCALE - 1; 1028 *Dry_real1++ = out_re; 1029 *Dry_imag1++ = out_im; 1030 } else { 1031 cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0], 1032 -ppb[4 * pb + 1]); 1033 out_re <<= PHASE_SCALE - 1; 1034 out_im <<= PHASE_SCALE - 1; 1035 *Dry_real0++ = out_re; 1036 *Dry_imag0++ = out_im; 1037 1038 cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2], 1039 -ppb[4 * pb + 3]); 1040 out_re <<= PHASE_SCALE - 1; 1041 out_im <<= PHASE_SCALE - 1; 1042 *Dry_real1++ = out_re; 1043 *Dry_imag1++ = out_im; 1044 } 1045 } 1046 1047 /* sign is +1 for qs >=3 */ 1048 for (qs = self->hybridBands - 3; qs--;) { 1049 FIXP_DBL out_re, out_im; 1050 1051 pb = *kernels++; 1052 cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0], 1053 ppb[4 * pb + 1]); 1054 out_re <<= PHASE_SCALE - 1; 1055 out_im <<= PHASE_SCALE - 1; 1056 *Dry_real0++ = out_re; 1057 *Dry_imag0++ = out_im; 1058 1059 cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2], 1060 ppb[4 * pb + 3]); 1061 out_re <<= PHASE_SCALE - 1; 1062 out_im <<= PHASE_SCALE - 1; 1063 *Dry_real1++ = out_re; 1064 *Dry_imag1++ = out_im; 1065 } 1066 } 1067