• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -----------------------------------------------------------------------------
2 Software License for The Fraunhofer FDK AAC Codec Library for Android
3 
4 © Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
5 Forschung e.V. All rights reserved.
6 
7  1.    INTRODUCTION
8 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
9 that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
10 scheme for digital audio. This FDK AAC Codec software is intended to be used on
11 a wide variety of Android devices.
12 
13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
14 general perceptual audio codecs. AAC-ELD is considered the best-performing
15 full-bandwidth communications codec by independent studies and is widely
16 deployed. AAC has been standardized by ISO and IEC as part of the MPEG
17 specifications.
18 
19 Patent licenses for necessary patent claims for the FDK AAC Codec (including
20 those of Fraunhofer) may be obtained through Via Licensing
21 (www.vialicensing.com) or through the respective patent owners individually for
22 the purpose of encoding or decoding bit streams in products that are compliant
23 with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
24 Android devices already license these patent claims through Via Licensing or
25 directly from the patent owners, and therefore FDK AAC Codec software may
26 already be covered under those patent licenses when it is used for those
27 licensed purposes only.
28 
29 Commercially-licensed AAC software libraries, including floating-point versions
30 with enhanced sound quality, are also available from Fraunhofer. Users are
31 encouraged to check the Fraunhofer website for additional applications
32 information and documentation.
33 
34 2.    COPYRIGHT LICENSE
35 
36 Redistribution and use in source and binary forms, with or without modification,
37 are permitted without payment of copyright license fees provided that you
38 satisfy the following conditions:
39 
40 You must retain the complete text of this software license in redistributions of
41 the FDK AAC Codec or your modifications thereto in source code form.
42 
43 You must retain the complete text of this software license in the documentation
44 and/or other materials provided with redistributions of the FDK AAC Codec or
45 your modifications thereto in binary form. You must make available free of
46 charge copies of the complete source code of the FDK AAC Codec and your
47 modifications thereto to recipients of copies in binary form.
48 
49 The name of Fraunhofer may not be used to endorse or promote products derived
50 from this library without prior written permission.
51 
52 You may not charge copyright license fees for anyone to use, copy or distribute
53 the FDK AAC Codec software or your modifications thereto.
54 
55 Your modified versions of the FDK AAC Codec must carry prominent notices stating
56 that you changed the software and the date of any change. For modified versions
57 of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
58 must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
59 AAC Codec Library for Android."
60 
61 3.    NO PATENT LICENSE
62 
63 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
64 limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
65 Fraunhofer provides no warranty of patent non-infringement with respect to this
66 software.
67 
68 You may use this FDK AAC Codec software or modifications thereto only for
69 purposes that are authorized by appropriate patent licenses.
70 
71 4.    DISCLAIMER
72 
73 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
74 holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
75 including but not limited to the implied warranties of merchantability and
76 fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
77 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
78 or consequential damages, including but not limited to procurement of substitute
79 goods or services; loss of use, data, or profits, or business interruption,
80 however caused and on any theory of liability, whether in contract, strict
81 liability, or tort (including negligence), arising in any way out of the use of
82 this software, even if advised of the possibility of such damage.
83 
84 5.    CONTACT INFORMATION
85 
86 Fraunhofer Institute for Integrated Circuits IIS
87 Attention: Audio and Multimedia Departments - FDK AAC LL
88 Am Wolfsmantel 33
89 91058 Erlangen, Germany
90 
91 www.iis.fraunhofer.de/amm
92 amm-info@iis.fraunhofer.de
93 ----------------------------------------------------------------------------- */
94 
95 /**************************** SBR encoder library ******************************
96 
97    Author(s):
98 
99    Description:
100 
101 *******************************************************************************/
102 
103 #include "ton_corr.h"
104 
105 #include "sbrenc_ram.h"
106 #include "sbr_misc.h"
107 #include "genericStds.h"
108 #include "autocorr2nd.h"
109 
110 #define BAND_V_SIZE 32
111 #define NUM_V_COMBINE \
112   8 /* Must be a divisor of 64 and fulfill the ASSERTs below */
113 
114 /**************************************************************************/
115 /*!
116   \brief Calculates the tonal to noise ration for different frequency bands
117    and time segments.
118 
119    The ratio between the predicted energy (tonal energy A) and the total
120    energy (A + B) is calculated. This is converted to the ratio between
121    the predicted energy (tonal energy A) and the non-predictable energy
122    (noise energy B). Hence the quota-matrix contains A/B = q/(1-q).
123 
124    The samples in nrgVector are scaled by 1.0/16.0
125    The samples in pNrgVectorFreq  are scaled by 1.0/2.0
126    The samples in quotaMatrix are scaled by RELAXATION
127 
128   \return none.
129 
130 */
131 /**************************************************************************/
132 
FDKsbrEnc_CalculateTonalityQuotas(HANDLE_SBR_TON_CORR_EST hTonCorr,FIXP_DBL ** RESTRICT sourceBufferReal,FIXP_DBL ** RESTRICT sourceBufferImag,INT usb,INT qmfScale)133 void FDKsbrEnc_CalculateTonalityQuotas(
134     HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */
135     FIXP_DBL **RESTRICT
136         sourceBufferReal, /*!< The real part of the QMF-matrix.  */
137     FIXP_DBL **RESTRICT
138         sourceBufferImag, /*!< The imaginary part of the QMF-matrix. */
139     INT usb,     /*!< upper side band, highest + 1 QMF band in the SBR range. */
140     INT qmfScale /*!< sclefactor of QMF subsamples */
141 ) {
142   INT i, k, r, r2, timeIndex, autoCorrScaling;
143 
144   INT startIndexMatrix = hTonCorr->startIndexMatrix;
145   INT totNoEst = hTonCorr->numberOfEstimates;
146   INT noEstPerFrame = hTonCorr->numberOfEstimatesPerFrame;
147   INT move = hTonCorr->move;
148   INT noQmfChannels = hTonCorr->noQmfChannels; /* Number of Bands */
149   INT buffLen = hTonCorr->bufferLength;        /* Number of Slots */
150   INT stepSize = hTonCorr->stepSize;
151   INT *pBlockLength = hTonCorr->lpcLength;
152   INT **RESTRICT signMatrix = hTonCorr->signMatrix;
153   FIXP_DBL *RESTRICT nrgVector = hTonCorr->nrgVector;
154   FIXP_DBL **RESTRICT quotaMatrix = hTonCorr->quotaMatrix;
155   FIXP_DBL *RESTRICT pNrgVectorFreq = hTonCorr->nrgVectorFreq;
156 
157   FIXP_DBL *realBuf;
158   FIXP_DBL *imagBuf;
159 
160   FIXP_DBL alphar[2], alphai[2], fac;
161 
162   C_ALLOC_SCRATCH_START(ac, ACORR_COEFS, 1)
163   C_ALLOC_SCRATCH_START(realBufRef, FIXP_DBL, 2 * BAND_V_SIZE * NUM_V_COMBINE)
164   realBuf = realBufRef;
165   imagBuf = realBuf + BAND_V_SIZE * NUM_V_COMBINE;
166 
167   FDK_ASSERT(buffLen <= BAND_V_SIZE);
168   FDK_ASSERT(sizeof(FIXP_DBL) * NUM_V_COMBINE * BAND_V_SIZE * 2 <
169              (1024 * sizeof(FIXP_DBL) - sizeof(ACORR_COEFS)));
170 
171   /*
172    * Buffering of the quotaMatrix and the quotaMatrixTransp.
173    *********************************************************/
174   for (i = 0; i < move; i++) {
175     FDKmemcpy(quotaMatrix[i], quotaMatrix[i + noEstPerFrame],
176               noQmfChannels * sizeof(FIXP_DBL));
177     FDKmemcpy(signMatrix[i], signMatrix[i + noEstPerFrame],
178               noQmfChannels * sizeof(INT));
179   }
180 
181   FDKmemmove(nrgVector, nrgVector + noEstPerFrame, move * sizeof(FIXP_DBL));
182   FDKmemclear(nrgVector + startIndexMatrix,
183               (totNoEst - startIndexMatrix) * sizeof(FIXP_DBL));
184   FDKmemclear(pNrgVectorFreq, noQmfChannels * sizeof(FIXP_DBL));
185 
186   /*
187    * Calculate the quotas for the current time steps.
188    **************************************************/
189 
190   for (r = 0; r < usb; r++) {
191     int blockLength;
192 
193     k = hTonCorr->nextSample; /* startSample */
194     timeIndex = startIndexMatrix;
195     /* Copy as many as possible Band across all Slots at once */
196     if (realBuf != realBufRef) {
197       realBuf -= BAND_V_SIZE;
198       imagBuf -= BAND_V_SIZE;
199     } else {
200       realBuf += BAND_V_SIZE * (NUM_V_COMBINE - 1);
201       imagBuf += BAND_V_SIZE * (NUM_V_COMBINE - 1);
202 
203       for (i = 0; i < buffLen; i++) {
204         int v;
205         FIXP_DBL *ptr;
206         ptr = realBuf + i;
207         for (v = 0; v < NUM_V_COMBINE; v++) {
208           ptr[0] = sourceBufferReal[i][r + v];
209           ptr[0 + BAND_V_SIZE * NUM_V_COMBINE] = sourceBufferImag[i][r + v];
210           ptr -= BAND_V_SIZE;
211         }
212       }
213     }
214 
215     blockLength = pBlockLength[0];
216 
217     while (k <= buffLen - blockLength) {
218       autoCorrScaling = fixMin(
219           getScalefactor(&realBuf[k - LPC_ORDER], LPC_ORDER + blockLength),
220           getScalefactor(&imagBuf[k - LPC_ORDER], LPC_ORDER + blockLength));
221       autoCorrScaling = fixMax(0, autoCorrScaling - 1);
222 
223       scaleValues(&realBuf[k - LPC_ORDER], LPC_ORDER + blockLength,
224                   autoCorrScaling);
225       scaleValues(&imagBuf[k - LPC_ORDER], LPC_ORDER + blockLength,
226                   autoCorrScaling);
227 
228       autoCorrScaling <<= 1; /* consider qmf buffer scaling twice */
229       autoCorrScaling +=
230           autoCorr2nd_cplx(ac, realBuf + k, imagBuf + k, blockLength);
231 
232       if (ac->det == FL2FXCONST_DBL(0.0f)) {
233         alphar[1] = alphai[1] = FL2FXCONST_DBL(0.0f);
234 
235         alphar[0] = (ac->r01r) >> 2;
236         alphai[0] = (ac->r01i) >> 2;
237 
238         fac = fMultDiv2(ac->r00r, ac->r11r) >> 1;
239       } else {
240         alphar[1] = (fMultDiv2(ac->r01r, ac->r12r) >> 1) -
241                     (fMultDiv2(ac->r01i, ac->r12i) >> 1) -
242                     (fMultDiv2(ac->r02r, ac->r11r) >> 1);
243         alphai[1] = (fMultDiv2(ac->r01i, ac->r12r) >> 1) +
244                     (fMultDiv2(ac->r01r, ac->r12i) >> 1) -
245                     (fMultDiv2(ac->r02i, ac->r11r) >> 1);
246 
247         alphar[0] = (fMultDiv2(ac->r01r, ac->det) >> (ac->det_scale + 1)) +
248                     fMult(alphar[1], ac->r12r) + fMult(alphai[1], ac->r12i);
249         alphai[0] = (fMultDiv2(ac->r01i, ac->det) >> (ac->det_scale + 1)) +
250                     fMult(alphai[1], ac->r12r) - fMult(alphar[1], ac->r12i);
251 
252         fac = fMultDiv2(ac->r00r, fMult(ac->det, ac->r11r)) >>
253               (ac->det_scale + 1);
254       }
255 
256       if (fac == FL2FXCONST_DBL(0.0f)) {
257         quotaMatrix[timeIndex][r] = FL2FXCONST_DBL(0.0f);
258         signMatrix[timeIndex][r] = 0;
259       } else {
260         /* quotaMatrix is scaled with the factor RELAXATION
261            parse RELAXATION in fractional part and shift factor: 1/(1/0.524288 *
262            2^RELAXATION_SHIFT) */
263         FIXP_DBL tmp, num, denom;
264         INT numShift, denomShift, commonShift;
265         INT sign;
266 
267         num = fMultDiv2(alphar[0], ac->r01r) + fMultDiv2(alphai[0], ac->r01i) -
268               fMultDiv2(alphar[1], fMult(ac->r02r, ac->r11r)) -
269               fMultDiv2(alphai[1], fMult(ac->r02i, ac->r11r));
270         num = fixp_abs(num);
271 
272         denom = (fac >> 1) +
273                 (fMultDiv2(fac, RELAXATION_FRACT) >> RELAXATION_SHIFT) - num;
274         denom = fixp_abs(denom);
275 
276         num = fMult(num, RELAXATION_FRACT);
277 
278         numShift = CountLeadingBits(num) - 2;
279         num = scaleValue(num, numShift);
280 
281         denomShift = CountLeadingBits(denom);
282         denom = (FIXP_DBL)denom << denomShift;
283 
284         if ((num > FL2FXCONST_DBL(0.0f)) && (denom != FL2FXCONST_DBL(0.0f))) {
285           commonShift =
286               fixMin(numShift - denomShift + RELAXATION_SHIFT, DFRACT_BITS - 1);
287           if (commonShift < 0) {
288             commonShift = -commonShift;
289             tmp = schur_div(num, denom, 16);
290             commonShift = fixMin(commonShift, CountLeadingBits(tmp));
291             quotaMatrix[timeIndex][r] = tmp << commonShift;
292           } else {
293             quotaMatrix[timeIndex][r] =
294                 schur_div(num, denom, 16) >> commonShift;
295           }
296         } else {
297           quotaMatrix[timeIndex][r] = FL2FXCONST_DBL(0.0f);
298         }
299 
300         if (ac->r11r != FL2FXCONST_DBL(0.0f)) {
301           if (((ac->r01r >= FL2FXCONST_DBL(0.0f)) &&
302                (ac->r11r >= FL2FXCONST_DBL(0.0f))) ||
303               ((ac->r01r < FL2FXCONST_DBL(0.0f)) &&
304                (ac->r11r < FL2FXCONST_DBL(0.0f)))) {
305             sign = 1;
306           } else {
307             sign = -1;
308           }
309         } else {
310           sign = 1;
311         }
312 
313         if (sign < 0) {
314           r2 = r; /* (INT) pow(-1, band); */
315         } else {
316           r2 = r + 1; /* (INT) pow(-1, band+1); */
317         }
318         signMatrix[timeIndex][r] = 1 - 2 * (r2 & 0x1);
319       }
320 
321       nrgVector[timeIndex] +=
322           ((ac->r00r) >>
323            fixMin(DFRACT_BITS - 1,
324                   (2 * qmfScale + autoCorrScaling + SCALE_NRGVEC)));
325       /* pNrgVectorFreq[r] finally has to be divided by noEstPerFrame, replaced
326        * division by shifting with one */
327       pNrgVectorFreq[r] =
328           pNrgVectorFreq[r] +
329           ((ac->r00r) >>
330            fixMin(DFRACT_BITS - 1,
331                   (2 * qmfScale + autoCorrScaling + SCALE_NRGVEC)));
332 
333       blockLength = pBlockLength[1];
334       k += stepSize;
335       timeIndex++;
336     }
337   }
338 
339   C_ALLOC_SCRATCH_END(realBufRef, FIXP_DBL, 2 * BAND_V_SIZE * NUM_V_COMBINE)
340   C_ALLOC_SCRATCH_END(ac, ACORR_COEFS, 1)
341 }
342 
343 /**************************************************************************/
344 /*!
345   \brief Extracts the parameters required in the decoder to obtain the
346   correct tonal to noise ratio after SBR.
347 
348   Estimates the tonal to noise ratio of the original signal (using LPC).
349   Predicts the tonal to noise ration of the SBR signal (in the decoder) by
350   patching the tonal to noise ratio values similar to the patching of the
351   lowband in the decoder. Given the tonal to noise ratio of the original
352   and the SBR signal, it estimates the required amount of inverse filtering,
353   additional noise as well as any additional sines.
354 
355   \return none.
356 
357 */
358 /**************************************************************************/
FDKsbrEnc_TonCorrParamExtr(HANDLE_SBR_TON_CORR_EST hTonCorr,INVF_MODE * infVec,FIXP_DBL * noiseLevels,INT * missingHarmonicFlag,UCHAR * missingHarmonicsIndex,UCHAR * envelopeCompensation,const SBR_FRAME_INFO * frameInfo,UCHAR * transientInfo,UCHAR * freqBandTable,INT nSfb,XPOS_MODE xposType,UINT sbrSyntaxFlags)359 void FDKsbrEnc_TonCorrParamExtr(
360     HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */
361     INVF_MODE *infVec, /*!< Vector where the inverse filtering levels will be
362                           stored. */
363     FIXP_DBL *noiseLevels, /*!< Vector where the noise levels will be stored. */
364     INT *missingHarmonicFlag, /*!< Flag set to one or zero, dependent on if any
365                                  strong sines are missing.*/
366     UCHAR *missingHarmonicsIndex, /*!< Vector indicating where sines are
367                                      missing. */
368     UCHAR *envelopeCompensation,  /*!< Vector to store compensation values for
369                                      the energies in. */
370     const SBR_FRAME_INFO *frameInfo, /*!< Frame info struct, contains the time
371                                         and frequency grid of the current
372                                         frame.*/
373     UCHAR *transientInfo,            /*!< Transient info.*/
374     UCHAR *freqBandTable,            /*!< Frequency band tables for high-res.*/
375     INT nSfb,           /*!< Number of scalefactor bands for high-res. */
376     XPOS_MODE xposType, /*!< Type of transposer used in the decoder.*/
377     UINT sbrSyntaxFlags) {
378   INT band;
379   INT transientFlag = transientInfo[1]; /*!< Flag indicating if a transient is
380                                            present in the current frame. */
381   INT transientPos = transientInfo[0];  /*!< Position of the transient.*/
382   INT transientFrame, transientFrameInvfEst;
383   INVF_MODE *infVecPtr;
384 
385   /* Determine if this is a frame where a transient starts...
386 
387   The detection of noise-floor, missing harmonics and invf_est, is not in sync
388   for the non-buf-opt decoder such as AAC. Hence we need to keep track on the
389   transient in the present frame as well as in the next.
390   */
391   transientFrame = 0;
392   if (hTonCorr->transientNextFrame) { /* The transient was detected in the
393                                          previous frame, but is actually */
394     transientFrame = 1;
395     hTonCorr->transientNextFrame = 0;
396 
397     if (transientFlag) {
398       if (transientPos + hTonCorr->transientPosOffset >=
399           frameInfo->borders[frameInfo->nEnvelopes]) {
400         hTonCorr->transientNextFrame = 1;
401       }
402     }
403   } else {
404     if (transientFlag) {
405       if (transientPos + hTonCorr->transientPosOffset <
406           frameInfo->borders[frameInfo->nEnvelopes]) {
407         transientFrame = 1;
408         hTonCorr->transientNextFrame = 0;
409       } else {
410         hTonCorr->transientNextFrame = 1;
411       }
412     }
413   }
414   transientFrameInvfEst = transientFrame;
415 
416   /*
417     Estimate the required invese filtereing level.
418   */
419   if (hTonCorr->switchInverseFilt)
420     FDKsbrEnc_qmfInverseFilteringDetector(
421         &hTonCorr->sbrInvFilt, hTonCorr->quotaMatrix, hTonCorr->nrgVector,
422         hTonCorr->indexVector, hTonCorr->frameStartIndexInvfEst,
423         hTonCorr->numberOfEstimatesPerFrame + hTonCorr->frameStartIndexInvfEst,
424         transientFrameInvfEst, infVec);
425 
426   /*
427       Detect what tones will be missing.
428    */
429   if (xposType == XPOS_LC) {
430     FDKsbrEnc_SbrMissingHarmonicsDetectorQmf(
431         &hTonCorr->sbrMissingHarmonicsDetector, hTonCorr->quotaMatrix,
432         hTonCorr->signMatrix, hTonCorr->indexVector, frameInfo, transientInfo,
433         missingHarmonicFlag, missingHarmonicsIndex, freqBandTable, nSfb,
434         envelopeCompensation, hTonCorr->nrgVectorFreq);
435   } else {
436     *missingHarmonicFlag = 0;
437     FDKmemclear(missingHarmonicsIndex, nSfb * sizeof(UCHAR));
438   }
439 
440   /*
441     Noise floor estimation
442   */
443 
444   infVecPtr = hTonCorr->sbrInvFilt.prevInvfMode;
445 
446   FDKsbrEnc_sbrNoiseFloorEstimateQmf(
447       &hTonCorr->sbrNoiseFloorEstimate, frameInfo, noiseLevels,
448       hTonCorr->quotaMatrix, hTonCorr->indexVector, *missingHarmonicFlag,
449       hTonCorr->frameStartIndex, hTonCorr->numberOfEstimatesPerFrame,
450       transientFrame, infVecPtr, sbrSyntaxFlags);
451 
452   /* Store the invfVec data for the next frame...*/
453   for (band = 0; band < hTonCorr->sbrInvFilt.noDetectorBands; band++) {
454     hTonCorr->sbrInvFilt.prevInvfMode[band] = infVec[band];
455   }
456 }
457 
458 /**************************************************************************/
459 /*!
460   \brief     Searches for the closest match in the frequency master table.
461 
462 
463 
464   \return   closest entry.
465 
466 */
467 /**************************************************************************/
findClosestEntry(INT goalSb,UCHAR * v_k_master,INT numMaster,INT direction)468 static INT findClosestEntry(INT goalSb, UCHAR *v_k_master, INT numMaster,
469                             INT direction) {
470   INT index;
471 
472   if (goalSb <= v_k_master[0]) return v_k_master[0];
473 
474   if (goalSb >= v_k_master[numMaster]) return v_k_master[numMaster];
475 
476   if (direction) {
477     index = 0;
478     while (v_k_master[index] < goalSb) {
479       index++;
480     }
481   } else {
482     index = numMaster;
483     while (v_k_master[index] > goalSb) {
484       index--;
485     }
486   }
487 
488   return v_k_master[index];
489 }
490 
491 /**************************************************************************/
492 /*!
493   \brief     resets the patch
494 
495 
496 
497   \return   errorCode, noError if successful.
498 
499 */
500 /**************************************************************************/
resetPatch(HANDLE_SBR_TON_CORR_EST hTonCorr,INT xposctrl,INT highBandStartSb,UCHAR * v_k_master,INT numMaster,INT fs,INT noChannels)501 static INT resetPatch(
502     HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */
503     INT xposctrl,                     /*!< Different patch modes. */
504     INT highBandStartSb,              /*!< Start band of the SBR range. */
505     UCHAR *v_k_master, /*!< Master frequency table from which all other table
506                           are derived.*/
507     INT numMaster,     /*!< Number of elements in the master table. */
508     INT fs,            /*!< Sampling frequency. */
509     INT noChannels)    /*!< Number of QMF-channels. */
510 {
511   INT patch, k, i;
512   INT targetStopBand;
513 
514   PATCH_PARAM *patchParam = hTonCorr->patchParam;
515 
516   INT sbGuard = hTonCorr->guard;
517   INT sourceStartBand;
518   INT patchDistance;
519   INT numBandsInPatch;
520 
521   INT lsb =
522       v_k_master[0]; /* Lowest subband related to the synthesis filterbank */
523   INT usb = v_k_master[numMaster]; /* Stop subband related to the synthesis
524                                       filterbank */
525   INT xoverOffset =
526       highBandStartSb -
527       v_k_master[0]; /* Calculate distance in subbands between k0 and kx */
528 
529   INT goalSb;
530 
531   /*
532    * Initialize the patching parameter
533    */
534 
535   if (xposctrl == 1) {
536     lsb += xoverOffset;
537     xoverOffset = 0;
538   }
539 
540   goalSb = (INT)((2 * noChannels * 16000 + (fs >> 1)) / fs); /* 16 kHz band */
541   goalSb = findClosestEntry(goalSb, v_k_master, numMaster,
542                             1); /* Adapt region to master-table */
543 
544   /* First patch */
545   sourceStartBand = hTonCorr->shiftStartSb + xoverOffset;
546   targetStopBand = lsb + xoverOffset;
547 
548   /* even (odd) numbered channel must be patched to even (odd) numbered channel
549    */
550   patch = 0;
551   while (targetStopBand < usb) {
552     /* To many patches */
553     if (patch >= MAX_NUM_PATCHES) return (1); /*Number of patches to high */
554 
555     patchParam[patch].guardStartBand = targetStopBand;
556     targetStopBand += sbGuard;
557     patchParam[patch].targetStartBand = targetStopBand;
558 
559     numBandsInPatch =
560         goalSb - targetStopBand; /* get the desired range of the patch */
561 
562     if (numBandsInPatch >= lsb - sourceStartBand) {
563       /* desired number bands are not available -> patch whole source range */
564       patchDistance =
565           targetStopBand - sourceStartBand; /* get the targetOffset */
566       patchDistance =
567           patchDistance & ~1; /* rounding off odd numbers and make all even */
568       numBandsInPatch = lsb - (targetStopBand - patchDistance);
569       numBandsInPatch = findClosestEntry(targetStopBand + numBandsInPatch,
570                                          v_k_master, numMaster, 0) -
571                         targetStopBand; /* Adapt region to master-table */
572     }
573 
574     /* desired number bands are available -> get the minimal even patching
575      * distance */
576     patchDistance =
577         numBandsInPatch + targetStopBand - lsb; /* get minimal distance */
578     patchDistance = (patchDistance + 1) &
579                     ~1; /* rounding up odd numbers and make all even */
580 
581     if (numBandsInPatch <= 0) {
582       patch--;
583     } else {
584       patchParam[patch].sourceStartBand = targetStopBand - patchDistance;
585       patchParam[patch].targetBandOffs = patchDistance;
586       patchParam[patch].numBandsInPatch = numBandsInPatch;
587       patchParam[patch].sourceStopBand =
588           patchParam[patch].sourceStartBand + numBandsInPatch;
589 
590       targetStopBand += patchParam[patch].numBandsInPatch;
591     }
592 
593     /* All patches but first */
594     sourceStartBand = hTonCorr->shiftStartSb;
595 
596     /* Check if we are close to goalSb */
597     if (fixp_abs(targetStopBand - goalSb) < 3) {
598       goalSb = usb;
599     }
600 
601     patch++;
602   }
603 
604   patch--;
605 
606   /* if highest patch contains less than three subband: skip it */
607   if (patchParam[patch].numBandsInPatch < 3 && patch > 0) {
608     patch--;
609   }
610 
611   hTonCorr->noOfPatches = patch + 1;
612 
613   /* Assign the index-vector, so we know where to look for the high-band.
614      -1 represents a guard-band. */
615   for (k = 0; k < hTonCorr->patchParam[0].guardStartBand; k++)
616     hTonCorr->indexVector[k] = k;
617 
618   for (i = 0; i < hTonCorr->noOfPatches; i++) {
619     INT sourceStart = hTonCorr->patchParam[i].sourceStartBand;
620     INT targetStart = hTonCorr->patchParam[i].targetStartBand;
621     INT numberOfBands = hTonCorr->patchParam[i].numBandsInPatch;
622     INT startGuardBand = hTonCorr->patchParam[i].guardStartBand;
623 
624     for (k = 0; k < (targetStart - startGuardBand); k++)
625       hTonCorr->indexVector[startGuardBand + k] = -1;
626 
627     for (k = 0; k < numberOfBands; k++)
628       hTonCorr->indexVector[targetStart + k] = sourceStart + k;
629   }
630 
631   return (0);
632 }
633 
634 /**************************************************************************/
635 /*!
636   \brief     Creates an instance of the tonality correction parameter module.
637 
638   The module includes modules for inverse filtering level estimation,
639   missing harmonics detection and noise floor level estimation.
640 
641   \return   errorCode, noError if successful.
642 */
643 /**************************************************************************/
FDKsbrEnc_CreateTonCorrParamExtr(HANDLE_SBR_TON_CORR_EST hTonCorr,INT chan)644 INT FDKsbrEnc_CreateTonCorrParamExtr(
645     HANDLE_SBR_TON_CORR_EST
646         hTonCorr, /*!< Pointer to handle to SBR_TON_CORR struct. */
647     INT chan)     /*!< Channel index, needed for mem allocation */
648 {
649   INT i;
650   FIXP_DBL *quotaMatrix = GetRam_Sbr_quotaMatrix(chan);
651   INT *signMatrix = GetRam_Sbr_signMatrix(chan);
652 
653   if ((NULL == quotaMatrix) || (NULL == signMatrix)) {
654     goto bail;
655   }
656 
657   FDKmemclear(hTonCorr, sizeof(SBR_TON_CORR_EST));
658 
659   for (i = 0; i < MAX_NO_OF_ESTIMATES; i++) {
660     hTonCorr->quotaMatrix[i] = quotaMatrix + (i * 64);
661     hTonCorr->signMatrix[i] = signMatrix + (i * 64);
662   }
663 
664   if (0 != FDKsbrEnc_CreateSbrMissingHarmonicsDetector(
665                &hTonCorr->sbrMissingHarmonicsDetector, chan)) {
666     goto bail;
667   }
668 
669   return 0;
670 
671 bail:
672   hTonCorr->quotaMatrix[0] = quotaMatrix;
673   hTonCorr->signMatrix[0] = signMatrix;
674 
675   FDKsbrEnc_DeleteTonCorrParamExtr(hTonCorr);
676 
677   return -1;
678 }
679 
680 /**************************************************************************/
681 /*!
682   \brief     Initialize an instance of the tonality correction parameter module.
683 
684   The module includes modules for inverse filtering level estimation,
685   missing harmonics detection and noise floor level estimation.
686 
687   \return   errorCode, noError if successful.
688 */
689 /**************************************************************************/
FDKsbrEnc_InitTonCorrParamExtr(INT frameSize,HANDLE_SBR_TON_CORR_EST hTonCorr,HANDLE_SBR_CONFIG_DATA sbrCfg,INT timeSlots,INT xposCtrl,INT ana_max_level,INT noiseBands,INT noiseFloorOffset,UINT useSpeechConfig)690 INT FDKsbrEnc_InitTonCorrParamExtr(
691     INT frameSize, /*!< Current SBR frame size. */
692     HANDLE_SBR_TON_CORR_EST
693         hTonCorr, /*!< Pointer to handle to SBR_TON_CORR struct. */
694     HANDLE_SBR_CONFIG_DATA
695         sbrCfg,           /*!< Pointer to SBR configuration parameters. */
696     INT timeSlots,        /*!< Number of time-slots per frame */
697     INT xposCtrl,         /*!< Different patch modes. */
698     INT ana_max_level,    /*!< Maximum level of the adaptive noise. */
699     INT noiseBands,       /*!< Number of noise bands per octave. */
700     INT noiseFloorOffset, /*!< Noise floor offset. */
701     UINT useSpeechConfig) /*!< Speech or music tuning. */
702 {
703   INT nCols = sbrCfg->noQmfSlots;
704   INT fs = sbrCfg->sampleFreq;
705   INT noQmfChannels = sbrCfg->noQmfBands;
706 
707   INT highBandStartSb = sbrCfg->freqBandTable[LOW_RES][0];
708   UCHAR *v_k_master = sbrCfg->v_k_master;
709   INT numMaster = sbrCfg->num_Master;
710 
711   UCHAR **freqBandTable = sbrCfg->freqBandTable;
712   INT *nSfb = sbrCfg->nSfb;
713 
714   INT i;
715 
716   /*
717   Reset the patching and allocate memory for the quota matrix.
718   Assuming parameters for the LPC analysis.
719   */
720   if (sbrCfg->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) {
721     switch (timeSlots) {
722       case NUMBER_TIME_SLOTS_1920:
723         hTonCorr->lpcLength[0] = 8 - LPC_ORDER;
724         hTonCorr->lpcLength[1] = 7 - LPC_ORDER;
725         hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LD;
726         hTonCorr->numberOfEstimatesPerFrame = 2; /* sbrCfg->noQmfSlots / 7 */
727         hTonCorr->frameStartIndexInvfEst = 0;
728         hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_512LD;
729         break;
730       case NUMBER_TIME_SLOTS_2048:
731         hTonCorr->lpcLength[0] = 8 - LPC_ORDER;
732         hTonCorr->lpcLength[1] = 8 - LPC_ORDER;
733         hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LD;
734         hTonCorr->numberOfEstimatesPerFrame = 2; /* sbrCfg->noQmfSlots / 8 */
735         hTonCorr->frameStartIndexInvfEst = 0;
736         hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_512LD;
737         break;
738     }
739   } else
740     switch (timeSlots) {
741       case NUMBER_TIME_SLOTS_2048:
742         hTonCorr->lpcLength[0] = 16 - LPC_ORDER; /* blockLength[0] */
743         hTonCorr->lpcLength[1] = 16 - LPC_ORDER; /* blockLength[0] */
744         hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LC;
745         hTonCorr->numberOfEstimatesPerFrame = sbrCfg->noQmfSlots / 16;
746         hTonCorr->frameStartIndexInvfEst = 0;
747         hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_2048;
748         break;
749       case NUMBER_TIME_SLOTS_1920:
750         hTonCorr->lpcLength[0] = 15 - LPC_ORDER; /* blockLength[0] */
751         hTonCorr->lpcLength[1] = 15 - LPC_ORDER; /* blockLength[0] */
752         hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LC;
753         hTonCorr->numberOfEstimatesPerFrame = sbrCfg->noQmfSlots / 15;
754         hTonCorr->frameStartIndexInvfEst = 0;
755         hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_1920;
756         break;
757       default:
758         return -1;
759     }
760 
761   hTonCorr->bufferLength = nCols;
762   hTonCorr->stepSize =
763       hTonCorr->lpcLength[0] + LPC_ORDER; /* stepSize[0] implicitly 0. */
764 
765   hTonCorr->nextSample = LPC_ORDER; /* firstSample */
766   hTonCorr->move = hTonCorr->numberOfEstimates -
767                    hTonCorr->numberOfEstimatesPerFrame; /* Number of estimates
768                                                            to move when
769                                                            buffering.*/
770   if (hTonCorr->move < 0) {
771     return -1;
772   }
773   hTonCorr->startIndexMatrix =
774       hTonCorr->numberOfEstimates -
775       hTonCorr->numberOfEstimatesPerFrame; /* Where to store the latest
776                                               estimations in the tonality
777                                               Matrix.*/
778   hTonCorr->frameStartIndex = 0; /* Where in the tonality matrix the current
779                                     frame (to be sent to the decoder) starts. */
780   hTonCorr->prevTransientFlag = 0;
781   hTonCorr->transientNextFrame = 0;
782 
783   hTonCorr->noQmfChannels = noQmfChannels;
784 
785   for (i = 0; i < hTonCorr->numberOfEstimates; i++) {
786     FDKmemclear(hTonCorr->quotaMatrix[i], sizeof(FIXP_DBL) * noQmfChannels);
787     FDKmemclear(hTonCorr->signMatrix[i], sizeof(INT) * noQmfChannels);
788   }
789 
790   /* Reset the patch.*/
791   hTonCorr->guard = 0;
792   hTonCorr->shiftStartSb = 1;
793 
794   if (resetPatch(hTonCorr, xposCtrl, highBandStartSb, v_k_master, numMaster, fs,
795                  noQmfChannels))
796     return (1);
797 
798   if (FDKsbrEnc_InitSbrNoiseFloorEstimate(
799           &hTonCorr->sbrNoiseFloorEstimate, ana_max_level, freqBandTable[LO],
800           nSfb[LO], noiseBands, noiseFloorOffset, timeSlots, useSpeechConfig))
801     return (1);
802 
803   if (FDKsbrEnc_initInvFiltDetector(
804           &hTonCorr->sbrInvFilt,
805           hTonCorr->sbrNoiseFloorEstimate.freqBandTableQmf,
806           hTonCorr->sbrNoiseFloorEstimate.noNoiseBands, useSpeechConfig))
807     return (1);
808 
809   if (FDKsbrEnc_InitSbrMissingHarmonicsDetector(
810           &hTonCorr->sbrMissingHarmonicsDetector, fs, frameSize, nSfb[HI],
811           noQmfChannels, hTonCorr->numberOfEstimates, hTonCorr->move,
812           hTonCorr->numberOfEstimatesPerFrame, sbrCfg->sbrSyntaxFlags))
813     return (1);
814 
815   return (0);
816 }
817 
818 /**************************************************************************/
819 /*!
820   \brief     resets tonality correction parameter module.
821 
822 
823 
824   \return   errorCode, noError if successful.
825 
826 */
827 /**************************************************************************/
FDKsbrEnc_ResetTonCorrParamExtr(HANDLE_SBR_TON_CORR_EST hTonCorr,INT xposctrl,INT highBandStartSb,UCHAR * v_k_master,INT numMaster,INT fs,UCHAR ** freqBandTable,INT * nSfb,INT noQmfChannels)828 INT FDKsbrEnc_ResetTonCorrParamExtr(
829     HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */
830     INT xposctrl,                     /*!< Different patch modes. */
831     INT highBandStartSb,              /*!< Start band of the SBR range. */
832     UCHAR *v_k_master, /*!< Master frequency table from which all other table
833                           are derived.*/
834     INT numMaster,     /*!< Number of elements in the master table. */
835     INT fs,            /*!< Sampling frequency (of the SBR part). */
836     UCHAR *
837         *freqBandTable, /*!< Frequency band table for low-res and high-res. */
838     INT *nSfb,          /*!< Number of frequency bands (hig-res and low-res). */
839     INT noQmfChannels   /*!< Number of QMF channels. */
840 ) {
841   /* Reset the patch.*/
842   hTonCorr->guard = 0;
843   hTonCorr->shiftStartSb = 1;
844 
845   if (resetPatch(hTonCorr, xposctrl, highBandStartSb, v_k_master, numMaster, fs,
846                  noQmfChannels))
847     return (1);
848 
849   /* Reset the noise floor estimate.*/
850   if (FDKsbrEnc_resetSbrNoiseFloorEstimate(&hTonCorr->sbrNoiseFloorEstimate,
851                                            freqBandTable[LO], nSfb[LO]))
852     return (1);
853 
854   /*
855   Reset the inveerse filtereing detector.
856   */
857   if (FDKsbrEnc_resetInvFiltDetector(
858           &hTonCorr->sbrInvFilt,
859           hTonCorr->sbrNoiseFloorEstimate.freqBandTableQmf,
860           hTonCorr->sbrNoiseFloorEstimate.noNoiseBands))
861     return (1);
862   /* Reset the missing harmonics detector. */
863   if (FDKsbrEnc_ResetSbrMissingHarmonicsDetector(
864           &hTonCorr->sbrMissingHarmonicsDetector, nSfb[HI]))
865     return (1);
866 
867   return (0);
868 }
869 
870 /**************************************************************************/
871 /*!
872   \brief  Deletes the tonality correction paramtere module.
873 
874 
875 
876   \return   none
877 
878 */
879 /**************************************************************************/
FDKsbrEnc_DeleteTonCorrParamExtr(HANDLE_SBR_TON_CORR_EST hTonCorr)880 void FDKsbrEnc_DeleteTonCorrParamExtr(
881     HANDLE_SBR_TON_CORR_EST hTonCorr) /*!< Handle to SBR_TON_CORR struct. */
882 {
883   if (hTonCorr) {
884     FreeRam_Sbr_quotaMatrix(hTonCorr->quotaMatrix);
885 
886     FreeRam_Sbr_signMatrix(hTonCorr->signMatrix);
887 
888     FDKsbrEnc_DeleteSbrMissingHarmonicsDetector(
889         &hTonCorr->sbrMissingHarmonicsDetector);
890   }
891 }
892