mirror of https://github.com/mstorsjo/fdk-aac.git
1733 lines
57 KiB
C++
1733 lines
57 KiB
C++
/* -----------------------------------------------------------------------------
|
|
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;
|
|
|
|
if (tranPosInternal >= numberTimeSlots) {
|
|
return 0;
|
|
}
|
|
|
|
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;
|
|
}
|