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
54f0d97057c5c640b25518358886f8c47da9fc052Jean-Michel Trivi� Copyright  1995 - 2013 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
1542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*static*/ 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
1602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*static*/ 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
1682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*static*/ 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
1772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*static*/ 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
1832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*static*/ 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
1912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*static*/ void adjustTimeSlotLC(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,
1992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int    fCldfb);
2002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*static*/ void adjustTimeSlotHQ(FIXP_DBL  *ptrReal,
2012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           FIXP_DBL  *ptrImag,
2022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env,
2032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           ENV_CALC_NRGS* nrgs,
2042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int    lowSubbands,
2052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int    noSubbands,
2062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int    scale_change,
2072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           FIXP_SGL smooth_ratio,
2082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int    noNoiseFlag,
2092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int    filtBufferNoiseShift);
2102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
2132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief     Map sine flags from bitstream to QMF bands
2142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  The bitstream carries only 1 sine flag per band and frame.
2162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  This function maps every sine flag from the bitstream to a specific QMF subband
2172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  and to a specific envelope where the sine shall start.
2182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  The result is stored in the vector sineMapped which contains one entry per
2192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  QMF subband. The value of an entry specifies the envelope where a sine
2202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  shall start. A value of #MAX_ENVELOPES indicates that no sine is present
2212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  in the subband.
2222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  The missing harmonics flags from the previous frame (harmFlagsPrev) determine
2232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if a sine starts at the beginning of the frame or at the transient position.
2242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Additionally, the flags in harmFlagsPrev are being updated by this function
2252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for the next frame.
2262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
2272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*static*/ void mapSineFlags(UCHAR *freqBandTable, /*!< Band borders (there's only 1 flag per band) */
2282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                         int nSfb,                     /*!< Number of bands in the table */
2292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                         UCHAR *addHarmonics,           /*!< vector with 1 flag per sfb */
2302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                         int *harmFlagsPrev,           /*!< Packed 'addHarmonics' */
2312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                         int tranEnv,                  /*!< Transient position */
2322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                         SCHAR *sineMapped)            /*!< Resulting vector of sine start positions for each QMF band */
2332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
2352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int i;
2362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int lowSubband2 = freqBandTable[0]<<1;
2372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int bitcount = 0;
2382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int oldflags = *harmFlagsPrev;
2392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int newflags = 0;
2402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
2422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    Format of harmFlagsPrev:
2432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    first word = flags for highest 16 sfb bands in use
2452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    second word = flags for next lower 16 sfb bands (if present)
2462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    third word = flags for lowest 16 sfb bands (if present)
2472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    Up to MAX_FREQ_COEFFS sfb bands can be flagged for a sign.
2492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    The lowest bit of the first word corresponds to the _highest_ sfb band in use.
2502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    This is ensures that each flag is  mapped to the same QMF band even after a
2512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    change of the crossover-frequency.
2522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
2532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Reset the output vector first */
2562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDKmemset(sineMapped, MAX_ENVELOPES,MAX_FREQ_COEFFS); /* MAX_ENVELOPES means 'no sine' */
2572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  freqBandTable += nSfb;
2592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  addHarmonics  += nSfb-1;
2602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (i=nSfb; i!=0; i--) {
2622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int ui = *freqBandTable--;                 /* Upper limit of the current scale factor band. */
2632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int li = *freqBandTable;                   /* Lower limit of the current scale factor band. */
2642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if ( *addHarmonics-- ) {                   /* There is a sine in this band */
2662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      unsigned int mask = 1 << bitcount;
2682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      newflags |= mask;                        /* Set flag */
2692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /*
2712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        If there was a sine in the last frame, let it continue from the first envelope on
2722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        else start at the transient position.
2732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      */
2742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sineMapped[(ui+li-lowSubband2) >> 1] = ( oldflags & mask ) ? 0 : tranEnv;
2752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
2762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if ((++bitcount == 16) || i==1) {
2782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      bitcount = 0;
2792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *harmFlagsPrev++ = newflags;
2802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      oldflags = *harmFlagsPrev;               /* Fetch 16 of the old flags */
2812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      newflags = 0;
2822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
2832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
2842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
2852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
2882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief     Reduce gain-adjustment induced aliasing for real valued filterbank.
2892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
2902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*static*/ void
2912228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectaliasingReduction(FIXP_DBL* degreeAlias,       /*!< estimated aliasing for each QMF channel */
2922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                  ENV_CALC_NRGS* nrgs,
2932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                  int*      useAliasReduction, /*!< synthetic sine engergy for each subband, used as flag */
2942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                  int       noSubbands)        /*!< number of QMF channels to process */
2952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
2962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL* nrgGain   = nrgs->nrgGain;          /*!< subband gains to be modified */
2972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR*    nrgGain_e = nrgs->nrgGain_e;        /*!< subband gains to be modified (exponents) */
2982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL* nrgEst    = nrgs->nrgEst;           /*!< subband energy before amplification */
2992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR*    nrgEst_e  = nrgs->nrgEst_e;         /*!< subband energy before amplification (exponents) */
3002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int grouping = 0, index = 0, noGroups, k;
3012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int groupVector[MAX_FREQ_COEFFS];
3022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Calculate grouping*/
3042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (k = 0; k < noSubbands-1; k++ ){
3052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if ( (degreeAlias[k + 1] != FL2FXCONST_DBL(0.0f)) && useAliasReduction[k] ) {
3062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if(grouping==0){
3072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        groupVector[index++] = k;
3082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        grouping = 1;
3092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
3102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else{
3112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if(groupVector[index-1] + 3 == k){
3122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          groupVector[index++] = k + 1;
3132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          grouping = 0;
3142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
3152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
3162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
3172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else{
3182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if(grouping){
3192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if(useAliasReduction[k])
3202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          groupVector[index++] = k + 1;
3212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        else
3222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          groupVector[index++] = k;
3232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        grouping = 0;
3242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
3252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
3262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
3272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if(grouping){
3292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    groupVector[index++] = noSubbands;
3302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
3312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  noGroups = index >> 1;
3322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*Calculate new gain*/
3352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (int group = 0; group < noGroups; group ++) {
3362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL nrgOrig = FL2FXCONST_DBL(0.0f);    /* Original signal energy in current group of bands */
3372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR    nrgOrig_e = 0;
3382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL nrgAmp = FL2FXCONST_DBL(0.0f);     /* Amplified signal energy in group (using current gains) */
3392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR    nrgAmp_e = 0;
3402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL nrgMod = FL2FXCONST_DBL(0.0f);   /* Signal energy in group when applying modified gains */
3412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR    nrgMod_e = 0;
3422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL groupGain;         /* Total energy gain in group */
3432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR    groupGain_e;
3442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL compensation;      /* Compensation factor for the energy change when applying modified gains */
3452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR    compensation_e;
3462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int startGroup = groupVector[2*group];
3482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int stopGroup  = groupVector[2*group+1];
3492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Calculate total energy in group before and after amplification with current gains: */
3512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for(k = startGroup; k < stopGroup; k++){
3522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Get original band energy */
3532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL tmp = nrgEst[k];
3542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      SCHAR    tmp_e = nrgEst_e[k];
3552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FDK_add_MantExp(tmp, tmp_e, nrgOrig, nrgOrig_e, &nrgOrig, &nrgOrig_e);
3572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Multiply band energy with current gain */
3592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      tmp = fMult(tmp,nrgGain[k]);
3602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      tmp_e = tmp_e + nrgGain_e[k];
3612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FDK_add_MantExp(tmp, tmp_e, nrgAmp, nrgAmp_e, &nrgAmp, &nrgAmp_e);
3632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
3642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Calculate total energy gain in group */
3662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FDK_divide_MantExp(nrgAmp, nrgAmp_e,
3672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       nrgOrig, nrgOrig_e,
3682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       &groupGain, &groupGain_e);
3692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for(k = startGroup; k < stopGroup; k++){
3712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL tmp;
3722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      SCHAR    tmp_e;
3732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL alpha = degreeAlias[k];
3752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (k < noSubbands - 1) {
3762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (degreeAlias[k + 1] > alpha)
3772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          alpha = degreeAlias[k + 1];
3782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
3792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Modify gain depending on the degree of aliasing */
3812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FDK_add_MantExp( fMult(alpha,groupGain), groupGain_e,
3822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       fMult(/*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - alpha,nrgGain[k]), nrgGain_e[k],
3832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       &nrgGain[k], &nrgGain_e[k] );
3842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Apply modified gain to original energy */
3862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      tmp = fMult(nrgGain[k],nrgEst[k]);
3872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      tmp_e = nrgGain_e[k] + nrgEst_e[k];
3882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Accumulate energy with modified gains applied */
3902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FDK_add_MantExp( tmp, tmp_e,
3912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       nrgMod, nrgMod_e,
3922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       &nrgMod, &nrgMod_e );
3932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
3942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Calculate compensation factor to retain the energy of the amplified signal */
3962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FDK_divide_MantExp(nrgAmp, nrgAmp_e,
3972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       nrgMod, nrgMod_e,
3982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       &compensation, &compensation_e);
3992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Apply compensation factor to all gains of the group */
4012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for(k = startGroup; k < stopGroup; k++){
4022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      nrgGain[k] = fMult(nrgGain[k],compensation);
4032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      nrgGain_e[k] = nrgGain_e[k] + compensation_e;
4042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
4052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
4062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
4072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project /* Convert headroom bits to exponent */
4102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define SCALE2EXP(s) (15-(s))
4112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define EXP2SCALE(e) (15-(e))
4122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
4142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief  Apply spectral envelope to subband samples
4152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  This function is called from sbr_dec.cpp in each frame.
4172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  To enhance accuracy and due to the usage of tables for squareroots and
4192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  inverse, some calculations are performed with the operands being split
4202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  into mantissa and exponent. The variable names in the source code carry
4212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  the suffixes <em>_m</em> and  <em>_e</em> respectively. The control data
4222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  in #hFrameData containts envelope data which is represented by this format but
4232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  stored in single words. (See requantizeEnvelopeData() for details). This data
4242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  is unpacked within calculateSbrEnvelope() to follow the described suffix convention.
4252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  The actual value (comparable to the corresponding float-variable in the
4272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  research-implementation) of a mantissa/exponent-pair can be calculated as
4282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \f$ value = value\_m * 2^{value\_e} \f$
4302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  All energies and noise levels decoded from the bitstream suit for an
4322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  original signal magnitude of \f$\pm 32768 \f$ rather than \f$ \pm 1\f$. Therefore,
4332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  the scale factor <em>hb_scale</em> passed into this function will be converted
4342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  to an 'input exponent' (#input_e), which fits the internal representation.
4352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Before the actual processing, an exponent #adj_e for resulting adjusted
4372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  samples is derived from the maximum reference energy.
4382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Then, for each envelope, the following steps are performed:
4402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \li Calculate energy in the signal to be adjusted. Depending on the the value of
4422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      #interpolFreq (interpolation mode), this is either done seperately
4432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for each QMF-subband or for each SBR-band.
4442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      The resulting energies are stored in #nrgEst_m[#MAX_FREQ_COEFFS] (mantissas)
4452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      and #nrgEst_e[#MAX_FREQ_COEFFS] (exponents).
4462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \li Calculate gain and noise level for each subband:<br>
4472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      \f$ gain  = \sqrt{ \frac{nrgRef}{nrgEst} \cdot (1 - noiseRatio) }
4482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          \hspace{2cm}
4492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          noise = \sqrt{ nrgRef \cdot noiseRatio }
4502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      \f$<br>
4512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      where <em>noiseRatio</em> and <em>nrgRef</em> are extracted from the
4522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      bitstream and <em>nrgEst</em> is the subband energy before adjustment.
4532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      The resulting gains are stored in #nrgGain_m[#MAX_FREQ_COEFFS]
4542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      (mantissas) and #nrgGain_e[#MAX_FREQ_COEFFS] (exponents), the noise levels
4552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      are stored in #noiseLevel_m[#MAX_FREQ_COEFFS] and #noiseLevel_e[#MAX_FREQ_COEFFS]
4562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      (exponents).
4572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      The sine levels are stored in #nrgSine_m[#MAX_FREQ_COEFFS]
4582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      and #nrgSine_e[#MAX_FREQ_COEFFS].
4592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \li Noise limiting: The gain for each subband is limited both absolutely
4602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      and relatively compared to the total gain over all subbands.
4612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \li Boost gain: Calculate and apply boost factor for each limiter band
4622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      in order to compensate for the energy loss imposed by the limiting.
4632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \li Apply gains and add noise: The gains and noise levels are applied
4642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      to all timeslots of the current envelope. A short FIR-filter (length 4
4652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      QMF-timeslots) can be used to smooth the sudden change at the envelope borders.
4662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      Each complex subband sample of the current timeslot is multiplied by the
4672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      smoothed gain, then random noise with the calculated level is added.
4682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \note
4702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  To reduce the stack size, some of the local arrays could be located within
4712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  the time output buffer. Of the 512 samples temporarily available there,
4722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  about half the size is already used by #SBR_FRAME_DATA. A pointer to the
4732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  remaining free memory could be supplied by an additional argument to calculateSbrEnvelope()
4742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  in sbr_dec:
4752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \par
4772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \code
4782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    calculateSbrEnvelope (&hSbrDec->sbrScaleFactor,
4792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          &hSbrDec->SbrCalculateEnvelope,
4802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          hHeaderData,
4812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          hFrameData,
4822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          QmfBufferReal,
4832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          QmfBufferImag,
4842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          timeOutPtr + sizeof(SBR_FRAME_DATA)/sizeof(Float) + 1);
4852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \endcode
4862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \par
4882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Within calculateSbrEnvelope(), some pointers could be defined instead of the arrays
4892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  #nrgRef_m, #nrgRef_e, #nrgEst_m, #nrgEst_e, #noiseLevel_m:
4902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \par
4922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \code
4932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    fract*        nrgRef_m = timeOutPtr;
4942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR*        nrgRef_e = nrgRef_m + MAX_FREQ_COEFFS;
4952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    fract*        nrgEst_m = nrgRef_e + MAX_FREQ_COEFFS;
4962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR*        nrgEst_e = nrgEst_m + MAX_FREQ_COEFFS;
4972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    fract*        noiseLevel_m = nrgEst_e + MAX_FREQ_COEFFS;
4982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \endcode
4992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  <br>
5012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
5022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectvoid
5032228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectcalculateSbrEnvelope (QMF_SCALE_FACTOR  *sbrScaleFactor,           /*!< Scaling factors */
5042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, /*!< Handle to struct filled by the create-function */
5052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      HANDLE_SBR_HEADER_DATA hHeaderData,          /*!< Static control data */
5062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      HANDLE_SBR_FRAME_DATA  hFrameData,           /*!< Control data of current frame */
5072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      FIXP_DBL **analysBufferReal,                 /*!< Real part of subband samples to be processed */
5082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      FIXP_DBL **analysBufferImag,                 /*!< Imag part of subband samples to be processed */
5092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      const int useLP,
5102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      FIXP_DBL *degreeAlias,                       /*!< Estimated aliasing for each QMF channel */
5112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      const UINT flags,
5122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      const int frameErrorFlag
5132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      )
5142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
5152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int c, i, j, envNoise = 0;
5162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR*   borders = hFrameData->frameInfo.borders;
5172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_SGL *noiseLevels       = hFrameData->sbrNoiseFloorLevel;
5192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData;
5202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int lowSubband  = hFreq->lowSubband;
5222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int highSubband = hFreq->highSubband;
5232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int noSubbands  = highSubband - lowSubband;
5242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int    noNoiseBands = hFreq->nNfb;
5262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int    no_cols      = hHeaderData->numberTimeSlots * hHeaderData->timeStep;
5272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR  first_start  = borders[0] * hHeaderData->timeStep;
5282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  sineMapped[MAX_FREQ_COEFFS];
5302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  ov_adj_e = SCALE2EXP(sbrScaleFactor->ov_hb_scale);
5312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  adj_e = 0;
5322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  output_e;
5332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  final_e = 0;
5342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  maxGainLimit_e = (frameErrorFlag) ? MAX_GAIN_CONCEAL_EXP : MAX_GAIN_EXP;
5362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int useAliasReduction[64];
5382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR smooth_length = 0;
5392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_SGL * pIenv = hFrameData->iEnvelope;
5412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
5432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    Extract sine flags for all QMF bands
5442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
5452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  mapSineFlags(hFreq->freqBandTable[1],
5462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project               hFreq->nSfb[1],
5472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project               hFrameData->addHarmonics,
5482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project               h_sbr_cal_env->harmFlagsPrev,
5492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project               hFrameData->frameInfo.tranEnv,
5502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project               sineMapped);
5512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
5542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    Scan for maximum in bufferd noise levels.
5552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    This is needed in case that we had strong noise in the previous frame
5562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    which is smoothed into the current frame.
5572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    The resulting exponent is used as start value for the maximum search
5582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    in reference energies
5592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
5602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (!useLP)
5612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    adj_e = h_sbr_cal_env->filtBufferNoise_e - getScalefactor(h_sbr_cal_env->filtBufferNoise, noSubbands);
5622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
5642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    Scan for maximum reference energy to be able
5652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    to select appropriate values for adj_e and final_e.
5662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
5672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (i = 0; i < hFrameData->frameInfo.nEnvelopes; i++) {
5692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    INT maxSfbNrg_e = -FRACT_BITS+NRG_EXP_OFFSET; /* start value for maximum search */
5702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Fetch frequency resolution for current envelope: */
5722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (j=hFreq->nSfb[hFrameData->frameInfo.freqRes[i]]; j!=0; j--) {
5732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      maxSfbNrg_e = fixMax(maxSfbNrg_e,(INT)((LONG)(*pIenv++) & MASK_E));
5742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
5752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    maxSfbNrg_e -= NRG_EXP_OFFSET;
5762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Energy -> magnitude (sqrt halfens exponent) */
5782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    maxSfbNrg_e = (maxSfbNrg_e+1) >> 1;  /* +1 to go safe (round to next higher int) */
5792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Some safety margin is needed for 2 reasons:
5812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       - The signal energy is not equally spread over all subband samples in
5822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         a specific sfb of an envelope (Nrg could be too high by a factor of
5832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         envWidth * sfbWidth)
5842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       - Smoothing can smear high gains of the previous envelope into the current
5852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    */
5862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    maxSfbNrg_e += 6;
5872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (borders[i] < hHeaderData->numberTimeSlots)
5892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* This envelope affects timeslots that belong to the output frame */
5902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      adj_e = (maxSfbNrg_e > adj_e) ? maxSfbNrg_e : adj_e;
5912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (borders[i+1] > hHeaderData->numberTimeSlots)
5932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* This envelope affects timeslots after the output frame */
5942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      final_e =  (maxSfbNrg_e > final_e) ? maxSfbNrg_e : final_e;
5952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
5972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
5992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    Calculate adjustment factors and apply them for every envelope.
6002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
6012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  pIenv = hFrameData->iEnvelope;
6022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (i = 0; i < hFrameData->frameInfo.nEnvelopes; i++) {
6042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int k, noNoiseFlag;
6062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    SCHAR  noise_e, input_e = SCALE2EXP(sbrScaleFactor->hb_scale);
6072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    C_ALLOC_SCRATCH_START(pNrgs, ENV_CALC_NRGS, 1);
6082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*
6102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      Helper variables.
6112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    */
6122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    UCHAR start_pos = hHeaderData->timeStep * borders[i];  /* Start-position in time (subband sample) for current envelope. */
6132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    UCHAR stop_pos = hHeaderData->timeStep * borders[i+1]; /* Stop-position in time (subband sample) for current envelope. */
6142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    UCHAR freq_res = hFrameData->frameInfo.freqRes[i];     /* Frequency resolution for current envelope. */
6152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Always do fully initialize the temporary energy table. This prevents negative energies and extreme gain factors in
6182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       cases where the number of limiter bands exceeds the number of subbands. The latter can be caused by undetected bit
6192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       errors and is tested by some streams from the certification set. */
6202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FDKmemclear(pNrgs, sizeof(ENV_CALC_NRGS));
6212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* If the start-pos of the current envelope equals the stop pos of the current
6232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       noise envelope, increase the pointer (i.e. choose the next noise-floor).*/
6242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (borders[i] == hFrameData->frameInfo.bordersNoise[envNoise+1]){
6252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      noiseLevels += noNoiseBands;   /* The noise floor data is stored in a row [noiseFloor1 noiseFloor2...].*/
6262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      envNoise++;
6272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
6282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if(i==hFrameData->frameInfo.tranEnv || i==h_sbr_cal_env->prevTranEnv) /* attack */
6302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
6312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      noNoiseFlag = 1;
6322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (!useLP)
6332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        smooth_length = 0;  /* No smoothing on attacks! */
6342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
6352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else {
6362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      noNoiseFlag = 0;
6372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (!useLP)
6382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        smooth_length = (1 - hHeaderData->bs_data.smoothingLength) << 2;  /* can become either 0 or 4 */
6392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
6402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*
6432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      Energy estimation in transposed highband.
6442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    */
6452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (hHeaderData->bs_data.interpolFreq)
6462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      calcNrgPerSubband(analysBufferReal,
6472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        (useLP) ? NULL : analysBufferImag,
6482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        lowSubband, highSubband,
6492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        start_pos, stop_pos,
6502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        input_e,
6512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        pNrgs->nrgEst,
6522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        pNrgs->nrgEst_e);
6532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else
6542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      calcNrgPerSfb(analysBufferReal,
6552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    (useLP) ? NULL : analysBufferImag,
6562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    hFreq->nSfb[freq_res],
6572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    hFreq->freqBandTable[freq_res],
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
6632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*
6642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      Calculate subband gains
6652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    */
6662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
6672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      UCHAR * table = hFreq->freqBandTable[freq_res];
6682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      UCHAR * pUiNoise = &hFreq->freqBandTableNoise[1]; /*! Upper limit of the current noise floor band. */
6692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_SGL * pNoiseLevels = noiseLevels;
6712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL tmpNoise = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M));
6732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      SCHAR    tmpNoise_e = (UCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET;
6742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      int cc = 0;
6762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      c = 0;
6772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (j = 0; j < hFreq->nSfb[freq_res]; j++) {
6782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FIXP_DBL refNrg   = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pIenv) & MASK_M));
6802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        SCHAR    refNrg_e = (SCHAR)((LONG)(*pIenv) & MASK_E) - NRG_EXP_OFFSET;
6812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        UCHAR sinePresentFlag = 0;
6832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        int li = table[j];
6842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        int ui = table[j+1];
6852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        for (k=li; k<ui; k++) {
6872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          sinePresentFlag |= (i >= sineMapped[cc]);
6882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          cc++;
6892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
6902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        for (k=li; k<ui; k++) {
6922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (k >= *pUiNoise) {
6932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            tmpNoise = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M));
6942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            tmpNoise_e = (SCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET;
6952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            pUiNoise++;
6972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
6982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FDK_ASSERT(k >= lowSubband);
7002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (useLP)
7022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            useAliasReduction[k-lowSubband] = !sinePresentFlag;
7032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->nrgSine[c] = FL2FXCONST_DBL(0.0f);
7052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->nrgSine_e[c] = 0;
7062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          calcSubbandGain(refNrg, refNrg_e, pNrgs, c,
7082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          tmpNoise, tmpNoise_e,
7092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          sinePresentFlag, i >= sineMapped[c],
7102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          noNoiseFlag);
7112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->nrgRef[c]   = refNrg;
7132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->nrgRef_e[c] = refNrg_e;
7142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          c++;
7162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
7172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pIenv++;
7182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
7192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
7202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*
7222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      Noise limiting
7232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    */
7242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (c = 0; c < hFreq->noLimiterBands; c++) {
7262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL sumRef, boostGain, maxGain;
7282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL accu = FL2FXCONST_DBL(0.0f);
7292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      SCHAR   sumRef_e, boostGain_e, maxGain_e, accu_e = 0;
7302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      calcAvgGain(pNrgs,
7322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                  hFreq->limiterBandTable[c], hFreq->limiterBandTable[c+1],
7332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                  &sumRef, &sumRef_e,
7342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                  &maxGain, &maxGain_e);
7352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Multiply maxGain with limiterGain: */
7372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      maxGain = fMult(maxGain, FDK_sbrDecoder_sbr_limGains_m[hHeaderData->bs_data.limiterGains]);
7382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      maxGain_e += FDK_sbrDecoder_sbr_limGains_e[hHeaderData->bs_data.limiterGains];
7392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Scale mantissa of MaxGain into range between 0.5 and 1: */
7412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (maxGain == FL2FXCONST_DBL(0.0f))
7422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxGain_e = -FRACT_BITS;
7432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else {
7442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        SCHAR charTemp = CountLeadingBits(maxGain);
7452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxGain_e -= charTemp;
7462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxGain  <<= (int)charTemp;
7472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
7482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (maxGain_e >= maxGainLimit_e) { /* upper limit (e.g. 96 dB) */
7502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxGain = FL2FXCONST_DBL(0.5f);
7512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxGain_e = maxGainLimit_e;
7522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
7532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Every subband gain is compared to the scaled "average gain"
7562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         and limited if necessary: */
7572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c+1]; k++) {
7582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if ( (pNrgs->nrgGain_e[k] > maxGain_e) || (pNrgs->nrgGain_e[k] == maxGain_e && pNrgs->nrgGain[k]>maxGain) ) {
7592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FIXP_DBL noiseAmp;
7612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          SCHAR    noiseAmp_e;
7622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FDK_divide_MantExp(maxGain, maxGain_e, pNrgs->nrgGain[k], pNrgs->nrgGain_e[k], &noiseAmp, &noiseAmp_e);
7642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->noiseLevel[k]    = fMult(pNrgs->noiseLevel[k],noiseAmp);
7652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->noiseLevel_e[k] += noiseAmp_e;
7662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->nrgGain[k]       = maxGain;
7672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->nrgGain_e[k]     = maxGain_e;
7682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
7692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
7702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* -- Boost gain
7722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        Calculate and apply boost factor for each limiter band:
7732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        1. Check how much energy would be present when using the limited gain
7742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        2. Calculate boost factor by comparison with reference energy
7752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        3. Apply boost factor to compensate for the energy loss due to limiting
7762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      */
7772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; k++) {
7782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* 1.a  Add energy of adjusted signal (using preliminary gain) */
7802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FIXP_DBL  tmp   = fMult(pNrgs->nrgGain[k],pNrgs->nrgEst[k]);
7812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        SCHAR     tmp_e = pNrgs->nrgGain_e[k] + pNrgs->nrgEst_e[k];
7822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FDK_add_MantExp(tmp, tmp_e, accu, accu_e, &accu, &accu_e);
7832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* 1.b  Add sine energy (if present) */
7852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if(pNrgs->nrgSine[k] != FL2FXCONST_DBL(0.0f)) {
7862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FDK_add_MantExp(pNrgs->nrgSine[k], pNrgs->nrgSine_e[k], accu, accu_e, &accu, &accu_e);
7872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
7882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        else {
7892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* 1.c  Add noise energy (if present) */
7902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if(noNoiseFlag == 0) {
7912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            FDK_add_MantExp(pNrgs->noiseLevel[k], pNrgs->noiseLevel_e[k], accu, accu_e, &accu, &accu_e);
7922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
7932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
7942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
7952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* 2.a  Calculate ratio of wanted energy and accumulated energy */
7972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (accu == (FIXP_DBL)0) { /* If divisor is 0, limit quotient to +4 dB */
7982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        boostGain = FL2FXCONST_DBL(0.6279716f);
7992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        boostGain_e = 2;
8002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      } else {
8012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        INT div_e;
8022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        boostGain = fDivNorm(sumRef, accu, &div_e);
8032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        boostGain_e = sumRef_e - accu_e + div_e;
8042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
8052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* 2.b Result too high? --> Limit the boost factor to +4 dB */
8082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if((boostGain_e  > 3) ||
8092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         (boostGain_e == 2 && boostGain > FL2FXCONST_DBL(0.6279716f)) ||
8102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         (boostGain_e == 3 && boostGain > FL2FXCONST_DBL(0.3139858f)) )
8112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
8122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        boostGain = FL2FXCONST_DBL(0.6279716f);
8132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        boostGain_e = 2;
8142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
8152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* 3.  Multiply all signal components with the boost factor */
8162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; k++) {
8172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pNrgs->nrgGain[k]   = fMultDiv2(pNrgs->nrgGain[k],boostGain);
8182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pNrgs->nrgGain_e[k] = pNrgs->nrgGain_e[k] + boostGain_e + 1;
8192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pNrgs->nrgSine[k]   = fMultDiv2(pNrgs->nrgSine[k],boostGain);
8212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pNrgs->nrgSine_e[k] = pNrgs->nrgSine_e[k] + boostGain_e + 1;
8222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pNrgs->noiseLevel[k]   = fMultDiv2(pNrgs->noiseLevel[k],boostGain);
8242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pNrgs->noiseLevel_e[k] = pNrgs->noiseLevel_e[k] + boostGain_e + 1;
8252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
8262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
8272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* End of noise limiting */
8282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (useLP)
8302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      aliasingReduction(degreeAlias+lowSubband,
8312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        pNrgs,
8322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        useAliasReduction,
8332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        noSubbands);
8342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* For the timeslots within the range for the output frame,
8362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       use the same scale for the noise levels.
8372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       Drawback: If the envelope exceeds the frame border, the noise levels
8382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                 will have to be rescaled later to fit final_e of
8392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                 the gain-values.
8402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    */
8412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    noise_e = (start_pos < no_cols) ? adj_e : final_e;
8422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*
8442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      Convert energies to amplitude levels
8452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    */
8462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (k=0; k<noSubbands; k++) {
8472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FDK_sqrt_MantExp(&pNrgs->nrgSine[k],    &pNrgs->nrgSine_e[k],    &noise_e);
8482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FDK_sqrt_MantExp(&pNrgs->nrgGain[k],    &pNrgs->nrgGain_e[k],    &pNrgs->nrgGain_e[k]);
8492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FDK_sqrt_MantExp(&pNrgs->noiseLevel[k], &pNrgs->noiseLevel_e[k], &noise_e);
8502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
8512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*
8552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      Apply calculated gains and adaptive noise
8562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    */
8572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* assembleHfSignals() */
8592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
8602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      int scale_change, sc_change;
8612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_SGL smooth_ratio;
8622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      int filtBufferNoiseShift=0;
8632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Initialize smoothing buffers with the first valid values */
8652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (h_sbr_cal_env->startUp)
8662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
8672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (!useLP) {
8682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          h_sbr_cal_env->filtBufferNoise_e = noise_e;
8692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FDKmemcpy(h_sbr_cal_env->filtBuffer_e,    pNrgs->nrgGain_e,  noSubbands*sizeof(SCHAR));
8712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FDKmemcpy(h_sbr_cal_env->filtBufferNoise, pNrgs->noiseLevel, noSubbands*sizeof(FIXP_DBL));
8722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FDKmemcpy(h_sbr_cal_env->filtBuffer,      pNrgs->nrgGain,    noSubbands*sizeof(FIXP_DBL));
8732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
8752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        h_sbr_cal_env->startUp = 0;
8762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
8772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (!useLP) {
8792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        equalizeFiltBufferExp(h_sbr_cal_env->filtBuffer,    /* buffered */
8812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              h_sbr_cal_env->filtBuffer_e,  /* buffered */
8822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              pNrgs->nrgGain,               /* current  */
8832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              pNrgs->nrgGain_e,             /* current  */
8842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              noSubbands);
8852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* Adapt exponent of buffered noise levels to the current exponent
8872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           so they can easily be smoothed */
8882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if((h_sbr_cal_env->filtBufferNoise_e - noise_e)>=0) {
8892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          int shift = fixMin(DFRACT_BITS-1,(int)(h_sbr_cal_env->filtBufferNoise_e - noise_e));
8902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          for (k=0; k<noSubbands; k++)
8912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            h_sbr_cal_env->filtBufferNoise[k] <<= shift;
8922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
8932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        else {
8942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          int shift = fixMin(DFRACT_BITS-1,-(int)(h_sbr_cal_env->filtBufferNoise_e - noise_e));
8952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          for (k=0; k<noSubbands; k++)
8962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            h_sbr_cal_env->filtBufferNoise[k] >>= shift;
8972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
8982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
8992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        h_sbr_cal_env->filtBufferNoise_e = noise_e;
9002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
9012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* find best scaling! */
9032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      scale_change = -(DFRACT_BITS-1);
9042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for(k=0;k<noSubbands;k++) {
9052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          scale_change = fixMax(scale_change,(int)pNrgs->nrgGain_e[k]);
9062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
9072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sc_change = (start_pos<no_cols)? adj_e - input_e : final_e - input_e;
9082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if ((scale_change-sc_change+1)<0)
9102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          scale_change-=(scale_change-sc_change+1);
9112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      scale_change = (scale_change-sc_change)+1;
9132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for(k=0;k<noSubbands;k++) {
9152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          int sc = scale_change-pNrgs->nrgGain_e[k] + (sc_change-1);
9162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->nrgGain[k]  >>= sc;
9172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          pNrgs->nrgGain_e[k] += sc;
9182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
9192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (!useLP) {
9212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        for(k=0;k<noSubbands;k++) {
9222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          int sc = scale_change-h_sbr_cal_env->filtBuffer_e[k] + (sc_change-1);
9232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          h_sbr_cal_env->filtBuffer[k] >>= sc;
9242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
9252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
9262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (j = start_pos; j < stop_pos; j++)
9282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
9292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* This timeslot is located within the first part of the processing buffer
9302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           and will be fed into the QMF-synthesis for the current frame.
9312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project               adj_e - input_e
9322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           This timeslot will not yet be fed into the QMF so we do not care
9332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           about the adj_e.
9342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project               sc_change = final_e - input_e
9352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        */
9362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if ( (j==no_cols) && (start_pos<no_cols) )
9372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
9382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          int shift = (int) (noise_e - final_e);
9392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (!useLP)
9402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            filtBufferNoiseShift = shift;               /* shifting of h_sbr_cal_env->filtBufferNoise[k] will be applied in function adjustTimeSlotHQ() */
9412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (shift>=0) {
9422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            shift = fixMin(DFRACT_BITS-1,shift);
9432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            for (k=0; k<noSubbands; k++) {
9442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              pNrgs->nrgSine[k] <<= shift;
9452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              pNrgs->noiseLevel[k]  <<= shift;
9462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              /*
9472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              if (!useLP)
9482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                h_sbr_cal_env->filtBufferNoise[k]  <<= shift;
9492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              */
9502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            }
9512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
9522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          else {
9532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            shift = fixMin(DFRACT_BITS-1,-shift);
9542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            for (k=0; k<noSubbands; k++) {
9552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              pNrgs->nrgSine[k] >>= shift;
9562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              pNrgs->noiseLevel[k]  >>= shift;
9572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              /*
9582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              if (!useLP)
9592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                h_sbr_cal_env->filtBufferNoise[k]  >>= shift;
9602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              */
9612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            }
9622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
9632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* update noise scaling */
9652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          noise_e = final_e;
9662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (!useLP)
9672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            h_sbr_cal_env->filtBufferNoise_e = noise_e;  /* scaling value unused! */
9682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* update gain buffer*/
9702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          sc_change -= (final_e - input_e);
9712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (sc_change<0) {
9732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            for(k=0;k<noSubbands;k++) {
9742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                pNrgs->nrgGain[k]  >>= -sc_change;
9752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                pNrgs->nrgGain_e[k] += -sc_change;
9762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            }
9772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            if (!useLP) {
9782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              for(k=0;k<noSubbands;k++) {
9792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    h_sbr_cal_env->filtBuffer[k] >>= -sc_change;
9802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              }
9812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            }
9822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          } else {
9832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            scale_change+=sc_change;
9842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
9852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        } // if
9872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (!useLP) {
9892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* Prevent the smoothing filter from running on constant levels */
9912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (j-start_pos < smooth_length)
9922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            smooth_ratio = FDK_sbrDecoder_sbr_smoothFilter[j-start_pos];
9932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          else
9952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            smooth_ratio = FL2FXCONST_SGL(0.0f);
9962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
9972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          adjustTimeSlotHQ(&analysBufferReal[j][lowSubband],
9982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           &analysBufferImag[j][lowSubband],
9992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           h_sbr_cal_env,
10002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           pNrgs,
10012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           lowSubband,
10022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           noSubbands,
10032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           scale_change,
10042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           smooth_ratio,
10052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           noNoiseFlag,
10062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           filtBufferNoiseShift);
10072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
10082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        else
10092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
10102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          adjustTimeSlotLC(&analysBufferReal[j][lowSubband],
10112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           pNrgs,
10122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          &h_sbr_cal_env->harmIndex,
10132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           lowSubband,
10142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           noSubbands,
10152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           scale_change,
10162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           noNoiseFlag,
10172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          &h_sbr_cal_env->phaseIndex,
10182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           (flags & SBRDEC_ELD_GRID));
10192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
10202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      } // for
10212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (!useLP) {
10232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* Update time-smoothing-buffers for gains and noise levels
10242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           The gains and the noise values of the current envelope are copied into the buffer.
10252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           This has to be done at the end of each envelope as the values are required for
10262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           a smooth transition to the next envelope. */
10272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FDKmemcpy(h_sbr_cal_env->filtBuffer,      pNrgs->nrgGain,    noSubbands*sizeof(FIXP_DBL));
10282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FDKmemcpy(h_sbr_cal_env->filtBuffer_e,    pNrgs->nrgGain_e,  noSubbands*sizeof(SCHAR));
10292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FDKmemcpy(h_sbr_cal_env->filtBufferNoise, pNrgs->noiseLevel, noSubbands*sizeof(FIXP_DBL));
10302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
10312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
10332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    C_ALLOC_SCRATCH_END(pNrgs, ENV_CALC_NRGS, 1);
10342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
10352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Rescale output samples */
10372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  {
10382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL maxVal;
10392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int ov_reserve, reserve;
10402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Determine headroom in old adjusted samples */
10422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    maxVal = maxSubbandSample( analysBufferReal,
10432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              (useLP) ? NULL : analysBufferImag,
10442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               lowSubband,
10452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               highSubband,
10462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               0,
10472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               first_start);
10482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    ov_reserve = fNorm(maxVal);
10502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Determine headroom in new adjusted samples */
10522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    maxVal = maxSubbandSample( analysBufferReal,
10532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               (useLP) ? NULL : analysBufferImag,
10542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               lowSubband,
10552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               highSubband,
10562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               first_start,
10572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                               no_cols);
10582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    reserve = fNorm(maxVal);
10602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Determine common output exponent */
10622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (ov_adj_e - ov_reserve  >  adj_e - reserve ) /* set output_e to the maximum */
10632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      output_e = ov_adj_e - ov_reserve;
10642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else
10652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      output_e = adj_e - reserve;
10662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Rescale old samples */
10682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    rescaleSubbandSamples( analysBufferReal,
10692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           (useLP) ? NULL : analysBufferImag,
10702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           lowSubband, highSubband,
10712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           0, first_start,
10722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           ov_adj_e - output_e);
10732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Rescale new samples */
10752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    rescaleSubbandSamples( analysBufferReal,
10762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           (useLP) ? NULL : analysBufferImag,
10772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           lowSubband, highSubband,
10782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           first_start, no_cols,
10792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           adj_e - output_e);
10802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
10812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Update hb_scale */
10832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  sbrScaleFactor->hb_scale = EXP2SCALE(output_e);
10842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Save the current final exponent for the next frame: */
10862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  sbrScaleFactor->ov_hb_scale = EXP2SCALE(final_e);
10872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* We need to remeber to the next frame that the transient
10902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project     will occur in the first envelope (if tranEnv == nEnvelopes). */
10912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if(hFrameData->frameInfo.tranEnv == hFrameData->frameInfo.nEnvelopes)
10922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    h_sbr_cal_env->prevTranEnv = 0;
10932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  else
10942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    h_sbr_cal_env->prevTranEnv = -1;
10952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
10972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
10992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
11002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief   Create envelope instance
11012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Must be called once for each channel before calculateSbrEnvelope() can be used.
11032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \return  errorCode, 0 if successful
11052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
11062228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectSBR_ERROR
11072228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectcreateSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hs,   /*!< pointer to envelope instance */
11082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       HANDLE_SBR_HEADER_DATA hHeaderData, /*!< static SBR control data, initialized with defaults */
11092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       const int chan,                     /*!< Channel for which to assign buffers */
11102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                       const UINT flags)
11112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
11122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SBR_ERROR err = SBRDEC_OK;
11132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int i;
11142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Clear previous missing harmonics flags */
11162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (i=0; i<(MAX_FREQ_COEFFS+15)>>4; i++) {
11172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    hs->harmFlagsPrev[i] = 0;
11182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
11192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  hs->harmIndex = 0;
11202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
11222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    Setup pointers for time smoothing.
11232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    The buffer itself will be initialized later triggered by the startUp-flag.
11242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
11252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  hs->prevTranEnv = -1;
11262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* initialization */
11292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  resetSbrEnvelopeCalc(hs);
11302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (chan==0) { /* do this only once */
11322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    err = resetFreqBandTables(hHeaderData, flags);
11332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
11342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  return err;
11362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
11372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
11392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief   Create envelope instance
11402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Must be called once for each channel before calculateSbrEnvelope() can be used.
11422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \return  errorCode, 0 if successful
11442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
11452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectint
11462228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectdeleteSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hs)
11472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
11482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  return 0;
11492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
11502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
11532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief   Reset envelope instance
11542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  This function must be called for each channel on a change of configuration.
11562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Note that resetFreqBandTables should also be called in this case.
11572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \return  errorCode, 0 if successful
11592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
11602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectvoid
11612228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectresetSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv) /*!< pointer to envelope instance */
11622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
11632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  hCalEnv->phaseIndex = 0;
11642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Noise exponent needs to be reset because the output exponent for the next frame depends on it */
11662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  hCalEnv->filtBufferNoise_e = 0;
11672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  hCalEnv->startUp = 1;
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  Equalize exponents of the buffered gain values and the new ones
11742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  After equalization of exponents, the FIR-filter addition for smoothing
11762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  can be performed.
11772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  This function is called once for each envelope before adjusting.
11782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
11792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*static*/ void equalizeFiltBufferExp(FIXP_DBL *filtBuffer,     /*!< bufferd gains */
11802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                  SCHAR    *filtBuffer_e,   /*!< exponents of bufferd gains */
11812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                  FIXP_DBL *nrgGain,        /*!< gains for current envelope */
11822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                  SCHAR    *nrgGain_e,      /*!< exponents of gains for current envelope */
11832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                  int       subbands)       /*!< Number of QMF subbands */
11842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
11852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int   band;
11862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int  diff;
11872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (band=0; band<subbands; band++){
11892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    diff = (int) (nrgGain_e[band] - filtBuffer_e[band]);
11902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (diff>0) {
11912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      filtBuffer[band] >>= diff;   /* Compensate for the scale change by shifting the mantissa. */
11922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      filtBuffer_e[band] += diff;  /* New gain is bigger, use its exponent */
11932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
11942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else if (diff<0) {
11952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* The buffered gains seem to be larger, but maybe there
11962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         are some unused bits left in the mantissa */
11972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
11982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      int reserve = CntLeadingZeros(fixp_abs(filtBuffer[band]))-1;
11992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if ((-diff) <= reserve) {
12012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* There is enough space in the buffered mantissa so
12022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           that we can take the new exponent as common.
12032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        */
12042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        filtBuffer[band] <<= (-diff);
12052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        filtBuffer_e[band] += diff;  /* becomes equal to *ptrNewExp */
12062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
12072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else {
12082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        filtBuffer[band] <<= reserve;   /* Shift the mantissa as far as possible: */
12092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        filtBuffer_e[band] -= reserve;  /* Compensate in the exponent: */
12102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* For the remaining difference, change the new gain value */
12122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        diff = fixMin(-(reserve + diff),DFRACT_BITS-1);
12132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        nrgGain[band] >>= diff;
12142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        nrgGain_e[band] += diff;
12152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
12162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
12172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
12182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
12192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
12212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief  Shift left the mantissas of all subband samples
12222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          in the giventime and frequency range by the specified number of bits.
12232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  This function is used to rescale the audio data in the overlap buffer
12252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  which has already been envelope adjusted with the last frame.
12262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
12272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectvoid rescaleSubbandSamples(FIXP_DBL ** re,   /*!< Real part of input and output subband samples */
12282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           FIXP_DBL ** im,   /*!< Imaginary part of input and output subband samples */
12292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int lowSubband,   /*!< Begin of frequency range to process */
12302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int highSubband,  /*!< End of frequency range to process */
12312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int start_pos,    /*!< Begin of time rage (QMF-timeslot) */
12322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int next_pos,     /*!< End of time rage (QMF-timeslot) */
12332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int shift)        /*!< number of bits to shift */
12342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
12352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int width = highSubband-lowSubband;
12362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if ( (width > 0) && (shift!=0) ) {
12382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (im!=NULL) {
12392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (int l=start_pos; l<next_pos; l++) {
12402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          scaleValues(&re[l][lowSubband], width, shift);
12412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          scaleValues(&im[l][lowSubband], width, shift);
12422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
12432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    } else
12442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
12452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (int l=start_pos; l<next_pos; l++) {
12462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          scaleValues(&re[l][lowSubband], width, shift);
12472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
12482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
12492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
12502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
12512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
12542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief   Determine headroom for shifting
12552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Determine by how much the spectrum can be shifted left
12572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for better accuracy in later processing.
12582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \return  Number of free bits in the biggest spectral value
12602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
12612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12622228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectFIXP_DBL maxSubbandSample( FIXP_DBL ** re,   /*!< Real part of input and output subband samples */
12632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           FIXP_DBL ** im,   /*!< Real part of input and output subband samples */
12642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int lowSubband,   /*!< Begin of frequency range to process */
12652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int highSubband,  /*!< Number of QMF bands to process */
12662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int start_pos,    /*!< Begin of time rage (QMF-timeslot) */
12672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                           int next_pos      /*!< End of time rage (QMF-timeslot) */
12682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          )
12692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
12702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL maxVal = FL2FX_DBL(0.0f);
12712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  unsigned int width = highSubband - lowSubband;
12722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDK_ASSERT(width <= (64));
12742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
12752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if ( width > 0 ) {
12762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (im!=NULL)
12772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
12782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (int l=start_pos; l<next_pos; l++)
12792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
12802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#ifdef FUNCTION_FDK_get_maxval
12812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxVal = FDK_get_maxval(maxVal, &re[l][lowSubband], &im[l][lowSubband], width);
12822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#else
12832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        int k=width;
12842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FIXP_DBL *reTmp = &re[l][lowSubband];
12852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FIXP_DBL *imTmp = &im[l][lowSubband];
12862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        do{
12872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FIXP_DBL tmp1 = *(reTmp++);
12882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FIXP_DBL tmp2 = *(imTmp++);
12892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          maxVal |= (FIXP_DBL)((LONG)(tmp1)^((LONG)tmp1>>(DFRACT_BITS-1)));
12902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          maxVal |= (FIXP_DBL)((LONG)(tmp2)^((LONG)tmp2>>(DFRACT_BITS-1)));
12912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        } while(--k!=0);
12922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#endif
12932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
12942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    } else
12952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
12962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (int l=start_pos; l<next_pos; l++) {
12972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        int k=width;
12982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FIXP_DBL *reTmp = &re[l][lowSubband];
12992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        do{
13002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FIXP_DBL tmp = *(reTmp++);
13012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          maxVal |= (FIXP_DBL)((LONG)(tmp)^((LONG)tmp>>(DFRACT_BITS-1)));
13022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }while(--k!=0);
13032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
13042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
13052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
13062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  return(maxVal);
13082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
13092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define SHIFT_BEFORE_SQUARE (3) /* (7/2) */
13112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!<
13122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  If the accumulator does not provide enough overflow bits or
13132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  does not provide a high dynamic range, the below energy calculation
13142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  requires an additional shift operation for each sample.
13152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  On the other hand, doing the shift allows using a single-precision
13162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  multiplication for the square (at least 16bit x 16bit).
13172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  For even values of OVRFLW_BITS (0, 2, 4, 6), saturated arithmetic
13182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  is required for the energy accumulation.
13192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Theoretically, the sample-squares can sum up to a value of 76,
13202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  requiring 7 overflow bits. However since such situations are *very*
13212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  rare, accu can be limited to 64.
13222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  In case native saturated arithmetic is not available, overflows
13232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  can be prevented by replacing the above #define by
13242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    #define SHIFT_BEFORE_SQUARE ((8 - OVRFLW_BITS) / 2)
13252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  which will result in slightly reduced accuracy.
13262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
13272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
13292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief  Estimates the mean energy of each filter-bank channel for the
13302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          duration of the current envelope
13312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  This function is used when interpolFreq is true.
13332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
13342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*static*/ void calcNrgPerSubband(FIXP_DBL  **analysBufferReal, /*!< Real part of subband samples */
13352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              FIXP_DBL  **analysBufferImag, /*!< Imaginary part of subband samples */
13362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              int       lowSubband,           /*!< Begin of the SBR frequency range */
13372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              int       highSubband,          /*!< High end of the SBR frequency range */
13382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              int       start_pos,            /*!< First QMF-slot of current envelope */
13392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              int       next_pos,             /*!< Last QMF-slot of current envelope + 1 */
13402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              SCHAR     frameExp,             /*!< Common exponent for all input samples */
13412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              FIXP_DBL *nrgEst,               /*!< resulting Energy (0..1) */
13422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                              SCHAR    *nrgEst_e )            /*!< Exponent of resulting Energy */
13432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
13442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_SGL invWidth;
13452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  preShift;
13462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  shift;
13472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL sum;
13482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int k,l;
13492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Divide by width of envelope later: */
13512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  invWidth = FX_DBL2FX_SGL(GetInvInt(next_pos - start_pos));
13522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* The common exponent needs to be doubled because all mantissas are squared: */
13532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  frameExp = frameExp << 1;
13542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (k=lowSubband; k<highSubband; k++) {
13562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL  bufferReal[(((1024)/(32))+(6))];
13572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL  bufferImag[(((1024)/(32))+(6))];
13582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL maxVal = FL2FX_DBL(0.0f);
13592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (analysBufferImag!=NULL)
13612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
13622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (l=start_pos;l<next_pos;l++)
13632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
13642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        bufferImag[l] = analysBufferImag[l][k];
13652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxVal |= (FIXP_DBL)((LONG)(bufferImag[l])^((LONG)bufferImag[l]>>(DFRACT_BITS-1)));
13662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        bufferReal[l] = analysBufferReal[l][k];
13672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxVal |= (FIXP_DBL)((LONG)(bufferReal[l])^((LONG)bufferReal[l]>>(DFRACT_BITS-1)));
13682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
13692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
13702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else
13712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
13722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (l=start_pos;l<next_pos;l++)
13732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
13742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        bufferReal[l] = analysBufferReal[l][k];
13752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        maxVal |= (FIXP_DBL)((LONG)(bufferReal[l])^((LONG)bufferReal[l]>>(DFRACT_BITS-1)));
13762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
13772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
13782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (maxVal!=FL2FXCONST_DBL(0.f)) {
13802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* If the accu does not provide enough overflow bits, we cannot
13832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         shift the samples up to the limit.
13842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         Instead, keep up to 3 free bits in each sample, i.e. up to
13852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         6 bits after calculation of square.
13862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         Please note the comment on saturated arithmetic above!
13872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      */
13882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL accu = FL2FXCONST_DBL(0.0f);
13892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      preShift = CntLeadingZeros(maxVal)-1;
13902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      preShift -= SHIFT_BEFORE_SQUARE;
13912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
13922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (preShift>=0) {
13932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (analysBufferImag!=NULL) {
13942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          for (l=start_pos; l<next_pos; l++) {
13952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            FIXP_DBL temp1 = bufferReal[l] << (int)preShift;
13962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            FIXP_DBL temp2 = bufferImag[l] << (int)preShift;
13972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            accu = fPow2AddDiv2(accu, temp1);
13982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            accu = fPow2AddDiv2(accu, temp2);
13992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
14002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        } else
14012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
14022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          for (l=start_pos; l<next_pos; l++) {
14032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            FIXP_DBL temp = bufferReal[l] << (int)preShift;
14042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            accu = fPow2AddDiv2(accu, temp);
14052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
14062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
14072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
14082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else {    /* if negative shift value */
14092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        int negpreShift = -preShift;
14102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (analysBufferImag!=NULL) {
14112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          for (l=start_pos; l<next_pos; l++) {
14122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            FIXP_DBL temp1 = bufferReal[l] >> (int)negpreShift;
14132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            FIXP_DBL temp2 = bufferImag[l] >> (int)negpreShift;
14142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            accu = fPow2AddDiv2(accu, temp1);
14152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            accu = fPow2AddDiv2(accu, temp2);
14162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
14172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        } else
14182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
14192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          for (l=start_pos; l<next_pos; l++) {
14202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            FIXP_DBL temp = bufferReal[l] >> (int)negpreShift;
14212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            accu = fPow2AddDiv2(accu, temp);
14222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
14232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
14242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
14252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      accu <<= 1;
14262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Convert double precision to Mantissa/Exponent: */
14282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      shift = fNorm(accu);
14292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sum = accu << (int)shift;
14302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Divide by width of envelope and apply frame scale: */
14322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *nrgEst++ = fMult(sum, invWidth);
14332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      shift += 2 * preShift;
14342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (analysBufferImag!=NULL)
14352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        *nrgEst_e++ = frameExp - shift;
14362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else
14372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        *nrgEst_e++ = frameExp - shift + 1;  /* +1 due to missing imag. part */
14382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    } /* maxVal!=0 */
14392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else {
14402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Prevent a zero-mantissa-number from being misinterpreted
14422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         due to its exponent. */
14432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *nrgEst++ = FL2FXCONST_DBL(0.0f);
14442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *nrgEst_e++ = 0;
14452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
14462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
14472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
14482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
14502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief   Estimates the mean energy of each Scale factor band for the
14512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           duration of the current envelope.
14522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  This function is used when interpolFreq is false.
14542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
14552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*static*/ void calcNrgPerSfb(FIXP_DBL  **analysBufferReal,  /*!< Real part of subband samples */
14562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          FIXP_DBL  **analysBufferImag,  /*!< Imaginary part of subband samples */
14572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          int       nSfb,                /*!< Number of scale factor bands */
14582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          UCHAR    *freqBandTable,       /*!< First Subband for each Sfb */
14592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          int       start_pos,           /*!< First QMF-slot of current envelope */
14602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          int       next_pos,            /*!< Last QMF-slot of current envelope + 1 */
14612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          SCHAR     input_e,             /*!< Common exponent for all input samples */
14622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          FIXP_DBL *nrgEst,              /*!< resulting Energy (0..1) */
14632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          SCHAR    *nrgEst_e )           /*!< Exponent of resulting Energy */
14642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
14652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_SGL  invWidth;
14662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL  temp;
14672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR  preShift;
14682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR   shift, sum_e;
14692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL  sum;
14702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int j,k,l,li,ui;
14722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL sumAll, sumLine; /* Single precision would be sufficient,
14732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                             but overflow bits are required for accumulation */
14742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Divide by width of envelope later: */
14762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  invWidth = FX_DBL2FX_SGL(GetInvInt(next_pos - start_pos));
14772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* The common exponent needs to be doubled because all mantissas are squared: */
14782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  input_e = input_e << 1;
14792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for(j=0; j<nSfb; j++) {
14812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    li = freqBandTable[j];
14822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    ui = freqBandTable[j+1];
14832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FIXP_DBL maxVal = maxSubbandSample( analysBufferReal,
14852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                        analysBufferImag,
14862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                        li,
14872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                        ui,
14882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                        start_pos,
14892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                        next_pos );
14902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (maxVal!=FL2FXCONST_DBL(0.f)) {
14922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      preShift = CntLeadingZeros(maxVal)-1;
14942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* If the accu does not provide enough overflow bits, we cannot
14962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         shift the samples up to the limit.
14972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         Instead, keep up to 3 free bits in each sample, i.e. up to
14982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         6 bits after calculation of square.
14992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         Please note the comment on saturated arithmetic above!
15002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      */
15012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      preShift -= SHIFT_BEFORE_SQUARE;
15022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sumAll = FL2FXCONST_DBL(0.0f);
15042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (k=li; k<ui; k++) {
15072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        sumLine = FL2FXCONST_DBL(0.0f);
15092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (analysBufferImag!=NULL) {
15112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (preShift>=0) {
15122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            for (l=start_pos; l<next_pos; l++) {
15132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              temp   = analysBufferReal[l][k] << (int)preShift;
15142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              sumLine += fPow2Div2(temp);
15152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              temp   = analysBufferImag[l][k] << (int)preShift;
15162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              sumLine += fPow2Div2(temp);
15172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            }
15192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          } else {
15202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            for (l=start_pos; l<next_pos; l++) {
15212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              temp   = analysBufferReal[l][k] >> -(int)preShift;
15222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              sumLine += fPow2Div2(temp);
15232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              temp   = analysBufferImag[l][k] >> -(int)preShift;
15242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              sumLine += fPow2Div2(temp);
15252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            }
15262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
15272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        } else
15282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
15292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (preShift>=0) {
15302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            for (l=start_pos; l<next_pos; l++) {
15312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              temp   = analysBufferReal[l][k] << (int)preShift;
15322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              sumLine += fPow2Div2(temp);
15332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            }
15342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          } else {
15352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            for (l=start_pos; l<next_pos; l++) {
15362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              temp   = analysBufferReal[l][k] >> -(int)preShift;
15372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              sumLine += fPow2Div2(temp);
15382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            }
15392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
15402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
15412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* The number of QMF-channels per SBR bands may be up to 15.
15432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           Shift right to avoid overflows in sum over all channels. */
15442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        sumLine = sumLine >> (4-1);
15452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        sumAll  += sumLine;
15462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
15472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Convert double precision to Mantissa/Exponent: */
15492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      shift = fNorm(sumAll);
15502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sum = sumAll << (int)shift;
15512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Divide by width of envelope: */
15532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sum = fMult(sum,invWidth);
15542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Divide by width of Sfb: */
15562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sum = fMult(sum, FX_DBL2FX_SGL(GetInvInt(ui-li)));
15572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Set all Subband energies in the Sfb to the average energy: */
15592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (analysBufferImag!=NULL)
15602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        sum_e = input_e + 4 - shift;  /* -4 to compensate right-shift */
15612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else
15622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        sum_e = input_e + 4 + 1 - shift;  /* -4 to compensate right-shift; +1 due to missing imag. part */
15632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sum_e -= 2 * preShift;
15652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    } /* maxVal!=0 */
15662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else {
15672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Prevent a zero-mantissa-number from being misinterpreted
15692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project         due to its exponent. */
15702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sum = FL2FXCONST_DBL(0.0f);
15712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      sum_e = 0;
15722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
15732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (k=li; k<ui; k++)
15752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
15762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *nrgEst++   = sum;
15772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *nrgEst_e++ = sum_e;
15782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
15792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
15802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
15812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
15842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief  Calculate gain, noise, and additional sine level for one subband.
15852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  The resulting energy gain is given by mantissa and exponent.
15872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
15882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*static*/ void calcSubbandGain(FIXP_DBL  nrgRef,            /*!< Reference Energy according to envelope data */
15892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            SCHAR     nrgRef_e,          /*!< Reference Energy according to envelope data (exponent) */
15902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            ENV_CALC_NRGS* nrgs,
15912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            int       i,
15922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            FIXP_DBL  tmpNoise,          /*!< Relative noise level */
15932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            SCHAR     tmpNoise_e,        /*!< Relative noise level (exponent) */
15942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            UCHAR     sinePresentFlag,   /*!< Indicates if sine is present on band */
15952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            UCHAR     sineMapped,        /*!< Indicates if sine must be added */
15962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                            int       noNoiseFlag)       /*!< Flag to suppress noise addition */
15972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
15982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL  nrgEst          = nrgs->nrgEst[i];            /*!< Energy in transposed signal */
15992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR     nrgEst_e        = nrgs->nrgEst_e[i];          /*!< Energy in transposed signal (exponent) */
16002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *ptrNrgGain      = &nrgs->nrgGain[i];          /*!< Resulting energy gain */
16012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR    *ptrNrgGain_e    = &nrgs->nrgGain_e[i];        /*!< Resulting energy gain (exponent) */
16022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *ptrNoiseLevel   = &nrgs->noiseLevel[i];       /*!< Resulting absolute noise energy */
16032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR    *ptrNoiseLevel_e = &nrgs->noiseLevel_e[i];     /*!< Resulting absolute noise energy (exponent) */
16042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *ptrNrgSine      = &nrgs->nrgSine[i];          /*!< Additional sine energy */
16052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR    *ptrNrgSine_e    = &nrgs->nrgSine_e[i];        /*!< Additional sine energy (exponent) */
16062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL a, b, c;
16082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR    a_e, b_e, c_e;
16092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
16112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project     This addition of 1 prevents divisions by zero in the reference code.
16122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project     For very small energies in nrgEst, it prevents the gains from becoming
16132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project     very high which could cause some trouble due to the smoothing.
16142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
16152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  b_e = (int)(nrgEst_e - 1);
16162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (b_e>=0) {
16172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    nrgEst = (FL2FXCONST_DBL(0.5f) >> (INT)fixMin(b_e+1,DFRACT_BITS-1)) + (nrgEst >> 1);
16182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    nrgEst_e += 1;  /* shift by 1 bit to avoid overflow */
16192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  } else {
16212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    nrgEst = (nrgEst >> (INT)(fixMin(-b_e+1,DFRACT_BITS-1))) + (FL2FXCONST_DBL(0.5f) >> 1);
16222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    nrgEst_e = 2;  /* shift by 1 bit to avoid overflow */
16232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
16242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*  A = NrgRef * TmpNoise */
16262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  a = fMult(nrgRef,tmpNoise);
16272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  a_e = nrgRef_e + tmpNoise_e;
16282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*  B = 1 + TmpNoise */
16302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  b_e = (int)(tmpNoise_e - 1);
16312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (b_e>=0) {
16322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    b = (FL2FXCONST_DBL(0.5f) >> (INT)fixMin(b_e+1,DFRACT_BITS-1)) + (tmpNoise >> 1);
16332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    b_e = tmpNoise_e + 1;  /* shift by 1 bit to avoid overflow */
16342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  } else {
16352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    b = (tmpNoise >> (INT)(fixMin(-b_e+1,DFRACT_BITS-1))) + (FL2FXCONST_DBL(0.5f) >> 1);
16362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    b_e = 2;  /* shift by 1 bit to avoid overflow */
16372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
16382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*  noiseLevel = A / B = (NrgRef * TmpNoise) / (1 + TmpNoise) */
16402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDK_divide_MantExp( a,  a_e,
16412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      b,  b_e,
16422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      ptrNoiseLevel, ptrNoiseLevel_e);
16432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (sinePresentFlag) {
16452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*  C = (1 + TmpNoise) * NrgEst */
16472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    c = fMult(b,nrgEst);
16482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    c_e = b_e + nrgEst_e;
16492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*  gain = A / C = (NrgRef * TmpNoise) / (1 + TmpNoise) * NrgEst */
16512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FDK_divide_MantExp( a,  a_e,
16522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        c,  c_e,
16532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        ptrNrgGain, ptrNrgGain_e);
16542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (sineMapped) {
16562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /*  sineLevel = nrgRef/ (1 + TmpNoise) */
16582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FDK_divide_MantExp( nrgRef,  nrgRef_e,
16592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          b,  b_e,
16602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                          ptrNrgSine, ptrNrgSine_e);
16612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
16622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
16632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  else {
16642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (noNoiseFlag) {
16652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /*  B = NrgEst */
16662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      b = nrgEst;
16672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      b_e = nrgEst_e;
16682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
16692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else {
16702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /*  B = NrgEst * (1 + TmpNoise) */
16712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      b = fMult(b,nrgEst);
16722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      b_e = b_e + nrgEst_e;
16732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
16742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /*  gain = nrgRef / B */
16772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FDK_divide_MantExp( nrgRef,  nrgRef_e,
16782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        b,  b_e,
16792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        ptrNrgGain, ptrNrgGain_e);
16802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
16812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
16822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
16852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief  Calculate "average gain" for the specified subband range.
16862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  This is rather a gain of the average magnitude than the average
16882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  of gains!
16892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  The result is used as a relative limit for all gains within the
16902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  current "limiter band" (a certain frequency range).
16912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
16922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*static*/ void calcAvgGain(ENV_CALC_NRGS* nrgs,
16932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        int        lowSubband,    /*!< Begin of the limiter band */
16942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        int        highSubband,   /*!< High end of the limiter band */
16952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        FIXP_DBL  *ptrSumRef,
16962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        SCHAR     *ptrSumRef_e,
16972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        FIXP_DBL  *ptrAvgGain,  /*!< Resulting overall gain (mantissa) */
16982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                        SCHAR     *ptrAvgGain_e)  /*!< Resulting overall gain (exponent) */
16992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
17002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL  *nrgRef   = nrgs->nrgRef;       /*!< Reference Energy according to envelope data */
17012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR     *nrgRef_e = nrgs->nrgRef_e;     /*!< Reference Energy according to envelope data (exponent) */
17022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL  *nrgEst   = nrgs->nrgEst;       /*!< Energy in transposed signal */
17032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR     *nrgEst_e = nrgs->nrgEst_e;     /*!< Energy in transposed signal (exponent) */
17042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL sumRef = 1;
17062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL sumEst = 1;
17072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR    sumRef_e = -FRACT_BITS;
17082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  SCHAR    sumEst_e = -FRACT_BITS;
17092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int      k;
17102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (k=lowSubband; k<highSubband; k++){
17122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Add nrgRef[k] to sumRef: */
17132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FDK_add_MantExp( sumRef, sumRef_e,
17142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                     nrgRef[k], nrgRef_e[k],
17152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                     &sumRef, &sumRef_e );
17162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Add nrgEst[k] to sumEst: */
17182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    FDK_add_MantExp( sumEst, sumEst_e,
17192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                     nrgEst[k], nrgEst_e[k],
17202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                     &sumEst, &sumEst_e );
17212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
17222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDK_divide_MantExp(sumRef, sumRef_e,
17242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                     sumEst, sumEst_e,
17252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                     ptrAvgGain, ptrAvgGain_e);
17262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *ptrSumRef = sumRef;
17282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *ptrSumRef_e = sumRef_e;
17292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
17302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
17332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief   Amplify one timeslot of the signal with the calculated gains
17342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           and add the noisefloor.
17352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
17362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*static*/ void adjustTimeSlotLC(FIXP_DBL *ptrReal,       /*!< Subband samples to be adjusted, real part */
17382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                             ENV_CALC_NRGS* nrgs,
17392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                             UCHAR    *ptrHarmIndex,  /*!< Harmonic index */
17402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                             int       lowSubband,    /*!< Lowest QMF-channel in the currently used SBR range. */
17412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                             int       noSubbands,    /*!< Number of QMF subbands */
17422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                             int       scale_change,  /*!< Number of bits to shift adjusted samples */
17432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                             int       noNoiseFlag,   /*!< Flag to suppress noise addition */
17442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                             int      *ptrPhaseIndex, /*!< Start index to random number array */
17452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                             int       fCldfb)        /*!< CLDFB 80 flag */
17462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
17472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *pGain       = nrgs->nrgGain;     /*!< Gains of current envelope */
17482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *pNoiseLevel = nrgs->noiseLevel;  /*!< Noise levels of current envelope */
17492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *pSineLevel  = nrgs->nrgSine;     /*!< Sine levels */
17502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int    k;
17522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int    index = *ptrPhaseIndex;
17532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR  harmIndex = *ptrHarmIndex;
17542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR  freqInvFlag = (lowSubband & 1);
17552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL  signalReal, sineLevel, sineLevelNext, sineLevelPrev;
17562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int    tone_count = 0;
17572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int    sineSign = 1;
17582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  #define C1   ((FIXP_SGL)FL2FXCONST_SGL(2.f*0.00815f))
17602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  #define C1_CLDFB ((FIXP_SGL)FL2FXCONST_SGL(2.f*0.16773f))
17612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
17632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    First pass for k=0 pulled out of the loop:
17642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
17652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  index = (index + 1) & (SBR_NF_NO_RANDOM_VAL - 1);
17672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
17692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    The next multiplication constitutes the actual envelope adjustment
17702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    of the signal and should be carried out with full accuracy
17712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    (supplying #FRACT_BITS valid bits).
17722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
17732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  signalReal    = fMultDiv2(*ptrReal,*pGain++) << ((int)scale_change);
17742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  sineLevel     = *pSineLevel++;
17752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  sineLevelNext = (noSubbands > 1) ? pSineLevel[0] : FL2FXCONST_DBL(0.0f);
17762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (sineLevel!=FL2FXCONST_DBL(0.0f)) tone_count++;
17782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  else if (!noNoiseFlag)
17802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* Add noisefloor to the amplified signal */
17812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4);
17822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (fCldfb) {
17842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (!(harmIndex&0x1)) {
17862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* harmIndex 0,2 */
17872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      signalReal += (harmIndex&0x2) ? -sineLevel : sineLevel;
17882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *ptrReal++ = signalReal;
17892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
17902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else {
17912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* harmIndex 1,3 in combination with freqInvFlag */
17922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      int shift = (int) (scale_change+1);
17932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      shift = (shift>=0) ? fixMin(DFRACT_BITS-1,shift) : fixMax(-(DFRACT_BITS-1),shift);
17942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL tmp1 = scaleValue( fMultDiv2(C1_CLDFB, sineLevel), -shift );
17962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL tmp2 = fMultDiv2(C1_CLDFB, sineLevelNext);
17982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
17992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* save switch and compare operations and reduce to XOR statement */
18012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if ( ((harmIndex>>1)&0x1)^freqInvFlag) {
18022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *(ptrReal-1) += tmp1;
18032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal   -= tmp2;
18042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      } else {
18052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *(ptrReal-1) -= tmp1;
18062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal   += tmp2;
18072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
18082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *ptrReal++ = signalReal;
18092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      freqInvFlag = !freqInvFlag;
18102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
18112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  } else
18132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  {
18142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (!(harmIndex&0x1)) {
18152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* harmIndex 0,2 */
18162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      signalReal += (harmIndex&0x2) ? -sineLevel : sineLevel;
18172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *ptrReal++ = signalReal;
18182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
18192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else {
18202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* harmIndex 1,3 in combination with freqInvFlag */
18212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      int shift = (int) (scale_change+1);
18222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      shift = (shift>=0) ? fixMin(DFRACT_BITS-1,shift) : fixMax(-(DFRACT_BITS-1),shift);
18232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL tmp1 = (shift>=0) ? ( fMultDiv2(C1, sineLevel) >> shift )
18252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                                 : ( fMultDiv2(C1, sineLevel) << (-shift) );
18262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      FIXP_DBL tmp2 = fMultDiv2(C1, sineLevelNext);
18272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* save switch and compare operations and reduce to XOR statement */
18302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if ( ((harmIndex>>1)&0x1)^freqInvFlag) {
18312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *(ptrReal-1) += tmp1;
18322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal   -= tmp2;
18332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      } else {
18342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *(ptrReal-1) -= tmp1;
18352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal   += tmp2;
18362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
18372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *ptrReal++ = signalReal;
18382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      freqInvFlag = !freqInvFlag;
18392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
18402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
18412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  pNoiseLevel++;
18432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if ( noSubbands > 2 ) {
18452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (!(harmIndex&0x1)) {
18462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* harmIndex 0,2 */
18472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if(!harmIndex)
18482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
18492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        sineSign = 0;
18502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
18512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (k=noSubbands-2; k!=0; k--) {
18532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        FIXP_DBL sinelevel = *pSineLevel++;
18542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        index++;
18552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (((signalReal = (sineSign ? -sinelevel : sinelevel)) == FL2FXCONST_DBL(0.0f))  && !noNoiseFlag)
18562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
18572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* Add noisefloor to the amplified signal */
18582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          index &= (SBR_NF_NO_RANDOM_VAL - 1);
18592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4);
18602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
18612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* The next multiplication constitutes the actual envelope adjustment of the signal. */
18632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        signalReal += fMultDiv2(*ptrReal,*pGain++) << ((int)scale_change);
18642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pNoiseLevel++;
18662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        *ptrReal++ = signalReal;
18672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      } /* for ... */
18682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
18692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else {
18702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* harmIndex 1,3 in combination with freqInvFlag */
18712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (harmIndex==1) freqInvFlag = !freqInvFlag;
18722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (k=noSubbands-2; k!=0; k--) {
18742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        index++;
18752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* The next multiplication constitutes the actual envelope adjustment of the signal. */
18762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        signalReal = fMultDiv2(*ptrReal,*pGain++) << ((int)scale_change);
18772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (*pSineLevel++!=FL2FXCONST_DBL(0.0f)) tone_count++;
18792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        else if (!noNoiseFlag) {
18802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* Add noisefloor to the amplified signal */
18812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          index &= (SBR_NF_NO_RANDOM_VAL - 1);
18822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4);
18832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
18842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        pNoiseLevel++;
18862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (tone_count <= 16) {
18882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          FIXP_DBL addSine = fMultDiv2((pSineLevel[-2] - pSineLevel[0]), C1);
18892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal += (freqInvFlag) ? (-addSine) : (addSine);
18902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
18912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        *ptrReal++ = signalReal;
18932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        freqInvFlag = !freqInvFlag;
18942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      } /* for ... */
18952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
18962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
18972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (noSubbands > -1) {
18992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    index++;
19002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* The next multiplication constitutes the actual envelope adjustment of the signal. */
19012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    signalReal    = fMultDiv2(*ptrReal,*pGain) << ((int)scale_change);
19022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    sineLevelPrev = fMultDiv2(pSineLevel[-1],FL2FX_SGL(0.0163f));
19032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    sineLevel     = pSineLevel[0];
19042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (pSineLevel[0]!=FL2FXCONST_DBL(0.0f)) tone_count++;
19062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else if (!noNoiseFlag) {
19072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* Add noisefloor to the amplified signal */
19082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        index &= (SBR_NF_NO_RANDOM_VAL - 1);
19092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        signalReal = signalReal + (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4);
19102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
19112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (!(harmIndex&0x1)) {
19132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* harmIndex 0,2 */
19142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *ptrReal = signalReal + ( (sineSign) ? -sineLevel : sineLevel);
19152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
19162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    else {
19172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* harmIndex 1,3 in combination with freqInvFlag */
19182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if(tone_count <= 16){
19192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (freqInvFlag) {
19202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrReal++   = signalReal - sineLevelPrev;
19212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (noSubbands + lowSubband < 63)
19222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            *ptrReal = *ptrReal + fMultDiv2(C1, sineLevel);
19232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
19242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        else {
19252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrReal++ = signalReal + sineLevelPrev;
19262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (noSubbands + lowSubband < 63)
19272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            *ptrReal = *ptrReal - fMultDiv2(C1, sineLevel);
19282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
19292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
19302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else *ptrReal = signalReal;
19312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
19322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
19332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *ptrHarmIndex = (harmIndex + 1) & 3;
19342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *ptrPhaseIndex = index & (SBR_NF_NO_RANDOM_VAL - 1);
19352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
19362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectvoid adjustTimeSlotHQ(FIXP_DBL *RESTRICT ptrReal,           /*!< Subband samples to be adjusted, real part */
19372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      FIXP_DBL *RESTRICT ptrImag,               /*!< Subband samples to be adjusted, imag part */
19382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env,
19392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      ENV_CALC_NRGS* nrgs,
19402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      int       lowSubband,            /*!< Lowest QMF-channel in the currently used SBR range. */
19412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      int       noSubbands,            /*!< Number of QMF subbands */
19422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      int       scale_change,          /*!< Number of bits to shift adjusted samples */
19432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      FIXP_SGL  smooth_ratio,          /*!< Impact of last envelope */
19442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      int       noNoiseFlag,           /*!< Start index to random number array */
19452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                      int       filtBufferNoiseShift)  /*!< Shift factor of filtBufferNoise */
19462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
19472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *RESTRICT gain       = nrgs->nrgGain;        /*!< Gains of current envelope */
19492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *RESTRICT noiseLevel = nrgs->noiseLevel;     /*!< Noise levels of current envelope */
19502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine;        /*!< Sine levels */
19512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *RESTRICT filtBuffer      = h_sbr_cal_env->filtBuffer;      /*!< Gains of last envelope */
19532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL *RESTRICT filtBufferNoise = h_sbr_cal_env->filtBufferNoise; /*!< Noise levels of last envelope */
19542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR    *RESTRICT ptrHarmIndex    =&h_sbr_cal_env->harmIndex;       /*!< Harmonic index */
19552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int      *RESTRICT ptrPhaseIndex   =&h_sbr_cal_env->phaseIndex;      /*!< Start index to random number array */
19562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int    k;
19582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL signalReal, signalImag;
19592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL noiseReal,  noiseImag;
19602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL  smoothedGain, smoothedNoise;
19612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_SGL direct_ratio = /*FL2FXCONST_SGL(1.0f) */ (FIXP_SGL)MAXVAL_SGL - smooth_ratio;
19622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int    index = *ptrPhaseIndex;
19632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR   harmIndex = *ptrHarmIndex;
19642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  register int freqInvFlag = (lowSubband & 1);
19652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL sineLevel;
19662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int shift;
19672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *ptrPhaseIndex = (index+noSubbands) & (SBR_NF_NO_RANDOM_VAL - 1);
19692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *ptrHarmIndex = (harmIndex + 1) & 3;
19702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /*
19722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    Possible optimization:
19732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    smooth_ratio and harmIndex stay constant during the loop.
19742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    It might be faster to include a separate loop in each path.
19752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    the check for smooth_ratio is now outside the loop and the workload
19772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    of the whole function decreased by about 20 %
19782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
19792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  filtBufferNoiseShift += 1;      /* due to later use of fMultDiv2 instead of fMult */
19812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (filtBufferNoiseShift<0)
19822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    shift = fixMin(DFRACT_BITS-1,-filtBufferNoiseShift);
19832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  else
19842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    shift = fixMin(DFRACT_BITS-1, filtBufferNoiseShift);
19852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (smooth_ratio > FL2FXCONST_SGL(0.0f)) {
19872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (k=0; k<noSubbands; k++) {
19892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /*
19902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        Smoothing: The old envelope has been bufferd and a certain ratio
19912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        of the old gains and noise levels is used.
19922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      */
19932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      smoothedGain = fMult(smooth_ratio,filtBuffer[k]) +
19952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                     fMult(direct_ratio,gain[k]);
19962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (filtBufferNoiseShift<0) {
19982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        smoothedNoise = (fMultDiv2(smooth_ratio,filtBufferNoise[k])>>shift) +
19992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                         fMult(direct_ratio,noiseLevel[k]);
20002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
20012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else {
20022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        smoothedNoise = (fMultDiv2(smooth_ratio,filtBufferNoise[k])<<shift) +
20032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                         fMult(direct_ratio,noiseLevel[k]);
20042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
20052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /*
20072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        The next 2 multiplications constitute the actual envelope adjustment
20082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        of the signal and should be carried out with full accuracy
20092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        (supplying #DFRACT_BITS valid bits).
20102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      */
20112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      signalReal = fMultDiv2(*ptrReal,smoothedGain)<<((int)scale_change);
20122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      signalImag = fMultDiv2(*ptrImag,smoothedGain)<<((int)scale_change);
20132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      index++;
20152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (pSineLevel[k] != FL2FXCONST_DBL(0.0f)) {
20172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        sineLevel = pSineLevel[k];
20182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        switch(harmIndex) {
20202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case 0:
20212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrReal++ = (signalReal + sineLevel);
20222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrImag++ = (signalImag);
20232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
20242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case 2:
20252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrReal++ = (signalReal - sineLevel);
20262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrImag++ = (signalImag);
20272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
20282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case 1:
20292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrReal++ = (signalReal);
20302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (freqInvFlag)
20312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            *ptrImag++ = (signalImag - sineLevel);
20322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          else
20332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            *ptrImag++ = (signalImag + sineLevel);
20342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
20352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case 3:
20362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrReal++ = signalReal;
20372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (freqInvFlag)
20382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            *ptrImag++ = (signalImag + sineLevel);
20392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          else
20402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            *ptrImag++ = (signalImag - sineLevel);
20412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
20422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
20432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
20442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else {
20452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (noNoiseFlag) {
20462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* Just the amplified signal is saved */
20472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrReal++ = (signalReal);
20482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrImag++ = (signalImag);
20492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
20502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        else {
20512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* Add noisefloor to the amplified signal */
20522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          index &= (SBR_NF_NO_RANDOM_VAL - 1);
20532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          noiseReal = fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], smoothedNoise)<<4;
20542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          noiseImag = fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][1], smoothedNoise)<<4;
20552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrReal++ = (signalReal + noiseReal);
20562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          *ptrImag++ = (signalImag + noiseImag);
20572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
20582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
20592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      freqInvFlag ^= 1;
20602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
20612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
20632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  else
20642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  {
20652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (k=0; k<noSubbands; k++)
20662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
20672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      smoothedGain  = gain[k];
20682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      signalReal = fMultDiv2(*ptrReal, smoothedGain) << scale_change;
20692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      signalImag = fMultDiv2(*ptrImag, smoothedGain) << scale_change;
20702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      index++;
20722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
20732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if ((sineLevel = pSineLevel[k]) != FL2FXCONST_DBL(0.0f))
20742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
20752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        switch (harmIndex)
20762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
20772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case 0:
20782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal += sineLevel;
20792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
20802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case 1:
20812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (freqInvFlag)
20822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            signalImag -= sineLevel;
20832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          else
20842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            signalImag += sineLevel;
20852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
20862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case 2:
20872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal -= sineLevel;
20882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
20892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case 3:
20902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (freqInvFlag)
20912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            signalImag += sineLevel;
20922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          else
20932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            signalImag -= sineLevel;
20942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
20952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
20962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
20972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      else
20982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      {
20992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (noNoiseFlag == 0)
21002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
21012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* Add noisefloor to the amplified signal */
21022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          smoothedNoise = noiseLevel[k];
21032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          index &= (SBR_NF_NO_RANDOM_VAL - 1);
21042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          noiseReal = fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], smoothedNoise);
21052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          noiseImag = fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][1], smoothedNoise);
21062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalReal += noiseReal<<4;
21072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          signalImag += noiseImag<<4;
21082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
21092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
21102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *ptrReal++ = signalReal;
21112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      *ptrImag++ = signalImag;
21122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      freqInvFlag ^= 1;
21142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
21152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
21162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
21172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/*!
21202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \brief   Reset limiter bands.
21212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  Build frequency band table for the gain limiter dependent on
21232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  the previously generated transposer patch areas.
21242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  \return  SBRDEC_OK if ok,  SBRDEC_UNSUPPORTED_CONFIG on error
21262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*/
21272228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectSBR_ERROR
21282228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectResetLimiterBands ( UCHAR *limiterBandTable,   /*!< Resulting band borders in QMF channels */
21292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    UCHAR *noLimiterBands,     /*!< Resulting number of limiter band */
21302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    UCHAR *freqBandTable,      /*!< Table with possible band borders */
21312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    int noFreqBands,                   /*!< Number of bands in freqBandTable */
21322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    const PATCH_PARAM *patchParam,     /*!< Transposer patch parameters */
21332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    int noPatches,                     /*!< Number of transposer patches */
21342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                    int limiterBands)                  /*!< Selected 'band density' from bitstream */
21352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
21362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int i, k, isPatchBorder[2], loLimIndex, hiLimIndex, tempNoLim, nBands;
21372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR workLimiterBandTable[MAX_FREQ_COEFFS / 2 + MAX_NUM_PATCHES + 1];
21382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int patchBorders[MAX_NUM_PATCHES + 1];
21392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int kx, k2;
21402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FIXP_DBL temp;
21412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int lowSubband = freqBandTable[0];
21432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int highSubband = freqBandTable[noFreqBands];
21442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* 1 limiter band. */
21462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if(limiterBands == 0) {
21472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    limiterBandTable[0] = 0;
21482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    limiterBandTable[1] = highSubband - lowSubband;
21492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    nBands = 1;
21502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  } else {
21512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (i = 0; i < noPatches; i++) {
21522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      patchBorders[i] = patchParam[i].guardStartBand - lowSubband;
21532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
21542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    patchBorders[i] = highSubband - lowSubband;
21552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* 1.2, 2, or 3 limiter bands/octave plus bandborders at patchborders. */
21572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (k = 0; k <= noFreqBands; k++) {
21582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      workLimiterBandTable[k] = freqBandTable[k] - lowSubband;
21592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
21602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (k = 1; k < noPatches; k++) {
21612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      workLimiterBandTable[noFreqBands + k] = patchBorders[k];
21622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
21632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    tempNoLim = nBands = noFreqBands + noPatches - 1;
21652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    shellsort(workLimiterBandTable, tempNoLim + 1);
21662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    loLimIndex = 0;
21682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    hiLimIndex = 1;
21692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    while (hiLimIndex <= tempNoLim) {
21722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      k2 = workLimiterBandTable[hiLimIndex] + lowSubband;
21732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      kx = workLimiterBandTable[loLimIndex] + lowSubband;
21742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      temp = FX_SGL2FX_DBL(FDK_getNumOctavesDiv8(kx,k2)); /* Number of octaves */
21762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      temp = fMult(temp, FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[limiterBands]);
21772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      if (temp < FL2FXCONST_DBL (0.49f)>>5) {
21792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (workLimiterBandTable[hiLimIndex] == workLimiterBandTable[loLimIndex]) {
21802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          workLimiterBandTable[hiLimIndex] = highSubband;
21812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          nBands--;
21822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          hiLimIndex++;
21832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          continue;
21842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
21852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        isPatchBorder[0] = isPatchBorder[1] = 0;
21862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        for (k = 0; k <= noPatches; k++) {
21872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (workLimiterBandTable[hiLimIndex] == patchBorders[k]) {
21882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            isPatchBorder[1] = 1;
21892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            break;
21902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
21912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
21922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (!isPatchBorder[1]) {
21932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          workLimiterBandTable[hiLimIndex] = highSubband;
21942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          nBands--;
21952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          hiLimIndex++;
21962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          continue;
21972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
21982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        for (k = 0; k <= noPatches; k++) {
21992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          if (workLimiterBandTable[loLimIndex] == patchBorders[k]) {
22002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            isPatchBorder[0] = 1;
22012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            break;
22022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
22032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
22042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (!isPatchBorder[0]) {
22052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          workLimiterBandTable[loLimIndex] = highSubband;
22062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          nBands--;
22072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
22082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
22092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      loLimIndex = hiLimIndex;
22102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      hiLimIndex++;
22112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
22122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
22132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    shellsort(workLimiterBandTable, tempNoLim + 1);
22142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
22152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Test if algorithm exceeded maximum allowed limiterbands */
22162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if( nBands > MAX_NUM_LIMITERS || nBands <= 0) {
22172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      return SBRDEC_UNSUPPORTED_CONFIG;
22182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
22192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
22202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Copy limiterbands from working buffer into final destination */
22212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (k = 0; k <= nBands; k++) {
22222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      limiterBandTable[k] = workLimiterBandTable[k];
22232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
22242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
22252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *noLimiterBands = nBands;
22262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
22272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  return SBRDEC_OK;
22282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
22292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2230