/src/aac/libFDK/src/qmf.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* ----------------------------------------------------------------------------- |
2 | | Software License for The Fraunhofer FDK AAC Codec Library for Android |
3 | | |
4 | | © Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten |
5 | | Forschung e.V. All rights reserved. |
6 | | |
7 | | 1. INTRODUCTION |
8 | | The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software |
9 | | that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding |
10 | | scheme for digital audio. This FDK AAC Codec software is intended to be used on |
11 | | a wide variety of Android devices. |
12 | | |
13 | | AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient |
14 | | general perceptual audio codecs. AAC-ELD is considered the best-performing |
15 | | full-bandwidth communications codec by independent studies and is widely |
16 | | deployed. AAC has been standardized by ISO and IEC as part of the MPEG |
17 | | specifications. |
18 | | |
19 | | Patent licenses for necessary patent claims for the FDK AAC Codec (including |
20 | | those of Fraunhofer) may be obtained through Via Licensing |
21 | | (www.vialicensing.com) or through the respective patent owners individually for |
22 | | the purpose of encoding or decoding bit streams in products that are compliant |
23 | | with the ISO/IEC MPEG audio standards. Please note that most manufacturers of |
24 | | Android devices already license these patent claims through Via Licensing or |
25 | | directly from the patent owners, and therefore FDK AAC Codec software may |
26 | | already be covered under those patent licenses when it is used for those |
27 | | licensed purposes only. |
28 | | |
29 | | Commercially-licensed AAC software libraries, including floating-point versions |
30 | | with enhanced sound quality, are also available from Fraunhofer. Users are |
31 | | encouraged to check the Fraunhofer website for additional applications |
32 | | information and documentation. |
33 | | |
34 | | 2. COPYRIGHT LICENSE |
35 | | |
36 | | Redistribution and use in source and binary forms, with or without modification, |
37 | | are permitted without payment of copyright license fees provided that you |
38 | | satisfy the following conditions: |
39 | | |
40 | | You must retain the complete text of this software license in redistributions of |
41 | | the FDK AAC Codec or your modifications thereto in source code form. |
42 | | |
43 | | You must retain the complete text of this software license in the documentation |
44 | | and/or other materials provided with redistributions of the FDK AAC Codec or |
45 | | your modifications thereto in binary form. You must make available free of |
46 | | charge copies of the complete source code of the FDK AAC Codec and your |
47 | | modifications thereto to recipients of copies in binary form. |
48 | | |
49 | | The name of Fraunhofer may not be used to endorse or promote products derived |
50 | | from this library without prior written permission. |
51 | | |
52 | | You may not charge copyright license fees for anyone to use, copy or distribute |
53 | | the FDK AAC Codec software or your modifications thereto. |
54 | | |
55 | | Your modified versions of the FDK AAC Codec must carry prominent notices stating |
56 | | that you changed the software and the date of any change. For modified versions |
57 | | of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" |
58 | | must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK |
59 | | AAC Codec Library for Android." |
60 | | |
61 | | 3. NO PATENT LICENSE |
62 | | |
63 | | NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without |
64 | | limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. |
65 | | Fraunhofer provides no warranty of patent non-infringement with respect to this |
66 | | software. |
67 | | |
68 | | You may use this FDK AAC Codec software or modifications thereto only for |
69 | | purposes that are authorized by appropriate patent licenses. |
70 | | |
71 | | 4. DISCLAIMER |
72 | | |
73 | | This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright |
74 | | holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, |
75 | | including but not limited to the implied warranties of merchantability and |
76 | | fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
77 | | CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, |
78 | | or consequential damages, including but not limited to procurement of substitute |
79 | | goods or services; loss of use, data, or profits, or business interruption, |
80 | | however caused and on any theory of liability, whether in contract, strict |
81 | | liability, or tort (including negligence), arising in any way out of the use of |
82 | | this software, even if advised of the possibility of such damage. |
83 | | |
84 | | 5. CONTACT INFORMATION |
85 | | |
86 | | Fraunhofer Institute for Integrated Circuits IIS |
87 | | Attention: Audio and Multimedia Departments - FDK AAC LL |
88 | | Am Wolfsmantel 33 |
89 | | 91058 Erlangen, Germany |
90 | | |
91 | | www.iis.fraunhofer.de/amm |
92 | | amm-info@iis.fraunhofer.de |
93 | | ----------------------------------------------------------------------------- */ |
94 | | |
95 | | /******************* Library for basic calculation routines ******************** |
96 | | |
97 | | Author(s): Markus Lohwasser, Josef Hoepfl, Manuel Jander |
98 | | |
99 | | Description: QMF filterbank |
100 | | |
101 | | *******************************************************************************/ |
102 | | |
103 | | /*! |
104 | | \file |
105 | | \brief Complex qmf analysis/synthesis |
106 | | This module contains the qmf filterbank for analysis [ |
107 | | cplxAnalysisQmfFiltering() ] and synthesis [ cplxSynthesisQmfFiltering() ]. It |
108 | | is a polyphase implementation of a complex exponential modulated filter bank. |
109 | | The analysis part usually runs at half the sample rate than the synthesis |
110 | | part. (So called "dual-rate" mode.) |
111 | | |
112 | | The coefficients of the prototype filter are specified in #qmf_pfilt640 (in |
113 | | sbr_rom.cpp). Thus only a 64 channel version (32 on the analysis side) with a |
114 | | 640 tap prototype filter are used. |
115 | | |
116 | | \anchor PolyphaseFiltering <h2>About polyphase filtering</h2> |
117 | | The polyphase implementation of a filterbank requires filtering at the input |
118 | | and output. This is implemented as part of cplxAnalysisQmfFiltering() and |
119 | | cplxSynthesisQmfFiltering(). The implementation requires the filter |
120 | | coefficients in a specific structure as described in #sbr_qmf_64_640_qmf (in |
121 | | sbr_rom.cpp). |
122 | | |
123 | | This module comprises the computationally most expensive functions of the SBR |
124 | | decoder. The accuracy of computations is also important and has a direct |
125 | | impact on the overall sound quality. Therefore a special test program is |
126 | | available which can be used to only test the filterbank: main_audio.cpp |
127 | | |
128 | | This modules also uses scaling of data to provide better SNR on fixed-point |
129 | | processors. See #QMF_SCALE_FACTOR (in sbr_scale.h) for details. An interesting |
130 | | note: The function getScalefactor() can constitute a significant amount of |
131 | | computational complexity - very much depending on the bitrate. Since it is a |
132 | | rather small function, effective assembler optimization might be possible. |
133 | | |
134 | | */ |
135 | | |
136 | | #include "qmf.h" |
137 | | |
138 | | #include "FDK_trigFcts.h" |
139 | | #include "fixpoint_math.h" |
140 | | #include "dct.h" |
141 | | |
142 | | #define QSSCALE (0) |
143 | | #define FX_DBL2FX_QSS(x) (x) |
144 | | #define FX_QSS2FX_DBL(x) (x) |
145 | | |
146 | | /* moved to qmf_pcm.h: -> qmfSynPrototypeFirSlot */ |
147 | | /* moved to qmf_pcm.h: -> qmfSynPrototypeFirSlot_NonSymmetric */ |
148 | | /* moved to qmf_pcm.h: -> qmfSynthesisFilteringSlot */ |
149 | | |
150 | | /*! |
151 | | * |
152 | | * \brief Perform real-valued forward modulation of the time domain |
153 | | * data of timeIn and stores the real part of the subband |
154 | | * samples in rSubband |
155 | | * |
156 | | */ |
157 | | static void qmfForwardModulationLP_even( |
158 | | HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ |
159 | | FIXP_DBL *timeIn, /*!< Time Signal */ |
160 | | FIXP_DBL *rSubband) /*!< Real Output */ |
161 | 0 | { |
162 | 0 | int i; |
163 | 0 | int L = anaQmf->no_channels; |
164 | 0 | int M = L >> 1; |
165 | 0 | int scale = 0; |
166 | 0 | FIXP_DBL accu; |
167 | |
|
168 | 0 | const FIXP_DBL *timeInTmp1 = (FIXP_DBL *)&timeIn[3 * M]; |
169 | 0 | const FIXP_DBL *timeInTmp2 = timeInTmp1; |
170 | 0 | FIXP_DBL *rSubbandTmp = rSubband; |
171 | |
|
172 | 0 | rSubband[0] = timeIn[3 * M] >> 1; |
173 | |
|
174 | 0 | for (i = M - 1; i != 0; i--) { |
175 | 0 | accu = ((*--timeInTmp1) >> 1) + ((*++timeInTmp2) >> 1); |
176 | 0 | *++rSubbandTmp = accu; |
177 | 0 | } |
178 | |
|
179 | 0 | timeInTmp1 = &timeIn[2 * M]; |
180 | 0 | timeInTmp2 = &timeIn[0]; |
181 | 0 | rSubbandTmp = &rSubband[M]; |
182 | |
|
183 | 0 | for (i = L - M; i != 0; i--) { |
184 | 0 | accu = ((*timeInTmp1--) >> 1) - ((*timeInTmp2++) >> 1); |
185 | 0 | *rSubbandTmp++ = accu; |
186 | 0 | } |
187 | |
|
188 | 0 | dct_III(rSubband, timeIn, L, &scale); |
189 | 0 | } |
190 | | |
191 | | #if !defined(FUNCTION_qmfForwardModulationLP_odd) |
192 | | static void qmfForwardModulationLP_odd( |
193 | | HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ |
194 | | const FIXP_DBL *timeIn, /*!< Time Signal */ |
195 | | FIXP_DBL *rSubband) /*!< Real Output */ |
196 | 0 | { |
197 | 0 | int i; |
198 | 0 | int L = anaQmf->no_channels; |
199 | 0 | int M = L >> 1; |
200 | 0 | int shift = (anaQmf->no_channels >> 6) + 1; |
201 | |
|
202 | 0 | for (i = 0; i < M; i++) { |
203 | 0 | rSubband[M + i] = (timeIn[L - 1 - i] >> 1) - (timeIn[i] >> shift); |
204 | 0 | rSubband[M - 1 - i] = |
205 | 0 | (timeIn[L + i] >> 1) + (timeIn[2 * L - 1 - i] >> shift); |
206 | 0 | } |
207 | |
|
208 | 0 | dct_IV(rSubband, L, &shift); |
209 | 0 | } |
210 | | #endif /* !defined(FUNCTION_qmfForwardModulationLP_odd) */ |
211 | | |
212 | | /*! |
213 | | * |
214 | | * \brief Perform complex-valued forward modulation of the time domain |
215 | | * data of timeIn and stores the real part of the subband |
216 | | * samples in rSubband, and the imaginary part in iSubband |
217 | | * |
218 | | * |
219 | | */ |
220 | | #if !defined(FUNCTION_qmfForwardModulationHQ) |
221 | | static void qmfForwardModulationHQ( |
222 | | HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ |
223 | | const FIXP_DBL *RESTRICT timeIn, /*!< Time Signal */ |
224 | | FIXP_DBL *RESTRICT rSubband, /*!< Real Output */ |
225 | | FIXP_DBL *RESTRICT iSubband /*!< Imaginary Output */ |
226 | 0 | ) { |
227 | 0 | int i; |
228 | 0 | int L = anaQmf->no_channels; |
229 | 0 | int L2 = L << 1; |
230 | 0 | int shift = 0; |
231 | | |
232 | | /* Time advance by one sample, which is equivalent to the complex |
233 | | rotation at the end of the analysis. Works only for STD mode. */ |
234 | 0 | if ((L == 64) && !(anaQmf->flags & (QMF_FLAG_CLDFB | QMF_FLAG_MPSLDFB))) { |
235 | 0 | FIXP_DBL x, y; |
236 | | |
237 | | /*rSubband[0] = u[1] + u[0]*/ |
238 | | /*iSubband[0] = u[1] - u[0]*/ |
239 | 0 | x = timeIn[1] >> 1; |
240 | 0 | y = timeIn[0]; |
241 | 0 | rSubband[0] = x + (y >> 1); |
242 | 0 | iSubband[0] = x - (y >> 1); |
243 | | |
244 | | /*rSubband[n] = u[n+1] - u[2M-n], n=1,...,M-1*/ |
245 | | /*iSubband[n] = u[n+1] + u[2M-n], n=1,...,M-1*/ |
246 | 0 | for (i = 1; i < L; i++) { |
247 | 0 | x = timeIn[i + 1] >> 1; /*u[n+1] */ |
248 | 0 | y = timeIn[L2 - i]; /*u[2M-n] */ |
249 | 0 | rSubband[i] = x - (y >> 1); |
250 | 0 | iSubband[i] = x + (y >> 1); |
251 | 0 | } |
252 | 0 | } else { |
253 | 0 | for (i = 0; i < L; i += 2) { |
254 | 0 | FIXP_DBL x0, x1, y0, y1; |
255 | |
|
256 | 0 | x0 = timeIn[i + 0] >> 1; |
257 | 0 | x1 = timeIn[i + 1] >> 1; |
258 | 0 | y0 = timeIn[L2 - 1 - i]; |
259 | 0 | y1 = timeIn[L2 - 2 - i]; |
260 | |
|
261 | 0 | rSubband[i + 0] = x0 - (y0 >> 1); |
262 | 0 | rSubband[i + 1] = x1 - (y1 >> 1); |
263 | 0 | iSubband[i + 0] = x0 + (y0 >> 1); |
264 | 0 | iSubband[i + 1] = x1 + (y1 >> 1); |
265 | 0 | } |
266 | 0 | } |
267 | |
|
268 | 0 | dct_IV(rSubband, L, &shift); |
269 | 0 | dst_IV(iSubband, L, &shift); |
270 | | |
271 | | /* Do the complex rotation except for the case of 64 bands (in STD mode). */ |
272 | 0 | if ((L != 64) || (anaQmf->flags & (QMF_FLAG_CLDFB | QMF_FLAG_MPSLDFB))) { |
273 | 0 | if (anaQmf->flags & QMF_FLAG_MPSLDFB_OPTIMIZE_MODULATION) { |
274 | 0 | FIXP_DBL iBand; |
275 | 0 | for (i = 0; i < fMin(anaQmf->lsb, L); i += 2) { |
276 | 0 | iBand = rSubband[i]; |
277 | 0 | rSubband[i] = -iSubband[i]; |
278 | 0 | iSubband[i] = iBand; |
279 | |
|
280 | 0 | iBand = -rSubband[i + 1]; |
281 | 0 | rSubband[i + 1] = iSubband[i + 1]; |
282 | 0 | iSubband[i + 1] = iBand; |
283 | 0 | } |
284 | 0 | } else { |
285 | 0 | const FIXP_QTW *sbr_t_cos; |
286 | 0 | const FIXP_QTW *sbr_t_sin; |
287 | 0 | const int len = L; /* was len = fMin(anaQmf->lsb, L) but in case of USAC |
288 | | the signal above lsb is actually needed in some |
289 | | cases (HBE?) */ |
290 | 0 | sbr_t_cos = anaQmf->t_cos; |
291 | 0 | sbr_t_sin = anaQmf->t_sin; |
292 | |
|
293 | 0 | for (i = 0; i < len; i++) { |
294 | 0 | cplxMult(&iSubband[i], &rSubband[i], iSubband[i], rSubband[i], |
295 | 0 | sbr_t_cos[i], sbr_t_sin[i]); |
296 | 0 | } |
297 | 0 | } |
298 | 0 | } |
299 | 0 | } |
300 | | #endif /* FUNCTION_qmfForwardModulationHQ */ |
301 | | |
302 | | /*! |
303 | | * |
304 | | * \brief Perform low power inverse modulation of the subband |
305 | | * samples stored in rSubband (real part) and iSubband (imaginary |
306 | | * part) and stores the result in pWorkBuffer. |
307 | | * |
308 | | */ |
309 | | inline static void qmfInverseModulationLP_even( |
310 | | HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ |
311 | | const FIXP_DBL *qmfReal, /*!< Pointer to qmf real subband slot (input) */ |
312 | | const int scaleFactorLowBand, /*!< Scalefactor for Low band */ |
313 | | const int scaleFactorHighBand, /*!< Scalefactor for High band */ |
314 | | FIXP_DBL *pTimeOut /*!< Pointer to qmf subband slot (output)*/ |
315 | 0 | ) { |
316 | 0 | int i; |
317 | 0 | int L = synQmf->no_channels; |
318 | 0 | int M = L >> 1; |
319 | 0 | int scale = 0; |
320 | 0 | FIXP_DBL tmp; |
321 | 0 | FIXP_DBL *RESTRICT tReal = pTimeOut; |
322 | 0 | FIXP_DBL *RESTRICT tImag = pTimeOut + L; |
323 | | |
324 | | /* Move input to output vector with offset */ |
325 | 0 | scaleValuesSaturate(&tReal[0], &qmfReal[0], synQmf->lsb, scaleFactorLowBand); |
326 | 0 | scaleValuesSaturate(&tReal[0 + synQmf->lsb], &qmfReal[0 + synQmf->lsb], |
327 | 0 | synQmf->usb - synQmf->lsb, scaleFactorHighBand); |
328 | 0 | FDKmemclear(&tReal[0 + synQmf->usb], (L - synQmf->usb) * sizeof(FIXP_DBL)); |
329 | | |
330 | | /* Dct type-2 transform */ |
331 | 0 | dct_II(tReal, tImag, L, &scale); |
332 | | |
333 | | /* Expand output and replace inplace the output buffers */ |
334 | 0 | tImag[0] = tReal[M]; |
335 | 0 | tImag[M] = (FIXP_DBL)0; |
336 | 0 | tmp = tReal[0]; |
337 | 0 | tReal[0] = tReal[M]; |
338 | 0 | tReal[M] = tmp; |
339 | |
|
340 | 0 | for (i = 1; i < M / 2; i++) { |
341 | | /* Imag */ |
342 | 0 | tmp = tReal[L - i]; |
343 | 0 | tImag[M - i] = tmp; |
344 | 0 | tImag[i + M] = -tmp; |
345 | |
|
346 | 0 | tmp = tReal[M + i]; |
347 | 0 | tImag[i] = tmp; |
348 | 0 | tImag[L - i] = -tmp; |
349 | | |
350 | | /* Real */ |
351 | 0 | tReal[M + i] = tReal[i]; |
352 | 0 | tReal[L - i] = tReal[M - i]; |
353 | 0 | tmp = tReal[i]; |
354 | 0 | tReal[i] = tReal[M - i]; |
355 | 0 | tReal[M - i] = tmp; |
356 | 0 | } |
357 | | /* Remaining odd terms */ |
358 | 0 | tmp = tReal[M + M / 2]; |
359 | 0 | tImag[M / 2] = tmp; |
360 | 0 | tImag[M / 2 + M] = -tmp; |
361 | |
|
362 | 0 | tReal[M + M / 2] = tReal[M / 2]; |
363 | 0 | } |
364 | | |
365 | | inline static void qmfInverseModulationLP_odd( |
366 | | HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ |
367 | | const FIXP_DBL *qmfReal, /*!< Pointer to qmf real subband slot (input) */ |
368 | | const int scaleFactorLowBand, /*!< Scalefactor for Low band */ |
369 | | const int scaleFactorHighBand, /*!< Scalefactor for High band */ |
370 | | FIXP_DBL *pTimeOut /*!< Pointer to qmf subband slot (output)*/ |
371 | 0 | ) { |
372 | 0 | int i; |
373 | 0 | int L = synQmf->no_channels; |
374 | 0 | int M = L >> 1; |
375 | 0 | int shift = 0; |
376 | | |
377 | | /* Move input to output vector with offset */ |
378 | 0 | scaleValuesSaturate(pTimeOut + M, qmfReal, synQmf->lsb, scaleFactorLowBand); |
379 | 0 | scaleValuesSaturate(pTimeOut + M + synQmf->lsb, qmfReal + synQmf->lsb, |
380 | 0 | synQmf->usb - synQmf->lsb, scaleFactorHighBand); |
381 | 0 | FDKmemclear(pTimeOut + M + synQmf->usb, (L - synQmf->usb) * sizeof(FIXP_DBL)); |
382 | |
|
383 | 0 | dct_IV(pTimeOut + M, L, &shift); |
384 | 0 | for (i = 0; i < M; i++) { |
385 | 0 | pTimeOut[i] = pTimeOut[L - 1 - i]; |
386 | 0 | pTimeOut[2 * L - 1 - i] = -pTimeOut[L + i]; |
387 | 0 | } |
388 | 0 | } |
389 | | |
390 | | #ifndef FUNCTION_qmfInverseModulationHQ |
391 | | /*! |
392 | | * |
393 | | * \brief Perform complex-valued inverse modulation of the subband |
394 | | * samples stored in rSubband (real part) and iSubband (imaginary |
395 | | * part) and stores the result in pWorkBuffer. |
396 | | * |
397 | | */ |
398 | | inline static void qmfInverseModulationHQ( |
399 | | HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ |
400 | | const FIXP_DBL *qmfReal, /*!< Pointer to qmf real subband slot */ |
401 | | const FIXP_DBL *qmfImag, /*!< Pointer to qmf imag subband slot */ |
402 | | const int scaleFactorLowBand, /*!< Scalefactor for Low band */ |
403 | | const int scaleFactorHighBand, /*!< Scalefactor for High band */ |
404 | | FIXP_DBL *pWorkBuffer /*!< WorkBuffer (output) */ |
405 | 0 | ) { |
406 | 0 | int i; |
407 | 0 | int L = synQmf->no_channels; |
408 | 0 | int M = L >> 1; |
409 | 0 | int shift = 0; |
410 | 0 | FIXP_DBL *RESTRICT tReal = pWorkBuffer; |
411 | 0 | FIXP_DBL *RESTRICT tImag = pWorkBuffer + L; |
412 | |
|
413 | 0 | if (synQmf->flags & QMF_FLAG_CLDFB) { |
414 | 0 | for (i = 0; i < synQmf->usb; i++) { |
415 | 0 | cplxMultDiv2(&tImag[i], &tReal[i], qmfImag[i], qmfReal[i], |
416 | 0 | synQmf->t_cos[i], synQmf->t_sin[i]); |
417 | 0 | } |
418 | 0 | scaleValuesSaturate(&tReal[0], synQmf->lsb, scaleFactorLowBand + 1); |
419 | 0 | scaleValuesSaturate(&tReal[0 + synQmf->lsb], synQmf->usb - synQmf->lsb, |
420 | 0 | scaleFactorHighBand + 1); |
421 | 0 | scaleValuesSaturate(&tImag[0], synQmf->lsb, scaleFactorLowBand + 1); |
422 | 0 | scaleValuesSaturate(&tImag[0 + synQmf->lsb], synQmf->usb - synQmf->lsb, |
423 | 0 | scaleFactorHighBand + 1); |
424 | 0 | } |
425 | |
|
426 | 0 | if ((synQmf->flags & QMF_FLAG_CLDFB) == 0) { |
427 | 0 | scaleValuesSaturate(&tReal[0], &qmfReal[0], synQmf->lsb, |
428 | 0 | scaleFactorLowBand); |
429 | 0 | scaleValuesSaturate(&tReal[0 + synQmf->lsb], &qmfReal[0 + synQmf->lsb], |
430 | 0 | synQmf->usb - synQmf->lsb, scaleFactorHighBand); |
431 | 0 | scaleValuesSaturate(&tImag[0], &qmfImag[0], synQmf->lsb, |
432 | 0 | scaleFactorLowBand); |
433 | 0 | scaleValuesSaturate(&tImag[0 + synQmf->lsb], &qmfImag[0 + synQmf->lsb], |
434 | 0 | synQmf->usb - synQmf->lsb, scaleFactorHighBand); |
435 | 0 | } |
436 | |
|
437 | 0 | FDKmemclear(&tReal[synQmf->usb], |
438 | 0 | (synQmf->no_channels - synQmf->usb) * sizeof(FIXP_DBL)); |
439 | 0 | FDKmemclear(&tImag[synQmf->usb], |
440 | 0 | (synQmf->no_channels - synQmf->usb) * sizeof(FIXP_DBL)); |
441 | |
|
442 | 0 | dct_IV(tReal, L, &shift); |
443 | 0 | dst_IV(tImag, L, &shift); |
444 | |
|
445 | 0 | if (synQmf->flags & QMF_FLAG_CLDFB) { |
446 | 0 | for (i = 0; i < M; i++) { |
447 | 0 | FIXP_DBL r1, i1, r2, i2; |
448 | 0 | r1 = tReal[i]; |
449 | 0 | i2 = tImag[L - 1 - i]; |
450 | 0 | r2 = tReal[L - i - 1]; |
451 | 0 | i1 = tImag[i]; |
452 | |
|
453 | 0 | tReal[i] = (r1 - i1) >> 1; |
454 | 0 | tImag[L - 1 - i] = -(r1 + i1) >> 1; |
455 | 0 | tReal[L - i - 1] = (r2 - i2) >> 1; |
456 | 0 | tImag[i] = -(r2 + i2) >> 1; |
457 | 0 | } |
458 | 0 | } else { |
459 | | /* The array accesses are negative to compensate the missing minus sign in |
460 | | * the low and hi band gain. */ |
461 | | /* 26 cycles on ARM926 */ |
462 | 0 | for (i = 0; i < M; i++) { |
463 | 0 | FIXP_DBL r1, i1, r2, i2; |
464 | 0 | r1 = -tReal[i]; |
465 | 0 | i2 = -tImag[L - 1 - i]; |
466 | 0 | r2 = -tReal[L - i - 1]; |
467 | 0 | i1 = -tImag[i]; |
468 | |
|
469 | 0 | tReal[i] = (r1 - i1) >> 1; |
470 | 0 | tImag[L - 1 - i] = -(r1 + i1) >> 1; |
471 | 0 | tReal[L - i - 1] = (r2 - i2) >> 1; |
472 | 0 | tImag[i] = -(r2 + i2) >> 1; |
473 | 0 | } |
474 | 0 | } |
475 | 0 | } |
476 | | #endif /* #ifndef FUNCTION_qmfInverseModulationHQ */ |
477 | | |
478 | | /*! |
479 | | * |
480 | | * \brief Create QMF filter bank instance |
481 | | * |
482 | | * \return 0 if successful |
483 | | * |
484 | | */ |
485 | | static int qmfInitFilterBank( |
486 | | HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Handle to return */ |
487 | | void *pFilterStates, /*!< Handle to filter states */ |
488 | | int noCols, /*!< Number of timeslots per frame */ |
489 | | int lsb, /*!< Lower end of QMF frequency range */ |
490 | | int usb, /*!< Upper end of QMF frequency range */ |
491 | | int no_channels, /*!< Number of channels (bands) */ |
492 | | UINT flags, /*!< flags */ |
493 | | int synflag) /*!< 1: synthesis; 0: analysis */ |
494 | 0 | { |
495 | 0 | FDKmemclear(h_Qmf, sizeof(QMF_FILTER_BANK)); |
496 | |
|
497 | 0 | if (flags & QMF_FLAG_MPSLDFB) { |
498 | 0 | flags |= QMF_FLAG_NONSYMMETRIC; |
499 | 0 | flags |= QMF_FLAG_MPSLDFB_OPTIMIZE_MODULATION; |
500 | |
|
501 | 0 | h_Qmf->t_cos = NULL; |
502 | 0 | h_Qmf->t_sin = NULL; |
503 | 0 | h_Qmf->filterScale = QMF_MPSLDFB_PFT_SCALE; |
504 | 0 | h_Qmf->p_stride = 1; |
505 | |
|
506 | 0 | switch (no_channels) { |
507 | 0 | case 64: |
508 | 0 | h_Qmf->p_filter = qmf_mpsldfb_640; |
509 | 0 | h_Qmf->FilterSize = 640; |
510 | 0 | break; |
511 | 0 | case 32: |
512 | 0 | h_Qmf->p_filter = qmf_mpsldfb_320; |
513 | 0 | h_Qmf->FilterSize = 320; |
514 | 0 | break; |
515 | 0 | default: |
516 | 0 | return -1; |
517 | 0 | } |
518 | 0 | } |
519 | | |
520 | 0 | if (!(flags & QMF_FLAG_MPSLDFB) && (flags & QMF_FLAG_CLDFB)) { |
521 | 0 | flags |= QMF_FLAG_NONSYMMETRIC; |
522 | 0 | h_Qmf->filterScale = QMF_CLDFB_PFT_SCALE; |
523 | |
|
524 | 0 | h_Qmf->p_stride = 1; |
525 | 0 | switch (no_channels) { |
526 | 0 | case 64: |
527 | 0 | h_Qmf->t_cos = qmf_phaseshift_cos64_cldfb; |
528 | 0 | h_Qmf->t_sin = qmf_phaseshift_sin64_cldfb; |
529 | 0 | h_Qmf->p_filter = qmf_cldfb_640; |
530 | 0 | h_Qmf->FilterSize = 640; |
531 | 0 | break; |
532 | 0 | case 32: |
533 | 0 | h_Qmf->t_cos = (synflag) ? qmf_phaseshift_cos32_cldfb_syn |
534 | 0 | : qmf_phaseshift_cos32_cldfb_ana; |
535 | 0 | h_Qmf->t_sin = qmf_phaseshift_sin32_cldfb; |
536 | 0 | h_Qmf->p_filter = qmf_cldfb_320; |
537 | 0 | h_Qmf->FilterSize = 320; |
538 | 0 | break; |
539 | 0 | case 16: |
540 | 0 | h_Qmf->t_cos = (synflag) ? qmf_phaseshift_cos16_cldfb_syn |
541 | 0 | : qmf_phaseshift_cos16_cldfb_ana; |
542 | 0 | h_Qmf->t_sin = qmf_phaseshift_sin16_cldfb; |
543 | 0 | h_Qmf->p_filter = qmf_cldfb_160; |
544 | 0 | h_Qmf->FilterSize = 160; |
545 | 0 | break; |
546 | 0 | case 8: |
547 | 0 | h_Qmf->t_cos = (synflag) ? qmf_phaseshift_cos8_cldfb_syn |
548 | 0 | : qmf_phaseshift_cos8_cldfb_ana; |
549 | 0 | h_Qmf->t_sin = qmf_phaseshift_sin8_cldfb; |
550 | 0 | h_Qmf->p_filter = qmf_cldfb_80; |
551 | 0 | h_Qmf->FilterSize = 80; |
552 | 0 | break; |
553 | 0 | default: |
554 | 0 | return -1; |
555 | 0 | } |
556 | 0 | } |
557 | | |
558 | 0 | if (!(flags & QMF_FLAG_MPSLDFB) && ((flags & QMF_FLAG_CLDFB) == 0)) { |
559 | 0 | switch (no_channels) { |
560 | 0 | case 64: |
561 | 0 | h_Qmf->p_filter = qmf_pfilt640; |
562 | 0 | h_Qmf->t_cos = qmf_phaseshift_cos64; |
563 | 0 | h_Qmf->t_sin = qmf_phaseshift_sin64; |
564 | 0 | h_Qmf->p_stride = 1; |
565 | 0 | h_Qmf->FilterSize = 640; |
566 | 0 | h_Qmf->filterScale = 0; |
567 | 0 | break; |
568 | 0 | case 40: |
569 | 0 | if (synflag) { |
570 | 0 | break; |
571 | 0 | } else { |
572 | 0 | h_Qmf->p_filter = qmf_pfilt400; /* Scaling factor 0.8 */ |
573 | 0 | h_Qmf->t_cos = qmf_phaseshift_cos40; |
574 | 0 | h_Qmf->t_sin = qmf_phaseshift_sin40; |
575 | 0 | h_Qmf->filterScale = 1; |
576 | 0 | h_Qmf->p_stride = 1; |
577 | 0 | h_Qmf->FilterSize = no_channels * 10; |
578 | 0 | } |
579 | 0 | break; |
580 | 0 | case 32: |
581 | 0 | h_Qmf->p_filter = qmf_pfilt640; |
582 | 0 | if (flags & QMF_FLAG_DOWNSAMPLED) { |
583 | 0 | h_Qmf->t_cos = qmf_phaseshift_cos_downsamp32; |
584 | 0 | h_Qmf->t_sin = qmf_phaseshift_sin_downsamp32; |
585 | 0 | } else { |
586 | 0 | h_Qmf->t_cos = qmf_phaseshift_cos32; |
587 | 0 | h_Qmf->t_sin = qmf_phaseshift_sin32; |
588 | 0 | } |
589 | 0 | h_Qmf->p_stride = 2; |
590 | 0 | h_Qmf->FilterSize = 640; |
591 | 0 | h_Qmf->filterScale = 0; |
592 | 0 | break; |
593 | 0 | case 20: |
594 | 0 | h_Qmf->p_filter = qmf_pfilt200; |
595 | 0 | h_Qmf->p_stride = 1; |
596 | 0 | h_Qmf->FilterSize = 200; |
597 | 0 | h_Qmf->filterScale = 0; |
598 | 0 | break; |
599 | 0 | case 12: |
600 | 0 | h_Qmf->p_filter = qmf_pfilt120; |
601 | 0 | h_Qmf->p_stride = 1; |
602 | 0 | h_Qmf->FilterSize = 120; |
603 | 0 | h_Qmf->filterScale = 0; |
604 | 0 | break; |
605 | 0 | case 8: |
606 | 0 | h_Qmf->p_filter = qmf_pfilt640; |
607 | 0 | h_Qmf->p_stride = 8; |
608 | 0 | h_Qmf->FilterSize = 640; |
609 | 0 | h_Qmf->filterScale = 0; |
610 | 0 | break; |
611 | 0 | case 16: |
612 | 0 | h_Qmf->p_filter = qmf_pfilt640; |
613 | 0 | h_Qmf->t_cos = qmf_phaseshift_cos16; |
614 | 0 | h_Qmf->t_sin = qmf_phaseshift_sin16; |
615 | 0 | h_Qmf->p_stride = 4; |
616 | 0 | h_Qmf->FilterSize = 640; |
617 | 0 | h_Qmf->filterScale = 0; |
618 | 0 | break; |
619 | 0 | case 24: |
620 | 0 | h_Qmf->p_filter = qmf_pfilt240; |
621 | 0 | h_Qmf->t_cos = qmf_phaseshift_cos24; |
622 | 0 | h_Qmf->t_sin = qmf_phaseshift_sin24; |
623 | 0 | h_Qmf->p_stride = 1; |
624 | 0 | h_Qmf->FilterSize = 240; |
625 | 0 | h_Qmf->filterScale = 1; |
626 | 0 | break; |
627 | 0 | default: |
628 | 0 | return -1; |
629 | 0 | } |
630 | 0 | } |
631 | | |
632 | 0 | h_Qmf->synScalefactor = h_Qmf->filterScale; |
633 | | // DCT|DST dependency |
634 | 0 | switch (no_channels) { |
635 | 0 | case 128: |
636 | 0 | h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + 1; |
637 | 0 | break; |
638 | 0 | case 40: { |
639 | 0 | h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 1; |
640 | 0 | } break; |
641 | 0 | case 64: |
642 | 0 | h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK; |
643 | 0 | break; |
644 | 0 | case 8: |
645 | 0 | h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 3; |
646 | 0 | break; |
647 | 0 | case 12: |
648 | 0 | h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK; |
649 | 0 | break; |
650 | 0 | case 20: |
651 | 0 | h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + 1; |
652 | 0 | break; |
653 | 0 | case 32: |
654 | 0 | h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 1; |
655 | 0 | break; |
656 | 0 | case 16: |
657 | 0 | h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 2; |
658 | 0 | break; |
659 | 0 | case 24: |
660 | 0 | h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 1; |
661 | 0 | break; |
662 | 0 | default: |
663 | 0 | return -1; |
664 | 0 | } |
665 | | |
666 | 0 | h_Qmf->flags = flags; |
667 | |
|
668 | 0 | h_Qmf->no_channels = no_channels; |
669 | 0 | h_Qmf->no_col = noCols; |
670 | |
|
671 | 0 | h_Qmf->lsb = fMin(lsb, h_Qmf->no_channels); |
672 | 0 | h_Qmf->usb = synflag |
673 | 0 | ? fMin(usb, h_Qmf->no_channels) |
674 | 0 | : usb; /* was: h_Qmf->usb = fMin(usb, h_Qmf->no_channels); */ |
675 | |
|
676 | 0 | h_Qmf->FilterStates = (void *)pFilterStates; |
677 | |
|
678 | 0 | h_Qmf->outScalefactor = |
679 | 0 | (ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + h_Qmf->filterScale) + |
680 | 0 | h_Qmf->synScalefactor; |
681 | |
|
682 | 0 | h_Qmf->outGain_m = |
683 | 0 | (FIXP_DBL)0x80000000; /* default init value will be not applied */ |
684 | 0 | h_Qmf->outGain_e = 0; |
685 | |
|
686 | 0 | return (0); |
687 | 0 | } |
688 | | |
689 | | /*! |
690 | | * |
691 | | * \brief Adjust synthesis qmf filter states |
692 | | * |
693 | | * \return void |
694 | | * |
695 | | */ |
696 | | static inline void qmfAdaptFilterStates( |
697 | | HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Filter Bank */ |
698 | | int scaleFactorDiff) /*!< Scale factor difference to be applied */ |
699 | 0 | { |
700 | 0 | if (synQmf == NULL || synQmf->FilterStates == NULL) { |
701 | 0 | return; |
702 | 0 | } |
703 | 0 | if (scaleFactorDiff > 0) { |
704 | 0 | scaleValuesSaturate((FIXP_QSS *)synQmf->FilterStates, |
705 | 0 | synQmf->no_channels * (QMF_NO_POLY * 2 - 1), |
706 | 0 | scaleFactorDiff); |
707 | 0 | } else { |
708 | 0 | scaleValues((FIXP_QSS *)synQmf->FilterStates, |
709 | 0 | synQmf->no_channels * (QMF_NO_POLY * 2 - 1), scaleFactorDiff); |
710 | 0 | } |
711 | 0 | } |
712 | | |
713 | | /*! |
714 | | * |
715 | | * \brief Create QMF filter bank instance |
716 | | * |
717 | | * |
718 | | * \return 0 if succesful |
719 | | * |
720 | | */ |
721 | | int qmfInitSynthesisFilterBank( |
722 | | HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */ |
723 | | FIXP_QSS *pFilterStates, /*!< Handle to filter states */ |
724 | | int noCols, /*!< Number of timeslots per frame */ |
725 | | int lsb, /*!< lower end of QMF */ |
726 | | int usb, /*!< upper end of QMF */ |
727 | | int no_channels, /*!< Number of channels (bands) */ |
728 | | int flags) /*!< Low Power flag */ |
729 | 0 | { |
730 | 0 | int oldOutScale = h_Qmf->outScalefactor; |
731 | 0 | int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, |
732 | 0 | no_channels, flags, 1); |
733 | 0 | if (h_Qmf->FilterStates != NULL) { |
734 | 0 | if (!(flags & QMF_FLAG_KEEP_STATES)) { |
735 | 0 | FDKmemclear( |
736 | 0 | h_Qmf->FilterStates, |
737 | 0 | (2 * QMF_NO_POLY - 1) * h_Qmf->no_channels * sizeof(FIXP_QSS)); |
738 | 0 | } else { |
739 | 0 | qmfAdaptFilterStates(h_Qmf, oldOutScale - h_Qmf->outScalefactor); |
740 | 0 | } |
741 | 0 | } |
742 | |
|
743 | 0 | FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->lsb); |
744 | 0 | FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->usb); |
745 | | |
746 | 0 | return err; |
747 | 0 | } |
748 | | |
749 | | /*! |
750 | | * |
751 | | * \brief Change scale factor for output data and adjust qmf filter states |
752 | | * |
753 | | * \return void |
754 | | * |
755 | | */ |
756 | | void qmfChangeOutScalefactor( |
757 | | HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ |
758 | | int outScalefactor /*!< New scaling factor for output data */ |
759 | 0 | ) { |
760 | 0 | if (synQmf == NULL) { |
761 | 0 | return; |
762 | 0 | } |
763 | | |
764 | | /* Add internal filterbank scale */ |
765 | 0 | outScalefactor += |
766 | 0 | (ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + synQmf->filterScale) + |
767 | 0 | synQmf->synScalefactor; |
768 | | |
769 | | /* adjust filter states when scale factor has been changed */ |
770 | 0 | if (synQmf->outScalefactor != outScalefactor) { |
771 | 0 | int diff; |
772 | |
|
773 | 0 | diff = synQmf->outScalefactor - outScalefactor; |
774 | |
|
775 | 0 | qmfAdaptFilterStates(synQmf, diff); |
776 | | |
777 | | /* save new scale factor */ |
778 | 0 | synQmf->outScalefactor = outScalefactor; |
779 | 0 | } |
780 | 0 | } |
781 | | |
782 | | /*! |
783 | | * |
784 | | * \brief Get scale factor change which was set by qmfChangeOutScalefactor() |
785 | | * |
786 | | * \return scaleFactor |
787 | | * |
788 | | */ |
789 | | int qmfGetOutScalefactor( |
790 | | HANDLE_QMF_FILTER_BANK synQmf) /*!< Handle of Qmf Synthesis Bank */ |
791 | 0 | { |
792 | 0 | int scaleFactor = synQmf->outScalefactor |
793 | 0 | ? (synQmf->outScalefactor - |
794 | 0 | (ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + |
795 | 0 | synQmf->filterScale + synQmf->synScalefactor)) |
796 | 0 | : 0; |
797 | 0 | return scaleFactor; |
798 | 0 | } |
799 | | |
800 | | /*! |
801 | | * |
802 | | * \brief Change gain for output data |
803 | | * |
804 | | * \return void |
805 | | * |
806 | | */ |
807 | | void qmfChangeOutGain( |
808 | | HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ |
809 | | FIXP_DBL outputGain, /*!< New gain for output data (mantissa) */ |
810 | | int outputGainScale /*!< New gain for output data (exponent) */ |
811 | 0 | ) { |
812 | 0 | synQmf->outGain_m = outputGain; |
813 | 0 | synQmf->outGain_e = outputGainScale; |
814 | 0 | } |
815 | | |
816 | 0 | #define INT_PCM_QMFOUT INT_PCM |
817 | 0 | #define SAMPLE_BITS_QMFOUT SAMPLE_BITS |
818 | | #include "qmf_pcm.h" |
819 | | #if SAMPLE_BITS == 16 |
820 | | /* also create a 32 bit output version */ |
821 | | #undef INT_PCM_QMFOUT |
822 | | #undef SAMPLE_BITS_QMFOUT |
823 | | #undef QMF_PCM_H |
824 | | #undef FIXP_QAS |
825 | | #undef QAS_BITS |
826 | | #undef INT_PCM_QMFIN |
827 | 0 | #define INT_PCM_QMFOUT LONG |
828 | 0 | #define SAMPLE_BITS_QMFOUT 32 |
829 | 0 | #define FIXP_QAS FIXP_DBL |
830 | | #define QAS_BITS 32 |
831 | | #define INT_PCM_QMFIN LONG |
832 | | #include "qmf_pcm.h" |
833 | | #endif |