Home | History | Annotate | Download | only in src
      1 
      2 /* -----------------------------------------------------------------------------------------------------------
      3 Software License for The Fraunhofer FDK AAC Codec Library for Android
      4 
      5  Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Frderung der angewandten Forschung e.V.
      6   All rights reserved.
      7 
      8  1.    INTRODUCTION
      9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
     10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
     11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
     12 
     13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
     14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
     15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
     16 of the MPEG specifications.
     17 
     18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
     19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
     20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
     21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
     22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
     23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
     24 
     25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
     26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
     27 applications information and documentation.
     28 
     29 2.    COPYRIGHT LICENSE
     30 
     31 Redistribution and use in source and binary forms, with or without modification, are permitted without
     32 payment of copyright license fees provided that you satisfy the following conditions:
     33 
     34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
     35 your modifications thereto in source code form.
     36 
     37 You must retain the complete text of this software license in the documentation and/or other materials
     38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
     39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
     40 modifications thereto to recipients of copies in binary form.
     41 
     42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
     43 prior written permission.
     44 
     45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
     46 software or your modifications thereto.
     47 
     48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
     49 and 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 
     53 3.    NO PATENT LICENSE
     54 
     55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
     56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
     57 respect to this software.
     58 
     59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
     60 by appropriate patent licenses.
     61 
     62 4.    DISCLAIMER
     63 
     64 This 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
     66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
     68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
     69 or business interruption, however caused and on any theory of liability, whether in contract, strict
     70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
     71 advised of the possibility of such damage.
     72 
     73 5.    CONTACT INFORMATION
     74 
     75 Fraunhofer Institute for Integrated Circuits IIS
     76 Attention: Audio and Multimedia Departments - FDK AAC LL
     77 Am Wolfsmantel 33
     78 91058 Erlangen, Germany
     79 
     80 www.iis.fraunhofer.de/amm
     81 amm-info (at) iis.fraunhofer.de
     82 ----------------------------------------------------------------------------------------------------------- */
     83 
     84 #include "psdec_hybrid.h"
     85 
     86 
     87 #include "fft.h"
     88 #include "sbr_ram.h"
     89 
     90 #include "FDK_tools_rom.h"
     91 #include "sbr_rom.h"
     92 
     93 /*******************************************************************************
     94  Functionname:  InitHybridFilterBank
     95  *******************************************************************************
     96 
     97  Description:   Init one instance of HANDLE_HYBRID stuct
     98 
     99  Arguments:
    100 
    101  Return:        none
    102 
    103 *******************************************************************************/
    104 
    105 
    106 SBR_ERROR
    107 InitHybridFilterBank ( HANDLE_HYBRID hs,          /*!< Handle to HYBRID struct. */
    108                        SCHAR frameSize,           /*!< Framesize (in Qmf sbband samples). */
    109                        SCHAR noBands,             /*!< Number of Qmf bands for hybrid filtering. */
    110                        const UCHAR *pResolution ) /*!< Resolution in Qmf bands (length noBands). */
    111 {
    112   SCHAR i;
    113   UCHAR maxNoChannels = 0;
    114 
    115   for (i = 0; i < noBands; i++) {
    116     hs->pResolution[i] = pResolution[i];
    117     if(pResolution[i] > maxNoChannels)
    118       maxNoChannels = pResolution[i];
    119   }
    120 
    121   hs->nQmfBands     = noBands;
    122   hs->frameSize     = frameSize;
    123   hs->qmfBufferMove = HYBRID_FILTER_LENGTH - 1;
    124 
    125   hs->sf_mQmfBuffer = 0;
    126 
    127   return SBRDEC_OK;
    128 }
    129 
    130 /*******************************************************************************
    131  Functionname:  dualChannelFiltering
    132  *******************************************************************************
    133 
    134  Description:   fast 2-channel real-valued filtering with 6-tap delay.
    135 
    136  Arguments:
    137 
    138  Return:        none
    139 
    140 *******************************************************************************/
    141 
    142 /*!
    143 2 channel filter
    144 <pre>
    145    Filter Coefs:
    146    0.0,
    147    0.01899487526049,
    148    0.0,
    149    -0.07293139167538,
    150    0.0,
    151    0.30596630545168,
    152    0.5,
    153    0.30596630545168,
    154    0.0,
    155    -0.07293139167538,
    156    0.0,
    157    0.01899487526049,
    158    0.0
    159 
    160 
    161    Filter design:
    162    h[q,n] = g[n] * cos(2pi/2 * q * (n-6) );  n = 0..12,  q = 0,1;
    163 
    164    ->  h[0,n] = g[n] * 1;
    165    ->  h[1,n] = g[n] * pow(-1,n);
    166 </pre>
    167 */
    168 
    169 static void slotBasedDualChannelFiltering( const FIXP_DBL *pQmfReal,
    170                                            const FIXP_DBL *pQmfImag,
    171 
    172                                            FIXP_DBL       *mHybridReal,
    173                                            FIXP_DBL       *mHybridImag)
    174 {
    175 
    176   FIXP_DBL  t1, t3, t5, t6;
    177 
    178   /* symmetric filter coefficients */
    179 
    180   /*  you don't have to shift the result after fMult because of p2_13_20 <= 0.5 */
    181   t1 = fMultDiv2(p2_13_20[1] , ( (pQmfReal[1] >> 1) + (pQmfReal[11] >> 1)));
    182   t3 = fMultDiv2(p2_13_20[3] , ( (pQmfReal[3] >> 1) + (pQmfReal[ 9] >> 1)));
    183   t5 = fMultDiv2(p2_13_20[5] , ( (pQmfReal[5] >> 1) + (pQmfReal[ 7] >> 1)));
    184   t6 = fMultDiv2(p2_13_20[6] ,   (pQmfReal[6] >> 1) );
    185 
    186   mHybridReal[0] = (t1 + t3 + t5 + t6) << 2;
    187   mHybridReal[1] = (- t1 - t3 - t5 + t6) << 2;
    188 
    189   t1 = fMultDiv2(p2_13_20[1] , ( (pQmfImag[1] >> 1) + (pQmfImag[11] >> 1)));
    190   t3 = fMultDiv2(p2_13_20[3] , ( (pQmfImag[3] >> 1) + (pQmfImag[ 9] >> 1)));
    191   t5 = fMultDiv2(p2_13_20[5] , ( (pQmfImag[5] >> 1) + (pQmfImag[ 7] >> 1)));
    192   t6 = fMultDiv2(p2_13_20[6] ,    pQmfImag[6] >> 1 );
    193 
    194   mHybridImag[0] = (t1 + t3 + t5 + t6) << 2;
    195   mHybridImag[1] = (- t1 - t3 - t5 + t6) << 2;
    196 }
    197 
    198 
    199 /*******************************************************************************
    200  Functionname:  eightChannelFiltering
    201  *******************************************************************************
    202 
    203  Description:   fast 8-channel complex-valued filtering with 6-tap delay.
    204 
    205  Arguments:
    206 
    207  Return:        none
    208 
    209 *******************************************************************************/
    210 /*!
    211    8 channel filter
    212 
    213    Implementation using a FFT of length 8
    214 <pre>
    215    prototype filter coefficients:
    216    0.00746082949812   0.02270420949825   0.04546865930473   0.07266113929591   0.09885108575264   0.11793710567217
    217    0.125
    218    0.11793710567217   0.09885108575264   0.07266113929591   0.04546865930473   0.02270420949825   0.00746082949812
    219 
    220    Filter design:
    221    N = 13; Q = 8;
    222    h[q,n]       = g[n] * exp(j * 2 * pi / Q * (q + .5) * (n - 6));  n = 0..(N-1),  q = 0..(Q-1);
    223 
    224    Time Signal:   x[t];
    225    Filter Bank Output
    226    y[q,t] = conv(x[t],h[q,t]) = conv(h[q,t],x[t]) = sum(x[k] * h[q, t - k] ) = sum(h[q, k] * x[t - k] ); k = 0..(N-1);
    227 
    228    y[q,t] =   x[t - 12]*h[q, 12]  +  x[t - 11]*h[q, 11]  +  x[t - 10]*h[q, 10]  +  x[t -  9]*h[q,  9]
    229            +  x[t -  8]*h[q,  8]  +  x[t -  7]*h[q,  7]
    230            +  x[t -  6]*h[q,  6]
    231            +  x[t -  5]*h[q,  5]  +  x[t -  4]*h[q,  4]
    232            +  x[t -  3]*h[q,  3]  +  x[t -  2]*h[q,  2]  +  x[t -  1]*h[q,  1]  +  x[t -  0]*h[q,  0];
    233 
    234    h'[q, n] = h[q,(N-1)-n] = g[n] * exp(j * 2 * pi / Q * (q + .5) * (6 - n));  n = 0..(N-1),  q = 0..(Q-1);
    235 
    236    y[q,t] =   x[t - 12]*h'[q,  0]  +  x[t - 11]*h'[q,  1]  +  x[t - 10]*h'[q,  2]  +  x[t -  9]*h'[q,  3]
    237            +  x[t -  8]*h'[q,  4]  +  x[t -  7]*h'[q,  5]
    238            +  x[t -  6]*h'[q,  6]
    239            +  x[t -  5]*h'[q,  7]  +  x[t -  4]*h'[q,  8]
    240            +  x[t -  3]*h'[q,  9]  +  x[t -  2]*h'[q, 10]  +  x[t -  1]*h'[q, 11]  +  x[t -  0]*h'[q, 12];
    241 
    242    Try to split off FFT Modulation Term:
    243    FFT(x[t], q) = sum(x[t+k]*exp(-j*2*pi/N *q * k))
    244                                            c                                           m
    245    Step 1:  h'[q,n] = g[n] * ( exp(j * 2 * pi / 8 * .5 * (6 - n)) ) * ( exp (j * 2 * pi / 8 * q * (6 - n)) );
    246 
    247     h'[q,n] = g[n] *c[n] * m[q,n]; (see above)
    248     c[n]    = exp( j * 2 * pi / 8 * .5 * (6 - n) );
    249     m[q,n]  = exp( j * 2 * pi / 8 *  q * (6 - n) );
    250 
    251     y[q,t] = x[t -  0]*g[0]*c[0]*m[q,0]  +  x[t -  1]*g[1]*c[ 1]*m[q, 1]  + ...
    252              ...                         +  x[t - 12]*g[2]*c[12]*m[q,12];
    253 
    254                                                                               |
    255     n                   m                            *exp(-j*2*pi)            |   n'                   fft
    256 -------------------------------------------------------------------------------------------------------------------------
    257     0       exp( j * 2 * pi / 8 * q * 6) ->  exp(-j * 2 * pi / 8 * q * 2)     |   2         exp(-j * 2 * pi / 8 * q * 0)
    258     1       exp( j * 2 * pi / 8 * q * 5) ->  exp(-j * 2 * pi / 8 * q * 3)     |   3         exp(-j * 2 * pi / 8 * q * 1)
    259     2       exp( j * 2 * pi / 8 * q * 4) ->  exp(-j * 2 * pi / 8 * q * 4)     |   4         exp(-j * 2 * pi / 8 * q * 2)
    260     3       exp( j * 2 * pi / 8 * q * 3) ->  exp(-j * 2 * pi / 8 * q * 5)     |   5         exp(-j * 2 * pi / 8 * q * 3)
    261     4       exp( j * 2 * pi / 8 * q * 2) ->  exp(-j * 2 * pi / 8 * q * 6)     |   6         exp(-j * 2 * pi / 8 * q * 4)
    262     5       exp( j * 2 * pi / 8 * q * 1) ->  exp(-j * 2 * pi / 8 * q * 7)     |   7         exp(-j * 2 * pi / 8 * q * 5)
    263     6       exp( j * 2 * pi / 8 * q * 0)                                      |   0         exp(-j * 2 * pi / 8 * q * 6)
    264     7       exp(-j * 2 * pi / 8 * q * 1)                                      |   1         exp(-j * 2 * pi / 8 * q * 7)
    265     8       exp(-j * 2 * pi / 8 * q * 2)                                      |   2
    266     9       exp(-j * 2 * pi / 8 * q * 3)                                      |   3
    267     10      exp(-j * 2 * pi / 8 * q * 4)                                      |   4
    268     11      exp(-j * 2 * pi / 8 * q * 5)                                      |   5
    269     12      exp(-j * 2 * pi / 8 * q * 6)                                      |   6
    270 
    271 
    272     now use fft modulation coefficients
    273     m[6]  =       = fft[0]
    274     m[7]  =       = fft[1]
    275     m[8]  = m[ 0] = fft[2]
    276     m[9]  = m[ 1] = fft[3]
    277     m[10] = m[ 2] = fft[4]
    278     m[11] = m[ 3] = fft[5]
    279     m[12] = m[ 4] = fft[6]
    280             m[ 5] = fft[7]
    281 
    282     y[q,t] = (                       x[t- 6]*g[ 6]*c[ 6] ) * fft[q,0]  +
    283              (                       x[t- 7]*g[ 7]*c[ 7] ) * fft[q,1]  +
    284              ( x[t- 0]*g[ 0]*c[ 0] + x[t- 8]*g[ 8]*c[ 8] ) * fft[q,2]  +
    285              ( x[t- 1]*g[ 1]*c[ 1] + x[t- 9]*g[ 9]*c[ 9] ) * fft[q,3]  +
    286              ( x[t- 2]*g[ 2]*c[ 2] + x[t-10]*g[10]*c[10] ) * fft[q,4]  +
    287              ( x[t- 3]*g[ 3]*c[ 3] + x[t-11]*g[11]*c[11] ) * fft[q,5]  +
    288              ( x[t- 4]*g[ 4]*c[ 4] + x[t-12]*g[12]*c[12] ) * fft[q,6]  +
    289              ( x[t- 5]*g[ 5]*c[ 5]                       ) * fft[q,7];
    290 
    291     pre twiddle factors c[n] = exp(j * 2 * pi / 8 * .5 * (6 - n));
    292     n                c]           |  n                c[n]         |  n                c[n]
    293 ---------------------------------------------------------------------------------------------------
    294     0       exp( j * 6 * pi / 8)  |  1       exp( j * 5 * pi / 8)  |  2       exp( j * 4 * pi / 8)
    295     3       exp( j * 3 * pi / 8)  |  4       exp( j * 2 * pi / 8)  |  5       exp( j * 1 * pi / 8)
    296     6       exp( j * 0 * pi / 8)  |  7       exp(-j * 1 * pi / 8)  |  8       exp(-j * 2 * pi / 8)
    297     9       exp(-j * 3 * pi / 8)  | 10       exp(-j * 4 * pi / 8)  | 11       exp(-j * 5 * pi / 8)
    298    12       exp(-j * 6 * pi / 8)  |                                |
    299 </pre>
    300 */
    301 
    302 /* defining rotation factors for *ChannelFiltering */
    303 
    304 #define cos0Pi    FL2FXCONST_DBL( 1.f)
    305 #define sin0Pi    FL2FXCONST_DBL( 0.f)
    306 
    307 #define cos1Pi    FL2FXCONST_DBL(-1.f)
    308 #define sin1Pi    FL2FXCONST_DBL( 0.f)
    309 
    310 #define cos1Pi_2  FL2FXCONST_DBL( 0.f)
    311 #define sin1Pi_2  FL2FXCONST_DBL( 1.f)
    312 
    313 #define cos1Pi_3  FL2FXCONST_DBL( 0.5f)
    314 #define sin1Pi_3  FL2FXCONST_DBL( 0.86602540378444f)
    315 
    316 #define cos0Pi_4  cos0Pi
    317 #define cos1Pi_4  FL2FXCONST_DBL(0.70710678118655f)
    318 #define cos2Pi_4  cos1Pi_2
    319 #define cos3Pi_4  (-cos1Pi_4)
    320 #define cos4Pi_4  (-cos0Pi_4)
    321 #define cos5Pi_4  cos3Pi_4
    322 #define cos6Pi_4  cos2Pi_4
    323 
    324 #define sin0Pi_4  sin0Pi
    325 #define sin1Pi_4  FL2FXCONST_DBL(0.70710678118655f)
    326 #define sin2Pi_4  sin1Pi_2
    327 #define sin3Pi_4  sin1Pi_4
    328 #define sin4Pi_4  sin0Pi_4
    329 #define sin5Pi_4  (-sin3Pi_4)
    330 #define sin6Pi_4  (-sin2Pi_4)
    331 
    332 #define cos0Pi_8  cos0Pi
    333 #define cos1Pi_8  FL2FXCONST_DBL(0.92387953251129f)
    334 #define cos2Pi_8  cos1Pi_4
    335 #define cos3Pi_8  FL2FXCONST_DBL(0.38268343236509f)
    336 #define cos4Pi_8  cos2Pi_4
    337 #define cos5Pi_8  (-cos3Pi_8)
    338 #define cos6Pi_8  (-cos2Pi_8)
    339 
    340 #define sin0Pi_8  sin0Pi
    341 #define sin1Pi_8  cos3Pi_8
    342 #define sin2Pi_8  sin1Pi_4
    343 #define sin3Pi_8  cos1Pi_8
    344 #define sin4Pi_8  sin2Pi_4
    345 #define sin5Pi_8  sin3Pi_8
    346 #define sin6Pi_8  sin1Pi_4
    347 
    348 #if defined(ARCH_PREFER_MULT_32x16)
    349   #define FIXP_HYB FIXP_SGL
    350   #define FIXP_CAST FX_DBL2FX_SGL
    351 #else
    352   #define FIXP_HYB FIXP_DBL
    353   #define FIXP_CAST
    354 #endif
    355 
    356 static const FIXP_HYB  cr[13] =
    357 {
    358    FIXP_CAST(cos6Pi_8), FIXP_CAST(cos5Pi_8), FIXP_CAST(cos4Pi_8),
    359    FIXP_CAST(cos3Pi_8), FIXP_CAST(cos2Pi_8), FIXP_CAST(cos1Pi_8),
    360    FIXP_CAST(cos0Pi_8),
    361    FIXP_CAST(cos1Pi_8), FIXP_CAST(cos2Pi_8), FIXP_CAST(cos3Pi_8),
    362    FIXP_CAST(cos4Pi_8), FIXP_CAST(cos5Pi_8), FIXP_CAST(cos6Pi_8)
    363 };
    364 
    365 static const FIXP_HYB  ci[13] =
    366 {
    367    FIXP_CAST( sin6Pi_8), FIXP_CAST( sin5Pi_8), FIXP_CAST( sin4Pi_8),
    368    FIXP_CAST( sin3Pi_8), FIXP_CAST( sin2Pi_8), FIXP_CAST( sin1Pi_8),
    369    FIXP_CAST( sin0Pi_8) ,
    370    FIXP_CAST(-sin1Pi_8), FIXP_CAST(-sin2Pi_8), FIXP_CAST(-sin3Pi_8),
    371    FIXP_CAST(-sin4Pi_8), FIXP_CAST(-sin5Pi_8), FIXP_CAST(-sin6Pi_8)
    372 };
    373 
    374 static void slotBasedEightChannelFiltering( const FIXP_DBL *pQmfReal,
    375                                             const FIXP_DBL *pQmfImag,
    376 
    377                                             FIXP_DBL  *mHybridReal,
    378                                             FIXP_DBL  *mHybridImag)
    379 {
    380 
    381   int bin;
    382   FIXP_DBL _fft[128 + ALIGNMENT_DEFAULT - 1];
    383   FIXP_DBL *fft = (FIXP_DBL *)ALIGN_PTR(_fft);
    384 
    385 #if defined(ARCH_PREFER_MULT_32x16)
    386   const FIXP_SGL *p = p8_13_20; /* BASELINE_PS */
    387 #else
    388   const FIXP_DBL *p = p8_13_20; /* BASELINE_PS */
    389 #endif
    390 
    391   /* pre twiddeling */
    392 
    393   /*   x*(a*b + c*d) = fMultDiv2(x, fMultAddDiv2(fMultDiv2(a, b), c, d)) */
    394   /*   x*(a*b - c*d) = fMultDiv2(x, fMultSubDiv2(fMultDiv2(a, b), c, d)) */
    395   FIXP_DBL accu1, accu2, accu3, accu4;
    396 
    397   #define TWIDDLE_1(n_0,n_1,n_2)                                                        \
    398          cplxMultDiv2(&accu1, &accu2, pQmfReal[n_0], pQmfImag[n_0], cr[n_0], ci[n_0]);  \
    399          accu1 = fMultDiv2(p[n_0], accu1);                                              \
    400          accu2 = fMultDiv2(p[n_0], accu2);                                              \
    401          cplxMultDiv2(&accu3, &accu4, pQmfReal[n_1], pQmfImag[n_1], cr[n_1], ci[n_1]);  \
    402          accu3 = fMultDiv2(p[n_1], accu3);                                              \
    403          accu4 = fMultDiv2(p[n_1], accu4);                                              \
    404          fft[FIXP_FFT_IDX_R(n_2)] = accu1 + accu3;                                      \
    405          fft[FIXP_FFT_IDX_I(n_2)] = accu2 + accu4;
    406 
    407   #define TWIDDLE_0(n_0,n_1)                                                            \
    408          cplxMultDiv2(&accu1, &accu2, pQmfReal[n_0], pQmfImag[n_0], cr[n_0], ci[n_0]);  \
    409          fft[FIXP_FFT_IDX_R(n_1)] = fMultDiv2(p[n_0], accu1);                           \
    410          fft[FIXP_FFT_IDX_I(n_1)] = fMultDiv2(p[n_0], accu2);
    411 
    412   TWIDDLE_0( 6, 0)
    413   TWIDDLE_0( 7, 1)
    414 
    415   TWIDDLE_1( 0, 8, 2)
    416   TWIDDLE_1( 1, 9, 3)
    417   TWIDDLE_1( 2,10, 4)
    418   TWIDDLE_1( 3,11, 5)
    419   TWIDDLE_1( 4,12, 6)
    420 
    421   TWIDDLE_0( 5, 7)
    422 
    423   fft_8 (fft);
    424 
    425   /* resort fft data into output array*/
    426   for(bin=0; bin<8;bin++ ) {
    427     mHybridReal[bin] = fft[FIXP_FFT_IDX_R(bin)] << 4;
    428     mHybridImag[bin] = fft[FIXP_FFT_IDX_I(bin)] << 4;
    429   }
    430 }
    431 
    432 
    433 /*******************************************************************************
    434  Functionname:  fillHybridDelayLine
    435  *******************************************************************************
    436 
    437  Description:   The delay line of the hybrid filter is filled and copied from
    438                 left to right.
    439 
    440  Return:        none
    441 
    442 *******************************************************************************/
    443 
    444 void
    445 fillHybridDelayLine( FIXP_DBL **fixpQmfReal,          /*!< Qmf real Values    */
    446                      FIXP_DBL **fixpQmfImag,          /*!< Qmf imag Values    */
    447                      FIXP_DBL   fixpHybridLeftR[12],  /*!< Hybrid real Values left channel  */
    448                      FIXP_DBL   fixpHybridLeftI[12],  /*!< Hybrid imag Values left channel  */
    449                      FIXP_DBL   fixpHybridRightR[12], /*!< Hybrid real Values right channel */
    450                      FIXP_DBL   fixpHybridRightI[12], /*!< Hybrid imag Values right channel */
    451                      HANDLE_HYBRID hHybrid )
    452 {
    453   int i;
    454 
    455   for (i = 0; i < HYBRID_FILTER_DELAY; i++) {
    456     slotBasedHybridAnalysis ( fixpQmfReal[i],
    457                               fixpQmfReal[i],
    458                               fixpHybridLeftR,
    459                               fixpHybridLeftI,
    460                               hHybrid );
    461   }
    462 
    463   FDKmemcpy(fixpHybridRightR, fixpHybridLeftR, sizeof(FIXP_DBL)*NO_SUB_QMF_CHANNELS);
    464   FDKmemcpy(fixpHybridRightI, fixpHybridLeftI, sizeof(FIXP_DBL)*NO_SUB_QMF_CHANNELS);
    465 }
    466 
    467 
    468 /*******************************************************************************
    469  Functionname:  slotBasedHybridAnalysis
    470  *******************************************************************************
    471 
    472  Description:   The lower QMF subbands are further split to provide better
    473                 frequency resolution for PS processing.
    474 
    475   Return:        none
    476 
    477 *******************************************************************************/
    478 
    479 
    480 void
    481 slotBasedHybridAnalysis ( FIXP_DBL *fixpQmfReal,      /*!< Qmf real Values */
    482                           FIXP_DBL *fixpQmfImag,      /*!< Qmf imag Values */
    483 
    484                           FIXP_DBL  fixpHybridReal[12],   /*!< Hybrid real Values */
    485                           FIXP_DBL  fixpHybridImag[12],   /*!< Hybrid imag Values */
    486 
    487                           HANDLE_HYBRID hHybrid)
    488 {
    489   int  k, band;
    490   HYBRID_RES hybridRes;
    491   int  chOffset = 0;
    492 
    493   C_ALLOC_SCRATCH_START(pTempRealSlot, FIXP_DBL, 4*HYBRID_FILTER_LENGTH);
    494 
    495   FIXP_DBL *pTempImagSlot = pTempRealSlot + HYBRID_FILTER_LENGTH;
    496   FIXP_DBL *pWorkRealSlot = pTempImagSlot + HYBRID_FILTER_LENGTH;
    497   FIXP_DBL *pWorkImagSlot = pWorkRealSlot + HYBRID_FILTER_LENGTH;
    498 
    499   /*!
    500   Hybrid filtering is applied to the first hHybrid->nQmfBands QMF bands (3 when 10 or 20 stereo bands
    501   are used, 5 when 34 stereo bands are used). For the remaining QMF bands a delay would be necessary.
    502   But there is no need to implement a delay because there is a look-ahead of HYBRID_FILTER_DELAY = 6
    503   QMF samples in the low-band buffer.
    504   */
    505 
    506   for(band = 0; band < hHybrid->nQmfBands; band++) {
    507 
    508     /*  get hybrid resolution per qmf band                */
    509     /*  in case of baseline ps 10/20 band stereo mode :   */
    510     /*                                                    */
    511     /*             qmfBand[0] : 8 ( HYBRID_8_CPLX )       */
    512     /*             qmfBand[1] : 2 ( HYBRID_2_REAL )       */
    513     /*             qmfBand[2] : 2 ( HYBRID_2_REAL )       */
    514     /*                                                    */
    515     /*  (split the 3 lower qmf band to 12 hybrid bands)   */
    516 
    517     hybridRes = (HYBRID_RES)hHybrid->pResolution[band];
    518 
    519     FDKmemcpy(pWorkRealSlot, hHybrid->mQmfBufferRealSlot[band], hHybrid->qmfBufferMove * sizeof(FIXP_DBL));
    520     FDKmemcpy(pWorkImagSlot, hHybrid->mQmfBufferImagSlot[band], hHybrid->qmfBufferMove * sizeof(FIXP_DBL));
    521 
    522     pWorkRealSlot[hHybrid->qmfBufferMove] = fixpQmfReal[band];
    523     pWorkImagSlot[hHybrid->qmfBufferMove] = fixpQmfImag[band];
    524 
    525     FDKmemcpy(hHybrid->mQmfBufferRealSlot[band], pWorkRealSlot + 1, hHybrid->qmfBufferMove * sizeof(FIXP_DBL));
    526     FDKmemcpy(hHybrid->mQmfBufferImagSlot[band], pWorkImagSlot + 1, hHybrid->qmfBufferMove * sizeof(FIXP_DBL));
    527 
    528     if (fixpQmfReal) {
    529 
    530       /* actual filtering only if output signal requested */
    531       switch( hybridRes ) {
    532 
    533       /* HYBRID_2_REAL & HYBRID_8_CPLX are only needful for baseline ps */
    534       case HYBRID_2_REAL:
    535 
    536         slotBasedDualChannelFiltering( pWorkRealSlot,
    537                                        pWorkImagSlot,
    538                                        pTempRealSlot,
    539                                        pTempImagSlot);
    540         break;
    541 
    542       case HYBRID_8_CPLX:
    543 
    544         slotBasedEightChannelFiltering( pWorkRealSlot,
    545                                         pWorkImagSlot,
    546                                         pTempRealSlot,
    547                                         pTempImagSlot);
    548         break;
    549 
    550       default:
    551         FDK_ASSERT(0);
    552       }
    553 
    554       for(k = 0; k < (SCHAR)hybridRes; k++) {
    555         fixpHybridReal [chOffset + k] = pTempRealSlot[k];
    556         fixpHybridImag [chOffset + k] = pTempImagSlot[k];
    557       }
    558       chOffset += hybridRes;
    559     } /* if (mHybridReal) */
    560   }
    561 
    562   /* group hybrid channels 3+4 -> 3 and 2+5 -> 2 */
    563   fixpHybridReal[3] += fixpHybridReal[4];
    564   fixpHybridImag[3] += fixpHybridImag[4];
    565   fixpHybridReal[4] = (FIXP_DBL)0;
    566   fixpHybridImag[4] = (FIXP_DBL)0;
    567 
    568   fixpHybridReal[2] += fixpHybridReal[5];
    569   fixpHybridImag[2] += fixpHybridImag[5];
    570   fixpHybridReal[5] = (FIXP_DBL)0;
    571   fixpHybridImag[5] = (FIXP_DBL)0;
    572 
    573   /* free memory on scratch */
    574   C_ALLOC_SCRATCH_END(pTempRealSlot, FIXP_DBL, 4*HYBRID_FILTER_LENGTH);
    575 
    576 }
    577 
    578 
    579 /*******************************************************************************
    580  Functionname:  slotBasedHybridSynthesis
    581  *******************************************************************************
    582 
    583  Description:  The coefficients offering higher resolution for the lower QMF
    584                channel are simply added prior to the synthesis with the 54
    585                subbands QMF.
    586 
    587  Arguments:
    588 
    589  Return:        none
    590 
    591 *******************************************************************************/
    592 
    593 /*! <pre>
    594       l,r0(n) ---\
    595       l,r1(n) ---- + --\
    596       l,r2(n) ---/      \
    597                          + --> F0(w)
    598       l,r3(n) ---\      /
    599       l,r4(n) ---- + --/
    600       l,r5(n) ---/
    601 
    602 
    603       l,r6(n) ---\
    604                   + ---------> F1(w)
    605       l,r7(n) ---/
    606 
    607 
    608       l,r8(n) ---\
    609                   + ---------> F2(w)
    610       l,r9(n) ---/
    611 
    612     </pre>
    613       Hybrid QMF synthesis filterbank for the 10 and 20 stereo-bands configurations. The
    614       coefficients offering higher resolution for the lower QMF channel are simply added
    615       prior to the synthesis with the 54 subbands QMF.
    616 
    617       [see ISO/IEC 14496-3:2001/FDAM 2:2004(E) - Page 52]
    618 */
    619 
    620 
    621 void
    622 slotBasedHybridSynthesis ( FIXP_DBL  *fixpHybridReal,  /*!< Hybrid real Values */
    623                            FIXP_DBL  *fixpHybridImag,  /*!< Hybrid imag Values */
    624                            FIXP_DBL  *fixpQmfReal,     /*!< Qmf real Values */
    625                            FIXP_DBL  *fixpQmfImag,     /*!< Qmf imag Values */
    626                            HANDLE_HYBRID hHybrid )     /*!< Handle to HYBRID struct. */
    627 {
    628   int  k, band;
    629 
    630   HYBRID_RES hybridRes;
    631   int  chOffset = 0;
    632 
    633   for(band = 0; band < hHybrid->nQmfBands; band++) {
    634 
    635     FIXP_DBL qmfReal = FL2FXCONST_DBL(0.f);
    636     FIXP_DBL qmfImag = FL2FXCONST_DBL(0.f);
    637     hybridRes = (HYBRID_RES)hHybrid->pResolution[band];
    638 
    639     for(k = 0; k < (SCHAR)hybridRes; k++) {
    640       qmfReal += fixpHybridReal[chOffset + k];
    641       qmfImag += fixpHybridImag[chOffset + k];
    642     }
    643 
    644     fixpQmfReal[band] = qmfReal;
    645     fixpQmfImag[band] = qmfImag;
    646 
    647     chOffset += hybridRes;
    648   }
    649 }
    650 
    651 
    652 
    653