/src/fdk-aac/libFDK/include/qmf_pcm.h
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 | | #ifndef QMF_PCM_H |
104 | | #define QMF_PCM_H |
105 | | |
106 | | /* |
107 | | All Synthesis functions dependent on datatype INT_PCM_QMFOUT |
108 | | Should only be included by qmf.cpp, but not compiled separately, please |
109 | | exclude compilation from project, if done otherwise. Is optional included |
110 | | twice to duplicate all functions with two different pre-definitions, as: |
111 | | #define INT_PCM_QMFOUT LONG |
112 | | and ... |
113 | | #define INT_PCM_QMFOUT SHORT |
114 | | needed to run QMF synthesis in both 16bit and 32bit sample output format. |
115 | | */ |
116 | | |
117 | | #define QSSCALE (0) |
118 | 0 | #define FX_DBL2FX_QSS(x) (x) |
119 | 0 | #define FX_QSS2FX_DBL(x) (x) |
120 | | |
121 | | /*! |
122 | | \brief Perform Synthesis Prototype Filtering on a single slot of input data. |
123 | | |
124 | | The filter takes 2 * qmf->no_channels of input data and |
125 | | generates qmf->no_channels time domain output samples. |
126 | | */ |
127 | | /* static */ |
128 | | #ifndef FUNCTION_qmfSynPrototypeFirSlot |
129 | | void qmfSynPrototypeFirSlot( |
130 | | #else |
131 | | void qmfSynPrototypeFirSlot_fallback( |
132 | | #endif |
133 | | HANDLE_QMF_FILTER_BANK qmf, |
134 | | FIXP_DBL *RESTRICT realSlot, /*!< Input: Pointer to real Slot */ |
135 | | FIXP_DBL *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */ |
136 | | INT_PCM_QMFOUT *RESTRICT timeOut, /*!< Time domain data */ |
137 | 0 | int stride) { |
138 | 0 | FIXP_QSS *FilterStates = (FIXP_QSS *)qmf->FilterStates; |
139 | 0 | int no_channels = qmf->no_channels; |
140 | 0 | const FIXP_PFT *p_Filter = qmf->p_filter; |
141 | 0 | int p_stride = qmf->p_stride; |
142 | 0 | int j; |
143 | 0 | FIXP_QSS *RESTRICT sta = FilterStates; |
144 | 0 | const FIXP_PFT *RESTRICT p_flt, *RESTRICT p_fltm; |
145 | 0 | int scale = (DFRACT_BITS - SAMPLE_BITS_QMFOUT) - 1 - qmf->outScalefactor - |
146 | 0 | qmf->outGain_e; |
147 | |
|
148 | 0 | p_flt = |
149 | 0 | p_Filter + p_stride * QMF_NO_POLY; /* 5th of 330 */ |
150 | 0 | p_fltm = p_Filter + (qmf->FilterSize / 2) - |
151 | 0 | p_stride * QMF_NO_POLY; /* 5 + (320 - 2*5) = 315th of 330 */ |
152 | |
|
153 | 0 | FIXP_SGL gain = FX_DBL2FX_SGL(qmf->outGain_m); |
154 | |
|
155 | 0 | FIXP_DBL rnd_val = 0; |
156 | |
|
157 | 0 | if (scale > 0) { |
158 | 0 | if (scale < (DFRACT_BITS - 1)) |
159 | 0 | rnd_val = FIXP_DBL(1 << (scale - 1)); |
160 | 0 | else |
161 | 0 | scale = (DFRACT_BITS - 1); |
162 | 0 | } else { |
163 | 0 | scale = fMax(scale, -(DFRACT_BITS - 1)); |
164 | 0 | } |
165 | |
|
166 | 0 | for (j = no_channels - 1; j >= 0; j--) { |
167 | 0 | FIXP_DBL imag = imagSlot[j]; /* no_channels-1 .. 0 */ |
168 | 0 | FIXP_DBL real = realSlot[j]; /* no_channels-1 .. 0 */ |
169 | 0 | { |
170 | 0 | INT_PCM_QMFOUT tmp; |
171 | 0 | FIXP_DBL Are = fMultAddDiv2(FX_QSS2FX_DBL(sta[0]), p_fltm[0], real); |
172 | | |
173 | | /* This PCM formatting performs: |
174 | | - multiplication with 16-bit gain, if not -1.0f |
175 | | - rounding, if shift right is applied |
176 | | - apply shift left (or right) with saturation to 32 (or 16) bits |
177 | | - store output with --stride in 32 (or 16) bit format |
178 | | */ |
179 | 0 | if (gain != (FIXP_SGL)(-32768)) /* -1.0f */ |
180 | 0 | { |
181 | 0 | Are = fMult(Are, gain); |
182 | 0 | } |
183 | 0 | if (scale >= 0) { |
184 | 0 | FDK_ASSERT( |
185 | 0 | Are <= |
186 | 0 | (Are + rnd_val)); /* Round-addition must not overflow, might be |
187 | | equal for rnd_val=0 */ |
188 | 0 | tmp = (INT_PCM_QMFOUT)( |
189 | 0 | SATURATE_RIGHT_SHIFT(Are + rnd_val, scale, SAMPLE_BITS_QMFOUT)); |
190 | 0 | } else { |
191 | 0 | tmp = (INT_PCM_QMFOUT)( |
192 | 0 | SATURATE_LEFT_SHIFT(Are, -scale, SAMPLE_BITS_QMFOUT)); |
193 | 0 | } |
194 | | |
195 | 0 | { timeOut[(j)*stride] = tmp; } |
196 | 0 | } |
197 | | |
198 | 0 | sta[0] = FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[1]), p_flt[4], imag)); |
199 | 0 | sta[1] = |
200 | 0 | FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[2]), p_fltm[1], real)); |
201 | 0 | sta[2] = FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[3]), p_flt[3], imag)); |
202 | 0 | sta[3] = |
203 | 0 | FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[4]), p_fltm[2], real)); |
204 | 0 | sta[4] = FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[5]), p_flt[2], imag)); |
205 | 0 | sta[5] = |
206 | 0 | FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[6]), p_fltm[3], real)); |
207 | 0 | sta[6] = FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[7]), p_flt[1], imag)); |
208 | 0 | sta[7] = |
209 | 0 | FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[8]), p_fltm[4], real)); |
210 | 0 | sta[8] = FX_DBL2FX_QSS(fMultDiv2(p_flt[0], imag)); |
211 | 0 | p_flt += (p_stride * QMF_NO_POLY); |
212 | 0 | p_fltm -= (p_stride * QMF_NO_POLY); |
213 | 0 | sta += 9; // = (2*QMF_NO_POLY-1); |
214 | 0 | } |
215 | 0 | } Unexecuted instantiation: qmfSynPrototypeFirSlot(QMF_FILTER_BANK*, int*, int*, short*, int) Unexecuted instantiation: qmfSynPrototypeFirSlot(QMF_FILTER_BANK*, int*, int*, int*, int) |
216 | | |
217 | | #ifndef FUNCTION_qmfSynPrototypeFirSlot_NonSymmetric |
218 | | /*! |
219 | | \brief Perform Synthesis Prototype Filtering on a single slot of input data. |
220 | | |
221 | | The filter takes 2 * qmf->no_channels of input data and |
222 | | generates qmf->no_channels time domain output samples. |
223 | | */ |
224 | | static void qmfSynPrototypeFirSlot_NonSymmetric( |
225 | | HANDLE_QMF_FILTER_BANK qmf, |
226 | | FIXP_DBL *RESTRICT realSlot, /*!< Input: Pointer to real Slot */ |
227 | | FIXP_DBL *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */ |
228 | | INT_PCM_QMFOUT *RESTRICT timeOut, /*!< Time domain data */ |
229 | 0 | int stride) { |
230 | 0 | FIXP_QSS *FilterStates = (FIXP_QSS *)qmf->FilterStates; |
231 | 0 | int no_channels = qmf->no_channels; |
232 | 0 | const FIXP_PFT *p_Filter = qmf->p_filter; |
233 | 0 | int p_stride = qmf->p_stride; |
234 | 0 | int j; |
235 | 0 | FIXP_QSS *RESTRICT sta = FilterStates; |
236 | 0 | const FIXP_PFT *RESTRICT p_flt, *RESTRICT p_fltm; |
237 | 0 | int scale = (DFRACT_BITS - SAMPLE_BITS_QMFOUT) - 1 - qmf->outScalefactor - |
238 | 0 | qmf->outGain_e; |
239 | |
|
240 | 0 | p_flt = p_Filter; /*!< Pointer to first half of filter coefficients */ |
241 | 0 | p_fltm = |
242 | 0 | &p_flt[qmf->FilterSize / 2]; /* at index 320, overall 640 coefficients */ |
243 | |
|
244 | 0 | FIXP_SGL gain = FX_DBL2FX_SGL(qmf->outGain_m); |
245 | |
|
246 | 0 | FIXP_DBL rnd_val = (FIXP_DBL)0; |
247 | |
|
248 | 0 | if (scale > 0) { |
249 | 0 | if (scale < (DFRACT_BITS - 1)) |
250 | 0 | rnd_val = FIXP_DBL(1 << (scale - 1)); |
251 | 0 | else |
252 | 0 | scale = (DFRACT_BITS - 1); |
253 | 0 | } else { |
254 | 0 | scale = fMax(scale, -(DFRACT_BITS - 1)); |
255 | 0 | } |
256 | |
|
257 | 0 | for (j = no_channels - 1; j >= 0; j--) { |
258 | 0 | FIXP_DBL imag = imagSlot[j]; /* no_channels-1 .. 0 */ |
259 | 0 | FIXP_DBL real = realSlot[j]; /* no_channels-1 .. 0 */ |
260 | 0 | { |
261 | 0 | INT_PCM_QMFOUT tmp; |
262 | 0 | FIXP_DBL Are = sta[0] + FX_DBL2FX_QSS(fMultDiv2(p_fltm[4], real)); |
263 | | |
264 | | /* This PCM formatting performs: |
265 | | - multiplication with 16-bit gain, if not -1.0f |
266 | | - rounding, if shift right is applied |
267 | | - apply shift left (or right) with saturation to 32 (or 16) bits |
268 | | - store output with --stride in 32 (or 16) bit format |
269 | | */ |
270 | 0 | if (gain != (FIXP_SGL)(-32768)) /* -1.0f */ |
271 | 0 | { |
272 | 0 | Are = fMult(Are, gain); |
273 | 0 | } |
274 | 0 | if (scale > 0) { |
275 | 0 | FDK_ASSERT(Are < |
276 | 0 | (Are + rnd_val)); /* Round-addition must not overflow */ |
277 | 0 | tmp = (INT_PCM_QMFOUT)( |
278 | 0 | SATURATE_RIGHT_SHIFT(Are + rnd_val, scale, SAMPLE_BITS_QMFOUT)); |
279 | 0 | } else { |
280 | 0 | tmp = (INT_PCM_QMFOUT)( |
281 | 0 | SATURATE_LEFT_SHIFT(Are, -scale, SAMPLE_BITS_QMFOUT)); |
282 | 0 | } |
283 | 0 | timeOut[j * stride] = tmp; |
284 | 0 | } |
285 | | |
286 | 0 | sta[0] = sta[1] + FX_DBL2FX_QSS(fMultDiv2(p_flt[4], imag)); |
287 | 0 | sta[1] = sta[2] + FX_DBL2FX_QSS(fMultDiv2(p_fltm[3], real)); |
288 | 0 | sta[2] = sta[3] + FX_DBL2FX_QSS(fMultDiv2(p_flt[3], imag)); |
289 | |
|
290 | 0 | sta[3] = sta[4] + FX_DBL2FX_QSS(fMultDiv2(p_fltm[2], real)); |
291 | 0 | sta[4] = sta[5] + FX_DBL2FX_QSS(fMultDiv2(p_flt[2], imag)); |
292 | 0 | sta[5] = sta[6] + FX_DBL2FX_QSS(fMultDiv2(p_fltm[1], real)); |
293 | 0 | sta[6] = sta[7] + FX_DBL2FX_QSS(fMultDiv2(p_flt[1], imag)); |
294 | |
|
295 | 0 | sta[7] = sta[8] + FX_DBL2FX_QSS(fMultDiv2(p_fltm[0], real)); |
296 | 0 | sta[8] = FX_DBL2FX_QSS(fMultDiv2(p_flt[0], imag)); |
297 | |
|
298 | 0 | p_flt += (p_stride * QMF_NO_POLY); |
299 | 0 | p_fltm += (p_stride * QMF_NO_POLY); |
300 | 0 | sta += 9; // = (2*QMF_NO_POLY-1); |
301 | 0 | } |
302 | 0 | } Unexecuted instantiation: qmf.cpp:qmfSynPrototypeFirSlot_NonSymmetric(QMF_FILTER_BANK*, int*, int*, short*, int) Unexecuted instantiation: qmf.cpp:qmfSynPrototypeFirSlot_NonSymmetric(QMF_FILTER_BANK*, int*, int*, int*, int) |
303 | | #endif /* FUNCTION_qmfSynPrototypeFirSlot_NonSymmetric */ |
304 | | |
305 | | void qmfSynthesisFilteringSlot(HANDLE_QMF_FILTER_BANK synQmf, |
306 | | const FIXP_DBL *realSlot, |
307 | | const FIXP_DBL *imagSlot, |
308 | | const int scaleFactorLowBand, |
309 | | const int scaleFactorHighBand, |
310 | | INT_PCM_QMFOUT *timeOut, const int stride, |
311 | 0 | FIXP_DBL *pWorkBuffer) { |
312 | 0 | if (!(synQmf->flags & QMF_FLAG_LP)) |
313 | 0 | qmfInverseModulationHQ(synQmf, realSlot, imagSlot, scaleFactorLowBand, |
314 | 0 | scaleFactorHighBand, pWorkBuffer); |
315 | 0 | else { |
316 | 0 | if (synQmf->flags & QMF_FLAG_CLDFB) { |
317 | 0 | qmfInverseModulationLP_odd(synQmf, realSlot, scaleFactorLowBand, |
318 | 0 | scaleFactorHighBand, pWorkBuffer); |
319 | 0 | } else { |
320 | 0 | qmfInverseModulationLP_even(synQmf, realSlot, scaleFactorLowBand, |
321 | 0 | scaleFactorHighBand, pWorkBuffer); |
322 | 0 | } |
323 | 0 | } |
324 | |
|
325 | 0 | if (synQmf->flags & QMF_FLAG_NONSYMMETRIC) { |
326 | 0 | qmfSynPrototypeFirSlot_NonSymmetric(synQmf, pWorkBuffer, |
327 | 0 | pWorkBuffer + synQmf->no_channels, |
328 | 0 | timeOut, stride); |
329 | 0 | } else { |
330 | 0 | qmfSynPrototypeFirSlot(synQmf, pWorkBuffer, |
331 | 0 | pWorkBuffer + synQmf->no_channels, timeOut, stride); |
332 | 0 | } |
333 | 0 | } Unexecuted instantiation: qmfSynthesisFilteringSlot(QMF_FILTER_BANK*, int const*, int const*, int, int, short*, int, int*) Unexecuted instantiation: qmfSynthesisFilteringSlot(QMF_FILTER_BANK*, int const*, int const*, int, int, int*, int, int*) |
334 | | |
335 | | /*! |
336 | | * |
337 | | * \brief Perform complex-valued subband synthesis of the |
338 | | * low band and the high band and store the |
339 | | * time domain data in timeOut |
340 | | * |
341 | | * First step: Calculate the proper scaling factor of current |
342 | | * spectral data in qmfReal/qmfImag, old spectral data in the overlap |
343 | | * range and filter states. |
344 | | * |
345 | | * Second step: Perform Frequency-to-Time mapping with inverse |
346 | | * Modulation slot-wise. |
347 | | * |
348 | | * Third step: Perform FIR-filter slot-wise. To save space for filter |
349 | | * states, the MAC operations are executed directly on the filter states |
350 | | * instead of accumulating several products in the accumulator. The |
351 | | * buffer shift at the end of the function should be replaced by a |
352 | | * modulo operation, which is available on some DSPs. |
353 | | * |
354 | | * Last step: Copy the upper part of the spectral data to the overlap buffer. |
355 | | * |
356 | | * The qmf coefficient table is symmetric. The symmetry is exploited by |
357 | | * shrinking the coefficient table to half the size. The addressing mode |
358 | | * takes care of the symmetries. If the #define #QMFTABLE_FULL is set, |
359 | | * coefficient addressing works on the full table size. The code will be |
360 | | * slightly faster and slightly more compact. |
361 | | * |
362 | | * Workbuffer requirement: 2 x sizeof(**QmfBufferReal) * synQmf->no_channels |
363 | | * The workbuffer must be aligned |
364 | | */ |
365 | | void qmfSynthesisFiltering( |
366 | | HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ |
367 | | FIXP_DBL **QmfBufferReal, /*!< Low and High band, real */ |
368 | | FIXP_DBL **QmfBufferImag, /*!< Low and High band, imag */ |
369 | | const QMF_SCALE_FACTOR *scaleFactor, |
370 | | const INT ov_len, /*!< split Slot of overlap and actual slots */ |
371 | | INT_PCM_QMFOUT *timeOut, /*!< Pointer to output */ |
372 | | const INT stride, /*!< stride factor of output */ |
373 | | FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ |
374 | 0 | ) { |
375 | 0 | int i; |
376 | 0 | int L = synQmf->no_channels; |
377 | 0 | int scaleFactorHighBand; |
378 | 0 | int scaleFactorLowBand_ov, scaleFactorLowBand_no_ov; |
379 | |
|
380 | 0 | FDK_ASSERT(synQmf->no_channels >= synQmf->lsb); |
381 | 0 | FDK_ASSERT(synQmf->no_channels >= synQmf->usb); |
382 | | |
383 | | /* adapt scaling */ |
384 | 0 | scaleFactorHighBand = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - |
385 | 0 | scaleFactor->hb_scale - synQmf->filterScale; |
386 | 0 | scaleFactorLowBand_ov = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - |
387 | 0 | scaleFactor->ov_lb_scale - synQmf->filterScale; |
388 | 0 | scaleFactorLowBand_no_ov = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - |
389 | 0 | scaleFactor->lb_scale - synQmf->filterScale; |
390 | |
|
391 | 0 | for (i = 0; i < synQmf->no_col; i++) /* ----- no_col loop ----- */ |
392 | 0 | { |
393 | 0 | const FIXP_DBL *QmfBufferImagSlot = NULL; |
394 | |
|
395 | 0 | int scaleFactorLowBand = |
396 | 0 | (i < ov_len) ? scaleFactorLowBand_ov : scaleFactorLowBand_no_ov; |
397 | |
|
398 | 0 | if (!(synQmf->flags & QMF_FLAG_LP)) QmfBufferImagSlot = QmfBufferImag[i]; |
399 | |
|
400 | 0 | qmfSynthesisFilteringSlot(synQmf, QmfBufferReal[i], QmfBufferImagSlot, |
401 | 0 | scaleFactorLowBand, scaleFactorHighBand, |
402 | 0 | timeOut + (i * L * stride), stride, pWorkBuffer); |
403 | 0 | } /* no_col loop i */ |
404 | 0 | } Unexecuted instantiation: qmfSynthesisFiltering(QMF_FILTER_BANK*, int**, int**, QMF_SCALE_FACTOR const*, int, short*, int, int*) Unexecuted instantiation: qmfSynthesisFiltering(QMF_FILTER_BANK*, int**, int**, QMF_SCALE_FACTOR const*, int, int*, int, int*) |
405 | | |
406 | | /*! |
407 | | * |
408 | | * \brief Create QMF filter bank instance |
409 | | * |
410 | | * |
411 | | * \return 0 if successful |
412 | | * |
413 | | */ |
414 | | int qmfInitAnalysisFilterBank( |
415 | | HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */ |
416 | | FIXP_QAS *pFilterStates, /*!< Handle to filter states */ |
417 | | int noCols, /*!< Number of timeslots per frame */ |
418 | | int lsb, /*!< lower end of QMF */ |
419 | | int usb, /*!< upper end of QMF */ |
420 | | int no_channels, /*!< Number of channels (bands) */ |
421 | | int flags) /*!< Low Power flag */ |
422 | 0 | { |
423 | 0 | int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, |
424 | 0 | no_channels, flags, 0); |
425 | 0 | if (!(flags & QMF_FLAG_KEEP_STATES) && (h_Qmf->FilterStates != NULL)) { |
426 | 0 | FDKmemclear(h_Qmf->FilterStates, |
427 | 0 | (2 * QMF_NO_POLY - 1) * h_Qmf->no_channels * sizeof(FIXP_QAS)); |
428 | 0 | } |
429 | |
|
430 | 0 | FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->lsb); |
431 | | |
432 | 0 | return err; |
433 | 0 | } Unexecuted instantiation: qmfInitAnalysisFilterBank(QMF_FILTER_BANK*, short*, int, int, int, int, int) Unexecuted instantiation: qmfInitAnalysisFilterBank(QMF_FILTER_BANK*, int*, int, int, int, int, int) |
434 | | |
435 | | #ifndef FUNCTION_qmfAnaPrototypeFirSlot |
436 | | /*! |
437 | | \brief Perform Analysis Prototype Filtering on a single slot of input data. |
438 | | */ |
439 | | static void qmfAnaPrototypeFirSlot( |
440 | | FIXP_DBL *analysisBuffer, |
441 | | INT no_channels, /*!< Number channels of analysis filter */ |
442 | | const FIXP_PFT *p_filter, INT p_stride, /*!< Stride of analysis filter */ |
443 | 0 | FIXP_QAS *RESTRICT pFilterStates) { |
444 | 0 | INT k; |
445 | |
|
446 | 0 | FIXP_DBL accu; |
447 | 0 | const FIXP_PFT *RESTRICT p_flt = p_filter; |
448 | 0 | FIXP_DBL *RESTRICT pData_0 = analysisBuffer + 2 * no_channels - 1; |
449 | 0 | FIXP_DBL *RESTRICT pData_1 = analysisBuffer; |
450 | |
|
451 | 0 | FIXP_QAS *RESTRICT sta_0 = (FIXP_QAS *)pFilterStates; |
452 | 0 | FIXP_QAS *RESTRICT sta_1 = |
453 | 0 | (FIXP_QAS *)pFilterStates + (2 * QMF_NO_POLY * no_channels) - 1; |
454 | 0 | INT pfltStep = QMF_NO_POLY * (p_stride); |
455 | 0 | INT staStep1 = no_channels << 1; |
456 | 0 | INT staStep2 = (no_channels << 3) - 1; /* Rewind one less */ |
457 | | |
458 | | /* FIR filters 127..64 0..63 */ |
459 | 0 | for (k = 0; k < no_channels; k++) { |
460 | 0 | accu = fMultDiv2(p_flt[0], *sta_1); |
461 | 0 | sta_1 -= staStep1; |
462 | 0 | accu += fMultDiv2(p_flt[1], *sta_1); |
463 | 0 | sta_1 -= staStep1; |
464 | 0 | accu += fMultDiv2(p_flt[2], *sta_1); |
465 | 0 | sta_1 -= staStep1; |
466 | 0 | accu += fMultDiv2(p_flt[3], *sta_1); |
467 | 0 | sta_1 -= staStep1; |
468 | 0 | accu += fMultDiv2(p_flt[4], *sta_1); |
469 | 0 | *pData_1++ = (accu << 1); |
470 | 0 | sta_1 += staStep2; |
471 | |
|
472 | 0 | p_flt += pfltStep; |
473 | 0 | accu = fMultDiv2(p_flt[0], *sta_0); |
474 | 0 | sta_0 += staStep1; |
475 | 0 | accu += fMultDiv2(p_flt[1], *sta_0); |
476 | 0 | sta_0 += staStep1; |
477 | 0 | accu += fMultDiv2(p_flt[2], *sta_0); |
478 | 0 | sta_0 += staStep1; |
479 | 0 | accu += fMultDiv2(p_flt[3], *sta_0); |
480 | 0 | sta_0 += staStep1; |
481 | 0 | accu += fMultDiv2(p_flt[4], *sta_0); |
482 | 0 | *pData_0-- = (accu << 1); |
483 | 0 | sta_0 -= staStep2; |
484 | 0 | } |
485 | 0 | } Unexecuted instantiation: qmf.cpp:qmfAnaPrototypeFirSlot(int*, int, short const*, int, short*) Unexecuted instantiation: qmf.cpp:qmfAnaPrototypeFirSlot(int*, int, short const*, int, int*) |
486 | | #endif /* !defined(FUNCTION_qmfAnaPrototypeFirSlot) */ |
487 | | |
488 | | #ifndef FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric |
489 | | /*! |
490 | | \brief Perform Analysis Prototype Filtering on a single slot of input data. |
491 | | */ |
492 | | static void qmfAnaPrototypeFirSlot_NonSymmetric( |
493 | | FIXP_DBL *analysisBuffer, |
494 | | int no_channels, /*!< Number channels of analysis filter */ |
495 | | const FIXP_PFT *p_filter, int p_stride, /*!< Stride of analysis filter */ |
496 | 0 | FIXP_QAS *RESTRICT pFilterStates) { |
497 | 0 | const FIXP_PFT *RESTRICT p_flt = p_filter; |
498 | 0 | int p, k; |
499 | |
|
500 | 0 | for (k = 0; k < 2 * no_channels; k++) { |
501 | 0 | FIXP_DBL accu = (FIXP_DBL)0; |
502 | |
|
503 | 0 | p_flt += QMF_NO_POLY * (p_stride - 1); |
504 | | |
505 | | /* |
506 | | Perform FIR-Filter |
507 | | */ |
508 | 0 | for (p = 0; p < QMF_NO_POLY; p++) { |
509 | 0 | accu += fMultDiv2(*p_flt++, pFilterStates[2 * no_channels * p]); |
510 | 0 | } |
511 | 0 | analysisBuffer[2 * no_channels - 1 - k] = (accu << 1); |
512 | 0 | pFilterStates++; |
513 | 0 | } |
514 | 0 | } Unexecuted instantiation: qmf.cpp:qmfAnaPrototypeFirSlot_NonSymmetric(int*, int, short const*, int, short*) Unexecuted instantiation: qmf.cpp:qmfAnaPrototypeFirSlot_NonSymmetric(int*, int, short const*, int, int*) |
515 | | #endif /* FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric */ |
516 | | |
517 | | /* |
518 | | * \brief Perform one QMF slot analysis of the time domain data of timeIn |
519 | | * with specified stride and stores the real part of the subband |
520 | | * samples in rSubband, and the imaginary part in iSubband |
521 | | * |
522 | | * Note: anaQmf->lsb can be greater than anaQmf->no_channels in case |
523 | | * of implicit resampling (USAC with reduced 3/4 core frame length). |
524 | | */ |
525 | | void qmfAnalysisFilteringSlot( |
526 | | HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ |
527 | | FIXP_DBL *qmfReal, /*!< Low and High band, real */ |
528 | | FIXP_DBL *qmfImag, /*!< Low and High band, imag */ |
529 | | const INT_PCM_QMFIN *RESTRICT timeIn, /*!< Pointer to input */ |
530 | | const int stride, /*!< stride factor of input */ |
531 | | FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ |
532 | 0 | ) { |
533 | 0 | int offset = anaQmf->no_channels * (QMF_NO_POLY * 2 - 1); |
534 | | /* |
535 | | Feed time signal into oldest anaQmf->no_channels states |
536 | | */ |
537 | 0 | { |
538 | 0 | FIXP_QAS *FilterStatesAnaTmp = ((FIXP_QAS *)anaQmf->FilterStates) + offset; |
539 | | |
540 | | /* Feed and scale actual time in slot */ |
541 | 0 | for (int i = anaQmf->no_channels >> 1; i != 0; i--) { |
542 | | /* Place INT_PCM value left aligned in scaledTimeIn */ |
543 | 0 | *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; |
544 | 0 | timeIn += stride; |
545 | 0 | *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; |
546 | 0 | timeIn += stride; |
547 | 0 | } |
548 | 0 | } |
549 | |
|
550 | 0 | if (anaQmf->flags & QMF_FLAG_NONSYMMETRIC) { |
551 | 0 | qmfAnaPrototypeFirSlot_NonSymmetric(pWorkBuffer, anaQmf->no_channels, |
552 | 0 | anaQmf->p_filter, anaQmf->p_stride, |
553 | 0 | (FIXP_QAS *)anaQmf->FilterStates); |
554 | 0 | } else { |
555 | 0 | qmfAnaPrototypeFirSlot(pWorkBuffer, anaQmf->no_channels, anaQmf->p_filter, |
556 | 0 | anaQmf->p_stride, (FIXP_QAS *)anaQmf->FilterStates); |
557 | 0 | } |
558 | |
|
559 | 0 | if (anaQmf->flags & QMF_FLAG_LP) { |
560 | 0 | if (anaQmf->flags & QMF_FLAG_CLDFB) |
561 | 0 | qmfForwardModulationLP_odd(anaQmf, pWorkBuffer, qmfReal); |
562 | 0 | else |
563 | 0 | qmfForwardModulationLP_even(anaQmf, pWorkBuffer, qmfReal); |
564 | |
|
565 | 0 | } else { |
566 | 0 | qmfForwardModulationHQ(anaQmf, pWorkBuffer, qmfReal, qmfImag); |
567 | 0 | } |
568 | | /* |
569 | | Shift filter states |
570 | | |
571 | | Should be realized with modulo addressing on a DSP instead of a true buffer |
572 | | shift |
573 | | */ |
574 | 0 | FDKmemmove(anaQmf->FilterStates, |
575 | 0 | (FIXP_QAS *)anaQmf->FilterStates + anaQmf->no_channels, |
576 | 0 | offset * sizeof(FIXP_QAS)); |
577 | 0 | } Unexecuted instantiation: qmfAnalysisFilteringSlot(QMF_FILTER_BANK*, int*, int*, short const*, int, int*) Unexecuted instantiation: qmfAnalysisFilteringSlot(QMF_FILTER_BANK*, int*, int*, int const*, int, int*) |
578 | | |
579 | | /*! |
580 | | * |
581 | | * \brief Perform complex-valued subband filtering of the time domain |
582 | | * data of timeIn and stores the real part of the subband |
583 | | * samples in rAnalysis, and the imaginary part in iAnalysis |
584 | | * The qmf coefficient table is symmetric. The symmetry is expoited by |
585 | | * shrinking the coefficient table to half the size. The addressing mode |
586 | | * takes care of the symmetries. |
587 | | * |
588 | | * |
589 | | * \sa PolyphaseFiltering |
590 | | */ |
591 | | void qmfAnalysisFiltering( |
592 | | HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ |
593 | | FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */ |
594 | | FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */ |
595 | | QMF_SCALE_FACTOR *scaleFactor, |
596 | | const INT_PCM_QMFIN *timeIn, /*!< Time signal */ |
597 | | const int timeIn_e, const int stride, |
598 | | FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ |
599 | 0 | ) { |
600 | 0 | int i; |
601 | 0 | int no_channels = anaQmf->no_channels; |
602 | |
|
603 | 0 | scaleFactor->lb_scale = |
604 | 0 | -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - timeIn_e; |
605 | 0 | scaleFactor->lb_scale -= anaQmf->filterScale; |
606 | |
|
607 | 0 | for (i = 0; i < anaQmf->no_col; i++) { |
608 | 0 | FIXP_DBL *qmfImagSlot = NULL; |
609 | |
|
610 | 0 | if (!(anaQmf->flags & QMF_FLAG_LP)) { |
611 | 0 | qmfImagSlot = qmfImag[i]; |
612 | 0 | } |
613 | |
|
614 | 0 | qmfAnalysisFilteringSlot(anaQmf, qmfReal[i], qmfImagSlot, timeIn, stride, |
615 | 0 | pWorkBuffer); |
616 | |
|
617 | 0 | timeIn += no_channels * stride; |
618 | |
|
619 | 0 | } /* no_col loop i */ |
620 | 0 | } Unexecuted instantiation: qmfAnalysisFiltering(QMF_FILTER_BANK*, int**, int**, QMF_SCALE_FACTOR*, short const*, int, int, int*) Unexecuted instantiation: qmfAnalysisFiltering(QMF_FILTER_BANK*, int**, int**, QMF_SCALE_FACTOR*, int const*, int, int, int*) |
621 | | #endif /* QMF_PCM_H */ |