1
2/* -----------------------------------------------------------------------------------------------------------
3Software License for The Fraunhofer FDK AAC Codec Library for Android
4
5© Copyright  1995 - 2012 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  &param_set48,
287  &param_set45,
288  &param_set41,
289  &param_set35,
290  &param_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