1 2/* ----------------------------------------------------------------------------------------------------------- 3Software License for The Fraunhofer FDK AAC Codec Library for Android 4 5� Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V. 6 All rights reserved. 7 8 1. INTRODUCTION 9The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements 10the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. 11This FDK AAC Codec software is intended to be used on a wide variety of Android devices. 12 13AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual 14audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by 15independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part 16of the MPEG specifications. 17 18Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) 19may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners 20individually for the purpose of encoding or decoding bit streams in products that are compliant with 21the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license 22these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec 23software may already be covered under those patent licenses when it is used for those licensed purposes only. 24 25Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, 26are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional 27applications information and documentation. 28 292. COPYRIGHT LICENSE 30 31Redistribution and use in source and binary forms, with or without modification, are permitted without 32payment of copyright license fees provided that you satisfy the following conditions: 33 34You must retain the complete text of this software license in redistributions of the FDK AAC Codec or 35your modifications thereto in source code form. 36 37You must retain the complete text of this software license in the documentation and/or other materials 38provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. 39You must make available free of charge copies of the complete source code of the FDK AAC Codec and your 40modifications thereto to recipients of copies in binary form. 41 42The name of Fraunhofer may not be used to endorse or promote products derived from this library without 43prior written permission. 44 45You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec 46software or your modifications thereto. 47 48Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software 49and the date of any change. For modified versions of the FDK AAC Codec, the term 50"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term 51"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." 52 533. NO PATENT LICENSE 54 55NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, 56ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with 57respect to this software. 58 59You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized 60by appropriate patent licenses. 61 624. DISCLAIMER 63 64This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors 65"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties 66of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 67CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, 68including but not limited to procurement of substitute goods or services; loss of use, data, or profits, 69or business interruption, however caused and on any theory of liability, whether in contract, strict 70liability, or tort (including negligence), arising in any way out of the use of this software, even if 71advised of the possibility of such damage. 72 735. CONTACT INFORMATION 74 75Fraunhofer Institute for Integrated Circuits IIS 76Attention: Audio and Multimedia Departments - FDK AAC LL 77Am Wolfsmantel 33 7891058 Erlangen, Germany 79 80www.iis.fraunhofer.de/amm 81amm-info@iis.fraunhofer.de 82----------------------------------------------------------------------------------------------------------- */ 83 84/******************************** Fraunhofer IIS *************************** 85 86 Author(s): Markus Lohwasser, Josef Hoepfl, Manuel Jander 87 Description: QMF filterbank 88 89******************************************************************************/ 90 91/*! 92 \file 93 \brief Complex qmf analysis/synthesis, 94 This module contains the qmf filterbank for analysis [ cplxAnalysisQmfFiltering() ] and 95 synthesis [ cplxSynthesisQmfFiltering() ]. It is a polyphase implementation of a complex 96 exponential modulated filter bank. The analysis part usually runs at half the sample rate 97 than the synthesis part. (So called "dual-rate" mode.) 98 99 The coefficients of the prototype filter are specified in #sbr_qmf_64_640 (in sbr_rom.cpp). 100 Thus only a 64 channel version (32 on the analysis side) with a 640 tap prototype filter 101 are used. 102 103 \anchor PolyphaseFiltering <h2>About polyphase filtering</h2> 104 The polyphase implementation of a filterbank requires filtering at the input and output. 105 This is implemented as part of cplxAnalysisQmfFiltering() and cplxSynthesisQmfFiltering(). 106 The implementation requires the filter coefficients in a specific structure as described in 107 #sbr_qmf_64_640_qmf (in sbr_rom.cpp). 108 109 This module comprises the computationally most expensive functions of the SBR decoder. The accuracy of 110 computations is also important and has a direct impact on the overall sound quality. Therefore a special 111 test program is available which can be used to only test the filterbank: main_audio.cpp 112 113 This modules also uses scaling of data to provide better SNR on fixed-point processors. See #QMF_SCALE_FACTOR (in sbr_scale.h) for details. 114 An interesting note: The function getScalefactor() can constitute a significant amount of computational complexity - very much depending on the 115 bitrate. Since it is a rather small function, effective assembler optimization might be possible. 116 117*/ 118 119#include "qmf.h" 120 121 122#include "fixpoint_math.h" 123#include "dct.h" 124 125#ifdef QMFSYN_STATES_16BIT 126#define QSSCALE (7) 127#define FX_DBL2FX_QSS(x) ((FIXP_QSS) ((x)>>(DFRACT_BITS-QSS_BITS-QSSCALE) )) 128#define FX_QSS2FX_DBL(x) ((FIXP_DBL)((LONG)x)<<(DFRACT_BITS-QSS_BITS-QSSCALE)) 129#else 130#define QSSCALE (0) 131#define FX_DBL2FX_QSS(x) (x) 132#define FX_QSS2FX_DBL(x) (x) 133#endif 134 135 136#if defined(__arm__) 137#include "arm/qmf_arm.cpp" 138 139#endif 140 141/*! 142 * \brief Algorithmic scaling in sbrForwardModulation() 143 * 144 * The scaling in sbrForwardModulation() is caused by: 145 * 146 * \li 1 R_SHIFT in sbrForwardModulation() 147 * \li 5/6 R_SHIFT in dct3() if using 32/64 Bands 148 * \li 1 ommited gain of 2.0 in qmfForwardModulation() 149 */ 150#define ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK 7 151 152/*! 153 * \brief Algorithmic scaling in cplxSynthesisQmfFiltering() 154 * 155 * The scaling in cplxSynthesisQmfFiltering() is caused by: 156 * 157 * \li 5/6 R_SHIFT in dct2() if using 32/64 Bands 158 * \li 1 ommited gain of 2.0 in qmfInverseModulation() 159 * \li -6 division by 64 in synthesis filterbank 160 * \li x bits external influence 161 */ 162#define ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK 1 163 164 165/*! 166 \brief Perform Synthesis Prototype Filtering on a single slot of input data. 167 168 The filter takes 2 * qmf->no_channels of input data and 169 generates qmf->no_channels time domain output samples. 170*/ 171static 172#ifndef FUNCTION_qmfSynPrototypeFirSlot 173void qmfSynPrototypeFirSlot( 174#else 175void qmfSynPrototypeFirSlot_fallback( 176#endif 177 HANDLE_QMF_FILTER_BANK qmf, 178 FIXP_QMF *RESTRICT realSlot, /*!< Input: Pointer to real Slot */ 179 FIXP_QMF *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */ 180 INT_PCM *RESTRICT timeOut, /*!< Time domain data */ 181 int stride 182 ) 183{ 184 FIXP_QSS* FilterStates = (FIXP_QSS*)qmf->FilterStates; 185 int no_channels = qmf->no_channels; 186 const FIXP_PFT *p_Filter = qmf->p_filter; 187 int p_stride = qmf->p_stride; 188 int j; 189 FIXP_QSS *RESTRICT sta = FilterStates; 190 const FIXP_PFT *RESTRICT p_flt, *RESTRICT p_fltm; 191 int scale = ((DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor); 192 193 p_flt = p_Filter+p_stride*QMF_NO_POLY; /* 5-ter von 330 */ 194 p_fltm = p_Filter+(qmf->FilterSize/2)-p_stride*QMF_NO_POLY; /* 5 + (320 - 2*5) = 315-ter von 330 */ 195 196 FDK_ASSERT(SAMPLE_BITS-1-qmf->outScalefactor >= 0); // (DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor >= 0); 197 198 for (j = no_channels-1; j >= 0; j--) { /* ---- l�uft ueber alle Linien eines Slots ---- */ 199 FIXP_QMF imag = imagSlot[j]; // no_channels-1 .. 0 200 FIXP_QMF real = realSlot[j]; // ~~"~~ 201 { 202 INT_PCM tmp; 203 FIXP_DBL Are = FX_QSS2FX_DBL(sta[0]) + fMultDiv2( p_fltm[0] , real); 204 205 if (qmf->outGain!=(FIXP_DBL)0x80000000) { 206 Are = fMult(Are,qmf->outGain); 207 } 208 209 #if SAMPLE_BITS > 16 210 tmp = (INT_PCM)(SATURATE_SHIFT(fAbs(Are), scale, SAMPLE_BITS)); 211 #else 212 tmp = (INT_PCM)(SATURATE_RIGHT_SHIFT(fAbs(Are), scale, SAMPLE_BITS)); 213 #endif 214 if (Are < (FIXP_QMF)0) { 215 tmp = -tmp; 216 } 217 timeOut[ (j)*stride ] = tmp; 218 } 219 220 sta[0] = sta[1] + FX_DBL2FX_QSS(fMultDiv2( p_flt [4] , imag )); 221 sta[1] = sta[2] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[1] , real )); 222 sta[2] = sta[3] + FX_DBL2FX_QSS(fMultDiv2( p_flt [3] , imag )); 223 sta[3] = sta[4] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[2] , real )); 224 sta[4] = sta[5] + FX_DBL2FX_QSS(fMultDiv2( p_flt [2] , imag )); 225 sta[5] = sta[6] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[3] , real )); 226 sta[6] = sta[7] + FX_DBL2FX_QSS(fMultDiv2( p_flt [1] , imag )); 227 sta[7] = sta[8] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[4] , real )); 228 sta[8] = FX_DBL2FX_QSS(fMultDiv2( p_flt [0] , imag )); 229 230 p_flt += (p_stride*QMF_NO_POLY); 231 p_fltm -= (p_stride*QMF_NO_POLY); 232 sta += 9; // = (2*QMF_NO_POLY-1); 233 } 234} 235 236#ifndef FUNCTION_qmfSynPrototypeFirSlot_NonSymmetric 237/*! 238 \brief Perform Synthesis Prototype Filtering on a single slot of input data. 239 240 The filter takes 2 * qmf->no_channels of input data and 241 generates qmf->no_channels time domain output samples. 242*/ 243static 244void qmfSynPrototypeFirSlot_NonSymmetric( 245 HANDLE_QMF_FILTER_BANK qmf, 246 FIXP_QMF *RESTRICT realSlot, /*!< Input: Pointer to real Slot */ 247 FIXP_QMF *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */ 248 INT_PCM *RESTRICT timeOut, /*!< Time domain data */ 249 int stride 250 ) 251{ 252 FIXP_QSS* FilterStates = (FIXP_QSS*)qmf->FilterStates; 253 int no_channels = qmf->no_channels; 254 const FIXP_PFT *p_Filter = qmf->p_filter; 255 int p_stride = qmf->p_stride; 256 int j; 257 FIXP_QSS *RESTRICT sta = FilterStates; 258 const FIXP_PFT *RESTRICT p_flt, *RESTRICT p_fltm; 259 int scale = ((DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor); 260 261 p_flt = p_Filter; /*!< Pointer to first half of filter coefficients */ 262 p_fltm = &p_flt[qmf->FilterSize/2]; /* at index 320, overall 640 coefficients */ 263 264 FDK_ASSERT(SAMPLE_BITS-1-qmf->outScalefactor >= 0); // (DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor >= 0); 265 266 for (j = no_channels-1; j >= 0; j--) { /* ---- l�uft ueber alle Linien eines Slots ---- */ 267 268 FIXP_QMF imag = imagSlot[j]; // no_channels-1 .. 0 269 FIXP_QMF real = realSlot[j]; // ~~"~~ 270 { 271 INT_PCM tmp; 272 FIXP_QMF Are = sta[0] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[4] , real )); 273 274 #if SAMPLE_BITS > 16 275 tmp = (INT_PCM)(SATURATE_SHIFT(fAbs(Are), scale, SAMPLE_BITS)); 276 #else 277 tmp = (INT_PCM)(SATURATE_RIGHT_SHIFT(fAbs(Are), scale, SAMPLE_BITS)); 278 #endif 279 if (Are < (FIXP_QMF)0) { 280 tmp = -tmp; 281 } 282 timeOut[j*stride] = tmp; 283 } 284 285 sta[0] = sta[1] + FX_DBL2FX_QSS(fMultDiv2( p_flt [4] , imag )); 286 sta[1] = sta[2] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[3] , real )); 287 sta[2] = sta[3] + FX_DBL2FX_QSS(fMultDiv2( p_flt [3] , imag )); 288 289 sta[3] = sta[4] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[2] , real )); 290 sta[4] = sta[5] + FX_DBL2FX_QSS(fMultDiv2( p_flt [2] , imag )); 291 sta[5] = sta[6] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[1] , real )); 292 sta[6] = sta[7] + FX_DBL2FX_QSS(fMultDiv2( p_flt [1] , imag )); 293 294 sta[7] = sta[8] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[0] , real )); 295 sta[8] = FX_DBL2FX_QSS(fMultDiv2( p_flt [0] , imag )); 296 297 p_flt += (p_stride*QMF_NO_POLY); 298 p_fltm += (p_stride*QMF_NO_POLY); 299 sta += 9; // = (2*QMF_NO_POLY-1); 300 } 301 302} 303#endif /* FUNCTION_qmfSynPrototypeFirSlot_NonSymmetric */ 304 305#ifndef FUNCTION_qmfAnaPrototypeFirSlot 306/*! 307 \brief Perform Analysis Prototype Filtering on a single slot of input data. 308*/ 309static 310void qmfAnaPrototypeFirSlot( FIXP_QMF *analysisBuffer, 311 int no_channels, /*!< Number channels of analysis filter */ 312 const FIXP_PFT *p_filter, 313 int p_stride, /*!< Stide of analysis filter */ 314 FIXP_QAS *RESTRICT pFilterStates 315 ) 316{ 317 int k; 318 319 FIXP_DBL accu; 320 const FIXP_PFT *RESTRICT p_flt = p_filter; 321 FIXP_QMF *RESTRICT pData_0 = analysisBuffer + 2*no_channels - 1; 322 FIXP_QMF *RESTRICT pData_1 = analysisBuffer; 323 324 FIXP_QAS *RESTRICT sta_0 = (FIXP_QAS *)pFilterStates; 325 FIXP_QAS *RESTRICT sta_1 = (FIXP_QAS *)pFilterStates + (2*QMF_NO_POLY*no_channels) - 1; 326 int pfltStep = QMF_NO_POLY * (p_stride); 327 int staStep1 = no_channels<<1; 328 int staStep2 = (no_channels<<3) - 1; /* Rewind one less */ 329 330 /* FIR filter 0 */ 331 accu = fMultDiv2( p_flt[0], *sta_1); sta_1 -= staStep1; 332 accu += fMultDiv2( p_flt[1], *sta_1); sta_1 -= staStep1; 333 accu += fMultDiv2( p_flt[2], *sta_1); sta_1 -= staStep1; 334 accu += fMultDiv2( p_flt[3], *sta_1); sta_1 -= staStep1; 335 accu += fMultDiv2( p_flt[4], *sta_1); 336 *pData_1++ = FX_DBL2FX_QMF(accu<<1); 337 sta_1 += staStep2; 338 339 p_flt += pfltStep; 340 341 /* FIR filters 1..63 127..65 */ 342 for (k=0; k<no_channels-1; k++) 343 { 344 accu = fMultDiv2( p_flt[0], *sta_0); sta_0 += staStep1; 345 accu += fMultDiv2( p_flt[1], *sta_0); sta_0 += staStep1; 346 accu += fMultDiv2( p_flt[2], *sta_0); sta_0 += staStep1; 347 accu += fMultDiv2( p_flt[3], *sta_0); sta_0 += staStep1; 348 accu += fMultDiv2( p_flt[4], *sta_0); 349 *pData_0-- = FX_DBL2FX_QMF(accu<<1); 350 sta_0 -= staStep2; 351 352 accu = fMultDiv2( p_flt[0], *sta_1); sta_1 -= staStep1; 353 accu += fMultDiv2( p_flt[1], *sta_1); sta_1 -= staStep1; 354 accu += fMultDiv2( p_flt[2], *sta_1); sta_1 -= staStep1; 355 accu += fMultDiv2( p_flt[3], *sta_1); sta_1 -= staStep1; 356 accu += fMultDiv2( p_flt[4], *sta_1); 357 *pData_1++ = FX_DBL2FX_QMF(accu<<1); 358 sta_1 += staStep2; 359 360 p_flt += pfltStep; 361 } 362 363 /* FIR filter 64 */ 364 accu = fMultDiv2( p_flt[0], *sta_0); sta_0 += staStep1; 365 accu += fMultDiv2( p_flt[1], *sta_0); sta_0 += staStep1; 366 accu += fMultDiv2( p_flt[2], *sta_0); sta_0 += staStep1; 367 accu += fMultDiv2( p_flt[3], *sta_0); sta_0 += staStep1; 368 accu += fMultDiv2( p_flt[4], *sta_0); 369 *pData_0-- = FX_DBL2FX_QMF(accu<<1); 370 sta_0 -= staStep2; 371} 372#endif /* !defined(FUNCTION_qmfAnaPrototypeFirSlot) */ 373 374 375#ifndef FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric 376/*! 377 \brief Perform Analysis Prototype Filtering on a single slot of input data. 378*/ 379static 380void qmfAnaPrototypeFirSlot_NonSymmetric( 381 FIXP_QMF *analysisBuffer, 382 int no_channels, /*!< Number channels of analysis filter */ 383 const FIXP_PFT *p_filter, 384 int p_stride, /*!< Stide of analysis filter */ 385 FIXP_QAS *RESTRICT pFilterStates 386 ) 387{ 388 const FIXP_PFT *RESTRICT p_flt = p_filter; 389 int p, k; 390 391 for (k = 0; k < 2*no_channels; k++) 392 { 393 FIXP_DBL accu = (FIXP_DBL)0; 394 395 p_flt += QMF_NO_POLY * (p_stride - 1); 396 397 /* 398 Perform FIR-Filter 399 */ 400 for (p = 0; p < QMF_NO_POLY; p++) { 401 accu += fMultDiv2(*p_flt++, pFilterStates[2*no_channels * p]); 402 } 403 analysisBuffer[2*no_channels - 1 - k] = FX_DBL2FX_QMF(accu<<1); 404 pFilterStates++; 405 } 406} 407#endif /* FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric */ 408 409/*! 410 * 411 * \brief Perform real-valued forward modulation of the time domain 412 * data of timeIn and stores the real part of the subband 413 * samples in rSubband 414 * 415 */ 416static void 417qmfForwardModulationLP_even( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ 418 FIXP_QMF *timeIn, /*!< Time Signal */ 419 FIXP_QMF *rSubband ) /*!< Real Output */ 420{ 421 int i; 422 int L = anaQmf->no_channels; 423 int M = L>>1; 424 int scale; 425 FIXP_QMF accu; 426 427 const FIXP_QMF *timeInTmp1 = (FIXP_QMF *) &timeIn[3 * M]; 428 const FIXP_QMF *timeInTmp2 = timeInTmp1; 429 FIXP_QMF *rSubbandTmp = rSubband; 430 431 rSubband[0] = timeIn[3 * M] >> 1; 432 433 for (i = M-1; i != 0; i--) { 434 accu = ((*--timeInTmp1) >> 1) + ((*++timeInTmp2) >> 1); 435 *++rSubbandTmp = accu; 436 } 437 438 timeInTmp1 = &timeIn[2 * M]; 439 timeInTmp2 = &timeIn[0]; 440 rSubbandTmp = &rSubband[M]; 441 442 for (i = L-M; i != 0; i--) { 443 accu = ((*timeInTmp1--) >> 1) - ((*timeInTmp2++) >> 1); 444 *rSubbandTmp++ = accu; 445 } 446 447 dct_III(rSubband, timeIn, L, &scale); 448} 449 450#if !defined(FUNCTION_qmfForwardModulationLP_odd) 451static void 452qmfForwardModulationLP_odd( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ 453 const FIXP_QMF *timeIn, /*!< Time Signal */ 454 FIXP_QMF *rSubband ) /*!< Real Output */ 455{ 456 int i; 457 int L = anaQmf->no_channels; 458 int M = L>>1; 459 int shift = (anaQmf->no_channels>>6) + 1; 460 461 for (i = 0; i < M; i++) { 462 rSubband[M + i] = (timeIn[L - 1 - i]>>1) - (timeIn[i]>>shift); 463 rSubband[M - 1 - i] = (timeIn[L + i]>>1) + (timeIn[2 * L - 1 - i]>>shift); 464 } 465 466 dct_IV(rSubband, L, &shift); 467} 468#endif /* !defined(FUNCTION_qmfForwardModulationLP_odd) */ 469 470 471 472/*! 473 * 474 * \brief Perform complex-valued forward modulation of the time domain 475 * data of timeIn and stores the real part of the subband 476 * samples in rSubband, and the imaginary part in iSubband 477 * 478 * Only the lower bands are obtained (upto anaQmf->lsb). For 479 * a full bandwidth analysis it is required to set both anaQmf->lsb 480 * and anaQmf->usb to the amount of QMF bands. 481 * 482 */ 483static void 484qmfForwardModulationHQ( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ 485 const FIXP_QMF *RESTRICT timeIn, /*!< Time Signal */ 486 FIXP_QMF *RESTRICT rSubband, /*!< Real Output */ 487 FIXP_QMF *RESTRICT iSubband /*!< Imaginary Output */ 488 ) 489{ 490 int i; 491 int L = anaQmf->no_channels; 492 int L2 = L<<1; 493 int shift = 0; 494 495 for (i = 0; i < L; i+=2) { 496 FIXP_QMF x0, x1, y0, y1; 497 498 x0 = timeIn[i] >> 1; 499 x1 = timeIn[i+1] >> 1; 500 y0 = timeIn[L2 - 1 - i] >> 1; 501 y1 = timeIn[L2 - 2 - i] >> 1; 502 503 rSubband[i] = x0 - y0; 504 rSubband[i+1] = x1 - y1; 505 iSubband[i] = x0 + y0; 506 iSubband[i+1] = x1 + y1; 507 } 508 509 dct_IV(rSubband, L, &shift); 510 dst_IV(iSubband, L, &shift); 511 512 { 513 { 514 const FIXP_QTW *RESTRICT sbr_t_cos; 515 const FIXP_QTW *RESTRICT sbr_t_sin; 516 sbr_t_cos = anaQmf->t_cos; 517 sbr_t_sin = anaQmf->t_sin; 518 519 for (i = 0; i < anaQmf->lsb; i++) { 520 cplxMult(&iSubband[i], &rSubband[i], iSubband[i], rSubband[i], sbr_t_cos[i], sbr_t_sin[i]); 521 } 522 } 523 } 524} 525 526/* 527 * \brief Perform one QMF slot analysis of the time domain data of timeIn 528 * with specified stride and stores the real part of the subband 529 * samples in rSubband, and the imaginary part in iSubband 530 * 531 * Only the lower bands are obtained (upto anaQmf->lsb). For 532 * a full bandwidth analysis it is required to set both anaQmf->lsb 533 * and anaQmf->usb to the amount of QMF bands. 534 */ 535void 536qmfAnalysisFilteringSlot( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ 537 FIXP_QMF *qmfReal, /*!< Low and High band, real */ 538 FIXP_QMF *qmfImag, /*!< Low and High band, imag */ 539 const INT_PCM *RESTRICT timeIn, /*!< Pointer to input */ 540 const int stride, /*!< stride factor of input */ 541 FIXP_QMF *pWorkBuffer /*!< pointer to temporal working buffer */ 542 ) 543{ 544 int i; 545 int offset = anaQmf->no_channels*(QMF_NO_POLY*2-1); 546 /* 547 Feed time signal into oldest anaQmf->no_channels states 548 */ 549 { 550 FIXP_QAS *RESTRICT FilterStatesAnaTmp = ((FIXP_QAS*)anaQmf->FilterStates)+offset; 551 552 /* Feed and scale actual time in slot */ 553 for(i=anaQmf->no_channels>>1; i!=0; i--) { 554 /* Place INT_PCM value left aligned in scaledTimeIn */ 555#if (QAS_BITS==SAMPLE_BITS) 556 *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; timeIn += stride; 557 *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; timeIn += stride; 558#elif (QAS_BITS>SAMPLE_BITS) 559 *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn)<<(QAS_BITS-SAMPLE_BITS)); timeIn += stride; 560 *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn)<<(QAS_BITS-SAMPLE_BITS)); timeIn += stride; 561#else 562 *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn)>>(SAMPLE_BITS-QAS_BITS)); timeIn += stride; 563 *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn)>>(SAMPLE_BITS-QAS_BITS)); timeIn += stride; 564#endif 565 } 566 } 567 568 if (anaQmf->flags & QMF_FLAG_NONSYMMETRIC) { 569 qmfAnaPrototypeFirSlot_NonSymmetric( 570 pWorkBuffer, 571 anaQmf->no_channels, 572 anaQmf->p_filter, 573 anaQmf->p_stride, 574 (FIXP_QAS*)anaQmf->FilterStates 575 ); 576 } else { 577 qmfAnaPrototypeFirSlot( pWorkBuffer, 578 anaQmf->no_channels, 579 anaQmf->p_filter, 580 anaQmf->p_stride, 581 (FIXP_QAS*)anaQmf->FilterStates 582 ); 583 } 584 585 if (anaQmf->flags & QMF_FLAG_LP) { 586 if (anaQmf->flags & QMF_FLAG_CLDFB) 587 qmfForwardModulationLP_odd( anaQmf, 588 pWorkBuffer, 589 qmfReal ); 590 else 591 qmfForwardModulationLP_even( anaQmf, 592 pWorkBuffer, 593 qmfReal ); 594 595 } else { 596 qmfForwardModulationHQ( anaQmf, 597 pWorkBuffer, 598 qmfReal, 599 qmfImag 600 ); 601 } 602 /* 603 Shift filter states 604 605 Should be realized with modulo adressing on a DSP instead of a true buffer shift 606 */ 607 FDKmemmove ((FIXP_QAS*)anaQmf->FilterStates, (FIXP_QAS*)anaQmf->FilterStates+anaQmf->no_channels, offset*sizeof(FIXP_QAS)); 608} 609 610 611/*! 612 * 613 * \brief Perform complex-valued subband filtering of the time domain 614 * data of timeIn and stores the real part of the subband 615 * samples in rAnalysis, and the imaginary part in iAnalysis 616 * The qmf coefficient table is symmetric. The symmetry is expoited by 617 * shrinking the coefficient table to half the size. The addressing mode 618 * takes care of the symmetries. 619 * 620 * Only the lower bands are obtained (upto anaQmf->lsb). For 621 * a full bandwidth analysis it is required to set both anaQmf->lsb 622 * and anaQmf->usb to the amount of QMF bands. 623 * 624 * \sa PolyphaseFiltering 625 */ 626 627void 628qmfAnalysisFiltering( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ 629 FIXP_QMF **qmfReal, /*!< Pointer to real subband slots */ 630 FIXP_QMF **qmfImag, /*!< Pointer to imag subband slots */ 631 QMF_SCALE_FACTOR *scaleFactor, 632 const INT_PCM *timeIn, /*!< Time signal */ 633 const int stride, 634 FIXP_QMF *pWorkBuffer /*!< pointer to temporal working buffer */ 635 ) 636{ 637 int i; 638 int no_channels = anaQmf->no_channels; 639 640 scaleFactor->lb_scale = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK; 641 scaleFactor->lb_scale -= anaQmf->filterScale; 642 643 for (i = 0; i < anaQmf->no_col; i++) 644 { 645 FIXP_QMF *qmfImagSlot = NULL; 646 647 if (!(anaQmf->flags & QMF_FLAG_LP)) { 648 qmfImagSlot = qmfImag[i]; 649 } 650 651 qmfAnalysisFilteringSlot( anaQmf, qmfReal[i], qmfImagSlot, timeIn , stride, pWorkBuffer ); 652 653 timeIn += no_channels*stride; 654 655 } /* no_col loop i */ 656} 657 658/*! 659 * 660 * \brief Perform low power inverse modulation of the subband 661 * samples stored in rSubband (real part) and iSubband (imaginary 662 * part) and stores the result in pWorkBuffer. 663 * 664 */ 665inline 666static void 667qmfInverseModulationLP_even( HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ 668 const FIXP_QMF *qmfReal, /*!< Pointer to qmf real subband slot (input) */ 669 const int scaleFactorLowBand, /*!< Scalefactor for Low band */ 670 const int scaleFactorHighBand, /*!< Scalefactor for High band */ 671 FIXP_QMF *pTimeOut /*!< Pointer to qmf subband slot (output)*/ 672 ) 673{ 674 int i; 675 int L = synQmf->no_channels; 676 int M = L>>1; 677 int scale; 678 FIXP_QMF tmp; 679 FIXP_QMF *RESTRICT tReal = pTimeOut; 680 FIXP_QMF *RESTRICT tImag = pTimeOut + L; 681 682 /* Move input to output vector with offset */ 683 scaleValues(&tReal[0], &qmfReal[0], synQmf->lsb, scaleFactorLowBand); 684 scaleValues(&tReal[0+synQmf->lsb], &qmfReal[0+synQmf->lsb], synQmf->usb-synQmf->lsb, scaleFactorHighBand); 685 FDKmemclear(&tReal[0+synQmf->usb], (L-synQmf->usb)*sizeof(FIXP_QMF)); 686 687 /* Dct type-2 transform */ 688 dct_II(tReal, tImag, L, &scale); 689 690 /* Expand output and replace inplace the output buffers */ 691 tImag[0] = tReal[M]; 692 tImag[M] = (FIXP_QMF)0; 693 tmp = tReal [0]; 694 tReal [0] = tReal[M]; 695 tReal [M] = tmp; 696 697 for (i = 1; i < M/2; i++) { 698 /* Imag */ 699 tmp = tReal[L - i]; 700 tImag[M - i] = tmp; 701 tImag[i + M] = -tmp; 702 703 tmp = tReal[M + i]; 704 tImag[i] = tmp; 705 tImag[L - i] = -tmp; 706 707 /* Real */ 708 tReal [M + i] = tReal[i]; 709 tReal [L - i] = tReal[M - i]; 710 tmp = tReal[i]; 711 tReal[i] = tReal [M - i]; 712 tReal [M - i] = tmp; 713 714 } 715 /* Remaining odd terms */ 716 tmp = tReal[M + M/2]; 717 tImag[M/2] = tmp; 718 tImag[M/2 + M] = -tmp; 719 720 tReal [M + M/2] = tReal[M/2]; 721} 722 723inline 724static void 725qmfInverseModulationLP_odd( HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ 726 const FIXP_QMF *qmfReal, /*!< Pointer to qmf real subband slot (input) */ 727 const int scaleFactorLowBand, /*!< Scalefactor for Low band */ 728 const int scaleFactorHighBand, /*!< Scalefactor for High band */ 729 FIXP_QMF *pTimeOut /*!< Pointer to qmf subband slot (output)*/ 730 ) 731{ 732 int i; 733 int L = synQmf->no_channels; 734 int M = L>>1; 735 int shift = 0; 736 737 /* Move input to output vector with offset */ 738 scaleValues(pTimeOut+M, qmfReal, synQmf->lsb, scaleFactorLowBand); 739 scaleValues(pTimeOut+M+synQmf->lsb, qmfReal+synQmf->lsb, synQmf->usb-synQmf->lsb, scaleFactorHighBand); 740 FDKmemclear(pTimeOut+M+synQmf->usb, (L-synQmf->usb)*sizeof(FIXP_QMF)); 741 742 dct_IV(pTimeOut+M, L, &shift); 743 for (i = 0; i < M; i++) { 744 pTimeOut[i] = pTimeOut[L - 1 - i]; 745 pTimeOut[2 * L - 1 - i] = -pTimeOut[L + i]; 746 } 747} 748 749 750/*! 751 * 752 * \brief Perform complex-valued inverse modulation of the subband 753 * samples stored in rSubband (real part) and iSubband (imaginary 754 * part) and stores the result in pWorkBuffer. 755 * 756 */ 757inline 758static void 759qmfInverseModulationHQ( HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ 760 const FIXP_QMF *qmfReal, /*!< Pointer to qmf real subband slot */ 761 const FIXP_QMF *qmfImag, /*!< Pointer to qmf imag subband slot */ 762 const int scaleFactorLowBand, /*!< Scalefactor for Low band */ 763 const int scaleFactorHighBand,/*!< Scalefactor for High band */ 764 FIXP_QMF *pWorkBuffer /*!< WorkBuffer (output) */ 765 ) 766{ 767 int i; 768 int L = synQmf->no_channels; 769 int M = L>>1; 770 int shift = 0; 771 FIXP_QMF *RESTRICT tReal = pWorkBuffer; 772 FIXP_QMF *RESTRICT tImag = pWorkBuffer+L; 773 774 if (synQmf->flags & QMF_FLAG_CLDFB){ 775 for (i = 0; i < synQmf->lsb; i++) { 776 cplxMult(&tImag[i], &tReal[i], 777 scaleValue(qmfImag[i],scaleFactorLowBand), scaleValue(qmfReal[i],scaleFactorLowBand), 778 synQmf->t_cos[i], synQmf->t_sin[i]); 779 } 780 for (; i < synQmf->usb; i++) { 781 cplxMult(&tImag[i], &tReal[i], 782 scaleValue(qmfImag[i],scaleFactorHighBand), scaleValue(qmfReal[i],scaleFactorHighBand), 783 synQmf->t_cos[i], synQmf->t_sin[i]); 784 } 785 } 786 787 if ( (synQmf->flags & QMF_FLAG_CLDFB) == 0) { 788 scaleValues(&tReal[0], &qmfReal[0], synQmf->lsb, scaleFactorLowBand); 789 scaleValues(&tReal[0+synQmf->lsb], &qmfReal[0+synQmf->lsb], synQmf->usb-synQmf->lsb, scaleFactorHighBand); 790 scaleValues(&tImag[0], &qmfImag[0], synQmf->lsb, scaleFactorLowBand); 791 scaleValues(&tImag[0+synQmf->lsb], &qmfImag[0+synQmf->lsb], synQmf->usb-synQmf->lsb, scaleFactorHighBand); 792 } 793 794 FDKmemclear(&tReal[synQmf->usb], (synQmf->no_channels-synQmf->usb)*sizeof(FIXP_QMF)); 795 FDKmemclear(&tImag[synQmf->usb], (synQmf->no_channels-synQmf->usb)*sizeof(FIXP_QMF)); 796 797 dct_IV(tReal, L, &shift); 798 dst_IV(tImag, L, &shift); 799 800 if (synQmf->flags & QMF_FLAG_CLDFB){ 801 for (i = 0; i < M; i++) { 802 FIXP_QMF r1, i1, r2, i2; 803 r1 = tReal[i]; 804 i2 = tImag[L - 1 - i]; 805 r2 = tReal[L - i - 1]; 806 i1 = tImag[i]; 807 808 tReal[i] = (r1 - i1)>>1; 809 tImag[L - 1 - i] = -(r1 + i1)>>1; 810 tReal[L - i - 1] = (r2 - i2)>>1; 811 tImag[i] = -(r2 + i2)>>1; 812 } 813 } else 814 { 815 /* The array accesses are negative to compensate the missing minus sign in the low and hi band gain. */ 816 /* 26 cycles on ARM926 */ 817 for (i = 0; i < M; i++) { 818 FIXP_QMF r1, i1, r2, i2; 819 r1 = -tReal[i]; 820 i2 = -tImag[L - 1 - i]; 821 r2 = -tReal[L - i - 1]; 822 i1 = -tImag[i]; 823 824 tReal[i] = (r1 - i1)>>1; 825 tImag[L - 1 - i] = -(r1 + i1)>>1; 826 tReal[L - i - 1] = (r2 - i2)>>1; 827 tImag[i] = -(r2 + i2)>>1; 828 } 829 } 830} 831 832void qmfSynthesisFilteringSlot( HANDLE_QMF_FILTER_BANK synQmf, 833 const FIXP_QMF *realSlot, 834 const FIXP_QMF *imagSlot, 835 const int scaleFactorLowBand, 836 const int scaleFactorHighBand, 837 INT_PCM *timeOut, 838 const int stride, 839 FIXP_QMF *pWorkBuffer) 840{ 841 if (!(synQmf->flags & QMF_FLAG_LP)) 842 qmfInverseModulationHQ ( synQmf, 843 realSlot, 844 imagSlot, 845 scaleFactorLowBand, 846 scaleFactorHighBand, 847 pWorkBuffer 848 ); 849 else 850 { 851 if (synQmf->flags & QMF_FLAG_CLDFB) { 852 qmfInverseModulationLP_odd ( synQmf, 853 realSlot, 854 scaleFactorLowBand, 855 scaleFactorHighBand, 856 pWorkBuffer 857 ); 858 } else { 859 qmfInverseModulationLP_even ( synQmf, 860 realSlot, 861 scaleFactorLowBand, 862 scaleFactorHighBand, 863 pWorkBuffer 864 ); 865 } 866 } 867 868 if (synQmf->flags & QMF_FLAG_NONSYMMETRIC) { 869 qmfSynPrototypeFirSlot_NonSymmetric ( 870 synQmf, 871 pWorkBuffer, 872 pWorkBuffer+synQmf->no_channels, 873 timeOut, 874 stride 875 ); 876 } else { 877 qmfSynPrototypeFirSlot ( synQmf, 878 pWorkBuffer, 879 pWorkBuffer+synQmf->no_channels, 880 timeOut, 881 stride 882 ); 883 } 884} 885 886 887/*! 888 * 889 * 890 * \brief Perform complex-valued subband synthesis of the 891 * low band and the high band and store the 892 * time domain data in timeOut 893 * 894 * First step: Calculate the proper scaling factor of current 895 * spectral data in qmfReal/qmfImag, old spectral data in the overlap 896 * range and filter states. 897 * 898 * Second step: Perform Frequency-to-Time mapping with inverse 899 * Modulation slot-wise. 900 * 901 * Third step: Perform FIR-filter slot-wise. To save space for filter 902 * states, the MAC operations are executed directly on the filter states 903 * instead of accumulating several products in the accumulator. The 904 * buffer shift at the end of the function should be replaced by a 905 * modulo operation, which is available on some DSPs. 906 * 907 * Last step: Copy the upper part of the spectral data to the overlap buffer. 908 * 909 * The qmf coefficient table is symmetric. The symmetry is exploited by 910 * shrinking the coefficient table to half the size. The addressing mode 911 * takes care of the symmetries. If the #define #QMFTABLE_FULL is set, 912 * coefficient addressing works on the full table size. The code will be 913 * slightly faster and slightly more compact. 914 * 915 * Workbuffer requirement: 2 x sizeof(**QmfBufferReal) * synQmf->no_channels 916 */ 917void 918qmfSynthesisFiltering( HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ 919 FIXP_QMF **QmfBufferReal, /*!< Low and High band, real */ 920 FIXP_QMF **QmfBufferImag, /*!< Low and High band, imag */ 921 const QMF_SCALE_FACTOR *scaleFactor, 922 const INT ov_len, /*!< split Slot of overlap and actual slots */ 923 INT_PCM *timeOut, /*!< Pointer to output */ 924 const INT stride, /*!< stride factor of output */ 925 FIXP_QMF *pWorkBuffer /*!< pointer to temporal working buffer */ 926 ) 927{ 928 int i; 929 int L = synQmf->no_channels; 930 SCHAR scaleFactorHighBand; 931 SCHAR scaleFactorLowBand_ov, scaleFactorLowBand_no_ov; 932 933 /* adapt scaling */ 934 scaleFactorHighBand = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - scaleFactor->hb_scale; 935 scaleFactorLowBand_ov = - ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - scaleFactor->ov_lb_scale; 936 scaleFactorLowBand_no_ov = - ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - scaleFactor->lb_scale; 937 938 for (i = 0; i < synQmf->no_col; i++) /* ----- no_col loop ----- */ 939 { 940 const FIXP_DBL *QmfBufferImagSlot = NULL; 941 942 SCHAR scaleFactorLowBand = (i<ov_len) ? scaleFactorLowBand_ov : scaleFactorLowBand_no_ov; 943 944 if (!(synQmf->flags & QMF_FLAG_LP)) 945 QmfBufferImagSlot = QmfBufferImag[i]; 946 947 qmfSynthesisFilteringSlot( synQmf, 948 QmfBufferReal[i], 949 QmfBufferImagSlot, 950 scaleFactorLowBand, 951 scaleFactorHighBand, 952 timeOut+(i*L*stride), 953 stride, 954 pWorkBuffer); 955 } /* no_col loop i */ 956 957} 958 959 960/*! 961 * 962 * \brief Create QMF filter bank instance 963 * 964 * \return 0 if successful 965 * 966 */ 967static int 968qmfInitFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Handle to return */ 969 void *pFilterStates, /*!< Handle to filter states */ 970 int noCols, /*!< Number of timeslots per frame */ 971 int lsb, /*!< Lower end of QMF frequency range */ 972 int usb, /*!< Upper end of QMF frequency range */ 973 int no_channels, /*!< Number of channels (bands) */ 974 UINT flags) /*!< flags */ 975{ 976 FDKmemclear(h_Qmf,sizeof(QMF_FILTER_BANK)); 977 978 if (flags & QMF_FLAG_MPSLDFB) 979 { 980 return -1; 981 } 982 983 if ( !(flags & QMF_FLAG_MPSLDFB) && (flags & QMF_FLAG_CLDFB) ) 984 { 985 flags |= QMF_FLAG_NONSYMMETRIC; 986 h_Qmf->filterScale = QMF_CLDFB_PFT_SCALE; 987 988 h_Qmf->p_stride = 1; 989 switch (no_channels) { 990 case 64: 991 h_Qmf->t_cos = qmf_phaseshift_cos64_cldfb; 992 h_Qmf->t_sin = qmf_phaseshift_sin64_cldfb; 993 h_Qmf->p_filter = qmf_cldfb_640; 994 h_Qmf->FilterSize = 640; 995 break; 996 case 32: 997 h_Qmf->t_cos = qmf_phaseshift_cos32_cldfb; 998 h_Qmf->t_sin = qmf_phaseshift_sin32_cldfb; 999 h_Qmf->p_filter = qmf_cldfb_320; 1000 h_Qmf->FilterSize = 320; 1001 break; 1002 default: 1003 return -1; 1004 } 1005 } 1006 1007 if ( !(flags & QMF_FLAG_MPSLDFB) && ((flags & QMF_FLAG_CLDFB) == 0) ) 1008 { 1009 switch (no_channels) { 1010 case 64: 1011 h_Qmf->p_filter = qmf_64; 1012 h_Qmf->t_cos = qmf_phaseshift_cos64; 1013 h_Qmf->t_sin = qmf_phaseshift_sin64; 1014 h_Qmf->p_stride = 1; 1015 h_Qmf->FilterSize = 640; 1016 h_Qmf->filterScale = 0; 1017 break; 1018 case 32: 1019 h_Qmf->p_filter = qmf_64; 1020 if (flags & QMF_FLAG_DOWNSAMPLED) { 1021 h_Qmf->t_cos = qmf_phaseshift_cos_downsamp32; 1022 h_Qmf->t_sin = qmf_phaseshift_sin_downsamp32; 1023 } 1024 else { 1025 h_Qmf->t_cos = qmf_phaseshift_cos32; 1026 h_Qmf->t_sin = qmf_phaseshift_sin32; 1027 } 1028 h_Qmf->p_stride = 2; 1029 h_Qmf->FilterSize = 640; 1030 h_Qmf->filterScale = 0; 1031 break; 1032 default: 1033 return -1; 1034 } 1035 } 1036 1037 h_Qmf->flags = flags; 1038 1039 h_Qmf->no_channels = no_channels; 1040 h_Qmf->no_col = noCols; 1041 1042 h_Qmf->lsb = lsb; 1043 h_Qmf->usb = fMin(usb, h_Qmf->no_channels); 1044 1045 h_Qmf->FilterStates = (void*)pFilterStates; 1046 1047 h_Qmf->outScalefactor = ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + h_Qmf->filterScale; 1048 1049 if ( (h_Qmf->p_stride == 2) 1050 || ((flags & QMF_FLAG_CLDFB) && (no_channels == 32)) ) { 1051 h_Qmf->outScalefactor -= 1; 1052 } 1053 h_Qmf->outGain = (FIXP_DBL)0x80000000; /* default init value will be not applied */ 1054 1055 return (0); 1056} 1057 1058/*! 1059 * 1060 * \brief Adjust synthesis qmf filter states 1061 * 1062 * \return void 1063 * 1064 */ 1065static inline void 1066qmfAdaptFilterStates (HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Filter Bank */ 1067 int scaleFactorDiff) /*!< Scale factor difference to be applied */ 1068{ 1069 if (synQmf == NULL || synQmf->FilterStates == NULL) { 1070 return; 1071 } 1072 scaleValues((FIXP_QSS*)synQmf->FilterStates, synQmf->no_channels*(QMF_NO_POLY*2 - 1), scaleFactorDiff); 1073} 1074 1075/*! 1076 * 1077 * \brief Create QMF filter bank instance 1078 * 1079 * Only the lower bands are obtained (upto anaQmf->lsb). For 1080 * a full bandwidth analysis it is required to set both anaQmf->lsb 1081 * and anaQmf->usb to the amount of QMF bands. 1082 * 1083 * \return 0 if succesful 1084 * 1085 */ 1086int 1087qmfInitAnalysisFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */ 1088 FIXP_QAS *pFilterStates, /*!< Handle to filter states */ 1089 int noCols, /*!< Number of timeslots per frame */ 1090 int lsb, /*!< lower end of QMF */ 1091 int usb, /*!< upper end of QMF */ 1092 int no_channels, /*!< Number of channels (bands) */ 1093 int flags) /*!< Low Power flag */ 1094{ 1095 int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, no_channels, flags); 1096 if ( !(flags & QMF_FLAG_KEEP_STATES) && (h_Qmf->FilterStates != NULL) ) { 1097 FDKmemclear(h_Qmf->FilterStates, (2*QMF_NO_POLY-1)*h_Qmf->no_channels*sizeof(FIXP_QAS)); 1098 } 1099 1100 return err; 1101} 1102 1103/*! 1104 * 1105 * \brief Create QMF filter bank instance 1106 * 1107 * Only the lower bands are obtained (upto anaQmf->lsb). For 1108 * a full bandwidth analysis it is required to set both anaQmf->lsb 1109 * and anaQmf->usb to the amount of QMF bands. 1110 * 1111 * \return 0 if succesful 1112 * 1113 */ 1114int 1115qmfInitSynthesisFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */ 1116 FIXP_QSS *pFilterStates, /*!< Handle to filter states */ 1117 int noCols, /*!< Number of timeslots per frame */ 1118 int lsb, /*!< lower end of QMF */ 1119 int usb, /*!< upper end of QMF */ 1120 int no_channels, /*!< Number of channels (bands) */ 1121 int flags) /*!< Low Power flag */ 1122{ 1123 int oldOutScale = h_Qmf->outScalefactor; 1124 int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, no_channels, flags); 1125 if ( h_Qmf->FilterStates != NULL ) { 1126 if ( !(flags & QMF_FLAG_KEEP_STATES) ) { 1127 FDKmemclear(h_Qmf->FilterStates, (2*QMF_NO_POLY-1)*h_Qmf->no_channels*sizeof(FIXP_QSS)); 1128 } else { 1129 qmfAdaptFilterStates(h_Qmf, oldOutScale-h_Qmf->outScalefactor); 1130 } 1131 } 1132 return err; 1133} 1134 1135 1136 1137 1138/*! 1139 * 1140 * \brief Change scale factor for output data and adjust qmf filter states 1141 * 1142 * \return void 1143 * 1144 */ 1145void 1146qmfChangeOutScalefactor (HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ 1147 int outScalefactor /*!< New scaling factor for output data */ 1148 ) 1149{ 1150 if (synQmf == NULL || synQmf->FilterStates == NULL) { 1151 return; 1152 } 1153 1154 /* Add internal filterbank scale */ 1155 outScalefactor += ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + synQmf->filterScale; 1156 1157 if ( (synQmf->p_stride == 2) 1158 || ((synQmf->flags & QMF_FLAG_CLDFB) && (synQmf->no_channels == 32)) ) { 1159 outScalefactor -= 1; 1160 } 1161 1162 /* adjust filter states when scale factor has been changed */ 1163 if (synQmf->outScalefactor != outScalefactor) 1164 { 1165 int diff; 1166 1167 if (outScalefactor > (SAMPLE_BITS - 1)) { 1168 outScalefactor = SAMPLE_BITS - 1; 1169 } else if (outScalefactor < (1 - SAMPLE_BITS)) { 1170 outScalefactor = 1 - SAMPLE_BITS; 1171 } 1172 1173 diff = synQmf->outScalefactor - outScalefactor; 1174 1175 qmfAdaptFilterStates(synQmf, diff); 1176 1177 /* save new scale factor */ 1178 synQmf->outScalefactor = outScalefactor; 1179 } 1180} 1181 1182/*! 1183 * 1184 * \brief Change gain for output data 1185 * 1186 * \return void 1187 * 1188 */ 1189void 1190qmfChangeOutGain (HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ 1191 FIXP_DBL outputGain /*!< New gain for output data */ 1192 ) 1193{ 1194 synQmf->outGain = outputGain; 1195} 1196 1197