summaryrefslogtreecommitdiffstats
path: root/libSBRdec/src/sbrdecoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libSBRdec/src/sbrdecoder.cpp')
-rw-r--r--libSBRdec/src/sbrdecoder.cpp1546
1 files changed, 0 insertions, 1546 deletions
diff --git a/libSBRdec/src/sbrdecoder.cpp b/libSBRdec/src/sbrdecoder.cpp
deleted file mode 100644
index 26b2ea2..0000000
--- a/libSBRdec/src/sbrdecoder.cpp
+++ /dev/null
@@ -1,1546 +0,0 @@
-
-/* -----------------------------------------------------------------------------------------------------------
-Software License for The Fraunhofer FDK AAC Codec Library for Android
-
-© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
- All rights reserved.
-
- 1. INTRODUCTION
-The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
-the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
-This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
-
-AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
-audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
-independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
-of the MPEG specifications.
-
-Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
-may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
-individually for the purpose of encoding or decoding bit streams in products that are compliant with
-the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
-these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
-software may already be covered under those patent licenses when it is used for those licensed purposes only.
-
-Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
-are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
-applications information and documentation.
-
-2. COPYRIGHT LICENSE
-
-Redistribution and use in source and binary forms, with or without modification, are permitted without
-payment of copyright license fees provided that you satisfy the following conditions:
-
-You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
-your modifications thereto in source code form.
-
-You must retain the complete text of this software license in the documentation and/or other materials
-provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
-You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
-modifications thereto to recipients of copies in binary form.
-
-The name of Fraunhofer may not be used to endorse or promote products derived from this library without
-prior written permission.
-
-You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
-software or your modifications thereto.
-
-Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
-and the date of any change. For modified versions of the FDK AAC Codec, the term
-"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
-"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
-
-3. NO PATENT LICENSE
-
-NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
-ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
-respect to this software.
-
-You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
-by appropriate patent licenses.
-
-4. DISCLAIMER
-
-This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
-"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
-of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
-CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
-including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
-or business interruption, however caused and on any theory of liability, whether in contract, strict
-liability, or tort (including negligence), arising in any way out of the use of this software, even if
-advised of the possibility of such damage.
-
-5. CONTACT INFORMATION
-
-Fraunhofer Institute for Integrated Circuits IIS
-Attention: Audio and Multimedia Departments - FDK AAC LL
-Am Wolfsmantel 33
-91058 Erlangen, Germany
-
-www.iis.fraunhofer.de/amm
-amm-info@iis.fraunhofer.de
------------------------------------------------------------------------------------------------------------ */
-
-/*!
- \file
- \brief SBR decoder frontend
- This module provides a frontend to the SBR decoder. The function openSBR() is called for
- initialization. The function sbrDecoder_Apply() is called for each frame. sbr_Apply() will call the
- required functions to decode the raw SBR data (provided by env_extr.cpp), to decode the envelope data and noise floor levels [decodeSbrData()],
- and to finally apply SBR to the current frame [sbr_dec()].
-
- \sa sbrDecoder_Apply(), \ref documentationOverview
-*/
-
-/*!
- \page documentationOverview Overview of important information resources and source code documentation
-
- The primary source code documentation is based on generated and cross-referenced HTML files using
- <a HREF="http://www.doxygen.org">doxygen</a>. As part of this documentation
- you can find more extensive descriptions about key concepts and algorithms at the following locations:
-
- <h2>Programming</h2>
-
- \li Buffer management: sbrDecoder_Apply() and sbr_dec()
- \li Internal scale factors to maximize SNR on fixed point processors: #QMF_SCALE_FACTOR
- \li Special mantissa-exponent format: Created in requantizeEnvelopeData() and used in calculateSbrEnvelope()
-
- <h2>Algorithmic details</h2>
- \li About the SBR data format: \ref SBR_HEADER_ELEMENT and \ref SBR_STANDARD_ELEMENT
- \li Details about the bitstream decoder: env_extr.cpp
- \li Details about the QMF filterbank and the provided polyphase implementation: qmf_dec.cpp
- \li Details about the transposer: lpp_tran.cpp
- \li Details about the envelope adjuster: env_calc.cpp
-
-*/
-
-#include "sbrdecoder.h"
-
-#include "FDK_bitstream.h"
-
-#include "sbrdec_freq_sca.h"
-#include "env_extr.h"
-#include "sbr_dec.h"
-#include "env_dec.h"
-#include "sbr_crc.h"
-#include "sbr_ram.h"
-#include "sbr_rom.h"
-#include "lpp_tran.h"
-#include "transcendent.h"
-
-
-#include "sbrdec_drc.h"
-
-#include "psbitdec.h"
-
-
-/* Decoder library info */
-#define SBRDECODER_LIB_VL0 2
-#define SBRDECODER_LIB_VL1 2
-#define SBRDECODER_LIB_VL2 3
-#define SBRDECODER_LIB_TITLE "SBR Decoder"
-#define SBRDECODER_LIB_BUILD_DATE __DATE__
-#define SBRDECODER_LIB_BUILD_TIME __TIME__
-
-
-
-
-static UCHAR getHeaderSlot( UCHAR currentSlot, UCHAR hdrSlotUsage[(1)+1] )
-{
- UINT occupied = 0;
- int s;
- UCHAR slot = hdrSlotUsage[currentSlot];
-
- FDK_ASSERT((1)+1 < 32);
-
- for (s = 0; s < (1)+1; s++) {
- if ( (hdrSlotUsage[s] == slot)
- && (s != slot) ) {
- occupied = 1;
- break;
- }
- }
-
- if (occupied) {
- occupied = 0;
-
- for (s = 0; s < (1)+1; s++) {
- occupied |= 1 << hdrSlotUsage[s];
- }
- for (s = 0; s < (1)+1; s++) {
- if ( !(occupied & 0x1) ) {
- slot = s;
- break;
- }
- occupied >>= 1;
- }
- }
-
- return slot;
-}
-
-static void copySbrHeader( HANDLE_SBR_HEADER_DATA hDst, const HANDLE_SBR_HEADER_DATA hSrc )
-{
- /* copy the whole header memory (including pointers) */
- FDKmemcpy( hDst, hSrc, sizeof(SBR_HEADER_DATA) );
-
- /* update pointers */
- hDst->freqBandData.freqBandTable[0] = hDst->freqBandData.freqBandTableLo;
- hDst->freqBandData.freqBandTable[1] = hDst->freqBandData.freqBandTableHi;
-}
-
-
-/*!
- \brief Reset SBR decoder.
-
- Reset should only be called if SBR has been sucessfully detected by
- an appropriate checkForPayload() function.
-
- \return Error code.
-*/
-static
-SBR_ERROR sbrDecoder_ResetElement (
- HANDLE_SBRDECODER self,
- int sampleRateIn,
- int sampleRateOut,
- int samplesPerFrame,
- const MP4_ELEMENT_ID elementID,
- const int elementIndex,
- const int overlap
- )
-{
- SBR_ERROR sbrError = SBRDEC_OK;
- HANDLE_SBR_HEADER_DATA hSbrHeader;
- UINT qmfFlags = 0;
-
- int i, synDownsampleFac;
-
- /* Check in/out samplerates */
- if ( sampleRateIn < 6400
- || sampleRateIn > 48000
- )
- {
- sbrError = SBRDEC_UNSUPPORTED_CONFIG;
- goto bail;
- }
-
- if ( sampleRateOut > 96000 )
- {
- sbrError = SBRDEC_UNSUPPORTED_CONFIG;
- goto bail;
- }
-
- /* Set QMF mode flags */
- if (self->flags & SBRDEC_LOW_POWER)
- qmfFlags |= QMF_FLAG_LP;
-
- if (self->coreCodec == AOT_ER_AAC_ELD) {
- if (self->flags & SBRDEC_LD_MPS_QMF) {
- qmfFlags |= QMF_FLAG_MPSLDFB;
- } else {
- qmfFlags |= QMF_FLAG_CLDFB;
- }
- }
-
- /* Set downsampling factor for synthesis filter bank */
- if (sampleRateOut == 0)
- {
- /* no single rate mode */
- sampleRateOut = sampleRateIn<<1; /* In case of implicit signalling, assume dual rate SBR */
- }
-
- if ( sampleRateIn == sampleRateOut ) {
- synDownsampleFac = 2;
- } else {
- synDownsampleFac = 1;
- }
-
- self->synDownsampleFac = synDownsampleFac;
- self->sampleRateOut = sampleRateOut;
-
- {
- int i;
-
- for (i = 0; i < (1)+1; i++)
- {
- hSbrHeader = &(self->sbrHeader[elementIndex][i]);
-
- /* init a default header such that we can at least do upsampling later */
- sbrError = initHeaderData(
- hSbrHeader,
- sampleRateIn,
- sampleRateOut,
- samplesPerFrame,
- self->flags
- );
- }
- }
-
- if (sbrError != SBRDEC_OK) {
- goto bail;
- }
-
- /* Init SBR channels going to be assigned to a SBR element */
- {
- int ch;
-
- for (ch=0; ch<self->pSbrElement[elementIndex]->nChannels; ch++)
- {
- /* and create sbrDec */
- sbrError = createSbrDec (self->pSbrElement[elementIndex]->pSbrChannel[ch],
- hSbrHeader,
- &self->pSbrElement[elementIndex]->transposerSettings,
- synDownsampleFac,
- qmfFlags,
- self->flags,
- overlap,
- ch );
-
- if (sbrError != SBRDEC_OK) {
- goto bail;
- }
- }
- }
-
- //FDKmemclear(sbr_OverlapBuffer, sizeof(sbr_OverlapBuffer));
-
- if (self->numSbrElements == 1) {
- switch ( self->coreCodec ) {
- case AOT_AAC_LC:
- case AOT_SBR:
- case AOT_PS:
- case AOT_ER_AAC_SCAL:
- case AOT_DRM_AAC:
- case AOT_DRM_SURROUND:
- if (CreatePsDec ( &self->hParametricStereoDec, samplesPerFrame )) {
- sbrError = SBRDEC_CREATE_ERROR;
- goto bail;
- }
- break;
- default:
- break;
- }
- }
-
- /* Init frame delay slot handling */
- self->pSbrElement[elementIndex]->useFrameSlot = 0;
- for (i = 0; i < ((1)+1); i++) {
- self->pSbrElement[elementIndex]->useHeaderSlot[i] = i;
- }
-
-bail:
-
- return sbrError;
-}
-
-
-SBR_ERROR sbrDecoder_Open ( HANDLE_SBRDECODER * pSelf )
-{
- HANDLE_SBRDECODER self = NULL;
- SBR_ERROR sbrError = SBRDEC_OK;
-
- /* Get memory for this instance */
- self = GetRam_SbrDecoder();
- if (self == NULL) {
- sbrError = SBRDEC_MEM_ALLOC_FAILED;
- goto bail;
- }
-
- self->workBuffer1 = GetRam_SbrDecWorkBuffer1();
- self->workBuffer2 = GetRam_SbrDecWorkBuffer2();
-
- if ( self->workBuffer1 == NULL
- || self->workBuffer2 == NULL )
- {
- sbrError = SBRDEC_MEM_ALLOC_FAILED;
- goto bail;
- }
-
- /*
- Already zero because of calloc
- self->numSbrElements = 0;
- self->numSbrChannels = 0;
- self->codecFrameSize = 0;
- */
-
- self->numDelayFrames = (1); /* set to the max value by default */
-
- *pSelf = self;
-
-bail:
- return sbrError;
-}
-
-/**
- * \brief determine if the given core codec AOT can be processed or not.
- * \param coreCodec core codec audio object type.
- * \return 1 if SBR can be processed, 0 if SBR cannot be processed/applied.
- */
-static
-int sbrDecoder_isCoreCodecValid(AUDIO_OBJECT_TYPE coreCodec)
-{
- switch (coreCodec) {
- case AOT_AAC_LC:
- case AOT_SBR:
- case AOT_PS:
- case AOT_ER_AAC_SCAL:
- case AOT_ER_AAC_ELD:
- return 1;
- default:
- return 0;
- }
-}
-
-static
-void sbrDecoder_DestroyElement (
- HANDLE_SBRDECODER self,
- const int elementIndex
- )
-{
- if (self->pSbrElement[elementIndex] != NULL) {
- int ch;
-
- for (ch=0; ch<SBRDEC_MAX_CH_PER_ELEMENT; ch++) {
- if (self->pSbrElement[elementIndex]->pSbrChannel[ch] != NULL) {
- deleteSbrDec( self->pSbrElement[elementIndex]->pSbrChannel[ch] );
- FreeRam_SbrDecChannel( &self->pSbrElement[elementIndex]->pSbrChannel[ch] );
- self->numSbrChannels -= 1;
- }
- }
- FreeRam_SbrDecElement( &self->pSbrElement[elementIndex] );
- self->numSbrElements -= 1;
- }
-}
-
-
-SBR_ERROR sbrDecoder_InitElement (
- HANDLE_SBRDECODER self,
- const int sampleRateIn,
- const int sampleRateOut,
- const int samplesPerFrame,
- const AUDIO_OBJECT_TYPE coreCodec,
- const MP4_ELEMENT_ID elementID,
- const int elementIndex
- )
-{
- SBR_ERROR sbrError = SBRDEC_OK;
- int chCnt=0;
- int nSbrElementsStart = self->numSbrElements;
-
- /* Check core codec AOT */
- if (! sbrDecoder_isCoreCodecValid(coreCodec) || elementIndex >= (4)) {
- sbrError = SBRDEC_UNSUPPORTED_CONFIG;
- goto bail;
- }
-
- if ( elementID != ID_SCE && elementID != ID_CPE && elementID != ID_LFE )
- {
- sbrError = SBRDEC_UNSUPPORTED_CONFIG;
- goto bail;
- }
-
- if ( self->sampleRateIn == sampleRateIn
- && self->codecFrameSize == samplesPerFrame
- && self->coreCodec == coreCodec
- && self->pSbrElement[elementIndex] != NULL
- && self->pSbrElement[elementIndex]->elementID == elementID
- )
- {
- /* Nothing to do */
- return SBRDEC_OK;
- }
-
- self->sampleRateIn = sampleRateIn;
- self->codecFrameSize = samplesPerFrame;
- self->coreCodec = coreCodec;
-
- self->flags = 0;
- self->flags |= (coreCodec == AOT_ER_AAC_ELD) ? SBRDEC_ELD_GRID : 0;
-
- /* Init SBR elements */
- {
- int elChannels, ch;
-
- if (self->pSbrElement[elementIndex] == NULL) {
- self->pSbrElement[elementIndex] = GetRam_SbrDecElement(elementIndex);
- if (self->pSbrElement[elementIndex] == NULL) {
- sbrError = SBRDEC_MEM_ALLOC_FAILED;
- goto bail;
- }
- self->numSbrElements ++;
- } else {
- self->numSbrChannels -= self->pSbrElement[elementIndex]->nChannels;
- }
-
- /* Save element ID for sanity checks and to have a fallback for concealment. */
- self->pSbrElement[elementIndex]->elementID = elementID;
-
- /* Determine amount of channels for this element */
- switch (elementID) {
- case ID_NONE:
- case ID_CPE: elChannels=2;
- break;
- case ID_LFE:
- case ID_SCE: elChannels=1;
- break;
- default: elChannels=0;
- break;
- }
-
- /* Handle case of Parametric Stereo */
- if ( elementIndex == 0 && elementID == ID_SCE ) {
- switch (coreCodec) {
- case AOT_AAC_LC:
- case AOT_SBR:
- case AOT_PS:
- case AOT_ER_AAC_SCAL:
- case AOT_DRM_AAC:
- case AOT_DRM_SURROUND:
- elChannels = 2;
- break;
- default:
- break;
- }
- }
-
- self->pSbrElement[elementIndex]->nChannels = elChannels;
-
- for (ch=0; ch<elChannels; ch++)
- {
- if (self->pSbrElement[elementIndex]->pSbrChannel[ch] == NULL) {
- self->pSbrElement[elementIndex]->pSbrChannel[ch] = GetRam_SbrDecChannel(chCnt);
- if (self->pSbrElement[elementIndex]->pSbrChannel[ch] == NULL) {
- sbrError = SBRDEC_MEM_ALLOC_FAILED;
- goto bail;
- }
- }
- self->numSbrChannels ++;
-
- sbrDecoder_drcInitChannel( &self->pSbrElement[elementIndex]->pSbrChannel[ch]->SbrDec.sbrDrcChannel );
-
- /* Add reference pointer to workbuffers. */
- self->pSbrElement[elementIndex]->pSbrChannel[ch]->SbrDec.WorkBuffer1 = self->workBuffer1;
- self->pSbrElement[elementIndex]->pSbrChannel[ch]->SbrDec.WorkBuffer2 = self->workBuffer2;
- chCnt++;
- }
- if (elChannels == 1 && self->pSbrElement[elementIndex]->pSbrChannel[ch] != NULL) {
- deleteSbrDec( self->pSbrElement[elementIndex]->pSbrChannel[ch] );
- FreeRam_SbrDecChannel( &self->pSbrElement[elementIndex]->pSbrChannel[ch] );
- }
- }
-
- /* clear error flags for all delay slots */
- FDKmemclear(self->pSbrElement[elementIndex]->frameErrorFlag, ((1)+1)*sizeof(UCHAR));
-
- /* Initialize this instance */
- sbrError = sbrDecoder_ResetElement(
- self,
- sampleRateIn,
- sampleRateOut,
- samplesPerFrame,
- elementID,
- elementIndex,
- (coreCodec == AOT_ER_AAC_ELD) ? 0 : (6)
- );
-
-
-
-bail:
- if (sbrError != SBRDEC_OK) {
- if (nSbrElementsStart < self->numSbrElements) {
- /* Free the memory allocated for this element */
- sbrDecoder_DestroyElement( self, elementIndex );
- } else if (self->pSbrElement[elementIndex] != NULL) {
- /* Set error flag to trigger concealment */
- self->pSbrElement[elementIndex]->frameErrorFlag[self->pSbrElement[elementIndex]->useFrameSlot] = 1;
- }
- }
-
- return sbrError;
-}
-
-/**
- * \brief Apply decoded SBR header for one element.
- * \param self SBR decoder instance handle
- * \param hSbrHeader SBR header handle to be processed.
- * \param hSbrChannel pointer array to the SBR element channels corresponding to the SBR header.
- * \param headerStatus header status value returned from SBR header parser.
- * \param numElementChannels amount of channels for the SBR element whos header is to be processed.
- */
-static
-SBR_ERROR sbrDecoder_HeaderUpdate(
- HANDLE_SBRDECODER self,
- HANDLE_SBR_HEADER_DATA hSbrHeader,
- SBR_HEADER_STATUS headerStatus,
- HANDLE_SBR_CHANNEL hSbrChannel[],
- const int numElementChannels
- )
-{
- SBR_ERROR errorStatus = SBRDEC_OK;
-
- /*
- change of control data, reset decoder
- */
- errorStatus = resetFreqBandTables(hSbrHeader, self->flags);
-
- if (errorStatus == SBRDEC_OK) {
- if (hSbrHeader->syncState == UPSAMPLING && headerStatus != HEADER_RESET)
- {
- /* As the default header would limit the frequency range,
- lowSubband and highSubband must be patched. */
- hSbrHeader->freqBandData.lowSubband = hSbrHeader->numberOfAnalysisBands;
- hSbrHeader->freqBandData.highSubband = hSbrHeader->numberOfAnalysisBands;
- }
-
- /* Trigger a reset before processing this slot */
- hSbrHeader->status |= SBRDEC_HDR_STAT_RESET;
- }
-
- return errorStatus;
-}
-
-INT sbrDecoder_Header (
- HANDLE_SBRDECODER self,
- HANDLE_FDK_BITSTREAM hBs,
- const INT sampleRateIn,
- const INT sampleRateOut,
- const INT samplesPerFrame,
- const AUDIO_OBJECT_TYPE coreCodec,
- const MP4_ELEMENT_ID elementID,
- const INT elementIndex
- )
-{
- SBR_HEADER_STATUS headerStatus;
- HANDLE_SBR_HEADER_DATA hSbrHeader;
- SBR_ERROR sbrError = SBRDEC_OK;
- int headerIndex;
-
- if ( self == NULL || elementIndex > (4) )
- {
- return SBRDEC_UNSUPPORTED_CONFIG;
- }
-
- if (! sbrDecoder_isCoreCodecValid(coreCodec)) {
- return SBRDEC_UNSUPPORTED_CONFIG;
- }
-
- sbrError = sbrDecoder_InitElement(
- self,
- sampleRateIn,
- sampleRateOut,
- samplesPerFrame,
- coreCodec,
- elementID,
- elementIndex
- );
-
- if (sbrError != SBRDEC_OK) {
- goto bail;
- }
-
- headerIndex = getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot,
- self->pSbrElement[elementIndex]->useHeaderSlot);
- hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]);
-
- headerStatus = sbrGetHeaderData ( hSbrHeader,
- hBs,
- self->flags,
- 0);
-
-
- {
- SBR_DECODER_ELEMENT *pSbrElement;
-
- pSbrElement = self->pSbrElement[elementIndex];
-
- /* Sanity check */
- if (pSbrElement != NULL) {
- if ( (elementID == ID_CPE && pSbrElement->nChannels != 2)
- || (elementID != ID_CPE && pSbrElement->nChannels != 1) )
- {
- return SBRDEC_UNSUPPORTED_CONFIG;
- }
- if ( headerStatus == HEADER_RESET ) {
-
- sbrError = sbrDecoder_HeaderUpdate(
- self,
- hSbrHeader,
- headerStatus,
- pSbrElement->pSbrChannel,
- pSbrElement->nChannels
- );
-
- if (sbrError == SBRDEC_OK) {
- hSbrHeader->syncState = SBR_HEADER;
- hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE;
- }
- /* else {
- Since we already have overwritten the old SBR header the only way out is UPSAMPLING!
- This will be prepared in the next step.
- } */
- }
- }
- }
-bail:
- return sbrError;
-}
-
-
-SBR_ERROR sbrDecoder_SetParam (HANDLE_SBRDECODER self,
- const SBRDEC_PARAM param,
- const INT value )
-{
- SBR_ERROR errorStatus = SBRDEC_OK;
-
- /* configure the subsystems */
- switch (param)
- {
- case SBR_SYSTEM_BITSTREAM_DELAY:
- if (value < 0 || value > (1)) {
- errorStatus = SBRDEC_SET_PARAM_FAIL;
- break;
- }
- if (self == NULL) {
- errorStatus = SBRDEC_NOT_INITIALIZED;
- } else {
- self->numDelayFrames = (UCHAR)value;
- }
- break;
- case SBR_QMF_MODE:
- if (self == NULL) {
- errorStatus = SBRDEC_NOT_INITIALIZED;
- } else {
- if (value == 1) {
- self->flags |= SBRDEC_LOW_POWER;
- } else {
- self->flags &= ~SBRDEC_LOW_POWER;
- }
- }
- break;
- case SBR_LD_QMF_TIME_ALIGN:
- if (self == NULL) {
- errorStatus = SBRDEC_NOT_INITIALIZED;
- } else {
- if (value == 1) {
- self->flags |= SBRDEC_LD_MPS_QMF;
- } else {
- self->flags &= ~SBRDEC_LD_MPS_QMF;
- }
- }
- break;
- case SBR_BS_INTERRUPTION:
- {
- int elementIndex;
-
- if (self == NULL) {
- errorStatus = SBRDEC_NOT_INITIALIZED;
- break;
- }
-
- /* Loop over SBR elements */
- for (elementIndex = 0; elementIndex < self->numSbrElements; elementIndex++)
- {
- HANDLE_SBR_HEADER_DATA hSbrHeader;
- int headerIndex = getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot,
- self->pSbrElement[elementIndex]->useHeaderSlot);
-
- hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]);
-
- /* Set sync state UPSAMPLING for the corresponding slot.
- This switches off bitstream parsing until a new header arrives. */
- hSbrHeader->syncState = UPSAMPLING;
- hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE;
- }
- }
- break;
- default:
- errorStatus = SBRDEC_SET_PARAM_FAIL;
- break;
- } /* switch(param) */
-
- return (errorStatus);
-}
-
-static
-SBRDEC_DRC_CHANNEL * sbrDecoder_drcGetChannel( const HANDLE_SBRDECODER self, const INT channel )
-{
- SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL;
- int elementIndex, elChanIdx=0, numCh=0;
-
- for (elementIndex = 0; (elementIndex < (4)) && (numCh <= channel); elementIndex++)
- {
- SBR_DECODER_ELEMENT *pSbrElement = self->pSbrElement[elementIndex];
- int c, elChannels;
-
- elChanIdx = 0;
- if (pSbrElement == NULL) break;
-
- /* Determine amount of channels for this element */
- switch (pSbrElement->elementID) {
- case ID_CPE: elChannels = 2;
- break;
- case ID_LFE:
- case ID_SCE: elChannels = 1;
- break;
- case ID_NONE:
- default: elChannels = 0;
- break;
- }
-
- /* Limit with actual allocated element channels */
- elChannels = FDKmin(elChannels, pSbrElement->nChannels);
-
- for (c = 0; (c < elChannels) && (numCh <= channel); c++) {
- if (pSbrElement->pSbrChannel[elChanIdx] != NULL) {
- numCh++;
- elChanIdx++;
- }
- }
- }
- elementIndex -= 1;
- elChanIdx -= 1;
-
- if (elChanIdx < 0 || elementIndex < 0) {
- return NULL;
- }
-
- if ( self->pSbrElement[elementIndex] != NULL ) {
- if ( self->pSbrElement[elementIndex]->pSbrChannel[elChanIdx] != NULL )
- {
- pSbrDrcChannelData = &self->pSbrElement[elementIndex]->pSbrChannel[elChanIdx]->SbrDec.sbrDrcChannel;
- }
- }
-
- return (pSbrDrcChannelData);
-}
-
-SBR_ERROR sbrDecoder_drcFeedChannel ( HANDLE_SBRDECODER self,
- INT ch,
- UINT numBands,
- FIXP_DBL *pNextFact_mag,
- INT nextFact_exp,
- SHORT drcInterpolationScheme,
- UCHAR winSequence,
- USHORT *pBandTop )
-{
- SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL;
- int band, isValidData = 0;
-
- if (self == NULL) {
- return SBRDEC_NOT_INITIALIZED;
- }
- if (ch > (6) || pNextFact_mag == NULL) {
- return SBRDEC_SET_PARAM_FAIL;
- }
-
- /* Search for gain values different to 1.0f */
- for (band = 0; band < numBands; band += 1) {
- if ( !((pNextFact_mag[band] == FL2FXCONST_DBL(0.5)) && (nextFact_exp == 1))
- && !((pNextFact_mag[band] == (FIXP_DBL)MAXVAL_DBL) && (nextFact_exp == 0)) ) {
- isValidData = 1;
- break;
- }
- }
-
- /* Find the right SBR channel */
- pSbrDrcChannelData = sbrDecoder_drcGetChannel( self, ch );
-
- if ( pSbrDrcChannelData != NULL ) {
- if ( pSbrDrcChannelData->enable || isValidData )
- { /* Activate processing only with real and valid data */
- int i;
-
- pSbrDrcChannelData->enable = 1;
- pSbrDrcChannelData->numBandsNext = numBands;
-
- pSbrDrcChannelData->winSequenceNext = winSequence;
- pSbrDrcChannelData->drcInterpolationSchemeNext = drcInterpolationScheme;
- pSbrDrcChannelData->nextFact_exp = nextFact_exp;
-
- for (i = 0; i < (int)numBands; i++) {
- pSbrDrcChannelData->bandTopNext[i] = pBandTop[i];
- pSbrDrcChannelData->nextFact_mag[i] = pNextFact_mag[i];
- }
- }
- }
-
- return SBRDEC_OK;
-}
-
-
-void sbrDecoder_drcDisable ( HANDLE_SBRDECODER self,
- INT ch )
-{
- SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL;
-
- if ( (self == NULL)
- || (ch > (6))
- || (self->numSbrElements == 0)
- || (self->numSbrChannels == 0) ) {
- return;
- }
-
- /* Find the right SBR channel */
- pSbrDrcChannelData = sbrDecoder_drcGetChannel( self, ch );
-
- if ( pSbrDrcChannelData != NULL ) {
- sbrDecoder_drcInitChannel( pSbrDrcChannelData );
- }
-}
-
-
-
-SBR_ERROR sbrDecoder_Parse(
- HANDLE_SBRDECODER self,
- HANDLE_FDK_BITSTREAM hBs,
- int *count,
- int bsPayLen,
- int crcFlag,
- MP4_ELEMENT_ID prevElement,
- int elementIndex,
- int fGlobalIndependencyFlag
- )
-{
- SBR_DECODER_ELEMENT *hSbrElement;
- HANDLE_SBR_HEADER_DATA hSbrHeader;
- HANDLE_SBR_CHANNEL *pSbrChannel;
-
- SBR_FRAME_DATA *hFrameDataLeft;
- SBR_FRAME_DATA *hFrameDataRight;
-
- SBR_ERROR errorStatus = SBRDEC_OK;
- SBR_SYNC_STATE initialSyncState;
- SBR_HEADER_STATUS headerStatus = HEADER_NOT_PRESENT;
-
- INT startPos;
- INT CRCLen = 0;
-
- int stereo;
- int fDoDecodeSbrData = 1;
-
- int lastSlot, lastHdrSlot = 0, thisHdrSlot;
-
- /* Remember start position of SBR element */
- startPos = FDKgetValidBits(hBs);
-
- /* SBR sanity checks */
- if ( self == NULL || self->pSbrElement[elementIndex] == NULL ) {
- errorStatus = SBRDEC_NOT_INITIALIZED;
- goto bail;
- }
-
- hSbrElement = self->pSbrElement[elementIndex];
-
- lastSlot = (hSbrElement->useFrameSlot > 0) ? hSbrElement->useFrameSlot-1 : self->numDelayFrames;
- lastHdrSlot = hSbrElement->useHeaderSlot[lastSlot];
- thisHdrSlot = getHeaderSlot( hSbrElement->useFrameSlot, hSbrElement->useHeaderSlot ); /* Get a free header slot not used by frames not processed yet. */
-
- /* Assign the free slot to store a new header if there is one. */
- hSbrHeader = &self->sbrHeader[elementIndex][thisHdrSlot];
-
- pSbrChannel = hSbrElement->pSbrChannel;
- stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0;
-
- hFrameDataLeft = &self->pSbrElement[elementIndex]->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
- hFrameDataRight = &self->pSbrElement[elementIndex]->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot];
-
- initialSyncState = hSbrHeader->syncState;
-
- /* reset PS flag; will be set after PS was found */
- self->flags &= ~SBRDEC_PS_DECODED;
-
- if (hSbrHeader->status & SBRDEC_HDR_STAT_UPDATE) {
- /* Got a new header from extern (e.g. from an ASC) */
- headerStatus = HEADER_OK;
- hSbrHeader->status &= ~SBRDEC_HDR_STAT_UPDATE;
- }
- else if (thisHdrSlot != lastHdrSlot) {
- /* Copy the last header into this slot otherwise the
- header compare will trigger more HEADER_RESETs than needed. */
- copySbrHeader( hSbrHeader, &self->sbrHeader[elementIndex][lastHdrSlot] );
- }
-
- /*
- Check if bit stream data is valid and matches the element context
- */
- if ( ((prevElement != ID_SCE) && (prevElement != ID_CPE)) || prevElement != hSbrElement->elementID) {
- /* In case of LFE we also land here, since there is no LFE SBR element (do upsampling only) */
- fDoDecodeSbrData = 0;
- }
-
- if (fDoDecodeSbrData)
- {
- if ((INT)FDKgetValidBits(hBs) <= 0) {
- fDoDecodeSbrData = 0;
- }
- }
-
- /*
- SBR CRC-check
- */
- if (fDoDecodeSbrData)
- {
- if (crcFlag == 1) {
- switch (self->coreCodec) {
- case AOT_ER_AAC_ELD:
- FDKpushFor (hBs, 10);
- /* check sbrcrc later: we don't know the payload length now */
- break;
- default:
- CRCLen = bsPayLen - 10; /* change: 0 => i */
- if (CRCLen < 0) {
- fDoDecodeSbrData = 0;
- } else {
- fDoDecodeSbrData = SbrCrcCheck (hBs, CRCLen);
- }
- break;
- }
- }
- } /* if (fDoDecodeSbrData) */
-
- /*
- Read in the header data and issue a reset if change occured
- */
- if (fDoDecodeSbrData)
- {
- int sbrHeaderPresent;
-
- {
- sbrHeaderPresent = FDKreadBit(hBs);
- }
-
- if ( sbrHeaderPresent ) {
- headerStatus = sbrGetHeaderData (hSbrHeader,
- hBs,
- self->flags,
- 1);
- }
-
- if (headerStatus == HEADER_RESET)
- {
- errorStatus = sbrDecoder_HeaderUpdate(
- self,
- hSbrHeader,
- headerStatus,
- pSbrChannel,
- hSbrElement->nChannels
- );
-
- if (errorStatus == SBRDEC_OK) {
- hSbrHeader->syncState = SBR_HEADER;
- } else {
- hSbrHeader->syncState = SBR_NOT_INITIALIZED;
- }
- }
-
- if (errorStatus != SBRDEC_OK) {
- fDoDecodeSbrData = 0;
- }
- } /* if (fDoDecodeSbrData) */
-
- /*
- Print debugging output only if state has changed
- */
-
- /* read frame data */
- if ((hSbrHeader->syncState >= SBR_HEADER) && fDoDecodeSbrData) {
- int sbrFrameOk;
- /* read the SBR element data */
- if (stereo) {
- sbrFrameOk = sbrGetChannelPairElement(hSbrHeader,
- hFrameDataLeft,
- hFrameDataRight,
- hBs,
- self->flags,
- self->pSbrElement[elementIndex]->transposerSettings.overlap);
- }
- else {
- if (self->hParametricStereoDec != NULL) {
- /* update slot index for PS bitstream parsing */
- self->hParametricStereoDec->bsLastSlot = self->hParametricStereoDec->bsReadSlot;
- self->hParametricStereoDec->bsReadSlot = hSbrElement->useFrameSlot;
- }
- sbrFrameOk = sbrGetSingleChannelElement(hSbrHeader,
- hFrameDataLeft,
- hBs,
- self->hParametricStereoDec,
- self->flags,
- self->pSbrElement[elementIndex]->transposerSettings.overlap);
- }
- if (!sbrFrameOk) {
- fDoDecodeSbrData = 0;
- }
- else {
- INT valBits;
-
- if (bsPayLen > 0) {
- valBits = bsPayLen - ((INT)startPos - (INT)FDKgetValidBits(hBs));
- } else {
- valBits = (INT)FDKgetValidBits(hBs);
- }
-
- if ( crcFlag == 1 ) {
- switch (self->coreCodec) {
- case AOT_ER_AAC_ELD:
- {
- /* late crc check for eld */
- INT payloadbits = (INT)startPos - (INT)FDKgetValidBits(hBs) - startPos;
- INT crcLen = payloadbits - 10;
- FDKpushBack(hBs, payloadbits);
- fDoDecodeSbrData = SbrCrcCheck (hBs, crcLen);
- FDKpushFor(hBs, crcLen);
- }
- break;
- default:
- break;
- }
- }
-
- /* sanity check of remaining bits */
- if (valBits < 0) {
- fDoDecodeSbrData = 0;
- } else {
- switch (self->coreCodec) {
- case AOT_SBR:
- case AOT_PS:
- case AOT_AAC_LC:
- {
- /* This sanity check is only meaningful with General Audio bitstreams */
- int alignBits = valBits & 0x7;
-
- if (valBits > alignBits) {
- fDoDecodeSbrData = 0;
- }
- }
- break;
- default:
- /* No sanity check available */
- break;
- }
- }
- }
- }
-
- if (!fDoDecodeSbrData) {
- /* Set error flag for this slot to trigger concealment */
- self->pSbrElement[elementIndex]->frameErrorFlag[hSbrElement->useFrameSlot] = 1;
- errorStatus = SBRDEC_PARSE_ERROR;
- } else {
- /* Everything seems to be ok so clear the error flag */
- self->pSbrElement[elementIndex]->frameErrorFlag[hSbrElement->useFrameSlot] = 0;
- }
-
- if (!stereo) {
- /* Turn coupling off explicitely to avoid access to absent right frame data
- that might occur with corrupt bitstreams. */
- hFrameDataLeft->coupling = COUPLING_OFF;
- }
-
-bail:
- if (errorStatus == SBRDEC_OK) {
- if (headerStatus == HEADER_NOT_PRESENT) {
- /* Use the old header for this frame */
- hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = lastHdrSlot;
- } else {
- /* Use the new header for this frame */
- hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = thisHdrSlot;
- }
-
- /* Move frame pointer to the next slot which is up to be decoded/applied next */
- hSbrElement->useFrameSlot = (hSbrElement->useFrameSlot+1) % (self->numDelayFrames+1);
- }
-
- *count -= startPos - FDKgetValidBits(hBs);
-
- return errorStatus;
-}
-
-
-/**
- * \brief Render one SBR element into time domain signal.
- * \param self SBR decoder handle
- * \param timeData pointer to output buffer
- * \param interleaved flag indicating interleaved channel output
- * \param channelMapping pointer to UCHAR array where next 2 channel offsets are stored.
- * \param elementIndex enumerating index of the SBR element to render.
- * \param numInChannels number of channels from core coder (reading stride).
- * \param numOutChannels pointer to a location to return number of output channels.
- * \param psPossible flag indicating if PS is possible or not.
- * \return SBRDEC_OK if successfull, else error code
- */
-static SBR_ERROR
-sbrDecoder_DecodeElement (
- HANDLE_SBRDECODER self,
- INT_PCM *timeData,
- const int interleaved,
- const UCHAR *channelMapping,
- const int elementIndex,
- const int numInChannels,
- int *numOutChannels,
- const int psPossible
- )
-{
- SBR_DECODER_ELEMENT *hSbrElement = self->pSbrElement[elementIndex];
- HANDLE_SBR_CHANNEL *pSbrChannel = self->pSbrElement[elementIndex]->pSbrChannel;
- HANDLE_SBR_HEADER_DATA hSbrHeader = &self->sbrHeader[elementIndex][hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]];
- HANDLE_PS_DEC h_ps_d = self->hParametricStereoDec;
-
- /* get memory for frame data from scratch */
- SBR_FRAME_DATA *hFrameDataLeft = &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
- SBR_FRAME_DATA *hFrameDataRight = &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot];
-
- SBR_ERROR errorStatus = SBRDEC_OK;
-
-
- INT strideIn, strideOut, offset0, offset1;
- INT codecFrameSize = self->codecFrameSize;
-
- int stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0;
- int numElementChannels = hSbrElement->nChannels; /* Number of channels of the current SBR element */
-
- /* Update the header error flag */
- hSbrHeader->frameErrorFlag = hSbrElement->frameErrorFlag[hSbrElement->useFrameSlot];
-
- /*
- Prepare filterbank for upsampling if no valid bit stream data is available.
- */
- if ( hSbrHeader->syncState == SBR_NOT_INITIALIZED )
- {
- errorStatus = initHeaderData(
- hSbrHeader,
- self->sampleRateIn,
- self->sampleRateOut,
- codecFrameSize,
- self->flags
- );
-
- if (errorStatus != SBRDEC_OK) {
- return errorStatus;
- }
-
- hSbrHeader->syncState = UPSAMPLING;
-
- errorStatus = sbrDecoder_HeaderUpdate(
- self,
- hSbrHeader,
- HEADER_NOT_PRESENT,
- pSbrChannel,
- hSbrElement->nChannels
- );
-
- if (errorStatus != SBRDEC_OK) {
- hSbrHeader->syncState = SBR_NOT_INITIALIZED;
- return errorStatus;
- }
- }
-
- /* reset */
- if (hSbrHeader->status & SBRDEC_HDR_STAT_RESET) {
- int ch;
- for (ch = 0 ; ch < numElementChannels; ch++) {
- SBR_ERROR errorStatusTmp = SBRDEC_OK;
-
- errorStatusTmp = resetSbrDec (
- &pSbrChannel[ch]->SbrDec,
- hSbrHeader,
- &pSbrChannel[ch]->prevFrameData,
- self->flags & SBRDEC_LOW_POWER,
- self->synDownsampleFac
- );
-
- if (errorStatusTmp != SBRDEC_OK) {
- errorStatus = errorStatusTmp;
- }
- }
- hSbrHeader->status &= ~SBRDEC_HDR_STAT_RESET;
- }
-
- /* decoding */
- if ( (hSbrHeader->syncState == SBR_ACTIVE)
- || ((hSbrHeader->syncState == SBR_HEADER) && (hSbrHeader->frameErrorFlag == 0)) )
- {
- errorStatus = SBRDEC_OK;
-
- decodeSbrData (hSbrHeader,
- hFrameDataLeft,
- &pSbrChannel[0]->prevFrameData,
- (stereo) ? hFrameDataRight : NULL,
- (stereo) ? &pSbrChannel[1]->prevFrameData : NULL);
-
-
- /* Now we have a full parameter set and can do parameter
- based concealment instead of plain upsampling. */
- hSbrHeader->syncState = SBR_ACTIVE;
- }
-
- /* decode PS data if available */
- if (h_ps_d != NULL && psPossible) {
- int applyPs = 1;
-
- /* define which frame delay line slot to process */
- h_ps_d->processSlot = hSbrElement->useFrameSlot;
-
- applyPs = DecodePs(h_ps_d, hSbrHeader->frameErrorFlag);
- self->flags |= (applyPs) ? SBRDEC_PS_DECODED : 0;
- }
-
- /* Set strides for reading and writing */
- if (interleaved) {
- strideIn = numInChannels;
- if ( psPossible )
- strideOut = (numInChannels < 2) ? 2 : numInChannels;
- else
- strideOut = numInChannels;
- offset0 = channelMapping[0];
- offset1 = channelMapping[1];
- } else {
- strideIn = 1;
- strideOut = 1;
- offset0 = channelMapping[0]*2*codecFrameSize;
- offset1 = channelMapping[1]*2*codecFrameSize;
- }
-
- /* use same buffers for left and right channel and apply PS per timeslot */
- /* Process left channel */
-//FDKprintf("self->codecFrameSize %d\t%d\n",self->codecFrameSize,self->sampleRateIn);
- sbr_dec (&pSbrChannel[0]->SbrDec,
- timeData + offset0,
- timeData + offset0,
- &pSbrChannel[1]->SbrDec,
- timeData + offset1,
- strideIn,
- strideOut,
- hSbrHeader,
- hFrameDataLeft,
- &pSbrChannel[0]->prevFrameData,
- (hSbrHeader->syncState == SBR_ACTIVE),
- h_ps_d,
- self->flags
- );
-
- if (stereo) {
- /* Process right channel */
- sbr_dec (&pSbrChannel[1]->SbrDec,
- timeData + offset1,
- timeData + offset1,
- NULL,
- NULL,
- strideIn,
- strideOut,
- hSbrHeader,
- hFrameDataRight,
- &pSbrChannel[1]->prevFrameData,
- (hSbrHeader->syncState == SBR_ACTIVE),
- NULL,
- self->flags
- );
- }
-
- if (h_ps_d != NULL) {
- /* save PS status for next run */
- h_ps_d->psDecodedPrv = (self->flags & SBRDEC_PS_DECODED) ? 1 : 0 ;
- }
-
- if ( psPossible
- )
- {
- FDK_ASSERT(strideOut > 1);
- if ( !(self->flags & SBRDEC_PS_DECODED) ) {
- /* A decoder which is able to decode PS has to produce a stereo output even if no PS data is availble. */
- /* So copy left channel to right channel. */
- if (interleaved) {
- INT_PCM *ptr;
- INT i;
- FDK_ASSERT(strideOut == 2);
-
- ptr = timeData;
- for (i = codecFrameSize; i--; )
- {
- INT_PCM tmp; /* This temporal variable is required because some compilers can't do *ptr++ = *ptr++ correctly. */
- tmp = *ptr++; *ptr++ = tmp;
- tmp = *ptr++; *ptr++ = tmp;
- }
- } else {
- FDKmemcpy( timeData+2*codecFrameSize, timeData, 2*codecFrameSize*sizeof(INT_PCM) );
- }
- }
- *numOutChannels = 2; /* Output minimum two channels when PS is enabled. */
- }
-
- return errorStatus;
-}
-
-
-SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self,
- INT_PCM *timeData,
- int *numChannels,
- int *sampleRate,
- const UCHAR channelMapping[(6)],
- const int interleaved,
- const int coreDecodedOk,
- UCHAR *psDecoded )
-{
- SBR_ERROR errorStatus = SBRDEC_OK;
-
- int psPossible = 0;
- int sbrElementNum;
- int numCoreChannels = *numChannels;
- int numSbrChannels = 0;
-
- psPossible = *psDecoded;
-
- if (self->numSbrElements < 1) {
- /* exit immediately to avoid access violations */
- return SBRDEC_CREATE_ERROR;
- }
-
- /* Sanity check of allocated SBR elements. */
- for (sbrElementNum=0; sbrElementNum<self->numSbrElements; sbrElementNum++) {
- if (self->pSbrElement[sbrElementNum] == NULL) {
- return SBRDEC_CREATE_ERROR;
- }
- }
-
- if (self->numSbrElements != 1 || self->pSbrElement[0]->elementID != ID_SCE) {
- psPossible = 0;
- }
-
-
- /* In case of non-interleaved time domain data and upsampling, make room for bigger SBR output. */
- if (self->synDownsampleFac == 1 && interleaved == 0) {
- int c, outputFrameSize;
-
- outputFrameSize =
- self->pSbrElement[0]->pSbrChannel[0]->SbrDec.SynthesisQMF.no_channels
- * self->pSbrElement[0]->pSbrChannel[0]->SbrDec.SynthesisQMF.no_col;
-
- for (c=numCoreChannels-1; c>0; c--) {
- FDKmemmove(timeData + c*outputFrameSize, timeData + c*self->codecFrameSize , self->codecFrameSize*sizeof(INT_PCM));
- }
- }
-
-
- /* Make sure that even if no SBR data was found/parsed *psDecoded is returned 1 if psPossible was 0. */
- if (psPossible == 0) {
- self->flags &= ~SBRDEC_PS_DECODED;
- }
-
- /* Loop over SBR elements */
- for (sbrElementNum = 0; sbrElementNum<self->numSbrElements; sbrElementNum++)
- {
- int numElementChan;
-
- if (psPossible && self->pSbrElement[sbrElementNum]->pSbrChannel[1] == NULL) {
- errorStatus = SBRDEC_UNSUPPORTED_CONFIG;
- goto bail;
- }
-
- numElementChan = (self->pSbrElement[sbrElementNum]->elementID == ID_CPE) ? 2 : 1;
-
- /* If core signal is bad then force upsampling */
- if ( ! coreDecodedOk ) {
- self->pSbrElement[sbrElementNum]->frameErrorFlag[self->pSbrElement[sbrElementNum]->useFrameSlot] = 1;
- }
-
- errorStatus = sbrDecoder_DecodeElement (
- self,
- timeData,
- interleaved,
- channelMapping,
- sbrElementNum,
- numCoreChannels,
- &numElementChan,
- psPossible
- );
-
- if (errorStatus != SBRDEC_OK) {
- goto bail;
- }
-
- numSbrChannels += numElementChan;
- channelMapping += numElementChan;
-
- if (numSbrChannels >= numCoreChannels) {
- break;
- }
- }
-
- /* Update numChannels and samplerate */
- *numChannels = numSbrChannels;
- *sampleRate = self->sampleRateOut;
- *psDecoded = (self->flags & SBRDEC_PS_DECODED) ? 1 : 0;
-
-
-
-bail:
-
- return errorStatus;
-}
-
-
-SBR_ERROR sbrDecoder_Close ( HANDLE_SBRDECODER *pSelf )
-{
- HANDLE_SBRDECODER self = *pSelf;
- int i;
-
- if (self != NULL)
- {
- if (self->hParametricStereoDec != NULL) {
- DeletePsDec ( &self->hParametricStereoDec );
- }
-
- if (self->workBuffer1 != NULL) {
- FreeRam_SbrDecWorkBuffer1(&self->workBuffer1);
- }
- if (self->workBuffer2 != NULL) {
- FreeRam_SbrDecWorkBuffer2(&self->workBuffer2);
- }
-
- for (i = 0; i < (4); i++) {
- sbrDecoder_DestroyElement( self, i );
- }
-
- FreeRam_SbrDecoder(pSelf);
- }
-
- return SBRDEC_OK;
-}
-
-
-INT sbrDecoder_GetLibInfo( LIB_INFO *info )
-{
- int i;
-
- if (info == NULL) {
- return -1;
- }
-
- /* search for next free tab */
- for (i = 0; i < FDK_MODULE_LAST; i++) {
- if (info[i].module_id == FDK_NONE)
- break;
- }
- if (i == FDK_MODULE_LAST)
- return -1;
- info += i;
-
- info->module_id = FDK_SBRDEC;
- info->version = LIB_VERSION(SBRDECODER_LIB_VL0, SBRDECODER_LIB_VL1, SBRDECODER_LIB_VL2);
- LIB_VERSION_STRING(info);
- info->build_date = (char *)SBRDECODER_LIB_BUILD_DATE;
- info->build_time = (char *)SBRDECODER_LIB_BUILD_TIME;
- info->title = (char *)SBRDECODER_LIB_TITLE;
-
- /* Set flags */
- info->flags = 0
- | CAPF_SBR_HQ
- | CAPF_SBR_LP
- | CAPF_SBR_PS_MPEG
- | CAPF_SBR_CONCEALMENT
- | CAPF_SBR_DRC
- ;
- /* End of flags */
-
- return 0;
-}
-