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#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
106SBR_ERROR
107InitHybridFilterBank ( 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/*!
1432 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
169static 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
356static 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
365static 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
374static 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
444void
445fillHybridDelayLine( 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
480void
481slotBasedHybridAnalysis ( 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
621void
622slotBasedHybridSynthesis ( 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