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/*! 85 \file 86 \brief FDK resampler tool box: 87 \author M. Werner 88*/ 89 90#include "resampler.h" 91 92#include "genericStds.h" 93 94 95/**************************************************************************/ 96/* BIQUAD Filter Specifications */ 97/**************************************************************************/ 98 99#define B1 0 100#define B2 1 101#define A1 2 102#define A2 3 103 104#define BQC(x) FL2FXCONST_SGL(x/2) 105 106 107struct FILTER_PARAM { 108 const FIXP_SGL *coeffa; /*! SOS matrix One row/section. Scaled using BQC(). Order of coefficients: B1,B2,A1,A2. B0=A0=1.0 */ 109 FIXP_DBL g; /*! overall gain */ 110 int Wc; /*! normalized passband bandwidth at input samplerate * 1000 */ 111 int noCoeffs; /*! number of filter coeffs */ 112 int delay; /*! delay in samples at input samplerate */ 113}; 114 115#define BIQUAD_COEFSTEP 4 116 117/** 118 *\brief Low Pass 119 Wc = 0,5, order 30, Stop Band -96dB. Wc criteria is "almost 0dB passband", not the usual -3db gain point. 120 [b,a]=cheby2(30,96,0.505) 121 [sos,g]=tf2sos(b,a) 122 bandwidth 0.48 123 */ 124static const FIXP_SGL sos48[] = { 125 BQC(1.98941075681938), BQC(0.999999996890811), BQC(0.863264527201963), BQC( 0.189553799960663), 126 BQC(1.90733804822445), BQC(1.00000001736189), BQC(0.836321575841691), BQC( 0.203505809266564), 127 BQC(1.75616665495325), BQC(0.999999946079721), BQC(0.784699225121588), BQC( 0.230471265506986), 128 BQC(1.55727745512726), BQC(1.00000011737815), BQC(0.712515423588351), BQC( 0.268752723900498), 129 BQC(1.33407591943643), BQC(0.999999795953228), BQC(0.625059117330989), BQC( 0.316194685288965), 130 BQC(1.10689898412458), BQC(1.00000035057114), BQC(0.52803514366398), BQC( 0.370517843224669), 131 BQC(0.89060371078454), BQC(0.999999343962822), BQC(0.426920462165257), BQC( 0.429608200207746), 132 BQC(0.694438261209433), BQC( 1.0000008629792), BQC(0.326530699561716), BQC( 0.491714450654174), 133 BQC(0.523237800935322), BQC(1.00000101349782), BQC(0.230829556274851), BQC( 0.555559034843281), 134 BQC(0.378631165929563), BQC(0.99998986482665), BQC(0.142906422036095), BQC( 0.620338874442411), 135 BQC(0.260786911308437), BQC(1.00003261460178), BQC(0.0651008576256505), BQC( 0.685759923926262), 136 BQC(0.168409429188098), BQC(0.999933049695828), BQC(-0.000790067789975562), BQC( 0.751905896602325), 137 BQC(0.100724533818628), BQC(1.00009472669872), BQC(-0.0533772830257041), BQC( 0.81930744384525), 138 BQC(0.0561434357867363), BQC(0.999911636304276), BQC(-0.0913550299236405), BQC( 0.88883625875915), 139 BQC(0.0341680678662057), BQC(1.00003667508676), BQC(-0.113405185536697), BQC( 0.961756638268446) 140}; 141 142#ifdef RS_BIQUAD_SCATTERGAIN 143static const FIXP_DBL g48 = FL2FXCONST_DBL(0.67436532061161992682404480717671 - 0.001); 144#else 145static const FIXP_DBL g48 = FL2FXCONST_DBL(0.002712866530047) - (FIXP_DBL)0x8000; 146#endif 147 148static const struct FILTER_PARAM param_set48 = { 149 sos48, 150 g48, 151 480, 152 15, 153 4 /* LF 2 */ 154}; 155 156/** 157 *\brief Low Pass 158 Wc = 0,5, order 24, Stop Band -96dB. Wc criteria is "almost 0dB passband", not the usual -3db gain point. 159 [b,a]=cheby2(24,96,0.5) 160 [sos,g]=tf2sos(b,a) 161 bandwidth 0.45 162 */ 163static const FIXP_SGL sos45[] = { 164 BQC(1.982962601444), BQC(1.00000000007504), BQC(0.646113303737836), BQC( 0.10851149979981), 165 BQC(1.85334094281111), BQC(0.999999999677192), BQC(0.612073220102006), BQC( 0.130022141698044), 166 BQC(1.62541051415425), BQC(1.00000000080398), BQC(0.547879702855959), BQC( 0.171165825133192), 167 BQC(1.34554656923247), BQC(0.9999999980169), BQC(0.460373914508491), BQC( 0.228677463376354), 168 BQC(1.05656568503116), BQC(1.00000000569363), BQC(0.357891894038287), BQC( 0.298676843912185), 169 BQC(0.787967587877312), BQC(0.999999984415017), BQC(0.248826893211877), BQC( 0.377441803512978), 170 BQC(0.555480971120497), BQC(1.00000003583307), BQC(0.140614263345315), BQC( 0.461979302213679), 171 BQC(0.364986207070964), BQC(0.999999932084303), BQC(0.0392669446074516), BQC( 0.55033451180825), 172 BQC(0.216827267631558), BQC(1.00000010534682), BQC(-0.0506232228865103), BQC( 0.641691581560946), 173 BQC(0.108951672277119), BQC(0.999999871167516), BQC(-0.125584840183225), BQC( 0.736367748771803), 174 BQC(0.0387988607229035), BQC(1.00000011205574), BQC(-0.182814849097974), BQC( 0.835802108714964), 175 BQC(0.0042866175809225), BQC(0.999999954830813), BQC(-0.21965740617151), BQC( 0.942623047782363) 176}; 177 178#ifdef RS_BIQUAD_SCATTERGAIN 179static const FIXP_DBL g45 = FL2FXCONST_DBL(0.60547428891341319051142629706723 - 0.001); 180#else 181static const FIXP_DBL g45 = FL2FXCONST_DBL(0.00242743980909524) - (FIXP_DBL)0x8000; 182#endif 183 184static const struct FILTER_PARAM param_set45 = { 185 sos45, 186 g45, 187 450, 188 12, 189 4 /* LF 2 */ 190}; 191 192/* 193 Created by Octave 2.1.73, Mon Oct 13 17:31:32 2008 CEST 194 Wc = 0,5, order 16, Stop Band -96dB damping. 195 [b,a]=cheby2(16,96,0.5) 196 [sos,g]=tf2sos(b,a) 197 bandwidth = 0.41 198 */ 199 200static const FIXP_SGL sos41[] = 201{ 202 BQC(1.96193625292), BQC(0.999999999999964), BQC(0.169266178786789), BQC(0.0128823300475907), 203 BQC(1.68913437662092), BQC(1.00000000000053), BQC(0.124751503206552), BQC(0.0537472273950989), 204 BQC(1.27274692366017), BQC(0.999999999995674), BQC(0.0433108625178357), BQC(0.131015753236317), 205 BQC(0.85214175088395), BQC(1.00000000001813), BQC(-0.0625658152550408), BQC(0.237763778993806), 206 BQC(0.503841579939009), BQC(0.999999999953223), BQC(-0.179176128722865), BQC(0.367475236424474), 207 BQC(0.249990711986162), BQC(1.00000000007952), BQC(-0.294425165824676), BQC(0.516594857170212), 208 BQC(0.087971668680286), BQC(0.999999999915528), BQC(-0.398956566777928), BQC(0.686417767801123), 209 BQC(0.00965373325350294), BQC(1.00000000003744), BQC(-0.48579173764817), BQC(0.884931534239068) 210}; 211 212#ifdef RS_BIQUAD_SCATTERGAIN 213static const FIXP_DBL g41 = FL2FXCONST_DBL(0.44578514476476679750811222123569); 214#else 215static const FIXP_DBL g41 = FL2FXCONST_DBL(0.00155956951169248); 216#endif 217 218static const struct FILTER_PARAM param_set41 = { 219 sos41, 220 g41, 221 410, 222 8, 223 5 /* LF 3 */ 224}; 225 226/* 227 # Created by Octave 2.1.73, Mon Oct 13 17:55:33 2008 CEST 228 Wc = 0,5, order 12, Stop Band -96dB damping. 229 [b,a]=cheby2(12,96,0.5); 230 [sos,g]=tf2sos(b,a) 231*/ 232static const FIXP_SGL sos35[] = 233{ 234 BQC(1.93299325235762), BQC(0.999999999999985), BQC(-0.140733187246596), BQC(0.0124139497836062), 235 BQC(1.4890416764109), BQC(1.00000000000011), BQC(-0.198215402588504), BQC(0.0746730616584138), 236 BQC(0.918450161309795), BQC(0.999999999999619), BQC(-0.30133912791941), BQC(0.192276468839529), 237 BQC(0.454877024246818), BQC(1.00000000000086), BQC(-0.432337328809815), BQC(0.356852933642815), 238 BQC(0.158017147118507), BQC(0.999999999998876), BQC(-0.574817494249777), BQC(0.566380436970833), 239 BQC(0.0171834649478749), BQC(1.00000000000055), BQC(-0.718581178041165), BQC(0.83367484487889) 240}; 241 242#ifdef RS_BIQUAD_SCATTERGAIN 243static const FIXP_DBL g35 = FL2FXCONST_DBL(0.34290853574973898694521267606792); 244#else 245static const FIXP_DBL g35 = FL2FXCONST_DBL(0.00162580994125131); 246#endif 247 248static const struct FILTER_PARAM param_set35 = { 249 sos35, 250 g35, 251 350, 252 6, 253 4 254}; 255 256/* 257 # Created by Octave 2.1.73, Mon Oct 13 18:15:38 2008 CEST 258 Wc = 0,5, order 8, Stop Band -96dB damping. 259 [b,a]=cheby2(8,96,0.5); 260 [sos,g]=tf2sos(b,a) 261*/ 262static const FIXP_SGL sos25[] = 263{ 264 BQC(1.85334094301225), BQC(1.0), BQC(-0.702127214212663), BQC(0.132452403998767), 265 BQC(1.056565682167), BQC(0.999999999999997), BQC(-0.789503667880785), BQC(0.236328693569128), 266 BQC(0.364986307455489), BQC(0.999999999999996), BQC(-0.955191189843375), BQC(0.442966457936379), 267 BQC(0.0387985751642125), BQC(1.0), BQC(-1.19817786088084), BQC(0.770493895456328) 268}; 269 270#ifdef RS_BIQUAD_SCATTERGAIN 271static const FIXP_DBL g25 = FL2FXCONST_DBL(0.17533917408936346960080259950471); 272#else 273static const FIXP_DBL g25 = FL2FXCONST_DBL(0.000945182835294559); 274#endif 275 276static const struct FILTER_PARAM param_set25 = { 277 sos25, 278 g25, 279 250, 280 4, 281 5 282}; 283 284/* Must be sorted in descending order */ 285static const struct FILTER_PARAM *const filter_paramSet[] = { 286 ¶m_set48, 287 ¶m_set45, 288 ¶m_set41, 289 ¶m_set35, 290 ¶m_set25 291}; 292 293 294/**************************************************************************/ 295/* Resampler Functions */ 296/**************************************************************************/ 297 298 299/*! 300 \brief Reset downsampler instance and clear delay lines 301 302 \return success of operation 303*/ 304 305INT FDKaacEnc_InitDownsampler(DOWNSAMPLER *DownSampler, /*!< pointer to downsampler instance */ 306 int Wc, /*!< normalized cutoff freq * 1000* */ 307 int ratio) /*!< downsampler ratio (only 2 supported at the momment) */ 308 309{ 310 UINT i; 311 const struct FILTER_PARAM *currentSet=NULL; 312 313 FDK_ASSERT(ratio == 2); 314 FDKmemclear(DownSampler->downFilter.states, sizeof(DownSampler->downFilter.states)); 315 DownSampler->downFilter.ptr = 0; 316 317 /* 318 find applicable parameter set 319 */ 320 currentSet = filter_paramSet[0]; 321 for(i=1;i<sizeof(filter_paramSet)/sizeof(struct FILTER_PARAM *);i++){ 322 if (filter_paramSet[i]->Wc <= Wc) { 323 break; 324 } 325 currentSet = filter_paramSet[i]; 326 } 327 328 DownSampler->downFilter.coeffa = currentSet->coeffa; 329 330 331 DownSampler->downFilter.gain = currentSet->g; 332 FDK_ASSERT(currentSet->noCoeffs <= MAXNR_SECTIONS*2); 333 334 DownSampler->downFilter.noCoeffs = currentSet->noCoeffs; 335 DownSampler->delay = currentSet->delay; 336 DownSampler->downFilter.Wc = currentSet->Wc; 337 338 DownSampler->ratio = ratio; 339 DownSampler->pending = ratio-1; 340 return(1); 341} 342 343 344/*! 345 \brief faster simple folding operation 346 Filter: 347 H(z) = A(z)/B(z) 348 with 349 A(z) = a[0]*z^0 + a[1]*z^1 + a[2]*z^2 ... a[n]*z^n 350 351 \return filtered value 352*/ 353 354static inline INT_PCM AdvanceFilter(LP_FILTER *downFilter, /*!< pointer to iir filter instance */ 355 INT_PCM *pInput, /*!< input of filter */ 356 int downRatio, 357 int inStride) 358{ 359 INT_PCM output; 360 int i, n; 361 362 363#ifdef RS_BIQUAD_SCATTERGAIN 364#define BIQUAD_SCALE 3 365#else 366#define BIQUAD_SCALE 12 367#endif 368 369 FIXP_DBL y = FL2FXCONST_DBL(0.0f); 370 FIXP_DBL input; 371 372 for (n=0; n<downRatio; n++) 373 { 374 FIXP_BQS (*states)[2] = downFilter->states; 375 const FIXP_SGL *coeff = downFilter->coeffa; 376 int s1,s2; 377 378 s1 = downFilter->ptr; 379 s2 = s1 ^ 1; 380 381#if (SAMPLE_BITS == 16) 382 input = ((FIXP_DBL)pInput[n*inStride]) << (DFRACT_BITS-SAMPLE_BITS-BIQUAD_SCALE); 383#elif (SAMPLE_BITS == 32) 384 input = pInput[n*inStride] >> BIQUAD_SCALE; 385#else 386#error NOT IMPLEMENTED 387#endif 388 389#ifndef RS_BIQUAD_SCATTERGAIN /* Merged Direct form I */ 390 391 FIXP_BQS state1, state2, state1b, state2b; 392 393 state1 = states[0][s1]; 394 state2 = states[0][s2]; 395 396 /* Loop over sections */ 397 for (i=0; i<downFilter->noCoeffs; i++) 398 { 399 FIXP_DBL state0; 400 401 /* Load merged states (from next section) */ 402 state1b = states[i+1][s1]; 403 state2b = states[i+1][s2]; 404 405 state0 = input + fMult(state1, coeff[B1]) + fMult(state2, coeff[B2]); 406 y = state0 - fMult(state1b, coeff[A1]) - fMult(state2b, coeff[A2]); 407 408 /* Store new feed forward merge state */ 409 states[i+1][s2] = y<<1; 410 /* Store new feed backward state */ 411 states[i][s2] = input<<1; 412 413 /* Feedback output to next section. */ 414 input = y; 415 416 /* Transfer merged states */ 417 state1 = state1b; 418 state2 = state2b; 419 420 /* Step to next coef set */ 421 coeff += BIQUAD_COEFSTEP; 422 } 423 downFilter->ptr ^= 1; 424 } 425 /* Apply global gain */ 426 y = fMult(y, downFilter->gain); 427 428#else /* Direct form II */ 429 430 /* Loop over sections */ 431 for (i=0; i<downFilter->noCoeffs; i++) 432 { 433 FIXP_BQS state1, state2; 434 FIXP_DBL state0; 435 436 /* Load states */ 437 state1 = states[i][s1]; 438 state2 = states[i][s2]; 439 440 state0 = input - fMult(state1, coeff[A1]) - fMult(state2, coeff[A2]); 441 y = state0 + fMult(state1, coeff[B1]) + fMult(state2, coeff[B2]); 442 /* Apply scattered gain */ 443 y = fMult(y, downFilter->gain); 444 445 /* Store new state in normalized form */ 446#ifdef RS_BIQUAD_STATES16 447 /* Do not saturate any state value ! The result would be unacceptable. Rounding makes SNR around 10dB better. */ 448 states[i][s2] = (FIXP_BQS)(LONG)((state0 + (FIXP_DBL)(1<<(DFRACT_BITS-FRACT_BITS-2))) >> (DFRACT_BITS-FRACT_BITS-1)); 449#else 450 states[i][s2] = state0<<1; 451#endif 452 453 /* Feedback output to next section. */ 454 input=y; 455 456 /* Step to next coef set */ 457 coeff += BIQUAD_COEFSTEP; 458 } 459 downFilter->ptr ^= 1; 460 } 461 462#endif 463 464 /* Apply final gain/scaling to output */ 465#if (SAMPLE_BITS == 16) 466 output = (INT_PCM) SATURATE_RIGHT_SHIFT(y+(FIXP_DBL)(1<<(DFRACT_BITS-SAMPLE_BITS-BIQUAD_SCALE-1)), DFRACT_BITS-SAMPLE_BITS-BIQUAD_SCALE, SAMPLE_BITS); 467 //output = (INT_PCM) SATURATE_RIGHT_SHIFT(y, DFRACT_BITS-SAMPLE_BITS-BIQUAD_SCALE, SAMPLE_BITS); 468#else 469 output = SATURATE_LEFT_SHIFT(y, BIQUAD_SCALE, SAMPLE_BITS); 470#endif 471 472 473 return output; 474} 475 476 477 478 479/*! 480 \brief FDKaacEnc_Downsample numInSamples of type INT_PCM 481 Returns number of output samples in numOutSamples 482 483 \return success of operation 484*/ 485 486INT FDKaacEnc_Downsample(DOWNSAMPLER *DownSampler, /*!< pointer to downsampler instance */ 487 INT_PCM *inSamples, /*!< pointer to input samples */ 488 INT numInSamples, /*!< number of input samples */ 489 INT inStride, /*!< increment of input samples */ 490 INT_PCM *outSamples, /*!< pointer to output samples */ 491 INT *numOutSamples, /*!< pointer tp number of output samples */ 492 INT outStride /*!< increment of output samples */ 493 ) 494{ 495 INT i; 496 *numOutSamples=0; 497 498 for(i=0; i<numInSamples; i+=DownSampler->ratio) 499 { 500 *outSamples = AdvanceFilter(&(DownSampler->downFilter), &inSamples[i*inStride], DownSampler->ratio, inStride); 501 outSamples += outStride; 502 } 503 *numOutSamples = numInSamples/DownSampler->ratio; 504 505 return 0; 506} 507 508