/src/aac/libSBRenc/src/invf_est.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 - 2018 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 | | /**************************** SBR encoder library ****************************** |
96 | | |
97 | | Author(s): |
98 | | |
99 | | Description: |
100 | | |
101 | | *******************************************************************************/ |
102 | | |
103 | | #include "invf_est.h" |
104 | | #include "sbr_misc.h" |
105 | | |
106 | | #include "genericStds.h" |
107 | | |
108 | | #define MAX_NUM_REGIONS 10 |
109 | | #define SCALE_FAC_QUO 512.0f |
110 | | #define SCALE_FAC_NRG 256.0f |
111 | | |
112 | | #ifndef min |
113 | 0 | #define min(a, b) (a < b ? a : b) |
114 | | #endif |
115 | | |
116 | | #ifndef max |
117 | 0 | #define max(a, b) (a > b ? a : b) |
118 | | #endif |
119 | | |
120 | | static const FIXP_DBL quantStepsSbr[4] = { |
121 | | 0x00400000, 0x02800000, 0x03800000, |
122 | | 0x04c00000}; /* table scaled with SCALE_FAC_QUO */ |
123 | | static const FIXP_DBL quantStepsOrig[4] = { |
124 | | 0x00000000, 0x00c00000, 0x01c00000, |
125 | | 0x02800000}; /* table scaled with SCALE_FAC_QUO */ |
126 | | static const FIXP_DBL nrgBorders[4] = { |
127 | | 0x0c800000, 0x0f000000, 0x11800000, |
128 | | 0x14000000}; /* table scaled with SCALE_FAC_NRG */ |
129 | | |
130 | | static const DETECTOR_PARAMETERS detectorParamsAAC = { |
131 | | quantStepsSbr, |
132 | | quantStepsOrig, |
133 | | nrgBorders, |
134 | | 4, /* Number of borders SBR. */ |
135 | | 4, /* Number of borders orig. */ |
136 | | 4, /* Number of borders Nrg. */ |
137 | | { |
138 | | /* Region space. */ |
139 | | {INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF, |
140 | | INVF_OFF}, /* | */ |
141 | | {INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF, |
142 | | INVF_OFF}, /* | */ |
143 | | {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, |
144 | | INVF_OFF}, /* regionSbr */ |
145 | | {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, |
146 | | INVF_OFF}, /* | */ |
147 | | {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, |
148 | | INVF_OFF} /* | */ |
149 | | }, /*------------------------ regionOrig ---------------------------------*/ |
150 | | { |
151 | | /* Region space transient. */ |
152 | | {INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_OFF, |
153 | | INVF_OFF}, /* | */ |
154 | | {INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_OFF, |
155 | | INVF_OFF}, /* | */ |
156 | | {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF, |
157 | | INVF_OFF}, /* regionSbr */ |
158 | | {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, |
159 | | INVF_OFF}, /* | */ |
160 | | {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, |
161 | | INVF_OFF} /* | */ |
162 | | }, /*------------------------ regionOrig ---------------------------------*/ |
163 | | {-4, -3, -2, -1, |
164 | | 0} /* Reduction factor of the inverse filtering for low energies.*/ |
165 | | }; |
166 | | |
167 | | static const FIXP_DBL hysteresis = |
168 | | 0x00400000; /* Delta value for hysteresis. scaled with SCALE_FAC_QUO */ |
169 | | |
170 | | /* |
171 | | * AAC+SBR PARAMETERS for Speech |
172 | | *********************************/ |
173 | | static const DETECTOR_PARAMETERS detectorParamsAACSpeech = { |
174 | | quantStepsSbr, |
175 | | quantStepsOrig, |
176 | | nrgBorders, |
177 | | 4, /* Number of borders SBR. */ |
178 | | 4, /* Number of borders orig. */ |
179 | | 4, /* Number of borders Nrg. */ |
180 | | { |
181 | | /* Region space. */ |
182 | | {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, |
183 | | INVF_OFF}, /* | */ |
184 | | {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, |
185 | | INVF_OFF}, /* | */ |
186 | | {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF, |
187 | | INVF_OFF}, /* regionSbr */ |
188 | | {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, |
189 | | INVF_OFF}, /* | */ |
190 | | {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, |
191 | | INVF_OFF} /* | */ |
192 | | }, /*------------------------ regionOrig ---------------------------------*/ |
193 | | { |
194 | | /* Region space transient. */ |
195 | | {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, |
196 | | INVF_OFF}, /* | */ |
197 | | {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, |
198 | | INVF_OFF}, /* | */ |
199 | | {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF, |
200 | | INVF_OFF}, /* regionSbr */ |
201 | | {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, |
202 | | INVF_OFF}, /* | */ |
203 | | {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, |
204 | | INVF_OFF} /* | */ |
205 | | }, /*------------------------ regionOrig ---------------------------------*/ |
206 | | {-4, -3, -2, -1, |
207 | | 0} /* Reduction factor of the inverse filtering for low energies.*/ |
208 | | }; |
209 | | |
210 | | /* |
211 | | * Smoothing filters. |
212 | | ************************/ |
213 | | typedef const FIXP_DBL FIR_FILTER[5]; |
214 | | |
215 | | static const FIR_FILTER fir_0 = {0x7fffffff, 0x00000000, 0x00000000, 0x00000000, |
216 | | 0x00000000}; |
217 | | static const FIR_FILTER fir_1 = {0x2aaaaa80, 0x555554ff, 0x00000000, 0x00000000, |
218 | | 0x00000000}; |
219 | | static const FIR_FILTER fir_2 = {0x10000000, 0x30000000, 0x40000000, 0x00000000, |
220 | | 0x00000000}; |
221 | | static const FIR_FILTER fir_3 = {0x077f80e8, 0x199999a0, 0x2bb3b240, 0x33333340, |
222 | | 0x00000000}; |
223 | | static const FIR_FILTER fir_4 = {0x04130598, 0x0ebdb000, 0x1becfa60, 0x2697a4c0, |
224 | | 0x2aaaaa80}; |
225 | | |
226 | | static const FIR_FILTER *const fir_table[5] = {&fir_0, &fir_1, &fir_2, &fir_3, |
227 | | &fir_4}; |
228 | | |
229 | | /**************************************************************************/ |
230 | | /*! |
231 | | \brief Calculates the values used for the detector. |
232 | | |
233 | | |
234 | | \return none |
235 | | |
236 | | */ |
237 | | /**************************************************************************/ |
238 | | static void calculateDetectorValues( |
239 | | FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the tonality values of the |
240 | | original. */ |
241 | | SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ |
242 | | FIXP_DBL *nrgVector, /*!< Energy vector. */ |
243 | | DETECTOR_VALUES *detectorValues, /*!< pointer to DETECTOR_VALUES struct. */ |
244 | | INT startChannel, /*!< Start channel. */ |
245 | | INT stopChannel, /*!< Stop channel. */ |
246 | | INT startIndex, /*!< Start index. */ |
247 | | INT stopIndex, /*!< Stop index. */ |
248 | | INT numberOfStrongest /*!< The number of sorted tonal components to be |
249 | | considered. */ |
250 | 0 | ) { |
251 | 0 | INT i, temp, j; |
252 | |
|
253 | 0 | const FIXP_DBL *filter = *fir_table[INVF_SMOOTHING_LENGTH]; |
254 | 0 | FIXP_DBL origQuotaMeanStrongest, sbrQuotaMeanStrongest; |
255 | 0 | FIXP_DBL origQuota, sbrQuota; |
256 | 0 | FIXP_DBL invIndex, invChannel, invTemp; |
257 | 0 | FIXP_DBL quotaVecOrig[64], quotaVecSbr[64]; |
258 | |
|
259 | 0 | FDKmemclear(quotaVecOrig, 64 * sizeof(FIXP_DBL)); |
260 | 0 | FDKmemclear(quotaVecSbr, 64 * sizeof(FIXP_DBL)); |
261 | |
|
262 | 0 | invIndex = GetInvInt(stopIndex - startIndex); |
263 | 0 | invChannel = GetInvInt(stopChannel - startChannel); |
264 | | |
265 | | /* |
266 | | Calculate the mean value, over the current time segment, for the original, |
267 | | the HFR and the difference, over all channels in the current frequency range. |
268 | | NOTE: the averaging is done on the values quota/(1 - quota + RELAXATION). |
269 | | */ |
270 | | |
271 | | /* The original, the sbr signal and the total energy */ |
272 | 0 | detectorValues->avgNrg = FL2FXCONST_DBL(0.0f); |
273 | 0 | for (j = startIndex; j < stopIndex; j++) { |
274 | 0 | for (i = startChannel; i < stopChannel; i++) { |
275 | 0 | quotaVecOrig[i] += fMult(quotaMatrixOrig[j][i], invIndex); |
276 | |
|
277 | 0 | if (indexVector[i] != -1) |
278 | 0 | quotaVecSbr[i] += fMult(quotaMatrixOrig[j][indexVector[i]], invIndex); |
279 | 0 | } |
280 | 0 | detectorValues->avgNrg += fMult(nrgVector[j], invIndex); |
281 | 0 | } |
282 | | |
283 | | /* |
284 | | Calculate the mean value, over the current frequency range, for the original, |
285 | | the HFR and the difference. Also calculate the same mean values for the three |
286 | | vectors, but only includeing the x strongest copmponents. |
287 | | */ |
288 | |
|
289 | 0 | origQuota = FL2FXCONST_DBL(0.0f); |
290 | 0 | sbrQuota = FL2FXCONST_DBL(0.0f); |
291 | 0 | for (i = startChannel; i < stopChannel; i++) { |
292 | 0 | origQuota += fMultDiv2(quotaVecOrig[i], invChannel); |
293 | 0 | sbrQuota += fMultDiv2(quotaVecSbr[i], invChannel); |
294 | 0 | } |
295 | | |
296 | | /* |
297 | | Calculate the mean value for the x strongest components |
298 | | */ |
299 | 0 | FDKsbrEnc_Shellsort_fract(quotaVecOrig + startChannel, |
300 | 0 | stopChannel - startChannel); |
301 | 0 | FDKsbrEnc_Shellsort_fract(quotaVecSbr + startChannel, |
302 | 0 | stopChannel - startChannel); |
303 | |
|
304 | 0 | origQuotaMeanStrongest = FL2FXCONST_DBL(0.0f); |
305 | 0 | sbrQuotaMeanStrongest = FL2FXCONST_DBL(0.0f); |
306 | |
|
307 | 0 | temp = min(stopChannel - startChannel, numberOfStrongest); |
308 | 0 | invTemp = GetInvInt(temp); |
309 | |
|
310 | 0 | for (i = 0; i < temp; i++) { |
311 | 0 | origQuotaMeanStrongest += |
312 | 0 | fMultDiv2(quotaVecOrig[i + stopChannel - temp], invTemp); |
313 | 0 | sbrQuotaMeanStrongest += |
314 | 0 | fMultDiv2(quotaVecSbr[i + stopChannel - temp], invTemp); |
315 | 0 | } |
316 | | |
317 | | /* |
318 | | The value for the strongest component |
319 | | */ |
320 | 0 | detectorValues->origQuotaMax = quotaVecOrig[stopChannel - 1]; |
321 | 0 | detectorValues->sbrQuotaMax = quotaVecSbr[stopChannel - 1]; |
322 | | |
323 | | /* |
324 | | Buffer values |
325 | | */ |
326 | 0 | FDKmemmove(detectorValues->origQuotaMean, detectorValues->origQuotaMean + 1, |
327 | 0 | INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL)); |
328 | 0 | FDKmemmove(detectorValues->sbrQuotaMean, detectorValues->sbrQuotaMean + 1, |
329 | 0 | INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL)); |
330 | 0 | FDKmemmove(detectorValues->origQuotaMeanStrongest, |
331 | 0 | detectorValues->origQuotaMeanStrongest + 1, |
332 | 0 | INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL)); |
333 | 0 | FDKmemmove(detectorValues->sbrQuotaMeanStrongest, |
334 | 0 | detectorValues->sbrQuotaMeanStrongest + 1, |
335 | 0 | INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL)); |
336 | |
|
337 | 0 | detectorValues->origQuotaMean[INVF_SMOOTHING_LENGTH] = origQuota << 1; |
338 | 0 | detectorValues->sbrQuotaMean[INVF_SMOOTHING_LENGTH] = sbrQuota << 1; |
339 | 0 | detectorValues->origQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] = |
340 | 0 | origQuotaMeanStrongest << 1; |
341 | 0 | detectorValues->sbrQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] = |
342 | 0 | sbrQuotaMeanStrongest << 1; |
343 | | |
344 | | /* |
345 | | Filter values |
346 | | */ |
347 | 0 | detectorValues->origQuotaMeanFilt = FL2FXCONST_DBL(0.0f); |
348 | 0 | detectorValues->sbrQuotaMeanFilt = FL2FXCONST_DBL(0.0f); |
349 | 0 | detectorValues->origQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f); |
350 | 0 | detectorValues->sbrQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f); |
351 | |
|
352 | 0 | for (i = 0; i < INVF_SMOOTHING_LENGTH + 1; i++) { |
353 | 0 | detectorValues->origQuotaMeanFilt += |
354 | 0 | fMult(detectorValues->origQuotaMean[i], filter[i]); |
355 | 0 | detectorValues->sbrQuotaMeanFilt += |
356 | 0 | fMult(detectorValues->sbrQuotaMean[i], filter[i]); |
357 | 0 | detectorValues->origQuotaMeanStrongestFilt += |
358 | 0 | fMult(detectorValues->origQuotaMeanStrongest[i], filter[i]); |
359 | 0 | detectorValues->sbrQuotaMeanStrongestFilt += |
360 | 0 | fMult(detectorValues->sbrQuotaMeanStrongest[i], filter[i]); |
361 | 0 | } |
362 | 0 | } |
363 | | |
364 | | /**************************************************************************/ |
365 | | /*! |
366 | | \brief Returns the region in which the input value belongs. |
367 | | |
368 | | |
369 | | |
370 | | \return region. |
371 | | |
372 | | */ |
373 | | /**************************************************************************/ |
374 | | static INT findRegion( |
375 | | FIXP_DBL currVal, /*!< The current value. */ |
376 | | const FIXP_DBL *borders, /*!< The border of the regions. */ |
377 | | const INT numBorders /*!< The number of borders. */ |
378 | 0 | ) { |
379 | 0 | INT i; |
380 | |
|
381 | 0 | if (currVal < borders[0]) { |
382 | 0 | return 0; |
383 | 0 | } |
384 | | |
385 | 0 | for (i = 1; i < numBorders; i++) { |
386 | 0 | if (currVal >= borders[i - 1] && currVal < borders[i]) { |
387 | 0 | return i; |
388 | 0 | } |
389 | 0 | } |
390 | | |
391 | 0 | if (currVal >= borders[numBorders - 1]) { |
392 | 0 | return numBorders; |
393 | 0 | } |
394 | | |
395 | 0 | return 0; /* We never get here, it's just to avoid compiler warnings.*/ |
396 | 0 | } |
397 | | |
398 | | /**************************************************************************/ |
399 | | /*! |
400 | | \brief Makes a clever decision based on the quota vector. |
401 | | |
402 | | |
403 | | \return decision on which invf mode to use |
404 | | |
405 | | */ |
406 | | /**************************************************************************/ |
407 | | static INVF_MODE decisionAlgorithm( |
408 | | const DETECTOR_PARAMETERS |
409 | | *detectorParams, /*!< Struct with the detector parameters. */ |
410 | | DETECTOR_VALUES *detectorValues, /*!< Struct with the detector values. */ |
411 | | INT transientFlag, /*!< Flag indicating if there is a transient present.*/ |
412 | | INT *prevRegionSbr, /*!< The previous region in which the Sbr value was. */ |
413 | | INT *prevRegionOrig /*!< The previous region in which the Orig value was. */ |
414 | 0 | ) { |
415 | 0 | INT invFiltLevel, regionSbr, regionOrig, regionNrg; |
416 | | |
417 | | /* |
418 | | Current thresholds. |
419 | | */ |
420 | 0 | const INT numRegionsSbr = detectorParams->numRegionsSbr; |
421 | 0 | const INT numRegionsOrig = detectorParams->numRegionsOrig; |
422 | 0 | const INT numRegionsNrg = detectorParams->numRegionsNrg; |
423 | |
|
424 | 0 | FIXP_DBL quantStepsSbrTmp[MAX_NUM_REGIONS]; |
425 | 0 | FIXP_DBL quantStepsOrigTmp[MAX_NUM_REGIONS]; |
426 | | |
427 | | /* |
428 | | Current detector values. |
429 | | */ |
430 | 0 | FIXP_DBL origQuotaMeanFilt; |
431 | 0 | FIXP_DBL sbrQuotaMeanFilt; |
432 | 0 | FIXP_DBL nrg; |
433 | | |
434 | | /* 0.375 = 3.0 / 8.0; 0.31143075889 = log2(RELAXATION)/64.0; 0.625 = |
435 | | * log(16)/64.0; 0.6875 = 44/64.0 */ |
436 | 0 | origQuotaMeanFilt = |
437 | 0 | (fMultDiv2(FL2FXCONST_DBL(2.f * 0.375f), |
438 | 0 | (FIXP_DBL)(CalcLdData(max(detectorValues->origQuotaMeanFilt, |
439 | 0 | (FIXP_DBL)1)) + |
440 | 0 | FL2FXCONST_DBL(0.31143075889f)))) |
441 | 0 | << 0; /* scaled by 1/2^9 */ |
442 | 0 | sbrQuotaMeanFilt = |
443 | 0 | (fMultDiv2(FL2FXCONST_DBL(2.f * 0.375f), |
444 | 0 | (FIXP_DBL)(CalcLdData(max(detectorValues->sbrQuotaMeanFilt, |
445 | 0 | (FIXP_DBL)1)) + |
446 | 0 | FL2FXCONST_DBL(0.31143075889f)))) |
447 | 0 | << 0; /* scaled by 1/2^9 */ |
448 | | /* If energy is zero then we will get different results for different word |
449 | | * lengths. */ |
450 | 0 | nrg = |
451 | 0 | (fMultDiv2(FL2FXCONST_DBL(2.f * 0.375f), |
452 | 0 | (FIXP_DBL)(CalcLdData(detectorValues->avgNrg + (FIXP_DBL)1) + |
453 | 0 | FL2FXCONST_DBL(0.0625f) + FL2FXCONST_DBL(0.6875f)))) |
454 | 0 | << 0; /* scaled by 1/2^8; 2^44 -> qmf energy scale */ |
455 | |
|
456 | 0 | FDKmemcpy(quantStepsSbrTmp, detectorParams->quantStepsSbr, |
457 | 0 | numRegionsSbr * sizeof(FIXP_DBL)); |
458 | 0 | FDKmemcpy(quantStepsOrigTmp, detectorParams->quantStepsOrig, |
459 | 0 | numRegionsOrig * sizeof(FIXP_DBL)); |
460 | |
|
461 | 0 | if (*prevRegionSbr < numRegionsSbr) |
462 | 0 | quantStepsSbrTmp[*prevRegionSbr] = |
463 | 0 | detectorParams->quantStepsSbr[*prevRegionSbr] + hysteresis; |
464 | 0 | if (*prevRegionSbr > 0) |
465 | 0 | quantStepsSbrTmp[*prevRegionSbr - 1] = |
466 | 0 | detectorParams->quantStepsSbr[*prevRegionSbr - 1] - hysteresis; |
467 | |
|
468 | 0 | if (*prevRegionOrig < numRegionsOrig) |
469 | 0 | quantStepsOrigTmp[*prevRegionOrig] = |
470 | 0 | detectorParams->quantStepsOrig[*prevRegionOrig] + hysteresis; |
471 | 0 | if (*prevRegionOrig > 0) |
472 | 0 | quantStepsOrigTmp[*prevRegionOrig - 1] = |
473 | 0 | detectorParams->quantStepsOrig[*prevRegionOrig - 1] - hysteresis; |
474 | |
|
475 | 0 | regionSbr = findRegion(sbrQuotaMeanFilt, quantStepsSbrTmp, numRegionsSbr); |
476 | 0 | regionOrig = findRegion(origQuotaMeanFilt, quantStepsOrigTmp, numRegionsOrig); |
477 | 0 | regionNrg = findRegion(nrg, detectorParams->nrgBorders, numRegionsNrg); |
478 | |
|
479 | 0 | *prevRegionSbr = regionSbr; |
480 | 0 | *prevRegionOrig = regionOrig; |
481 | | |
482 | | /* Use different settings if a transient is present*/ |
483 | 0 | invFiltLevel = |
484 | 0 | (transientFlag == 1) |
485 | 0 | ? detectorParams->regionSpaceTransient[regionSbr][regionOrig] |
486 | 0 | : detectorParams->regionSpace[regionSbr][regionOrig]; |
487 | | |
488 | | /* Compensate for low energy.*/ |
489 | 0 | invFiltLevel = |
490 | 0 | max(invFiltLevel + detectorParams->EnergyCompFactor[regionNrg], 0); |
491 | |
|
492 | 0 | return (INVF_MODE)(invFiltLevel); |
493 | 0 | } |
494 | | |
495 | | /**************************************************************************/ |
496 | | /*! |
497 | | \brief Estiamtion of the inverse filtering level required |
498 | | in the decoder. |
499 | | |
500 | | A second order LPC is calculated for every filterbank channel, using |
501 | | the covariance method. THe ratio between the energy of the predicted |
502 | | signal and the energy of the non-predictable signal is calcualted. |
503 | | |
504 | | \return none. |
505 | | |
506 | | */ |
507 | | /**************************************************************************/ |
508 | | void FDKsbrEnc_qmfInverseFilteringDetector( |
509 | | HANDLE_SBR_INV_FILT_EST |
510 | | hInvFilt, /*!< Handle to the SBR_INV_FILT_EST struct. */ |
511 | | FIXP_DBL **quotaMatrix, /*!< The matrix holding the tonality values of the |
512 | | original. */ |
513 | | FIXP_DBL *nrgVector, /*!< The energy vector. */ |
514 | | SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ |
515 | | INT startIndex, /*!< Start index. */ |
516 | | INT stopIndex, /*!< Stop index. */ |
517 | | INT transientFlag, /*!< Flag indicating if a transient is present or not.*/ |
518 | | INVF_MODE *infVec /*!< Vector holding the inverse filtering levels. */ |
519 | 0 | ) { |
520 | 0 | INT band; |
521 | | |
522 | | /* |
523 | | * Do the inverse filtering level estimation. |
524 | | *****************************************************/ |
525 | 0 | for (band = 0; band < hInvFilt->noDetectorBands; band++) { |
526 | 0 | INT startChannel = hInvFilt->freqBandTableInvFilt[band]; |
527 | 0 | INT stopChannel = hInvFilt->freqBandTableInvFilt[band + 1]; |
528 | |
|
529 | 0 | calculateDetectorValues(quotaMatrix, indexVector, nrgVector, |
530 | 0 | &hInvFilt->detectorValues[band], startChannel, |
531 | 0 | stopChannel, startIndex, stopIndex, |
532 | 0 | hInvFilt->numberOfStrongest); |
533 | |
|
534 | 0 | infVec[band] = decisionAlgorithm( |
535 | 0 | hInvFilt->detectorParams, &hInvFilt->detectorValues[band], |
536 | 0 | transientFlag, &hInvFilt->prevRegionSbr[band], |
537 | 0 | &hInvFilt->prevRegionOrig[band]); |
538 | 0 | } |
539 | 0 | } |
540 | | |
541 | | /**************************************************************************/ |
542 | | /*! |
543 | | \brief Initialize an instance of the inverse filtering level estimator. |
544 | | |
545 | | |
546 | | \return errorCode, noError if successful. |
547 | | |
548 | | */ |
549 | | /**************************************************************************/ |
550 | | INT FDKsbrEnc_initInvFiltDetector( |
551 | | HANDLE_SBR_INV_FILT_EST |
552 | | hInvFilt, /*!< Pointer to a handle to the SBR_INV_FILT_EST struct. */ |
553 | | INT *freqBandTableDetector, /*!< Frequency band table for the inverse |
554 | | filtering. */ |
555 | | INT numDetectorBands, /*!< Number of inverse filtering bands. */ |
556 | | UINT |
557 | | useSpeechConfig /*!< Flag: adapt tuning parameters according to speech*/ |
558 | 0 | ) { |
559 | 0 | INT i; |
560 | |
|
561 | 0 | FDKmemclear(hInvFilt, sizeof(SBR_INV_FILT_EST)); |
562 | |
|
563 | 0 | hInvFilt->detectorParams = |
564 | 0 | (useSpeechConfig) ? &detectorParamsAACSpeech : &detectorParamsAAC; |
565 | |
|
566 | 0 | hInvFilt->noDetectorBandsMax = numDetectorBands; |
567 | | |
568 | | /* |
569 | | Memory initialisation |
570 | | */ |
571 | 0 | for (i = 0; i < hInvFilt->noDetectorBandsMax; i++) { |
572 | 0 | FDKmemclear(&hInvFilt->detectorValues[i], sizeof(DETECTOR_VALUES)); |
573 | 0 | hInvFilt->prevInvfMode[i] = INVF_OFF; |
574 | 0 | hInvFilt->prevRegionOrig[i] = 0; |
575 | 0 | hInvFilt->prevRegionSbr[i] = 0; |
576 | 0 | } |
577 | | |
578 | | /* |
579 | | Reset the inverse fltering detector. |
580 | | */ |
581 | 0 | FDKsbrEnc_resetInvFiltDetector(hInvFilt, freqBandTableDetector, |
582 | 0 | hInvFilt->noDetectorBandsMax); |
583 | |
|
584 | 0 | return (0); |
585 | 0 | } |
586 | | |
587 | | /**************************************************************************/ |
588 | | /*! |
589 | | \brief resets sbr inverse filtering structure. |
590 | | |
591 | | |
592 | | |
593 | | \return errorCode, noError if successful. |
594 | | |
595 | | */ |
596 | | /**************************************************************************/ |
597 | | INT FDKsbrEnc_resetInvFiltDetector( |
598 | | HANDLE_SBR_INV_FILT_EST |
599 | | hInvFilt, /*!< Handle to the SBR_INV_FILT_EST struct. */ |
600 | | INT *freqBandTableDetector, /*!< Frequency band table for the inverse |
601 | | filtering. */ |
602 | | INT numDetectorBands) /*!< Number of inverse filtering bands. */ |
603 | 0 | { |
604 | 0 | hInvFilt->numberOfStrongest = 1; |
605 | 0 | FDKmemcpy(hInvFilt->freqBandTableInvFilt, freqBandTableDetector, |
606 | 0 | (numDetectorBands + 1) * sizeof(INT)); |
607 | 0 | hInvFilt->noDetectorBands = numDetectorBands; |
608 | |
|
609 | 0 | return (0); |
610 | 0 | } |