• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* -----------------------------------------------------------------------------------------------------------
3 Software 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
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@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
InitHybridFilterBank(HANDLE_HYBRID hs,SCHAR frameSize,SCHAR noBands,const UCHAR * pResolution)107 InitHybridFilterBank ( HANDLE_HYBRID hs,          /*!< Handle to HYBRID struct. */
108                        SCHAR frameSize,           /*!< Framesize (in Qmf s�bband 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 
slotBasedDualChannelFiltering(const FIXP_DBL * pQmfReal,const FIXP_DBL * pQmfImag,FIXP_DBL * mHybridReal,FIXP_DBL * mHybridImag)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 
slotBasedEightChannelFiltering(const FIXP_DBL * pQmfReal,const FIXP_DBL * pQmfImag,FIXP_DBL * mHybridReal,FIXP_DBL * mHybridImag)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
fillHybridDelayLine(FIXP_DBL ** fixpQmfReal,FIXP_DBL ** fixpQmfImag,FIXP_DBL fixpHybridLeftR[12],FIXP_DBL fixpHybridLeftI[12],FIXP_DBL fixpHybridRightR[12],FIXP_DBL fixpHybridRightI[12],HANDLE_HYBRID hHybrid)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
slotBasedHybridAnalysis(FIXP_DBL * fixpQmfReal,FIXP_DBL * fixpQmfImag,FIXP_DBL fixpHybridReal[12],FIXP_DBL fixpHybridImag[12],HANDLE_HYBRID hHybrid)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
slotBasedHybridSynthesis(FIXP_DBL * fixpHybridReal,FIXP_DBL * fixpHybridImag,FIXP_DBL * fixpQmfReal,FIXP_DBL * fixpQmfImag,HANDLE_HYBRID hHybrid)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