From 14c7b800eaa23e9da7c92c7c4df397d0c191f097 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Sat, 10 Sep 2016 20:15:44 +0200 Subject: Remove FDK-AAC --- libSBRdec/src/env_calc.cpp | 2229 -------------------------------------------- 1 file changed, 2229 deletions(-) delete mode 100644 libSBRdec/src/env_calc.cpp (limited to 'libSBRdec/src/env_calc.cpp') diff --git a/libSBRdec/src/env_calc.cpp b/libSBRdec/src/env_calc.cpp deleted file mode 100644 index ade57fc..0000000 --- a/libSBRdec/src/env_calc.cpp +++ /dev/null @@ -1,2229 +0,0 @@ - -/* ----------------------------------------------------------------------------------------------------------- -Software License for The Fraunhofer FDK AAC Codec Library for Android - -© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. - - 1. INTRODUCTION -The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements -the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. -This FDK AAC Codec software is intended to be used on a wide variety of Android devices. - -AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual -audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by -independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part -of the MPEG specifications. - -Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) -may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners -individually for the purpose of encoding or decoding bit streams in products that are compliant with -the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license -these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec -software may already be covered under those patent licenses when it is used for those licensed purposes only. - -Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, -are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional -applications information and documentation. - -2. COPYRIGHT LICENSE - -Redistribution and use in source and binary forms, with or without modification, are permitted without -payment of copyright license fees provided that you satisfy the following conditions: - -You must retain the complete text of this software license in redistributions of the FDK AAC Codec or -your modifications thereto in source code form. - -You must retain the complete text of this software license in the documentation and/or other materials -provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. -You must make available free of charge copies of the complete source code of the FDK AAC Codec and your -modifications thereto to recipients of copies in binary form. - -The name of Fraunhofer may not be used to endorse or promote products derived from this library without -prior written permission. - -You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec -software or your modifications thereto. - -Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software -and the date of any change. For modified versions of the FDK AAC Codec, the term -"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term -"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." - -3. NO PATENT LICENSE - -NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, -ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with -respect to this software. - -You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized -by appropriate patent licenses. - -4. DISCLAIMER - -This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors -"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties -of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, -including but not limited to procurement of substitute goods or services; loss of use, data, or profits, -or business interruption, however caused and on any theory of liability, whether in contract, strict -liability, or tort (including negligence), arising in any way out of the use of this software, even if -advised of the possibility of such damage. - -5. CONTACT INFORMATION - -Fraunhofer Institute for Integrated Circuits IIS -Attention: Audio and Multimedia Departments - FDK AAC LL -Am Wolfsmantel 33 -91058 Erlangen, Germany - -www.iis.fraunhofer.de/amm -amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ - -/*! - \file - \brief Envelope calculation - - The envelope adjustor compares the energies present in the transposed - highband to the reference energies conveyed with the bitstream. - The highband is amplified (sometimes) or attenuated (mostly) to the - desired level. - - The spectral shape of the reference energies can be changed several times per - frame if necessary. Each set of energy values corresponding to a certain range - in time will be called an envelope here. - The bitstream supports several frequency scales and two resolutions. Normally, - one or more QMF-subbands are grouped to one SBR-band. An envelope contains - reference energies for each SBR-band. - In addition to the energy envelopes, noise envelopes are transmitted that - define the ratio of energy which is generated by adding noise instead of - transposing the lowband. The noise envelopes are given in a coarser time - and frequency resolution. - If a signal contains strong tonal components, synthetic sines can be - generated in individual SBR bands. - - An overlap buffer of 6 QMF-timeslots is used to allow a more - flexible alignment of the envelopes in time that is not restricted to the - core codec's frame borders. - Therefore the envelope adjustor has access to the spectral data of the - current frame as well as the last 6 QMF-timeslots of the previous frame. - However, in average only the data of 1 frame is being processed as - the adjustor is called once per frame. - - Depending on the frequency range set in the bitstream, only QMF-subbands between - lowSubband and highSubband are adjusted. - - Scaling of spectral data to maximize SNR (see #QMF_SCALE_FACTOR) as well as a special Mantissa-Exponent format - ( see calculateSbrEnvelope() ) are being used. The main entry point for this modules is calculateSbrEnvelope(). - - \sa sbr_scale.h, #QMF_SCALE_FACTOR, calculateSbrEnvelope(), \ref documentationOverview -*/ - - -#include "env_calc.h" - -#include "sbrdec_freq_sca.h" -#include "env_extr.h" -#include "transcendent.h" -#include "sbr_ram.h" -#include "sbr_rom.h" - -#include "genericStds.h" /* need FDKpow() for debug outputs */ - -#if defined(__arm__) -#include "arm/env_calc_arm.cpp" -#endif - -typedef struct -{ - FIXP_DBL nrgRef[MAX_FREQ_COEFFS]; - FIXP_DBL nrgEst[MAX_FREQ_COEFFS]; - FIXP_DBL nrgGain[MAX_FREQ_COEFFS]; - FIXP_DBL noiseLevel[MAX_FREQ_COEFFS]; - FIXP_DBL nrgSine[MAX_FREQ_COEFFS]; - - SCHAR nrgRef_e[MAX_FREQ_COEFFS]; - SCHAR nrgEst_e[MAX_FREQ_COEFFS]; - SCHAR nrgGain_e[MAX_FREQ_COEFFS]; - SCHAR noiseLevel_e[MAX_FREQ_COEFFS]; - SCHAR nrgSine_e[MAX_FREQ_COEFFS]; -} -ENV_CALC_NRGS; - -/*static*/ void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, - SCHAR *filtBuffer_e, - FIXP_DBL *NrgGain, - SCHAR *NrgGain_e, - int subbands); - -/*static*/ void calcNrgPerSubband(FIXP_DBL **analysBufferReal, - FIXP_DBL **analysBufferImag, - int lowSubband, int highSubband, - int start_pos, int next_pos, - SCHAR frameExp, - FIXP_DBL *nrgEst, - SCHAR *nrgEst_e ); - -/*static*/ void calcNrgPerSfb(FIXP_DBL **analysBufferReal, - FIXP_DBL **analysBufferImag, - int nSfb, - UCHAR *freqBandTable, - int start_pos, int next_pos, - SCHAR input_e, - FIXP_DBL *nrg_est, - SCHAR *nrg_est_e ); - -/*static*/ void calcSubbandGain(FIXP_DBL nrgRef, SCHAR nrgRef_e, ENV_CALC_NRGS* nrgs, int c, - FIXP_DBL tmpNoise, SCHAR tmpNoise_e, - UCHAR sinePresentFlag, - UCHAR sineMapped, - int noNoiseFlag); - -/*static*/ void calcAvgGain(ENV_CALC_NRGS* nrgs, - int lowSubband, - int highSubband, - FIXP_DBL *sumRef_m, - SCHAR *sumRef_e, - FIXP_DBL *ptrAvgGain_m, - SCHAR *ptrAvgGain_e); - -/*static*/ void adjustTimeSlotLC(FIXP_DBL *ptrReal, - ENV_CALC_NRGS* nrgs, - UCHAR *ptrHarmIndex, - int lowSubbands, - int noSubbands, - int scale_change, - int noNoiseFlag, - int *ptrPhaseIndex, - int fCldfb); -/*static*/ void adjustTimeSlotHQ(FIXP_DBL *ptrReal, - FIXP_DBL *ptrImag, - HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, - ENV_CALC_NRGS* nrgs, - int lowSubbands, - int noSubbands, - int scale_change, - FIXP_SGL smooth_ratio, - int noNoiseFlag, - int filtBufferNoiseShift); - - -/*! - \brief Map sine flags from bitstream to QMF bands - - The bitstream carries only 1 sine flag per band and frame. - This function maps every sine flag from the bitstream to a specific QMF subband - and to a specific envelope where the sine shall start. - The result is stored in the vector sineMapped which contains one entry per - QMF subband. The value of an entry specifies the envelope where a sine - shall start. A value of #MAX_ENVELOPES indicates that no sine is present - in the subband. - The missing harmonics flags from the previous frame (harmFlagsPrev) determine - if a sine starts at the beginning of the frame or at the transient position. - Additionally, the flags in harmFlagsPrev are being updated by this function - for the next frame. -*/ -/*static*/ void mapSineFlags(UCHAR *freqBandTable, /*!< Band borders (there's only 1 flag per band) */ - int nSfb, /*!< Number of bands in the table */ - UCHAR *addHarmonics, /*!< vector with 1 flag per sfb */ - int *harmFlagsPrev, /*!< Packed 'addHarmonics' */ - int tranEnv, /*!< Transient position */ - SCHAR *sineMapped) /*!< Resulting vector of sine start positions for each QMF band */ - -{ - int i; - int lowSubband2 = freqBandTable[0]<<1; - int bitcount = 0; - int oldflags = *harmFlagsPrev; - int newflags = 0; - - /* - Format of harmFlagsPrev: - - first word = flags for highest 16 sfb bands in use - second word = flags for next lower 16 sfb bands (if present) - third word = flags for lowest 16 sfb bands (if present) - - Up to MAX_FREQ_COEFFS sfb bands can be flagged for a sign. - The lowest bit of the first word corresponds to the _highest_ sfb band in use. - This is ensures that each flag is mapped to the same QMF band even after a - change of the crossover-frequency. - */ - - - /* Reset the output vector first */ - FDKmemset(sineMapped, MAX_ENVELOPES,MAX_FREQ_COEFFS); /* MAX_ENVELOPES means 'no sine' */ - - freqBandTable += nSfb; - addHarmonics += nSfb-1; - - for (i=nSfb; i!=0; i--) { - int ui = *freqBandTable--; /* Upper limit of the current scale factor band. */ - int li = *freqBandTable; /* Lower limit of the current scale factor band. */ - - if ( *addHarmonics-- ) { /* There is a sine in this band */ - - unsigned int mask = 1 << bitcount; - newflags |= mask; /* Set flag */ - - /* - If there was a sine in the last frame, let it continue from the first envelope on - else start at the transient position. - */ - sineMapped[(ui+li-lowSubband2) >> 1] = ( oldflags & mask ) ? 0 : tranEnv; - } - - if ((++bitcount == 16) || i==1) { - bitcount = 0; - *harmFlagsPrev++ = newflags; - oldflags = *harmFlagsPrev; /* Fetch 16 of the old flags */ - newflags = 0; - } - } -} - - -/*! - \brief Reduce gain-adjustment induced aliasing for real valued filterbank. -*/ -/*static*/ void -aliasingReduction(FIXP_DBL* degreeAlias, /*!< estimated aliasing for each QMF channel */ - ENV_CALC_NRGS* nrgs, - int* useAliasReduction, /*!< synthetic sine engergy for each subband, used as flag */ - int noSubbands) /*!< number of QMF channels to process */ -{ - FIXP_DBL* nrgGain = nrgs->nrgGain; /*!< subband gains to be modified */ - SCHAR* nrgGain_e = nrgs->nrgGain_e; /*!< subband gains to be modified (exponents) */ - FIXP_DBL* nrgEst = nrgs->nrgEst; /*!< subband energy before amplification */ - SCHAR* nrgEst_e = nrgs->nrgEst_e; /*!< subband energy before amplification (exponents) */ - int grouping = 0, index = 0, noGroups, k; - int groupVector[MAX_FREQ_COEFFS]; - - /* Calculate grouping*/ - for (k = 0; k < noSubbands-1; k++ ){ - if ( (degreeAlias[k + 1] != FL2FXCONST_DBL(0.0f)) && useAliasReduction[k] ) { - if(grouping==0){ - groupVector[index++] = k; - grouping = 1; - } - else{ - if(groupVector[index-1] + 3 == k){ - groupVector[index++] = k + 1; - grouping = 0; - } - } - } - else{ - if(grouping){ - if(useAliasReduction[k]) - groupVector[index++] = k + 1; - else - groupVector[index++] = k; - grouping = 0; - } - } - } - - if(grouping){ - groupVector[index++] = noSubbands; - } - noGroups = index >> 1; - - - /*Calculate new gain*/ - for (int group = 0; group < noGroups; group ++) { - FIXP_DBL nrgOrig = FL2FXCONST_DBL(0.0f); /* Original signal energy in current group of bands */ - SCHAR nrgOrig_e = 0; - FIXP_DBL nrgAmp = FL2FXCONST_DBL(0.0f); /* Amplified signal energy in group (using current gains) */ - SCHAR nrgAmp_e = 0; - FIXP_DBL nrgMod = FL2FXCONST_DBL(0.0f); /* Signal energy in group when applying modified gains */ - SCHAR nrgMod_e = 0; - FIXP_DBL groupGain; /* Total energy gain in group */ - SCHAR groupGain_e; - FIXP_DBL compensation; /* Compensation factor for the energy change when applying modified gains */ - SCHAR compensation_e; - - int startGroup = groupVector[2*group]; - int stopGroup = groupVector[2*group+1]; - - /* Calculate total energy in group before and after amplification with current gains: */ - for(k = startGroup; k < stopGroup; k++){ - /* Get original band energy */ - FIXP_DBL tmp = nrgEst[k]; - SCHAR tmp_e = nrgEst_e[k]; - - FDK_add_MantExp(tmp, tmp_e, nrgOrig, nrgOrig_e, &nrgOrig, &nrgOrig_e); - - /* Multiply band energy with current gain */ - tmp = fMult(tmp,nrgGain[k]); - tmp_e = tmp_e + nrgGain_e[k]; - - FDK_add_MantExp(tmp, tmp_e, nrgAmp, nrgAmp_e, &nrgAmp, &nrgAmp_e); - } - - /* Calculate total energy gain in group */ - FDK_divide_MantExp(nrgAmp, nrgAmp_e, - nrgOrig, nrgOrig_e, - &groupGain, &groupGain_e); - - for(k = startGroup; k < stopGroup; k++){ - FIXP_DBL tmp; - SCHAR tmp_e; - - FIXP_DBL alpha = degreeAlias[k]; - if (k < noSubbands - 1) { - if (degreeAlias[k + 1] > alpha) - alpha = degreeAlias[k + 1]; - } - - /* Modify gain depending on the degree of aliasing */ - FDK_add_MantExp( fMult(alpha,groupGain), groupGain_e, - fMult(/*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - alpha,nrgGain[k]), nrgGain_e[k], - &nrgGain[k], &nrgGain_e[k] ); - - /* Apply modified gain to original energy */ - tmp = fMult(nrgGain[k],nrgEst[k]); - tmp_e = nrgGain_e[k] + nrgEst_e[k]; - - /* Accumulate energy with modified gains applied */ - FDK_add_MantExp( tmp, tmp_e, - nrgMod, nrgMod_e, - &nrgMod, &nrgMod_e ); - } - - /* Calculate compensation factor to retain the energy of the amplified signal */ - FDK_divide_MantExp(nrgAmp, nrgAmp_e, - nrgMod, nrgMod_e, - &compensation, &compensation_e); - - /* Apply compensation factor to all gains of the group */ - for(k = startGroup; k < stopGroup; k++){ - nrgGain[k] = fMult(nrgGain[k],compensation); - nrgGain_e[k] = nrgGain_e[k] + compensation_e; - } - } -} - - - /* Convert headroom bits to exponent */ -#define SCALE2EXP(s) (15-(s)) -#define EXP2SCALE(e) (15-(e)) - -/*! - \brief Apply spectral envelope to subband samples - - This function is called from sbr_dec.cpp in each frame. - - To enhance accuracy and due to the usage of tables for squareroots and - inverse, some calculations are performed with the operands being split - into mantissa and exponent. The variable names in the source code carry - the suffixes _m and _e respectively. The control data - in #hFrameData containts envelope data which is represented by this format but - stored in single words. (See requantizeEnvelopeData() for details). This data - is unpacked within calculateSbrEnvelope() to follow the described suffix convention. - - The actual value (comparable to the corresponding float-variable in the - research-implementation) of a mantissa/exponent-pair can be calculated as - - \f$ value = value\_m * 2^{value\_e} \f$ - - All energies and noise levels decoded from the bitstream suit for an - original signal magnitude of \f$\pm 32768 \f$ rather than \f$ \pm 1\f$. Therefore, - the scale factor hb_scale passed into this function will be converted - to an 'input exponent' (#input_e), which fits the internal representation. - - Before the actual processing, an exponent #adj_e for resulting adjusted - samples is derived from the maximum reference energy. - - Then, for each envelope, the following steps are performed: - - \li Calculate energy in the signal to be adjusted. Depending on the the value of - #interpolFreq (interpolation mode), this is either done seperately - for each QMF-subband or for each SBR-band. - The resulting energies are stored in #nrgEst_m[#MAX_FREQ_COEFFS] (mantissas) - and #nrgEst_e[#MAX_FREQ_COEFFS] (exponents). - \li Calculate gain and noise level for each subband:
- \f$ gain = \sqrt{ \frac{nrgRef}{nrgEst} \cdot (1 - noiseRatio) } - \hspace{2cm} - noise = \sqrt{ nrgRef \cdot noiseRatio } - \f$
- where noiseRatio and nrgRef are extracted from the - bitstream and nrgEst is the subband energy before adjustment. - The resulting gains are stored in #nrgGain_m[#MAX_FREQ_COEFFS] - (mantissas) and #nrgGain_e[#MAX_FREQ_COEFFS] (exponents), the noise levels - are stored in #noiseLevel_m[#MAX_FREQ_COEFFS] and #noiseLevel_e[#MAX_FREQ_COEFFS] - (exponents). - The sine levels are stored in #nrgSine_m[#MAX_FREQ_COEFFS] - and #nrgSine_e[#MAX_FREQ_COEFFS]. - \li Noise limiting: The gain for each subband is limited both absolutely - and relatively compared to the total gain over all subbands. - \li Boost gain: Calculate and apply boost factor for each limiter band - in order to compensate for the energy loss imposed by the limiting. - \li Apply gains and add noise: The gains and noise levels are applied - to all timeslots of the current envelope. A short FIR-filter (length 4 - QMF-timeslots) can be used to smooth the sudden change at the envelope borders. - Each complex subband sample of the current timeslot is multiplied by the - smoothed gain, then random noise with the calculated level is added. - - \note - To reduce the stack size, some of the local arrays could be located within - the time output buffer. Of the 512 samples temporarily available there, - about half the size is already used by #SBR_FRAME_DATA. A pointer to the - remaining free memory could be supplied by an additional argument to calculateSbrEnvelope() - in sbr_dec: - - \par - \code - calculateSbrEnvelope (&hSbrDec->sbrScaleFactor, - &hSbrDec->SbrCalculateEnvelope, - hHeaderData, - hFrameData, - QmfBufferReal, - QmfBufferImag, - timeOutPtr + sizeof(SBR_FRAME_DATA)/sizeof(Float) + 1); - \endcode - - \par - Within calculateSbrEnvelope(), some pointers could be defined instead of the arrays - #nrgRef_m, #nrgRef_e, #nrgEst_m, #nrgEst_e, #noiseLevel_m: - - \par - \code - fract* nrgRef_m = timeOutPtr; - SCHAR* nrgRef_e = nrgRef_m + MAX_FREQ_COEFFS; - fract* nrgEst_m = nrgRef_e + MAX_FREQ_COEFFS; - SCHAR* nrgEst_e = nrgEst_m + MAX_FREQ_COEFFS; - fract* noiseLevel_m = nrgEst_e + MAX_FREQ_COEFFS; - \endcode - -
-*/ -void -calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ - HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, /*!< Handle to struct filled by the create-function */ - HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ - HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ - FIXP_DBL **analysBufferReal, /*!< Real part of subband samples to be processed */ - FIXP_DBL **analysBufferImag, /*!< Imag part of subband samples to be processed */ - const int useLP, - FIXP_DBL *degreeAlias, /*!< Estimated aliasing for each QMF channel */ - const UINT flags, - const int frameErrorFlag - ) -{ - int c, i, j, envNoise = 0; - UCHAR* borders = hFrameData->frameInfo.borders; - - FIXP_SGL *noiseLevels = hFrameData->sbrNoiseFloorLevel; - HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; - - int lowSubband = hFreq->lowSubband; - int highSubband = hFreq->highSubband; - int noSubbands = highSubband - lowSubband; - - int noNoiseBands = hFreq->nNfb; - int no_cols = hHeaderData->numberTimeSlots * hHeaderData->timeStep; - UCHAR first_start = borders[0] * hHeaderData->timeStep; - - SCHAR sineMapped[MAX_FREQ_COEFFS]; - SCHAR ov_adj_e = SCALE2EXP(sbrScaleFactor->ov_hb_scale); - SCHAR adj_e = 0; - SCHAR output_e; - SCHAR final_e = 0; - - SCHAR maxGainLimit_e = (frameErrorFlag) ? MAX_GAIN_CONCEAL_EXP : MAX_GAIN_EXP; - - int useAliasReduction[64]; - UCHAR smooth_length = 0; - - FIXP_SGL * pIenv = hFrameData->iEnvelope; - - /* - Extract sine flags for all QMF bands - */ - mapSineFlags(hFreq->freqBandTable[1], - hFreq->nSfb[1], - hFrameData->addHarmonics, - h_sbr_cal_env->harmFlagsPrev, - hFrameData->frameInfo.tranEnv, - sineMapped); - - - /* - Scan for maximum in bufferd noise levels. - This is needed in case that we had strong noise in the previous frame - which is smoothed into the current frame. - The resulting exponent is used as start value for the maximum search - in reference energies - */ - if (!useLP) - adj_e = h_sbr_cal_env->filtBufferNoise_e - getScalefactor(h_sbr_cal_env->filtBufferNoise, noSubbands); - - /* - Scan for maximum reference energy to be able - to select appropriate values for adj_e and final_e. - */ - - for (i = 0; i < hFrameData->frameInfo.nEnvelopes; i++) { - INT maxSfbNrg_e = -FRACT_BITS+NRG_EXP_OFFSET; /* start value for maximum search */ - - /* Fetch frequency resolution for current envelope: */ - for (j=hFreq->nSfb[hFrameData->frameInfo.freqRes[i]]; j!=0; j--) { - maxSfbNrg_e = fixMax(maxSfbNrg_e,(INT)((LONG)(*pIenv++) & MASK_E)); - } - maxSfbNrg_e -= NRG_EXP_OFFSET; - - /* Energy -> magnitude (sqrt halfens exponent) */ - maxSfbNrg_e = (maxSfbNrg_e+1) >> 1; /* +1 to go safe (round to next higher int) */ - - /* Some safety margin is needed for 2 reasons: - - The signal energy is not equally spread over all subband samples in - a specific sfb of an envelope (Nrg could be too high by a factor of - envWidth * sfbWidth) - - Smoothing can smear high gains of the previous envelope into the current - */ - maxSfbNrg_e += 6; - - if (borders[i] < hHeaderData->numberTimeSlots) - /* This envelope affects timeslots that belong to the output frame */ - adj_e = (maxSfbNrg_e > adj_e) ? maxSfbNrg_e : adj_e; - - if (borders[i+1] > hHeaderData->numberTimeSlots) - /* This envelope affects timeslots after the output frame */ - final_e = (maxSfbNrg_e > final_e) ? maxSfbNrg_e : final_e; - - } - - /* - Calculate adjustment factors and apply them for every envelope. - */ - pIenv = hFrameData->iEnvelope; - - for (i = 0; i < hFrameData->frameInfo.nEnvelopes; i++) { - - int k, noNoiseFlag; - SCHAR noise_e, input_e = SCALE2EXP(sbrScaleFactor->hb_scale); - C_ALLOC_SCRATCH_START(pNrgs, ENV_CALC_NRGS, 1); - - /* - Helper variables. - */ - UCHAR start_pos = hHeaderData->timeStep * borders[i]; /* Start-position in time (subband sample) for current envelope. */ - UCHAR stop_pos = hHeaderData->timeStep * borders[i+1]; /* Stop-position in time (subband sample) for current envelope. */ - UCHAR freq_res = hFrameData->frameInfo.freqRes[i]; /* Frequency resolution for current envelope. */ - - - /* Always do fully initialize the temporary energy table. This prevents negative energies and extreme gain factors in - cases where the number of limiter bands exceeds the number of subbands. The latter can be caused by undetected bit - errors and is tested by some streams from the certification set. */ - FDKmemclear(pNrgs, sizeof(ENV_CALC_NRGS)); - - /* If the start-pos of the current envelope equals the stop pos of the current - noise envelope, increase the pointer (i.e. choose the next noise-floor).*/ - if (borders[i] == hFrameData->frameInfo.bordersNoise[envNoise+1]){ - noiseLevels += noNoiseBands; /* The noise floor data is stored in a row [noiseFloor1 noiseFloor2...].*/ - envNoise++; - } - - if(i==hFrameData->frameInfo.tranEnv || i==h_sbr_cal_env->prevTranEnv) /* attack */ - { - noNoiseFlag = 1; - if (!useLP) - smooth_length = 0; /* No smoothing on attacks! */ - } - else { - noNoiseFlag = 0; - if (!useLP) - smooth_length = (1 - hHeaderData->bs_data.smoothingLength) << 2; /* can become either 0 or 4 */ - } - - - /* - Energy estimation in transposed highband. - */ - if (hHeaderData->bs_data.interpolFreq) - calcNrgPerSubband(analysBufferReal, - (useLP) ? NULL : analysBufferImag, - lowSubband, highSubband, - start_pos, stop_pos, - input_e, - pNrgs->nrgEst, - pNrgs->nrgEst_e); - else - calcNrgPerSfb(analysBufferReal, - (useLP) ? NULL : analysBufferImag, - hFreq->nSfb[freq_res], - hFreq->freqBandTable[freq_res], - start_pos, stop_pos, - input_e, - pNrgs->nrgEst, - pNrgs->nrgEst_e); - - /* - Calculate subband gains - */ - { - UCHAR * table = hFreq->freqBandTable[freq_res]; - UCHAR * pUiNoise = &hFreq->freqBandTableNoise[1]; /*! Upper limit of the current noise floor band. */ - - FIXP_SGL * pNoiseLevels = noiseLevels; - - FIXP_DBL tmpNoise = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M)); - SCHAR tmpNoise_e = (UCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET; - - int cc = 0; - c = 0; - for (j = 0; j < hFreq->nSfb[freq_res]; j++) { - - FIXP_DBL refNrg = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pIenv) & MASK_M)); - SCHAR refNrg_e = (SCHAR)((LONG)(*pIenv) & MASK_E) - NRG_EXP_OFFSET; - - UCHAR sinePresentFlag = 0; - int li = table[j]; - int ui = table[j+1]; - - for (k=li; k= sineMapped[cc]); - cc++; - } - - for (k=li; k= *pUiNoise) { - tmpNoise = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M)); - tmpNoise_e = (SCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET; - - pUiNoise++; - } - - FDK_ASSERT(k >= lowSubband); - - if (useLP) - useAliasReduction[k-lowSubband] = !sinePresentFlag; - - pNrgs->nrgSine[c] = FL2FXCONST_DBL(0.0f); - pNrgs->nrgSine_e[c] = 0; - - calcSubbandGain(refNrg, refNrg_e, pNrgs, c, - tmpNoise, tmpNoise_e, - sinePresentFlag, i >= sineMapped[c], - noNoiseFlag); - - pNrgs->nrgRef[c] = refNrg; - pNrgs->nrgRef_e[c] = refNrg_e; - - c++; - } - pIenv++; - } - } - - /* - Noise limiting - */ - - for (c = 0; c < hFreq->noLimiterBands; c++) { - - FIXP_DBL sumRef, boostGain, maxGain; - FIXP_DBL accu = FL2FXCONST_DBL(0.0f); - SCHAR sumRef_e, boostGain_e, maxGain_e, accu_e = 0; - - calcAvgGain(pNrgs, - hFreq->limiterBandTable[c], hFreq->limiterBandTable[c+1], - &sumRef, &sumRef_e, - &maxGain, &maxGain_e); - - /* Multiply maxGain with limiterGain: */ - maxGain = fMult(maxGain, FDK_sbrDecoder_sbr_limGains_m[hHeaderData->bs_data.limiterGains]); - maxGain_e += FDK_sbrDecoder_sbr_limGains_e[hHeaderData->bs_data.limiterGains]; - - /* Scale mantissa of MaxGain into range between 0.5 and 1: */ - if (maxGain == FL2FXCONST_DBL(0.0f)) - maxGain_e = -FRACT_BITS; - else { - SCHAR charTemp = CountLeadingBits(maxGain); - maxGain_e -= charTemp; - maxGain <<= (int)charTemp; - } - - if (maxGain_e >= maxGainLimit_e) { /* upper limit (e.g. 96 dB) */ - maxGain = FL2FXCONST_DBL(0.5f); - maxGain_e = maxGainLimit_e; - } - - - /* Every subband gain is compared to the scaled "average gain" - and limited if necessary: */ - for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c+1]; k++) { - if ( (pNrgs->nrgGain_e[k] > maxGain_e) || (pNrgs->nrgGain_e[k] == maxGain_e && pNrgs->nrgGain[k]>maxGain) ) { - - FIXP_DBL noiseAmp; - SCHAR noiseAmp_e; - - FDK_divide_MantExp(maxGain, maxGain_e, pNrgs->nrgGain[k], pNrgs->nrgGain_e[k], &noiseAmp, &noiseAmp_e); - pNrgs->noiseLevel[k] = fMult(pNrgs->noiseLevel[k],noiseAmp); - pNrgs->noiseLevel_e[k] += noiseAmp_e; - pNrgs->nrgGain[k] = maxGain; - pNrgs->nrgGain_e[k] = maxGain_e; - } - } - - /* -- Boost gain - Calculate and apply boost factor for each limiter band: - 1. Check how much energy would be present when using the limited gain - 2. Calculate boost factor by comparison with reference energy - 3. Apply boost factor to compensate for the energy loss due to limiting - */ - for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; k++) { - - /* 1.a Add energy of adjusted signal (using preliminary gain) */ - FIXP_DBL tmp = fMult(pNrgs->nrgGain[k],pNrgs->nrgEst[k]); - SCHAR tmp_e = pNrgs->nrgGain_e[k] + pNrgs->nrgEst_e[k]; - FDK_add_MantExp(tmp, tmp_e, accu, accu_e, &accu, &accu_e); - - /* 1.b Add sine energy (if present) */ - if(pNrgs->nrgSine[k] != FL2FXCONST_DBL(0.0f)) { - FDK_add_MantExp(pNrgs->nrgSine[k], pNrgs->nrgSine_e[k], accu, accu_e, &accu, &accu_e); - } - else { - /* 1.c Add noise energy (if present) */ - if(noNoiseFlag == 0) { - FDK_add_MantExp(pNrgs->noiseLevel[k], pNrgs->noiseLevel_e[k], accu, accu_e, &accu, &accu_e); - } - } - } - - /* 2.a Calculate ratio of wanted energy and accumulated energy */ - if (accu == (FIXP_DBL)0) { /* If divisor is 0, limit quotient to +4 dB */ - boostGain = FL2FXCONST_DBL(0.6279716f); - boostGain_e = 2; - } else { - INT div_e; - boostGain = fDivNorm(sumRef, accu, &div_e); - boostGain_e = sumRef_e - accu_e + div_e; - } - - - /* 2.b Result too high? --> Limit the boost factor to +4 dB */ - if((boostGain_e > 3) || - (boostGain_e == 2 && boostGain > FL2FXCONST_DBL(0.6279716f)) || - (boostGain_e == 3 && boostGain > FL2FXCONST_DBL(0.3139858f)) ) - { - boostGain = FL2FXCONST_DBL(0.6279716f); - boostGain_e = 2; - } - /* 3. Multiply all signal components with the boost factor */ - for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; k++) { - pNrgs->nrgGain[k] = fMultDiv2(pNrgs->nrgGain[k],boostGain); - pNrgs->nrgGain_e[k] = pNrgs->nrgGain_e[k] + boostGain_e + 1; - - pNrgs->nrgSine[k] = fMultDiv2(pNrgs->nrgSine[k],boostGain); - pNrgs->nrgSine_e[k] = pNrgs->nrgSine_e[k] + boostGain_e + 1; - - pNrgs->noiseLevel[k] = fMultDiv2(pNrgs->noiseLevel[k],boostGain); - pNrgs->noiseLevel_e[k] = pNrgs->noiseLevel_e[k] + boostGain_e + 1; - } - } - /* End of noise limiting */ - - if (useLP) - aliasingReduction(degreeAlias+lowSubband, - pNrgs, - useAliasReduction, - noSubbands); - - /* For the timeslots within the range for the output frame, - use the same scale for the noise levels. - Drawback: If the envelope exceeds the frame border, the noise levels - will have to be rescaled later to fit final_e of - the gain-values. - */ - noise_e = (start_pos < no_cols) ? adj_e : final_e; - - /* - Convert energies to amplitude levels - */ - for (k=0; knrgSine[k], &pNrgs->nrgSine_e[k], &noise_e); - FDK_sqrt_MantExp(&pNrgs->nrgGain[k], &pNrgs->nrgGain_e[k], &pNrgs->nrgGain_e[k]); - FDK_sqrt_MantExp(&pNrgs->noiseLevel[k], &pNrgs->noiseLevel_e[k], &noise_e); - } - - - - /* - Apply calculated gains and adaptive noise - */ - - /* assembleHfSignals() */ - { - int scale_change, sc_change; - FIXP_SGL smooth_ratio; - int filtBufferNoiseShift=0; - - /* Initialize smoothing buffers with the first valid values */ - if (h_sbr_cal_env->startUp) - { - if (!useLP) { - h_sbr_cal_env->filtBufferNoise_e = noise_e; - - FDKmemcpy(h_sbr_cal_env->filtBuffer_e, pNrgs->nrgGain_e, noSubbands*sizeof(SCHAR)); - FDKmemcpy(h_sbr_cal_env->filtBufferNoise, pNrgs->noiseLevel, noSubbands*sizeof(FIXP_DBL)); - FDKmemcpy(h_sbr_cal_env->filtBuffer, pNrgs->nrgGain, noSubbands*sizeof(FIXP_DBL)); - - } - h_sbr_cal_env->startUp = 0; - } - - if (!useLP) { - - equalizeFiltBufferExp(h_sbr_cal_env->filtBuffer, /* buffered */ - h_sbr_cal_env->filtBuffer_e, /* buffered */ - pNrgs->nrgGain, /* current */ - pNrgs->nrgGain_e, /* current */ - noSubbands); - - /* Adapt exponent of buffered noise levels to the current exponent - so they can easily be smoothed */ - if((h_sbr_cal_env->filtBufferNoise_e - noise_e)>=0) { - int shift = fixMin(DFRACT_BITS-1,(int)(h_sbr_cal_env->filtBufferNoise_e - noise_e)); - for (k=0; kfiltBufferNoise[k] <<= shift; - } - else { - int shift = fixMin(DFRACT_BITS-1,-(int)(h_sbr_cal_env->filtBufferNoise_e - noise_e)); - for (k=0; kfiltBufferNoise[k] >>= shift; - } - - h_sbr_cal_env->filtBufferNoise_e = noise_e; - } - - /* find best scaling! */ - scale_change = -(DFRACT_BITS-1); - for(k=0;knrgGain_e[k]); - } - sc_change = (start_posnrgGain_e[k] + (sc_change-1); - pNrgs->nrgGain[k] >>= sc; - pNrgs->nrgGain_e[k] += sc; - } - - if (!useLP) { - for(k=0;kfiltBuffer_e[k] + (sc_change-1); - h_sbr_cal_env->filtBuffer[k] >>= sc; - } - } - - for (j = start_pos; j < stop_pos; j++) - { - /* This timeslot is located within the first part of the processing buffer - and will be fed into the QMF-synthesis for the current frame. - adj_e - input_e - This timeslot will not yet be fed into the QMF so we do not care - about the adj_e. - sc_change = final_e - input_e - */ - if ( (j==no_cols) && (start_posfiltBufferNoise[k] will be applied in function adjustTimeSlotHQ() */ - if (shift>=0) { - shift = fixMin(DFRACT_BITS-1,shift); - for (k=0; knrgSine[k] <<= shift; - pNrgs->noiseLevel[k] <<= shift; - /* - if (!useLP) - h_sbr_cal_env->filtBufferNoise[k] <<= shift; - */ - } - } - else { - shift = fixMin(DFRACT_BITS-1,-shift); - for (k=0; knrgSine[k] >>= shift; - pNrgs->noiseLevel[k] >>= shift; - /* - if (!useLP) - h_sbr_cal_env->filtBufferNoise[k] >>= shift; - */ - } - } - - /* update noise scaling */ - noise_e = final_e; - if (!useLP) - h_sbr_cal_env->filtBufferNoise_e = noise_e; /* scaling value unused! */ - - /* update gain buffer*/ - sc_change -= (final_e - input_e); - - if (sc_change<0) { - for(k=0;knrgGain[k] >>= -sc_change; - pNrgs->nrgGain_e[k] += -sc_change; - } - if (!useLP) { - for(k=0;kfiltBuffer[k] >>= -sc_change; - } - } - } else { - scale_change+=sc_change; - } - - } // if - - if (!useLP) { - - /* Prevent the smoothing filter from running on constant levels */ - if (j-start_pos < smooth_length) - smooth_ratio = FDK_sbrDecoder_sbr_smoothFilter[j-start_pos]; - - else - smooth_ratio = FL2FXCONST_SGL(0.0f); - - adjustTimeSlotHQ(&analysBufferReal[j][lowSubband], - &analysBufferImag[j][lowSubband], - h_sbr_cal_env, - pNrgs, - lowSubband, - noSubbands, - scale_change, - smooth_ratio, - noNoiseFlag, - filtBufferNoiseShift); - } - else - { - adjustTimeSlotLC(&analysBufferReal[j][lowSubband], - pNrgs, - &h_sbr_cal_env->harmIndex, - lowSubband, - noSubbands, - scale_change, - noNoiseFlag, - &h_sbr_cal_env->phaseIndex, - (flags & SBRDEC_ELD_GRID)); - } - } // for - - if (!useLP) { - /* Update time-smoothing-buffers for gains and noise levels - The gains and the noise values of the current envelope are copied into the buffer. - This has to be done at the end of each envelope as the values are required for - a smooth transition to the next envelope. */ - FDKmemcpy(h_sbr_cal_env->filtBuffer, pNrgs->nrgGain, noSubbands*sizeof(FIXP_DBL)); - FDKmemcpy(h_sbr_cal_env->filtBuffer_e, pNrgs->nrgGain_e, noSubbands*sizeof(SCHAR)); - FDKmemcpy(h_sbr_cal_env->filtBufferNoise, pNrgs->noiseLevel, noSubbands*sizeof(FIXP_DBL)); - } - - } - C_ALLOC_SCRATCH_END(pNrgs, ENV_CALC_NRGS, 1); - } - - /* Rescale output samples */ - { - FIXP_DBL maxVal; - int ov_reserve, reserve; - - /* Determine headroom in old adjusted samples */ - maxVal = maxSubbandSample( analysBufferReal, - (useLP) ? NULL : analysBufferImag, - lowSubband, - highSubband, - 0, - first_start); - - ov_reserve = fNorm(maxVal); - - /* Determine headroom in new adjusted samples */ - maxVal = maxSubbandSample( analysBufferReal, - (useLP) ? NULL : analysBufferImag, - lowSubband, - highSubband, - first_start, - no_cols); - - reserve = fNorm(maxVal); - - /* Determine common output exponent */ - if (ov_adj_e - ov_reserve > adj_e - reserve ) /* set output_e to the maximum */ - output_e = ov_adj_e - ov_reserve; - else - output_e = adj_e - reserve; - - /* Rescale old samples */ - rescaleSubbandSamples( analysBufferReal, - (useLP) ? NULL : analysBufferImag, - lowSubband, highSubband, - 0, first_start, - ov_adj_e - output_e); - - /* Rescale new samples */ - rescaleSubbandSamples( analysBufferReal, - (useLP) ? NULL : analysBufferImag, - lowSubband, highSubband, - first_start, no_cols, - adj_e - output_e); - } - - /* Update hb_scale */ - sbrScaleFactor->hb_scale = EXP2SCALE(output_e); - - /* Save the current final exponent for the next frame: */ - sbrScaleFactor->ov_hb_scale = EXP2SCALE(final_e); - - - /* We need to remeber to the next frame that the transient - will occur in the first envelope (if tranEnv == nEnvelopes). */ - if(hFrameData->frameInfo.tranEnv == hFrameData->frameInfo.nEnvelopes) - h_sbr_cal_env->prevTranEnv = 0; - else - h_sbr_cal_env->prevTranEnv = -1; - -} - - -/*! - \brief Create envelope instance - - Must be called once for each channel before calculateSbrEnvelope() can be used. - - \return errorCode, 0 if successful -*/ -SBR_ERROR -createSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hs, /*!< pointer to envelope instance */ - HANDLE_SBR_HEADER_DATA hHeaderData, /*!< static SBR control data, initialized with defaults */ - const int chan, /*!< Channel for which to assign buffers */ - const UINT flags) -{ - SBR_ERROR err = SBRDEC_OK; - int i; - - /* Clear previous missing harmonics flags */ - for (i=0; i<(MAX_FREQ_COEFFS+15)>>4; i++) { - hs->harmFlagsPrev[i] = 0; - } - hs->harmIndex = 0; - - /* - Setup pointers for time smoothing. - The buffer itself will be initialized later triggered by the startUp-flag. - */ - hs->prevTranEnv = -1; - - - /* initialization */ - resetSbrEnvelopeCalc(hs); - - if (chan==0) { /* do this only once */ - err = resetFreqBandTables(hHeaderData, flags); - } - - return err; -} - -/*! - \brief Create envelope instance - - Must be called once for each channel before calculateSbrEnvelope() can be used. - - \return errorCode, 0 if successful -*/ -int -deleteSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hs) -{ - return 0; -} - - -/*! - \brief Reset envelope instance - - This function must be called for each channel on a change of configuration. - Note that resetFreqBandTables should also be called in this case. - - \return errorCode, 0 if successful -*/ -void -resetSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv) /*!< pointer to envelope instance */ -{ - hCalEnv->phaseIndex = 0; - - /* Noise exponent needs to be reset because the output exponent for the next frame depends on it */ - hCalEnv->filtBufferNoise_e = 0; - - hCalEnv->startUp = 1; -} - - -/*! - \brief Equalize exponents of the buffered gain values and the new ones - - After equalization of exponents, the FIR-filter addition for smoothing - can be performed. - This function is called once for each envelope before adjusting. -*/ -/*static*/ void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, /*!< bufferd gains */ - SCHAR *filtBuffer_e, /*!< exponents of bufferd gains */ - FIXP_DBL *nrgGain, /*!< gains for current envelope */ - SCHAR *nrgGain_e, /*!< exponents of gains for current envelope */ - int subbands) /*!< Number of QMF subbands */ -{ - int band; - int diff; - - for (band=0; band0) { - filtBuffer[band] >>= diff; /* Compensate for the scale change by shifting the mantissa. */ - filtBuffer_e[band] += diff; /* New gain is bigger, use its exponent */ - } - else if (diff<0) { - /* The buffered gains seem to be larger, but maybe there - are some unused bits left in the mantissa */ - - int reserve = CntLeadingZeros(fixp_abs(filtBuffer[band]))-1; - - if ((-diff) <= reserve) { - /* There is enough space in the buffered mantissa so - that we can take the new exponent as common. - */ - filtBuffer[band] <<= (-diff); - filtBuffer_e[band] += diff; /* becomes equal to *ptrNewExp */ - } - else { - filtBuffer[band] <<= reserve; /* Shift the mantissa as far as possible: */ - filtBuffer_e[band] -= reserve; /* Compensate in the exponent: */ - - /* For the remaining difference, change the new gain value */ - diff = fixMin(-(reserve + diff),DFRACT_BITS-1); - nrgGain[band] >>= diff; - nrgGain_e[band] += diff; - } - } - } -} - -/*! - \brief Shift left the mantissas of all subband samples - in the giventime and frequency range by the specified number of bits. - - This function is used to rescale the audio data in the overlap buffer - which has already been envelope adjusted with the last frame. -*/ -void rescaleSubbandSamples(FIXP_DBL ** re, /*!< Real part of input and output subband samples */ - FIXP_DBL ** im, /*!< Imaginary part of input and output subband samples */ - int lowSubband, /*!< Begin of frequency range to process */ - int highSubband, /*!< End of frequency range to process */ - int start_pos, /*!< Begin of time rage (QMF-timeslot) */ - int next_pos, /*!< End of time rage (QMF-timeslot) */ - int shift) /*!< number of bits to shift */ -{ - int width = highSubband-lowSubband; - - if ( (width > 0) && (shift!=0) ) { - if (im!=NULL) { - for (int l=start_pos; l 0 ) { - if (im!=NULL) - { - for (int l=start_pos; l>(DFRACT_BITS-1))); - maxVal |= (FIXP_DBL)((LONG)(tmp2)^((LONG)tmp2>>(DFRACT_BITS-1))); - } while(--k!=0); -#endif - } - } else - { - for (int l=start_pos; l>(DFRACT_BITS-1))); - }while(--k!=0); - } - } - } - - return(maxVal); -} - -#define SHIFT_BEFORE_SQUARE (3) /* (7/2) */ -/*!< - If the accumulator does not provide enough overflow bits or - does not provide a high dynamic range, the below energy calculation - requires an additional shift operation for each sample. - On the other hand, doing the shift allows using a single-precision - multiplication for the square (at least 16bit x 16bit). - For even values of OVRFLW_BITS (0, 2, 4, 6), saturated arithmetic - is required for the energy accumulation. - Theoretically, the sample-squares can sum up to a value of 76, - requiring 7 overflow bits. However since such situations are *very* - rare, accu can be limited to 64. - In case native saturated arithmetic is not available, overflows - can be prevented by replacing the above #define by - #define SHIFT_BEFORE_SQUARE ((8 - OVRFLW_BITS) / 2) - which will result in slightly reduced accuracy. -*/ - -/*! - \brief Estimates the mean energy of each filter-bank channel for the - duration of the current envelope - - This function is used when interpolFreq is true. -*/ -/*static*/ void calcNrgPerSubband(FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */ - FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */ - int lowSubband, /*!< Begin of the SBR frequency range */ - int highSubband, /*!< High end of the SBR frequency range */ - int start_pos, /*!< First QMF-slot of current envelope */ - int next_pos, /*!< Last QMF-slot of current envelope + 1 */ - SCHAR frameExp, /*!< Common exponent for all input samples */ - FIXP_DBL *nrgEst, /*!< resulting Energy (0..1) */ - SCHAR *nrgEst_e ) /*!< Exponent of resulting Energy */ -{ - FIXP_SGL invWidth; - SCHAR preShift; - SCHAR shift; - FIXP_DBL sum; - int k,l; - - /* Divide by width of envelope later: */ - invWidth = FX_DBL2FX_SGL(GetInvInt(next_pos - start_pos)); - /* The common exponent needs to be doubled because all mantissas are squared: */ - frameExp = frameExp << 1; - - for (k=lowSubband; k>(DFRACT_BITS-1))); - bufferReal[l] = analysBufferReal[l][k]; - maxVal |= (FIXP_DBL)((LONG)(bufferReal[l])^((LONG)bufferReal[l]>>(DFRACT_BITS-1))); - } - } - else - { - for (l=start_pos;l>(DFRACT_BITS-1))); - } - } - - if (maxVal!=FL2FXCONST_DBL(0.f)) { - - - /* If the accu does not provide enough overflow bits, we cannot - shift the samples up to the limit. - Instead, keep up to 3 free bits in each sample, i.e. up to - 6 bits after calculation of square. - Please note the comment on saturated arithmetic above! - */ - FIXP_DBL accu = FL2FXCONST_DBL(0.0f); - preShift = CntLeadingZeros(maxVal)-1; - preShift -= SHIFT_BEFORE_SQUARE; - - if (preShift>=0) { - if (analysBufferImag!=NULL) { - for (l=start_pos; l> (int)negpreShift; - FIXP_DBL temp2 = bufferImag[l] >> (int)negpreShift; - accu = fPow2AddDiv2(accu, temp1); - accu = fPow2AddDiv2(accu, temp2); - } - } else - { - for (l=start_pos; l> (int)negpreShift; - accu = fPow2AddDiv2(accu, temp); - } - } - } - accu <<= 1; - - /* Convert double precision to Mantissa/Exponent: */ - shift = fNorm(accu); - sum = accu << (int)shift; - - /* Divide by width of envelope and apply frame scale: */ - *nrgEst++ = fMult(sum, invWidth); - shift += 2 * preShift; - if (analysBufferImag!=NULL) - *nrgEst_e++ = frameExp - shift; - else - *nrgEst_e++ = frameExp - shift + 1; /* +1 due to missing imag. part */ - } /* maxVal!=0 */ - else { - - /* Prevent a zero-mantissa-number from being misinterpreted - due to its exponent. */ - *nrgEst++ = FL2FXCONST_DBL(0.0f); - *nrgEst_e++ = 0; - } - } -} - -/*! - \brief Estimates the mean energy of each Scale factor band for the - duration of the current envelope. - - This function is used when interpolFreq is false. -*/ -/*static*/ void calcNrgPerSfb(FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */ - FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */ - int nSfb, /*!< Number of scale factor bands */ - UCHAR *freqBandTable, /*!< First Subband for each Sfb */ - int start_pos, /*!< First QMF-slot of current envelope */ - int next_pos, /*!< Last QMF-slot of current envelope + 1 */ - SCHAR input_e, /*!< Common exponent for all input samples */ - FIXP_DBL *nrgEst, /*!< resulting Energy (0..1) */ - SCHAR *nrgEst_e ) /*!< Exponent of resulting Energy */ -{ - FIXP_SGL invWidth; - FIXP_DBL temp; - SCHAR preShift; - SCHAR shift, sum_e; - FIXP_DBL sum; - - int j,k,l,li,ui; - FIXP_DBL sumAll, sumLine; /* Single precision would be sufficient, - but overflow bits are required for accumulation */ - - /* Divide by width of envelope later: */ - invWidth = FX_DBL2FX_SGL(GetInvInt(next_pos - start_pos)); - /* The common exponent needs to be doubled because all mantissas are squared: */ - input_e = input_e << 1; - - for(j=0; j=0) { - for (l=start_pos; l> -(int)preShift; - sumLine += fPow2Div2(temp); - temp = analysBufferImag[l][k] >> -(int)preShift; - sumLine += fPow2Div2(temp); - } - } - } else - { - if (preShift>=0) { - for (l=start_pos; l> -(int)preShift; - sumLine += fPow2Div2(temp); - } - } - } - - /* The number of QMF-channels per SBR bands may be up to 15. - Shift right to avoid overflows in sum over all channels. */ - sumLine = sumLine >> (4-1); - sumAll += sumLine; - } - - /* Convert double precision to Mantissa/Exponent: */ - shift = fNorm(sumAll); - sum = sumAll << (int)shift; - - /* Divide by width of envelope: */ - sum = fMult(sum,invWidth); - - /* Divide by width of Sfb: */ - sum = fMult(sum, FX_DBL2FX_SGL(GetInvInt(ui-li))); - - /* Set all Subband energies in the Sfb to the average energy: */ - if (analysBufferImag!=NULL) - sum_e = input_e + 4 - shift; /* -4 to compensate right-shift */ - else - sum_e = input_e + 4 + 1 - shift; /* -4 to compensate right-shift; +1 due to missing imag. part */ - - sum_e -= 2 * preShift; - } /* maxVal!=0 */ - else { - - /* Prevent a zero-mantissa-number from being misinterpreted - due to its exponent. */ - sum = FL2FXCONST_DBL(0.0f); - sum_e = 0; - } - - for (k=li; knrgEst[i]; /*!< Energy in transposed signal */ - SCHAR nrgEst_e = nrgs->nrgEst_e[i]; /*!< Energy in transposed signal (exponent) */ - FIXP_DBL *ptrNrgGain = &nrgs->nrgGain[i]; /*!< Resulting energy gain */ - SCHAR *ptrNrgGain_e = &nrgs->nrgGain_e[i]; /*!< Resulting energy gain (exponent) */ - FIXP_DBL *ptrNoiseLevel = &nrgs->noiseLevel[i]; /*!< Resulting absolute noise energy */ - SCHAR *ptrNoiseLevel_e = &nrgs->noiseLevel_e[i]; /*!< Resulting absolute noise energy (exponent) */ - FIXP_DBL *ptrNrgSine = &nrgs->nrgSine[i]; /*!< Additional sine energy */ - SCHAR *ptrNrgSine_e = &nrgs->nrgSine_e[i]; /*!< Additional sine energy (exponent) */ - - FIXP_DBL a, b, c; - SCHAR a_e, b_e, c_e; - - /* - This addition of 1 prevents divisions by zero in the reference code. - For very small energies in nrgEst, it prevents the gains from becoming - very high which could cause some trouble due to the smoothing. - */ - b_e = (int)(nrgEst_e - 1); - if (b_e>=0) { - nrgEst = (FL2FXCONST_DBL(0.5f) >> (INT)fixMin(b_e+1,DFRACT_BITS-1)) + (nrgEst >> 1); - nrgEst_e += 1; /* shift by 1 bit to avoid overflow */ - - } else { - nrgEst = (nrgEst >> (INT)(fixMin(-b_e+1,DFRACT_BITS-1))) + (FL2FXCONST_DBL(0.5f) >> 1); - nrgEst_e = 2; /* shift by 1 bit to avoid overflow */ - } - - /* A = NrgRef * TmpNoise */ - a = fMult(nrgRef,tmpNoise); - a_e = nrgRef_e + tmpNoise_e; - - /* B = 1 + TmpNoise */ - b_e = (int)(tmpNoise_e - 1); - if (b_e>=0) { - b = (FL2FXCONST_DBL(0.5f) >> (INT)fixMin(b_e+1,DFRACT_BITS-1)) + (tmpNoise >> 1); - b_e = tmpNoise_e + 1; /* shift by 1 bit to avoid overflow */ - } else { - b = (tmpNoise >> (INT)(fixMin(-b_e+1,DFRACT_BITS-1))) + (FL2FXCONST_DBL(0.5f) >> 1); - b_e = 2; /* shift by 1 bit to avoid overflow */ - } - - /* noiseLevel = A / B = (NrgRef * TmpNoise) / (1 + TmpNoise) */ - FDK_divide_MantExp( a, a_e, - b, b_e, - ptrNoiseLevel, ptrNoiseLevel_e); - - if (sinePresentFlag) { - - /* C = (1 + TmpNoise) * NrgEst */ - c = fMult(b,nrgEst); - c_e = b_e + nrgEst_e; - - /* gain = A / C = (NrgRef * TmpNoise) / (1 + TmpNoise) * NrgEst */ - FDK_divide_MantExp( a, a_e, - c, c_e, - ptrNrgGain, ptrNrgGain_e); - - if (sineMapped) { - - /* sineLevel = nrgRef/ (1 + TmpNoise) */ - FDK_divide_MantExp( nrgRef, nrgRef_e, - b, b_e, - ptrNrgSine, ptrNrgSine_e); - } - } - else { - if (noNoiseFlag) { - /* B = NrgEst */ - b = nrgEst; - b_e = nrgEst_e; - } - else { - /* B = NrgEst * (1 + TmpNoise) */ - b = fMult(b,nrgEst); - b_e = b_e + nrgEst_e; - } - - - /* gain = nrgRef / B */ - FDK_divide_MantExp( nrgRef, nrgRef_e, - b, b_e, - ptrNrgGain, ptrNrgGain_e); - } -} - - -/*! - \brief Calculate "average gain" for the specified subband range. - - This is rather a gain of the average magnitude than the average - of gains! - The result is used as a relative limit for all gains within the - current "limiter band" (a certain frequency range). -*/ -/*static*/ void calcAvgGain(ENV_CALC_NRGS* nrgs, - int lowSubband, /*!< Begin of the limiter band */ - int highSubband, /*!< High end of the limiter band */ - FIXP_DBL *ptrSumRef, - SCHAR *ptrSumRef_e, - FIXP_DBL *ptrAvgGain, /*!< Resulting overall gain (mantissa) */ - SCHAR *ptrAvgGain_e) /*!< Resulting overall gain (exponent) */ -{ - FIXP_DBL *nrgRef = nrgs->nrgRef; /*!< Reference Energy according to envelope data */ - SCHAR *nrgRef_e = nrgs->nrgRef_e; /*!< Reference Energy according to envelope data (exponent) */ - FIXP_DBL *nrgEst = nrgs->nrgEst; /*!< Energy in transposed signal */ - SCHAR *nrgEst_e = nrgs->nrgEst_e; /*!< Energy in transposed signal (exponent) */ - - FIXP_DBL sumRef = 1; - FIXP_DBL sumEst = 1; - SCHAR sumRef_e = -FRACT_BITS; - SCHAR sumEst_e = -FRACT_BITS; - int k; - - for (k=lowSubband; knrgGain; /*!< Gains of current envelope */ - FIXP_DBL *pNoiseLevel = nrgs->noiseLevel; /*!< Noise levels of current envelope */ - FIXP_DBL *pSineLevel = nrgs->nrgSine; /*!< Sine levels */ - - int k; - int index = *ptrPhaseIndex; - UCHAR harmIndex = *ptrHarmIndex; - UCHAR freqInvFlag = (lowSubband & 1); - FIXP_DBL signalReal, sineLevel, sineLevelNext, sineLevelPrev; - int tone_count = 0; - int sineSign = 1; - - #define C1 ((FIXP_SGL)FL2FXCONST_SGL(2.f*0.00815f)) - #define C1_CLDFB ((FIXP_SGL)FL2FXCONST_SGL(2.f*0.16773f)) - - /* - First pass for k=0 pulled out of the loop: - */ - - index = (index + 1) & (SBR_NF_NO_RANDOM_VAL - 1); - - /* - The next multiplication constitutes the actual envelope adjustment - of the signal and should be carried out with full accuracy - (supplying #FRACT_BITS valid bits). - */ - signalReal = fMultDiv2(*ptrReal,*pGain++) << ((int)scale_change); - sineLevel = *pSineLevel++; - sineLevelNext = (noSubbands > 1) ? pSineLevel[0] : FL2FXCONST_DBL(0.0f); - - if (sineLevel!=FL2FXCONST_DBL(0.0f)) tone_count++; - - else if (!noNoiseFlag) - /* Add noisefloor to the amplified signal */ - signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4); - - if (fCldfb) { - - if (!(harmIndex&0x1)) { - /* harmIndex 0,2 */ - signalReal += (harmIndex&0x2) ? -sineLevel : sineLevel; - *ptrReal++ = signalReal; - } - else { - /* harmIndex 1,3 in combination with freqInvFlag */ - int shift = (int) (scale_change+1); - shift = (shift>=0) ? fixMin(DFRACT_BITS-1,shift) : fixMax(-(DFRACT_BITS-1),shift); - - FIXP_DBL tmp1 = scaleValue( fMultDiv2(C1_CLDFB, sineLevel), -shift ); - - FIXP_DBL tmp2 = fMultDiv2(C1_CLDFB, sineLevelNext); - - - /* save switch and compare operations and reduce to XOR statement */ - if ( ((harmIndex>>1)&0x1)^freqInvFlag) { - *(ptrReal-1) += tmp1; - signalReal -= tmp2; - } else { - *(ptrReal-1) -= tmp1; - signalReal += tmp2; - } - *ptrReal++ = signalReal; - freqInvFlag = !freqInvFlag; - } - - } else - { - if (!(harmIndex&0x1)) { - /* harmIndex 0,2 */ - signalReal += (harmIndex&0x2) ? -sineLevel : sineLevel; - *ptrReal++ = signalReal; - } - else { - /* harmIndex 1,3 in combination with freqInvFlag */ - int shift = (int) (scale_change+1); - shift = (shift>=0) ? fixMin(DFRACT_BITS-1,shift) : fixMax(-(DFRACT_BITS-1),shift); - - FIXP_DBL tmp1 = (shift>=0) ? ( fMultDiv2(C1, sineLevel) >> shift ) - : ( fMultDiv2(C1, sineLevel) << (-shift) ); - FIXP_DBL tmp2 = fMultDiv2(C1, sineLevelNext); - - - /* save switch and compare operations and reduce to XOR statement */ - if ( ((harmIndex>>1)&0x1)^freqInvFlag) { - *(ptrReal-1) += tmp1; - signalReal -= tmp2; - } else { - *(ptrReal-1) -= tmp1; - signalReal += tmp2; - } - *ptrReal++ = signalReal; - freqInvFlag = !freqInvFlag; - } - } - - pNoiseLevel++; - - if ( noSubbands > 2 ) { - if (!(harmIndex&0x1)) { - /* harmIndex 0,2 */ - if(!harmIndex) - { - sineSign = 0; - } - - for (k=noSubbands-2; k!=0; k--) { - FIXP_DBL sinelevel = *pSineLevel++; - index++; - if (((signalReal = (sineSign ? -sinelevel : sinelevel)) == FL2FXCONST_DBL(0.0f)) && !noNoiseFlag) - { - /* Add noisefloor to the amplified signal */ - index &= (SBR_NF_NO_RANDOM_VAL - 1); - signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4); - } - - /* The next multiplication constitutes the actual envelope adjustment of the signal. */ - signalReal += fMultDiv2(*ptrReal,*pGain++) << ((int)scale_change); - - pNoiseLevel++; - *ptrReal++ = signalReal; - } /* for ... */ - } - else { - /* harmIndex 1,3 in combination with freqInvFlag */ - if (harmIndex==1) freqInvFlag = !freqInvFlag; - - for (k=noSubbands-2; k!=0; k--) { - index++; - /* The next multiplication constitutes the actual envelope adjustment of the signal. */ - signalReal = fMultDiv2(*ptrReal,*pGain++) << ((int)scale_change); - - if (*pSineLevel++!=FL2FXCONST_DBL(0.0f)) tone_count++; - else if (!noNoiseFlag) { - /* Add noisefloor to the amplified signal */ - index &= (SBR_NF_NO_RANDOM_VAL - 1); - signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4); - } - - pNoiseLevel++; - - if (tone_count <= 16) { - FIXP_DBL addSine = fMultDiv2((pSineLevel[-2] - pSineLevel[0]), C1); - signalReal += (freqInvFlag) ? (-addSine) : (addSine); - } - - *ptrReal++ = signalReal; - freqInvFlag = !freqInvFlag; - } /* for ... */ - } - } - - if (noSubbands > -1) { - index++; - /* The next multiplication constitutes the actual envelope adjustment of the signal. */ - signalReal = fMultDiv2(*ptrReal,*pGain) << ((int)scale_change); - sineLevelPrev = fMultDiv2(pSineLevel[-1],FL2FX_SGL(0.0163f)); - sineLevel = pSineLevel[0]; - - if (pSineLevel[0]!=FL2FXCONST_DBL(0.0f)) tone_count++; - else if (!noNoiseFlag) { - /* Add noisefloor to the amplified signal */ - index &= (SBR_NF_NO_RANDOM_VAL - 1); - signalReal = signalReal + (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4); - } - - if (!(harmIndex&0x1)) { - /* harmIndex 0,2 */ - *ptrReal = signalReal + ( (sineSign) ? -sineLevel : sineLevel); - } - else { - /* harmIndex 1,3 in combination with freqInvFlag */ - if(tone_count <= 16){ - if (freqInvFlag) { - *ptrReal++ = signalReal - sineLevelPrev; - if (noSubbands + lowSubband < 63) - *ptrReal = *ptrReal + fMultDiv2(C1, sineLevel); - } - else { - *ptrReal++ = signalReal + sineLevelPrev; - if (noSubbands + lowSubband < 63) - *ptrReal = *ptrReal - fMultDiv2(C1, sineLevel); - } - } - else *ptrReal = signalReal; - } - } - *ptrHarmIndex = (harmIndex + 1) & 3; - *ptrPhaseIndex = index & (SBR_NF_NO_RANDOM_VAL - 1); -} -void adjustTimeSlotHQ(FIXP_DBL *RESTRICT ptrReal, /*!< Subband samples to be adjusted, real part */ - FIXP_DBL *RESTRICT ptrImag, /*!< Subband samples to be adjusted, imag part */ - HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, - ENV_CALC_NRGS* nrgs, - int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ - int noSubbands, /*!< Number of QMF subbands */ - int scale_change, /*!< Number of bits to shift adjusted samples */ - FIXP_SGL smooth_ratio, /*!< Impact of last envelope */ - int noNoiseFlag, /*!< Start index to random number array */ - int filtBufferNoiseShift) /*!< Shift factor of filtBufferNoise */ -{ - - FIXP_DBL *RESTRICT gain = nrgs->nrgGain; /*!< Gains of current envelope */ - FIXP_DBL *RESTRICT noiseLevel = nrgs->noiseLevel; /*!< Noise levels of current envelope */ - FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine; /*!< Sine levels */ - - FIXP_DBL *RESTRICT filtBuffer = h_sbr_cal_env->filtBuffer; /*!< Gains of last envelope */ - FIXP_DBL *RESTRICT filtBufferNoise = h_sbr_cal_env->filtBufferNoise; /*!< Noise levels of last envelope */ - UCHAR *RESTRICT ptrHarmIndex =&h_sbr_cal_env->harmIndex; /*!< Harmonic index */ - int *RESTRICT ptrPhaseIndex =&h_sbr_cal_env->phaseIndex; /*!< Start index to random number array */ - - int k; - FIXP_DBL signalReal, signalImag; - FIXP_DBL noiseReal, noiseImag; - FIXP_DBL smoothedGain, smoothedNoise; - FIXP_SGL direct_ratio = /*FL2FXCONST_SGL(1.0f) */ (FIXP_SGL)MAXVAL_SGL - smooth_ratio; - int index = *ptrPhaseIndex; - UCHAR harmIndex = *ptrHarmIndex; - register int freqInvFlag = (lowSubband & 1); - FIXP_DBL sineLevel; - int shift; - - *ptrPhaseIndex = (index+noSubbands) & (SBR_NF_NO_RANDOM_VAL - 1); - *ptrHarmIndex = (harmIndex + 1) & 3; - - /* - Possible optimization: - smooth_ratio and harmIndex stay constant during the loop. - It might be faster to include a separate loop in each path. - - the check for smooth_ratio is now outside the loop and the workload - of the whole function decreased by about 20 % - */ - - filtBufferNoiseShift += 1; /* due to later use of fMultDiv2 instead of fMult */ - if (filtBufferNoiseShift<0) - shift = fixMin(DFRACT_BITS-1,-filtBufferNoiseShift); - else - shift = fixMin(DFRACT_BITS-1, filtBufferNoiseShift); - - if (smooth_ratio > FL2FXCONST_SGL(0.0f)) { - - for (k=0; k>shift) + - fMult(direct_ratio,noiseLevel[k]); - } - else { - smoothedNoise = (fMultDiv2(smooth_ratio,filtBufferNoise[k])<>5) { - if (workLimiterBandTable[hiLimIndex] == workLimiterBandTable[loLimIndex]) { - workLimiterBandTable[hiLimIndex] = highSubband; - nBands--; - hiLimIndex++; - continue; - } - isPatchBorder[0] = isPatchBorder[1] = 0; - for (k = 0; k <= noPatches; k++) { - if (workLimiterBandTable[hiLimIndex] == patchBorders[k]) { - isPatchBorder[1] = 1; - break; - } - } - if (!isPatchBorder[1]) { - workLimiterBandTable[hiLimIndex] = highSubband; - nBands--; - hiLimIndex++; - continue; - } - for (k = 0; k <= noPatches; k++) { - if (workLimiterBandTable[loLimIndex] == patchBorders[k]) { - isPatchBorder[0] = 1; - break; - } - } - if (!isPatchBorder[0]) { - workLimiterBandTable[loLimIndex] = highSubband; - nBands--; - } - } - loLimIndex = hiLimIndex; - hiLimIndex++; - - } - shellsort(workLimiterBandTable, tempNoLim + 1); - - /* Test if algorithm exceeded maximum allowed limiterbands */ - if( nBands > MAX_NUM_LIMITERS || nBands <= 0) { - return SBRDEC_UNSUPPORTED_CONFIG; - } - - /* Copy limiterbands from working buffer into final destination */ - for (k = 0; k <= nBands; k++) { - limiterBandTable[k] = workLimiterBandTable[k]; - } - } - *noLimiterBands = nBands; - - return SBRDEC_OK; -} - -- cgit v1.2.3