diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2019-11-11 11:38:02 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2019-11-11 11:38:02 +0100 |
commit | 0e5af65c467b2423a0b857ae3ad98c91acc1e190 (patch) | |
tree | d07f69550d8886271e44fe79c4dcfb299cafbd38 /fdk-aac/libSBRdec/src/env_extr.cpp | |
parent | efe406d9724f959c8bc2a31802559ca6d41fd897 (diff) | |
download | ODR-AudioEnc-0e5af65c467b2423a0b857ae3ad98c91acc1e190.tar.gz ODR-AudioEnc-0e5af65c467b2423a0b857ae3ad98c91acc1e190.tar.bz2 ODR-AudioEnc-0e5af65c467b2423a0b857ae3ad98c91acc1e190.zip |
Include patched FDK-AAC in the repository
The initial idea was to get the DAB+ patch into upstream, but since
that follows the android source releases, there is no place for a custom
DAB+ patch there.
So instead of having to maintain a patched fdk-aac that has to have the
same .so version as the distribution package on which it is installed,
we prefer having a separate fdk-aac-dab library to avoid collision.
At that point, there's no reason to keep fdk-aac in a separate
repository, as odr-audioenc is the only tool that needs DAB+ encoding
support. Including it here simplifies installation, and makes it
consistent with toolame-dab, also shipped in this repository.
DAB+ decoding support (needed by ODR-SourceCompanion, dablin, etisnoop,
welle.io and others) can be done using upstream FDK-AAC.
Diffstat (limited to 'fdk-aac/libSBRdec/src/env_extr.cpp')
-rw-r--r-- | fdk-aac/libSBRdec/src/env_extr.cpp | 1728 |
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; +} |