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