1
2 /* -----------------------------------------------------------------------------------------------------------
3 Software 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
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