Imported Debian version 0.1.3.1
[deb_fdk-aac.git] / libSBRenc / src / mh_det.cpp
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 "mh_det.h"
85
86 #include "sbr_ram.h"
87 #include "sbr_misc.h"
88
89
90 #include "genericStds.h"
91
92 #define SFM_SHIFT 2 /* Attention: SFM_SCALE depends on SFM_SHIFT */
93 #define SFM_SCALE (MAXVAL_DBL >> SFM_SHIFT) /* 1.0 >> SFM_SHIFT */
94
95
96 /*!< Detector Parameters for AAC core codec. */
97 static const DETECTOR_PARAMETERS_MH paramsAac = {
98 9, /*!< deltaTime */
99 {
100 FL2FXCONST_DBL(20.0f*RELAXATION_FLOAT), /*!< thresHoldDiff */
101 FL2FXCONST_DBL(1.26f*RELAXATION_FLOAT), /*!< thresHoldDiffGuide */
102 FL2FXCONST_DBL(15.0f*RELAXATION_FLOAT), /*!< thresHoldTone */
103 FL2FXCONST_DBL((1.0f/15.0f)*RELAXATION_FLOAT), /*!< invThresHoldTone */
104 FL2FXCONST_DBL(1.26f*RELAXATION_FLOAT), /*!< thresHoldToneGuide */
105 FL2FXCONST_DBL(0.3f)>>SFM_SHIFT, /*!< sfmThresSbr */
106 FL2FXCONST_DBL(0.1f)>>SFM_SHIFT, /*!< sfmThresOrig */
107 FL2FXCONST_DBL(0.3f), /*!< decayGuideOrig */
108 FL2FXCONST_DBL(0.5f), /*!< decayGuideDiff */
109 FL2FXCONST_DBL(-0.000112993269), /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresMaxLD64 */
110 FL2FXCONST_DBL(-0.000112993269), /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresBelowLD64 */
111 FL2FXCONST_DBL(-0.005030126483f) /* LD64(FL2FXCONST_DBL(0.8f)) */ /*!< derivThresAboveLD64 */
112 },
113 50 /*!< maxComp */
114 };
115
116 /*!< Detector Parameters for AAC LD core codec. */
117 static const DETECTOR_PARAMETERS_MH paramsAacLd = {
118 16, /*!< Delta time. */
119 {
120 FL2FXCONST_DBL(25.0f*RELAXATION_FLOAT), /*!< thresHoldDiff */
121 FL2FXCONST_DBL(1.26f*RELAXATION_FLOAT), /*!< tresHoldDiffGuide */
122 FL2FXCONST_DBL(15.0f*RELAXATION_FLOAT), /*!< thresHoldTone */
123 FL2FXCONST_DBL((1.0f/15.0f)*RELAXATION_FLOAT), /*!< invThresHoldTone */
124 FL2FXCONST_DBL(1.26f*RELAXATION_FLOAT), /*!< thresHoldToneGuide */
125 FL2FXCONST_DBL(0.3f)>>SFM_SHIFT, /*!< sfmThresSbr */
126 FL2FXCONST_DBL(0.1f)>>SFM_SHIFT, /*!< sfmThresOrig */
127 FL2FXCONST_DBL(0.3f), /*!< decayGuideOrig */
128 FL2FXCONST_DBL(0.2f), /*!< decayGuideDiff */
129 FL2FXCONST_DBL(-0.000112993269), /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresMaxLD64 */
130 FL2FXCONST_DBL(-0.000112993269), /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresBelowLD64 */
131 FL2FXCONST_DBL(-0.005030126483f) /* LD64(FL2FXCONST_DBL(0.8f)) */ /*!< derivThresAboveLD64 */
132 },
133 50 /*!< maxComp */
134 };
135
136
137 /**************************************************************************/
138 /*!
139 \brief Calculates the difference in tonality between original and SBR
140 for a given time and frequency region.
141
142 The values for pDiffMapped2Scfb are scaled by RELAXATION
143
144 \return none.
145
146 */
147 /**************************************************************************/
148 static void diff(FIXP_DBL *RESTRICT pTonalityOrig,
149 FIXP_DBL *pDiffMapped2Scfb,
150 const UCHAR *RESTRICT pFreqBandTable,
151 INT nScfb,
152 SCHAR *indexVector)
153 {
154 UCHAR i, ll, lu, k;
155 FIXP_DBL maxValOrig, maxValSbr, tmp;
156 INT scale;
157
158 for(i=0; i < nScfb; i++){
159 ll = pFreqBandTable[i];
160 lu = pFreqBandTable[i+1];
161
162 maxValOrig = FL2FXCONST_DBL(0.0f);
163 maxValSbr = FL2FXCONST_DBL(0.0f);
164
165 for(k=ll;k<lu;k++){
166 maxValOrig = fixMax(maxValOrig, pTonalityOrig[k]);
167 maxValSbr = fixMax(maxValSbr, pTonalityOrig[indexVector[k]]);
168 }
169
170 if ((maxValSbr >= RELAXATION)) {
171 tmp = fDivNorm(maxValOrig, maxValSbr, &scale);
172 pDiffMapped2Scfb[i] = scaleValue(fMult(tmp,RELAXATION_FRACT), fixMax(-(DFRACT_BITS-1),(scale-RELAXATION_SHIFT)));
173 }
174 else {
175 pDiffMapped2Scfb[i] = maxValOrig;
176 }
177 }
178 }
179
180
181 /**************************************************************************/
182 /*!
183 \brief Calculates a flatness measure of the tonality measures.
184
185 Calculation of the power function and using scalefactor for basis:
186 Using log2:
187 z = (2^k * x)^y;
188 z' = CalcLd(z) = y*CalcLd(x) + y*k;
189 z = CalcInvLd(z');
190
191 Using ld64:
192 z = (2^k * x)^y;
193 z' = CalcLd64(z) = y*CalcLd64(x)/64 + y*k/64;
194 z = CalcInvLd64(z');
195
196 The values pSfmOrigVec and pSfmSbrVec are scaled by the factor 1/4.0
197
198 \return none.
199
200 */
201 /**************************************************************************/
202 static void calculateFlatnessMeasure(FIXP_DBL *pQuotaBuffer,
203 SCHAR *indexVector,
204 FIXP_DBL *pSfmOrigVec,
205 FIXP_DBL *pSfmSbrVec,
206 const UCHAR *pFreqBandTable,
207 INT nSfb)
208 {
209 INT i,j;
210 FIXP_DBL invBands,tmp1,tmp2;
211 INT shiftFac0,shiftFacSum0;
212 INT shiftFac1,shiftFacSum1;
213 FIXP_DBL accu;
214
215 for(i=0;i<nSfb;i++)
216 {
217 INT ll = pFreqBandTable[i];
218 INT lu = pFreqBandTable[i+1];
219 pSfmOrigVec[i] = (FIXP_DBL)(MAXVAL_DBL>>2);
220 pSfmSbrVec[i] = (FIXP_DBL)(MAXVAL_DBL>>2);
221
222 if(lu - ll > 1){
223 FIXP_DBL amOrig,amTransp,gmOrig,gmTransp,sfmOrig,sfmTransp;
224 invBands = GetInvInt(lu-ll);
225 shiftFacSum0 = 0;
226 shiftFacSum1 = 0;
227 amOrig = amTransp = FL2FXCONST_DBL(0.0f);
228 gmOrig = gmTransp = (FIXP_DBL)MAXVAL_DBL;
229
230 for(j= ll; j<lu; j++) {
231 sfmOrig = pQuotaBuffer[j];
232 sfmTransp = pQuotaBuffer[indexVector[j]];
233
234 amOrig += fMult(sfmOrig, invBands);
235 amTransp += fMult(sfmTransp, invBands);
236
237 shiftFac0 = CountLeadingBits(sfmOrig);
238 shiftFac1 = CountLeadingBits(sfmTransp);
239
240 gmOrig = fMult(gmOrig, sfmOrig<<shiftFac0);
241 gmTransp = fMult(gmTransp, sfmTransp<<shiftFac1);
242
243 shiftFacSum0 += shiftFac0;
244 shiftFacSum1 += shiftFac1;
245 }
246
247 if (gmOrig > FL2FXCONST_DBL(0.0f)) {
248
249 tmp1 = CalcLdData(gmOrig); /* CalcLd64(x)/64 */
250 tmp1 = fMult(invBands, tmp1); /* y*CalcLd64(x)/64 */
251
252 /* y*k/64 */
253 accu = (FIXP_DBL)-shiftFacSum0 << (DFRACT_BITS-1-8);
254 tmp2 = fMultDiv2(invBands, accu) << (2+1);
255
256 tmp2 = tmp1 + tmp2; /* y*CalcLd64(x)/64 + y*k/64 */
257 gmOrig = CalcInvLdData(tmp2); /* CalcInvLd64(z'); */
258 }
259 else {
260 gmOrig = FL2FXCONST_DBL(0.0f);
261 }
262
263 if (gmTransp > FL2FXCONST_DBL(0.0f)) {
264
265 tmp1 = CalcLdData(gmTransp); /* CalcLd64(x)/64 */
266 tmp1 = fMult(invBands, tmp1); /* y*CalcLd64(x)/64 */
267
268 /* y*k/64 */
269 accu = (FIXP_DBL)-shiftFacSum1 << (DFRACT_BITS-1-8);
270 tmp2 = fMultDiv2(invBands, accu) << (2+1);
271
272 tmp2 = tmp1 + tmp2; /* y*CalcLd64(x)/64 + y*k/64 */
273 gmTransp = CalcInvLdData(tmp2); /* CalcInvLd64(z'); */
274 }
275 else {
276 gmTransp = FL2FXCONST_DBL(0.0f);
277 }
278 if ( amOrig != FL2FXCONST_DBL(0.0f) )
279 pSfmOrigVec[i] = FDKsbrEnc_LSI_divide_scale_fract(gmOrig,amOrig,SFM_SCALE);
280
281 if ( amTransp != FL2FXCONST_DBL(0.0f) )
282 pSfmSbrVec[i] = FDKsbrEnc_LSI_divide_scale_fract(gmTransp,amTransp,SFM_SCALE);
283 }
284 }
285 }
286
287 /**************************************************************************/
288 /*!
289 \brief Calculates the input to the missing harmonics detection.
290
291
292 \return none.
293
294 */
295 /**************************************************************************/
296 static void calculateDetectorInput(FIXP_DBL **RESTRICT pQuotaBuffer, /*!< Pointer to tonality matrix. */
297 SCHAR *RESTRICT indexVector,
298 FIXP_DBL **RESTRICT tonalityDiff,
299 FIXP_DBL **RESTRICT pSfmOrig,
300 FIXP_DBL **RESTRICT pSfmSbr,
301 const UCHAR *freqBandTable,
302 INT nSfb,
303 INT noEstPerFrame,
304 INT move)
305 {
306 INT est;
307
308 /*
309 New estimate.
310 */
311 for (est=0; est < noEstPerFrame; est++) {
312
313 diff(pQuotaBuffer[est+move],
314 tonalityDiff[est+move],
315 freqBandTable,
316 nSfb,
317 indexVector);
318
319 calculateFlatnessMeasure(pQuotaBuffer[est+ move],
320 indexVector,
321 pSfmOrig[est + move],
322 pSfmSbr[est + move],
323 freqBandTable,
324 nSfb);
325 }
326 }
327
328
329 /**************************************************************************/
330 /*!
331 \brief Checks that the detection is not due to a LP filter
332
333 This function determines if a newly detected missing harmonics is not
334 in fact just a low-pass filtere input signal. If so, the detection is
335 removed.
336
337 \return none.
338
339 */
340 /**************************************************************************/
341 static void removeLowPassDetection(UCHAR *RESTRICT pAddHarmSfb,
342 UCHAR **RESTRICT pDetectionVectors,
343 INT start,
344 INT stop,
345 INT nSfb,
346 const UCHAR *RESTRICT pFreqBandTable,
347 FIXP_DBL *RESTRICT pNrgVector,
348 THRES_HOLDS mhThresh)
349
350 {
351 INT i,est;
352 INT maxDerivPos = pFreqBandTable[nSfb];
353 INT numBands = pFreqBandTable[nSfb];
354 FIXP_DBL nrgLow,nrgHigh;
355 FIXP_DBL nrgLD64,nrgLowLD64,nrgHighLD64,nrgDiffLD64;
356 FIXP_DBL valLD64,maxValLD64,maxValAboveLD64;
357 INT bLPsignal = 0;
358
359 maxValLD64 = FL2FXCONST_DBL(-1.0f);
360 for(i = numBands - 1 - 2; i > pFreqBandTable[0];i--){
361 nrgLow = pNrgVector[i];
362 nrgHigh = pNrgVector[i + 2];
363
364 if(nrgLow != FL2FXCONST_DBL(0.0f) && nrgLow > nrgHigh){
365 nrgLowLD64 = CalcLdData(nrgLow>>1);
366 nrgDiffLD64 = CalcLdData((nrgLow>>1)-(nrgHigh>>1));
367 valLD64 = nrgDiffLD64-nrgLowLD64;
368 if(valLD64 > maxValLD64){
369 maxDerivPos = i;
370 maxValLD64 = valLD64;
371 }
372 if(maxValLD64 > mhThresh.derivThresMaxLD64) {
373 break;
374 }
375 }
376 }
377
378 /* Find the largest "gradient" above. (should be relatively flat, hence we expect a low value
379 if the signal is LP.*/
380 maxValAboveLD64 = FL2FXCONST_DBL(-1.0f);
381 for(i = numBands - 1 - 2; i > maxDerivPos + 2;i--){
382 nrgLow = pNrgVector[i];
383 nrgHigh = pNrgVector[i + 2];
384
385 if(nrgLow != FL2FXCONST_DBL(0.0f) && nrgLow > nrgHigh){
386 nrgLowLD64 = CalcLdData(nrgLow>>1);
387 nrgDiffLD64 = CalcLdData((nrgLow>>1)-(nrgHigh>>1));
388 valLD64 = nrgDiffLD64-nrgLowLD64;
389 if(valLD64 > maxValAboveLD64){
390 maxValAboveLD64 = valLD64;
391 }
392 }
393 else {
394 if(nrgHigh != FL2FXCONST_DBL(0.0f) && nrgHigh > nrgLow){
395 nrgHighLD64 = CalcLdData(nrgHigh>>1);
396 nrgDiffLD64 = CalcLdData((nrgHigh>>1)-(nrgLow>>1));
397 valLD64 = nrgDiffLD64-nrgHighLD64;
398 if(valLD64 > maxValAboveLD64){
399 maxValAboveLD64 = valLD64;
400 }
401 }
402 }
403 }
404
405 if(maxValLD64 > mhThresh.derivThresMaxLD64 && maxValAboveLD64 < mhThresh.derivThresAboveLD64){
406 bLPsignal = 1;
407
408 for(i = maxDerivPos - 1; i > maxDerivPos - 5 && i >= 0 ; i--){
409 if(pNrgVector[i] != FL2FXCONST_DBL(0.0f) && pNrgVector[i] > pNrgVector[maxDerivPos + 2]){
410 nrgDiffLD64 = CalcLdData((pNrgVector[i]>>1)-(pNrgVector[maxDerivPos + 2]>>1));
411 nrgLD64 = CalcLdData(pNrgVector[i]>>1);
412 valLD64 = nrgDiffLD64-nrgLD64;
413 if(valLD64 < mhThresh.derivThresBelowLD64) {
414 bLPsignal = 0;
415 break;
416 }
417 }
418 else{
419 bLPsignal = 0;
420 break;
421 }
422 }
423 }
424
425 if(bLPsignal){
426 for(i=0;i<nSfb;i++){
427 if(maxDerivPos >= pFreqBandTable[i] && maxDerivPos < pFreqBandTable[i+1])
428 break;
429 }
430
431 if(pAddHarmSfb[i]){
432 pAddHarmSfb[i] = 0;
433 for(est = start; est < stop ; est++){
434 pDetectionVectors[est][i] = 0;
435 }
436 }
437 }
438 }
439
440 /**************************************************************************/
441 /*!
442 \brief Checks if it is allowed to detect a missing tone, that wasn't
443 detected previously.
444
445
446 \return newDetectionAllowed flag.
447
448 */
449 /**************************************************************************/
450 static INT isDetectionOfNewToneAllowed(const SBR_FRAME_INFO *pFrameInfo,
451 INT *pDetectionStartPos,
452 INT noEstPerFrame,
453 INT prevTransientFrame,
454 INT prevTransientPos,
455 INT prevTransientFlag,
456 INT transientPosOffset,
457 INT transientFlag,
458 INT transientPos,
459 INT deltaTime,
460 HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMissingHarmonicsDetector)
461 {
462 INT transientFrame, newDetectionAllowed;
463
464
465 /* Determine if this is a frame where a transient starts...
466 * If the transient flag was set the previous frame but not the
467 * transient frame flag, the transient frame flag is set in the current frame.
468 *****************************************************************************/
469 transientFrame = 0;
470 if(transientFlag){
471 if(transientPos + transientPosOffset < pFrameInfo->borders[pFrameInfo->nEnvelopes])
472 transientFrame = 1;
473 if(noEstPerFrame > 1){
474 if(transientPos + transientPosOffset > h_sbrMissingHarmonicsDetector->timeSlots >> 1){
475 *pDetectionStartPos = noEstPerFrame;
476 }
477 else{
478 *pDetectionStartPos = noEstPerFrame >> 1;
479 }
480
481 }
482 else{
483 *pDetectionStartPos = noEstPerFrame;
484 }
485 }
486 else{
487 if(prevTransientFlag && !prevTransientFrame){
488 transientFrame = 1;
489 *pDetectionStartPos = 0;
490 }
491 }
492
493 /*
494 * Determine if detection of new missing harmonics are allowed.
495 * If the frame contains a transient it's ok. If the previous
496 * frame contained a transient it needs to be sufficiently close
497 * to the start of the current frame.
498 ****************************************************************/
499 newDetectionAllowed = 0;
500 if(transientFrame){
501 newDetectionAllowed = 1;
502 }
503 else {
504 if(prevTransientFrame &&
505 fixp_abs(pFrameInfo->borders[0] - (prevTransientPos + transientPosOffset -
506 h_sbrMissingHarmonicsDetector->timeSlots)) < deltaTime)
507 newDetectionAllowed = 1;
508 *pDetectionStartPos = 0;
509 }
510
511 h_sbrMissingHarmonicsDetector->previousTransientFlag = transientFlag;
512 h_sbrMissingHarmonicsDetector->previousTransientFrame = transientFrame;
513 h_sbrMissingHarmonicsDetector->previousTransientPos = transientPos;
514
515 return (newDetectionAllowed);
516 }
517
518
519 /**************************************************************************/
520 /*!
521 \brief Cleans up the detection after a transient.
522
523
524 \return none.
525
526 */
527 /**************************************************************************/
528 static void transientCleanUp(FIXP_DBL **quotaBuffer,
529 INT nSfb,
530 UCHAR **detectionVectors,
531 UCHAR *pAddHarmSfb,
532 UCHAR *pPrevAddHarmSfb,
533 INT ** signBuffer,
534 const UCHAR *pFreqBandTable,
535 INT start,
536 INT stop,
537 INT newDetectionAllowed,
538 FIXP_DBL *pNrgVector,
539 THRES_HOLDS mhThresh)
540 {
541 INT i,j,li, ui,est;
542
543 for(est=start; est < stop; est++) {
544 for(i=0; i<nSfb; i++) {
545 pAddHarmSfb[i] = pAddHarmSfb[i] || detectionVectors[est][i];
546 }
547 }
548
549 if(newDetectionAllowed == 1){
550 /*
551 * Check for duplication of sines located
552 * on the border of two scf-bands.
553 *************************************************/
554 for(i=0;i<nSfb-1;i++) {
555 li = pFreqBandTable[i];
556 ui = pFreqBandTable[i+1];
557
558 /* detection in adjacent channels.*/
559 if(pAddHarmSfb[i] && pAddHarmSfb[i+1]) {
560 FIXP_DBL maxVal1, maxVal2;
561 INT maxPos1, maxPos2, maxPosTime1, maxPosTime2;
562
563 li = pFreqBandTable[i];
564 ui = pFreqBandTable[i+1];
565
566 /* Find maximum tonality in the the two scf bands.*/
567 maxPosTime1 = start;
568 maxPos1 = li;
569 maxVal1 = quotaBuffer[start][li];
570 for(est = start; est < stop; est++){
571 for(j = li; j<ui; j++){
572 if(quotaBuffer[est][j] > maxVal1){
573 maxVal1 = quotaBuffer[est][j];
574 maxPos1 = j;
575 maxPosTime1 = est;
576 }
577 }
578 }
579
580 li = pFreqBandTable[i+1];
581 ui = pFreqBandTable[i+2];
582
583 /* Find maximum tonality in the the two scf bands.*/
584 maxPosTime2 = start;
585 maxPos2 = li;
586 maxVal2 = quotaBuffer[start][li];
587 for(est = start; est < stop; est++){
588 for(j = li; j<ui; j++){
589 if(quotaBuffer[est][j] > maxVal2){
590 maxVal2 = quotaBuffer[est][j];
591 maxPos2 = j;
592 maxPosTime2 = est;
593 }
594 }
595 }
596
597 /* If the maximum values are in adjacent QMF-channels, we need to remove
598 the lowest of the two.*/
599 if(maxPos2-maxPos1 < 2){
600
601 if(pPrevAddHarmSfb[i] == 1 && pPrevAddHarmSfb[i+1] == 0){
602 /* Keep the lower, remove the upper.*/
603 pAddHarmSfb[i+1] = 0;
604 for(est=start; est<stop; est++){
605 detectionVectors[est][i+1] = 0;
606 }
607 }
608 else{
609 if(pPrevAddHarmSfb[i] == 0 && pPrevAddHarmSfb[i+1] == 1){
610 /* Keep the upper, remove the lower.*/
611 pAddHarmSfb[i] = 0;
612 for(est=start; est<stop; est++){
613 detectionVectors[est][i] = 0;
614 }
615 }
616 else{
617 /* If the maximum values are in adjacent QMF-channels, and if the signs indicate that it is the same sine,
618 we need to remove the lowest of the two.*/
619 if(maxVal1 > maxVal2){
620 if(signBuffer[maxPosTime1][maxPos2] < 0 && signBuffer[maxPosTime1][maxPos1] > 0){
621 /* Keep the lower, remove the upper.*/
622 pAddHarmSfb[i+1] = 0;
623 for(est=start; est<stop; est++){
624 detectionVectors[est][i+1] = 0;
625 }
626 }
627 }
628 else{
629 if(signBuffer[maxPosTime2][maxPos2] < 0 && signBuffer[maxPosTime2][maxPos1] > 0){
630 /* Keep the upper, remove the lower.*/
631 pAddHarmSfb[i] = 0;
632 for(est=start; est<stop; est++){
633 detectionVectors[est][i] = 0;
634 }
635 }
636 }
637 }
638 }
639 }
640 }
641 }
642
643 /* Make sure that the detection is not the cut-off of a low pass filter. */
644 removeLowPassDetection(pAddHarmSfb,
645 detectionVectors,
646 start,
647 stop,
648 nSfb,
649 pFreqBandTable,
650 pNrgVector,
651 mhThresh);
652 }
653 else {
654 /*
655 * If a missing harmonic wasn't missing the previous frame
656 * the transient-flag needs to be set in order to be allowed to detect it.
657 *************************************************************************/
658 for(i=0;i<nSfb;i++){
659 if(pAddHarmSfb[i] - pPrevAddHarmSfb[i] > 0)
660 pAddHarmSfb[i] = 0;
661 }
662 }
663 }
664
665
666 /**************************************************************************/
667 /*!
668 \brief Do detection for one tonality estimate.
669
670
671 \return none.
672
673 */
674 /**************************************************************************/
675 static void detection(FIXP_DBL *quotaBuffer,
676 FIXP_DBL *pDiffVecScfb,
677 INT nSfb,
678 UCHAR *pHarmVec,
679 const UCHAR *pFreqBandTable,
680 FIXP_DBL *sfmOrig,
681 FIXP_DBL *sfmSbr,
682 GUIDE_VECTORS guideVectors,
683 GUIDE_VECTORS newGuideVectors,
684 THRES_HOLDS mhThresh)
685 {
686
687 INT i,j,ll, lu;
688 FIXP_DBL thresTemp,thresOrig;
689
690 /*
691 * Do detection on the difference vector, i.e. the difference between
692 * the original and the transposed.
693 *********************************************************************/
694 for(i=0;i<nSfb;i++){
695
696 thresTemp = (guideVectors.guideVectorDiff[i] != FL2FXCONST_DBL(0.0f))
697 ? fixMax(fMult(mhThresh.decayGuideDiff,guideVectors.guideVectorDiff[i]), mhThresh.thresHoldDiffGuide)
698 : mhThresh.thresHoldDiff;
699
700 thresTemp = fixMin(thresTemp, mhThresh.thresHoldDiff);
701
702 if(pDiffVecScfb[i] > thresTemp){
703 pHarmVec[i] = 1;
704 newGuideVectors.guideVectorDiff[i] = pDiffVecScfb[i];
705 }
706 else{
707 /* If the guide wasn't zero, but the current level is to low,
708 start tracking the decay on the tone in the original rather
709 than the difference.*/
710 if(guideVectors.guideVectorDiff[i] != FL2FXCONST_DBL(0.0f)){
711 guideVectors.guideVectorOrig[i] = mhThresh.thresHoldToneGuide;
712 }
713 }
714 }
715
716 /*
717 * Trace tones in the original signal that at one point
718 * have been detected because they will be replaced by
719 * multiple tones in the sbr signal.
720 ****************************************************/
721
722 for(i=0;i<nSfb;i++){
723 ll = pFreqBandTable[i];
724 lu = pFreqBandTable[i+1];
725
726 thresOrig = fixMax(fMult(guideVectors.guideVectorOrig[i], mhThresh.decayGuideOrig), mhThresh.thresHoldToneGuide);
727 thresOrig = fixMin(thresOrig, mhThresh.thresHoldTone);
728
729 if(guideVectors.guideVectorOrig[i] != FL2FXCONST_DBL(0.0f)){
730 for(j= ll;j<lu;j++){
731 if(quotaBuffer[j] > thresOrig){
732 pHarmVec[i] = 1;
733 newGuideVectors.guideVectorOrig[i] = quotaBuffer[j];
734 }
735 }
736 }
737 }
738
739 /*
740 * Check for multiple sines in the transposed signal,
741 * where there is only one in the original.
742 ****************************************************/
743 thresOrig = mhThresh.thresHoldTone;
744
745 for(i=0;i<nSfb;i++){
746 ll = pFreqBandTable[i];
747 lu = pFreqBandTable[i+1];
748
749 if(pHarmVec[i] == 0){
750 if(lu -ll > 1){
751 for(j= ll;j<lu;j++){
752 if(quotaBuffer[j] > thresOrig && (sfmSbr[i] > mhThresh.sfmThresSbr && sfmOrig[i] < mhThresh.sfmThresOrig)){
753 pHarmVec[i] = 1;
754 newGuideVectors.guideVectorOrig[i] = quotaBuffer[j];
755 }
756 }
757 }
758 else{
759 if(i < nSfb -1){
760 ll = pFreqBandTable[i];
761
762 if(i>0){
763 if(quotaBuffer[ll] > mhThresh.thresHoldTone && (pDiffVecScfb[i+1] < mhThresh.invThresHoldTone || pDiffVecScfb[i-1] < mhThresh.invThresHoldTone)){
764 pHarmVec[i] = 1;
765 newGuideVectors.guideVectorOrig[i] = quotaBuffer[ll];
766 }
767 }
768 else{
769 if(quotaBuffer[ll] > mhThresh.thresHoldTone && pDiffVecScfb[i+1] < mhThresh.invThresHoldTone){
770 pHarmVec[i] = 1;
771 newGuideVectors.guideVectorOrig[i] = quotaBuffer[ll];
772 }
773 }
774 }
775 }
776 }
777 }
778 }
779
780
781 /**************************************************************************/
782 /*!
783 \brief Do detection for every tonality estimate, using forward prediction.
784
785
786 \return none.
787
788 */
789 /**************************************************************************/
790 static void detectionWithPrediction(FIXP_DBL **quotaBuffer,
791 FIXP_DBL **pDiffVecScfb,
792 INT ** signBuffer,
793 INT nSfb,
794 const UCHAR* pFreqBandTable,
795 FIXP_DBL **sfmOrig,
796 FIXP_DBL **sfmSbr,
797 UCHAR **detectionVectors,
798 UCHAR *pPrevAddHarmSfb,
799 GUIDE_VECTORS *guideVectors,
800 INT noEstPerFrame,
801 INT detectionStart,
802 INT totNoEst,
803 INT newDetectionAllowed,
804 INT *pAddHarmFlag,
805 UCHAR *pAddHarmSfb,
806 FIXP_DBL *pNrgVector,
807 const DETECTOR_PARAMETERS_MH *mhParams)
808 {
809 INT est = 0,i;
810 INT start;
811
812 FDKmemclear(pAddHarmSfb,nSfb*sizeof(UCHAR));
813
814 if(newDetectionAllowed){
815
816 if(totNoEst > 1){
817 start = detectionStart;
818
819 if (start != 0) {
820 FDKmemcpy(guideVectors[start].guideVectorDiff,guideVectors[0].guideVectorDiff,nSfb*sizeof(FIXP_DBL));
821 FDKmemcpy(guideVectors[start].guideVectorOrig,guideVectors[0].guideVectorOrig,nSfb*sizeof(FIXP_DBL));
822 FDKmemclear(guideVectors[start-1].guideVectorDetected,nSfb*sizeof(UCHAR));
823 }
824 }
825 else{
826 start = 0;
827 }
828 }
829 else{
830 start = 0;
831 }
832
833
834 for(est = start; est < totNoEst; est++){
835
836 /*
837 * Do detection on the current frame using
838 * guide-info from the previous.
839 *******************************************/
840 if(est > 0){
841 FDKmemcpy(guideVectors[est].guideVectorDetected,detectionVectors[est-1],nSfb*sizeof(UCHAR));
842 }
843
844 FDKmemclear(detectionVectors[est], nSfb*sizeof(UCHAR));
845
846 if(est < totNoEst-1){
847 FDKmemclear(guideVectors[est+1].guideVectorDiff,nSfb*sizeof(FIXP_DBL));
848 FDKmemclear(guideVectors[est+1].guideVectorOrig,nSfb*sizeof(FIXP_DBL));
849 FDKmemclear(guideVectors[est+1].guideVectorDetected,nSfb*sizeof(UCHAR));
850
851 detection(quotaBuffer[est],
852 pDiffVecScfb[est],
853 nSfb,
854 detectionVectors[est],
855 pFreqBandTable,
856 sfmOrig[est],
857 sfmSbr[est],
858 guideVectors[est],
859 guideVectors[est+1],
860 mhParams->thresHolds);
861 }
862 else{
863 FDKmemclear(guideVectors[est].guideVectorDiff,nSfb*sizeof(FIXP_DBL));
864 FDKmemclear(guideVectors[est].guideVectorOrig,nSfb*sizeof(FIXP_DBL));
865 FDKmemclear(guideVectors[est].guideVectorDetected,nSfb*sizeof(UCHAR));
866
867 detection(quotaBuffer[est],
868 pDiffVecScfb[est],
869 nSfb,
870 detectionVectors[est],
871 pFreqBandTable,
872 sfmOrig[est],
873 sfmSbr[est],
874 guideVectors[est],
875 guideVectors[est],
876 mhParams->thresHolds);
877 }
878 }
879
880
881 /* Clean up the detection.*/
882 transientCleanUp(quotaBuffer,
883 nSfb,
884 detectionVectors,
885 pAddHarmSfb,
886 pPrevAddHarmSfb,
887 signBuffer,
888 pFreqBandTable,
889 start,
890 totNoEst,
891 newDetectionAllowed,
892 pNrgVector,
893 mhParams->thresHolds);
894
895
896 /* Set flag... */
897 *pAddHarmFlag = 0;
898 for(i=0; i<nSfb; i++){
899 if(pAddHarmSfb[i]){
900 *pAddHarmFlag = 1;
901 break;
902 }
903 }
904
905 FDKmemcpy(pPrevAddHarmSfb, pAddHarmSfb, nSfb*sizeof(UCHAR));
906 FDKmemcpy(guideVectors[0].guideVectorDetected,pAddHarmSfb,nSfb*sizeof(INT));
907
908 for(i=0; i<nSfb ; i++){
909
910 guideVectors[0].guideVectorDiff[i] = FL2FXCONST_DBL(0.0f);
911 guideVectors[0].guideVectorOrig[i] = FL2FXCONST_DBL(0.0f);
912
913 if(pAddHarmSfb[i] == 1){
914 /* If we had a detection use the guide-value in the next frame from the last estimate were the detection
915 was done.*/
916 for(est=start; est < totNoEst; est++){
917 if(guideVectors[est].guideVectorDiff[i] != FL2FXCONST_DBL(0.0f)){
918 guideVectors[0].guideVectorDiff[i] = guideVectors[est].guideVectorDiff[i];
919 }
920 if(guideVectors[est].guideVectorOrig[i] != FL2FXCONST_DBL(0.0f)){
921 guideVectors[0].guideVectorOrig[i] = guideVectors[est].guideVectorOrig[i];
922 }
923 }
924 }
925 }
926
927 }
928
929
930 /**************************************************************************/
931 /*!
932 \brief Calculates a compensation vector for the energy data.
933
934 This function calculates a compensation vector for the energy data (i.e.
935 envelope data) that is calculated elsewhere. This is since, one sine on
936 the border of two scalefactor bands, will be replace by one sine in the
937 middle of either scalefactor band. However, since the sine that is replaced
938 will influence the energy estimate in both scalefactor bands (in the envelops
939 calculation function) a compensation value is required in order to avoid
940 noise substitution in the decoder next to the synthetic sine.
941
942 \return none.
943
944 */
945 /**************************************************************************/
946 static void calculateCompVector(UCHAR *pAddHarmSfb,
947 FIXP_DBL **pTonalityMatrix,
948 INT ** pSignMatrix,
949 UCHAR *pEnvComp,
950 INT nSfb,
951 const UCHAR *freqBandTable,
952 INT totNoEst,
953 INT maxComp,
954 UCHAR *pPrevEnvComp,
955 INT newDetectionAllowed)
956 {
957
958 INT scfBand,est,l,ll,lu,maxPosF,maxPosT;
959 FIXP_DBL maxVal;
960 INT compValue;
961 FIXP_DBL tmp;
962
963 FDKmemclear(pEnvComp,nSfb*sizeof(UCHAR));
964
965 for(scfBand=0; scfBand < nSfb; scfBand++){
966
967 if(pAddHarmSfb[scfBand]){ /* A missing sine was detected */
968 ll = freqBandTable[scfBand];
969 lu = freqBandTable[scfBand+1];
970
971 maxPosF = 0; /* First find the maximum*/
972 maxPosT = 0;
973 maxVal = FL2FXCONST_DBL(0.0f);
974
975 for(est=0;est<totNoEst;est++){
976 for(l=ll; l<lu; l++){
977 if(pTonalityMatrix[est][l] > maxVal){
978 maxVal = pTonalityMatrix[est][l];
979 maxPosF = l;
980 maxPosT = est;
981 }
982 }
983 }
984
985 /*
986 * If the maximum tonality is at the lower border of the
987 * scalefactor band, we check the sign of the adjacent channels
988 * to see if this sine is shared by the lower channel. If so, the
989 * energy of the single sine will be present in two scalefactor bands
990 * in the SBR data, which will cause problems in the decoder, when we
991 * add a sine to just one of the channels.
992 *********************************************************************/
993 if(maxPosF == ll && scfBand){
994 if(!pAddHarmSfb[scfBand - 1]) { /* No detection below*/
995 if (pSignMatrix[maxPosT][maxPosF - 1] > 0 && pSignMatrix[maxPosT][maxPosF] < 0) {
996 /* The comp value is calulated as the tonallity value, i.e we want to
997 reduce the envelope data for this channel with as much as the tonality
998 that is spread from the channel above. (ld64(RELAXATION) = 0.31143075889) */
999 tmp = fixp_abs((FIXP_DBL)CalcLdData(pTonalityMatrix[maxPosT][maxPosF - 1]) + RELAXATION_LD64);
1000 tmp = (tmp >> (DFRACT_BITS-1-LD_DATA_SHIFT-1)) + (FIXP_DBL)1; /* shift one bit less for rounding */
1001 compValue = ((INT)(LONG)tmp) >> 1;
1002
1003 /* limit the comp-value*/
1004 if (compValue > maxComp)
1005 compValue = maxComp;
1006
1007 pEnvComp[scfBand-1] = compValue;
1008 }
1009 }
1010 }
1011
1012 /*
1013 * Same as above, but for the upper end of the scalefactor-band.
1014 ***************************************************************/
1015 if(maxPosF == lu-1 && scfBand+1 < nSfb){ /* Upper border*/
1016 if(!pAddHarmSfb[scfBand + 1]) {
1017 if (pSignMatrix[maxPosT][maxPosF] > 0 && pSignMatrix[maxPosT][maxPosF + 1] < 0) {
1018 tmp = fixp_abs((FIXP_DBL)CalcLdData(pTonalityMatrix[maxPosT][maxPosF + 1]) + RELAXATION_LD64);
1019 tmp = (tmp >> (DFRACT_BITS-1-LD_DATA_SHIFT-1)) + (FIXP_DBL)1; /* shift one bit less for rounding */
1020 compValue = ((INT)(LONG)tmp) >> 1;
1021
1022 if (compValue > maxComp)
1023 compValue = maxComp;
1024
1025 pEnvComp[scfBand+1] = compValue;
1026 }
1027 }
1028 }
1029 }
1030 }
1031
1032 if(newDetectionAllowed == 0){
1033 for(scfBand=0;scfBand<nSfb;scfBand++){
1034 if(pEnvComp[scfBand] != 0 && pPrevEnvComp[scfBand] == 0)
1035 pEnvComp[scfBand] = 0;
1036 }
1037 }
1038
1039 /* remember the value for the next frame.*/
1040 FDKmemcpy(pPrevEnvComp,pEnvComp,nSfb*sizeof(UCHAR));
1041 }
1042
1043
1044 /**************************************************************************/
1045 /*!
1046 \brief Detects where strong tonal components will be missing after
1047 HFR in the decoder.
1048
1049
1050 \return none.
1051
1052 */
1053 /**************************************************************************/
1054 void
1055 FDKsbrEnc_SbrMissingHarmonicsDetectorQmf(HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMHDet,
1056 FIXP_DBL ** pQuotaBuffer,
1057 INT ** pSignBuffer,
1058 SCHAR* indexVector,
1059 const SBR_FRAME_INFO *pFrameInfo,
1060 const UCHAR* pTranInfo,
1061 INT* pAddHarmonicsFlag,
1062 UCHAR* pAddHarmonicsScaleFactorBands,
1063 const UCHAR* freqBandTable,
1064 INT nSfb,
1065 UCHAR* envelopeCompensation,
1066 FIXP_DBL *pNrgVector)
1067 {
1068 INT transientFlag = pTranInfo[1];
1069 INT transientPos = pTranInfo[0];
1070 INT newDetectionAllowed;
1071 INT transientDetStart = 0;
1072
1073 UCHAR ** detectionVectors = h_sbrMHDet->detectionVectors;
1074 INT move = h_sbrMHDet->move;
1075 INT noEstPerFrame = h_sbrMHDet->noEstPerFrame;
1076 INT totNoEst = h_sbrMHDet->totNoEst;
1077 INT prevTransientFlag = h_sbrMHDet->previousTransientFlag;
1078 INT prevTransientFrame = h_sbrMHDet->previousTransientFrame;
1079 INT transientPosOffset = h_sbrMHDet->transientPosOffset;
1080 INT prevTransientPos = h_sbrMHDet->previousTransientPos;
1081 GUIDE_VECTORS* guideVectors = h_sbrMHDet->guideVectors;
1082 INT deltaTime = h_sbrMHDet->mhParams->deltaTime;
1083 INT maxComp = h_sbrMHDet->mhParams->maxComp;
1084
1085 int est;
1086
1087 /*
1088 Buffer values.
1089 */
1090 FDK_ASSERT(move<=(MAX_NO_OF_ESTIMATES>>1));
1091 FDK_ASSERT(noEstPerFrame<=(MAX_NO_OF_ESTIMATES>>1));
1092
1093 FIXP_DBL *sfmSbr[MAX_NO_OF_ESTIMATES];
1094 FIXP_DBL *sfmOrig[MAX_NO_OF_ESTIMATES];
1095 FIXP_DBL *tonalityDiff[MAX_NO_OF_ESTIMATES];
1096
1097 for (est=0; est < MAX_NO_OF_ESTIMATES/2; est++) {
1098 sfmSbr[est] = h_sbrMHDet->sfmSbr[est];
1099 sfmOrig[est] = h_sbrMHDet->sfmOrig[est];
1100 tonalityDiff[est] = h_sbrMHDet->tonalityDiff[est];
1101 }
1102
1103 C_ALLOC_SCRATCH_START(scratch_mem, FIXP_DBL, (3*MAX_NO_OF_ESTIMATES/2*MAX_FREQ_COEFFS));
1104 FIXP_DBL *scratch = scratch_mem;
1105 for (; est < MAX_NO_OF_ESTIMATES; est++) {
1106 sfmSbr[est] = scratch; scratch+=MAX_FREQ_COEFFS;
1107 sfmOrig[est] = scratch; scratch+=MAX_FREQ_COEFFS;
1108 tonalityDiff[est] = scratch; scratch+=MAX_FREQ_COEFFS;
1109 }
1110
1111
1112
1113 /* Determine if we're allowed to detect "missing harmonics" that wasn't detected before.
1114 In order to be allowed to do new detection, there must be a transient in the current
1115 frame, or a transient in the previous frame sufficiently close to the current frame. */
1116 newDetectionAllowed = isDetectionOfNewToneAllowed(pFrameInfo,
1117 &transientDetStart,
1118 noEstPerFrame,
1119 prevTransientFrame,
1120 prevTransientPos,
1121 prevTransientFlag,
1122 transientPosOffset,
1123 transientFlag,
1124 transientPos,
1125 deltaTime,
1126 h_sbrMHDet);
1127
1128 /* Calulate the variables that will be used subsequently for the actual detection */
1129 calculateDetectorInput(pQuotaBuffer,
1130 indexVector,
1131 tonalityDiff,
1132 sfmOrig,
1133 sfmSbr,
1134 freqBandTable,
1135 nSfb,
1136 noEstPerFrame,
1137 move);
1138
1139 /* Do the actual detection using information from previous detections */
1140 detectionWithPrediction(pQuotaBuffer,
1141 tonalityDiff,
1142 pSignBuffer,
1143 nSfb,
1144 freqBandTable,
1145 sfmOrig,
1146 sfmSbr,
1147 detectionVectors,
1148 h_sbrMHDet->guideScfb,
1149 guideVectors,
1150 noEstPerFrame,
1151 transientDetStart,
1152 totNoEst,
1153 newDetectionAllowed,
1154 pAddHarmonicsFlag,
1155 pAddHarmonicsScaleFactorBands,
1156 pNrgVector,
1157 h_sbrMHDet->mhParams);
1158
1159 /* Calculate the comp vector, so that the energy can be
1160 compensated for a sine between two QMF-bands. */
1161 calculateCompVector(pAddHarmonicsScaleFactorBands,
1162 pQuotaBuffer,
1163 pSignBuffer,
1164 envelopeCompensation,
1165 nSfb,
1166 freqBandTable,
1167 totNoEst,
1168 maxComp,
1169 h_sbrMHDet->prevEnvelopeCompensation,
1170 newDetectionAllowed);
1171
1172 for (est=0; est < move; est++) {
1173 FDKmemcpy(tonalityDiff[est], tonalityDiff[est + noEstPerFrame], sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
1174 FDKmemcpy(sfmOrig[est], sfmOrig[est + noEstPerFrame], sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
1175 FDKmemcpy(sfmSbr[est], sfmSbr[est + noEstPerFrame], sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
1176 }
1177 C_ALLOC_SCRATCH_END(scratch, FIXP_DBL, (3*MAX_NO_OF_ESTIMATES/2*MAX_FREQ_COEFFS));
1178
1179
1180 }
1181
1182 /**************************************************************************/
1183 /*!
1184 \brief Initialize an instance of the missing harmonics detector.
1185
1186
1187 \return errorCode, noError if OK.
1188
1189 */
1190 /**************************************************************************/
1191 INT
1192 FDKsbrEnc_CreateSbrMissingHarmonicsDetector (
1193 HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet,
1194 INT chan)
1195 {
1196 HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet;
1197 INT i;
1198
1199 UCHAR* detectionVectors = GetRam_Sbr_detectionVectors(chan);
1200 UCHAR* guideVectorDetected = GetRam_Sbr_guideVectorDetected(chan);
1201 FIXP_DBL* guideVectorDiff = GetRam_Sbr_guideVectorDiff(chan);
1202 FIXP_DBL* guideVectorOrig = GetRam_Sbr_guideVectorOrig(chan);
1203
1204 FDKmemclear (hs,sizeof(SBR_MISSING_HARMONICS_DETECTOR));
1205
1206 hs->prevEnvelopeCompensation = GetRam_Sbr_prevEnvelopeCompensation(chan);
1207 hs->guideScfb = GetRam_Sbr_guideScfb(chan);
1208
1209 for(i=0; i<MAX_NO_OF_ESTIMATES; i++) {
1210 hs->guideVectors[i].guideVectorDiff = guideVectorDiff + (i*MAX_FREQ_COEFFS);
1211 hs->guideVectors[i].guideVectorOrig = guideVectorOrig + (i*MAX_FREQ_COEFFS);
1212 hs->detectionVectors[i] = detectionVectors + (i*MAX_FREQ_COEFFS);
1213 hs->guideVectors[i].guideVectorDetected = guideVectorDetected + (i*MAX_FREQ_COEFFS);
1214 }
1215
1216 return 0;
1217 }
1218
1219
1220 /**************************************************************************/
1221 /*!
1222 \brief Initialize an instance of the missing harmonics detector.
1223
1224
1225 \return errorCode, noError if OK.
1226
1227 */
1228 /**************************************************************************/
1229 INT
1230 FDKsbrEnc_InitSbrMissingHarmonicsDetector (
1231 HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet,
1232 INT sampleFreq,
1233 INT frameSize,
1234 INT nSfb,
1235 INT qmfNoChannels,
1236 INT totNoEst,
1237 INT move,
1238 INT noEstPerFrame,
1239 UINT sbrSyntaxFlags
1240 )
1241 {
1242 HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet;
1243 int i;
1244
1245 FDK_ASSERT(totNoEst <= MAX_NO_OF_ESTIMATES);
1246
1247 if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY)
1248 {
1249 switch(frameSize){
1250 case 1024:
1251 case 512:
1252 hs->transientPosOffset = FRAME_MIDDLE_SLOT_512LD;
1253 hs->timeSlots = 16;
1254 break;
1255 case 960:
1256 case 480:
1257 hs->transientPosOffset = FRAME_MIDDLE_SLOT_512LD;
1258 hs->timeSlots = 15;
1259 break;
1260 default:
1261 return -1;
1262 }
1263 } else
1264 {
1265 switch(frameSize){
1266 case 2048:
1267 case 1024:
1268 hs->transientPosOffset = FRAME_MIDDLE_SLOT_2048;
1269 hs->timeSlots = NUMBER_TIME_SLOTS_2048;
1270 break;
1271 case 1920:
1272 case 960:
1273 hs->transientPosOffset = FRAME_MIDDLE_SLOT_1920;
1274 hs->timeSlots = NUMBER_TIME_SLOTS_1920;
1275 break;
1276 default:
1277 return -1;
1278 }
1279 }
1280
1281 if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) {
1282 hs->mhParams = &paramsAacLd;
1283 } else
1284 hs->mhParams = &paramsAac;
1285
1286 hs->qmfNoChannels = qmfNoChannels;
1287 hs->sampleFreq = sampleFreq;
1288 hs->nSfb = nSfb;
1289
1290 hs->totNoEst = totNoEst;
1291 hs->move = move;
1292 hs->noEstPerFrame = noEstPerFrame;
1293
1294 for(i=0; i<totNoEst; i++) {
1295 FDKmemclear (hs->guideVectors[i].guideVectorDiff,sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
1296 FDKmemclear (hs->guideVectors[i].guideVectorOrig,sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
1297 FDKmemclear (hs->detectionVectors[i],sizeof(UCHAR)*MAX_FREQ_COEFFS);
1298 FDKmemclear (hs->guideVectors[i].guideVectorDetected,sizeof(UCHAR)*MAX_FREQ_COEFFS);
1299 }
1300
1301 //for(i=0; i<totNoEst/2; i++) {
1302 for(i=0; i<MAX_NO_OF_ESTIMATES/2; i++) {
1303 FDKmemclear (hs->tonalityDiff[i],sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
1304 FDKmemclear (hs->sfmOrig[i],sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
1305 FDKmemclear (hs->sfmSbr[i],sizeof(FIXP_DBL)*MAX_FREQ_COEFFS);
1306 }
1307
1308 FDKmemclear ( hs->prevEnvelopeCompensation, sizeof(UCHAR)*MAX_FREQ_COEFFS);
1309 FDKmemclear ( hs->guideScfb, sizeof(UCHAR)*MAX_FREQ_COEFFS);
1310
1311 hs->previousTransientFlag = 0;
1312 hs->previousTransientFrame = 0;
1313 hs->previousTransientPos = 0;
1314
1315 return (0);
1316 }
1317
1318 /**************************************************************************/
1319 /*!
1320 \brief Deletes an instance of the missing harmonics detector.
1321
1322
1323 \return none.
1324
1325 */
1326 /**************************************************************************/
1327 void
1328 FDKsbrEnc_DeleteSbrMissingHarmonicsDetector(HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet)
1329 {
1330 if (hSbrMHDet) {
1331 HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet;
1332
1333 FreeRam_Sbr_detectionVectors(&hs->detectionVectors[0]);
1334 FreeRam_Sbr_guideVectorDetected(&hs->guideVectors[0].guideVectorDetected);
1335 FreeRam_Sbr_guideVectorDiff(&hs->guideVectors[0].guideVectorDiff);
1336 FreeRam_Sbr_guideVectorOrig(&hs->guideVectors[0].guideVectorOrig);
1337 FreeRam_Sbr_prevEnvelopeCompensation(&hs->prevEnvelopeCompensation);
1338 FreeRam_Sbr_guideScfb(&hs->guideScfb);
1339
1340 }
1341 }
1342
1343 /**************************************************************************/
1344 /*!
1345 \brief Resets an instance of the missing harmonics detector.
1346
1347
1348 \return error code, noError if OK.
1349
1350 */
1351 /**************************************************************************/
1352 INT
1353 FDKsbrEnc_ResetSbrMissingHarmonicsDetector (HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMissingHarmonicsDetector,
1354 INT nSfb)
1355 {
1356 int i;
1357 FIXP_DBL tempGuide[MAX_FREQ_COEFFS];
1358 UCHAR tempGuideInt[MAX_FREQ_COEFFS];
1359 INT nSfbPrev;
1360
1361 nSfbPrev = hSbrMissingHarmonicsDetector->nSfb;
1362 hSbrMissingHarmonicsDetector->nSfb = nSfb;
1363
1364 FDKmemcpy( tempGuideInt, hSbrMissingHarmonicsDetector->guideScfb, nSfbPrev * sizeof(UCHAR) );
1365
1366 if ( nSfb > nSfbPrev ) {
1367 for ( i = 0; i < (nSfb - nSfbPrev); i++ ) {
1368 hSbrMissingHarmonicsDetector->guideScfb[i] = 0;
1369 }
1370
1371 for ( i = 0; i < nSfbPrev; i++ ) {
1372 hSbrMissingHarmonicsDetector->guideScfb[i + (nSfb - nSfbPrev)] = tempGuideInt[i];
1373 }
1374 }
1375 else {
1376 for ( i = 0; i < nSfb; i++ ) {
1377 hSbrMissingHarmonicsDetector->guideScfb[i] = tempGuideInt[i + (nSfbPrev-nSfb)];
1378 }
1379 }
1380
1381 FDKmemcpy ( tempGuide, hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff, nSfbPrev * sizeof(FIXP_DBL) );
1382
1383 if (nSfb > nSfbPrev ) {
1384 for ( i = 0; i < (nSfb - nSfbPrev); i++ ) {
1385 hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff[i] = FL2FXCONST_DBL(0.0f);
1386 }
1387
1388 for ( i = 0; i < nSfbPrev; i++ ) {
1389 hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff[i + (nSfb - nSfbPrev)] = tempGuide[i];
1390 }
1391 }
1392 else {
1393 for ( i = 0; i < nSfb; i++ ) {
1394 hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff[i] = tempGuide[i + (nSfbPrev-nSfb)];
1395 }
1396 }
1397
1398 FDKmemcpy ( tempGuide, hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig, nSfbPrev * sizeof(FIXP_DBL) );
1399
1400 if ( nSfb > nSfbPrev ) {
1401 for ( i = 0; i< (nSfb - nSfbPrev); i++ ) {
1402 hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig[i] = FL2FXCONST_DBL(0.0f);
1403 }
1404
1405 for ( i = 0; i < nSfbPrev; i++ ) {
1406 hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig[i + (nSfb - nSfbPrev)] = tempGuide[i];
1407 }
1408 }
1409 else {
1410 for ( i = 0; i < nSfb; i++ ) {
1411 hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig[i] = tempGuide[i + (nSfbPrev-nSfb)];
1412 }
1413 }
1414
1415 FDKmemcpy ( tempGuideInt, hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected, nSfbPrev * sizeof(UCHAR) );
1416
1417 if ( nSfb > nSfbPrev ) {
1418 for ( i = 0; i < (nSfb - nSfbPrev); i++ ) {
1419 hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected[i] = 0;
1420 }
1421
1422 for ( i = 0; i < nSfbPrev; i++ ) {
1423 hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected[i + (nSfb - nSfbPrev)] = tempGuideInt[i];
1424 }
1425 }
1426 else {
1427 for ( i = 0; i < nSfb; i++ ) {
1428 hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected[i] = tempGuideInt[i + (nSfbPrev-nSfb)];
1429 }
1430 }
1431
1432 FDKmemcpy ( tempGuideInt, hSbrMissingHarmonicsDetector->prevEnvelopeCompensation, nSfbPrev * sizeof(UCHAR) );
1433
1434 if ( nSfb > nSfbPrev ) {
1435 for ( i = 0; i < (nSfb - nSfbPrev); i++ ) {
1436 hSbrMissingHarmonicsDetector->prevEnvelopeCompensation[i] = 0;
1437 }
1438
1439 for ( i = 0; i < nSfbPrev; i++ ) {
1440 hSbrMissingHarmonicsDetector->prevEnvelopeCompensation[i + (nSfb - nSfbPrev)] = tempGuideInt[i];
1441 }
1442 }
1443 else {
1444 for ( i = 0; i < nSfb; i++ ) {
1445 hSbrMissingHarmonicsDetector->prevEnvelopeCompensation[i] = tempGuideInt[i + (nSfbPrev-nSfb)];
1446 }
1447 }
1448
1449 return 0;
1450 }
1451