12228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
22228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/* -----------------------------------------------------------------------------------------------------------
32228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectSoftware License for The Fraunhofer FDK AAC Codec Library for Android
42228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi� Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V.
62228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  All rights reserved.
72228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
82228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 1.    INTRODUCTION
92228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectThe Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectthe MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
112228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectThis FDK AAC Codec software is intended to be used on a wide variety of Android devices.
122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
132228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectAAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectaudio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectindependent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectof the MPEG specifications.
172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
182228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectPatent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectmay be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectindividually for the purpose of encoding or decoding bit streams in products that are compliant with
212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectthe ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectthese patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectsoftware may already be covered under those patent licenses when it is used for those licensed purposes only.
242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
252228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectCommercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectare also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectapplications information and documentation.
282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project2.    COPYRIGHT LICENSE
302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
312228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectRedistribution and use in source and binary forms, with or without modification, are permitted without
322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectpayment of copyright license fees provided that you satisfy the following conditions:
332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
342228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectYou must retain the complete text of this software license in redistributions of the FDK AAC Codec or
352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectyour modifications thereto in source code form.
362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
372228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectYou must retain the complete text of this software license in the documentation and/or other materials
382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectprovided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
392228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectYou must make available free of charge copies of the complete source code of the FDK AAC Codec and your
402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectmodifications thereto to recipients of copies in binary form.
412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
422228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectThe name of Fraunhofer may not be used to endorse or promote products derived from this library without
432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectprior written permission.
442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
452228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectYou may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectsoftware or your modifications thereto.
472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
482228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectYour modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectand the date of any change. For modified versions of the FDK AAC Codec, the term
502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project3.    NO PATENT LICENSE
542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
552228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectNO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
562228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectrespect to this software.
582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
592228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectYou may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectby appropriate patent licenses.
612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project4.    DISCLAIMER
632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
642228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectThis FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectof merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
672228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectCONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectincluding but not limited to procurement of substitute goods or services; loss of use, data, or profits,
692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projector business interruption, however caused and on any theory of liability, whether in contract, strict
702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectliability, or tort (including negligence), arising in any way out of the use of this software, even if
712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectadvised of the possibility of such damage.
722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project5.    CONTACT INFORMATION
742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
752228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectFraunhofer Institute for Integrated Circuits IIS
762228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectAttention: Audio and Multimedia Departments - FDK AAC LL
772228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectAm Wolfsmantel 33
782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project91058 Erlangen, Germany
792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectwww.iis.fraunhofer.de/amm
812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectamm-info@iis.fraunhofer.de
822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project----------------------------------------------------------------------------------------------------------- */
832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \file
862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief  Envelope calculation
872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  The envelope adjustor compares the energies present in the transposed
892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  highband to the reference energies conveyed with the bitstream.
902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  The highband is amplified (sometimes) or attenuated (mostly) to the
912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  desired level.
922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  The spectral shape of the reference energies can be changed several times per
942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  frame if necessary. Each set of energy values corresponding to a certain range
952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  in time will be called an <em>envelope</em> here.
962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  The bitstream supports several frequency scales and two resolutions. Normally,
972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  one or more QMF-subbands are grouped to one SBR-band. An envelope contains
982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  reference energies for each SBR-band.
992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  In addition to the energy envelopes, noise envelopes are transmitted that
1002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  define the ratio of energy which is generated by adding noise instead of
1012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  transposing the lowband. The noise envelopes are given in a coarser time
1022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  and frequency resolution.
1032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  If a signal contains strong tonal components, synthetic sines can be
1042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  generated in individual SBR bands.
1052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  An overlap buffer of 6 QMF-timeslots is used to allow a more
1072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  flexible alignment of the envelopes in time that is not restricted to the
1082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  core codec's frame borders.
1092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Therefore the envelope adjustor has access to the spectral data of the
1102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  current frame as well as the last 6 QMF-timeslots of the previous frame.
1112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  However, in average only the data of 1 frame is being processed as
1122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  the adjustor is called once per frame.
1132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Depending on the frequency range set in the bitstream, only QMF-subbands between
1152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  <em>lowSubband</em> and <em>highSubband</em> are adjusted.
1162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Scaling of spectral data to maximize SNR (see #QMF_SCALE_FACTOR) as well as a special Mantissa-Exponent format
1182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  ( see  calculateSbrEnvelope() ) are being used. The main entry point for this modules is calculateSbrEnvelope().
1192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \sa sbr_scale.h, #QMF_SCALE_FACTOR, calculateSbrEnvelope(), \ref documentationOverview
1212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
1222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "env_calc.h"
1252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "sbrdec_freq_sca.h"
1272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "env_extr.h"
1282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "transcendent.h"
1292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "sbr_ram.h"
1302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "sbr_rom.h"
1312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "genericStds.h"           /* need FDKpow() for debug outputs */
1332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#if defined(__arm__)
1352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "arm/env_calc_arm.cpp"
1362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#endif
1372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projecttypedef struct
1392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
1402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL nrgRef[MAX_FREQ_COEFFS];
1412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL nrgEst[MAX_FREQ_COEFFS];
1422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL nrgGain[MAX_FREQ_COEFFS];
1432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL noiseLevel[MAX_FREQ_COEFFS];
1442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL nrgSine[MAX_FREQ_COEFFS];
1452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR   nrgRef_e[MAX_FREQ_COEFFS];
1472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR   nrgEst_e[MAX_FREQ_COEFFS];
1482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR   nrgGain_e[MAX_FREQ_COEFFS];
1492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR   noiseLevel_e[MAX_FREQ_COEFFS];
1502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR   nrgSine_e[MAX_FREQ_COEFFS];
1512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
1522228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectENV_CALC_NRGS;
1532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
154203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void equalizeFiltBufferExp(FIXP_DBL *filtBuffer,
1552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                  SCHAR   *filtBuffer_e,
1562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                  FIXP_DBL *NrgGain,
1572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                  SCHAR   *NrgGain_e,
1582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                  int    subbands);
1592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
160203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void calcNrgPerSubband(FIXP_DBL  **analysBufferReal,
1612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              FIXP_DBL  **analysBufferImag,
1622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              int       lowSubband, int highSubband,
1632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              int       start_pos,  int next_pos,
1642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              SCHAR     frameExp,
1652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              FIXP_DBL *nrgEst,
1662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              SCHAR    *nrgEst_e );
1672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
168203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void calcNrgPerSfb(FIXP_DBL  **analysBufferReal,
1692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          FIXP_DBL  **analysBufferImag,
1702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          int       nSfb,
1712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          UCHAR    *freqBandTable,
1722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          int       start_pos,  int next_pos,
1732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          SCHAR     input_e,
1742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          FIXP_DBL *nrg_est,
1752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          SCHAR    *nrg_est_e );
1762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
177203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void calcSubbandGain(FIXP_DBL  nrgRef, SCHAR nrgRef_e, ENV_CALC_NRGS* nrgs, int c,
1782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            FIXP_DBL  tmpNoise, SCHAR tmpNoise_e,
1792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            UCHAR     sinePresentFlag,
1802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            UCHAR     sineMapped,
1812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            int       noNoiseFlag);
1822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
183203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void calcAvgGain(ENV_CALC_NRGS* nrgs,
1842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        int        lowSubband,
1852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        int        highSubband,
1862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        FIXP_DBL  *sumRef_m,
1872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        SCHAR     *sumRef_e,
1882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        FIXP_DBL  *ptrAvgGain_m,
1892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        SCHAR     *ptrAvgGain_e);
1902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
191203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void adjustTimeSlot_EldGrid(FIXP_DBL  *ptrReal,
1922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           ENV_CALC_NRGS* nrgs,
1932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           UCHAR *ptrHarmIndex,
1942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int    lowSubbands,
1952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int    noSubbands,
1962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int    scale_change,
1972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int    noNoiseFlag,
1982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int   *ptrPhaseIndex,
199203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                           int    scale_diff_low);
200203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
201203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void adjustTimeSlotLC(FIXP_DBL  *ptrReal,
202203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                           ENV_CALC_NRGS* nrgs,
203203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                           UCHAR *ptrHarmIndex,
204203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                           int    lowSubbands,
205203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                           int    noSubbands,
206203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                           int    scale_change,
207203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                           int    noNoiseFlag,
208203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                           int   *ptrPhaseIndex);
209203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void adjustTimeSlotHQ(FIXP_DBL  *ptrReal,
2102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           FIXP_DBL  *ptrImag,
2112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env,
2122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           ENV_CALC_NRGS* nrgs,
2132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int    lowSubbands,
2142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int    noSubbands,
2152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int    scale_change,
2162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           FIXP_SGL smooth_ratio,
2172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int    noNoiseFlag,
2182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int    filtBufferNoiseShift);
2192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
2222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief     Map sine flags from bitstream to QMF bands
2232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  The bitstream carries only 1 sine flag per band and frame.
2252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  This function maps every sine flag from the bitstream to a specific QMF subband
2262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  and to a specific envelope where the sine shall start.
2272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  The result is stored in the vector sineMapped which contains one entry per
2282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  QMF subband. The value of an entry specifies the envelope where a sine
2292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  shall start. A value of #MAX_ENVELOPES indicates that no sine is present
2302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  in the subband.
2312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  The missing harmonics flags from the previous frame (harmFlagsPrev) determine
2322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if a sine starts at the beginning of the frame or at the transient position.
2332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Additionally, the flags in harmFlagsPrev are being updated by this function
2342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for the next frame.
2352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
236203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void mapSineFlags(UCHAR *freqBandTable,         /*!< Band borders (there's only 1 flag per band) */
2372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                         int nSfb,                     /*!< Number of bands in the table */
2382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                         UCHAR *addHarmonics,           /*!< vector with 1 flag per sfb */
2392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                         int *harmFlagsPrev,           /*!< Packed 'addHarmonics' */
2402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                         int tranEnv,                  /*!< Transient position */
2412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                         SCHAR *sineMapped)            /*!< Resulting vector of sine start positions for each QMF band */
2422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
2442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int i;
2452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int lowSubband2 = freqBandTable[0]<<1;
2462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int bitcount = 0;
2472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int oldflags = *harmFlagsPrev;
2482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int newflags = 0;
2492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
2512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    Format of harmFlagsPrev:
2522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    first word = flags for highest 16 sfb bands in use
2542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    second word = flags for next lower 16 sfb bands (if present)
2552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    third word = flags for lowest 16 sfb bands (if present)
2562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    Up to MAX_FREQ_COEFFS sfb bands can be flagged for a sign.
2582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    The lowest bit of the first word corresponds to the _highest_ sfb band in use.
2592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    This is ensures that each flag is  mapped to the same QMF band even after a
2602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    change of the crossover-frequency.
2612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
2622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Reset the output vector first */
2652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDKmemset(sineMapped, MAX_ENVELOPES,MAX_FREQ_COEFFS); /* MAX_ENVELOPES means 'no sine' */
2662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  freqBandTable += nSfb;
2682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  addHarmonics  += nSfb-1;
2692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (i=nSfb; i!=0; i--) {
2712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int ui = *freqBandTable--;                 /* Upper limit of the current scale factor band. */
2722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int li = *freqBandTable;                   /* Lower limit of the current scale factor band. */
2732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if ( *addHarmonics-- ) {                   /* There is a sine in this band */
2752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      unsigned int mask = 1 << bitcount;
2772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      newflags |= mask;                        /* Set flag */
2782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /*
2802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        If there was a sine in the last frame, let it continue from the first envelope on
2812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        else start at the transient position.
2822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      */
2832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sineMapped[(ui+li-lowSubband2) >> 1] = ( oldflags & mask ) ? 0 : tranEnv;
2842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
2852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if ((++bitcount == 16) || i==1) {
2872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      bitcount = 0;
2882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *harmFlagsPrev++ = newflags;
2892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      oldflags = *harmFlagsPrev;               /* Fetch 16 of the old flags */
2902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      newflags = 0;
2912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
2922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
2932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
2942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
2972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief     Reduce gain-adjustment induced aliasing for real valued filterbank.
2982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
2992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*static*/ void
3002228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectaliasingReduction(FIXP_DBL* degreeAlias,       /*!< estimated aliasing for each QMF channel */
3012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                  ENV_CALC_NRGS* nrgs,
3022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                  int*      useAliasReduction, /*!< synthetic sine engergy for each subband, used as flag */
3032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                  int       noSubbands)        /*!< number of QMF channels to process */
3042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
3052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL* nrgGain   = nrgs->nrgGain;          /*!< subband gains to be modified */
3062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR*    nrgGain_e = nrgs->nrgGain_e;        /*!< subband gains to be modified (exponents) */
3072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL* nrgEst    = nrgs->nrgEst;           /*!< subband energy before amplification */
3082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR*    nrgEst_e  = nrgs->nrgEst_e;         /*!< subband energy before amplification (exponents) */
3092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int grouping = 0, index = 0, noGroups, k;
3102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int groupVector[MAX_FREQ_COEFFS];
3112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Calculate grouping*/
3132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (k = 0; k < noSubbands-1; k++ ){
3142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if ( (degreeAlias[k + 1] != FL2FXCONST_DBL(0.0f)) && useAliasReduction[k] ) {
3152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if(grouping==0){
3162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        groupVector[index++] = k;
3172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        grouping = 1;
3182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
3192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else{
3202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if(groupVector[index-1] + 3 == k){
3212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          groupVector[index++] = k + 1;
3222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          grouping = 0;
3232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
3242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
3252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
3262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else{
3272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if(grouping){
3282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if(useAliasReduction[k])
3292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          groupVector[index++] = k + 1;
3302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        else
3312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          groupVector[index++] = k;
3322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        grouping = 0;
3332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
3342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
3352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
3362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if(grouping){
3382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    groupVector[index++] = noSubbands;
3392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
3402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  noGroups = index >> 1;
3412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*Calculate new gain*/
3442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (int group = 0; group < noGroups; group ++) {
3452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL nrgOrig = FL2FXCONST_DBL(0.0f);    /* Original signal energy in current group of bands */
3462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR    nrgOrig_e = 0;
3472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL nrgAmp = FL2FXCONST_DBL(0.0f);     /* Amplified signal energy in group (using current gains) */
3482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR    nrgAmp_e = 0;
3492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL nrgMod = FL2FXCONST_DBL(0.0f);   /* Signal energy in group when applying modified gains */
3502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR    nrgMod_e = 0;
3512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL groupGain;         /* Total energy gain in group */
3522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR    groupGain_e;
3532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL compensation;      /* Compensation factor for the energy change when applying modified gains */
3542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR    compensation_e;
3552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int startGroup = groupVector[2*group];
3572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int stopGroup  = groupVector[2*group+1];
3582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Calculate total energy in group before and after amplification with current gains: */
3602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for(k = startGroup; k < stopGroup; k++){
3612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Get original band energy */
3622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL tmp = nrgEst[k];
3632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      SCHAR    tmp_e = nrgEst_e[k];
3642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FDK_add_MantExp(tmp, tmp_e, nrgOrig, nrgOrig_e, &nrgOrig, &nrgOrig_e);
3662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Multiply band energy with current gain */
3682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      tmp = fMult(tmp,nrgGain[k]);
3692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      tmp_e = tmp_e + nrgGain_e[k];
3702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FDK_add_MantExp(tmp, tmp_e, nrgAmp, nrgAmp_e, &nrgAmp, &nrgAmp_e);
3722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
3732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Calculate total energy gain in group */
3752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FDK_divide_MantExp(nrgAmp, nrgAmp_e,
3762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       nrgOrig, nrgOrig_e,
3772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       &groupGain, &groupGain_e);
3782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for(k = startGroup; k < stopGroup; k++){
3802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL tmp;
3812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      SCHAR    tmp_e;
3822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL alpha = degreeAlias[k];
3842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (k < noSubbands - 1) {
3852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (degreeAlias[k + 1] > alpha)
3862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          alpha = degreeAlias[k + 1];
3872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
3882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Modify gain depending on the degree of aliasing */
3902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FDK_add_MantExp( fMult(alpha,groupGain), groupGain_e,
3912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       fMult(/*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - alpha,nrgGain[k]), nrgGain_e[k],
3922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       &nrgGain[k], &nrgGain_e[k] );
3932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Apply modified gain to original energy */
3952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      tmp = fMult(nrgGain[k],nrgEst[k]);
3962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      tmp_e = nrgGain_e[k] + nrgEst_e[k];
3972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Accumulate energy with modified gains applied */
3992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FDK_add_MantExp( tmp, tmp_e,
4002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       nrgMod, nrgMod_e,
4012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       &nrgMod, &nrgMod_e );
4022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
4032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Calculate compensation factor to retain the energy of the amplified signal */
4052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FDK_divide_MantExp(nrgAmp, nrgAmp_e,
4062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       nrgMod, nrgMod_e,
4072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       &compensation, &compensation_e);
4082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Apply compensation factor to all gains of the group */
4102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for(k = startGroup; k < stopGroup; k++){
4112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      nrgGain[k] = fMult(nrgGain[k],compensation);
4122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      nrgGain_e[k] = nrgGain_e[k] + compensation_e;
4132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
4142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
4152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
4162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project /* Convert headroom bits to exponent */
4192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define SCALE2EXP(s) (15-(s))
4202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define EXP2SCALE(e) (15-(e))
4212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
4232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief  Apply spectral envelope to subband samples
4242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  This function is called from sbr_dec.cpp in each frame.
4262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  To enhance accuracy and due to the usage of tables for squareroots and
4282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  inverse, some calculations are performed with the operands being split
4292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  into mantissa and exponent. The variable names in the source code carry
4302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  the suffixes <em>_m</em> and  <em>_e</em> respectively. The control data
4312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  in #hFrameData containts envelope data which is represented by this format but
4322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  stored in single words. (See requantizeEnvelopeData() for details). This data
4332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  is unpacked within calculateSbrEnvelope() to follow the described suffix convention.
4342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  The actual value (comparable to the corresponding float-variable in the
4362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  research-implementation) of a mantissa/exponent-pair can be calculated as
4372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \f$ value = value\_m * 2^{value\_e} \f$
4392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  All energies and noise levels decoded from the bitstream suit for an
4412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  original signal magnitude of \f$\pm 32768 \f$ rather than \f$ \pm 1\f$. Therefore,
4422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  the scale factor <em>hb_scale</em> passed into this function will be converted
4432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  to an 'input exponent' (#input_e), which fits the internal representation.
4442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Before the actual processing, an exponent #adj_e for resulting adjusted
4462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  samples is derived from the maximum reference energy.
4472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Then, for each envelope, the following steps are performed:
4492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \li Calculate energy in the signal to be adjusted. Depending on the the value of
4512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      #interpolFreq (interpolation mode), this is either done seperately
4522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for each QMF-subband or for each SBR-band.
4532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      The resulting energies are stored in #nrgEst_m[#MAX_FREQ_COEFFS] (mantissas)
4542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      and #nrgEst_e[#MAX_FREQ_COEFFS] (exponents).
4552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \li Calculate gain and noise level for each subband:<br>
4562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      \f$ gain  = \sqrt{ \frac{nrgRef}{nrgEst} \cdot (1 - noiseRatio) }
4572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          \hspace{2cm}
4582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          noise = \sqrt{ nrgRef \cdot noiseRatio }
4592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      \f$<br>
4602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      where <em>noiseRatio</em> and <em>nrgRef</em> are extracted from the
4612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      bitstream and <em>nrgEst</em> is the subband energy before adjustment.
4622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      The resulting gains are stored in #nrgGain_m[#MAX_FREQ_COEFFS]
4632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      (mantissas) and #nrgGain_e[#MAX_FREQ_COEFFS] (exponents), the noise levels
4642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      are stored in #noiseLevel_m[#MAX_FREQ_COEFFS] and #noiseLevel_e[#MAX_FREQ_COEFFS]
4652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      (exponents).
4662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      The sine levels are stored in #nrgSine_m[#MAX_FREQ_COEFFS]
4672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      and #nrgSine_e[#MAX_FREQ_COEFFS].
4682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \li Noise limiting: The gain for each subband is limited both absolutely
4692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      and relatively compared to the total gain over all subbands.
4702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \li Boost gain: Calculate and apply boost factor for each limiter band
4712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      in order to compensate for the energy loss imposed by the limiting.
4722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \li Apply gains and add noise: The gains and noise levels are applied
4732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      to all timeslots of the current envelope. A short FIR-filter (length 4
4742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      QMF-timeslots) can be used to smooth the sudden change at the envelope borders.
4752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      Each complex subband sample of the current timeslot is multiplied by the
4762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      smoothed gain, then random noise with the calculated level is added.
4772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \note
4792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  To reduce the stack size, some of the local arrays could be located within
4802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  the time output buffer. Of the 512 samples temporarily available there,
4812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  about half the size is already used by #SBR_FRAME_DATA. A pointer to the
4822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  remaining free memory could be supplied by an additional argument to calculateSbrEnvelope()
4832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  in sbr_dec:
4842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \par
4862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \code
4872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    calculateSbrEnvelope (&hSbrDec->sbrScaleFactor,
4882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          &hSbrDec->SbrCalculateEnvelope,
4892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          hHeaderData,
4902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          hFrameData,
4912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          QmfBufferReal,
4922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          QmfBufferImag,
4932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          timeOutPtr + sizeof(SBR_FRAME_DATA)/sizeof(Float) + 1);
4942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \endcode
4952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \par
4972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Within calculateSbrEnvelope(), some pointers could be defined instead of the arrays
4982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  #nrgRef_m, #nrgRef_e, #nrgEst_m, #nrgEst_e, #noiseLevel_m:
4992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \par
5012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \code
5022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    fract*        nrgRef_m = timeOutPtr;
5032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR*        nrgRef_e = nrgRef_m + MAX_FREQ_COEFFS;
5042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    fract*        nrgEst_m = nrgRef_e + MAX_FREQ_COEFFS;
5052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR*        nrgEst_e = nrgEst_m + MAX_FREQ_COEFFS;
5062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    fract*        noiseLevel_m = nrgEst_e + MAX_FREQ_COEFFS;
5072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \endcode
5082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  <br>
5102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
5112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectvoid
5122228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectcalculateSbrEnvelope (QMF_SCALE_FACTOR  *sbrScaleFactor,           /*!< Scaling factors */
5132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, /*!< Handle to struct filled by the create-function */
5142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      HANDLE_SBR_HEADER_DATA hHeaderData,          /*!< Static control data */
5152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      HANDLE_SBR_FRAME_DATA  hFrameData,           /*!< Control data of current frame */
5162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      FIXP_DBL **analysBufferReal,                 /*!< Real part of subband samples to be processed */
5172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      FIXP_DBL **analysBufferImag,                 /*!< Imag part of subband samples to be processed */
5182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      const int useLP,
5192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      FIXP_DBL *degreeAlias,                       /*!< Estimated aliasing for each QMF channel */
5202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      const UINT flags,
5212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      const int frameErrorFlag
5222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      )
5232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
5242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int c, i, j, envNoise = 0;
5252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR*   borders = hFrameData->frameInfo.borders;
5262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_SGL *noiseLevels       = hFrameData->sbrNoiseFloorLevel;
5282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData;
5292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int lowSubband  = hFreq->lowSubband;
5312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int highSubband = hFreq->highSubband;
5322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int noSubbands  = highSubband - lowSubband;
5332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int    noNoiseBands = hFreq->nNfb;
5352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int    no_cols      = hHeaderData->numberTimeSlots * hHeaderData->timeStep;
5362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR  first_start  = borders[0] * hHeaderData->timeStep;
5372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  sineMapped[MAX_FREQ_COEFFS];
5392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  ov_adj_e = SCALE2EXP(sbrScaleFactor->ov_hb_scale);
5402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  adj_e = 0;
5412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  output_e;
5422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  final_e = 0;
5432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  maxGainLimit_e = (frameErrorFlag) ? MAX_GAIN_CONCEAL_EXP : MAX_GAIN_EXP;
5452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int useAliasReduction[64];
5472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR smooth_length = 0;
5482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_SGL * pIenv = hFrameData->iEnvelope;
5502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
5522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    Extract sine flags for all QMF bands
5532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
5542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  mapSineFlags(hFreq->freqBandTable[1],
5552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project               hFreq->nSfb[1],
5562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project               hFrameData->addHarmonics,
5572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project               h_sbr_cal_env->harmFlagsPrev,
5582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project               hFrameData->frameInfo.tranEnv,
5592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project               sineMapped);
5602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
5632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    Scan for maximum in bufferd noise levels.
5642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    This is needed in case that we had strong noise in the previous frame
5652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    which is smoothed into the current frame.
5662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    The resulting exponent is used as start value for the maximum search
5672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    in reference energies
5682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
5692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (!useLP)
5702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    adj_e = h_sbr_cal_env->filtBufferNoise_e - getScalefactor(h_sbr_cal_env->filtBufferNoise, noSubbands);
5712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
5732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    Scan for maximum reference energy to be able
5742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    to select appropriate values for adj_e and final_e.
5752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
5762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (i = 0; i < hFrameData->frameInfo.nEnvelopes; i++) {
5782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    INT maxSfbNrg_e = -FRACT_BITS+NRG_EXP_OFFSET; /* start value for maximum search */
5792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Fetch frequency resolution for current envelope: */
5812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (j=hFreq->nSfb[hFrameData->frameInfo.freqRes[i]]; j!=0; j--) {
5822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      maxSfbNrg_e = fixMax(maxSfbNrg_e,(INT)((LONG)(*pIenv++) & MASK_E));
5832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
5842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    maxSfbNrg_e -= NRG_EXP_OFFSET;
5852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Energy -> magnitude (sqrt halfens exponent) */
5872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    maxSfbNrg_e = (maxSfbNrg_e+1) >> 1;  /* +1 to go safe (round to next higher int) */
5882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Some safety margin is needed for 2 reasons:
5902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       - The signal energy is not equally spread over all subband samples in
5912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         a specific sfb of an envelope (Nrg could be too high by a factor of
5922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         envWidth * sfbWidth)
5932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       - Smoothing can smear high gains of the previous envelope into the current
5942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    */
5952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    maxSfbNrg_e += 6;
5962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (borders[i] < hHeaderData->numberTimeSlots)
5982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* This envelope affects timeslots that belong to the output frame */
5992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      adj_e = (maxSfbNrg_e > adj_e) ? maxSfbNrg_e : adj_e;
6002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (borders[i+1] > hHeaderData->numberTimeSlots)
6022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* This envelope affects timeslots after the output frame */
6032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      final_e =  (maxSfbNrg_e > final_e) ? maxSfbNrg_e : final_e;
6042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
6062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
6082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    Calculate adjustment factors and apply them for every envelope.
6092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
6102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  pIenv = hFrameData->iEnvelope;
6112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (i = 0; i < hFrameData->frameInfo.nEnvelopes; i++) {
6132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int k, noNoiseFlag;
6152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR  noise_e, input_e = SCALE2EXP(sbrScaleFactor->hb_scale);
6162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    C_ALLOC_SCRATCH_START(pNrgs, ENV_CALC_NRGS, 1);
6172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*
6192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      Helper variables.
6202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    */
6212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    UCHAR start_pos = hHeaderData->timeStep * borders[i];  /* Start-position in time (subband sample) for current envelope. */
6222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    UCHAR stop_pos = hHeaderData->timeStep * borders[i+1]; /* Stop-position in time (subband sample) for current envelope. */
6232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    UCHAR freq_res = hFrameData->frameInfo.freqRes[i];     /* Frequency resolution for current envelope. */
6242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Always do fully initialize the temporary energy table. This prevents negative energies and extreme gain factors in
6272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       cases where the number of limiter bands exceeds the number of subbands. The latter can be caused by undetected bit
6282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       errors and is tested by some streams from the certification set. */
6292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FDKmemclear(pNrgs, sizeof(ENV_CALC_NRGS));
6302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* If the start-pos of the current envelope equals the stop pos of the current
6322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       noise envelope, increase the pointer (i.e. choose the next noise-floor).*/
6332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (borders[i] == hFrameData->frameInfo.bordersNoise[envNoise+1]){
6342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      noiseLevels += noNoiseBands;   /* The noise floor data is stored in a row [noiseFloor1 noiseFloor2...].*/
6352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      envNoise++;
6362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
6372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if(i==hFrameData->frameInfo.tranEnv || i==h_sbr_cal_env->prevTranEnv) /* attack */
6392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
6402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      noNoiseFlag = 1;
6412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (!useLP)
6422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        smooth_length = 0;  /* No smoothing on attacks! */
6432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
6442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else {
6452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      noNoiseFlag = 0;
6462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (!useLP)
6472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        smooth_length = (1 - hHeaderData->bs_data.smoothingLength) << 2;  /* can become either 0 or 4 */
6482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
6492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*
6522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      Energy estimation in transposed highband.
6532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    */
6542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (hHeaderData->bs_data.interpolFreq)
6552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      calcNrgPerSubband(analysBufferReal,
6562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        (useLP) ? NULL : analysBufferImag,
6572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        lowSubband, highSubband,
6582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        start_pos, stop_pos,
6592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        input_e,
6602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        pNrgs->nrgEst,
6612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        pNrgs->nrgEst_e);
6622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else
6632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      calcNrgPerSfb(analysBufferReal,
6642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    (useLP) ? NULL : analysBufferImag,
6652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    hFreq->nSfb[freq_res],
6662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    hFreq->freqBandTable[freq_res],
6672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    start_pos, stop_pos,
6682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    input_e,
6692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    pNrgs->nrgEst,
6702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    pNrgs->nrgEst_e);
6712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*
6732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      Calculate subband gains
6742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    */
6752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
6762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      UCHAR * table = hFreq->freqBandTable[freq_res];
6772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      UCHAR * pUiNoise = &hFreq->freqBandTableNoise[1]; /*! Upper limit of the current noise floor band. */
6782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_SGL * pNoiseLevels = noiseLevels;
6802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL tmpNoise = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M));
6822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      SCHAR    tmpNoise_e = (UCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET;
6832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      int cc = 0;
6852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      c = 0;
6862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (j = 0; j < hFreq->nSfb[freq_res]; j++) {
6872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FIXP_DBL refNrg   = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pIenv) & MASK_M));
6892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        SCHAR    refNrg_e = (SCHAR)((LONG)(*pIenv) & MASK_E) - NRG_EXP_OFFSET;
6902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        UCHAR sinePresentFlag = 0;
6922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        int li = table[j];
6932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        int ui = table[j+1];
6942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        for (k=li; k<ui; k++) {
6962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          sinePresentFlag |= (i >= sineMapped[cc]);
6972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          cc++;
6982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
6992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        for (k=li; k<ui; k++) {
7012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (k >= *pUiNoise) {
7022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            tmpNoise = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M));
7032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            tmpNoise_e = (SCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET;
7042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            pUiNoise++;
7062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
7072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FDK_ASSERT(k >= lowSubband);
7092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (useLP)
7112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            useAliasReduction[k-lowSubband] = !sinePresentFlag;
7122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->nrgSine[c] = FL2FXCONST_DBL(0.0f);
7142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->nrgSine_e[c] = 0;
7152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          calcSubbandGain(refNrg, refNrg_e, pNrgs, c,
7172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          tmpNoise, tmpNoise_e,
7182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          sinePresentFlag, i >= sineMapped[c],
7192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          noNoiseFlag);
7202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->nrgRef[c]   = refNrg;
7222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->nrgRef_e[c] = refNrg_e;
7232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          c++;
7252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
7262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pIenv++;
7272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
7282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
7292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*
7312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      Noise limiting
7322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    */
7332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (c = 0; c < hFreq->noLimiterBands; c++) {
7352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL sumRef, boostGain, maxGain;
7372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL accu = FL2FXCONST_DBL(0.0f);
7382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      SCHAR   sumRef_e, boostGain_e, maxGain_e, accu_e = 0;
7392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      calcAvgGain(pNrgs,
7412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                  hFreq->limiterBandTable[c], hFreq->limiterBandTable[c+1],
7422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                  &sumRef, &sumRef_e,
7432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                  &maxGain, &maxGain_e);
7442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Multiply maxGain with limiterGain: */
7462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      maxGain = fMult(maxGain, FDK_sbrDecoder_sbr_limGains_m[hHeaderData->bs_data.limiterGains]);
7472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      maxGain_e += FDK_sbrDecoder_sbr_limGains_e[hHeaderData->bs_data.limiterGains];
7482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Scale mantissa of MaxGain into range between 0.5 and 1: */
7502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (maxGain == FL2FXCONST_DBL(0.0f))
7512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxGain_e = -FRACT_BITS;
7522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else {
7532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        SCHAR charTemp = CountLeadingBits(maxGain);
7542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxGain_e -= charTemp;
7552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxGain  <<= (int)charTemp;
7562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
7572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (maxGain_e >= maxGainLimit_e) { /* upper limit (e.g. 96 dB) */
7592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxGain = FL2FXCONST_DBL(0.5f);
7602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxGain_e = maxGainLimit_e;
7612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
7622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Every subband gain is compared to the scaled "average gain"
7652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         and limited if necessary: */
7662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c+1]; k++) {
7672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if ( (pNrgs->nrgGain_e[k] > maxGain_e) || (pNrgs->nrgGain_e[k] == maxGain_e && pNrgs->nrgGain[k]>maxGain) ) {
7682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FIXP_DBL noiseAmp;
7702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          SCHAR    noiseAmp_e;
7712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FDK_divide_MantExp(maxGain, maxGain_e, pNrgs->nrgGain[k], pNrgs->nrgGain_e[k], &noiseAmp, &noiseAmp_e);
7732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->noiseLevel[k]    = fMult(pNrgs->noiseLevel[k],noiseAmp);
7742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->noiseLevel_e[k] += noiseAmp_e;
7752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->nrgGain[k]       = maxGain;
7762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->nrgGain_e[k]     = maxGain_e;
7772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
7782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
7792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* -- Boost gain
7812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        Calculate and apply boost factor for each limiter band:
7822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        1. Check how much energy would be present when using the limited gain
7832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        2. Calculate boost factor by comparison with reference energy
7842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        3. Apply boost factor to compensate for the energy loss due to limiting
7852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      */
7862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; k++) {
7872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* 1.a  Add energy of adjusted signal (using preliminary gain) */
7892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FIXP_DBL  tmp   = fMult(pNrgs->nrgGain[k],pNrgs->nrgEst[k]);
7902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        SCHAR     tmp_e = pNrgs->nrgGain_e[k] + pNrgs->nrgEst_e[k];
7912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FDK_add_MantExp(tmp, tmp_e, accu, accu_e, &accu, &accu_e);
7922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* 1.b  Add sine energy (if present) */
7942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if(pNrgs->nrgSine[k] != FL2FXCONST_DBL(0.0f)) {
7952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FDK_add_MantExp(pNrgs->nrgSine[k], pNrgs->nrgSine_e[k], accu, accu_e, &accu, &accu_e);
7962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
7972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        else {
7982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* 1.c  Add noise energy (if present) */
7992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if(noNoiseFlag == 0) {
8002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            FDK_add_MantExp(pNrgs->noiseLevel[k], pNrgs->noiseLevel_e[k], accu, accu_e, &accu, &accu_e);
8012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
8022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
8032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
8042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* 2.a  Calculate ratio of wanted energy and accumulated energy */
8062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (accu == (FIXP_DBL)0) { /* If divisor is 0, limit quotient to +4 dB */
8072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        boostGain = FL2FXCONST_DBL(0.6279716f);
8082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        boostGain_e = 2;
8092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      } else {
8102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        INT div_e;
8112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        boostGain = fDivNorm(sumRef, accu, &div_e);
8122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        boostGain_e = sumRef_e - accu_e + div_e;
8132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
8142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* 2.b Result too high? --> Limit the boost factor to +4 dB */
8172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if((boostGain_e  > 3) ||
8182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         (boostGain_e == 2 && boostGain > FL2FXCONST_DBL(0.6279716f)) ||
8192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         (boostGain_e == 3 && boostGain > FL2FXCONST_DBL(0.3139858f)) )
8202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
8212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        boostGain = FL2FXCONST_DBL(0.6279716f);
8222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        boostGain_e = 2;
8232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
8242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* 3.  Multiply all signal components with the boost factor */
8252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; k++) {
8262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pNrgs->nrgGain[k]   = fMultDiv2(pNrgs->nrgGain[k],boostGain);
8272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pNrgs->nrgGain_e[k] = pNrgs->nrgGain_e[k] + boostGain_e + 1;
8282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pNrgs->nrgSine[k]   = fMultDiv2(pNrgs->nrgSine[k],boostGain);
8302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pNrgs->nrgSine_e[k] = pNrgs->nrgSine_e[k] + boostGain_e + 1;
8312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pNrgs->noiseLevel[k]   = fMultDiv2(pNrgs->noiseLevel[k],boostGain);
8332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pNrgs->noiseLevel_e[k] = pNrgs->noiseLevel_e[k] + boostGain_e + 1;
8342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
8352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
8362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* End of noise limiting */
8372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (useLP)
8392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      aliasingReduction(degreeAlias+lowSubband,
8402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        pNrgs,
8412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        useAliasReduction,
8422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        noSubbands);
8432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* For the timeslots within the range for the output frame,
8452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       use the same scale for the noise levels.
8462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       Drawback: If the envelope exceeds the frame border, the noise levels
8472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                 will have to be rescaled later to fit final_e of
8482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                 the gain-values.
8492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    */
8502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    noise_e = (start_pos < no_cols) ? adj_e : final_e;
8512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*
8532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      Convert energies to amplitude levels
8542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    */
8552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (k=0; k<noSubbands; k++) {
8562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FDK_sqrt_MantExp(&pNrgs->nrgSine[k],    &pNrgs->nrgSine_e[k],    &noise_e);
8572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FDK_sqrt_MantExp(&pNrgs->nrgGain[k],    &pNrgs->nrgGain_e[k],    &pNrgs->nrgGain_e[k]);
8582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FDK_sqrt_MantExp(&pNrgs->noiseLevel[k], &pNrgs->noiseLevel_e[k], &noise_e);
8592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
8602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*
8642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      Apply calculated gains and adaptive noise
8652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    */
8662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* assembleHfSignals() */
8682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
8692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      int scale_change, sc_change;
8702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_SGL smooth_ratio;
8712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      int filtBufferNoiseShift=0;
8722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Initialize smoothing buffers with the first valid values */
8742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (h_sbr_cal_env->startUp)
8752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
8762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (!useLP) {
8772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          h_sbr_cal_env->filtBufferNoise_e = noise_e;
8782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FDKmemcpy(h_sbr_cal_env->filtBuffer_e,    pNrgs->nrgGain_e,  noSubbands*sizeof(SCHAR));
8802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FDKmemcpy(h_sbr_cal_env->filtBufferNoise, pNrgs->noiseLevel, noSubbands*sizeof(FIXP_DBL));
8812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FDKmemcpy(h_sbr_cal_env->filtBuffer,      pNrgs->nrgGain,    noSubbands*sizeof(FIXP_DBL));
8822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
8842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        h_sbr_cal_env->startUp = 0;
8852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
8862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (!useLP) {
8882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        equalizeFiltBufferExp(h_sbr_cal_env->filtBuffer,    /* buffered */
8902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              h_sbr_cal_env->filtBuffer_e,  /* buffered */
8912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              pNrgs->nrgGain,               /* current  */
8922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              pNrgs->nrgGain_e,             /* current  */
8932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              noSubbands);
8942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* Adapt exponent of buffered noise levels to the current exponent
8962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           so they can easily be smoothed */
8972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if((h_sbr_cal_env->filtBufferNoise_e - noise_e)>=0) {
8982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          int shift = fixMin(DFRACT_BITS-1,(int)(h_sbr_cal_env->filtBufferNoise_e - noise_e));
8992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          for (k=0; k<noSubbands; k++)
9002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            h_sbr_cal_env->filtBufferNoise[k] <<= shift;
9012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
9022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        else {
9032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          int shift = fixMin(DFRACT_BITS-1,-(int)(h_sbr_cal_env->filtBufferNoise_e - noise_e));
9042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          for (k=0; k<noSubbands; k++)
9052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            h_sbr_cal_env->filtBufferNoise[k] >>= shift;
9062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
9072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        h_sbr_cal_env->filtBufferNoise_e = noise_e;
9092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
9102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* find best scaling! */
9122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      scale_change = -(DFRACT_BITS-1);
9132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for(k=0;k<noSubbands;k++) {
9142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          scale_change = fixMax(scale_change,(int)pNrgs->nrgGain_e[k]);
9152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
9162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sc_change = (start_pos<no_cols)? adj_e - input_e : final_e - input_e;
9172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if ((scale_change-sc_change+1)<0)
9192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          scale_change-=(scale_change-sc_change+1);
9202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      scale_change = (scale_change-sc_change)+1;
9222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for(k=0;k<noSubbands;k++) {
9242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          int sc = scale_change-pNrgs->nrgGain_e[k] + (sc_change-1);
9252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->nrgGain[k]  >>= sc;
9262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->nrgGain_e[k] += sc;
9272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
9282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (!useLP) {
9302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        for(k=0;k<noSubbands;k++) {
9312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          int sc = scale_change-h_sbr_cal_env->filtBuffer_e[k] + (sc_change-1);
9322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          h_sbr_cal_env->filtBuffer[k] >>= sc;
9332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
9342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
9352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (j = start_pos; j < stop_pos; j++)
9372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
9382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* This timeslot is located within the first part of the processing buffer
9392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           and will be fed into the QMF-synthesis for the current frame.
9402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project               adj_e - input_e
9412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           This timeslot will not yet be fed into the QMF so we do not care
9422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           about the adj_e.
9432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project               sc_change = final_e - input_e
9442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        */
9452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if ( (j==no_cols) && (start_pos<no_cols) )
9462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
9472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          int shift = (int) (noise_e - final_e);
9482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (!useLP)
9492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            filtBufferNoiseShift = shift;               /* shifting of h_sbr_cal_env->filtBufferNoise[k] will be applied in function adjustTimeSlotHQ() */
9502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (shift>=0) {
9512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            shift = fixMin(DFRACT_BITS-1,shift);
9522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            for (k=0; k<noSubbands; k++) {
9532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              pNrgs->nrgSine[k] <<= shift;
9542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              pNrgs->noiseLevel[k]  <<= shift;
9552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              /*
9562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              if (!useLP)
9572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                h_sbr_cal_env->filtBufferNoise[k]  <<= shift;
9582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              */
9592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            }
9602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
9612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          else {
9622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            shift = fixMin(DFRACT_BITS-1,-shift);
9632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            for (k=0; k<noSubbands; k++) {
9642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              pNrgs->nrgSine[k] >>= shift;
9652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              pNrgs->noiseLevel[k]  >>= shift;
9662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              /*
9672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              if (!useLP)
9682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                h_sbr_cal_env->filtBufferNoise[k]  >>= shift;
9692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              */
9702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            }
9712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
9722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* update noise scaling */
9742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          noise_e = final_e;
9752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (!useLP)
9762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            h_sbr_cal_env->filtBufferNoise_e = noise_e;  /* scaling value unused! */
9772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* update gain buffer*/
9792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          sc_change -= (final_e - input_e);
9802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (sc_change<0) {
9822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            for(k=0;k<noSubbands;k++) {
9832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                pNrgs->nrgGain[k]  >>= -sc_change;
9842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                pNrgs->nrgGain_e[k] += -sc_change;
9852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            }
9862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            if (!useLP) {
9872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              for(k=0;k<noSubbands;k++) {
9882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    h_sbr_cal_env->filtBuffer[k] >>= -sc_change;
9892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              }
9902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            }
9912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          } else {
9922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            scale_change+=sc_change;
9932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
9942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        } // if
9962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (!useLP) {
9982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* Prevent the smoothing filter from running on constant levels */
10002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (j-start_pos < smooth_length)
10012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            smooth_ratio = FDK_sbrDecoder_sbr_smoothFilter[j-start_pos];
10022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          else
10032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            smooth_ratio = FL2FXCONST_SGL(0.0f);
10042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          adjustTimeSlotHQ(&analysBufferReal[j][lowSubband],
10062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           &analysBufferImag[j][lowSubband],
10072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           h_sbr_cal_env,
10082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           pNrgs,
10092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           lowSubband,
10102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           noSubbands,
10112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           scale_change,
10122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           smooth_ratio,
10132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           noNoiseFlag,
10142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           filtBufferNoiseShift);
10152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
10162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        else
10172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
1018203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi          if (flags & SBRDEC_ELD_GRID) {
1019203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi            adjustTimeSlot_EldGrid(&analysBufferReal[j][lowSubband],
10202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           pNrgs,
10212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          &h_sbr_cal_env->harmIndex,
10222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           lowSubband,
10232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           noSubbands,
10242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           scale_change,
10252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           noNoiseFlag,
10262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          &h_sbr_cal_env->phaseIndex,
1027203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                           EXP2SCALE(adj_e) - sbrScaleFactor->lb_scale);
1028203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi          } else
1029203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi          {
1030203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi            adjustTimeSlotLC(&analysBufferReal[j][lowSubband],
1031203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                           pNrgs,
1032203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                          &h_sbr_cal_env->harmIndex,
1033203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                           lowSubband,
1034203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                           noSubbands,
1035203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                           scale_change,
1036203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                           noNoiseFlag,
1037203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                          &h_sbr_cal_env->phaseIndex);
1038203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi          }
10392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
10402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      } // for
10412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (!useLP) {
10432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* Update time-smoothing-buffers for gains and noise levels
10442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           The gains and the noise values of the current envelope are copied into the buffer.
10452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           This has to be done at the end of each envelope as the values are required for
10462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           a smooth transition to the next envelope. */
10472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FDKmemcpy(h_sbr_cal_env->filtBuffer,      pNrgs->nrgGain,    noSubbands*sizeof(FIXP_DBL));
10482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FDKmemcpy(h_sbr_cal_env->filtBuffer_e,    pNrgs->nrgGain_e,  noSubbands*sizeof(SCHAR));
10492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FDKmemcpy(h_sbr_cal_env->filtBufferNoise, pNrgs->noiseLevel, noSubbands*sizeof(FIXP_DBL));
10502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
10512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
10532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    C_ALLOC_SCRATCH_END(pNrgs, ENV_CALC_NRGS, 1);
10542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
10552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Rescale output samples */
10572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  {
10582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL maxVal;
10592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int ov_reserve, reserve;
10602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Determine headroom in old adjusted samples */
10622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    maxVal = maxSubbandSample( analysBufferReal,
10632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              (useLP) ? NULL : analysBufferImag,
10642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               lowSubband,
10652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               highSubband,
10662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               0,
10672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               first_start);
10682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    ov_reserve = fNorm(maxVal);
10702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Determine headroom in new adjusted samples */
10722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    maxVal = maxSubbandSample( analysBufferReal,
10732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               (useLP) ? NULL : analysBufferImag,
10742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               lowSubband,
10752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               highSubband,
10762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               first_start,
10772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               no_cols);
10782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    reserve = fNorm(maxVal);
10802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Determine common output exponent */
10822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (ov_adj_e - ov_reserve  >  adj_e - reserve ) /* set output_e to the maximum */
10832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      output_e = ov_adj_e - ov_reserve;
10842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else
10852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      output_e = adj_e - reserve;
10862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Rescale old samples */
10882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    rescaleSubbandSamples( analysBufferReal,
10892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           (useLP) ? NULL : analysBufferImag,
10902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           lowSubband, highSubband,
10912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           0, first_start,
10922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           ov_adj_e - output_e);
10932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Rescale new samples */
10952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    rescaleSubbandSamples( analysBufferReal,
10962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           (useLP) ? NULL : analysBufferImag,
10972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           lowSubband, highSubband,
10982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           first_start, no_cols,
10992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           adj_e - output_e);
11002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
11012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Update hb_scale */
11032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  sbrScaleFactor->hb_scale = EXP2SCALE(output_e);
11042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Save the current final exponent for the next frame: */
11062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  sbrScaleFactor->ov_hb_scale = EXP2SCALE(final_e);
11072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* We need to remeber to the next frame that the transient
11102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project     will occur in the first envelope (if tranEnv == nEnvelopes). */
11112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if(hFrameData->frameInfo.tranEnv == hFrameData->frameInfo.nEnvelopes)
11122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    h_sbr_cal_env->prevTranEnv = 0;
11132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  else
11142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    h_sbr_cal_env->prevTranEnv = -1;
11152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
11172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
11202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief   Create envelope instance
11212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Must be called once for each channel before calculateSbrEnvelope() can be used.
11232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \return  errorCode, 0 if successful
11252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
11262228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectSBR_ERROR
11272228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectcreateSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hs,   /*!< pointer to envelope instance */
11282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       HANDLE_SBR_HEADER_DATA hHeaderData, /*!< static SBR control data, initialized with defaults */
11292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       const int chan,                     /*!< Channel for which to assign buffers */
11302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       const UINT flags)
11312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
11322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SBR_ERROR err = SBRDEC_OK;
11332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int i;
11342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Clear previous missing harmonics flags */
11362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (i=0; i<(MAX_FREQ_COEFFS+15)>>4; i++) {
11372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    hs->harmFlagsPrev[i] = 0;
11382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
11392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  hs->harmIndex = 0;
11402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
11422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    Setup pointers for time smoothing.
11432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    The buffer itself will be initialized later triggered by the startUp-flag.
11442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
11452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  hs->prevTranEnv = -1;
11462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* initialization */
11492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  resetSbrEnvelopeCalc(hs);
11502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (chan==0) { /* do this only once */
11522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    err = resetFreqBandTables(hHeaderData, flags);
11532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
11542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  return err;
11562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
11572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
11592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief   Create envelope instance
11602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Must be called once for each channel before calculateSbrEnvelope() can be used.
11622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \return  errorCode, 0 if successful
11642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
11652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectint
11662228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectdeleteSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hs)
11672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
11682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  return 0;
11692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
11702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
11732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief   Reset envelope instance
11742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  This function must be called for each channel on a change of configuration.
11762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Note that resetFreqBandTables should also be called in this case.
11772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \return  errorCode, 0 if successful
11792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
11802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectvoid
11812228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectresetSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv) /*!< pointer to envelope instance */
11822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
11832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  hCalEnv->phaseIndex = 0;
11842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Noise exponent needs to be reset because the output exponent for the next frame depends on it */
11862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  hCalEnv->filtBufferNoise_e = 0;
11872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  hCalEnv->startUp = 1;
11892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
11902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
11932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief  Equalize exponents of the buffered gain values and the new ones
11942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  After equalization of exponents, the FIR-filter addition for smoothing
11962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  can be performed.
11972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  This function is called once for each envelope before adjusting.
11982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
1199203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void equalizeFiltBufferExp(FIXP_DBL *filtBuffer,     /*!< bufferd gains */
12002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                  SCHAR    *filtBuffer_e,   /*!< exponents of bufferd gains */
12012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                  FIXP_DBL *nrgGain,        /*!< gains for current envelope */
12022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                  SCHAR    *nrgGain_e,      /*!< exponents of gains for current envelope */
12032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                  int       subbands)       /*!< Number of QMF subbands */
12042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
12052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int   band;
12062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int  diff;
12072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (band=0; band<subbands; band++){
12092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    diff = (int) (nrgGain_e[band] - filtBuffer_e[band]);
12102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (diff>0) {
12112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      filtBuffer[band] >>= diff;   /* Compensate for the scale change by shifting the mantissa. */
12122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      filtBuffer_e[band] += diff;  /* New gain is bigger, use its exponent */
12132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
12142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else if (diff<0) {
12152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* The buffered gains seem to be larger, but maybe there
12162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         are some unused bits left in the mantissa */
12172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      int reserve = CntLeadingZeros(fixp_abs(filtBuffer[band]))-1;
12192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if ((-diff) <= reserve) {
12212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* There is enough space in the buffered mantissa so
12222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           that we can take the new exponent as common.
12232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        */
12242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        filtBuffer[band] <<= (-diff);
12252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        filtBuffer_e[band] += diff;  /* becomes equal to *ptrNewExp */
12262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
12272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else {
12282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        filtBuffer[band] <<= reserve;   /* Shift the mantissa as far as possible: */
12292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        filtBuffer_e[band] -= reserve;  /* Compensate in the exponent: */
12302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* For the remaining difference, change the new gain value */
12322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        diff = fixMin(-(reserve + diff),DFRACT_BITS-1);
12332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        nrgGain[band] >>= diff;
12342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        nrgGain_e[band] += diff;
12352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
12362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
12372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
12382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
12392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
12412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief  Shift left the mantissas of all subband samples
12422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          in the giventime and frequency range by the specified number of bits.
12432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  This function is used to rescale the audio data in the overlap buffer
12452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  which has already been envelope adjusted with the last frame.
12462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
12472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectvoid rescaleSubbandSamples(FIXP_DBL ** re,   /*!< Real part of input and output subband samples */
12482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           FIXP_DBL ** im,   /*!< Imaginary part of input and output subband samples */
12492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int lowSubband,   /*!< Begin of frequency range to process */
12502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int highSubband,  /*!< End of frequency range to process */
12512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int start_pos,    /*!< Begin of time rage (QMF-timeslot) */
12522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int next_pos,     /*!< End of time rage (QMF-timeslot) */
12532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int shift)        /*!< number of bits to shift */
12542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
12552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int width = highSubband-lowSubband;
12562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if ( (width > 0) && (shift!=0) ) {
12582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (im!=NULL) {
12592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (int l=start_pos; l<next_pos; l++) {
12602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          scaleValues(&re[l][lowSubband], width, shift);
12612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          scaleValues(&im[l][lowSubband], width, shift);
12622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
12632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    } else
12642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
12652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (int l=start_pos; l<next_pos; l++) {
12662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          scaleValues(&re[l][lowSubband], width, shift);
12672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
12682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
12692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
12702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
12712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
12742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief   Determine headroom for shifting
12752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Determine by how much the spectrum can be shifted left
12772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for better accuracy in later processing.
12782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \return  Number of free bits in the biggest spectral value
12802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
12812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12822228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectFIXP_DBL maxSubbandSample( FIXP_DBL ** re,   /*!< Real part of input and output subband samples */
12832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           FIXP_DBL ** im,   /*!< Real part of input and output subband samples */
12842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int lowSubband,   /*!< Begin of frequency range to process */
12852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int highSubband,  /*!< Number of QMF bands to process */
12862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int start_pos,    /*!< Begin of time rage (QMF-timeslot) */
12872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int next_pos      /*!< End of time rage (QMF-timeslot) */
12882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          )
12892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
12902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL maxVal = FL2FX_DBL(0.0f);
12912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  unsigned int width = highSubband - lowSubband;
12922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDK_ASSERT(width <= (64));
12942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if ( width > 0 ) {
12962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (im!=NULL)
12972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
12982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (int l=start_pos; l<next_pos; l++)
12992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
13002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#ifdef FUNCTION_FDK_get_maxval
13012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxVal = FDK_get_maxval(maxVal, &re[l][lowSubband], &im[l][lowSubband], width);
13022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#else
13032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        int k=width;
13042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FIXP_DBL *reTmp = &re[l][lowSubband];
13052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FIXP_DBL *imTmp = &im[l][lowSubband];
13062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        do{
13072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FIXP_DBL tmp1 = *(reTmp++);
13082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FIXP_DBL tmp2 = *(imTmp++);
13092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          maxVal |= (FIXP_DBL)((LONG)(tmp1)^((LONG)tmp1>>(DFRACT_BITS-1)));
13102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          maxVal |= (FIXP_DBL)((LONG)(tmp2)^((LONG)tmp2>>(DFRACT_BITS-1)));
13112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        } while(--k!=0);
13122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#endif
13132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
13142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    } else
13152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
13162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (int l=start_pos; l<next_pos; l++) {
13172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        int k=width;
13182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FIXP_DBL *reTmp = &re[l][lowSubband];
13192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        do{
13202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FIXP_DBL tmp = *(reTmp++);
13212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          maxVal |= (FIXP_DBL)((LONG)(tmp)^((LONG)tmp>>(DFRACT_BITS-1)));
13222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }while(--k!=0);
13232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
13242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
13252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
13262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  return(maxVal);
13282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
13292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define SHIFT_BEFORE_SQUARE (3) /* (7/2) */
13312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!<
13322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  If the accumulator does not provide enough overflow bits or
13332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  does not provide a high dynamic range, the below energy calculation
13342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  requires an additional shift operation for each sample.
13352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  On the other hand, doing the shift allows using a single-precision
13362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  multiplication for the square (at least 16bit x 16bit).
13372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  For even values of OVRFLW_BITS (0, 2, 4, 6), saturated arithmetic
13382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  is required for the energy accumulation.
13392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Theoretically, the sample-squares can sum up to a value of 76,
13402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  requiring 7 overflow bits. However since such situations are *very*
13412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  rare, accu can be limited to 64.
13422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  In case native saturated arithmetic is not available, overflows
13432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  can be prevented by replacing the above #define by
13442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    #define SHIFT_BEFORE_SQUARE ((8 - OVRFLW_BITS) / 2)
13452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  which will result in slightly reduced accuracy.
13462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
13472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
13492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief  Estimates the mean energy of each filter-bank channel for the
13502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          duration of the current envelope
13512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  This function is used when interpolFreq is true.
13532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
1354203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void calcNrgPerSubband(FIXP_DBL  **analysBufferReal, /*!< Real part of subband samples */
13552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              FIXP_DBL  **analysBufferImag, /*!< Imaginary part of subband samples */
13562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              int       lowSubband,           /*!< Begin of the SBR frequency range */
13572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              int       highSubband,          /*!< High end of the SBR frequency range */
13582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              int       start_pos,            /*!< First QMF-slot of current envelope */
13592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              int       next_pos,             /*!< Last QMF-slot of current envelope + 1 */
13602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              SCHAR     frameExp,             /*!< Common exponent for all input samples */
13612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              FIXP_DBL *nrgEst,               /*!< resulting Energy (0..1) */
13622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              SCHAR    *nrgEst_e )            /*!< Exponent of resulting Energy */
13632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
13642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_SGL invWidth;
13652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  preShift;
13662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  shift;
13672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL sum;
13682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int k,l;
13692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Divide by width of envelope later: */
13712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  invWidth = FX_DBL2FX_SGL(GetInvInt(next_pos - start_pos));
13722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* The common exponent needs to be doubled because all mantissas are squared: */
13732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  frameExp = frameExp << 1;
13742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (k=lowSubband; k<highSubband; k++) {
13762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL  bufferReal[(((1024)/(32))+(6))];
13772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL  bufferImag[(((1024)/(32))+(6))];
13782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL maxVal = FL2FX_DBL(0.0f);
13792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (analysBufferImag!=NULL)
13812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
13822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (l=start_pos;l<next_pos;l++)
13832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
13842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        bufferImag[l] = analysBufferImag[l][k];
13852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxVal |= (FIXP_DBL)((LONG)(bufferImag[l])^((LONG)bufferImag[l]>>(DFRACT_BITS-1)));
13862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        bufferReal[l] = analysBufferReal[l][k];
13872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxVal |= (FIXP_DBL)((LONG)(bufferReal[l])^((LONG)bufferReal[l]>>(DFRACT_BITS-1)));
13882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
13892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
13902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else
13912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
13922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (l=start_pos;l<next_pos;l++)
13932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
13942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        bufferReal[l] = analysBufferReal[l][k];
13952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxVal |= (FIXP_DBL)((LONG)(bufferReal[l])^((LONG)bufferReal[l]>>(DFRACT_BITS-1)));
13962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
13972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
13982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (maxVal!=FL2FXCONST_DBL(0.f)) {
14002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* If the accu does not provide enough overflow bits, we cannot
14032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         shift the samples up to the limit.
14042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         Instead, keep up to 3 free bits in each sample, i.e. up to
14052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         6 bits after calculation of square.
14062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         Please note the comment on saturated arithmetic above!
14072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      */
14082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL accu = FL2FXCONST_DBL(0.0f);
14092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      preShift = CntLeadingZeros(maxVal)-1;
14102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      preShift -= SHIFT_BEFORE_SQUARE;
14112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (preShift>=0) {
14132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (analysBufferImag!=NULL) {
14142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          for (l=start_pos; l<next_pos; l++) {
14152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            FIXP_DBL temp1 = bufferReal[l] << (int)preShift;
14162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            FIXP_DBL temp2 = bufferImag[l] << (int)preShift;
14172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            accu = fPow2AddDiv2(accu, temp1);
14182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            accu = fPow2AddDiv2(accu, temp2);
14192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
14202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        } else
14212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
14222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          for (l=start_pos; l<next_pos; l++) {
14232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            FIXP_DBL temp = bufferReal[l] << (int)preShift;
14242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            accu = fPow2AddDiv2(accu, temp);
14252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
14262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
14272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
14282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else {    /* if negative shift value */
14292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        int negpreShift = -preShift;
14302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (analysBufferImag!=NULL) {
14312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          for (l=start_pos; l<next_pos; l++) {
14322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            FIXP_DBL temp1 = bufferReal[l] >> (int)negpreShift;
14332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            FIXP_DBL temp2 = bufferImag[l] >> (int)negpreShift;
14342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            accu = fPow2AddDiv2(accu, temp1);
14352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            accu = fPow2AddDiv2(accu, temp2);
14362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
14372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        } else
14382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
14392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          for (l=start_pos; l<next_pos; l++) {
14402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            FIXP_DBL temp = bufferReal[l] >> (int)negpreShift;
14412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            accu = fPow2AddDiv2(accu, temp);
14422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
14432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
14442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
14452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      accu <<= 1;
14462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Convert double precision to Mantissa/Exponent: */
14482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      shift = fNorm(accu);
14492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sum = accu << (int)shift;
14502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Divide by width of envelope and apply frame scale: */
14522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *nrgEst++ = fMult(sum, invWidth);
14532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      shift += 2 * preShift;
14542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (analysBufferImag!=NULL)
14552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        *nrgEst_e++ = frameExp - shift;
14562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else
14572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        *nrgEst_e++ = frameExp - shift + 1;  /* +1 due to missing imag. part */
14582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    } /* maxVal!=0 */
14592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else {
14602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Prevent a zero-mantissa-number from being misinterpreted
14622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         due to its exponent. */
14632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *nrgEst++ = FL2FXCONST_DBL(0.0f);
14642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *nrgEst_e++ = 0;
14652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
14662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
14672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
14682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
14702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief   Estimates the mean energy of each Scale factor band for the
14712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           duration of the current envelope.
14722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  This function is used when interpolFreq is false.
14742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
1475203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void calcNrgPerSfb(FIXP_DBL  **analysBufferReal,  /*!< Real part of subband samples */
14762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          FIXP_DBL  **analysBufferImag,  /*!< Imaginary part of subband samples */
14772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          int       nSfb,                /*!< Number of scale factor bands */
14782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          UCHAR    *freqBandTable,       /*!< First Subband for each Sfb */
14792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          int       start_pos,           /*!< First QMF-slot of current envelope */
14802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          int       next_pos,            /*!< Last QMF-slot of current envelope + 1 */
14812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          SCHAR     input_e,             /*!< Common exponent for all input samples */
14822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          FIXP_DBL *nrgEst,              /*!< resulting Energy (0..1) */
14832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          SCHAR    *nrgEst_e )           /*!< Exponent of resulting Energy */
14842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
14852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_SGL  invWidth;
14862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL  temp;
14872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  preShift;
14882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR   shift, sum_e;
14892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL  sum;
14902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int j,k,l,li,ui;
14922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL sumAll, sumLine; /* Single precision would be sufficient,
14932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                             but overflow bits are required for accumulation */
14942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Divide by width of envelope later: */
14962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  invWidth = FX_DBL2FX_SGL(GetInvInt(next_pos - start_pos));
14972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* The common exponent needs to be doubled because all mantissas are squared: */
14982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  input_e = input_e << 1;
14992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for(j=0; j<nSfb; j++) {
15012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    li = freqBandTable[j];
15022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    ui = freqBandTable[j+1];
15032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL maxVal = maxSubbandSample( analysBufferReal,
15052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                        analysBufferImag,
15062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                        li,
15072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                        ui,
15082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                        start_pos,
15092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                        next_pos );
15102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (maxVal!=FL2FXCONST_DBL(0.f)) {
15122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      preShift = CntLeadingZeros(maxVal)-1;
15142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* If the accu does not provide enough overflow bits, we cannot
15162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         shift the samples up to the limit.
15172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         Instead, keep up to 3 free bits in each sample, i.e. up to
15182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         6 bits after calculation of square.
15192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         Please note the comment on saturated arithmetic above!
15202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      */
15212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      preShift -= SHIFT_BEFORE_SQUARE;
15222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sumAll = FL2FXCONST_DBL(0.0f);
15242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (k=li; k<ui; k++) {
15272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        sumLine = FL2FXCONST_DBL(0.0f);
15292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (analysBufferImag!=NULL) {
15312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (preShift>=0) {
15322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            for (l=start_pos; l<next_pos; l++) {
15332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              temp   = analysBufferReal[l][k] << (int)preShift;
15342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              sumLine += fPow2Div2(temp);
15352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              temp   = analysBufferImag[l][k] << (int)preShift;
15362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              sumLine += fPow2Div2(temp);
15372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            }
15392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          } else {
15402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            for (l=start_pos; l<next_pos; l++) {
15412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              temp   = analysBufferReal[l][k] >> -(int)preShift;
15422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              sumLine += fPow2Div2(temp);
15432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              temp   = analysBufferImag[l][k] >> -(int)preShift;
15442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              sumLine += fPow2Div2(temp);
15452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            }
15462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
15472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        } else
15482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
15492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (preShift>=0) {
15502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            for (l=start_pos; l<next_pos; l++) {
15512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              temp   = analysBufferReal[l][k] << (int)preShift;
15522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              sumLine += fPow2Div2(temp);
15532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            }
15542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          } else {
15552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            for (l=start_pos; l<next_pos; l++) {
15562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              temp   = analysBufferReal[l][k] >> -(int)preShift;
15572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              sumLine += fPow2Div2(temp);
15582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            }
15592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
15602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
15612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* The number of QMF-channels per SBR bands may be up to 15.
15632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           Shift right to avoid overflows in sum over all channels. */
15642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        sumLine = sumLine >> (4-1);
15652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        sumAll  += sumLine;
15662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
15672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Convert double precision to Mantissa/Exponent: */
15692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      shift = fNorm(sumAll);
15702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sum = sumAll << (int)shift;
15712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Divide by width of envelope: */
15732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sum = fMult(sum,invWidth);
15742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Divide by width of Sfb: */
15762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sum = fMult(sum, FX_DBL2FX_SGL(GetInvInt(ui-li)));
15772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Set all Subband energies in the Sfb to the average energy: */
15792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (analysBufferImag!=NULL)
15802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        sum_e = input_e + 4 - shift;  /* -4 to compensate right-shift */
15812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else
15822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        sum_e = input_e + 4 + 1 - shift;  /* -4 to compensate right-shift; +1 due to missing imag. part */
15832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sum_e -= 2 * preShift;
15852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    } /* maxVal!=0 */
15862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else {
15872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Prevent a zero-mantissa-number from being misinterpreted
15892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         due to its exponent. */
15902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sum = FL2FXCONST_DBL(0.0f);
15912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sum_e = 0;
15922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
15932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (k=li; k<ui; k++)
15952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
15962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *nrgEst++   = sum;
15972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *nrgEst_e++ = sum_e;
15982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
15992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
16002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
16012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
16042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief  Calculate gain, noise, and additional sine level for one subband.
16052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  The resulting energy gain is given by mantissa and exponent.
16072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
1608203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void calcSubbandGain(FIXP_DBL  nrgRef,            /*!< Reference Energy according to envelope data */
16092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            SCHAR     nrgRef_e,          /*!< Reference Energy according to envelope data (exponent) */
16102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            ENV_CALC_NRGS* nrgs,
16112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            int       i,
16122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            FIXP_DBL  tmpNoise,          /*!< Relative noise level */
16132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            SCHAR     tmpNoise_e,        /*!< Relative noise level (exponent) */
16142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            UCHAR     sinePresentFlag,   /*!< Indicates if sine is present on band */
16152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            UCHAR     sineMapped,        /*!< Indicates if sine must be added */
16162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            int       noNoiseFlag)       /*!< Flag to suppress noise addition */
16172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
16182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL  nrgEst          = nrgs->nrgEst[i];            /*!< Energy in transposed signal */
16192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR     nrgEst_e        = nrgs->nrgEst_e[i];          /*!< Energy in transposed signal (exponent) */
16202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *ptrNrgGain      = &nrgs->nrgGain[i];          /*!< Resulting energy gain */
16212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR    *ptrNrgGain_e    = &nrgs->nrgGain_e[i];        /*!< Resulting energy gain (exponent) */
16222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *ptrNoiseLevel   = &nrgs->noiseLevel[i];       /*!< Resulting absolute noise energy */
16232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR    *ptrNoiseLevel_e = &nrgs->noiseLevel_e[i];     /*!< Resulting absolute noise energy (exponent) */
16242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *ptrNrgSine      = &nrgs->nrgSine[i];          /*!< Additional sine energy */
16252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR    *ptrNrgSine_e    = &nrgs->nrgSine_e[i];        /*!< Additional sine energy (exponent) */
16262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL a, b, c;
16282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR    a_e, b_e, c_e;
16292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
16312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project     This addition of 1 prevents divisions by zero in the reference code.
16322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project     For very small energies in nrgEst, it prevents the gains from becoming
16332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project     very high which could cause some trouble due to the smoothing.
16342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
16352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  b_e = (int)(nrgEst_e - 1);
16362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (b_e>=0) {
16372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    nrgEst = (FL2FXCONST_DBL(0.5f) >> (INT)fixMin(b_e+1,DFRACT_BITS-1)) + (nrgEst >> 1);
16382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    nrgEst_e += 1;  /* shift by 1 bit to avoid overflow */
16392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  } else {
16412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    nrgEst = (nrgEst >> (INT)(fixMin(-b_e+1,DFRACT_BITS-1))) + (FL2FXCONST_DBL(0.5f) >> 1);
16422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    nrgEst_e = 2;  /* shift by 1 bit to avoid overflow */
16432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
16442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*  A = NrgRef * TmpNoise */
16462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  a = fMult(nrgRef,tmpNoise);
16472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  a_e = nrgRef_e + tmpNoise_e;
16482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*  B = 1 + TmpNoise */
16502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  b_e = (int)(tmpNoise_e - 1);
16512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (b_e>=0) {
16522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    b = (FL2FXCONST_DBL(0.5f) >> (INT)fixMin(b_e+1,DFRACT_BITS-1)) + (tmpNoise >> 1);
16532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    b_e = tmpNoise_e + 1;  /* shift by 1 bit to avoid overflow */
16542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  } else {
16552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    b = (tmpNoise >> (INT)(fixMin(-b_e+1,DFRACT_BITS-1))) + (FL2FXCONST_DBL(0.5f) >> 1);
16562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    b_e = 2;  /* shift by 1 bit to avoid overflow */
16572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
16582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*  noiseLevel = A / B = (NrgRef * TmpNoise) / (1 + TmpNoise) */
16602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDK_divide_MantExp( a,  a_e,
16612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      b,  b_e,
16622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      ptrNoiseLevel, ptrNoiseLevel_e);
16632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (sinePresentFlag) {
16652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*  C = (1 + TmpNoise) * NrgEst */
16672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    c = fMult(b,nrgEst);
16682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    c_e = b_e + nrgEst_e;
16692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*  gain = A / C = (NrgRef * TmpNoise) / (1 + TmpNoise) * NrgEst */
16712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FDK_divide_MantExp( a,  a_e,
16722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        c,  c_e,
16732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        ptrNrgGain, ptrNrgGain_e);
16742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (sineMapped) {
16762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /*  sineLevel = nrgRef/ (1 + TmpNoise) */
16782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FDK_divide_MantExp( nrgRef,  nrgRef_e,
16792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          b,  b_e,
16802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          ptrNrgSine, ptrNrgSine_e);
16812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
16822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
16832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  else {
16842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (noNoiseFlag) {
16852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /*  B = NrgEst */
16862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      b = nrgEst;
16872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      b_e = nrgEst_e;
16882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
16892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else {
16902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /*  B = NrgEst * (1 + TmpNoise) */
16912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      b = fMult(b,nrgEst);
16922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      b_e = b_e + nrgEst_e;
16932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
16942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*  gain = nrgRef / B */
16972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FDK_divide_MantExp( nrgRef,  nrgRef_e,
16982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        b,  b_e,
16992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        ptrNrgGain, ptrNrgGain_e);
17002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
17012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
17022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
17052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief  Calculate "average gain" for the specified subband range.
17062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  This is rather a gain of the average magnitude than the average
17082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  of gains!
17092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  The result is used as a relative limit for all gains within the
17102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  current "limiter band" (a certain frequency range).
17112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
1712203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void calcAvgGain(ENV_CALC_NRGS* nrgs,
17132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        int        lowSubband,    /*!< Begin of the limiter band */
17142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        int        highSubband,   /*!< High end of the limiter band */
17152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        FIXP_DBL  *ptrSumRef,
17162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        SCHAR     *ptrSumRef_e,
17172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        FIXP_DBL  *ptrAvgGain,  /*!< Resulting overall gain (mantissa) */
17182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        SCHAR     *ptrAvgGain_e)  /*!< Resulting overall gain (exponent) */
17192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
17202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL  *nrgRef   = nrgs->nrgRef;       /*!< Reference Energy according to envelope data */
17212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR     *nrgRef_e = nrgs->nrgRef_e;     /*!< Reference Energy according to envelope data (exponent) */
17222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL  *nrgEst   = nrgs->nrgEst;       /*!< Energy in transposed signal */
17232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR     *nrgEst_e = nrgs->nrgEst_e;     /*!< Energy in transposed signal (exponent) */
17242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL sumRef = 1;
17262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL sumEst = 1;
17272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR    sumRef_e = -FRACT_BITS;
17282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR    sumEst_e = -FRACT_BITS;
17292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int      k;
17302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (k=lowSubband; k<highSubband; k++){
17322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Add nrgRef[k] to sumRef: */
17332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FDK_add_MantExp( sumRef, sumRef_e,
17342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                     nrgRef[k], nrgRef_e[k],
17352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                     &sumRef, &sumRef_e );
17362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Add nrgEst[k] to sumEst: */
17382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FDK_add_MantExp( sumEst, sumEst_e,
17392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                     nrgEst[k], nrgEst_e[k],
17402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                     &sumEst, &sumEst_e );
17412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
17422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDK_divide_MantExp(sumRef, sumRef_e,
17442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                     sumEst, sumEst_e,
17452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                     ptrAvgGain, ptrAvgGain_e);
17462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *ptrSumRef = sumRef;
17482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *ptrSumRef_e = sumRef_e;
17492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
17502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1751203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void adjustTimeSlot_EldGrid(
1752203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                              FIXP_DBL *ptrReal,        /*!< Subband samples to be adjusted, real part */
1753203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                              ENV_CALC_NRGS* nrgs,
1754203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                              UCHAR    *ptrHarmIndex,   /*!< Harmonic index */
1755203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                              int       lowSubband,     /*!< Lowest QMF-channel in the currently used SBR range. */
1756203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                              int       noSubbands,     /*!< Number of QMF subbands */
1757203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                              int       scale_change,   /*!< Number of bits to shift adjusted samples */
1758203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                              int       noNoiseFlag,    /*!< Flag to suppress noise addition */
1759203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                              int      *ptrPhaseIndex,  /*!< Start index to random number array */
1760203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                              int       scale_diff_low) /*!<  */
1761203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi{
1762203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi  int k;
1763203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi  FIXP_DBL  signalReal, sbNoise;
1764203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi  int tone_count = 0;
1765203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
1766203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi  FIXP_DBL *pGain       = nrgs->nrgGain;     /*!< Gains of current envelope */
1767203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi  FIXP_DBL *pNoiseLevel = nrgs->noiseLevel;  /*!< Noise levels of current envelope */
1768203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi  FIXP_DBL *pSineLevel  = nrgs->nrgSine;     /*!< Sine levels */
1769203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
1770203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi  int    phaseIndex = *ptrPhaseIndex;
1771203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi  UCHAR  harmIndex  = *ptrHarmIndex;
1772203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
1773203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi  static const INT harmonicPhase [2][4] = {
1774203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    { 1, 0, -1,  0},
1775203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    { 0, 1,  0, -1}
1776203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi  };
1777203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
1778203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi  static const FIXP_DBL harmonicPhaseX [2][4] = {
1779203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    { FL2FXCONST_DBL(2.0*1.245183154539139e-001),  FL2FXCONST_DBL(2.0*-1.123767859325028e-001),  FL2FXCONST_DBL(2.0*-1.245183154539139e-001), FL2FXCONST_DBL(2.0* 1.123767859325028e-001) },
1780203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    { FL2FXCONST_DBL(2.0*1.245183154539139e-001),  FL2FXCONST_DBL(2.0* 1.123767859325028e-001),  FL2FXCONST_DBL(2.0*-1.245183154539139e-001), FL2FXCONST_DBL(2.0*-1.123767859325028e-001) }
1781203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi  };
1782203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
1783203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi  for (k=0; k < noSubbands; k++) {
1784203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
1785203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    phaseIndex = (phaseIndex + 1) & (SBR_NF_NO_RANDOM_VAL - 1);
1786203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
1787203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    if( (pSineLevel[0] != FL2FXCONST_DBL(0.0f)) || (noNoiseFlag == 1) ){
1788203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      sbNoise = FL2FXCONST_DBL(0.0f);
1789203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    } else {
1790203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      sbNoise = pNoiseLevel[0];
1791203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    }
1792203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
1793203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    signalReal = fMultDiv2(*ptrReal,*pGain) << ((int)scale_change);
1794203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
1795203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[phaseIndex][0], sbNoise)<<4);
1796203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
1797203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    signalReal += pSineLevel[0] * harmonicPhase[0][harmIndex];
1798203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
1799203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    *ptrReal = signalReal;
1800203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
1801203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    if (k == 0) {
1802203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      *(ptrReal-1) += scaleValue(fMultDiv2(harmonicPhaseX[lowSubband&1][harmIndex], pSineLevel[0]), -scale_diff_low)  ;
1803203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      if (k < noSubbands - 1) {
1804203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi        *(ptrReal)   += fMultDiv2(pSineLevel[1], harmonicPhaseX[(lowSubband+1)&1][harmIndex]);
1805203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      }
1806203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    }
1807203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    if (k > 0 && k < noSubbands - 1 && tone_count < 16) {
1808203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      *(ptrReal)   += fMultDiv2(pSineLevel[- 1], harmonicPhaseX [(lowSubband+k)&1]  [harmIndex]);
1809203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      *(ptrReal)   += fMultDiv2(pSineLevel[+ 1], harmonicPhaseX [(lowSubband+k+1)&1][harmIndex]);
1810203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    }
1811203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    if (k == noSubbands - 1 && tone_count < 16) {
1812203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      if (k > 0) {
1813203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi        *(ptrReal)   += fMultDiv2(pSineLevel[- 1], harmonicPhaseX [(lowSubband+k)&1][harmIndex]);
1814203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      }
1815203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      if (k + lowSubband + 1< 63) {
1816203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi        *(ptrReal+1) += fMultDiv2(pSineLevel[0], harmonicPhaseX[(lowSubband+k+1)&1][harmIndex]);
1817203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      }
1818203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    }
1819203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
1820203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    if(pSineLevel[0] != FL2FXCONST_DBL(0.0f)){
1821203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      tone_count++;
1822203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    }
1823203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    ptrReal++;
1824203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    pNoiseLevel++;
1825203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    pGain++;
1826203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi    pSineLevel++;
1827203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi  }
1828203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
1829203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi  *ptrHarmIndex = (harmIndex + 1) & 3;
1830203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi  *ptrPhaseIndex = phaseIndex & (SBR_NF_NO_RANDOM_VAL - 1);
1831203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi}
18322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
18342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief   Amplify one timeslot of the signal with the calculated gains
18352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           and add the noisefloor.
18362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
18372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1838203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void adjustTimeSlotLC(FIXP_DBL *ptrReal,       /*!< Subband samples to be adjusted, real part */
18392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                             ENV_CALC_NRGS* nrgs,
18402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                             UCHAR    *ptrHarmIndex,  /*!< Harmonic index */
18412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                             int       lowSubband,    /*!< Lowest QMF-channel in the currently used SBR range. */
18422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                             int       noSubbands,    /*!< Number of QMF subbands */
18432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                             int       scale_change,  /*!< Number of bits to shift adjusted samples */
18442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                             int       noNoiseFlag,   /*!< Flag to suppress noise addition */
1845203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                             int      *ptrPhaseIndex) /*!< Start index to random number array */
18462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
18472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *pGain       = nrgs->nrgGain;     /*!< Gains of current envelope */
18482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *pNoiseLevel = nrgs->noiseLevel;  /*!< Noise levels of current envelope */
18492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *pSineLevel  = nrgs->nrgSine;     /*!< Sine levels */
18502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int    k;
18522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int    index = *ptrPhaseIndex;
18532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR  harmIndex = *ptrHarmIndex;
18542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR  freqInvFlag = (lowSubband & 1);
18552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL  signalReal, sineLevel, sineLevelNext, sineLevelPrev;
18562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int    tone_count = 0;
18572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int    sineSign = 1;
18582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  #define C1   ((FIXP_SGL)FL2FXCONST_SGL(2.f*0.00815f))
18602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  #define C1_CLDFB ((FIXP_SGL)FL2FXCONST_SGL(2.f*0.16773f))
18612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
18632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    First pass for k=0 pulled out of the loop:
18642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
18652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  index = (index + 1) & (SBR_NF_NO_RANDOM_VAL - 1);
18672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
18692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    The next multiplication constitutes the actual envelope adjustment
18702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    of the signal and should be carried out with full accuracy
18712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    (supplying #FRACT_BITS valid bits).
18722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
18732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  signalReal    = fMultDiv2(*ptrReal,*pGain++) << ((int)scale_change);
18742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  sineLevel     = *pSineLevel++;
18752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  sineLevelNext = (noSubbands > 1) ? pSineLevel[0] : FL2FXCONST_DBL(0.0f);
18762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (sineLevel!=FL2FXCONST_DBL(0.0f)) tone_count++;
18782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  else if (!noNoiseFlag)
18792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* Add noisefloor to the amplified signal */
18802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4);
18812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  {
18832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (!(harmIndex&0x1)) {
18842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* harmIndex 0,2 */
18852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      signalReal += (harmIndex&0x2) ? -sineLevel : sineLevel;
18862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *ptrReal++ = signalReal;
18872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
18882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else {
18892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* harmIndex 1,3 in combination with freqInvFlag */
18902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      int shift = (int) (scale_change+1);
18912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      shift = (shift>=0) ? fixMin(DFRACT_BITS-1,shift) : fixMax(-(DFRACT_BITS-1),shift);
18922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL tmp1 = (shift>=0) ? ( fMultDiv2(C1, sineLevel) >> shift )
18942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                 : ( fMultDiv2(C1, sineLevel) << (-shift) );
18952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL tmp2 = fMultDiv2(C1, sineLevelNext);
18962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* save switch and compare operations and reduce to XOR statement */
18992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if ( ((harmIndex>>1)&0x1)^freqInvFlag) {
19002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *(ptrReal-1) += tmp1;
19012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal   -= tmp2;
19022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      } else {
19032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *(ptrReal-1) -= tmp1;
19042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal   += tmp2;
19052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
19062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *ptrReal++ = signalReal;
19072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      freqInvFlag = !freqInvFlag;
19082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
19092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
19102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  pNoiseLevel++;
19122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if ( noSubbands > 2 ) {
19142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (!(harmIndex&0x1)) {
19152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* harmIndex 0,2 */
19162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if(!harmIndex)
19172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
19182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        sineSign = 0;
19192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
19202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (k=noSubbands-2; k!=0; k--) {
19222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FIXP_DBL sinelevel = *pSineLevel++;
19232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        index++;
19242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (((signalReal = (sineSign ? -sinelevel : sinelevel)) == FL2FXCONST_DBL(0.0f))  && !noNoiseFlag)
19252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
19262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* Add noisefloor to the amplified signal */
19272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          index &= (SBR_NF_NO_RANDOM_VAL - 1);
19282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4);
19292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
19302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* The next multiplication constitutes the actual envelope adjustment of the signal. */
19322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        signalReal += fMultDiv2(*ptrReal,*pGain++) << ((int)scale_change);
19332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pNoiseLevel++;
19352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        *ptrReal++ = signalReal;
19362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      } /* for ... */
19372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
19382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else {
19392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* harmIndex 1,3 in combination with freqInvFlag */
19402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (harmIndex==1) freqInvFlag = !freqInvFlag;
19412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (k=noSubbands-2; k!=0; k--) {
19432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        index++;
19442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* The next multiplication constitutes the actual envelope adjustment of the signal. */
19452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        signalReal = fMultDiv2(*ptrReal,*pGain++) << ((int)scale_change);
19462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (*pSineLevel++!=FL2FXCONST_DBL(0.0f)) tone_count++;
19482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        else if (!noNoiseFlag) {
19492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* Add noisefloor to the amplified signal */
19502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          index &= (SBR_NF_NO_RANDOM_VAL - 1);
19512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4);
19522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
19532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pNoiseLevel++;
19552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (tone_count <= 16) {
19572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FIXP_DBL addSine = fMultDiv2((pSineLevel[-2] - pSineLevel[0]), C1);
19582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal += (freqInvFlag) ? (-addSine) : (addSine);
19592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
19602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        *ptrReal++ = signalReal;
19622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        freqInvFlag = !freqInvFlag;
19632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      } /* for ... */
19642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
19652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
19662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (noSubbands > -1) {
19682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    index++;
19692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* The next multiplication constitutes the actual envelope adjustment of the signal. */
19702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    signalReal    = fMultDiv2(*ptrReal,*pGain) << ((int)scale_change);
19712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    sineLevelPrev = fMultDiv2(pSineLevel[-1],FL2FX_SGL(0.0163f));
19722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    sineLevel     = pSineLevel[0];
19732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (pSineLevel[0]!=FL2FXCONST_DBL(0.0f)) tone_count++;
19752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else if (!noNoiseFlag) {
19762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* Add noisefloor to the amplified signal */
19772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        index &= (SBR_NF_NO_RANDOM_VAL - 1);
19782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        signalReal = signalReal + (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4);
19792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
19802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (!(harmIndex&0x1)) {
19822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* harmIndex 0,2 */
19832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *ptrReal = signalReal + ( (sineSign) ? -sineLevel : sineLevel);
19842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
19852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else {
19862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* harmIndex 1,3 in combination with freqInvFlag */
19872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if(tone_count <= 16){
19882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (freqInvFlag) {
19892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrReal++   = signalReal - sineLevelPrev;
19902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (noSubbands + lowSubband < 63)
19912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            *ptrReal = *ptrReal + fMultDiv2(C1, sineLevel);
19922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
19932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        else {
19942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrReal++ = signalReal + sineLevelPrev;
19952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (noSubbands + lowSubband < 63)
19962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            *ptrReal = *ptrReal - fMultDiv2(C1, sineLevel);
19972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
19982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
19992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else *ptrReal = signalReal;
20002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
20012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
20022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *ptrHarmIndex = (harmIndex + 1) & 3;
20032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *ptrPhaseIndex = index & (SBR_NF_NO_RANDOM_VAL - 1);
20042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
2005203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivistatic void adjustTimeSlotHQ(
2006203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                      FIXP_DBL *RESTRICT ptrReal,      /*!< Subband samples to be adjusted, real part */
2007203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi                      FIXP_DBL *RESTRICT ptrImag,      /*!< Subband samples to be adjusted, imag part */
20082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env,
20092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      ENV_CALC_NRGS* nrgs,
20102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      int       lowSubband,            /*!< Lowest QMF-channel in the currently used SBR range. */
20112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      int       noSubbands,            /*!< Number of QMF subbands */
20122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      int       scale_change,          /*!< Number of bits to shift adjusted samples */
20132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      FIXP_SGL  smooth_ratio,          /*!< Impact of last envelope */
20142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      int       noNoiseFlag,           /*!< Start index to random number array */
20152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      int       filtBufferNoiseShift)  /*!< Shift factor of filtBufferNoise */
20162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
20172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *RESTRICT gain       = nrgs->nrgGain;        /*!< Gains of current envelope */
20192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *RESTRICT noiseLevel = nrgs->noiseLevel;     /*!< Noise levels of current envelope */
20202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine;        /*!< Sine levels */
20212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *RESTRICT filtBuffer      = h_sbr_cal_env->filtBuffer;      /*!< Gains of last envelope */
20232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *RESTRICT filtBufferNoise = h_sbr_cal_env->filtBufferNoise; /*!< Noise levels of last envelope */
20242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR    *RESTRICT ptrHarmIndex    =&h_sbr_cal_env->harmIndex;       /*!< Harmonic index */
20252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int      *RESTRICT ptrPhaseIndex   =&h_sbr_cal_env->phaseIndex;      /*!< Start index to random number array */
20262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int    k;
20282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL signalReal, signalImag;
20292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL noiseReal,  noiseImag;
20302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL  smoothedGain, smoothedNoise;
20312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_SGL direct_ratio = /*FL2FXCONST_SGL(1.0f) */ (FIXP_SGL)MAXVAL_SGL - smooth_ratio;
20322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int    index = *ptrPhaseIndex;
20332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR   harmIndex = *ptrHarmIndex;
20342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  register int freqInvFlag = (lowSubband & 1);
20352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL sineLevel;
20362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int shift;
20372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *ptrPhaseIndex = (index+noSubbands) & (SBR_NF_NO_RANDOM_VAL - 1);
20392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *ptrHarmIndex = (harmIndex + 1) & 3;
20402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
20422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    Possible optimization:
20432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    smooth_ratio and harmIndex stay constant during the loop.
20442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    It might be faster to include a separate loop in each path.
20452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    the check for smooth_ratio is now outside the loop and the workload
20472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    of the whole function decreased by about 20 %
20482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
20492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  filtBufferNoiseShift += 1;      /* due to later use of fMultDiv2 instead of fMult */
20512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (filtBufferNoiseShift<0)
20522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    shift = fixMin(DFRACT_BITS-1,-filtBufferNoiseShift);
20532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  else
20542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    shift = fixMin(DFRACT_BITS-1, filtBufferNoiseShift);
20552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (smooth_ratio > FL2FXCONST_SGL(0.0f)) {
20572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (k=0; k<noSubbands; k++) {
20592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /*
20602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        Smoothing: The old envelope has been bufferd and a certain ratio
20612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        of the old gains and noise levels is used.
20622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      */
20632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      smoothedGain = fMult(smooth_ratio,filtBuffer[k]) +
20652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                     fMult(direct_ratio,gain[k]);
20662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (filtBufferNoiseShift<0) {
20682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        smoothedNoise = (fMultDiv2(smooth_ratio,filtBufferNoise[k])>>shift) +
20692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                         fMult(direct_ratio,noiseLevel[k]);
20702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
20712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else {
20722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        smoothedNoise = (fMultDiv2(smooth_ratio,filtBufferNoise[k])<<shift) +
20732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                         fMult(direct_ratio,noiseLevel[k]);
20742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
20752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /*
20772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        The next 2 multiplications constitute the actual envelope adjustment
20782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        of the signal and should be carried out with full accuracy
20792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        (supplying #DFRACT_BITS valid bits).
20802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      */
20812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      signalReal = fMultDiv2(*ptrReal,smoothedGain)<<((int)scale_change);
20822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      signalImag = fMultDiv2(*ptrImag,smoothedGain)<<((int)scale_change);
20832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      index++;
20852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (pSineLevel[k] != FL2FXCONST_DBL(0.0f)) {
20872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        sineLevel = pSineLevel[k];
20882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        switch(harmIndex) {
20902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case 0:
20912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrReal++ = (signalReal + sineLevel);
20922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrImag++ = (signalImag);
20932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
20942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case 2:
20952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrReal++ = (signalReal - sineLevel);
20962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrImag++ = (signalImag);
20972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
20982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case 1:
20992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrReal++ = (signalReal);
21002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (freqInvFlag)
21012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            *ptrImag++ = (signalImag - sineLevel);
21022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          else
21032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            *ptrImag++ = (signalImag + sineLevel);
21042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
21052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case 3:
21062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrReal++ = signalReal;
21072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (freqInvFlag)
21082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            *ptrImag++ = (signalImag + sineLevel);
21092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          else
21102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            *ptrImag++ = (signalImag - sineLevel);
21112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
21122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
21132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
21142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else {
21152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (noNoiseFlag) {
21162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* Just the amplified signal is saved */
21172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrReal++ = (signalReal);
21182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrImag++ = (signalImag);
21192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
21202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        else {
21212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* Add noisefloor to the amplified signal */
21222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          index &= (SBR_NF_NO_RANDOM_VAL - 1);
21232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          noiseReal = fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], smoothedNoise)<<4;
21242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          noiseImag = fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][1], smoothedNoise)<<4;
21252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrReal++ = (signalReal + noiseReal);
21262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrImag++ = (signalImag + noiseImag);
21272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
21282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
21292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      freqInvFlag ^= 1;
21302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
21312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
21332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  else
21342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  {
21352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (k=0; k<noSubbands; k++)
21362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
21372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      smoothedGain  = gain[k];
21382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      signalReal = fMultDiv2(*ptrReal, smoothedGain) << scale_change;
21392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      signalImag = fMultDiv2(*ptrImag, smoothedGain) << scale_change;
21402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      index++;
21422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if ((sineLevel = pSineLevel[k]) != FL2FXCONST_DBL(0.0f))
21442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
21452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        switch (harmIndex)
21462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
21472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case 0:
21482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal += sineLevel;
21492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
21502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case 1:
21512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (freqInvFlag)
21522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            signalImag -= sineLevel;
21532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          else
21542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            signalImag += sineLevel;
21552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
21562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case 2:
21572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal -= sineLevel;
21582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
21592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case 3:
21602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (freqInvFlag)
21612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            signalImag += sineLevel;
21622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          else
21632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            signalImag -= sineLevel;
21642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
21652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
21662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
21672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else
21682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
21692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (noNoiseFlag == 0)
21702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
21712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* Add noisefloor to the amplified signal */
21722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          smoothedNoise = noiseLevel[k];
21732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          index &= (SBR_NF_NO_RANDOM_VAL - 1);
21742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          noiseReal = fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], smoothedNoise);
21752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          noiseImag = fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][1], smoothedNoise);
21762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal += noiseReal<<4;
21772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalImag += noiseImag<<4;
21782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
21792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
21802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *ptrReal++ = signalReal;
21812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *ptrImag++ = signalImag;
21822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      freqInvFlag ^= 1;
21842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
21852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
21862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
21872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
21902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief   Reset limiter bands.
21912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Build frequency band table for the gain limiter dependent on
21932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  the previously generated transposer patch areas.
21942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \return  SBRDEC_OK if ok,  SBRDEC_UNSUPPORTED_CONFIG on error
21962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
21972228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectSBR_ERROR
21982228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectResetLimiterBands ( UCHAR *limiterBandTable,   /*!< Resulting band borders in QMF channels */
21992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    UCHAR *noLimiterBands,     /*!< Resulting number of limiter band */
22002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    UCHAR *freqBandTable,      /*!< Table with possible band borders */
22012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    int noFreqBands,                   /*!< Number of bands in freqBandTable */
22022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    const PATCH_PARAM *patchParam,     /*!< Transposer patch parameters */
22032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    int noPatches,                     /*!< Number of transposer patches */
22042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    int limiterBands)                  /*!< Selected 'band density' from bitstream */
22052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
22062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int i, k, isPatchBorder[2], loLimIndex, hiLimIndex, tempNoLim, nBands;
22072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR workLimiterBandTable[MAX_FREQ_COEFFS / 2 + MAX_NUM_PATCHES + 1];
22082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int patchBorders[MAX_NUM_PATCHES + 1];
22092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int kx, k2;
22102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
22112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int lowSubband = freqBandTable[0];
22122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int highSubband = freqBandTable[noFreqBands];
22132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
22142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* 1 limiter band. */
22152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if(limiterBands == 0) {
22162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    limiterBandTable[0] = 0;
22172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    limiterBandTable[1] = highSubband - lowSubband;
22182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    nBands = 1;
22192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  } else {
22202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (i = 0; i < noPatches; i++) {
22212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      patchBorders[i] = patchParam[i].guardStartBand - lowSubband;
22222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
22232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    patchBorders[i] = highSubband - lowSubband;
22242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
22252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* 1.2, 2, or 3 limiter bands/octave plus bandborders at patchborders. */
22262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (k = 0; k <= noFreqBands; k++) {
22272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      workLimiterBandTable[k] = freqBandTable[k] - lowSubband;
22282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
22292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (k = 1; k < noPatches; k++) {
22302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      workLimiterBandTable[noFreqBands + k] = patchBorders[k];
22312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
22322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
22332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    tempNoLim = nBands = noFreqBands + noPatches - 1;
22342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    shellsort(workLimiterBandTable, tempNoLim + 1);
22352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
22362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    loLimIndex = 0;
22372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    hiLimIndex = 1;
22382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
22392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
22402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    while (hiLimIndex <= tempNoLim) {
2241203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      FIXP_DBL div_m, oct_m, temp;
2242203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      INT div_e  = 0, oct_e  = 0, temp_e = 0;
2243203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
22442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      k2 = workLimiterBandTable[hiLimIndex] + lowSubband;
22452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      kx = workLimiterBandTable[loLimIndex] + lowSubband;
22462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2247203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      div_m  = fDivNorm(k2, kx, &div_e);
2248203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
2249203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      /* calculate number of octaves */
2250203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      oct_m  = fLog2(div_m, div_e, &oct_e);
2251203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
2252203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      /* multiply with limiterbands per octave    */
2253203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      /* values 1, 1.2, 2, 3 -> scale factor of 2 */
2254203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      temp = fMultNorm(oct_m, FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[limiterBands], &temp_e);
2255203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
2256203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      /* overall scale factor of temp ist addition of scalefactors from log2 calculation,
2257203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi         limiter bands scalefactor (2) and limiter bands multiplication */
2258203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      temp_e += oct_e + 2;
2259203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi
2260203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      /*    div can be a maximum of 64 (k2 = 64 and kx = 1)
2261203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi         -> oct can be a maximum of 6
2262203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi         -> temp can be a maximum of 18 (as limiterBandsPerOctoave is a maximum factor of 3)
2263203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi         -> we need a scale factor of 5 for comparisson
2264203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      */
2265203e3f28fbebec7011342017fafc2a0bda0ce530Jean-Michel Trivi      if (temp >> (5 - temp_e) < FL2FXCONST_DBL (0.49f) >> 5) {
22662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
22672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (workLimiterBandTable[hiLimIndex] == workLimiterBandTable[loLimIndex]) {
22682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          workLimiterBandTable[hiLimIndex] = highSubband;
22692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          nBands--;
22702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          hiLimIndex++;
22712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          continue;
22722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
22732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        isPatchBorder[0] = isPatchBorder[1] = 0;
22742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        for (k = 0; k <= noPatches; k++) {
22752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (workLimiterBandTable[hiLimIndex] == patchBorders[k]) {
22762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            isPatchBorder[1] = 1;
22772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            break;
22782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
22792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
22802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (!isPatchBorder[1]) {
22812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          workLimiterBandTable[hiLimIndex] = highSubband;
22822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          nBands--;
22832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          hiLimIndex++;
22842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          continue;
22852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
22862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        for (k = 0; k <= noPatches; k++) {
22872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (workLimiterBandTable[loLimIndex] == patchBorders[k]) {
22882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            isPatchBorder[0] = 1;
22892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            break;
22902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
22912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
22922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (!isPatchBorder[0]) {
22932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          workLimiterBandTable[loLimIndex] = highSubband;
22942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          nBands--;
22952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
22962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
22972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      loLimIndex = hiLimIndex;
22982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      hiLimIndex++;
22992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
23002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
23012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    shellsort(workLimiterBandTable, tempNoLim + 1);
23022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
23032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Test if algorithm exceeded maximum allowed limiterbands */
23042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if( nBands > MAX_NUM_LIMITERS || nBands <= 0) {
23052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      return SBRDEC_UNSUPPORTED_CONFIG;
23062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
23072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
23082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Copy limiterbands from working buffer into final destination */
23092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (k = 0; k <= nBands; k++) {
23102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      limiterBandTable[k] = workLimiterBandTable[k];
23112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
23122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
23132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *noLimiterBands = nBands;
23142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
23152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  return SBRDEC_OK;
23162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
23172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2318