aboutsummaryrefslogtreecommitdiffstats
path: root/fdk-aac/libSBRdec/src/env_extr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'fdk-aac/libSBRdec/src/env_extr.cpp')
-rw-r--r--fdk-aac/libSBRdec/src/env_extr.cpp1728
1 files changed, 1728 insertions, 0 deletions
diff --git a/fdk-aac/libSBRdec/src/env_extr.cpp b/fdk-aac/libSBRdec/src/env_extr.cpp
new file mode 100644
index 0000000..c72a7b6
--- /dev/null
+++ b/fdk-aac/libSBRdec/src/env_extr.cpp
@@ -0,0 +1,1728 @@
+/* -----------------------------------------------------------------------------
+Software License for The Fraunhofer FDK AAC Codec Library for Android
+
+© Copyright 1995 - 2018 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
+----------------------------------------------------------------------------- */
+
+/**************************** SBR decoder library ******************************
+
+ Author(s):
+
+ Description:
+
+*******************************************************************************/
+
+/*!
+ \file
+ \brief Envelope extraction
+ The functions provided by this module are mostly called by applySBR(). After
+ it is determined that there is valid SBR data, sbrGetHeaderData() might be
+ called if the current SBR data contains an \ref SBR_HEADER_ELEMENT as opposed
+ to a \ref SBR_STANDARD_ELEMENT. This function may return various error codes
+ as defined in #SBR_HEADER_STATUS . Most importantly it returns HEADER_RESET
+ when decoder settings need to be recalculated according to the SBR
+ specifications. In that case applySBR() will initiatite the required
+ re-configuration.
+
+ The header data is stored in a #SBR_HEADER_DATA structure.
+
+ The actual SBR data for the current frame is decoded into SBR_FRAME_DATA
+ stuctures by sbrGetChannelPairElement() [for stereo streams] and
+ sbrGetSingleChannelElement() [for mono streams]. There is no fractional
+ arithmetic involved.
+
+ Once the information is extracted, the data needs to be further prepared
+ before the actual decoding process. This is done in decodeSbrData().
+
+ \sa Description of buffer management in applySBR(). \ref documentationOverview
+
+ <h1>About the SBR data format:</h1>
+
+ Each frame includes SBR data (side chain information), and can be either the
+ \ref SBR_HEADER_ELEMENT or the \ref SBR_STANDARD_ELEMENT. Parts of the data
+ can be protected by a CRC checksum.
+
+ \anchor SBR_HEADER_ELEMENT <h2>The SBR_HEADER_ELEMENT</h2>
+
+ The SBR_HEADER_ELEMENT can be transmitted with every frame, however, it
+ typically is send every second or so. It contains fundamental information such
+ as SBR sampling frequency and frequency range as well as control signals that
+ do not require frequent changes. It also includes the \ref
+ SBR_STANDARD_ELEMENT.
+
+ Depending on the changes between the information in a current
+ SBR_HEADER_ELEMENT and the previous SBR_HEADER_ELEMENT, the SBR decoder might
+ need to be reset and reconfigured (e.g. new tables need to be calculated).
+
+ \anchor SBR_STANDARD_ELEMENT <h2>The SBR_STANDARD_ELEMENT</h2>
+
+ This data can be subdivided into "side info" and "raw data", where side info
+ is defined as signals needed to decode the raw data and some decoder tuning
+ signals. Raw data is referred to as PCM and Huffman coded envelope and noise
+ floor estimates. The side info also includes information about the
+ time-frequency grid for the current frame.
+
+ \sa \ref documentationOverview
+*/
+
+#include "env_extr.h"
+
+#include "sbr_ram.h"
+#include "sbr_rom.h"
+#include "huff_dec.h"
+
+#include "psbitdec.h"
+
+#define DRM_PARAMETRIC_STEREO 0
+#define EXTENSION_ID_PS_CODING 2
+
+static int extractPvcFrameInfo(
+ HANDLE_FDK_BITSTREAM hBs, /*!< bitbuffer handle */
+ HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
+ HANDLE_SBR_FRAME_DATA h_frame_data, /*!< pointer to memory where the
+ frame-info will be stored */
+ HANDLE_SBR_PREV_FRAME_DATA h_prev_frame_data, /*!< pointer to memory where
+ the previous frame-info
+ will be stored */
+ UCHAR pvc_mode_last, /**< PVC mode of last frame */
+ const UINT flags);
+static int extractFrameInfo(HANDLE_FDK_BITSTREAM hBs,
+ HANDLE_SBR_HEADER_DATA hHeaderData,
+ HANDLE_SBR_FRAME_DATA h_frame_data,
+ const UINT nrOfChannels, const UINT flags);
+
+static int sbrGetPvcEnvelope(HANDLE_SBR_HEADER_DATA hHeaderData,
+ HANDLE_SBR_FRAME_DATA h_frame_data,
+ HANDLE_FDK_BITSTREAM hBs, const UINT flags,
+ const UINT pvcMode);
+static int sbrGetEnvelope(HANDLE_SBR_HEADER_DATA hHeaderData,
+ HANDLE_SBR_FRAME_DATA h_frame_data,
+ HANDLE_FDK_BITSTREAM hBs, const UINT flags);
+
+static void sbrGetDirectionControlData(HANDLE_SBR_FRAME_DATA hFrameData,
+ HANDLE_FDK_BITSTREAM hBs,
+ const UINT flags, const int bs_pvc_mode);
+
+static void sbrGetNoiseFloorData(HANDLE_SBR_HEADER_DATA hHeaderData,
+ HANDLE_SBR_FRAME_DATA h_frame_data,
+ HANDLE_FDK_BITSTREAM hBs);
+
+static int checkFrameInfo(FRAME_INFO *pFrameInfo, int numberOfTimeSlots,
+ int overlap, int timeStep);
+
+/* Mapping to std samplerate table according to 14496-3 (4.6.18.2.6) */
+typedef struct SR_MAPPING {
+ UINT fsRangeLo; /* If fsRangeLo(n+1)>fs>=fsRangeLo(n), it will be mapped to...
+ */
+ UINT fsMapped; /* fsMapped. */
+} SR_MAPPING;
+
+static const SR_MAPPING stdSampleRatesMapping[] = {
+ {0, 8000}, {9391, 11025}, {11502, 12000}, {13856, 16000},
+ {18783, 22050}, {23004, 24000}, {27713, 32000}, {37566, 44100},
+ {46009, 48000}, {55426, 64000}, {75132, 88200}, {92017, 96000}};
+static const SR_MAPPING stdSampleRatesMappingUsac[] = {
+ {0, 16000}, {18783, 22050}, {23004, 24000}, {27713, 32000},
+ {35777, 40000}, {42000, 44100}, {46009, 48000}, {55426, 64000},
+ {75132, 88200}, {92017, 96000}};
+
+UINT sbrdec_mapToStdSampleRate(UINT fs,
+ UINT isUsac) /*!< Output sampling frequency */
+{
+ UINT fsMapped = fs, tableSize = 0;
+ const SR_MAPPING *mappingTable;
+ int i;
+
+ if (!isUsac) {
+ mappingTable = stdSampleRatesMapping;
+ tableSize = sizeof(stdSampleRatesMapping) / sizeof(SR_MAPPING);
+ } else {
+ mappingTable = stdSampleRatesMappingUsac;
+ tableSize = sizeof(stdSampleRatesMappingUsac) / sizeof(SR_MAPPING);
+ }
+
+ for (i = tableSize - 1; i >= 0; i--) {
+ if (fs >= mappingTable[i].fsRangeLo) {
+ fsMapped = mappingTable[i].fsMapped;
+ break;
+ }
+ }
+
+ return (fsMapped);
+}
+
+SBR_ERROR
+initHeaderData(HANDLE_SBR_HEADER_DATA hHeaderData, const int sampleRateIn,
+ const int sampleRateOut, const INT downscaleFactor,
+ const int samplesPerFrame, const UINT flags,
+ const int setDefaultHdr) {
+ HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData;
+ SBR_ERROR sbrError = SBRDEC_OK;
+ int numAnalysisBands;
+ int sampleRateProc;
+
+ if (!(flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50))) {
+ sampleRateProc =
+ sbrdec_mapToStdSampleRate(sampleRateOut * downscaleFactor, 0);
+ } else {
+ sampleRateProc = sampleRateOut * downscaleFactor;
+ }
+
+ if (sampleRateIn == sampleRateOut) {
+ hHeaderData->sbrProcSmplRate = sampleRateProc << 1;
+ numAnalysisBands = 32;
+ } else {
+ hHeaderData->sbrProcSmplRate = sampleRateProc;
+ if ((sampleRateOut >> 1) == sampleRateIn) {
+ /* 1:2 */
+ numAnalysisBands = 32;
+ } else if ((sampleRateOut >> 2) == sampleRateIn) {
+ /* 1:4 */
+ numAnalysisBands = 16;
+ } else if ((sampleRateOut * 3) >> 3 == (sampleRateIn * 8) >> 3) {
+ /* 3:8, 3/4 core frame length */
+ numAnalysisBands = 24;
+ } else {
+ sbrError = SBRDEC_UNSUPPORTED_CONFIG;
+ goto bail;
+ }
+ }
+ numAnalysisBands /= downscaleFactor;
+
+ if (setDefaultHdr) {
+ /* Fill in default values first */
+ hHeaderData->syncState = SBR_NOT_INITIALIZED;
+ hHeaderData->status = 0;
+ hHeaderData->frameErrorFlag = 0;
+
+ hHeaderData->bs_info.ampResolution = 1;
+ hHeaderData->bs_info.xover_band = 0;
+ hHeaderData->bs_info.sbr_preprocessing = 0;
+ hHeaderData->bs_info.pvc_mode = 0;
+
+ hHeaderData->bs_data.startFreq = 5;
+ hHeaderData->bs_data.stopFreq = 0;
+ hHeaderData->bs_data.freqScale =
+ 0; /* previously 2; for ELD reduced delay bitstreams
+ /samplerates initializing of the sbr decoder instance fails if
+ freqScale is set to 2 because no master table can be generated; in
+ ELD reduced delay bitstreams this value is always 0; gets overwritten
+ when header is read */
+ hHeaderData->bs_data.alterScale = 1;
+ hHeaderData->bs_data.noise_bands = 2;
+ hHeaderData->bs_data.limiterBands = 2;
+ hHeaderData->bs_data.limiterGains = 2;
+ hHeaderData->bs_data.interpolFreq = 1;
+ hHeaderData->bs_data.smoothingLength = 1;
+
+ /* Patch some entries */
+ if (sampleRateOut * downscaleFactor >= 96000) {
+ hHeaderData->bs_data.startFreq =
+ 4; /* having read these frequency values from bit stream before. */
+ hHeaderData->bs_data.stopFreq = 3;
+ } else if (sampleRateOut * downscaleFactor >
+ 24000) { /* Trigger an error if SBR is going to be processed
+ without */
+ hHeaderData->bs_data.startFreq =
+ 7; /* having read these frequency values from bit stream before. */
+ hHeaderData->bs_data.stopFreq = 3;
+ }
+ }
+
+ if ((sampleRateOut >> 2) == sampleRateIn) {
+ hHeaderData->timeStep = 4;
+ } else {
+ hHeaderData->timeStep = (flags & SBRDEC_ELD_GRID) ? 1 : 2;
+ }
+
+ /* Setup pointers to frequency band tables */
+ hFreq->freqBandTable[0] = hFreq->freqBandTableLo;
+ hFreq->freqBandTable[1] = hFreq->freqBandTableHi;
+
+ /* One SBR timeslot corresponds to the amount of samples equal to the amount
+ * of analysis bands, divided by the timestep. */
+ hHeaderData->numberTimeSlots =
+ (samplesPerFrame / numAnalysisBands) >> (hHeaderData->timeStep - 1);
+ if (hHeaderData->numberTimeSlots > (16)) {
+ sbrError = SBRDEC_UNSUPPORTED_CONFIG;
+ }
+
+ hHeaderData->numberOfAnalysisBands = numAnalysisBands;
+ if ((sampleRateOut >> 2) == sampleRateIn) {
+ hHeaderData->numberTimeSlots <<= 1;
+ }
+
+bail:
+ return sbrError;
+}
+
+/*!
+ \brief Initialize the SBR_PREV_FRAME_DATA struct
+*/
+void initSbrPrevFrameData(
+ HANDLE_SBR_PREV_FRAME_DATA
+ h_prev_data, /*!< handle to struct SBR_PREV_FRAME_DATA */
+ int timeSlots) /*!< Framelength in SBR-timeslots */
+{
+ int i;
+
+ /* Set previous energy and noise levels to 0 for the case
+ that decoding starts in the middle of a bitstream */
+ for (i = 0; i < MAX_FREQ_COEFFS; i++)
+ h_prev_data->sfb_nrg_prev[i] = (FIXP_DBL)0;
+ for (i = 0; i < MAX_NOISE_COEFFS; i++)
+ h_prev_data->prevNoiseLevel[i] = (FIXP_DBL)0;
+ for (i = 0; i < MAX_INVF_BANDS; i++) h_prev_data->sbr_invf_mode[i] = INVF_OFF;
+
+ h_prev_data->stopPos = timeSlots;
+ h_prev_data->coupling = COUPLING_OFF;
+ h_prev_data->ampRes = 0;
+
+ FDKmemclear(&h_prev_data->prevFrameInfo, sizeof(h_prev_data->prevFrameInfo));
+}
+
+/*!
+ \brief Read header data from bitstream
+
+ \return error status - 0 if ok
+*/
+SBR_HEADER_STATUS
+sbrGetHeaderData(HANDLE_SBR_HEADER_DATA hHeaderData, HANDLE_FDK_BITSTREAM hBs,
+ const UINT flags, const int fIsSbrData,
+ const UCHAR configMode) {
+ SBR_HEADER_DATA_BS *pBsData;
+ SBR_HEADER_DATA_BS lastHeader;
+ SBR_HEADER_DATA_BS_INFO lastInfo;
+ int headerExtra1 = 0, headerExtra2 = 0;
+
+ /* Read and discard new header in config change detection mode */
+ if (configMode & AC_CM_DET_CFG_CHANGE) {
+ if (!(flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC))) {
+ /* ampResolution */
+ FDKreadBits(hBs, 1);
+ }
+ /* startFreq, stopFreq */
+ FDKpushFor(hBs, 8);
+ if (!(flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC))) {
+ /* xover_band */
+ FDKreadBits(hBs, 3);
+ /* reserved bits */
+ FDKreadBits(hBs, 2);
+ }
+ headerExtra1 = FDKreadBit(hBs);
+ headerExtra2 = FDKreadBit(hBs);
+ FDKpushFor(hBs, 5 * headerExtra1 + 6 * headerExtra2);
+
+ return HEADER_OK;
+ }
+
+ /* Copy SBR bit stream header to temporary header */
+ lastHeader = hHeaderData->bs_data;
+ lastInfo = hHeaderData->bs_info;
+
+ /* Read new header from bitstream */
+ if ((flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC)) && !fIsSbrData) {
+ pBsData = &hHeaderData->bs_dflt;
+ } else {
+ pBsData = &hHeaderData->bs_data;
+ }
+
+ if (!(flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC))) {
+ hHeaderData->bs_info.ampResolution = FDKreadBits(hBs, 1);
+ }
+
+ pBsData->startFreq = FDKreadBits(hBs, 4);
+ pBsData->stopFreq = FDKreadBits(hBs, 4);
+
+ if (!(flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC))) {
+ hHeaderData->bs_info.xover_band = FDKreadBits(hBs, 3);
+ FDKreadBits(hBs, 2);
+ }
+
+ headerExtra1 = FDKreadBits(hBs, 1);
+ headerExtra2 = FDKreadBits(hBs, 1);
+
+ /* Handle extra header information */
+ if (headerExtra1) {
+ pBsData->freqScale = FDKreadBits(hBs, 2);
+ pBsData->alterScale = FDKreadBits(hBs, 1);
+ pBsData->noise_bands = FDKreadBits(hBs, 2);
+ } else {
+ pBsData->freqScale = 2;
+ pBsData->alterScale = 1;
+ pBsData->noise_bands = 2;
+ }
+
+ if (headerExtra2) {
+ pBsData->limiterBands = FDKreadBits(hBs, 2);
+ pBsData->limiterGains = FDKreadBits(hBs, 2);
+ pBsData->interpolFreq = FDKreadBits(hBs, 1);
+ pBsData->smoothingLength = FDKreadBits(hBs, 1);
+ } else {
+ pBsData->limiterBands = 2;
+ pBsData->limiterGains = 2;
+ pBsData->interpolFreq = 1;
+ pBsData->smoothingLength = 1;
+ }
+
+ /* Look for new settings. IEC 14496-3, 4.6.18.3.1 */
+ if (hHeaderData->syncState < SBR_HEADER ||
+ lastHeader.startFreq != pBsData->startFreq ||
+ lastHeader.stopFreq != pBsData->stopFreq ||
+ lastHeader.freqScale != pBsData->freqScale ||
+ lastHeader.alterScale != pBsData->alterScale ||
+ lastHeader.noise_bands != pBsData->noise_bands ||
+ lastInfo.xover_band != hHeaderData->bs_info.xover_band) {
+ return HEADER_RESET; /* New settings */
+ }
+
+ return HEADER_OK;
+}
+
+/*!
+ \brief Get missing harmonics parameters (only used for AAC+SBR)
+
+ \return error status - 0 if ok
+*/
+int sbrGetSyntheticCodedData(HANDLE_SBR_HEADER_DATA hHeaderData,
+ HANDLE_SBR_FRAME_DATA hFrameData,
+ HANDLE_FDK_BITSTREAM hBs, const UINT flags) {
+ int i, bitsRead = 0;
+
+ int add_harmonic_flag = FDKreadBits(hBs, 1);
+ bitsRead++;
+
+ if (add_harmonic_flag) {
+ int nSfb = hHeaderData->freqBandData.nSfb[1];
+ for (i = 0; i < ADD_HARMONICS_FLAGS_SIZE; i++) {
+ /* read maximum 32 bits and align them to the MSB */
+ int readBits = fMin(32, nSfb);
+ nSfb -= readBits;
+ if (readBits > 0) {
+ hFrameData->addHarmonics[i] = FDKreadBits(hBs, readBits)
+ << (32 - readBits);
+ } else {
+ hFrameData->addHarmonics[i] = 0;
+ }
+
+ bitsRead += readBits;
+ }
+ /* bs_pvc_mode = 0 for Rsvd50 */
+ if (flags & SBRDEC_SYNTAX_USAC) {
+ if (hHeaderData->bs_info.pvc_mode) {
+ int bs_sinusoidal_position = 31;
+ if (FDKreadBit(hBs) /* bs_sinusoidal_position_flag */) {
+ bs_sinusoidal_position = FDKreadBits(hBs, 5);
+ }
+ hFrameData->sinusoidal_position = bs_sinusoidal_position;
+ }
+ }
+ } else {
+ for (i = 0; i < ADD_HARMONICS_FLAGS_SIZE; i++)
+ hFrameData->addHarmonics[i] = 0;
+ }
+
+ return (bitsRead);
+}
+
+/*!
+ \brief Reads extension data from the bitstream
+
+ The bitstream format allows up to 4 kinds of extended data element.
+ Extended data may contain several elements, each identified by a 2-bit-ID.
+ So far, no extended data elements are defined hence the first 2 parameters
+ are unused. The data should be skipped in order to update the number
+ of read bits for the consistency check in applySBR().
+*/
+static int extractExtendedData(
+ HANDLE_SBR_HEADER_DATA hHeaderData, /*!< handle to SBR header */
+ HANDLE_FDK_BITSTREAM hBs /*!< Handle to the bit buffer */
+ ,
+ HANDLE_PS_DEC hParametricStereoDec /*!< Parametric Stereo Decoder */
+) {
+ INT nBitsLeft;
+ int extended_data;
+ int i, frameOk = 1;
+
+ extended_data = FDKreadBits(hBs, 1);
+
+ if (extended_data) {
+ int cnt;
+ int bPsRead = 0;
+
+ cnt = FDKreadBits(hBs, 4);
+ if (cnt == (1 << 4) - 1) cnt += FDKreadBits(hBs, 8);
+
+ nBitsLeft = 8 * cnt;
+
+ /* sanity check for cnt */
+ if (nBitsLeft > (INT)FDKgetValidBits(hBs)) {
+ /* limit nBitsLeft */
+ nBitsLeft = (INT)FDKgetValidBits(hBs);
+ /* set frame error */
+ frameOk = 0;
+ }
+
+ while (nBitsLeft > 7) {
+ int extension_id = FDKreadBits(hBs, 2);
+ nBitsLeft -= 2;
+
+ switch (extension_id) {
+ case EXTENSION_ID_PS_CODING:
+
+ /* Read PS data from bitstream */
+
+ if (hParametricStereoDec != NULL) {
+ if (bPsRead &&
+ !hParametricStereoDec->bsData[hParametricStereoDec->bsReadSlot]
+ .mpeg.bPsHeaderValid) {
+ cnt = nBitsLeft >> 3; /* number of remaining bytes */
+ for (i = 0; i < cnt; i++) FDKreadBits(hBs, 8);
+ nBitsLeft -= cnt * 8;
+ } else {
+ nBitsLeft -=
+ (INT)ReadPsData(hParametricStereoDec, hBs, nBitsLeft);
+ bPsRead = 1;
+ }
+ }
+
+ /* parametric stereo detected, could set channelMode accordingly here
+ */
+ /* */
+ /* "The usage of this parametric stereo extension to HE-AAC is */
+ /* signalled implicitly in the bitstream. Hence, if an sbr_extension()
+ */
+ /* with bs_extension_id==EXTENSION_ID_PS is found in the SBR part of
+ */
+ /* the bitstream, a decoder supporting the combination of SBR and PS
+ */
+ /* shall operate the PS tool to generate a stereo output signal." */
+ /* source: ISO/IEC 14496-3:2001/FDAM 2:2004(E) */
+
+ break;
+
+ default:
+ cnt = nBitsLeft >> 3; /* number of remaining bytes */
+ for (i = 0; i < cnt; i++) FDKreadBits(hBs, 8);
+ nBitsLeft -= cnt * 8;
+ break;
+ }
+ }
+
+ if (nBitsLeft < 0) {
+ frameOk = 0;
+ goto bail;
+ } else {
+ /* Read fill bits for byte alignment */
+ FDKreadBits(hBs, nBitsLeft);
+ }
+ }
+
+bail:
+ return (frameOk);
+}
+
+/*!
+ \brief Read bitstream elements of a SBR channel element
+ \return SbrFrameOK
+*/
+int sbrGetChannelElement(HANDLE_SBR_HEADER_DATA hHeaderData,
+ HANDLE_SBR_FRAME_DATA hFrameDataLeft,
+ HANDLE_SBR_FRAME_DATA hFrameDataRight,
+ HANDLE_SBR_PREV_FRAME_DATA hFrameDataLeftPrev,
+ UCHAR pvc_mode_last, HANDLE_FDK_BITSTREAM hBs,
+ HANDLE_PS_DEC hParametricStereoDec, const UINT flags,
+ const int overlap) {
+ int i, bs_coupling = COUPLING_OFF;
+ const int nCh = (hFrameDataRight == NULL) ? 1 : 2;
+
+ if (!(flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50))) {
+ /* Reserved bits */
+ if (FDKreadBits(hBs, 1)) { /* bs_data_extra */
+ FDKreadBits(hBs, 4);
+ if ((flags & SBRDEC_SYNTAX_SCAL) || (nCh == 2)) {
+ FDKreadBits(hBs, 4);
+ }
+ }
+ }
+
+ if (nCh == 2) {
+ /* Read coupling flag */
+ bs_coupling = FDKreadBits(hBs, 1);
+ if (bs_coupling) {
+ hFrameDataLeft->coupling = COUPLING_LEVEL;
+ hFrameDataRight->coupling = COUPLING_BAL;
+ } else {
+ hFrameDataLeft->coupling = COUPLING_OFF;
+ hFrameDataRight->coupling = COUPLING_OFF;
+ }
+ } else {
+ if (flags & SBRDEC_SYNTAX_SCAL) {
+ FDKreadBits(hBs, 1); /* bs_coupling */
+ }
+ hFrameDataLeft->coupling = COUPLING_OFF;
+ }
+
+ if (flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) {
+ if (flags & SBRDEC_USAC_HARMONICSBR) {
+ hFrameDataLeft->sbrPatchingMode = FDKreadBit(hBs);
+ if (hFrameDataLeft->sbrPatchingMode == 0) {
+ hFrameDataLeft->sbrOversamplingFlag = FDKreadBit(hBs);
+ if (FDKreadBit(hBs)) { /* sbrPitchInBinsFlag */
+ hFrameDataLeft->sbrPitchInBins = FDKreadBits(hBs, 7);
+ } else {
+ hFrameDataLeft->sbrPitchInBins = 0;
+ }
+ } else {
+ hFrameDataLeft->sbrOversamplingFlag = 0;
+ hFrameDataLeft->sbrPitchInBins = 0;
+ }
+
+ if (nCh == 2) {
+ if (bs_coupling) {
+ hFrameDataRight->sbrPatchingMode = hFrameDataLeft->sbrPatchingMode;
+ hFrameDataRight->sbrOversamplingFlag =
+ hFrameDataLeft->sbrOversamplingFlag;
+ hFrameDataRight->sbrPitchInBins = hFrameDataLeft->sbrPitchInBins;
+ } else {
+ hFrameDataRight->sbrPatchingMode = FDKreadBit(hBs);
+ if (hFrameDataRight->sbrPatchingMode == 0) {
+ hFrameDataRight->sbrOversamplingFlag = FDKreadBit(hBs);
+ if (FDKreadBit(hBs)) { /* sbrPitchInBinsFlag */
+ hFrameDataRight->sbrPitchInBins = FDKreadBits(hBs, 7);
+ } else {
+ hFrameDataRight->sbrPitchInBins = 0;
+ }
+ } else {
+ hFrameDataRight->sbrOversamplingFlag = 0;
+ hFrameDataRight->sbrPitchInBins = 0;
+ }
+ }
+ }
+ } else {
+ if (nCh == 2) {
+ hFrameDataRight->sbrPatchingMode = 1;
+ hFrameDataRight->sbrOversamplingFlag = 0;
+ hFrameDataRight->sbrPitchInBins = 0;
+ }
+
+ hFrameDataLeft->sbrPatchingMode = 1;
+ hFrameDataLeft->sbrOversamplingFlag = 0;
+ hFrameDataLeft->sbrPitchInBins = 0;
+ }
+ } else {
+ if (nCh == 2) {
+ hFrameDataRight->sbrPatchingMode = 1;
+ hFrameDataRight->sbrOversamplingFlag = 0;
+ hFrameDataRight->sbrPitchInBins = 0;
+ }
+
+ hFrameDataLeft->sbrPatchingMode = 1;
+ hFrameDataLeft->sbrOversamplingFlag = 0;
+ hFrameDataLeft->sbrPitchInBins = 0;
+ }
+
+ /*
+ sbr_grid(): Grid control
+ */
+ if (hHeaderData->bs_info.pvc_mode) {
+ FDK_ASSERT(nCh == 1); /* PVC not possible for CPE */
+ if (!extractPvcFrameInfo(hBs, hHeaderData, hFrameDataLeft,
+ hFrameDataLeftPrev, pvc_mode_last, flags))
+ return 0;
+
+ if (!checkFrameInfo(&hFrameDataLeft->frameInfo,
+ hHeaderData->numberTimeSlots, overlap,
+ hHeaderData->timeStep))
+ return 0;
+ } else {
+ if (!extractFrameInfo(hBs, hHeaderData, hFrameDataLeft, 1, flags)) return 0;
+
+ if (!checkFrameInfo(&hFrameDataLeft->frameInfo,
+ hHeaderData->numberTimeSlots, overlap,
+ hHeaderData->timeStep))
+ return 0;
+ }
+ if (nCh == 2) {
+ if (hFrameDataLeft->coupling) {
+ FDKmemcpy(&hFrameDataRight->frameInfo, &hFrameDataLeft->frameInfo,
+ sizeof(FRAME_INFO));
+ hFrameDataRight->ampResolutionCurrentFrame =
+ hFrameDataLeft->ampResolutionCurrentFrame;
+ } else {
+ if (!extractFrameInfo(hBs, hHeaderData, hFrameDataRight, 2, flags))
+ return 0;
+
+ if (!checkFrameInfo(&hFrameDataRight->frameInfo,
+ hHeaderData->numberTimeSlots, overlap,
+ hHeaderData->timeStep))
+ return 0;
+ }
+ }
+
+ /*
+ sbr_dtdf(): Fetch domain vectors (time or frequency direction for
+ delta-coding)
+ */
+ sbrGetDirectionControlData(hFrameDataLeft, hBs, flags,
+ hHeaderData->bs_info.pvc_mode);
+ if (nCh == 2) {
+ sbrGetDirectionControlData(hFrameDataRight, hBs, flags, 0);
+ }
+
+ /* sbr_invf() */
+ for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) {
+ hFrameDataLeft->sbr_invf_mode[i] = (INVF_MODE)FDKreadBits(hBs, 2);
+ }
+ if (nCh == 2) {
+ if (hFrameDataLeft->coupling) {
+ for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) {
+ hFrameDataRight->sbr_invf_mode[i] = hFrameDataLeft->sbr_invf_mode[i];
+ }
+ } else {
+ for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) {
+ hFrameDataRight->sbr_invf_mode[i] = (INVF_MODE)FDKreadBits(hBs, 2);
+ }
+ }
+ }
+
+ if (nCh == 1) {
+ if (hHeaderData->bs_info.pvc_mode) {
+ if (!sbrGetPvcEnvelope(hHeaderData, hFrameDataLeft, hBs, flags,
+ hHeaderData->bs_info.pvc_mode))
+ return 0;
+ } else if (!sbrGetEnvelope(hHeaderData, hFrameDataLeft, hBs, flags))
+ return 0;
+
+ sbrGetNoiseFloorData(hHeaderData, hFrameDataLeft, hBs);
+ } else if (hFrameDataLeft->coupling) {
+ if (!sbrGetEnvelope(hHeaderData, hFrameDataLeft, hBs, flags)) {
+ return 0;
+ }
+
+ sbrGetNoiseFloorData(hHeaderData, hFrameDataLeft, hBs);
+
+ if (!sbrGetEnvelope(hHeaderData, hFrameDataRight, hBs, flags)) {
+ return 0;
+ }
+ sbrGetNoiseFloorData(hHeaderData, hFrameDataRight, hBs);
+ } else { /* nCh == 2 && no coupling */
+
+ if (!sbrGetEnvelope(hHeaderData, hFrameDataLeft, hBs, flags)) return 0;
+
+ if (!sbrGetEnvelope(hHeaderData, hFrameDataRight, hBs, flags)) return 0;
+
+ sbrGetNoiseFloorData(hHeaderData, hFrameDataLeft, hBs);
+
+ sbrGetNoiseFloorData(hHeaderData, hFrameDataRight, hBs);
+ }
+
+ sbrGetSyntheticCodedData(hHeaderData, hFrameDataLeft, hBs, flags);
+ if (nCh == 2) {
+ sbrGetSyntheticCodedData(hHeaderData, hFrameDataRight, hBs, flags);
+ }
+
+ if (!(flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50))) {
+ if (!extractExtendedData(hHeaderData, hBs, hParametricStereoDec)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/*!
+ \brief Read direction control data from bitstream
+*/
+void sbrGetDirectionControlData(
+ HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */
+ HANDLE_FDK_BITSTREAM hBs, /*!< handle to struct BIT_BUF */
+ const UINT flags, const int bs_pvc_mode)
+
+{
+ int i;
+ int indepFlag = 0;
+
+ if (flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) {
+ indepFlag = flags & SBRDEC_USAC_INDEP;
+ }
+
+ if (bs_pvc_mode == 0) {
+ i = 0;
+ if (indepFlag) {
+ h_frame_data->domain_vec[i++] = 0;
+ }
+ for (; i < h_frame_data->frameInfo.nEnvelopes; i++) {
+ h_frame_data->domain_vec[i] = FDKreadBits(hBs, 1);
+ }
+ }
+
+ i = 0;
+ if (indepFlag) {
+ h_frame_data->domain_vec_noise[i++] = 0;
+ }
+ for (; i < h_frame_data->frameInfo.nNoiseEnvelopes; i++) {
+ h_frame_data->domain_vec_noise[i] = FDKreadBits(hBs, 1);
+ }
+}
+
+/*!
+ \brief Read noise-floor-level data from bitstream
+*/
+void sbrGetNoiseFloorData(
+ HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
+ HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */
+ HANDLE_FDK_BITSTREAM hBs) /*!< handle to struct BIT_BUF */
+{
+ int i, j;
+ int delta;
+ COUPLING_MODE coupling;
+ int noNoiseBands = hHeaderData->freqBandData.nNfb;
+
+ Huffman hcb_noiseF;
+ Huffman hcb_noise;
+ int envDataTableCompFactor;
+
+ coupling = h_frame_data->coupling;
+
+ /*
+ Select huffman codebook depending on coupling mode
+ */
+ if (coupling == COUPLING_BAL) {
+ hcb_noise = (Huffman)&FDK_sbrDecoder_sbr_huffBook_NoiseBalance11T;
+ hcb_noiseF =
+ (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11F; /* "sbr_huffBook_NoiseBalance11F"
+ */
+ envDataTableCompFactor = 1;
+ } else {
+ hcb_noise = (Huffman)&FDK_sbrDecoder_sbr_huffBook_NoiseLevel11T;
+ hcb_noiseF =
+ (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel11F; /* "sbr_huffBook_NoiseLevel11F"
+ */
+ envDataTableCompFactor = 0;
+ }
+
+ /*
+ Read raw noise-envelope data
+ */
+ for (i = 0; i < h_frame_data->frameInfo.nNoiseEnvelopes; i++) {
+ if (h_frame_data->domain_vec_noise[i] == 0) {
+ if (coupling == COUPLING_BAL) {
+ h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands] =
+ (FIXP_SGL)(((int)FDKreadBits(hBs, 5)) << envDataTableCompFactor);
+ } else {
+ h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands] =
+ (FIXP_SGL)(int)FDKreadBits(hBs, 5);
+ }
+
+ for (j = 1; j < noNoiseBands; j++) {
+ delta = DecodeHuffmanCW(hcb_noiseF, hBs);
+ h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands + j] =
+ (FIXP_SGL)(delta << envDataTableCompFactor);
+ }
+ } else {
+ for (j = 0; j < noNoiseBands; j++) {
+ delta = DecodeHuffmanCW(hcb_noise, hBs);
+ h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands + j] =
+ (FIXP_SGL)(delta << envDataTableCompFactor);
+ }
+ }
+ }
+}
+
+/* ns = mapNsMode2ns[pvcMode-1][nsMode] */
+static const UCHAR mapNsMode2ns[2][2] = {
+ {16, 4}, /* pvcMode = 1 */
+ {12, 3} /* pvcMode = 2 */
+};
+
+static int sbrGetPvcEnvelope(
+ HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
+ HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */
+ HANDLE_FDK_BITSTREAM hBs, /*!< handle to struct BIT_BUF */
+ const UINT flags, const UINT pvcMode) {
+ int divMode, nsMode;
+ int indepFlag = flags & SBRDEC_USAC_INDEP;
+ UCHAR *pvcID = h_frame_data->pvcID;
+
+ divMode = FDKreadBits(hBs, PVC_DIVMODE_BITS);
+ nsMode = FDKreadBit(hBs);
+ FDK_ASSERT((pvcMode == 1) || (pvcMode == 2));
+ h_frame_data->ns = mapNsMode2ns[pvcMode - 1][nsMode];
+
+ if (divMode <= 3) {
+ int i, k = 1, sum_length = 0, reuse_pcvID;
+
+ /* special treatment for first time slot k=0 */
+ indepFlag ? (reuse_pcvID = 0) : (reuse_pcvID = FDKreadBit(hBs));
+ if (reuse_pcvID) {
+ pvcID[0] = hHeaderData->pvcIDprev;
+ } else {
+ pvcID[0] = FDKreadBits(hBs, PVC_PVCID_BITS);
+ }
+
+ /* other time slots k>0 */
+ for (i = 0; i < divMode; i++) {
+ int length, numBits = 4;
+
+ if (sum_length >= 13) {
+ numBits = 1;
+ } else if (sum_length >= 11) {
+ numBits = 2;
+ } else if (sum_length >= 7) {
+ numBits = 3;
+ }
+
+ length = FDKreadBits(hBs, numBits);
+ sum_length += length + 1;
+ if (sum_length >= PVC_NTIMESLOT) {
+ return 0; /* parse error */
+ }
+ for (; length--; k++) {
+ pvcID[k] = pvcID[k - 1];
+ }
+ pvcID[k++] = FDKreadBits(hBs, PVC_PVCID_BITS);
+ }
+ for (; k < 16; k++) {
+ pvcID[k] = pvcID[k - 1];
+ }
+ } else { /* divMode >= 4 */
+ int num_grid_info, fixed_length, grid_info, j, k = 0;
+
+ divMode -= 4;
+ num_grid_info = 2 << divMode;
+ fixed_length = 8 >> divMode;
+ FDK_ASSERT(num_grid_info * fixed_length == PVC_NTIMESLOT);
+
+ /* special treatment for first time slot k=0 */
+ indepFlag ? (grid_info = 1) : (grid_info = FDKreadBit(hBs));
+ if (grid_info) {
+ pvcID[k++] = FDKreadBits(hBs, PVC_PVCID_BITS);
+ } else {
+ pvcID[k++] = hHeaderData->pvcIDprev;
+ }
+ j = fixed_length - 1;
+ for (; j--; k++) {
+ pvcID[k] = pvcID[k - 1];
+ }
+ num_grid_info--;
+
+ /* other time slots k>0 */
+ for (; num_grid_info--;) {
+ j = fixed_length;
+ grid_info = FDKreadBit(hBs);
+ if (grid_info) {
+ pvcID[k++] = FDKreadBits(hBs, PVC_PVCID_BITS);
+ j--;
+ }
+ for (; j--; k++) {
+ pvcID[k] = pvcID[k - 1];
+ }
+ }
+ }
+
+ hHeaderData->pvcIDprev = pvcID[PVC_NTIMESLOT - 1];
+
+ /* usage of PVC excludes inter-TES tool */
+ h_frame_data->iTESactive = (UCHAR)0;
+
+ return 1;
+}
+/*!
+ \brief Read envelope data from bitstream
+*/
+static int sbrGetEnvelope(
+ HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
+ HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */
+ HANDLE_FDK_BITSTREAM hBs, /*!< handle to struct BIT_BUF */
+ const UINT flags) {
+ int i, j;
+ UCHAR no_band[MAX_ENVELOPES];
+ int delta = 0;
+ int offset = 0;
+ COUPLING_MODE coupling = h_frame_data->coupling;
+ int ampRes = hHeaderData->bs_info.ampResolution;
+ int nEnvelopes = h_frame_data->frameInfo.nEnvelopes;
+ int envDataTableCompFactor;
+ int start_bits, start_bits_balance;
+ Huffman hcb_t, hcb_f;
+
+ h_frame_data->nScaleFactors = 0;
+
+ if ((h_frame_data->frameInfo.frameClass == 0) && (nEnvelopes == 1)) {
+ if (flags & SBRDEC_ELD_GRID)
+ ampRes = h_frame_data->ampResolutionCurrentFrame;
+ else
+ ampRes = 0;
+ }
+ h_frame_data->ampResolutionCurrentFrame = ampRes;
+
+ /*
+ Set number of bits for first value depending on amplitude resolution
+ */
+ if (ampRes == 1) {
+ start_bits = 6;
+ start_bits_balance = 5;
+ } else {
+ start_bits = 7;
+ start_bits_balance = 6;
+ }
+
+ /*
+ Calculate number of values for each envelope and alltogether
+ */
+ for (i = 0; i < nEnvelopes; i++) {
+ no_band[i] =
+ hHeaderData->freqBandData.nSfb[h_frame_data->frameInfo.freqRes[i]];
+ h_frame_data->nScaleFactors += no_band[i];
+ }
+ if (h_frame_data->nScaleFactors > MAX_NUM_ENVELOPE_VALUES) return 0;
+
+ /*
+ Select Huffman codebook depending on coupling mode and amplitude resolution
+ */
+ if (coupling == COUPLING_BAL) {
+ envDataTableCompFactor = 1;
+ if (ampRes == 0) {
+ hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance10T;
+ hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance10F;
+ } else {
+ hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11T;
+ hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11F;
+ }
+ } else {
+ envDataTableCompFactor = 0;
+ if (ampRes == 0) {
+ hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel10T;
+ hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel10F;
+ } else {
+ hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel11T;
+ hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel11F;
+ }
+ }
+
+ h_frame_data->iTESactive = (UCHAR)0; /* disable inter-TES by default */
+ /*
+ Now read raw envelope data
+ */
+ for (j = 0, offset = 0; j < nEnvelopes; j++) {
+ if (h_frame_data->domain_vec[j] == 0) {
+ if (coupling == COUPLING_BAL) {
+ h_frame_data->iEnvelope[offset] =
+ (FIXP_SGL)(((int)FDKreadBits(hBs, start_bits_balance))
+ << envDataTableCompFactor);
+ } else {
+ h_frame_data->iEnvelope[offset] =
+ (FIXP_SGL)(int)FDKreadBits(hBs, start_bits);
+ }
+ }
+
+ for (i = (1 - h_frame_data->domain_vec[j]); i < no_band[j]; i++) {
+ if (h_frame_data->domain_vec[j] == 0) {
+ delta = DecodeHuffmanCW(hcb_f, hBs);
+ } else {
+ delta = DecodeHuffmanCW(hcb_t, hBs);
+ }
+
+ h_frame_data->iEnvelope[offset + i] =
+ (FIXP_SGL)(delta << envDataTableCompFactor);
+ }
+ if ((flags & SBRDEC_SYNTAX_USAC) && (flags & SBRDEC_USAC_ITES)) {
+ int bs_temp_shape = FDKreadBit(hBs);
+ FDK_ASSERT(j < 8);
+ h_frame_data->iTESactive |= (UCHAR)(bs_temp_shape << j);
+ if (bs_temp_shape) {
+ h_frame_data->interTempShapeMode[j] =
+ FDKread2Bits(hBs); /* bs_inter_temp_shape_mode */
+ } else {
+ h_frame_data->interTempShapeMode[j] = 0;
+ }
+ }
+ offset += no_band[j];
+ }
+
+#if ENV_EXP_FRACT
+ /* Convert from int to scaled fract (ENV_EXP_FRACT bits for the fractional
+ * part) */
+ for (i = 0; i < h_frame_data->nScaleFactors; i++) {
+ h_frame_data->iEnvelope[i] <<= ENV_EXP_FRACT;
+ }
+#endif
+
+ return 1;
+}
+
+/***************************************************************************/
+/*!
+ \brief Generates frame info for FIXFIXonly frame class used for low delay
+ version
+
+ \return zero for error, one for correct.
+ ****************************************************************************/
+static int generateFixFixOnly(FRAME_INFO *hSbrFrameInfo, int tranPosInternal,
+ int numberTimeSlots, const UINT flags) {
+ int nEnv, i, tranIdx;
+ const int *pTable;
+
+ switch (numberTimeSlots) {
+ case 8:
+ pTable = FDK_sbrDecoder_envelopeTable_8[tranPosInternal];
+ break;
+ case 15:
+ pTable = FDK_sbrDecoder_envelopeTable_15[tranPosInternal];
+ break;
+ case 16:
+ pTable = FDK_sbrDecoder_envelopeTable_16[tranPosInternal];
+ break;
+ default:
+ return 0;
+ }
+
+ /* look number of envelopes in table */
+ nEnv = pTable[0];
+ /* look up envelope distribution in table */
+ for (i = 1; i < nEnv; i++) hSbrFrameInfo->borders[i] = pTable[i + 2];
+ /* open and close frame border */
+ hSbrFrameInfo->borders[0] = 0;
+ hSbrFrameInfo->borders[nEnv] = numberTimeSlots;
+ hSbrFrameInfo->nEnvelopes = nEnv;
+
+ /* transient idx */
+ tranIdx = hSbrFrameInfo->tranEnv = pTable[1];
+
+ /* add noise floors */
+ hSbrFrameInfo->bordersNoise[0] = 0;
+ hSbrFrameInfo->bordersNoise[1] =
+ hSbrFrameInfo->borders[tranIdx ? tranIdx : 1];
+ hSbrFrameInfo->bordersNoise[2] = numberTimeSlots;
+ /* nEnv is always > 1, so nNoiseEnvelopes is always 2 (IEC 14496-3 4.6.19.3.2)
+ */
+ hSbrFrameInfo->nNoiseEnvelopes = 2;
+
+ return 1;
+}
+
+/*!
+ \brief Extracts LowDelaySBR control data from the bitstream.
+
+ \return zero for bitstream error, one for correct.
+*/
+static int extractLowDelayGrid(
+ HANDLE_FDK_BITSTREAM hBitBuf, /*!< bitbuffer handle */
+ HANDLE_SBR_HEADER_DATA hHeaderData,
+ HANDLE_SBR_FRAME_DATA
+ h_frame_data, /*!< contains the FRAME_INFO struct to be filled */
+ int timeSlots, const UINT flags) {
+ FRAME_INFO *pFrameInfo = &h_frame_data->frameInfo;
+ INT numberTimeSlots = hHeaderData->numberTimeSlots;
+ INT temp = 0, k;
+
+ /* FIXFIXonly framing case */
+ h_frame_data->frameInfo.frameClass = 0;
+
+ /* get the transient position from the bitstream */
+ switch (timeSlots) {
+ case 8:
+ /* 3bit transient position (temp={0;..;7}) */
+ temp = FDKreadBits(hBitBuf, 3);
+ break;
+
+ case 16:
+ case 15:
+ /* 4bit transient position (temp={0;..;15}) */
+ temp = FDKreadBits(hBitBuf, 4);
+ break;
+
+ default:
+ return 0;
+ }
+
+ /* For "case 15" only*/
+ if (temp >= timeSlots) {
+ return 0;
+ }
+
+ /* calculate borders according to the transient position */
+ if (!generateFixFixOnly(pFrameInfo, temp, numberTimeSlots, flags)) {
+ return 0;
+ }
+
+ /* decode freq res: */
+ for (k = 0; k < pFrameInfo->nEnvelopes; k++) {
+ pFrameInfo->freqRes[k] =
+ (UCHAR)FDKreadBits(hBitBuf, 1); /* f = F [1 bits] */
+ }
+
+ return 1;
+}
+
+/*!
+ \brief Extract the PVC frame information (structure FRAME_INFO) from the
+ bitstream \return Zero for bitstream error, one for correct.
+*/
+int extractPvcFrameInfo(
+ HANDLE_FDK_BITSTREAM hBs, /*!< bitbuffer handle */
+ HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
+ HANDLE_SBR_FRAME_DATA h_frame_data, /*!< pointer to memory where the
+ frame-info will be stored */
+ HANDLE_SBR_PREV_FRAME_DATA h_prev_frame_data, /*!< pointer to memory where
+ the previous frame-info
+ will be stored */
+ UCHAR pvc_mode_last, /**< PVC mode of last frame */
+ const UINT flags) {
+ FRAME_INFO *pFrameInfo = &h_frame_data->frameInfo;
+ FRAME_INFO *pPrevFrameInfo = &h_prev_frame_data->prevFrameInfo;
+ int bs_var_len_hf, bs_noise_position;
+ bs_noise_position = FDKreadBits(hBs, 4); /* SBR_PVC_NOISEPOSITION_BITS 4 */
+ bs_var_len_hf = FDKreadBit(hBs);
+ pFrameInfo->noisePosition = bs_noise_position;
+ pFrameInfo->tranEnv = -1;
+
+ /* Init for bs_noise_position == 0 in case a parse error is found below. */
+ pFrameInfo->nEnvelopes = 1;
+ pFrameInfo->nNoiseEnvelopes = 1;
+ pFrameInfo->freqRes[0] = 0;
+
+ if (bs_var_len_hf) { /* 1 or 3 Bits */
+ pFrameInfo->varLength = FDKreadBits(hBs, 2) + 1;
+ if (pFrameInfo->varLength > 3) {
+ pFrameInfo->varLength =
+ 0; /* assume bs_var_len_hf == 0 in case of error */
+ return 0; /* reserved value -> parse error */
+ }
+ } else {
+ pFrameInfo->varLength = 0;
+ }
+
+ if (bs_noise_position) {
+ pFrameInfo->nEnvelopes = 2;
+ pFrameInfo->nNoiseEnvelopes = 2;
+ FDKmemclear(pFrameInfo->freqRes, sizeof(pFrameInfo->freqRes));
+ }
+
+ /* frame border calculation */
+ if (hHeaderData->bs_info.pvc_mode > 0) {
+ /* See "7.5.1.4 HF adjustment of SBR envelope scalefactors" for reference.
+ */
+
+ FDK_ASSERT((pFrameInfo->nEnvelopes == 1) || (pFrameInfo->nEnvelopes == 2));
+
+ /* left timeborder-offset: use the timeborder of prev SBR frame */
+ if (pPrevFrameInfo->nEnvelopes > 0) {
+ pFrameInfo->borders[0] =
+ pPrevFrameInfo->borders[pPrevFrameInfo->nEnvelopes] - PVC_NTIMESLOT;
+ FDK_ASSERT(pFrameInfo->borders[0] <= 3);
+ } else {
+ pFrameInfo->borders[0] = 0;
+ }
+
+ /* right timeborder-offset: */
+ pFrameInfo->borders[pFrameInfo->nEnvelopes] = 16 + pFrameInfo->varLength;
+
+ if (pFrameInfo->nEnvelopes == 2) {
+ pFrameInfo->borders[1] = pFrameInfo->noisePosition;
+ }
+
+ /* Calculation of PVC time borders t_EPVC */
+ if (pvc_mode_last == 0) {
+ /* there was a legacy SBR frame before this frame => use bs_var_len' for
+ * first PVC timeslot */
+ pFrameInfo->pvcBorders[0] = pFrameInfo->borders[0];
+ } else {
+ pFrameInfo->pvcBorders[0] = 0;
+ }
+ if (pFrameInfo->nEnvelopes == 2) {
+ pFrameInfo->pvcBorders[1] = pFrameInfo->borders[1];
+ }
+ pFrameInfo->pvcBorders[pFrameInfo->nEnvelopes] = 16;
+
+ /* calculation of SBR noise-floor time-border vector: */
+ for (INT i = 0; i <= pFrameInfo->nNoiseEnvelopes; i++) {
+ pFrameInfo->bordersNoise[i] = pFrameInfo->borders[i];
+ }
+
+ pFrameInfo->tranEnv = -1; /* tranEnv not used */
+ }
+ return 1;
+}
+
+/*!
+ \brief Extract the frame information (structure FRAME_INFO) from the
+ bitstream \return Zero for bitstream error, one for correct.
+*/
+int extractFrameInfo(
+ HANDLE_FDK_BITSTREAM hBs, /*!< bitbuffer handle */
+ HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */
+ HANDLE_SBR_FRAME_DATA h_frame_data, /*!< pointer to memory where the
+ frame-info will be stored */
+ const UINT nrOfChannels, const UINT flags) {
+ FRAME_INFO *pFrameInfo = &h_frame_data->frameInfo;
+ int numberTimeSlots = hHeaderData->numberTimeSlots;
+ int pointer_bits = 0, nEnv = 0, b = 0, border, i, n = 0, k, p, aL, aR, nL, nR,
+ temp = 0, staticFreqRes;
+ UCHAR frameClass;
+
+ if (flags & SBRDEC_ELD_GRID) {
+ /* CODEC_AACLD (LD+SBR) only uses the normal 0 Grid for non-transient Frames
+ * and the LowDelayGrid for transient Frames */
+ frameClass = FDKreadBits(hBs, 1); /* frameClass = [1 bit] */
+ if (frameClass == 1) {
+ /* if frameClass == 1, extract LowDelaySbrGrid, otherwise extract normal
+ * SBR-Grid for FIXIFX */
+ /* extract the AACLD-Sbr-Grid */
+ pFrameInfo->frameClass = frameClass;
+ int err = 1;
+ err = extractLowDelayGrid(hBs, hHeaderData, h_frame_data, numberTimeSlots,
+ flags);
+ return err;
+ }
+ } else {
+ frameClass = FDKreadBits(hBs, 2); /* frameClass = C [2 bits] */
+ }
+
+ switch (frameClass) {
+ case 0:
+ temp = FDKreadBits(hBs, 2); /* E [2 bits ] */
+ nEnv = (int)(1 << temp); /* E -> e */
+
+ if ((flags & SBRDEC_ELD_GRID) && (nEnv == 1))
+ h_frame_data->ampResolutionCurrentFrame =
+ FDKreadBits(hBs, 1); /* new ELD Syntax 07-11-09 */
+
+ staticFreqRes = FDKreadBits(hBs, 1);
+
+ if (flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) {
+ if (nEnv > MAX_ENVELOPES_USAC) return 0;
+ } else
+
+ b = nEnv + 1;
+ switch (nEnv) {
+ case 1:
+ switch (numberTimeSlots) {
+ case 15:
+ FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info1_15,
+ sizeof(FRAME_INFO));
+ break;
+ case 16:
+ FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info1_16,
+ sizeof(FRAME_INFO));
+ break;
+ default:
+ FDK_ASSERT(0);
+ }
+ break;
+ case 2:
+ switch (numberTimeSlots) {
+ case 15:
+ FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info2_15,
+ sizeof(FRAME_INFO));
+ break;
+ case 16:
+ FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info2_16,
+ sizeof(FRAME_INFO));
+ break;
+ default:
+ FDK_ASSERT(0);
+ }
+ break;
+ case 4:
+ switch (numberTimeSlots) {
+ case 15:
+ FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info4_15,
+ sizeof(FRAME_INFO));
+ break;
+ case 16:
+ FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info4_16,
+ sizeof(FRAME_INFO));
+ break;
+ default:
+ FDK_ASSERT(0);
+ }
+ break;
+ case 8:
+#if (MAX_ENVELOPES >= 8)
+ switch (numberTimeSlots) {
+ case 15:
+ FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info8_15,
+ sizeof(FRAME_INFO));
+ break;
+ case 16:
+ FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info8_16,
+ sizeof(FRAME_INFO));
+ break;
+ default:
+ FDK_ASSERT(0);
+ }
+ break;
+#else
+ return 0;
+#endif
+ }
+ /* Apply correct freqRes (High is default) */
+ if (!staticFreqRes) {
+ for (i = 0; i < nEnv; i++) pFrameInfo->freqRes[i] = 0;
+ }
+
+ break;
+ case 1:
+ case 2:
+ temp = FDKreadBits(hBs, 2); /* A [2 bits] */
+
+ n = FDKreadBits(hBs, 2); /* n = N [2 bits] */
+
+ nEnv = n + 1; /* # envelopes */
+ b = nEnv + 1; /* # borders */
+
+ break;
+ }
+
+ switch (frameClass) {
+ case 1:
+ /* Decode borders: */
+ pFrameInfo->borders[0] = 0; /* first border */
+ border = temp + numberTimeSlots; /* A -> aR */
+ i = b - 1; /* frame info index for last border */
+ pFrameInfo->borders[i] = border; /* last border */
+
+ for (k = 0; k < n; k++) {
+ temp = FDKreadBits(hBs, 2); /* R [2 bits] */
+ border -= (2 * temp + 2); /* R -> r */
+ pFrameInfo->borders[--i] = border;
+ }
+
+ /* Decode pointer: */
+ pointer_bits = DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(n + 1));
+ p = FDKreadBits(hBs, pointer_bits); /* p = P [pointer_bits bits] */
+
+ if (p > n + 1) return 0;
+
+ pFrameInfo->tranEnv = p ? n + 2 - p : -1;
+
+ /* Decode freq res: */
+ for (k = n; k >= 0; k--) {
+ pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */
+ }
+
+ /* Calculate noise floor middle border: */
+ if (p == 0 || p == 1)
+ pFrameInfo->bordersNoise[1] = pFrameInfo->borders[n];
+ else
+ pFrameInfo->bordersNoise[1] = pFrameInfo->borders[pFrameInfo->tranEnv];
+
+ break;
+
+ case 2:
+ /* Decode borders: */
+ border = temp; /* A -> aL */
+ pFrameInfo->borders[0] = border; /* first border */
+
+ for (k = 1; k <= n; k++) {
+ temp = FDKreadBits(hBs, 2); /* R [2 bits] */
+ border += (2 * temp + 2); /* R -> r */
+ pFrameInfo->borders[k] = border;
+ }
+ pFrameInfo->borders[k] = numberTimeSlots; /* last border */
+
+ /* Decode pointer: */
+ pointer_bits = DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(n + 1));
+ p = FDKreadBits(hBs, pointer_bits); /* p = P [pointer_bits bits] */
+ if (p > n + 1) return 0;
+
+ if (p == 0 || p == 1)
+ pFrameInfo->tranEnv = -1;
+ else
+ pFrameInfo->tranEnv = p - 1;
+
+ /* Decode freq res: */
+ for (k = 0; k <= n; k++) {
+ pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */
+ }
+
+ /* Calculate noise floor middle border: */
+ switch (p) {
+ case 0:
+ pFrameInfo->bordersNoise[1] = pFrameInfo->borders[1];
+ break;
+ case 1:
+ pFrameInfo->bordersNoise[1] = pFrameInfo->borders[n];
+ break;
+ default:
+ pFrameInfo->bordersNoise[1] =
+ pFrameInfo->borders[pFrameInfo->tranEnv];
+ break;
+ }
+
+ break;
+
+ case 3:
+ /* v_ctrlSignal = [frameClass,aL,aR,nL,nR,v_rL,v_rR,p,v_fLR]; */
+
+ aL = FDKreadBits(hBs, 2); /* AL [2 bits], AL -> aL */
+
+ aR = FDKreadBits(hBs, 2) + numberTimeSlots; /* AR [2 bits], AR -> aR */
+
+ nL = FDKreadBits(hBs, 2); /* nL = NL [2 bits] */
+
+ nR = FDKreadBits(hBs, 2); /* nR = NR [2 bits] */
+
+ /*-------------------------------------------------------------------------
+ Calculate help variables
+ --------------------------------------------------------------------------*/
+
+ /* general: */
+ nEnv = nL + nR + 1; /* # envelopes */
+ if (nEnv > MAX_ENVELOPES) return 0;
+ b = nEnv + 1; /* # borders */
+
+ /*-------------------------------------------------------------------------
+ Decode envelopes
+ --------------------------------------------------------------------------*/
+
+ /* L-borders: */
+ border = aL; /* first border */
+ pFrameInfo->borders[0] = border;
+
+ for (k = 1; k <= nL; k++) {
+ temp = FDKreadBits(hBs, 2); /* R [2 bits] */
+ border += (2 * temp + 2); /* R -> r */
+ pFrameInfo->borders[k] = border;
+ }
+
+ /* R-borders: */
+ border = aR; /* last border */
+ i = nEnv;
+
+ pFrameInfo->borders[i] = border;
+
+ for (k = 0; k < nR; k++) {
+ temp = FDKreadBits(hBs, 2); /* R [2 bits] */
+ border -= (2 * temp + 2); /* R -> r */
+ pFrameInfo->borders[--i] = border;
+ }
+
+ /* decode pointer: */
+ pointer_bits =
+ DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(nL + nR + 1));
+ p = FDKreadBits(hBs, pointer_bits); /* p = P [pointer_bits bits] */
+
+ if (p > nL + nR + 1) return 0;
+
+ pFrameInfo->tranEnv = p ? b - p : -1;
+
+ /* decode freq res: */
+ for (k = 0; k < nEnv; k++) {
+ pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */
+ }
+
+ /*-------------------------------------------------------------------------
+ Decode noise floors
+ --------------------------------------------------------------------------*/
+ pFrameInfo->bordersNoise[0] = aL;
+
+ if (nEnv == 1) {
+ /* 1 noise floor envelope: */
+ pFrameInfo->bordersNoise[1] = aR;
+ } else {
+ /* 2 noise floor envelopes */
+ if (p == 0 || p == 1)
+ pFrameInfo->bordersNoise[1] = pFrameInfo->borders[nEnv - 1];
+ else
+ pFrameInfo->bordersNoise[1] =
+ pFrameInfo->borders[pFrameInfo->tranEnv];
+ pFrameInfo->bordersNoise[2] = aR;
+ }
+ break;
+ }
+
+ /*
+ Store number of envelopes, noise floor envelopes and frame class
+ */
+ pFrameInfo->nEnvelopes = nEnv;
+
+ if (nEnv == 1)
+ pFrameInfo->nNoiseEnvelopes = 1;
+ else
+ pFrameInfo->nNoiseEnvelopes = 2;
+
+ pFrameInfo->frameClass = frameClass;
+
+ if (pFrameInfo->frameClass == 2 || pFrameInfo->frameClass == 1) {
+ /* calculate noise floor first and last borders: */
+ pFrameInfo->bordersNoise[0] = pFrameInfo->borders[0];
+ pFrameInfo->bordersNoise[pFrameInfo->nNoiseEnvelopes] =
+ pFrameInfo->borders[nEnv];
+ }
+
+ return 1;
+}
+
+/*!
+ \brief Check if the frameInfo vector has reasonable values.
+ \return Zero for error, one for correct
+*/
+static int checkFrameInfo(
+ FRAME_INFO *pFrameInfo, /*!< pointer to frameInfo */
+ int numberOfTimeSlots, /*!< QMF time slots per frame */
+ int overlap, /*!< Amount of overlap QMF time slots */
+ int timeStep) /*!< QMF slots to SBR slots step factor */
+{
+ int maxPos, i, j;
+ int startPos;
+ int stopPos;
+ int tranEnv;
+ int startPosNoise;
+ int stopPosNoise;
+ int nEnvelopes = pFrameInfo->nEnvelopes;
+ int nNoiseEnvelopes = pFrameInfo->nNoiseEnvelopes;
+
+ if (nEnvelopes < 1 || nEnvelopes > MAX_ENVELOPES) return 0;
+
+ if (nNoiseEnvelopes > MAX_NOISE_ENVELOPES) return 0;
+
+ startPos = pFrameInfo->borders[0];
+ stopPos = pFrameInfo->borders[nEnvelopes];
+ tranEnv = pFrameInfo->tranEnv;
+ startPosNoise = pFrameInfo->bordersNoise[0];
+ stopPosNoise = pFrameInfo->bordersNoise[nNoiseEnvelopes];
+
+ if (overlap < 0 || overlap > (3 * (4))) {
+ return 0;
+ }
+ if (timeStep < 1 || timeStep > (4)) {
+ return 0;
+ }
+ maxPos = numberOfTimeSlots + (overlap / timeStep);
+
+ /* Check that the start and stop positions of the frame are reasonable values.
+ */
+ if ((startPos < 0) || (startPos >= stopPos)) return 0;
+ if (startPos > maxPos - numberOfTimeSlots) /* First env. must start in or
+ directly after the overlap
+ buffer */
+ return 0;
+ if (stopPos < numberOfTimeSlots) /* One complete frame must be ready for
+ output after processing */
+ return 0;
+ if (stopPos > maxPos) return 0;
+
+ /* Check that the start border for every envelope is strictly later in time
+ */
+ for (i = 0; i < nEnvelopes; i++) {
+ if (pFrameInfo->borders[i] >= pFrameInfo->borders[i + 1]) return 0;
+ }
+
+ /* Check that the envelope to be shortened is actually among the envelopes */
+ if (tranEnv > nEnvelopes) return 0;
+
+ /* Check the noise borders */
+ if (nEnvelopes == 1 && nNoiseEnvelopes > 1) return 0;
+
+ if (startPos != startPosNoise || stopPos != stopPosNoise) return 0;
+
+ /* Check that the start border for every noise-envelope is strictly later in
+ * time*/
+ for (i = 0; i < nNoiseEnvelopes; i++) {
+ if (pFrameInfo->bordersNoise[i] >= pFrameInfo->bordersNoise[i + 1])
+ return 0;
+ }
+
+ /* Check that every noise border is the same as an envelope border*/
+ for (i = 0; i < nNoiseEnvelopes; i++) {
+ startPosNoise = pFrameInfo->bordersNoise[i];
+
+ for (j = 0; j < nEnvelopes; j++) {
+ if (pFrameInfo->borders[j] == startPosNoise) break;
+ }
+ if (j == nEnvelopes) return 0;
+ }
+
+ return 1;
+}