diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2012-07-11 10:15:24 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2012-07-11 10:15:24 -0700 |
commit | 2228e360595641dd906bf1773307f43d304f5b2e (patch) | |
tree | 57f3d390ebb0782cc0de0fb984c8ea7e45b4f386 /libSBRdec/src/env_extr.cpp | |
download | fdk-aac-2228e360595641dd906bf1773307f43d304f5b2e.tar.gz fdk-aac-2228e360595641dd906bf1773307f43d304f5b2e.tar.bz2 fdk-aac-2228e360595641dd906bf1773307f43d304f5b2e.zip |
Snapshot 2bda038c163298531d47394bc2c09e1409c5d0db
Change-Id: If584e579464f28b97d50e51fc76ba654a5536c54
Diffstat (limited to 'libSBRdec/src/env_extr.cpp')
-rw-r--r-- | libSBRdec/src/env_extr.cpp | 1395 |
1 files changed, 1395 insertions, 0 deletions
diff --git a/libSBRdec/src/env_extr.cpp b/libSBRdec/src/env_extr.cpp new file mode 100644 index 0000000..716fb91 --- /dev/null +++ b/libSBRdec/src/env_extr.cpp @@ -0,0 +1,1395 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2012 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Envelope 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 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 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); + +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); + +SBR_ERROR +initHeaderData ( + HANDLE_SBR_HEADER_DATA hHeaderData, + const int sampleRateIn, + const int sampleRateOut, + const int samplesPerFrame, + const UINT flags + ) +{ + HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; + SBR_ERROR sbrError = SBRDEC_OK; + int numAnalysisBands; + + if ( sampleRateIn == sampleRateOut ) { + hHeaderData->sbrProcSmplRate = sampleRateOut<<1; + numAnalysisBands = 32; + } else { + hHeaderData->sbrProcSmplRate = sampleRateOut; + if ( (sampleRateOut>>1) == sampleRateIn) { + /* 1:2 */ + numAnalysisBands = 32; + } else if ( (sampleRateOut>>2) == sampleRateIn ) { + /* 1:4 */ + numAnalysisBands = 32; + } else if ( (sampleRateOut*3)>>3 == (sampleRateIn*8)>>3 ) { + /* 3:8, 3/4 core frame length */ + numAnalysisBands = 24; + } else { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + goto bail; + } + } + + /* 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_data.startFreq = 5; + hHeaderData->bs_data.stopFreq = 0; + hHeaderData->bs_data.freqScale = 2; + 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; + + hHeaderData->timeStep = (flags & SBRDEC_ELD_GRID) ? 1 : 2; + + /* Setup pointers to frequency band tables */ + hFreq->freqBandTable[0] = hFreq->freqBandTableLo; + hFreq->freqBandTable[1] = hFreq->freqBandTableHi; + + /* Patch some entries */ + if (sampleRateOut > 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; + } + + /* 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; + +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; +} + + +/*! + \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) +{ + SBR_HEADER_DATA_BS *pBsData; + SBR_HEADER_DATA_BS lastHeader; + SBR_HEADER_DATA_BS_INFO lastInfo; + int headerExtra1=0, headerExtra2=0; + + /* Copy SBR bit stream header to temporary header */ + lastHeader = hHeaderData->bs_data; + lastInfo = hHeaderData->bs_info; + + /* Read new header from bitstream */ + { + pBsData = &hHeaderData->bs_data; + } + + { + hHeaderData->bs_info.ampResolution = FDKreadBits (hBs, 1); + } + + pBsData->startFreq = FDKreadBits (hBs, 4); + pBsData->stopFreq = FDKreadBits (hBs, 4); + + { + 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_ACTIVE || + 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) +{ + int i, bitsRead = 0; + + int flag = FDKreadBits(hBs,1); + bitsRead++; + + if(flag){ + for(i=0;i<hHeaderData->freqBandData.nSfb[1];i++){ + hFrameData->addHarmonics[i] = FDKreadBits (hBs, 1 ); + bitsRead++; + } + } + else { + for(i=0; i<MAX_FREQ_COEFFS; 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 -= 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 one channel + + \return SbrFrameOK: 1=ok, 0=error +*/ +int +sbrGetSingleChannelElement (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ + HANDLE_FDK_BITSTREAM hBs, /*!< Handle to struct BIT_BUF */ + HANDLE_PS_DEC hParametricStereoDec, /*!< Handle to PS decoder */ + const UINT flags, + const int overlap + ) +{ + int i; + + + hFrameData->coupling = COUPLING_OFF; + + { + /* Reserved bits */ + if (FDKreadBits(hBs, 1)) { /* bs_data_extra */ + FDKreadBits(hBs, 4); + if (flags & SBRDEC_SYNTAX_SCAL) { + FDKreadBits(hBs, 4); + } + } + } + + if (flags & SBRDEC_SYNTAX_SCAL) { + FDKreadBits (hBs, 1); /* bs_coupling */ + } + + /* + Grid control + */ + if ( !extractFrameInfo ( hBs, hHeaderData, hFrameData, 1, flags) ) + return 0; + + if ( !checkFrameInfo (&hFrameData->frameInfo, hHeaderData->numberTimeSlots, overlap, hHeaderData->timeStep) ) + return 0; + + + /* + Fetch domain vectors (time or frequency direction for delta-coding) + */ + sbrGetDirectionControlData (hFrameData, hBs); + + for (i=0; i<hHeaderData->freqBandData.nInvfBands; i++) { + hFrameData->sbr_invf_mode[i] = + (INVF_MODE) FDKreadBits (hBs, 2); + } + + + + /* raw data */ + if ( !sbrGetEnvelope (hHeaderData, hFrameData, hBs, flags) ) + return 0; + + + sbrGetNoiseFloorData (hHeaderData, hFrameData, hBs); + + sbrGetSyntheticCodedData(hHeaderData, hFrameData, hBs); + + { + /* sbr extended data */ + if (! extractExtendedData( + hHeaderData, + hBs + ,hParametricStereoDec + )) { + return 0; + } + } + + return 1; +} + + + +/*! + \brief Read bitstream elements of a channel pair + \return SbrFrameOK +*/ +int +sbrGetChannelPairElement (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA hFrameDataLeft, /*!< Dynamic control data for first channel */ + HANDLE_SBR_FRAME_DATA hFrameDataRight,/*!< Dynamic control data for second channel */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to struct BIT_BUF */ + const UINT flags, + const int overlap ) +{ + int i, bit; + + + /* Reserved bits */ + if (FDKreadBits(hBs, 1)) { /* bs_data_extra */ + FDKreadBits(hBs, 4); + FDKreadBits(hBs, 4); + } + + /* Read coupling flag */ + bit = FDKreadBits (hBs, 1); + + if (bit) { + hFrameDataLeft->coupling = COUPLING_LEVEL; + hFrameDataRight->coupling = COUPLING_BAL; + } + else { + hFrameDataLeft->coupling = COUPLING_OFF; + hFrameDataRight->coupling = COUPLING_OFF; + } + + + /* + Grid control + */ + if ( !extractFrameInfo (hBs, hHeaderData, hFrameDataLeft, 2, flags) ) + return 0; + + if ( !checkFrameInfo (&hFrameDataLeft->frameInfo, hHeaderData->numberTimeSlots, overlap, hHeaderData->timeStep) ) + return 0; + + 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; + } + + /* + Fetch domain vectors (time or frequency direction for delta-coding) + */ + sbrGetDirectionControlData (hFrameDataLeft, hBs); + sbrGetDirectionControlData (hFrameDataRight, hBs); + + for (i=0; i<hHeaderData->freqBandData.nInvfBands; i++) { + hFrameDataLeft->sbr_invf_mode[i] = (INVF_MODE) FDKreadBits (hBs, 2); + } + + if (hFrameDataLeft->coupling) { + for (i=0; i<hHeaderData->freqBandData.nInvfBands; i++) { + hFrameDataRight->sbr_invf_mode[i] = hFrameDataLeft->sbr_invf_mode[i]; + } + + + if ( !sbrGetEnvelope (hHeaderData, hFrameDataLeft, hBs, flags) ) { + return 0; + } + + sbrGetNoiseFloorData (hHeaderData, hFrameDataLeft, hBs); + + if ( !sbrGetEnvelope (hHeaderData, hFrameDataRight, hBs, flags) ) { + return 0; + } + } + else { + + for (i=0; i<hHeaderData->freqBandData.nInvfBands; i++) { + hFrameDataRight->sbr_invf_mode[i] = (INVF_MODE) FDKreadBits (hBs, 2); + } + + + + 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); + sbrGetSyntheticCodedData(hHeaderData, hFrameDataRight, hBs); + + { + if (! extractExtendedData( + hHeaderData, + hBs + ,NULL + ) ) { + 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 */ +{ + int i; + + for (i = 0; i < h_frame_data->frameInfo.nEnvelopes; i++) { + h_frame_data->domain_vec[i] = FDKreadBits (hBs, 1); + } + + for (i = 0; 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); + } + } + } +} + + +/*! + \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; + } + } + + /* + 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); + } + 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; +} + + +//static const FRAME_INFO v_frame_info1_8 = { 0, 1, {0, 8}, {1}, -1, 1, {0, 8} }; +static const FRAME_INFO v_frame_info2_8 = { 0, 2, {0, 4, 8}, {1, 1}, -1, 2, {0, 4, 8} }; +static const FRAME_INFO v_frame_info4_8 = { 0, 4, {0, 2, 4, 6, 8}, {1, 1, 1, 1}, -1, 2, {0, 4, 8} }; + +/***************************************************************************/ +/*! + \brief Generates frame info for FIXFIXonly frame class used for low delay version + + \return nothing + ****************************************************************************/ + static void generateFixFixOnly ( FRAME_INFO *hSbrFrameInfo, + int tranPosInternal, + int numberTimeSlots + ) +{ + 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: + FDK_ASSERT(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; +} + +/*! + \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 + ) +{ + 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; + } + + /* calculate borders according to the transient position */ + generateFixFixOnly ( pFrameInfo, + temp, + numberTimeSlots + ); + + /* 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 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; + extractLowDelayGrid (hBs, hHeaderData, h_frame_data, numberTimeSlots); + return 1; + } + } 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 (nEnv > MAX_ENVELOPES_HEAAC) + return 0; + } + + 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 > (6)) { + return 0; + } + if (timeStep < 1 || timeStep > 2) { + 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; +} |