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 /******************* Library for basic calculation routines ******************** 96 97 Author(s): Markus Lohwasser, Josef Hoepfl, Manuel Jander 98 99 Description: QMF filterbank 100 101 *******************************************************************************/ 102 103 /*! 104 \file 105 \brief Complex qmf analysis/synthesis 106 This module contains the qmf filterbank for analysis [ 107 cplxAnalysisQmfFiltering() ] and synthesis [ cplxSynthesisQmfFiltering() ]. It 108 is a polyphase implementation of a complex exponential modulated filter bank. 109 The analysis part usually runs at half the sample rate than the synthesis 110 part. (So called "dual-rate" mode.) 111 112 The coefficients of the prototype filter are specified in #qmf_pfilt640 (in 113 sbr_rom.cpp). Thus only a 64 channel version (32 on the analysis side) with a 114 640 tap prototype filter are used. 115 116 \anchor PolyphaseFiltering <h2>About polyphase filtering</h2> 117 The polyphase implementation of a filterbank requires filtering at the input 118 and output. This is implemented as part of cplxAnalysisQmfFiltering() and 119 cplxSynthesisQmfFiltering(). The implementation requires the filter 120 coefficients in a specific structure as described in #sbr_qmf_64_640_qmf (in 121 sbr_rom.cpp). 122 123 This module comprises the computationally most expensive functions of the SBR 124 decoder. The accuracy of computations is also important and has a direct 125 impact on the overall sound quality. Therefore a special test program is 126 available which can be used to only test the filterbank: main_audio.cpp 127 128 This modules also uses scaling of data to provide better SNR on fixed-point 129 processors. See #QMF_SCALE_FACTOR (in sbr_scale.h) for details. An interesting 130 note: The function getScalefactor() can constitute a significant amount of 131 computational complexity - very much depending on the bitrate. Since it is a 132 rather small function, effective assembler optimization might be possible. 133 134 */ 135 136 #include "qmf.h" 137 138 #include "FDK_trigFcts.h" 139 #include "fixpoint_math.h" 140 #include "dct.h" 141 142 #define QSSCALE (0) 143 #define FX_DBL2FX_QSS(x) (x) 144 #define FX_QSS2FX_DBL(x) (x) 145 146 /* moved to qmf_pcm.h: -> qmfSynPrototypeFirSlot */ 147 /* moved to qmf_pcm.h: -> qmfSynPrototypeFirSlot_NonSymmetric */ 148 /* moved to qmf_pcm.h: -> qmfSynthesisFilteringSlot */ 149 150 #ifndef FUNCTION_qmfAnaPrototypeFirSlot 151 /*! 152 \brief Perform Analysis Prototype Filtering on a single slot of input data. 153 */ 154 static void qmfAnaPrototypeFirSlot( 155 FIXP_DBL *analysisBuffer, 156 INT no_channels, /*!< Number channels of analysis filter */ 157 const FIXP_PFT *p_filter, INT p_stride, /*!< Stride of analysis filter */ 158 FIXP_QAS *RESTRICT pFilterStates) { 159 INT k; 160 161 FIXP_DBL accu; 162 const FIXP_PFT *RESTRICT p_flt = p_filter; 163 FIXP_DBL *RESTRICT pData_0 = analysisBuffer + 2 * no_channels - 1; 164 FIXP_DBL *RESTRICT pData_1 = analysisBuffer; 165 166 FIXP_QAS *RESTRICT sta_0 = (FIXP_QAS *)pFilterStates; 167 FIXP_QAS *RESTRICT sta_1 = 168 (FIXP_QAS *)pFilterStates + (2 * QMF_NO_POLY * no_channels) - 1; 169 INT pfltStep = QMF_NO_POLY * (p_stride); 170 INT staStep1 = no_channels << 1; 171 INT staStep2 = (no_channels << 3) - 1; /* Rewind one less */ 172 173 /* FIR filters 127..64 0..63 */ 174 for (k = 0; k < no_channels; k++) { 175 accu = fMultDiv2(p_flt[0], *sta_1); 176 sta_1 -= staStep1; 177 accu += fMultDiv2(p_flt[1], *sta_1); 178 sta_1 -= staStep1; 179 accu += fMultDiv2(p_flt[2], *sta_1); 180 sta_1 -= staStep1; 181 accu += fMultDiv2(p_flt[3], *sta_1); 182 sta_1 -= staStep1; 183 accu += fMultDiv2(p_flt[4], *sta_1); 184 *pData_1++ = (accu << 1); 185 sta_1 += staStep2; 186 187 p_flt += pfltStep; 188 accu = fMultDiv2(p_flt[0], *sta_0); 189 sta_0 += staStep1; 190 accu += fMultDiv2(p_flt[1], *sta_0); 191 sta_0 += staStep1; 192 accu += fMultDiv2(p_flt[2], *sta_0); 193 sta_0 += staStep1; 194 accu += fMultDiv2(p_flt[3], *sta_0); 195 sta_0 += staStep1; 196 accu += fMultDiv2(p_flt[4], *sta_0); 197 *pData_0-- = (accu << 1); 198 sta_0 -= staStep2; 199 } 200 } 201 #endif /* !defined(FUNCTION_qmfAnaPrototypeFirSlot) */ 202 203 #ifndef FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric 204 /*! 205 \brief Perform Analysis Prototype Filtering on a single slot of input data. 206 */ 207 static void qmfAnaPrototypeFirSlot_NonSymmetric( 208 FIXP_DBL *analysisBuffer, 209 int no_channels, /*!< Number channels of analysis filter */ 210 const FIXP_PFT *p_filter, int p_stride, /*!< Stride of analysis filter */ 211 FIXP_QAS *RESTRICT pFilterStates) { 212 const FIXP_PFT *RESTRICT p_flt = p_filter; 213 int p, k; 214 215 for (k = 0; k < 2 * no_channels; k++) { 216 FIXP_DBL accu = (FIXP_DBL)0; 217 218 p_flt += QMF_NO_POLY * (p_stride - 1); 219 220 /* 221 Perform FIR-Filter 222 */ 223 for (p = 0; p < QMF_NO_POLY; p++) { 224 accu += fMultDiv2(*p_flt++, pFilterStates[2 * no_channels * p]); 225 } 226 analysisBuffer[2 * no_channels - 1 - k] = (accu << 1); 227 pFilterStates++; 228 } 229 } 230 #endif /* FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric */ 231 232 /*! 233 * 234 * \brief Perform real-valued forward modulation of the time domain 235 * data of timeIn and stores the real part of the subband 236 * samples in rSubband 237 * 238 */ 239 static void qmfForwardModulationLP_even( 240 HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ 241 FIXP_DBL *timeIn, /*!< Time Signal */ 242 FIXP_DBL *rSubband) /*!< Real Output */ 243 { 244 int i; 245 int L = anaQmf->no_channels; 246 int M = L >> 1; 247 int scale; 248 FIXP_DBL accu; 249 250 const FIXP_DBL *timeInTmp1 = (FIXP_DBL *)&timeIn[3 * M]; 251 const FIXP_DBL *timeInTmp2 = timeInTmp1; 252 FIXP_DBL *rSubbandTmp = rSubband; 253 254 rSubband[0] = timeIn[3 * M] >> 1; 255 256 for (i = M - 1; i != 0; i--) { 257 accu = ((*--timeInTmp1) >> 1) + ((*++timeInTmp2) >> 1); 258 *++rSubbandTmp = accu; 259 } 260 261 timeInTmp1 = &timeIn[2 * M]; 262 timeInTmp2 = &timeIn[0]; 263 rSubbandTmp = &rSubband[M]; 264 265 for (i = L - M; i != 0; i--) { 266 accu = ((*timeInTmp1--) >> 1) - ((*timeInTmp2++) >> 1); 267 *rSubbandTmp++ = accu; 268 } 269 270 dct_III(rSubband, timeIn, L, &scale); 271 } 272 273 #if !defined(FUNCTION_qmfForwardModulationLP_odd) 274 static void qmfForwardModulationLP_odd( 275 HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ 276 const FIXP_DBL *timeIn, /*!< Time Signal */ 277 FIXP_DBL *rSubband) /*!< Real Output */ 278 { 279 int i; 280 int L = anaQmf->no_channels; 281 int M = L >> 1; 282 int shift = (anaQmf->no_channels >> 6) + 1; 283 284 for (i = 0; i < M; i++) { 285 rSubband[M + i] = (timeIn[L - 1 - i] >> 1) - (timeIn[i] >> shift); 286 rSubband[M - 1 - i] = 287 (timeIn[L + i] >> 1) + (timeIn[2 * L - 1 - i] >> shift); 288 } 289 290 dct_IV(rSubband, L, &shift); 291 } 292 #endif /* !defined(FUNCTION_qmfForwardModulationLP_odd) */ 293 294 /*! 295 * 296 * \brief Perform complex-valued forward modulation of the time domain 297 * data of timeIn and stores the real part of the subband 298 * samples in rSubband, and the imaginary part in iSubband 299 * 300 * 301 */ 302 #if !defined(FUNCTION_qmfForwardModulationHQ) 303 static void qmfForwardModulationHQ( 304 HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ 305 const FIXP_DBL *RESTRICT timeIn, /*!< Time Signal */ 306 FIXP_DBL *RESTRICT rSubband, /*!< Real Output */ 307 FIXP_DBL *RESTRICT iSubband /*!< Imaginary Output */ 308 ) { 309 int i; 310 int L = anaQmf->no_channels; 311 int L2 = L << 1; 312 int shift = 0; 313 314 /* Time advance by one sample, which is equivalent to the complex 315 rotation at the end of the analysis. Works only for STD mode. */ 316 if ((L == 64) && !(anaQmf->flags & (QMF_FLAG_CLDFB | QMF_FLAG_MPSLDFB))) { 317 FIXP_DBL x, y; 318 319 /*rSubband[0] = u[1] + u[0]*/ 320 /*iSubband[0] = u[1] - u[0]*/ 321 x = timeIn[1] >> 1; 322 y = timeIn[0]; 323 rSubband[0] = x + (y >> 1); 324 iSubband[0] = x - (y >> 1); 325 326 /*rSubband[n] = u[n+1] - u[2M-n], n=1,...,M-1*/ 327 /*iSubband[n] = u[n+1] + u[2M-n], n=1,...,M-1*/ 328 for (i = 1; i < L; i++) { 329 x = timeIn[i + 1] >> 1; /*u[n+1] */ 330 y = timeIn[L2 - i]; /*u[2M-n] */ 331 rSubband[i] = x - (y >> 1); 332 iSubband[i] = x + (y >> 1); 333 } 334 } else { 335 for (i = 0; i < L; i += 2) { 336 FIXP_DBL x0, x1, y0, y1; 337 338 x0 = timeIn[i + 0] >> 1; 339 x1 = timeIn[i + 1] >> 1; 340 y0 = timeIn[L2 - 1 - i]; 341 y1 = timeIn[L2 - 2 - i]; 342 343 rSubband[i + 0] = x0 - (y0 >> 1); 344 rSubband[i + 1] = x1 - (y1 >> 1); 345 iSubband[i + 0] = x0 + (y0 >> 1); 346 iSubband[i + 1] = x1 + (y1 >> 1); 347 } 348 } 349 350 dct_IV(rSubband, L, &shift); 351 dst_IV(iSubband, L, &shift); 352 353 /* Do the complex rotation except for the case of 64 bands (in STD mode). */ 354 if ((L != 64) || (anaQmf->flags & (QMF_FLAG_CLDFB | QMF_FLAG_MPSLDFB))) { 355 if (anaQmf->flags & QMF_FLAG_MPSLDFB_OPTIMIZE_MODULATION) { 356 FIXP_DBL iBand; 357 for (i = 0; i < fMin(anaQmf->lsb, L); i += 2) { 358 iBand = rSubband[i]; 359 rSubband[i] = -iSubband[i]; 360 iSubband[i] = iBand; 361 362 iBand = -rSubband[i + 1]; 363 rSubband[i + 1] = iSubband[i + 1]; 364 iSubband[i + 1] = iBand; 365 } 366 } else { 367 const FIXP_QTW *sbr_t_cos; 368 const FIXP_QTW *sbr_t_sin; 369 const int len = L; /* was len = fMin(anaQmf->lsb, L) but in case of USAC 370 the signal above lsb is actually needed in some 371 cases (HBE?) */ 372 sbr_t_cos = anaQmf->t_cos; 373 sbr_t_sin = anaQmf->t_sin; 374 375 for (i = 0; i < len; i++) { 376 cplxMult(&iSubband[i], &rSubband[i], iSubband[i], rSubband[i], 377 sbr_t_cos[i], sbr_t_sin[i]); 378 } 379 } 380 } 381 } 382 #endif /* FUNCTION_qmfForwardModulationHQ */ 383 384 /* 385 * \brief Perform one QMF slot analysis of the time domain data of timeIn 386 * with specified stride and stores the real part of the subband 387 * samples in rSubband, and the imaginary part in iSubband 388 * 389 * Note: anaQmf->lsb can be greater than anaQmf->no_channels in case 390 * of implicit resampling (USAC with reduced 3/4 core frame length). 391 */ 392 #if (SAMPLE_BITS != DFRACT_BITS) && (QAS_BITS == DFRACT_BITS) 393 void qmfAnalysisFilteringSlot( 394 HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ 395 FIXP_DBL *qmfReal, /*!< Low and High band, real */ 396 FIXP_DBL *qmfImag, /*!< Low and High band, imag */ 397 const LONG *RESTRICT timeIn, /*!< Pointer to input */ 398 const int stride, /*!< stride factor of input */ 399 FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ 400 ) { 401 int offset = anaQmf->no_channels * (QMF_NO_POLY * 2 - 1); 402 /* 403 Feed time signal into oldest anaQmf->no_channels states 404 */ 405 { 406 FIXP_DBL *FilterStatesAnaTmp = ((FIXP_DBL *)anaQmf->FilterStates) + offset; 407 408 /* Feed and scale actual time in slot */ 409 for (int i = anaQmf->no_channels >> 1; i != 0; i--) { 410 /* Place INT_PCM value left aligned in scaledTimeIn */ 411 412 *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; 413 timeIn += stride; 414 *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; 415 timeIn += stride; 416 } 417 } 418 419 if (anaQmf->flags & QMF_FLAG_NONSYMMETRIC) { 420 qmfAnaPrototypeFirSlot_NonSymmetric(pWorkBuffer, anaQmf->no_channels, 421 anaQmf->p_filter, anaQmf->p_stride, 422 (FIXP_QAS *)anaQmf->FilterStates); 423 } else { 424 qmfAnaPrototypeFirSlot(pWorkBuffer, anaQmf->no_channels, anaQmf->p_filter, 425 anaQmf->p_stride, (FIXP_QAS *)anaQmf->FilterStates); 426 } 427 428 if (anaQmf->flags & QMF_FLAG_LP) { 429 if (anaQmf->flags & QMF_FLAG_CLDFB) 430 qmfForwardModulationLP_odd(anaQmf, pWorkBuffer, qmfReal); 431 else 432 qmfForwardModulationLP_even(anaQmf, pWorkBuffer, qmfReal); 433 434 } else { 435 qmfForwardModulationHQ(anaQmf, pWorkBuffer, qmfReal, qmfImag); 436 } 437 /* 438 Shift filter states 439 440 Should be realized with modulo adressing on a DSP instead of a true buffer 441 shift 442 */ 443 FDKmemmove(anaQmf->FilterStates, 444 (FIXP_QAS *)anaQmf->FilterStates + anaQmf->no_channels, 445 offset * sizeof(FIXP_QAS)); 446 } 447 #endif 448 449 void qmfAnalysisFilteringSlot( 450 HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ 451 FIXP_DBL *qmfReal, /*!< Low and High band, real */ 452 FIXP_DBL *qmfImag, /*!< Low and High band, imag */ 453 const INT_PCM *RESTRICT timeIn, /*!< Pointer to input */ 454 const int stride, /*!< stride factor of input */ 455 FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ 456 ) { 457 int offset = anaQmf->no_channels * (QMF_NO_POLY * 2 - 1); 458 /* 459 Feed time signal into oldest anaQmf->no_channels states 460 */ 461 { 462 FIXP_QAS *FilterStatesAnaTmp = ((FIXP_QAS *)anaQmf->FilterStates) + offset; 463 464 /* Feed and scale actual time in slot */ 465 for (int i = anaQmf->no_channels >> 1; i != 0; i--) { 466 /* Place INT_PCM value left aligned in scaledTimeIn */ 467 #if (QAS_BITS == SAMPLE_BITS) 468 *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; 469 timeIn += stride; 470 *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; 471 timeIn += stride; 472 #elif (QAS_BITS > SAMPLE_BITS) 473 *FilterStatesAnaTmp++ = ((FIXP_QAS)*timeIn) << (QAS_BITS - SAMPLE_BITS); 474 timeIn += stride; 475 *FilterStatesAnaTmp++ = ((FIXP_QAS)*timeIn) << (QAS_BITS - SAMPLE_BITS); 476 timeIn += stride; 477 #else 478 *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn) >> (SAMPLE_BITS - QAS_BITS)); 479 timeIn += stride; 480 *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn) >> (SAMPLE_BITS - QAS_BITS)); 481 timeIn += stride; 482 #endif 483 } 484 } 485 486 if (anaQmf->flags & QMF_FLAG_NONSYMMETRIC) { 487 qmfAnaPrototypeFirSlot_NonSymmetric(pWorkBuffer, anaQmf->no_channels, 488 anaQmf->p_filter, anaQmf->p_stride, 489 (FIXP_QAS *)anaQmf->FilterStates); 490 } else { 491 qmfAnaPrototypeFirSlot(pWorkBuffer, anaQmf->no_channels, anaQmf->p_filter, 492 anaQmf->p_stride, (FIXP_QAS *)anaQmf->FilterStates); 493 } 494 495 if (anaQmf->flags & QMF_FLAG_LP) { 496 if (anaQmf->flags & QMF_FLAG_CLDFB) 497 qmfForwardModulationLP_odd(anaQmf, pWorkBuffer, qmfReal); 498 else 499 qmfForwardModulationLP_even(anaQmf, pWorkBuffer, qmfReal); 500 501 } else { 502 qmfForwardModulationHQ(anaQmf, pWorkBuffer, qmfReal, qmfImag); 503 } 504 /* 505 Shift filter states 506 507 Should be realized with modulo adressing on a DSP instead of a true buffer 508 shift 509 */ 510 FDKmemmove(anaQmf->FilterStates, 511 (FIXP_QAS *)anaQmf->FilterStates + anaQmf->no_channels, 512 offset * sizeof(FIXP_QAS)); 513 } 514 515 /*! 516 * 517 * \brief Perform complex-valued subband filtering of the time domain 518 * data of timeIn and stores the real part of the subband 519 * samples in rAnalysis, and the imaginary part in iAnalysis 520 * The qmf coefficient table is symmetric. The symmetry is expoited by 521 * shrinking the coefficient table to half the size. The addressing mode 522 * takes care of the symmetries. 523 * 524 * 525 * \sa PolyphaseFiltering 526 */ 527 #if (SAMPLE_BITS != DFRACT_BITS) && (QAS_BITS == DFRACT_BITS) 528 void qmfAnalysisFiltering( 529 HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ 530 FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */ 531 FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */ 532 QMF_SCALE_FACTOR *scaleFactor, const LONG *timeIn, /*!< Time signal */ 533 const int timeIn_e, const int stride, 534 FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ 535 ) { 536 int i; 537 int no_channels = anaQmf->no_channels; 538 539 scaleFactor->lb_scale = 540 -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - timeIn_e; 541 scaleFactor->lb_scale -= anaQmf->filterScale; 542 543 for (i = 0; i < anaQmf->no_col; i++) { 544 FIXP_DBL *qmfImagSlot = NULL; 545 546 if (!(anaQmf->flags & QMF_FLAG_LP)) { 547 qmfImagSlot = qmfImag[i]; 548 } 549 550 qmfAnalysisFilteringSlot(anaQmf, qmfReal[i], qmfImagSlot, timeIn, stride, 551 pWorkBuffer); 552 553 timeIn += no_channels * stride; 554 555 } /* no_col loop i */ 556 } 557 #endif 558 559 void qmfAnalysisFiltering( 560 HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ 561 FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */ 562 FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */ 563 QMF_SCALE_FACTOR *scaleFactor, const INT_PCM *timeIn, /*!< Time signal */ 564 const int timeIn_e, const int stride, 565 FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ 566 ) { 567 int i; 568 int no_channels = anaQmf->no_channels; 569 570 scaleFactor->lb_scale = 571 -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - timeIn_e; 572 scaleFactor->lb_scale -= anaQmf->filterScale; 573 574 for (i = 0; i < anaQmf->no_col; i++) { 575 FIXP_DBL *qmfImagSlot = NULL; 576 577 if (!(anaQmf->flags & QMF_FLAG_LP)) { 578 qmfImagSlot = qmfImag[i]; 579 } 580 581 qmfAnalysisFilteringSlot(anaQmf, qmfReal[i], qmfImagSlot, timeIn, stride, 582 pWorkBuffer); 583 584 timeIn += no_channels * stride; 585 586 } /* no_col loop i */ 587 } 588 589 /*! 590 * 591 * \brief Perform low power inverse modulation of the subband 592 * samples stored in rSubband (real part) and iSubband (imaginary 593 * part) and stores the result in pWorkBuffer. 594 * 595 */ 596 inline static void qmfInverseModulationLP_even( 597 HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ 598 const FIXP_DBL *qmfReal, /*!< Pointer to qmf real subband slot (input) */ 599 const int scaleFactorLowBand, /*!< Scalefactor for Low band */ 600 const int scaleFactorHighBand, /*!< Scalefactor for High band */ 601 FIXP_DBL *pTimeOut /*!< Pointer to qmf subband slot (output)*/ 602 ) { 603 int i; 604 int L = synQmf->no_channels; 605 int M = L >> 1; 606 int scale; 607 FIXP_DBL tmp; 608 FIXP_DBL *RESTRICT tReal = pTimeOut; 609 FIXP_DBL *RESTRICT tImag = pTimeOut + L; 610 611 /* Move input to output vector with offset */ 612 scaleValues(&tReal[0], &qmfReal[0], synQmf->lsb, (int)scaleFactorLowBand); 613 scaleValues(&tReal[0 + synQmf->lsb], &qmfReal[0 + synQmf->lsb], 614 synQmf->usb - synQmf->lsb, (int)scaleFactorHighBand); 615 FDKmemclear(&tReal[0 + synQmf->usb], (L - synQmf->usb) * sizeof(FIXP_DBL)); 616 617 /* Dct type-2 transform */ 618 dct_II(tReal, tImag, L, &scale); 619 620 /* Expand output and replace inplace the output buffers */ 621 tImag[0] = tReal[M]; 622 tImag[M] = (FIXP_DBL)0; 623 tmp = tReal[0]; 624 tReal[0] = tReal[M]; 625 tReal[M] = tmp; 626 627 for (i = 1; i < M / 2; i++) { 628 /* Imag */ 629 tmp = tReal[L - i]; 630 tImag[M - i] = tmp; 631 tImag[i + M] = -tmp; 632 633 tmp = tReal[M + i]; 634 tImag[i] = tmp; 635 tImag[L - i] = -tmp; 636 637 /* Real */ 638 tReal[M + i] = tReal[i]; 639 tReal[L - i] = tReal[M - i]; 640 tmp = tReal[i]; 641 tReal[i] = tReal[M - i]; 642 tReal[M - i] = tmp; 643 } 644 /* Remaining odd terms */ 645 tmp = tReal[M + M / 2]; 646 tImag[M / 2] = tmp; 647 tImag[M / 2 + M] = -tmp; 648 649 tReal[M + M / 2] = tReal[M / 2]; 650 } 651 652 inline static void qmfInverseModulationLP_odd( 653 HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ 654 const FIXP_DBL *qmfReal, /*!< Pointer to qmf real subband slot (input) */ 655 const int scaleFactorLowBand, /*!< Scalefactor for Low band */ 656 const int scaleFactorHighBand, /*!< Scalefactor for High band */ 657 FIXP_DBL *pTimeOut /*!< Pointer to qmf subband slot (output)*/ 658 ) { 659 int i; 660 int L = synQmf->no_channels; 661 int M = L >> 1; 662 int shift = 0; 663 664 /* Move input to output vector with offset */ 665 scaleValues(pTimeOut + M, qmfReal, synQmf->lsb, scaleFactorLowBand); 666 scaleValues(pTimeOut + M + synQmf->lsb, qmfReal + synQmf->lsb, 667 synQmf->usb - synQmf->lsb, scaleFactorHighBand); 668 FDKmemclear(pTimeOut + M + synQmf->usb, (L - synQmf->usb) * sizeof(FIXP_DBL)); 669 670 dct_IV(pTimeOut + M, L, &shift); 671 for (i = 0; i < M; i++) { 672 pTimeOut[i] = pTimeOut[L - 1 - i]; 673 pTimeOut[2 * L - 1 - i] = -pTimeOut[L + i]; 674 } 675 } 676 677 #ifndef FUNCTION_qmfInverseModulationHQ 678 /*! 679 * 680 * \brief Perform complex-valued inverse modulation of the subband 681 * samples stored in rSubband (real part) and iSubband (imaginary 682 * part) and stores the result in pWorkBuffer. 683 * 684 */ 685 inline static void qmfInverseModulationHQ( 686 HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ 687 const FIXP_DBL *qmfReal, /*!< Pointer to qmf real subband slot */ 688 const FIXP_DBL *qmfImag, /*!< Pointer to qmf imag subband slot */ 689 const int scaleFactorLowBand, /*!< Scalefactor for Low band */ 690 const int scaleFactorHighBand, /*!< Scalefactor for High band */ 691 FIXP_DBL *pWorkBuffer /*!< WorkBuffer (output) */ 692 ) { 693 int i; 694 int L = synQmf->no_channels; 695 int M = L >> 1; 696 int shift = 0; 697 FIXP_DBL *RESTRICT tReal = pWorkBuffer; 698 FIXP_DBL *RESTRICT tImag = pWorkBuffer + L; 699 700 if (synQmf->flags & QMF_FLAG_CLDFB) { 701 for (i = 0; i < synQmf->lsb; i++) { 702 cplxMult(&tImag[i], &tReal[i], scaleValue(qmfImag[i], scaleFactorLowBand), 703 scaleValue(qmfReal[i], scaleFactorLowBand), synQmf->t_cos[i], 704 synQmf->t_sin[i]); 705 } 706 for (; i < synQmf->usb; i++) { 707 cplxMult(&tImag[i], &tReal[i], 708 scaleValue(qmfImag[i], scaleFactorHighBand), 709 scaleValue(qmfReal[i], scaleFactorHighBand), synQmf->t_cos[i], 710 synQmf->t_sin[i]); 711 } 712 } 713 714 if ((synQmf->flags & QMF_FLAG_CLDFB) == 0) { 715 scaleValues(&tReal[0], &qmfReal[0], synQmf->lsb, (int)scaleFactorLowBand); 716 scaleValues(&tReal[0 + synQmf->lsb], &qmfReal[0 + synQmf->lsb], 717 synQmf->usb - synQmf->lsb, (int)scaleFactorHighBand); 718 scaleValues(&tImag[0], &qmfImag[0], synQmf->lsb, (int)scaleFactorLowBand); 719 scaleValues(&tImag[0 + synQmf->lsb], &qmfImag[0 + synQmf->lsb], 720 synQmf->usb - synQmf->lsb, (int)scaleFactorHighBand); 721 } 722 723 FDKmemclear(&tReal[synQmf->usb], 724 (synQmf->no_channels - synQmf->usb) * sizeof(FIXP_DBL)); 725 FDKmemclear(&tImag[synQmf->usb], 726 (synQmf->no_channels - synQmf->usb) * sizeof(FIXP_DBL)); 727 728 dct_IV(tReal, L, &shift); 729 dst_IV(tImag, L, &shift); 730 731 if (synQmf->flags & QMF_FLAG_CLDFB) { 732 for (i = 0; i < M; i++) { 733 FIXP_DBL r1, i1, r2, i2; 734 r1 = tReal[i]; 735 i2 = tImag[L - 1 - i]; 736 r2 = tReal[L - i - 1]; 737 i1 = tImag[i]; 738 739 tReal[i] = (r1 - i1) >> 1; 740 tImag[L - 1 - i] = -(r1 + i1) >> 1; 741 tReal[L - i - 1] = (r2 - i2) >> 1; 742 tImag[i] = -(r2 + i2) >> 1; 743 } 744 } else { 745 /* The array accesses are negative to compensate the missing minus sign in 746 * the low and hi band gain. */ 747 /* 26 cycles on ARM926 */ 748 for (i = 0; i < M; i++) { 749 FIXP_DBL r1, i1, r2, i2; 750 r1 = -tReal[i]; 751 i2 = -tImag[L - 1 - i]; 752 r2 = -tReal[L - i - 1]; 753 i1 = -tImag[i]; 754 755 tReal[i] = (r1 - i1) >> 1; 756 tImag[L - 1 - i] = -(r1 + i1) >> 1; 757 tReal[L - i - 1] = (r2 - i2) >> 1; 758 tImag[i] = -(r2 + i2) >> 1; 759 } 760 } 761 } 762 #endif /* #ifndef FUNCTION_qmfInverseModulationHQ */ 763 764 /*! 765 * 766 * \brief Create QMF filter bank instance 767 * 768 * \return 0 if successful 769 * 770 */ 771 static int qmfInitFilterBank( 772 HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Handle to return */ 773 void *pFilterStates, /*!< Handle to filter states */ 774 int noCols, /*!< Number of timeslots per frame */ 775 int lsb, /*!< Lower end of QMF frequency range */ 776 int usb, /*!< Upper end of QMF frequency range */ 777 int no_channels, /*!< Number of channels (bands) */ 778 UINT flags, /*!< flags */ 779 int synflag) /*!< 1: synthesis; 0: analysis */ 780 { 781 FDKmemclear(h_Qmf, sizeof(QMF_FILTER_BANK)); 782 783 if (flags & QMF_FLAG_MPSLDFB) { 784 flags |= QMF_FLAG_NONSYMMETRIC; 785 flags |= QMF_FLAG_MPSLDFB_OPTIMIZE_MODULATION; 786 787 h_Qmf->t_cos = NULL; 788 h_Qmf->t_sin = NULL; 789 h_Qmf->filterScale = QMF_MPSLDFB_PFT_SCALE; 790 h_Qmf->p_stride = 1; 791 792 switch (no_channels) { 793 case 64: 794 h_Qmf->p_filter = qmf_mpsldfb_640; 795 h_Qmf->FilterSize = 640; 796 break; 797 case 32: 798 h_Qmf->p_filter = qmf_mpsldfb_320; 799 h_Qmf->FilterSize = 320; 800 break; 801 default: 802 return -1; 803 } 804 } 805 806 if (!(flags & QMF_FLAG_MPSLDFB) && (flags & QMF_FLAG_CLDFB)) { 807 flags |= QMF_FLAG_NONSYMMETRIC; 808 h_Qmf->filterScale = QMF_CLDFB_PFT_SCALE; 809 810 h_Qmf->p_stride = 1; 811 switch (no_channels) { 812 case 64: 813 h_Qmf->t_cos = qmf_phaseshift_cos64_cldfb; 814 h_Qmf->t_sin = qmf_phaseshift_sin64_cldfb; 815 h_Qmf->p_filter = qmf_cldfb_640; 816 h_Qmf->FilterSize = 640; 817 break; 818 case 32: 819 h_Qmf->t_cos = (synflag) ? qmf_phaseshift_cos32_cldfb_syn 820 : qmf_phaseshift_cos32_cldfb_ana; 821 h_Qmf->t_sin = qmf_phaseshift_sin32_cldfb; 822 h_Qmf->p_filter = qmf_cldfb_320; 823 h_Qmf->FilterSize = 320; 824 break; 825 case 16: 826 h_Qmf->t_cos = (synflag) ? qmf_phaseshift_cos16_cldfb_syn 827 : qmf_phaseshift_cos16_cldfb_ana; 828 h_Qmf->t_sin = qmf_phaseshift_sin16_cldfb; 829 h_Qmf->p_filter = qmf_cldfb_160; 830 h_Qmf->FilterSize = 160; 831 break; 832 case 8: 833 h_Qmf->t_cos = (synflag) ? qmf_phaseshift_cos8_cldfb_syn 834 : qmf_phaseshift_cos8_cldfb_ana; 835 h_Qmf->t_sin = qmf_phaseshift_sin8_cldfb; 836 h_Qmf->p_filter = qmf_cldfb_80; 837 h_Qmf->FilterSize = 80; 838 break; 839 default: 840 return -1; 841 } 842 } 843 844 if (!(flags & QMF_FLAG_MPSLDFB) && ((flags & QMF_FLAG_CLDFB) == 0)) { 845 switch (no_channels) { 846 case 64: 847 h_Qmf->p_filter = qmf_pfilt640; 848 h_Qmf->t_cos = qmf_phaseshift_cos64; 849 h_Qmf->t_sin = qmf_phaseshift_sin64; 850 h_Qmf->p_stride = 1; 851 h_Qmf->FilterSize = 640; 852 h_Qmf->filterScale = 0; 853 break; 854 case 40: 855 if (synflag) { 856 break; 857 } else { 858 h_Qmf->p_filter = qmf_pfilt400; /* Scaling factor 0.8 */ 859 h_Qmf->t_cos = qmf_phaseshift_cos40; 860 h_Qmf->t_sin = qmf_phaseshift_sin40; 861 h_Qmf->filterScale = 1; 862 h_Qmf->p_stride = 1; 863 h_Qmf->FilterSize = no_channels * 10; 864 } 865 break; 866 case 32: 867 h_Qmf->p_filter = qmf_pfilt640; 868 if (flags & QMF_FLAG_DOWNSAMPLED) { 869 h_Qmf->t_cos = qmf_phaseshift_cos_downsamp32; 870 h_Qmf->t_sin = qmf_phaseshift_sin_downsamp32; 871 } else { 872 h_Qmf->t_cos = qmf_phaseshift_cos32; 873 h_Qmf->t_sin = qmf_phaseshift_sin32; 874 } 875 h_Qmf->p_stride = 2; 876 h_Qmf->FilterSize = 640; 877 h_Qmf->filterScale = 0; 878 break; 879 case 20: 880 h_Qmf->p_filter = qmf_pfilt200; 881 h_Qmf->p_stride = 1; 882 h_Qmf->FilterSize = 200; 883 h_Qmf->filterScale = 0; 884 break; 885 case 12: 886 h_Qmf->p_filter = qmf_pfilt120; 887 h_Qmf->p_stride = 1; 888 h_Qmf->FilterSize = 120; 889 h_Qmf->filterScale = 0; 890 break; 891 case 8: 892 h_Qmf->p_filter = qmf_pfilt640; 893 h_Qmf->p_stride = 8; 894 h_Qmf->FilterSize = 640; 895 h_Qmf->filterScale = 0; 896 break; 897 case 16: 898 h_Qmf->p_filter = qmf_pfilt640; 899 h_Qmf->t_cos = qmf_phaseshift_cos16; 900 h_Qmf->t_sin = qmf_phaseshift_sin16; 901 h_Qmf->p_stride = 4; 902 h_Qmf->FilterSize = 640; 903 h_Qmf->filterScale = 0; 904 break; 905 case 24: 906 h_Qmf->p_filter = qmf_pfilt240; 907 h_Qmf->t_cos = qmf_phaseshift_cos24; 908 h_Qmf->t_sin = qmf_phaseshift_sin24; 909 h_Qmf->p_stride = 1; 910 h_Qmf->FilterSize = 240; 911 h_Qmf->filterScale = 1; 912 break; 913 default: 914 return -1; 915 } 916 } 917 918 h_Qmf->synScalefactor = h_Qmf->filterScale; 919 // DCT|DST dependency 920 switch (no_channels) { 921 case 128: 922 h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + 1; 923 break; 924 case 40: { 925 h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 1; 926 } break; 927 case 64: 928 h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK; 929 break; 930 case 8: 931 h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 3; 932 break; 933 case 12: 934 h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK; 935 break; 936 case 20: 937 h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + 1; 938 break; 939 case 32: 940 h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 1; 941 break; 942 case 16: 943 h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 2; 944 break; 945 case 24: 946 h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 1; 947 break; 948 default: 949 return -1; 950 } 951 952 h_Qmf->flags = flags; 953 954 h_Qmf->no_channels = no_channels; 955 h_Qmf->no_col = noCols; 956 957 h_Qmf->lsb = fMin(lsb, h_Qmf->no_channels); 958 h_Qmf->usb = synflag 959 ? fMin(usb, h_Qmf->no_channels) 960 : usb; /* was: h_Qmf->usb = fMin(usb, h_Qmf->no_channels); */ 961 962 h_Qmf->FilterStates = (void *)pFilterStates; 963 964 h_Qmf->outScalefactor = 965 (ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + h_Qmf->filterScale) + 966 h_Qmf->synScalefactor; 967 968 h_Qmf->outGain_m = 969 (FIXP_DBL)0x80000000; /* default init value will be not applied */ 970 h_Qmf->outGain_e = 0; 971 972 return (0); 973 } 974 975 /*! 976 * 977 * \brief Adjust synthesis qmf filter states 978 * 979 * \return void 980 * 981 */ 982 static inline void qmfAdaptFilterStates( 983 HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Filter Bank */ 984 int scaleFactorDiff) /*!< Scale factor difference to be applied */ 985 { 986 if (synQmf == NULL || synQmf->FilterStates == NULL) { 987 return; 988 } 989 if (scaleFactorDiff > 0) { 990 scaleValuesSaturate((FIXP_QSS *)synQmf->FilterStates, 991 synQmf->no_channels * (QMF_NO_POLY * 2 - 1), 992 scaleFactorDiff); 993 } else { 994 scaleValues((FIXP_QSS *)synQmf->FilterStates, 995 synQmf->no_channels * (QMF_NO_POLY * 2 - 1), scaleFactorDiff); 996 } 997 } 998 999 /*! 1000 * 1001 * \brief Create QMF filter bank instance 1002 * 1003 * 1004 * \return 0 if succesful 1005 * 1006 */ 1007 int qmfInitAnalysisFilterBank( 1008 HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */ 1009 FIXP_QAS *pFilterStates, /*!< Handle to filter states */ 1010 int noCols, /*!< Number of timeslots per frame */ 1011 int lsb, /*!< lower end of QMF */ 1012 int usb, /*!< upper end of QMF */ 1013 int no_channels, /*!< Number of channels (bands) */ 1014 int flags) /*!< Low Power flag */ 1015 { 1016 int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, 1017 no_channels, flags, 0); 1018 if (!(flags & QMF_FLAG_KEEP_STATES) && (h_Qmf->FilterStates != NULL)) { 1019 FDKmemclear(h_Qmf->FilterStates, 1020 (2 * QMF_NO_POLY - 1) * h_Qmf->no_channels * sizeof(FIXP_QAS)); 1021 } 1022 1023 FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->lsb); 1024 1025 return err; 1026 } 1027 1028 /*! 1029 * 1030 * \brief Create QMF filter bank instance 1031 * 1032 * 1033 * \return 0 if succesful 1034 * 1035 */ 1036 int qmfInitSynthesisFilterBank( 1037 HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */ 1038 FIXP_QSS *pFilterStates, /*!< Handle to filter states */ 1039 int noCols, /*!< Number of timeslots per frame */ 1040 int lsb, /*!< lower end of QMF */ 1041 int usb, /*!< upper end of QMF */ 1042 int no_channels, /*!< Number of channels (bands) */ 1043 int flags) /*!< Low Power flag */ 1044 { 1045 int oldOutScale = h_Qmf->outScalefactor; 1046 int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, 1047 no_channels, flags, 1); 1048 if (h_Qmf->FilterStates != NULL) { 1049 if (!(flags & QMF_FLAG_KEEP_STATES)) { 1050 FDKmemclear( 1051 h_Qmf->FilterStates, 1052 (2 * QMF_NO_POLY - 1) * h_Qmf->no_channels * sizeof(FIXP_QSS)); 1053 } else { 1054 qmfAdaptFilterStates(h_Qmf, oldOutScale - h_Qmf->outScalefactor); 1055 } 1056 } 1057 1058 FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->lsb); 1059 FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->usb); 1060 1061 return err; 1062 } 1063 1064 /*! 1065 * 1066 * \brief Change scale factor for output data and adjust qmf filter states 1067 * 1068 * \return void 1069 * 1070 */ 1071 void qmfChangeOutScalefactor( 1072 HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ 1073 int outScalefactor /*!< New scaling factor for output data */ 1074 ) { 1075 if (synQmf == NULL) { 1076 return; 1077 } 1078 1079 /* Add internal filterbank scale */ 1080 outScalefactor += 1081 (ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + synQmf->filterScale) + 1082 synQmf->synScalefactor; 1083 1084 /* adjust filter states when scale factor has been changed */ 1085 if (synQmf->outScalefactor != outScalefactor) { 1086 int diff; 1087 1088 diff = synQmf->outScalefactor - outScalefactor; 1089 1090 qmfAdaptFilterStates(synQmf, diff); 1091 1092 /* save new scale factor */ 1093 synQmf->outScalefactor = outScalefactor; 1094 } 1095 } 1096 1097 /*! 1098 * 1099 * \brief Get scale factor change which was set by qmfChangeOutScalefactor() 1100 * 1101 * \return scaleFactor 1102 * 1103 */ 1104 int qmfGetOutScalefactor( 1105 HANDLE_QMF_FILTER_BANK synQmf) /*!< Handle of Qmf Synthesis Bank */ 1106 { 1107 int scaleFactor = synQmf->outScalefactor 1108 ? (synQmf->outScalefactor - 1109 (ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + 1110 synQmf->filterScale + synQmf->synScalefactor)) 1111 : 0; 1112 return scaleFactor; 1113 } 1114 1115 /*! 1116 * 1117 * \brief Change gain for output data 1118 * 1119 * \return void 1120 * 1121 */ 1122 void qmfChangeOutGain( 1123 HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ 1124 FIXP_DBL outputGain, /*!< New gain for output data (mantissa) */ 1125 int outputGainScale /*!< New gain for output data (exponent) */ 1126 ) { 1127 synQmf->outGain_m = outputGain; 1128 synQmf->outGain_e = outputGainScale; 1129 } 1130 1131 /* When QMF_16IN_32OUT is set, synthesis functions for 16 and 32 bit parallel 1132 * output is compiled */ 1133 #define INT_PCM_QMFOUT INT_PCM 1134 #define SAMPLE_BITS_QMFOUT SAMPLE_BITS 1135 #include "qmf_pcm.h" 1136