diff options
Diffstat (limited to 'libSBRdec')
45 files changed, 16747 insertions, 10852 deletions
diff --git a/libSBRdec/include/sbrdecoder.h b/libSBRdec/include/sbrdecoder.h index 3bb9ba3..cc55572 100644 --- a/libSBRdec/include/sbrdecoder.h +++ b/libSBRdec/include/sbrdecoder.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,25 +90,28 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -/************************ Fraunhofer IIS SBR decoder library ****************** +/**************************** SBR decoder library ****************************** Author(s): + Description: SBR decoder front-end prototypes and definitions. -******************************************************************************/ +*******************************************************************************/ -#ifndef __SBRDECODER_H -#define __SBRDECODER_H +#ifndef SBRDECODER_H +#define SBRDECODER_H #include "common_fix.h" #include "FDK_bitstream.h" #include "FDK_audio.h" +#include "FDK_qmf_domain.h" -#define SBR_DEBUG_EXTHLP "\ +#define SBR_DEBUG_EXTHLP \ + "\ --- SBR ---\n\ 0x00000010 Ancillary data and SBR-Header\n\ 0x00000020 SBR-Side info\n\ @@ -110,64 +124,92 @@ amm-info@iis.fraunhofer.de " /* Capability flags */ -#define CAPF_SBR_LP 0x00000001 /*!< Flag indicating library's capability of Low Power mode. */ -#define CAPF_SBR_HQ 0x00000002 /*!< Flag indicating library's capability of High Quality mode. */ -#define CAPF_SBR_DRM_BS 0x00000004 /*!< Flag indicating library's capability to decode DRM SBR data. */ -#define CAPF_SBR_CONCEALMENT 0x00000008 /*!< Flag indicating library's capability to conceal erroneous frames. */ -#define CAPF_SBR_DRC 0x00000010 /*!< Flag indicating library's capability for Dynamic Range Control. */ -#define CAPF_SBR_PS_MPEG 0x00000020 /*!< Flag indicating library's capability to do MPEG Parametric Stereo. */ -#define CAPF_SBR_PS_DRM 0x00000040 /*!< Flag indicating library's capability to do DRM Parametric Stereo. */ - -typedef enum -{ - SBRDEC_OK = 0, /*!< All fine. */ - /* SBRDEC_CONCEAL, */ - /* SBRDEC_NOSYNCH, */ - /* SBRDEC_ILLEGAL_PROGRAM, */ - /* SBRDEC_ILLEGAL_TAG, */ - /* SBRDEC_ILLEGAL_CHN_CONFIG, */ - /* SBRDEC_ILLEGAL_SECTION, */ - /* SBRDEC_ILLEGAL_SCFACTORS, */ - /* SBRDEC_ILLEGAL_PULSE_DATA, */ - /* SBRDEC_MAIN_PROFILE_NOT_IMPLEMENTED, */ - /* SBRDEC_GC_NOT_IMPLEMENTED, */ - /* SBRDEC_ILLEGAL_PLUS_ELE_ID, */ - SBRDEC_CREATE_ERROR, /*!< */ - SBRDEC_NOT_INITIALIZED, /*!< */ - SBRDEC_MEM_ALLOC_FAILED, /*!< Memory allocation failed. Probably not enough memory available. */ - SBRDEC_PARSE_ERROR, /*!< */ - SBRDEC_UNSUPPORTED_CONFIG, /*!< */ - SBRDEC_SET_PARAM_FAIL /*!< */ +#define CAPF_SBR_LP \ + 0x00000001 /*!< Flag indicating library's capability of Low Power mode. */ +#define CAPF_SBR_HQ \ + 0x00000002 /*!< Flag indicating library's capability of High Quality mode. \ + */ +#define CAPF_SBR_DRM_BS \ + 0x00000004 /*!< Flag indicating library's capability to decode DRM SBR data. \ + */ +#define CAPF_SBR_CONCEALMENT \ + 0x00000008 /*!< Flag indicating library's capability to conceal erroneous \ + frames. */ +#define CAPF_SBR_DRC \ + 0x00000010 /*!< Flag indicating library's capability for Dynamic Range \ + Control. */ +#define CAPF_SBR_PS_MPEG \ + 0x00000020 /*!< Flag indicating library's capability to do MPEG Parametric \ + Stereo. */ +#define CAPF_SBR_PS_DRM \ + 0x00000040 /*!< Flag indicating library's capability to do DRM Parametric \ + Stereo. */ +#define CAPF_SBR_ELD_DOWNSCALE \ + 0x00000080 /*!< Flag indicating library's capability to do ELD decoding in \ + downscaled mode */ +#define CAPF_SBR_HBEHQ \ + 0x00000100 /*!< Flag indicating library's capability to do HQ Harmonic \ + transposing */ + +typedef enum { + SBRDEC_OK = 0, /*!< All fine. */ + /* SBRDEC_CONCEAL, */ + /* SBRDEC_NOSYNCH, */ + /* SBRDEC_ILLEGAL_PROGRAM, */ + /* SBRDEC_ILLEGAL_TAG, */ + /* SBRDEC_ILLEGAL_CHN_CONFIG, */ + /* SBRDEC_ILLEGAL_SECTION, */ + /* SBRDEC_ILLEGAL_SCFACTORS, */ + /* SBRDEC_ILLEGAL_PULSE_DATA, */ + /* SBRDEC_MAIN_PROFILE_NOT_IMPLEMENTED, */ + /* SBRDEC_GC_NOT_IMPLEMENTED, */ + /* SBRDEC_ILLEGAL_PLUS_ELE_ID, */ + SBRDEC_INVALID_ARGUMENT, /*!< */ + SBRDEC_CREATE_ERROR, /*!< */ + SBRDEC_NOT_INITIALIZED, /*!< */ + SBRDEC_MEM_ALLOC_FAILED, /*!< Memory allocation failed. Probably not enough + memory available. */ + SBRDEC_PARSE_ERROR, /*!< */ + SBRDEC_UNSUPPORTED_CONFIG, /*!< */ + SBRDEC_SET_PARAM_FAIL, /*!< */ + SBRDEC_OUTPUT_BUFFER_TOO_SMALL /*!< */ } SBR_ERROR; -typedef enum -{ - SBR_SYSTEM_BITSTREAM_DELAY, /*!< System: Switch to enable an additional SBR bitstream delay of one frame. */ - SBR_QMF_MODE, /*!< Set QMF mode, either complex or low power. */ - SBR_LD_QMF_TIME_ALIGN, /*!< Set QMF type, either LD-MPS or CLDFB. Relevant for ELD streams only. */ - SBR_FLUSH_DATA, /*!< Set internal state to flush the decoder with the next process call. */ - SBR_CLEAR_HISTORY, /*!< Clear all internal states (delay lines, QMF states, ...). */ - SBR_BS_INTERRUPTION /*!< Signal bit stream interruption. Value is ignored. */ +typedef enum { + SBR_SYSTEM_BITSTREAM_DELAY, /*!< System: Switch to enable an additional SBR + bitstream delay of one frame. */ + SBR_QMF_MODE, /*!< Set QMF mode, either complex or low power. */ + SBR_LD_QMF_TIME_ALIGN, /*!< Set QMF type, either LD-MPS or CLDFB. Relevant for + ELD streams only. */ + SBR_FLUSH_DATA, /*!< Set internal state to flush the decoder with the next + process call. */ + SBR_CLEAR_HISTORY, /*!< Clear all internal states (delay lines, QMF states, + ...). */ + SBR_BS_INTERRUPTION /*!< Signal bit stream interruption. Value is ignored. */ + , + SBR_SKIP_QMF /*!< Enable skipping of QMF step: 1 skip analysis, 2 skip + synthesis */ } SBRDEC_PARAM; typedef struct SBR_DECODER_INSTANCE *HANDLE_SBRDECODER; - #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif - /** - * \brief Allocates and initializes one SBR decoder instance. - * \param pSelf Pointer to where a SBR decoder handle is copied into. - * \return Error code. + * \brief Allocates and initializes one SBR decoder instance. + * \param pSelf Pointer to where a SBR decoder handle is copied into. + * \param pQmfDomain Pointer to QMF domain data structure. + * + * \return Error code. */ -SBR_ERROR sbrDecoder_Open ( HANDLE_SBRDECODER *pSelf ); +SBR_ERROR sbrDecoder_Open(HANDLE_SBRDECODER *pSelf, + HANDLE_FDK_QMF_DOMAIN pQmfDomain); /** - * \brief Initialize a SBR decoder runtime instance. Must be called before decoding starts. + * \brief Initialize a SBR decoder runtime instance. Must be called before + * decoding starts. * * \param self Handle to a SBR decoder instance. * \param sampleRateIn Input samplerate of the SBR decoder instance. @@ -175,40 +217,52 @@ SBR_ERROR sbrDecoder_Open ( HANDLE_SBRDECODER *pSelf ); * \param samplesPerFrame Number of samples per frames. * \param coreCodec Audio Object Type (AOT) of the core codec. * \param elementID Table with MPEG-4 element Ids in canonical order. - * \param forceReset Flag that enforces a complete decoder reset. + * \param elementIndex SBR element index + * \param harmonicSBR + * \param stereoConfigIndex + * \param downscaleFactor ELD downscale factor + * \param configMode Table with MPEG-4 element Ids in canonical order. + * \param configChanged Flag that enforces a complete decoder reset. * * \return Error code. */ -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 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, + const UCHAR harmonicSBR, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, const INT downscaleFactor); + +/** + * \brief Free config dependent SBR memory. + * \param self SBR decoder instance handle + */ +SBR_ERROR sbrDecoder_FreeMem(HANDLE_SBRDECODER *self); /** * \brief pass out of band SBR header to SBR decoder * * \param self Handle to a SBR decoder instance. * \param hBs bit stream handle data source. + * \param sampleRateIn SBR input sampling rate + * \param sampleRateOut SBR output sampling rate + * \param samplesPerFrame frame length * \param elementID SBR element ID. * \param elementIndex SBR element index. + * \param harmonicSBR + * \param stereoConfigIndex + * \param downscaleFactor ELD downscale factor * * \return Error code. */ -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 - ); +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, + const UCHAR harmonicSBR, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, + const INT downscaleFactor); /** * \brief Set a parameter of the SBR decoder runtime instance. @@ -217,32 +271,32 @@ INT sbrDecoder_Header ( * \param value New parameter value. * \return Error code. */ -SBR_ERROR sbrDecoder_SetParam ( HANDLE_SBRDECODER self, - const SBRDEC_PARAM param, - const INT value ); +SBR_ERROR sbrDecoder_SetParam(HANDLE_SBRDECODER self, const SBRDEC_PARAM param, + const INT value); /** * \brief Feed DRC channel data into a SBR decoder runtime instance. * * \param self SBR decoder handle. - * \param ch Channel number to which the DRC data is associated to. + * \param ch Channel number to which the DRC data is + * associated to. * \param numBands Number of DRC bands. - * \param pNextFact_mag Pointer to a table with the DRC factor magnitudes. + * \param pNextFact_mag Pointer to a table with the DRC factor + * magnitudes. * \param nextFact_exp Exponent for all DRC factors. * \param drcInterpolationScheme DRC interpolation scheme. - * \param winSequence Window sequence from core coder (eight short or one long window). - * \param pBandTop Pointer to a table with the top borders for all DRC bands. + * \param winSequence Window sequence from core coder (eight short + * or one long window). + * \param pBandTop Pointer to a table with the top borders for + * all DRC bands. * * \return Error code. */ -SBR_ERROR sbrDecoder_drcFeedChannel ( HANDLE_SBRDECODER self, - INT ch, - UINT numBands, - FIXP_DBL *pNextFact_mag, - INT nextFact_exp, - SHORT drcInterpolationScheme, - UCHAR winSequence, - USHORT *pBandTop ); +SBR_ERROR sbrDecoder_drcFeedChannel(HANDLE_SBRDECODER self, INT ch, + UINT numBands, FIXP_DBL *pNextFact_mag, + INT nextFact_exp, + SHORT drcInterpolationScheme, + UCHAR winSequence, USHORT *pBandTop); /** * \brief Disable SBR DRC for a certain channel. @@ -252,42 +306,41 @@ SBR_ERROR sbrDecoder_drcFeedChannel ( HANDLE_SBRDECODER self, * * \return None. */ -void sbrDecoder_drcDisable ( HANDLE_SBRDECODER self, - INT ch ); - +void sbrDecoder_drcDisable(HANDLE_SBRDECODER self, INT ch); /** - * \brief Parse one SBR element data extension data block. The bit stream position will - * be placed at the end of the SBR payload block. The remaining bits will be returned - * into *count if a payload length is given (byPayLen > 0). If no SBR payload length is - * given (bsPayLen < 0) then the bit stream position on return will be random after this - * function call in case of errors, and any further decoding will be completely pointless. - * This function accepts either normal ordered SBR data or reverse ordered DRM SBR data. + * \brief Parse one SBR element data extension data block. The bit stream + * position will be placed at the end of the SBR payload block. The remaining + * bits will be returned into *count if a payload length is given + * (byPayLen > 0). If no SBR payload length is given (bsPayLen < 0) then + * the bit stream position on return will be random after this function + * call in case of errors, and any further decoding will be completely + * pointless. This function accepts either normal ordered SBR data or reverse + * ordered DRM SBR data. * * \param self SBR decoder handle. * \param hBs Bit stream handle as data source. - * \param count Pointer to an integer where the amount of parsed SBR payload bits is stored into. - * \param bsPayLen If > 0 this value is the SBR payload length. If < 0, the SBR payload length is unknown. + * \param count Pointer to an integer where the amount of parsed SBR + * payload bits is stored into. + * \param bsPayLen If > 0 this value is the SBR payload length. If < 0, + * the SBR payload length is unknown. * \param flags CRC flag (0: EXT_SBR_DATA; 1: EXT_SBR_DATA_CRC) * \param prev_element Previous MPEG-4 element ID. * \param element_index Index of the current element. + * \param acFlags Audio codec flags * * \return Error code. */ -SBR_ERROR sbrDecoder_Parse ( - HANDLE_SBRDECODER self, - HANDLE_FDK_BITSTREAM hBs, - int *count, - int bsPayLen, - int crcFlag, - MP4_ELEMENT_ID prev_element, - int element_index, - int fGlobalIndependencyFlag - ); +SBR_ERROR sbrDecoder_Parse(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs, + UCHAR *pDrmBsBuffer, USHORT drmBsBufferSize, + int *count, int bsPayLen, int crcFlag, + MP4_ELEMENT_ID prev_element, int element_index, + UINT acFlags, UINT acElFlags[]); /** - * \brief This function decodes the given SBR bitstreams and applies SBR to the given time data. - * + * \brief This function decodes the given SBR bitstreams and applies SBR to the + * given time data. + * * SBR-processing works InPlace. I.e. the calling function has to provide * a time domain buffer timeData which can hold the completely decoded * result. @@ -297,48 +350,49 @@ SBR_ERROR sbrDecoder_Parse ( * * \param self Handle of an open SBR decoder instance. * \param hSbrBs SBR Bitstream handle. - * \param timeData Pointer to input and finally upsampled output data. - * \param numChannels Pointer to a buffer holding the number of channels in time data buffer. + * \param input Pointer to input data. + * \param timeData Pointer to upsampled output data. + * \param timeDataSize Size of timeData. + * \param numChannels Pointer to a buffer holding the number of channels in + * time data buffer. * \param sampleRate Output samplerate. * \param channelMapping Channel mapping indices. - * \param interleaved Flag indicating if time data is stored interleaved (1: Interleaved time data, 0: non-interleaved timedata). - * \param coreDecodedOk Flag indicating if the core decoder did not find any error (0: core decoder found errors, 1: no errors). - * \param psDecoded Pointer to a buffer holding a flag. Input: PS is possible, Output: PS has been rendered. + * \param coreDecodedOk Flag indicating if the core decoder did not find any + * error (0: core decoder found errors, 1: no errors). + * \param psDecoded Pointer to a buffer holding a flag. Input: PS is + * possible, Output: PS has been rendered. * * \return Error code. */ -SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self, - INT_PCM *timeData, - int *numChannels, - int *sampleRate, - const UCHAR channelMapping[(8)], - const int interleaved, - const int coreDecodedOk, - UCHAR *psDecoded ); - +SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, INT_PCM *input, + INT_PCM *timeData, const int timeDataSize, + int *numChannels, int *sampleRate, + const FDK_channelMapDescr *const mapDescr, + const int mapIdx, const int coreDecodedOk, + UCHAR *psDecoded); /** * \brief Close SBR decoder instance and free memory. * \param self SBR decoder handle. * \return Error Code. */ -SBR_ERROR sbrDecoder_Close ( HANDLE_SBRDECODER *self ); - +SBR_ERROR sbrDecoder_Close(HANDLE_SBRDECODER *self); /** * \brief Get SBR decoder library information. - * \param info Pointer to a LIB_INFO struct, where library information is written to. - * \return 0 on success, -1 if invalid handle or if no free element is available to write information to. + * \param info Pointer to a LIB_INFO struct, where library information is + * written to. + * \return 0 on success, -1 if invalid handle or if no free element is + * available to write information to. */ -INT sbrDecoder_GetLibInfo( LIB_INFO *info ); +INT sbrDecoder_GetLibInfo(LIB_INFO *info); /** * \brief Determine the modules output signal delay in samples. * \param self SBR decoder handle. * \return The number of samples signal delay added by the module. */ -UINT sbrDecoder_GetDelay( const HANDLE_SBRDECODER self ); - +UINT sbrDecoder_GetDelay(const HANDLE_SBRDECODER self); #ifdef __cplusplus } diff --git a/libSBRdec/src/HFgen_preFlat.cpp b/libSBRdec/src/HFgen_preFlat.cpp new file mode 100644 index 0000000..96adbb9 --- /dev/null +++ b/libSBRdec/src/HFgen_preFlat.cpp @@ -0,0 +1,993 @@ +/* ----------------------------------------------------------------------------- +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): Oliver Moser, Manuel Jander, Matthias Hildenbrand + + Description: QMF frequency pre-whitening for SBR. + In the documentation the terms "scale factor" and "exponent" + mean the same. Variables containing such information have + the suffix "_sf". + +*******************************************************************************/ + +#include "HFgen_preFlat.h" + +#define POLY_ORDER 3 +#define MAXLOWBANDS 32 +#define LOG10FAC 0.752574989159953f /* == 10/log2(10) * 2^-2 */ +#define LOG10FAC_INV 0.664385618977472f /* == log2(10)/20 * 2^2 */ + +#define FIXP_CHB FIXP_SGL /* STB sinus Tab used in transformation */ +#define CHC(a) (FX_DBL2FXCONST_SGL(a)) +#define FX_CHB2FX_DBL(a) FX_SGL2FX_DBL(a) + +typedef struct backsubst_data { + FIXP_CHB Lnorm1d[3]; /*!< Normalized L matrix */ + SCHAR Lnorm1d_sf[3]; + FIXP_CHB Lnormii + [3]; /*!< The diagonal data points [i][i] of the normalized L matrix */ + SCHAR Lnormii_sf[3]; + FIXP_CHB Bmul0 + [4]; /*!< To normalize L*x=b, Bmul0 is what we need to multiply b with. */ + SCHAR Bmul0_sf[4]; + FIXP_CHB LnormInv1d[6]; /*!< Normalized inverted L matrix (L') */ + SCHAR LnormInv1d_sf[6]; + FIXP_CHB + Bmul1[4]; /*!< To normalize L'*x=b, Bmul1 is what we need to multiply b + with. */ + SCHAR Bmul1_sf[4]; +} backsubst_data; + +/* for each element n do, f(n) = trunc(log2(n))+1 */ +const UCHAR getLog2[32] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}; + +/** \def BSD_IDX_OFFSET + * + * bsd[] begins at index 0 with data for numBands=5. The correct bsd[] is + * indexed like bsd[numBands-BSD_IDX_OFFSET]. + */ +#define BSD_IDX_OFFSET 5 + +#define N_NUMBANDS \ + MAXLOWBANDS - BSD_IDX_OFFSET + \ + 1 /*!< Number of backsubst_data elements in bsd */ + +const backsubst_data bsd[N_NUMBANDS] = { + { + /* numBands=5 */ + {CHC(0x66c85a52), CHC(0x4278e587), CHC(0x697dcaff)}, + {-1, 0, 0}, + {CHC(0x66a61789), CHC(0x5253b8e3), CHC(0x5addad81)}, + {3, 4, 1}, + {CHC(0x7525ee90), CHC(0x6e2a1210), CHC(0x6523bb40), CHC(0x59822ead)}, + {-6, -4, -2, 0}, + {CHC(0x609e4cad), CHC(0x59c7e312), CHC(0x681eecac), CHC(0x440ea893), + CHC(0x4a214bb3), CHC(0x53c345a1)}, + {1, 0, -1, -1, -3, -5}, + {CHC(0x7525ee90), CHC(0x58587936), CHC(0x410d0b38), CHC(0x7f1519d6)}, + {-6, -1, 2, 0}, + }, + { + /* numBands=6 */ + {CHC(0x68943285), CHC(0x4841d2c3), CHC(0x6a6214c7)}, + {-1, 0, 0}, + {CHC(0x63c5923e), CHC(0x4e906e18), CHC(0x6285af8a)}, + {3, 4, 1}, + {CHC(0x7263940b), CHC(0x424a69a5), CHC(0x4ae8383a), CHC(0x517b7730)}, + {-7, -4, -2, 0}, + {CHC(0x518aee5f), CHC(0x4823a096), CHC(0x43764a39), CHC(0x6e6faf23), + CHC(0x61bba44f), CHC(0x59d8b132)}, + {1, 0, -1, -2, -4, -6}, + {CHC(0x7263940b), CHC(0x6757bff2), CHC(0x5bf40fe0), CHC(0x7d6f4292)}, + {-7, -2, 1, 0}, + }, + { + /* numBands=7 */ + {CHC(0x699b4c3c), CHC(0x4b8b702f), CHC(0x6ae51a4f)}, + {-1, 0, 0}, + {CHC(0x623a7f49), CHC(0x4ccc91fc), CHC(0x68f048dd)}, + {3, 4, 1}, + {CHC(0x7e6ebe18), CHC(0x5701daf2), CHC(0x74a8198b), CHC(0x4b399aa1)}, + {-8, -5, -3, 0}, + {CHC(0x464a64a6), CHC(0x78e42633), CHC(0x5ee174ba), CHC(0x5d0008c8), + CHC(0x455cff0f), CHC(0x6b9100e7)}, + {1, -1, -2, -2, -4, -7}, + {CHC(0x7e6ebe18), CHC(0x42c52efe), CHC(0x45fe401f), CHC(0x7b5808ef)}, + {-8, -2, 1, 0}, + }, + { + /* numBands=8 */ + {CHC(0x6a3fd9b4), CHC(0x4d99823f), CHC(0x6b372a94)}, + {-1, 0, 0}, + {CHC(0x614c6ef7), CHC(0x4bd06699), CHC(0x6e59cfca)}, + {3, 4, 1}, + {CHC(0x4c389cc5), CHC(0x79686681), CHC(0x5e2544c2), CHC(0x46305b43)}, + {-8, -6, -3, 0}, + {CHC(0x7b4ca7c6), CHC(0x68270ac5), CHC(0x467c644c), CHC(0x505c1b0f), + CHC(0x67a14778), CHC(0x45801767)}, + {0, -1, -2, -2, -5, -7}, + {CHC(0x4c389cc5), CHC(0x5c499ceb), CHC(0x6f863c9f), CHC(0x79059bfc)}, + {-8, -3, 0, 0}, + }, + { + /* numBands=9 */ + {CHC(0x6aad9988), CHC(0x4ef8ac18), CHC(0x6b6df116)}, + {-1, 0, 0}, + {CHC(0x60b159b0), CHC(0x4b33f772), CHC(0x72f5573d)}, + {3, 4, 1}, + {CHC(0x6206cb18), CHC(0x58a7d8dc), CHC(0x4e0b2d0b), CHC(0x4207ad84)}, + {-9, -6, -3, 0}, + {CHC(0x6dadadae), CHC(0x5b8b2cfc), CHC(0x6cf61db2), CHC(0x46c3c90b), + CHC(0x506314ea), CHC(0x5f034acd)}, + {0, -1, -3, -2, -5, -8}, + {CHC(0x6206cb18), CHC(0x42f8b8de), CHC(0x5bb4776f), CHC(0x769acc79)}, + {-9, -3, 0, 0}, + }, + { + /* numBands=10 */ + {CHC(0x6afa7252), CHC(0x4feed3ed), CHC(0x6b94504d)}, + {-1, 0, 0}, + {CHC(0x60467899), CHC(0x4acbafba), CHC(0x76eb327f)}, + {3, 4, 1}, + {CHC(0x42415b15), CHC(0x431080da), CHC(0x420f1c32), CHC(0x7d0c1aeb)}, + {-9, -6, -3, -1}, + {CHC(0x62b2c7a4), CHC(0x51b040a6), CHC(0x56caddb4), CHC(0x7e74a2c8), + CHC(0x4030adf5), CHC(0x43d1dc4f)}, + {0, -1, -3, -3, -5, -8}, + {CHC(0x42415b15), CHC(0x64e299b3), CHC(0x4d33b5e8), CHC(0x742cee5f)}, + {-9, -4, 0, 0}, + }, + { + /* numBands=11 */ + {CHC(0x6b3258bb), CHC(0x50a21233), CHC(0x6bb03c19)}, + {-1, 0, 0}, + {CHC(0x5ff997c6), CHC(0x4a82706e), CHC(0x7a5aae36)}, + {3, 4, 1}, + {CHC(0x5d2fb4fb), CHC(0x685bddd8), CHC(0x71b5e983), CHC(0x7708c90b)}, + {-10, -7, -4, -1}, + {CHC(0x59aceea2), CHC(0x49c428a0), CHC(0x46ca5527), CHC(0x724be884), + CHC(0x68e586da), CHC(0x643485b6)}, + {0, -1, -3, -3, -6, -9}, + {CHC(0x5d2fb4fb), CHC(0x4e3fad1a), CHC(0x42310ba2), CHC(0x71c8b3ce)}, + {-10, -4, 0, 0}, + }, + { + /* numBands=12 */ + {CHC(0x6b5c4726), CHC(0x5128a4a8), CHC(0x6bc52ee1)}, + {-1, 0, 0}, + {CHC(0x5fc06618), CHC(0x4a4ce559), CHC(0x7d5c16e9)}, + {3, 4, 1}, + {CHC(0x43af8342), CHC(0x531533d3), CHC(0x633660a6), CHC(0x71ce6052)}, + {-10, -7, -4, -1}, + {CHC(0x522373d7), CHC(0x434150cb), CHC(0x75b58afc), CHC(0x68474f2d), + CHC(0x575348a5), CHC(0x4c20973f)}, + {0, -1, -4, -3, -6, -9}, + {CHC(0x43af8342), CHC(0x7c4d3d11), CHC(0x732e13db), CHC(0x6f756ac4)}, + {-10, -5, -1, 0}, + }, + { + /* numBands=13 */ + {CHC(0x6b7c8953), CHC(0x51903fcd), CHC(0x6bd54d2e)}, + {-1, 0, 0}, + {CHC(0x5f94abf0), CHC(0x4a2480fa), CHC(0x40013553)}, + {3, 4, 2}, + {CHC(0x6501236e), CHC(0x436b9c4e), CHC(0x578d7881), CHC(0x6d34f92e)}, + {-11, -7, -4, -1}, + {CHC(0x4bc0e2b2), CHC(0x7b9d12ac), CHC(0x636c1c1b), CHC(0x5fe15c2b), + CHC(0x49d54879), CHC(0x7662cfa5)}, + {0, -2, -4, -3, -6, -10}, + {CHC(0x6501236e), CHC(0x64b059fe), CHC(0x656d8359), CHC(0x6d370900)}, + {-11, -5, -1, 0}, + }, + { + /* numBands=14 */ + {CHC(0x6b95e276), CHC(0x51e1b637), CHC(0x6be1f7ed)}, + {-1, 0, 0}, + {CHC(0x5f727a1c), CHC(0x4a053e9c), CHC(0x412e528c)}, + {3, 4, 2}, + {CHC(0x4d178bd4), CHC(0x6f33b4e8), CHC(0x4e028f7f), CHC(0x691ee104)}, + {-11, -8, -4, -1}, + {CHC(0x46473d3f), CHC(0x725bd0a6), CHC(0x55199885), CHC(0x58bcc56b), + CHC(0x7e7e6288), CHC(0x5ddef6eb)}, + {0, -2, -4, -3, -7, -10}, + {CHC(0x4d178bd4), CHC(0x52ebd467), CHC(0x5a395a6e), CHC(0x6b0f724f)}, + {-11, -5, -1, 0}, + }, + { + /* numBands=15 */ + {CHC(0x6baa2a22), CHC(0x5222eb91), CHC(0x6bec1a86)}, + {-1, 0, 0}, + {CHC(0x5f57393b), CHC(0x49ec8934), CHC(0x423b5b58)}, + {3, 4, 2}, + {CHC(0x77fd2486), CHC(0x5cfbdf2c), CHC(0x46153bd1), CHC(0x65757ed9)}, + {-12, -8, -4, -1}, + {CHC(0x41888ee6), CHC(0x6a661db3), CHC(0x49abc8c8), CHC(0x52965848), + CHC(0x6d9301b7), CHC(0x4bb04721)}, + {0, -2, -4, -3, -7, -10}, + {CHC(0x77fd2486), CHC(0x45424c68), CHC(0x50f33cc6), CHC(0x68ff43f0)}, + {-12, -5, -1, 0}, + }, + { + /* numBands=16 */ + {CHC(0x6bbaa499), CHC(0x5257ed94), CHC(0x6bf456e4)}, + {-1, 0, 0}, + {CHC(0x5f412594), CHC(0x49d8a766), CHC(0x432d1dbd)}, + {3, 4, 2}, + {CHC(0x5ef5cfde), CHC(0x4eafcd2d), CHC(0x7ed36893), CHC(0x62274b45)}, + {-12, -8, -5, -1}, + {CHC(0x7ac438f5), CHC(0x637aab21), CHC(0x4067617a), CHC(0x4d3c6ec7), + CHC(0x5fd6e0dd), CHC(0x7bd5f024)}, + {-1, -2, -4, -3, -7, -11}, + {CHC(0x5ef5cfde), CHC(0x751d0d4f), CHC(0x492b3c41), CHC(0x67065409)}, + {-12, -6, -1, 0}, + }, + { + /* numBands=17 */ + {CHC(0x6bc836c9), CHC(0x5283997e), CHC(0x6bfb1f5e)}, + {-1, 0, 0}, + {CHC(0x5f2f02b6), CHC(0x49c868e9), CHC(0x44078151)}, + {3, 4, 2}, + {CHC(0x4c43b65a), CHC(0x4349dcf6), CHC(0x73799e2d), CHC(0x5f267274)}, + {-12, -8, -5, -1}, + {CHC(0x73726394), CHC(0x5d68511a), CHC(0x7191bbcc), CHC(0x48898c70), + CHC(0x548956e1), CHC(0x66981ce8)}, + {-1, -2, -5, -3, -7, -11}, + {CHC(0x4c43b65a), CHC(0x64131116), CHC(0x429028e2), CHC(0x65240211)}, + {-12, -6, -1, 0}, + }, + { + /* numBands=18 */ + {CHC(0x6bd3860d), CHC(0x52a80156), CHC(0x6c00c68d)}, + {-1, 0, 0}, + {CHC(0x5f1fed86), CHC(0x49baf636), CHC(0x44cdb9dc)}, + {3, 4, 2}, + {CHC(0x7c189389), CHC(0x742666d8), CHC(0x69b8c776), CHC(0x5c67e27d)}, + {-13, -9, -5, -1}, + {CHC(0x6cf1ea76), CHC(0x58095703), CHC(0x64e351a9), CHC(0x4460da90), + CHC(0x4b1f8083), CHC(0x55f2d3e1)}, + {-1, -2, -5, -3, -7, -11}, + {CHC(0x7c189389), CHC(0x5651792a), CHC(0x79cb9b3d), CHC(0x635769c0)}, + {-13, -6, -2, 0}, + }, + { + /* numBands=19 */ + {CHC(0x6bdd0c40), CHC(0x52c6abf6), CHC(0x6c058950)}, + {-1, 0, 0}, + {CHC(0x5f133f88), CHC(0x49afb305), CHC(0x45826d73)}, + {3, 4, 2}, + {CHC(0x6621a164), CHC(0x6512528e), CHC(0x61449fc8), CHC(0x59e2a0c0)}, + {-13, -9, -5, -1}, + {CHC(0x6721cadb), CHC(0x53404cd4), CHC(0x5a389e91), CHC(0x40abcbd2), + CHC(0x43332f01), CHC(0x48b82e46)}, + {-1, -2, -5, -3, -7, -11}, + {CHC(0x6621a164), CHC(0x4b12cc28), CHC(0x6ffd4df8), CHC(0x619f835e)}, + {-13, -6, -2, 0}, + }, + { + /* numBands=20 */ + {CHC(0x6be524c5), CHC(0x52e0beb3), CHC(0x6c099552)}, + {-1, 0, 0}, + {CHC(0x5f087c68), CHC(0x49a62bb5), CHC(0x4627d175)}, + {3, 4, 2}, + {CHC(0x54ec6afe), CHC(0x58991a42), CHC(0x59e23e8c), CHC(0x578f4ef4)}, + {-13, -9, -5, -1}, + {CHC(0x61e78f6f), CHC(0x4ef5e1e9), CHC(0x5129c3b8), CHC(0x7ab0f7b2), + CHC(0x78efb076), CHC(0x7c2567ea)}, + {-1, -2, -5, -4, -8, -12}, + {CHC(0x54ec6afe), CHC(0x41c7812c), CHC(0x676f6f8d), CHC(0x5ffb383f)}, + {-13, -6, -2, 0}, + }, + { + /* numBands=21 */ + {CHC(0x6bec1542), CHC(0x52f71929), CHC(0x6c0d0d5e)}, + {-1, 0, 0}, + {CHC(0x5eff45c5), CHC(0x499e092d), CHC(0x46bfc0c9)}, + {3, 4, 2}, + {CHC(0x47457a78), CHC(0x4e2d99b3), CHC(0x53637ea5), CHC(0x5567d0e9)}, + {-13, -9, -5, -1}, + {CHC(0x5d2dc61b), CHC(0x4b1760c8), CHC(0x4967cf39), CHC(0x74b113d8), + CHC(0x6d6676b6), CHC(0x6ad114e9)}, + {-1, -2, -5, -4, -8, -12}, + {CHC(0x47457a78), CHC(0x740accaa), CHC(0x5feb6609), CHC(0x5e696f95)}, + {-13, -7, -2, 0}, + }, + { + /* numBands=22 */ + {CHC(0x6bf21387), CHC(0x530a683c), CHC(0x6c100c59)}, + {-1, 0, 0}, + {CHC(0x5ef752ea), CHC(0x499708c6), CHC(0x474bcd1b)}, + {3, 4, 2}, + {CHC(0x78a21ab7), CHC(0x45658aec), CHC(0x4da3c4fe), CHC(0x5367094b)}, + {-14, -9, -5, -1}, + {CHC(0x58e2df6a), CHC(0x4795990e), CHC(0x42b5e0f7), CHC(0x6f408c64), + CHC(0x6370bebf), CHC(0x5c91ca85)}, + {-1, -2, -5, -4, -8, -12}, + {CHC(0x78a21ab7), CHC(0x66f951d6), CHC(0x594605bb), CHC(0x5ce91657)}, + {-14, -7, -2, 0}, + }, + { + /* numBands=23 */ + {CHC(0x6bf749b2), CHC(0x531b3348), CHC(0x6c12a750)}, + {-1, 0, 0}, + {CHC(0x5ef06b17), CHC(0x4990f6c9), CHC(0x47cd4c5b)}, + {3, 4, 2}, + {CHC(0x66dede36), CHC(0x7bdf90a9), CHC(0x4885b2b9), CHC(0x5188a6b7)}, + {-14, -10, -5, -1}, + {CHC(0x54f85812), CHC(0x446414ae), CHC(0x79c8d519), CHC(0x6a4c2f31), + CHC(0x5ac8325f), CHC(0x50bf9200)}, + {-1, -2, -6, -4, -8, -12}, + {CHC(0x66dede36), CHC(0x5be0d90e), CHC(0x535cc453), CHC(0x5b7923f0)}, + {-14, -7, -2, 0}, + }, + { + /* numBands=24 */ + {CHC(0x6bfbd91d), CHC(0x5329e580), CHC(0x6c14eeed)}, + {-1, 0, 0}, + {CHC(0x5eea6179), CHC(0x498baa90), CHC(0x4845635d)}, + {3, 4, 2}, + {CHC(0x58559b7e), CHC(0x6f1b231f), CHC(0x43f1789b), CHC(0x4fc8fcb8)}, + {-14, -10, -5, -1}, + {CHC(0x51621775), CHC(0x417881a3), CHC(0x6f9ba9b6), CHC(0x65c412b2), + CHC(0x53352c61), CHC(0x46db9caf)}, + {-1, -2, -6, -4, -8, -12}, + {CHC(0x58559b7e), CHC(0x52636003), CHC(0x4e13b316), CHC(0x5a189cdf)}, + {-14, -7, -2, 0}, + }, + { + /* numBands=25 */ + {CHC(0x6bffdc73), CHC(0x5336d4af), CHC(0x6c16f084)}, + {-1, 0, 0}, + {CHC(0x5ee51249), CHC(0x498703cc), CHC(0x48b50e4f)}, + {3, 4, 2}, + {CHC(0x4c5616cf), CHC(0x641b9fad), CHC(0x7fa735e0), CHC(0x4e24e57a)}, + {-14, -10, -6, -1}, + {CHC(0x4e15f47a), CHC(0x7d9481d6), CHC(0x66a82f8a), CHC(0x619ae971), + CHC(0x4c8b2f5f), CHC(0x7d09ec11)}, + {-1, -3, -6, -4, -8, -13}, + {CHC(0x4c5616cf), CHC(0x4a3770fb), CHC(0x495402de), CHC(0x58c693fa)}, + {-14, -7, -2, 0}, + }, + { + /* numBands=26 */ + {CHC(0x6c036943), CHC(0x53424625), CHC(0x6c18b6dc)}, + {-1, 0, 0}, + {CHC(0x5ee060aa), CHC(0x4982e88a), CHC(0x491d277f)}, + {3, 4, 2}, + {CHC(0x425ada5b), CHC(0x5a9368ac), CHC(0x78380a42), CHC(0x4c99aa05)}, + {-14, -10, -6, -1}, + {CHC(0x4b0b569c), CHC(0x78a420da), CHC(0x5ebdf203), CHC(0x5dc57e63), + CHC(0x46a650ff), CHC(0x6ee13fb8)}, + {-1, -3, -6, -4, -8, -13}, + {CHC(0x425ada5b), CHC(0x4323073c), CHC(0x450ae92b), CHC(0x57822ad5)}, + {-14, -7, -2, 0}, + }, + { + /* numBands=27 */ + {CHC(0x6c06911a), CHC(0x534c7261), CHC(0x6c1a4aba)}, + {-1, 0, 0}, + {CHC(0x5edc3524), CHC(0x497f43c0), CHC(0x497e6cd8)}, + {3, 4, 2}, + {CHC(0x73fb550e), CHC(0x5244894f), CHC(0x717aad78), CHC(0x4b24ef6c)}, + {-15, -10, -6, -1}, + {CHC(0x483aebe4), CHC(0x74139116), CHC(0x57b58037), CHC(0x5a3a4f3c), + CHC(0x416950fe), CHC(0x62c7f4f2)}, + {-1, -3, -6, -4, -8, -13}, + {CHC(0x73fb550e), CHC(0x79efb994), CHC(0x4128cab7), CHC(0x564a919a)}, + {-15, -8, -2, 0}, + }, + { + /* numBands=28 */ + {CHC(0x6c096264), CHC(0x535587cd), CHC(0x6c1bb355)}, + {-1, 0, 0}, + {CHC(0x5ed87c76), CHC(0x497c0439), CHC(0x49d98452)}, + {3, 4, 2}, + {CHC(0x65dec5bf), CHC(0x4afd1ba3), CHC(0x6b58b4b3), CHC(0x49c4a7b0)}, + {-15, -10, -6, -1}, + {CHC(0x459e6eb1), CHC(0x6fd850b7), CHC(0x516e7be9), CHC(0x56f13d05), + CHC(0x79785594), CHC(0x58617de7)}, + {-1, -3, -6, -4, -9, -13}, + {CHC(0x65dec5bf), CHC(0x6f2168aa), CHC(0x7b41310f), CHC(0x551f0692)}, + {-15, -8, -3, 0}, + }, + { + /* numBands=29 */ + {CHC(0x6c0be913), CHC(0x535dacd5), CHC(0x6c1cf6a3)}, + {-1, 0, 0}, + {CHC(0x5ed526b4), CHC(0x49791bc5), CHC(0x4a2eff99)}, + {3, 4, 2}, + {CHC(0x59e44afe), CHC(0x44949ada), CHC(0x65bf36f5), CHC(0x487705a0)}, + {-15, -10, -6, -1}, + {CHC(0x43307779), CHC(0x6be959c4), CHC(0x4bce2122), CHC(0x53e34d89), + CHC(0x7115ff82), CHC(0x4f6421a1)}, + {-1, -3, -6, -4, -9, -13}, + {CHC(0x59e44afe), CHC(0x659eab7d), CHC(0x74cea459), CHC(0x53fed574)}, + {-15, -8, -3, 0}, + }, + { + /* numBands=30 */ + {CHC(0x6c0e2f17), CHC(0x53650181), CHC(0x6c1e199d)}, + {-1, 0, 0}, + {CHC(0x5ed2269f), CHC(0x49767e9e), CHC(0x4a7f5f0b)}, + {3, 4, 2}, + {CHC(0x4faa4ae6), CHC(0x7dd3bf11), CHC(0x609e2732), CHC(0x473a72e9)}, + {-15, -11, -6, -1}, + {CHC(0x40ec57c6), CHC(0x683ee147), CHC(0x46be261d), CHC(0x510a7983), + CHC(0x698a84cb), CHC(0x4794a927)}, + {-1, -3, -6, -4, -9, -13}, + {CHC(0x4faa4ae6), CHC(0x5d3615ad), CHC(0x6ee74773), CHC(0x52e956a1)}, + {-15, -8, -3, 0}, + }, + { + /* numBands=31 */ + {CHC(0x6c103cc9), CHC(0x536ba0ac), CHC(0x6c1f2070)}, + {-1, 0, 0}, + {CHC(0x5ecf711e), CHC(0x497422ea), CHC(0x4acb1438)}, + {3, 4, 2}, + {CHC(0x46e322ad), CHC(0x73c32f3c), CHC(0x5be7d172), CHC(0x460d8800)}, + {-15, -11, -6, -1}, + {CHC(0x7d9bf8ad), CHC(0x64d22351), CHC(0x422bdc81), CHC(0x4e6184aa), + CHC(0x62ba2375), CHC(0x40c325de)}, + {-2, -3, -6, -4, -9, -13}, + {CHC(0x46e322ad), CHC(0x55bef2a3), CHC(0x697b3135), CHC(0x51ddee4d)}, + {-15, -8, -3, 0}, + }, + { + // numBands=32 + {CHC(0x6c121933), CHC(0x5371a104), CHC(0x6c200ea0)}, + {-1, 0, 0}, + {CHC(0x5eccfcd3), CHC(0x49720060), CHC(0x4b1283f0)}, + {3, 4, 2}, + {CHC(0x7ea12a52), CHC(0x6aca3303), CHC(0x579072bf), CHC(0x44ef056e)}, + {-16, -11, -6, -1}, + {CHC(0x79a3a9ab), CHC(0x619d38fc), CHC(0x7c0f0734), CHC(0x4be3dd5d), + CHC(0x5c8d7163), CHC(0x7591065f)}, + {-2, -3, -7, -4, -9, -14}, + {CHC(0x7ea12a52), CHC(0x4f1782a6), CHC(0x647cbcb2), CHC(0x50dc0bb1)}, + {-16, -8, -3, 0}, + }, +}; + +/** \def SUM_SAFETY + * + * SUM_SAFTEY defines the bits needed to right-shift every summand in + * order to be overflow-safe. In the two backsubst functions we sum up 4 + * values. Since one of which is definitely not MAXVAL_DBL (the L[x][y]), + * we spare just 2 safety bits instead of 3. + */ +#define SUM_SAFETY 2 + +/** + * \brief Solves L*x=b via backsubstitution according to the following + * structure: + * + * x[0] = b[0]; + * x[1] = (b[1] - x[0]) / L[1][1]; + * x[2] = (b[2] - x[1]*L[2][1] - x[0]) / L[2][2]; + * x[3] = (b[3] - x[2]*L[3][2] - x[1]*L[3][1] - x[0]) / L[3][3]; + * + * \param[in] numBands SBR crossover band index + * \param[in] b the b in L*x=b (one-dimensional) + * \param[out] x output polynomial coefficients (mantissa) + * \param[out] x_sf exponents of x[] + */ +static void backsubst_fw(const int numBands, const FIXP_DBL *const b, + FIXP_DBL *RESTRICT x, int *RESTRICT x_sf) { + int i, k; + int m; /* the trip counter that indexes incrementally through Lnorm1d[] */ + + const FIXP_CHB *RESTRICT pLnorm1d = bsd[numBands - BSD_IDX_OFFSET].Lnorm1d; + const SCHAR *RESTRICT pLnorm1d_sf = bsd[numBands - BSD_IDX_OFFSET].Lnorm1d_sf; + const FIXP_CHB *RESTRICT pLnormii = bsd[numBands - BSD_IDX_OFFSET].Lnormii; + const SCHAR *RESTRICT pLnormii_sf = bsd[numBands - BSD_IDX_OFFSET].Lnormii_sf; + + x[0] = b[0]; + + for (i = 1, m = 0; i <= POLY_ORDER; ++i) { + FIXP_DBL sum = b[i] >> SUM_SAFETY; + int sum_sf = x_sf[i]; + for (k = i - 1; k > 0; --k, ++m) { + int e; + FIXP_DBL mult = fMultNorm(FX_CHB2FX_DBL(pLnorm1d[m]), x[k], &e); + int mult_sf = pLnorm1d_sf[m] + x_sf[k] + e; + + /* check if the new summand mult has a different sf than the sum currently + * has */ + int diff = mult_sf - sum_sf; + + if (diff > 0) { + /* yes, and it requires the sum to be adjusted (scaled down) */ + sum >>= diff; + sum_sf = mult_sf; + } else if (diff < 0) { + /* yes, but here mult needs to be scaled down */ + mult >>= -diff; + } + sum -= (mult >> SUM_SAFETY); + } + + /* - x[0] */ + if (x_sf[0] > sum_sf) { + sum >>= (x_sf[0] - sum_sf); + sum_sf = x_sf[0]; + } + sum -= (x[0] >> (sum_sf - x_sf[0] + SUM_SAFETY)); + + /* instead of the division /L[i][i], we multiply by the inverse */ + int e; + x[i] = fMultNorm(sum, FX_CHB2FX_DBL(pLnormii[i - 1]), &e); + x_sf[i] = sum_sf + pLnormii_sf[i - 1] + e + SUM_SAFETY; + } +} + +/** + * \brief Solves L*x=b via backsubstitution according to the following + * structure: + * + * x[3] = b[3]; + * x[2] = b[2] - L[2][3]*x[3]; + * x[1] = b[1] - L[1][2]*x[2] - L[1][3]*x[3]; + * x[0] = b[0] - L[0][1]*x[1] - L[0][2]*x[2] - L[0][3]*x[3]; + * + * \param[in] numBands SBR crossover band index + * \param[in] b the b in L*x=b (one-dimensional) + * \param[out] x solution vector + * \param[out] x_sf exponents of x[] + */ +static void backsubst_bw(const int numBands, const FIXP_DBL *const b, + FIXP_DBL *RESTRICT x, int *RESTRICT x_sf) { + int i, k; + int m; /* the trip counter that indexes incrementally through LnormInv1d[] */ + + const FIXP_CHB *RESTRICT pLnormInv1d = + bsd[numBands - BSD_IDX_OFFSET].LnormInv1d; + const SCHAR *RESTRICT pLnormInv1d_sf = + bsd[numBands - BSD_IDX_OFFSET].LnormInv1d_sf; + + x[POLY_ORDER] = b[POLY_ORDER]; + + for (i = POLY_ORDER - 1, m = 0; i >= 0; i--) { + FIXP_DBL sum = b[i] >> SUM_SAFETY; + int sum_sf = x_sf[i]; /* sum's sf but disregarding SUM_SAFETY (added at the + iteration's end) */ + + for (k = i + 1; k <= POLY_ORDER; ++k, ++m) { + int e; + FIXP_DBL mult = fMultNorm(FX_CHB2FX_DBL(pLnormInv1d[m]), x[k], &e); + int mult_sf = pLnormInv1d_sf[m] + x_sf[k] + e; + + /* check if the new summand mult has a different sf than sum currently has + */ + int diff = mult_sf - sum_sf; + + if (diff > 0) { + /* yes, and it requires the sum v to be adjusted (scaled down) */ + sum >>= diff; + sum_sf = mult_sf; + } else if (diff < 0) { + /* yes, but here mult needs to be scaled down */ + mult >>= -diff; + } + + /* mult has now the same sf than what it is about to be added to. */ + /* scale mult down additionally so that building the sum is overflow-safe. + */ + sum -= (mult >> SUM_SAFETY); + } + + x_sf[i] = sum_sf + SUM_SAFETY; + x[i] = sum; + } +} + +/** + * \brief Solves a system of linear equations (L*x=b) with the Cholesky + * algorithm. + * + * \param[in] numBands SBR crossover band index + * \param[in,out] b input: vector b, output: solution vector p. + * \param[in,out] b_sf input: exponent of b; output: exponent of solution + * p. + */ +static void choleskySolve(const int numBands, FIXP_DBL *RESTRICT b, + int *RESTRICT b_sf) { + int i, e; + + const FIXP_CHB *RESTRICT pBmul0 = bsd[numBands - BSD_IDX_OFFSET].Bmul0; + const SCHAR *RESTRICT pBmul0_sf = bsd[numBands - BSD_IDX_OFFSET].Bmul0_sf; + const FIXP_CHB *RESTRICT pBmul1 = bsd[numBands - BSD_IDX_OFFSET].Bmul1; + const SCHAR *RESTRICT pBmul1_sf = bsd[numBands - BSD_IDX_OFFSET].Bmul1_sf; + + /* normalize b */ + FIXP_DBL bnormed[POLY_ORDER + 1]; + for (i = 0; i <= POLY_ORDER; ++i) { + bnormed[i] = fMultNorm(b[i], FX_CHB2FX_DBL(pBmul0[i]), &e); + b_sf[i] += pBmul0_sf[i] + e; + } + + backsubst_fw(numBands, bnormed, b, b_sf); + + /* normalize b again */ + for (i = 0; i <= POLY_ORDER; ++i) { + bnormed[i] = fMultNorm(b[i], FX_CHB2FX_DBL(pBmul1[i]), &e); + b_sf[i] += pBmul1_sf[i] + e; + } + + backsubst_bw(numBands, bnormed, b, b_sf); +} + +/** + * \brief Find polynomial approximation of vector y with implicit abscisas + * x=0,1,2,3..n-1 + * + * The problem (V^T * V * p = V^T * y) is solved with Cholesky. + * V is the Vandermode Matrix constructed with x = 0...n-1; + * A = V^T * V; b = V^T * y; + * + * \param[in] numBands SBR crossover band index (BSD_IDX_OFFSET <= numBands <= + * MAXLOWBANDS) + * \param[in] y input vector (mantissa) + * \param[in] y_sf exponents of y[] + * \param[out] p output polynomial coefficients (mantissa) + * \param[out] p_sf exponents of p[] + */ +static void polyfit(const int numBands, const FIXP_DBL *const y, const int y_sf, + FIXP_DBL *RESTRICT p, int *RESTRICT p_sf) { + int i, k; + LONG v[POLY_ORDER + 1]; + int sum_saftey = getLog2[numBands - 1]; + + FDK_ASSERT((numBands >= BSD_IDX_OFFSET) && (numBands <= MAXLOWBANDS)); + + /* construct vector b[] temporarily stored in array p[] */ + FDKmemclear(p, (POLY_ORDER + 1) * sizeof(FIXP_DBL)); + + /* p[] are the sums over n values and each p[i] has its own sf */ + for (i = 0; i <= POLY_ORDER; ++i) p_sf[i] = 1 - DFRACT_BITS; + + for (k = 0; k < numBands; k++) { + v[0] = (LONG)1; + for (i = 1; i <= POLY_ORDER; i++) { + v[i] = k * v[i - 1]; + } + + for (i = 0; i <= POLY_ORDER; i++) { + if (v[POLY_ORDER - i] != 0 && y[k] != FIXP_DBL(0)) { + int e; + FIXP_DBL mult = fMultNorm((FIXP_DBL)v[POLY_ORDER - i], y[k], &e); + int sf = DFRACT_BITS - 1 + y_sf + e; + + /* check if the new summand has a different sf than the sum p[i] + * currently has */ + int diff = sf - p_sf[i]; + + if (diff > 0) { + /* yes, and it requires the sum p[i] to be adjusted (scaled down) */ + p[i] >>= fMin(DFRACT_BITS - 1, diff); + p_sf[i] = sf; + } else if (diff < 0) { + /* yes, but here mult needs to be scaled down */ + mult >>= -diff; + } + + /* mult has now the same sf than what it is about to be added to. + scale mult down additionally so that building the sum is + overflow-safe. */ + p[i] += mult >> sum_saftey; + } + } + } + + p_sf[0] += sum_saftey; + p_sf[1] += sum_saftey; + p_sf[2] += sum_saftey; + p_sf[3] += sum_saftey; + + choleskySolve(numBands, p, p_sf); +} + +/** + * \brief Calculates the output of a POLY_ORDER-degree polynomial function + * with Horner scheme: + * + * y(x) = p3 + p2*x + p1*x^2 + p0*x^3 + * = p3 + x*(p2 + x*(p1 + x*p0)) + * + * The for loop iterates through the mult/add parts in y(x) as above, + * during which regular upscaling ensures a stable exponent of the + * result. + * + * \param[in] p coefficients as in y(x) + * \param[in] p_sf exponents of p[] + * \param[in] x_int non-fractional integer representation of x as in y(x) + * \param[out] out_sf exponent of return value + * + * \return result y(x) + */ +static FIXP_DBL polyval(const FIXP_DBL *const p, const int *const p_sf, + const int x_int, int *out_sf) { + FDK_ASSERT(x_int <= 31); /* otherwise getLog2[] needs more elements */ + + int k, x_sf; + int result_sf; /* working space to compute return value *out_sf */ + FIXP_DBL x; /* fractional value of x_int */ + FIXP_DBL result; /* return value */ + + /* if x == 0, then y(x) is just p3 */ + if (x_int != 0) { + x_sf = getLog2[x_int]; + x = (FIXP_DBL)x_int << (DFRACT_BITS - 1 - x_sf); + } else { + *out_sf = p_sf[3]; + return p[3]; + } + + result = p[0]; + result_sf = p_sf[0]; + + for (k = 1; k <= POLY_ORDER; ++k) { + FIXP_DBL mult = fMult(x, result); + int mult_sf = x_sf + result_sf; + + int room = CountLeadingBits(mult); + mult <<= room; + mult_sf -= room; + + FIXP_DBL pp = p[k]; + int pp_sf = p_sf[k]; + + /* equalize the shift factors of pp and mult so that we can sum them up */ + int diff = pp_sf - mult_sf; + + if (diff > 0) { + diff = fMin(diff, DFRACT_BITS - 1); + mult >>= diff; + } else if (diff < 0) { + diff = fMax(diff, 1 - DFRACT_BITS); + pp >>= -diff; + } + + /* downshift by 1 to ensure safe summation */ + mult >>= 1; + mult_sf++; + pp >>= 1; + pp_sf++; + + result_sf = fMax(pp_sf, mult_sf); + + result = mult + pp; + /* rarely, mult and pp happen to be almost equal except their sign, + and then upon summation, result becomes so small, that it is within + the inaccuracy range of a few bits, and then the relative error + produced by this function may become HUGE */ + } + + *out_sf = result_sf; + return result; +} + +void sbrDecoder_calculateGainVec(FIXP_DBL **sourceBufferReal, + FIXP_DBL **sourceBufferImag, + int sourceBuf_e_overlap, + int sourceBuf_e_current, int overlap, + FIXP_DBL *RESTRICT GainVec, int *GainVec_exp, + int numBands, const int startSample, + const int stopSample) { + FIXP_DBL p[POLY_ORDER + 1]; + FIXP_DBL meanNrg; + FIXP_DBL LowEnv[MAXLOWBANDS]; + FIXP_DBL invNumBands = GetInvInt(numBands); + FIXP_DBL invNumSlots = GetInvInt(stopSample - startSample); + int i, loBand, exp, scale_nrg, scale_nrg_ov; + int sum_scale = 5, sum_scale_ov = 3; + + if (overlap > 8) { + FDK_ASSERT(overlap <= 16); + sum_scale_ov += 1; + sum_scale += 1; + } + + /* exponents of energy values */ + sourceBuf_e_overlap = sourceBuf_e_overlap * 2 + sum_scale_ov; + sourceBuf_e_current = sourceBuf_e_current * 2 + sum_scale; + exp = fMax(sourceBuf_e_overlap, sourceBuf_e_current); + scale_nrg = sourceBuf_e_current - exp; + scale_nrg_ov = sourceBuf_e_overlap - exp; + + meanNrg = (FIXP_DBL)0; + /* Calculate the spectral envelope in dB over the current copy-up frame. */ + for (loBand = 0; loBand < numBands; loBand++) { + FIXP_DBL nrg_ov, nrg; + INT reserve = 0, exp_new; + FIXP_DBL maxVal = FL2FX_DBL(0.0f); + + for (i = startSample; i < stopSample; i++) { + maxVal |= + (FIXP_DBL)((LONG)(sourceBufferReal[i][loBand]) ^ + ((LONG)sourceBufferReal[i][loBand] >> (SAMPLE_BITS - 1))); + maxVal |= + (FIXP_DBL)((LONG)(sourceBufferImag[i][loBand]) ^ + ((LONG)sourceBufferImag[i][loBand] >> (SAMPLE_BITS - 1))); + } + + if (maxVal != FL2FX_DBL(0.0f)) { + reserve = fixMax(0, CntLeadingZeros(maxVal) - 2); + } + + nrg_ov = nrg = (FIXP_DBL)0; + if (scale_nrg_ov > -31) { + for (i = startSample; i < overlap; i++) { + nrg_ov += (fPow2Div2(sourceBufferReal[i][loBand] << reserve) + + fPow2Div2(sourceBufferImag[i][loBand] << reserve)) >> + sum_scale_ov; + } + } else { + scale_nrg_ov = 0; + } + if (scale_nrg > -31) { + for (i = overlap; i < stopSample; i++) { + nrg += (fPow2Div2(sourceBufferReal[i][loBand] << reserve) + + fPow2Div2(sourceBufferImag[i][loBand] << reserve)) >> + sum_scale; + } + } else { + scale_nrg = 0; + } + + nrg = (scaleValue(nrg_ov, scale_nrg_ov) >> 1) + + (scaleValue(nrg, scale_nrg) >> 1); + nrg = fMult(nrg, invNumSlots); + + exp_new = + exp - (2 * reserve) + + 2; /* +1 for addition directly above, +1 for fPow2Div2 in loops above */ + + /* LowEnv = 10*log10(nrg) = log2(nrg) * 10/log2(10) */ + /* exponent of logarithmic energy is 8 */ + if (nrg > (FIXP_DBL)0) { + int exp_log2; + nrg = CalcLog2(nrg, exp_new, &exp_log2); + nrg = scaleValue(nrg, exp_log2 - 6); + nrg = fMult(FL2FXCONST_SGL(LOG10FAC), nrg); + } else { + nrg = (FIXP_DBL)0; + } + LowEnv[loBand] = nrg; + meanNrg += fMult(nrg, invNumBands); + } + exp = 6 + 2; /* exponent of LowEnv: +2 is exponent of LOG10FAC */ + + /* subtract mean before polynomial approximation to reduce dynamic of p[] */ + for (loBand = 0; loBand < numBands; loBand++) { + LowEnv[loBand] = meanNrg - LowEnv[loBand]; + } + + /* For numBands < BSD_IDX_OFFSET (== POLY_ORDER+2) we dont get an + overdetermined equation system. The calculated polynomial will exactly fit + the input data and evaluating the polynomial will lead to the same vector + than the original input vector: lowEnvSlope[] == lowEnv[] + */ + if (numBands > POLY_ORDER + 1) { + /* Find polynomial approximation of LowEnv */ + int p_sf[POLY_ORDER + 1]; + + polyfit(numBands, LowEnv, exp, p, p_sf); + + for (i = 0; i < numBands; i++) { + int sf; + + /* lowBandEnvSlope[i] = tmp; */ + FIXP_DBL tmp = polyval(p, p_sf, i, &sf); + + /* GainVec = 10^((mean(y)-y)/20) = 2^( (mean(y)-y) * log2(10)/20 ) */ + tmp = fMult(tmp, FL2FXCONST_SGL(LOG10FAC_INV)); + GainVec[i] = f2Pow(tmp, sf - 2, + &GainVec_exp[i]); /* -2 is exponent of LOG10FAC_INV */ + } + } else { /* numBands <= POLY_ORDER+1 */ + for (i = 0; i < numBands; i++) { + int sf = exp; /* exponent of LowEnv[] */ + + /* lowBandEnvSlope[i] = LowEnv[i]; */ + FIXP_DBL tmp = LowEnv[i]; + + /* GainVec = 10^((mean(y)-y)/20) = 2^( (mean(y)-y) * log2(10)/20 ) */ + tmp = fMult(tmp, FL2FXCONST_SGL(LOG10FAC_INV)); + GainVec[i] = f2Pow(tmp, sf - 2, + &GainVec_exp[i]); /* -2 is exponent of LOG10FAC_INV */ + } + } +} diff --git a/libSBRdec/src/HFgen_preFlat.h b/libSBRdec/src/HFgen_preFlat.h new file mode 100644 index 0000000..c1fc49d --- /dev/null +++ b/libSBRdec/src/HFgen_preFlat.h @@ -0,0 +1,132 @@ +/* ----------------------------------------------------------------------------- +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): Manuel Jander, Matthias Hildenbrand + + Description: QMF frequency pre whitening for SBR + +*******************************************************************************/ + +#include "common_fix.h" + +#ifndef HFGEN_PREFLAT_H +#define HFGEN_PREFLAT_H + +#define GAIN_VEC_EXP 6 /* exponent of GainVec[] */ + +/** + * \brief Find gain vector to flatten the QMF frequency bands whithout loosing + * the fine structure. + * \param[in] sourceBufferReal real part of QMF domain data. + * \param[in] sourceBufferImag imaginary part of QMF domain data. + * \param[in] sourceBuffer_e_overlap exponent of sourceBufferReal. + * \param[in] sourceBuffer_e_current exponent of sourceBufferImag. + * \param[in] overlap number of overlap samples. + * \param[out] GainVec array of gain values (one for each QMF band). + * \param[out] GainVec_exp exponents of GainVec (one for each QMF band). + * \param[in] numBands number of low bands (k_0). + * \param[in] startSample time slot start. + * \param[in] stopSample time slot stop. + */ +void sbrDecoder_calculateGainVec(FIXP_DBL **sourceBufferReal, + FIXP_DBL **sourceBufferImag, + int sourceBuffer_e_overlap, + int sourceBuffer_e_current, int overlap, + FIXP_DBL GainVec[], int GainVec_exp[], + const int numBands, const int startSample, + const int stopSample); + +#endif /* __HFGEN_PREFLAT_H */ diff --git a/libSBRdec/src/arm/env_calc_arm.cpp b/libSBRdec/src/arm/env_calc_arm.cpp deleted file mode 100644 index 12b17d8..0000000 --- a/libSBRdec/src/arm/env_calc_arm.cpp +++ /dev/null @@ -1,148 +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 ------------------------------------------------------------------------------------------------------------ */ - -/******************************** Fraunhofer IIS *************************** - - Author(s): Arthur Tritthart - Description: (ARM optimised) SBR domain coding - -******************************************************************************/ -#ifndef INCLUSION_GUARD_CALC_ENV_ARM -#define INCLUSION_GUARD_CALC_ENV_ARM - - -/*! - \brief Compute maximal value of a complex array (re/im) of a given width - Negative values are temporarily logically or'ed with 0xFFFFFFFF - instead of negating the value, if the sign bit is set. - \param maxVal Preset maximal value - \param reTmp real input signal - \param imTmp imaginary input signal - \return new maximal value -*/ - -#ifdef FUNCTION_FDK_get_maxval -__asm FIXP_DBL FDK_get_maxval (FIXP_DBL maxVal, FIXP_DBL *reTmp, FIXP_DBL *imTmp, int width ) -{ - - /* Register map: - r0 maxVal - r1 reTmp - r2 imTmp - r3 width - r4 real - r5 imag - */ - PUSH {r4-r5} - - MOVS r3, r3, ASR #1 - ADC r3, r3, #0 - BCS FDK_get_maxval_loop_2nd_part - BEQ FDK_get_maxval_loop_end - -FDK_get_maxval_loop - LDR r4, [r1], #4 - LDR r5, [r2], #4 - EOR r4, r4, r4, ASR #31 - EOR r5, r5, r5, ASR #31 - ORR r0, r0, r4 - ORR r0, r0, r5 - -FDK_get_maxval_loop_2nd_part - LDR r4, [r1], #4 - LDR r5, [r2], #4 - EOR r4, r4, r4, ASR #31 - EOR r5, r5, r5, ASR #31 - ORR r0, r0, r4 - ORR r0, r0, r5 - - SUBS r3, r3, #1 - BNE FDK_get_maxval_loop - -FDK_get_maxval_loop_end - POP {r4-r5} - BX lr -} -#endif /* FUNCTION_FDK_get_maxval */ - -#endif /* INCLUSION_GUARD_CALC_ENV_ARM */ diff --git a/libSBRdec/src/arm/lpp_tran_arm.cpp b/libSBRdec/src/arm/lpp_tran_arm.cpp index 78bbc2c..db1948f 100644 --- a/libSBRdec/src/arm/lpp_tran_arm.cpp +++ b/libSBRdec/src/arm/lpp_tran_arm.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,73 +90,70 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -/******************************** Fraunhofer IIS *************************** +/**************************** SBR decoder library ****************************** Author(s): Arthur Tritthart - Description: (ARM optimised) LPP transposer subroutines -******************************************************************************/ + Description: (ARM optimised) LPP transposer subroutines +*******************************************************************************/ #if defined(__arm__) - #define FUNCTION_LPPTRANSPOSER_func1 #ifdef FUNCTION_LPPTRANSPOSER_func1 -/* Note: This code requires only 43 cycles per iteration instead of 61 on ARM926EJ-S */ -__attribute__ ((noinline)) static void lppTransposer_func1( - FIXP_DBL *lowBandReal, - FIXP_DBL *lowBandImag, - FIXP_DBL **qmfBufferReal, - FIXP_DBL **qmfBufferImag, - int loops, - int hiBand, - int dynamicScale, - int descale, - FIXP_SGL a0r, - FIXP_SGL a0i, - FIXP_SGL a1r, - FIXP_SGL a1i) -{ - +/* Note: This code requires only 43 cycles per iteration instead of 61 on + * ARM926EJ-S */ +static void lppTransposer_func1(FIXP_DBL *lowBandReal, FIXP_DBL *lowBandImag, + FIXP_DBL **qmfBufferReal, + FIXP_DBL **qmfBufferImag, int loops, int hiBand, + int dynamicScale, int descale, FIXP_SGL a0r, + FIXP_SGL a0i, FIXP_SGL a1r, FIXP_SGL a1i, + const int fPreWhitening, + FIXP_DBL preWhiteningGain, + int preWhiteningGains_sf) { FIXP_DBL real1, real2, imag1, imag2, accu1, accu2; real2 = lowBandReal[-2]; real1 = lowBandReal[-1]; imag2 = lowBandImag[-2]; imag1 = lowBandImag[-1]; - for(int i=0; i < loops; i++) - { - accu1 = fMultDiv2( a0r,real1); - accu2 = fMultDiv2( a0i,imag1); - accu1 = fMultAddDiv2(accu1,a1r,real2); - accu2 = fMultAddDiv2(accu2,a1i,imag2); - real2 = fMultDiv2( a1i,real2); + for (int i = 0; i < loops; i++) { + accu1 = fMultDiv2(a0r, real1); + accu2 = fMultDiv2(a0i, imag1); + accu1 = fMultAddDiv2(accu1, a1r, real2); + accu2 = fMultAddDiv2(accu2, a1i, imag2); + real2 = fMultDiv2(a1i, real2); accu1 = accu1 - accu2; accu1 = accu1 >> dynamicScale; - accu2 = fMultAddDiv2(real2,a1r,imag2); + accu2 = fMultAddDiv2(real2, a1r, imag2); real2 = real1; imag2 = imag1; - accu2 = fMultAddDiv2(accu2,a0i,real1); + accu2 = fMultAddDiv2(accu2, a0i, real1); real1 = lowBandReal[i]; - accu2 = fMultAddDiv2(accu2,a0r,imag1); + accu2 = fMultAddDiv2(accu2, a0r, imag1); imag1 = lowBandImag[i]; accu2 = accu2 >> dynamicScale; accu1 <<= 1; accu2 <<= 1; - - qmfBufferReal[i][hiBand] = accu1 + (real1>>descale); - qmfBufferImag[i][hiBand] = accu2 + (imag1>>descale); + accu1 += (real1 >> descale); + accu2 += (imag1 >> descale); + if (fPreWhitening) { + accu1 = scaleValueSaturate(fMultDiv2(accu1, preWhiteningGain), + preWhiteningGains_sf); + accu2 = scaleValueSaturate(fMultDiv2(accu2, preWhiteningGain), + preWhiteningGains_sf); + } + qmfBufferReal[i][hiBand] = accu1; + qmfBufferImag[i][hiBand] = accu2; } } -#endif /* #ifdef FUNCTION_LPPTRANSPOSER_func1 */ -#endif /* __arm__ */ - - +#endif /* #ifdef FUNCTION_LPPTRANSPOSER_func1 */ +#endif /* __arm__ */ diff --git a/libSBRdec/src/env_calc.cpp b/libSBRdec/src/env_calc.cpp index 73bd7ba..d7a8bb5 100644 --- a/libSBRdec/src/env_calc.cpp +++ b/libSBRdec/src/env_calc.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,11 +90,19 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief Envelope calculation + \brief Envelope calculation The envelope adjustor compares the energies present in the transposed highband to the reference energies conveyed with the bitstream. @@ -111,16 +130,17 @@ amm-info@iis.fraunhofer.de However, in average only the data of 1 frame is being processed as the adjustor is called once per frame. - Depending on the frequency range set in the bitstream, only QMF-subbands between - <em>lowSubband</em> and <em>highSubband</em> are adjusted. + Depending on the frequency range set in the bitstream, only QMF-subbands + between <em>lowSubband</em> and <em>highSubband</em> are adjusted. - Scaling of spectral data to maximize SNR (see #QMF_SCALE_FACTOR) as well as a special Mantissa-Exponent format - ( see calculateSbrEnvelope() ) are being used. The main entry point for this modules is calculateSbrEnvelope(). + Scaling of spectral data to maximize SNR (see #QMF_SCALE_FACTOR) as well as a + special Mantissa-Exponent format ( see calculateSbrEnvelope() ) are being + used. The main entry point for this modules is calculateSbrEnvelope(). - \sa sbr_scale.h, #QMF_SCALE_FACTOR, calculateSbrEnvelope(), \ref documentationOverview + \sa sbr_scale.h, #QMF_SCALE_FACTOR, calculateSbrEnvelope(), \ref + documentationOverview */ - #include "env_calc.h" #include "sbrdec_freq_sca.h" @@ -129,203 +149,260 @@ amm-info@iis.fraunhofer.de #include "sbr_ram.h" #include "sbr_rom.h" -#include "genericStds.h" /* need FDKpow() for debug outputs */ - -#if defined(__arm__) -#include "arm/env_calc_arm.cpp" -#endif - -typedef struct -{ - FIXP_DBL nrgRef[MAX_FREQ_COEFFS]; - FIXP_DBL nrgEst[MAX_FREQ_COEFFS]; - FIXP_DBL nrgGain[MAX_FREQ_COEFFS]; - FIXP_DBL noiseLevel[MAX_FREQ_COEFFS]; - FIXP_DBL nrgSine[MAX_FREQ_COEFFS]; - - SCHAR nrgRef_e[MAX_FREQ_COEFFS]; - SCHAR nrgEst_e[MAX_FREQ_COEFFS]; - SCHAR nrgGain_e[MAX_FREQ_COEFFS]; - SCHAR noiseLevel_e[MAX_FREQ_COEFFS]; - SCHAR nrgSine_e[MAX_FREQ_COEFFS]; -} -ENV_CALC_NRGS; - -static void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, - SCHAR *filtBuffer_e, - FIXP_DBL *NrgGain, - SCHAR *NrgGain_e, - int subbands); - -static void calcNrgPerSubband(FIXP_DBL **analysBufferReal, - FIXP_DBL **analysBufferImag, - int lowSubband, int highSubband, - int start_pos, int next_pos, - SCHAR frameExp, - FIXP_DBL *nrgEst, - SCHAR *nrgEst_e ); - -static void calcNrgPerSfb(FIXP_DBL **analysBufferReal, - FIXP_DBL **analysBufferImag, - int nSfb, - UCHAR *freqBandTable, - int start_pos, int next_pos, - SCHAR input_e, - FIXP_DBL *nrg_est, - SCHAR *nrg_est_e ); - -static void calcSubbandGain(FIXP_DBL nrgRef, SCHAR nrgRef_e, ENV_CALC_NRGS* nrgs, int c, - FIXP_DBL tmpNoise, SCHAR tmpNoise_e, - UCHAR sinePresentFlag, - UCHAR sineMapped, - int noNoiseFlag); - -static void calcAvgGain(ENV_CALC_NRGS* nrgs, - int lowSubband, - int highSubband, - FIXP_DBL *sumRef_m, - SCHAR *sumRef_e, - FIXP_DBL *ptrAvgGain_m, - SCHAR *ptrAvgGain_e); - -static void adjustTimeSlot_EldGrid(FIXP_DBL *ptrReal, - ENV_CALC_NRGS* nrgs, - UCHAR *ptrHarmIndex, - int lowSubbands, - int noSubbands, - int scale_change, - int noNoiseFlag, - int *ptrPhaseIndex, - int scale_diff_low); - -static void adjustTimeSlotLC(FIXP_DBL *ptrReal, - ENV_CALC_NRGS* nrgs, - UCHAR *ptrHarmIndex, - int lowSubbands, - int noSubbands, - int scale_change, - int noNoiseFlag, - int *ptrPhaseIndex); -static void adjustTimeSlotHQ(FIXP_DBL *ptrReal, - FIXP_DBL *ptrImag, - HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, - ENV_CALC_NRGS* nrgs, - int lowSubbands, - int noSubbands, - int scale_change, - FIXP_SGL smooth_ratio, - int noNoiseFlag, - int filtBufferNoiseShift); - +#include "genericStds.h" /* need FDKpow() for debug outputs */ + +typedef struct { + FIXP_DBL nrgRef[MAX_FREQ_COEFFS]; + FIXP_DBL nrgEst[MAX_FREQ_COEFFS]; + FIXP_DBL nrgGain[MAX_FREQ_COEFFS]; + FIXP_DBL noiseLevel[MAX_FREQ_COEFFS]; + FIXP_DBL nrgSine[MAX_FREQ_COEFFS]; + + SCHAR nrgRef_e[MAX_FREQ_COEFFS]; + SCHAR nrgEst_e[MAX_FREQ_COEFFS]; + SCHAR nrgGain_e[MAX_FREQ_COEFFS]; + SCHAR noiseLevel_e[MAX_FREQ_COEFFS]; + SCHAR nrgSine_e[MAX_FREQ_COEFFS]; + /* yet another exponent [0]: for ts < no_cols; [1]: for ts >= no_cols */ + SCHAR exponent[2]; +} ENV_CALC_NRGS; + +static void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, SCHAR *filtBuffer_e, + FIXP_DBL *NrgGain, SCHAR *NrgGain_e, + int subbands); + +static void calcNrgPerSubband(FIXP_DBL **analysBufferReal, + FIXP_DBL **analysBufferImag, int lowSubband, + int highSubband, int start_pos, int next_pos, + SCHAR frameExp, FIXP_DBL *nrgEst, + SCHAR *nrgEst_e); + +static void calcNrgPerSfb(FIXP_DBL **analysBufferReal, + FIXP_DBL **analysBufferImag, int nSfb, + UCHAR *freqBandTable, int start_pos, int next_pos, + SCHAR input_e, FIXP_DBL *nrg_est, SCHAR *nrg_est_e); + +static void calcSubbandGain(FIXP_DBL nrgRef, SCHAR nrgRef_e, + ENV_CALC_NRGS *nrgs, int c, FIXP_DBL tmpNoise, + SCHAR tmpNoise_e, UCHAR sinePresentFlag, + UCHAR sineMapped, int noNoiseFlag); + +static void calcAvgGain(ENV_CALC_NRGS *nrgs, int lowSubband, int highSubband, + FIXP_DBL *sumRef_m, SCHAR *sumRef_e, + FIXP_DBL *ptrAvgGain_m, SCHAR *ptrAvgGain_e); + +static void adjustTimeSlot_EldGrid(FIXP_DBL *ptrReal, ENV_CALC_NRGS *nrgs, + UCHAR *ptrHarmIndex, int lowSubbands, + int noSubbands, int scale_change, + int noNoiseFlag, int *ptrPhaseIndex, + int scale_diff_low); + +static void adjustTimeSlotLC(FIXP_DBL *ptrReal, ENV_CALC_NRGS *nrgs, + UCHAR *ptrHarmIndex, int lowSubbands, + int noSubbands, int scale_change, int noNoiseFlag, + int *ptrPhaseIndex); + +/** + * \brief Variant of adjustTimeSlotHQ() which only regards gain and noise but no + * additional harmonics + */ +static void adjustTimeSlotHQ_GainAndNoise( + FIXP_DBL *ptrReal, FIXP_DBL *ptrImag, + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS *nrgs, + int lowSubbands, int noSubbands, int scale_change, FIXP_SGL smooth_ratio, + int noNoiseFlag, int filtBufferNoiseShift); +/** + * \brief Variant of adjustTimeSlotHQ() which only adds the additional harmonics + */ +static void adjustTimeSlotHQ_AddHarmonics( + FIXP_DBL *ptrReal, FIXP_DBL *ptrImag, + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS *nrgs, + int lowSubbands, int noSubbands, int scale_change); + +static void adjustTimeSlotHQ(FIXP_DBL *ptrReal, FIXP_DBL *ptrImag, + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, + ENV_CALC_NRGS *nrgs, int lowSubbands, + int noSubbands, int scale_change, + FIXP_SGL smooth_ratio, int noNoiseFlag, + int filtBufferNoiseShift); /*! \brief Map sine flags from bitstream to QMF bands - The bitstream carries only 1 sine flag per band and frame. - This function maps every sine flag from the bitstream to a specific QMF subband - and to a specific envelope where the sine shall start. - The result is stored in the vector sineMapped which contains one entry per - QMF subband. The value of an entry specifies the envelope where a sine - shall start. A value of #MAX_ENVELOPES indicates that no sine is present - in the subband. - The missing harmonics flags from the previous frame (harmFlagsPrev) determine - if a sine starts at the beginning of the frame or at the transient position. - Additionally, the flags in harmFlagsPrev are being updated by this function - for the next frame. + The bitstream carries only 1 sine flag per band (Sfb) and frame. + This function maps every sine flag from the bitstream to a specific QMF + subband and to a specific envelope where the sine shall start. The result is + stored in the vector sineMapped which contains one entry per QMF subband. The + value of an entry specifies the envelope where a sine shall start. A value of + 32 indicates that no sine is present in the subband. The missing harmonics + flags from the previous frame (harmFlagsPrev) determine if a sine starts at + the beginning of the frame or at the transient position. Additionally, the + flags in harmFlagsPrev are being updated by this function for the next frame. */ -static void mapSineFlags(UCHAR *freqBandTable, /*!< Band borders (there's only 1 flag per band) */ - int nSfb, /*!< Number of bands in the table */ - UCHAR *addHarmonics, /*!< vector with 1 flag per sfb */ - int *harmFlagsPrev, /*!< Packed 'addHarmonics' */ - int tranEnv, /*!< Transient position */ - SCHAR *sineMapped) /*!< Resulting vector of sine start positions for each QMF band */ +static void mapSineFlags( + UCHAR *freqBandTable, /*!< Band borders (there's only 1 flag per band) */ + int nSfb, /*!< Number of bands in the table */ + ULONG *addHarmonics, /*!< Packed addHarmonics of current frame (aligned to + the MSB) */ + ULONG *harmFlagsPrev, /*!< Packed addHarmonics of previous frame (aligned to + the LSB) */ + ULONG *harmFlagsPrevActive, /*!< Packed sineMapped of previous frame + (aligned to the LSB) */ + int tranEnv, /*!< Transient position */ + SCHAR *sineMapped) /*!< Resulting vector of sine start positions for each + QMF band */ { int i; - int lowSubband2 = freqBandTable[0]<<1; - int bitcount = 0; - int oldflags = *harmFlagsPrev; - int newflags = 0; + int bitcount = 31; + ULONG harmFlagsQmfBands[ADD_HARMONICS_FLAGS_SIZE] = {0}; + ULONG *curFlags = addHarmonics; /* - Format of harmFlagsPrev: + Format of addHarmonics (aligned to MSB): - first word = flags for highest 16 sfb bands in use - second word = flags for next lower 16 sfb bands (if present) - third word = flags for lowest 16 sfb bands (if present) + Up to MAX_FREQ_COEFFS sfb bands can be flagged for a sign. + first word = flags for lowest 32 sfb bands in use + second word = flags for higest 32 sfb bands (if present) - Up to MAX_FREQ_COEFFS sfb bands can be flagged for a sign. - The lowest bit of the first word corresponds to the _highest_ sfb band in use. - This is ensures that each flag is mapped to the same QMF band even after a - change of the crossover-frequency. - */ + Format of harmFlagsPrev (aligned to LSB): + Index is absolute (not relative to lsb) so it is correct even if lsb + changes first word = flags for lowest 32 qmf bands (0...31) second word = + flags for next higher 32 qmf bands (32...63) - /* Reset the output vector first */ - FDKmemset(sineMapped, MAX_ENVELOPES,MAX_FREQ_COEFFS); /* MAX_ENVELOPES means 'no sine' */ - - freqBandTable += nSfb; - addHarmonics += nSfb-1; - - for (i=nSfb; i!=0; i--) { - int ui = *freqBandTable--; /* Upper limit of the current scale factor band. */ - int li = *freqBandTable; /* Lower limit of the current scale factor band. */ - - if ( *addHarmonics-- ) { /* There is a sine in this band */ + */ - unsigned int mask = 1 << bitcount; - newflags |= mask; /* Set flag */ + /* Reset the output vector first */ + FDKmemset(sineMapped, 32, + MAX_FREQ_COEFFS * sizeof(SCHAR)); /* 32 means 'no sine' */ + FDKmemclear(harmFlagsPrevActive, ADD_HARMONICS_FLAGS_SIZE * sizeof(ULONG)); + for (i = 0; i < nSfb; i++) { + ULONG maskSfb = + 1 << bitcount; /* mask to extract addHarmonics flag of current Sfb */ + + if (*curFlags & maskSfb) { /* There is a sine in this band */ + const int lsb = freqBandTable[0]; /* start of sbr range */ + /* qmf band to which sine should be added */ + const int qmfBand = (freqBandTable[i] + freqBandTable[i + 1]) >> 1; + const int qmfBandDiv32 = qmfBand >> 5; + const int maskQmfBand = + 1 << (qmfBand & + 31); /* mask to extract harmonic flag from prevFlags */ + + /* mapping of sfb with sine to a certain qmf band -> for harmFlagsPrev */ + harmFlagsQmfBands[qmfBandDiv32] |= maskQmfBand; /* - If there was a sine in the last frame, let it continue from the first envelope on - else start at the transient position. + If there was a sine in the last frame, let it continue from the first + envelope on else start at the transient position. Indexing of sineMapped + starts relative to lsb. */ - sineMapped[(ui+li-lowSubband2) >> 1] = ( oldflags & mask ) ? 0 : tranEnv; + sineMapped[qmfBand - lsb] = + (harmFlagsPrev[qmfBandDiv32] & maskQmfBand) ? 0 : tranEnv; + if (sineMapped[qmfBand - lsb] < PVC_NTIMESLOT) { + harmFlagsPrevActive[qmfBandDiv32] |= maskQmfBand; + } } - if ((++bitcount == 16) || i==1) { - bitcount = 0; - *harmFlagsPrev++ = newflags; - oldflags = *harmFlagsPrev; /* Fetch 16 of the old flags */ - newflags = 0; + if (bitcount-- == 0) { + bitcount = 31; + curFlags++; } } + FDKmemcpy(harmFlagsPrev, harmFlagsQmfBands, + sizeof(ULONG) * ADD_HARMONICS_FLAGS_SIZE); } +/*! + \brief Restore sineMapped of previous frame + + For PVC it might happen that the PVC framing (always 0) is out of sync with + the SBR framing. The adding of additional harmonics is done based on the SBR + framing. If the SBR framing is trailing the PVC framing the sine mapping of + the previous SBR frame needs to be used for the overlapping time slots. +*/ +/*static*/ void mapSineFlagsPvc( + UCHAR *freqBandTable, /*!< Band borders (there's only 1 flag per + band) */ + int nSfb, /*!< Number of bands in the table */ + ULONG *harmFlagsPrev, /*!< Packed addHarmonics of previous frame + (aligned to the MSB) */ + ULONG *harmFlagsPrevActive, /*!< Packed sineMapped of previous + frame (aligned to the LSB) */ + SCHAR *sineMapped, /*!< Resulting vector of sine start positions + for each QMF band */ + int sinusoidalPos, /*!< sinusoidal position */ + SCHAR *sinusoidalPosPrev, /*!< sinusoidal position of previous + frame */ + int trailingSbrFrame) /*!< indication if the SBR framing is + trailing the PVC framing */ +{ + /* Reset the output vector first */ + FDKmemset(sineMapped, 32, MAX_FREQ_COEFFS); /* 32 means 'no sine' */ + + if (trailingSbrFrame) { + /* restore sineMapped[] of previous frame */ + int i; + const int lsb = freqBandTable[0]; + const int usb = freqBandTable[nSfb]; + for (i = lsb; i < usb; i++) { + const int qmfBandDiv32 = i >> 5; + const int maskQmfBand = + 1 << (i & 31); /* mask to extract harmonic flag from prevFlags */ + + /* Two cases need to be distinguished ... */ + if (harmFlagsPrevActive[qmfBandDiv32] & maskQmfBand) { + /* the sine mapping already started last PVC frame -> seamlessly + * continue */ + sineMapped[i - lsb] = 0; + } else if (harmFlagsPrev[qmfBandDiv32] & maskQmfBand) { + /* sinusoidalPos of prev PVC frame was >= PVC_NTIMESLOT -> sine starts + * in this frame */ + sineMapped[i - lsb] = + *sinusoidalPosPrev - PVC_NTIMESLOT; /* we are 16 sbr time slots + ahead of last frame now */ + } + } + } + *sinusoidalPosPrev = sinusoidalPos; +} /*! \brief Reduce gain-adjustment induced aliasing for real valued filterbank. */ -/*static*/ void -aliasingReduction(FIXP_DBL* degreeAlias, /*!< estimated aliasing for each QMF channel */ - ENV_CALC_NRGS* nrgs, - int* useAliasReduction, /*!< synthetic sine engergy for each subband, used as flag */ - int noSubbands) /*!< number of QMF channels to process */ +/*static*/ void aliasingReduction( + FIXP_DBL *degreeAlias, /*!< estimated aliasing for each QMF + channel */ + ENV_CALC_NRGS *nrgs, + UCHAR *useAliasReduction, /*!< synthetic sine energy for each + subband, used as flag */ + int noSubbands) /*!< number of QMF channels to process */ { - FIXP_DBL* nrgGain = nrgs->nrgGain; /*!< subband gains to be modified */ - SCHAR* nrgGain_e = nrgs->nrgGain_e; /*!< subband gains to be modified (exponents) */ - FIXP_DBL* nrgEst = nrgs->nrgEst; /*!< subband energy before amplification */ - SCHAR* nrgEst_e = nrgs->nrgEst_e; /*!< subband energy before amplification (exponents) */ + FIXP_DBL *nrgGain = nrgs->nrgGain; /*!< subband gains to be modified */ + SCHAR *nrgGain_e = + nrgs->nrgGain_e; /*!< subband gains to be modified (exponents) */ + FIXP_DBL *nrgEst = nrgs->nrgEst; /*!< subband energy before amplification */ + SCHAR *nrgEst_e = + nrgs->nrgEst_e; /*!< subband energy before amplification (exponents) */ int grouping = 0, index = 0, noGroups, k; int groupVector[MAX_FREQ_COEFFS]; /* Calculate grouping*/ - for (k = 0; k < noSubbands-1; k++ ){ - if ( (degreeAlias[k + 1] != FL2FXCONST_DBL(0.0f)) && useAliasReduction[k] ) { - if(grouping==0){ + for (k = 0; k < noSubbands - 1; k++) { + if ((degreeAlias[k + 1] != FL2FXCONST_DBL(0.0f)) && useAliasReduction[k]) { + if (grouping == 0) { groupVector[index++] = k; grouping = 1; - } - else{ - if(groupVector[index-1] + 3 == k){ + } else { + if (groupVector[index - 1] + 3 == k) { groupVector[index++] = k + 1; grouping = 0; } } - } - else{ - if(grouping){ - if(useAliasReduction[k]) + } else { + if (grouping) { + if (useAliasReduction[k]) groupVector[index++] = k + 1; else groupVector[index++] = k; @@ -334,90 +411,384 @@ aliasingReduction(FIXP_DBL* degreeAlias, /*!< estimated aliasing for each } } - if(grouping){ + if (grouping) { groupVector[index++] = noSubbands; } noGroups = index >> 1; - /*Calculate new gain*/ - for (int group = 0; group < noGroups; group ++) { - FIXP_DBL nrgOrig = FL2FXCONST_DBL(0.0f); /* Original signal energy in current group of bands */ - SCHAR nrgOrig_e = 0; - FIXP_DBL nrgAmp = FL2FXCONST_DBL(0.0f); /* Amplified signal energy in group (using current gains) */ - SCHAR nrgAmp_e = 0; - FIXP_DBL nrgMod = FL2FXCONST_DBL(0.0f); /* Signal energy in group when applying modified gains */ - SCHAR nrgMod_e = 0; - FIXP_DBL groupGain; /* Total energy gain in group */ - SCHAR groupGain_e; - FIXP_DBL compensation; /* Compensation factor for the energy change when applying modified gains */ - SCHAR compensation_e; - - int startGroup = groupVector[2*group]; - int stopGroup = groupVector[2*group+1]; - - /* Calculate total energy in group before and after amplification with current gains: */ - for(k = startGroup; k < stopGroup; k++){ + for (int group = 0; group < noGroups; group++) { + FIXP_DBL nrgOrig = FL2FXCONST_DBL( + 0.0f); /* Original signal energy in current group of bands */ + SCHAR nrgOrig_e = 0; + FIXP_DBL nrgAmp = FL2FXCONST_DBL( + 0.0f); /* Amplified signal energy in group (using current gains) */ + SCHAR nrgAmp_e = 0; + FIXP_DBL nrgMod = FL2FXCONST_DBL( + 0.0f); /* Signal energy in group when applying modified gains */ + SCHAR nrgMod_e = 0; + FIXP_DBL groupGain; /* Total energy gain in group */ + SCHAR groupGain_e; + FIXP_DBL compensation; /* Compensation factor for the energy change when + applying modified gains */ + SCHAR compensation_e; + + int startGroup = groupVector[2 * group]; + int stopGroup = groupVector[2 * group + 1]; + + /* Calculate total energy in group before and after amplification with + * current gains: */ + for (k = startGroup; k < stopGroup; k++) { /* Get original band energy */ FIXP_DBL tmp = nrgEst[k]; - SCHAR tmp_e = nrgEst_e[k]; + SCHAR tmp_e = nrgEst_e[k]; FDK_add_MantExp(tmp, tmp_e, nrgOrig, nrgOrig_e, &nrgOrig, &nrgOrig_e); /* Multiply band energy with current gain */ - tmp = fMult(tmp,nrgGain[k]); + tmp = fMult(tmp, nrgGain[k]); tmp_e = tmp_e + nrgGain_e[k]; FDK_add_MantExp(tmp, tmp_e, nrgAmp, nrgAmp_e, &nrgAmp, &nrgAmp_e); } /* Calculate total energy gain in group */ - FDK_divide_MantExp(nrgAmp, nrgAmp_e, - nrgOrig, nrgOrig_e, - &groupGain, &groupGain_e); + FDK_divide_MantExp(nrgAmp, nrgAmp_e, nrgOrig, nrgOrig_e, &groupGain, + &groupGain_e); - for(k = startGroup; k < stopGroup; k++){ + for (k = startGroup; k < stopGroup; k++) { FIXP_DBL tmp; - SCHAR tmp_e; + SCHAR tmp_e; FIXP_DBL alpha = degreeAlias[k]; if (k < noSubbands - 1) { - if (degreeAlias[k + 1] > alpha) - alpha = degreeAlias[k + 1]; + if (degreeAlias[k + 1] > alpha) alpha = degreeAlias[k + 1]; } /* Modify gain depending on the degree of aliasing */ - FDK_add_MantExp( fMult(alpha,groupGain), groupGain_e, - fMult(/*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - alpha,nrgGain[k]), nrgGain_e[k], - &nrgGain[k], &nrgGain_e[k] ); + FDK_add_MantExp( + fMult(alpha, groupGain), groupGain_e, + fMult(/*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - alpha, + nrgGain[k]), + nrgGain_e[k], &nrgGain[k], &nrgGain_e[k]); /* Apply modified gain to original energy */ - tmp = fMult(nrgGain[k],nrgEst[k]); + tmp = fMult(nrgGain[k], nrgEst[k]); tmp_e = nrgGain_e[k] + nrgEst_e[k]; /* Accumulate energy with modified gains applied */ - FDK_add_MantExp( tmp, tmp_e, - nrgMod, nrgMod_e, - &nrgMod, &nrgMod_e ); + FDK_add_MantExp(tmp, tmp_e, nrgMod, nrgMod_e, &nrgMod, &nrgMod_e); } - /* Calculate compensation factor to retain the energy of the amplified signal */ - FDK_divide_MantExp(nrgAmp, nrgAmp_e, - nrgMod, nrgMod_e, - &compensation, &compensation_e); + /* Calculate compensation factor to retain the energy of the amplified + * signal */ + FDK_divide_MantExp(nrgAmp, nrgAmp_e, nrgMod, nrgMod_e, &compensation, + &compensation_e); /* Apply compensation factor to all gains of the group */ - for(k = startGroup; k < stopGroup; k++){ - nrgGain[k] = fMult(nrgGain[k],compensation); + for (k = startGroup; k < stopGroup; k++) { + nrgGain[k] = fMult(nrgGain[k], compensation); nrgGain_e[k] = nrgGain_e[k] + compensation_e; } } } +#define INTER_TES_SF_CHANGE 3 + +typedef struct { + FIXP_DBL subsample_power_low[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL subsample_power_high[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL gain[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + SCHAR subsample_power_low_sf[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + SCHAR subsample_power_high_sf[(((1024) / (32) * (4) / 2) + (3 * (4)))]; +} ITES_TEMP; + +static void apply_inter_tes(FIXP_DBL **qmfReal, FIXP_DBL **qmfImag, + const QMF_SCALE_FACTOR *sbrScaleFactor, + const SCHAR exp[2], const int RATE, + const int startPos, const int stopPos, + const int lowSubband, const int nbSubband, + const UCHAR gamma_idx) { + int highSubband = lowSubband + nbSubband; + FIXP_DBL *subsample_power_high, *subsample_power_low; + SCHAR *subsample_power_high_sf, *subsample_power_low_sf; + FIXP_DBL total_power_high = (FIXP_DBL)0; + FIXP_DBL total_power_low = (FIXP_DBL)0; + FIXP_DBL *gain; + int gain_sf[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + + /* gamma[gamma_idx] = {0.0f, 1.0f, 2.0f, 4.0f} */ + int gamma_sf = + (int)gamma_idx - 1; /* perhaps +1 to save one bit? (0.99999f vs 1.f) */ + + int nbSubsample = stopPos - startPos; + int i, j; + + C_ALLOC_SCRATCH_START(pTmp, ITES_TEMP, 1); + subsample_power_high = pTmp->subsample_power_high; + subsample_power_low = pTmp->subsample_power_low; + subsample_power_high_sf = pTmp->subsample_power_high_sf; + subsample_power_low_sf = pTmp->subsample_power_low_sf; + gain = pTmp->gain; + + if (gamma_idx > 0) { + int preShift2 = 32 - fNormz((FIXP_DBL)nbSubsample); + int total_power_low_sf = 1 - DFRACT_BITS; + int total_power_high_sf = 1 - DFRACT_BITS; + + for (i = 0; i < nbSubsample; ++i) { + FIXP_DBL bufferReal[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL bufferImag[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL maxVal = (FIXP_DBL)0; + + int ts = startPos + i; + + int low_sf = (ts < 3 * RATE) ? sbrScaleFactor->ov_lb_scale + : sbrScaleFactor->lb_scale; + low_sf = 15 - low_sf; + + for (j = 0; j < lowSubband; ++j) { + bufferImag[j] = qmfImag[startPos + i][j]; + maxVal |= (FIXP_DBL)((LONG)(bufferImag[j]) ^ + ((LONG)bufferImag[j] >> (DFRACT_BITS - 1))); + bufferReal[j] = qmfReal[startPos + i][j]; + maxVal |= (FIXP_DBL)((LONG)(bufferReal[j]) ^ + ((LONG)bufferReal[j] >> (DFRACT_BITS - 1))); + } + + subsample_power_low[i] = (FIXP_DBL)0; + subsample_power_low_sf[i] = 0; + + if (maxVal != FL2FXCONST_DBL(0.f)) { + /* multiply first, then shift for safe summation */ + int preShift = 1 - CntLeadingZeros(maxVal); + int postShift = 32 - fNormz((FIXP_DBL)lowSubband); + + /* reduce preShift because otherwise we risk to square -1.f */ + if (preShift != 0) preShift++; + + subsample_power_low_sf[i] += (low_sf + preShift) * 2 + postShift + 1; + + scaleValues(bufferReal, lowSubband, -preShift); + scaleValues(bufferImag, lowSubband, -preShift); + for (j = 0; j < lowSubband; ++j) { + FIXP_DBL addme; + addme = fPow2Div2(bufferReal[j]); + subsample_power_low[i] += addme >> postShift; + addme = fPow2Div2(bufferImag[j]); + subsample_power_low[i] += addme >> postShift; + } + } + + /* now get high */ + + maxVal = (FIXP_DBL)0; + + int high_sf = exp[(ts < 16 * RATE) ? 0 : 1]; + + for (j = lowSubband; j < highSubband; ++j) { + bufferImag[j] = qmfImag[startPos + i][j]; + maxVal |= (FIXP_DBL)((LONG)(bufferImag[j]) ^ + ((LONG)bufferImag[j] >> (DFRACT_BITS - 1))); + bufferReal[j] = qmfReal[startPos + i][j]; + maxVal |= (FIXP_DBL)((LONG)(bufferReal[j]) ^ + ((LONG)bufferReal[j] >> (DFRACT_BITS - 1))); + } + + subsample_power_high[i] = (FIXP_DBL)0; + subsample_power_high_sf[i] = 0; + + if (maxVal != FL2FXCONST_DBL(0.f)) { + int preShift = 1 - CntLeadingZeros(maxVal); + /* reduce preShift because otherwise we risk to square -1.f */ + if (preShift != 0) preShift++; + + int postShift = 32 - fNormz((FIXP_DBL)(highSubband - lowSubband)); + subsample_power_high_sf[i] += (high_sf + preShift) * 2 + postShift + 1; - /* Convert headroom bits to exponent */ -#define SCALE2EXP(s) (15-(s)) -#define EXP2SCALE(e) (15-(e)) + scaleValues(&bufferReal[lowSubband], highSubband - lowSubband, + -preShift); + scaleValues(&bufferImag[lowSubband], highSubband - lowSubband, + -preShift); + for (j = lowSubband; j < highSubband; j++) { + subsample_power_high[i] += fPow2Div2(bufferReal[j]) >> postShift; + subsample_power_high[i] += fPow2Div2(bufferImag[j]) >> postShift; + } + } + + /* sum all together */ + FIXP_DBL new_summand = subsample_power_low[i]; + int new_summand_sf = subsample_power_low_sf[i]; + + /* make sure the current sum, and the new summand have the same SF */ + if (new_summand_sf > total_power_low_sf) { + int diff = fMin(DFRACT_BITS - 1, new_summand_sf - total_power_low_sf); + total_power_low >>= diff; + total_power_low_sf = new_summand_sf; + } else if (new_summand_sf < total_power_low_sf) { + new_summand >>= total_power_low_sf - new_summand_sf; + } + + total_power_low += (new_summand >> preShift2); + + new_summand = subsample_power_high[i]; + new_summand_sf = subsample_power_high_sf[i]; + if (new_summand_sf > total_power_high_sf) { + total_power_high >>= + fMin(DFRACT_BITS - 1, new_summand_sf - total_power_high_sf); + total_power_high_sf = new_summand_sf; + } else if (new_summand_sf < total_power_high_sf) { + new_summand >>= total_power_high_sf - new_summand_sf; + } + + total_power_high += (new_summand >> preShift2); + } + + total_power_low_sf += preShift2; + total_power_high_sf += preShift2; + + /* gain[i] = e_LOW[i] */ + for (i = 0; i < nbSubsample; ++i) { + int sf2; + FIXP_DBL mult = + fMultNorm(subsample_power_low[i], (FIXP_DBL)nbSubsample, &sf2); + int mult_sf = subsample_power_low_sf[i] + DFRACT_BITS - 1 + sf2; + + if (total_power_low != FIXP_DBL(0)) { + gain[i] = fDivNorm(mult, total_power_low, &sf2); + gain_sf[i] = mult_sf - total_power_low_sf + sf2; + gain[i] = sqrtFixp_lookup(gain[i], &gain_sf[i]); + if (gain_sf[i] < 0) { + gain[i] >>= -gain_sf[i]; + gain_sf[i] = 0; + } + } else { + if (mult == FIXP_DBL(0)) { + gain[i] = FIXP_DBL(0); + gain_sf[i] = 0; + } else { + gain[i] = (FIXP_DBL)MAXVAL_DBL; + gain_sf[i] = 0; + } + } + } + + FIXP_DBL total_power_high_after = (FIXP_DBL)0; + int total_power_high_after_sf = 1 - DFRACT_BITS; + + /* gain[i] = g_inter[i] */ + for (i = 0; i < nbSubsample; ++i) { + if (gain_sf[i] < 0) { + gain[i] >>= -gain_sf[i]; + gain_sf[i] = 0; + } + + /* calculate: gain[i] = 1.0f + gamma * (gain[i] - 1.0f); */ + FIXP_DBL one = (FIXP_DBL)MAXVAL_DBL >> + gain_sf[i]; /* to substract this from gain[i] */ + + /* gamma is actually always 1 according to the table, so skip the + * fMultDiv2 */ + FIXP_DBL mult = (gain[i] - one) >> 1; + int mult_sf = gain_sf[i] + gamma_sf; + + one = FL2FXCONST_DBL(0.5f) >> mult_sf; + gain[i] = one + mult; + gain_sf[i] += gamma_sf + 1; /* +1 because of fMultDiv2() */ + + /* set gain to at least 0.2f */ + FIXP_DBL point_two = FL2FXCONST_DBL(0.8f); /* scaled up by 2 */ + int point_two_sf = -2; + + FIXP_DBL tmp = gain[i]; + if (point_two_sf < gain_sf[i]) { + point_two >>= gain_sf[i] - point_two_sf; + } else { + tmp >>= point_two_sf - gain_sf[i]; + } + + /* limit and calculate gain[i]^2 too */ + FIXP_DBL gain_pow2; + int gain_pow2_sf; + if (tmp < point_two) { + gain[i] = FL2FXCONST_DBL(0.8f); + gain_sf[i] = -2; + gain_pow2 = FL2FXCONST_DBL(0.64f); + gain_pow2_sf = -4; + } else { + /* this upscaling seems quite important */ + int r = CountLeadingBits(gain[i]); + gain[i] <<= r; + gain_sf[i] -= r; + + gain_pow2 = fPow2(gain[i]); + gain_pow2_sf = gain_sf[i] << 1; + } + + int room; + subsample_power_high[i] = + fMultNorm(subsample_power_high[i], gain_pow2, &room); + subsample_power_high_sf[i] = + subsample_power_high_sf[i] + gain_pow2_sf + room; + + int new_summand_sf = subsample_power_high_sf[i]; /* + gain_pow2_sf; */ + if (new_summand_sf > total_power_high_after_sf) { + total_power_high_after >>= + fMin(DFRACT_BITS - 1, new_summand_sf - total_power_high_after_sf); + total_power_high_after_sf = new_summand_sf; + } else if (new_summand_sf < total_power_high_after_sf) { + subsample_power_high[i] >>= total_power_high_after_sf - new_summand_sf; + } + total_power_high_after += subsample_power_high[i] >> preShift2; + } + + total_power_high_after_sf += preShift2; + + int sf2 = 0; + FIXP_DBL gain_adj_2 = FL2FX_DBL(0.5f); + int gain_adj_2_sf = 1; + + if ((total_power_high != (FIXP_DBL)0) && + (total_power_high_after != (FIXP_DBL)0)) { + gain_adj_2 = fDivNorm(total_power_high, total_power_high_after, &sf2); + gain_adj_2_sf = total_power_high_sf - total_power_high_after_sf + sf2; + } + + FIXP_DBL gain_adj = sqrtFixp_lookup(gain_adj_2, &gain_adj_2_sf); + int gain_adj_sf = gain_adj_2_sf; + + for (i = 0; i < nbSubsample; ++i) { + gain[i] = fMult(gain[i], gain_adj); + gain_sf[i] += gain_adj_sf; + + /* limit gain */ + if (gain_sf[i] > INTER_TES_SF_CHANGE) { + gain[i] = (FIXP_DBL)MAXVAL_DBL; + gain_sf[i] = INTER_TES_SF_CHANGE; + } + } + + for (i = 0; i < nbSubsample; ++i) { + /* equalize gain[]'s scale factors */ + gain[i] >>= INTER_TES_SF_CHANGE - gain_sf[i]; + + for (j = lowSubband; j < highSubband; j++) { + qmfReal[startPos + i][j] = fMult(qmfReal[startPos + i][j], gain[i]); + qmfImag[startPos + i][j] = fMult(qmfImag[startPos + i][j], gain[i]); + } + } + } else { /* gamma_idx == 0 */ + /* Inter-TES is not active. Still perform the scale change to have a + * consistent scaling for all envelopes of this frame. */ + for (i = 0; i < nbSubsample; ++i) { + for (j = lowSubband; j < highSubband; j++) { + qmfReal[startPos + i][j] >>= INTER_TES_SF_CHANGE; + qmfImag[startPos + i][j] >>= INTER_TES_SF_CHANGE; + } + } + } + C_ALLOC_SCRATCH_END(pTmp, ITES_TEMP, 1); +} /*! \brief Apply spectral envelope to subband samples @@ -430,7 +801,8 @@ aliasingReduction(FIXP_DBL* degreeAlias, /*!< estimated aliasing for each the suffixes <em>_m</em> and <em>_e</em> respectively. The control data in #hFrameData containts envelope data which is represented by this format but stored in single words. (See requantizeEnvelopeData() for details). This data - is unpacked within calculateSbrEnvelope() to follow the described suffix convention. + is unpacked within calculateSbrEnvelope() to follow the described suffix + convention. The actual value (comparable to the corresponding float-variable in the research-implementation) of a mantissa/exponent-pair can be calculated as @@ -438,49 +810,45 @@ aliasingReduction(FIXP_DBL* degreeAlias, /*!< estimated aliasing for each \f$ value = value\_m * 2^{value\_e} \f$ All energies and noise levels decoded from the bitstream suit for an - original signal magnitude of \f$\pm 32768 \f$ rather than \f$ \pm 1\f$. Therefore, - the scale factor <em>hb_scale</em> passed into this function will be converted - to an 'input exponent' (#input_e), which fits the internal representation. + original signal magnitude of \f$\pm 32768 \f$ rather than \f$ \pm 1\f$. + Therefore, the scale factor <em>hb_scale</em> passed into this function will + be converted to an 'input exponent' (#input_e), which fits the internal + representation. Before the actual processing, an exponent #adj_e for resulting adjusted samples is derived from the maximum reference energy. Then, for each envelope, the following steps are performed: - \li Calculate energy in the signal to be adjusted. Depending on the the value of - #interpolFreq (interpolation mode), this is either done seperately - for each QMF-subband or for each SBR-band. - The resulting energies are stored in #nrgEst_m[#MAX_FREQ_COEFFS] (mantissas) - and #nrgEst_e[#MAX_FREQ_COEFFS] (exponents). - \li Calculate gain and noise level for each subband:<br> - \f$ gain = \sqrt{ \frac{nrgRef}{nrgEst} \cdot (1 - noiseRatio) } - \hspace{2cm} - noise = \sqrt{ nrgRef \cdot noiseRatio } - \f$<br> - where <em>noiseRatio</em> and <em>nrgRef</em> are extracted from the - bitstream and <em>nrgEst</em> is the subband energy before adjustment. - The resulting gains are stored in #nrgGain_m[#MAX_FREQ_COEFFS] - (mantissas) and #nrgGain_e[#MAX_FREQ_COEFFS] (exponents), the noise levels - are stored in #noiseLevel_m[#MAX_FREQ_COEFFS] and #noiseLevel_e[#MAX_FREQ_COEFFS] - (exponents). - The sine levels are stored in #nrgSine_m[#MAX_FREQ_COEFFS] - and #nrgSine_e[#MAX_FREQ_COEFFS]. - \li Noise limiting: The gain for each subband is limited both absolutely - and relatively compared to the total gain over all subbands. - \li Boost gain: Calculate and apply boost factor for each limiter band - in order to compensate for the energy loss imposed by the limiting. - \li Apply gains and add noise: The gains and noise levels are applied - to all timeslots of the current envelope. A short FIR-filter (length 4 - QMF-timeslots) can be used to smooth the sudden change at the envelope borders. - Each complex subband sample of the current timeslot is multiplied by the - smoothed gain, then random noise with the calculated level is added. + \li Calculate energy in the signal to be adjusted. Depending on the the value + of #interpolFreq (interpolation mode), this is either done seperately for each + QMF-subband or for each SBR-band. The resulting energies are stored in + #nrgEst_m[#MAX_FREQ_COEFFS] (mantissas) and #nrgEst_e[#MAX_FREQ_COEFFS] + (exponents). \li Calculate gain and noise level for each subband:<br> \f$ gain + = \sqrt{ \frac{nrgRef}{nrgEst} \cdot (1 - noiseRatio) } \hspace{2cm} noise = + \sqrt{ nrgRef \cdot noiseRatio } \f$<br> where <em>noiseRatio</em> and + <em>nrgRef</em> are extracted from the bitstream and <em>nrgEst</em> is the + subband energy before adjustment. The resulting gains are stored in + #nrgGain_m[#MAX_FREQ_COEFFS] (mantissas) and #nrgGain_e[#MAX_FREQ_COEFFS] + (exponents), the noise levels are stored in #noiseLevel_m[#MAX_FREQ_COEFFS] + and #noiseLevel_e[#MAX_FREQ_COEFFS] (exponents). The sine levels are stored in + #nrgSine_m[#MAX_FREQ_COEFFS] and #nrgSine_e[#MAX_FREQ_COEFFS]. \li Noise + limiting: The gain for each subband is limited both absolutely and relatively + compared to the total gain over all subbands. \li Boost gain: Calculate and + apply boost factor for each limiter band in order to compensate for the energy + loss imposed by the limiting. \li Apply gains and add noise: The gains and + noise levels are applied to all timeslots of the current envelope. A short + FIR-filter (length 4 QMF-timeslots) can be used to smooth the sudden change at + the envelope borders. Each complex subband sample of the current timeslot is + multiplied by the smoothed gain, then random noise with the calculated level + is added. \note To reduce the stack size, some of the local arrays could be located within the time output buffer. Of the 512 samples temporarily available there, about half the size is already used by #SBR_FRAME_DATA. A pointer to the - remaining free memory could be supplied by an additional argument to calculateSbrEnvelope() - in sbr_dec: + remaining free memory could be supplied by an additional argument to + calculateSbrEnvelope() in sbr_dec: \par \code @@ -490,12 +858,12 @@ aliasingReduction(FIXP_DBL* degreeAlias, /*!< estimated aliasing for each hFrameData, QmfBufferReal, QmfBufferImag, - timeOutPtr + sizeof(SBR_FRAME_DATA)/sizeof(Float) + 1); - \endcode + timeOutPtr + sizeof(SBR_FRAME_DATA)/sizeof(Float) + + 1); \endcode \par - Within calculateSbrEnvelope(), some pointers could be defined instead of the arrays - #nrgRef_m, #nrgRef_e, #nrgEst_m, #nrgEst_e, #noiseLevel_m: + Within calculateSbrEnvelope(), some pointers could be defined instead of the + arrays #nrgRef_m, #nrgRef_e, #nrgEst_m, #nrgEst_e, #noiseLevel_m: \par \code @@ -508,56 +876,103 @@ aliasingReduction(FIXP_DBL* degreeAlias, /*!< estimated aliasing for each <br> */ -void -calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ - HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, /*!< Handle to struct filled by the create-function */ - HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ - HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ - FIXP_DBL **analysBufferReal, /*!< Real part of subband samples to be processed */ - FIXP_DBL **analysBufferImag, /*!< Imag part of subband samples to be processed */ - const int useLP, - FIXP_DBL *degreeAlias, /*!< Estimated aliasing for each QMF channel */ - const UINT flags, - const int frameErrorFlag - ) -{ - int c, i, j, envNoise = 0; - UCHAR* borders = hFrameData->frameInfo.borders; - - FIXP_SGL *noiseLevels = hFrameData->sbrNoiseFloorLevel; +void calculateSbrEnvelope( + QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ + HANDLE_SBR_CALCULATE_ENVELOPE + h_sbr_cal_env, /*!< Handle to struct filled by the create-function */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ + PVC_DYNAMIC_DATA *pPvcDynamicData, + FIXP_DBL * + *analysBufferReal, /*!< Real part of subband samples to be processed */ + FIXP_DBL * + *analysBufferImag, /*!< Imag part of subband samples to be processed */ + const int useLP, + FIXP_DBL *degreeAlias, /*!< Estimated aliasing for each QMF channel */ + const UINT flags, const int frameErrorFlag) { + int c, i, i_stop, j, envNoise = 0; + UCHAR *borders = hFrameData->frameInfo.borders; + UCHAR *bordersPvc = hFrameData->frameInfo.pvcBorders; + int pvc_mode = pPvcDynamicData->pvc_mode; + int first_start = + ((pvc_mode > 0) ? bordersPvc[0] : borders[0]) * hHeaderData->timeStep; + FIXP_SGL *noiseLevels = hFrameData->sbrNoiseFloorLevel; HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; + UCHAR **pFreqBandTable = hFreq->freqBandTable; + UCHAR *pFreqBandTableNoise = hFreq->freqBandTableNoise; - int lowSubband = hFreq->lowSubband; + int lowSubband = hFreq->lowSubband; int highSubband = hFreq->highSubband; - int noSubbands = highSubband - lowSubband; + int noSubbands = highSubband - lowSubband; + + /* old high subband before headerchange + we asume no headerchange here */ + int ov_highSubband = hFreq->highSubband; + + int noNoiseBands = hFreq->nNfb; + UCHAR *noSubFrameBands = hFreq->nSfb; + int no_cols = hHeaderData->numberTimeSlots * hHeaderData->timeStep; + + SCHAR sineMapped[MAX_FREQ_COEFFS]; + SCHAR ov_adj_e = SCALE2EXP(sbrScaleFactor->ov_hb_scale); + SCHAR adj_e = 0; + SCHAR output_e; + SCHAR final_e = 0; + /* inter-TES is active in one or more envelopes of the current SBR frame */ + const int iTES_enable = hFrameData->iTESactive; + const int iTES_scale_change = (iTES_enable) ? INTER_TES_SF_CHANGE : 0; + SCHAR maxGainLimit_e = (frameErrorFlag) ? MAX_GAIN_CONCEAL_EXP : MAX_GAIN_EXP; - int noNoiseBands = hFreq->nNfb; - int no_cols = hHeaderData->numberTimeSlots * hHeaderData->timeStep; - UCHAR first_start = borders[0] * hHeaderData->timeStep; + UCHAR smooth_length = 0; - SCHAR sineMapped[MAX_FREQ_COEFFS]; - SCHAR ov_adj_e = SCALE2EXP(sbrScaleFactor->ov_hb_scale); - SCHAR adj_e = 0; - SCHAR output_e; - SCHAR final_e = 0; + FIXP_SGL *pIenv = hFrameData->iEnvelope; - SCHAR maxGainLimit_e = (frameErrorFlag) ? MAX_GAIN_CONCEAL_EXP : MAX_GAIN_EXP; + C_ALLOC_SCRATCH_START(useAliasReduction, UCHAR, 64) - int useAliasReduction[64]; - UCHAR smooth_length = 0; + /* if values differ we had a headerchange; if old highband is bigger then new + one we need to patch overlap-highband-scaling for this frame (see use of + ov_highSubband) as overlap contains higher frequency components which would + get lost */ + if (hFreq->highSubband < hFreq->ov_highSubband) { + ov_highSubband = hFreq->ov_highSubband; + } - FIXP_SGL * pIenv = hFrameData->iEnvelope; + if (pvc_mode > 0) { + if (hFrameData->frameInfo.bordersNoise[0] > bordersPvc[0]) { + /* noise envelope of previous frame is trailing into current PVC frame */ + envNoise = -1; + noiseLevels = h_sbr_cal_env->prevSbrNoiseFloorLevel; + noNoiseBands = h_sbr_cal_env->prevNNfb; + noSubFrameBands = h_sbr_cal_env->prevNSfb; + lowSubband = h_sbr_cal_env->prevLoSubband; + highSubband = h_sbr_cal_env->prevHiSubband; + + noSubbands = highSubband - lowSubband; + ov_highSubband = highSubband; + if (highSubband < h_sbr_cal_env->prev_ov_highSubband) { + ov_highSubband = h_sbr_cal_env->prev_ov_highSubband; + } - /* - Extract sine flags for all QMF bands - */ - mapSineFlags(hFreq->freqBandTable[1], - hFreq->nSfb[1], - hFrameData->addHarmonics, - h_sbr_cal_env->harmFlagsPrev, - hFrameData->frameInfo.tranEnv, - sineMapped); + pFreqBandTable[0] = h_sbr_cal_env->prevFreqBandTableLo; + pFreqBandTable[1] = h_sbr_cal_env->prevFreqBandTableHi; + pFreqBandTableNoise = h_sbr_cal_env->prevFreqBandTableNoise; + } + mapSineFlagsPvc(pFreqBandTable[1], noSubFrameBands[1], + h_sbr_cal_env->harmFlagsPrev, + h_sbr_cal_env->harmFlagsPrevActive, sineMapped, + hFrameData->sinusoidal_position, + &h_sbr_cal_env->sinusoidal_positionPrev, + (borders[0] > bordersPvc[0]) ? 1 : 0); + } else { + /* + Extract sine flags for all QMF bands + */ + mapSineFlags(pFreqBandTable[1], noSubFrameBands[1], + hFrameData->addHarmonics, h_sbr_cal_env->harmFlagsPrev, + h_sbr_cal_env->harmFlagsPrevActive, + hFrameData->frameInfo.tranEnv, sineMapped); + } /* Scan for maximum in bufferd noise levels. @@ -567,163 +982,289 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling in reference energies */ if (!useLP) - adj_e = h_sbr_cal_env->filtBufferNoise_e - getScalefactor(h_sbr_cal_env->filtBufferNoise, noSubbands); + adj_e = h_sbr_cal_env->filtBufferNoise_e - + getScalefactor(h_sbr_cal_env->filtBufferNoise, noSubbands); /* Scan for maximum reference energy to be able to select appropriate values for adj_e and final_e. */ - - for (i = 0; i < hFrameData->frameInfo.nEnvelopes; i++) { - INT maxSfbNrg_e = -FRACT_BITS+NRG_EXP_OFFSET; /* start value for maximum search */ - - /* Fetch frequency resolution for current envelope: */ - for (j=hFreq->nSfb[hFrameData->frameInfo.freqRes[i]]; j!=0; j--) { - maxSfbNrg_e = fixMax(maxSfbNrg_e,(INT)((LONG)(*pIenv++) & MASK_E)); - } - maxSfbNrg_e -= NRG_EXP_OFFSET; + if (pvc_mode > 0) { + INT maxSfbNrg_e = pPvcDynamicData->predEsg_expMax; /* Energy -> magnitude (sqrt halfens exponent) */ - maxSfbNrg_e = (maxSfbNrg_e+1) >> 1; /* +1 to go safe (round to next higher int) */ + maxSfbNrg_e = + (maxSfbNrg_e + 1) >> 1; /* +1 to go safe (round to next higher int) */ /* Some safety margin is needed for 2 reasons: - The signal energy is not equally spread over all subband samples in a specific sfb of an envelope (Nrg could be too high by a factor of envWidth * sfbWidth) - - Smoothing can smear high gains of the previous envelope into the current + - Smoothing can smear high gains of the previous envelope into the + current */ maxSfbNrg_e += 6; - if (borders[i] < hHeaderData->numberTimeSlots) - /* This envelope affects timeslots that belong to the output frame */ - adj_e = (maxSfbNrg_e > adj_e) ? maxSfbNrg_e : adj_e; + adj_e = maxSfbNrg_e; + // final_e should not exist for PVC fixfix framing + } else { + for (i = 0; i < hFrameData->frameInfo.nEnvelopes; i++) { + INT maxSfbNrg_e = + -FRACT_BITS + NRG_EXP_OFFSET; /* start value for maximum search */ + + /* Fetch frequency resolution for current envelope: */ + for (j = noSubFrameBands[hFrameData->frameInfo.freqRes[i]]; j != 0; j--) { + maxSfbNrg_e = fixMax(maxSfbNrg_e, (INT)((LONG)(*pIenv++) & MASK_E)); + } + maxSfbNrg_e -= NRG_EXP_OFFSET; + + /* Energy -> magnitude (sqrt halfens exponent) */ + maxSfbNrg_e = + (maxSfbNrg_e + 1) >> 1; /* +1 to go safe (round to next higher int) */ + + /* Some safety margin is needed for 2 reasons: + - The signal energy is not equally spread over all subband samples in + a specific sfb of an envelope (Nrg could be too high by a factor of + envWidth * sfbWidth) + - Smoothing can smear high gains of the previous envelope into the + current + */ + maxSfbNrg_e += 6; - if (borders[i+1] > hHeaderData->numberTimeSlots) - /* This envelope affects timeslots after the output frame */ - final_e = (maxSfbNrg_e > final_e) ? maxSfbNrg_e : final_e; + if (borders[i] < hHeaderData->numberTimeSlots) + /* This envelope affects timeslots that belong to the output frame */ + adj_e = fMax(maxSfbNrg_e, adj_e); + if (borders[i + 1] > hHeaderData->numberTimeSlots) + /* This envelope affects timeslots after the output frame */ + final_e = fMax(maxSfbNrg_e, final_e); + } } - /* Calculate adjustment factors and apply them for every envelope. */ pIenv = hFrameData->iEnvelope; - for (i = 0; i < hFrameData->frameInfo.nEnvelopes; i++) { - + if (pvc_mode > 0) { + /* iterate over SBR time slots starting with bordersPvc[i] */ + i = bordersPvc[0]; /* usually 0; can be >0 if switching from legacy SBR to + PVC */ + i_stop = PVC_NTIMESLOT; + FDK_ASSERT(bordersPvc[hFrameData->frameInfo.nEnvelopes] == PVC_NTIMESLOT); + } else { + /* iterate over SBR envelopes starting with 0 */ + i = 0; + i_stop = hFrameData->frameInfo.nEnvelopes; + } + for (; i < i_stop; i++) { int k, noNoiseFlag; - SCHAR noise_e, input_e = SCALE2EXP(sbrScaleFactor->hb_scale); + SCHAR noise_e, input_e = SCALE2EXP(sbrScaleFactor->hb_scale); C_ALLOC_SCRATCH_START(pNrgs, ENV_CALC_NRGS, 1); /* Helper variables. */ - UCHAR start_pos = hHeaderData->timeStep * borders[i]; /* Start-position in time (subband sample) for current envelope. */ - UCHAR stop_pos = hHeaderData->timeStep * borders[i+1]; /* Stop-position in time (subband sample) for current envelope. */ - UCHAR freq_res = hFrameData->frameInfo.freqRes[i]; /* Frequency resolution for current envelope. */ - + int start_pos, stop_pos, freq_res; + if (pvc_mode > 0) { + start_pos = + hHeaderData->timeStep * + i; /* Start-position in time (subband sample) for current envelope. */ + stop_pos = hHeaderData->timeStep * (i + 1); /* Stop-position in time + (subband sample) for + current envelope. */ + freq_res = + hFrameData->frameInfo + .freqRes[0]; /* Frequency resolution for current envelope. */ + FDK_ASSERT( + freq_res == + hFrameData->frameInfo.freqRes[hFrameData->frameInfo.nEnvelopes - 1]); + } else { + start_pos = hHeaderData->timeStep * + borders[i]; /* Start-position in time (subband sample) for + current envelope. */ + stop_pos = hHeaderData->timeStep * + borders[i + 1]; /* Stop-position in time (subband sample) for + current envelope. */ + freq_res = + hFrameData->frameInfo + .freqRes[i]; /* Frequency resolution for current envelope. */ + } - /* Always do fully initialize the temporary energy table. This prevents negative energies and extreme gain factors in - cases where the number of limiter bands exceeds the number of subbands. The latter can be caused by undetected bit - errors and is tested by some streams from the certification set. */ + /* Always fully initialize the temporary energy table. This prevents + negative energies and extreme gain factors in cases where the number of + limiter bands exceeds the number of subbands. The latter can be caused by + undetected bit errors and is tested by some streams from the + certification set. */ FDKmemclear(pNrgs, sizeof(ENV_CALC_NRGS)); - /* If the start-pos of the current envelope equals the stop pos of the current - noise envelope, increase the pointer (i.e. choose the next noise-floor).*/ - if (borders[i] == hFrameData->frameInfo.bordersNoise[envNoise+1]){ - noiseLevels += noNoiseBands; /* The noise floor data is stored in a row [noiseFloor1 noiseFloor2...].*/ - envNoise++; - } + if (pvc_mode > 0) { + /* get predicted energy values from PVC module */ + expandPredEsg(pPvcDynamicData, i, (int)MAX_FREQ_COEFFS, pNrgs->nrgRef, + pNrgs->nrgRef_e); - if(i==hFrameData->frameInfo.tranEnv || i==h_sbr_cal_env->prevTranEnv) /* attack */ + if (i == borders[0]) { + mapSineFlags(pFreqBandTable[1], noSubFrameBands[1], + hFrameData->addHarmonics, h_sbr_cal_env->harmFlagsPrev, + h_sbr_cal_env->harmFlagsPrevActive, + hFrameData->sinusoidal_position, sineMapped); + } + + if (i >= hFrameData->frameInfo.bordersNoise[envNoise + 1]) { + if (envNoise >= 0) { + noiseLevels += noNoiseBands; /* The noise floor data is stored in a + row [noiseFloor1 noiseFloor2...].*/ + } else { + /* leave trailing noise envelope of past frame */ + noNoiseBands = hFreq->nNfb; + noSubFrameBands = hFreq->nSfb; + noiseLevels = hFrameData->sbrNoiseFloorLevel; + + lowSubband = hFreq->lowSubband; + highSubband = hFreq->highSubband; + + noSubbands = highSubband - lowSubband; + ov_highSubband = highSubband; + if (highSubband < hFreq->ov_highSubband) { + ov_highSubband = hFreq->ov_highSubband; + } + + pFreqBandTable[0] = hFreq->freqBandTableLo; + pFreqBandTable[1] = hFreq->freqBandTableHi; + pFreqBandTableNoise = hFreq->freqBandTableNoise; + } + envNoise++; + } + } else { + /* If the start-pos of the current envelope equals the stop pos of the + current noise envelope, increase the pointer (i.e. choose the next + noise-floor).*/ + if (borders[i] == hFrameData->frameInfo.bordersNoise[envNoise + 1]) { + noiseLevels += noNoiseBands; /* The noise floor data is stored in a row + [noiseFloor1 noiseFloor2...].*/ + envNoise++; + } + } + if (i == hFrameData->frameInfo.tranEnv || + i == h_sbr_cal_env->prevTranEnv) /* attack */ { noNoiseFlag = 1; - if (!useLP) - smooth_length = 0; /* No smoothing on attacks! */ - } - else { + if (!useLP) smooth_length = 0; /* No smoothing on attacks! */ + } else { noNoiseFlag = 0; if (!useLP) - smooth_length = (1 - hHeaderData->bs_data.smoothingLength) << 2; /* can become either 0 or 4 */ + smooth_length = (1 - hHeaderData->bs_data.smoothingLength) + << 2; /* can become either 0 or 4 */ } - /* Energy estimation in transposed highband. */ if (hHeaderData->bs_data.interpolFreq) - calcNrgPerSubband(analysBufferReal, - (useLP) ? NULL : analysBufferImag, - lowSubband, highSubband, - start_pos, stop_pos, - input_e, - pNrgs->nrgEst, - pNrgs->nrgEst_e); + calcNrgPerSubband(analysBufferReal, (useLP) ? NULL : analysBufferImag, + lowSubband, highSubband, start_pos, stop_pos, input_e, + pNrgs->nrgEst, pNrgs->nrgEst_e); else - calcNrgPerSfb(analysBufferReal, - (useLP) ? NULL : analysBufferImag, - hFreq->nSfb[freq_res], - hFreq->freqBandTable[freq_res], - start_pos, stop_pos, - input_e, - pNrgs->nrgEst, + calcNrgPerSfb(analysBufferReal, (useLP) ? NULL : analysBufferImag, + noSubFrameBands[freq_res], pFreqBandTable[freq_res], + start_pos, stop_pos, input_e, pNrgs->nrgEst, pNrgs->nrgEst_e); /* Calculate subband gains */ { - UCHAR * table = hFreq->freqBandTable[freq_res]; - UCHAR * pUiNoise = &hFreq->freqBandTableNoise[1]; /*! Upper limit of the current noise floor band. */ + UCHAR *table = pFreqBandTable[freq_res]; + UCHAR *pUiNoise = + &pFreqBandTableNoise[1]; /*! Upper limit of the current noise floor + band. */ - FIXP_SGL * pNoiseLevels = noiseLevels; + FIXP_SGL *pNoiseLevels = noiseLevels; - FIXP_DBL tmpNoise = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M)); - SCHAR tmpNoise_e = (UCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET; + FIXP_DBL tmpNoise = + FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M)); + SCHAR tmpNoise_e = + (UCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET; int cc = 0; c = 0; - for (j = 0; j < hFreq->nSfb[freq_res]; j++) { + if (pvc_mode > 0) { + for (j = 0; j < noSubFrameBands[freq_res]; j++) { + UCHAR sinePresentFlag = 0; + int li = table[j]; + int ui = table[j + 1]; + + for (k = li; k < ui; k++) { + sinePresentFlag |= (i >= sineMapped[cc]); + cc++; + } - FIXP_DBL refNrg = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pIenv) & MASK_M)); - SCHAR refNrg_e = (SCHAR)((LONG)(*pIenv) & MASK_E) - NRG_EXP_OFFSET; + for (k = li; k < ui; k++) { + FIXP_DBL refNrg = pNrgs->nrgRef[k - lowSubband]; + SCHAR refNrg_e = pNrgs->nrgRef_e[k - lowSubband]; + + if (k >= *pUiNoise) { + tmpNoise = + FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M)); + tmpNoise_e = + (SCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET; + + pUiNoise++; + } - UCHAR sinePresentFlag = 0; - int li = table[j]; - int ui = table[j+1]; + FDK_ASSERT(k >= lowSubband); - for (k=li; k<ui; k++) { - sinePresentFlag |= (i >= sineMapped[cc]); - cc++; + if (useLP) useAliasReduction[k - lowSubband] = !sinePresentFlag; + + pNrgs->nrgSine[c] = FL2FXCONST_DBL(0.0f); + pNrgs->nrgSine_e[c] = 0; + + calcSubbandGain(refNrg, refNrg_e, pNrgs, c, tmpNoise, tmpNoise_e, + sinePresentFlag, i >= sineMapped[c], noNoiseFlag); + + c++; + } } + } else { + for (j = 0; j < noSubFrameBands[freq_res]; j++) { + FIXP_DBL refNrg = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pIenv) & MASK_M)); + SCHAR refNrg_e = (SCHAR)((LONG)(*pIenv) & MASK_E) - NRG_EXP_OFFSET; - for (k=li; k<ui; k++) { - if (k >= *pUiNoise) { - tmpNoise = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M)); - tmpNoise_e = (SCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET; + UCHAR sinePresentFlag = 0; + int li = table[j]; + int ui = table[j + 1]; - pUiNoise++; + for (k = li; k < ui; k++) { + sinePresentFlag |= (i >= sineMapped[cc]); + cc++; } - FDK_ASSERT(k >= lowSubband); + for (k = li; k < ui; k++) { + if (k >= *pUiNoise) { + tmpNoise = + FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M)); + tmpNoise_e = + (SCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET; + + pUiNoise++; + } + + FDK_ASSERT(k >= lowSubband); - if (useLP) - useAliasReduction[k-lowSubband] = !sinePresentFlag; + if (useLP) useAliasReduction[k - lowSubband] = !sinePresentFlag; - pNrgs->nrgSine[c] = FL2FXCONST_DBL(0.0f); - pNrgs->nrgSine_e[c] = 0; + pNrgs->nrgSine[c] = FL2FXCONST_DBL(0.0f); + pNrgs->nrgSine_e[c] = 0; - calcSubbandGain(refNrg, refNrg_e, pNrgs, c, - tmpNoise, tmpNoise_e, - sinePresentFlag, i >= sineMapped[c], - noNoiseFlag); + calcSubbandGain(refNrg, refNrg_e, pNrgs, c, tmpNoise, tmpNoise_e, + sinePresentFlag, i >= sineMapped[c], noNoiseFlag); - pNrgs->nrgRef[c] = refNrg; - pNrgs->nrgRef_e[c] = refNrg_e; + pNrgs->nrgRef[c] = refNrg; + pNrgs->nrgRef_e[c] = refNrg_e; - c++; + c++; + } + pIenv++; } - pIenv++; } } @@ -732,19 +1273,30 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling */ for (c = 0; c < hFreq->noLimiterBands; c++) { - FIXP_DBL sumRef, boostGain, maxGain; FIXP_DBL accu = FL2FXCONST_DBL(0.0f); - SCHAR sumRef_e, boostGain_e, maxGain_e, accu_e = 0; + SCHAR sumRef_e, boostGain_e, maxGain_e, accu_e = 0; + int maxGainLimGainSum_e = 0; - calcAvgGain(pNrgs, - hFreq->limiterBandTable[c], hFreq->limiterBandTable[c+1], - &sumRef, &sumRef_e, - &maxGain, &maxGain_e); + calcAvgGain(pNrgs, hFreq->limiterBandTable[c], + hFreq->limiterBandTable[c + 1], &sumRef, &sumRef_e, &maxGain, + &maxGain_e); /* Multiply maxGain with limiterGain: */ - maxGain = fMult(maxGain, FDK_sbrDecoder_sbr_limGains_m[hHeaderData->bs_data.limiterGains]); - maxGain_e += FDK_sbrDecoder_sbr_limGains_e[hHeaderData->bs_data.limiterGains]; + maxGain = fMult( + maxGain, + FDK_sbrDecoder_sbr_limGains_m[hHeaderData->bs_data.limiterGains]); + /* maxGain_e += + * FDK_sbrDecoder_sbr_limGains_e[hHeaderData->bs_data.limiterGains]; */ + /* The addition of maxGain_e and FDK_sbrDecoder_sbr_limGains_e[3] might + yield values greater than 127 which doesn't fit into an SCHAR! In these + rare situations limit maxGain_e to 127. + */ + maxGainLimGainSum_e = + maxGain_e + + FDK_sbrDecoder_sbr_limGains_e[hHeaderData->bs_data.limiterGains]; + maxGain_e = + (maxGainLimGainSum_e > 127) ? (SCHAR)127 : (SCHAR)maxGainLimGainSum_e; /* Scale mantissa of MaxGain into range between 0.5 and 1: */ if (maxGain == FL2FXCONST_DBL(0.0f)) @@ -752,7 +1304,7 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling else { SCHAR charTemp = CountLeadingBits(maxGain); maxGain_e -= charTemp; - maxGain <<= (int)charTemp; + maxGain <<= (int)charTemp; } if (maxGain_e >= maxGainLimit_e) { /* upper limit (e.g. 96 dB) */ @@ -760,20 +1312,21 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling maxGain_e = maxGainLimit_e; } - /* Every subband gain is compared to the scaled "average gain" and limited if necessary: */ - for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c+1]; k++) { - if ( (pNrgs->nrgGain_e[k] > maxGain_e) || (pNrgs->nrgGain_e[k] == maxGain_e && pNrgs->nrgGain[k]>maxGain) ) { - + for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; + k++) { + if ((pNrgs->nrgGain_e[k] > maxGain_e) || + (pNrgs->nrgGain_e[k] == maxGain_e && pNrgs->nrgGain[k] > maxGain)) { FIXP_DBL noiseAmp; - SCHAR noiseAmp_e; + SCHAR noiseAmp_e; - FDK_divide_MantExp(maxGain, maxGain_e, pNrgs->nrgGain[k], pNrgs->nrgGain_e[k], &noiseAmp, &noiseAmp_e); - pNrgs->noiseLevel[k] = fMult(pNrgs->noiseLevel[k],noiseAmp); + FDK_divide_MantExp(maxGain, maxGain_e, pNrgs->nrgGain[k], + pNrgs->nrgGain_e[k], &noiseAmp, &noiseAmp_e); + pNrgs->noiseLevel[k] = fMult(pNrgs->noiseLevel[k], noiseAmp); pNrgs->noiseLevel_e[k] += noiseAmp_e; - pNrgs->nrgGain[k] = maxGain; - pNrgs->nrgGain_e[k] = maxGain_e; + pNrgs->nrgGain[k] = maxGain; + pNrgs->nrgGain_e[k] = maxGain_e; } } @@ -783,21 +1336,22 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling 2. Calculate boost factor by comparison with reference energy 3. Apply boost factor to compensate for the energy loss due to limiting */ - for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; k++) { - + for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; + k++) { /* 1.a Add energy of adjusted signal (using preliminary gain) */ - FIXP_DBL tmp = fMult(pNrgs->nrgGain[k],pNrgs->nrgEst[k]); - SCHAR tmp_e = pNrgs->nrgGain_e[k] + pNrgs->nrgEst_e[k]; + FIXP_DBL tmp = fMult(pNrgs->nrgGain[k], pNrgs->nrgEst[k]); + SCHAR tmp_e = pNrgs->nrgGain_e[k] + pNrgs->nrgEst_e[k]; FDK_add_MantExp(tmp, tmp_e, accu, accu_e, &accu, &accu_e); /* 1.b Add sine energy (if present) */ - if(pNrgs->nrgSine[k] != FL2FXCONST_DBL(0.0f)) { - FDK_add_MantExp(pNrgs->nrgSine[k], pNrgs->nrgSine_e[k], accu, accu_e, &accu, &accu_e); - } - else { + if (pNrgs->nrgSine[k] != FL2FXCONST_DBL(0.0f)) { + FDK_add_MantExp(pNrgs->nrgSine[k], pNrgs->nrgSine_e[k], accu, accu_e, + &accu, &accu_e); + } else { /* 1.c Add noise energy (if present) */ - if(noNoiseFlag == 0) { - FDK_add_MantExp(pNrgs->noiseLevel[k], pNrgs->noiseLevel_e[k], accu, accu_e, &accu, &accu_e); + if (noNoiseFlag == 0) { + FDK_add_MantExp(pNrgs->noiseLevel[k], pNrgs->noiseLevel_e[k], accu, + accu_e, &accu, &accu_e); } } } @@ -812,33 +1366,30 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling boostGain_e = sumRef_e - accu_e + div_e; } - /* 2.b Result too high? --> Limit the boost factor to +4 dB */ - if((boostGain_e > 3) || - (boostGain_e == 2 && boostGain > FL2FXCONST_DBL(0.6279716f)) || - (boostGain_e == 3 && boostGain > FL2FXCONST_DBL(0.3139858f)) ) - { + if ((boostGain_e > 3) || + (boostGain_e == 2 && boostGain > FL2FXCONST_DBL(0.6279716f)) || + (boostGain_e == 3 && boostGain > FL2FXCONST_DBL(0.3139858f))) { boostGain = FL2FXCONST_DBL(0.6279716f); boostGain_e = 2; } /* 3. Multiply all signal components with the boost factor */ - for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; k++) { - pNrgs->nrgGain[k] = fMultDiv2(pNrgs->nrgGain[k],boostGain); + for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; + k++) { + pNrgs->nrgGain[k] = fMultDiv2(pNrgs->nrgGain[k], boostGain); pNrgs->nrgGain_e[k] = pNrgs->nrgGain_e[k] + boostGain_e + 1; - pNrgs->nrgSine[k] = fMultDiv2(pNrgs->nrgSine[k],boostGain); + pNrgs->nrgSine[k] = fMultDiv2(pNrgs->nrgSine[k], boostGain); pNrgs->nrgSine_e[k] = pNrgs->nrgSine_e[k] + boostGain_e + 1; - pNrgs->noiseLevel[k] = fMultDiv2(pNrgs->noiseLevel[k],boostGain); + pNrgs->noiseLevel[k] = fMultDiv2(pNrgs->noiseLevel[k], boostGain); pNrgs->noiseLevel_e[k] = pNrgs->noiseLevel_e[k] + boostGain_e + 1; } } /* End of noise limiting */ if (useLP) - aliasingReduction(degreeAlias+lowSubband, - pNrgs, - useAliasReduction, + aliasingReduction(degreeAlias + lowSubband, pNrgs, useAliasReduction, noSubbands); /* For the timeslots within the range for the output frame, @@ -852,14 +1403,14 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling /* Convert energies to amplitude levels */ - for (k=0; k<noSubbands; k++) { - FDK_sqrt_MantExp(&pNrgs->nrgSine[k], &pNrgs->nrgSine_e[k], &noise_e); - FDK_sqrt_MantExp(&pNrgs->nrgGain[k], &pNrgs->nrgGain_e[k], &pNrgs->nrgGain_e[k]); - FDK_sqrt_MantExp(&pNrgs->noiseLevel[k], &pNrgs->noiseLevel_e[k], &noise_e); + for (k = 0; k < noSubbands; k++) { + FDK_sqrt_MantExp(&pNrgs->nrgSine[k], &pNrgs->nrgSine_e[k], &noise_e); + FDK_sqrt_MantExp(&pNrgs->nrgGain[k], &pNrgs->nrgGain_e[k], + &pNrgs->nrgGain_e[k]); + FDK_sqrt_MantExp(&pNrgs->noiseLevel[k], &pNrgs->noiseLevel_e[k], + &noise_e); } - - /* Apply calculated gains and adaptive noise */ @@ -868,40 +1419,42 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling { int scale_change, sc_change; FIXP_SGL smooth_ratio; - int filtBufferNoiseShift=0; + int filtBufferNoiseShift = 0; /* Initialize smoothing buffers with the first valid values */ - if (h_sbr_cal_env->startUp) - { + if (h_sbr_cal_env->startUp) { if (!useLP) { h_sbr_cal_env->filtBufferNoise_e = noise_e; - FDKmemcpy(h_sbr_cal_env->filtBuffer_e, pNrgs->nrgGain_e, noSubbands*sizeof(SCHAR)); - FDKmemcpy(h_sbr_cal_env->filtBufferNoise, pNrgs->noiseLevel, noSubbands*sizeof(FIXP_DBL)); - FDKmemcpy(h_sbr_cal_env->filtBuffer, pNrgs->nrgGain, noSubbands*sizeof(FIXP_DBL)); - + FDKmemcpy(h_sbr_cal_env->filtBuffer_e, pNrgs->nrgGain_e, + noSubbands * sizeof(SCHAR)); + FDKmemcpy(h_sbr_cal_env->filtBufferNoise, pNrgs->noiseLevel, + noSubbands * sizeof(FIXP_DBL)); + FDKmemcpy(h_sbr_cal_env->filtBuffer, pNrgs->nrgGain, + noSubbands * sizeof(FIXP_DBL)); } h_sbr_cal_env->startUp = 0; } if (!useLP) { - - equalizeFiltBufferExp(h_sbr_cal_env->filtBuffer, /* buffered */ - h_sbr_cal_env->filtBuffer_e, /* buffered */ - pNrgs->nrgGain, /* current */ - pNrgs->nrgGain_e, /* current */ + equalizeFiltBufferExp(h_sbr_cal_env->filtBuffer, /* buffered */ + h_sbr_cal_env->filtBuffer_e, /* buffered */ + pNrgs->nrgGain, /* current */ + pNrgs->nrgGain_e, /* current */ noSubbands); /* Adapt exponent of buffered noise levels to the current exponent so they can easily be smoothed */ - if((h_sbr_cal_env->filtBufferNoise_e - noise_e)>=0) { - int shift = fixMin(DFRACT_BITS-1,(int)(h_sbr_cal_env->filtBufferNoise_e - noise_e)); - for (k=0; k<noSubbands; k++) + if ((h_sbr_cal_env->filtBufferNoise_e - noise_e) >= 0) { + int shift = fixMin(DFRACT_BITS - 1, + (int)(h_sbr_cal_env->filtBufferNoise_e - noise_e)); + for (k = 0; k < noSubbands; k++) h_sbr_cal_env->filtBufferNoise[k] <<= shift; - } - else { - int shift = fixMin(DFRACT_BITS-1,-(int)(h_sbr_cal_env->filtBufferNoise_e - noise_e)); - for (k=0; k<noSubbands; k++) + } else { + int shift = + fixMin(DFRACT_BITS - 1, + -(int)(h_sbr_cal_env->filtBufferNoise_e - noise_e)); + for (k = 0; k < noSubbands; k++) h_sbr_cal_env->filtBufferNoise[k] >>= shift; } @@ -909,60 +1462,61 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling } /* find best scaling! */ - scale_change = -(DFRACT_BITS-1); - for(k=0;k<noSubbands;k++) { - scale_change = fixMax(scale_change,(int)pNrgs->nrgGain_e[k]); + scale_change = -(DFRACT_BITS - 1); + for (k = 0; k < noSubbands; k++) { + scale_change = fixMax(scale_change, (int)pNrgs->nrgGain_e[k]); } - sc_change = (start_pos<no_cols)? adj_e - input_e : final_e - input_e; + sc_change = (start_pos < no_cols) ? adj_e - input_e : final_e - input_e; - if ((scale_change-sc_change+1)<0) - scale_change-=(scale_change-sc_change+1); + if ((scale_change - sc_change + 1) < 0) + scale_change -= (scale_change - sc_change + 1); - scale_change = (scale_change-sc_change)+1; + scale_change = (scale_change - sc_change) + 1; - for(k=0;k<noSubbands;k++) { - int sc = scale_change-pNrgs->nrgGain_e[k] + (sc_change-1); - pNrgs->nrgGain[k] >>= sc; - pNrgs->nrgGain_e[k] += sc; + for (k = 0; k < noSubbands; k++) { + int sc = scale_change - pNrgs->nrgGain_e[k] + (sc_change - 1); + pNrgs->nrgGain[k] >>= sc; + pNrgs->nrgGain_e[k] += sc; } if (!useLP) { - for(k=0;k<noSubbands;k++) { - int sc = scale_change-h_sbr_cal_env->filtBuffer_e[k] + (sc_change-1); + for (k = 0; k < noSubbands; k++) { + int sc = + scale_change - h_sbr_cal_env->filtBuffer_e[k] + (sc_change - 1); h_sbr_cal_env->filtBuffer[k] >>= sc; } } - for (j = start_pos; j < stop_pos; j++) - { - /* This timeslot is located within the first part of the processing buffer - and will be fed into the QMF-synthesis for the current frame. + for (j = start_pos; j < stop_pos; j++) { + /* This timeslot is located within the first part of the processing + buffer and will be fed into the QMF-synthesis for the current frame. adj_e - input_e This timeslot will not yet be fed into the QMF so we do not care about the adj_e. sc_change = final_e - input_e */ - if ( (j==no_cols) && (start_pos<no_cols) ) - { - int shift = (int) (noise_e - final_e); + if ((j == no_cols) && (start_pos < no_cols)) { + int shift = (int)(noise_e - final_e); if (!useLP) - filtBufferNoiseShift = shift; /* shifting of h_sbr_cal_env->filtBufferNoise[k] will be applied in function adjustTimeSlotHQ() */ - if (shift>=0) { - shift = fixMin(DFRACT_BITS-1,shift); - for (k=0; k<noSubbands; k++) { + filtBufferNoiseShift = shift; /* shifting of + h_sbr_cal_env->filtBufferNoise[k] + will be applied in function + adjustTimeSlotHQ() */ + if (shift >= 0) { + shift = fixMin(DFRACT_BITS - 1, shift); + for (k = 0; k < noSubbands; k++) { pNrgs->nrgSine[k] <<= shift; - pNrgs->noiseLevel[k] <<= shift; + pNrgs->noiseLevel[k] <<= shift; /* if (!useLP) h_sbr_cal_env->filtBufferNoise[k] <<= shift; */ } - } - else { - shift = fixMin(DFRACT_BITS-1,-shift); - for (k=0; k<noSubbands; k++) { + } else { + shift = fixMin(DFRACT_BITS - 1, -shift); + for (k = 0; k < noSubbands; k++) { pNrgs->nrgSine[k] >>= shift; - pNrgs->noiseLevel[k] >>= shift; + pNrgs->noiseLevel[k] >>= shift; /* if (!useLP) h_sbr_cal_env->filtBufferNoise[k] >>= shift; @@ -973,182 +1527,248 @@ calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling /* update noise scaling */ noise_e = final_e; if (!useLP) - h_sbr_cal_env->filtBufferNoise_e = noise_e; /* scaling value unused! */ + h_sbr_cal_env->filtBufferNoise_e = + noise_e; /* scaling value unused! */ /* update gain buffer*/ sc_change -= (final_e - input_e); - if (sc_change<0) { - for(k=0;k<noSubbands;k++) { - pNrgs->nrgGain[k] >>= -sc_change; - pNrgs->nrgGain_e[k] += -sc_change; + if (sc_change < 0) { + for (k = 0; k < noSubbands; k++) { + pNrgs->nrgGain[k] >>= -sc_change; + pNrgs->nrgGain_e[k] += -sc_change; } if (!useLP) { - for(k=0;k<noSubbands;k++) { - h_sbr_cal_env->filtBuffer[k] >>= -sc_change; + for (k = 0; k < noSubbands; k++) { + h_sbr_cal_env->filtBuffer[k] >>= -sc_change; } } } else { - scale_change+=sc_change; + scale_change += sc_change; } - } // if + } /* if */ if (!useLP) { - /* Prevent the smoothing filter from running on constant levels */ - if (j-start_pos < smooth_length) - smooth_ratio = FDK_sbrDecoder_sbr_smoothFilter[j-start_pos]; + if (j - start_pos < smooth_length) + smooth_ratio = FDK_sbrDecoder_sbr_smoothFilter[j - start_pos]; else smooth_ratio = FL2FXCONST_SGL(0.0f); - adjustTimeSlotHQ(&analysBufferReal[j][lowSubband], - &analysBufferImag[j][lowSubband], - h_sbr_cal_env, - pNrgs, - lowSubband, - noSubbands, - scale_change, - smooth_ratio, - noNoiseFlag, - filtBufferNoiseShift); - } - else - { + if (iTES_enable) { + /* adjustTimeSlotHQ() without adding of additional harmonics */ + adjustTimeSlotHQ_GainAndNoise( + &analysBufferReal[j][lowSubband], + &analysBufferImag[j][lowSubband], h_sbr_cal_env, pNrgs, + lowSubband, noSubbands, scale_change, smooth_ratio, noNoiseFlag, + filtBufferNoiseShift); + } else { + adjustTimeSlotHQ(&analysBufferReal[j][lowSubband], + &analysBufferImag[j][lowSubband], h_sbr_cal_env, + pNrgs, lowSubband, noSubbands, scale_change, + smooth_ratio, noNoiseFlag, filtBufferNoiseShift); + } + } else { + FDK_ASSERT(!iTES_enable); /* not supported */ if (flags & SBRDEC_ELD_GRID) { - adjustTimeSlot_EldGrid(&analysBufferReal[j][lowSubband], - pNrgs, - &h_sbr_cal_env->harmIndex, - lowSubband, - noSubbands, - scale_change, - noNoiseFlag, - &h_sbr_cal_env->phaseIndex, - EXP2SCALE(adj_e) - sbrScaleFactor->lb_scale); - } else - { - adjustTimeSlotLC(&analysBufferReal[j][lowSubband], - pNrgs, - &h_sbr_cal_env->harmIndex, - lowSubband, - noSubbands, - scale_change, - noNoiseFlag, - &h_sbr_cal_env->phaseIndex); + /* FDKmemset(analysBufferReal[j], 0, 64 * sizeof(FIXP_DBL)); */ + adjustTimeSlot_EldGrid(&analysBufferReal[j][lowSubband], pNrgs, + &h_sbr_cal_env->harmIndex, lowSubband, + noSubbands, scale_change, noNoiseFlag, + &h_sbr_cal_env->phaseIndex, + EXP2SCALE(adj_e) - sbrScaleFactor->lb_scale); + } else { + adjustTimeSlotLC(&analysBufferReal[j][lowSubband], pNrgs, + &h_sbr_cal_env->harmIndex, lowSubband, noSubbands, + scale_change, noNoiseFlag, + &h_sbr_cal_env->phaseIndex); + } + } + /* In case the envelope spans accross the no_cols border both exponents + * are needed. */ + /* nrgGain_e[0...(noSubbands-1)] are equalized by + * equalizeFiltBufferExp() */ + pNrgs->exponent[(j < no_cols) ? 0 : 1] = + (SCHAR)((15 - sbrScaleFactor->hb_scale) + pNrgs->nrgGain_e[0] + 1 - + scale_change); + } /* for */ + + if (iTES_enable) { + apply_inter_tes( + analysBufferReal, /* pABufR, */ + analysBufferImag, /* pABufI, */ + sbrScaleFactor, pNrgs->exponent, hHeaderData->timeStep, start_pos, + stop_pos, lowSubband, noSubbands, + hFrameData + ->interTempShapeMode[i] /* frameData->interTempShapeMode[env] */ + ); + + /* add additional harmonics */ + for (j = start_pos; j < stop_pos; j++) { + /* match exponent of additional harmonics to scale change of QMF data + * caused by apply_inter_tes() */ + scale_change = 0; + + if ((start_pos <= no_cols) && (stop_pos > no_cols)) { + /* Scaling of analysBuffers was potentially changed within this + envelope. The pNrgs->nrgSine_e match the second part of the + envelope. For (j<=no_cols) the exponent of the sine energies has + to be adapted. */ + scale_change = pNrgs->exponent[1] - pNrgs->exponent[0]; } + + adjustTimeSlotHQ_AddHarmonics( + &analysBufferReal[j][lowSubband], + &analysBufferImag[j][lowSubband], h_sbr_cal_env, pNrgs, + lowSubband, noSubbands, + -iTES_scale_change + ((j < no_cols) ? scale_change : 0)); } - } // for + } if (!useLP) { /* Update time-smoothing-buffers for gains and noise levels - The gains and the noise values of the current envelope are copied into the buffer. - This has to be done at the end of each envelope as the values are required for - a smooth transition to the next envelope. */ - FDKmemcpy(h_sbr_cal_env->filtBuffer, pNrgs->nrgGain, noSubbands*sizeof(FIXP_DBL)); - FDKmemcpy(h_sbr_cal_env->filtBuffer_e, pNrgs->nrgGain_e, noSubbands*sizeof(SCHAR)); - FDKmemcpy(h_sbr_cal_env->filtBufferNoise, pNrgs->noiseLevel, noSubbands*sizeof(FIXP_DBL)); + The gains and the noise values of the current envelope are copied + into the buffer. This has to be done at the end of each envelope as + the values are required for a smooth transition to the next envelope. + */ + FDKmemcpy(h_sbr_cal_env->filtBuffer, pNrgs->nrgGain, + noSubbands * sizeof(FIXP_DBL)); + FDKmemcpy(h_sbr_cal_env->filtBuffer_e, pNrgs->nrgGain_e, + noSubbands * sizeof(SCHAR)); + FDKmemcpy(h_sbr_cal_env->filtBufferNoise, pNrgs->noiseLevel, + noSubbands * sizeof(FIXP_DBL)); } - } C_ALLOC_SCRATCH_END(pNrgs, ENV_CALC_NRGS, 1); } + /* adapt adj_e to the scale change caused by apply_inter_tes() */ + adj_e += iTES_scale_change; + /* Rescale output samples */ { FIXP_DBL maxVal; int ov_reserve, reserve; /* Determine headroom in old adjusted samples */ - maxVal = maxSubbandSample( analysBufferReal, - (useLP) ? NULL : analysBufferImag, - lowSubband, - highSubband, - 0, - first_start); + maxVal = + maxSubbandSample(analysBufferReal, (useLP) ? NULL : analysBufferImag, + lowSubband, ov_highSubband, 0, first_start); ov_reserve = fNorm(maxVal); /* Determine headroom in new adjusted samples */ - maxVal = maxSubbandSample( analysBufferReal, - (useLP) ? NULL : analysBufferImag, - lowSubband, - highSubband, - first_start, - no_cols); + maxVal = + maxSubbandSample(analysBufferReal, (useLP) ? NULL : analysBufferImag, + lowSubband, highSubband, first_start, no_cols); reserve = fNorm(maxVal); /* Determine common output exponent */ - if (ov_adj_e - ov_reserve > adj_e - reserve ) /* set output_e to the maximum */ - output_e = ov_adj_e - ov_reserve; - else - output_e = adj_e - reserve; + output_e = fMax(ov_adj_e - ov_reserve, adj_e - reserve); /* Rescale old samples */ - rescaleSubbandSamples( analysBufferReal, - (useLP) ? NULL : analysBufferImag, - lowSubband, highSubband, - 0, first_start, - ov_adj_e - output_e); + rescaleSubbandSamples(analysBufferReal, (useLP) ? NULL : analysBufferImag, + lowSubband, ov_highSubband, 0, first_start, + ov_adj_e - output_e); /* Rescale new samples */ - rescaleSubbandSamples( analysBufferReal, - (useLP) ? NULL : analysBufferImag, - lowSubband, highSubband, - first_start, no_cols, - adj_e - output_e); + rescaleSubbandSamples(analysBufferReal, (useLP) ? NULL : analysBufferImag, + lowSubband, highSubband, first_start, no_cols, + adj_e - output_e); } /* Update hb_scale */ sbrScaleFactor->hb_scale = EXP2SCALE(output_e); /* Save the current final exponent for the next frame: */ - sbrScaleFactor->ov_hb_scale = EXP2SCALE(final_e); + /* adapt final_e to the scale change caused by apply_inter_tes() */ + sbrScaleFactor->ov_hb_scale = EXP2SCALE(final_e + iTES_scale_change); - - /* We need to remeber to the next frame that the transient + /* We need to remember to the next frame that the transient will occur in the first envelope (if tranEnv == nEnvelopes). */ - if(hFrameData->frameInfo.tranEnv == hFrameData->frameInfo.nEnvelopes) + if (hFrameData->frameInfo.tranEnv == hFrameData->frameInfo.nEnvelopes) h_sbr_cal_env->prevTranEnv = 0; else h_sbr_cal_env->prevTranEnv = -1; -} + if (pvc_mode > 0) { + /* Not more than just the last noise envelope reaches into the next PVC + frame! This should be true because bs_noise_position is <= 15 */ + FDK_ASSERT(hFrameData->frameInfo + .bordersNoise[hFrameData->frameInfo.nNoiseEnvelopes - 1] < + PVC_NTIMESLOT); + if (hFrameData->frameInfo + .bordersNoise[hFrameData->frameInfo.nNoiseEnvelopes] > + PVC_NTIMESLOT) { + FDK_ASSERT(noiseLevels == + (hFrameData->sbrNoiseFloorLevel + + (hFrameData->frameInfo.nNoiseEnvelopes - 1) * noNoiseBands)); + h_sbr_cal_env->prevNNfb = noNoiseBands; + + h_sbr_cal_env->prevNSfb[0] = noSubFrameBands[0]; + h_sbr_cal_env->prevNSfb[1] = noSubFrameBands[1]; + + h_sbr_cal_env->prevLoSubband = lowSubband; + h_sbr_cal_env->prevHiSubband = highSubband; + h_sbr_cal_env->prev_ov_highSubband = ov_highSubband; + + FDKmemcpy(h_sbr_cal_env->prevFreqBandTableLo, pFreqBandTable[0], + noSubFrameBands[0] + 1); + FDKmemcpy(h_sbr_cal_env->prevFreqBandTableHi, pFreqBandTable[1], + noSubFrameBands[1] + 1); + FDKmemcpy(h_sbr_cal_env->prevFreqBandTableNoise, + hFreq->freqBandTableNoise, sizeof(hFreq->freqBandTableNoise)); + + FDKmemcpy(h_sbr_cal_env->prevSbrNoiseFloorLevel, noiseLevels, + MAX_NOISE_COEFFS * sizeof(FIXP_SGL)); + } + } + C_ALLOC_SCRATCH_END(useAliasReduction, UCHAR, 64) +} /*! \brief Create envelope instance - Must be called once for each channel before calculateSbrEnvelope() can be used. + Must be called once for each channel before calculateSbrEnvelope() can be + used. \return errorCode, 0 if successful */ SBR_ERROR -createSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hs, /*!< pointer to envelope instance */ - HANDLE_SBR_HEADER_DATA hHeaderData, /*!< static SBR control data, initialized with defaults */ - const int chan, /*!< Channel for which to assign buffers */ - const UINT flags) -{ +createSbrEnvelopeCalc( + HANDLE_SBR_CALCULATE_ENVELOPE hs, /*!< pointer to envelope instance */ + HANDLE_SBR_HEADER_DATA + hHeaderData, /*!< static SBR control data, initialized with defaults */ + const int chan, /*!< Channel for which to assign buffers */ + const UINT flags) { SBR_ERROR err = SBRDEC_OK; int i; /* Clear previous missing harmonics flags */ - for (i=0; i<(MAX_FREQ_COEFFS+15)>>4; i++) { + for (i = 0; i < ADD_HARMONICS_FLAGS_SIZE; i++) { hs->harmFlagsPrev[i] = 0; + hs->harmFlagsPrevActive[i] = 0; } hs->harmIndex = 0; + FDKmemclear(hs->prevSbrNoiseFloorLevel, sizeof(hs->prevSbrNoiseFloorLevel)); + hs->prevNNfb = 0; + FDKmemclear(hs->prevFreqBandTableNoise, sizeof(hs->prevFreqBandTableNoise)); + hs->sinusoidal_positionPrev = 0; + /* Setup pointers for time smoothing. The buffer itself will be initialized later triggered by the startUp-flag. */ hs->prevTranEnv = -1; - /* initialization */ resetSbrEnvelopeCalc(hs); - if (chan==0) { /* do this only once */ + if (chan == 0) { /* do this only once */ err = resetFreqBandTables(hHeaderData, flags); } @@ -1158,16 +1778,12 @@ createSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hs, /*!< pointer to envel /*! \brief Create envelope instance - Must be called once for each channel before calculateSbrEnvelope() can be used. + Must be called once for each channel before calculateSbrEnvelope() can be + used. \return errorCode, 0 if successful */ -int -deleteSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hs) -{ - return 0; -} - +int deleteSbrEnvelopeCalc(HANDLE_SBR_CALCULATE_ENVELOPE hs) { return 0; } /*! \brief Reset envelope instance @@ -1177,18 +1793,18 @@ deleteSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hs) \return errorCode, 0 if successful */ -void -resetSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv) /*!< pointer to envelope instance */ +void resetSbrEnvelopeCalc( + HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv) /*!< pointer to envelope instance */ { hCalEnv->phaseIndex = 0; - /* Noise exponent needs to be reset because the output exponent for the next frame depends on it */ + /* Noise exponent needs to be reset because the output exponent for the next + * frame depends on it */ hCalEnv->filtBufferNoise_e = 0; hCalEnv->startUp = 1; } - /*! \brief Equalize exponents of the buffered gain values and the new ones @@ -1196,40 +1812,41 @@ resetSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv) /*!< pointer to env can be performed. This function is called once for each envelope before adjusting. */ -static void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, /*!< bufferd gains */ - SCHAR *filtBuffer_e, /*!< exponents of bufferd gains */ - FIXP_DBL *nrgGain, /*!< gains for current envelope */ - SCHAR *nrgGain_e, /*!< exponents of gains for current envelope */ - int subbands) /*!< Number of QMF subbands */ +static void equalizeFiltBufferExp( + FIXP_DBL *filtBuffer, /*!< bufferd gains */ + SCHAR *filtBuffer_e, /*!< exponents of bufferd gains */ + FIXP_DBL *nrgGain, /*!< gains for current envelope */ + SCHAR *nrgGain_e, /*!< exponents of gains for current envelope */ + int subbands) /*!< Number of QMF subbands */ { - int band; - int diff; - - for (band=0; band<subbands; band++){ - diff = (int) (nrgGain_e[band] - filtBuffer_e[band]); - if (diff>0) { - filtBuffer[band] >>= diff; /* Compensate for the scale change by shifting the mantissa. */ - filtBuffer_e[band] += diff; /* New gain is bigger, use its exponent */ - } - else if (diff<0) { + int band; + int diff; + + for (band = 0; band < subbands; band++) { + diff = (int)(nrgGain_e[band] - filtBuffer_e[band]); + if (diff > 0) { + filtBuffer[band] >>= + diff; /* Compensate for the scale change by shifting the mantissa. */ + filtBuffer_e[band] += diff; /* New gain is bigger, use its exponent */ + } else if (diff < 0) { /* The buffered gains seem to be larger, but maybe there are some unused bits left in the mantissa */ - int reserve = CntLeadingZeros(fixp_abs(filtBuffer[band]))-1; + int reserve = CntLeadingZeros(fixp_abs(filtBuffer[band])) - 1; if ((-diff) <= reserve) { /* There is enough space in the buffered mantissa so that we can take the new exponent as common. */ filtBuffer[band] <<= (-diff); - filtBuffer_e[band] += diff; /* becomes equal to *ptrNewExp */ - } - else { - filtBuffer[band] <<= reserve; /* Shift the mantissa as far as possible: */ - filtBuffer_e[band] -= reserve; /* Compensate in the exponent: */ + filtBuffer_e[band] += diff; /* becomes equal to *ptrNewExp */ + } else { + filtBuffer[band] <<= + reserve; /* Shift the mantissa as far as possible: */ + filtBuffer_e[band] -= reserve; /* Compensate in the exponent: */ /* For the remaining difference, change the new gain value */ - diff = fixMin(-(reserve + diff),DFRACT_BITS-1); + diff = fixMin(-(reserve + diff), DFRACT_BITS - 1); nrgGain[band] >>= diff; nrgGain_e[band] += diff; } @@ -1244,31 +1861,41 @@ static void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, /*!< bufferd gains * This function is used to rescale the audio data in the overlap buffer which has already been envelope adjusted with the last frame. */ -void rescaleSubbandSamples(FIXP_DBL ** re, /*!< Real part of input and output subband samples */ - FIXP_DBL ** im, /*!< Imaginary part of input and output subband samples */ - int lowSubband, /*!< Begin of frequency range to process */ - int highSubband, /*!< End of frequency range to process */ - int start_pos, /*!< Begin of time rage (QMF-timeslot) */ - int next_pos, /*!< End of time rage (QMF-timeslot) */ - int shift) /*!< number of bits to shift */ +void rescaleSubbandSamples( + FIXP_DBL **re, /*!< Real part of input and output subband samples */ + FIXP_DBL **im, /*!< Imaginary part of input and output subband samples */ + int lowSubband, /*!< Begin of frequency range to process */ + int highSubband, /*!< End of frequency range to process */ + int start_pos, /*!< Begin of time rage (QMF-timeslot) */ + int next_pos, /*!< End of time rage (QMF-timeslot) */ + int shift) /*!< number of bits to shift */ { - int width = highSubband-lowSubband; + int width = highSubband - lowSubband; - if ( (width > 0) && (shift!=0) ) { - if (im!=NULL) { - for (int l=start_pos; l<next_pos; l++) { - scaleValues(&re[l][lowSubband], width, shift); - scaleValues(&im[l][lowSubband], width, shift); + if ((width > 0) && (shift != 0)) { + if (im != NULL) { + for (int l = start_pos; l < next_pos; l++) { + scaleValues(&re[l][lowSubband], width, shift); + scaleValues(&im[l][lowSubband], width, shift); } - } else - { - for (int l=start_pos; l<next_pos; l++) { - scaleValues(&re[l][lowSubband], width, shift); + } else { + for (int l = start_pos; l < next_pos; l++) { + scaleValues(&re[l][lowSubband], width, shift); } } } } +static inline FIXP_DBL FDK_get_maxval_real(FIXP_DBL maxVal, FIXP_DBL *reTmp, + INT width) { + maxVal = (FIXP_DBL)0; + while (width-- != 0) { + FIXP_DBL tmp = *(reTmp++); + maxVal |= (FIXP_DBL)((LONG)(tmp) ^ ((LONG)tmp >> (DFRACT_BITS - 1))); + } + + return maxVal; +} /*! \brief Determine headroom for shifting @@ -1279,55 +1906,58 @@ void rescaleSubbandSamples(FIXP_DBL ** re, /*!< Real part of input and output \return Number of free bits in the biggest spectral value */ -FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output subband samples */ - FIXP_DBL ** im, /*!< Real part of input and output subband samples */ - int lowSubband, /*!< Begin of frequency range to process */ - int highSubband, /*!< Number of QMF bands to process */ - int start_pos, /*!< Begin of time rage (QMF-timeslot) */ - int next_pos /*!< End of time rage (QMF-timeslot) */ - ) -{ +FIXP_DBL maxSubbandSample( + FIXP_DBL **re, /*!< Real part of input and output subband samples */ + FIXP_DBL **im, /*!< Real part of input and output subband samples */ + int lowSubband, /*!< Begin of frequency range to process */ + int highSubband, /*!< Number of QMF bands to process */ + int start_pos, /*!< Begin of time rage (QMF-timeslot) */ + int next_pos /*!< End of time rage (QMF-timeslot) */ +) { FIXP_DBL maxVal = FL2FX_DBL(0.0f); unsigned int width = highSubband - lowSubband; FDK_ASSERT(width <= (64)); - if ( width > 0 ) { - if (im!=NULL) - { - for (int l=start_pos; l<next_pos; l++) - { -#ifdef FUNCTION_FDK_get_maxval - maxVal = FDK_get_maxval(maxVal, &re[l][lowSubband], &im[l][lowSubband], width); -#else - int k=width; + if (width > 0) { + if (im != NULL) { + for (int l = start_pos; l < next_pos; l++) { + int k = width; FIXP_DBL *reTmp = &re[l][lowSubband]; FIXP_DBL *imTmp = &im[l][lowSubband]; - do{ + do { FIXP_DBL tmp1 = *(reTmp++); FIXP_DBL tmp2 = *(imTmp++); - maxVal |= (FIXP_DBL)((LONG)(tmp1)^((LONG)tmp1>>(DFRACT_BITS-1))); - maxVal |= (FIXP_DBL)((LONG)(tmp2)^((LONG)tmp2>>(DFRACT_BITS-1))); - } while(--k!=0); -#endif + maxVal |= + (FIXP_DBL)((LONG)(tmp1) ^ ((LONG)tmp1 >> (DFRACT_BITS - 1))); + maxVal |= + (FIXP_DBL)((LONG)(tmp2) ^ ((LONG)tmp2 >> (DFRACT_BITS - 1))); + } while (--k != 0); } - } else - { - for (int l=start_pos; l<next_pos; l++) { - int k=width; - FIXP_DBL *reTmp = &re[l][lowSubband]; - do{ - FIXP_DBL tmp = *(reTmp++); - maxVal |= (FIXP_DBL)((LONG)(tmp)^((LONG)tmp>>(DFRACT_BITS-1))); - }while(--k!=0); + } else { + for (int l = start_pos; l < next_pos; l++) { + maxVal |= FDK_get_maxval_real(maxVal, &re[l][lowSubband], width); } } } - return(maxVal); + if (maxVal > (FIXP_DBL)0) { + /* For negative input values, maxVal is too small by 1. Add 1 only when + * necessary: if maxVal is a power of 2 */ + FIXP_DBL lowerPow2 = + (FIXP_DBL)(1 << (DFRACT_BITS - 1 - CntLeadingZeros(maxVal))); + if (maxVal == lowerPow2) maxVal += (FIXP_DBL)1; + } + + return (maxVal); } -#define SHIFT_BEFORE_SQUARE (3) /* (7/2) */ +/* #define SHIFT_BEFORE_SQUARE (3) */ /* (7/2) */ +/* Avoid assertion failures triggerd by overflows which occured in robustness + tests. Setting the SHIFT_BEFORE_SQUARE to 4 has negligible effect on (USAC) + conformance results. */ +#define SHIFT_BEFORE_SQUARE (4) /* ((8 - 0) / 2) */ + /*!< If the accumulator does not provide enough overflow bits or does not provide a high dynamic range, the below energy calculation @@ -1351,92 +1981,100 @@ FIXP_DBL maxSubbandSample( FIXP_DBL ** re, /*!< Real part of input and output This function is used when interpolFreq is true. */ -static void calcNrgPerSubband(FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */ - FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */ - int lowSubband, /*!< Begin of the SBR frequency range */ - int highSubband, /*!< High end of the SBR frequency range */ - int start_pos, /*!< First QMF-slot of current envelope */ - int next_pos, /*!< Last QMF-slot of current envelope + 1 */ - SCHAR frameExp, /*!< Common exponent for all input samples */ - FIXP_DBL *nrgEst, /*!< resulting Energy (0..1) */ - SCHAR *nrgEst_e ) /*!< Exponent of resulting Energy */ +static void calcNrgPerSubband( + FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */ + FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */ + int lowSubband, /*!< Begin of the SBR frequency range */ + int highSubband, /*!< High end of the SBR frequency range */ + int start_pos, /*!< First QMF-slot of current envelope */ + int next_pos, /*!< Last QMF-slot of current envelope + 1 */ + SCHAR frameExp, /*!< Common exponent for all input samples */ + FIXP_DBL *nrgEst, /*!< resulting Energy (0..1) */ + SCHAR *nrgEst_e) /*!< Exponent of resulting Energy */ { FIXP_SGL invWidth; - SCHAR preShift; - SCHAR shift; + SCHAR preShift; + SCHAR shift; FIXP_DBL sum; - int k,l; + int k; /* Divide by width of envelope later: */ invWidth = FX_DBL2FX_SGL(GetInvInt(next_pos - start_pos)); - /* The common exponent needs to be doubled because all mantissas are squared: */ + /* The common exponent needs to be doubled because all mantissas are squared: + */ frameExp = frameExp << 1; - for (k=lowSubband; k<highSubband; k++) { - FIXP_DBL bufferReal[(((1024)/(32))+(6))]; - FIXP_DBL bufferImag[(((1024)/(32))+(6))]; - FIXP_DBL maxVal = FL2FX_DBL(0.0f); + for (k = lowSubband; k < highSubband; k++) { + FIXP_DBL bufferReal[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL bufferImag[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL maxVal; - if (analysBufferImag!=NULL) - { - for (l=start_pos;l<next_pos;l++) - { + if (analysBufferImag != NULL) { + int l; + maxVal = FL2FX_DBL(0.0f); + for (l = start_pos; l < next_pos; l++) { bufferImag[l] = analysBufferImag[l][k]; - maxVal |= (FIXP_DBL)((LONG)(bufferImag[l])^((LONG)bufferImag[l]>>(DFRACT_BITS-1))); + maxVal |= (FIXP_DBL)((LONG)(bufferImag[l]) ^ + ((LONG)bufferImag[l] >> (DFRACT_BITS - 1))); bufferReal[l] = analysBufferReal[l][k]; - maxVal |= (FIXP_DBL)((LONG)(bufferReal[l])^((LONG)bufferReal[l]>>(DFRACT_BITS-1))); + maxVal |= (FIXP_DBL)((LONG)(bufferReal[l]) ^ + ((LONG)bufferReal[l] >> (DFRACT_BITS - 1))); } - } - else - { - for (l=start_pos;l<next_pos;l++) - { + } else { + int l; + maxVal = FL2FX_DBL(0.0f); + for (l = start_pos; l < next_pos; l++) { bufferReal[l] = analysBufferReal[l][k]; - maxVal |= (FIXP_DBL)((LONG)(bufferReal[l])^((LONG)bufferReal[l]>>(DFRACT_BITS-1))); + maxVal |= (FIXP_DBL)((LONG)(bufferReal[l]) ^ + ((LONG)bufferReal[l] >> (DFRACT_BITS - 1))); } } - if (maxVal!=FL2FXCONST_DBL(0.f)) { - - + if (maxVal != FL2FXCONST_DBL(0.f)) { /* If the accu does not provide enough overflow bits, we cannot shift the samples up to the limit. Instead, keep up to 3 free bits in each sample, i.e. up to 6 bits after calculation of square. Please note the comment on saturated arithmetic above! */ - FIXP_DBL accu = FL2FXCONST_DBL(0.0f); - preShift = CntLeadingZeros(maxVal)-1; + FIXP_DBL accu; + preShift = CntLeadingZeros(maxVal) - 1; preShift -= SHIFT_BEFORE_SQUARE; - if (preShift>=0) { - if (analysBufferImag!=NULL) { - for (l=start_pos; l<next_pos; l++) { + /* Limit preShift to a maximum value to prevent accumulator overflow in + exceptional situations where the signal in the analysis-buffer is very + small (small maxVal). + */ + preShift = fMin(preShift, (SCHAR)25); + + accu = FL2FXCONST_DBL(0.0f); + if (preShift >= 0) { + int l; + if (analysBufferImag != NULL) { + for (l = start_pos; l < next_pos; l++) { FIXP_DBL temp1 = bufferReal[l] << (int)preShift; FIXP_DBL temp2 = bufferImag[l] << (int)preShift; accu = fPow2AddDiv2(accu, temp1); accu = fPow2AddDiv2(accu, temp2); } - } else - { - for (l=start_pos; l<next_pos; l++) { + } else { + for (l = start_pos; l < next_pos; l++) { FIXP_DBL temp = bufferReal[l] << (int)preShift; accu = fPow2AddDiv2(accu, temp); } } - } - else { /* if negative shift value */ + } else { /* if negative shift value */ + int l; int negpreShift = -preShift; - if (analysBufferImag!=NULL) { - for (l=start_pos; l<next_pos; l++) { + if (analysBufferImag != NULL) { + for (l = start_pos; l < next_pos; l++) { FIXP_DBL temp1 = bufferReal[l] >> (int)negpreShift; FIXP_DBL temp2 = bufferImag[l] >> (int)negpreShift; accu = fPow2AddDiv2(accu, temp1); accu = fPow2AddDiv2(accu, temp2); } - } else - { - for (l=start_pos; l<next_pos; l++) { + } else { + for (l = start_pos; l < next_pos; l++) { FIXP_DBL temp = bufferReal[l] >> (int)negpreShift; accu = fPow2AddDiv2(accu, temp); } @@ -1451,13 +2089,12 @@ static void calcNrgPerSubband(FIXP_DBL **analysBufferReal, /*!< Real part of su /* Divide by width of envelope and apply frame scale: */ *nrgEst++ = fMult(sum, invWidth); shift += 2 * preShift; - if (analysBufferImag!=NULL) + if (analysBufferImag != NULL) *nrgEst_e++ = frameExp - shift; else - *nrgEst_e++ = frameExp - shift + 1; /* +1 due to missing imag. part */ - } /* maxVal!=0 */ + *nrgEst_e++ = frameExp - shift + 1; /* +1 due to missing imag. part */ + } /* maxVal!=0 */ else { - /* Prevent a zero-mantissa-number from being misinterpreted due to its exponent. */ *nrgEst++ = FL2FXCONST_DBL(0.0f); @@ -1472,45 +2109,42 @@ static void calcNrgPerSubband(FIXP_DBL **analysBufferReal, /*!< Real part of su This function is used when interpolFreq is false. */ -static void calcNrgPerSfb(FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */ - FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */ - int nSfb, /*!< Number of scale factor bands */ - UCHAR *freqBandTable, /*!< First Subband for each Sfb */ - int start_pos, /*!< First QMF-slot of current envelope */ - int next_pos, /*!< Last QMF-slot of current envelope + 1 */ - SCHAR input_e, /*!< Common exponent for all input samples */ - FIXP_DBL *nrgEst, /*!< resulting Energy (0..1) */ - SCHAR *nrgEst_e ) /*!< Exponent of resulting Energy */ +static void calcNrgPerSfb( + FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */ + FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */ + int nSfb, /*!< Number of scale factor bands */ + UCHAR *freqBandTable, /*!< First Subband for each Sfb */ + int start_pos, /*!< First QMF-slot of current envelope */ + int next_pos, /*!< Last QMF-slot of current envelope + 1 */ + SCHAR input_e, /*!< Common exponent for all input samples */ + FIXP_DBL *nrgEst, /*!< resulting Energy (0..1) */ + SCHAR *nrgEst_e) /*!< Exponent of resulting Energy */ { - FIXP_SGL invWidth; - FIXP_DBL temp; - SCHAR preShift; - SCHAR shift, sum_e; - FIXP_DBL sum; + FIXP_SGL invWidth; + FIXP_DBL temp; + SCHAR preShift; + SCHAR shift, sum_e; + FIXP_DBL sum; - int j,k,l,li,ui; + int j, k, l, li, ui; FIXP_DBL sumAll, sumLine; /* Single precision would be sufficient, but overflow bits are required for accumulation */ /* Divide by width of envelope later: */ invWidth = FX_DBL2FX_SGL(GetInvInt(next_pos - start_pos)); - /* The common exponent needs to be doubled because all mantissas are squared: */ + /* The common exponent needs to be doubled because all mantissas are squared: + */ input_e = input_e << 1; - for(j=0; j<nSfb; j++) { + for (j = 0; j < nSfb; j++) { li = freqBandTable[j]; - ui = freqBandTable[j+1]; + ui = freqBandTable[j + 1]; - FIXP_DBL maxVal = maxSubbandSample( analysBufferReal, - analysBufferImag, - li, - ui, - start_pos, - next_pos ); + FIXP_DBL maxVal = maxSubbandSample(analysBufferReal, analysBufferImag, li, + ui, start_pos, next_pos); - if (maxVal!=FL2FXCONST_DBL(0.f)) { - - preShift = CntLeadingZeros(maxVal)-1; + if (maxVal != FL2FXCONST_DBL(0.f)) { + preShift = CntLeadingZeros(maxVal) - 1; /* If the accu does not provide enough overflow bits, we cannot shift the samples up to the limit. @@ -1522,38 +2156,34 @@ static void calcNrgPerSfb(FIXP_DBL **analysBufferReal, /*!< Real part of subba sumAll = FL2FXCONST_DBL(0.0f); - - for (k=li; k<ui; k++) { - + for (k = li; k < ui; k++) { sumLine = FL2FXCONST_DBL(0.0f); - if (analysBufferImag!=NULL) { - if (preShift>=0) { - for (l=start_pos; l<next_pos; l++) { - temp = analysBufferReal[l][k] << (int)preShift; + if (analysBufferImag != NULL) { + if (preShift >= 0) { + for (l = start_pos; l < next_pos; l++) { + temp = analysBufferReal[l][k] << (int)preShift; sumLine += fPow2Div2(temp); - temp = analysBufferImag[l][k] << (int)preShift; + temp = analysBufferImag[l][k] << (int)preShift; sumLine += fPow2Div2(temp); - } } else { - for (l=start_pos; l<next_pos; l++) { - temp = analysBufferReal[l][k] >> -(int)preShift; + for (l = start_pos; l < next_pos; l++) { + temp = analysBufferReal[l][k] >> -(int)preShift; sumLine += fPow2Div2(temp); - temp = analysBufferImag[l][k] >> -(int)preShift; + temp = analysBufferImag[l][k] >> -(int)preShift; sumLine += fPow2Div2(temp); } } - } else - { - if (preShift>=0) { - for (l=start_pos; l<next_pos; l++) { - temp = analysBufferReal[l][k] << (int)preShift; + } else { + if (preShift >= 0) { + for (l = start_pos; l < next_pos; l++) { + temp = analysBufferReal[l][k] << (int)preShift; sumLine += fPow2Div2(temp); } } else { - for (l=start_pos; l<next_pos; l++) { - temp = analysBufferReal[l][k] >> -(int)preShift; + for (l = start_pos; l < next_pos; l++) { + temp = analysBufferReal[l][k] >> -(int)preShift; sumLine += fPow2Div2(temp); } } @@ -1561,8 +2191,8 @@ static void calcNrgPerSfb(FIXP_DBL **analysBufferReal, /*!< Real part of subba /* The number of QMF-channels per SBR bands may be up to 15. Shift right to avoid overflows in sum over all channels. */ - sumLine = sumLine >> (4-1); - sumAll += sumLine; + sumLine = sumLine >> (4 - 1); + sumAll += sumLine; } /* Convert double precision to Mantissa/Exponent: */ @@ -1570,62 +2200,66 @@ static void calcNrgPerSfb(FIXP_DBL **analysBufferReal, /*!< Real part of subba sum = sumAll << (int)shift; /* Divide by width of envelope: */ - sum = fMult(sum,invWidth); + sum = fMult(sum, invWidth); /* Divide by width of Sfb: */ - sum = fMult(sum, FX_DBL2FX_SGL(GetInvInt(ui-li))); + sum = fMult(sum, FX_DBL2FX_SGL(GetInvInt(ui - li))); /* Set all Subband energies in the Sfb to the average energy: */ - if (analysBufferImag!=NULL) - sum_e = input_e + 4 - shift; /* -4 to compensate right-shift */ + if (analysBufferImag != NULL) + sum_e = input_e + 4 - shift; /* -4 to compensate right-shift */ else - sum_e = input_e + 4 + 1 - shift; /* -4 to compensate right-shift; +1 due to missing imag. part */ + sum_e = input_e + 4 + 1 - + shift; /* -4 to compensate right-shift; +1 due to missing + imag. part */ sum_e -= 2 * preShift; } /* maxVal!=0 */ else { - /* Prevent a zero-mantissa-number from being misinterpreted due to its exponent. */ sum = FL2FXCONST_DBL(0.0f); sum_e = 0; } - for (k=li; k<ui; k++) - { - *nrgEst++ = sum; + for (k = li; k < ui; k++) { + *nrgEst++ = sum; *nrgEst_e++ = sum_e; } } } - /*! \brief Calculate gain, noise, and additional sine level for one subband. The resulting energy gain is given by mantissa and exponent. */ -static void calcSubbandGain(FIXP_DBL nrgRef, /*!< Reference Energy according to envelope data */ - SCHAR nrgRef_e, /*!< Reference Energy according to envelope data (exponent) */ - ENV_CALC_NRGS* nrgs, - int i, - FIXP_DBL tmpNoise, /*!< Relative noise level */ - SCHAR tmpNoise_e, /*!< Relative noise level (exponent) */ - UCHAR sinePresentFlag, /*!< Indicates if sine is present on band */ - UCHAR sineMapped, /*!< Indicates if sine must be added */ - int noNoiseFlag) /*!< Flag to suppress noise addition */ +static void calcSubbandGain( + FIXP_DBL nrgRef, /*!< Reference Energy according to envelope data */ + SCHAR + nrgRef_e, /*!< Reference Energy according to envelope data (exponent) */ + ENV_CALC_NRGS *nrgs, int i, FIXP_DBL tmpNoise, /*!< Relative noise level */ + SCHAR tmpNoise_e, /*!< Relative noise level (exponent) */ + UCHAR sinePresentFlag, /*!< Indicates if sine is present on band */ + UCHAR sineMapped, /*!< Indicates if sine must be added */ + int noNoiseFlag) /*!< Flag to suppress noise addition */ { - FIXP_DBL nrgEst = nrgs->nrgEst[i]; /*!< Energy in transposed signal */ - SCHAR nrgEst_e = nrgs->nrgEst_e[i]; /*!< Energy in transposed signal (exponent) */ - FIXP_DBL *ptrNrgGain = &nrgs->nrgGain[i]; /*!< Resulting energy gain */ - SCHAR *ptrNrgGain_e = &nrgs->nrgGain_e[i]; /*!< Resulting energy gain (exponent) */ - FIXP_DBL *ptrNoiseLevel = &nrgs->noiseLevel[i]; /*!< Resulting absolute noise energy */ - SCHAR *ptrNoiseLevel_e = &nrgs->noiseLevel_e[i]; /*!< Resulting absolute noise energy (exponent) */ - FIXP_DBL *ptrNrgSine = &nrgs->nrgSine[i]; /*!< Additional sine energy */ - SCHAR *ptrNrgSine_e = &nrgs->nrgSine_e[i]; /*!< Additional sine energy (exponent) */ + FIXP_DBL nrgEst = nrgs->nrgEst[i]; /*!< Energy in transposed signal */ + SCHAR nrgEst_e = + nrgs->nrgEst_e[i]; /*!< Energy in transposed signal (exponent) */ + FIXP_DBL *ptrNrgGain = &nrgs->nrgGain[i]; /*!< Resulting energy gain */ + SCHAR *ptrNrgGain_e = + &nrgs->nrgGain_e[i]; /*!< Resulting energy gain (exponent) */ + FIXP_DBL *ptrNoiseLevel = + &nrgs->noiseLevel[i]; /*!< Resulting absolute noise energy */ + SCHAR *ptrNoiseLevel_e = + &nrgs->noiseLevel_e[i]; /*!< Resulting absolute noise energy (exponent) */ + FIXP_DBL *ptrNrgSine = &nrgs->nrgSine[i]; /*!< Additional sine energy */ + SCHAR *ptrNrgSine_e = + &nrgs->nrgSine_e[i]; /*!< Additional sine energy (exponent) */ FIXP_DBL a, b, c; - SCHAR a_e, b_e, c_e; + SCHAR a_e, b_e, c_e; /* This addition of 1 prevents divisions by zero in the reference code. @@ -1633,74 +2267,64 @@ static void calcSubbandGain(FIXP_DBL nrgRef, /*!< Reference Energy a very high which could cause some trouble due to the smoothing. */ b_e = (int)(nrgEst_e - 1); - if (b_e>=0) { - nrgEst = (FL2FXCONST_DBL(0.5f) >> (INT)fixMin(b_e+1,DFRACT_BITS-1)) + (nrgEst >> 1); - nrgEst_e += 1; /* shift by 1 bit to avoid overflow */ + if (b_e >= 0) { + nrgEst = (FL2FXCONST_DBL(0.5f) >> (INT)fixMin(b_e + 1, DFRACT_BITS - 1)) + + (nrgEst >> 1); + nrgEst_e += 1; /* shift by 1 bit to avoid overflow */ } else { - nrgEst = (nrgEst >> (INT)(fixMin(-b_e+1,DFRACT_BITS-1))) + (FL2FXCONST_DBL(0.5f) >> 1); - nrgEst_e = 2; /* shift by 1 bit to avoid overflow */ + nrgEst = (nrgEst >> (INT)(fixMin(-b_e + 1, DFRACT_BITS - 1))) + + (FL2FXCONST_DBL(0.5f) >> 1); + nrgEst_e = 2; /* shift by 1 bit to avoid overflow */ } /* A = NrgRef * TmpNoise */ - a = fMult(nrgRef,tmpNoise); + a = fMult(nrgRef, tmpNoise); a_e = nrgRef_e + tmpNoise_e; /* B = 1 + TmpNoise */ b_e = (int)(tmpNoise_e - 1); - if (b_e>=0) { - b = (FL2FXCONST_DBL(0.5f) >> (INT)fixMin(b_e+1,DFRACT_BITS-1)) + (tmpNoise >> 1); - b_e = tmpNoise_e + 1; /* shift by 1 bit to avoid overflow */ + if (b_e >= 0) { + b = (FL2FXCONST_DBL(0.5f) >> (INT)fixMin(b_e + 1, DFRACT_BITS - 1)) + + (tmpNoise >> 1); + b_e = tmpNoise_e + 1; /* shift by 1 bit to avoid overflow */ } else { - b = (tmpNoise >> (INT)(fixMin(-b_e+1,DFRACT_BITS-1))) + (FL2FXCONST_DBL(0.5f) >> 1); - b_e = 2; /* shift by 1 bit to avoid overflow */ + b = (tmpNoise >> (INT)(fixMin(-b_e + 1, DFRACT_BITS - 1))) + + (FL2FXCONST_DBL(0.5f) >> 1); + b_e = 2; /* shift by 1 bit to avoid overflow */ } /* noiseLevel = A / B = (NrgRef * TmpNoise) / (1 + TmpNoise) */ - FDK_divide_MantExp( a, a_e, - b, b_e, - ptrNoiseLevel, ptrNoiseLevel_e); + FDK_divide_MantExp(a, a_e, b, b_e, ptrNoiseLevel, ptrNoiseLevel_e); if (sinePresentFlag) { - /* C = (1 + TmpNoise) * NrgEst */ - c = fMult(b,nrgEst); + c = fMult(b, nrgEst); c_e = b_e + nrgEst_e; /* gain = A / C = (NrgRef * TmpNoise) / (1 + TmpNoise) * NrgEst */ - FDK_divide_MantExp( a, a_e, - c, c_e, - ptrNrgGain, ptrNrgGain_e); + FDK_divide_MantExp(a, a_e, c, c_e, ptrNrgGain, ptrNrgGain_e); if (sineMapped) { - /* sineLevel = nrgRef/ (1 + TmpNoise) */ - FDK_divide_MantExp( nrgRef, nrgRef_e, - b, b_e, - ptrNrgSine, ptrNrgSine_e); + FDK_divide_MantExp(nrgRef, nrgRef_e, b, b_e, ptrNrgSine, ptrNrgSine_e); } - } - else { + } else { if (noNoiseFlag) { /* B = NrgEst */ b = nrgEst; b_e = nrgEst_e; - } - else { + } else { /* B = NrgEst * (1 + TmpNoise) */ - b = fMult(b,nrgEst); + b = fMult(b, nrgEst); b_e = b_e + nrgEst_e; } - /* gain = nrgRef / B */ - FDK_divide_MantExp( nrgRef, nrgRef_e, - b, b_e, - ptrNrgGain, ptrNrgGain_e); + FDK_divide_MantExp(nrgRef, nrgRef_e, b, b_e, ptrNrgGain, ptrNrgGain_e); } } - /*! \brief Calculate "average gain" for the specified subband range. @@ -1709,121 +2333,140 @@ static void calcSubbandGain(FIXP_DBL nrgRef, /*!< Reference Energy a The result is used as a relative limit for all gains within the current "limiter band" (a certain frequency range). */ -static void calcAvgGain(ENV_CALC_NRGS* nrgs, - int lowSubband, /*!< Begin of the limiter band */ - int highSubband, /*!< High end of the limiter band */ - FIXP_DBL *ptrSumRef, - SCHAR *ptrSumRef_e, - FIXP_DBL *ptrAvgGain, /*!< Resulting overall gain (mantissa) */ - SCHAR *ptrAvgGain_e) /*!< Resulting overall gain (exponent) */ +static void calcAvgGain( + ENV_CALC_NRGS *nrgs, int lowSubband, /*!< Begin of the limiter band */ + int highSubband, /*!< High end of the limiter band */ + FIXP_DBL *ptrSumRef, SCHAR *ptrSumRef_e, + FIXP_DBL *ptrAvgGain, /*!< Resulting overall gain (mantissa) */ + SCHAR *ptrAvgGain_e) /*!< Resulting overall gain (exponent) */ { - FIXP_DBL *nrgRef = nrgs->nrgRef; /*!< Reference Energy according to envelope data */ - SCHAR *nrgRef_e = nrgs->nrgRef_e; /*!< Reference Energy according to envelope data (exponent) */ - FIXP_DBL *nrgEst = nrgs->nrgEst; /*!< Energy in transposed signal */ - SCHAR *nrgEst_e = nrgs->nrgEst_e; /*!< Energy in transposed signal (exponent) */ + FIXP_DBL *nrgRef = + nrgs->nrgRef; /*!< Reference Energy according to envelope data */ + SCHAR *nrgRef_e = + nrgs->nrgRef_e; /*!< Reference Energy according to envelope data + (exponent) */ + FIXP_DBL *nrgEst = nrgs->nrgEst; /*!< Energy in transposed signal */ + SCHAR *nrgEst_e = + nrgs->nrgEst_e; /*!< Energy in transposed signal (exponent) */ FIXP_DBL sumRef = 1; FIXP_DBL sumEst = 1; - SCHAR sumRef_e = -FRACT_BITS; - SCHAR sumEst_e = -FRACT_BITS; - int k; + SCHAR sumRef_e = -FRACT_BITS; + SCHAR sumEst_e = -FRACT_BITS; + int k; - for (k=lowSubband; k<highSubband; k++){ + for (k = lowSubband; k < highSubband; k++) { /* Add nrgRef[k] to sumRef: */ - FDK_add_MantExp( sumRef, sumRef_e, - nrgRef[k], nrgRef_e[k], - &sumRef, &sumRef_e ); + FDK_add_MantExp(sumRef, sumRef_e, nrgRef[k], nrgRef_e[k], &sumRef, + &sumRef_e); /* Add nrgEst[k] to sumEst: */ - FDK_add_MantExp( sumEst, sumEst_e, - nrgEst[k], nrgEst_e[k], - &sumEst, &sumEst_e ); + FDK_add_MantExp(sumEst, sumEst_e, nrgEst[k], nrgEst_e[k], &sumEst, + &sumEst_e); } - FDK_divide_MantExp(sumRef, sumRef_e, - sumEst, sumEst_e, - ptrAvgGain, ptrAvgGain_e); + FDK_divide_MantExp(sumRef, sumRef_e, sumEst, sumEst_e, ptrAvgGain, + ptrAvgGain_e); *ptrSumRef = sumRef; *ptrSumRef_e = sumRef_e; } static void adjustTimeSlot_EldGrid( - FIXP_DBL *ptrReal, /*!< Subband samples to be adjusted, real part */ - ENV_CALC_NRGS* nrgs, - UCHAR *ptrHarmIndex, /*!< Harmonic index */ - int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ - int noSubbands, /*!< Number of QMF subbands */ - int scale_change, /*!< Number of bits to shift adjusted samples */ - int noNoiseFlag, /*!< Flag to suppress noise addition */ - int *ptrPhaseIndex, /*!< Start index to random number array */ - int scale_diff_low) /*!< */ + FIXP_DBL *RESTRICT + ptrReal, /*!< Subband samples to be adjusted, real part */ + ENV_CALC_NRGS *nrgs, UCHAR *ptrHarmIndex, /*!< Harmonic index */ + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change, /*!< Number of bits to shift adjusted samples */ + int noNoiseFlag, /*!< Flag to suppress noise addition */ + int *ptrPhaseIndex, /*!< Start index to random number array */ + int scale_diff_low) /*!< */ + { int k; - FIXP_DBL signalReal, sbNoise; + FIXP_DBL signalReal, sbNoise; int tone_count = 0; - FIXP_DBL *pGain = nrgs->nrgGain; /*!< Gains of current envelope */ - FIXP_DBL *pNoiseLevel = nrgs->noiseLevel; /*!< Noise levels of current envelope */ - FIXP_DBL *pSineLevel = nrgs->nrgSine; /*!< Sine levels */ - - int phaseIndex = *ptrPhaseIndex; - UCHAR harmIndex = *ptrHarmIndex; - - static const INT harmonicPhase [2][4] = { - { 1, 0, -1, 0}, - { 0, 1, 0, -1} - }; - - static const FIXP_DBL harmonicPhaseX [2][4] = { - { FL2FXCONST_DBL(2.0*1.245183154539139e-001), FL2FXCONST_DBL(2.0*-1.123767859325028e-001), FL2FXCONST_DBL(2.0*-1.245183154539139e-001), FL2FXCONST_DBL(2.0* 1.123767859325028e-001) }, - { FL2FXCONST_DBL(2.0*1.245183154539139e-001), FL2FXCONST_DBL(2.0* 1.123767859325028e-001), FL2FXCONST_DBL(2.0*-1.245183154539139e-001), FL2FXCONST_DBL(2.0*-1.123767859325028e-001) } - }; + FIXP_DBL *pGain = nrgs->nrgGain; /*!< Gains of current envelope */ + FIXP_DBL *RESTRICT pNoiseLevel = + nrgs->noiseLevel; /*!< Noise levels of current envelope */ + FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine; /*!< Sine levels */ - for (k=0; k < noSubbands; k++) { + int phaseIndex = *ptrPhaseIndex; + UCHAR harmIndex = *ptrHarmIndex; - phaseIndex = (phaseIndex + 1) & (SBR_NF_NO_RANDOM_VAL - 1); + static const INT harmonicPhase[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; - if( (pSineLevel[0] != FL2FXCONST_DBL(0.0f)) || (noNoiseFlag == 1) ){ - sbNoise = FL2FXCONST_DBL(0.0f); - } else { - sbNoise = pNoiseLevel[0]; - } + static const FIXP_DBL harmonicPhaseX[4][2] = { + {FL2FXCONST_DBL(2.0 * 1.245183154539139e-001), + FL2FXCONST_DBL(2.0 * 1.245183154539139e-001)}, + {FL2FXCONST_DBL(2.0 * -1.123767859325028e-001), + FL2FXCONST_DBL(2.0 * 1.123767859325028e-001)}, + {FL2FXCONST_DBL(2.0 * -1.245183154539139e-001), + FL2FXCONST_DBL(2.0 * -1.245183154539139e-001)}, + {FL2FXCONST_DBL(2.0 * 1.123767859325028e-001), + FL2FXCONST_DBL(2.0 * -1.123767859325028e-001)}}; - signalReal = fMultDiv2(*ptrReal,*pGain) << ((int)scale_change); + const FIXP_DBL *p_harmonicPhaseX = &harmonicPhaseX[harmIndex][0]; + const INT *p_harmonicPhase = &harmonicPhase[harmIndex][0]; - signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[phaseIndex][0], sbNoise)<<4); + *(ptrReal - 1) = fAddSaturate( + *(ptrReal - 1), + SATURATE_SHIFT(fMultDiv2(p_harmonicPhaseX[lowSubband & 1], pSineLevel[0]), + scale_diff_low, DFRACT_BITS)); + FIXP_DBL pSineLevel_prev = (FIXP_DBL)0; - signalReal += pSineLevel[0] * harmonicPhase[0][harmIndex]; + int idx_k = lowSubband & 1; - *ptrReal = signalReal; + for (k = 0; k < noSubbands; k++) { + FIXP_DBL sineLevel_curr = *pSineLevel++; + phaseIndex = (phaseIndex + 1) & (SBR_NF_NO_RANDOM_VAL - 1); - if (k == 0) { - *(ptrReal-1) += scaleValue(fMultDiv2(harmonicPhaseX[lowSubband&1][harmIndex], pSineLevel[0]), -scale_diff_low) ; - if (k < noSubbands - 1) { - *(ptrReal) += fMultDiv2(pSineLevel[1], harmonicPhaseX[(lowSubband+1)&1][harmIndex]); - } + signalReal = fMultDiv2(*ptrReal, *pGain++) << ((int)scale_change); + sbNoise = *pNoiseLevel++; + if (((INT)sineLevel_curr | noNoiseFlag) == 0) { + signalReal += + (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[phaseIndex][0], sbNoise) + << 4); } - if (k > 0 && k < noSubbands - 1 && tone_count < 16) { - *(ptrReal) += fMultDiv2(pSineLevel[- 1], harmonicPhaseX [(lowSubband+k)&1] [harmIndex]); - *(ptrReal) += fMultDiv2(pSineLevel[+ 1], harmonicPhaseX [(lowSubband+k+1)&1][harmIndex]); - } - if (k == noSubbands - 1 && tone_count < 16) { - if (k > 0) { - *(ptrReal) += fMultDiv2(pSineLevel[- 1], harmonicPhaseX [(lowSubband+k)&1][harmIndex]); + signalReal += sineLevel_curr * p_harmonicPhase[0]; + signalReal = + fMultAddDiv2(signalReal, pSineLevel_prev, p_harmonicPhaseX[idx_k]); + pSineLevel_prev = sineLevel_curr; + idx_k = !idx_k; + if (k < noSubbands - 1) { + signalReal = + fMultAddDiv2(signalReal, pSineLevel[0], p_harmonicPhaseX[idx_k]); + } else /* (k == noSubbands - 1) */ + { + if (k + lowSubband + 1 < 63) { + *(ptrReal + 1) += fMultDiv2(pSineLevel_prev, p_harmonicPhaseX[idx_k]); } - if (k + lowSubband + 1< 63) { - *(ptrReal+1) += fMultDiv2(pSineLevel[0], harmonicPhaseX[(lowSubband+k+1)&1][harmIndex]); + } + *ptrReal++ = signalReal; + + if (pSineLevel_prev != FL2FXCONST_DBL(0.0f)) { + if (++tone_count == 16) { + k++; + break; } } + } + /* Run again, if previous loop got breaked with tone_count = 16 */ + for (; k < noSubbands; k++) { + FIXP_DBL sineLevel_curr = *pSineLevel++; + phaseIndex = (phaseIndex + 1) & (SBR_NF_NO_RANDOM_VAL - 1); - if(pSineLevel[0] != FL2FXCONST_DBL(0.0f)){ - tone_count++; + signalReal = fMultDiv2(*ptrReal, *pGain++) << ((int)scale_change); + sbNoise = *pNoiseLevel++; + if (((INT)sineLevel_curr | noNoiseFlag) == 0) { + signalReal += + (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[phaseIndex][0], sbNoise) + << 4); } - ptrReal++; - pNoiseLevel++; - pGain++; - pSineLevel++; + signalReal += sineLevel_curr * p_harmonicPhase[0]; + *ptrReal++ = signalReal; } *ptrHarmIndex = (harmIndex + 1) & 3; @@ -1835,29 +2478,30 @@ static void adjustTimeSlot_EldGrid( and add the noisefloor. */ -static void adjustTimeSlotLC(FIXP_DBL *ptrReal, /*!< Subband samples to be adjusted, real part */ - ENV_CALC_NRGS* nrgs, - UCHAR *ptrHarmIndex, /*!< Harmonic index */ - int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ - int noSubbands, /*!< Number of QMF subbands */ - int scale_change, /*!< Number of bits to shift adjusted samples */ - int noNoiseFlag, /*!< Flag to suppress noise addition */ - int *ptrPhaseIndex) /*!< Start index to random number array */ +static void adjustTimeSlotLC( + FIXP_DBL *ptrReal, /*!< Subband samples to be adjusted, real part */ + ENV_CALC_NRGS *nrgs, UCHAR *ptrHarmIndex, /*!< Harmonic index */ + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change, /*!< Number of bits to shift adjusted samples */ + int noNoiseFlag, /*!< Flag to suppress noise addition */ + int *ptrPhaseIndex) /*!< Start index to random number array */ { - FIXP_DBL *pGain = nrgs->nrgGain; /*!< Gains of current envelope */ - FIXP_DBL *pNoiseLevel = nrgs->noiseLevel; /*!< Noise levels of current envelope */ - FIXP_DBL *pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + FIXP_DBL *pGain = nrgs->nrgGain; /*!< Gains of current envelope */ + FIXP_DBL *pNoiseLevel = + nrgs->noiseLevel; /*!< Noise levels of current envelope */ + FIXP_DBL *pSineLevel = nrgs->nrgSine; /*!< Sine levels */ - int k; - int index = *ptrPhaseIndex; - UCHAR harmIndex = *ptrHarmIndex; - UCHAR freqInvFlag = (lowSubband & 1); - FIXP_DBL signalReal, sineLevel, sineLevelNext, sineLevelPrev; - int tone_count = 0; - int sineSign = 1; + int k; + int index = *ptrPhaseIndex; + UCHAR harmIndex = *ptrHarmIndex; + UCHAR freqInvFlag = (lowSubband & 1); + FIXP_DBL signalReal, sineLevel, sineLevelNext, sineLevelPrev; + int tone_count = 0; + int sineSign = 1; - #define C1 ((FIXP_SGL)FL2FXCONST_SGL(2.f*0.00815f)) - #define C1_CLDFB ((FIXP_SGL)FL2FXCONST_SGL(2.f*0.16773f)) +#define C1 ((FIXP_SGL)FL2FXCONST_SGL(2.f * 0.00815f)) +#define C1_CLDFB ((FIXP_SGL)FL2FXCONST_SGL(2.f * 0.16773f)) /* First pass for k=0 pulled out of the loop: @@ -1870,38 +2514,40 @@ static void adjustTimeSlotLC(FIXP_DBL *ptrReal, /*!< Subband samples to be of the signal and should be carried out with full accuracy (supplying #FRACT_BITS valid bits). */ - signalReal = fMultDiv2(*ptrReal,*pGain++) << ((int)scale_change); - sineLevel = *pSineLevel++; + signalReal = fMultDiv2(*ptrReal, *pGain++) << ((int)scale_change); + sineLevel = *pSineLevel++; sineLevelNext = (noSubbands > 1) ? pSineLevel[0] : FL2FXCONST_DBL(0.0f); - if (sineLevel!=FL2FXCONST_DBL(0.0f)) tone_count++; + if (sineLevel != FL2FXCONST_DBL(0.0f)) + tone_count++; else if (!noNoiseFlag) - /* Add noisefloor to the amplified signal */ - signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4); + /* Add noisefloor to the amplified signal */ + signalReal += + (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0]) + << 4); { - if (!(harmIndex&0x1)) { + if (!(harmIndex & 0x1)) { /* harmIndex 0,2 */ - signalReal += (harmIndex&0x2) ? -sineLevel : sineLevel; + signalReal += (harmIndex & 0x2) ? -sineLevel : sineLevel; *ptrReal++ = signalReal; - } - else { + } else { /* harmIndex 1,3 in combination with freqInvFlag */ - int shift = (int) (scale_change+1); - shift = (shift>=0) ? fixMin(DFRACT_BITS-1,shift) : fixMax(-(DFRACT_BITS-1),shift); + int shift = (int)(scale_change + 1); + shift = (shift >= 0) ? fixMin(DFRACT_BITS - 1, shift) + : fixMax(-(DFRACT_BITS - 1), shift); - FIXP_DBL tmp1 = (shift>=0) ? ( fMultDiv2(C1, sineLevel) >> shift ) - : ( fMultDiv2(C1, sineLevel) << (-shift) ); + FIXP_DBL tmp1 = (shift >= 0) ? (fMultDiv2(C1, sineLevel) >> shift) + : (fMultDiv2(C1, sineLevel) << (-shift)); FIXP_DBL tmp2 = fMultDiv2(C1, sineLevelNext); - /* save switch and compare operations and reduce to XOR statement */ - if ( ((harmIndex>>1)&0x1)^freqInvFlag) { - *(ptrReal-1) += tmp1; - signalReal -= tmp2; + if (((harmIndex >> 1) & 0x1) ^ freqInvFlag) { + *(ptrReal - 1) += tmp1; + signalReal -= tmp2; } else { - *(ptrReal-1) -= tmp1; - signalReal += tmp2; + *(ptrReal - 1) -= tmp1; + signalReal += tmp2; } *ptrReal++ = signalReal; freqInvFlag = !freqInvFlag; @@ -1910,45 +2556,51 @@ static void adjustTimeSlotLC(FIXP_DBL *ptrReal, /*!< Subband samples to be pNoiseLevel++; - if ( noSubbands > 2 ) { - if (!(harmIndex&0x1)) { + if (noSubbands > 2) { + if (!(harmIndex & 0x1)) { /* harmIndex 0,2 */ - if(!harmIndex) - { + if (!harmIndex) { sineSign = 0; } - for (k=noSubbands-2; k!=0; k--) { + for (k = noSubbands - 2; k != 0; k--) { FIXP_DBL sinelevel = *pSineLevel++; index++; - if (((signalReal = (sineSign ? -sinelevel : sinelevel)) == FL2FXCONST_DBL(0.0f)) && !noNoiseFlag) - { + if (((signalReal = (sineSign ? -sinelevel : sinelevel)) == + FL2FXCONST_DBL(0.0f)) && + !noNoiseFlag) { /* Add noisefloor to the amplified signal */ index &= (SBR_NF_NO_RANDOM_VAL - 1); - signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4); + signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], + pNoiseLevel[0]) + << 4); } - - /* The next multiplication constitutes the actual envelope adjustment of the signal. */ - signalReal += fMultDiv2(*ptrReal,*pGain++) << ((int)scale_change); + + /* The next multiplication constitutes the actual envelope adjustment of + * the signal. */ + signalReal += fMultDiv2(*ptrReal, *pGain++) << ((int)scale_change); pNoiseLevel++; *ptrReal++ = signalReal; } /* for ... */ - } - else { + } else { /* harmIndex 1,3 in combination with freqInvFlag */ - if (harmIndex==1) freqInvFlag = !freqInvFlag; + if (harmIndex == 1) freqInvFlag = !freqInvFlag; - for (k=noSubbands-2; k!=0; k--) { + for (k = noSubbands - 2; k != 0; k--) { index++; - /* The next multiplication constitutes the actual envelope adjustment of the signal. */ - signalReal = fMultDiv2(*ptrReal,*pGain++) << ((int)scale_change); + /* The next multiplication constitutes the actual envelope adjustment of + * the signal. */ + signalReal = fMultDiv2(*ptrReal, *pGain++) << ((int)scale_change); - if (*pSineLevel++!=FL2FXCONST_DBL(0.0f)) tone_count++; + if (*pSineLevel++ != FL2FXCONST_DBL(0.0f)) + tone_count++; else if (!noNoiseFlag) { /* Add noisefloor to the amplified signal */ index &= (SBR_NF_NO_RANDOM_VAL - 1); - signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4); + signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], + pNoiseLevel[0]) + << 4); } pNoiseLevel++; @@ -1966,76 +2618,247 @@ static void adjustTimeSlotLC(FIXP_DBL *ptrReal, /*!< Subband samples to be if (noSubbands > -1) { index++; - /* The next multiplication constitutes the actual envelope adjustment of the signal. */ - signalReal = fMultDiv2(*ptrReal,*pGain) << ((int)scale_change); - sineLevelPrev = fMultDiv2(pSineLevel[-1],FL2FX_SGL(0.0163f)); - sineLevel = pSineLevel[0]; + /* The next multiplication constitutes the actual envelope adjustment of the + * signal. */ + signalReal = fMultDiv2(*ptrReal, *pGain) << ((int)scale_change); + sineLevelPrev = fMultDiv2(pSineLevel[-1], FL2FX_SGL(0.0163f)); + sineLevel = pSineLevel[0]; - if (pSineLevel[0]!=FL2FXCONST_DBL(0.0f)) tone_count++; + if (pSineLevel[0] != FL2FXCONST_DBL(0.0f)) + tone_count++; else if (!noNoiseFlag) { - /* Add noisefloor to the amplified signal */ - index &= (SBR_NF_NO_RANDOM_VAL - 1); - signalReal = signalReal + (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4); + /* Add noisefloor to the amplified signal */ + index &= (SBR_NF_NO_RANDOM_VAL - 1); + signalReal = + signalReal + + (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0]) + << 4); } - if (!(harmIndex&0x1)) { + if (!(harmIndex & 0x1)) { /* harmIndex 0,2 */ - *ptrReal = signalReal + ( (sineSign) ? -sineLevel : sineLevel); - } - else { + *ptrReal = signalReal + ((sineSign) ? -sineLevel : sineLevel); + } else { /* harmIndex 1,3 in combination with freqInvFlag */ - if(tone_count <= 16){ + if (tone_count <= 16) { if (freqInvFlag) { - *ptrReal++ = signalReal - sineLevelPrev; + *ptrReal++ = signalReal - sineLevelPrev; if (noSubbands + lowSubband < 63) *ptrReal = *ptrReal + fMultDiv2(C1, sineLevel); - } - else { + } else { *ptrReal++ = signalReal + sineLevelPrev; if (noSubbands + lowSubband < 63) *ptrReal = *ptrReal - fMultDiv2(C1, sineLevel); } - } - else *ptrReal = signalReal; + } else + *ptrReal = signalReal; } } *ptrHarmIndex = (harmIndex + 1) & 3; *ptrPhaseIndex = index & (SBR_NF_NO_RANDOM_VAL - 1); } -static void adjustTimeSlotHQ( - FIXP_DBL *RESTRICT ptrReal, /*!< Subband samples to be adjusted, real part */ - FIXP_DBL *RESTRICT ptrImag, /*!< Subband samples to be adjusted, imag part */ - HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, - ENV_CALC_NRGS* nrgs, - int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ - int noSubbands, /*!< Number of QMF subbands */ - int scale_change, /*!< Number of bits to shift adjusted samples */ - FIXP_SGL smooth_ratio, /*!< Impact of last envelope */ - int noNoiseFlag, /*!< Start index to random number array */ - int filtBufferNoiseShift) /*!< Shift factor of filtBufferNoise */ + +static void adjustTimeSlotHQ_GainAndNoise( + FIXP_DBL *RESTRICT + ptrReal, /*!< Subband samples to be adjusted, real part */ + FIXP_DBL *RESTRICT + ptrImag, /*!< Subband samples to be adjusted, imag part */ + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS *nrgs, + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change, /*!< Number of bits to shift adjusted samples */ + FIXP_SGL smooth_ratio, /*!< Impact of last envelope */ + int noNoiseFlag, /*!< Start index to random number array */ + int filtBufferNoiseShift) /*!< Shift factor of filtBufferNoise */ { + FIXP_DBL *RESTRICT gain = nrgs->nrgGain; /*!< Gains of current envelope */ + FIXP_DBL *RESTRICT noiseLevel = + nrgs->noiseLevel; /*!< Noise levels of current envelope */ + FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + + FIXP_DBL *RESTRICT filtBuffer = + h_sbr_cal_env->filtBuffer; /*!< Gains of last envelope */ + FIXP_DBL *RESTRICT filtBufferNoise = + h_sbr_cal_env->filtBufferNoise; /*!< Noise levels of last envelope */ + int *RESTRICT ptrPhaseIndex = + &h_sbr_cal_env->phaseIndex; /*!< Start index to random number array */ + + int k; + FIXP_DBL signalReal, signalImag; + FIXP_DBL noiseReal, noiseImag; + FIXP_DBL smoothedGain, smoothedNoise; + FIXP_SGL direct_ratio = + /*FL2FXCONST_SGL(1.0f) */ (FIXP_SGL)MAXVAL_SGL - smooth_ratio; + int index = *ptrPhaseIndex; + int shift; - FIXP_DBL *RESTRICT gain = nrgs->nrgGain; /*!< Gains of current envelope */ - FIXP_DBL *RESTRICT noiseLevel = nrgs->noiseLevel; /*!< Noise levels of current envelope */ - FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + *ptrPhaseIndex = (index + noSubbands) & (SBR_NF_NO_RANDOM_VAL - 1); - FIXP_DBL *RESTRICT filtBuffer = h_sbr_cal_env->filtBuffer; /*!< Gains of last envelope */ - FIXP_DBL *RESTRICT filtBufferNoise = h_sbr_cal_env->filtBufferNoise; /*!< Noise levels of last envelope */ - UCHAR *RESTRICT ptrHarmIndex =&h_sbr_cal_env->harmIndex; /*!< Harmonic index */ - int *RESTRICT ptrPhaseIndex =&h_sbr_cal_env->phaseIndex; /*!< Start index to random number array */ + filtBufferNoiseShift += + 1; /* due to later use of fMultDiv2 instead of fMult */ + if (filtBufferNoiseShift < 0) { + shift = fixMin(DFRACT_BITS - 1, -filtBufferNoiseShift); + } else { + shift = fixMin(DFRACT_BITS - 1, filtBufferNoiseShift); + } - int k; + if (smooth_ratio > FL2FXCONST_SGL(0.0f)) { + for (k = 0; k < noSubbands; k++) { + /* + Smoothing: The old envelope has been bufferd and a certain ratio + of the old gains and noise levels is used. + */ + smoothedGain = + fMult(smooth_ratio, filtBuffer[k]) + fMult(direct_ratio, gain[k]); + + if (filtBufferNoiseShift < 0) { + smoothedNoise = (fMultDiv2(smooth_ratio, filtBufferNoise[k]) >> shift) + + fMult(direct_ratio, noiseLevel[k]); + } else { + smoothedNoise = (fMultDiv2(smooth_ratio, filtBufferNoise[k]) << shift) + + fMult(direct_ratio, noiseLevel[k]); + } + + /* + The next 2 multiplications constitute the actual envelope adjustment + of the signal and should be carried out with full accuracy + (supplying #DFRACT_BITS valid bits). + */ + signalReal = fMultDiv2(*ptrReal, smoothedGain) << ((int)scale_change); + signalImag = fMultDiv2(*ptrImag, smoothedGain) << ((int)scale_change); + + index++; + + if ((pSineLevel[k] != FL2FXCONST_DBL(0.0f)) || noNoiseFlag) { + /* Just the amplified signal is saved */ + *ptrReal++ = signalReal; + *ptrImag++ = signalImag; + } else { + /* Add noisefloor to the amplified signal */ + index &= (SBR_NF_NO_RANDOM_VAL - 1); + noiseReal = + fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], smoothedNoise) + << 4; + noiseImag = + fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][1], smoothedNoise) + << 4; + *ptrReal++ = (signalReal + noiseReal); + *ptrImag++ = (signalImag + noiseImag); + } + } + } else { + for (k = 0; k < noSubbands; k++) { + smoothedGain = gain[k]; + signalReal = fMultDiv2(*ptrReal, smoothedGain) << scale_change; + signalImag = fMultDiv2(*ptrImag, smoothedGain) << scale_change; + + index++; + + if ((pSineLevel[k] == FL2FXCONST_DBL(0.0f)) && (noNoiseFlag == 0)) { + /* Add noisefloor to the amplified signal */ + smoothedNoise = noiseLevel[k]; + index &= (SBR_NF_NO_RANDOM_VAL - 1); + noiseReal = + fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], smoothedNoise); + noiseImag = + fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][1], smoothedNoise); + + /* FDK_sbrDecoder_sbr_randomPhase is downscaled by 2^3 */ + signalReal += noiseReal << 4; + signalImag += noiseImag << 4; + } + *ptrReal++ = signalReal; + *ptrImag++ = signalImag; + } + } +} + +static void adjustTimeSlotHQ_AddHarmonics( + FIXP_DBL *RESTRICT + ptrReal, /*!< Subband samples to be adjusted, real part */ + FIXP_DBL *RESTRICT + ptrImag, /*!< Subband samples to be adjusted, imag part */ + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS *nrgs, + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change /*!< Scale mismatch between QMF input and sineLevel + exponent. */ +) { + FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + UCHAR *RESTRICT ptrHarmIndex = + &h_sbr_cal_env->harmIndex; /*!< Harmonic index */ + + int k; + FIXP_DBL signalReal, signalImag; + UCHAR harmIndex = *ptrHarmIndex; + int freqInvFlag = (lowSubband & 1); + FIXP_DBL sineLevel; + + *ptrHarmIndex = (harmIndex + 1) & 3; + + for (k = 0; k < noSubbands; k++) { + sineLevel = pSineLevel[k]; + freqInvFlag ^= 1; + if (sineLevel != FL2FXCONST_DBL(0.f)) { + signalReal = ptrReal[k]; + signalImag = ptrImag[k]; + sineLevel = scaleValue(sineLevel, scale_change); + if (harmIndex & 2) { + /* case 2,3 */ + sineLevel = -sineLevel; + } + if (!(harmIndex & 1)) { + /* case 0,2: */ + ptrReal[k] = signalReal + sineLevel; + } else { + /* case 1,3 */ + if (!freqInvFlag) sineLevel = -sineLevel; + ptrImag[k] = signalImag + sineLevel; + } + } + } +} + +static void adjustTimeSlotHQ( + FIXP_DBL *RESTRICT + ptrReal, /*!< Subband samples to be adjusted, real part */ + FIXP_DBL *RESTRICT + ptrImag, /*!< Subband samples to be adjusted, imag part */ + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS *nrgs, + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change, /*!< Number of bits to shift adjusted samples */ + FIXP_SGL smooth_ratio, /*!< Impact of last envelope */ + int noNoiseFlag, /*!< Start index to random number array */ + int filtBufferNoiseShift) /*!< Shift factor of filtBufferNoise */ +{ + FIXP_DBL *RESTRICT gain = nrgs->nrgGain; /*!< Gains of current envelope */ + FIXP_DBL *RESTRICT noiseLevel = + nrgs->noiseLevel; /*!< Noise levels of current envelope */ + FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + + FIXP_DBL *RESTRICT filtBuffer = + h_sbr_cal_env->filtBuffer; /*!< Gains of last envelope */ + FIXP_DBL *RESTRICT filtBufferNoise = + h_sbr_cal_env->filtBufferNoise; /*!< Noise levels of last envelope */ + UCHAR *RESTRICT ptrHarmIndex = + &h_sbr_cal_env->harmIndex; /*!< Harmonic index */ + int *RESTRICT ptrPhaseIndex = + &h_sbr_cal_env->phaseIndex; /*!< Start index to random number array */ + + int k; FIXP_DBL signalReal, signalImag; - FIXP_DBL noiseReal, noiseImag; - FIXP_DBL smoothedGain, smoothedNoise; - FIXP_SGL direct_ratio = /*FL2FXCONST_SGL(1.0f) */ (FIXP_SGL)MAXVAL_SGL - smooth_ratio; - int index = *ptrPhaseIndex; - UCHAR harmIndex = *ptrHarmIndex; + FIXP_DBL noiseReal, noiseImag; + FIXP_DBL smoothedGain, smoothedNoise; + FIXP_SGL direct_ratio = + /*FL2FXCONST_SGL(1.0f) */ (FIXP_SGL)MAXVAL_SGL - smooth_ratio; + int index = *ptrPhaseIndex; + UCHAR harmIndex = *ptrHarmIndex; int freqInvFlag = (lowSubband & 1); FIXP_DBL sineLevel; int shift; - *ptrPhaseIndex = (index+noSubbands) & (SBR_NF_NO_RANDOM_VAL - 1); + *ptrPhaseIndex = (index + noSubbands) & (SBR_NF_NO_RANDOM_VAL - 1); *ptrHarmIndex = (harmIndex + 1) & 3; /* @@ -2047,30 +2870,29 @@ static void adjustTimeSlotHQ( of the whole function decreased by about 20 % */ - filtBufferNoiseShift += 1; /* due to later use of fMultDiv2 instead of fMult */ - if (filtBufferNoiseShift<0) - shift = fixMin(DFRACT_BITS-1,-filtBufferNoiseShift); + filtBufferNoiseShift += + 1; /* due to later use of fMultDiv2 instead of fMult */ + if (filtBufferNoiseShift < 0) + shift = fixMin(DFRACT_BITS - 1, -filtBufferNoiseShift); else - shift = fixMin(DFRACT_BITS-1, filtBufferNoiseShift); + shift = fixMin(DFRACT_BITS - 1, filtBufferNoiseShift); if (smooth_ratio > FL2FXCONST_SGL(0.0f)) { - - for (k=0; k<noSubbands; k++) { + for (k = 0; k < noSubbands; k++) { /* Smoothing: The old envelope has been bufferd and a certain ratio of the old gains and noise levels is used. */ - smoothedGain = fMult(smooth_ratio,filtBuffer[k]) + - fMult(direct_ratio,gain[k]); + smoothedGain = + fMult(smooth_ratio, filtBuffer[k]) + fMult(direct_ratio, gain[k]); - if (filtBufferNoiseShift<0) { - smoothedNoise = (fMultDiv2(smooth_ratio,filtBufferNoise[k])>>shift) + - fMult(direct_ratio,noiseLevel[k]); - } - else { - smoothedNoise = (fMultDiv2(smooth_ratio,filtBufferNoise[k])<<shift) + - fMult(direct_ratio,noiseLevel[k]); + if (filtBufferNoiseShift < 0) { + smoothedNoise = (fMultDiv2(smooth_ratio, filtBufferNoise[k]) >> shift) + + fMult(direct_ratio, noiseLevel[k]); + } else { + smoothedNoise = (fMultDiv2(smooth_ratio, filtBufferNoise[k]) << shift) + + fMult(direct_ratio, noiseLevel[k]); } /* @@ -2078,50 +2900,53 @@ static void adjustTimeSlotHQ( of the signal and should be carried out with full accuracy (supplying #DFRACT_BITS valid bits). */ - signalReal = fMultDiv2(*ptrReal,smoothedGain)<<((int)scale_change); - signalImag = fMultDiv2(*ptrImag,smoothedGain)<<((int)scale_change); + signalReal = fMultDiv2(*ptrReal, smoothedGain) << ((int)scale_change); + signalImag = fMultDiv2(*ptrImag, smoothedGain) << ((int)scale_change); index++; if (pSineLevel[k] != FL2FXCONST_DBL(0.0f)) { sineLevel = pSineLevel[k]; - switch(harmIndex) { - case 0: - *ptrReal++ = (signalReal + sineLevel); - *ptrImag++ = (signalImag); - break; - case 2: - *ptrReal++ = (signalReal - sineLevel); - *ptrImag++ = (signalImag); - break; - case 1: - *ptrReal++ = (signalReal); - if (freqInvFlag) - *ptrImag++ = (signalImag - sineLevel); - else - *ptrImag++ = (signalImag + sineLevel); - break; - case 3: - *ptrReal++ = signalReal; - if (freqInvFlag) - *ptrImag++ = (signalImag + sineLevel); - else - *ptrImag++ = (signalImag - sineLevel); - break; + switch (harmIndex) { + case 0: + *ptrReal++ = (signalReal + sineLevel); + *ptrImag++ = (signalImag); + break; + case 2: + *ptrReal++ = (signalReal - sineLevel); + *ptrImag++ = (signalImag); + break; + case 1: + *ptrReal++ = (signalReal); + if (freqInvFlag) + *ptrImag++ = (signalImag - sineLevel); + else + *ptrImag++ = (signalImag + sineLevel); + break; + case 3: + *ptrReal++ = signalReal; + if (freqInvFlag) + *ptrImag++ = (signalImag + sineLevel); + else + *ptrImag++ = (signalImag - sineLevel); + break; } - } - else { + } else { if (noNoiseFlag) { /* Just the amplified signal is saved */ *ptrReal++ = (signalReal); *ptrImag++ = (signalImag); - } - else { + } else { /* Add noisefloor to the amplified signal */ index &= (SBR_NF_NO_RANDOM_VAL - 1); - noiseReal = fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], smoothedNoise)<<4; - noiseImag = fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][1], smoothedNoise)<<4; + /* FDK_sbrDecoder_sbr_randomPhase is downscaled by 2^3 */ + noiseReal = + fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], smoothedNoise) + << 4; + noiseImag = + fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][1], smoothedNoise) + << 4; *ptrReal++ = (signalReal + noiseReal); *ptrImag++ = (signalImag + noiseImag); } @@ -2129,52 +2954,48 @@ static void adjustTimeSlotHQ( freqInvFlag ^= 1; } - } - else - { - for (k=0; k<noSubbands; k++) - { - smoothedGain = gain[k]; + } else { + for (k = 0; k < noSubbands; k++) { + smoothedGain = gain[k]; signalReal = fMultDiv2(*ptrReal, smoothedGain) << scale_change; signalImag = fMultDiv2(*ptrImag, smoothedGain) << scale_change; index++; - if ((sineLevel = pSineLevel[k]) != FL2FXCONST_DBL(0.0f)) - { - switch (harmIndex) - { - case 0: - signalReal += sineLevel; - break; - case 1: - if (freqInvFlag) - signalImag -= sineLevel; - else - signalImag += sineLevel; - break; - case 2: - signalReal -= sineLevel; - break; - case 3: - if (freqInvFlag) - signalImag += sineLevel; - else - signalImag -= sineLevel; - break; + if ((sineLevel = pSineLevel[k]) != FL2FXCONST_DBL(0.0f)) { + switch (harmIndex) { + case 0: + signalReal += sineLevel; + break; + case 1: + if (freqInvFlag) + signalImag -= sineLevel; + else + signalImag += sineLevel; + break; + case 2: + signalReal -= sineLevel; + break; + case 3: + if (freqInvFlag) + signalImag += sineLevel; + else + signalImag -= sineLevel; + break; } - } - else - { - if (noNoiseFlag == 0) - { + } else { + if (noNoiseFlag == 0) { /* Add noisefloor to the amplified signal */ smoothedNoise = noiseLevel[k]; index &= (SBR_NF_NO_RANDOM_VAL - 1); - noiseReal = fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], smoothedNoise); - noiseImag = fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][1], smoothedNoise); - signalReal += noiseReal<<4; - signalImag += noiseImag<<4; + noiseReal = fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], + smoothedNoise); + noiseImag = fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][1], + smoothedNoise); + + /* FDK_sbrDecoder_sbr_randomPhase is downscaled by 2^3 */ + signalReal += noiseReal << 4; + signalImag += noiseImag << 4; } } *ptrReal++ = signalReal; @@ -2185,7 +3006,6 @@ static void adjustTimeSlotHQ( } } - /*! \brief Reset limiter bands. @@ -2195,14 +3015,15 @@ static void adjustTimeSlotHQ( \return SBRDEC_OK if ok, SBRDEC_UNSUPPORTED_CONFIG on error */ SBR_ERROR -ResetLimiterBands ( UCHAR *limiterBandTable, /*!< Resulting band borders in QMF channels */ - UCHAR *noLimiterBands, /*!< Resulting number of limiter band */ - UCHAR *freqBandTable, /*!< Table with possible band borders */ - int noFreqBands, /*!< Number of bands in freqBandTable */ - const PATCH_PARAM *patchParam, /*!< Transposer patch parameters */ - int noPatches, /*!< Number of transposer patches */ - int limiterBands) /*!< Selected 'band density' from bitstream */ -{ +ResetLimiterBands( + UCHAR *limiterBandTable, /*!< Resulting band borders in QMF channels */ + UCHAR *noLimiterBands, /*!< Resulting number of limiter band */ + UCHAR *freqBandTable, /*!< Table with possible band borders */ + int noFreqBands, /*!< Number of bands in freqBandTable */ + const PATCH_PARAM *patchParam, /*!< Transposer patch parameters */ + int noPatches, /*!< Number of transposer patches */ + int limiterBands, /*!< Selected 'band density' from bitstream */ + UCHAR sbrPatchingMode, int xOverQmf[MAX_NUM_PATCHES], int b41Sbr) { int i, k, isPatchBorder[2], loLimIndex, hiLimIndex, tempNoLim, nBands; UCHAR workLimiterBandTable[MAX_FREQ_COEFFS / 2 + MAX_NUM_PATCHES + 1]; int patchBorders[MAX_NUM_PATCHES + 1]; @@ -2212,13 +3033,28 @@ ResetLimiterBands ( UCHAR *limiterBandTable, /*!< Resulting band borders in QM int highSubband = freqBandTable[noFreqBands]; /* 1 limiter band. */ - if(limiterBands == 0) { + if (limiterBands == 0) { limiterBandTable[0] = 0; limiterBandTable[1] = highSubband - lowSubband; nBands = 1; } else { - for (i = 0; i < noPatches; i++) { - patchBorders[i] = patchParam[i].guardStartBand - lowSubband; + if (!sbrPatchingMode && xOverQmf != NULL) { + noPatches = 0; + + if (b41Sbr == 1) { + for (i = 1; i < MAX_NUM_PATCHES_HBE; i++) + if (xOverQmf[i] != 0) noPatches++; + } else { + for (i = 1; i < MAX_STRETCH_HBE; i++) + if (xOverQmf[i] != 0) noPatches++; + } + for (i = 0; i < noPatches; i++) { + patchBorders[i] = xOverQmf[i] - lowSubband; + } + } else { + for (i = 0; i < noPatches; i++) { + patchBorders[i] = patchParam[i].guardStartBand - lowSubband; + } } patchBorders[i] = highSubband - lowSubband; @@ -2236,35 +3072,38 @@ ResetLimiterBands ( UCHAR *limiterBandTable, /*!< Resulting band borders in QM loLimIndex = 0; hiLimIndex = 1; - while (hiLimIndex <= tempNoLim) { FIXP_DBL div_m, oct_m, temp; - INT div_e = 0, oct_e = 0, temp_e = 0; + INT div_e = 0, oct_e = 0, temp_e = 0; k2 = workLimiterBandTable[hiLimIndex] + lowSubband; kx = workLimiterBandTable[loLimIndex] + lowSubband; - div_m = fDivNorm(k2, kx, &div_e); + div_m = fDivNorm(k2, kx, &div_e); /* calculate number of octaves */ - oct_m = fLog2(div_m, div_e, &oct_e); + oct_m = fLog2(div_m, div_e, &oct_e); /* multiply with limiterbands per octave */ /* values 1, 1.2, 2, 3 -> scale factor of 2 */ - temp = fMultNorm(oct_m, FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[limiterBands], &temp_e); + temp = fMultNorm( + oct_m, FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[limiterBands], + &temp_e); - /* overall scale factor of temp ist addition of scalefactors from log2 calculation, - limiter bands scalefactor (2) and limiter bands multiplication */ + /* overall scale factor of temp ist addition of scalefactors from log2 + calculation, limiter bands scalefactor (2) and limiter bands + multiplication */ temp_e += oct_e + 2; /* div can be a maximum of 64 (k2 = 64 and kx = 1) -> oct can be a maximum of 6 - -> temp can be a maximum of 18 (as limiterBandsPerOctoave is a maximum factor of 3) + -> temp can be a maximum of 18 (as limiterBandsPerOctoave is a maximum + factor of 3) -> we need a scale factor of 5 for comparisson */ - if (temp >> (5 - temp_e) < FL2FXCONST_DBL (0.49f) >> 5) { - - if (workLimiterBandTable[hiLimIndex] == workLimiterBandTable[loLimIndex]) { + if (temp >> (5 - temp_e) < FL2FXCONST_DBL(0.49f) >> 5) { + if (workLimiterBandTable[hiLimIndex] == + workLimiterBandTable[loLimIndex]) { workLimiterBandTable[hiLimIndex] = highSubband; nBands--; hiLimIndex++; @@ -2296,12 +3135,11 @@ ResetLimiterBands ( UCHAR *limiterBandTable, /*!< Resulting band borders in QM } loLimIndex = hiLimIndex; hiLimIndex++; - } shellsort(workLimiterBandTable, tempNoLim + 1); /* Test if algorithm exceeded maximum allowed limiterbands */ - if( nBands > MAX_NUM_LIMITERS || nBands <= 0) { + if (nBands > MAX_NUM_LIMITERS || nBands <= 0) { return SBRDEC_UNSUPPORTED_CONFIG; } @@ -2314,4 +3152,3 @@ ResetLimiterBands ( UCHAR *limiterBandTable, /*!< Resulting band borders in QM return SBRDEC_OK; } - diff --git a/libSBRdec/src/env_calc.h b/libSBRdec/src/env_calc.h index 8154166..cff365d 100644 --- a/libSBRdec/src/env_calc.h +++ b/libSBRdec/src/env_calc.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,87 +90,93 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -/*! - \file - \brief Envelope calculation prototypes -*/ -#ifndef __ENV_CALC_H -#define __ENV_CALC_H - -#include "sbrdecoder.h" -#include "env_extr.h" /* for HANDLE_SBR_HEADER_DATA */ -#include "sbr_scale.h" +/**************************** SBR decoder library ****************************** + Author(s): -typedef struct -{ - FIXP_DBL filtBuffer[MAX_FREQ_COEFFS]; /*!< previous gains (required for smoothing) */ - FIXP_DBL filtBufferNoise[MAX_FREQ_COEFFS]; /*!< previous noise levels (required for smoothing) */ - SCHAR filtBuffer_e[MAX_FREQ_COEFFS]; /*!< Exponents of previous gains */ - SCHAR filtBufferNoise_e; /*!< Common exponent of previous noise levels */ + Description: - int startUp; /*!< flag to signal initial conditions in buffers */ - int phaseIndex; /*!< Index for randomPase array */ - int prevTranEnv; /*!< The transient envelope of the previous frame. */ +*******************************************************************************/ - int harmFlagsPrev[(MAX_FREQ_COEFFS+15)/16]; - /*!< Words with 16 flags each indicating where a sine was added in the previous frame.*/ - UCHAR harmIndex; /*!< Current phase of synthetic sine */ +/*! + \file + \brief Envelope calculation prototypes +*/ +#ifndef ENV_CALC_H +#define ENV_CALC_H -} -SBR_CALCULATE_ENVELOPE; +#include "sbrdecoder.h" +#include "env_extr.h" /* for HANDLE_SBR_HEADER_DATA */ + +typedef struct { + FIXP_DBL filtBuffer[MAX_FREQ_COEFFS]; /*!< previous gains (required for + smoothing) */ + FIXP_DBL filtBufferNoise[MAX_FREQ_COEFFS]; /*!< previous noise levels + (required for smoothing) */ + SCHAR filtBuffer_e[MAX_FREQ_COEFFS]; /*!< Exponents of previous gains */ + SCHAR filtBufferNoise_e; /*!< Common exponent of previous noise levels */ + + int startUp; /*!< flag to signal initial conditions in buffers */ + int phaseIndex; /*!< Index for randomPase array */ + int prevTranEnv; /*!< The transient envelope of the previous frame. */ + + ULONG harmFlagsPrev[ADD_HARMONICS_FLAGS_SIZE]; + /*!< Words with 16 flags each indicating where a sine was added in the + * previous frame.*/ + UCHAR harmIndex; /*!< Current phase of synthetic sine */ + int sbrPatchingMode; /*!< Current patching mode */ + + FIXP_SGL prevSbrNoiseFloorLevel[MAX_NOISE_COEFFS]; + UCHAR prevNNfb; + UCHAR prevNSfb[2]; + UCHAR prevLoSubband; + UCHAR prevHiSubband; + UCHAR prev_ov_highSubband; + UCHAR *prevFreqBandTable[2]; + UCHAR prevFreqBandTableLo[MAX_FREQ_COEFFS / 2 + 1]; + UCHAR prevFreqBandTableHi[MAX_FREQ_COEFFS + 1]; + UCHAR prevFreqBandTableNoise[MAX_NOISE_COEFFS + 1]; + SCHAR sinusoidal_positionPrev; + ULONG harmFlagsPrevActive[ADD_HARMONICS_FLAGS_SIZE]; +} SBR_CALCULATE_ENVELOPE; typedef SBR_CALCULATE_ENVELOPE *HANDLE_SBR_CALCULATE_ENVELOPE; +void calculateSbrEnvelope( + QMF_SCALE_FACTOR *sbrScaleFactor, + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, + HANDLE_SBR_HEADER_DATA hHeaderData, HANDLE_SBR_FRAME_DATA hFrameData, + PVC_DYNAMIC_DATA *pPvcDynamicData, FIXP_DBL **analysBufferReal, + FIXP_DBL * + *analysBufferImag, /*!< Imag part of subband samples to be processed */ + const int useLP, + FIXP_DBL *degreeAlias, /*!< Estimated aliasing for each QMF channel */ + const UINT flags, const int frameErrorFlag); +SBR_ERROR +createSbrEnvelopeCalc(HANDLE_SBR_CALCULATE_ENVELOPE hSbrCalculateEnvelope, + HANDLE_SBR_HEADER_DATA hHeaderData, const int chan, + const UINT flags); + +int deleteSbrEnvelopeCalc(HANDLE_SBR_CALCULATE_ENVELOPE hSbrCalculateEnvelope); -void -calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, - HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, - HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_FRAME_DATA hFrameData, - FIXP_DBL **analysBufferReal, - FIXP_DBL **analysBufferImag, /*!< Imag part of subband samples to be processed */ - const int useLP, - FIXP_DBL *degreeAlias, /*!< Estimated aliasing for each QMF channel */ - const UINT flags, - const int frameErrorFlag - ); +void resetSbrEnvelopeCalc(HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv); SBR_ERROR -createSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hSbrCalculateEnvelope, - HANDLE_SBR_HEADER_DATA hHeaderData, - const int chan, - const UINT flags); +ResetLimiterBands(UCHAR *limiterBandTable, UCHAR *noLimiterBands, + UCHAR *freqBandTable, int noFreqBands, + const PATCH_PARAM *patchParam, int noPatches, + int limiterBands, UCHAR sbrPatchingMode, + int xOverQmf[MAX_NUM_PATCHES], int sbrRatio); -int -deleteSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hSbrCalculateEnvelope); +void rescaleSubbandSamples(FIXP_DBL **re, FIXP_DBL **im, int lowSubband, + int noSubbands, int start_pos, int next_pos, + int shift); -void -resetSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv); +FIXP_DBL maxSubbandSample(FIXP_DBL **analysBufferReal_m, + FIXP_DBL **analysBufferImag_m, int lowSubband, + int highSubband, int start_pos, int stop_pos); -SBR_ERROR -ResetLimiterBands ( UCHAR *limiterBandTable, - UCHAR *noLimiterBands, - UCHAR *freqBandTable, - int noFreqBands, - const PATCH_PARAM *patchParam, - int noPatches, - int limiterBands); - -void rescaleSubbandSamples( FIXP_DBL ** re, - FIXP_DBL ** im, - int lowSubband, int noSubbands, - int start_pos, int next_pos, - int shift); - -FIXP_DBL maxSubbandSample( FIXP_DBL ** analysBufferReal_m, - FIXP_DBL ** analysBufferImag_m, - int lowSubband, - int highSubband, - int start_pos, - int stop_pos); - -#endif // __ENV_CALC_H +#endif // ENV_CALC_H diff --git a/libSBRdec/src/env_dec.cpp b/libSBRdec/src/env_dec.cpp index c65c169..88c92cd 100644 --- a/libSBRdec/src/env_dec.cpp +++ b/libSBRdec/src/env_dec.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,13 +90,21 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief envelope decoding - This module provides envelope decoding and error concealment algorithms. The main - entry point is decodeSbrData(). + \brief envelope decoding + This module provides envelope decoding and error concealment algorithms. The + main entry point is decodeSbrData(). \sa decodeSbrData(),\ref documentationOverview */ @@ -97,43 +116,41 @@ amm-info@iis.fraunhofer.de #include "genericStds.h" - -static void decodeEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_FRAME_DATA h_sbr_data, - HANDLE_SBR_PREV_FRAME_DATA h_prev_data, - HANDLE_SBR_PREV_FRAME_DATA h_prev_data_otherChannel); -static void sbr_envelope_unmapping (HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_FRAME_DATA h_data_left, - HANDLE_SBR_FRAME_DATA h_data_right); -static void requantizeEnvelopeData (HANDLE_SBR_FRAME_DATA h_sbr_data, - int ampResolution); -static void deltaToLinearPcmEnvelopeDecoding (HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_FRAME_DATA h_sbr_data, - HANDLE_SBR_PREV_FRAME_DATA h_prev_data); -static void decodeNoiseFloorlevels (HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_FRAME_DATA h_sbr_data, - HANDLE_SBR_PREV_FRAME_DATA h_prev_data); -static void timeCompensateFirstEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_FRAME_DATA h_sbr_data, - HANDLE_SBR_PREV_FRAME_DATA h_prev_data); -static int checkEnvelopeData (HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_FRAME_DATA h_sbr_data, - HANDLE_SBR_PREV_FRAME_DATA h_prev_data); - - - -#define SBR_ENERGY_PAN_OFFSET (12 << ENV_EXP_FRACT) -#define SBR_MAX_ENERGY (35 << ENV_EXP_FRACT) - -#define DECAY ( 1 << ENV_EXP_FRACT) +static void decodeEnvelope(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data_otherChannel); +static void sbr_envelope_unmapping(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_data_left, + HANDLE_SBR_FRAME_DATA h_data_right); +static void requantizeEnvelopeData(HANDLE_SBR_FRAME_DATA h_sbr_data, + int ampResolution); +static void deltaToLinearPcmEnvelopeDecoding( + HANDLE_SBR_HEADER_DATA hHeaderData, HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data); +static void decodeNoiseFloorlevels(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data); +static void timeCompensateFirstEnvelope(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data); +static int checkEnvelopeData(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data); + +#define SBR_ENERGY_PAN_OFFSET (12 << ENV_EXP_FRACT) +#define SBR_MAX_ENERGY (35 << ENV_EXP_FRACT) + +#define DECAY (1 << ENV_EXP_FRACT) #if ENV_EXP_FRACT -#define DECAY_COUPLING ( 1 << (ENV_EXP_FRACT-1) ) /*!< corresponds to a value of 0.5 */ +#define DECAY_COUPLING \ + (1 << (ENV_EXP_FRACT - 1)) /*!< corresponds to a value of 0.5 */ #else -#define DECAY_COUPLING 1 /*!< If the energy data is not shifted, use 1 instead of 0.5 */ +#define DECAY_COUPLING \ + 1 /*!< If the energy data is not shifted, use 1 instead of 0.5 */ #endif - /*! \brief Convert table index */ @@ -141,29 +158,23 @@ static int indexLow2High(int offset, /*!< mapping factor */ int index, /*!< index to scalefactor band */ int res) /*!< frequency resolution */ { - if(res == 0) - { - if (offset >= 0) - { - if (index < offset) - return(index); - else - return(2*index - offset); - } - else - { - offset = -offset; - if (index < offset) - return(2*index+index); - else - return(2*index + offset); + if (res == 0) { + if (offset >= 0) { + if (index < offset) + return (index); + else + return (2 * index - offset); + } else { + offset = -offset; + if (index < offset) + return (2 * index + index); + else + return (2 * index + offset); } - } - else - return(index); + } else + return (index); } - /*! \brief Update previous envelope value for delta-coding @@ -173,115 +184,119 @@ static int indexLow2High(int offset, /*!< mapping factor */ low frequency resolution, the energy value will be mapped to the corresponding high-res bands. */ -static void mapLowResEnergyVal(FIXP_SGL currVal, /*!< current energy value */ - FIXP_SGL* prevData,/*!< pointer to previous data vector */ - int offset, /*!< mapping factor */ - int index, /*!< index to scalefactor band */ - int res) /*!< frequeny resolution */ +static void mapLowResEnergyVal( + FIXP_SGL currVal, /*!< current energy value */ + FIXP_SGL *prevData, /*!< pointer to previous data vector */ + int offset, /*!< mapping factor */ + int index, /*!< index to scalefactor band */ + int res) /*!< frequeny resolution */ { - if(res == 0) - { - if (offset >= 0) - { - if(index < offset) - prevData[index] = currVal; - else - { - prevData[2*index - offset] = currVal; - prevData[2*index+1 - offset] = currVal; - } - } - else - { - offset = -offset; - if (index < offset) - { - prevData[3*index] = currVal; - prevData[3*index+1] = currVal; - prevData[3*index+2] = currVal; - } - else - { - prevData[2*index + offset] = currVal; - prevData[2*index + 1 + offset] = currVal; - } + if (res == 0) { + if (offset >= 0) { + if (index < offset) + prevData[index] = currVal; + else { + prevData[2 * index - offset] = currVal; + prevData[2 * index + 1 - offset] = currVal; + } + } else { + offset = -offset; + if (index < offset) { + prevData[3 * index] = currVal; + prevData[3 * index + 1] = currVal; + prevData[3 * index + 2] = currVal; + } else { + prevData[2 * index + offset] = currVal; + prevData[2 * index + 1 + offset] = currVal; + } } - } - else + } else prevData[index] = currVal; } - - /*! \brief Convert raw envelope and noisefloor data to energy levels - This function is being called by sbrDecoder_ParseElement() and provides two important algorithms: + This function is being called by sbrDecoder_ParseElement() and provides two + important algorithms: - First the function decodes envelopes and noise floor levels as described in requantizeEnvelopeData() - and sbr_envelope_unmapping(). The function also implements concealment algorithms in case there are errors - within the sbr data. For both operations fractional arithmetic is used. - Therefore you might encounter different output values on your target - system compared to the reference implementation. + First the function decodes envelopes and noise floor levels as described in + requantizeEnvelopeData() and sbr_envelope_unmapping(). The function also + implements concealment algorithms in case there are errors within the sbr + data. For both operations fractional arithmetic is used. Therefore you might + encounter different output values on your target system compared to the + reference implementation. */ -void -decodeSbrData (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ - HANDLE_SBR_FRAME_DATA h_data_left, /*!< pointer to left channel frame data */ - HANDLE_SBR_PREV_FRAME_DATA h_prev_data_left, /*!< pointer to left channel previous frame data */ - HANDLE_SBR_FRAME_DATA h_data_right, /*!< pointer to right channel frame data */ - HANDLE_SBR_PREV_FRAME_DATA h_prev_data_right)/*!< pointer to right channel previous frame data */ +void decodeSbrData( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA + h_data_left, /*!< pointer to left channel frame data */ + HANDLE_SBR_PREV_FRAME_DATA + h_prev_data_left, /*!< pointer to left channel previous frame data */ + HANDLE_SBR_FRAME_DATA + h_data_right, /*!< pointer to right channel frame data */ + HANDLE_SBR_PREV_FRAME_DATA + h_prev_data_right) /*!< pointer to right channel previous frame data */ { FIXP_SGL tempSfbNrgPrev[MAX_FREQ_COEFFS]; int errLeft; - /* Save previous energy values to be able to reuse them later for concealment. */ - FDKmemcpy (tempSfbNrgPrev, h_prev_data_left->sfb_nrg_prev, MAX_FREQ_COEFFS * sizeof(FIXP_SGL)); + /* Save previous energy values to be able to reuse them later for concealment. + */ + FDKmemcpy(tempSfbNrgPrev, h_prev_data_left->sfb_nrg_prev, + MAX_FREQ_COEFFS * sizeof(FIXP_SGL)); - decodeEnvelope (hHeaderData, h_data_left, h_prev_data_left, h_prev_data_right); - decodeNoiseFloorlevels (hHeaderData, h_data_left, h_prev_data_left); + if (hHeaderData->frameErrorFlag || hHeaderData->bs_info.pvc_mode == 0) { + decodeEnvelope(hHeaderData, h_data_left, h_prev_data_left, + h_prev_data_right); + } else { + FDK_ASSERT(h_data_right == NULL); + } + decodeNoiseFloorlevels(hHeaderData, h_data_left, h_prev_data_left); - if(h_data_right != NULL) { + if (h_data_right != NULL) { errLeft = hHeaderData->frameErrorFlag; - decodeEnvelope (hHeaderData, h_data_right, h_prev_data_right, h_prev_data_left); - decodeNoiseFloorlevels (hHeaderData, h_data_right, h_prev_data_right); + decodeEnvelope(hHeaderData, h_data_right, h_prev_data_right, + h_prev_data_left); + decodeNoiseFloorlevels(hHeaderData, h_data_right, h_prev_data_right); if (!errLeft && hHeaderData->frameErrorFlag) { - /* If an error occurs in the right channel where the left channel seemed ok, - we apply concealment also on the left channel. This ensures that the coupling - modes of both channels match and that we have the same number of envelopes in - coupling mode. - However, as the left channel has already been processed before, the resulting - energy levels are not the same as if the left channel had been concealed - during the first call of decodeEnvelope(). + /* If an error occurs in the right channel where the left channel seemed + ok, we apply concealment also on the left channel. This ensures that + the coupling modes of both channels match and that we have the same + number of envelopes in coupling mode. However, as the left channel has + already been processed before, the resulting energy levels are not the + same as if the left channel had been concealed during the first call of + decodeEnvelope(). */ - /* Restore previous energy values for concealment, because the values have been - overwritten by the first call of decodeEnvelope(). */ - FDKmemcpy (h_prev_data_left->sfb_nrg_prev, tempSfbNrgPrev, MAX_FREQ_COEFFS * sizeof(FIXP_SGL)); + /* Restore previous energy values for concealment, because the values have + been overwritten by the first call of decodeEnvelope(). */ + FDKmemcpy(h_prev_data_left->sfb_nrg_prev, tempSfbNrgPrev, + MAX_FREQ_COEFFS * sizeof(FIXP_SGL)); /* Do concealment */ - decodeEnvelope (hHeaderData, h_data_left, h_prev_data_left, h_prev_data_right); + decodeEnvelope(hHeaderData, h_data_left, h_prev_data_left, + h_prev_data_right); } if (h_data_left->coupling) { - sbr_envelope_unmapping (hHeaderData, h_data_left, h_data_right); + sbr_envelope_unmapping(hHeaderData, h_data_left, h_data_right); } } /* Display the data for debugging: */ } - /*! \brief Convert from coupled channels to independent L/R data */ -static void -sbr_envelope_unmapping (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ - HANDLE_SBR_FRAME_DATA h_data_left, /*!< pointer to left channel */ - HANDLE_SBR_FRAME_DATA h_data_right) /*!< pointer to right channel */ +static void sbr_envelope_unmapping( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_data_left, /*!< pointer to left channel */ + HANDLE_SBR_FRAME_DATA h_data_right) /*!< pointer to right channel */ { int i; FIXP_SGL tempL_m, tempR_m, tempRplus1_m, newL_m, newR_m; - SCHAR tempL_e, tempR_e, tempRplus1_e, newL_e, newR_e; - + SCHAR tempL_e, tempR_e, tempRplus1_e, newL_e, newR_e; /* 1. Unmap (already dequantized) coupled envelope energies */ @@ -289,51 +304,53 @@ sbr_envelope_unmapping (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control tempR_m = (FIXP_SGL)((LONG)h_data_right->iEnvelope[i] & MASK_M); tempR_e = (SCHAR)((LONG)h_data_right->iEnvelope[i] & MASK_E); - tempR_e -= (18 + NRG_EXP_OFFSET); /* -18 = ld(UNMAPPING_SCALE / h_data_right->nChannels) */ + tempR_e -= (18 + NRG_EXP_OFFSET); /* -18 = ld(UNMAPPING_SCALE / + h_data_right->nChannels) */ tempL_m = (FIXP_SGL)((LONG)h_data_left->iEnvelope[i] & MASK_M); tempL_e = (SCHAR)((LONG)h_data_left->iEnvelope[i] & MASK_E); tempL_e -= NRG_EXP_OFFSET; /* Calculate tempRight+1 */ - FDK_add_MantExp( tempR_m, tempR_e, - FL2FXCONST_SGL(0.5f), 1, /* 1.0 */ - &tempRplus1_m, &tempRplus1_e); + FDK_add_MantExp(tempR_m, tempR_e, FL2FXCONST_SGL(0.5f), 1, /* 1.0 */ + &tempRplus1_m, &tempRplus1_e); - FDK_divide_MantExp( tempL_m, tempL_e+1, /* 2 * tempLeft */ - tempRplus1_m, tempRplus1_e, - &newR_m, &newR_e ); + FDK_divide_MantExp(tempL_m, tempL_e + 1, /* 2 * tempLeft */ + tempRplus1_m, tempRplus1_e, &newR_m, &newR_e); if (newR_m >= ((FIXP_SGL)MAXVAL_SGL - ROUNDING)) { newR_m >>= 1; newR_e += 1; } - newL_m = FX_DBL2FX_SGL(fMult(tempR_m,newR_m)); + newL_m = FX_DBL2FX_SGL(fMult(tempR_m, newR_m)); newL_e = tempR_e + newR_e; - h_data_right->iEnvelope[i] = ((FIXP_SGL)((SHORT)(FIXP_SGL)(newR_m + ROUNDING) & MASK_M)) + - (FIXP_SGL)((SHORT)(FIXP_SGL)(newR_e + NRG_EXP_OFFSET) & MASK_E); - h_data_left->iEnvelope[i] = ((FIXP_SGL)((SHORT)(FIXP_SGL)(newL_m + ROUNDING) & MASK_M)) + - (FIXP_SGL)((SHORT)(FIXP_SGL)(newL_e + NRG_EXP_OFFSET) & MASK_E); + h_data_right->iEnvelope[i] = + ((FIXP_SGL)((SHORT)(FIXP_SGL)(newR_m + ROUNDING) & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)(newR_e + NRG_EXP_OFFSET) & MASK_E); + h_data_left->iEnvelope[i] = + ((FIXP_SGL)((SHORT)(FIXP_SGL)(newL_m + ROUNDING) & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)(newL_e + NRG_EXP_OFFSET) & MASK_E); } /* 2. Dequantize and unmap coupled noise floor levels */ - for (i = 0; i < hHeaderData->freqBandData.nNfb * h_data_left->frameInfo.nNoiseEnvelopes; i++) { - + for (i = 0; i < hHeaderData->freqBandData.nNfb * + h_data_left->frameInfo.nNoiseEnvelopes; + i++) { tempL_e = (SCHAR)(6 - (LONG)h_data_left->sbrNoiseFloorLevel[i]); - tempR_e = (SCHAR)((LONG)h_data_right->sbrNoiseFloorLevel[i] - 12) /*SBR_ENERGY_PAN_OFFSET*/; + tempR_e = (SCHAR)((LONG)h_data_right->sbrNoiseFloorLevel[i] - + 12) /*SBR_ENERGY_PAN_OFFSET*/; /* Calculate tempR+1 */ - FDK_add_MantExp( FL2FXCONST_SGL(0.5f), 1+tempR_e, /* tempR */ - FL2FXCONST_SGL(0.5f), 1, /* 1.0 */ - &tempRplus1_m, &tempRplus1_e); + FDK_add_MantExp(FL2FXCONST_SGL(0.5f), 1 + tempR_e, /* tempR */ + FL2FXCONST_SGL(0.5f), 1, /* 1.0 */ + &tempRplus1_m, &tempRplus1_e); /* Calculate 2*tempLeft/(tempR+1) */ - FDK_divide_MantExp( FL2FXCONST_SGL(0.5f), tempL_e+2, /* 2 * tempLeft */ - tempRplus1_m, tempRplus1_e, - &newR_m, &newR_e ); + FDK_divide_MantExp(FL2FXCONST_SGL(0.5f), tempL_e + 2, /* 2 * tempLeft */ + tempRplus1_m, tempRplus1_e, &newR_m, &newR_e); /* if (newR_m >= ((FIXP_SGL)MAXVAL_SGL - ROUNDING)) { newR_m >>= 1; @@ -343,14 +360,15 @@ sbr_envelope_unmapping (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control /* L = tempR * R */ newL_m = newR_m; newL_e = newR_e + tempR_e; - h_data_right->sbrNoiseFloorLevel[i] = ((FIXP_SGL)((SHORT)(FIXP_SGL)(newR_m + ROUNDING) & MASK_M)) + - (FIXP_SGL)((SHORT)(FIXP_SGL)(newR_e + NOISE_EXP_OFFSET) & MASK_E); - h_data_left->sbrNoiseFloorLevel[i] = ((FIXP_SGL)((SHORT)(FIXP_SGL)(newL_m + ROUNDING) & MASK_M)) + - (FIXP_SGL)((SHORT)(FIXP_SGL)(newL_e + NOISE_EXP_OFFSET) & MASK_E); + h_data_right->sbrNoiseFloorLevel[i] = + ((FIXP_SGL)((SHORT)(FIXP_SGL)(newR_m + ROUNDING) & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)(newR_e + NOISE_EXP_OFFSET) & MASK_E); + h_data_left->sbrNoiseFloorLevel[i] = + ((FIXP_SGL)((SHORT)(FIXP_SGL)(newL_m + ROUNDING) & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)(newL_e + NOISE_EXP_OFFSET) & MASK_E); } } - /*! \brief Simple alternative to the real SBR concealment @@ -359,24 +377,23 @@ sbr_envelope_unmapping (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control The delta-coded energies are set to negative values, resulting in a fade-down. In case of coupling, the balance-channel will move towards the center. */ -static void -leanSbrConcealment(HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ - HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ - HANDLE_SBR_PREV_FRAME_DATA h_prev_data /*!< pointer to data of last frame */ - ) -{ - FIXP_SGL target; /* targeted level for sfb_nrg_prev during fade-down */ - FIXP_SGL step; /* speed of fade */ +static void leanSbrConcealment( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data /*!< pointer to data of last frame */ +) { + FIXP_SGL target; /* targeted level for sfb_nrg_prev during fade-down */ + FIXP_SGL step; /* speed of fade */ int i; - int currentStartPos = FDKmax(0, h_prev_data->stopPos - hHeaderData->numberTimeSlots); + int currentStartPos = + fMax(0, h_prev_data->stopPos - hHeaderData->numberTimeSlots); int currentStopPos = hHeaderData->numberTimeSlots; - /* Use some settings of the previous frame */ h_sbr_data->ampResolutionCurrentFrame = h_prev_data->ampRes; h_sbr_data->coupling = h_prev_data->coupling; - for(i=0;i<MAX_INVF_BANDS;i++) + for (i = 0; i < MAX_INVF_BANDS; i++) h_sbr_data->sbr_invf_mode[i] = h_prev_data->sbr_invf_mode[i]; /* Generate concealing control data */ @@ -385,7 +402,7 @@ leanSbrConcealment(HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control d h_sbr_data->frameInfo.borders[0] = currentStartPos; h_sbr_data->frameInfo.borders[1] = currentStopPos; h_sbr_data->frameInfo.freqRes[0] = 1; - h_sbr_data->frameInfo.tranEnv = -1; /* no transient */ + h_sbr_data->frameInfo.tranEnv = -1; /* no transient */ h_sbr_data->frameInfo.nNoiseEnvelopes = 1; h_sbr_data->frameInfo.bordersNoise[0] = currentStartPos; h_sbr_data->frameInfo.bordersNoise[1] = currentStopPos; @@ -399,17 +416,16 @@ leanSbrConcealment(HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control d if (h_sbr_data->coupling == COUPLING_BAL) { target = (FIXP_SGL)SBR_ENERGY_PAN_OFFSET; step = (FIXP_SGL)DECAY_COUPLING; - } - else { + } else { target = FL2FXCONST_SGL(0.0f); - step = (FIXP_SGL)DECAY; + step = (FIXP_SGL)DECAY; } if (hHeaderData->bs_info.ampResolution == 0) { target <<= 1; - step <<= 1; + step <<= 1; } - for (i=0; i < h_sbr_data->nScaleFactors; i++) { + for (i = 0; i < h_sbr_data->nScaleFactors; i++) { if (h_prev_data->sfb_nrg_prev[i] > target) h_sbr_data->iEnvelope[i] = -step; else @@ -419,123 +435,125 @@ leanSbrConcealment(HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control d /* Noisefloor levels are always cleared ... */ h_sbr_data->domain_vec_noise[0] = 1; - for (i=0; i < hHeaderData->freqBandData.nNfb; i++) + for (i = 0; i < hHeaderData->freqBandData.nNfb; i++) h_sbr_data->sbrNoiseFloorLevel[i] = FL2FXCONST_SGL(0.0f); /* ... and so are the sines */ - FDKmemclear(h_sbr_data->addHarmonics, MAX_FREQ_COEFFS); + FDKmemclear(h_sbr_data->addHarmonics, + sizeof(ULONG) * ADD_HARMONICS_FLAGS_SIZE); } - /*! \brief Build reference energies and noise levels from bitstream elements */ -static void -decodeEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ - HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ - HANDLE_SBR_PREV_FRAME_DATA h_prev_data, /*!< pointer to data of last frame */ - HANDLE_SBR_PREV_FRAME_DATA otherChannel /*!< other channel's last frame data */ - ) -{ +static void decodeEnvelope( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA + h_prev_data, /*!< pointer to data of last frame */ + HANDLE_SBR_PREV_FRAME_DATA + otherChannel /*!< other channel's last frame data */ +) { int i; int fFrameError = hHeaderData->frameErrorFlag; FIXP_SGL tempSfbNrgPrev[MAX_FREQ_COEFFS]; if (!fFrameError) { /* - To avoid distortions after bad frames, set the error flag if delta coding in time occurs. - However, SBR can take a little longer to come up again. + To avoid distortions after bad frames, set the error flag if delta coding + in time occurs. However, SBR can take a little longer to come up again. */ - if ( h_prev_data->frameErrorFlag ) { + if (h_prev_data->frameErrorFlag) { if (h_sbr_data->domain_vec[0] != 0) { fFrameError = 1; } } else { - /* Check that the previous stop position and the current start position match. - (Could be done in checkFrameInfo(), but the previous frame data is not available there) */ - if ( h_sbr_data->frameInfo.borders[0] != h_prev_data->stopPos - hHeaderData->numberTimeSlots ) { - /* Both the previous as well as the current frame are flagged to be ok, but they do not match! */ + /* Check that the previous stop position and the current start position + match. (Could be done in checkFrameInfo(), but the previous frame data + is not available there) */ + if (h_sbr_data->frameInfo.borders[0] != + h_prev_data->stopPos - hHeaderData->numberTimeSlots) { + /* Both the previous as well as the current frame are flagged to be ok, + * but they do not match! */ if (h_sbr_data->domain_vec[0] == 1) { - /* Prefer concealment over delta-time coding between the mismatching frames */ + /* Prefer concealment over delta-time coding between the mismatching + * frames */ fFrameError = 1; - } - else { - /* Close the gap in time by triggering timeCompensateFirstEnvelope() */ + } else { + /* Close the gap in time by triggering timeCompensateFirstEnvelope() + */ fFrameError = 1; } } } } + if (fFrameError) /* Error is detected */ + { + leanSbrConcealment(hHeaderData, h_sbr_data, h_prev_data); - if (fFrameError) /* Error is detected */ - { - leanSbrConcealment(hHeaderData, - h_sbr_data, - h_prev_data); - - /* decode the envelope data to linear PCM */ - deltaToLinearPcmEnvelopeDecoding (hHeaderData, h_sbr_data, h_prev_data); - } - else /*Do a temporary dummy decoding and check that the envelope values are within limits */ - { - if (h_prev_data->frameErrorFlag) { - timeCompensateFirstEnvelope (hHeaderData, h_sbr_data, h_prev_data); - if (h_sbr_data->coupling != h_prev_data->coupling) { - /* - Coupling mode has changed during concealment. - The stored energy levels need to be converted. - */ - for (i = 0; i < hHeaderData->freqBandData.nSfb[1]; i++) { - /* Former Level-Channel will be used for both channels */ - if (h_prev_data->coupling == COUPLING_BAL) - h_prev_data->sfb_nrg_prev[i] = otherChannel->sfb_nrg_prev[i]; - /* Former L/R will be combined as the new Level-Channel */ - else if (h_sbr_data->coupling == COUPLING_LEVEL) - h_prev_data->sfb_nrg_prev[i] = (h_prev_data->sfb_nrg_prev[i] + otherChannel->sfb_nrg_prev[i]) >> 1; - else if (h_sbr_data->coupling == COUPLING_BAL) - h_prev_data->sfb_nrg_prev[i] = (FIXP_SGL)SBR_ENERGY_PAN_OFFSET; - } + /* decode the envelope data to linear PCM */ + deltaToLinearPcmEnvelopeDecoding(hHeaderData, h_sbr_data, h_prev_data); + } else /*Do a temporary dummy decoding and check that the envelope values are + within limits */ + { + if (h_prev_data->frameErrorFlag) { + timeCompensateFirstEnvelope(hHeaderData, h_sbr_data, h_prev_data); + if (h_sbr_data->coupling != h_prev_data->coupling) { + /* + Coupling mode has changed during concealment. + The stored energy levels need to be converted. + */ + for (i = 0; i < hHeaderData->freqBandData.nSfb[1]; i++) { + /* Former Level-Channel will be used for both channels */ + if (h_prev_data->coupling == COUPLING_BAL) + h_prev_data->sfb_nrg_prev[i] = otherChannel->sfb_nrg_prev[i]; + /* Former L/R will be combined as the new Level-Channel */ + else if (h_sbr_data->coupling == COUPLING_LEVEL) + h_prev_data->sfb_nrg_prev[i] = (h_prev_data->sfb_nrg_prev[i] + + otherChannel->sfb_nrg_prev[i]) >> + 1; + else if (h_sbr_data->coupling == COUPLING_BAL) + h_prev_data->sfb_nrg_prev[i] = (FIXP_SGL)SBR_ENERGY_PAN_OFFSET; } } - FDKmemcpy (tempSfbNrgPrev, h_prev_data->sfb_nrg_prev, - MAX_FREQ_COEFFS * sizeof (FIXP_SGL)); + } + FDKmemcpy(tempSfbNrgPrev, h_prev_data->sfb_nrg_prev, + MAX_FREQ_COEFFS * sizeof(FIXP_SGL)); - deltaToLinearPcmEnvelopeDecoding (hHeaderData, h_sbr_data, h_prev_data); + deltaToLinearPcmEnvelopeDecoding(hHeaderData, h_sbr_data, h_prev_data); - fFrameError = checkEnvelopeData (hHeaderData, h_sbr_data, h_prev_data); + fFrameError = checkEnvelopeData(hHeaderData, h_sbr_data, h_prev_data); - if (fFrameError) - { - hHeaderData->frameErrorFlag = 1; - FDKmemcpy (h_prev_data->sfb_nrg_prev, tempSfbNrgPrev, - MAX_FREQ_COEFFS * sizeof (FIXP_SGL)); - decodeEnvelope (hHeaderData, h_sbr_data, h_prev_data, otherChannel); - return; - } + if (fFrameError) { + hHeaderData->frameErrorFlag = 1; + FDKmemcpy(h_prev_data->sfb_nrg_prev, tempSfbNrgPrev, + MAX_FREQ_COEFFS * sizeof(FIXP_SGL)); + decodeEnvelope(hHeaderData, h_sbr_data, h_prev_data, otherChannel); + return; } + } - requantizeEnvelopeData (h_sbr_data, h_sbr_data->ampResolutionCurrentFrame); + requantizeEnvelopeData(h_sbr_data, h_sbr_data->ampResolutionCurrentFrame); hHeaderData->frameErrorFlag = fFrameError; } - /*! \brief Verify that envelope energies are within the allowed range \return 0 if all is fine, 1 if an envelope value was too high */ -static int -checkEnvelopeData (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ - HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ - HANDLE_SBR_PREV_FRAME_DATA h_prev_data /*!< pointer to data of last frame */ - ) -{ +static int checkEnvelopeData( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data /*!< pointer to data of last frame */ +) { FIXP_SGL *iEnvelope = h_sbr_data->iEnvelope; FIXP_SGL *sfb_nrg_prev = h_prev_data->sfb_nrg_prev; - int i = 0, errorFlag = 0; - FIXP_SGL sbr_max_energy = - (h_sbr_data->ampResolutionCurrentFrame == 1) ? SBR_MAX_ENERGY : (SBR_MAX_ENERGY << 1); + int i = 0, errorFlag = 0; + FIXP_SGL sbr_max_energy = (h_sbr_data->ampResolutionCurrentFrame == 1) + ? SBR_MAX_ENERGY + : (SBR_MAX_ENERGY << 1); /* Range check for current energies @@ -561,7 +579,6 @@ checkEnvelopeData (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control d return (errorFlag); } - /*! \brief Verify that the noise levels are within the allowed range @@ -569,49 +586,55 @@ checkEnvelopeData (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control d When the noise-levels are being decoded, it is already too late for concealment. Therefore the noise levels are simply limited here. */ -static void -limitNoiseLevels(HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ - HANDLE_SBR_FRAME_DATA h_sbr_data) /*!< pointer to current data */ +static void limitNoiseLevels( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data) /*!< pointer to current data */ { int i; int nNfb = hHeaderData->freqBandData.nNfb; - /* - Set range limits. The exact values depend on the coupling mode. - However this limitation is primarily intended to avoid unlimited - accumulation of the delta-coded noise levels. - */ - #define lowerLimit ((FIXP_SGL)0) /* lowerLimit actually refers to the _highest_ noise energy */ - #define upperLimit ((FIXP_SGL)35) /* upperLimit actually refers to the _lowest_ noise energy */ +/* + Set range limits. The exact values depend on the coupling mode. + However this limitation is primarily intended to avoid unlimited + accumulation of the delta-coded noise levels. +*/ +#define lowerLimit \ + ((FIXP_SGL)0) /* lowerLimit actually refers to the _highest_ noise energy */ +#define upperLimit \ + ((FIXP_SGL)35) /* upperLimit actually refers to the _lowest_ noise energy */ /* Range check for current noise levels */ for (i = 0; i < h_sbr_data->frameInfo.nNoiseEnvelopes * nNfb; i++) { - h_sbr_data->sbrNoiseFloorLevel[i] = fixMin(h_sbr_data->sbrNoiseFloorLevel[i], upperLimit); - h_sbr_data->sbrNoiseFloorLevel[i] = fixMax(h_sbr_data->sbrNoiseFloorLevel[i], lowerLimit); + h_sbr_data->sbrNoiseFloorLevel[i] = + fixMin(h_sbr_data->sbrNoiseFloorLevel[i], upperLimit); + h_sbr_data->sbrNoiseFloorLevel[i] = + fixMax(h_sbr_data->sbrNoiseFloorLevel[i], lowerLimit); } } - /*! \brief Compensate for the wrong timing that might occur after a frame error. */ -static void -timeCompensateFirstEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ - HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to actual data */ - HANDLE_SBR_PREV_FRAME_DATA h_prev_data) /*!< pointer to data of last frame */ +static void timeCompensateFirstEnvelope( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to actual data */ + HANDLE_SBR_PREV_FRAME_DATA + h_prev_data) /*!< pointer to data of last frame */ { int i, nScalefactors; FRAME_INFO *pFrameInfo = &h_sbr_data->frameInfo; UCHAR *nSfb = hHeaderData->freqBandData.nSfb; - int estimatedStartPos = h_prev_data->stopPos - hHeaderData->numberTimeSlots; + int estimatedStartPos = + fMax(0, h_prev_data->stopPos - hHeaderData->numberTimeSlots); int refLen, newLen, shift; - FIXP_SGL deltaExp; + FIXP_SGL deltaExp; /* Original length of first envelope according to bitstream */ refLen = pFrameInfo->borders[1] - pFrameInfo->borders[0]; - /* Corrected length of first envelope (concealing can make the first envelope longer) */ + /* Corrected length of first envelope (concealing can make the first envelope + * longer) */ newLen = pFrameInfo->borders[1] - estimatedStartPos; if (newLen <= 0) { @@ -625,7 +648,8 @@ timeCompensateFirstEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static con deltaExp = FDK_getNumOctavesDiv8(newLen, refLen); /* Shift by -3 to rescale ld-table, ampRes-1 to enable coarser steps */ - shift = (FRACT_BITS - 1 - ENV_EXP_FRACT - 1 + h_sbr_data->ampResolutionCurrentFrame - 3); + shift = (FRACT_BITS - 1 - ENV_EXP_FRACT - 1 + + h_sbr_data->ampResolutionCurrentFrame - 3); deltaExp = deltaExp >> shift; pFrameInfo->borders[0] = estimatedStartPos; pFrameInfo->bordersNoise[0] = estimatedStartPos; @@ -638,8 +662,6 @@ timeCompensateFirstEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static con } } - - /*! \brief Convert each envelope value from logarithmic to linear domain @@ -660,9 +682,8 @@ timeCompensateFirstEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static con The data is then used in calculateSbrEnvelope(). */ -static void -requantizeEnvelopeData (HANDLE_SBR_FRAME_DATA h_sbr_data, int ampResolution) -{ +static void requantizeEnvelopeData(HANDLE_SBR_FRAME_DATA h_sbr_data, + int ampResolution) { int i; FIXP_SGL mantissa; int ampShift = 1 - ampResolution; @@ -672,16 +693,15 @@ requantizeEnvelopeData (HANDLE_SBR_FRAME_DATA h_sbr_data, int ampResolution) the initialization of this array has to be adapted! */ #if ENV_EXP_FRACT - static const FIXP_SGL pow2[ENV_EXP_FRACT] = - { - FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 1))), /* 0.7071 */ - FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 2))), /* 0.5946 */ - FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 3))), - FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 4))), - FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 5))), - FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 6))), - FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 7))), - FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 8))) /* 0.5013 */ + static const FIXP_SGL pow2[ENV_EXP_FRACT] = { + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 1))), /* 0.7071 */ + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 2))), /* 0.5946 */ + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 3))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 4))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 5))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 6))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 7))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 8))) /* 0.5013 */ }; int bit, mask; @@ -698,13 +718,13 @@ requantizeEnvelopeData (HANDLE_SBR_FRAME_DATA h_sbr_data, int ampResolution) /* Amplify mantissa according to the fractional part of the exponent (result will be between 0.500000 and 0.999999) */ - mask = 1; /* begin with lowest bit of exponent */ + mask = 1; /* begin with lowest bit of exponent */ - for ( bit=ENV_EXP_FRACT-1; bit>=0; bit-- ) { + for (bit = ENV_EXP_FRACT - 1; bit >= 0; bit--) { if (exponent & mask) { /* The current bit of the exponent is set, multiply mantissa with the corresponding factor: */ - mantissa = (FIXP_SGL)( (mantissa * pow2[bit]) << 1); + mantissa = (FIXP_SGL)((mantissa * pow2[bit]) << 1); } /* Advance to next bit */ mask = mask << 1; @@ -714,40 +734,43 @@ requantizeEnvelopeData (HANDLE_SBR_FRAME_DATA h_sbr_data, int ampResolution) exponent = exponent >> ENV_EXP_FRACT; #else - /* In case of the high amplitude resolution, 1 bit of the exponent gets lost by the shift. - This will be compensated by a mantissa of 0.5*sqrt(2) instead of 0.5 if that bit is 1. */ - mantissa = (exponent & ampShift) ? FL2FXCONST_SGL(0.707106781186548f) : FL2FXCONST_SGL(0.5f); + /* In case of the high amplitude resolution, 1 bit of the exponent gets lost + by the shift. This will be compensated by a mantissa of 0.5*sqrt(2) + instead of 0.5 if that bit is 1. */ + mantissa = (exponent & ampShift) ? FL2FXCONST_SGL(0.707106781186548f) + : FL2FXCONST_SGL(0.5f); exponent = exponent >> ampShift; #endif /* - Mantissa was set to 0.5 (instead of 1.0, therefore increase exponent by 1). - Multiply by L=nChannels=64 by increasing exponent by another 6. + Mantissa was set to 0.5 (instead of 1.0, therefore increase exponent by + 1). Multiply by L=nChannels=64 by increasing exponent by another 6. => Increase exponent by 7 */ exponent += 7 + NRG_EXP_OFFSET; /* Combine mantissa and exponent and write back the result */ - h_sbr_data->iEnvelope[i] = (FIXP_SGL)(((LONG)mantissa & MASK_M) | (exponent & MASK_E)); - + h_sbr_data->iEnvelope[i] = + ((FIXP_SGL)((SHORT)(FIXP_SGL)mantissa & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)exponent & MASK_E); } } - /*! \brief Build new reference energies from old ones and delta coded data */ -static void -deltaToLinearPcmEnvelopeDecoding (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ - HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ - HANDLE_SBR_PREV_FRAME_DATA h_prev_data) /*!< pointer to previous data */ +static void deltaToLinearPcmEnvelopeDecoding( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data) /*!< pointer to previous data */ { int i, domain, no_of_bands, band, freqRes; FIXP_SGL *sfb_nrg_prev = h_prev_data->sfb_nrg_prev; FIXP_SGL *ptr_nrg = h_sbr_data->iEnvelope; - int offset = 2 * hHeaderData->freqBandData.nSfb[0] - hHeaderData->freqBandData.nSfb[1]; + int offset = + 2 * hHeaderData->freqBandData.nSfb[0] - hHeaderData->freqBandData.nSfb[1]; for (i = 0; i < h_sbr_data->frameInfo.nEnvelopes; i++) { domain = h_sbr_data->domain_vec[i]; @@ -759,22 +782,18 @@ deltaToLinearPcmEnvelopeDecoding (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< S FDK_ASSERT(no_of_bands < (64)); - if (domain == 0) - { + if (domain == 0) { mapLowResEnergyVal(*ptr_nrg, sfb_nrg_prev, offset, 0, freqRes); ptr_nrg++; - for (band = 1; band < no_of_bands; band++) - { - *ptr_nrg = *ptr_nrg + *(ptr_nrg-1); + for (band = 1; band < no_of_bands; band++) { + *ptr_nrg = *ptr_nrg + *(ptr_nrg - 1); mapLowResEnergyVal(*ptr_nrg, sfb_nrg_prev, offset, band, freqRes); ptr_nrg++; } - } - else - { - for (band = 0; band < no_of_bands; band++) - { - *ptr_nrg = *ptr_nrg + sfb_nrg_prev[indexLow2High(offset, band, freqRes)]; + } else { + for (band = 0; band < no_of_bands; band++) { + *ptr_nrg = + *ptr_nrg + sfb_nrg_prev[indexLow2High(offset, band, freqRes)]; mapLowResEnergyVal(*ptr_nrg, sfb_nrg_prev, offset, band, freqRes); ptr_nrg++; } @@ -782,14 +801,13 @@ deltaToLinearPcmEnvelopeDecoding (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< S } } - /*! \brief Build new noise levels from old ones and delta coded data */ -static void -decodeNoiseFloorlevels (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ - HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ - HANDLE_SBR_PREV_FRAME_DATA h_prev_data) /*!< pointer to previous data */ +static void decodeNoiseFloorlevels( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data) /*!< pointer to previous data */ { int i; int nNfb = hHeaderData->freqBandData.nNfb; @@ -803,8 +821,7 @@ decodeNoiseFloorlevels (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static cont noiseLevel += h_sbr_data->sbrNoiseFloorLevel[i]; h_sbr_data->sbrNoiseFloorLevel[i] = noiseLevel; } - } - else { + } else { for (i = 0; i < nNfb; i++) { h_sbr_data->sbrNoiseFloorLevel[i] += h_prev_data->prevNoiseLevel[i]; } @@ -816,14 +833,14 @@ decodeNoiseFloorlevels (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static cont if (nNoiseFloorEnvelopes > 1) { if (h_sbr_data->domain_vec_noise[1] == 0) { FIXP_SGL noiseLevel = h_sbr_data->sbrNoiseFloorLevel[nNfb]; - for (i = nNfb + 1; i < 2*nNfb; i++) { + for (i = nNfb + 1; i < 2 * nNfb; i++) { noiseLevel += h_sbr_data->sbrNoiseFloorLevel[i]; h_sbr_data->sbrNoiseFloorLevel[i] = noiseLevel; } - } - else { + } else { for (i = 0; i < nNfb; i++) { - h_sbr_data->sbrNoiseFloorLevel[i + nNfb] += h_sbr_data->sbrNoiseFloorLevel[i]; + h_sbr_data->sbrNoiseFloorLevel[i + nNfb] += + h_sbr_data->sbrNoiseFloorLevel[i]; } } } @@ -832,21 +849,20 @@ decodeNoiseFloorlevels (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static cont /* Update prevNoiseLevel with the last noise envelope */ for (i = 0; i < nNfb; i++) - h_prev_data->prevNoiseLevel[i] = h_sbr_data->sbrNoiseFloorLevel[i + nNfb*(nNoiseFloorEnvelopes-1)]; - + h_prev_data->prevNoiseLevel[i] = + h_sbr_data->sbrNoiseFloorLevel[i + nNfb * (nNoiseFloorEnvelopes - 1)]; /* Requantize the noise floor levels in COUPLING_OFF-mode */ if (!h_sbr_data->coupling) { int nf_e; - for (i = 0; i < nNoiseFloorEnvelopes*nNfb; i++) { + for (i = 0; i < nNoiseFloorEnvelopes * nNfb; i++) { nf_e = 6 - (LONG)h_sbr_data->sbrNoiseFloorLevel[i] + 1 + NOISE_EXP_OFFSET; /* +1 to compensate for a mantissa of 0.5 instead of 1.0 */ h_sbr_data->sbrNoiseFloorLevel[i] = - (FIXP_SGL)( ((LONG)FL2FXCONST_SGL(0.5f)) + /* mantissa */ - (nf_e & MASK_E) ); /* exponent */ - + (FIXP_SGL)(((LONG)FL2FXCONST_SGL(0.5f)) + /* mantissa */ + (nf_e & MASK_E)); /* exponent */ } } } diff --git a/libSBRdec/src/env_dec.h b/libSBRdec/src/env_dec.h index 6f6dae3..0b11ce1 100644 --- a/libSBRdec/src/env_dec.h +++ b/libSBRdec/src/env_dec.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,23 +90,30 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief Envelope decoding + \brief Envelope decoding */ -#ifndef __ENV_DEC_H -#define __ENV_DEC_H +#ifndef ENV_DEC_H +#define ENV_DEC_H #include "sbrdecoder.h" #include "env_extr.h" -void decodeSbrData (HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_FRAME_DATA h_data_left, - HANDLE_SBR_PREV_FRAME_DATA h_prev_data_left, - HANDLE_SBR_FRAME_DATA h_data_right, - HANDLE_SBR_PREV_FRAME_DATA h_prev_data_right); - +void decodeSbrData(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_data_left, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data_left, + HANDLE_SBR_FRAME_DATA h_data_right, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data_right); #endif diff --git a/libSBRdec/src/env_extr.cpp b/libSBRdec/src/env_extr.cpp index 4d53a13..e6ae6dc 100644 --- a/libSBRdec/src/env_extr.cpp +++ b/libSBRdec/src/env_extr.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,47 +90,65 @@ Am Wolfsmantel 33 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. + \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. + 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(). + 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. + 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. + 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). + 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. + 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 */ @@ -130,60 +159,115 @@ amm-info@iis.fraunhofer.de #include "sbr_rom.h" #include "huff_dec.h" - #include "psbitdec.h" -#define DRM_PARAMETRIC_STEREO 0 -#define EXTENSION_ID_PS_CODING 2 - - -static int extractFrameInfo (HANDLE_FDK_BITSTREAM hBs, - HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_FRAME_DATA h_frame_data, - const UINT nrOfChannels, - const UINT flags - ); - - -static int sbrGetEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_FRAME_DATA h_frame_data, - HANDLE_FDK_BITSTREAM hBs, - const UINT flags); +#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; -static void sbrGetDirectionControlData (HANDLE_SBR_FRAME_DATA hFrameData, - HANDLE_FDK_BITSTREAM hBs); + if (!isUsac) { + mappingTable = stdSampleRatesMapping; + tableSize = sizeof(stdSampleRatesMapping) / sizeof(SR_MAPPING); + } else { + mappingTable = stdSampleRatesMappingUsac; + tableSize = sizeof(stdSampleRatesMappingUsac) / sizeof(SR_MAPPING); + } -static void sbrGetNoiseFloorData (HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_FRAME_DATA h_frame_data, - HANDLE_FDK_BITSTREAM hBs); + for (i = tableSize - 1; i >= 0; i--) { + if (fs >= mappingTable[i].fsRangeLo) { + fsMapped = mappingTable[i].fsMapped; + break; + } + } -static int checkFrameInfo (FRAME_INFO *pFrameInfo, int numberOfTimeSlots, int overlap, int timeStep); + return (fsMapped); +} SBR_ERROR -initHeaderData ( - HANDLE_SBR_HEADER_DATA hHeaderData, - const int sampleRateIn, - const int sampleRateOut, - const int samplesPerFrame, - const UINT flags - ) -{ +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 ( sampleRateIn == sampleRateOut ) { - hHeaderData->sbrProcSmplRate = sampleRateOut<<1; + 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 = sampleRateOut; - if ( (sampleRateOut>>1) == sampleRateIn) { + hHeaderData->sbrProcSmplRate = sampleRateProc; + if ((sampleRateOut >> 1) == sampleRateIn) { /* 1:2 */ numAnalysisBands = 32; - } else if ( (sampleRateOut>>2) == sampleRateIn ) { + } else if ((sampleRateOut >> 2) == sampleRateIn) { /* 1:4 */ - numAnalysisBands = 32; - } else if ( (sampleRateOut*3)>>3 == (sampleRateIn*8)>>3 ) { + numAnalysisBands = 16; + } else if ((sampleRateOut * 3) >> 3 == (sampleRateIn * 8) >> 3) { /* 3:8, 3/4 core frame length */ numAnalysisBands = 24; } else { @@ -191,74 +275,99 @@ initHeaderData ( 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; + } + } - /* Fill in default values first */ - hHeaderData->syncState = SBR_NOT_INITIALIZED; - hHeaderData->status = 0; - hHeaderData->frameErrorFlag = 0; - - hHeaderData->bs_info.ampResolution = 1; - hHeaderData->bs_info.xover_band = 0; - hHeaderData->bs_info.sbr_preprocessing = 0; - - hHeaderData->bs_data.startFreq = 5; - hHeaderData->bs_data.stopFreq = 0; - hHeaderData->bs_data.freqScale = 2; - hHeaderData->bs_data.alterScale = 1; - hHeaderData->bs_data.noise_bands = 2; - hHeaderData->bs_data.limiterBands = 2; - hHeaderData->bs_data.limiterGains = 2; - hHeaderData->bs_data.interpolFreq = 1; - hHeaderData->bs_data.smoothingLength = 1; - - hHeaderData->timeStep = (flags & SBRDEC_ELD_GRID) ? 1 : 2; + 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[0] = hFreq->freqBandTableLo; hFreq->freqBandTable[1] = hFreq->freqBandTableHi; - /* Patch some entries */ - if (sampleRateOut > 24000) { /* Trigger an error if SBR is going to be processed without */ - hHeaderData->bs_data.startFreq = 7; /* having read these frequency values from bit stream before. */ - hHeaderData->bs_data.stopFreq = 3; - } - - /* One SBR timeslot corresponds to the amount of samples equal to the amount of analysis bands, divided by the timestep. */ - hHeaderData->numberTimeSlots = (samplesPerFrame/numAnalysisBands) >> (hHeaderData->timeStep - 1); + /* 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 */ +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++) + 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++) + 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; + 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 @@ -266,74 +375,92 @@ initSbrPrevFrameData (HANDLE_SBR_PREV_FRAME_DATA h_prev_data, /*!< handle to str \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) -{ +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; + 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; + 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; } - { - hHeaderData->bs_info.ampResolution = FDKreadBits (hBs, 1); + 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); + pBsData->startFreq = FDKreadBits(hBs, 4); + pBsData->stopFreq = FDKreadBits(hBs, 4); - { - hHeaderData->bs_info.xover_band = FDKreadBits (hBs, 3); - FDKreadBits (hBs, 2); + 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); + 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; + 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->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) { + 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 */ } @@ -345,27 +472,45 @@ sbrGetHeaderData (HANDLE_SBR_HEADER_DATA hHeaderData, \return error status - 0 if ok */ -int -sbrGetSyntheticCodedData(HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_FRAME_DATA hFrameData, - HANDLE_FDK_BITSTREAM hBs) -{ +int sbrGetSyntheticCodedData(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA hFrameData, + HANDLE_FDK_BITSTREAM hBs, const UINT flags) { int i, bitsRead = 0; - int flag = FDKreadBits(hBs,1); + int add_harmonic_flag = FDKreadBits(hBs, 1); bitsRead++; - if(flag){ - for(i=0;i<hHeaderData->freqBandData.nSfb[1];i++){ - hFrameData->addHarmonics[i] = 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; } - else { - for(i=0; i<MAX_FREQ_COEFFS; i++) - hFrameData->addHarmonics[i] = 0; - } - return(bitsRead); + + return (bitsRead); } /*! @@ -377,16 +522,16 @@ sbrGetSyntheticCodedData(HANDLE_SBR_HEADER_DATA hHeaderData, 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 */ - ) { +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) { @@ -394,9 +539,7 @@ static int extractExtendedData( int bPsRead = 0; cnt = FDKreadBits(hBs, 4); - if (cnt == (1<<4)-1) - cnt += FDKreadBits(hBs, 8); - + if (cnt == (1 << 4) - 1) cnt += FDKreadBits(hBs, 8); nBitsLeft = 8 * cnt; @@ -412,52 +555,52 @@ static int extractExtendedData( int extension_id = FDKreadBits(hBs, 2); nBitsLeft -= 2; - switch(extension_id) { - - - + switch (extension_id) { case EXTENSION_ID_PS_CODING: - /* Read PS data from bitstream */ - - if (hParametricStereoDec != NULL) { - if(bPsRead && !hParametricStereoDec->bsData[hParametricStereoDec->bsReadSlot].mpeg.bPsHeaderValid) { - cnt = nBitsLeft >> 3; /* number of remaining bytes */ - for (i=0; i<cnt; i++) - FDKreadBits(hBs, 8); - nBitsLeft -= cnt * 8; - } else { - nBitsLeft -= ReadPsData(hParametricStereoDec, hBs, nBitsLeft); - bPsRead = 1; + /* 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 */ + /* 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; + /* "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 { + } else { /* Read fill bits for byte alignment */ FDKreadBits(hBs, nBitsLeft); } @@ -467,196 +610,208 @@ bail: return (frameOk); } - /*! - \brief Read bitstream elements of one channel - - \return SbrFrameOK: 1=ok, 0=error + \brief Read bitstream elements of a SBR channel element + \return SbrFrameOK */ -int -sbrGetSingleChannelElement (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ - HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ - HANDLE_FDK_BITSTREAM hBs, /*!< Handle to struct BIT_BUF */ - HANDLE_PS_DEC hParametricStereoDec, /*!< Handle to PS decoder */ - const UINT flags, - const int overlap - ) -{ - int i; - - - hFrameData->coupling = COUPLING_OFF; - - { +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 */ + if (FDKreadBits(hBs, 1)) { /* bs_data_extra */ FDKreadBits(hBs, 4); - if (flags & SBRDEC_SYNTAX_SCAL) { + if ((flags & SBRDEC_SYNTAX_SCAL) || (nCh == 2)) { FDKreadBits(hBs, 4); } } } - if (flags & SBRDEC_SYNTAX_SCAL) { - FDKreadBits (hBs, 1); /* bs_coupling */ - } - - /* - Grid control - */ - if ( !extractFrameInfo ( hBs, hHeaderData, hFrameData, 1, flags) ) - return 0; - - if ( !checkFrameInfo (&hFrameData->frameInfo, hHeaderData->numberTimeSlots, overlap, hHeaderData->timeStep) ) - return 0; - - - /* - Fetch domain vectors (time or frequency direction for delta-coding) - */ - sbrGetDirectionControlData (hFrameData, hBs); - - for (i=0; i<hHeaderData->freqBandData.nInvfBands; i++) { - hFrameData->sbr_invf_mode[i] = - (INVF_MODE) FDKreadBits (hBs, 2); - } - - - - /* raw data */ - if ( !sbrGetEnvelope (hHeaderData, hFrameData, hBs, flags) ) - return 0; - - - sbrGetNoiseFloorData (hHeaderData, hFrameData, hBs); - - sbrGetSyntheticCodedData(hHeaderData, hFrameData, hBs); - - { - /* sbr extended data */ - if (! extractExtendedData( - hHeaderData, - hBs - ,hParametricStereoDec - )) { - return 0; + 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; } - return 1; -} - - - -/*! - \brief Read bitstream elements of a channel pair - \return SbrFrameOK -*/ -int -sbrGetChannelPairElement (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ - HANDLE_SBR_FRAME_DATA hFrameDataLeft, /*!< Dynamic control data for first channel */ - HANDLE_SBR_FRAME_DATA hFrameDataRight,/*!< Dynamic control data for second channel */ - HANDLE_FDK_BITSTREAM hBs, /*!< handle to struct BIT_BUF */ - const UINT flags, - const int overlap ) -{ - int i, bit; - + 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; + } - /* Reserved bits */ - if (FDKreadBits(hBs, 1)) { /* bs_data_extra */ - FDKreadBits(hBs, 4); - FDKreadBits(hBs, 4); - } + 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; + } - /* Read coupling flag */ - bit = FDKreadBits (hBs, 1); + hFrameDataLeft->sbrPatchingMode = 1; + hFrameDataLeft->sbrOversamplingFlag = 0; + hFrameDataLeft->sbrPitchInBins = 0; + } + } else { + if (nCh == 2) { + hFrameDataRight->sbrPatchingMode = 1; + hFrameDataRight->sbrOversamplingFlag = 0; + hFrameDataRight->sbrPitchInBins = 0; + } - if (bit) { - hFrameDataLeft->coupling = COUPLING_LEVEL; - hFrameDataRight->coupling = COUPLING_BAL; - } - else { - hFrameDataLeft->coupling = COUPLING_OFF; - hFrameDataRight->coupling = COUPLING_OFF; + hFrameDataLeft->sbrPatchingMode = 1; + hFrameDataLeft->sbrOversamplingFlag = 0; + hFrameDataLeft->sbrPitchInBins = 0; } - /* - Grid control + sbr_grid(): Grid control */ - if ( !extractFrameInfo (hBs, hHeaderData, hFrameDataLeft, 2, flags) ) - return 0; - - if ( !checkFrameInfo (&hFrameDataLeft->frameInfo, hHeaderData->numberTimeSlots, overlap, hHeaderData->timeStep) ) - return 0; + 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 (hFrameDataLeft->coupling) { - FDKmemcpy (&hFrameDataRight->frameInfo, &hFrameDataLeft->frameInfo, sizeof(FRAME_INFO)); - hFrameDataRight->ampResolutionCurrentFrame = hFrameDataLeft->ampResolutionCurrentFrame; - } - else { - if ( !extractFrameInfo (hBs, hHeaderData, hFrameDataRight, 2, flags) ) + if (!checkFrameInfo(&hFrameDataLeft->frameInfo, + hHeaderData->numberTimeSlots, overlap, + hHeaderData->timeStep)) return 0; + } else { + if (!extractFrameInfo(hBs, hHeaderData, hFrameDataLeft, 1, flags)) return 0; - if ( !checkFrameInfo (&hFrameDataRight->frameInfo, hHeaderData->numberTimeSlots, overlap, hHeaderData->timeStep) ) + 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; + } + } /* - Fetch domain vectors (time or frequency direction for delta-coding) + sbr_dtdf(): Fetch domain vectors (time or frequency direction for + delta-coding) */ - sbrGetDirectionControlData (hFrameDataLeft, hBs); - sbrGetDirectionControlData (hFrameDataRight, hBs); - - for (i=0; i<hHeaderData->freqBandData.nInvfBands; i++) { - hFrameDataLeft->sbr_invf_mode[i] = (INVF_MODE) FDKreadBits (hBs, 2); + sbrGetDirectionControlData(hFrameDataLeft, hBs, flags, + hHeaderData->bs_info.pvc_mode); + if (nCh == 2) { + sbrGetDirectionControlData(hFrameDataRight, hBs, flags, 0); } - if (hFrameDataLeft->coupling) { - for (i=0; i<hHeaderData->freqBandData.nInvfBands; i++) { - hFrameDataRight->sbr_invf_mode[i] = hFrameDataLeft->sbr_invf_mode[i]; + /* 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; - if ( !sbrGetEnvelope (hHeaderData, hFrameDataLeft, hBs, flags) ) { + sbrGetNoiseFloorData(hHeaderData, hFrameDataLeft, hBs); + } else if (hFrameDataLeft->coupling) { + if (!sbrGetEnvelope(hHeaderData, hFrameDataLeft, hBs, flags)) { return 0; } - sbrGetNoiseFloorData (hHeaderData, hFrameDataLeft, hBs); + sbrGetNoiseFloorData(hHeaderData, hFrameDataLeft, hBs); - if ( !sbrGetEnvelope (hHeaderData, hFrameDataRight, hBs, flags) ) { + if (!sbrGetEnvelope(hHeaderData, hFrameDataRight, hBs, flags)) { return 0; } - } - else { - - for (i=0; i<hHeaderData->freqBandData.nInvfBands; i++) { - hFrameDataRight->sbr_invf_mode[i] = (INVF_MODE) FDKreadBits (hBs, 2); - } - + sbrGetNoiseFloorData(hHeaderData, hFrameDataRight, hBs); + } else { /* nCh == 2 && no coupling */ + if (!sbrGetEnvelope(hHeaderData, hFrameDataLeft, hBs, flags)) return 0; - if ( !sbrGetEnvelope (hHeaderData, hFrameDataLeft, hBs, flags) ) - return 0; + if (!sbrGetEnvelope(hHeaderData, hFrameDataRight, hBs, flags)) return 0; - if ( !sbrGetEnvelope (hHeaderData, hFrameDataRight, hBs, flags) ) - return 0; - - sbrGetNoiseFloorData (hHeaderData, hFrameDataLeft, hBs); + sbrGetNoiseFloorData(hHeaderData, hFrameDataLeft, hBs); + sbrGetNoiseFloorData(hHeaderData, hFrameDataRight, hBs); } - sbrGetNoiseFloorData (hHeaderData, hFrameDataRight, hBs); - sbrGetSyntheticCodedData(hHeaderData, hFrameDataLeft, hBs); - sbrGetSyntheticCodedData(hHeaderData, hFrameDataRight, hBs); + sbrGetSyntheticCodedData(hHeaderData, hFrameDataLeft, hBs, flags); + if (nCh == 2) { + sbrGetSyntheticCodedData(hHeaderData, hFrameDataRight, hBs, flags); + } - { - if (! extractExtendedData( - hHeaderData, - hBs - ,NULL - ) ) { + if (!(flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50))) { + if (!extractExtendedData(hHeaderData, hBs, hParametricStereoDec)) { return 0; } } @@ -664,38 +819,50 @@ sbrGetChannelPairElement (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static con 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 */ +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; - for (i = 0; i < h_frame_data->frameInfo.nEnvelopes; i++) { - h_frame_data->domain_vec[i] = FDKreadBits (hBs, 1); + if (flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) { + indepFlag = flags & SBRDEC_USAC_INDEP; } - for (i = 0; i < h_frame_data->frameInfo.nNoiseEnvelopes; i++) { - h_frame_data->domain_vec_noise[i] = FDKreadBits (hBs, 1); + 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 */ +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 i, j; int delta; COUPLING_MODE coupling; int noNoiseBands = hHeaderData->freqBandData.nNfb; @@ -706,61 +873,157 @@ sbrGetNoiseFloorData (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control d 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" */ + hcb_noiseF = + (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11F; /* "sbr_huffBook_NoiseBalance11F" + */ envDataTableCompFactor = 1; - } - else { + } else { hcb_noise = (Huffman)&FDK_sbrDecoder_sbr_huffBook_NoiseLevel11T; - hcb_noiseF = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel11F; /* "sbr_huffBook_NoiseLevel11F" */ + 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++) { - - + 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); + 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); + h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands + j] = + (FIXP_SGL)(delta << envDataTableCompFactor); } - } - else { + } else { for (j = 0; j < noNoiseBands; j++) { delta = DecodeHuffmanCW(hcb_noise, hBs); - h_frame_data->sbrNoiseFloorLevel[i*noNoiseBands+j] = (FIXP_SGL) (delta << envDataTableCompFactor); + 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) -{ +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; @@ -774,7 +1037,7 @@ sbrGetEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ h_frame_data->nScaleFactors = 0; - if ( (h_frame_data->frameInfo.frameClass == 0) && (nEnvelopes == 1) ) { + if ((h_frame_data->frameInfo.frameClass == 0) && (nEnvelopes == 1)) { if (flags & SBRDEC_ELD_GRID) ampRes = h_frame_data->ampResolutionCurrentFrame; else @@ -785,13 +1048,10 @@ sbrGetEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ /* Set number of bits for first value depending on amplitude resolution */ - if(ampRes == 1) - { + if (ampRes == 1) { start_bits = 6; start_bits_balance = 5; - } - else - { + } else { start_bits = 7; start_bits_balance = 6; } @@ -800,11 +1060,11 @@ sbrGetEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ 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]]; + 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; + if (h_frame_data->nScaleFactors > MAX_NUM_ENVELOPE_VALUES) return 0; /* Select Huffman codebook depending on coupling mode and amplitude resolution @@ -814,57 +1074,64 @@ sbrGetEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ if (ampRes == 0) { hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance10T; hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance10F; - } - else { + } else { hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11T; hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11F; } - } - else { + } else { envDataTableCompFactor = 0; if (ampRes == 0) { hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel10T; hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel10F; - } - else { + } 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 { + (FIXP_SGL)(((int)FDKreadBits(hBs, start_bits_balance)) + << envDataTableCompFactor); + } else { h_frame_data->iEnvelope[offset] = - (FIXP_SGL) (int)FDKreadBits (hBs, start_bits); + (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 { + } else { delta = DecodeHuffmanCW(hcb_t, hBs); } - h_frame_data->iEnvelope[offset + i] = (FIXP_SGL) (delta << envDataTableCompFactor); + 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) */ + /* 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; } @@ -873,61 +1140,53 @@ sbrGetEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ return 1; } - -//static const FRAME_INFO v_frame_info1_8 = { 0, 1, {0, 8}, {1}, -1, 1, {0, 8} }; -static const FRAME_INFO v_frame_info2_8 = { 0, 2, {0, 4, 8}, {1, 1}, -1, 2, {0, 4, 8} }; -static const FRAME_INFO v_frame_info4_8 = { 0, 4, {0, 2, 4, 6, 8}, {1, 1, 1, 1}, -1, 2, {0, 4, 8} }; - /***************************************************************************/ /*! - \brief Generates frame info for FIXFIXonly frame class used for low delay version + \brief Generates frame info for FIXFIXonly frame class used for low delay + version \return nothing ****************************************************************************/ - static void generateFixFixOnly ( FRAME_INFO *hSbrFrameInfo, - int tranPosInternal, - int numberTimeSlots - ) -{ - int nEnv, i, tranIdx; - const int *pTable; +static void generateFixFixOnly(FRAME_INFO *hSbrFrameInfo, int tranPosInternal, + int numberTimeSlots, const UINT flags) { + int nEnv, i, tranIdx; + const int *pTable; - switch (numberTimeSlots) { - case 8: - pTable = FDK_sbrDecoder_envelopeTable_8[tranPosInternal]; - break; - case 15: - pTable = FDK_sbrDecoder_envelopeTable_15[tranPosInternal]; - break; - case 16: - pTable = FDK_sbrDecoder_envelopeTable_16[tranPosInternal]; - break; - default: - FDK_ASSERT(0); - /* in case assertion checks are disabled, force a definite memory fault at first access */ - pTable = NULL; - break; - } + switch (numberTimeSlots) { + case 8: + pTable = FDK_sbrDecoder_envelopeTable_8[tranPosInternal]; + break; + case 15: + pTable = FDK_sbrDecoder_envelopeTable_15[tranPosInternal]; + break; + default: + FDK_ASSERT(0); + /* fall through */ + case 16: + pTable = FDK_sbrDecoder_envelopeTable_16[tranPosInternal]; + break; + } - /* 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; + /* 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; } /*! @@ -935,356 +1194,431 @@ static const FRAME_INFO v_frame_info4_8 = { 0, 4, {0, 2, 4, 6, 8}, {1, 1, 1, 1}, \return zero for bitstream error, one for correct. */ -static int -extractLowDelayGrid (HANDLE_FDK_BITSTREAM hBitBuf, /*!< bitbuffer handle */ - HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_FRAME_DATA h_frame_data, /*!< contains the FRAME_INFO struct to be filled */ - int timeSlots - ) -{ - FRAME_INFO * pFrameInfo = &h_frame_data->frameInfo; +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; + /* 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; + /* 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; + case 16: + case 15: + /* 4bit transient position (temp={0;..;15}) */ + temp = FDKreadBits(hBitBuf, 4); + break; - default: - return 0; - } + default: + return 0; + } - /* calculate borders according to the transient position */ - generateFixFixOnly ( pFrameInfo, - temp, - numberTimeSlots - ); + /* For "case 15" only*/ + if (temp >= timeSlots) { + return 0; + } - /* decode freq res: */ - for (k = 0; k < pFrameInfo->nEnvelopes; k++) { - pFrameInfo->freqRes[k] = (UCHAR) FDKreadBits (hBitBuf, 1); /* f = F [1 bits] */ - } + /* calculate borders according to the transient position */ + generateFixFixOnly(pFrameInfo, temp, numberTimeSlots, flags); + /* decode freq res: */ + for (k = 0; k < pFrameInfo->nEnvelopes; k++) { + pFrameInfo->freqRes[k] = + (UCHAR)FDKreadBits(hBitBuf, 1); /* f = F [1 bits] */ + } return 1; } /*! - \brief Extract the frame information (structure FRAME_INFO) from the bitstream - \return Zero for bitstream error, one for correct. + \brief Extract the PVC 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; +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 (flags & SBRDEC_ELD_GRID) { - /* CODEC_AACLD (LD+SBR) only uses the normal 0 Grid for non-transient Frames and the LowDelayGrid for transient Frames */ - frameClass = FDKreadBits (hBs, 1); /* frameClass = [1 bit] */ - if ( frameClass == 1 ) { - /* if frameClass == 1, extract LowDelaySbrGrid, otherwise extract normal SBR-Grid for FIXIFX */ - /* extract the AACLD-Sbr-Grid */ - pFrameInfo->frameClass = frameClass; - extractLowDelayGrid (hBs, hHeaderData, h_frame_data, numberTimeSlots); - return 1; - } - } else - { - frameClass = FDKreadBits (hBs, 2); /* frameClass = C [2 bits] */ + 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. + */ - switch (frameClass) { - case 0: - temp = FDKreadBits (hBs, 2); /* E [2 bits ] */ - nEnv = (int) (1 << temp); /* E -> e */ + FDK_ASSERT((pFrameInfo->nEnvelopes == 1) || (pFrameInfo->nEnvelopes == 2)); - if ((flags & SBRDEC_ELD_GRID) && (nEnv == 1)) - h_frame_data->ampResolutionCurrentFrame = FDKreadBits( hBs, 1); /* new ELD Syntax 07-11-09 */ + /* 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; + } - staticFreqRes = FDKreadBits (hBs, 1); + /* right timeborder-offset: */ + pFrameInfo->borders[pFrameInfo->nEnvelopes] = 16 + pFrameInfo->varLength; - { - if (nEnv > MAX_ENVELOPES_HEAAC) - return 0; + if (pFrameInfo->nEnvelopes == 2) { + pFrameInfo->borders[1] = pFrameInfo->noisePosition; } - 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; + /* 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; } - - 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; + if (pFrameInfo->nEnvelopes == 2) { + pFrameInfo->pvcBorders[1] = pFrameInfo->borders[1]; } + pFrameInfo->pvcBorders[pFrameInfo->nEnvelopes] = 16; - - /* 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] */ + /* 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; +} - /* 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 */ +/*! + \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; - for (k = 1; k <= n; k++) { - temp = FDKreadBits (hBs, 2);/* R [2 bits] */ - border += (2 * temp + 2); /* R -> r */ - pFrameInfo->borders[k] = border; + 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; } - 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; - + } 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; + } - /* Decode freq res: */ - for (k = 0; k <= n; k++) { - pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */ - } + 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 */ - /* 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; + 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; + } - case 3: - /* v_ctrlSignal = [frameClass,aL,aR,nL,nR,v_rL,v_rR,p,v_fLR]; */ + /* Decode pointer: */ + pointer_bits = DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(n + 1)); + p = FDKreadBits(hBs, pointer_bits); /* p = P [pointer_bits bits] */ - aL = FDKreadBits (hBs, 2); /* AL [2 bits], AL -> aL */ + if (p > n + 1) return 0; - aR = FDKreadBits (hBs, 2) + numberTimeSlots; /* AR [2 bits], AR -> aR */ + pFrameInfo->tranEnv = p ? n + 2 - p : -1; - nL = FDKreadBits (hBs, 2); /* nL = NL [2 bits] */ + /* Decode freq res: */ + for (k = n; k >= 0; k--) { + pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */ + } - nR = FDKreadBits (hBs, 2); /* nR = NR [2 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 */ - /*------------------------------------------------------------------------- - Calculate help variables - --------------------------------------------------------------------------*/ + /* 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; - /* general: */ - nEnv = nL + nR + 1; /* # envelopes */ - if (nEnv > MAX_ENVELOPES) - return 0; - b = nEnv + 1; /* # borders */ + 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; + } - /*------------------------------------------------------------------------- - Decode envelopes - --------------------------------------------------------------------------*/ + break; + case 3: + /* v_ctrlSignal = [frameClass,aL,aR,nL,nR,v_rL,v_rR,p,v_fLR]; */ - /* L-borders: */ - border = aL; /* first border */ - pFrameInfo->borders[0] = border; + aL = FDKreadBits(hBs, 2); /* AL [2 bits], AL -> aL */ - for (k = 1; k <= nL; k++) { - temp = FDKreadBits (hBs, 2);/* R [2 bits] */ - border += (2 * temp + 2); /* R -> r */ - pFrameInfo->borders[k] = border; - } + aR = FDKreadBits(hBs, 2) + numberTimeSlots; /* AR [2 bits], AR -> aR */ + nL = FDKreadBits(hBs, 2); /* nL = NL [2 bits] */ - /* R-borders: */ - border = aR; /* last border */ - i = nEnv; + nR = FDKreadBits(hBs, 2); /* nR = NR [2 bits] */ - pFrameInfo->borders[i] = border; + /*------------------------------------------------------------------------- + Calculate help variables + --------------------------------------------------------------------------*/ - for (k = 0; k < nR; k++) { - temp = FDKreadBits (hBs, 2);/* R [2 bits] */ - border -= (2 * temp + 2); /* R -> r */ - pFrameInfo->borders[--i] = border; - } + /* general: */ + nEnv = nL + nR + 1; /* # envelopes */ + if (nEnv > MAX_ENVELOPES) return 0; + b = nEnv + 1; /* # borders */ + /*------------------------------------------------------------------------- + Decode envelopes + --------------------------------------------------------------------------*/ - /* decode pointer: */ - pointer_bits = DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(nL+nR+1)); - p = FDKreadBits (hBs, pointer_bits); /* p = P [pointer_bits bits] */ + /* L-borders: */ + border = aL; /* first border */ + pFrameInfo->borders[0] = border; - if (p > nL+nR+1) - return 0; + for (k = 1; k <= nL; k++) { + temp = FDKreadBits(hBs, 2); /* R [2 bits] */ + border += (2 * temp + 2); /* R -> r */ + pFrameInfo->borders[k] = border; + } - pFrameInfo->tranEnv = p ? b - p : -1; + /* 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 freq res: */ - for (k = 0; k < nEnv; k++) { - pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */ - } + /* 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 noise floors - --------------------------------------------------------------------------*/ - pFrameInfo->bordersNoise[0] = aL; + /* decode freq res: */ + for (k = 0; k < nEnv; k++) { + pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */ + } - 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; + /*------------------------------------------------------------------------- + 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 */ @@ -1300,25 +1634,24 @@ extractFrameInfo ( HANDLE_FDK_BITSTREAM hBs, /*!< bitbuffer handle */ 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]; + 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 */ +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 maxPos, i, j; int startPos; int stopPos; int tranEnv; @@ -1327,71 +1660,65 @@ checkFrameInfo (FRAME_INFO * pFrameInfo, /*!< pointer to frameInfo */ int nEnvelopes = pFrameInfo->nEnvelopes; int nNoiseEnvelopes = pFrameInfo->nNoiseEnvelopes; - if(nEnvelopes < 1 || nEnvelopes > MAX_ENVELOPES) - return 0; + if (nEnvelopes < 1 || nEnvelopes > MAX_ENVELOPES) return 0; - if(nNoiseEnvelopes > MAX_NOISE_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]; + startPos = pFrameInfo->borders[0]; + stopPos = pFrameInfo->borders[nEnvelopes]; + tranEnv = pFrameInfo->tranEnv; + startPosNoise = pFrameInfo->bordersNoise[0]; + stopPosNoise = pFrameInfo->bordersNoise[nNoiseEnvelopes]; - if (overlap < 0 || overlap > (6)) { + if (overlap < 0 || overlap > (3 * (4))) { return 0; } - if (timeStep < 1 || timeStep > 2) { + 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 */ + 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) + 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 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; - + if (tranEnv > nEnvelopes) return 0; /* Check the noise borders */ - if(nEnvelopes==1 && nNoiseEnvelopes>1) - return 0; - - if(startPos != startPosNoise || stopPos != stopPosNoise) - return 0; + 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]) + /* 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++) { + for (i = 0; i < nNoiseEnvelopes; i++) { startPosNoise = pFrameInfo->bordersNoise[i]; - for(j=0; j<nEnvelopes; j++) { - if(pFrameInfo->borders[j] == startPosNoise) - break; + for (j = 0; j < nEnvelopes; j++) { + if (pFrameInfo->borders[j] == startPosNoise) break; } - if(j==nEnvelopes) - return 0; + if (j == nEnvelopes) return 0; } return 1; diff --git a/libSBRdec/src/env_extr.h b/libSBRdec/src/env_extr.h index 0518ea9..38c04a3 100644 --- a/libSBRdec/src/env_extr.h +++ b/libSBRdec/src/env_extr.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,15 +90,23 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief Envelope extraction prototypes + \brief Envelope extraction prototypes */ -#ifndef __ENVELOPE_EXTRACTION_H -#define __ENVELOPE_EXTRACTION_H +#ifndef ENV_EXTR_H +#define ENV_EXTR_H #include "sbrdecoder.h" @@ -95,6 +114,7 @@ amm-info@iis.fraunhofer.de #include "lpp_tran.h" #include "psdec.h" +#include "pvc_dec.h" #define ENV_EXP_FRACT 0 /*!< Shift raw envelope data to support fractional numbers. @@ -104,208 +124,278 @@ amm-info@iis.fraunhofer.de */ #define EXP_BITS 6 -/*!< Size of exponent-part of a pseudo float envelope value (should be at least 6). - The remaining bits in each word are used for the mantissa (should be at least 10). - This format is used in the arrays iEnvelope[] and sbrNoiseFloorLevel[] - in the FRAME_DATA struct which must fit in a certain part of the output buffer - (See buffer management in sbr_dec.cpp). - Exponents and mantissas could also be stored in separate arrays. - Accessing the exponent or the mantissa would be simplified and the masks #MASK_E - resp. #MASK_M would no longer be required. +/*!< Size of exponent-part of a pseudo float envelope value (should be at least + 6). The remaining bits in each word are used for the mantissa (should be at + least 10). This format is used in the arrays iEnvelope[] and + sbrNoiseFloorLevel[] in the FRAME_DATA struct which must fit in a certain part + of the output buffer (See buffer management in sbr_dec.cpp). Exponents and + mantissas could also be stored in separate arrays. Accessing the exponent or + the mantissa would be simplified and the masks #MASK_E resp. #MASK_M would + no longer be required. */ -#define MASK_M (((1 << (FRACT_BITS - EXP_BITS)) - 1) << EXP_BITS) /*!< Mask for extracting the mantissa of a pseudo float envelope value */ -#define MASK_E ((1 << EXP_BITS) - 1) /*!< Mask for extracting the exponent of a pseudo float envelope value */ - -#define SIGN_EXT ( ((SCHAR)-1) ^ MASK_E) /*!< a CHAR-constant with all bits above our sign-bit set */ -#define ROUNDING ( (FIXP_SGL)(1<<(EXP_BITS-1)) ) /*!< 0.5-offset for rounding the mantissa of a pseudo-float envelope value */ -#define NRG_EXP_OFFSET 16 /*!< Will be added to the reference energy's exponent to prevent negative numbers */ -#define NOISE_EXP_OFFSET 38 /*!< Will be added to the noise level exponent to prevent negative numbers */ - -typedef enum -{ +#define MASK_M \ + (((1 << (FRACT_BITS - EXP_BITS)) - 1) \ + << EXP_BITS) /*!< Mask for extracting the mantissa of a pseudo float \ + envelope value */ +#define MASK_E \ + ((1 << EXP_BITS) - 1) /*!< Mask for extracting the exponent of a pseudo \ + float envelope value */ + +#define SIGN_EXT \ + (((SCHAR)-1) ^ \ + MASK_E) /*!< a CHAR-constant with all bits above our sign-bit set */ +#define ROUNDING \ + ((FIXP_SGL)( \ + 1 << (EXP_BITS - 1))) /*!< 0.5-offset for rounding the mantissa of a \ + pseudo-float envelope value */ +#define NRG_EXP_OFFSET \ + 16 /*!< Will be added to the reference energy's exponent to prevent negative \ + numbers */ +#define NOISE_EXP_OFFSET \ + 38 /*!< Will be added to the noise level exponent to prevent negative \ + numbers */ + +#define ADD_HARMONICS_FLAGS_SIZE 2 /* ceil(MAX_FREQ_COEFFS/32) */ + +typedef enum { HEADER_NOT_PRESENT, HEADER_ERROR, HEADER_OK, HEADER_RESET -} -SBR_HEADER_STATUS; +} SBR_HEADER_STATUS; -typedef enum -{ +typedef enum { SBR_NOT_INITIALIZED = 0, UPSAMPLING = 1, SBR_HEADER = 2, SBR_ACTIVE = 3 -} -SBR_SYNC_STATE; - - -typedef enum -{ - COUPLING_OFF = 0, - COUPLING_LEVEL, - COUPLING_BAL -} -COUPLING_MODE; - -typedef struct -{ - UCHAR nSfb[2]; /*!< Number of SBR-bands for low and high freq-resolution */ - UCHAR nNfb; /*!< Actual number of noise bands to read from the bitstream*/ - UCHAR numMaster; /*!< Number of SBR-bands in v_k_master */ - UCHAR lowSubband; /*!< QMF-band where SBR frequency range starts */ - UCHAR highSubband; /*!< QMF-band where SBR frequency range ends */ - UCHAR limiterBandTable[MAX_NUM_LIMITERS+1]; /*!< Limiter band table. */ - UCHAR noLimiterBands; /*!< Number of limiter bands. */ - UCHAR nInvfBands; /*!< Number of bands for inverse filtering */ - UCHAR *freqBandTable[2]; /*!< Pointers to freqBandTableLo and freqBandTableHi */ - UCHAR freqBandTableLo[MAX_FREQ_COEFFS/2+1]; - /*!< Mapping of SBR bands to QMF bands for low frequency resolution */ - UCHAR freqBandTableHi[MAX_FREQ_COEFFS+1]; - /*!< Mapping of SBR bands to QMF bands for high frequency resolution */ - UCHAR freqBandTableNoise[MAX_NOISE_COEFFS+1]; - /*!< Mapping of SBR noise bands to QMF bands */ - UCHAR v_k_master[MAX_FREQ_COEFFS+1]; - /*!< Master BandTable which freqBandTable is derived from */ -} -FREQ_BAND_DATA; +} SBR_SYNC_STATE; + +typedef enum { COUPLING_OFF = 0, COUPLING_LEVEL, COUPLING_BAL } COUPLING_MODE; + +typedef struct { + UCHAR nSfb[2]; /*!< Number of SBR-bands for low and high freq-resolution */ + UCHAR nNfb; /*!< Actual number of noise bands to read from the bitstream*/ + UCHAR numMaster; /*!< Number of SBR-bands in v_k_master */ + UCHAR lowSubband; /*!< QMF-band where SBR frequency range starts */ + UCHAR highSubband; /*!< QMF-band where SBR frequency range ends */ + UCHAR ov_highSubband; /*!< if headerchange applies this value holds the old + highband value -> highband value of overlap area; + required for overlap in usac when headerchange + occurs between XVAR and VARX frame */ + UCHAR limiterBandTable[MAX_NUM_LIMITERS + 1]; /*!< Limiter band table. */ + UCHAR noLimiterBands; /*!< Number of limiter bands. */ + UCHAR nInvfBands; /*!< Number of bands for inverse filtering */ + UCHAR + *freqBandTable[2]; /*!< Pointers to freqBandTableLo and freqBandTableHi */ + UCHAR freqBandTableLo[MAX_FREQ_COEFFS / 2 + 1]; + /*!< Mapping of SBR bands to QMF bands for low frequency resolution */ + UCHAR freqBandTableHi[MAX_FREQ_COEFFS + 1]; + /*!< Mapping of SBR bands to QMF bands for high frequency resolution */ + UCHAR freqBandTableNoise[MAX_NOISE_COEFFS + 1]; + /*!< Mapping of SBR noise bands to QMF bands */ + UCHAR v_k_master[MAX_FREQ_COEFFS + 1]; + /*!< Master BandTable which freqBandTable is derived from */ +} FREQ_BAND_DATA; typedef FREQ_BAND_DATA *HANDLE_FREQ_BAND_DATA; -#define SBRDEC_ELD_GRID 1 -#define SBRDEC_SYNTAX_SCAL 2 -#define SBRDEC_SYNTAX_USAC 4 -#define SBRDEC_SYNTAX_RSVD50 8 -#define SBRDEC_LOW_POWER 16 /* Flag indicating that Low Power QMF mode shall be used. */ -#define SBRDEC_PS_DECODED 32 /* Flag indicating that PS was decoded and rendered. */ -#define SBRDEC_LD_MPS_QMF 512 /* Flag indicating that the LD-MPS QMF shall be used. */ -#define SBRDEC_SYNTAX_DRM 2048 /* Flag indicating that DRM30/DRM+ reverse syntax is being used. */ -#define SBRDEC_DOWNSAMPLE 8192 /* Flag indicating that the downsampling mode is used. */ -#define SBRDEC_FLUSH 16384 /* Flag is used to flush all elements in use. */ -#define SBRDEC_FORCE_RESET 32768 /* Flag is used to force a reset of all elements in use. */ - -#define SBRDEC_HDR_STAT_RESET 1 +#define SBRDEC_ELD_GRID 1 +#define SBRDEC_SYNTAX_SCAL 2 +#define SBRDEC_SYNTAX_USAC 4 +#define SBRDEC_SYNTAX_RSVD50 8 +#define SBRDEC_USAC_INDEP \ + 16 /* Flag indicating that USAC global independency flag is active. */ +#define SBRDEC_LOW_POWER \ + 32 /* Flag indicating that Low Power QMF mode shall be used. */ +#define SBRDEC_PS_DECODED \ + 64 /* Flag indicating that PS was decoded and rendered. */ +#define SBRDEC_QUAD_RATE \ + 128 /* Flag indicating that USAC SBR 4:1 is active. \ + */ +#define SBRDEC_USAC_HARMONICSBR \ + 256 /* Flag indicating that USAC HBE tool is active. */ +#define SBRDEC_LD_MPS_QMF \ + 512 /* Flag indicating that the LD-MPS QMF shall be used. */ +#define SBRDEC_USAC_ITES \ + 1024 /* Flag indicating that USAC inter TES tool is active. */ +#define SBRDEC_SYNTAX_DRM \ + 2048 /* Flag indicating that DRM30/DRM+ reverse syntax is being used. */ +#define SBRDEC_ELD_DOWNSCALE \ + 4096 /* Flag indicating that ELD downscaled mode decoding is used */ +#define SBRDEC_DOWNSAMPLE \ + 8192 /* Flag indicating that the downsampling mode is used. */ +#define SBRDEC_FLUSH 16384 /* Flag is used to flush all elements in use. */ +#define SBRDEC_FORCE_RESET \ + 32768 /* Flag is used to force a reset of all elements in use. */ +#define SBRDEC_SKIP_QMF_ANA \ + (1 << 21) /* Flag indicating that the input data is provided in the QMF \ + domain. */ +#define SBRDEC_SKIP_QMF_SYN \ + (1 << 22) /* Flag indicating that the output data is exported in the QMF \ + domain. */ + +#define SBRDEC_HDR_STAT_RESET 1 #define SBRDEC_HDR_STAT_UPDATE 2 typedef struct { - UCHAR ampResolution; /*!< Amplitude resolution of envelope values (0: 1.5dB, 1: 3dB) */ - UCHAR xover_band; /*!< Start index in #v_k_master[] used for dynamic crossover frequency */ - UCHAR sbr_preprocessing; /*!< SBR prewhitening flag. */ + UCHAR ampResolution; /*!< Amplitude resolution of envelope values (0: 1.5dB, + 1: 3dB) */ + UCHAR + xover_band; /*!< Start index in #v_k_master[] used for dynamic crossover + frequency */ + UCHAR sbr_preprocessing; /*!< SBR prewhitening flag. */ + UCHAR pvc_mode; /*!< Predictive vector coding mode */ } SBR_HEADER_DATA_BS_INFO; typedef struct { /* Changes in these variables causes a reset of the decoder */ - UCHAR startFreq; /*!< Index for SBR start frequency */ - UCHAR stopFreq; /*!< Index for SBR highest frequency */ - UCHAR freqScale; /*!< 0: linear scale, 1-3 logarithmic scales */ - UCHAR alterScale; /*!< Flag for coarser frequency resolution */ - UCHAR noise_bands; /*!< Noise bands per octave, read from bitstream*/ + UCHAR startFreq; /*!< Index for SBR start frequency */ + UCHAR stopFreq; /*!< Index for SBR highest frequency */ + UCHAR freqScale; /*!< 0: linear scale, 1-3 logarithmic scales */ + UCHAR alterScale; /*!< Flag for coarser frequency resolution */ + UCHAR noise_bands; /*!< Noise bands per octave, read from bitstream*/ /* don't require reset */ - UCHAR limiterBands; /*!< Index for number of limiter bands per octave */ - UCHAR limiterGains; /*!< Index to select gain limit */ - UCHAR interpolFreq; /*!< Select gain calculation method (1: per QMF channel, 0: per SBR band) */ - UCHAR smoothingLength; /*!< Smoothing of gains over time (0: on 1: off) */ + UCHAR limiterBands; /*!< Index for number of limiter bands per octave */ + UCHAR limiterGains; /*!< Index to select gain limit */ + UCHAR interpolFreq; /*!< Select gain calculation method (1: per QMF channel, + 0: per SBR band) */ + UCHAR smoothingLength; /*!< Smoothing of gains over time (0: on 1: off) */ } SBR_HEADER_DATA_BS; -typedef struct -{ - SBR_SYNC_STATE syncState; /*!< The current initialization status of the header */ - - UCHAR status; /*!< Flags field used for signaling a reset right before the processing starts and an update from config (e.g. ASC). */ - UCHAR frameErrorFlag; /*!< Frame data valid flag. CAUTION: This variable will be overwritten by the flag stored in the element structure. - This is necessary because of the frame delay. There it might happen that different slots use the same header. */ +typedef struct { + SBR_SYNC_STATE + syncState; /*!< The current initialization status of the header */ + + UCHAR status; /*!< Flags field used for signaling a reset right before the + processing starts and an update from config (e.g. ASC). */ + UCHAR + frameErrorFlag; /*!< Frame data valid flag. CAUTION: This variable will be + overwritten by the flag stored in the element + structure. This is necessary because of the frame + delay. There it might happen that different slots use + the same header. */ UCHAR numberTimeSlots; /*!< AAC: 16,15 */ UCHAR numberOfAnalysisBands; /*!< Number of QMF analysis bands */ UCHAR timeStep; /*!< Time resolution of SBR in QMF-slots */ - UINT sbrProcSmplRate; /*!< SBR processing sampling frequency (!= OutputSamplingRate) - (always: CoreSamplingRate * UpSamplingFactor; even in single rate mode) */ + UINT + sbrProcSmplRate; /*!< SBR processing sampling frequency (!= + OutputSamplingRate) (always: CoreSamplingRate * + UpSamplingFactor; even in single rate mode) */ - SBR_HEADER_DATA_BS bs_data; /*!< current SBR header. */ - SBR_HEADER_DATA_BS_INFO bs_info; /*!< SBR info. */ + SBR_HEADER_DATA_BS bs_data; /*!< current SBR header. */ + SBR_HEADER_DATA_BS bs_dflt; /*!< Default sbr header. */ + SBR_HEADER_DATA_BS_INFO bs_info; /*!< SBR info. */ - FREQ_BAND_DATA freqBandData; /*!< Pointer to struct #FREQ_BAND_DATA */ -} -SBR_HEADER_DATA; + FREQ_BAND_DATA freqBandData; /*!< Pointer to struct #FREQ_BAND_DATA */ + UCHAR pvcIDprev; +} SBR_HEADER_DATA; typedef SBR_HEADER_DATA *HANDLE_SBR_HEADER_DATA; +typedef struct { + UCHAR frameClass; /*!< Select grid type */ + UCHAR nEnvelopes; /*!< Number of envelopes */ + UCHAR borders[MAX_ENVELOPES + 1]; /*!< Envelope borders (in SBR-timeslots, + e.g. mp3PRO: 0..11) */ + UCHAR freqRes[MAX_ENVELOPES]; /*!< Frequency resolution for each envelope + (0=low, 1=high) */ + SCHAR tranEnv; /*!< Transient envelope, -1 if none */ + UCHAR nNoiseEnvelopes; /*!< Number of noise envelopes */ + UCHAR + bordersNoise[MAX_NOISE_ENVELOPES + 1]; /*!< borders of noise envelopes */ + UCHAR pvcBorders[MAX_PVC_ENVELOPES + 1]; + UCHAR noisePosition; + UCHAR varLength; +} FRAME_INFO; -typedef struct -{ - UCHAR frameClass; /*!< Select grid type */ - UCHAR nEnvelopes; /*!< Number of envelopes */ - UCHAR borders[MAX_ENVELOPES+1]; /*!< Envelope borders (in SBR-timeslots, e.g. mp3PRO: 0..11) */ - UCHAR freqRes[MAX_ENVELOPES]; /*!< Frequency resolution for each envelope (0=low, 1=high) */ - SCHAR tranEnv; /*!< Transient envelope, -1 if none */ - UCHAR nNoiseEnvelopes; /*!< Number of noise envelopes */ - UCHAR bordersNoise[MAX_NOISE_ENVELOPES+1];/*!< borders of noise envelopes */ -} -FRAME_INFO; - - -typedef struct -{ - FIXP_SGL sfb_nrg_prev[MAX_FREQ_COEFFS]; /*!< Previous envelope (required for differential-coded values) */ - FIXP_SGL prevNoiseLevel[MAX_NOISE_COEFFS]; /*!< Previous noise envelope (required for differential-coded values) */ - COUPLING_MODE coupling; /*!< Stereo-mode of previous frame */ - INVF_MODE sbr_invf_mode[MAX_INVF_BANDS]; /*!< Previous strength of filtering in transposer */ - UCHAR ampRes; /*!< Previous amplitude resolution (0: 1.5dB, 1: 3dB) */ - UCHAR stopPos; /*!< Position in time where last envelope ended */ - UCHAR frameErrorFlag; /*!< Previous frame status */ -} -SBR_PREV_FRAME_DATA; +typedef struct { + FIXP_SGL sfb_nrg_prev[MAX_FREQ_COEFFS]; /*!< Previous envelope (required for + differential-coded values) */ + FIXP_SGL + prevNoiseLevel[MAX_NOISE_COEFFS]; /*!< Previous noise envelope (required + for differential-coded values) */ + COUPLING_MODE coupling; /*!< Stereo-mode of previous frame */ + INVF_MODE sbr_invf_mode[MAX_INVF_BANDS]; /*!< Previous strength of filtering + in transposer */ + UCHAR ampRes; /*!< Previous amplitude resolution (0: 1.5dB, 1: 3dB) */ + UCHAR stopPos; /*!< Position in time where last envelope ended */ + UCHAR frameErrorFlag; /*!< Previous frame status */ + UCHAR prevSbrPitchInBins; /*!< Previous frame pitchInBins */ + FRAME_INFO prevFrameInfo; +} SBR_PREV_FRAME_DATA; typedef SBR_PREV_FRAME_DATA *HANDLE_SBR_PREV_FRAME_DATA; +typedef struct { + int nScaleFactors; /*!< total number of scalefactors in frame */ -typedef struct -{ - int nScaleFactors; /*!< total number of scalefactors in frame */ - - FRAME_INFO frameInfo; /*!< time grid for current frame */ - UCHAR domain_vec[MAX_ENVELOPES]; /*!< Bitfield containing direction of delta-coding for each envelope (0:frequency, 1:time) */ - UCHAR domain_vec_noise[MAX_NOISE_ENVELOPES]; /*!< Same as above, but for noise envelopes */ + FRAME_INFO frameInfo; /*!< time grid for current frame */ + UCHAR domain_vec[MAX_ENVELOPES]; /*!< Bitfield containing direction of + delta-coding for each envelope + (0:frequency, 1:time) */ + UCHAR domain_vec_noise + [MAX_NOISE_ENVELOPES]; /*!< Same as above, but for noise envelopes */ - INVF_MODE sbr_invf_mode[MAX_INVF_BANDS]; /*!< Strength of filtering in transposer */ - COUPLING_MODE coupling; /*!< Stereo-mode */ - int ampResolutionCurrentFrame; /*!< Amplitude resolution of envelope values (0: 1.5dB, 1: 3dB) */ + INVF_MODE + sbr_invf_mode[MAX_INVF_BANDS]; /*!< Strength of filtering in transposer */ + COUPLING_MODE coupling; /*!< Stereo-mode */ + int ampResolutionCurrentFrame; /*!< Amplitude resolution of envelope values + (0: 1.5dB, 1: 3dB) */ - UCHAR addHarmonics[MAX_FREQ_COEFFS]; /*!< Flags for synthetic sine addition */ + ULONG addHarmonics[ADD_HARMONICS_FLAGS_SIZE]; /*!< Flags for synthetic sine + addition (aligned to MSB) */ FIXP_SGL iEnvelope[MAX_NUM_ENVELOPE_VALUES]; /*!< Envelope data */ FIXP_SGL sbrNoiseFloorLevel[MAX_NUM_NOISE_VALUES]; /*!< Noise envelope data */ -} -SBR_FRAME_DATA; + UCHAR iTESactive; /*!< One flag for each envelope to enable USAC inter-TES */ + UCHAR + interTempShapeMode[MAX_ENVELOPES]; /*!< USAC inter-TES: + bs_inter_temp_shape_mode[ch][env] + value */ + UCHAR pvcID[PVC_NTIMESLOT]; /*!< One PVC ID value for each time slot */ + UCHAR ns; + UCHAR sinusoidal_position; + + UCHAR sbrPatchingMode; + UCHAR sbrOversamplingFlag; + UCHAR sbrPitchInBins; +} SBR_FRAME_DATA; typedef SBR_FRAME_DATA *HANDLE_SBR_FRAME_DATA; -void initSbrPrevFrameData (HANDLE_SBR_PREV_FRAME_DATA h_prev_data, - int timeSlots); +/*! +\brief Maps sampling frequencies to frequencies for which setup tables are +available +Maps arbitary sampling frequency to nearest neighbors for which setup tables +are available (e.g. 25600 -> 24000). +Used for startFreq calculation. +The mapping is defined in 14496-3 (4.6.18.2.6), fs(SBR), and table 4.82 -int sbrGetSingleChannelElement (HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_FRAME_DATA hFrameData, - HANDLE_FDK_BITSTREAM hBitBuf, - HANDLE_PS_DEC hParametricStereoDec, - const UINT flags, - const int overlap - ); +\return mapped sampling frequency +*/ +UINT sbrdec_mapToStdSampleRate(UINT fs, + UINT isUsac); /*!< Output sampling frequency */ -int sbrGetChannelPairElement (HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_FRAME_DATA hFrameDataLeft, - HANDLE_SBR_FRAME_DATA hFrameDataRight, - HANDLE_FDK_BITSTREAM hBitBuf, - const UINT flags, - const int overlap); +void initSbrPrevFrameData(HANDLE_SBR_PREV_FRAME_DATA h_prev_data, + int timeSlots); + +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 hBitBuf, + HANDLE_PS_DEC hParametricStereoDec, const UINT flags, + const int overlap); SBR_HEADER_STATUS -sbrGetHeaderData (HANDLE_SBR_HEADER_DATA headerData, - HANDLE_FDK_BITSTREAM hBitBuf, - const UINT flags, - const int fIsSbrData); +sbrGetHeaderData(HANDLE_SBR_HEADER_DATA headerData, + HANDLE_FDK_BITSTREAM hBitBuf, const UINT flags, + const int fIsSbrData, const UCHAR configMode); /*! \brief Initialize SBR header data @@ -314,11 +404,12 @@ sbrGetHeaderData (HANDLE_SBR_HEADER_DATA headerData, depending on the core codec. */ SBR_ERROR -initHeaderData ( - HANDLE_SBR_HEADER_DATA hHeaderData, - const int sampleRateIn, - const int sampleRateOut, - const int samplesPerFrame, - const UINT flags - ); +initHeaderData(HANDLE_SBR_HEADER_DATA hHeaderData, const int sampleRateIn, + const int sampleRateOut, const INT downscaleFactor, + const int samplesPerFrame, const UINT flags, + const int setDefaultHdr); #endif + +/* Convert headroom bits to exponent */ +#define SCALE2EXP(s) (15 - (s)) +#define EXP2SCALE(e) (15 - (e)) diff --git a/libSBRdec/src/hbe.cpp b/libSBRdec/src/hbe.cpp new file mode 100644 index 0000000..53b21c9 --- /dev/null +++ b/libSBRdec/src/hbe.cpp @@ -0,0 +1,2198 @@ +/* ----------------------------------------------------------------------------- +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 Fast FFT routines prototypes + \author Fabian Haussel +*/ + +#include "hbe.h" +#include "qmf.h" +#include "env_extr.h" + +#define HBE_MAX_QMF_BANDS (40) + +#define HBE_MAX_OUT_SLOTS (11) + +#define QMF_WIN_LEN \ + (12 + 6 - 4 - 1) /* 6 subband slots extra delay to align with HQ - 4 slots \ + to compensate for critical sampling delay - 1 slot to \ + align critical sampling exactly (w additional time \ + domain delay)*/ + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + +static const int xProducts[MAX_STRETCH_HBE - 1] = { + 1, 1, 1}; /* Cross products on(1)/off(0) for T=2,3,4. */ +static const int startSubband2kL[33] = { + 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, + 6, 8, 8, 8, 8, 8, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12}; + +static const int pmin = 12; + +static const FIXP_DBL hintReal_F[4][3] = { + {FL2FXCONST_DBL(0.39840335f), FL2FXCONST_DBL(0.39840335f), + FL2FXCONST_DBL(-0.39840335f)}, + {FL2FXCONST_DBL(0.39840335f), FL2FXCONST_DBL(-0.39840335f), + FL2FXCONST_DBL(-0.39840335f)}, + {FL2FXCONST_DBL(-0.39840335f), FL2FXCONST_DBL(-0.39840335f), + FL2FXCONST_DBL(0.39840335f)}, + {FL2FXCONST_DBL(-0.39840335f), FL2FXCONST_DBL(0.39840335f), + FL2FXCONST_DBL(0.39840335f)}}; + +static const FIXP_DBL factors[4] = { + FL2FXCONST_DBL(0.39840335f), FL2FXCONST_DBL(-0.39840335f), + FL2FXCONST_DBL(-0.39840335f), FL2FXCONST_DBL(0.39840335f)}; + +#define PSCALE 32 + +static const FIXP_DBL p_F[128] = {FL2FXCONST_DBL(0.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(1.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(2.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(3.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(4.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(5.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(6.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(7.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(8.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(9.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(10.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(11.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(12.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(13.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(14.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(15.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(16.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(17.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(18.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(19.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(20.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(21.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(22.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(23.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(24.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(25.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(26.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(27.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(28.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(29.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(30.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(31.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(32.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(33.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(34.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(35.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(36.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(37.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(38.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(39.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(40.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(41.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(42.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(43.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(44.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(45.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(46.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(47.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(48.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(49.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(50.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(51.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(52.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(53.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(54.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(55.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(56.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(57.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(58.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(59.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(60.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(61.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(62.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(63.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(64.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(65.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(66.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(67.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(68.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(69.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(70.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(71.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(72.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(73.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(74.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(75.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(76.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(77.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(78.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(79.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(80.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(81.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(82.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(83.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(84.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(85.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(86.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(87.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(88.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(89.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(90.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(91.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(92.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(93.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(94.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(95.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(96.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(97.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(98.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(99.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(100.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(101.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(102.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(103.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(104.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(105.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(106.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(107.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(108.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(109.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(110.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(111.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(112.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(113.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(114.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(115.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(116.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(117.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(118.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(119.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(120.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(121.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(122.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(123.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(124.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(125.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(126.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(127.f / (PSCALE * 12.f))}; + +static const FIXP_DBL band_F[64] = { + FL2FXCONST_DBL((0.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((1.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((2.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((3.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((4.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((5.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((6.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((7.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((8.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((9.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((10.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((11.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((12.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((13.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((14.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((15.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((16.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((17.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((18.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((19.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((20.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((21.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((22.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((23.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((24.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((25.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((26.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((27.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((28.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((29.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((30.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((31.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((32.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((33.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((34.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((35.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((36.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((37.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((38.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((39.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((40.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((41.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((42.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((43.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((44.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((45.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((46.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((47.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((48.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((49.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((50.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((51.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((52.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((53.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((54.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((55.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((56.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((57.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((58.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((59.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((60.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((61.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((62.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((63.f * 2.f + 1) / (PSCALE << 2))}; + +static const FIXP_DBL tr_str[3] = {FL2FXCONST_DBL(1.f / 4.f), + FL2FXCONST_DBL(2.f / 4.f), + FL2FXCONST_DBL(3.f / 4.f)}; + +static const FIXP_DBL stretchfac[3] = {FL2FXCONST_DBL(1.f / 2.f), + FL2FXCONST_DBL(1.f / 3.f), + FL2FXCONST_DBL(1.f / 4.f)}; + +static const FIXP_DBL cos_F[64] = { + 26353028, -79043208, 131685776, -184244944, 236697216, -289006912, + 341142496, -393072608, 444773984, -496191392, 547325824, -598114752, + 648559104, -698597248, 748230016, -797411904, 846083200, -894275136, + 941928192, -989013760, 1035474624, -1081340672, 1126555136, -1171063296, + 1214893696, -1257992192, 1300332544, -1341889408, 1382612736, -1422503808, + 1461586944, -1499741440, 1537039104, -1573364864, 1608743808, -1643196672, + 1676617344, -1709028992, 1740450560, -1770784896, 1800089472, -1828273536, + 1855357440, -1881356288, 1906190080, -1929876608, 1952428928, -1973777664, + 1993962880, -2012922240, 2030670208, -2047216000, 2062508288, -2076559488, + 2089376128, -2100932224, 2111196800, -2120214784, 2127953792, -2134394368, + 2139565056, -2143444864, 2146026624, -2147321856}; + +static const FIXP_DBL twiddle[121] = {1073741824, + 1071442860, + 1064555814, + 1053110176, + 1037154959, + 1016758484, + 992008094, + 963009773, + 929887697, + 892783698, + 851856663, + 807281846, + 759250125, + 707967178, + 653652607, + 596538995, + 536870912, + 474903865, + 410903207, + 345142998, + 277904834, + 209476638, + 140151432, + 70226075, + 0, + -70226075, + -140151432, + -209476638, + -277904834, + -345142998, + -410903207, + -474903865, + -536870912, + -596538995, + -653652607, + -707967178, + -759250125, + -807281846, + -851856663, + -892783698, + -929887697, + -963009773, + -992008094, + -1016758484, + -1037154959, + -1053110176, + -1064555814, + -1071442860, + -1073741824, + -1071442860, + -1064555814, + -1053110176, + -1037154959, + -1016758484, + -992008094, + -963009773, + -929887697, + -892783698, + -851856663, + -807281846, + -759250125, + -707967178, + -653652607, + -596538995, + -536870912, + -474903865, + -410903207, + -345142998, + -277904834, + -209476638, + -140151432, + -70226075, + 0, + 70226075, + 140151432, + 209476638, + 277904834, + 345142998, + 410903207, + 474903865, + 536870912, + 596538995, + 653652607, + 707967178, + 759250125, + 807281846, + 851856663, + 892783698, + 929887697, + 963009773, + 992008094, + 1016758484, + 1037154959, + 1053110176, + 1064555814, + 1071442860, + 1073741824, + 1071442860, + 1064555814, + 1053110176, + 1037154959, + 1016758484, + 992008094, + 963009773, + 929887697, + 892783698, + 851856663, + 807281846, + 759250125, + 707967178, + 653652607, + 596538995, + 536870912, + 474903865, + 410903207, + 345142998, + 277904834, + 209476638, + 140151432, + 70226075, + 0}; + +#if FIXP_QTW == FIXP_SGL +#define HTW(x) (x) +#else +#define HTW(x) FX_DBL2FX_QTW(FX_SGL2FX_DBL((const FIXP_SGL)x)) +#endif + +static const FIXP_QTW post_twiddle_cos_8[8] = { + HTW(-1606), HTW(4756), HTW(-7723), HTW(10394), + HTW(-12665), HTW(14449), HTW(-15679), HTW(16305)}; + +static const FIXP_QTW post_twiddle_cos_16[16] = { + HTW(-804), HTW(2404), HTW(-3981), HTW(5520), HTW(-7005), HTW(8423), + HTW(-9760), HTW(11003), HTW(-12140), HTW(13160), HTW(-14053), HTW(14811), + HTW(-15426), HTW(15893), HTW(-16207), HTW(16364)}; + +static const FIXP_QTW post_twiddle_cos_24[24] = { + HTW(-536), HTW(1606), HTW(-2669), HTW(3720), HTW(-4756), HTW(5771), + HTW(-6762), HTW(7723), HTW(-8652), HTW(9543), HTW(-10394), HTW(11200), + HTW(-11958), HTW(12665), HTW(-13318), HTW(13913), HTW(-14449), HTW(14924), + HTW(-15334), HTW(15679), HTW(-15956), HTW(16165), HTW(-16305), HTW(16375)}; + +static const FIXP_QTW post_twiddle_cos_32[32] = { + HTW(-402), HTW(1205), HTW(-2006), HTW(2801), HTW(-3590), HTW(4370), + HTW(-5139), HTW(5897), HTW(-6639), HTW(7366), HTW(-8076), HTW(8765), + HTW(-9434), HTW(10080), HTW(-10702), HTW(11297), HTW(-11866), HTW(12406), + HTW(-12916), HTW(13395), HTW(-13842), HTW(14256), HTW(-14635), HTW(14978), + HTW(-15286), HTW(15557), HTW(-15791), HTW(15986), HTW(-16143), HTW(16261), + HTW(-16340), HTW(16379)}; + +static const FIXP_QTW post_twiddle_cos_40[40] = { + HTW(-322), HTW(965), HTW(-1606), HTW(2245), HTW(-2880), HTW(3511), + HTW(-4137), HTW(4756), HTW(-5368), HTW(5971), HTW(-6566), HTW(7150), + HTW(-7723), HTW(8285), HTW(-8833), HTW(9368), HTW(-9889), HTW(10394), + HTW(-10883), HTW(11356), HTW(-11810), HTW(12247), HTW(-12665), HTW(13063), + HTW(-13441), HTW(13799), HTW(-14135), HTW(14449), HTW(-14741), HTW(15011), + HTW(-15257), HTW(15480), HTW(-15679), HTW(15853), HTW(-16003), HTW(16129), + HTW(-16229), HTW(16305), HTW(-16356), HTW(16381)}; + +static const FIXP_QTW post_twiddle_sin_8[8] = { + HTW(16305), HTW(-15679), HTW(14449), HTW(-12665), + HTW(10394), HTW(-7723), HTW(4756), HTW(-1606)}; + +static const FIXP_QTW post_twiddle_sin_16[16] = { + HTW(16364), HTW(-16207), HTW(15893), HTW(-15426), HTW(14811), HTW(-14053), + HTW(13160), HTW(-12140), HTW(11003), HTW(-9760), HTW(8423), HTW(-7005), + HTW(5520), HTW(-3981), HTW(2404), HTW(-804)}; + +static const FIXP_QTW post_twiddle_sin_24[24] = { + HTW(16375), HTW(-16305), HTW(16165), HTW(-15956), HTW(15679), HTW(-15334), + HTW(14924), HTW(-14449), HTW(13913), HTW(-13318), HTW(12665), HTW(-11958), + HTW(11200), HTW(-10394), HTW(9543), HTW(-8652), HTW(7723), HTW(-6762), + HTW(5771), HTW(-4756), HTW(3720), HTW(-2669), HTW(1606), HTW(-536)}; + +static const FIXP_QTW post_twiddle_sin_32[32] = { + HTW(16379), HTW(-16340), HTW(16261), HTW(-16143), HTW(15986), HTW(-15791), + HTW(15557), HTW(-15286), HTW(14978), HTW(-14635), HTW(14256), HTW(-13842), + HTW(13395), HTW(-12916), HTW(12406), HTW(-11866), HTW(11297), HTW(-10702), + HTW(10080), HTW(-9434), HTW(8765), HTW(-8076), HTW(7366), HTW(-6639), + HTW(5897), HTW(-5139), HTW(4370), HTW(-3590), HTW(2801), HTW(-2006), + HTW(1205), HTW(-402)}; + +static const FIXP_QTW post_twiddle_sin_40[40] = { + HTW(16381), HTW(-16356), HTW(16305), HTW(-16229), HTW(16129), HTW(-16003), + HTW(15853), HTW(-15679), HTW(15480), HTW(-15257), HTW(15011), HTW(-14741), + HTW(14449), HTW(-14135), HTW(13799), HTW(-13441), HTW(13063), HTW(-12665), + HTW(12247), HTW(-11810), HTW(11356), HTW(-10883), HTW(10394), HTW(-9889), + HTW(9368), HTW(-8833), HTW(8285), HTW(-7723), HTW(7150), HTW(-6566), + HTW(5971), HTW(-5368), HTW(4756), HTW(-4137), HTW(3511), HTW(-2880), + HTW(2245), HTW(-1606), HTW(965), HTW(-322)}; + +static const FIXP_DBL preModCos[32] = { + -749875776, 786681536, 711263552, -821592064, -670937792, 854523392, + 628995648, -885396032, -585538240, 914135680, 540670208, -940673088, + -494499680, 964944384, 447137824, -986891008, -398698816, 1006460096, + 349299264, -1023604544, -299058240, 1038283072, 248096752, -1050460288, + -196537584, 1060106816, 144504928, -1067199488, -92124160, 1071721152, + 39521456, -1073660992}; + +static const FIXP_DBL preModSin[32] = { + 768510144, 730789760, -804379072, -691308864, 838310208, 650162560, + -870221760, -607449920, 900036928, 563273856, -927683776, -517740896, + 953095808, 470960608, -976211712, -423045728, 996975808, 374111712, + -1015338112, -324276416, 1031254400, 273659904, -1044686336, -222384144, + 1055601472, 170572640, -1063973632, -118350192, 1069782528, 65842640, + -1073014208, -13176464}; + +/* The cube root function */ +/***************************************************************************** + + functionname: invCubeRootNorm2 + description: delivers 1/cuberoot(op) in Q1.31 format and modified exponent + +*****************************************************************************/ +#define CUBE_ROOT_BITS 7 +#define CUBE_ROOT_VALUES (128 + 2) +#define CUBE_ROOT_BITS_MASK 0x7f +#define CUBE_ROOT_FRACT_BITS_MASK 0x007FFFFF +/* Inverse cube root table for operands running from 0.5 to 1.0 */ +/* (INT) (1.0/cuberoot((op))); */ +/* Implicit exponent is 1. */ + +LNK_SECTION_CONSTDATA +static const FIXP_DBL invCubeRootTab[CUBE_ROOT_VALUES] = { + (0x50a28be6), (0x506d1172), (0x503823c4), (0x5003c05a), (0x4fcfe4c0), + (0x4f9c8e92), (0x4f69bb7d), (0x4f37693b), (0x4f059594), (0x4ed43e5f), + (0x4ea36181), (0x4e72fcea), (0x4e430e98), (0x4e139495), (0x4de48cf5), + (0x4db5f5db), (0x4d87cd73), (0x4d5a11f2), (0x4d2cc19c), (0x4cffdabb), + (0x4cd35ba4), (0x4ca742b7), (0x4c7b8e5c), (0x4c503d05), (0x4c254d2a), + (0x4bfabd50), (0x4bd08c00), (0x4ba6b7cd), (0x4b7d3f53), (0x4b542134), + (0x4b2b5c18), (0x4b02eeb1), (0x4adad7b8), (0x4ab315ea), (0x4a8ba80d), + (0x4a648cec), (0x4a3dc35b), (0x4a174a30), (0x49f1204a), (0x49cb448d), + (0x49a5b5e2), (0x49807339), (0x495b7b86), (0x4936cdc2), (0x491268ec), + (0x48ee4c08), (0x48ca761f), (0x48a6e63e), (0x48839b76), (0x486094de), + (0x483dd190), (0x481b50ad), (0x47f91156), (0x47d712b3), (0x47b553f0), + (0x4793d43c), (0x477292c9), (0x47518ece), (0x4730c785), (0x47103c2d), + (0x46efec06), (0x46cfd655), (0x46affa61), (0x46905777), (0x4670ece4), + (0x4651b9f9), (0x4632be0b), (0x4613f871), (0x45f56885), (0x45d70da5), + (0x45b8e72f), (0x459af487), (0x457d3511), (0x455fa835), (0x45424d5d), + (0x452523f6), (0x45082b6e), (0x44eb6337), (0x44cecac5), (0x44b2618d), + (0x44962708), (0x447a1ab1), (0x445e3c02), (0x44428a7c), (0x4427059e), + (0x440bacec), (0x43f07fe9), (0x43d57e1c), (0x43baa70e), (0x439ffa48), + (0x43857757), (0x436b1dc8), (0x4350ed2b), (0x4336e511), (0x431d050c), + (0x43034cb2), (0x42e9bb98), (0x42d05156), (0x42b70d85), (0x429defc0), + (0x4284f7a2), (0x426c24cb), (0x425376d8), (0x423aed6a), (0x42228823), + (0x420a46a6), (0x41f22898), (0x41da2d9f), (0x41c25561), (0x41aa9f86), + (0x41930bba), (0x417b99a5), (0x416448f5), (0x414d1956), (0x41360a76), + (0x411f1c06), (0x41084db5), (0x40f19f35), (0x40db1039), (0x40c4a074), + (0x40ae4f9b), (0x40981d64), (0x40820985), (0x406c13b6), (0x40563bb1), + (0x4040812e), (0x402ae3e7), (0x40156399), (0x40000000), (0x3FEAB8D9)}; +/* n.a. */ +static const FIXP_DBL invCubeRootCorrection[3] = {0x40000000, 0x50A28BE6, + 0x6597FA95}; + +/***************************************************************************** + * \brief calculate 1.0/cube_root(op), op contains mantissa and exponent + * \param op_m: (i) mantissa of operand, must not be zero (0x0000.0000) or + * negative + * \param op_e: (i) pointer to the exponent of the operand (must be initialized) + * and .. (o) pointer to the exponent of the result + * \return: (o) mantissa of the result + * \description: + * This routine calculates the cube root of the input operand, that is + * given with its mantissa in Q31 format (FIXP_DBL) and its exponent (INT). + * The resulting mantissa is returned in format Q31. The exponent (*op_e) + * is modified accordingly. It is not assured, that the result is fully + * left-aligned but assumed to have not more than 2 bits headroom. There is one + * macro to activate the use of this algorithm: FUNCTION_invCubeRootNorm2 By + * means of activating the macro INVCUBEROOTNORM2_LINEAR_INTERPOLATE_HQ, a + * slightly higher precision is reachable (by default, not active). For DEBUG + * purpose only: a FDK_ASSERT macro validates, if the input mantissa is greater + * zero. + * + */ +static +#ifdef __arm__ + FIXP_DBL __attribute__((always_inline)) + invCubeRootNorm2(FIXP_DBL op_m, INT* op_e) +#else + FIXP_DBL + invCubeRootNorm2(FIXP_DBL op_m, INT* op_e) +#endif +{ + FDK_ASSERT(op_m > FIXP_DBL(0)); + + /* normalize input, calculate shift value */ + INT exponent = (INT)fNormz(op_m) - 1; + op_m <<= exponent; + + INT index = (INT)(op_m >> (DFRACT_BITS - 1 - (CUBE_ROOT_BITS + 1))) & + CUBE_ROOT_BITS_MASK; + FIXP_DBL fract = (FIXP_DBL)(((INT)op_m & CUBE_ROOT_FRACT_BITS_MASK) + << (CUBE_ROOT_BITS + 1)); + FIXP_DBL diff = invCubeRootTab[index + 1] - invCubeRootTab[index]; + op_m = fMultAddDiv2(invCubeRootTab[index], diff << 1, fract); +#if defined(INVCUBEROOTNORM2_LINEAR_INTERPOLATE_HQ) + /* reg1 = t[i] + (t[i+1]-t[i])*fract ... already computed ... + + * (1-fract)fract*(t[i+2]-t[i+1])/2 */ + if (fract != (FIXP_DBL)0) { + /* fract = fract * (1 - fract) */ + fract = fMultDiv2(fract, (FIXP_DBL)((LONG)0x80000000 - (LONG)fract)) << 1; + diff = diff - (invCubeRootTab[index + 2] - invCubeRootTab[index + 1]); + op_m = fMultAddDiv2(op_m, fract, diff); + } +#endif /* INVCUBEROOTNORM2_LINEAR_INTERPOLATE_HQ */ + + /* calculate the output exponent = input * exp/3 = cubicroot(m)*2^(exp/3) + * where 2^(exp/3) = 2^k'*2 or 2^k'*2^(1/3) or 2^k'*2^(2/3) */ + exponent = exponent - *op_e + 3; + INT shift_tmp = + ((INT)fMultDiv2((FIXP_SGL)fAbs(exponent), (FIXP_SGL)0x5556)) >> 16; + if (exponent < 0) { + shift_tmp = -shift_tmp; + } + INT rem = exponent - 3 * shift_tmp; + if (rem < 0) { + rem += 3; + shift_tmp--; + } + + *op_e = shift_tmp; + op_m = fMultDiv2(op_m, invCubeRootCorrection[rem]) << 2; + + return (op_m); +} + + /***************************************************************************** + + functionname: invFourthRootNorm2 + description: delivers 1/FourthRoot(op) in Q1.31 format and modified + exponent + + *****************************************************************************/ + +#define FOURTHROOT_BITS 7 +#define FOURTHROOT_VALUES (128 + 2) +#define FOURTHROOT_BITS_MASK 0x7f +#define FOURTHROOT_FRACT_BITS_MASK 0x007FFFFF + +LNK_SECTION_CONSTDATA +static const FIXP_DBL invFourthRootTab[FOURTHROOT_VALUES] = { + (0x4c1bf829), (0x4bf61977), (0x4bd09843), (0x4bab72ef), (0x4b86a7eb), + (0x4b6235ac), (0x4b3e1ab6), (0x4b1a5592), (0x4af6e4d4), (0x4ad3c718), + (0x4ab0fb03), (0x4a8e7f42), (0x4a6c5288), (0x4a4a7393), (0x4a28e126), + (0x4a079a0c), (0x49e69d16), (0x49c5e91f), (0x49a57d04), (0x498557ac), + (0x49657802), (0x4945dcf9), (0x49268588), (0x490770ac), (0x48e89d6a), + (0x48ca0ac9), (0x48abb7d6), (0x488da3a6), (0x486fcd4f), (0x485233ed), + (0x4834d6a3), (0x4817b496), (0x47faccf0), (0x47de1ee0), (0x47c1a999), + (0x47a56c51), (0x47896643), (0x476d96af), (0x4751fcd6), (0x473697ff), + (0x471b6773), (0x47006a81), (0x46e5a079), (0x46cb08ae), (0x46b0a279), + (0x46966d34), (0x467c683d), (0x466292f4), (0x4648ecbc), (0x462f74fe), + (0x46162b20), (0x45fd0e91), (0x45e41ebe), (0x45cb5b19), (0x45b2c315), + (0x459a562a), (0x458213cf), (0x4569fb81), (0x45520cbc), (0x453a4701), + (0x4522a9d1), (0x450b34b0), (0x44f3e726), (0x44dcc0ba), (0x44c5c0f7), + (0x44aee768), (0x4498339e), (0x4481a527), (0x446b3b96), (0x4454f67e), + (0x443ed576), (0x4428d815), (0x4412fdf3), (0x43fd46ad), (0x43e7b1de), + (0x43d23f23), (0x43bcee1e), (0x43a7be6f), (0x4392afb8), (0x437dc19d), + (0x4368f3c5), (0x435445d6), (0x433fb779), (0x432b4856), (0x4316f81a), + (0x4302c66f), (0x42eeb305), (0x42dabd8a), (0x42c6e5ad), (0x42b32b21), + (0x429f8d96), (0x428c0cc2), (0x4278a859), (0x42656010), (0x4252339e), + (0x423f22bc), (0x422c2d23), (0x4219528b), (0x420692b2), (0x41f3ed51), + (0x41e16228), (0x41cef0f2), (0x41bc9971), (0x41aa5b62), (0x41983687), + (0x41862aa2), (0x41743775), (0x41625cc3), (0x41509a50), (0x413eefe2), + (0x412d5d3e), (0x411be22b), (0x410a7e70), (0x40f931d5), (0x40e7fc23), + (0x40d6dd24), (0x40c5d4a2), (0x40b4e268), (0x40a40642), (0x40933ffc), + (0x40828f64), (0x4071f447), (0x40616e73), (0x4050fdb9), (0x4040a1e6), + (0x40305acc), (0x4020283c), (0x40100a08), (0x40000000), (0x3ff009f9), +}; + +static const FIXP_DBL invFourthRootCorrection[4] = {0x40000000, 0x4C1BF829, + 0x5A82799A, 0x6BA27E65}; + +/* The fourth root function */ +/***************************************************************************** + * \brief calculate 1.0/fourth_root(op), op contains mantissa and exponent + * \param op_m: (i) mantissa of operand, must not be zero (0x0000.0000) or + * negative + * \param op_e: (i) pointer to the exponent of the operand (must be initialized) + * and .. (o) pointer to the exponent of the result + * \return: (o) mantissa of the result + * \description: + * This routine calculates the cube root of the input operand, that is + * given with its mantissa in Q31 format (FIXP_DBL) and its exponent (INT). + * The resulting mantissa is returned in format Q31. The exponent (*op_e) + * is modified accordingly. It is not assured, that the result is fully + * left-aligned but assumed to have not more than 2 bits headroom. There is one + * macro to activate the use of this algorithm: FUNCTION_invFourthRootNorm2 By + * means of activating the macro INVFOURTHROOTNORM2_LINEAR_INTERPOLATE_HQ, a + * slightly higher precision is reachable (by default, not active). For DEBUG + * purpose only: a FDK_ASSERT macro validates, if the input mantissa is greater + * zero. + * + */ + +/* #define INVFOURTHROOTNORM2_LINEAR_INTERPOLATE_HQ */ + +static +#ifdef __arm__ + FIXP_DBL __attribute__((always_inline)) + invFourthRootNorm2(FIXP_DBL op_m, INT* op_e) +#else + FIXP_DBL + invFourthRootNorm2(FIXP_DBL op_m, INT* op_e) +#endif +{ + FDK_ASSERT(op_m > FL2FXCONST_DBL(0.0)); + + /* normalize input, calculate shift value */ + INT exponent = (INT)fNormz(op_m) - 1; + op_m <<= exponent; + + INT index = (INT)(op_m >> (DFRACT_BITS - 1 - (FOURTHROOT_BITS + 1))) & + FOURTHROOT_BITS_MASK; + FIXP_DBL fract = (FIXP_DBL)(((INT)op_m & FOURTHROOT_FRACT_BITS_MASK) + << (FOURTHROOT_BITS + 1)); + FIXP_DBL diff = invFourthRootTab[index + 1] - invFourthRootTab[index]; + op_m = invFourthRootTab[index] + (fMultDiv2(diff, fract) << 1); + +#if defined(INVFOURTHROOTNORM2_LINEAR_INTERPOLATE_HQ) + /* reg1 = t[i] + (t[i+1]-t[i])*fract ... already computed ... + + * (1-fract)fract*(t[i+2]-t[i+1])/2 */ + if (fract != (FIXP_DBL)0) { + /* fract = fract * (1 - fract) */ + fract = fMultDiv2(fract, (FIXP_DBL)((LONG)0x80000000 - (LONG)fract)) << 1; + diff = diff - (invFourthRootTab[index + 2] - invFourthRootTab[index + 1]); + op_m = fMultAddDiv2(op_m, fract, diff); + } +#endif /* INVFOURTHROOTNORM2_LINEAR_INTERPOLATE_HQ */ + + exponent = exponent - *op_e + 4; + INT rem = exponent & 0x00000003; + INT shift_tmp = (exponent >> 2); + + *op_e = shift_tmp; + op_m = fMultDiv2(op_m, invFourthRootCorrection[rem]) << 2; + + return (op_m); +} + +/***************************************************************************** + + functionname: inv3EigthRootNorm2 + description: delivers 1/cubert(op) normalized to .5...1 and the shift value +of the OUTPUT + +*****************************************************************************/ +#define THREEIGTHROOT_BITS 7 +#define THREEIGTHROOT_VALUES (128 + 2) +#define THREEIGTHROOT_BITS_MASK 0x7f +#define THREEIGTHROOT_FRACT_BITS_MASK 0x007FFFFF + +LNK_SECTION_CONSTDATA +static const FIXP_DBL inv3EigthRootTab[THREEIGTHROOT_VALUES] = { + (0x45cae0f2), (0x45b981bf), (0x45a8492a), (0x45973691), (0x45864959), + (0x457580e6), (0x4564dca4), (0x45545c00), (0x4543fe6b), (0x4533c35a), + (0x4523aa44), (0x4513b2a4), (0x4503dbf7), (0x44f425be), (0x44e48f7b), + (0x44d518b6), (0x44c5c0f7), (0x44b687c8), (0x44a76cb8), (0x44986f58), + (0x44898f38), (0x447acbef), (0x446c2514), (0x445d9a3f), (0x444f2b0d), + (0x4440d71a), (0x44329e07), (0x44247f73), (0x44167b04), (0x4408905e), + (0x43fabf28), (0x43ed070b), (0x43df67b0), (0x43d1e0c5), (0x43c471f7), + (0x43b71af6), (0x43a9db71), (0x439cb31c), (0x438fa1ab), (0x4382a6d2), + (0x4375c248), (0x4368f3c5), (0x435c3b03), (0x434f97bc), (0x434309ac), + (0x43369091), (0x432a2c28), (0x431ddc30), (0x4311a06c), (0x4305789c), + (0x42f96483), (0x42ed63e5), (0x42e17688), (0x42d59c30), (0x42c9d4a6), + (0x42be1fb1), (0x42b27d1a), (0x42a6ecac), (0x429b6e2f), (0x42900172), + (0x4284a63f), (0x42795c64), (0x426e23b0), (0x4262fbf2), (0x4257e4f9), + (0x424cde96), (0x4241e89a), (0x423702d8), (0x422c2d23), (0x4221674d), + (0x4216b12c), (0x420c0a94), (0x4201735b), (0x41f6eb57), (0x41ec725f), + (0x41e2084b), (0x41d7acf3), (0x41cd6030), (0x41c321db), (0x41b8f1ce), + (0x41aecfe5), (0x41a4bbf8), (0x419ab5e6), (0x4190bd89), (0x4186d2bf), + (0x417cf565), (0x41732558), (0x41696277), (0x415faca1), (0x415603b4), + (0x414c6792), (0x4142d818), (0x4139552a), (0x412fdea6), (0x41267470), + (0x411d1668), (0x4113c472), (0x410a7e70), (0x41014445), (0x40f815d4), + (0x40eef302), (0x40e5dbb4), (0x40dccfcd), (0x40d3cf33), (0x40cad9cb), + (0x40c1ef7b), (0x40b9102a), (0x40b03bbd), (0x40a7721c), (0x409eb32e), + (0x4095feda), (0x408d5508), (0x4084b5a0), (0x407c208b), (0x407395b2), + (0x406b14fd), (0x40629e56), (0x405a31a6), (0x4051ced8), (0x404975d5), + (0x40412689), (0x4038e0dd), (0x4030a4bd), (0x40287215), (0x402048cf), + (0x401828d7), (0x4010121a), (0x40080483), (0x40000000), (0x3ff8047d), +}; + +/* The last value is rounded in order to avoid any overflow due to the values + * range of the root table */ +static const FIXP_DBL inv3EigthRootCorrection[8] = { + 0x40000000, 0x45CAE0F2, 0x4C1BF829, 0x52FF6B55, + 0x5A82799A, 0x62B39509, 0x6BA27E65, 0x75606373}; + +/* The 3/8 root function */ +/***************************************************************************** + * \brief calculate 1.0/3Eigth_root(op) = 1.0/(x)^(3/8), op contains mantissa + * and exponent + * \param op_m: (i) mantissa of operand, must not be zero (0x0000.0000) or + * negative + * \param op_e: (i) pointer to the exponent of the operand (must be initialized) + * and .. (o) pointer to the exponent of the result + * \return: (o) mantissa of the result + * \description: + * This routine calculates the cube root of the input operand, that is + * given with its mantissa in Q31 format (FIXP_DBL) and its exponent (INT). + * The resulting mantissa is returned in format Q31. The exponent (*op_e) + * is modified accordingly. It is not assured, that the result is fully + * left-aligned but assumed to have not more than 2 bits headroom. There is one + * macro to activate the use of this algorithm: FUNCTION_inv3EigthRootNorm2 By + * means of activating the macro INVTHREEIGTHROOTNORM2_LINEAR_INTERPOLATE_HQ, a + * slightly higher precision is reachable (by default, not active). For DEBUG + * purpose only: a FDK_ASSERT macro validates, if the input mantissa is greater + * zero. + * + */ + +/* #define INVTHREEIGTHROOTNORM2_LINEAR_INTERPOLATE_HQ */ + +static +#ifdef __arm__ + FIXP_DBL __attribute__((always_inline)) + inv3EigthRootNorm2(FIXP_DBL op_m, INT* op_e) +#else + FIXP_DBL + inv3EigthRootNorm2(FIXP_DBL op_m, INT* op_e) +#endif +{ + FDK_ASSERT(op_m > FL2FXCONST_DBL(0.0)); + + /* normalize input, calculate shift op_mue */ + INT exponent = (INT)fNormz(op_m) - 1; + op_m <<= exponent; + + INT index = (INT)(op_m >> (DFRACT_BITS - 1 - (THREEIGTHROOT_BITS + 1))) & + THREEIGTHROOT_BITS_MASK; + FIXP_DBL fract = (FIXP_DBL)(((INT)op_m & THREEIGTHROOT_FRACT_BITS_MASK) + << (THREEIGTHROOT_BITS + 1)); + FIXP_DBL diff = inv3EigthRootTab[index + 1] - inv3EigthRootTab[index]; + op_m = inv3EigthRootTab[index] + (fMultDiv2(diff, fract) << 1); + +#if defined(INVTHREEIGTHROOTNORM2_LINEAR_INTERPOLATE_HQ) + /* op_m = t[i] + (t[i+1]-t[i])*fract ... already computed ... + + * (1-fract)fract*(t[i+2]-t[i+1])/2 */ + if (fract != (FIXP_DBL)0) { + /* fract = fract * (1 - fract) */ + fract = fMultDiv2(fract, (FIXP_DBL)((LONG)0x80000000 - (LONG)fract)) << 1; + diff = diff - (inv3EigthRootTab[index + 2] - inv3EigthRootTab[index + 1]); + op_m = fMultAddDiv2(op_m, fract, diff); + } +#endif /* INVTHREEIGTHROOTNORM2_LINEAR_INTERPOLATE_HQ */ + + exponent = exponent - *op_e + 8; + INT rem = exponent & 0x00000007; + INT shift_tmp = (exponent >> 3); + + *op_e = shift_tmp * 3; + op_m = fMultDiv2(op_m, inv3EigthRootCorrection[rem]) << 2; + + return (fMult(op_m, fMult(op_m, op_m))); +} + +SBR_ERROR +QmfTransposerCreate(HANDLE_HBE_TRANSPOSER* hQmfTransposer, const int frameSize, + int bDisableCrossProducts, int bSbr41) { + HANDLE_HBE_TRANSPOSER hQmfTran = NULL; + + int i; + + if (hQmfTransposer != NULL) { + /* Memory allocation */ + /*--------------------------------------------------------------------------------------------*/ + hQmfTran = + (HANDLE_HBE_TRANSPOSER)FDKcalloc(1, sizeof(struct hbeTransposer)); + if (hQmfTran == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + + for (i = 0; i < MAX_STRETCH_HBE - 1; i++) { + hQmfTran->bXProducts[i] = (bDisableCrossProducts ? 0 : xProducts[i]); + } + + hQmfTran->timeDomainWinLen = frameSize; + if (frameSize == 768) { + hQmfTran->noCols = + (8 * frameSize / 3) / QMF_SYNTH_CHANNELS; /* 32 for 24:64 */ + } else { + hQmfTran->noCols = + (bSbr41 + 1) * 2 * frameSize / + QMF_SYNTH_CHANNELS; /* 32 for 32:64 and 64 for 16:64 -> identical to + sbrdec->no_cols */ + } + + hQmfTran->noChannels = frameSize / hQmfTran->noCols; + + hQmfTran->qmfInBufSize = QMF_WIN_LEN; + hQmfTran->qmfOutBufSize = 2 * (hQmfTran->noCols / 2 + QMF_WIN_LEN - 1); + + hQmfTran->inBuf_F = + (INT_PCM*)FDKcalloc(QMF_SYNTH_CHANNELS + 20 + 1, sizeof(INT_PCM)); + /* buffered time signal needs to be delayed by synthesis_size; max + * synthesis_size = 20; */ + if (hQmfTran->inBuf_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + + hQmfTran->qmfInBufReal_F = + (FIXP_DBL**)FDKcalloc(hQmfTran->qmfInBufSize, sizeof(FIXP_DBL*)); + hQmfTran->qmfInBufImag_F = + (FIXP_DBL**)FDKcalloc(hQmfTran->qmfInBufSize, sizeof(FIXP_DBL*)); + + if (hQmfTran->qmfInBufReal_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + if (hQmfTran->qmfInBufImag_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + + for (i = 0; i < hQmfTran->qmfInBufSize; i++) { + hQmfTran->qmfInBufReal_F[i] = (FIXP_DBL*)FDKaalloc( + QMF_SYNTH_CHANNELS * sizeof(FIXP_DBL), ALIGNMENT_DEFAULT); + hQmfTran->qmfInBufImag_F[i] = (FIXP_DBL*)FDKaalloc( + QMF_SYNTH_CHANNELS * sizeof(FIXP_DBL), ALIGNMENT_DEFAULT); + if (hQmfTran->qmfInBufReal_F[i] == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + if (hQmfTran->qmfInBufImag_F[i] == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + } + + hQmfTran->qmfHBEBufReal_F = + (FIXP_DBL**)FDKcalloc(HBE_MAX_OUT_SLOTS, sizeof(FIXP_DBL*)); + hQmfTran->qmfHBEBufImag_F = + (FIXP_DBL**)FDKcalloc(HBE_MAX_OUT_SLOTS, sizeof(FIXP_DBL*)); + + if (hQmfTran->qmfHBEBufReal_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + if (hQmfTran->qmfHBEBufImag_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + + for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) { + hQmfTran->qmfHBEBufReal_F[i] = + (FIXP_DBL*)FDKcalloc(QMF_SYNTH_CHANNELS, sizeof(FIXP_DBL)); + hQmfTran->qmfHBEBufImag_F[i] = + (FIXP_DBL*)FDKcalloc(QMF_SYNTH_CHANNELS, sizeof(FIXP_DBL)); + if (hQmfTran->qmfHBEBufReal_F[i] == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + if (hQmfTran->qmfHBEBufImag_F[i] == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + } + + hQmfTran->qmfBufferCodecTempSlot_F = + (FIXP_DBL*)FDKcalloc(QMF_SYNTH_CHANNELS / 2, sizeof(FIXP_DBL)); + if (hQmfTran->qmfBufferCodecTempSlot_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + + hQmfTran->bSbr41 = bSbr41; + + hQmfTran->highband_exp[0] = 0; + hQmfTran->highband_exp[1] = 0; + hQmfTran->target_exp[0] = 0; + hQmfTran->target_exp[1] = 0; + + *hQmfTransposer = hQmfTran; + } + + return SBRDEC_OK; +} + +SBR_ERROR QmfTransposerReInit(HANDLE_HBE_TRANSPOSER hQmfTransposer, + UCHAR* FreqBandTable[2], UCHAR NSfb[2]) +/* removed bSbr41 from parameterlist: + don't know where to get this value from + at call-side */ +{ + int L, sfb, patch, stopPatch, qmfErr; + + if (hQmfTransposer != NULL) { + const FIXP_QTW* tmp_t_cos; + const FIXP_QTW* tmp_t_sin; + + hQmfTransposer->startBand = FreqBandTable[0][0]; + hQmfTransposer->stopBand = FreqBandTable[0][NSfb[0]]; + + hQmfTransposer->synthSize = + 4 * ((hQmfTransposer->startBand + 4) / 8 + 1); /* 8, 12, 16, 20 */ + hQmfTransposer->kstart = startSubband2kL[hQmfTransposer->startBand]; + + /* don't know where to take this information from */ + /* hQmfTransposer->bSbr41 = bSbr41; */ + + if (hQmfTransposer->bSbr41) { + if (hQmfTransposer->kstart + hQmfTransposer->synthSize > 16) + hQmfTransposer->kstart = 16 - hQmfTransposer->synthSize; + } else if (hQmfTransposer->timeDomainWinLen == 768) { + if (hQmfTransposer->kstart + hQmfTransposer->synthSize > 24) + hQmfTransposer->kstart = 24 - hQmfTransposer->synthSize; + } + + hQmfTransposer->synthesisQmfPreModCos_F = + &preModCos[hQmfTransposer->kstart]; + hQmfTransposer->synthesisQmfPreModSin_F = + &preModSin[hQmfTransposer->kstart]; + + L = 2 * hQmfTransposer->synthSize; /* 8, 16, 24, 32, 40 */ + /* Change analysis post twiddles */ + + switch (L) { + case 8: + tmp_t_cos = post_twiddle_cos_8; + tmp_t_sin = post_twiddle_sin_8; + break; + case 16: + tmp_t_cos = post_twiddle_cos_16; + tmp_t_sin = post_twiddle_sin_16; + break; + case 24: + tmp_t_cos = post_twiddle_cos_24; + tmp_t_sin = post_twiddle_sin_24; + break; + case 32: + tmp_t_cos = post_twiddle_cos_32; + tmp_t_sin = post_twiddle_sin_32; + break; + case 40: + tmp_t_cos = post_twiddle_cos_40; + tmp_t_sin = post_twiddle_sin_40; + break; + default: + return SBRDEC_UNSUPPORTED_CONFIG; + } + + qmfErr = qmfInitSynthesisFilterBank( + &hQmfTransposer->HBESynthesisQMF, hQmfTransposer->synQmfStates, + hQmfTransposer->noCols, 0, hQmfTransposer->synthSize, + hQmfTransposer->synthSize, 1); + if (qmfErr != 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + qmfErr = qmfInitAnalysisFilterBank( + &hQmfTransposer->HBEAnalysiscQMF, hQmfTransposer->anaQmfStates, + hQmfTransposer->noCols / 2, 0, 2 * hQmfTransposer->synthSize, + 2 * hQmfTransposer->synthSize, 0); + + if (qmfErr != 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + hQmfTransposer->HBEAnalysiscQMF.t_cos = tmp_t_cos; + hQmfTransposer->HBEAnalysiscQMF.t_sin = tmp_t_sin; + + FDKmemset(hQmfTransposer->xOverQmf, 0, + MAX_NUM_PATCHES * sizeof(int)); /* global */ + sfb = 0; + if (hQmfTransposer->bSbr41) { + stopPatch = MAX_NUM_PATCHES; + hQmfTransposer->maxStretch = MAX_STRETCH_HBE; + } else { + stopPatch = MAX_STRETCH_HBE; + } + + for (patch = 1; patch <= stopPatch; patch++) { + while (sfb <= NSfb[0] && + FreqBandTable[0][sfb] <= patch * hQmfTransposer->startBand) + sfb++; + if (sfb <= NSfb[0]) { + /* If the distance is larger than three QMF bands - try aligning to high + * resolution frequency bands instead. */ + if ((patch * hQmfTransposer->startBand - FreqBandTable[0][sfb - 1]) <= + 3) { + hQmfTransposer->xOverQmf[patch - 1] = FreqBandTable[0][sfb - 1]; + } else { + int sfb_tmp = 0; + while (sfb_tmp <= NSfb[1] && + FreqBandTable[1][sfb_tmp] <= patch * hQmfTransposer->startBand) + sfb_tmp++; + hQmfTransposer->xOverQmf[patch - 1] = FreqBandTable[1][sfb_tmp - 1]; + } + } else { + hQmfTransposer->xOverQmf[patch - 1] = hQmfTransposer->stopBand; + hQmfTransposer->maxStretch = fMin(patch, MAX_STRETCH_HBE); + break; + } + } + + hQmfTransposer->highband_exp[0] = 0; + hQmfTransposer->highband_exp[1] = 0; + hQmfTransposer->target_exp[0] = 0; + hQmfTransposer->target_exp[1] = 0; + } + + return SBRDEC_OK; +} + +void QmfTransposerClose(HANDLE_HBE_TRANSPOSER hQmfTransposer) { + int i; + + if (hQmfTransposer != NULL) { + if (hQmfTransposer->inBuf_F) FDKfree(hQmfTransposer->inBuf_F); + + if (hQmfTransposer->qmfInBufReal_F) { + for (i = 0; i < hQmfTransposer->qmfInBufSize; i++) { + FDKafree(hQmfTransposer->qmfInBufReal_F[i]); + } + FDKfree(hQmfTransposer->qmfInBufReal_F); + } + + if (hQmfTransposer->qmfInBufImag_F) { + for (i = 0; i < hQmfTransposer->qmfInBufSize; i++) { + FDKafree(hQmfTransposer->qmfInBufImag_F[i]); + } + FDKfree(hQmfTransposer->qmfInBufImag_F); + } + + if (hQmfTransposer->qmfHBEBufReal_F) { + for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) { + FDKfree(hQmfTransposer->qmfHBEBufReal_F[i]); + } + FDKfree(hQmfTransposer->qmfHBEBufReal_F); + } + + if (hQmfTransposer->qmfHBEBufImag_F) { + for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) { + FDKfree(hQmfTransposer->qmfHBEBufImag_F[i]); + } + FDKfree(hQmfTransposer->qmfHBEBufImag_F); + } + + FDKfree(hQmfTransposer->qmfBufferCodecTempSlot_F); + + FDKfree(hQmfTransposer); + } +} + +inline void scaleUp(FIXP_DBL* real_m, FIXP_DBL* imag_m, INT* _e) { + INT reserve; + /* shift gc_r and gc_i up if possible */ + reserve = CntLeadingZeros((INT(*real_m) ^ INT((*real_m >> 31))) | + (INT(*imag_m) ^ INT((*imag_m >> 31)))) - + 1; + reserve = fMax(reserve - 1, + 0); /* Leave one bit headroom such that (real_m^2 + imag_m^2) + does not overflow later if both are 0x80000000. */ + reserve = fMin(reserve, *_e); + FDK_ASSERT(reserve >= 0); + *real_m <<= reserve; + *imag_m <<= reserve; + *_e -= reserve; +} + +static void calculateCenterFIXP(FIXP_DBL gammaVecReal, FIXP_DBL gammaVecImag, + FIXP_DBL* centerReal, FIXP_DBL* centerImag, + INT* exponent, int stretch, int mult) { + scaleUp(&gammaVecReal, &gammaVecImag, exponent); + FIXP_DBL energy = fPow2Div2(gammaVecReal) + fPow2Div2(gammaVecImag); + + if (energy != FL2FXCONST_DBL(0.f)) { + FIXP_DBL gc_r_m, gc_i_m, factor_m = (FIXP_DBL)0; + INT factor_e, gc_e; + factor_e = 2 * (*exponent) + 1; + + switch (stretch) { + case 2: + factor_m = invFourthRootNorm2(energy, &factor_e); + break; + case 3: + factor_m = invCubeRootNorm2(energy, &factor_e); + break; + case 4: + factor_m = inv3EigthRootNorm2(energy, &factor_e); + break; + } + + gc_r_m = fMultDiv2(gammaVecReal, + factor_m); /* exponent = HBE_SCALE + factor_e + 1 */ + gc_i_m = fMultDiv2(gammaVecImag, + factor_m); /* exponent = HBE_SCALE + factor_e + 1*/ + gc_e = *exponent + factor_e + 1; + + scaleUp(&gc_r_m, &gc_i_m, &gc_e); + + switch (mult) { + case 0: + *centerReal = gc_r_m; + *centerImag = gc_i_m; + break; + case 1: + *centerReal = fPow2Div2(gc_r_m) - fPow2Div2(gc_i_m); + *centerImag = fMult(gc_r_m, gc_i_m); + gc_e = 2 * gc_e + 1; + break; + case 2: + FIXP_DBL tmp_r = gc_r_m; + FIXP_DBL tmp_i = gc_i_m; + gc_r_m = fPow2Div2(gc_r_m) - fPow2Div2(gc_i_m); + gc_i_m = fMult(tmp_r, gc_i_m); + gc_e = 3 * gc_e + 1 + 1; + cplxMultDiv2(¢erReal[0], ¢erImag[0], gc_r_m, gc_i_m, tmp_r, + tmp_i); + break; + } + + scaleUp(centerReal, centerImag, &gc_e); + + FDK_ASSERT(gc_e >= 0); + *exponent = gc_e; + } else { + *centerReal = energy; /* energy = 0 */ + *centerImag = energy; /* energy = 0 */ + *exponent = (INT)energy; + } +} + +static int getHBEScaleFactorFrame(const int bSbr41, const int maxStretch, + const int pitchInBins) { + if (pitchInBins >= pmin * (1 + bSbr41)) { + /* crossproducts enabled */ + return 26; + } else { + return (maxStretch == 2) ? 24 : 25; + } +} + +static void addHighBandPart(FIXP_DBL g_r_m, FIXP_DBL g_i_m, INT g_e, + FIXP_DBL mult, FIXP_DBL gammaCenterReal_m, + FIXP_DBL gammaCenterImag_m, INT gammaCenter_e, + INT stretch, INT scale_factor_hbe, + FIXP_DBL* qmfHBEBufReal_F, + FIXP_DBL* qmfHBEBufImag_F) { + if ((g_r_m | g_i_m) != FL2FXCONST_DBL(0.f)) { + FIXP_DBL factor_m = (FIXP_DBL)0; + INT factor_e; + INT add = (stretch == 4) ? 1 : 0; + INT shift = (stretch == 4) ? 1 : 2; + + scaleUp(&g_r_m, &g_i_m, &g_e); + FIXP_DBL energy = fPow2AddDiv2(fPow2Div2(g_r_m), g_i_m); + factor_e = 2 * g_e + 1; + + switch (stretch) { + case 2: + factor_m = invFourthRootNorm2(energy, &factor_e); + break; + case 3: + factor_m = invCubeRootNorm2(energy, &factor_e); + break; + case 4: + factor_m = inv3EigthRootNorm2(energy, &factor_e); + break; + } + + factor_m = fMult(factor_m, mult); + + FIXP_DBL tmp_r, tmp_i; + cplxMultDiv2(&tmp_r, &tmp_i, g_r_m, g_i_m, gammaCenterReal_m, + gammaCenterImag_m); + + g_r_m = fMultDiv2(tmp_r, factor_m) << shift; + g_i_m = fMultDiv2(tmp_i, factor_m) << shift; + g_e = scale_factor_hbe - (g_e + factor_e + gammaCenter_e + add); + fMax((INT)0, g_e); + *qmfHBEBufReal_F += g_r_m >> g_e; + *qmfHBEBufImag_F += g_i_m >> g_e; + } +} + +void QmfTransposerApply(HANDLE_HBE_TRANSPOSER hQmfTransposer, + FIXP_DBL** qmfBufferCodecReal, + FIXP_DBL** qmfBufferCodecImag, int nColsIn, + FIXP_DBL** ppQmfBufferOutReal_F, + FIXP_DBL** ppQmfBufferOutImag_F, + FIXP_DBL lpcFilterStatesReal[2 + (3 * (4))][(64)], + FIXP_DBL lpcFilterStatesImag[2 + (3 * (4))][(64)], + int pitchInBins, int scale_lb, int scale_hbe, + int* scale_hb, int timeStep, int firstSlotOffsset, + int ov_len, + KEEP_STATES_SYNCED_MODE keepStatesSyncedMode) { + int i, j, stretch, band, sourceband, r, s; + int qmfVocoderColsIn = hQmfTransposer->noCols / 2; + int bSbr41 = hQmfTransposer->bSbr41; + + const int winLength[3] = {10, 8, 6}; + const int slotOffset = 6; /* hQmfTransposer->winLen-6; */ + + int qmfOffset = 2 * hQmfTransposer->kstart; + int scale_border = (nColsIn == 64) ? 32 : nColsIn; + + INT slot_stretch4[9] = {0, 0, 0, 0, 2, 4, 6, 8, 10}; + INT slot_stretch2[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + INT slot_stretch3[10] = {0, 0, 0, 1, 3, 4, 6, 7, 9, 10}; + INT filt_stretch3[10] = {0, 0, 0, 1, 0, 1, 0, 1, 0, 1}; + INT filt_dummy[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + INT* pSlotStretch; + INT* pFilt; + + int offset = 0; /* where to take QmfTransposer data */ + + int signPreMod = + (hQmfTransposer->synthesisQmfPreModCos_F[0] < FL2FXCONST_DBL(0.f)) ? 1 + : -1; + + int scale_factor_hbe = + getHBEScaleFactorFrame(bSbr41, hQmfTransposer->maxStretch, pitchInBins); + + if (keepStatesSyncedMode != KEEP_STATES_SYNCED_OFF) { + offset = hQmfTransposer->noCols - ov_len - LPC_ORDER; + } + + hQmfTransposer->highband_exp[0] = hQmfTransposer->highband_exp[1]; + hQmfTransposer->target_exp[0] = hQmfTransposer->target_exp[1]; + + hQmfTransposer->highband_exp[1] = scale_factor_hbe; + hQmfTransposer->target_exp[1] = + fixMax(hQmfTransposer->highband_exp[1], hQmfTransposer->highband_exp[0]); + + scale_factor_hbe = hQmfTransposer->target_exp[1]; + + int shift_ov = hQmfTransposer->target_exp[0] - hQmfTransposer->target_exp[1]; + + if (shift_ov != 0) { + for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) { + for (band = 0; band < QMF_SYNTH_CHANNELS; band++) { + if (shift_ov >= 0) { + hQmfTransposer->qmfHBEBufReal_F[i][band] <<= shift_ov; + hQmfTransposer->qmfHBEBufImag_F[i][band] <<= shift_ov; + } else { + hQmfTransposer->qmfHBEBufReal_F[i][band] >>= (-shift_ov); + hQmfTransposer->qmfHBEBufImag_F[i][band] >>= (-shift_ov); + } + } + } + } + + if ((keepStatesSyncedMode == KEEP_STATES_SYNCED_OFF) && shift_ov != 0) { + for (i = timeStep * firstSlotOffsset; i < ov_len; i++) { + for (band = hQmfTransposer->startBand; band < hQmfTransposer->stopBand; + band++) { + if (shift_ov >= 0) { + ppQmfBufferOutReal_F[i][band] <<= shift_ov; + ppQmfBufferOutImag_F[i][band] <<= shift_ov; + } else { + ppQmfBufferOutReal_F[i][band] >>= (-shift_ov); + ppQmfBufferOutImag_F[i][band] >>= (-shift_ov); + } + } + } + + /* shift lpc filterstates */ + for (i = 0; i < timeStep * firstSlotOffsset + LPC_ORDER; i++) { + for (band = 0; band < (64); band++) { + if (shift_ov >= 0) { + lpcFilterStatesReal[i][band] <<= shift_ov; + lpcFilterStatesImag[i][band] <<= shift_ov; + } else { + lpcFilterStatesReal[i][band] >>= (-shift_ov); + lpcFilterStatesImag[i][band] >>= (-shift_ov); + } + } + } + } + + FIXP_DBL twid_m_new[3][2]; /* [stretch][cos/sin] */ + INT stepsize = 1 + !bSbr41, sine_offset = 24, mod = 96; + INT mult[3] = {1, 2, 3}; + + for (s = 0; s <= MAX_STRETCH_HBE - 2; s++) { + twid_m_new[s][0] = twiddle[(mult[s] * (stepsize * pitchInBins)) % mod]; + twid_m_new[s][1] = + twiddle[((mult[s] * (stepsize * pitchInBins)) + sine_offset) % mod]; + } + + /* Time-stretch */ + for (j = 0; j < qmfVocoderColsIn; j++) { + int sign = -1, k, z, addrshift, codecTemp_e; + /* update inbuf */ + for (i = 0; i < hQmfTransposer->synthSize; i++) { + hQmfTransposer->inBuf_F[i] = + hQmfTransposer->inBuf_F[i + 2 * hQmfTransposer->synthSize]; + } + + /* run synthesis for two sbr slots as transposer uses + half slots double bands representation */ + for (z = 0; z < 2; z++) { + int scale_factor = ((nColsIn == 64) && ((2 * j + z) < scale_border)) + ? scale_lb + : scale_hbe; + codecTemp_e = scale_factor - 1; /* -2 for Div2 and cos/sin scale of 1 */ + + for (k = 0; k < hQmfTransposer->synthSize; k++) { + int ki = hQmfTransposer->kstart + k; + hQmfTransposer->qmfBufferCodecTempSlot_F[k] = + fMultDiv2(signPreMod * hQmfTransposer->synthesisQmfPreModCos_F[k], + qmfBufferCodecReal[2 * j + z][ki]); + hQmfTransposer->qmfBufferCodecTempSlot_F[k] += + fMultDiv2(signPreMod * hQmfTransposer->synthesisQmfPreModSin_F[k], + qmfBufferCodecImag[2 * j + z][ki]); + } + + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, (HBE_MAX_QMF_BANDS << 1)); + + qmfSynthesisFilteringSlot( + &hQmfTransposer->HBESynthesisQMF, + hQmfTransposer->qmfBufferCodecTempSlot_F, NULL, 0, + -7 - hQmfTransposer->HBESynthesisQMF.filterScale - codecTemp_e + 1, + hQmfTransposer->inBuf_F + hQmfTransposer->synthSize * (z + 1), 1, + pWorkBuffer); + + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (HBE_MAX_QMF_BANDS << 1)); + } + + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, (HBE_MAX_QMF_BANDS << 1)); + + qmfAnalysisFilteringSlot(&hQmfTransposer->HBEAnalysiscQMF, + hQmfTransposer->qmfInBufReal_F[QMF_WIN_LEN - 1], + hQmfTransposer->qmfInBufImag_F[QMF_WIN_LEN - 1], + hQmfTransposer->inBuf_F + 1, 1, pWorkBuffer); + + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (HBE_MAX_QMF_BANDS << 1)); + + if ((keepStatesSyncedMode == KEEP_STATES_SYNCED_NORMAL) && + j <= qmfVocoderColsIn - ((LPC_ORDER + ov_len + QMF_WIN_LEN - 1) >> 1)) { + /* update in buffer */ + for (i = 0; i < QMF_WIN_LEN - 1; i++) { + FDKmemcpy( + hQmfTransposer->qmfInBufReal_F[i], + hQmfTransposer->qmfInBufReal_F[i + 1], + sizeof(FIXP_DBL) * hQmfTransposer->HBEAnalysiscQMF.no_channels); + FDKmemcpy( + hQmfTransposer->qmfInBufImag_F[i], + hQmfTransposer->qmfInBufImag_F[i + 1], + sizeof(FIXP_DBL) * hQmfTransposer->HBEAnalysiscQMF.no_channels); + } + continue; + } + + for (stretch = 2; stretch <= hQmfTransposer->maxStretch; stretch++) { + int start = slotOffset - winLength[stretch - 2] / 2; + int stop = slotOffset + winLength[stretch - 2] / 2; + + FIXP_DBL factor = FL2FXCONST_DBL(1.f / 3.f); + + for (band = hQmfTransposer->xOverQmf[stretch - 2]; + band < hQmfTransposer->xOverQmf[stretch - 1]; band++) { + FIXP_DBL gammaCenterReal_m[2] = {(FIXP_DBL)0, (FIXP_DBL)0}, + gammaCenterImag_m[2] = {(FIXP_DBL)0, (FIXP_DBL)0}; + INT gammaCenter_e[2] = {0, 0}; + + FIXP_DBL gammaVecReal_m[2] = {(FIXP_DBL)0, (FIXP_DBL)0}, + gammaVecImag_m[2] = {(FIXP_DBL)0, (FIXP_DBL)0}; + INT gammaVec_e[2] = {0, 0}; + + FIXP_DBL wingain = (FIXP_DBL)0; + + gammaCenter_e[0] = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + gammaCenter_e[1] = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + /* interpolation filters for 3rd order */ + sourceband = 2 * band / stretch - qmfOffset; + FDK_ASSERT(sourceband >= 0); + + /* maximum gammaCenter_e == 20 */ + calculateCenterFIXP( + hQmfTransposer->qmfInBufReal_F[slotOffset][sourceband], + hQmfTransposer->qmfInBufImag_F[slotOffset][sourceband], + &gammaCenterReal_m[0], &gammaCenterImag_m[0], &gammaCenter_e[0], + stretch, stretch - 2); + + if (stretch == 4) { + r = band - 2 * (band / 2); + sourceband += (r == 0) ? -1 : 1; + pSlotStretch = slot_stretch4; + factor = FL2FXCONST_DBL(2.f / 3.f); + pFilt = filt_dummy; + } else if (stretch == 2) { + r = 0; + sourceband = 2 * band / stretch - qmfOffset; + pSlotStretch = slot_stretch2; + factor = FL2FXCONST_DBL(1.f / 3.f); + pFilt = filt_dummy; + } else { + r = 2 * band - 3 * (2 * band / 3); + sourceband = 2 * band / stretch - qmfOffset; + pSlotStretch = slot_stretch3; + factor = FL2FXCONST_DBL(1.4142f / 3.0f); + pFilt = filt_stretch3; + } + + if (r == 2) { + calculateCenterFIXP( + hQmfTransposer->qmfInBufReal_F[slotOffset][sourceband + 1], + hQmfTransposer->qmfInBufImag_F[slotOffset][sourceband + 1], + &gammaCenterReal_m[1], &gammaCenterImag_m[1], &gammaCenter_e[1], + stretch, stretch - 2); + + factor = FL2FXCONST_DBL(1.4142f / 6.0f); + } + + if (r == 2) { + for (k = start; k < stop; k++) { + gammaVecReal_m[0] = + hQmfTransposer->qmfInBufReal_F[pSlotStretch[k]][sourceband]; + gammaVecReal_m[1] = + hQmfTransposer->qmfInBufReal_F[pSlotStretch[k]][sourceband + 1]; + gammaVecImag_m[0] = + hQmfTransposer->qmfInBufImag_F[pSlotStretch[k]][sourceband]; + gammaVecImag_m[1] = + hQmfTransposer->qmfInBufImag_F[pSlotStretch[k]][sourceband + 1]; + gammaVec_e[0] = gammaVec_e[1] = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + if (pFilt[k] == 1) { + FIXP_DBL tmpRealF = gammaVecReal_m[0], tmpImagF; + gammaVecReal_m[0] = + (fMult(gammaVecReal_m[0], hintReal_F[sourceband % 4][1]) - + fMult(gammaVecImag_m[0], + hintReal_F[(sourceband + 3) % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVecImag_m[0] = + (fMult(tmpRealF, hintReal_F[(sourceband + 3) % 4][1]) + + fMult(gammaVecImag_m[0], hintReal_F[sourceband % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + + tmpRealF = hQmfTransposer + ->qmfInBufReal_F[pSlotStretch[k] + 1][sourceband]; + tmpImagF = hQmfTransposer + ->qmfInBufImag_F[pSlotStretch[k] + 1][sourceband]; + + gammaVecReal_m[0] += + (fMult(tmpRealF, hintReal_F[sourceband % 4][1]) - + fMult(tmpImagF, hintReal_F[(sourceband + 1) % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVecImag_m[0] += + (fMult(tmpRealF, hintReal_F[(sourceband + 1) % 4][1]) + + fMult(tmpImagF, hintReal_F[sourceband % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVec_e[0]++; + + tmpRealF = gammaVecReal_m[1]; + + gammaVecReal_m[1] = + (fMult(gammaVecReal_m[1], hintReal_F[sourceband % 4][2]) - + fMult(gammaVecImag_m[1], + hintReal_F[(sourceband + 3) % 4][2])) >> + 1; + gammaVecImag_m[1] = + (fMult(tmpRealF, hintReal_F[(sourceband + 3) % 4][2]) + + fMult(gammaVecImag_m[1], hintReal_F[sourceband % 4][2])) >> + 1; + + tmpRealF = + hQmfTransposer + ->qmfInBufReal_F[pSlotStretch[k] + 1][sourceband + 1]; + tmpImagF = + hQmfTransposer + ->qmfInBufImag_F[pSlotStretch[k] + 1][sourceband + 1]; + + gammaVecReal_m[1] += + (fMult(tmpRealF, hintReal_F[sourceband % 4][2]) - + fMult(tmpImagF, hintReal_F[(sourceband + 1) % 4][2])) >> + 1; + gammaVecImag_m[1] += + (fMult(tmpRealF, hintReal_F[(sourceband + 1) % 4][2]) + + fMult(tmpImagF, hintReal_F[sourceband % 4][2])) >> + 1; + gammaVec_e[1]++; + } + + addHighBandPart(gammaVecReal_m[1], gammaVecImag_m[1], gammaVec_e[1], + factor, gammaCenterReal_m[0], gammaCenterImag_m[0], + gammaCenter_e[0], stretch, scale_factor_hbe, + &hQmfTransposer->qmfHBEBufReal_F[k][band], + &hQmfTransposer->qmfHBEBufImag_F[k][band]); + + addHighBandPart(gammaVecReal_m[0], gammaVecImag_m[0], gammaVec_e[0], + factor, gammaCenterReal_m[1], gammaCenterImag_m[1], + gammaCenter_e[1], stretch, scale_factor_hbe, + &hQmfTransposer->qmfHBEBufReal_F[k][band], + &hQmfTransposer->qmfHBEBufImag_F[k][band]); + } + } else { + for (k = start; k < stop; k++) { + gammaVecReal_m[0] = + hQmfTransposer->qmfInBufReal_F[pSlotStretch[k]][sourceband]; + gammaVecImag_m[0] = + hQmfTransposer->qmfInBufImag_F[pSlotStretch[k]][sourceband]; + gammaVec_e[0] = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + if (pFilt[k] == 1) { + FIXP_DBL tmpRealF = gammaVecReal_m[0], tmpImagF; + gammaVecReal_m[0] = + (fMult(gammaVecReal_m[0], hintReal_F[sourceband % 4][1]) - + fMult(gammaVecImag_m[0], + hintReal_F[(sourceband + 3) % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVecImag_m[0] = + (fMult(tmpRealF, hintReal_F[(sourceband + 3) % 4][1]) + + fMult(gammaVecImag_m[0], hintReal_F[sourceband % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + + tmpRealF = hQmfTransposer + ->qmfInBufReal_F[pSlotStretch[k] + 1][sourceband]; + tmpImagF = hQmfTransposer + ->qmfInBufImag_F[pSlotStretch[k] + 1][sourceband]; + + gammaVecReal_m[0] += + (fMult(tmpRealF, hintReal_F[sourceband % 4][1]) - + fMult(tmpImagF, hintReal_F[(sourceband + 1) % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVecImag_m[0] += + (fMult(tmpRealF, hintReal_F[(sourceband + 1) % 4][1]) + + fMult(tmpImagF, hintReal_F[sourceband % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVec_e[0]++; + } + + addHighBandPart(gammaVecReal_m[0], gammaVecImag_m[0], gammaVec_e[0], + factor, gammaCenterReal_m[0], gammaCenterImag_m[0], + gammaCenter_e[0], stretch, scale_factor_hbe, + &hQmfTransposer->qmfHBEBufReal_F[k][band], + &hQmfTransposer->qmfHBEBufImag_F[k][band]); + } + } + + /* pitchInBins is given with the resolution of a 768 bins FFT and we + * need 64 QMF units so factor 768/64 = 12 */ + if (pitchInBins >= pmin * (1 + bSbr41)) { + int tr, ti1, ti2, mTr = 0, ts1 = 0, ts2 = 0, mVal_e = 0, temp_e = 0; + int sqmag0_e = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + FIXP_DBL mVal_F = FL2FXCONST_DBL(0.f), sqmag0_F, sqmag1_F, sqmag2_F, + temp_F, f1_F; /* all equal exponent */ + sign = -1; + + sourceband = 2 * band / stretch - qmfOffset; /* consistent with the + already computed for + stretch = 3,4. */ + FDK_ASSERT(sourceband >= 0); + + FIXP_DBL sqmag0R_F = + hQmfTransposer->qmfInBufReal_F[slotOffset][sourceband]; + FIXP_DBL sqmag0I_F = + hQmfTransposer->qmfInBufImag_F[slotOffset][sourceband]; + scaleUp(&sqmag0R_F, &sqmag0I_F, &sqmag0_e); + + sqmag0_F = fPow2Div2(sqmag0R_F); + sqmag0_F += fPow2Div2(sqmag0I_F); + sqmag0_e = 2 * sqmag0_e + 1; + + for (tr = 1; tr < stretch; tr++) { + int sqmag1_e = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + int sqmag2_e = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + FIXP_DBL tmp_band = band_F[band]; + FIXP_DBL tr_p = + fMult(p_F[pitchInBins] >> bSbr41, tr_str[tr - 1]); /* scale 7 */ + f1_F = + fMult(tmp_band - tr_p, stretchfac[stretch - 2]); /* scale 7 */ + ti1 = (INT)(f1_F >> (DFRACT_BITS - 1 - 7)) - qmfOffset; + ti2 = (INT)(((f1_F) + ((p_F[pitchInBins] >> bSbr41) >> 2)) >> + (DFRACT_BITS - 1 - 7)) - + qmfOffset; + + if (ti1 >= 0 && ti2 < 2 * hQmfTransposer->synthSize) { + FIXP_DBL sqmag1R_F = + hQmfTransposer->qmfInBufReal_F[slotOffset][ti1]; + FIXP_DBL sqmag1I_F = + hQmfTransposer->qmfInBufImag_F[slotOffset][ti1]; + scaleUp(&sqmag1R_F, &sqmag1I_F, &sqmag1_e); + sqmag1_F = fPow2Div2(sqmag1R_F); + sqmag1_F += fPow2Div2(sqmag1I_F); + sqmag1_e = 2 * sqmag1_e + 1; + + FIXP_DBL sqmag2R_F = + hQmfTransposer->qmfInBufReal_F[slotOffset][ti2]; + FIXP_DBL sqmag2I_F = + hQmfTransposer->qmfInBufImag_F[slotOffset][ti2]; + scaleUp(&sqmag2R_F, &sqmag2I_F, &sqmag2_e); + sqmag2_F = fPow2Div2(sqmag2R_F); + sqmag2_F += fPow2Div2(sqmag2I_F); + sqmag2_e = 2 * sqmag2_e + 1; + + int shift1 = fMin(fMax(sqmag1_e, sqmag2_e) - sqmag1_e, 31); + int shift2 = fMin(fMax(sqmag1_e, sqmag2_e) - sqmag2_e, 31); + + temp_F = fMin((sqmag1_F >> shift1), (sqmag2_F >> shift2)); + temp_e = fMax(sqmag1_e, sqmag2_e); + + int shift3 = fMin(fMax(temp_e, mVal_e) - temp_e, 31); + int shift4 = fMin(fMax(temp_e, mVal_e) - mVal_e, 31); + + if ((temp_F >> shift3) > (mVal_F >> shift4)) { + mVal_F = temp_F; + mVal_e = temp_e; /* equals sqmag2_e + shift2 */ + mTr = tr; + ts1 = ti1; + ts2 = ti2; + } + } + } + + int shift1 = fMin(fMax(sqmag0_e, mVal_e) - sqmag0_e, 31); + int shift2 = fMin(fMax(sqmag0_e, mVal_e) - mVal_e, 31); + + if ((mVal_F >> shift2) > (sqmag0_F >> shift1) && ts1 >= 0 && + ts2 < 2 * hQmfTransposer->synthSize) { + INT gammaOut_e[2]; + FIXP_DBL gammaOutReal_m[2], gammaOutImag_m[2]; + FIXP_DBL tmpReal_m = (FIXP_DBL)0, tmpImag_m = (FIXP_DBL)0; + + int Tcenter, Tvec; + + Tcenter = stretch - mTr; /* default phase power parameters */ + Tvec = mTr; + switch (stretch) /* 2 tap block creation design depends on stretch + order */ + { + case 2: + wingain = + FL2FXCONST_DBL(5.f / 12.f); /* sum of taps divided by two */ + + if (hQmfTransposer->bXProducts[0]) { + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + + for (k = 0; k < 2; k++) { + gammaVecReal_m[k] = + hQmfTransposer->qmfInBufReal_F[slotOffset - 1 + k][ts2]; + gammaVecImag_m[k] = + hQmfTransposer->qmfInBufImag_F[slotOffset - 1 + k][ts2]; + } + + gammaCenter_e[0] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + gammaVec_e[0] = gammaVec_e[1] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + } + break; + + case 4: + wingain = + FL2FXCONST_DBL(6.f / 12.f); /* sum of taps divided by two */ + if (hQmfTransposer->bXProducts[2]) { + if (mTr == 1) { + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + + for (k = 0; k < 2; k++) { + gammaVecReal_m[k] = + hQmfTransposer + ->qmfInBufReal_F[slotOffset + 2 * (k - 1)][ts2]; + gammaVecImag_m[k] = + hQmfTransposer + ->qmfInBufImag_F[slotOffset + 2 * (k - 1)][ts2]; + } + } else if (mTr == 2) { + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + + for (k = 0; k < 2; k++) { + gammaVecReal_m[k] = + hQmfTransposer + ->qmfInBufReal_F[slotOffset + (k - 1)][ts2]; + gammaVecImag_m[k] = + hQmfTransposer + ->qmfInBufImag_F[slotOffset + (k - 1)][ts2]; + } + } else /* (mTr == 3) */ + { + sign = 1; + Tcenter = mTr; /* opposite phase power parameters as ts2 is + center */ + Tvec = stretch - mTr; + + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts2]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts2]; + + for (k = 0; k < 2; k++) { + gammaVecReal_m[k] = + hQmfTransposer + ->qmfInBufReal_F[slotOffset + 2 * (k - 1)][ts1]; + gammaVecImag_m[k] = + hQmfTransposer + ->qmfInBufImag_F[slotOffset + 2 * (k - 1)][ts1]; + } + } + + gammaCenter_e[0] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + gammaVec_e[0] = gammaVec_e[1] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + } + break; + + case 3: + wingain = FL2FXCONST_DBL(5.6568f / + 12.f); /* sum of taps divided by two */ + + if (hQmfTransposer->bXProducts[1]) { + FIXP_DBL tmpReal_F, tmpImag_F; + if (mTr == 1) { + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + gammaVecReal_m[1] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts2]; + gammaVecImag_m[1] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts2]; + + addrshift = -2; + tmpReal_F = + hQmfTransposer + ->qmfInBufReal_F[addrshift + slotOffset][ts2]; + tmpImag_F = + hQmfTransposer + ->qmfInBufImag_F[addrshift + slotOffset][ts2]; + + gammaVecReal_m[0] = + (fMult(factors[ts2 % 4], tmpReal_F) - + fMult(factors[(ts2 + 3) % 4], tmpImag_F)) >> + 1; + gammaVecImag_m[0] = + (fMult(factors[(ts2 + 3) % 4], tmpReal_F) + + fMult(factors[ts2 % 4], tmpImag_F)) >> + 1; + + tmpReal_F = + hQmfTransposer + ->qmfInBufReal_F[addrshift + 1 + slotOffset][ts2]; + tmpImag_F = + hQmfTransposer + ->qmfInBufImag_F[addrshift + 1 + slotOffset][ts2]; + + gammaVecReal_m[0] += + (fMult(factors[ts2 % 4], tmpReal_F) - + fMult(factors[(ts2 + 1) % 4], tmpImag_F)) >> + 1; + gammaVecImag_m[0] += + (fMult(factors[(ts2 + 1) % 4], tmpReal_F) + + fMult(factors[ts2 % 4], tmpImag_F)) >> + 1; + + } else /* (mTr == 2) */ + { + sign = 1; + Tcenter = mTr; /* opposite phase power parameters as ts2 is + center */ + Tvec = stretch - mTr; + + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts2]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts2]; + gammaVecReal_m[1] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaVecImag_m[1] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + + addrshift = -2; + tmpReal_F = + hQmfTransposer + ->qmfInBufReal_F[addrshift + slotOffset][ts1]; + tmpImag_F = + hQmfTransposer + ->qmfInBufImag_F[addrshift + slotOffset][ts1]; + + gammaVecReal_m[0] = + (fMult(factors[ts1 % 4], tmpReal_F) - + fMult(factors[(ts1 + 3) % 4], tmpImag_F)) >> + 1; + gammaVecImag_m[0] = + (fMult(factors[(ts1 + 3) % 4], tmpReal_F) + + fMult(factors[ts1 % 4], tmpImag_F)) >> + 1; + + tmpReal_F = + hQmfTransposer + ->qmfInBufReal_F[addrshift + 1 + slotOffset][ts1]; + tmpImag_F = + hQmfTransposer + ->qmfInBufImag_F[addrshift + 1 + slotOffset][ts1]; + + gammaVecReal_m[0] += + (fMult(factors[ts1 % 4], tmpReal_F) - + fMult(factors[(ts1 + 1) % 4], tmpImag_F)) >> + 1; + gammaVecImag_m[0] += + (fMult(factors[(ts1 + 1) % 4], tmpReal_F) + + fMult(factors[ts1 % 4], tmpImag_F)) >> + 1; + } + + gammaCenter_e[0] = gammaVec_e[1] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + gammaVec_e[0] = + SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor) + + 1; + } + break; + default: + FDK_ASSERT(0); + break; + } /* stretch cases */ + + /* parameter controlled phase modification parts */ + /* maximum *_e == 20 */ + calculateCenterFIXP(gammaCenterReal_m[0], gammaCenterImag_m[0], + &gammaCenterReal_m[0], &gammaCenterImag_m[0], + &gammaCenter_e[0], stretch, Tcenter - 1); + calculateCenterFIXP(gammaVecReal_m[0], gammaVecImag_m[0], + &gammaVecReal_m[0], &gammaVecImag_m[0], + &gammaVec_e[0], stretch, Tvec - 1); + calculateCenterFIXP(gammaVecReal_m[1], gammaVecImag_m[1], + &gammaVecReal_m[1], &gammaVecImag_m[1], + &gammaVec_e[1], stretch, Tvec - 1); + + /* Final multiplication of prepared parts */ + for (k = 0; k < 2; k++) { + gammaOutReal_m[k] = + fMultDiv2(gammaVecReal_m[k], gammaCenterReal_m[0]) - + fMultDiv2(gammaVecImag_m[k], gammaCenterImag_m[0]); + gammaOutImag_m[k] = + fMultDiv2(gammaVecReal_m[k], gammaCenterImag_m[0]) + + fMultDiv2(gammaVecImag_m[k], gammaCenterReal_m[0]); + gammaOut_e[k] = gammaCenter_e[0] + gammaVec_e[k] + 1; + } + + scaleUp(&gammaOutReal_m[0], &gammaOutImag_m[0], &gammaOut_e[0]); + scaleUp(&gammaOutReal_m[1], &gammaOutImag_m[1], &gammaOut_e[1]); + FDK_ASSERT(gammaOut_e[0] >= 0); + FDK_ASSERT(gammaOut_e[0] < 32); + + tmpReal_m = gammaOutReal_m[0]; + tmpImag_m = gammaOutImag_m[0]; + + INT modstretch4 = ((stretch == 4) && (mTr == 2)); + + FIXP_DBL cos_twid = twid_m_new[stretch - 2 - modstretch4][0]; + FIXP_DBL sin_twid = sign * twid_m_new[stretch - 2 - modstretch4][1]; + + gammaOutReal_m[0] = + fMult(tmpReal_m, cos_twid) - + fMult(tmpImag_m, sin_twid); /* sum should be <= 1 because of + sin/cos multiplication */ + gammaOutImag_m[0] = + fMult(tmpImag_m, cos_twid) + + fMult(tmpReal_m, sin_twid); /* sum should be <= 1 because of + sin/cos multiplication */ + + /* wingain */ + for (k = 0; k < 2; k++) { + gammaOutReal_m[k] = (fMult(gammaOutReal_m[k], wingain) << 1); + gammaOutImag_m[k] = (fMult(gammaOutImag_m[k], wingain) << 1); + } + + gammaOutReal_m[1] >>= 1; + gammaOutImag_m[1] >>= 1; + gammaOut_e[0] += 2; + gammaOut_e[1] += 2; + + /* OLA including window scaling by wingain/3 */ + for (k = 0; k < 2; k++) /* need k=1 to correspond to + grainModImag[slotOffset] -> out to + j*2+(slotOffset-offset) */ + { + hQmfTransposer->qmfHBEBufReal_F[(k + slotOffset - 1)][band] += + gammaOutReal_m[k] >> (scale_factor_hbe - gammaOut_e[k]); + hQmfTransposer->qmfHBEBufImag_F[(k + slotOffset - 1)][band] += + gammaOutImag_m[k] >> (scale_factor_hbe - gammaOut_e[k]); + } + } /* mVal > qThrQMF * qThrQMF * sqmag0 && ts1 > 0 && ts2 < 64 */ + } /* p >= pmin */ + } /* for band */ + } /* for stretch */ + + for (i = 0; i < QMF_WIN_LEN - 1; i++) { + FDKmemcpy(hQmfTransposer->qmfInBufReal_F[i], + hQmfTransposer->qmfInBufReal_F[i + 1], + sizeof(FIXP_DBL) * hQmfTransposer->HBEAnalysiscQMF.no_channels); + FDKmemcpy(hQmfTransposer->qmfInBufImag_F[i], + hQmfTransposer->qmfInBufImag_F[i + 1], + sizeof(FIXP_DBL) * hQmfTransposer->HBEAnalysiscQMF.no_channels); + } + + if (keepStatesSyncedMode != KEEP_STATES_SYNCED_NOOUT) { + if (2 * j >= offset) { + /* copy first two slots of internal buffer to output */ + if (keepStatesSyncedMode == KEEP_STATES_SYNCED_OUTDIFF) { + for (i = 0; i < 2; i++) { + FDKmemcpy(&ppQmfBufferOutReal_F[2 * j - offset + i] + [hQmfTransposer->xOverQmf[0]], + &hQmfTransposer + ->qmfHBEBufReal_F[i][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + FDKmemcpy(&ppQmfBufferOutImag_F[2 * j - offset + i] + [hQmfTransposer->xOverQmf[0]], + &hQmfTransposer + ->qmfHBEBufImag_F[i][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + } + } else { + for (i = 0; i < 2; i++) { + FDKmemcpy(&ppQmfBufferOutReal_F[2 * j + i + ov_len] + [hQmfTransposer->xOverQmf[0]], + &hQmfTransposer + ->qmfHBEBufReal_F[i][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + FDKmemcpy(&ppQmfBufferOutImag_F[2 * j + i + ov_len] + [hQmfTransposer->xOverQmf[0]], + &hQmfTransposer + ->qmfHBEBufImag_F[i][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + } + } + } + } + + /* move slots up */ + for (i = 0; i < HBE_MAX_OUT_SLOTS - 2; i++) { + FDKmemcpy( + &hQmfTransposer->qmfHBEBufReal_F[i][hQmfTransposer->xOverQmf[0]], + &hQmfTransposer->qmfHBEBufReal_F[i + 2][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + FDKmemcpy( + &hQmfTransposer->qmfHBEBufImag_F[i][hQmfTransposer->xOverQmf[0]], + &hQmfTransposer->qmfHBEBufImag_F[i + 2][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + } + + /* finally set last two slot to zero */ + for (i = 0; i < 2; i++) { + FDKmemset(&hQmfTransposer->qmfHBEBufReal_F[HBE_MAX_OUT_SLOTS - 1 - i] + [hQmfTransposer->xOverQmf[0]], + 0, + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + FDKmemset(&hQmfTransposer->qmfHBEBufImag_F[HBE_MAX_OUT_SLOTS - 1 - i] + [hQmfTransposer->xOverQmf[0]], + 0, + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + } + } /* qmfVocoderColsIn */ + + if (keepStatesSyncedMode != KEEP_STATES_SYNCED_NOOUT) { + if (keepStatesSyncedMode == KEEP_STATES_SYNCED_OUTDIFF) { + for (i = 0; i < ov_len + LPC_ORDER; i++) { + for (band = hQmfTransposer->startBand; band < hQmfTransposer->stopBand; + band++) { + FIXP_DBL tmpR = ppQmfBufferOutReal_F[i][band]; + FIXP_DBL tmpI = ppQmfBufferOutImag_F[i][band]; + + ppQmfBufferOutReal_F[i][band] = + fMult(tmpR, cos_F[band]) - + fMult(tmpI, (-cos_F[64 - band - 1])); /* sum should be <= 1 + because of sin/cos + multiplication */ + ppQmfBufferOutImag_F[i][band] = + fMult(tmpR, (-cos_F[64 - band - 1])) + + fMult(tmpI, cos_F[band]); /* sum should by <= 1 because of sin/cos + multiplication */ + } + } + } else { + for (i = offset; i < hQmfTransposer->noCols; i++) { + for (band = hQmfTransposer->startBand; band < hQmfTransposer->stopBand; + band++) { + FIXP_DBL tmpR = ppQmfBufferOutReal_F[i + ov_len][band]; + FIXP_DBL tmpI = ppQmfBufferOutImag_F[i + ov_len][band]; + + ppQmfBufferOutReal_F[i + ov_len][band] = + fMult(tmpR, cos_F[band]) - + fMult(tmpI, (-cos_F[64 - band - 1])); /* sum should be <= 1 + because of sin/cos + multiplication */ + ppQmfBufferOutImag_F[i + ov_len][band] = + fMult(tmpR, (-cos_F[64 - band - 1])) + + fMult(tmpI, cos_F[band]); /* sum should by <= 1 because of sin/cos + multiplication */ + } + } + } + } + + *scale_hb = EXP2SCALE(scale_factor_hbe); +} + +int* GetxOverBandQmfTransposer(HANDLE_HBE_TRANSPOSER hQmfTransposer) { + if (hQmfTransposer) + return hQmfTransposer->xOverQmf; + else + return NULL; +} + +int Get41SbrQmfTransposer(HANDLE_HBE_TRANSPOSER hQmfTransposer) { + if (hQmfTransposer != NULL) + return hQmfTransposer->bSbr41; + else + return 0; +} diff --git a/libSBRdec/src/hbe.h b/libSBRdec/src/hbe.h new file mode 100644 index 0000000..fdffe1e --- /dev/null +++ b/libSBRdec/src/hbe.h @@ -0,0 +1,200 @@ +/* ----------------------------------------------------------------------------- +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: + +*******************************************************************************/ + +#ifndef HBE_H +#define HBE_H + +#include "sbrdecoder.h" + +#ifndef QMF_SYNTH_CHANNELS +#define QMF_SYNTH_CHANNELS (64) +#endif + +#define HBE_QMF_FILTER_STATE_ANA_SIZE (400) +#define HBE_QMF_FILTER_STATE_SYN_SIZE (200) + +#ifndef MAX_NUM_PATCHES_HBE +#define MAX_NUM_PATCHES_HBE (6) +#endif +#define MAX_STRETCH_HBE (4) + +typedef enum { + KEEP_STATES_SYNCED_OFF = 0, /*!< normal QMF transposer behaviour */ + KEEP_STATES_SYNCED_NORMAL = 1, /*!< QMF transposer called for syncing of + states the last 8/14 slots are calculated in + case next frame is HBE */ + KEEP_STATES_SYNCED_OUTDIFF = + 2, /*!< QMF transposer behaviour as in normal case, but the calculated + slots are directly written to overlap area of buffer; only used in + resetSbrDec function */ + KEEP_STATES_SYNCED_NOOUT = + 3 /*!< QMF transposer is called for syncing of states only, not output + is generated at all; only used in resetSbrDec function */ +} KEEP_STATES_SYNCED_MODE; + +struct hbeTransposer { + int xOverQmf[MAX_NUM_PATCHES_HBE]; + + int maxStretch; + int timeDomainWinLen; + int qmfInBufSize; + int qmfOutBufSize; + int noCols; + int noChannels; + int startBand; + int stopBand; + int bSbr41; + + INT_PCM *inBuf_F; + FIXP_DBL **qmfInBufReal_F; + FIXP_DBL **qmfInBufImag_F; + + FIXP_DBL *qmfBufferCodecTempSlot_F; + + QMF_FILTER_BANK HBEAnalysiscQMF; + QMF_FILTER_BANK HBESynthesisQMF; + + FIXP_DBL const *synthesisQmfPreModCos_F; + FIXP_DBL const *synthesisQmfPreModSin_F; + + FIXP_QAS anaQmfStates[HBE_QMF_FILTER_STATE_ANA_SIZE]; + FIXP_QSS synQmfStates[HBE_QMF_FILTER_STATE_SYN_SIZE]; + + FIXP_DBL **qmfHBEBufReal_F; + FIXP_DBL **qmfHBEBufImag_F; + + int bXProducts[MAX_STRETCH_HBE]; + + int kstart; + int synthSize; + + int highband_exp[2]; + int target_exp[2]; +}; + +typedef struct hbeTransposer *HANDLE_HBE_TRANSPOSER; + +SBR_ERROR QmfTransposerCreate(HANDLE_HBE_TRANSPOSER *hQmfTransposer, + const int frameSize, int bDisableCrossProducts, + int bSbr41); + +SBR_ERROR QmfTransposerReInit(HANDLE_HBE_TRANSPOSER hQmfTransposer, + UCHAR *FreqBandTable[2], UCHAR NSfb[2]); + +void QmfTransposerClose(HANDLE_HBE_TRANSPOSER hQmfTransposer); + +void QmfTransposerApply(HANDLE_HBE_TRANSPOSER hQmfTransposer, + FIXP_DBL **qmfBufferCodecReal, + FIXP_DBL **qmfBufferCodecImag, int nColsIn, + FIXP_DBL **ppQmfBufferOutReal_F, + FIXP_DBL **ppQmfBufferOutImag_F, + FIXP_DBL lpcFilterStatesReal[2 + (3 * (4))][(64)], + FIXP_DBL lpcFilterStatesImag[2 + (3 * (4))][(64)], + int pitchInBins, int scale_lb, int scale_hbe, + int *scale_hb, int timeStep, int firstSlotOffsset, + int ov_len, + KEEP_STATES_SYNCED_MODE keepStatesSyncedMode); + +int *GetxOverBandQmfTransposer(HANDLE_HBE_TRANSPOSER hQmfTransposer); + +int Get41SbrQmfTransposer(HANDLE_HBE_TRANSPOSER hQmfTransposer); +#endif /* HBE_H */ diff --git a/libSBRdec/src/huff_dec.cpp b/libSBRdec/src/huff_dec.cpp index 31d686d..90c9541 100644 --- a/libSBRdec/src/huff_dec.cpp +++ b/libSBRdec/src/huff_dec.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,11 +90,19 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief Huffman Decoder + \brief Huffman Decoder */ #include "huff_dec.h" @@ -101,20 +120,18 @@ amm-info@iis.fraunhofer.de \author ****************************************************************************/ -int -DecodeHuffmanCW (Huffman h, /*!< pointer to huffman codebook table */ - HANDLE_FDK_BITSTREAM hBs) /*!< Handle to Bitbuffer */ +int DecodeHuffmanCW(Huffman h, /*!< pointer to huffman codebook table */ + HANDLE_FDK_BITSTREAM hBs) /*!< Handle to Bitbuffer */ { SCHAR index = 0; int value, bit; while (index >= 0) { - bit = FDKreadBits (hBs, 1); + bit = FDKreadBits(hBs, 1); index = h[index][bit]; } - value = index+64; /* Add offset */ - + value = index + 64; /* Add offset */ return value; } diff --git a/libSBRdec/src/huff_dec.h b/libSBRdec/src/huff_dec.h index 5443658..9aa62b4 100644 --- a/libSBRdec/src/huff_dec.h +++ b/libSBRdec/src/huff_dec.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,22 +90,28 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief Huffman Decoder + \brief Huffman Decoder */ -#ifndef __HUFF_DEC_H -#define __HUFF_DEC_H +#ifndef HUFF_DEC_H +#define HUFF_DEC_H #include "sbrdecoder.h" #include "FDK_bitstream.h" typedef const SCHAR (*Huffman)[2]; -int -DecodeHuffmanCW (Huffman h, - HANDLE_FDK_BITSTREAM hBitBuf); +int DecodeHuffmanCW(Huffman h, HANDLE_FDK_BITSTREAM hBitBuf); #endif diff --git a/libSBRdec/src/lpp_tran.cpp b/libSBRdec/src/lpp_tran.cpp index 343aec3..aa1fd5d 100644 --- a/libSBRdec/src/lpp_tran.cpp +++ b/libSBRdec/src/lpp_tran.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,19 +90,30 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief Low Power Profile Transposer, - This module provides the transposer. The main entry point is lppTransposer(). The function generates - high frequency content by copying data from the low band (provided by core codec) into the high band. - This process is also referred to as "patching". The function also implements spectral whitening by means of - inverse filtering based on LPC coefficients. - - Together with the QMF filterbank the transposer can be tested using a supplied test program. See main_audio.cpp for details. - This module does use fractional arithmetic and the accuracy of the computations has an impact on the overall sound quality. - The module also needs to take into account the different scaling of spectral data. + \brief Low Power Profile Transposer + This module provides the transposer. The main entry point is lppTransposer(). + The function generates high frequency content by copying data from the low + band (provided by core codec) into the high band. This process is also + referred to as "patching". The function also implements spectral whitening by + means of inverse filtering based on LPC coefficients. + + Together with the QMF filterbank the transposer can be tested using a supplied + test program. See main_audio.cpp for details. This module does use fractional + arithmetic and the accuracy of the computations has an impact on the overall + sound quality. The module also needs to take into account the different + scaling of spectral data. \sa lppTransposer(), main_audio.cpp, sbr_scale.h, \ref documentationOverview */ @@ -104,16 +126,13 @@ amm-info@iis.fraunhofer.de #include "genericStds.h" #include "autocorr2nd.h" - +#include "HFgen_preFlat.h" #if defined(__arm__) #include "arm/lpp_tran_arm.cpp" #endif - - -#define LPC_SCALE_FACTOR 2 - +#define LPC_SCALE_FACTOR 2 /*! * @@ -125,33 +144,28 @@ amm-info@iis.fraunhofer.de * level is being inserted to achieve a smooth transition. */ -#ifndef FUNCTION_mapInvfMode -static FIXP_DBL -mapInvfMode (INVF_MODE mode, - INVF_MODE prevMode, - WHITENING_FACTORS whFactors) -{ +static FIXP_DBL mapInvfMode(INVF_MODE mode, INVF_MODE prevMode, + WHITENING_FACTORS whFactors) { switch (mode) { - case INVF_LOW_LEVEL: - if(prevMode == INVF_OFF) - return whFactors.transitionLevel; - else - return whFactors.lowLevel; - - case INVF_MID_LEVEL: - return whFactors.midLevel; - - case INVF_HIGH_LEVEL: - return whFactors.highLevel; - - default: - if(prevMode == INVF_LOW_LEVEL) - return whFactors.transitionLevel; - else - return whFactors.off; + case INVF_LOW_LEVEL: + if (prevMode == INVF_OFF) + return whFactors.transitionLevel; + else + return whFactors.lowLevel; + + case INVF_MID_LEVEL: + return whFactors.midLevel; + + case INVF_HIGH_LEVEL: + return whFactors.highLevel; + + default: + if (prevMode == INVF_LOW_LEVEL) + return whFactors.transitionLevel; + else + return whFactors.off; } } -#endif /* #ifndef FUNCTION_mapInvfMode */ /*! * @@ -161,124 +175,148 @@ mapInvfMode (INVF_MODE mode, * */ -#ifndef FUNCTION_inverseFilteringLevelEmphasis -static void -inverseFilteringLevelEmphasis(HANDLE_SBR_LPP_TRANS hLppTrans,/*!< Handle of lpp transposer */ - UCHAR nInvfBands, /*!< Number of bands for inverse filtering */ - INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ - INVF_MODE *sbr_invf_mode_prev, /*!< Previous inverse filtering modes */ - FIXP_DBL * bwVector /*!< Resulting filtering levels */ - ) -{ - for(int i = 0; i < nInvfBands; i++) { +static void inverseFilteringLevelEmphasis( + HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + UCHAR nInvfBands, /*!< Number of bands for inverse filtering */ + INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ + INVF_MODE *sbr_invf_mode_prev, /*!< Previous inverse filtering modes */ + FIXP_DBL *bwVector /*!< Resulting filtering levels */ +) { + for (int i = 0; i < nInvfBands; i++) { FIXP_DBL accu; - FIXP_DBL bwTmp = mapInvfMode (sbr_invf_mode[i], - sbr_invf_mode_prev[i], - hLppTrans->pSettings->whFactors); - - if(bwTmp < hLppTrans->bwVectorOld[i]) { - accu = fMultDiv2(FL2FXCONST_DBL(0.75f),bwTmp) + - fMultDiv2(FL2FXCONST_DBL(0.25f),hLppTrans->bwVectorOld[i]); - } - else { - accu = fMultDiv2(FL2FXCONST_DBL(0.90625f),bwTmp) + - fMultDiv2(FL2FXCONST_DBL(0.09375f),hLppTrans->bwVectorOld[i]); + FIXP_DBL bwTmp = mapInvfMode(sbr_invf_mode[i], sbr_invf_mode_prev[i], + hLppTrans->pSettings->whFactors); + + if (bwTmp < hLppTrans->bwVectorOld[i]) { + accu = fMultDiv2(FL2FXCONST_DBL(0.75f), bwTmp) + + fMultDiv2(FL2FXCONST_DBL(0.25f), hLppTrans->bwVectorOld[i]); + } else { + accu = fMultDiv2(FL2FXCONST_DBL(0.90625f), bwTmp) + + fMultDiv2(FL2FXCONST_DBL(0.09375f), hLppTrans->bwVectorOld[i]); } - if (accu < FL2FXCONST_DBL(0.015625f)>>1) + if (accu<FL2FXCONST_DBL(0.015625f)>> 1) { bwVector[i] = FL2FXCONST_DBL(0.0f); - else - bwVector[i] = fixMin(accu<<1,FL2FXCONST_DBL(0.99609375f)); + } else { + bwVector[i] = fixMin(accu << 1, FL2FXCONST_DBL(0.99609375f)); + } } } -#endif /* #ifndef FUNCTION_inverseFilteringLevelEmphasis */ /* Resulting autocorrelation determinant exponent */ -#define ACDET_EXP (2*(DFRACT_BITS+sbrScaleFactor->lb_scale+10-ac.det_scale)) -#define AC_EXP (-sbrScaleFactor->lb_scale+LPC_SCALE_FACTOR) -#define ALPHA_EXP (-sbrScaleFactor->lb_scale+LPC_SCALE_FACTOR+1) -/* Resulting transposed QMF values exponent 16 bit normalized samplebits assumed. */ -#define QMFOUT_EXP ((SAMPLE_BITS-15)-sbrScaleFactor->lb_scale) +#define ACDET_EXP \ + (2 * (DFRACT_BITS + sbrScaleFactor->lb_scale + 10 - ac.det_scale)) +#define AC_EXP (-sbrScaleFactor->lb_scale + LPC_SCALE_FACTOR) +#define ALPHA_EXP (-sbrScaleFactor->lb_scale + LPC_SCALE_FACTOR + 1) +/* Resulting transposed QMF values exponent 16 bit normalized samplebits + * assumed. */ +#define QMFOUT_EXP ((SAMPLE_BITS - 15) - sbrScaleFactor->lb_scale) + +static inline void calc_qmfBufferReal(FIXP_DBL **qmfBufferReal, + const FIXP_DBL *const lowBandReal, + const int startSample, + const int stopSample, const UCHAR hiBand, + const int dynamicScale, const int descale, + const FIXP_SGL a0r, const FIXP_SGL a1r) { + FIXP_DBL accu1, accu2; + int i; + + for (i = 0; i < stopSample - startSample; i++) { + accu1 = fMultDiv2(a1r, lowBandReal[i]); + accu1 = (fMultDiv2(a0r, lowBandReal[i + 1]) + accu1); + accu1 = accu1 >> dynamicScale; + + accu1 <<= 1; + accu2 = (lowBandReal[i + 2] >> descale); + qmfBufferReal[i + startSample][hiBand] = accu1 + accu2; + } +} /*! * * \brief Perform transposition by patching of subband samples. - * This function serves as the main entry point into the module. The function determines the areas for the - * patching process (these are the source range as well as the target range) and implements spectral whitening - * by means of inverse filtering. The function autoCorrelation2nd() is an auxiliary function for calculating the - * LPC coefficients for the filtering. The actual calculation of the LPC coefficients and the implementation - * of the filtering are done as part of lppTransposer(). + * This function serves as the main entry point into the module. The function + * determines the areas for the patching process (these are the source range as + * well as the target range) and implements spectral whitening by means of + * inverse filtering. The function autoCorrelation2nd() is an auxiliary function + * for calculating the LPC coefficients for the filtering. The actual + * calculation of the LPC coefficients and the implementation of the filtering + * are done as part of lppTransposer(). * - * Note that the filtering is done on all available QMF subsamples, whereas the patching is only done on those QMF - * subsamples that will be used in the next QMF synthesis. The filtering is also implemented before the patching - * includes further dependencies on parameters from the SBR data. + * Note that the filtering is done on all available QMF subsamples, whereas the + * patching is only done on those QMF subsamples that will be used in the next + * QMF synthesis. The filtering is also implemented before the patching includes + * further dependencies on parameters from the SBR data. * */ -void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ - QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ - FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband samples (source) */ - - FIXP_DBL *degreeAlias, /*!< Vector for results of aliasing estimation */ - FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of subband samples (source) */ - const int useLP, - const int timeStep, /*!< Time step of envelope */ - const int firstSlotOffs, /*!< Start position in time */ - const int lastSlotOffs, /*!< Number of overlap-slots into next frame */ - const int nInvfBands, /*!< Number of bands for inverse filtering */ - INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ - INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */ - ) -{ - INT bwIndex[MAX_NUM_PATCHES]; - FIXP_DBL bwVector[MAX_NUM_PATCHES]; /*!< pole moving factors */ - - int i; - int loBand, start, stop; +void lppTransposer( + HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ + FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband + samples (source) */ + + FIXP_DBL *degreeAlias, /*!< Vector for results of aliasing estimation */ + FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of + subband samples (source) */ + const int useLP, const int fPreWhitening, const int v_k_master0, + const int timeStep, /*!< Time step of envelope */ + const int firstSlotOffs, /*!< Start position in time */ + const int lastSlotOffs, /*!< Number of overlap-slots into next frame */ + const int nInvfBands, /*!< Number of bands for inverse filtering */ + INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ + INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */ +) { + INT bwIndex[MAX_NUM_PATCHES]; + FIXP_DBL bwVector[MAX_NUM_PATCHES]; /*!< pole moving factors */ + FIXP_DBL preWhiteningGains[(64) / 2]; + int preWhiteningGains_exp[(64) / 2]; + + int i; + int loBand, start, stop; TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings; PATCH_PARAM *patchParam = pSettings->patchParam; - int patch; + int patch; - FIXP_SGL alphar[LPC_ORDER], a0r, a1r; - FIXP_SGL alphai[LPC_ORDER], a0i=0, a1i=0; - FIXP_SGL bw = FL2FXCONST_SGL(0.0f); + FIXP_SGL alphar[LPC_ORDER], a0r, a1r; + FIXP_SGL alphai[LPC_ORDER], a0i = 0, a1i = 0; + FIXP_SGL bw = FL2FXCONST_SGL(0.0f); - int autoCorrLength; + int autoCorrLength; - FIXP_DBL k1, k1_below=0, k1_below2=0; + FIXP_DBL k1, k1_below = 0, k1_below2 = 0; ACORR_COEFS ac; - int startSample; - int stopSample; - int stopSampleClear; + int startSample; + int stopSample; + int stopSampleClear; int comLowBandScale; int ovLowBandShift; int lowBandShift; -/* int ovHighBandShift;*/ + /* int ovHighBandShift;*/ int targetStopBand; - alphai[0] = FL2FXCONST_SGL(0.0f); alphai[1] = FL2FXCONST_SGL(0.0f); - startSample = firstSlotOffs * timeStep; - stopSample = pSettings->nCols + lastSlotOffs * timeStep; + stopSample = pSettings->nCols + lastSlotOffs * timeStep; + FDK_ASSERT((lastSlotOffs * timeStep) <= pSettings->overlap); - - inverseFilteringLevelEmphasis(hLppTrans, nInvfBands, sbr_invf_mode, sbr_invf_mode_prev, bwVector); + inverseFilteringLevelEmphasis(hLppTrans, nInvfBands, sbr_invf_mode, + sbr_invf_mode_prev, bwVector); stopSampleClear = stopSample; autoCorrLength = pSettings->nCols + pSettings->overlap; /* Set upper subbands to zero: - This is required in case that the patches do not cover the complete highband - (because the last patch would be too short). - Possible optimization: Clearing bands up to usb would be sufficient here. */ - targetStopBand = patchParam[pSettings->noOfPatches-1].targetStartBand - + patchParam[pSettings->noOfPatches-1].numBandsInPatch; + This is required in case that the patches do not cover the complete + highband (because the last patch would be too short). Possible + optimization: Clearing bands up to usb would be sufficient here. */ + targetStopBand = patchParam[pSettings->noOfPatches - 1].targetStartBand + + patchParam[pSettings->noOfPatches - 1].numBandsInPatch; int memSize = ((64) - targetStopBand) * sizeof(FIXP_DBL); @@ -287,67 +325,84 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize); FDKmemclear(&qmfBufferImag[i][targetStopBand], memSize); } - } else - for (i = startSample; i < stopSampleClear; i++) { - FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize); + } else { + for (i = startSample; i < stopSampleClear; i++) { + FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize); + } } /* init bwIndex for each patch */ - FDKmemclear(bwIndex, MAX_NUM_PATCHES*sizeof(INT)); + FDKmemclear(bwIndex, sizeof(bwIndex)); /* Calc common low band scale factor */ - comLowBandScale = fixMin(sbrScaleFactor->ov_lb_scale,sbrScaleFactor->lb_scale); + comLowBandScale = + fixMin(sbrScaleFactor->ov_lb_scale, sbrScaleFactor->lb_scale); - ovLowBandShift = sbrScaleFactor->ov_lb_scale - comLowBandScale; - lowBandShift = sbrScaleFactor->lb_scale - comLowBandScale; + ovLowBandShift = sbrScaleFactor->ov_lb_scale - comLowBandScale; + lowBandShift = sbrScaleFactor->lb_scale - comLowBandScale; /* ovHighBandShift = firstSlotOffs == 0 ? ovLowBandShift:0;*/ + if (fPreWhitening) { + sbrDecoder_calculateGainVec( + qmfBufferReal, qmfBufferImag, + DFRACT_BITS - 1 - 16 - + sbrScaleFactor->ov_lb_scale, /* convert scale to exponent */ + DFRACT_BITS - 1 - 16 - + sbrScaleFactor->lb_scale, /* convert scale to exponent */ + pSettings->overlap, preWhiteningGains, preWhiteningGains_exp, + v_k_master0, startSample, stopSample); + } + /* outer loop over bands to do analysis only once for each band */ if (!useLP) { start = pSettings->lbStartPatching; stop = pSettings->lbStopPatching; - } else - { + } else { start = fixMax(1, pSettings->lbStartPatching - 2); stop = patchParam[0].targetStartBand; } - - for ( loBand = start; loBand < stop; loBand++ ) { - - FIXP_DBL lowBandReal[(((1024)/(32))+(6))+LPC_ORDER]; + for (loBand = start; loBand < stop; loBand++) { + FIXP_DBL lowBandReal[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER]; FIXP_DBL *plowBandReal = lowBandReal; - FIXP_DBL **pqmfBufferReal = qmfBufferReal; - FIXP_DBL lowBandImag[(((1024)/(32))+(6))+LPC_ORDER]; + FIXP_DBL **pqmfBufferReal = + qmfBufferReal + firstSlotOffs * timeStep /* + pSettings->overlap */; + FIXP_DBL lowBandImag[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER]; FIXP_DBL *plowBandImag = lowBandImag; - FIXP_DBL **pqmfBufferImag = qmfBufferImag; - int resetLPCCoeffs=0; - int dynamicScale = DFRACT_BITS-1-LPC_SCALE_FACTOR; + FIXP_DBL **pqmfBufferImag = + qmfBufferImag + firstSlotOffs * timeStep /* + pSettings->overlap */; + int resetLPCCoeffs = 0; + int dynamicScale = DFRACT_BITS - 1 - LPC_SCALE_FACTOR; int acDetScale = 0; /* scaling of autocorrelation determinant */ - for(i=0;i<LPC_ORDER;i++){ - *plowBandReal++ = hLppTrans->lpcFilterStatesReal[i][loBand]; + for (i = 0; + i < LPC_ORDER + firstSlotOffs * timeStep /*+pSettings->overlap*/; + i++) { + *plowBandReal++ = hLppTrans->lpcFilterStatesRealLegSBR[i][loBand]; if (!useLP) - *plowBandImag++ = hLppTrans->lpcFilterStatesImag[i][loBand]; + *plowBandImag++ = hLppTrans->lpcFilterStatesImagLegSBR[i][loBand]; } /* Take old slope length qmf slot source values out of (overlap)qmf buffer */ if (!useLP) { - for(i=0;i<pSettings->nCols+pSettings->overlap;i++){ + for (i = 0; + i < pSettings->nCols + pSettings->overlap - firstSlotOffs * timeStep; + i++) { *plowBandReal++ = (*pqmfBufferReal++)[loBand]; *plowBandImag++ = (*pqmfBufferImag++)[loBand]; } - } else - { + } else { /* pSettings->overlap is always even */ FDK_ASSERT((pSettings->overlap & 1) == 0); - - for(i=0;i<((pSettings->overlap+pSettings->nCols)>>1);i++) { + for (i = 0; i < ((pSettings->nCols + pSettings->overlap - + firstSlotOffs * timeStep) >> + 1); + i++) { *plowBandReal++ = (*pqmfBufferReal++)[loBand]; *plowBandReal++ = (*pqmfBufferReal++)[loBand]; } @@ -359,61 +414,77 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp /* Determine dynamic scaling value. */ - dynamicScale = fixMin(dynamicScale, getScalefactor(lowBandReal, LPC_ORDER+pSettings->overlap) + ovLowBandShift); - dynamicScale = fixMin(dynamicScale, getScalefactor(&lowBandReal[LPC_ORDER+pSettings->overlap], pSettings->nCols) + lowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(lowBandReal, LPC_ORDER + pSettings->overlap) + + ovLowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(&lowBandReal[LPC_ORDER + pSettings->overlap], + pSettings->nCols) + + lowBandShift); if (!useLP) { - dynamicScale = fixMin(dynamicScale, getScalefactor(lowBandImag, LPC_ORDER+pSettings->overlap) + ovLowBandShift); - dynamicScale = fixMin(dynamicScale, getScalefactor(&lowBandImag[LPC_ORDER+pSettings->overlap], pSettings->nCols) + lowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(lowBandImag, LPC_ORDER + pSettings->overlap) + + ovLowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(&lowBandImag[LPC_ORDER + pSettings->overlap], + pSettings->nCols) + + lowBandShift); } - dynamicScale = fixMax(0, dynamicScale-1); /* one additional bit headroom to prevent -1.0 */ + dynamicScale = fixMax( + 0, dynamicScale - 1); /* one additional bit headroom to prevent -1.0 */ /* Scale temporal QMF buffer. */ - scaleValues(&lowBandReal[0], LPC_ORDER+pSettings->overlap, dynamicScale-ovLowBandShift); - scaleValues(&lowBandReal[LPC_ORDER+pSettings->overlap], pSettings->nCols, dynamicScale-lowBandShift); + scaleValues(&lowBandReal[0], LPC_ORDER + pSettings->overlap, + dynamicScale - ovLowBandShift); + scaleValues(&lowBandReal[LPC_ORDER + pSettings->overlap], pSettings->nCols, + dynamicScale - lowBandShift); if (!useLP) { - scaleValues(&lowBandImag[0], LPC_ORDER+pSettings->overlap, dynamicScale-ovLowBandShift); - scaleValues(&lowBandImag[LPC_ORDER+pSettings->overlap], pSettings->nCols, dynamicScale-lowBandShift); + scaleValues(&lowBandImag[0], LPC_ORDER + pSettings->overlap, + dynamicScale - ovLowBandShift); + scaleValues(&lowBandImag[LPC_ORDER + pSettings->overlap], + pSettings->nCols, dynamicScale - lowBandShift); } + if (!useLP) { + acDetScale += autoCorr2nd_cplx(&ac, lowBandReal + LPC_ORDER, + lowBandImag + LPC_ORDER, autoCorrLength); + } else { + acDetScale += + autoCorr2nd_real(&ac, lowBandReal + LPC_ORDER, autoCorrLength); + } - if (!useLP) { - acDetScale += autoCorr2nd_cplx(&ac, lowBandReal+LPC_ORDER, lowBandImag+LPC_ORDER, autoCorrLength); - } - else - { - acDetScale += autoCorr2nd_real(&ac, lowBandReal+LPC_ORDER, autoCorrLength); - } - - /* Examine dynamic of determinant in autocorrelation. */ - acDetScale += 2*(comLowBandScale + dynamicScale); - acDetScale *= 2; /* two times reflection coefficent scaling */ - acDetScale += ac.det_scale; /* ac scaling of determinant */ - - /* In case of determinant < 10^-38, resetLPCCoeffs=1 has to be enforced. */ - if (acDetScale>126 ) { - resetLPCCoeffs = 1; - } + /* Examine dynamic of determinant in autocorrelation. */ + acDetScale += 2 * (comLowBandScale + dynamicScale); + acDetScale *= 2; /* two times reflection coefficent scaling */ + acDetScale += ac.det_scale; /* ac scaling of determinant */ + /* In case of determinant < 10^-38, resetLPCCoeffs=1 has to be enforced. */ + if (acDetScale > 126) { + resetLPCCoeffs = 1; + } alphar[1] = FL2FXCONST_SGL(0.0f); - if (!useLP) - alphai[1] = FL2FXCONST_SGL(0.0f); + if (!useLP) alphai[1] = FL2FXCONST_SGL(0.0f); if (ac.det != FL2FXCONST_DBL(0.0f)) { - FIXP_DBL tmp,absTmp,absDet; + FIXP_DBL tmp, absTmp, absDet; absDet = fixp_abs(ac.det); if (!useLP) { - tmp = ( fMultDiv2(ac.r01r,ac.r12r) >> (LPC_SCALE_FACTOR-1) ) - - ( (fMultDiv2(ac.r01i,ac.r12i) + fMultDiv2(ac.r02r,ac.r11r)) >> (LPC_SCALE_FACTOR-1) ); - } else - { - tmp = ( fMultDiv2(ac.r01r,ac.r12r) >> (LPC_SCALE_FACTOR-1) ) - - ( fMultDiv2(ac.r02r,ac.r11r) >> (LPC_SCALE_FACTOR-1) ); + tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) - + ((fMultDiv2(ac.r01i, ac.r12i) + fMultDiv2(ac.r02r, ac.r11r)) >> + (LPC_SCALE_FACTOR - 1)); + } else { + tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) - + (fMultDiv2(ac.r02r, ac.r11r) >> (LPC_SCALE_FACTOR - 1)); } absTmp = fixp_abs(tmp); @@ -423,23 +494,23 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp { INT scale; FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); - scale = scale+ac.det_scale; + scale = scale + ac.det_scale; - if ( (scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL>>scale) ) { + if ((scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL >> scale)) { resetLPCCoeffs = 1; - } - else { - alphar[1] = FX_DBL2FX_SGL(scaleValue(result,scale)); - if((tmp<FL2FX_DBL(0.0f)) ^ (ac.det<FL2FX_DBL(0.0f))) { + } else { + alphar[1] = FX_DBL2FX_SGL(scaleValue(result, scale)); + if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) { alphar[1] = -alphar[1]; } } } - if (!useLP) - { - tmp = ( fMultDiv2(ac.r01i,ac.r12r) >> (LPC_SCALE_FACTOR-1) ) + - ( (fMultDiv2(ac.r01r,ac.r12i) - (FIXP_DBL)fMultDiv2(ac.r02i,ac.r11r)) >> (LPC_SCALE_FACTOR-1) ) ; + if (!useLP) { + tmp = (fMultDiv2(ac.r01i, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) + + ((fMultDiv2(ac.r01r, ac.r12i) - + (FIXP_DBL)fMultDiv2(ac.r02i, ac.r11r)) >> + (LPC_SCALE_FACTOR - 1)); absTmp = fixp_abs(tmp); @@ -449,14 +520,15 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp { INT scale; FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); - scale = scale+ac.det_scale; + scale = scale + ac.det_scale; - if ( (scale > 0) && (result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL>>scale) ) { + if ((scale > 0) && + (result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL >> + scale)) { resetLPCCoeffs = 1; - } - else { - alphai[1] = FX_DBL2FX_SGL(scaleValue(result,scale)); - if((tmp<FL2FX_DBL(0.0f)) ^ (ac.det<FL2FX_DBL(0.0f))) { + } else { + alphai[1] = FX_DBL2FX_SGL(scaleValue(result, scale)); + if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) { alphai[1] = -alphai[1]; } } @@ -464,24 +536,23 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp } } - alphar[0] = FL2FXCONST_SGL(0.0f); - if (!useLP) - alphai[0] = FL2FXCONST_SGL(0.0f); - - if ( ac.r11r != FL2FXCONST_DBL(0.0f) ) { + alphar[0] = FL2FXCONST_SGL(0.0f); + if (!useLP) alphai[0] = FL2FXCONST_SGL(0.0f); + if (ac.r11r != FL2FXCONST_DBL(0.0f)) { /* ac.r11r is always >=0 */ - FIXP_DBL tmp,absTmp; + FIXP_DBL tmp, absTmp; if (!useLP) { - tmp = (ac.r01r>>(LPC_SCALE_FACTOR+1)) + - (fMultDiv2(alphar[1],ac.r12r) + fMultDiv2(alphai[1],ac.r12i)); - } else - { - if(ac.r01r>=FL2FXCONST_DBL(0.0f)) - tmp = (ac.r01r>>(LPC_SCALE_FACTOR+1)) + fMultDiv2(alphar[1],ac.r12r); + tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) + + (fMultDiv2(alphar[1], ac.r12r) + fMultDiv2(alphai[1], ac.r12i)); + } else { + if (ac.r01r >= FL2FXCONST_DBL(0.0f)) + tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) + + fMultDiv2(alphar[1], ac.r12r); else - tmp = -((-ac.r01r)>>(LPC_SCALE_FACTOR+1)) + fMultDiv2(alphar[1],ac.r12r); + tmp = -((-ac.r01r) >> (LPC_SCALE_FACTOR + 1)) + + fMultDiv2(alphar[1], ac.r12r); } absTmp = fixp_abs(tmp); @@ -490,111 +561,108 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp Quick check: is first filter coeff >= 1(4) */ - if (absTmp >= (ac.r11r>>1)) { - resetLPCCoeffs=1; - } - else { + if (absTmp >= (ac.r11r >> 1)) { + resetLPCCoeffs = 1; + } else { INT scale; FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); - alphar[0] = FX_DBL2FX_SGL(scaleValue(result,scale+1)); + alphar[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1)); - if((tmp>FL2FX_DBL(0.0f)) ^ (ac.r11r<FL2FX_DBL(0.0f))) + if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) alphar[0] = -alphar[0]; } - if (!useLP) - { - tmp = (ac.r01i>>(LPC_SCALE_FACTOR+1)) + - (fMultDiv2(alphai[1],ac.r12r) - fMultDiv2(alphar[1],ac.r12i)); + if (!useLP) { + tmp = (ac.r01i >> (LPC_SCALE_FACTOR + 1)) + + (fMultDiv2(alphai[1], ac.r12r) - fMultDiv2(alphar[1], ac.r12i)); absTmp = fixp_abs(tmp); /* Quick check: is second filter coeff >= 1(4) */ - if (absTmp >= (ac.r11r>>1)) { - resetLPCCoeffs=1; - } - else { + if (absTmp >= (ac.r11r >> 1)) { + resetLPCCoeffs = 1; + } else { INT scale; FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); - alphai[0] = FX_DBL2FX_SGL(scaleValue(result,scale+1)); - if((tmp>FL2FX_DBL(0.0f)) ^ (ac.r11r<FL2FX_DBL(0.0f))) + alphai[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1)); + if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) alphai[0] = -alphai[0]; } } } - - if (!useLP) - { + if (!useLP) { /* Now check the quadratic criteria */ - if( (fMultDiv2(alphar[0],alphar[0]) + fMultDiv2(alphai[0],alphai[0])) >= FL2FXCONST_DBL(0.5f) ) - resetLPCCoeffs=1; - if( (fMultDiv2(alphar[1],alphar[1]) + fMultDiv2(alphai[1],alphai[1])) >= FL2FXCONST_DBL(0.5f) ) - resetLPCCoeffs=1; + if ((fMultDiv2(alphar[0], alphar[0]) + fMultDiv2(alphai[0], alphai[0])) >= + FL2FXCONST_DBL(0.5f)) + resetLPCCoeffs = 1; + if ((fMultDiv2(alphar[1], alphar[1]) + fMultDiv2(alphai[1], alphai[1])) >= + FL2FXCONST_DBL(0.5f)) + resetLPCCoeffs = 1; } - if(resetLPCCoeffs){ + if (resetLPCCoeffs) { alphar[0] = FL2FXCONST_SGL(0.0f); alphar[1] = FL2FXCONST_SGL(0.0f); - if (!useLP) - { + if (!useLP) { alphai[0] = FL2FXCONST_SGL(0.0f); alphai[1] = FL2FXCONST_SGL(0.0f); } } - if (useLP) - { - + if (useLP) { /* Aliasing detection */ - if(ac.r11r==FL2FXCONST_DBL(0.0f)) { + if (ac.r11r == FL2FXCONST_DBL(0.0f)) { k1 = FL2FXCONST_DBL(0.0f); - } - else { - if ( fixp_abs(ac.r01r) >= fixp_abs(ac.r11r) ) { - if ( fMultDiv2(ac.r01r,ac.r11r) < FL2FX_DBL(0.0f)) { + } else { + if (fixp_abs(ac.r01r) >= fixp_abs(ac.r11r)) { + if (fMultDiv2(ac.r01r, ac.r11r) < FL2FX_DBL(0.0f)) { k1 = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_SGL(1.0f)*/; - }else { - /* Since this value is squared later, it must not ever become -1.0f. */ - k1 = (FIXP_DBL)(MINVAL_DBL+1) /*FL2FXCONST_SGL(-1.0f)*/; + } else { + /* Since this value is squared later, it must not ever become -1.0f. + */ + k1 = (FIXP_DBL)(MINVAL_DBL + 1) /*FL2FXCONST_SGL(-1.0f)*/; } - } - else { + } else { INT scale; - FIXP_DBL result = fDivNorm(fixp_abs(ac.r01r), fixp_abs(ac.r11r), &scale); - k1 = scaleValue(result,scale); + FIXP_DBL result = + fDivNorm(fixp_abs(ac.r01r), fixp_abs(ac.r11r), &scale); + k1 = scaleValue(result, scale); - if(!((ac.r01r<FL2FX_DBL(0.0f)) ^ (ac.r11r<FL2FX_DBL(0.0f)))) { + if (!((ac.r01r < FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))) { k1 = -k1; } } } - if(loBand > 1){ + if ((loBand > 1) && (loBand < v_k_master0)) { /* Check if the gain should be locked */ - FIXP_DBL deg = /*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - fPow2(k1_below); + FIXP_DBL deg = + /*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - fPow2(k1_below); degreeAlias[loBand] = FL2FXCONST_DBL(0.0f); - if (((loBand & 1) == 0) && (k1 < FL2FXCONST_DBL(0.0f))){ - if (k1_below < FL2FXCONST_DBL(0.0f)) { /* 2-Ch Aliasing Detection */ + if (((loBand & 1) == 0) && (k1 < FL2FXCONST_DBL(0.0f))) { + if (k1_below < FL2FXCONST_DBL(0.0f)) { /* 2-Ch Aliasing Detection */ degreeAlias[loBand] = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/; - if ( k1_below2 > FL2FXCONST_DBL(0.0f) ) { /* 3-Ch Aliasing Detection */ - degreeAlias[loBand-1] = deg; + if (k1_below2 > + FL2FXCONST_DBL(0.0f)) { /* 3-Ch Aliasing Detection */ + degreeAlias[loBand - 1] = deg; } - } - else if ( k1_below2 > FL2FXCONST_DBL(0.0f) ) { /* 3-Ch Aliasing Detection */ - degreeAlias[loBand] = deg; + } else if (k1_below2 > + FL2FXCONST_DBL(0.0f)) { /* 3-Ch Aliasing Detection */ + degreeAlias[loBand] = deg; } } - if (((loBand & 1) == 1) && (k1 > FL2FXCONST_DBL(0.0f))){ - if (k1_below > FL2FXCONST_DBL(0.0f)) { /* 2-CH Aliasing Detection */ + if (((loBand & 1) == 1) && (k1 > FL2FXCONST_DBL(0.0f))) { + if (k1_below > FL2FXCONST_DBL(0.0f)) { /* 2-CH Aliasing Detection */ degreeAlias[loBand] = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/; - if ( k1_below2 < FL2FXCONST_DBL(0.0f) ) { /* 3-CH Aliasing Detection */ - degreeAlias[loBand-1] = deg; + if (k1_below2 < + FL2FXCONST_DBL(0.0f)) { /* 3-CH Aliasing Detection */ + degreeAlias[loBand - 1] = deg; } - } - else if ( k1_below2 < FL2FXCONST_DBL(0.0f) ) { /* 3-CH Aliasing Detection */ - degreeAlias[loBand] = deg; + } else if (k1_below2 < + FL2FXCONST_DBL(0.0f)) { /* 3-CH Aliasing Detection */ + degreeAlias[loBand] = deg; } } } @@ -605,23 +673,25 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp patch = 0; - while ( patch < pSettings->noOfPatches ) { /* inner loop over every patch */ + while (patch < pSettings->noOfPatches) { /* inner loop over every patch */ int hiBand = loBand + patchParam[patch].targetBandOffs; - if ( loBand < patchParam[patch].sourceStartBand - || loBand >= patchParam[patch].sourceStopBand - //|| hiBand >= hLppTrans->pSettings->noChannels - ) { + if (loBand < patchParam[patch].sourceStartBand || + loBand >= patchParam[patch].sourceStopBand + //|| hiBand >= hLppTrans->pSettings->noChannels + ) { /* Lowband not in current patch - proceed */ patch++; continue; } - FDK_ASSERT( hiBand < (64) ); + FDK_ASSERT(hiBand < (64)); - /* bwIndex[patch] is already initialized with value from previous band inside this patch */ - while (hiBand >= pSettings->bwBorders[bwIndex[patch]] && bwIndex[patch] < MAX_NUM_PATCHES-1) { + /* bwIndex[patch] is already initialized with value from previous band + * inside this patch */ + while (hiBand >= pSettings->bwBorders[bwIndex[patch]] && + bwIndex[patch] < MAX_NUM_PATCHES - 1) { bwIndex[patch]++; } @@ -631,121 +701,498 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp */ bw = FX_DBL2FX_SGL(bwVector[bwIndex[patch]]); - a0r = FX_DBL2FX_SGL(fMult(bw,alphar[0])); /* Apply current bandwidth expansion factor */ - - - if (!useLP) - a0i = FX_DBL2FX_SGL(fMult(bw,alphai[0])); - bw = FX_DBL2FX_SGL(fPow2(bw)); - a1r = FX_DBL2FX_SGL(fMult(bw,alphar[1])); - if (!useLP) - a1i = FX_DBL2FX_SGL(fMult(bw,alphai[1])); - + a0r = FX_DBL2FX_SGL( + fMult(bw, alphar[0])); /* Apply current bandwidth expansion factor */ + if (!useLP) a0i = FX_DBL2FX_SGL(fMult(bw, alphai[0])); + bw = FX_DBL2FX_SGL(fPow2(bw)); + a1r = FX_DBL2FX_SGL(fMult(bw, alphar[1])); + if (!useLP) a1i = FX_DBL2FX_SGL(fMult(bw, alphai[1])); /* Filter Step 3: insert the middle part which won't be windowed */ - - if ( bw <= FL2FXCONST_SGL(0.0f) ) { + if (bw <= FL2FXCONST_SGL(0.0f)) { if (!useLP) { - int descale = fixMin(DFRACT_BITS-1, (LPC_SCALE_FACTOR+dynamicScale)); - for(i = startSample; i < stopSample; i++ ) { - qmfBufferReal[i][hiBand] = lowBandReal[LPC_ORDER+i]>>descale; - qmfBufferImag[i][hiBand] = lowBandImag[LPC_ORDER+i]>>descale; + int descale = + fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); + for (i = startSample; i < stopSample; i++) { + FIXP_DBL accu1, accu2; + accu1 = lowBandReal[LPC_ORDER + i] >> descale; + accu2 = lowBandImag[LPC_ORDER + i] >> descale; + if (fPreWhitening) { + accu1 = scaleValueSaturate( + fMultDiv2(accu1, preWhiteningGains[loBand]), + preWhiteningGains_exp[loBand] + 1); + accu2 = scaleValueSaturate( + fMultDiv2(accu2, preWhiteningGains[loBand]), + preWhiteningGains_exp[loBand] + 1); + } + qmfBufferReal[i][hiBand] = accu1; + qmfBufferImag[i][hiBand] = accu2; } - } else - { - int descale = fixMin(DFRACT_BITS-1, (LPC_SCALE_FACTOR+dynamicScale)); - for(i = startSample; i < stopSample; i++ ) { - qmfBufferReal[i][hiBand] = lowBandReal[LPC_ORDER+i]>>descale; + } else { + int descale = + fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); + for (i = startSample; i < stopSample; i++) { + qmfBufferReal[i][hiBand] = lowBandReal[LPC_ORDER + i] >> descale; } } - } - else { /* bw <= 0 */ + } else { /* bw <= 0 */ if (!useLP) { - int descale = fixMin(DFRACT_BITS-1, (LPC_SCALE_FACTOR+dynamicScale)); + int descale = + fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); #ifdef FUNCTION_LPPTRANSPOSER_func1 - lppTransposer_func1(lowBandReal+LPC_ORDER+startSample,lowBandImag+LPC_ORDER+startSample, - qmfBufferReal+startSample,qmfBufferImag+startSample, - stopSample-startSample, (int) hiBand, - dynamicScale,descale, - a0r, a0i, a1r, a1i); + lppTransposer_func1( + lowBandReal + LPC_ORDER + startSample, + lowBandImag + LPC_ORDER + startSample, + qmfBufferReal + startSample, qmfBufferImag + startSample, + stopSample - startSample, (int)hiBand, dynamicScale, descale, a0r, + a0i, a1r, a1i, fPreWhitening, preWhiteningGains[loBand], + preWhiteningGains_exp[loBand] + 1); #else - for(i = startSample; i < stopSample; i++ ) { + for (i = startSample; i < stopSample; i++) { FIXP_DBL accu1, accu2; - accu1 = (fMultDiv2(a0r,lowBandReal[LPC_ORDER+i-1]) - fMultDiv2(a0i,lowBandImag[LPC_ORDER+i-1]) + - fMultDiv2(a1r,lowBandReal[LPC_ORDER+i-2]) - fMultDiv2(a1i,lowBandImag[LPC_ORDER+i-2]))>>dynamicScale; - accu2 = (fMultDiv2(a0i,lowBandReal[LPC_ORDER+i-1]) + fMultDiv2(a0r,lowBandImag[LPC_ORDER+i-1]) + - fMultDiv2(a1i,lowBandReal[LPC_ORDER+i-2]) + fMultDiv2(a1r,lowBandImag[LPC_ORDER+i-2]))>>dynamicScale; - - qmfBufferReal[i][hiBand] = (lowBandReal[LPC_ORDER+i]>>descale) + (accu1<<1); - qmfBufferImag[i][hiBand] = (lowBandImag[LPC_ORDER+i]>>descale) + (accu2<<1); + accu1 = (fMultDiv2(a0r, lowBandReal[LPC_ORDER + i - 1]) - + fMultDiv2(a0i, lowBandImag[LPC_ORDER + i - 1]) + + fMultDiv2(a1r, lowBandReal[LPC_ORDER + i - 2]) - + fMultDiv2(a1i, lowBandImag[LPC_ORDER + i - 2])) >> + dynamicScale; + accu2 = (fMultDiv2(a0i, lowBandReal[LPC_ORDER + i - 1]) + + fMultDiv2(a0r, lowBandImag[LPC_ORDER + i - 1]) + + fMultDiv2(a1i, lowBandReal[LPC_ORDER + i - 2]) + + fMultDiv2(a1r, lowBandImag[LPC_ORDER + i - 2])) >> + dynamicScale; + + accu1 = (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 << 1); + accu2 = (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 << 1); + if (fPreWhitening) { + accu1 = scaleValueSaturate( + fMultDiv2(accu1, preWhiteningGains[loBand]), + preWhiteningGains_exp[loBand] + 1); + accu2 = scaleValueSaturate( + fMultDiv2(accu2, preWhiteningGains[loBand]), + preWhiteningGains_exp[loBand] + 1); + } + qmfBufferReal[i][hiBand] = accu1; + qmfBufferImag[i][hiBand] = accu2; } #endif - } else - { - int descale = fixMin(DFRACT_BITS-1, (LPC_SCALE_FACTOR+dynamicScale)); - + } else { FDK_ASSERT(dynamicScale >= 0); - for(i = startSample; i < stopSample; i++ ) { - FIXP_DBL accu1; - - accu1 = (fMultDiv2(a0r,lowBandReal[LPC_ORDER+i-1]) + fMultDiv2(a1r,lowBandReal[LPC_ORDER+i-2]))>>dynamicScale; - - qmfBufferReal[i][hiBand] = (lowBandReal[LPC_ORDER+i]>>descale) + (accu1<<1); - } + calc_qmfBufferReal( + qmfBufferReal, &(lowBandReal[LPC_ORDER + startSample - 2]), + startSample, stopSample, hiBand, dynamicScale, + fMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)), a0r, + a1r); } } /* bw <= 0 */ patch++; - } /* inner loop over patches */ + } /* inner loop over patches */ - /* + /* * store the unmodified filter coefficients if there is * an overlapping envelope *****************************************************************/ + } /* outer loop over bands (loBand) */ - } /* outer loop over bands (loBand) */ - - if (useLP) - { - for ( loBand = pSettings->lbStartPatching; loBand < pSettings->lbStopPatching; loBand++ ) { + if (useLP) { + for (loBand = pSettings->lbStartPatching; + loBand < pSettings->lbStopPatching; loBand++) { patch = 0; - while ( patch < pSettings->noOfPatches ) { - + while (patch < pSettings->noOfPatches) { UCHAR hiBand = loBand + patchParam[patch].targetBandOffs; - if ( loBand < patchParam[patch].sourceStartBand - || loBand >= patchParam[patch].sourceStopBand - || hiBand >= (64) /* Highband out of range (biterror) */ - ) { - /* Lowband not in current patch or highband out of range (might be caused by biterrors)- proceed */ + if (loBand < patchParam[patch].sourceStartBand || + loBand >= patchParam[patch].sourceStopBand || + hiBand >= (64) /* Highband out of range (biterror) */ + ) { + /* Lowband not in current patch or highband out of range (might be + * caused by biterrors)- proceed */ patch++; continue; } - if(hiBand != patchParam[patch].targetStartBand) + if (hiBand != patchParam[patch].targetStartBand) degreeAlias[hiBand] = degreeAlias[loBand]; patch++; } - }/* end for loop */ + } /* end for loop */ } - for (i = 0; i < nInvfBands; i++ ) { - hLppTrans->bwVectorOld[i] = bwVector[i]; - } + for (i = 0; i < nInvfBands; i++) { + hLppTrans->bwVectorOld[i] = bwVector[i]; + } /* set high band scale factor */ - sbrScaleFactor->hb_scale = comLowBandScale-(LPC_SCALE_FACTOR); + sbrScaleFactor->hb_scale = comLowBandScale - (LPC_SCALE_FACTOR); +} + +void lppTransposerHBE( + HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + HANDLE_HBE_TRANSPOSER hQmfTransposer, + QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ + FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband + samples (source) */ + FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of + subband samples (source) */ + const int timeStep, /*!< Time step of envelope */ + const int firstSlotOffs, /*!< Start position in time */ + const int lastSlotOffs, /*!< Number of overlap-slots into next frame */ + const int nInvfBands, /*!< Number of bands for inverse filtering */ + INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ + INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */ +) { + INT bwIndex; + FIXP_DBL bwVector[MAX_NUM_PATCHES_HBE]; /*!< pole moving factors */ + + int i; + int loBand, start, stop; + TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings; + PATCH_PARAM *patchParam = pSettings->patchParam; + + FIXP_SGL alphar[LPC_ORDER], a0r, a1r; + FIXP_SGL alphai[LPC_ORDER], a0i = 0, a1i = 0; + FIXP_SGL bw = FL2FXCONST_SGL(0.0f); + + int autoCorrLength; + + ACORR_COEFS ac; + int startSample; + int stopSample; + int stopSampleClear; + + int comBandScale; + int ovLowBandShift; + int lowBandShift; + /* int ovHighBandShift;*/ + int targetStopBand; + + alphai[0] = FL2FXCONST_SGL(0.0f); + alphai[1] = FL2FXCONST_SGL(0.0f); + + startSample = firstSlotOffs * timeStep; + stopSample = pSettings->nCols + lastSlotOffs * timeStep; + + inverseFilteringLevelEmphasis(hLppTrans, nInvfBands, sbr_invf_mode, + sbr_invf_mode_prev, bwVector); + + stopSampleClear = stopSample; + + autoCorrLength = pSettings->nCols + pSettings->overlap; + + /* Set upper subbands to zero: + This is required in case that the patches do not cover the complete + highband (because the last patch would be too short). Possible + optimization: Clearing bands up to usb would be sufficient here. */ + targetStopBand = patchParam[pSettings->noOfPatches - 1].targetStartBand + + patchParam[pSettings->noOfPatches - 1].numBandsInPatch; + + int memSize = ((64) - targetStopBand) * sizeof(FIXP_DBL); + + for (i = startSample; i < stopSampleClear; i++) { + FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize); + FDKmemclear(&qmfBufferImag[i][targetStopBand], memSize); + } + + /* + Calc common low band scale factor + */ + comBandScale = sbrScaleFactor->hb_scale; + + ovLowBandShift = sbrScaleFactor->hb_scale - comBandScale; + lowBandShift = sbrScaleFactor->hb_scale - comBandScale; + /* ovHighBandShift = firstSlotOffs == 0 ? ovLowBandShift:0;*/ + + /* outer loop over bands to do analysis only once for each band */ + + start = hQmfTransposer->startBand; + stop = hQmfTransposer->stopBand; + + for (loBand = start; loBand < stop; loBand++) { + bwIndex = 0; + + FIXP_DBL lowBandReal[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER]; + FIXP_DBL lowBandImag[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER]; + + int resetLPCCoeffs = 0; + int dynamicScale = DFRACT_BITS - 1 - LPC_SCALE_FACTOR; + int acDetScale = 0; /* scaling of autocorrelation determinant */ + + for (i = 0; i < LPC_ORDER; i++) { + lowBandReal[i] = hLppTrans->lpcFilterStatesRealHBE[i][loBand]; + lowBandImag[i] = hLppTrans->lpcFilterStatesImagHBE[i][loBand]; + } + + for (; i < LPC_ORDER + firstSlotOffs * timeStep; i++) { + lowBandReal[i] = hLppTrans->lpcFilterStatesRealHBE[i][loBand]; + lowBandImag[i] = hLppTrans->lpcFilterStatesImagHBE[i][loBand]; + } + + /* + Take old slope length qmf slot source values out of (overlap)qmf buffer + */ + for (i = firstSlotOffs * timeStep; + i < pSettings->nCols + pSettings->overlap; i++) { + lowBandReal[i + LPC_ORDER] = qmfBufferReal[i][loBand]; + lowBandImag[i + LPC_ORDER] = qmfBufferImag[i][loBand]; + } + + /* store unmodified values to buffer */ + for (i = 0; i < LPC_ORDER + pSettings->overlap; i++) { + hLppTrans->lpcFilterStatesRealHBE[i][loBand] = + qmfBufferReal[pSettings->nCols - LPC_ORDER + i][loBand]; + hLppTrans->lpcFilterStatesImagHBE[i][loBand] = + qmfBufferImag[pSettings->nCols - LPC_ORDER + i][loBand]; + } + + /* + Determine dynamic scaling value. + */ + dynamicScale = + fixMin(dynamicScale, + getScalefactor(lowBandReal, LPC_ORDER + pSettings->overlap) + + ovLowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(&lowBandReal[LPC_ORDER + pSettings->overlap], + pSettings->nCols) + + lowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(lowBandImag, LPC_ORDER + pSettings->overlap) + + ovLowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(&lowBandImag[LPC_ORDER + pSettings->overlap], + pSettings->nCols) + + lowBandShift); + + dynamicScale = fixMax( + 0, dynamicScale - 1); /* one additional bit headroom to prevent -1.0 */ + + /* + Scale temporal QMF buffer. + */ + scaleValues(&lowBandReal[0], LPC_ORDER + pSettings->overlap, + dynamicScale - ovLowBandShift); + scaleValues(&lowBandReal[LPC_ORDER + pSettings->overlap], pSettings->nCols, + dynamicScale - lowBandShift); + scaleValues(&lowBandImag[0], LPC_ORDER + pSettings->overlap, + dynamicScale - ovLowBandShift); + scaleValues(&lowBandImag[LPC_ORDER + pSettings->overlap], pSettings->nCols, + dynamicScale - lowBandShift); + + acDetScale += autoCorr2nd_cplx(&ac, lowBandReal + LPC_ORDER, + lowBandImag + LPC_ORDER, autoCorrLength); + + /* Examine dynamic of determinant in autocorrelation. */ + acDetScale += 2 * (comBandScale + dynamicScale); + acDetScale *= 2; /* two times reflection coefficent scaling */ + acDetScale += ac.det_scale; /* ac scaling of determinant */ + + /* In case of determinant < 10^-38, resetLPCCoeffs=1 has to be enforced. */ + if (acDetScale > 126) { + resetLPCCoeffs = 1; + } + + alphar[1] = FL2FXCONST_SGL(0.0f); + alphai[1] = FL2FXCONST_SGL(0.0f); + + if (ac.det != FL2FXCONST_DBL(0.0f)) { + FIXP_DBL tmp, absTmp, absDet; + + absDet = fixp_abs(ac.det); + + tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) - + ((fMultDiv2(ac.r01i, ac.r12i) + fMultDiv2(ac.r02r, ac.r11r)) >> + (LPC_SCALE_FACTOR - 1)); + absTmp = fixp_abs(tmp); + + /* + Quick check: is first filter coeff >= 1(4) + */ + { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); + scale = scale + ac.det_scale; + + if ((scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL >> scale)) { + resetLPCCoeffs = 1; + } else { + alphar[1] = FX_DBL2FX_SGL(scaleValue(result, scale)); + if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) { + alphar[1] = -alphar[1]; + } + } + } + + tmp = (fMultDiv2(ac.r01i, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) + + ((fMultDiv2(ac.r01r, ac.r12i) - + (FIXP_DBL)fMultDiv2(ac.r02i, ac.r11r)) >> + (LPC_SCALE_FACTOR - 1)); + + absTmp = fixp_abs(tmp); + + /* + Quick check: is second filter coeff >= 1(4) + */ + { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); + scale = scale + ac.det_scale; + + if ((scale > 0) && + (result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL >> scale)) { + resetLPCCoeffs = 1; + } else { + alphai[1] = FX_DBL2FX_SGL(scaleValue(result, scale)); + if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) { + alphai[1] = -alphai[1]; + } + } + } + } + + alphar[0] = FL2FXCONST_SGL(0.0f); + alphai[0] = FL2FXCONST_SGL(0.0f); + + if (ac.r11r != FL2FXCONST_DBL(0.0f)) { + /* ac.r11r is always >=0 */ + FIXP_DBL tmp, absTmp; + + tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) + + (fMultDiv2(alphar[1], ac.r12r) + fMultDiv2(alphai[1], ac.r12i)); + + absTmp = fixp_abs(tmp); + + /* + Quick check: is first filter coeff >= 1(4) + */ + + if (absTmp >= (ac.r11r >> 1)) { + resetLPCCoeffs = 1; + } else { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); + alphar[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1)); + + if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) + alphar[0] = -alphar[0]; + } + + tmp = (ac.r01i >> (LPC_SCALE_FACTOR + 1)) + + (fMultDiv2(alphai[1], ac.r12r) - fMultDiv2(alphar[1], ac.r12i)); + + absTmp = fixp_abs(tmp); + + /* + Quick check: is second filter coeff >= 1(4) + */ + if (absTmp >= (ac.r11r >> 1)) { + resetLPCCoeffs = 1; + } else { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); + alphai[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1)); + if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) { + alphai[0] = -alphai[0]; + } + } + } + /* Now check the quadratic criteria */ + if ((fMultDiv2(alphar[0], alphar[0]) + fMultDiv2(alphai[0], alphai[0])) >= + FL2FXCONST_DBL(0.5f)) { + resetLPCCoeffs = 1; + } + if ((fMultDiv2(alphar[1], alphar[1]) + fMultDiv2(alphai[1], alphai[1])) >= + FL2FXCONST_DBL(0.5f)) { + resetLPCCoeffs = 1; + } + + if (resetLPCCoeffs) { + alphar[0] = FL2FXCONST_SGL(0.0f); + alphar[1] = FL2FXCONST_SGL(0.0f); + alphai[0] = FL2FXCONST_SGL(0.0f); + alphai[1] = FL2FXCONST_SGL(0.0f); + } + + while (bwIndex < MAX_NUM_PATCHES - 1 && + loBand >= pSettings->bwBorders[bwIndex]) { + bwIndex++; + } + + /* + Filter Step 2: add the left slope with the current filter to the buffer + pure source values are already in there + */ + bw = FX_DBL2FX_SGL(bwVector[bwIndex]); + + a0r = FX_DBL2FX_SGL( + fMult(bw, alphar[0])); /* Apply current bandwidth expansion factor */ + a0i = FX_DBL2FX_SGL(fMult(bw, alphai[0])); + bw = FX_DBL2FX_SGL(fPow2(bw)); + a1r = FX_DBL2FX_SGL(fMult(bw, alphar[1])); + a1i = FX_DBL2FX_SGL(fMult(bw, alphai[1])); + + /* + Filter Step 3: insert the middle part which won't be windowed + */ + if (bw <= FL2FXCONST_SGL(0.0f)) { + int descale = fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); + for (i = startSample; i < stopSample; i++) { + qmfBufferReal[i][loBand] = lowBandReal[LPC_ORDER + i] >> descale; + qmfBufferImag[i][loBand] = lowBandImag[LPC_ORDER + i] >> descale; + } + } else { /* bw <= 0 */ + + int descale = fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); + + for (i = startSample; i < stopSample; i++) { + FIXP_DBL accu1, accu2; + + accu1 = (fMultDiv2(a0r, lowBandReal[LPC_ORDER + i - 1]) - + fMultDiv2(a0i, lowBandImag[LPC_ORDER + i - 1]) + + fMultDiv2(a1r, lowBandReal[LPC_ORDER + i - 2]) - + fMultDiv2(a1i, lowBandImag[LPC_ORDER + i - 2])) >> + dynamicScale; + accu2 = (fMultDiv2(a0i, lowBandReal[LPC_ORDER + i - 1]) + + fMultDiv2(a0r, lowBandImag[LPC_ORDER + i - 1]) + + fMultDiv2(a1i, lowBandReal[LPC_ORDER + i - 2]) + + fMultDiv2(a1r, lowBandImag[LPC_ORDER + i - 2])) >> + dynamicScale; + + qmfBufferReal[i][loBand] = + (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 << 1); + qmfBufferImag[i][loBand] = + (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 << 1); + } + } /* bw <= 0 */ + + /* + * store the unmodified filter coefficients if there is + * an overlapping envelope + *****************************************************************/ + + } /* outer loop over bands (loBand) */ + + for (i = 0; i < nInvfBands; i++) { + hLppTrans->bwVectorOld[i] = bwVector[i]; + } + + /* + set high band scale factor + */ + sbrScaleFactor->hb_scale = comBandScale - (LPC_SCALE_FACTOR); } /*! @@ -755,21 +1202,20 @@ void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transp * */ SBR_ERROR -createLppTransposer (HANDLE_SBR_LPP_TRANS hs, /*!< Handle of low power transposer */ - TRANSPOSER_SETTINGS *pSettings, /*!< Pointer to settings */ - const int highBandStartSb, /*!< ? */ - UCHAR *v_k_master, /*!< Master table */ - const int numMaster, /*!< Valid entries in master table */ - const int usb, /*!< Highband area stop subband */ - const int timeSlots, /*!< Number of time slots */ - const int nCols, /*!< Number of colums (codec qmf bank) */ - UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */ - const int noNoiseBands, /*!< Number of noise bands */ - UINT fs, /*!< Sample Frequency */ - const int chan, /*!< Channel number */ - const int overlap - ) -{ +createLppTransposer( + HANDLE_SBR_LPP_TRANS hs, /*!< Handle of low power transposer */ + TRANSPOSER_SETTINGS *pSettings, /*!< Pointer to settings */ + const int highBandStartSb, /*!< ? */ + UCHAR *v_k_master, /*!< Master table */ + const int numMaster, /*!< Valid entries in master table */ + const int usb, /*!< Highband area stop subband */ + const int timeSlots, /*!< Number of time slots */ + const int nCols, /*!< Number of colums (codec qmf bank) */ + UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */ + const int noNoiseBands, /*!< Number of noise bands */ + UINT fs, /*!< Sample Frequency */ + const int chan, /*!< Channel number */ + const int overlap) { /* FB inverse filtering settings */ hs->pSettings = pSettings; @@ -777,50 +1223,40 @@ createLppTransposer (HANDLE_SBR_LPP_TRANS hs, /*!< Handle of low power transpose pSettings->overlap = overlap; switch (timeSlots) { + case 15: + case 16: + break; - case 15: - case 16: - break; - - default: - return SBRDEC_UNSUPPORTED_CONFIG; /* Unimplemented */ + default: + return SBRDEC_UNSUPPORTED_CONFIG; /* Unimplemented */ } - if (chan==0) { + if (chan == 0) { /* Init common data only once */ hs->pSettings->nCols = nCols; - return resetLppTransposer (hs, - highBandStartSb, - v_k_master, - numMaster, - noiseBandTable, - noNoiseBands, - usb, - fs); + return resetLppTransposer(hs, highBandStartSb, v_k_master, numMaster, + noiseBandTable, noNoiseBands, usb, fs); } return SBRDEC_OK; } - -static int findClosestEntry(UCHAR goalSb, UCHAR *v_k_master, UCHAR numMaster, UCHAR direction) -{ +static int findClosestEntry(UCHAR goalSb, UCHAR *v_k_master, UCHAR numMaster, + UCHAR direction) { int index; - if( goalSb <= v_k_master[0] ) - return v_k_master[0]; + if (goalSb <= v_k_master[0]) return v_k_master[0]; - if( goalSb >= v_k_master[numMaster] ) - return v_k_master[numMaster]; + if (goalSb >= v_k_master[numMaster]) return v_k_master[numMaster]; - if(direction) { + if (direction) { index = 0; - while( v_k_master[index] < goalSb ) { + while (v_k_master[index] < goalSb) { index++; } } else { index = numMaster; - while( v_k_master[index] > goalSb ) { + while (v_k_master[index] > goalSb) { index--; } } @@ -828,7 +1264,6 @@ static int findClosestEntry(UCHAR goalSb, UCHAR *v_k_master, UCHAR numMaster, UC return v_k_master[index]; } - /*! * * \brief Reset memory for one lpp transposer instance @@ -836,18 +1271,18 @@ static int findClosestEntry(UCHAR goalSb, UCHAR *v_k_master, UCHAR numMaster, UC * \return SBRDEC_OK on success, SBRDEC_UNSUPPORTED_CONFIG on error */ SBR_ERROR -resetLppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ - UCHAR highBandStartSb, /*!< High band area: start subband */ - UCHAR *v_k_master, /*!< Master table */ - UCHAR numMaster, /*!< Valid entries in master table */ - UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */ - UCHAR noNoiseBands, /*!< Number of noise bands */ - UCHAR usb, /*!< High band area: stop subband */ - UINT fs /*!< SBR output sampling frequency */ - ) -{ +resetLppTransposer( + HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + UCHAR highBandStartSb, /*!< High band area: start subband */ + UCHAR *v_k_master, /*!< Master table */ + UCHAR numMaster, /*!< Valid entries in master table */ + UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */ + UCHAR noNoiseBands, /*!< Number of noise bands */ + UCHAR usb, /*!< High band area: stop subband */ + UINT fs /*!< SBR output sampling frequency */ +) { TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings; - PATCH_PARAM *patchParam = pSettings->patchParam; + PATCH_PARAM *patchParam = pSettings->patchParam; int i, patch; int targetStopBand; @@ -855,43 +1290,52 @@ resetLppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transpos int patchDistance; int numBandsInPatch; - int lsb = v_k_master[0]; /* Start subband expressed in "non-critical" sampling terms*/ - int xoverOffset = highBandStartSb - lsb; /* Calculate distance in QMF bands between k0 and kx */ + int lsb = v_k_master[0]; /* Start subband expressed in "non-critical" sampling + terms*/ + int xoverOffset = highBandStartSb - + lsb; /* Calculate distance in QMF bands between k0 and kx */ int startFreqHz; int desiredBorder; - usb = fixMin(usb, v_k_master[numMaster]); /* Avoid endless loops (compare with float code). */ + usb = fixMin(usb, v_k_master[numMaster]); /* Avoid endless loops (compare with + float code). */ /* * Plausibility check */ - if ( lsb - SHIFT_START_SB < 4 ) { + if (pSettings->nCols == 64) { + if (lsb < 4) { + /* 4:1 SBR Requirement k0 >= 4 missed! */ + return SBRDEC_UNSUPPORTED_CONFIG; + } + } else if (lsb - SHIFT_START_SB < 4) { return SBRDEC_UNSUPPORTED_CONFIG; } - /* * Initialize the patching parameter */ /* ISO/IEC 14496-3 (Figure 4.48): goalSb = round( 2.048e6 / fs ) */ - desiredBorder = (((2048000*2) / fs) + 1) >> 1; + desiredBorder = (((2048000 * 2) / fs) + 1) >> 1; - desiredBorder = findClosestEntry(desiredBorder, v_k_master, numMaster, 1); /* Adapt region to master-table */ + desiredBorder = findClosestEntry(desiredBorder, v_k_master, numMaster, + 1); /* Adapt region to master-table */ /* First patch */ sourceStartBand = SHIFT_START_SB + xoverOffset; targetStopBand = lsb + xoverOffset; /* upperBand */ - /* Even (odd) numbered channel must be patched to even (odd) numbered channel */ + /* Even (odd) numbered channel must be patched to even (odd) numbered channel + */ patch = 0; - while(targetStopBand < usb) { - + while (targetStopBand < usb) { /* Too many patches? Allow MAX_NUM_PATCHES+1 patches here. we need to check later again, since patch might be the highest patch - AND contain less than 3 bands => actual number of patches will be reduced by 1. + AND contain less than 3 bands => actual number of patches will be reduced + by 1. */ if (patch > MAX_NUM_PATCHES) { return SBRDEC_UNSUPPORTED_CONFIG; @@ -900,26 +1344,42 @@ resetLppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transpos patchParam[patch].guardStartBand = targetStopBand; patchParam[patch].targetStartBand = targetStopBand; - numBandsInPatch = desiredBorder - targetStopBand; /* Get the desired range of the patch */ + numBandsInPatch = + desiredBorder - targetStopBand; /* Get the desired range of the patch */ - if ( numBandsInPatch >= lsb - sourceStartBand ) { + if (numBandsInPatch >= lsb - sourceStartBand) { /* Desired number bands are not available -> patch whole source range */ - patchDistance = targetStopBand - sourceStartBand; /* Get the targetOffset */ - patchDistance = patchDistance & ~1; /* Rounding off odd numbers and make all even */ - numBandsInPatch = lsb - (targetStopBand - patchDistance); /* Update number of bands to be patched */ - numBandsInPatch = findClosestEntry(targetStopBand + numBandsInPatch, v_k_master, numMaster, 0) - - targetStopBand; /* Adapt region to master-table */ + patchDistance = + targetStopBand - sourceStartBand; /* Get the targetOffset */ + patchDistance = + patchDistance & ~1; /* Rounding off odd numbers and make all even */ + numBandsInPatch = + lsb - (targetStopBand - + patchDistance); /* Update number of bands to be patched */ + numBandsInPatch = findClosestEntry(targetStopBand + numBandsInPatch, + v_k_master, numMaster, 0) - + targetStopBand; /* Adapt region to master-table */ + } + + if (pSettings->nCols == 64) { + if (numBandsInPatch == 0 && sourceStartBand == SHIFT_START_SB) { + return SBRDEC_UNSUPPORTED_CONFIG; + } } - /* Desired number bands are available -> get the minimal even patching distance */ - patchDistance = numBandsInPatch + targetStopBand - lsb; /* Get minimal distance */ - patchDistance = (patchDistance + 1) & ~1; /* Rounding up odd numbers and make all even */ + /* Desired number bands are available -> get the minimal even patching + * distance */ + patchDistance = + numBandsInPatch + targetStopBand - lsb; /* Get minimal distance */ + patchDistance = (patchDistance + 1) & + ~1; /* Rounding up odd numbers and make all even */ if (numBandsInPatch > 0) { patchParam[patch].sourceStartBand = targetStopBand - patchDistance; - patchParam[patch].targetBandOffs = patchDistance; + patchParam[patch].targetBandOffs = patchDistance; patchParam[patch].numBandsInPatch = numBandsInPatch; - patchParam[patch].sourceStopBand = patchParam[patch].sourceStartBand + numBandsInPatch; + patchParam[patch].sourceStopBand = + patchParam[patch].sourceStartBand + numBandsInPatch; targetStopBand += patchParam[patch].numBandsInPatch; patch++; @@ -929,19 +1389,19 @@ resetLppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transpos sourceStartBand = SHIFT_START_SB; /* Check if we are close to desiredBorder */ - if( desiredBorder - targetStopBand < 3) /* MPEG doc */ + if (desiredBorder - targetStopBand < 3) /* MPEG doc */ { desiredBorder = usb; } - } patch--; /* If highest patch contains less than three subband: skip it */ - if ( (patch>0) && (patchParam[patch].numBandsInPatch < 3) ) { + if ((patch > 0) && (patchParam[patch].numBandsInPatch < 3)) { patch--; - targetStopBand = patchParam[patch].targetStartBand + patchParam[patch].numBandsInPatch; + targetStopBand = + patchParam[patch].targetStartBand + patchParam[patch].numBandsInPatch; } /* now check if we don't have one too many */ @@ -953,35 +1413,36 @@ resetLppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transpos /* Check lowest and highest source subband */ pSettings->lbStartPatching = targetStopBand; - pSettings->lbStopPatching = 0; - for ( patch = 0; patch < pSettings->noOfPatches; patch++ ) { - pSettings->lbStartPatching = fixMin( pSettings->lbStartPatching, patchParam[patch].sourceStartBand ); - pSettings->lbStopPatching = fixMax( pSettings->lbStopPatching, patchParam[patch].sourceStopBand ); + pSettings->lbStopPatching = 0; + for (patch = 0; patch < pSettings->noOfPatches; patch++) { + pSettings->lbStartPatching = + fixMin(pSettings->lbStartPatching, patchParam[patch].sourceStartBand); + pSettings->lbStopPatching = + fixMax(pSettings->lbStopPatching, patchParam[patch].sourceStopBand); } - for(i = 0 ; i < noNoiseBands; i++){ - pSettings->bwBorders[i] = noiseBandTable[i+1]; + for (i = 0; i < noNoiseBands; i++) { + pSettings->bwBorders[i] = noiseBandTable[i + 1]; } - for (;i < MAX_NUM_NOISE_VALUES; i++) { + for (; i < MAX_NUM_NOISE_VALUES; i++) { pSettings->bwBorders[i] = 255; } - /* * Choose whitening factors */ - startFreqHz = ( (lsb + xoverOffset)*fs ) >> 7; /* Shift does a division by 2*(64) */ + startFreqHz = + ((lsb + xoverOffset) * fs) >> 7; /* Shift does a division by 2*(64) */ - for( i = 1; i < NUM_WHFACTOR_TABLE_ENTRIES; i++ ) - { - if( startFreqHz < FDK_sbrDecoder_sbr_whFactorsIndex[i]) - break; + for (i = 1; i < NUM_WHFACTOR_TABLE_ENTRIES; i++) { + if (startFreqHz < FDK_sbrDecoder_sbr_whFactorsIndex[i]) break; } i--; pSettings->whFactors.off = FDK_sbrDecoder_sbr_whFactorsTable[i][0]; - pSettings->whFactors.transitionLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][1]; + pSettings->whFactors.transitionLevel = + FDK_sbrDecoder_sbr_whFactorsTable[i][1]; pSettings->whFactors.lowLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][2]; pSettings->whFactors.midLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][3]; pSettings->whFactors.highLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][4]; diff --git a/libSBRdec/src/lpp_tran.h b/libSBRdec/src/lpp_tran.h index 003a547..51b4395 100644 --- a/libSBRdec/src/lpp_tran.h +++ b/libSBRdec/src/lpp_tran.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,164 +90,186 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief Low Power Profile Transposer, + \brief Low Power Profile Transposer */ -#ifndef _LPP_TRANS_H -#define _LPP_TRANS_H +#ifndef LPP_TRAN_H +#define LPP_TRAN_H #include "sbrdecoder.h" +#include "hbe.h" #include "qmf.h" /* Common */ -#define QMF_OUT_SCALE 8 +#define QMF_OUT_SCALE 8 + +/* + Frequency scales +*/ /* Env-Adjust */ -#define MAX_NOISE_ENVELOPES 2 -#define MAX_NOISE_COEFFS 5 -#define MAX_NUM_NOISE_VALUES (MAX_NOISE_ENVELOPES * MAX_NOISE_COEFFS) -#define MAX_NUM_LIMITERS 12 +#define MAX_NOISE_ENVELOPES 2 +#define MAX_NOISE_COEFFS 5 +#define MAX_NUM_NOISE_VALUES (MAX_NOISE_ENVELOPES * MAX_NOISE_COEFFS) +#define MAX_NUM_LIMITERS 12 /* Set MAX_ENVELOPES to the largest value of all supported BSFORMATs by overriding MAX_ENVELOPES in the correct order: */ -#define MAX_ENVELOPES_HEAAC 5 -#define MAX_ENVELOPES MAX_ENVELOPES_HEAAC +#define MAX_ENVELOPES_LEGACY 5 +#define MAX_ENVELOPES_USAC 8 +#define MAX_ENVELOPES MAX_ENVELOPES_USAC -#define MAX_FREQ_COEFFS 48 -#define MAX_FREQ_COEFFS_FS44100 35 -#define MAX_FREQ_COEFFS_FS48000 32 +#define MAX_FREQ_COEFFS_DUAL_RATE 48 +#define MAX_FREQ_COEFFS_QUAD_RATE 56 +#define MAX_FREQ_COEFFS MAX_FREQ_COEFFS_QUAD_RATE +#define MAX_FREQ_COEFFS_FS44100 35 +#define MAX_FREQ_COEFFS_FS48000 32 -#define MAX_NUM_ENVELOPE_VALUES (MAX_ENVELOPES * MAX_FREQ_COEFFS) +#define MAX_NUM_ENVELOPE_VALUES (MAX_ENVELOPES * MAX_FREQ_COEFFS) -#define MAX_GAIN_EXP 34 +#define MAX_GAIN_EXP 34 /* Maximum gain will be sqrt(0.5 * 2^MAX_GAIN_EXP) example: 34=99dB */ -#define MAX_GAIN_CONCEAL_EXP 1 -/* Maximum gain will be sqrt(0.5 * 2^MAX_GAIN_CONCEAL_EXP) in concealment case (0dB) */ +#define MAX_GAIN_CONCEAL_EXP 1 +/* Maximum gain will be sqrt(0.5 * 2^MAX_GAIN_CONCEAL_EXP) in concealment case + * (0dB) */ /* LPP Transposer */ -#define LPC_ORDER 2 +#define LPC_ORDER 2 -#define MAX_INVF_BANDS MAX_NOISE_COEFFS +#define MAX_INVF_BANDS MAX_NOISE_COEFFS -#define MAX_NUM_PATCHES 6 -#define SHIFT_START_SB 1 /*!< lowest subband of source range */ +#define MAX_NUM_PATCHES 6 +#define SHIFT_START_SB 1 /*!< lowest subband of source range */ -typedef enum -{ +typedef enum { INVF_OFF = 0, INVF_LOW_LEVEL, INVF_MID_LEVEL, INVF_HIGH_LEVEL, INVF_SWITCHED /* not a real choice but used here to control behaviour */ -} -INVF_MODE; - +} INVF_MODE; /** parameter set for one single patch */ typedef struct { - UCHAR sourceStartBand; /*!< first band in lowbands where to take the samples from */ - UCHAR sourceStopBand; /*!< first band in lowbands which is not included in the patch anymore */ - UCHAR guardStartBand; /*!< first band in highbands to be filled with zeros in order to - reduce interferences between patches */ - UCHAR targetStartBand; /*!< first band in highbands to be filled with whitened lowband signal */ - UCHAR targetBandOffs; /*!< difference between 'startTargetBand' and 'startSourceBand' */ - UCHAR numBandsInPatch; /*!< number of consecutive bands in this one patch */ + UCHAR sourceStartBand; /*!< first band in lowbands where to take the samples + from */ + UCHAR + sourceStopBand; /*!< first band in lowbands which is not included in the + patch anymore */ + UCHAR guardStartBand; /*!< first band in highbands to be filled with zeros in + order to reduce interferences between patches */ + UCHAR + targetStartBand; /*!< first band in highbands to be filled with whitened + lowband signal */ + UCHAR targetBandOffs; /*!< difference between 'startTargetBand' and + 'startSourceBand' */ + UCHAR numBandsInPatch; /*!< number of consecutive bands in this one patch */ } PATCH_PARAM; - /** whitening factors for different levels of whitening need to be initialized corresponding to crossover frequency */ typedef struct { - FIXP_DBL off; /*!< bw factor for signal OFF */ - FIXP_DBL transitionLevel; - FIXP_DBL lowLevel; /*!< bw factor for signal LOW_LEVEL */ - FIXP_DBL midLevel; /*!< bw factor for signal MID_LEVEL */ - FIXP_DBL highLevel; /*!< bw factor for signal HIGH_LEVEL */ + FIXP_DBL off; /*!< bw factor for signal OFF */ + FIXP_DBL transitionLevel; + FIXP_DBL lowLevel; /*!< bw factor for signal LOW_LEVEL */ + FIXP_DBL midLevel; /*!< bw factor for signal MID_LEVEL */ + FIXP_DBL highLevel; /*!< bw factor for signal HIGH_LEVEL */ } WHITENING_FACTORS; - -/*! The transposer settings are calculated on a header reset and are shared by both channels. */ +/*! The transposer settings are calculated on a header reset and are shared by + * both channels. */ typedef struct { - UCHAR nCols; /*!< number subsamples of a codec frame */ - UCHAR noOfPatches; /*!< number of patches */ - UCHAR lbStartPatching; /*!< first band of lowbands that will be patched */ - UCHAR lbStopPatching; /*!< first band that won't be patched anymore*/ - UCHAR bwBorders[MAX_NUM_NOISE_VALUES]; /*!< spectral bands with different inverse filtering levels */ - - PATCH_PARAM patchParam[MAX_NUM_PATCHES]; /*!< new parameter set for patching */ - WHITENING_FACTORS whFactors; /*!< the pole moving factors for certain whitening levels as indicated - in the bitstream depending on the crossover frequency */ - UCHAR overlap; /*!< Overlap size */ + UCHAR nCols; /*!< number subsamples of a codec frame */ + UCHAR noOfPatches; /*!< number of patches */ + UCHAR lbStartPatching; /*!< first band of lowbands that will be patched */ + UCHAR lbStopPatching; /*!< first band that won't be patched anymore*/ + UCHAR bwBorders[MAX_NUM_NOISE_VALUES]; /*!< spectral bands with different + inverse filtering levels */ + + PATCH_PARAM + patchParam[MAX_NUM_PATCHES]; /*!< new parameter set for patching */ + WHITENING_FACTORS + whFactors; /*!< the pole moving factors for certain + whitening levels as indicated in the bitstream + depending on the crossover frequency */ + UCHAR overlap; /*!< Overlap size */ } TRANSPOSER_SETTINGS; +typedef struct { + TRANSPOSER_SETTINGS *pSettings; /*!< Common settings for both channels */ + FIXP_DBL + bwVectorOld[MAX_NUM_PATCHES]; /*!< pole moving factors of past frame */ + FIXP_DBL lpcFilterStatesRealLegSBR[LPC_ORDER + (3 * (4))][( + 32)]; /*!< pointer array to save filter states */ -typedef struct -{ - TRANSPOSER_SETTINGS *pSettings; /*!< Common settings for both channels */ - FIXP_DBL bwVectorOld[MAX_NUM_PATCHES]; /*!< pole moving factors of past frame */ - FIXP_DBL lpcFilterStatesReal[LPC_ORDER][(32)]; /*!< pointer array to save filter states */ - FIXP_DBL lpcFilterStatesImag[LPC_ORDER][(32)]; /*!< pointer array to save filter states */ -} -SBR_LPP_TRANS; - -typedef SBR_LPP_TRANS *HANDLE_SBR_LPP_TRANS; - + FIXP_DBL lpcFilterStatesImagLegSBR[LPC_ORDER + (3 * (4))][( + 32)]; /*!< pointer array to save filter states */ -void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, - QMF_SCALE_FACTOR *sbrScaleFactor, - FIXP_DBL **qmfBufferReal, + FIXP_DBL lpcFilterStatesRealHBE[LPC_ORDER + (3 * (4))][( + 64)]; /*!< pointer array to save filter states */ + FIXP_DBL lpcFilterStatesImagHBE[LPC_ORDER + (3 * (4))][( + 64)]; /*!< pointer array to save filter states */ +} SBR_LPP_TRANS; - FIXP_DBL *degreeAlias, - FIXP_DBL **qmfBufferImag, - const int useLP, - const int timeStep, - const int firstSlotOffset, - const int lastSlotOffset, - const int nInvfBands, - INVF_MODE *sbr_invf_mode, - INVF_MODE *sbr_invf_mode_prev - ); +typedef SBR_LPP_TRANS *HANDLE_SBR_LPP_TRANS; +void lppTransposer(HANDLE_SBR_LPP_TRANS hLppTrans, + QMF_SCALE_FACTOR *sbrScaleFactor, FIXP_DBL **qmfBufferReal, + + FIXP_DBL *degreeAlias, FIXP_DBL **qmfBufferImag, + const int useLP, const int fPreWhitening, + const int v_k_master0, const int timeStep, + const int firstSlotOffset, const int lastSlotOffset, + const int nInvfBands, INVF_MODE *sbr_invf_mode, + INVF_MODE *sbr_invf_mode_prev); + +void lppTransposerHBE( + HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + HANDLE_HBE_TRANSPOSER hQmfTransposer, + QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ + FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband + samples (source) */ + FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of + subband samples (source) */ + const int timeStep, /*!< Time step of envelope */ + const int firstSlotOffs, /*!< Start position in time */ + const int lastSlotOffs, /*!< Number of overlap-slots into next frame */ + const int nInvfBands, /*!< Number of bands for inverse filtering */ + INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ + INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */ +); SBR_ERROR -createLppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, - TRANSPOSER_SETTINGS *pSettings, - const int highBandStartSb, - UCHAR *v_k_master, - const int numMaster, - const int usb, - const int timeSlots, - const int nCols, - UCHAR *noiseBandTable, - const int noNoiseBands, - UINT fs, - const int chan, - const int overlap); - +createLppTransposer(HANDLE_SBR_LPP_TRANS hLppTrans, + TRANSPOSER_SETTINGS *pSettings, const int highBandStartSb, + UCHAR *v_k_master, const int numMaster, const int usb, + const int timeSlots, const int nCols, UCHAR *noiseBandTable, + const int noNoiseBands, UINT fs, const int chan, + const int overlap); SBR_ERROR -resetLppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, - UCHAR highBandStartSb, - UCHAR *v_k_master, - UCHAR numMaster, - UCHAR *noiseBandTable, - UCHAR noNoiseBands, - UCHAR usb, - UINT fs); - - - -#endif /* _LPP_TRANS_H */ +resetLppTransposer(HANDLE_SBR_LPP_TRANS hLppTrans, UCHAR highBandStartSb, + UCHAR *v_k_master, UCHAR numMaster, UCHAR *noiseBandTable, + UCHAR noNoiseBands, UCHAR usb, UINT fs); +#endif /* LPP_TRAN_H */ diff --git a/libSBRdec/src/psbitdec.cpp b/libSBRdec/src/psbitdec.cpp index 29bddf7..b2ea2e9 100644 --- a/libSBRdec/src/psbitdec.cpp +++ b/libSBRdec/src/psbitdec.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,17 +90,23 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -#include "psbitdec.h" +/**************************** SBR decoder library ****************************** + + Author(s): + Description: + +*******************************************************************************/ + +#include "psbitdec.h" #include "sbr_rom.h" #include "huff_dec.h" /* PS dec privat functions */ SBR_ERROR ResetPsDec(HANDLE_PS_DEC h_ps_d); -void ResetPsDeCor (HANDLE_PS_DEC h_ps_d); /***************************************************************************/ /*! @@ -98,24 +115,24 @@ void ResetPsDeCor (HANDLE_PS_DEC h_ps_d); \return index of huffman codebook table ****************************************************************************/ -static SCHAR -decode_huff_cw (Huffman h, /*!< pointer to huffman codebook table */ - HANDLE_FDK_BITSTREAM hBitBuf, /*!< Handle to Bitbuffer */ - int *length) /*!< length of huffman codeword (or NULL) */ +static SCHAR decode_huff_cw( + Huffman h, /*!< pointer to huffman codebook table */ + HANDLE_FDK_BITSTREAM hBitBuf, /*!< Handle to Bitbuffer */ + int *length) /*!< length of huffman codeword (or NULL) */ { UCHAR bit = 0; SCHAR index = 0; UCHAR bitCount = 0; while (index >= 0) { - bit = FDKreadBits (hBitBuf, 1); + bit = FDKreadBits(hBitBuf, 1); bitCount++; index = h[index][bit]; } if (length) { *length = bitCount; } - return( index+64 ); /* Add offset */ + return (index + 64); /* Add offset */ } /***************************************************************************/ @@ -126,14 +143,10 @@ decode_huff_cw (Huffman h, /*!< pointer to huffman codebook ****************************************************************************/ -static SCHAR -limitMinMax(SCHAR i, - SCHAR min, - SCHAR max) -{ - if (i<min) +static SCHAR limitMinMax(SCHAR i, SCHAR min, SCHAR max) { + if (i < min) return min; - else if (i>max) + else if (i > max) return max; else return i; @@ -150,44 +163,38 @@ limitMinMax(SCHAR i, \return none ****************************************************************************/ -static void -deltaDecodeArray(SCHAR enable, - SCHAR *aIndex, /*!< ICC/IID parameters */ - SCHAR *aPrevFrameIndex, /*!< ICC/IID parameters of previous frame */ - SCHAR DtDf, - UCHAR nrElements, /*!< as conveyed in bitstream */ - /*!< output array size: nrElements*stride */ - UCHAR stride, /*!< 1=dflt, 2=half freq. resolution */ - SCHAR minIdx, - SCHAR maxIdx) -{ +static void deltaDecodeArray( + SCHAR enable, SCHAR *aIndex, /*!< ICC/IID parameters */ + SCHAR *aPrevFrameIndex, /*!< ICC/IID parameters of previous frame */ + SCHAR DtDf, UCHAR nrElements, /*!< as conveyed in bitstream */ + /*!< output array size: nrElements*stride */ + UCHAR stride, /*!< 1=dflt, 2=half freq. resolution */ + SCHAR minIdx, SCHAR maxIdx) { int i; /* Delta decode */ - if ( enable==1 ) { - if (DtDf == 0) { /* Delta coded in freq */ + if (enable == 1) { + if (DtDf == 0) { /* Delta coded in freq */ aIndex[0] = 0 + aIndex[0]; - aIndex[0] = limitMinMax(aIndex[0],minIdx,maxIdx); + aIndex[0] = limitMinMax(aIndex[0], minIdx, maxIdx); for (i = 1; i < nrElements; i++) { - aIndex[i] = aIndex[i-1] + aIndex[i]; - aIndex[i] = limitMinMax(aIndex[i],minIdx,maxIdx); + aIndex[i] = aIndex[i - 1] + aIndex[i]; + aIndex[i] = limitMinMax(aIndex[i], minIdx, maxIdx); } - } - else { /* Delta time */ + } else { /* Delta time */ for (i = 0; i < nrElements; i++) { - aIndex[i] = aPrevFrameIndex[i*stride] + aIndex[i]; - aIndex[i] = limitMinMax(aIndex[i],minIdx,maxIdx); + aIndex[i] = aPrevFrameIndex[i * stride] + aIndex[i]; + aIndex[i] = limitMinMax(aIndex[i], minIdx, maxIdx); } } - } - else { /* No data is sent, set index to zero */ + } else { /* No data is sent, set index to zero */ for (i = 0; i < nrElements; i++) { aIndex[i] = 0; } } - if (stride==2) { - for (i=nrElements*stride-1; i>0; i--) { - aIndex[i] = aIndex[i>>1]; + if (stride == 2) { + for (i = nrElements * stride - 1; i > 0; i--) { + aIndex[i] = aIndex[i >> 1]; } } } @@ -199,33 +206,32 @@ deltaDecodeArray(SCHAR enable, \return none ****************************************************************************/ -static void map34IndexTo20 (SCHAR *aIndex, /*!< decoded ICC/IID parameters */ - UCHAR noBins) /*!< number of stereo bands */ +static void map34IndexTo20(SCHAR *aIndex, /*!< decoded ICC/IID parameters */ + UCHAR noBins) /*!< number of stereo bands */ { - aIndex[0] = (2*aIndex[0]+aIndex[1])/3; - aIndex[1] = (aIndex[1]+2*aIndex[2])/3; - aIndex[2] = (2*aIndex[3]+aIndex[4])/3; - aIndex[3] = (aIndex[4]+2*aIndex[5])/3; - aIndex[4] = (aIndex[6]+aIndex[7])/2; - aIndex[5] = (aIndex[8]+aIndex[9])/2; - aIndex[6] = aIndex[10]; - aIndex[7] = aIndex[11]; - aIndex[8] = (aIndex[12]+aIndex[13])/2; - aIndex[9] = (aIndex[14]+aIndex[15])/2; + aIndex[0] = (2 * aIndex[0] + aIndex[1]) / 3; + aIndex[1] = (aIndex[1] + 2 * aIndex[2]) / 3; + aIndex[2] = (2 * aIndex[3] + aIndex[4]) / 3; + aIndex[3] = (aIndex[4] + 2 * aIndex[5]) / 3; + aIndex[4] = (aIndex[6] + aIndex[7]) / 2; + aIndex[5] = (aIndex[8] + aIndex[9]) / 2; + aIndex[6] = aIndex[10]; + aIndex[7] = aIndex[11]; + aIndex[8] = (aIndex[12] + aIndex[13]) / 2; + aIndex[9] = (aIndex[14] + aIndex[15]) / 2; aIndex[10] = aIndex[16]; /* For IPD/OPD it stops here */ - if (noBins == NO_HI_RES_BINS) - { + if (noBins == NO_HI_RES_BINS) { aIndex[11] = aIndex[17]; aIndex[12] = aIndex[18]; aIndex[13] = aIndex[19]; - aIndex[14] = (aIndex[20]+aIndex[21])/2; - aIndex[15] = (aIndex[22]+aIndex[23])/2; - aIndex[16] = (aIndex[24]+aIndex[25])/2; - aIndex[17] = (aIndex[26]+aIndex[27])/2; - aIndex[18] = (aIndex[28]+aIndex[29]+aIndex[30]+aIndex[31])/4; - aIndex[19] = (aIndex[32]+aIndex[33])/2; + aIndex[14] = (aIndex[20] + aIndex[21]) / 2; + aIndex[15] = (aIndex[22] + aIndex[23]) / 2; + aIndex[16] = (aIndex[24] + aIndex[25]) / 2; + aIndex[17] = (aIndex[26] + aIndex[27]) / 2; + aIndex[18] = (aIndex[28] + aIndex[29] + aIndex[30] + aIndex[31]) / 4; + aIndex[19] = (aIndex[32] + aIndex[33]) / 2; } } @@ -236,24 +242,28 @@ static void map34IndexTo20 (SCHAR *aIndex, /*!< decoded ICC/IID parameters */ \return PS processing flag. If set to 1 ****************************************************************************/ -int -DecodePs( struct PS_DEC *h_ps_d, /*!< PS handle */ - const UCHAR frameError ) /*!< Flag telling that frame had errors */ -{ +int DecodePs(struct PS_DEC *h_ps_d, /*!< PS handle */ + const UCHAR frameError, /*!< Flag telling that frame had errors */ + PS_DEC_COEFFICIENTS *pScratch) { MPEG_PS_BS_DATA *pBsData; UCHAR gr, env; - int bPsHeaderValid, bPsDataAvail; + int bPsHeaderValid, bPsDataAvail; + + /* Assign Scratch */ + h_ps_d->specificTo.mpeg.pCoef = pScratch; /* Shortcuts to avoid deferencing and keep the code readable */ pBsData = &h_ps_d->bsData[h_ps_d->processSlot].mpeg; bPsHeaderValid = pBsData->bPsHeaderValid; - bPsDataAvail = (h_ps_d->bPsDataAvail[h_ps_d->processSlot] == ppt_mpeg) ? 1 : 0; + bPsDataAvail = + (h_ps_d->bPsDataAvail[h_ps_d->processSlot] == ppt_mpeg) ? 1 : 0; - /*************************************************************************************** - * Decide whether to process or to conceal PS data or not. */ + /*************************************************************************************** + * Decide whether to process or to conceal PS data or not. */ - if ( ( h_ps_d->psDecodedPrv && !frameError && !bPsDataAvail) - || (!h_ps_d->psDecodedPrv && (frameError || !bPsDataAvail || !bPsHeaderValid)) ) { + if ((h_ps_d->psDecodedPrv && !frameError && !bPsDataAvail) || + (!h_ps_d->psDecodedPrv && + (frameError || !bPsDataAvail || !bPsHeaderValid))) { /* Don't apply PS processing. * Declare current PS header and bitstream data invalid. */ pBsData->bPsHeaderValid = 0; @@ -261,75 +271,64 @@ DecodePs( struct PS_DEC *h_ps_d, /*!< PS handle */ return (0); } - if (frameError || !bPsHeaderValid) - { /* no new PS data available (e.g. frame loss) */ + if (frameError || + !bPsHeaderValid) { /* no new PS data available (e.g. frame loss) */ /* => keep latest data constant (i.e. FIX with noEnv=0) */ pBsData->noEnv = 0; } - /*************************************************************************************** - * Decode bitstream payload or prepare parameter for concealment: - */ - for (env=0; env<pBsData->noEnv; env++) { + /*************************************************************************************** + * Decode bitstream payload or prepare parameter for concealment: + */ + for (env = 0; env < pBsData->noEnv; env++) { SCHAR *aPrevIidIndex; SCHAR *aPrevIccIndex; - UCHAR noIidSteps = pBsData->bFineIidQ?NO_IID_STEPS_FINE:NO_IID_STEPS; + UCHAR noIidSteps = pBsData->bFineIidQ ? NO_IID_STEPS_FINE : NO_IID_STEPS; - if (env==0) { + if (env == 0) { aPrevIidIndex = h_ps_d->specificTo.mpeg.aIidPrevFrameIndex; aPrevIccIndex = h_ps_d->specificTo.mpeg.aIccPrevFrameIndex; - } - else { - aPrevIidIndex = pBsData->aaIidIndex[env-1]; - aPrevIccIndex = pBsData->aaIccIndex[env-1]; + } else { + aPrevIidIndex = pBsData->aaIidIndex[env - 1]; + aPrevIccIndex = pBsData->aaIccIndex[env - 1]; } - deltaDecodeArray(pBsData->bEnableIid, - pBsData->aaIidIndex[env], - aPrevIidIndex, - pBsData->abIidDtFlag[env], + deltaDecodeArray(pBsData->bEnableIid, pBsData->aaIidIndex[env], + aPrevIidIndex, pBsData->abIidDtFlag[env], FDK_sbrDecoder_aNoIidBins[pBsData->freqResIid], - (pBsData->freqResIid)?1:2, - -noIidSteps, - noIidSteps); - - deltaDecodeArray(pBsData->bEnableIcc, - pBsData->aaIccIndex[env], - aPrevIccIndex, - pBsData->abIccDtFlag[env], + (pBsData->freqResIid) ? 1 : 2, -noIidSteps, noIidSteps); + + deltaDecodeArray(pBsData->bEnableIcc, pBsData->aaIccIndex[env], + aPrevIccIndex, pBsData->abIccDtFlag[env], FDK_sbrDecoder_aNoIccBins[pBsData->freqResIcc], - (pBsData->freqResIcc)?1:2, - 0, - NO_ICC_STEPS-1); - } /* for (env=0; env<pBsData->noEnv; env++) */ + (pBsData->freqResIcc) ? 1 : 2, 0, NO_ICC_STEPS - 1); + } /* for (env=0; env<pBsData->noEnv; env++) */ /* handling of FIX noEnv=0 */ - if (pBsData->noEnv==0) { + if (pBsData->noEnv == 0) { /* set noEnv=1, keep last parameters or force 0 if not enabled */ pBsData->noEnv = 1; if (pBsData->bEnableIid) { for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) { - pBsData->aaIidIndex[pBsData->noEnv-1][gr] = - h_ps_d->specificTo.mpeg.aIidPrevFrameIndex[gr]; + pBsData->aaIidIndex[pBsData->noEnv - 1][gr] = + h_ps_d->specificTo.mpeg.aIidPrevFrameIndex[gr]; } - } - else { + } else { for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) { - pBsData->aaIidIndex[pBsData->noEnv-1][gr] = 0; + pBsData->aaIidIndex[pBsData->noEnv - 1][gr] = 0; } } if (pBsData->bEnableIcc) { for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) { - pBsData->aaIccIndex[pBsData->noEnv-1][gr] = - h_ps_d->specificTo.mpeg.aIccPrevFrameIndex[gr]; + pBsData->aaIccIndex[pBsData->noEnv - 1][gr] = + h_ps_d->specificTo.mpeg.aIccPrevFrameIndex[gr]; } - } - else { + } else { for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) { - pBsData->aaIccIndex[pBsData->noEnv-1][gr] = 0; + pBsData->aaIccIndex[pBsData->noEnv - 1][gr] = 0; } } } @@ -337,11 +336,11 @@ DecodePs( struct PS_DEC *h_ps_d, /*!< PS handle */ /* Update previous frame index buffers */ for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) { h_ps_d->specificTo.mpeg.aIidPrevFrameIndex[gr] = - pBsData->aaIidIndex[pBsData->noEnv-1][gr]; + pBsData->aaIidIndex[pBsData->noEnv - 1][gr]; } for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) { h_ps_d->specificTo.mpeg.aIccPrevFrameIndex[gr] = - pBsData->aaIccIndex[pBsData->noEnv-1][gr]; + pBsData->aaIccIndex[pBsData->noEnv - 1][gr]; } /* PS data from bitstream (if avail) was decoded now */ @@ -351,15 +350,14 @@ DecodePs( struct PS_DEC *h_ps_d, /*!< PS handle */ if (pBsData->bFrameClass == 0) { /* FIX_BORDERS NoEnv=0,1,2,4 */ pBsData->aEnvStartStop[0] = 0; - for (env=1; env<pBsData->noEnv; env++) { + for (env = 1; env < pBsData->noEnv; env++) { pBsData->aEnvStartStop[env] = - (env * h_ps_d->noSubSamples) / pBsData->noEnv; + (env * h_ps_d->noSubSamples) / pBsData->noEnv; } pBsData->aEnvStartStop[pBsData->noEnv] = h_ps_d->noSubSamples; /* 1024 (32 slots) env borders: 0, 8, 16, 24, 32 */ /* 960 (30 slots) env borders: 0, 7, 15, 22, 30 */ - } - else { /* if (h_ps_d->bFrameClass == 0) */ + } else { /* if (h_ps_d->bFrameClass == 0) */ /* VAR_BORDERS NoEnv=1,2,3,4 */ pBsData->aEnvStartStop[0] = 0; @@ -368,55 +366,59 @@ DecodePs( struct PS_DEC *h_ps_d, /*!< PS handle */ if (pBsData->aEnvStartStop[pBsData->noEnv] < h_ps_d->noSubSamples) { for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) { pBsData->aaIidIndex[pBsData->noEnv][gr] = - pBsData->aaIidIndex[pBsData->noEnv-1][gr]; + pBsData->aaIidIndex[pBsData->noEnv - 1][gr]; } for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) { pBsData->aaIccIndex[pBsData->noEnv][gr] = - pBsData->aaIccIndex[pBsData->noEnv-1][gr]; + pBsData->aaIccIndex[pBsData->noEnv - 1][gr]; } pBsData->noEnv++; pBsData->aEnvStartStop[pBsData->noEnv] = h_ps_d->noSubSamples; } /* enforce strictly monotonic increasing borders */ - for (env=1; env<pBsData->noEnv; env++) { + for (env = 1; env < pBsData->noEnv; env++) { UCHAR thr; thr = (UCHAR)h_ps_d->noSubSamples - (pBsData->noEnv - env); if (pBsData->aEnvStartStop[env] > thr) { pBsData->aEnvStartStop[env] = thr; - } - else { - thr = pBsData->aEnvStartStop[env-1]+1; + } else { + thr = pBsData->aEnvStartStop[env - 1] + 1; if (pBsData->aEnvStartStop[env] < thr) { pBsData->aEnvStartStop[env] = thr; } } } - } /* if (h_ps_d->bFrameClass == 0) ... else */ + } /* if (h_ps_d->bFrameClass == 0) ... else */ /* copy data prior to possible 20<->34 in-place mapping */ - for (env=0; env<pBsData->noEnv; env++) { + for (env = 0; env < pBsData->noEnv; env++) { UCHAR i; - for (i=0; i<NO_HI_RES_IID_BINS; i++) { - h_ps_d->specificTo.mpeg.coef.aaIidIndexMapped[env][i] = pBsData->aaIidIndex[env][i]; + for (i = 0; i < NO_HI_RES_IID_BINS; i++) { + h_ps_d->specificTo.mpeg.pCoef->aaIidIndexMapped[env][i] = + pBsData->aaIidIndex[env][i]; } - for (i=0; i<NO_HI_RES_ICC_BINS; i++) { - h_ps_d->specificTo.mpeg.coef.aaIccIndexMapped[env][i] = pBsData->aaIccIndex[env][i]; + for (i = 0; i < NO_HI_RES_ICC_BINS; i++) { + h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env][i] = + pBsData->aaIccIndex[env][i]; } } - /* MPEG baseline PS */ - /* Baseline version of PS always uses the hybrid filter structure with 20 stereo bands. */ - /* If ICC/IID parameters for 34 stereo bands are decoded they have to be mapped to 20 */ - /* stereo bands. */ - /* Additionaly the IPD/OPD parameters won't be used. */ - - for (env=0; env<pBsData->noEnv; env++) { + /* Baseline version of PS always uses the hybrid filter structure with 20 + * stereo bands. */ + /* If ICC/IID parameters for 34 stereo bands are decoded they have to be + * mapped to 20 */ + /* stereo bands. */ + /* Additionaly the IPD/OPD parameters won't be used. */ + + for (env = 0; env < pBsData->noEnv; env++) { if (pBsData->freqResIid == 2) - map34IndexTo20 (h_ps_d->specificTo.mpeg.coef.aaIidIndexMapped[env], NO_HI_RES_IID_BINS); + map34IndexTo20(h_ps_d->specificTo.mpeg.pCoef->aaIidIndexMapped[env], + NO_HI_RES_IID_BINS); if (pBsData->freqResIcc == 2) - map34IndexTo20 (h_ps_d->specificTo.mpeg.coef.aaIccIndexMapped[env], NO_HI_RES_ICC_BINS); + map34IndexTo20(h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env], + NO_HI_RES_ICC_BINS); /* IPD/OPD is disabled in baseline version and thus was removed here */ } @@ -424,7 +426,6 @@ DecodePs( struct PS_DEC *h_ps_d, /*!< PS handle */ return (1); } - /***************************************************************************/ /*! @@ -433,62 +434,60 @@ DecodePs( struct PS_DEC *h_ps_d, /*!< PS handle */ \return ****************************************************************************/ -unsigned int -ReadPsData (HANDLE_PS_DEC h_ps_d, /*!< handle to struct PS_DEC */ - HANDLE_FDK_BITSTREAM hBitBuf, /*!< handle to struct BIT_BUF */ - int nBitsLeft /*!< max number of bits available */ - ) -{ +unsigned int ReadPsData( + HANDLE_PS_DEC h_ps_d, /*!< handle to struct PS_DEC */ + HANDLE_FDK_BITSTREAM hBitBuf, /*!< handle to struct BIT_BUF */ + int nBitsLeft /*!< max number of bits available */ +) { MPEG_PS_BS_DATA *pBsData; - UCHAR gr, env; - SCHAR dtFlag; - INT startbits; - Huffman CurrentTable; - SCHAR bEnableHeader; + UCHAR gr, env; + SCHAR dtFlag; + INT startbits; + Huffman CurrentTable; + SCHAR bEnableHeader; - if (!h_ps_d) - return 0; + if (!h_ps_d) return 0; pBsData = &h_ps_d->bsData[h_ps_d->bsReadSlot].mpeg; if (h_ps_d->bsReadSlot != h_ps_d->bsLastSlot) { /* Copy last header data */ - FDKmemcpy(pBsData, &h_ps_d->bsData[h_ps_d->bsLastSlot].mpeg, sizeof(MPEG_PS_BS_DATA)); + FDKmemcpy(pBsData, &h_ps_d->bsData[h_ps_d->bsLastSlot].mpeg, + sizeof(MPEG_PS_BS_DATA)); } + startbits = (INT)FDKgetValidBits(hBitBuf); - startbits = (INT) FDKgetValidBits(hBitBuf); - - bEnableHeader = (SCHAR) FDKreadBits (hBitBuf, 1); + bEnableHeader = (SCHAR)FDKreadBits(hBitBuf, 1); /* Read header */ if (bEnableHeader) { pBsData->bPsHeaderValid = 1; - pBsData->bEnableIid = (UCHAR) FDKreadBits (hBitBuf, 1); + pBsData->bEnableIid = (UCHAR)FDKreadBits(hBitBuf, 1); if (pBsData->bEnableIid) { - pBsData->modeIid = (UCHAR) FDKreadBits (hBitBuf, 3); + pBsData->modeIid = (UCHAR)FDKreadBits(hBitBuf, 3); } - pBsData->bEnableIcc = (UCHAR) FDKreadBits (hBitBuf, 1); + pBsData->bEnableIcc = (UCHAR)FDKreadBits(hBitBuf, 1); if (pBsData->bEnableIcc) { - pBsData->modeIcc = (UCHAR) FDKreadBits (hBitBuf, 3); + pBsData->modeIcc = (UCHAR)FDKreadBits(hBitBuf, 3); } - pBsData->bEnableExt = (UCHAR) FDKreadBits (hBitBuf, 1); + pBsData->bEnableExt = (UCHAR)FDKreadBits(hBitBuf, 1); } - pBsData->bFrameClass = (UCHAR) FDKreadBits (hBitBuf, 1); + pBsData->bFrameClass = (UCHAR)FDKreadBits(hBitBuf, 1); if (pBsData->bFrameClass == 0) { /* FIX_BORDERS NoEnv=0,1,2,4 */ - pBsData->noEnv = FDK_sbrDecoder_aFixNoEnvDecode[(UCHAR) FDKreadBits (hBitBuf, 2)]; + pBsData->noEnv = + FDK_sbrDecoder_aFixNoEnvDecode[(UCHAR)FDKreadBits(hBitBuf, 2)]; /* all additional handling of env borders is now in DecodePs() */ - } - else { + } else { /* VAR_BORDERS NoEnv=1,2,3,4 */ - pBsData->noEnv = 1+(UCHAR) FDKreadBits (hBitBuf, 2); - for (env=1; env<pBsData->noEnv+1; env++) - pBsData->aEnvStartStop[env] = ((UCHAR) FDKreadBits (hBitBuf, 5)) + 1; + pBsData->noEnv = 1 + (UCHAR)FDKreadBits(hBitBuf, 2); + for (env = 1; env < pBsData->noEnv + 1; env++) + pBsData->aEnvStartStop[env] = ((UCHAR)FDKreadBits(hBitBuf, 5)) + 1; /* all additional handling of env borders is now in DecodePs() */ } @@ -498,76 +497,71 @@ ReadPsData (HANDLE_PS_DEC h_ps_d, /*!< handle to struct PS_DEC */ h_ps_d->bPsDataAvail[h_ps_d->bsReadSlot] = ppt_none; /* discard all remaining bits */ nBitsLeft -= startbits - FDKgetValidBits(hBitBuf); - while (nBitsLeft) { + while (nBitsLeft > 0) { int i = nBitsLeft; - if (i>8) { + if (i > 8) { i = 8; } - FDKreadBits (hBitBuf, i); + FDKreadBits(hBitBuf, i); nBitsLeft -= i; } return (startbits - FDKgetValidBits(hBitBuf)); } - if (pBsData->modeIid > 2){ - pBsData->freqResIid = pBsData->modeIid-3; + if (pBsData->modeIid > 2) { + pBsData->freqResIid = pBsData->modeIid - 3; pBsData->bFineIidQ = 1; - } - else{ + } else { pBsData->freqResIid = pBsData->modeIid; pBsData->bFineIidQ = 0; } - if (pBsData->modeIcc > 2){ - pBsData->freqResIcc = pBsData->modeIcc-3; - } - else{ + if (pBsData->modeIcc > 2) { + pBsData->freqResIcc = pBsData->modeIcc - 3; + } else { pBsData->freqResIcc = pBsData->modeIcc; } - /* Extract IID data */ if (pBsData->bEnableIid) { - for (env=0; env<pBsData->noEnv; env++) { - dtFlag = (SCHAR)FDKreadBits (hBitBuf, 1); - if (!dtFlag) - { + for (env = 0; env < pBsData->noEnv; env++) { + dtFlag = (SCHAR)FDKreadBits(hBitBuf, 1); + if (!dtFlag) { if (pBsData->bFineIidQ) CurrentTable = (Huffman)&aBookPsIidFineFreqDecode; else CurrentTable = (Huffman)&aBookPsIidFreqDecode; - } - else - { + } else { if (pBsData->bFineIidQ) - CurrentTable = (Huffman)&aBookPsIidFineTimeDecode; + CurrentTable = (Huffman)&aBookPsIidFineTimeDecode; else CurrentTable = (Huffman)&aBookPsIidTimeDecode; } for (gr = 0; gr < FDK_sbrDecoder_aNoIidBins[pBsData->freqResIid]; gr++) - pBsData->aaIidIndex[env][gr] = decode_huff_cw(CurrentTable,hBitBuf,NULL); + pBsData->aaIidIndex[env][gr] = + decode_huff_cw(CurrentTable, hBitBuf, NULL); pBsData->abIidDtFlag[env] = dtFlag; } } /* Extract ICC data */ if (pBsData->bEnableIcc) { - for (env=0; env<pBsData->noEnv; env++) { - dtFlag = (SCHAR)FDKreadBits (hBitBuf, 1); + for (env = 0; env < pBsData->noEnv; env++) { + dtFlag = (SCHAR)FDKreadBits(hBitBuf, 1); if (!dtFlag) CurrentTable = (Huffman)&aBookPsIccFreqDecode; else CurrentTable = (Huffman)&aBookPsIccTimeDecode; for (gr = 0; gr < FDK_sbrDecoder_aNoIccBins[pBsData->freqResIcc]; gr++) - pBsData->aaIccIndex[env][gr] = decode_huff_cw(CurrentTable,hBitBuf,NULL); + pBsData->aaIccIndex[env][gr] = + decode_huff_cw(CurrentTable, hBitBuf, NULL); pBsData->abIccDtFlag[env] = dtFlag; } } if (pBsData->bEnableExt) { - /*! Decoders that support only the baseline version of the PS tool are allowed to ignore the IPD/OPD data, but according header data has to be parsed. @@ -575,19 +569,14 @@ ReadPsData (HANDLE_PS_DEC h_ps_d, /*!< handle to struct PS_DEC */ */ int cnt = FDKreadBits(hBitBuf, PS_EXTENSION_SIZE_BITS); - if (cnt == (1<<PS_EXTENSION_SIZE_BITS)-1) { + if (cnt == (1 << PS_EXTENSION_SIZE_BITS) - 1) { cnt += FDKreadBits(hBitBuf, PS_EXTENSION_ESC_COUNT_BITS); } - while (cnt--) - FDKreadBits(hBitBuf, 8); + while (cnt--) FDKreadBits(hBitBuf, 8); } - /* new PS data was read from bitstream */ h_ps_d->bPsDataAvail[h_ps_d->bsReadSlot] = ppt_mpeg; - - - return (startbits - FDKgetValidBits(hBitBuf)); + return (startbits - (INT)FDKgetValidBits(hBitBuf)); } - diff --git a/libSBRdec/src/psbitdec.h b/libSBRdec/src/psbitdec.h index a2d4d6c..f0fc43a 100644 --- a/libSBRdec/src/psbitdec.h +++ b/libSBRdec/src/psbitdec.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,25 +90,27 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -#ifndef __PSBITDEC_H -#define __PSBITDEC_H +/**************************** SBR decoder library ****************************** -#include "sbrdecoder.h" + Author(s): + Description: -#include "psdec.h" +*******************************************************************************/ +#ifndef PSBITDEC_H +#define PSBITDEC_H -unsigned int -ReadPsData (struct PS_DEC *h_ps_d, - HANDLE_FDK_BITSTREAM hBs, - int nBitsLeft); +#include "sbrdecoder.h" + +#include "psdec.h" -int -DecodePs(struct PS_DEC *h_ps_d, - const UCHAR frameError); +unsigned int ReadPsData(struct PS_DEC *h_ps_d, HANDLE_FDK_BITSTREAM hBs, + int nBitsLeft); +int DecodePs(struct PS_DEC *h_ps_d, const UCHAR frameError, + PS_DEC_COEFFICIENTS *pCoef); -#endif /* __PSBITDEC_H */ +#endif /* PSBITDEC_H */ diff --git a/libSBRdec/src/psdec.cpp b/libSBRdec/src/psdec.cpp index 965917a..13a21bf 100644 --- a/libSBRdec/src/psdec.cpp +++ b/libSBRdec/src/psdec.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,19 +90,24 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief parametric stereo decoder + \brief parametric stereo decoder */ #include "psdec.h" - - #include "FDK_bitbuffer.h" -#include "psdec_hybrid.h" #include "sbr_rom.h" #include "sbr_ram.h" @@ -102,30 +118,17 @@ amm-info@iis.fraunhofer.de #include "FDK_trigFcts.h" - /********************************************************************/ /* MLQUAL DEFINES */ /********************************************************************/ - #define FRACT_ZERO FRACT_BITS-1 +#define FRACT_ZERO FRACT_BITS - 1 /********************************************************************/ -SBR_ERROR ResetPsDec( HANDLE_PS_DEC h_ps_d ); - -void ResetPsDeCor( HANDLE_PS_DEC h_ps_d ); - +SBR_ERROR ResetPsDec(HANDLE_PS_DEC h_ps_d); /***** HELPERS *****/ -static void assignTimeSlotsPS (FIXP_DBL *bufAdr, FIXP_DBL **bufPtr, const int numSlots, const int numChan); - - - -/*******************/ - -#define DIV3 FL2FXCONST_DBL(1.f/3.f) /* division 3.0 */ -#define DIV1_5 FL2FXCONST_DBL(2.f/3.f) /* division 1.5 */ - /***************************************************************************/ /*! \brief Creates one instance of the PS_DEC struct @@ -133,20 +136,16 @@ static void assignTimeSlotsPS (FIXP_DBL *bufAdr, FIXP_DBL **bufPtr, const int nu \return Error info ****************************************************************************/ -int -CreatePsDec( HANDLE_PS_DEC *h_PS_DEC, /*!< pointer to the module state */ - int aacSamplesPerFrame - ) -{ +int CreatePsDec(HANDLE_PS_DEC *h_PS_DEC, /*!< pointer to the module state */ + int aacSamplesPerFrame) { SBR_ERROR errorInfo = SBRDEC_OK; - HANDLE_PS_DEC h_ps_d; + HANDLE_PS_DEC h_ps_d; int i; if (*h_PS_DEC == NULL) { /* Get ps dec ram */ h_ps_d = GetRam_ps_dec(); if (h_ps_d == NULL) { - errorInfo = SBRDEC_MEM_ALLOC_FAILED; goto bail; } } else { @@ -154,52 +153,61 @@ CreatePsDec( HANDLE_PS_DEC *h_PS_DEC, /*!< pointer to the module state */ h_ps_d = *h_PS_DEC; } - /* initialisation */ - switch (aacSamplesPerFrame) { - case 960: - h_ps_d->noSubSamples = 30; /* col */ - break; - case 1024: - h_ps_d->noSubSamples = 32; /* col */ - break; - default: - h_ps_d->noSubSamples = -1; - break; - } + /* + * Create Analysis Hybrid filterbank. + */ + FDKhybridAnalysisOpen(&h_ps_d->specificTo.mpeg.hybridAnalysis, + h_ps_d->specificTo.mpeg.pHybridAnaStatesLFdmx, + sizeof(h_ps_d->specificTo.mpeg.pHybridAnaStatesLFdmx), + NULL, 0); - if (h_ps_d->noSubSamples > MAX_NUM_COL - || h_ps_d->noSubSamples <= 0) - { + /* initialisation */ + switch (aacSamplesPerFrame) { + case 960: + h_ps_d->noSubSamples = 30; /* col */ + break; + case 1024: + h_ps_d->noSubSamples = 32; /* col */ + break; + default: + h_ps_d->noSubSamples = -1; + break; + } + + if (h_ps_d->noSubSamples > MAX_NUM_COL || h_ps_d->noSubSamples <= 0) { goto bail; } - h_ps_d->noChannels = NO_QMF_CHANNELS; /* row */ + h_ps_d->noChannels = NO_QMF_CHANNELS; /* row */ - h_ps_d->psDecodedPrv = 0; + h_ps_d->psDecodedPrv = 0; h_ps_d->procFrameBased = -1; - for (i = 0; i < (1)+1; i++) { - h_ps_d->bPsDataAvail[i] = ppt_none; + for (i = 0; i < (1) + 1; i++) { + h_ps_d->bPsDataAvail[i] = ppt_none; + } + { + int error; + error = FDKdecorrelateOpen(&(h_ps_d->specificTo.mpeg.apDecor), + h_ps_d->specificTo.mpeg.decorrBufferCplx, + (2 * ((825) + (373)))); + if (error) goto bail; } - - for (i = 0; i < (1)+1; i++) { + for (i = 0; i < (1) + 1; i++) { FDKmemclear(&h_ps_d->bsData[i].mpeg, sizeof(MPEG_PS_BS_DATA)); } - errorInfo = ResetPsDec( h_ps_d ); + errorInfo = ResetPsDec(h_ps_d); - if ( errorInfo != SBRDEC_OK ) - goto bail; - - ResetPsDeCor( h_ps_d ); + if (errorInfo != SBRDEC_OK) goto bail; *h_PS_DEC = h_ps_d; - - return 0; bail: - DeletePsDec(&h_ps_d); + if (h_ps_d != NULL) { + DeletePsDec(&h_ps_d); + } return -1; } /*END CreatePsDec */ @@ -211,17 +219,19 @@ bail: \return Error info ****************************************************************************/ -int -DeletePsDec( HANDLE_PS_DEC *h_PS_DEC) /*!< pointer to the module state */ +int DeletePsDec(HANDLE_PS_DEC *h_PS_DEC) /*!< pointer to the module state */ { if (*h_PS_DEC == NULL) { return -1; } + { + HANDLE_PS_DEC h_ps_d = *h_PS_DEC; + FDKdecorrelateClose(&(h_ps_d->specificTo.mpeg.apDecor)); + } FreeRam_ps_dec(h_PS_DEC); - return 0; } /*END DeletePsDec */ @@ -232,825 +242,179 @@ DeletePsDec( HANDLE_PS_DEC *h_PS_DEC) /*!< pointer to the module state */ \return ****************************************************************************/ -SBR_ERROR ResetPsDec( HANDLE_PS_DEC h_ps_d ) /*!< pointer to the module state */ +SBR_ERROR ResetPsDec(HANDLE_PS_DEC h_ps_d) /*!< pointer to the module state */ { SBR_ERROR errorInfo = SBRDEC_OK; INT i; - const UCHAR noQmfBandsInHybrid20 = 3; - /* const UCHAR noQmfBandsInHybrid34 = 5; */ - - const UCHAR aHybridResolution20[] = { HYBRID_8_CPLX, - HYBRID_2_REAL, - HYBRID_2_REAL }; - - h_ps_d->specificTo.mpeg.delayBufIndex = 0; + /* explicitly init state variables to safe values (until first ps header + * arrives) */ - /* explicitly init state variables to safe values (until first ps header arrives) */ + h_ps_d->specificTo.mpeg.lastUsb = 0; - h_ps_d->specificTo.mpeg.lastUsb = 0; + /* + * Initialize Analysis Hybrid filterbank. + */ + FDKhybridAnalysisInit(&h_ps_d->specificTo.mpeg.hybridAnalysis, THREE_TO_TEN, + NO_QMF_BANDS_HYBRID20, NO_QMF_BANDS_HYBRID20, 1); - h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer = -(DFRACT_BITS-1); - - FDKmemclear(h_ps_d->specificTo.mpeg.aDelayBufIndexDelayQmf, (NO_QMF_CHANNELS-FIRST_DELAY_SB)*sizeof(UCHAR)); - h_ps_d->specificTo.mpeg.noSampleDelay = delayIndexQmf[0]; - - for (i=0 ; i < NO_SERIAL_ALLPASS_LINKS; i++) { - h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[i] = 0; + /* + * Initialize Synthesis Hybrid filterbank. + */ + for (i = 0; i < 2; i++) { + FDKhybridSynthesisInit(&h_ps_d->specificTo.mpeg.hybridSynthesis[i], + THREE_TO_TEN, NO_QMF_CHANNELS, NO_QMF_CHANNELS); } - - h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[0] = h_ps_d->specificTo.mpeg.aaQmfDelayBufReal; - - assignTimeSlotsPS ( h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[0] + (NO_QMF_CHANNELS-FIRST_DELAY_SB), - &h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[1], - h_ps_d->specificTo.mpeg.noSampleDelay-1, - (NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB)); - - h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[0] = h_ps_d->specificTo.mpeg.aaQmfDelayBufImag; - - assignTimeSlotsPS ( h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[0] + (NO_QMF_CHANNELS-FIRST_DELAY_SB), - &h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[1], - h_ps_d->specificTo.mpeg.noSampleDelay-1, - (NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB)); - - /* Hybrid Filter Bank 1 creation. */ - errorInfo = InitHybridFilterBank ( &h_ps_d->specificTo.mpeg.hybrid, - h_ps_d->noSubSamples, - noQmfBandsInHybrid20, - aHybridResolution20 ); - - for ( i = 0; i < NO_IID_GROUPS; i++ ) { + INT error; + error = FDKdecorrelateInit(&h_ps_d->specificTo.mpeg.apDecor, 71, DECORR_PS, + DUCKER_AUTOMATIC, 0, 0, 0, 0, 1, /* isLegacyPS */ + 1); + if (error) return SBRDEC_NOT_INITIALIZED; + } + + for (i = 0; i < NO_IID_GROUPS; i++) { h_ps_d->specificTo.mpeg.h11rPrev[i] = FL2FXCONST_DBL(0.5f); h_ps_d->specificTo.mpeg.h12rPrev[i] = FL2FXCONST_DBL(0.5f); } - FDKmemclear( h_ps_d->specificTo.mpeg.h21rPrev, sizeof( h_ps_d->specificTo.mpeg.h21rPrev ) ); - FDKmemclear( h_ps_d->specificTo.mpeg.h22rPrev, sizeof( h_ps_d->specificTo.mpeg.h22rPrev ) ); + FDKmemclear(h_ps_d->specificTo.mpeg.h21rPrev, + sizeof(h_ps_d->specificTo.mpeg.h21rPrev)); + FDKmemclear(h_ps_d->specificTo.mpeg.h22rPrev, + sizeof(h_ps_d->specificTo.mpeg.h22rPrev)); return errorInfo; } /***************************************************************************/ /*! - \brief clear some buffers used in decorrelation process - - \return - -****************************************************************************/ -void ResetPsDeCor( HANDLE_PS_DEC h_ps_d ) /*!< pointer to the module state */ -{ - INT i; - - FDKmemclear(h_ps_d->specificTo.mpeg.aPeakDecayFastBin, NO_MID_RES_BINS*sizeof(FIXP_DBL)); - FDKmemclear(h_ps_d->specificTo.mpeg.aPrevNrgBin, NO_MID_RES_BINS*sizeof(FIXP_DBL)); - FDKmemclear(h_ps_d->specificTo.mpeg.aPrevPeakDiffBin, NO_MID_RES_BINS*sizeof(FIXP_DBL)); - FDKmemclear(h_ps_d->specificTo.mpeg.aPowerPrevScal, NO_MID_RES_BINS*sizeof(SCHAR)); - - for (i=0 ; i < FIRST_DELAY_SB ; i++) { - FDKmemclear(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL)); - FDKmemclear(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL)); - } - for (i=0 ; i < NO_SUB_QMF_CHANNELS ; i++) { - FDKmemclear(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL)); - FDKmemclear(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL)); - } - -} - -/*******************************************************************************/ - -/* slot based funcion prototypes */ - -static void deCorrelateSlotBased( HANDLE_PS_DEC h_ps_d, - - FIXP_DBL *mHybridRealLeft, - FIXP_DBL *mHybridImagLeft, - SCHAR sf_mHybridLeft, - - FIXP_DBL *rIntBufferLeft, - FIXP_DBL *iIntBufferLeft, - SCHAR sf_IntBuffer, - - FIXP_DBL *mHybridRealRight, - FIXP_DBL *mHybridImagRight, - - FIXP_DBL *rIntBufferRight, - FIXP_DBL *iIntBufferRight ); - -static void applySlotBasedRotation( HANDLE_PS_DEC h_ps_d, - - FIXP_DBL *mHybridRealLeft, - FIXP_DBL *mHybridImagLeft, - - FIXP_DBL *QmfLeftReal, - FIXP_DBL *QmfLeftImag, - - FIXP_DBL *mHybridRealRight, - FIXP_DBL *mHybridImagRight, - - FIXP_DBL *QmfRightReal, - FIXP_DBL *QmfRightImag - ); - - -/***************************************************************************/ -/*! - \brief Get scale factor for all ps delay buffer. - - \return - -****************************************************************************/ -static -int getScaleFactorPsStatesBuffer(HANDLE_PS_DEC h_ps_d) -{ - INT i; - int scale = DFRACT_BITS-1; - - for (i=0; i<NO_QMF_BANDS_HYBRID20; i++) { - scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.hybrid.mQmfBufferRealSlot[i], NO_SUB_QMF_CHANNELS)); - scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.hybrid.mQmfBufferImagSlot[i], NO_SUB_QMF_CHANNELS)); - } - - for (i=0; i<NO_SAMPLE_DELAY_ALLPASS; i++) { - scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaRealDelayBufferQmf[i], FIRST_DELAY_SB)); - scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaImagDelayBufferQmf[i], FIRST_DELAY_SB)); - } - - for (i=0; i<NO_SAMPLE_DELAY_ALLPASS; i++) { - scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaRealDelayBufferSubQmf[i], NO_SUB_QMF_CHANNELS)); - scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaImagDelayBufferSubQmf[i], NO_SUB_QMF_CHANNELS)); - } - - for (i=0; i<FIRST_DELAY_SB; i++) { - scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS)); - scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS)); - } - - for (i=0; i<NO_SUB_QMF_CHANNELS; i++) { - scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS)); - scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS)); - } - - for (i=0; i<MAX_DELAY_BUFFER_SIZE; i++) - { - INT len; - if (i==0) - len = NO_QMF_CHANNELS-FIRST_DELAY_SB; - else - len = NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB; - - scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[i], len)); - scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[i], len)); - } - - return (scale); -} - -/***************************************************************************/ -/*! - \brief Rescale all ps delay buffer. - + \brief Feed delaylines when parametric stereo is switched on. \return - ****************************************************************************/ -static -void scalePsStatesBuffer(HANDLE_PS_DEC h_ps_d, - int scale) -{ - INT i; - - if (scale < 0) - scale = fixMax((INT)scale,(INT)-(DFRACT_BITS-1)); - else - scale = fixMin((INT)scale,(INT)DFRACT_BITS-1); - - for (i=0; i<NO_QMF_BANDS_HYBRID20; i++) { - scaleValues( h_ps_d->specificTo.mpeg.hybrid.mQmfBufferRealSlot[i], NO_SUB_QMF_CHANNELS, scale ); - scaleValues( h_ps_d->specificTo.mpeg.hybrid.mQmfBufferImagSlot[i], NO_SUB_QMF_CHANNELS, scale ); - } - - for (i=0; i<NO_SAMPLE_DELAY_ALLPASS; i++) { - scaleValues( h_ps_d->specificTo.mpeg.aaRealDelayBufferQmf[i], FIRST_DELAY_SB, scale ); - scaleValues( h_ps_d->specificTo.mpeg.aaImagDelayBufferQmf[i], FIRST_DELAY_SB, scale ); - } - - for (i=0; i<NO_SAMPLE_DELAY_ALLPASS; i++) { - scaleValues( h_ps_d->specificTo.mpeg.aaRealDelayBufferSubQmf[i], NO_SUB_QMF_CHANNELS, scale ); - scaleValues( h_ps_d->specificTo.mpeg.aaImagDelayBufferSubQmf[i], NO_SUB_QMF_CHANNELS, scale ); - } - - for (i=0; i<FIRST_DELAY_SB; i++) { - scaleValues( h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS, scale ); - scaleValues( h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS, scale ); - } - - for (i=0; i<NO_SUB_QMF_CHANNELS; i++) { - scaleValues( h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS, scale ); - scaleValues( h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS, scale ); - } - - for (i=0; i<MAX_DELAY_BUFFER_SIZE; i++) { - INT len; - if (i==0) - len = NO_QMF_CHANNELS-FIRST_DELAY_SB; - else - len = NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB; - - scaleValues( h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[i], len, scale ); - scaleValues( h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[i], len, scale ); - } - - scale <<= 1; - - scaleValues( h_ps_d->specificTo.mpeg.aPeakDecayFastBin, NO_MID_RES_BINS, scale ); - scaleValues( h_ps_d->specificTo.mpeg.aPrevPeakDiffBin, NO_MID_RES_BINS, scale ); - scaleValues( h_ps_d->specificTo.mpeg.aPrevNrgBin, NO_MID_RES_BINS, scale ); -} - -/***************************************************************************/ -/*! - \brief Scale input channel to the same scalefactor and rescale hybrid - filterbank values - - \return - -****************************************************************************/ - -void scalFilterBankValues( HANDLE_PS_DEC h_ps_d, - FIXP_DBL **fixpQmfReal, - FIXP_DBL **fixpQmfImag, - int lsb, - int scaleFactorLowBandSplitLow, - int scaleFactorLowBandSplitHigh, - SCHAR *scaleFactorLowBand_lb, - SCHAR *scaleFactorLowBand_hb, - int scaleFactorHighBands, - INT *scaleFactorHighBand, - INT noCols - ) -{ - INT maxScal; - - INT i; - - scaleFactorHighBands = -scaleFactorHighBands; - scaleFactorLowBandSplitLow = -scaleFactorLowBandSplitLow; - scaleFactorLowBandSplitHigh = -scaleFactorLowBandSplitHigh; - - /* get max scale factor */ - maxScal = fixMax(scaleFactorHighBands,fixMax(scaleFactorLowBandSplitLow, scaleFactorLowBandSplitHigh )); - - { - int headroom = getScaleFactorPsStatesBuffer(h_ps_d); - maxScal = fixMax(maxScal,(INT)(h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer-headroom)); - maxScal += 1; - } - - /* scale whole left channel to the same scale factor */ - - /* low band ( overlap buffer ) */ - if ( maxScal != scaleFactorLowBandSplitLow ) { - INT scale = scaleFactorLowBandSplitLow - maxScal; - for ( i=0; i<(6); i++ ) { - scaleValues( fixpQmfReal[i], lsb, scale ); - scaleValues( fixpQmfImag[i], lsb, scale ); - } - } - /* low band ( current frame ) */ - if ( maxScal != scaleFactorLowBandSplitHigh ) { - INT scale = scaleFactorLowBandSplitHigh - maxScal; - /* for ( i=(6); i<(6)+MAX_NUM_COL; i++ ) { */ - for ( i=(6); i<(6)+noCols; i++ ) { - scaleValues( fixpQmfReal[i], lsb, scale ); - scaleValues( fixpQmfImag[i], lsb, scale ); - } - } - /* high band */ - if ( maxScal != scaleFactorHighBands ) { - INT scale = scaleFactorHighBands - maxScal; - /* for ( i=0; i<MAX_NUM_COL; i++ ) { */ - for ( i=0; i<noCols; i++ ) { - scaleValues( &fixpQmfReal[i][lsb], (64)-lsb, scale ); - scaleValues( &fixpQmfImag[i][lsb], (64)-lsb, scale ); - } - } - - if ( maxScal != h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer ) - scalePsStatesBuffer(h_ps_d,(h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer-maxScal)); - - h_ps_d->specificTo.mpeg.hybrid.sf_mQmfBuffer = maxScal; - h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer = maxScal; - - *scaleFactorHighBand += maxScal - scaleFactorHighBands; - - h_ps_d->rescal = maxScal - scaleFactorLowBandSplitHigh; - h_ps_d->sf_IntBuffer = maxScal; - - *scaleFactorLowBand_lb += maxScal - scaleFactorLowBandSplitLow; - *scaleFactorLowBand_hb += maxScal - scaleFactorLowBandSplitHigh; -} - -void rescalFilterBankValues( HANDLE_PS_DEC h_ps_d, /* parametric stereo decoder handle */ - FIXP_DBL **QmfBufferReal, /* qmf filterbank values */ - FIXP_DBL **QmfBufferImag, /* qmf filterbank values */ - int lsb, /* sbr start subband */ - INT noCols) -{ - int i; - /* scale back 6 timeslots look ahead for hybrid filterbank to original value */ - for ( i=noCols; i<noCols + (6); i++ ) { - scaleValues( QmfBufferReal[i], lsb, h_ps_d->rescal ); - scaleValues( QmfBufferImag[i], lsb, h_ps_d->rescal ); - } -} - -/***************************************************************************/ -/*! - \brief Generate decorrelated side channel using allpass/delay - - \return - -****************************************************************************/ -static void -deCorrelateSlotBased( HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */ - - FIXP_DBL *mHybridRealLeft, /*!< left (mono) hybrid values real */ - FIXP_DBL *mHybridImagLeft, /*!< left (mono) hybrid values imag */ - SCHAR sf_mHybridLeft, /*!< scalefactor for left (mono) hybrid bands */ - - FIXP_DBL *rIntBufferLeft, /*!< real qmf bands left (mono) (38x64) */ - FIXP_DBL *iIntBufferLeft, /*!< real qmf bands left (mono) (38x64) */ - SCHAR sf_IntBuffer, /*!< scalefactor for all left and right qmf bands */ - - FIXP_DBL *mHybridRealRight, /*!< right (decorrelated) hybrid values real */ - FIXP_DBL *mHybridImagRight, /*!< right (decorrelated) hybrid values imag */ - - FIXP_DBL *rIntBufferRight, /*!< real qmf bands right (decorrelated) (38x64) */ - FIXP_DBL *iIntBufferRight ) /*!< real qmf bands right (decorrelated) (38x64) */ -{ - - INT i, m, sb, gr, bin; - - FIXP_DBL peakDiff, nrg, transRatio; - - FIXP_DBL *RESTRICT aaLeftReal; - FIXP_DBL *RESTRICT aaLeftImag; - - FIXP_DBL *RESTRICT aaRightReal; - FIXP_DBL *RESTRICT aaRightImag; - - FIXP_DBL *RESTRICT pRealDelayBuffer; - FIXP_DBL *RESTRICT pImagDelayBuffer; - - C_ALLOC_SCRATCH_START(aaPowerSlot, FIXP_DBL, NO_MID_RES_BINS); - C_ALLOC_SCRATCH_START(aaTransRatioSlot, FIXP_DBL, NO_MID_RES_BINS); - -/*! -<pre> - parameter index qmf bands hybrid bands - ---------------------------------------------------------------------------- - 0 0 0,7 - 1 0 1,6 - 2 0 2 - 3 0 3 HYBRID BANDS - 4 1 9 - 5 1 8 - 6 2 10 - 7 2 11 - ---------------------------------------------------------------------------- - 8 3 - 9 4 - 10 5 - 11 6 - 12 7 - 13 8 - 14 9,10 (2 ) QMF BANDS - 15 11 - 13 (3 ) - 16 14 - 17 (4 ) - 17 18 - 22 (5 ) - 18 23 - 34 (12) - 19 35 - 63 (29) - ---------------------------------------------------------------------------- -</pre> -*/ - - #define FLTR_SCALE 3 - - /* hybrid bands (parameter index 0 - 7) */ - aaLeftReal = mHybridRealLeft; - aaLeftImag = mHybridImagLeft; - - aaPowerSlot[0] = ( fMultAddDiv2( fMultDiv2(aaLeftReal[0], aaLeftReal[0]), aaLeftImag[0], aaLeftImag[0] ) >> FLTR_SCALE ) + - ( fMultAddDiv2( fMultDiv2(aaLeftReal[7], aaLeftReal[7]), aaLeftImag[7], aaLeftImag[7] ) >> FLTR_SCALE ); - - aaPowerSlot[1] = ( fMultAddDiv2( fMultDiv2(aaLeftReal[1], aaLeftReal[1]), aaLeftImag[1], aaLeftImag[1] ) >> FLTR_SCALE ) + - ( fMultAddDiv2( fMultDiv2(aaLeftReal[6], aaLeftReal[6]), aaLeftImag[6], aaLeftImag[6] ) >> FLTR_SCALE ); - - aaPowerSlot[2] = fMultAddDiv2( fMultDiv2(aaLeftReal[2], aaLeftReal[2]), aaLeftImag[2], aaLeftImag[2] ) >> FLTR_SCALE; - aaPowerSlot[3] = fMultAddDiv2( fMultDiv2(aaLeftReal[3], aaLeftReal[3]), aaLeftImag[3], aaLeftImag[3] ) >> FLTR_SCALE; - - aaPowerSlot[4] = fMultAddDiv2( fMultDiv2(aaLeftReal[9], aaLeftReal[9]), aaLeftImag[9], aaLeftImag[9] ) >> FLTR_SCALE; - aaPowerSlot[5] = fMultAddDiv2( fMultDiv2(aaLeftReal[8], aaLeftReal[8]), aaLeftImag[8], aaLeftImag[8] ) >> FLTR_SCALE; - - aaPowerSlot[6] = fMultAddDiv2( fMultDiv2(aaLeftReal[10], aaLeftReal[10]), aaLeftImag[10], aaLeftImag[10] ) >> FLTR_SCALE; - aaPowerSlot[7] = fMultAddDiv2( fMultDiv2(aaLeftReal[11], aaLeftReal[11]), aaLeftImag[11], aaLeftImag[11] ) >> FLTR_SCALE; - - /* qmf bands (parameter index 8 - 19) */ - for ( bin = 8; bin < NO_MID_RES_BINS; bin++ ) { - FIXP_DBL slotNrg = FL2FXCONST_DBL(0.f); - - for ( i = groupBorders20[bin+2]; i < groupBorders20[bin+3]; i++ ) { /* max loops: 29 */ - slotNrg += fMultAddDiv2 ( fMultDiv2(rIntBufferLeft[i], rIntBufferLeft[i]), iIntBufferLeft[i], iIntBufferLeft[i]) >> FLTR_SCALE; - } - aaPowerSlot[bin] = slotNrg; - - } - - - /* calculation of transient ratio */ - for (bin=0; bin < NO_MID_RES_BINS; bin++) { /* noBins = 20 ( BASELINE_PS ) */ - - h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin] = fMult( h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin], PEAK_DECAY_FACTOR ); - - if (h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin] < aaPowerSlot[bin]) { - h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin] = aaPowerSlot[bin]; - } - - /* calculate PSmoothPeakDecayDiffNrg */ - peakDiff = fMultAdd ( (h_ps_d->specificTo.mpeg.aPrevPeakDiffBin[bin]>>1), - INT_FILTER_COEFF, h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin] - aaPowerSlot[bin] - h_ps_d->specificTo.mpeg.aPrevPeakDiffBin[bin]); - - /* save peakDiff for the next frame */ - h_ps_d->specificTo.mpeg.aPrevPeakDiffBin[bin] = peakDiff; - - nrg = h_ps_d->specificTo.mpeg.aPrevNrgBin[bin] + fMult( INT_FILTER_COEFF, aaPowerSlot[bin] - h_ps_d->specificTo.mpeg.aPrevNrgBin[bin] ); - - /* Negative energies don't exist. But sometimes they appear due to rounding. */ - - nrg = fixMax(nrg,FL2FXCONST_DBL(0.f)); - - /* save nrg for the next frame */ - h_ps_d->specificTo.mpeg.aPrevNrgBin[bin] = nrg; - - nrg = fMult( nrg, TRANSIENT_IMPACT_FACTOR ); - - /* save transient impact factor */ - if ( peakDiff <= nrg || peakDiff == FL2FXCONST_DBL(0.0) ) { - aaTransRatioSlot[bin] = (FIXP_DBL)MAXVAL_DBL /* FL2FXCONST_DBL(1.0f)*/; - } - else if ( nrg <= FL2FXCONST_DBL(0.0f) ) { - aaTransRatioSlot[bin] = FL2FXCONST_DBL(0.f); +void PreparePsProcessing(HANDLE_PS_DEC h_ps_d, + const FIXP_DBL *const *const rIntBufferLeft, + const FIXP_DBL *const *const iIntBufferLeft, + const int scaleFactorLowBand) { + if (h_ps_d->procFrameBased == + 1) /* If we have switched from frame to slot based processing */ + { /* fill hybrid delay buffer. */ + int i, j; + + for (i = 0; i < HYBRID_FILTER_DELAY; i++) { + FIXP_DBL qmfInputData[2][NO_QMF_BANDS_HYBRID20]; + FIXP_DBL hybridOutputData[2][NO_SUB_QMF_CHANNELS]; + + for (j = 0; j < NO_QMF_BANDS_HYBRID20; j++) { + qmfInputData[0][j] = + scaleValue(rIntBufferLeft[i][j], scaleFactorLowBand); + qmfInputData[1][j] = + scaleValue(iIntBufferLeft[i][j], scaleFactorLowBand); } - else { - /* scale to denominator */ - INT scale_left = fixMax(0, CntLeadingZeros(peakDiff) - 1); - aaTransRatioSlot[bin] = schur_div( nrg<<scale_left, peakDiff<<scale_left, 16); - } - } /* bin */ - - - - - #define DELAY_GROUP_OFFSET 20 - #define NR_OF_DELAY_GROUPS 2 - - FIXP_DBL rTmp, iTmp, rTmp0, iTmp0, rR0, iR0; - - INT TempDelay = h_ps_d->specificTo.mpeg.delayBufIndex; /* set delay indices */ - - pRealDelayBuffer = h_ps_d->specificTo.mpeg.aaRealDelayBufferSubQmf[TempDelay]; - pImagDelayBuffer = h_ps_d->specificTo.mpeg.aaImagDelayBufferSubQmf[TempDelay]; - - aaLeftReal = mHybridRealLeft; - aaLeftImag = mHybridImagLeft; - aaRightReal = mHybridRealRight; - aaRightImag = mHybridImagRight; - - /************************/ - /* ICC groups : 0 - 9 */ - /************************/ - - /* gr = ICC groups */ - for (gr=0; gr < SUBQMF_GROUPS; gr++) { - - transRatio = aaTransRatioSlot[bins2groupMap20[gr]]; - - /* sb = subQMF/QMF subband */ - sb = groupBorders20[gr]; - - /* Update delay buffers, sample delay allpass = 2 */ - rTmp0 = pRealDelayBuffer[sb]; - iTmp0 = pImagDelayBuffer[sb]; - - pRealDelayBuffer[sb] = aaLeftReal[sb]; - pImagDelayBuffer[sb] = aaLeftImag[sb]; - - /* delay by fraction */ - cplxMultDiv2(&rR0, &iR0, rTmp0, iTmp0, aaFractDelayPhaseFactorReSubQmf20[sb], aaFractDelayPhaseFactorImSubQmf20[sb]); - rR0<<=1; - iR0<<=1; - - FIXP_DBL *pAaaRealDelayRBufferSerSubQmf = h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerSubQmf[sb]; - FIXP_DBL *pAaaImagDelayRBufferSerSubQmf = h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerSubQmf[sb]; - - for (m=0; m<NO_SERIAL_ALLPASS_LINKS ; m++) { - - INT tmpDelayRSer = h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[m]; - - /* get delayed values from according buffer : m(0)=3; m(1)=4; m(2)=5; */ - rTmp0 = pAaaRealDelayRBufferSerSubQmf[tmpDelayRSer]; - iTmp0 = pAaaImagDelayRBufferSerSubQmf[tmpDelayRSer]; - - /* delay by fraction */ - cplxMultDiv2(&rTmp, &iTmp, rTmp0, iTmp0, aaFractDelayPhaseFactorSerReSubQmf20[sb][m], aaFractDelayPhaseFactorSerImSubQmf20[sb][m]); - - rTmp = (rTmp - fMultDiv2(aAllpassLinkDecaySer[m], rR0)) << 1; - iTmp = (iTmp - fMultDiv2(aAllpassLinkDecaySer[m], iR0)) << 1; - - pAaaRealDelayRBufferSerSubQmf[tmpDelayRSer] = rR0 + fMult(aAllpassLinkDecaySer[m], rTmp); - pAaaImagDelayRBufferSerSubQmf[tmpDelayRSer] = iR0 + fMult(aAllpassLinkDecaySer[m], iTmp); - - rR0 = rTmp; - iR0 = iTmp; - - pAaaRealDelayRBufferSerSubQmf += aAllpassLinkDelaySer[m]; - pAaaImagDelayRBufferSerSubQmf += aAllpassLinkDelaySer[m]; - - } /* m */ - - /* duck if a past transient is found */ - aaRightReal[sb] = fMult(transRatio, rR0); - aaRightImag[sb] = fMult(transRatio, iR0); - - } /* gr */ - - - scaleValues( mHybridRealLeft, NO_SUB_QMF_CHANNELS, -SCAL_HEADROOM ); - scaleValues( mHybridImagLeft, NO_SUB_QMF_CHANNELS, -SCAL_HEADROOM ); - scaleValues( mHybridRealRight, NO_SUB_QMF_CHANNELS, -SCAL_HEADROOM ); - scaleValues( mHybridImagRight, NO_SUB_QMF_CHANNELS, -SCAL_HEADROOM ); - - - /************************/ - - aaLeftReal = rIntBufferLeft; - aaLeftImag = iIntBufferLeft; - aaRightReal = rIntBufferRight; - aaRightImag = iIntBufferRight; - pRealDelayBuffer = h_ps_d->specificTo.mpeg.aaRealDelayBufferQmf[TempDelay]; - pImagDelayBuffer = h_ps_d->specificTo.mpeg.aaImagDelayBufferQmf[TempDelay]; - - /************************/ - /* ICC groups : 10 - 19 */ - /************************/ - - - /* gr = ICC groups */ - for (gr=SUBQMF_GROUPS; gr < NO_IID_GROUPS - NR_OF_DELAY_GROUPS; gr++) { - - transRatio = aaTransRatioSlot[bins2groupMap20[gr]]; - - /* sb = subQMF/QMF subband */ - for (sb = groupBorders20[gr]; sb < groupBorders20[gr+1]; sb++) { - FIXP_DBL resR, resI; - - /* decayScaleFactor = 1.0f + decay_cutoff * DECAY_SLOPE - DECAY_SLOPE * sb; DECAY_SLOPE = 0.05 */ - FIXP_DBL decayScaleFactor = decayScaleFactTable[sb]; - - /* Update delay buffers, sample delay allpass = 2 */ - rTmp0 = pRealDelayBuffer[sb]; - iTmp0 = pImagDelayBuffer[sb]; - - pRealDelayBuffer[sb] = aaLeftReal[sb]; - pImagDelayBuffer[sb] = aaLeftImag[sb]; - - /* delay by fraction */ - cplxMultDiv2(&rR0, &iR0, rTmp0, iTmp0, aaFractDelayPhaseFactorReQmf[sb], aaFractDelayPhaseFactorImQmf[sb]); - rR0<<=1; - iR0<<=1; - - resR = fMult(decayScaleFactor, rR0); - resI = fMult(decayScaleFactor, iR0); - - FIXP_DBL *pAaaRealDelayRBufferSerQmf = h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[sb]; - FIXP_DBL *pAaaImagDelayRBufferSerQmf = h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[sb]; - - for (m=0; m<NO_SERIAL_ALLPASS_LINKS ; m++) { - - INT tmpDelayRSer = h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[m]; - - /* get delayed values from according buffer : m(0)=3; m(1)=4; m(2)=5; */ - rTmp0 = pAaaRealDelayRBufferSerQmf[tmpDelayRSer]; - iTmp0 = pAaaImagDelayRBufferSerQmf[tmpDelayRSer]; - - /* delay by fraction */ - cplxMultDiv2(&rTmp, &iTmp, rTmp0, iTmp0, aaFractDelayPhaseFactorSerReQmf[sb][m], aaFractDelayPhaseFactorSerImQmf[sb][m]); - - rTmp = (rTmp - fMultDiv2(aAllpassLinkDecaySer[m], resR))<<1; - iTmp = (iTmp - fMultDiv2(aAllpassLinkDecaySer[m], resI))<<1; - - resR = fMult(decayScaleFactor, rTmp); - resI = fMult(decayScaleFactor, iTmp); - - pAaaRealDelayRBufferSerQmf[tmpDelayRSer] = rR0 + fMult(aAllpassLinkDecaySer[m], resR); - pAaaImagDelayRBufferSerQmf[tmpDelayRSer] = iR0 + fMult(aAllpassLinkDecaySer[m], resI); - - rR0 = rTmp; - iR0 = iTmp; - - pAaaRealDelayRBufferSerQmf += aAllpassLinkDelaySer[m]; - pAaaImagDelayRBufferSerQmf += aAllpassLinkDelaySer[m]; - - } /* m */ - - /* duck if a past transient is found */ - aaRightReal[sb] = fMult(transRatio, rR0); - aaRightImag[sb] = fMult(transRatio, iR0); - - } /* sb */ - } /* gr */ - - /************************/ - /* ICC groups : 20, 21 */ - /************************/ - - - /* gr = ICC groups */ - for (gr=DELAY_GROUP_OFFSET; gr < NO_IID_GROUPS; gr++) { - - INT sbStart = groupBorders20[gr]; - INT sbStop = groupBorders20[gr+1]; - - UCHAR *pDelayBufIdx = &h_ps_d->specificTo.mpeg.aDelayBufIndexDelayQmf[sbStart-FIRST_DELAY_SB]; - - transRatio = aaTransRatioSlot[bins2groupMap20[gr]]; - - /* sb = subQMF/QMF subband */ - for (sb = sbStart; sb < sbStop; sb++) { - - /* Update delay buffers */ - rR0 = h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[*pDelayBufIdx][sb-FIRST_DELAY_SB]; - iR0 = h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[*pDelayBufIdx][sb-FIRST_DELAY_SB]; - - h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[*pDelayBufIdx][sb-FIRST_DELAY_SB] = aaLeftReal[sb]; - h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[*pDelayBufIdx][sb-FIRST_DELAY_SB] = aaLeftImag[sb]; - - /* duck if a past transient is found */ - aaRightReal[sb] = fMult(transRatio, rR0); - aaRightImag[sb] = fMult(transRatio, iR0); - - if (++(*pDelayBufIdx) >= delayIndexQmf[sb]) { - *pDelayBufIdx = 0; - } - pDelayBufIdx++; - - } /* sb */ - } /* gr */ - - - /* Update delay buffer index */ - if (++h_ps_d->specificTo.mpeg.delayBufIndex >= NO_SAMPLE_DELAY_ALLPASS) - h_ps_d->specificTo.mpeg.delayBufIndex = 0; - - for (m=0; m<NO_SERIAL_ALLPASS_LINKS ; m++) { - if (++h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[m] >= aAllpassLinkDelaySer[m]) - h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[m] = 0; - } - - - scaleValues( &rIntBufferLeft[NO_QMF_BANDS_HYBRID20], NO_QMF_CHANNELS-NO_QMF_BANDS_HYBRID20, -SCAL_HEADROOM ); - scaleValues( &iIntBufferLeft[NO_QMF_BANDS_HYBRID20], NO_QMF_CHANNELS-NO_QMF_BANDS_HYBRID20, -SCAL_HEADROOM ); - scaleValues( &rIntBufferRight[NO_QMF_BANDS_HYBRID20], NO_QMF_CHANNELS-NO_QMF_BANDS_HYBRID20, -SCAL_HEADROOM ); - scaleValues( &iIntBufferRight[NO_QMF_BANDS_HYBRID20], NO_QMF_CHANNELS-NO_QMF_BANDS_HYBRID20, -SCAL_HEADROOM ); + FDKhybridAnalysisApply(&h_ps_d->specificTo.mpeg.hybridAnalysis, + qmfInputData[0], qmfInputData[1], + hybridOutputData[0], hybridOutputData[1]); + } + h_ps_d->procFrameBased = 0; /* switch to slot based processing. */ - /* free memory on scratch */ - C_ALLOC_SCRATCH_END(aaTransRatioSlot, FIXP_DBL, NO_MID_RES_BINS); - C_ALLOC_SCRATCH_END(aaPowerSlot, FIXP_DBL, NO_MID_RES_BINS); + } /* procFrameBased==1 */ } +void initSlotBasedRotation( + HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */ + int env, int usb) { + INT group = 0; + INT bin = 0; + INT noIidSteps; -void initSlotBasedRotation( HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */ - int env, - int usb - ) { - - INT group = 0; - INT bin = 0; - INT noIidSteps; - -/* const UCHAR *pQuantizedIIDs;*/ - - FIXP_SGL invL; - FIXP_DBL ScaleL, ScaleR; - FIXP_DBL Alpha, Beta; - FIXP_DBL h11r, h12r, h21r, h22r; + FIXP_SGL invL; + FIXP_DBL ScaleL, ScaleR; + FIXP_DBL Alpha, Beta; + FIXP_DBL h11r, h12r, h21r, h22r; - const FIXP_DBL *PScaleFactors; + const FIXP_DBL *PScaleFactors; - /* Overwrite old values in delay buffers when upper subband is higher than in last frame */ - if (env == 0) { - - if ((usb > h_ps_d->specificTo.mpeg.lastUsb) && h_ps_d->specificTo.mpeg.lastUsb) { - - INT i,k,length; - - for (i=h_ps_d->specificTo.mpeg.lastUsb ; i < FIRST_DELAY_SB; i++) { - FDKmemclear(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL)); - FDKmemclear(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL)); - } - - for (k=0 ; k<NO_SAMPLE_DELAY_ALLPASS; k++) { - FDKmemclear(h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[k], FIRST_DELAY_SB*sizeof(FIXP_DBL)); - } - length = (usb-FIRST_DELAY_SB)*sizeof(FIXP_DBL); - if(length>0) { - FDKmemclear(h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[0], length); - FDKmemclear(h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[0], length); - } - length = (fixMin(NO_DELAY_BUFFER_BANDS,(INT)usb)-FIRST_DELAY_SB)*sizeof(FIXP_DBL); - if(length>0) { - for (k=1 ; k < h_ps_d->specificTo.mpeg.noSampleDelay; k++) { - FDKmemclear(h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[k], length); - FDKmemclear(h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[k], length); - } - } - } - h_ps_d->specificTo.mpeg.lastUsb = usb; - } /* env == 0 */ - - if (h_ps_d->bsData[h_ps_d->processSlot].mpeg.bFineIidQ) - { + if (h_ps_d->bsData[h_ps_d->processSlot].mpeg.bFineIidQ) { PScaleFactors = ScaleFactorsFine; /* values are shiftet right by one */ noIidSteps = NO_IID_STEPS_FINE; - /*pQuantizedIIDs = quantizedIIDsFine;*/ - } - - else - { + } else { PScaleFactors = ScaleFactors; /* values are shiftet right by one */ noIidSteps = NO_IID_STEPS; - /*pQuantizedIIDs = quantizedIIDs;*/ } - /* dequantize and decode */ - for ( group = 0; group < NO_IID_GROUPS; group++ ) { - + for (group = 0; group < NO_IID_GROUPS; group++) { bin = bins2groupMap20[group]; /*! <h3> type 'A' rotation </h3> mixing procedure R_a, used in baseline version<br> - Scale-factor vectors c1 and c2 are precalculated in initPsTables () and stored in - scaleFactors[] and scaleFactorsFine[] = pScaleFactors []. - From the linearized IID parameters (intensity differences), two scale factors are + Scale-factor vectors c1 and c2 are precalculated in initPsTables () and + stored in scaleFactors[] and scaleFactorsFine[] = pScaleFactors []. From the + linearized IID parameters (intensity differences), two scale factors are calculated. They are used to obtain the coefficients h11... h22. */ /* ScaleR and ScaleL are scaled by 1 shift right */ - ScaleR = PScaleFactors[noIidSteps + h_ps_d->specificTo.mpeg.coef.aaIidIndexMapped[env][bin]]; - ScaleL = PScaleFactors[noIidSteps - h_ps_d->specificTo.mpeg.coef.aaIidIndexMapped[env][bin]]; + ScaleR = PScaleFactors[noIidSteps + h_ps_d->specificTo.mpeg.pCoef + ->aaIidIndexMapped[env][bin]]; + ScaleL = PScaleFactors[noIidSteps - h_ps_d->specificTo.mpeg.pCoef + ->aaIidIndexMapped[env][bin]]; - Beta = fMult (fMult( Alphas[h_ps_d->specificTo.mpeg.coef.aaIccIndexMapped[env][bin]], ( ScaleR - ScaleL )), FIXP_SQRT05); - Alpha = Alphas[h_ps_d->specificTo.mpeg.coef.aaIccIndexMapped[env][bin]]>>1; + Beta = fMult( + fMult(Alphas[h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env][bin]], + (ScaleR - ScaleL)), + FIXP_SQRT05); + Alpha = + Alphas[h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env][bin]] >> 1; /* Alpha and Beta are now both scaled by 2 shifts right */ - /* calculate the coefficients h11... h22 from scale-factors and ICC parameters */ + /* calculate the coefficients h11... h22 from scale-factors and ICC + * parameters */ /* h values are scaled by 1 shift right */ { FIXP_DBL trigData[4]; inline_fixp_cos_sin(Beta + Alpha, Beta - Alpha, 2, trigData); - h11r = fMult( ScaleL, trigData[0]); - h12r = fMult( ScaleR, trigData[2]); - h21r = fMult( ScaleL, trigData[1]); - h22r = fMult( ScaleR, trigData[3]); + h11r = fMult(ScaleL, trigData[0]); + h12r = fMult(ScaleR, trigData[2]); + h21r = fMult(ScaleL, trigData[1]); + h22r = fMult(ScaleR, trigData[3]); } /*****************************************************************************************/ - /* Interpolation of the matrices H11... H22: */ + /* Interpolation of the matrices H11... H22: */ /* */ - /* H11(k,n) = H11(k,n[e]) + (n-n[e]) * (H11(k,n[e+1] - H11(k,n[e])) / (n[e+1] - n[e]) */ - /* ... */ + /* H11(k,n) = H11(k,n[e]) + (n-n[e]) * (H11(k,n[e+1] - H11(k,n[e])) / + * (n[e+1] - n[e]) */ + /* ... */ /*****************************************************************************************/ /* invL = 1/(length of envelope) */ - invL = FX_DBL2FX_SGL(GetInvInt(h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env + 1] - h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env])); - - h_ps_d->specificTo.mpeg.coef.H11r[group] = h_ps_d->specificTo.mpeg.h11rPrev[group]; - h_ps_d->specificTo.mpeg.coef.H12r[group] = h_ps_d->specificTo.mpeg.h12rPrev[group]; - h_ps_d->specificTo.mpeg.coef.H21r[group] = h_ps_d->specificTo.mpeg.h21rPrev[group]; - h_ps_d->specificTo.mpeg.coef.H22r[group] = h_ps_d->specificTo.mpeg.h22rPrev[group]; - - h_ps_d->specificTo.mpeg.coef.DeltaH11r[group] = fMult ( h11r - h_ps_d->specificTo.mpeg.coef.H11r[group], invL ); - h_ps_d->specificTo.mpeg.coef.DeltaH12r[group] = fMult ( h12r - h_ps_d->specificTo.mpeg.coef.H12r[group], invL ); - h_ps_d->specificTo.mpeg.coef.DeltaH21r[group] = fMult ( h21r - h_ps_d->specificTo.mpeg.coef.H21r[group], invL ); - h_ps_d->specificTo.mpeg.coef.DeltaH22r[group] = fMult ( h22r - h_ps_d->specificTo.mpeg.coef.H22r[group], invL ); + invL = FX_DBL2FX_SGL(GetInvInt( + h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env + 1] - + h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env])); + + h_ps_d->specificTo.mpeg.pCoef->H11r[group] = + h_ps_d->specificTo.mpeg.h11rPrev[group]; + h_ps_d->specificTo.mpeg.pCoef->H12r[group] = + h_ps_d->specificTo.mpeg.h12rPrev[group]; + h_ps_d->specificTo.mpeg.pCoef->H21r[group] = + h_ps_d->specificTo.mpeg.h21rPrev[group]; + h_ps_d->specificTo.mpeg.pCoef->H22r[group] = + h_ps_d->specificTo.mpeg.h22rPrev[group]; + + h_ps_d->specificTo.mpeg.pCoef->DeltaH11r[group] = + fMult(h11r - h_ps_d->specificTo.mpeg.pCoef->H11r[group], invL); + h_ps_d->specificTo.mpeg.pCoef->DeltaH12r[group] = + fMult(h12r - h_ps_d->specificTo.mpeg.pCoef->H12r[group], invL); + h_ps_d->specificTo.mpeg.pCoef->DeltaH21r[group] = + fMult(h21r - h_ps_d->specificTo.mpeg.pCoef->H21r[group], invL); + h_ps_d->specificTo.mpeg.pCoef->DeltaH22r[group] = + fMult(h22r - h_ps_d->specificTo.mpeg.pCoef->H22r[group], invL); /* update prev coefficients for interpolation in next envelope */ @@ -1062,79 +426,67 @@ void initSlotBasedRotation( HANDLE_PS_DEC h_ps_d, /*!< pointer to the module sta } /* group loop */ } +static const UCHAR groupTable[NO_IID_GROUPS + 1] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 18, 21, 25, 30, 42, 71}; -static void applySlotBasedRotation( HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */ - - FIXP_DBL *mHybridRealLeft, /*!< hybrid values real left */ - FIXP_DBL *mHybridImagLeft, /*!< hybrid values imag left */ - - FIXP_DBL *QmfLeftReal, /*!< real bands left qmf channel */ - FIXP_DBL *QmfLeftImag, /*!< imag bands left qmf channel */ - - FIXP_DBL *mHybridRealRight, /*!< hybrid values real right */ - FIXP_DBL *mHybridImagRight, /*!< hybrid values imag right */ - - FIXP_DBL *QmfRightReal, /*!< real bands right qmf channel */ - FIXP_DBL *QmfRightImag /*!< imag bands right qmf channel */ - ) -{ - INT group; - INT subband; - - FIXP_DBL *RESTRICT HybrLeftReal; - FIXP_DBL *RESTRICT HybrLeftImag; - FIXP_DBL *RESTRICT HybrRightReal; - FIXP_DBL *RESTRICT HybrRightImag; +static void applySlotBasedRotation( + HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */ - FIXP_DBL tmpLeft, tmpRight; + FIXP_DBL *mHybridRealLeft, /*!< hybrid values real left */ + FIXP_DBL *mHybridImagLeft, /*!< hybrid values imag left */ + FIXP_DBL *mHybridRealRight, /*!< hybrid values real right */ + FIXP_DBL *mHybridImagRight /*!< hybrid values imag right */ +) { + INT group; + INT subband; /**********************************************************************************************/ /*! <h2> Mapping </h2> - The number of stereo bands that is actually used depends on the number of availble - parameters for IID and ICC: - <pre> - nr. of IID para.| nr. of ICC para. | nr. of Stereo bands + The number of stereo bands that is actually used depends on the number of + availble parameters for IID and ICC: <pre> nr. of IID para.| nr. of ICC para. + | nr. of Stereo bands ----------------|------------------|------------------- 10,20 | 10,20 | 20 10,20 | 34 | 34 34 | 10,20 | 34 34 | 34 | 34 </pre> - In the case the number of parameters for IIS and ICC differs from the number of stereo - bands, a mapping from the lower number to the higher number of parameters is applied. - Index mapping of IID and ICC parameters is already done in psbitdec.cpp. Further mapping is - not needed here in baseline version. + In the case the number of parameters for IIS and ICC differs from the number + of stereo bands, a mapping from the lower number to the higher number of + parameters is applied. Index mapping of IID and ICC parameters is already done + in psbitdec.cpp. Further mapping is not needed here in baseline version. **********************************************************************************************/ /************************************************************************************************/ /*! <h2> Mixing </h2> - To generate the QMF subband signals for the subband samples n = n[e]+1 ,,, n_[e+1] the - parameters at position n[e] and n[e+1] are required as well as the subband domain signals - s_k(n) and d_k(n) for n = n[e]+1... n_[e+1]. n[e] represents the start position for - envelope e. The border positions n[e] are handled in DecodePS(). + To generate the QMF subband signals for the subband samples n = n[e]+1 ,,, + n_[e+1] the parameters at position n[e] and n[e+1] are required as well as the + subband domain signals s_k(n) and d_k(n) for n = n[e]+1... n_[e+1]. n[e] + represents the start position for envelope e. The border positions n[e] are + handled in DecodePS(). The stereo sub subband signals are constructed as: <pre> l_k(n) = H11(k,n) s_k(n) + H21(k,n) d_k(n) r_k(n) = H21(k,n) s_k(n) + H22(k,n) d_k(n) </pre> - In order to obtain the matrices H11(k,n)... H22 (k,n), the vectors h11(b)... h22(b) need to - be calculated first (b: parameter index). Depending on ICC mode either mixing procedure R_a - or R_b is used for that. For both procedures, the parameters for parameter position n[e+1] - is used. + In order to obtain the matrices H11(k,n)... H22 (k,n), the vectors h11(b)... + h22(b) need to be calculated first (b: parameter index). Depending on ICC mode + either mixing procedure R_a or R_b is used for that. For both procedures, the + parameters for parameter position n[e+1] is used. ************************************************************************************************/ - /************************************************************************************************/ /*! <h2>Phase parameters </h2> - With disabled phase parameters (which is the case in baseline version), the H-matrices are - just calculated by: + With disabled phase parameters (which is the case in baseline version), the + H-matrices are just calculated by: <pre> H11(k,n[e+1] = h11(b(k)) @@ -1146,69 +498,44 @@ static void applySlotBasedRotation( HANDLE_PS_DEC h_ps_d, /*!< pointer to this loop includes the interpolation of the coefficients Hxx ************************************************************************************************/ - - /* loop thru all groups ... */ - HybrLeftReal = mHybridRealLeft; - HybrLeftImag = mHybridImagLeft; - HybrRightReal = mHybridRealRight; - HybrRightImag = mHybridImagRight; - /******************************************************/ /* construct stereo sub subband signals according to: */ /* */ /* l_k(n) = H11(k,n) s_k(n) + H21(k,n) d_k(n) */ /* r_k(n) = H12(k,n) s_k(n) + H22(k,n) d_k(n) */ /******************************************************/ - for ( group = 0; group < SUBQMF_GROUPS; group++ ) { - - h_ps_d->specificTo.mpeg.coef.H11r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH11r[group]; - h_ps_d->specificTo.mpeg.coef.H12r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH12r[group]; - h_ps_d->specificTo.mpeg.coef.H21r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH21r[group]; - h_ps_d->specificTo.mpeg.coef.H22r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH22r[group]; - - subband = groupBorders20[group]; - - tmpLeft = fMultAddDiv2( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H11r[group], HybrLeftReal[subband]), h_ps_d->specificTo.mpeg.coef.H21r[group], HybrRightReal[subband]); - tmpRight = fMultAddDiv2( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H12r[group], HybrLeftReal[subband]), h_ps_d->specificTo.mpeg.coef.H22r[group], HybrRightReal[subband]); - HybrLeftReal [subband] = tmpLeft<<1; - HybrRightReal[subband] = tmpRight<<1; - - tmpLeft = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H11r[group], HybrLeftImag[subband]), h_ps_d->specificTo.mpeg.coef.H21r[group], HybrRightImag[subband]); - tmpRight = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H12r[group], HybrLeftImag[subband]), h_ps_d->specificTo.mpeg.coef.H22r[group], HybrRightImag[subband]); - HybrLeftImag [subband] = tmpLeft; - HybrRightImag[subband] = tmpRight; - } - - /* continue in the qmf buffers */ - HybrLeftReal = QmfLeftReal; - HybrLeftImag = QmfLeftImag; - HybrRightReal = QmfRightReal; - HybrRightImag = QmfRightImag; - - for (; group < NO_IID_GROUPS; group++ ) { - - h_ps_d->specificTo.mpeg.coef.H11r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH11r[group]; - h_ps_d->specificTo.mpeg.coef.H12r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH12r[group]; - h_ps_d->specificTo.mpeg.coef.H21r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH21r[group]; - h_ps_d->specificTo.mpeg.coef.H22r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH22r[group]; - - for ( subband = groupBorders20[group]; subband < groupBorders20[group + 1]; subband++ ) - { - tmpLeft = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H11r[group], HybrLeftReal[subband]), h_ps_d->specificTo.mpeg.coef.H21r[group], HybrRightReal[subband]); - tmpRight = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H12r[group], HybrLeftReal[subband]), h_ps_d->specificTo.mpeg.coef.H22r[group], HybrRightReal[subband]); - HybrLeftReal [subband] = tmpLeft; - HybrRightReal[subband] = tmpRight; - - tmpLeft = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H11r[group], HybrLeftImag[subband]), h_ps_d->specificTo.mpeg.coef.H21r[group], HybrRightImag[subband]); - tmpRight = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H12r[group], HybrLeftImag[subband]), h_ps_d->specificTo.mpeg.coef.H22r[group], HybrRightImag[subband]); - HybrLeftImag [subband] = tmpLeft; - HybrRightImag[subband] = tmpRight; - + PS_DEC_COEFFICIENTS *pCoef = h_ps_d->specificTo.mpeg.pCoef; + + for (group = 0; group < NO_IID_GROUPS; group++) { + pCoef->H11r[group] += pCoef->DeltaH11r[group]; + pCoef->H12r[group] += pCoef->DeltaH12r[group]; + pCoef->H21r[group] += pCoef->DeltaH21r[group]; + pCoef->H22r[group] += pCoef->DeltaH22r[group]; + + const int start = groupTable[group]; + const int stop = groupTable[group + 1]; + for (subband = start; subband < stop; subband++) { + FIXP_DBL tmpLeft = + fMultAdd(fMultDiv2(pCoef->H11r[group], mHybridRealLeft[subband]), + pCoef->H21r[group], mHybridRealRight[subband]); + FIXP_DBL tmpRight = + fMultAdd(fMultDiv2(pCoef->H12r[group], mHybridRealLeft[subband]), + pCoef->H22r[group], mHybridRealRight[subband]); + mHybridRealLeft[subband] = tmpLeft; + mHybridRealRight[subband] = tmpRight; + + tmpLeft = + fMultAdd(fMultDiv2(pCoef->H11r[group], mHybridImagLeft[subband]), + pCoef->H21r[group], mHybridImagRight[subband]); + tmpRight = + fMultAdd(fMultDiv2(pCoef->H12r[group], mHybridImagLeft[subband]), + pCoef->H22r[group], mHybridImagRight[subband]); + mHybridImagLeft[subband] = tmpLeft; + mHybridImagRight[subband] = tmpRight; } /* subband */ } } - /***************************************************************************/ /*! \brief Applies IID, ICC, IPD and OPD parameters to the current frame. @@ -1216,199 +543,172 @@ static void applySlotBasedRotation( HANDLE_PS_DEC h_ps_d, /*!< pointer to \return none ****************************************************************************/ -void -ApplyPsSlot( HANDLE_PS_DEC h_ps_d, /*!< handle PS_DEC*/ - FIXP_DBL **rIntBufferLeft, /*!< real bands left qmf channel (38x64) */ - FIXP_DBL **iIntBufferLeft, /*!< imag bands left qmf channel (38x64) */ - FIXP_DBL *rIntBufferRight, /*!< real bands right qmf channel (38x64) */ - FIXP_DBL *iIntBufferRight /*!< imag bands right qmf channel (38x64) */ - ) -{ - - /*! - The 64-band QMF representation of the monaural signal generated by the SBR tool - is used as input of the PS tool. After the PS processing, the outputs of the left - and right hybrid synthesis filterbanks are used to generate the stereo output - signal. - - <pre> - - ------------- ---------- ------------- - | Hybrid | M_n[k,m] | | L_n[k,m] | Hybrid | l[n] - m[n] --->| analysis |--------->| |--------->| synthesis |-----> - | filter bank | | | | filter bank | - ------------- | Stereo | ------------- - | | recon- | - | | stuction | - \|/ | | - ------------- | | - | De- | D_n[k,m] | | - | correlation |--------->| | - ------------- | | ------------- - | | R_n[k,m] | Hybrid | r[n] - | |--------->| synthesis |-----> - IID, ICC ------------------------>| | | filter bank | - (IPD, OPD) ---------- ------------- - - m[n]: QMF represantation of the mono input - M_n[k,m]: (sub-)sub-band domain signals of the mono input - D_n[k,m]: decorrelated (sub-)sub-band domain signals - L_n[k,m]: (sub-)sub-band domain signals of the left output - R_n[k,m]: (sub-)sub-band domain signals of the right output - l[n],r[n]: left/right output signals - - </pre> - */ +void ApplyPsSlot( + HANDLE_PS_DEC h_ps_d, /*!< handle PS_DEC*/ + FIXP_DBL **rIntBufferLeft, /*!< real bands left qmf channel (38x64) */ + FIXP_DBL **iIntBufferLeft, /*!< imag bands left qmf channel (38x64) */ + FIXP_DBL *rIntBufferRight, /*!< real bands right qmf channel (38x64) */ + FIXP_DBL *iIntBufferRight, /*!< imag bands right qmf channel (38x64) */ + const int scaleFactorLowBand_no_ov, const int scaleFactorLowBand, + const int scaleFactorHighBand, const int lsb, const int usb) { +/*! +The 64-band QMF representation of the monaural signal generated by the SBR tool +is used as input of the PS tool. After the PS processing, the outputs of the +left and right hybrid synthesis filterbanks are used to generate the stereo +output signal. - /* get temporary hybrid qmf values of one timeslot */ - C_ALLOC_SCRATCH_START(hybridRealLeft, FIXP_DBL, NO_SUB_QMF_CHANNELS); - C_ALLOC_SCRATCH_START(hybridImagLeft, FIXP_DBL, NO_SUB_QMF_CHANNELS); - C_ALLOC_SCRATCH_START(hybridRealRight, FIXP_DBL, NO_SUB_QMF_CHANNELS); - C_ALLOC_SCRATCH_START(hybridImagRight, FIXP_DBL, NO_SUB_QMF_CHANNELS); +<pre> - SCHAR sf_IntBuffer = h_ps_d->sf_IntBuffer; + ------------- ---------- ------------- + | Hybrid | M_n[k,m] | | L_n[k,m] | Hybrid | l[n] + m[n] --->| analysis |--------->| |--------->| synthesis |-----> + ------------- | Stereo | ------------- + | | recon- | + | | stuction | + \|/ | | + ------------- | | + | De- | D_n[k,m] | | + | correlation |--------->| | + ------------- | | ------------- + | | R_n[k,m] | Hybrid | r[n] + | |--------->| synthesis |-----> + IID, ICC ------------------------>| | | filter bank | +(IPD, OPD) ---------- ------------- + +m[n]: QMF represantation of the mono input +M_n[k,m]: (sub-)sub-band domain signals of the mono input +D_n[k,m]: decorrelated (sub-)sub-band domain signals +L_n[k,m]: (sub-)sub-band domain signals of the left output +R_n[k,m]: (sub-)sub-band domain signals of the right output +l[n],r[n]: left/right output signals - /* clear workbuffer */ - FDKmemclear(hybridRealLeft, NO_SUB_QMF_CHANNELS*sizeof(FIXP_DBL)); - FDKmemclear(hybridImagLeft, NO_SUB_QMF_CHANNELS*sizeof(FIXP_DBL)); - FDKmemclear(hybridRealRight, NO_SUB_QMF_CHANNELS*sizeof(FIXP_DBL)); - FDKmemclear(hybridImagRight, NO_SUB_QMF_CHANNELS*sizeof(FIXP_DBL)); +</pre> +*/ +#define NO_HYBRID_DATA_BANDS (71) + int i; + FIXP_DBL qmfInputData[2][NO_QMF_BANDS_HYBRID20]; + FIXP_DBL *hybridData[2][2]; + C_ALLOC_SCRATCH_START(pHybridData, FIXP_DBL, 4 * NO_HYBRID_DATA_BANDS); + + hybridData[0][0] = + pHybridData + 0 * NO_HYBRID_DATA_BANDS; /* left real hybrid data */ + hybridData[0][1] = + pHybridData + 1 * NO_HYBRID_DATA_BANDS; /* left imag hybrid data */ + hybridData[1][0] = + pHybridData + 2 * NO_HYBRID_DATA_BANDS; /* right real hybrid data */ + hybridData[1][1] = + pHybridData + 3 * NO_HYBRID_DATA_BANDS; /* right imag hybrid data */ /*! Hybrid analysis filterbank: - The lower 3 (5) of the 64 QMF subbands are further split to provide better frequency resolution. - for PS processing. - For the 10 and 20 stereo bands configuration, the QMF band H_0(w) is split - up into 8 (sub-) sub-bands and the QMF bands H_1(w) and H_2(w) are spit into 2 (sub-) - 4th. (See figures 8.20 and 8.22 of ISO/IEC 14496-3:2001/FDAM 2:2004(E) ) + The lower 3 (5) of the 64 QMF subbands are further split to provide better + frequency resolution. for PS processing. For the 10 and 20 stereo bands + configuration, the QMF band H_0(w) is split up into 8 (sub-) sub-bands and the + QMF bands H_1(w) and H_2(w) are spit into 2 (sub-) 4th. (See figures 8.20 + and 8.22 of ISO/IEC 14496-3:2001/FDAM 2:2004(E) ) */ - - if (h_ps_d->procFrameBased == 1) /* If we have switched from frame to slot based processing */ - { /* fill hybrid delay buffer. */ - h_ps_d->procFrameBased = 0; - - fillHybridDelayLine( rIntBufferLeft, - iIntBufferLeft, - hybridRealLeft, - hybridImagLeft, - hybridRealRight, - hybridImagRight, - &h_ps_d->specificTo.mpeg.hybrid ); - } - - slotBasedHybridAnalysis ( rIntBufferLeft[HYBRID_FILTER_DELAY], /* qmf filterbank values */ - iIntBufferLeft[HYBRID_FILTER_DELAY], /* qmf filterbank values */ - hybridRealLeft, /* hybrid filterbank values */ - hybridImagLeft, /* hybrid filterbank values */ - &h_ps_d->specificTo.mpeg.hybrid); /* hybrid filterbank handle */ - - - SCHAR hybridScal = h_ps_d->specificTo.mpeg.hybrid.sf_mQmfBuffer; - + /* + * Hybrid analysis. + */ + + /* Get qmf input data and apply descaling */ + for (i = 0; i < NO_QMF_BANDS_HYBRID20; i++) { + qmfInputData[0][i] = scaleValue(rIntBufferLeft[HYBRID_FILTER_DELAY][i], + scaleFactorLowBand_no_ov); + qmfInputData[1][i] = scaleValue(iIntBufferLeft[HYBRID_FILTER_DELAY][i], + scaleFactorLowBand_no_ov); + } + + /* LF - part */ + FDKhybridAnalysisApply(&h_ps_d->specificTo.mpeg.hybridAnalysis, + qmfInputData[0], qmfInputData[1], hybridData[0][0], + hybridData[0][1]); + + /* HF - part */ + /* bands up to lsb */ + scaleValues(&hybridData[0][0][NO_SUB_QMF_CHANNELS - 2], + &rIntBufferLeft[0][NO_QMF_BANDS_HYBRID20], + lsb - NO_QMF_BANDS_HYBRID20, scaleFactorLowBand); + scaleValues(&hybridData[0][1][NO_SUB_QMF_CHANNELS - 2], + &iIntBufferLeft[0][NO_QMF_BANDS_HYBRID20], + lsb - NO_QMF_BANDS_HYBRID20, scaleFactorLowBand); + + /* bands from lsb to usb */ + scaleValues(&hybridData[0][0][lsb + (NO_SUB_QMF_CHANNELS - 2 - + NO_QMF_BANDS_HYBRID20)], + &rIntBufferLeft[0][lsb], usb - lsb, scaleFactorHighBand); + scaleValues(&hybridData[0][1][lsb + (NO_SUB_QMF_CHANNELS - 2 - + NO_QMF_BANDS_HYBRID20)], + &iIntBufferLeft[0][lsb], usb - lsb, scaleFactorHighBand); + + /* bands from usb to NO_SUB_QMF_CHANNELS which should be zero for non-overlap + slots but can be non-zero for overlap slots */ + FDKmemcpy( + &hybridData[0][0] + [usb + (NO_SUB_QMF_CHANNELS - 2 - NO_QMF_BANDS_HYBRID20)], + &rIntBufferLeft[0][usb], sizeof(FIXP_DBL) * (NO_QMF_CHANNELS - usb)); + FDKmemcpy( + &hybridData[0][1] + [usb + (NO_SUB_QMF_CHANNELS - 2 - NO_QMF_BANDS_HYBRID20)], + &iIntBufferLeft[0][usb], sizeof(FIXP_DBL) * (NO_QMF_CHANNELS - usb)); /*! Decorrelation: - By means of all-pass filtering and delaying, the (sub-)sub-band samples s_k(n) are - converted into de-correlated (sub-)sub-band samples d_k(n). + By means of all-pass filtering and delaying, the (sub-)sub-band samples s_k(n) + are converted into de-correlated (sub-)sub-band samples d_k(n). - k: frequency in hybrid spectrum - n: time index */ - deCorrelateSlotBased( h_ps_d, /* parametric stereo decoder handle */ - hybridRealLeft, /* left hybrid time slot */ - hybridImagLeft, - hybridScal, /* scale factor of left hybrid time slot */ - rIntBufferLeft[0], /* left qmf time slot */ - iIntBufferLeft[0], - sf_IntBuffer, /* scale factor of left and right qmf time slot */ - hybridRealRight, /* right hybrid time slot */ - hybridImagRight, - rIntBufferRight, /* right qmf time slot */ - iIntBufferRight ); - - + FDKdecorrelateApply(&h_ps_d->specificTo.mpeg.apDecor, + &hybridData[0][0][0], /* left real hybrid data */ + &hybridData[0][1][0], /* left imag hybrid data */ + &hybridData[1][0][0], /* right real hybrid data */ + &hybridData[1][1][0], /* right imag hybrid data */ + 0 /* startHybBand */ + ); /*! Stereo Processing: - The sets of (sub-)sub-band samples s_k(n) and d_k(n) are processed according to - the stereo cues which are defined per stereo band. + The sets of (sub-)sub-band samples s_k(n) and d_k(n) are processed according + to the stereo cues which are defined per stereo band. */ - - applySlotBasedRotation( h_ps_d, /* parametric stereo decoder handle */ - hybridRealLeft, /* left hybrid time slot */ - hybridImagLeft, - rIntBufferLeft[0], /* left qmf time slot */ - iIntBufferLeft[0], - hybridRealRight, /* right hybrid time slot */ - hybridImagRight, - rIntBufferRight, /* right qmf time slot */ - iIntBufferRight ); - - - + applySlotBasedRotation(h_ps_d, + &hybridData[0][0][0], /* left real hybrid data */ + &hybridData[0][1][0], /* left imag hybrid data */ + &hybridData[1][0][0], /* right real hybrid data */ + &hybridData[1][1][0] /* right imag hybrid data */ + ); /*! Hybrid synthesis filterbank: - The stereo processed hybrid subband signals l_k(n) and r_k(n) are fed into the hybrid synthesis - filterbanks which are identical to the 64 complex synthesis filterbank of the SBR tool. The - input to the filterbank are slots of 64 QMF samples. For each slot the filterbank outputs one - block of 64 samples of one reconstructed stereo channel. The hybrid synthesis filterbank is - computed seperatly for the left and right channel. + The stereo processed hybrid subband signals l_k(n) and r_k(n) are fed into the + hybrid synthesis filterbanks which are identical to the 64 complex synthesis + filterbank of the SBR tool. The input to the filterbank are slots of 64 QMF + samples. For each slot the filterbank outputs one block of 64 samples of one + reconstructed stereo channel. The hybrid synthesis filterbank is computed + seperatly for the left and right channel. */ - - /* left channel */ - slotBasedHybridSynthesis ( hybridRealLeft, /* one timeslot of hybrid filterbank values */ - hybridImagLeft, - rIntBufferLeft[0], /* one timeslot of qmf filterbank values */ - iIntBufferLeft[0], - &h_ps_d->specificTo.mpeg.hybrid ); /* hybrid filterbank handle */ - - /* right channel */ - slotBasedHybridSynthesis ( hybridRealRight, /* one timeslot of hybrid filterbank values */ - hybridImagRight, - rIntBufferRight, /* one timeslot of qmf filterbank values */ - iIntBufferRight, - &h_ps_d->specificTo.mpeg.hybrid ); /* hybrid filterbank handle */ - - - - - - + /* + * Hybrid synthesis. + */ + for (i = 0; i < 2; i++) { + FDKhybridSynthesisApply( + &h_ps_d->specificTo.mpeg.hybridSynthesis[i], + hybridData[i][0], /* real hybrid data */ + hybridData[i][1], /* imag hybrid data */ + (i == 0) ? rIntBufferLeft[0] + : rIntBufferRight, /* output real qmf buffer */ + (i == 0) ? iIntBufferLeft[0] + : iIntBufferRight /* output imag qmf buffer */ + ); + } /* free temporary hybrid qmf values of one timeslot */ - C_ALLOC_SCRATCH_END(hybridImagRight, FIXP_DBL, NO_SUB_QMF_CHANNELS); - C_ALLOC_SCRATCH_END(hybridRealRight, FIXP_DBL, NO_SUB_QMF_CHANNELS); - C_ALLOC_SCRATCH_END(hybridImagLeft, FIXP_DBL, NO_SUB_QMF_CHANNELS); - C_ALLOC_SCRATCH_END(hybridRealLeft, FIXP_DBL, NO_SUB_QMF_CHANNELS); - -}/* END ApplyPsSlot */ - - -/***************************************************************************/ -/*! - - \brief assigns timeslots to an array - - \return - -****************************************************************************/ - -static void assignTimeSlotsPS (FIXP_DBL *bufAdr, - FIXP_DBL **bufPtr, - const int numSlots, - const int numChan) -{ - FIXP_DBL *ptr; - int slot; - ptr = bufAdr; - for(slot=0; slot < numSlots; slot++) { - bufPtr [slot] = ptr; - ptr += numChan; - } -} + C_ALLOC_SCRATCH_END(pHybridData, FIXP_DBL, 4 * NO_HYBRID_DATA_BANDS); +} /* END ApplyPsSlot */ diff --git a/libSBRdec/src/psdec.h b/libSBRdec/src/psdec.h index 3dbc76d..b6d9a12 100644 --- a/libSBRdec/src/psdec.h +++ b/libSBRdec/src/psdec.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,18 +90,27 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief Sbr decoder + \brief Sbr decoder */ -#ifndef __PSDEC_H -#define __PSDEC_H +#ifndef PSDEC_H +#define PSDEC_H #include "sbrdecoder.h" +#include "FDK_hybrid.h" - +#include "FDK_decorrelate.h" /* This PS decoder implements the baseline version. So it always uses the */ /* hybrid filter structure for 20 stereo bands and does not implemet IPD/OPD */ @@ -99,254 +119,209 @@ amm-info@iis.fraunhofer.de /* is used in the bitstream for IIS/ICC the decoded parameters are mapped to */ /* 20 stereo bands. */ - #include "FDK_bitstream.h" -#include "psdec_hybrid.h" - -#define SCAL_HEADROOM ( 2 ) - -#define PS_EXTENSION_SIZE_BITS ( 4 ) -#define PS_EXTENSION_ESC_COUNT_BITS ( 8 ) - -#define NO_QMF_CHANNELS ( 64 ) -#define MAX_NUM_COL ( 32 ) - - - #define NO_QMF_BANDS_HYBRID20 ( 3 ) - #define NO_SUB_QMF_CHANNELS ( 12 ) - - #define NRG_INT_COEFF ( 0.75f ) - #define INT_FILTER_COEFF (FL2FXCONST_DBL( 1.0f - NRG_INT_COEFF )) - #define PEAK_DECAY_FACTOR (FL2FXCONST_DBL( 0.765928338364649f )) - #define TRANSIENT_IMPACT_FACTOR (FL2FXCONST_DBL( 2.0 / 3.0 )) - - #define NO_SERIAL_ALLPASS_LINKS ( 3 ) - #define MAX_NO_PS_ENV ( 4 + 1 ) /* +1 needed for VAR_BORDER */ +#define SCAL_HEADROOM (2) - #define MAX_DELAY_BUFFER_SIZE ( 14 ) - #define NO_DELAY_BUFFER_BANDS ( 35 ) +#define PS_EXTENSION_SIZE_BITS (4) +#define PS_EXTENSION_ESC_COUNT_BITS (8) - #define NO_HI_RES_BINS ( 34 ) - #define NO_MID_RES_BINS ( 20 ) - #define NO_LOW_RES_BINS ( 10 ) +#define NO_QMF_CHANNELS (64) +#define MAX_NUM_COL (32) - #define FIRST_DELAY_SB ( 23 ) - #define NO_SAMPLE_DELAY_ALLPASS ( 2 ) - #define NO_DELAY_LENGTH_VECTORS ( 12 ) /* d(m): d(0)=3 + d(1)=4 + d(2)=5 */ +#define NO_QMF_BANDS_HYBRID20 (3) +#define NO_SUB_QMF_CHANNELS (12) +#define HYBRID_FILTER_DELAY (6) - #define NO_HI_RES_IID_BINS ( NO_HI_RES_BINS ) - #define NO_HI_RES_ICC_BINS ( NO_HI_RES_BINS ) +#define MAX_NO_PS_ENV (4 + 1) /* +1 needed for VAR_BORDER */ - #define NO_MID_RES_IID_BINS ( NO_MID_RES_BINS ) - #define NO_MID_RES_ICC_BINS ( NO_MID_RES_BINS ) +#define NO_HI_RES_BINS (34) +#define NO_MID_RES_BINS (20) +#define NO_LOW_RES_BINS (10) - #define NO_LOW_RES_IID_BINS ( NO_LOW_RES_BINS ) - #define NO_LOW_RES_ICC_BINS ( NO_LOW_RES_BINS ) +#define NO_HI_RES_IID_BINS (NO_HI_RES_BINS) +#define NO_HI_RES_ICC_BINS (NO_HI_RES_BINS) - #define SUBQMF_GROUPS ( 10 ) - #define QMF_GROUPS ( 12 ) +#define NO_MID_RES_IID_BINS (NO_MID_RES_BINS) +#define NO_MID_RES_ICC_BINS (NO_MID_RES_BINS) - #define SUBQMF_GROUPS_HI_RES ( 32 ) - #define QMF_GROUPS_HI_RES ( 18 ) +#define NO_LOW_RES_IID_BINS (NO_LOW_RES_BINS) +#define NO_LOW_RES_ICC_BINS (NO_LOW_RES_BINS) - #define NO_IID_GROUPS ( SUBQMF_GROUPS + QMF_GROUPS ) - #define NO_IID_GROUPS_HI_RES ( SUBQMF_GROUPS_HI_RES + QMF_GROUPS_HI_RES ) +#define SUBQMF_GROUPS (10) +#define QMF_GROUPS (12) - #define NO_IID_STEPS ( 7 ) /* 1 .. + 7 */ - #define NO_IID_STEPS_FINE ( 15 ) /* 1 .. +15 */ - #define NO_ICC_STEPS ( 8 ) /* 0 .. + 7 */ +//#define SUBQMF_GROUPS_HI_RES ( 32 ) +//#define QMF_GROUPS_HI_RES ( 18 ) - #define NO_IID_LEVELS ( 2 * NO_IID_STEPS + 1 ) /* - 7 .. + 7 */ - #define NO_IID_LEVELS_FINE ( 2 * NO_IID_STEPS_FINE + 1 ) /* -15 .. +15 */ - #define NO_ICC_LEVELS ( NO_ICC_STEPS ) /* 0 .. + 7 */ +#define NO_IID_GROUPS (SUBQMF_GROUPS + QMF_GROUPS) +//#define NO_IID_GROUPS_HI_RES ( SUBQMF_GROUPS_HI_RES + +// QMF_GROUPS_HI_RES ) - #define FIXP_SQRT05 ((FIXP_DBL)0x5a827980) /* 1/SQRT2 */ +#define NO_IID_STEPS (7) /* 1 .. + 7 */ +#define NO_IID_STEPS_FINE (15) /* 1 .. +15 */ +#define NO_ICC_STEPS (8) /* 0 .. + 7 */ - struct PS_DEC_COEFFICIENTS { +#define NO_IID_LEVELS (2 * NO_IID_STEPS + 1) /* - 7 .. + 7 */ +#define NO_IID_LEVELS_FINE (2 * NO_IID_STEPS_FINE + 1) /* -15 .. +15 */ +#define NO_ICC_LEVELS (NO_ICC_STEPS) /* 0 .. + 7 */ - FIXP_DBL H11r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ - FIXP_DBL H12r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ - FIXP_DBL H21r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ - FIXP_DBL H22r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ +#define FIXP_SQRT05 ((FIXP_DBL)0x5a827980) /* 1/SQRT2 */ - FIXP_DBL DeltaH11r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ - FIXP_DBL DeltaH12r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ - FIXP_DBL DeltaH21r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ - FIXP_DBL DeltaH22r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ +struct PS_DEC_COEFFICIENTS { + FIXP_DBL H11r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL H12r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL H21r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL H22r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ - SCHAR aaIidIndexMapped[MAX_NO_PS_ENV][NO_HI_RES_IID_BINS]; /*!< The mapped IID index for all envelopes and all IID bins */ - SCHAR aaIccIndexMapped[MAX_NO_PS_ENV][NO_HI_RES_ICC_BINS]; /*!< The mapped ICC index for all envelopes and all ICC bins */ + FIXP_DBL + DeltaH11r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL + DeltaH12r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL + DeltaH21r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL + DeltaH22r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ - }; - - - - -typedef enum { - ppt_none = 0, - ppt_mpeg = 1, - ppt_drm = 2 -} PS_PAYLOAD_TYPE; + SCHAR + aaIidIndexMapped[MAX_NO_PS_ENV] + [NO_HI_RES_IID_BINS]; /*!< The mapped IID index for all + envelopes and all IID bins */ + SCHAR + aaIccIndexMapped[MAX_NO_PS_ENV] + [NO_HI_RES_ICC_BINS]; /*!< The mapped ICC index for all + envelopes and all ICC bins */ +}; +typedef enum { ppt_none = 0, ppt_mpeg = 1, ppt_drm = 2 } PS_PAYLOAD_TYPE; typedef struct { - UCHAR bPsHeaderValid; /*!< set if new header is available from bitstream */ - - UCHAR bEnableIid; /*!< One bit denoting the presence of IID parameters */ - UCHAR bEnableIcc; /*!< One bit denoting the presence of ICC parameters */ - UCHAR bEnableExt; /*!< The PS extension layer is enabled using the enable_ext bit. - If it is set to %1 the IPD and OPD parameters are sent. - If it is disabled, i.e. %0, the extension layer is skipped. */ - - UCHAR modeIid; /*!< The configuration of IID parameters (number of bands and - quantisation grid, iid_quant) is determined by iid_mode. */ - UCHAR modeIcc; /*!< The configuration of Inter-channel Coherence parameters - (number of bands and quantisation grid) is determined by - icc_mode. */ - - UCHAR freqResIid; /*!< 0=low, 1=mid or 2=high frequency resolution for iid */ - UCHAR freqResIcc; /*!< 0=low, 1=mid or 2=high frequency resolution for icc */ - - UCHAR bFineIidQ; /*!< Use fine Iid quantisation. */ - - UCHAR bFrameClass; /*!< The frame_class bit determines whether the parameter - positions of the current frame are uniformly spaced - accross the frame or they are defined using the positions - described by border_position. */ - - UCHAR noEnv; /*!< The number of envelopes per frame */ - UCHAR aEnvStartStop[MAX_NO_PS_ENV+1]; /*!< In case of variable parameter spacing the parameter - positions are determined by border_position */ - - SCHAR abIidDtFlag[MAX_NO_PS_ENV]; /*!< Deltacoding time/freq flag for IID, 0 => freq */ - SCHAR abIccDtFlag[MAX_NO_PS_ENV]; /*!< Deltacoding time/freq flag for ICC, 0 => freq */ - - SCHAR aaIidIndex[MAX_NO_PS_ENV][NO_HI_RES_IID_BINS]; /*!< The IID index for all envelopes and all IID bins */ - SCHAR aaIccIndex[MAX_NO_PS_ENV][NO_HI_RES_ICC_BINS]; /*!< The ICC index for all envelopes and all ICC bins */ + UCHAR bPsHeaderValid; /*!< set if new header is available from bitstream */ + + UCHAR bEnableIid; /*!< One bit denoting the presence of IID parameters */ + UCHAR bEnableIcc; /*!< One bit denoting the presence of ICC parameters */ + UCHAR bEnableExt; /*!< The PS extension layer is enabled using the enable_ext + bit. If it is set to %1 the IPD and OPD parameters are + sent. If it is disabled, i.e. %0, the extension layer is + skipped. */ + + UCHAR + modeIid; /*!< The configuration of IID parameters (number of bands and + quantisation grid, iid_quant) is determined by iid_mode. */ + UCHAR modeIcc; /*!< The configuration of Inter-channel Coherence parameters + (number of bands and quantisation grid) is determined by + icc_mode. */ + + UCHAR freqResIid; /*!< 0=low, 1=mid or 2=high frequency resolution for iid */ + UCHAR freqResIcc; /*!< 0=low, 1=mid or 2=high frequency resolution for icc */ + + UCHAR bFineIidQ; /*!< Use fine Iid quantisation. */ + + UCHAR bFrameClass; /*!< The frame_class bit determines whether the parameter + positions of the current frame are uniformly spaced + accross the frame or they are defined using the + positions described by border_position. + */ + + UCHAR noEnv; /*!< The number of envelopes per frame */ + UCHAR aEnvStartStop[MAX_NO_PS_ENV + 1]; /*!< In case of variable parameter + spacing the parameter positions are + determined by border_position */ + + SCHAR abIidDtFlag[MAX_NO_PS_ENV]; /*!< Deltacoding time/freq flag for IID, 0 + => freq */ + SCHAR abIccDtFlag[MAX_NO_PS_ENV]; /*!< Deltacoding time/freq flag for ICC, 0 + => freq */ + + SCHAR + aaIidIndex[MAX_NO_PS_ENV] + [NO_HI_RES_IID_BINS]; /*!< The IID index for all envelopes and + all IID bins */ + SCHAR + aaIccIndex[MAX_NO_PS_ENV] + [NO_HI_RES_ICC_BINS]; /*!< The ICC index for all envelopes and + all ICC bins */ } MPEG_PS_BS_DATA; - - struct PS_DEC { - SCHAR noSubSamples; SCHAR noChannels; - SCHAR procFrameBased; /*!< Helper to detected switching from frame based to slot based - processing */ + SCHAR procFrameBased; /*!< Helper to detected switching from frame based to + slot based processing + */ - PS_PAYLOAD_TYPE bPsDataAvail[(1)+1]; /*!< set if new data available from bitstream */ - UCHAR psDecodedPrv; /*!< set if PS has been processed in the last frame */ + PS_PAYLOAD_TYPE + bPsDataAvail[(1) + 1]; /*!< set if new data available from bitstream */ + UCHAR psDecodedPrv; /*!< set if PS has been processed in the last frame */ /* helpers for frame delay line */ - UCHAR bsLastSlot; /*!< Index of last read slot. */ - UCHAR bsReadSlot; /*!< Index of current read slot for additional delay. */ - UCHAR processSlot; /*!< Index of current slot for processing (need for add. delay). */ - - - INT rescal; - INT sf_IntBuffer; - - union { /* Bitstream data */ - MPEG_PS_BS_DATA mpeg; /*!< Struct containing all MPEG specific PS data from bitstream. */ - } bsData[(1)+1]; - - shouldBeUnion { /* Static data */ + UCHAR bsLastSlot; /*!< Index of last read slot. */ + UCHAR bsReadSlot; /*!< Index of current read slot for additional delay. */ + UCHAR processSlot; /*!< Index of current slot for processing (need for add. + delay). */ + + union { /* Bitstream data */ + MPEG_PS_BS_DATA + mpeg; /*!< Struct containing all MPEG specific PS data from bitstream. + */ + } bsData[(1) + 1]; + + shouldBeUnion { /* Static data */ struct { - SCHAR aIidPrevFrameIndex[NO_HI_RES_IID_BINS]; /*!< The IID index for previous frame */ - SCHAR aIccPrevFrameIndex[NO_HI_RES_ICC_BINS]; /*!< The ICC index for previous frame */ - - UCHAR delayBufIndex; /*!< Pointer to where the latest sample is in buffer */ - UCHAR noSampleDelay; /*!< How many QMF samples delay is used. */ - UCHAR lastUsb; /*!< uppermost WMF delay band of last frame */ - - UCHAR aDelayRBufIndexSer[NO_SERIAL_ALLPASS_LINKS]; /*!< Delay buffer for reverb filter */ - UCHAR aDelayBufIndexDelayQmf[NO_QMF_CHANNELS-FIRST_DELAY_SB]; /*!< Delay buffer for ICC group 20 & 21 */ - - SCHAR scaleFactorPsDelayBuffer; /*!< Scale factor for ps delay buffer */ - - /* hybrid filter bank delay lines */ - FIXP_DBL aaQmfDelayBufReal[(NO_QMF_CHANNELS-FIRST_DELAY_SB) + (MAX_DELAY_BUFFER_SIZE-1)*(NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB)]; - FIXP_DBL aaQmfDelayBufImag[(NO_QMF_CHANNELS-FIRST_DELAY_SB) + (MAX_DELAY_BUFFER_SIZE-1)*(NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB)]; - - FIXP_DBL *pAaRealDelayBufferQmf[MAX_DELAY_BUFFER_SIZE]; /*!< Real part delay buffer */ - FIXP_DBL *pAaImagDelayBufferQmf[MAX_DELAY_BUFFER_SIZE]; /*!< Imaginary part delay buffer */ - - FIXP_DBL aaRealDelayBufferQmf[NO_SAMPLE_DELAY_ALLPASS][FIRST_DELAY_SB]; /*!< Real part delay buffer */ - FIXP_DBL aaImagDelayBufferQmf[NO_SAMPLE_DELAY_ALLPASS][FIRST_DELAY_SB]; /*!< Imaginary part delay buffer*/ - - FIXP_DBL aaRealDelayBufferSubQmf[NO_SAMPLE_DELAY_ALLPASS][NO_SUB_QMF_CHANNELS]; /*!< Real part delay buffer */ - FIXP_DBL aaImagDelayBufferSubQmf[NO_SAMPLE_DELAY_ALLPASS][NO_SUB_QMF_CHANNELS]; /*!< Imaginary part delay buffer */ - - FIXP_DBL aaaRealDelayRBufferSerQmf[FIRST_DELAY_SB][NO_DELAY_LENGTH_VECTORS]; /*!< Real part delay buffer */ - FIXP_DBL aaaImagDelayRBufferSerQmf[FIRST_DELAY_SB][NO_DELAY_LENGTH_VECTORS]; /*!< Imaginary part delay buffer */ - - FIXP_DBL aaaRealDelayRBufferSerSubQmf[NO_SUB_QMF_CHANNELS][NO_DELAY_LENGTH_VECTORS]; /*!< Real part delay buffer */ - FIXP_DBL aaaImagDelayRBufferSerSubQmf[NO_SUB_QMF_CHANNELS][NO_DELAY_LENGTH_VECTORS]; /*!< Imaginary part delay buffer */ - - HYBRID hybrid; /*!< hybrid filter bank struct 1 or 2. */ - - FIXP_DBL aPrevNrgBin[NO_MID_RES_BINS]; /*!< energy of previous frame */ - FIXP_DBL aPrevPeakDiffBin[NO_MID_RES_BINS]; /*!< peak difference of previous frame */ - FIXP_DBL aPeakDecayFastBin[NO_MID_RES_BINS]; /*!< Saved max. peak decay value per bin */ - SCHAR aPowerPrevScal[NO_MID_RES_BINS]; /*!< Last power value (each bin) of previous frame */ - - FIXP_DBL h11rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) coefficients */ - FIXP_DBL h12rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) coefficients */ - FIXP_DBL h21rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) coefficients */ - FIXP_DBL h22rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) coefficients */ - - PS_DEC_COEFFICIENTS coef; /*!< temporal coefficients (reusable scratch memory) */ + SCHAR aIidPrevFrameIndex[NO_HI_RES_IID_BINS]; /*!< The IID index for + previous frame */ + SCHAR aIccPrevFrameIndex[NO_HI_RES_ICC_BINS]; /*!< The ICC index for + previous frame */ + UCHAR lastUsb; /*!< uppermost WMF delay band of last frame */ + + FIXP_DBL pHybridAnaStatesLFdmx + [2 * 13 * NO_QMF_BANDS_HYBRID20]; /*!< Memory used in hybrid analysis + for filter states. */ + FDK_ANA_HYB_FILTER hybridAnalysis; + FDK_SYN_HYB_FILTER hybridSynthesis[2]; + + DECORR_DEC apDecor; /*!< Decorrelator instance. */ + FIXP_DBL decorrBufferCplx[(2 * ((825) + (373)))]; + + FIXP_DBL h11rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) + coefficients */ + FIXP_DBL h12rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) + coefficients */ + FIXP_DBL h21rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) + coefficients */ + FIXP_DBL h22rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) + coefficients */ + + PS_DEC_COEFFICIENTS + *pCoef; /*!< temporal coefficients are on reusable scratch memory */ } mpeg; - - } specificTo; - - + } + specificTo; }; typedef struct PS_DEC *HANDLE_PS_DEC; - int CreatePsDec(HANDLE_PS_DEC *h_PS_DEC, int aacSamplesPerFrame); int DeletePsDec(HANDLE_PS_DEC *h_PS_DEC); -void -scalFilterBankValues( HANDLE_PS_DEC h_ps_d, /* parametric stereo decoder handle */ - FIXP_DBL **fixpQmfReal, /* qmf filterbank values */ - FIXP_DBL **fixpQmfImag, /* qmf filterbank values */ - int lsb, /* sbr start subband */ - int scaleFactorLowBandSplitLow, - int scaleFactorLowBandSplitHigh, - SCHAR *scaleFactorLowBand_lb, - SCHAR *scaleFactorLowBand_hb, - int scaleFactorHighBands, - INT *scaleFactorHighBand, - INT noCols); - -void -rescalFilterBankValues( HANDLE_PS_DEC h_ps_d, /* parametric stereo decoder handle */ - FIXP_DBL **QmfBufferReal, /* qmf filterbank values */ - FIXP_DBL **QmfBufferImag, /* qmf filterbank values */ - int lsb, /* sbr start subband */ - INT noCols); - - -void -initSlotBasedRotation( HANDLE_PS_DEC h_ps_d, - int env, - int usb); - -void -ApplyPsSlot( HANDLE_PS_DEC h_ps_d, /* parametric stereo decoder handle */ - FIXP_DBL **rIntBufferLeft, /* real values of left qmf timeslot */ - FIXP_DBL **iIntBufferLeft, /* imag values of left qmf timeslot */ - FIXP_DBL *rIntBufferRight, /* real values of right qmf timeslot */ - FIXP_DBL *iIntBufferRight); /* imag values of right qmf timeslot */ - - - -#endif /* __PSDEC_H */ +void PreparePsProcessing(HANDLE_PS_DEC h_ps_d, + const FIXP_DBL *const *const rIntBufferLeft, + const FIXP_DBL *const *const iIntBufferLeft, + const int scaleFactorLowBand); + +void initSlotBasedRotation(HANDLE_PS_DEC h_ps_d, int env, int usb); + +void ApplyPsSlot( + HANDLE_PS_DEC h_ps_d, /* parametric stereo decoder handle */ + FIXP_DBL **rIntBufferLeft, /* real values of left qmf timeslot */ + FIXP_DBL **iIntBufferLeft, /* imag values of left qmf timeslot */ + FIXP_DBL *rIntBufferRight, /* real values of right qmf timeslot */ + FIXP_DBL *iIntBufferRight, /* imag values of right qmf timeslot */ + const int scaleFactorLowBand_no_ov, const int scaleFactorLowBand, + const int scaleFactorHighBand, const int lsb, const int usb); + +#endif /* PSDEC_H */ diff --git a/libSBRdec/src/psdec_drm.cpp b/libSBRdec/src/psdec_drm.cpp new file mode 100644 index 0000000..6971f53 --- /dev/null +++ b/libSBRdec/src/psdec_drm.cpp @@ -0,0 +1,108 @@ +/* ----------------------------------------------------------------------------- +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 parametric stereo decoder for Digital radio mondial +*/ + +#include "psdec_drm.h" diff --git a/libSBRdec/src/psdec_drm.h b/libSBRdec/src/psdec_drm.h new file mode 100644 index 0000000..5e2575d --- /dev/null +++ b/libSBRdec/src/psdec_drm.h @@ -0,0 +1,113 @@ +/* ----------------------------------------------------------------------------- +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 parametric stereo decoder for digital radio mondial +*/ + +#ifndef PSDEC_DRM_H +#define PSDEC_DRM_H + +#include "sbrdecoder.h" + +#endif /* PSDEC_DRM_H */ diff --git a/libSBRdec/src/psdec_hybrid.cpp b/libSBRdec/src/psdec_hybrid.cpp deleted file mode 100644 index cbd0e92..0000000 --- a/libSBRdec/src/psdec_hybrid.cpp +++ /dev/null @@ -1,652 +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 ------------------------------------------------------------------------------------------------------------ */ - -#include "psdec_hybrid.h" - - -#include "fft.h" -#include "sbr_ram.h" - -#include "FDK_tools_rom.h" -#include "sbr_rom.h" - -/******************************************************************************* - Functionname: InitHybridFilterBank - ******************************************************************************* - - Description: Init one instance of HANDLE_HYBRID stuct - - Arguments: - - Return: none - -*******************************************************************************/ - - -SBR_ERROR -InitHybridFilterBank ( HANDLE_HYBRID hs, /*!< Handle to HYBRID struct. */ - SCHAR frameSize, /*!< Framesize (in Qmf súbband samples). */ - SCHAR noBands, /*!< Number of Qmf bands for hybrid filtering. */ - const UCHAR *pResolution ) /*!< Resolution in Qmf bands (length noBands). */ -{ - SCHAR i; - UCHAR maxNoChannels = 0; - - for (i = 0; i < noBands; i++) { - hs->pResolution[i] = pResolution[i]; - if(pResolution[i] > maxNoChannels) - maxNoChannels = pResolution[i]; - } - - hs->nQmfBands = noBands; - hs->frameSize = frameSize; - hs->qmfBufferMove = HYBRID_FILTER_LENGTH - 1; - - hs->sf_mQmfBuffer = 0; - - return SBRDEC_OK; -} - -/******************************************************************************* - Functionname: dualChannelFiltering - ******************************************************************************* - - Description: fast 2-channel real-valued filtering with 6-tap delay. - - Arguments: - - Return: none - -*******************************************************************************/ - -/*! -2 channel filter -<pre> - Filter Coefs: - 0.0, - 0.01899487526049, - 0.0, - -0.07293139167538, - 0.0, - 0.30596630545168, - 0.5, - 0.30596630545168, - 0.0, - -0.07293139167538, - 0.0, - 0.01899487526049, - 0.0 - - - Filter design: - h[q,n] = g[n] * cos(2pi/2 * q * (n-6) ); n = 0..12, q = 0,1; - - -> h[0,n] = g[n] * 1; - -> h[1,n] = g[n] * pow(-1,n); -</pre> -*/ - -static void slotBasedDualChannelFiltering( const FIXP_DBL *pQmfReal, - const FIXP_DBL *pQmfImag, - - FIXP_DBL *mHybridReal, - FIXP_DBL *mHybridImag) -{ - - FIXP_DBL t1, t3, t5, t6; - - /* symmetric filter coefficients */ - - /* you don't have to shift the result after fMult because of p2_13_20 <= 0.5 */ - t1 = fMultDiv2(p2_13_20[1] , ( (pQmfReal[1] >> 1) + (pQmfReal[11] >> 1))); - t3 = fMultDiv2(p2_13_20[3] , ( (pQmfReal[3] >> 1) + (pQmfReal[ 9] >> 1))); - t5 = fMultDiv2(p2_13_20[5] , ( (pQmfReal[5] >> 1) + (pQmfReal[ 7] >> 1))); - t6 = fMultDiv2(p2_13_20[6] , (pQmfReal[6] >> 1) ); - - mHybridReal[0] = (t1 + t3 + t5 + t6) << 2; - mHybridReal[1] = (- t1 - t3 - t5 + t6) << 2; - - t1 = fMultDiv2(p2_13_20[1] , ( (pQmfImag[1] >> 1) + (pQmfImag[11] >> 1))); - t3 = fMultDiv2(p2_13_20[3] , ( (pQmfImag[3] >> 1) + (pQmfImag[ 9] >> 1))); - t5 = fMultDiv2(p2_13_20[5] , ( (pQmfImag[5] >> 1) + (pQmfImag[ 7] >> 1))); - t6 = fMultDiv2(p2_13_20[6] , pQmfImag[6] >> 1 ); - - mHybridImag[0] = (t1 + t3 + t5 + t6) << 2; - mHybridImag[1] = (- t1 - t3 - t5 + t6) << 2; -} - - -/******************************************************************************* - Functionname: eightChannelFiltering - ******************************************************************************* - - Description: fast 8-channel complex-valued filtering with 6-tap delay. - - Arguments: - - Return: none - -*******************************************************************************/ -/*! - 8 channel filter - - Implementation using a FFT of length 8 -<pre> - prototype filter coefficients: - 0.00746082949812 0.02270420949825 0.04546865930473 0.07266113929591 0.09885108575264 0.11793710567217 - 0.125 - 0.11793710567217 0.09885108575264 0.07266113929591 0.04546865930473 0.02270420949825 0.00746082949812 - - Filter design: - N = 13; Q = 8; - h[q,n] = g[n] * exp(j * 2 * pi / Q * (q + .5) * (n - 6)); n = 0..(N-1), q = 0..(Q-1); - - Time Signal: x[t]; - Filter Bank Output - y[q,t] = conv(x[t],h[q,t]) = conv(h[q,t],x[t]) = sum(x[k] * h[q, t - k] ) = sum(h[q, k] * x[t - k] ); k = 0..(N-1); - - y[q,t] = x[t - 12]*h[q, 12] + x[t - 11]*h[q, 11] + x[t - 10]*h[q, 10] + x[t - 9]*h[q, 9] - + x[t - 8]*h[q, 8] + x[t - 7]*h[q, 7] - + x[t - 6]*h[q, 6] - + x[t - 5]*h[q, 5] + x[t - 4]*h[q, 4] - + x[t - 3]*h[q, 3] + x[t - 2]*h[q, 2] + x[t - 1]*h[q, 1] + x[t - 0]*h[q, 0]; - - h'[q, n] = h[q,(N-1)-n] = g[n] * exp(j * 2 * pi / Q * (q + .5) * (6 - n)); n = 0..(N-1), q = 0..(Q-1); - - y[q,t] = x[t - 12]*h'[q, 0] + x[t - 11]*h'[q, 1] + x[t - 10]*h'[q, 2] + x[t - 9]*h'[q, 3] - + x[t - 8]*h'[q, 4] + x[t - 7]*h'[q, 5] - + x[t - 6]*h'[q, 6] - + x[t - 5]*h'[q, 7] + x[t - 4]*h'[q, 8] - + x[t - 3]*h'[q, 9] + x[t - 2]*h'[q, 10] + x[t - 1]*h'[q, 11] + x[t - 0]*h'[q, 12]; - - Try to split off FFT Modulation Term: - FFT(x[t], q) = sum(x[t+k]*exp(-j*2*pi/N *q * k)) - c m - Step 1: h'[q,n] = g[n] * ( exp(j * 2 * pi / 8 * .5 * (6 - n)) ) * ( exp (j * 2 * pi / 8 * q * (6 - n)) ); - - h'[q,n] = g[n] *c[n] * m[q,n]; (see above) - c[n] = exp( j * 2 * pi / 8 * .5 * (6 - n) ); - m[q,n] = exp( j * 2 * pi / 8 * q * (6 - n) ); - - y[q,t] = x[t - 0]*g[0]*c[0]*m[q,0] + x[t - 1]*g[1]*c[ 1]*m[q, 1] + ... - ... + x[t - 12]*g[2]*c[12]*m[q,12]; - - | - n m *exp(-j*2*pi) | n' fft -------------------------------------------------------------------------------------------------------------------------- - 0 exp( j * 2 * pi / 8 * q * 6) -> exp(-j * 2 * pi / 8 * q * 2) | 2 exp(-j * 2 * pi / 8 * q * 0) - 1 exp( j * 2 * pi / 8 * q * 5) -> exp(-j * 2 * pi / 8 * q * 3) | 3 exp(-j * 2 * pi / 8 * q * 1) - 2 exp( j * 2 * pi / 8 * q * 4) -> exp(-j * 2 * pi / 8 * q * 4) | 4 exp(-j * 2 * pi / 8 * q * 2) - 3 exp( j * 2 * pi / 8 * q * 3) -> exp(-j * 2 * pi / 8 * q * 5) | 5 exp(-j * 2 * pi / 8 * q * 3) - 4 exp( j * 2 * pi / 8 * q * 2) -> exp(-j * 2 * pi / 8 * q * 6) | 6 exp(-j * 2 * pi / 8 * q * 4) - 5 exp( j * 2 * pi / 8 * q * 1) -> exp(-j * 2 * pi / 8 * q * 7) | 7 exp(-j * 2 * pi / 8 * q * 5) - 6 exp( j * 2 * pi / 8 * q * 0) | 0 exp(-j * 2 * pi / 8 * q * 6) - 7 exp(-j * 2 * pi / 8 * q * 1) | 1 exp(-j * 2 * pi / 8 * q * 7) - 8 exp(-j * 2 * pi / 8 * q * 2) | 2 - 9 exp(-j * 2 * pi / 8 * q * 3) | 3 - 10 exp(-j * 2 * pi / 8 * q * 4) | 4 - 11 exp(-j * 2 * pi / 8 * q * 5) | 5 - 12 exp(-j * 2 * pi / 8 * q * 6) | 6 - - - now use fft modulation coefficients - m[6] = = fft[0] - m[7] = = fft[1] - m[8] = m[ 0] = fft[2] - m[9] = m[ 1] = fft[3] - m[10] = m[ 2] = fft[4] - m[11] = m[ 3] = fft[5] - m[12] = m[ 4] = fft[6] - m[ 5] = fft[7] - - y[q,t] = ( x[t- 6]*g[ 6]*c[ 6] ) * fft[q,0] + - ( x[t- 7]*g[ 7]*c[ 7] ) * fft[q,1] + - ( x[t- 0]*g[ 0]*c[ 0] + x[t- 8]*g[ 8]*c[ 8] ) * fft[q,2] + - ( x[t- 1]*g[ 1]*c[ 1] + x[t- 9]*g[ 9]*c[ 9] ) * fft[q,3] + - ( x[t- 2]*g[ 2]*c[ 2] + x[t-10]*g[10]*c[10] ) * fft[q,4] + - ( x[t- 3]*g[ 3]*c[ 3] + x[t-11]*g[11]*c[11] ) * fft[q,5] + - ( x[t- 4]*g[ 4]*c[ 4] + x[t-12]*g[12]*c[12] ) * fft[q,6] + - ( x[t- 5]*g[ 5]*c[ 5] ) * fft[q,7]; - - pre twiddle factors c[n] = exp(j * 2 * pi / 8 * .5 * (6 - n)); - n c] | n c[n] | n c[n] ---------------------------------------------------------------------------------------------------- - 0 exp( j * 6 * pi / 8) | 1 exp( j * 5 * pi / 8) | 2 exp( j * 4 * pi / 8) - 3 exp( j * 3 * pi / 8) | 4 exp( j * 2 * pi / 8) | 5 exp( j * 1 * pi / 8) - 6 exp( j * 0 * pi / 8) | 7 exp(-j * 1 * pi / 8) | 8 exp(-j * 2 * pi / 8) - 9 exp(-j * 3 * pi / 8) | 10 exp(-j * 4 * pi / 8) | 11 exp(-j * 5 * pi / 8) - 12 exp(-j * 6 * pi / 8) | | -</pre> -*/ - -/* defining rotation factors for *ChannelFiltering */ - -#define cos0Pi FL2FXCONST_DBL( 1.f) -#define sin0Pi FL2FXCONST_DBL( 0.f) - -#define cos1Pi FL2FXCONST_DBL(-1.f) -#define sin1Pi FL2FXCONST_DBL( 0.f) - -#define cos1Pi_2 FL2FXCONST_DBL( 0.f) -#define sin1Pi_2 FL2FXCONST_DBL( 1.f) - -#define cos1Pi_3 FL2FXCONST_DBL( 0.5f) -#define sin1Pi_3 FL2FXCONST_DBL( 0.86602540378444f) - -#define cos0Pi_4 cos0Pi -#define cos1Pi_4 FL2FXCONST_DBL(0.70710678118655f) -#define cos2Pi_4 cos1Pi_2 -#define cos3Pi_4 (-cos1Pi_4) -#define cos4Pi_4 (-cos0Pi_4) -#define cos5Pi_4 cos3Pi_4 -#define cos6Pi_4 cos2Pi_4 - -#define sin0Pi_4 sin0Pi -#define sin1Pi_4 FL2FXCONST_DBL(0.70710678118655f) -#define sin2Pi_4 sin1Pi_2 -#define sin3Pi_4 sin1Pi_4 -#define sin4Pi_4 sin0Pi_4 -#define sin5Pi_4 (-sin3Pi_4) -#define sin6Pi_4 (-sin2Pi_4) - -#define cos0Pi_8 cos0Pi -#define cos1Pi_8 FL2FXCONST_DBL(0.92387953251129f) -#define cos2Pi_8 cos1Pi_4 -#define cos3Pi_8 FL2FXCONST_DBL(0.38268343236509f) -#define cos4Pi_8 cos2Pi_4 -#define cos5Pi_8 (-cos3Pi_8) -#define cos6Pi_8 (-cos2Pi_8) - -#define sin0Pi_8 sin0Pi -#define sin1Pi_8 cos3Pi_8 -#define sin2Pi_8 sin1Pi_4 -#define sin3Pi_8 cos1Pi_8 -#define sin4Pi_8 sin2Pi_4 -#define sin5Pi_8 sin3Pi_8 -#define sin6Pi_8 sin1Pi_4 - -#if defined(ARCH_PREFER_MULT_32x16) - #define FIXP_HYB FIXP_SGL - #define FIXP_CAST FX_DBL2FX_SGL -#else - #define FIXP_HYB FIXP_DBL - #define FIXP_CAST -#endif - -static const FIXP_HYB cr[13] = -{ - FIXP_CAST(cos6Pi_8), FIXP_CAST(cos5Pi_8), FIXP_CAST(cos4Pi_8), - FIXP_CAST(cos3Pi_8), FIXP_CAST(cos2Pi_8), FIXP_CAST(cos1Pi_8), - FIXP_CAST(cos0Pi_8), - FIXP_CAST(cos1Pi_8), FIXP_CAST(cos2Pi_8), FIXP_CAST(cos3Pi_8), - FIXP_CAST(cos4Pi_8), FIXP_CAST(cos5Pi_8), FIXP_CAST(cos6Pi_8) -}; - -static const FIXP_HYB ci[13] = -{ - FIXP_CAST( sin6Pi_8), FIXP_CAST( sin5Pi_8), FIXP_CAST( sin4Pi_8), - FIXP_CAST( sin3Pi_8), FIXP_CAST( sin2Pi_8), FIXP_CAST( sin1Pi_8), - FIXP_CAST( sin0Pi_8) , - FIXP_CAST(-sin1Pi_8), FIXP_CAST(-sin2Pi_8), FIXP_CAST(-sin3Pi_8), - FIXP_CAST(-sin4Pi_8), FIXP_CAST(-sin5Pi_8), FIXP_CAST(-sin6Pi_8) -}; - -static void slotBasedEightChannelFiltering( const FIXP_DBL *pQmfReal, - const FIXP_DBL *pQmfImag, - - FIXP_DBL *mHybridReal, - FIXP_DBL *mHybridImag) -{ - - int bin; - FIXP_DBL _fft[128 + ALIGNMENT_DEFAULT - 1]; - FIXP_DBL *fft = (FIXP_DBL *)ALIGN_PTR(_fft); - -#if defined(ARCH_PREFER_MULT_32x16) - const FIXP_SGL *p = p8_13_20; /* BASELINE_PS */ -#else - const FIXP_DBL *p = p8_13_20; /* BASELINE_PS */ -#endif - - /* pre twiddeling */ - - /* x*(a*b + c*d) = fMultDiv2(x, fMultAddDiv2(fMultDiv2(a, b), c, d)) */ - /* x*(a*b - c*d) = fMultDiv2(x, fMultSubDiv2(fMultDiv2(a, b), c, d)) */ - FIXP_DBL accu1, accu2, accu3, accu4; - - #define TWIDDLE_1(n_0,n_1,n_2) \ - cplxMultDiv2(&accu1, &accu2, pQmfReal[n_0], pQmfImag[n_0], cr[n_0], ci[n_0]); \ - accu1 = fMultDiv2(p[n_0], accu1); \ - accu2 = fMultDiv2(p[n_0], accu2); \ - cplxMultDiv2(&accu3, &accu4, pQmfReal[n_1], pQmfImag[n_1], cr[n_1], ci[n_1]); \ - accu3 = fMultDiv2(p[n_1], accu3); \ - accu4 = fMultDiv2(p[n_1], accu4); \ - fft[FIXP_FFT_IDX_R(n_2)] = accu1 + accu3; \ - fft[FIXP_FFT_IDX_I(n_2)] = accu2 + accu4; - - #define TWIDDLE_0(n_0,n_1) \ - cplxMultDiv2(&accu1, &accu2, pQmfReal[n_0], pQmfImag[n_0], cr[n_0], ci[n_0]); \ - fft[FIXP_FFT_IDX_R(n_1)] = fMultDiv2(p[n_0], accu1); \ - fft[FIXP_FFT_IDX_I(n_1)] = fMultDiv2(p[n_0], accu2); - - TWIDDLE_0( 6, 0) - TWIDDLE_0( 7, 1) - - TWIDDLE_1( 0, 8, 2) - TWIDDLE_1( 1, 9, 3) - TWIDDLE_1( 2,10, 4) - TWIDDLE_1( 3,11, 5) - TWIDDLE_1( 4,12, 6) - - TWIDDLE_0( 5, 7) - - fft_8 (fft); - - /* resort fft data into output array*/ - for(bin=0; bin<8;bin++ ) { - mHybridReal[bin] = fft[FIXP_FFT_IDX_R(bin)] << 4; - mHybridImag[bin] = fft[FIXP_FFT_IDX_I(bin)] << 4; - } -} - - -/******************************************************************************* - Functionname: fillHybridDelayLine - ******************************************************************************* - - Description: The delay line of the hybrid filter is filled and copied from - left to right. - - Return: none - -*******************************************************************************/ - -void -fillHybridDelayLine( FIXP_DBL **fixpQmfReal, /*!< Qmf real Values */ - FIXP_DBL **fixpQmfImag, /*!< Qmf imag Values */ - FIXP_DBL fixpHybridLeftR[12], /*!< Hybrid real Values left channel */ - FIXP_DBL fixpHybridLeftI[12], /*!< Hybrid imag Values left channel */ - FIXP_DBL fixpHybridRightR[12], /*!< Hybrid real Values right channel */ - FIXP_DBL fixpHybridRightI[12], /*!< Hybrid imag Values right channel */ - HANDLE_HYBRID hHybrid ) -{ - int i; - - for (i = 0; i < HYBRID_FILTER_DELAY; i++) { - slotBasedHybridAnalysis ( fixpQmfReal[i], - fixpQmfReal[i], - fixpHybridLeftR, - fixpHybridLeftI, - hHybrid ); - } - - FDKmemcpy(fixpHybridRightR, fixpHybridLeftR, sizeof(FIXP_DBL)*NO_SUB_QMF_CHANNELS); - FDKmemcpy(fixpHybridRightI, fixpHybridLeftI, sizeof(FIXP_DBL)*NO_SUB_QMF_CHANNELS); -} - - -/******************************************************************************* - Functionname: slotBasedHybridAnalysis - ******************************************************************************* - - Description: The lower QMF subbands are further split to provide better - frequency resolution for PS processing. - - Return: none - -*******************************************************************************/ - - -void -slotBasedHybridAnalysis ( FIXP_DBL *fixpQmfReal, /*!< Qmf real Values */ - FIXP_DBL *fixpQmfImag, /*!< Qmf imag Values */ - - FIXP_DBL fixpHybridReal[12], /*!< Hybrid real Values */ - FIXP_DBL fixpHybridImag[12], /*!< Hybrid imag Values */ - - HANDLE_HYBRID hHybrid) -{ - int k, band; - HYBRID_RES hybridRes; - int chOffset = 0; - - C_ALLOC_SCRATCH_START(pTempRealSlot, FIXP_DBL, 4*HYBRID_FILTER_LENGTH); - - FIXP_DBL *pTempImagSlot = pTempRealSlot + HYBRID_FILTER_LENGTH; - FIXP_DBL *pWorkRealSlot = pTempImagSlot + HYBRID_FILTER_LENGTH; - FIXP_DBL *pWorkImagSlot = pWorkRealSlot + HYBRID_FILTER_LENGTH; - - /*! - Hybrid filtering is applied to the first hHybrid->nQmfBands QMF bands (3 when 10 or 20 stereo bands - are used, 5 when 34 stereo bands are used). For the remaining QMF bands a delay would be necessary. - But there is no need to implement a delay because there is a look-ahead of HYBRID_FILTER_DELAY = 6 - QMF samples in the low-band buffer. - */ - - for(band = 0; band < hHybrid->nQmfBands; band++) { - - /* get hybrid resolution per qmf band */ - /* in case of baseline ps 10/20 band stereo mode : */ - /* */ - /* qmfBand[0] : 8 ( HYBRID_8_CPLX ) */ - /* qmfBand[1] : 2 ( HYBRID_2_REAL ) */ - /* qmfBand[2] : 2 ( HYBRID_2_REAL ) */ - /* */ - /* (split the 3 lower qmf band to 12 hybrid bands) */ - - hybridRes = (HYBRID_RES)hHybrid->pResolution[band]; - - FDKmemcpy(pWorkRealSlot, hHybrid->mQmfBufferRealSlot[band], hHybrid->qmfBufferMove * sizeof(FIXP_DBL)); - FDKmemcpy(pWorkImagSlot, hHybrid->mQmfBufferImagSlot[band], hHybrid->qmfBufferMove * sizeof(FIXP_DBL)); - - pWorkRealSlot[hHybrid->qmfBufferMove] = fixpQmfReal[band]; - pWorkImagSlot[hHybrid->qmfBufferMove] = fixpQmfImag[band]; - - FDKmemcpy(hHybrid->mQmfBufferRealSlot[band], pWorkRealSlot + 1, hHybrid->qmfBufferMove * sizeof(FIXP_DBL)); - FDKmemcpy(hHybrid->mQmfBufferImagSlot[band], pWorkImagSlot + 1, hHybrid->qmfBufferMove * sizeof(FIXP_DBL)); - - if (fixpQmfReal) { - - /* actual filtering only if output signal requested */ - switch( hybridRes ) { - - /* HYBRID_2_REAL & HYBRID_8_CPLX are only needful for baseline ps */ - case HYBRID_2_REAL: - - slotBasedDualChannelFiltering( pWorkRealSlot, - pWorkImagSlot, - pTempRealSlot, - pTempImagSlot); - break; - - case HYBRID_8_CPLX: - - slotBasedEightChannelFiltering( pWorkRealSlot, - pWorkImagSlot, - pTempRealSlot, - pTempImagSlot); - break; - - default: - FDK_ASSERT(0); - } - - for(k = 0; k < (SCHAR)hybridRes; k++) { - fixpHybridReal [chOffset + k] = pTempRealSlot[k]; - fixpHybridImag [chOffset + k] = pTempImagSlot[k]; - } - chOffset += hybridRes; - } /* if (mHybridReal) */ - } - - /* group hybrid channels 3+4 -> 3 and 2+5 -> 2 */ - fixpHybridReal[3] += fixpHybridReal[4]; - fixpHybridImag[3] += fixpHybridImag[4]; - fixpHybridReal[4] = (FIXP_DBL)0; - fixpHybridImag[4] = (FIXP_DBL)0; - - fixpHybridReal[2] += fixpHybridReal[5]; - fixpHybridImag[2] += fixpHybridImag[5]; - fixpHybridReal[5] = (FIXP_DBL)0; - fixpHybridImag[5] = (FIXP_DBL)0; - - /* free memory on scratch */ - C_ALLOC_SCRATCH_END(pTempRealSlot, FIXP_DBL, 4*HYBRID_FILTER_LENGTH); - -} - - -/******************************************************************************* - Functionname: slotBasedHybridSynthesis - ******************************************************************************* - - Description: The coefficients offering higher resolution for the lower QMF - channel are simply added prior to the synthesis with the 54 - subbands QMF. - - Arguments: - - Return: none - -*******************************************************************************/ - -/*! <pre> - l,r0(n) ---\ - l,r1(n) ---- + --\ - l,r2(n) ---/ \ - + --> F0(w) - l,r3(n) ---\ / - l,r4(n) ---- + --/ - l,r5(n) ---/ - - - l,r6(n) ---\ - + ---------> F1(w) - l,r7(n) ---/ - - - l,r8(n) ---\ - + ---------> F2(w) - l,r9(n) ---/ - - </pre> - Hybrid QMF synthesis filterbank for the 10 and 20 stereo-bands configurations. The - coefficients offering higher resolution for the lower QMF channel are simply added - prior to the synthesis with the 54 subbands QMF. - - [see ISO/IEC 14496-3:2001/FDAM 2:2004(E) - Page 52] -*/ - - -void -slotBasedHybridSynthesis ( FIXP_DBL *fixpHybridReal, /*!< Hybrid real Values */ - FIXP_DBL *fixpHybridImag, /*!< Hybrid imag Values */ - FIXP_DBL *fixpQmfReal, /*!< Qmf real Values */ - FIXP_DBL *fixpQmfImag, /*!< Qmf imag Values */ - HANDLE_HYBRID hHybrid ) /*!< Handle to HYBRID struct. */ -{ - int k, band; - - HYBRID_RES hybridRes; - int chOffset = 0; - - for(band = 0; band < hHybrid->nQmfBands; band++) { - - FIXP_DBL qmfReal = FL2FXCONST_DBL(0.f); - FIXP_DBL qmfImag = FL2FXCONST_DBL(0.f); - hybridRes = (HYBRID_RES)hHybrid->pResolution[band]; - - for(k = 0; k < (SCHAR)hybridRes; k++) { - qmfReal += fixpHybridReal[chOffset + k]; - qmfImag += fixpHybridImag[chOffset + k]; - } - - fixpQmfReal[band] = qmfReal; - fixpQmfImag[band] = qmfImag; - - chOffset += hybridRes; - } -} - - - diff --git a/libSBRdec/src/psdec_hybrid.h b/libSBRdec/src/psdec_hybrid.h deleted file mode 100644 index fcf9e3e..0000000 --- a/libSBRdec/src/psdec_hybrid.h +++ /dev/null @@ -1,165 +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 ------------------------------------------------------------------------------------------------------------ */ - -#ifndef __HYBRID_H -#define __HYBRID_H - -#include "sbrdecoder.h" - - -#define HYBRID_FILTER_LENGTH 13 -#define HYBRID_FILTER_DELAY 6 - - -#define FAST_FILTER2 -#define FAST_FILTER4 -#define FAST_FILTER8 -#define FAST_FILTER12 - -#define FFT_IDX_R(a) (2*a) -#define FFT_IDX_I(a) (2*a+1) - -#define FIXP_FFT_IDX_R(a) (a<<1) -#define FIXP_FFT_IDX_I(a) ((a<<1) + 1) - - -typedef enum { - - HYBRID_2_REAL = 2, - HYBRID_4_CPLX = 4, - HYBRID_8_CPLX = 8, - HYBRID_12_CPLX = 12 - -} HYBRID_RES; - -typedef struct -{ - SCHAR nQmfBands; - SCHAR frameSize; - SCHAR qmfBufferMove; - - UCHAR pResolution[3]; - - FIXP_DBL mQmfBufferRealSlot[3][HYBRID_FILTER_LENGTH]; /**< Stores old Qmf samples. */ - FIXP_DBL mQmfBufferImagSlot[3][HYBRID_FILTER_LENGTH]; - SCHAR sf_mQmfBuffer; - -} HYBRID; - -typedef HYBRID *HANDLE_HYBRID; - -void -fillHybridDelayLine( FIXP_DBL **fixpQmfReal, - FIXP_DBL **fixpQmfImag, - FIXP_DBL fixpHybridLeftR[12], - FIXP_DBL fixpHybridLeftI[12], - FIXP_DBL fixpHybridRightR[12], - FIXP_DBL fixpHybridRightI[12], - HANDLE_HYBRID hHybrid ); - -void -slotBasedHybridAnalysis ( FIXP_DBL *fixpQmfReal, - FIXP_DBL *fixpQmfImag, - - FIXP_DBL *fixpHybridReal, - FIXP_DBL *fixpHybridImag, - - HANDLE_HYBRID hHybrid); - - -void -slotBasedHybridSynthesis ( FIXP_DBL *fixpHybridReal, - FIXP_DBL *fixpHybridImag, - - FIXP_DBL *fixpQmfReal, - FIXP_DBL *fixpQmfImag, - - HANDLE_HYBRID hHybrid ); - -SBR_ERROR InitHybridFilterBank ( HANDLE_HYBRID hHybrid, - SCHAR frameSize, - SCHAR noBands, - const UCHAR *pResolution ); - - -#endif /* __HYBRID_H */ diff --git a/libSBRdec/src/psdecrom_drm.cpp b/libSBRdec/src/psdecrom_drm.cpp new file mode 100644 index 0000000..2033a83 --- /dev/null +++ b/libSBRdec/src/psdecrom_drm.cpp @@ -0,0 +1,108 @@ +/* ----------------------------------------------------------------------------- +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 rom tables for Drm parametric stereo decoder +*/ + +#include "psdec_drm.h" diff --git a/libSBRdec/src/pvc_dec.cpp b/libSBRdec/src/pvc_dec.cpp new file mode 100644 index 0000000..b477122 --- /dev/null +++ b/libSBRdec/src/pvc_dec.cpp @@ -0,0 +1,683 @@ +/* ----------------------------------------------------------------------------- +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): Matthias Hildenbrand + + Description: Decode Predictive Vector Coding Data + +*******************************************************************************/ + +#include "pvc_dec.h" + +/* PVC interal definitions */ +#define PVC_DIVMODE_BITS 3 +#define PVC_NSMODE_BITS 1 +#define PVC_REUSEPVCID_BITS 1 +#define PVC_PVCID_BITS 7 +#define PVC_GRIDINFO_BITS 1 +#define PVC_NQMFBAND 64 +#define PVC_NBLOW 3 /* max. number of grouped QMF subbands below SBR range */ + +#define PVC_NTAB1 3 +#define PVC_NTAB2 128 +#define PVC_ID_NBIT 7 + +/* Exponent of pPvcStaticData->Esg and predictedEsg in dB domain. + max(Esg) = 10*log10(2^15*2^15) = 90.30; + min(Esg) = 10*log10(0.1) = -10 + max of predicted Esg seems to be higher than 90dB but 7 Bit should be enough. +*/ +#define PVC_ESG_EXP 7 + +#define LOG10FAC 0.752574989159953f /* == 10/log2(10) * 2^-2 */ +#define LOG10FAC_INV 0.664385618977472f /* == log2(10)/10 * 2^1 */ + +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const FIXP_SGL pvc_SC_16[] = { + FX_DBL2FXCONST_SGL(0x14413695), FX_DBL2FXCONST_SGL(0x1434b6cb), + FX_DBL2FXCONST_SGL(0x140f27c7), FX_DBL2FXCONST_SGL(0x13d0591d), + FX_DBL2FXCONST_SGL(0x1377f502), FX_DBL2FXCONST_SGL(0x130577d6), + FX_DBL2FXCONST_SGL(0x12782266), FX_DBL2FXCONST_SGL(0x11cee459), + FX_DBL2FXCONST_SGL(0x11083a2a), FX_DBL2FXCONST_SGL(0x1021f5e9), + FX_DBL2FXCONST_SGL(0x0f18e17c), FX_DBL2FXCONST_SGL(0x0de814ca), + FX_DBL2FXCONST_SGL(0x0c87a568), FX_DBL2FXCONST_SGL(0x0ae9b167), + FX_DBL2FXCONST_SGL(0x08f24226), FX_DBL2FXCONST_SGL(0x06575ed5), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const FIXP_SGL pvc_SC_12[] = { + FX_DBL2FXCONST_SGL(0x1aba6b3e), FX_DBL2FXCONST_SGL(0x1a9d164e), + FX_DBL2FXCONST_SGL(0x1a44d56d), FX_DBL2FXCONST_SGL(0x19b0d742), + FX_DBL2FXCONST_SGL(0x18df969a), FX_DBL2FXCONST_SGL(0x17ce91a0), + FX_DBL2FXCONST_SGL(0x1679c3fa), FX_DBL2FXCONST_SGL(0x14daabfc), + FX_DBL2FXCONST_SGL(0x12e65221), FX_DBL2FXCONST_SGL(0x1088d125), + FX_DBL2FXCONST_SGL(0x0d9907b3), FX_DBL2FXCONST_SGL(0x09a80e9d), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const FIXP_SGL pvc_SC_4[] = { + FX_DBL2FXCONST_SGL(0x4ad6ab0f), + FX_DBL2FXCONST_SGL(0x47ef0dbe), + FX_DBL2FXCONST_SGL(0x3eee7496), + FX_DBL2FXCONST_SGL(0x2e4bd29d), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const FIXP_SGL pvc_SC_3[] = { + FX_DBL2FXCONST_SGL(0x610dc761), + FX_DBL2FXCONST_SGL(0x5a519a3d), + FX_DBL2FXCONST_SGL(0x44a09e62), +}; + +static const UCHAR g_3a_pvcTab1_mode1[PVC_NTAB1][PVC_NBLOW][PVC_NBHIGH_MODE1] = + {{{0x4F, 0x5B, 0x57, 0x52, 0x4D, 0x65, 0x45, 0x57}, + {0xF3, 0x0F, 0x18, 0x20, 0x19, 0x4F, 0x3D, 0x23}, + {0x78, 0x57, 0x55, 0x50, 0x50, 0x20, 0x36, 0x37}}, + {{0x4C, 0x5F, 0x53, 0x37, 0x1E, 0xFD, 0x15, 0x0A}, + {0x05, 0x0E, 0x28, 0x41, 0x48, 0x6E, 0x54, 0x5B}, + {0x59, 0x47, 0x40, 0x40, 0x3D, 0x33, 0x3F, 0x39}}, + {{0x47, 0x5F, 0x57, 0x34, 0x3C, 0x2E, 0x2E, 0x31}, + {0xFA, 0x13, 0x23, 0x4E, 0x44, 0x7C, 0x34, 0x38}, + {0x63, 0x43, 0x41, 0x3D, 0x35, 0x19, 0x3D, 0x33}}}; + +static const UCHAR g_2a_pvcTab2_mode1[PVC_NTAB2][PVC_NBHIGH_MODE1] = { + {0xCB, 0xD1, 0xCC, 0xD2, 0xE2, 0xEB, 0xE7, 0xE8}, + {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, + {0x84, 0x8C, 0x88, 0x83, 0x90, 0x93, 0x86, 0x80}, + {0xD7, 0xD8, 0xC0, 0xC7, 0xCF, 0xE5, 0xF1, 0xF6}, + {0xA5, 0xA6, 0xAA, 0xA8, 0xB0, 0xB1, 0xB8, 0xB8}, + {0xD7, 0xCB, 0xC1, 0xC3, 0xC5, 0xC9, 0xC9, 0xCE}, + {0xCA, 0xB5, 0xB8, 0xB3, 0xAC, 0xB6, 0xBB, 0xB8}, + {0xC1, 0xC4, 0xC3, 0xC5, 0xC6, 0xCA, 0xCA, 0xCB}, + {0xE0, 0xE1, 0xD8, 0xCD, 0xCB, 0xCB, 0xCE, 0xCC}, + {0xDB, 0xE1, 0xDF, 0xDB, 0xDC, 0xD9, 0xD9, 0xD6}, + {0xE0, 0xDE, 0xDD, 0xDD, 0xE0, 0xE3, 0xE5, 0xE6}, + {0xCA, 0xD2, 0xCD, 0xCE, 0xD5, 0xDB, 0xD9, 0xDB}, + {0xD2, 0xE0, 0xDB, 0xD5, 0xDB, 0xDE, 0xE3, 0xE1}, + {0xE5, 0xDB, 0xD0, 0xD2, 0xD8, 0xDD, 0xDB, 0xDD}, + {0xC0, 0xB5, 0xBF, 0xDD, 0xE3, 0xDC, 0xDC, 0xE4}, + {0xDB, 0xCE, 0xC6, 0xCF, 0xCF, 0xD1, 0xD3, 0xD4}, + {0xC9, 0xD7, 0xDA, 0xE2, 0xE9, 0xE7, 0xDF, 0xDC}, + {0x0A, 0x07, 0x0A, 0x08, 0x19, 0x24, 0x1F, 0x22}, + {0x1E, 0x1F, 0x11, 0x0E, 0x22, 0x2D, 0x33, 0x32}, + {0xF0, 0xDA, 0xDC, 0x18, 0x1F, 0x19, 0x0A, 0x1E}, + {0x09, 0xF8, 0xE6, 0x05, 0x19, 0x11, 0x0E, 0x0B}, + {0x09, 0x10, 0x0E, 0xE6, 0xF4, 0x20, 0x22, 0xFA}, + {0xF2, 0xE5, 0xF8, 0x0E, 0x18, 0x15, 0x0D, 0x10}, + {0x15, 0x13, 0x16, 0x0A, 0x0D, 0x1F, 0x1D, 0x1B}, + {0xFA, 0xFF, 0xFE, 0xFF, 0x09, 0x11, 0x03, 0x0B}, + {0xFE, 0xFA, 0xF2, 0xF8, 0x0C, 0x1E, 0x11, 0x12}, + {0xFA, 0xF8, 0x0B, 0x17, 0x1D, 0x17, 0x0E, 0x16}, + {0x00, 0xF3, 0xFD, 0x0A, 0x1C, 0x17, 0xFD, 0x08}, + {0xEA, 0xEA, 0x03, 0x12, 0x1E, 0x14, 0x09, 0x04}, + {0x02, 0xFE, 0x04, 0xFB, 0x0C, 0x0E, 0x07, 0x02}, + {0xF6, 0x02, 0x07, 0x0B, 0x17, 0x17, 0x01, 0xFF}, + {0xF5, 0xFB, 0xFE, 0x04, 0x12, 0x14, 0x0C, 0x0D}, + {0x10, 0x10, 0x0E, 0x04, 0x07, 0x11, 0x0F, 0x13}, + {0x0C, 0x0F, 0xFB, 0xF2, 0x0A, 0x12, 0x09, 0x0D}, + {0x0D, 0x1D, 0xF1, 0xF4, 0x2A, 0x06, 0x3B, 0x32}, + {0xFC, 0x08, 0x06, 0x02, 0x0E, 0x17, 0x08, 0x0E}, + {0x07, 0x02, 0xEE, 0xEE, 0x2B, 0xF6, 0x23, 0x13}, + {0x04, 0x02, 0x05, 0x08, 0x0B, 0x0E, 0xFB, 0xFB}, + {0x00, 0x04, 0x10, 0x18, 0x22, 0x25, 0x1D, 0x1F}, + {0xFB, 0x0D, 0x07, 0x00, 0x0C, 0x0F, 0xFC, 0x02}, + {0x00, 0x00, 0x00, 0x01, 0x05, 0x07, 0x03, 0x05}, + {0x04, 0x05, 0x08, 0x13, 0xFF, 0xEB, 0x0C, 0x06}, + {0x05, 0x13, 0x0E, 0x0B, 0x12, 0x15, 0x09, 0x0A}, + {0x09, 0x03, 0x09, 0x05, 0x12, 0x16, 0x11, 0x12}, + {0x14, 0x1A, 0x06, 0x01, 0x10, 0x11, 0xFE, 0x02}, + {0x01, 0x0B, 0x0B, 0x0C, 0x18, 0x21, 0x10, 0x13}, + {0x12, 0x0D, 0x0A, 0x10, 0x1C, 0x1D, 0x0D, 0x10}, + {0x03, 0x09, 0x14, 0x15, 0x1B, 0x1A, 0x01, 0xFF}, + {0x08, 0x12, 0x13, 0x0E, 0x16, 0x1D, 0x14, 0x1B}, + {0x07, 0x15, 0x1C, 0x1B, 0x20, 0x21, 0x11, 0x0E}, + {0x12, 0x18, 0x19, 0x17, 0x20, 0x25, 0x1A, 0x1E}, + {0x0C, 0x1A, 0x1D, 0x22, 0x2F, 0x33, 0x27, 0x28}, + {0x0E, 0x1A, 0x17, 0x10, 0x0A, 0x0E, 0xFF, 0x06}, + {0x1A, 0x1C, 0x18, 0x14, 0x1A, 0x16, 0x0A, 0x0E}, + {0x1E, 0x27, 0x25, 0x26, 0x27, 0x2A, 0x21, 0x21}, + {0xF1, 0x0A, 0x16, 0x1C, 0x28, 0x25, 0x15, 0x19}, + {0x08, 0x12, 0x09, 0x08, 0x16, 0x17, 0xEF, 0xF6}, + {0x0C, 0x0B, 0x00, 0xFC, 0x04, 0x09, 0xFC, 0x03}, + {0xFB, 0xF1, 0xF8, 0x26, 0x24, 0x18, 0x1D, 0x20}, + {0xF9, 0x01, 0x0C, 0x0F, 0x07, 0x08, 0x06, 0x07}, + {0x07, 0x06, 0x08, 0x04, 0x07, 0x0D, 0x07, 0x09}, + {0xFE, 0x01, 0x06, 0x05, 0x13, 0x1B, 0x14, 0x19}, + {0x09, 0x0C, 0x0E, 0x01, 0x08, 0x05, 0xFB, 0xFD}, + {0x07, 0x06, 0x03, 0x0A, 0x16, 0x12, 0x04, 0x07}, + {0x04, 0x01, 0x00, 0x04, 0x1F, 0x20, 0x0E, 0x0A}, + {0x03, 0xFF, 0xF6, 0xFB, 0x15, 0x1A, 0x00, 0x03}, + {0xFC, 0x18, 0x0B, 0x2D, 0x35, 0x23, 0x12, 0x09}, + {0x02, 0xFE, 0x01, 0xFF, 0x0C, 0x11, 0x0D, 0x0F}, + {0xFA, 0xE9, 0xD9, 0xFF, 0x0D, 0x05, 0x0D, 0x10}, + {0xF1, 0xE0, 0xF0, 0x01, 0x06, 0x06, 0x06, 0x10}, + {0xE9, 0xD4, 0xD7, 0x0F, 0x14, 0x0B, 0x0D, 0x16}, + {0x00, 0xFF, 0xEE, 0xE5, 0xFF, 0x08, 0x02, 0xF9}, + {0xE0, 0xDA, 0xE5, 0xFE, 0x09, 0x02, 0xF9, 0x04}, + {0xE0, 0xE2, 0xF4, 0x09, 0x13, 0x0C, 0x0D, 0x09}, + {0xFC, 0x02, 0x04, 0xFF, 0x00, 0xFF, 0xF8, 0xF7}, + {0xFE, 0xFB, 0xED, 0xF2, 0xFE, 0xFE, 0x08, 0x0C}, + {0xF3, 0xEF, 0xD0, 0xE3, 0x05, 0x11, 0xFD, 0xFF}, + {0xFA, 0xEF, 0xEA, 0xFE, 0x0D, 0x0E, 0xFE, 0x02}, + {0xF7, 0xFB, 0xDB, 0xDF, 0x14, 0xDD, 0x07, 0xFE}, + {0xFE, 0x08, 0x00, 0xDB, 0xE5, 0x1A, 0x13, 0xED}, + {0xF9, 0xFE, 0xFF, 0xF4, 0xF3, 0x00, 0x05, 0x02}, + {0xEF, 0xDE, 0xD8, 0xEB, 0xEA, 0xF5, 0x0E, 0x19}, + {0xFB, 0xFC, 0xFA, 0xEC, 0xEB, 0xED, 0xEE, 0xE8}, + {0xEE, 0xFC, 0xFD, 0x00, 0x04, 0xFC, 0xF0, 0xF5}, + {0x00, 0xFA, 0xF4, 0xF1, 0xF5, 0xFA, 0xFB, 0xF9}, + {0xEB, 0xF0, 0xDF, 0xE3, 0xEF, 0x07, 0x02, 0x05}, + {0xF7, 0xF0, 0xE6, 0xE7, 0x06, 0x15, 0x06, 0x0C}, + {0xF1, 0xE4, 0xD8, 0xEA, 0x06, 0xF2, 0x07, 0x09}, + {0xFF, 0xFE, 0xFE, 0xF9, 0xFF, 0xFF, 0x02, 0xF9}, + {0xDD, 0xF4, 0xF0, 0xF1, 0xFF, 0xFF, 0xEA, 0xF1}, + {0xF0, 0xF1, 0xFD, 0x03, 0x03, 0xFE, 0x00, 0x05}, + {0xF1, 0xF6, 0xE0, 0xDF, 0xF5, 0x01, 0xF4, 0xF8}, + {0x02, 0x03, 0xE5, 0xDC, 0xE7, 0xFD, 0x02, 0x08}, + {0xEC, 0xF1, 0xF5, 0xEC, 0xF2, 0xF8, 0xF6, 0xEE}, + {0xF3, 0xF4, 0xF6, 0xF4, 0xF5, 0xF1, 0xE7, 0xEA}, + {0xF7, 0xF3, 0xEC, 0xEA, 0xEF, 0xF0, 0xEE, 0xF1}, + {0xEB, 0xF6, 0xFB, 0xFA, 0xEF, 0xF3, 0xF3, 0xF7}, + {0x01, 0x03, 0xF1, 0xF6, 0x05, 0xF8, 0xE1, 0xEB}, + {0xF5, 0xF6, 0xF6, 0xF4, 0xFB, 0xFB, 0xFF, 0x00}, + {0xF8, 0x01, 0xFB, 0xFA, 0xFF, 0x03, 0xFE, 0x04}, + {0x04, 0xFB, 0x03, 0xFD, 0xF5, 0xF7, 0xF6, 0xFB}, + {0x06, 0x09, 0xFB, 0xF4, 0xF9, 0xFA, 0xFC, 0xFF}, + {0xF5, 0xF6, 0xF1, 0xEE, 0xF5, 0xF8, 0xF5, 0xF9}, + {0xF5, 0xF9, 0xFA, 0xFC, 0x07, 0x09, 0x01, 0xFB}, + {0xD7, 0xE9, 0xE8, 0xEC, 0x00, 0x0C, 0xFE, 0xF1}, + {0xEC, 0x04, 0xE9, 0xDF, 0x03, 0xE8, 0x00, 0xFA}, + {0xE6, 0xE2, 0xFF, 0x0A, 0x13, 0x01, 0x00, 0xF7}, + {0xF1, 0xFA, 0xF7, 0xF5, 0x01, 0x06, 0x05, 0x0A}, + {0xF6, 0xF6, 0xFC, 0xF6, 0xE8, 0x11, 0xF2, 0xFE}, + {0xFE, 0x08, 0x05, 0x12, 0xFD, 0xD0, 0x0E, 0x07}, + {0xF1, 0xFE, 0xF7, 0xF2, 0xFB, 0x02, 0xFA, 0xF8}, + {0xF4, 0xEA, 0xEC, 0xF3, 0xFE, 0x01, 0xF7, 0xF6}, + {0xFF, 0xFA, 0xFB, 0xF9, 0xFF, 0x01, 0x04, 0x03}, + {0x00, 0xF9, 0xF4, 0xFC, 0x05, 0xFC, 0xF7, 0xFB}, + {0xF8, 0xFF, 0xEF, 0xEC, 0xFB, 0x04, 0xF8, 0x03}, + {0xEB, 0xF1, 0xED, 0xF4, 0x02, 0x0E, 0x0B, 0x04}, + {0xF7, 0x01, 0xF8, 0xF4, 0xF8, 0xEF, 0xF8, 0x04}, + {0xEB, 0xF0, 0xF7, 0xFC, 0x10, 0x0D, 0xF8, 0xF8}, + {0xE8, 0xFE, 0xEE, 0xE8, 0xED, 0xF7, 0xF5, 0xF8}, + {0xED, 0xEB, 0xE9, 0xEA, 0xF2, 0xF5, 0xF4, 0xF9}, + {0xEA, 0xF2, 0xEF, 0xEE, 0xF9, 0xFE, 0xFD, 0x02}, + {0xFA, 0xFD, 0x02, 0x0D, 0xFA, 0xE4, 0x0F, 0x01}, + {0xFF, 0x08, 0x05, 0xF6, 0xF7, 0xFB, 0xF1, 0xF1}, + {0xF4, 0xEC, 0xEE, 0xF6, 0xEE, 0xEE, 0xF8, 0x06}, + {0xE8, 0xFA, 0xF8, 0xE8, 0xF8, 0xE9, 0xEE, 0xF9}, + {0xE5, 0xE9, 0xF0, 0x00, 0x00, 0xEF, 0xF3, 0xF8}, + {0xF7, 0xFB, 0xFB, 0xF7, 0xF9, 0xF9, 0xF5, 0xF0}, + {0xFD, 0xFF, 0xF2, 0xEE, 0xF2, 0xF5, 0xF1, 0xF3}}; + +static const UCHAR g_3a_pvcTab1_mode2[PVC_NTAB1][PVC_NBLOW][PVC_NBHIGH_MODE2] = + {{{0x11, 0x27, 0x0F, 0xFD, 0x04, 0xFC}, + {0x00, 0xBE, 0xE3, 0xF4, 0xDB, 0xF0}, + {0x09, 0x1E, 0x18, 0x1A, 0x21, 0x1B}}, + {{0x16, 0x28, 0x2B, 0x29, 0x25, 0x32}, + {0xF2, 0xE9, 0xE4, 0xE5, 0xE2, 0xD4}, + {0x0E, 0x0B, 0x0C, 0x0D, 0x0D, 0x0E}}, + {{0x2E, 0x3C, 0x20, 0x16, 0x1B, 0x1A}, + {0xE4, 0xC6, 0xE5, 0xF4, 0xDC, 0xDC}, + {0x0F, 0x1B, 0x18, 0x14, 0x1E, 0x1A}}}; + +static const UCHAR g_2a_pvcTab2_mode2[PVC_NTAB2][PVC_NBHIGH_MODE2] = { + {0x26, 0x25, 0x11, 0x0C, 0xFA, 0x15}, {0x1B, 0x18, 0x11, 0x0E, 0x0E, 0x0E}, + {0x12, 0x10, 0x10, 0x10, 0x11, 0x10}, {0x1E, 0x24, 0x19, 0x15, 0x14, 0x12}, + {0x24, 0x16, 0x12, 0x13, 0x15, 0x1C}, {0xEA, 0xED, 0xEB, 0xEA, 0xEC, 0xEB}, + {0xFC, 0xFD, 0xFD, 0xFC, 0xFE, 0xFE}, {0x0F, 0x0C, 0x0B, 0x0A, 0x0B, 0x0B}, + {0x22, 0x0B, 0x16, 0x18, 0x13, 0x19}, {0x1C, 0x14, 0x1D, 0x20, 0x19, 0x1A}, + {0x10, 0x08, 0x00, 0xFF, 0x02, 0x05}, {0x06, 0x07, 0x05, 0x03, 0x05, 0x04}, + {0x2A, 0x1F, 0x12, 0x12, 0x11, 0x18}, {0x19, 0x19, 0x02, 0x04, 0x00, 0x04}, + {0x18, 0x17, 0x17, 0x15, 0x16, 0x15}, {0x21, 0x1E, 0x1B, 0x19, 0x1C, 0x1B}, + {0x3C, 0x35, 0x20, 0x1D, 0x30, 0x34}, {0x3A, 0x1F, 0x37, 0x38, 0x33, 0x31}, + {0x37, 0x34, 0x25, 0x27, 0x35, 0x34}, {0x34, 0x2E, 0x32, 0x31, 0x34, 0x31}, + {0x36, 0x33, 0x2F, 0x2F, 0x32, 0x2F}, {0x35, 0x20, 0x2F, 0x32, 0x2F, 0x2C}, + {0x2E, 0x2B, 0x2F, 0x34, 0x36, 0x30}, {0x3F, 0x39, 0x30, 0x28, 0x29, 0x29}, + {0x3C, 0x30, 0x32, 0x37, 0x39, 0x36}, {0x37, 0x36, 0x30, 0x2B, 0x26, 0x24}, + {0x44, 0x38, 0x2F, 0x2D, 0x2D, 0x2D}, {0x38, 0x2B, 0x2C, 0x2C, 0x30, 0x2D}, + {0x37, 0x36, 0x2F, 0x23, 0x2D, 0x32}, {0x3C, 0x39, 0x29, 0x2E, 0x38, 0x37}, + {0x3B, 0x3A, 0x35, 0x32, 0x31, 0x2D}, {0x32, 0x31, 0x2F, 0x2C, 0x2D, 0x28}, + {0x2C, 0x31, 0x32, 0x30, 0x32, 0x2D}, {0x35, 0x34, 0x34, 0x34, 0x35, 0x33}, + {0x34, 0x38, 0x3B, 0x3C, 0x3E, 0x3A}, {0x3E, 0x3C, 0x3B, 0x3A, 0x3C, 0x39}, + {0x3D, 0x41, 0x46, 0x41, 0x3D, 0x38}, {0x44, 0x41, 0x40, 0x3E, 0x3F, 0x3A}, + {0x47, 0x47, 0x47, 0x42, 0x44, 0x40}, {0x4C, 0x4A, 0x4A, 0x46, 0x49, 0x45}, + {0x53, 0x52, 0x52, 0x4C, 0x4E, 0x49}, {0x41, 0x3D, 0x39, 0x2C, 0x2E, 0x2E}, + {0x2D, 0x37, 0x36, 0x30, 0x28, 0x36}, {0x3B, 0x32, 0x2E, 0x2D, 0x2D, 0x29}, + {0x40, 0x39, 0x36, 0x35, 0x36, 0x32}, {0x30, 0x2D, 0x2D, 0x2E, 0x31, 0x30}, + {0x38, 0x3D, 0x3B, 0x37, 0x35, 0x34}, {0x44, 0x3D, 0x3C, 0x38, 0x37, 0x33}, + {0x3A, 0x36, 0x37, 0x37, 0x39, 0x36}, {0x32, 0x36, 0x37, 0x30, 0x2E, 0x2A}, + {0x3C, 0x33, 0x33, 0x31, 0x33, 0x30}, {0x30, 0x31, 0x36, 0x37, 0x38, 0x34}, + {0x26, 0x27, 0x2E, 0x29, 0x1C, 0x16}, {0x14, 0x15, 0x1F, 0x17, 0x15, 0x1C}, + {0x38, 0x2D, 0x18, 0x13, 0x1E, 0x2B}, {0x30, 0x22, 0x17, 0x1A, 0x26, 0x2B}, + {0x24, 0x20, 0x1F, 0x10, 0x0C, 0x11}, {0x27, 0x1F, 0x13, 0x17, 0x24, 0x2A}, + {0x2F, 0x13, 0x18, 0x13, 0x2A, 0x32}, {0x31, 0x1E, 0x1E, 0x1E, 0x21, 0x28}, + {0x2A, 0x12, 0x19, 0x17, 0x16, 0x24}, {0x27, 0x0F, 0x16, 0x1D, 0x17, 0x1C}, + {0x2F, 0x26, 0x25, 0x22, 0x20, 0x22}, {0x1E, 0x1B, 0x1E, 0x18, 0x1E, 0x24}, + {0x31, 0x26, 0x0E, 0x15, 0x15, 0x25}, {0x2D, 0x22, 0x1E, 0x14, 0x10, 0x22}, + {0x25, 0x1B, 0x18, 0x11, 0x13, 0x1F}, {0x2F, 0x1B, 0x13, 0x1B, 0x18, 0x22}, + {0x21, 0x24, 0x1D, 0x1C, 0x1D, 0x1B}, {0x23, 0x1E, 0x28, 0x29, 0x27, 0x25}, + {0x2E, 0x2A, 0x1D, 0x17, 0x26, 0x2D}, {0x31, 0x2C, 0x1A, 0x0E, 0x1A, 0x24}, + {0x26, 0x16, 0x20, 0x1D, 0x14, 0x1E}, {0x29, 0x20, 0x1B, 0x1B, 0x17, 0x17}, + {0x1D, 0x06, 0x1A, 0x1E, 0x1B, 0x1D}, {0x2B, 0x23, 0x1F, 0x1F, 0x1D, 0x1C}, + {0x27, 0x1A, 0x0C, 0x0E, 0x0F, 0x1A}, {0x29, 0x1D, 0x1E, 0x22, 0x22, 0x24}, + {0x20, 0x21, 0x1B, 0x18, 0x13, 0x21}, {0x27, 0x0E, 0x10, 0x14, 0x10, 0x1A}, + {0x26, 0x24, 0x25, 0x25, 0x26, 0x28}, {0x1A, 0x24, 0x25, 0x29, 0x26, 0x24}, + {0x1D, 0x1D, 0x15, 0x12, 0x0F, 0x18}, {0x1E, 0x14, 0x13, 0x12, 0x14, 0x18}, + {0x16, 0x13, 0x13, 0x1A, 0x1B, 0x1D}, {0x20, 0x27, 0x22, 0x24, 0x1A, 0x19}, + {0x1F, 0x17, 0x19, 0x18, 0x17, 0x18}, {0x20, 0x1B, 0x1C, 0x1C, 0x1B, 0x1A}, + {0x23, 0x19, 0x1D, 0x1F, 0x1E, 0x21}, {0x26, 0x1F, 0x1D, 0x1B, 0x19, 0x1A}, + {0x23, 0x1E, 0x1F, 0x20, 0x1F, 0x1E}, {0x29, 0x20, 0x22, 0x20, 0x20, 0x1F}, + {0x26, 0x23, 0x21, 0x22, 0x23, 0x23}, {0x29, 0x1F, 0x24, 0x25, 0x26, 0x29}, + {0x2B, 0x22, 0x25, 0x27, 0x23, 0x21}, {0x29, 0x21, 0x19, 0x0E, 0x22, 0x2D}, + {0x32, 0x29, 0x1F, 0x1C, 0x1B, 0x21}, {0x1E, 0x1A, 0x1E, 0x24, 0x25, 0x25}, + {0x24, 0x1D, 0x21, 0x22, 0x22, 0x25}, {0x2C, 0x25, 0x21, 0x22, 0x23, 0x25}, + {0x24, 0x1E, 0x21, 0x26, 0x2B, 0x2C}, {0x28, 0x24, 0x1B, 0x1F, 0x28, 0x2D}, + {0x23, 0x13, 0x16, 0x22, 0x22, 0x29}, {0x1B, 0x23, 0x1C, 0x20, 0x14, 0x0D}, + {0x1E, 0x16, 0x1A, 0x1E, 0x1C, 0x1D}, {0x2B, 0x1C, 0x1D, 0x20, 0x1B, 0x1C}, + {0x1C, 0x1B, 0x23, 0x1F, 0x19, 0x1E}, {0x21, 0x23, 0x26, 0x20, 0x20, 0x22}, + {0x1D, 0x0B, 0x19, 0x1E, 0x11, 0x19}, {0x18, 0x17, 0x16, 0x17, 0x14, 0x16}, + {0x16, 0x19, 0x1C, 0x20, 0x21, 0x22}, {0x30, 0x1E, 0x22, 0x24, 0x25, 0x26}, + {0x1B, 0x1F, 0x17, 0x1D, 0x1E, 0x21}, {0x32, 0x2B, 0x27, 0x1F, 0x1B, 0x1A}, + {0x28, 0x20, 0x1A, 0x1B, 0x1F, 0x23}, {0x32, 0x21, 0x20, 0x21, 0x1D, 0x1F}, + {0x22, 0x18, 0x12, 0x15, 0x1B, 0x20}, {0x27, 0x27, 0x2A, 0x24, 0x21, 0x21}, + {0x1E, 0x0F, 0x0D, 0x1A, 0x1D, 0x23}, {0x28, 0x25, 0x27, 0x21, 0x17, 0x25}, + {0x2B, 0x27, 0x23, 0x19, 0x13, 0x14}, {0x25, 0x2B, 0x22, 0x22, 0x20, 0x21}, + {0x27, 0x1B, 0x16, 0x17, 0x0F, 0x15}, {0x29, 0x26, 0x23, 0x15, 0x1E, 0x28}, + {0x24, 0x1C, 0x19, 0x1A, 0x18, 0x19}, {0x2D, 0x15, 0x27, 0x2B, 0x24, 0x23}, + {0x2C, 0x12, 0x1F, 0x23, 0x1F, 0x20}, {0x25, 0x0F, 0x22, 0x27, 0x1F, 0x21}}; + +static const UCHAR g_a_pvcTab1_dp_mode1[PVC_NTAB1 - 1] = {17, 68}; +static const UCHAR g_a_pvcTab1_dp_mode2[PVC_NTAB1 - 1] = {16, 52}; +/* fractional exponent which corresponds to Q representation value */ +static const SCHAR g_a_scalingCoef_mode1[PVC_NBLOW + 1] = { + -1, -1, 0, 6}; /* { 8, 8, 7, 1 }; Q scaling */ +static const SCHAR g_a_scalingCoef_mode2[PVC_NBLOW + 1] = { + 0, 0, 1, 7}; /* { 7, 7, 6, 0 }; Q scaling */ + +int pvcInitFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, const UCHAR pvcMode, + const UCHAR ns, const int RATE, const int kx, + const int pvcBorder0, const UCHAR *pPvcID) { + int lbw, hbw, i, temp; + pPvcDynamicData->pvc_mode = pvcMode; + pPvcDynamicData->kx = kx; + pPvcDynamicData->RATE = RATE; + + switch (pvcMode) { + case 0: + /* legacy SBR, nothing to do */ + return 0; + case 1: + pPvcDynamicData->nbHigh = 8; + pPvcDynamicData->pPVCTab1 = (const UCHAR *)g_3a_pvcTab1_mode1; + pPvcDynamicData->pPVCTab2 = (const UCHAR *)g_2a_pvcTab2_mode1; + pPvcDynamicData->pPVCTab1_dp = g_a_pvcTab1_dp_mode1; + pPvcDynamicData->pScalingCoef = g_a_scalingCoef_mode1; + hbw = 8 / RATE; + break; + case 2: + pPvcDynamicData->nbHigh = 6; + pPvcDynamicData->pPVCTab1 = (const UCHAR *)g_3a_pvcTab1_mode2; + pPvcDynamicData->pPVCTab2 = (const UCHAR *)g_2a_pvcTab2_mode2; + pPvcDynamicData->pPVCTab1_dp = g_a_pvcTab1_dp_mode2; + pPvcDynamicData->pScalingCoef = g_a_scalingCoef_mode2; + hbw = 12 / RATE; + break; + default: + /* invalid pvcMode */ + return 1; + } + + pPvcDynamicData->pvcBorder0 = pvcBorder0; + UCHAR pvcBorder0_last = pPvcStaticData->pvcBorder0; + pPvcStaticData->pvcBorder0 = pvcBorder0; + pPvcDynamicData->pPvcID = pPvcID; + + pPvcDynamicData->ns = ns; + switch (ns) { + case 16: + pPvcDynamicData->pSCcoeffs = pvc_SC_16; + break; + case 12: + pPvcDynamicData->pSCcoeffs = pvc_SC_12; + break; + case 4: + pPvcDynamicData->pSCcoeffs = pvc_SC_4; + break; + case 3: + pPvcDynamicData->pSCcoeffs = pvc_SC_3; + break; + default: + return 1; + } + + /* in the lower part of Esg-array there are previous values of Esg (from last + call to this function In case of an previous legay-SBR frame, or if there + was a change in cross-over FQ the value of first PVC SBR timeslot is + propagated to prev-values in order to have reasonable values for + smooth-filtering + */ + if ((pPvcStaticData->pvc_mode_last == 0) || (pPvcStaticData->kx_last != kx)) { + pPvcDynamicData->pastEsgSlotsAvail = 0; + } else { + pPvcDynamicData->pastEsgSlotsAvail = PVC_NS_MAX - pvcBorder0_last; + } + + lbw = 8 / RATE; + + temp = kx; + for (i = PVC_NBLOW; i >= 0; i--) { + pPvcDynamicData->sg_offset_low[i] = temp; + temp -= lbw; + } + + temp = 0; + for (i = 0; i <= pPvcDynamicData->nbHigh; i++) { + pPvcDynamicData->sg_offset_high_kx[i] = temp; + temp += hbw; + } + + return 0; +} + +/* call if pvcMode = 1,2 */ +void pvcDecodeFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, FIXP_DBL **qmfBufferReal, + FIXP_DBL **qmfBufferImag, const int overlap, + const int qmfExponentOverlap, + const int qmfExponentCurrent) { + int t; + FIXP_DBL *predictedEsgSlot; + int RATE = pPvcDynamicData->RATE; + int pvcBorder0 = pPvcDynamicData->pvcBorder0; + + for (t = pvcBorder0; t < PVC_NTIMESLOT; t++) { + int *pPredEsg_exp = &pPvcDynamicData->predEsg_exp[t]; + predictedEsgSlot = pPvcDynamicData->predEsg[t]; + + pvcDecodeTimeSlot( + pPvcStaticData, pPvcDynamicData, &qmfBufferReal[t * RATE], + &qmfBufferImag[t * RATE], + (t * RATE < overlap) ? qmfExponentOverlap : qmfExponentCurrent, + pvcBorder0, t, predictedEsgSlot, pPredEsg_exp); + } + + return; +} + +void pvcDecodeTimeSlot(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, + FIXP_DBL **qmfSlotReal, FIXP_DBL **qmfSlotImag, + const int qmfExponent, const int pvcBorder0, + const int timeSlotNumber, FIXP_DBL predictedEsgSlot[], + int *predictedEsg_exp) { + int i, band, ksg, ksg_start = 0; + int RATE = pPvcDynamicData->RATE; + int Esg_index = pPvcStaticData->Esg_slot_index; + const SCHAR *sg_borders = pPvcDynamicData->sg_offset_low; + FIXP_DBL *pEsg = pPvcStaticData->Esg[Esg_index]; + FIXP_DBL E[PVC_NBLOW] = {0}; + + /* Subband grouping in QMF subbands below SBR range */ + /* Within one timeslot ( i = [0...(RATE-1)] QMF subsamples) calculate energy + E(ib,t) and group them to Esg(ksg,t). Then transfer values to logarithmical + domain and store them for time domain smoothing. (7.5.6.3 Subband grouping + in QMF subbands below SBR range) + */ + for (ksg = 0; sg_borders[ksg] < 0; ksg++) { + pEsg[ksg] = FL2FXCONST_DBL(-10.0 / (1 << PVC_ESG_EXP)); /* 10*log10(0.1) */ + ksg_start++; + } + + for (i = 0; i < RATE; i++) { + FIXP_DBL *qmfR, *qmfI; + qmfR = qmfSlotReal[i]; + qmfI = qmfSlotImag[i]; + for (ksg = ksg_start; ksg < PVC_NBLOW; ksg++) { + for (band = sg_borders[ksg]; band < sg_borders[ksg + 1]; band++) { + /* The division by 8 == (RATE*lbw) is required algorithmically */ + E[ksg] += (fPow2Div2(qmfR[band]) + fPow2Div2(qmfI[band])) >> 2; + } + } + } + for (ksg = ksg_start; ksg < PVC_NBLOW; ksg++) { + if (E[ksg] > (FIXP_DBL)0) { + /* 10/log2(10) = 0.752574989159953 * 2^2 */ + int exp_log; + FIXP_DBL nrg = CalcLog2(E[ksg], 2 * qmfExponent, &exp_log); + nrg = fMult(nrg, FL2FXCONST_SGL(LOG10FAC)); + nrg = scaleValue(nrg, exp_log - PVC_ESG_EXP + 2); + pEsg[ksg] = fMax(nrg, FL2FXCONST_DBL(-10.0 / (1 << PVC_ESG_EXP))); + } else { + pEsg[ksg] = + FL2FXCONST_DBL(-10.0 / (1 << PVC_ESG_EXP)); /* 10*log10(0.1) */ + } + } + + /* Time domain smoothing of subband-grouped energy */ + { + int idx = pPvcStaticData->Esg_slot_index; + FIXP_DBL *pEsg_filt; + FIXP_SGL SCcoeff; + + E[0] = E[1] = E[2] = (FIXP_DBL)0; + for (i = 0; i < pPvcDynamicData->ns; i++) { + SCcoeff = pPvcDynamicData->pSCcoeffs[i]; + pEsg_filt = pPvcStaticData->Esg[idx]; + /* Div2 is compensated by scaling of coeff table */ + E[0] = fMultAddDiv2(E[0], pEsg_filt[0], SCcoeff); + E[1] = fMultAddDiv2(E[1], pEsg_filt[1], SCcoeff); + E[2] = fMultAddDiv2(E[2], pEsg_filt[2], SCcoeff); + if (i >= pPvcDynamicData->pastEsgSlotsAvail) { + /* if past Esg values are not available use the ones from the last valid + * slot */ + continue; + } + if (idx > 0) { + idx--; + } else { + idx += PVC_NS_MAX - 1; + } + } + } + + /* SBR envelope scalefactor prediction */ + { + int E_high_exp[PVC_NBHIGH_MAX]; + int E_high_exp_max = 0; + int pvcTab1ID; + int pvcTab2ID = (int)pPvcDynamicData->pPvcID[timeSlotNumber]; + const UCHAR *pTab1, *pTab2; + if (pvcTab2ID < pPvcDynamicData->pPVCTab1_dp[0]) { + pvcTab1ID = 0; + } else if (pvcTab2ID < pPvcDynamicData->pPVCTab1_dp[1]) { + pvcTab1ID = 1; + } else { + pvcTab1ID = 2; + } + pTab1 = &(pPvcDynamicData + ->pPVCTab1[pvcTab1ID * PVC_NBLOW * pPvcDynamicData->nbHigh]); + pTab2 = &(pPvcDynamicData->pPVCTab2[pvcTab2ID * pPvcDynamicData->nbHigh]); + for (ksg = 0; ksg < pPvcDynamicData->nbHigh; ksg++) { + FIXP_SGL predCoeff; + FIXP_DBL accu; + int predCoeff_exp, kb; + E_high_exp[ksg] = 0; + + /* residual part */ + accu = ((LONG)(SCHAR)*pTab2++) << (DFRACT_BITS - 8 - PVC_ESG_EXP + + pPvcDynamicData->pScalingCoef[3]); + + /* linear combination of lower grouped energies part */ + for (kb = 0; kb < PVC_NBLOW; kb++) { + predCoeff = (FIXP_SGL)( + (SHORT)(SCHAR)pTab1[kb * pPvcDynamicData->nbHigh + ksg] << 8); + predCoeff_exp = pPvcDynamicData->pScalingCoef[kb] + + 1; /* +1 to compensate for Div2 */ + accu += fMultDiv2(E[kb], predCoeff) << predCoeff_exp; + } + /* convert back to linear domain */ + accu = fMult(accu, FL2FXCONST_SGL(LOG10FAC_INV)); + accu = f2Pow( + accu, PVC_ESG_EXP - 1, + &predCoeff_exp); /* -1 compensates for exponent of LOG10FAC_INV */ + predictedEsgSlot[ksg] = accu; + E_high_exp[ksg] = predCoeff_exp; + if (predCoeff_exp > E_high_exp_max) { + E_high_exp_max = predCoeff_exp; + } + } + + /* rescale output vector according to largest exponent */ + for (ksg = 0; ksg < pPvcDynamicData->nbHigh; ksg++) { + int scale = E_high_exp[ksg] - E_high_exp_max; + predictedEsgSlot[ksg] = scaleValue(predictedEsgSlot[ksg], scale); + } + *predictedEsg_exp = E_high_exp_max; + } + + pPvcStaticData->Esg_slot_index = + (pPvcStaticData->Esg_slot_index + 1) & (PVC_NS_MAX - 1); + pPvcDynamicData->pastEsgSlotsAvail = + fMin(pPvcDynamicData->pastEsgSlotsAvail + 1, PVC_NS_MAX - 1); + return; +} + +/* call if pvcMode = 0,1,2 */ +void pvcEndFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData) { + pPvcStaticData->pvc_mode_last = pPvcDynamicData->pvc_mode; + pPvcStaticData->kx_last = pPvcDynamicData->kx; + + if (pPvcDynamicData->pvc_mode == 0) return; + + { + int t, max = -100; + for (t = pPvcDynamicData->pvcBorder0; t < PVC_NTIMESLOT; t++) { + if (pPvcDynamicData->predEsg_exp[t] > max) { + max = pPvcDynamicData->predEsg_exp[t]; + } + } + pPvcDynamicData->predEsg_expMax = max; + } + return; +} + +void expandPredEsg(const PVC_DYNAMIC_DATA *pPvcDynamicData, const int timeSlot, + const int lengthOutputVector, FIXP_DBL *pOutput, + SCHAR *pOutput_exp) { + int k = 0, ksg; + const FIXP_DBL *predEsg = pPvcDynamicData->predEsg[timeSlot]; + + for (ksg = 0; ksg < pPvcDynamicData->nbHigh; ksg++) { + for (; k < pPvcDynamicData->sg_offset_high_kx[ksg + 1]; k++) { + pOutput[k] = predEsg[ksg]; + pOutput_exp[k] = (SCHAR)pPvcDynamicData->predEsg_exp[timeSlot]; + } + } + ksg--; + for (; k < lengthOutputVector; k++) { + pOutput[k] = predEsg[ksg]; + pOutput_exp[k] = (SCHAR)pPvcDynamicData->predEsg_exp[timeSlot]; + } + + return; +} diff --git a/libSBRdec/src/pvc_dec.h b/libSBRdec/src/pvc_dec.h new file mode 100644 index 0000000..f5a467f --- /dev/null +++ b/libSBRdec/src/pvc_dec.h @@ -0,0 +1,238 @@ +/* ----------------------------------------------------------------------------- +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): Matthias Hildenbrand + + Description: Decode Predictive Vector Coding Data + +*******************************************************************************/ + +#ifndef PVC_DEC_H +#define PVC_DEC_H + +#include "common_fix.h" + +#define PVC_DIVMODE_BITS 3 +#define PVC_REUSEPVCID_BITS 1 +#define PVC_PVCID_BITS 7 +#define PVC_GRIDINFO_BITS 1 + +#define MAX_PVC_ENVELOPES 2 +#define PVC_NTIMESLOT 16 +#define PVC_NBLOW 3 /* max. number of grouped QMF subbands below SBR range */ + +#define PVC_NBHIGH_MODE1 8 +#define PVC_NBHIGH_MODE2 6 +#define PVC_NBHIGH_MAX (PVC_NBHIGH_MODE1) +#define PVC_NS_MAX 16 + +/** Data for each PVC instance which needs to be persistent accross SBR frames + */ +typedef struct { + UCHAR kx_last; /**< Xover frequency of last frame */ + UCHAR pvc_mode_last; /**< PVC mode of last frame */ + UCHAR Esg_slot_index; /**< Ring buffer index to current Esg time slot */ + UCHAR pvcBorder0; /**< Start SBR time slot of PVC frame */ + FIXP_DBL Esg[PVC_NS_MAX][PVC_NBLOW]; /**< Esg(ksg,t) of current and 15 + previous time slots (ring buffer) in + logarithmical domain */ +} PVC_STATIC_DATA; + +/** Data for each PVC instance which is valid during one SBR frame */ +typedef struct { + UCHAR pvc_mode; /**< PVC mode 1 or 2, 0 means legacy SBR */ + UCHAR pvcBorder0; /**< Start SBR time slot of PVC frame */ + UCHAR kx; /**< Index of the first QMF subband in the SBR range */ + UCHAR RATE; /**< Number of QMF subband samples per time slot (2 or 4) */ + UCHAR ns; /**< Number of time slots for time-domain smoothing of Esg(ksg,t) */ + const UCHAR + *pPvcID; /**< Pointer to prediction coefficient matrix index table */ + UCHAR pastEsgSlotsAvail; /**< Number of past Esg(ksg,t) which are available + for smoothing filter */ + const FIXP_SGL *pSCcoeffs; /**< Pointer to smoothing window table */ + SCHAR + sg_offset_low[PVC_NBLOW + 1]; /**< Offset table for PVC grouping of SBR + subbands below SBR range */ + SCHAR sg_offset_high_kx[PVC_NBHIGH_MAX + 1]; /**< Offset table for PVC + grouping of SBR subbands in + SBR range (relativ to kx) */ + UCHAR nbHigh; /**< Number of grouped QMF subbands in the SBR range */ + const SCHAR *pScalingCoef; /**< Pointer to scaling coeff table */ + const UCHAR *pPVCTab1; /**< PVC mode 1 table */ + const UCHAR *pPVCTab2; /**< PVC mode 2 table */ + const UCHAR *pPVCTab1_dp; /**< Mapping of pvcID to PVC mode 1 table */ + FIXP_DBL predEsg[PVC_NTIMESLOT] + [PVC_NBHIGH_MAX]; /**< Predicted Energy in linear domain */ + int predEsg_exp[PVC_NTIMESLOT]; /**< Exponent of predicted Energy in linear + domain */ + int predEsg_expMax; /**< Maximum of predEsg_exp[] */ +} PVC_DYNAMIC_DATA; + +/** + * \brief Initialize PVC data structures for current frame (call if pvcMode = + * 0,1,2) + * \param[in] pPvcStaticData Pointer to PVC persistent data + * \param[out] pPvcDynamicData Pointer to PVC dynamic data + * \param[in] pvcMode PVC mode 1 or 2, 0 means legacy SBR + * \param[in] ns Number of time slots for time-domain smoothing of Esg(ksg,t) + * \param[in] RATE Number of QMF subband samples per time slot (2 or 4) + * \param[in] kx Index of the first QMF subband in the SBR range + * \param[in] pvcBorder0 Start SBR time slot of PVC frame + * \param[in] pPvcID Pointer to array of PvcIDs read from bitstream + */ +int pvcInitFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, const UCHAR pvcMode, + const UCHAR ns, const int RATE, const int kx, + const int pvcBorder0, const UCHAR *pPvcID); + +/** + * \brief Wrapper function for pvcDecodeTimeSlot() to decode PVC data of one + * frame (call if pvcMode = 1,2) + * \param[in,out] pPvcStaticData Pointer to PVC persistent data + * \param[in,out] pPvcDynamicData Pointer to PVC dynamic data + * \param[in] qmfBufferReal Pointer to array with real QMF subbands + * \param[in] qmfBufferImag Pointer to array with imag QMF subbands + * \param[in] overlap Number of QMF overlap slots + * \param[in] qmfExponentOverlap Exponent of qmfBuffer (low part) of overlap + * slots + * \param[in] qmfExponentCurrent Exponent of qmfBuffer (low part) + */ +void pvcDecodeFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, FIXP_DBL **qmfBufferReal, + FIXP_DBL **qmfBufferImag, const int overlap, + const int qmfExponentOverlap, const int qmfExponentCurrent); + +/** + * \brief Decode PVC data for one SBR time slot (call if pvcMode = 1,2) + * \param[in,out] pPvcStaticData Pointer to PVC persistent data + * \param[in,out] pPvcDynamicData Pointer to PVC dynamic data + * \param[in] qmfBufferReal Pointer to array with real QMF subbands + * \param[in] qmfBufferImag Pointer to array with imag QMF subbands + * \param[in] qmfExponent Exponent of qmfBuffer of current time slot + * \param[in] pvcBorder0 Start SBR time slot of PVC frame + * \param[in] timeSlotNumber Number of current SBR time slot (0..15) + * \param[out] predictedEsgSlot Predicted Energy of current time slot + * \param[out] predictedEsg_exp Exponent of predicted Energy of current time + * slot + */ +void pvcDecodeTimeSlot(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, + FIXP_DBL **qmfSlotReal, FIXP_DBL **qmfSlotImag, + const int qmfExponent, const int pvcBorder0, + const int timeSlotNumber, FIXP_DBL predictedEsgSlot[], + int *predictedEsg_exp); + +/** + * \brief Finish the current PVC frame (call if pvcMode = 0,1,2) + * \param[in,out] pPvcStaticData Pointer to PVC persistent data + * \param[in,out] pPvcDynamicData Pointer to PVC dynamic data + */ +void pvcEndFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData); + +/** + * \brief Expand predicted PVC grouped energies to full QMF subband resolution + * \param[in] pPvcDynamicData Pointer to PVC dynamic data + * \param[in] timeSlot Number of current SBR time slot (0..15) + * \param[in] lengthOutputVector Lenght of output vector + * \param[out] pOutput Output array for predicted energies + * \param[out] pOutput_exp Exponent of predicted energies + */ +void expandPredEsg(const PVC_DYNAMIC_DATA *pPvcDynamicData, const int timeSlot, + const int lengthOutputVector, FIXP_DBL *pOutput, + SCHAR *pOutput_exp); + +#endif /* PVC_DEC_H*/ diff --git a/libSBRdec/src/sbr_crc.cpp b/libSBRdec/src/sbr_crc.cpp index a495f10..ba0fd05 100644 --- a/libSBRdec/src/sbr_crc.cpp +++ b/libSBRdec/src/sbr_crc.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,11 +90,19 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief CRC check coutines + \brief CRC check coutines */ #include "sbr_crc.h" @@ -91,15 +110,13 @@ amm-info@iis.fraunhofer.de #include "FDK_bitstream.h" #include "transcendent.h" -#define MAXCRCSTEP 16 -#define MAXCRCSTEP_LD 4 +#define MAXCRCSTEP 16 +#define MAXCRCSTEP_LD 4 /*! \brief crc calculation */ -static ULONG -calcCRC (HANDLE_CRC hCrcBuf, ULONG bValue, int nBits) -{ +static ULONG calcCRC(HANDLE_CRC hCrcBuf, ULONG bValue, int nBits) { int i; ULONG bMask = (1UL << (nBits - 1)); @@ -109,52 +126,45 @@ calcCRC (HANDLE_CRC hCrcBuf, ULONG bValue, int nBits) flag ^= flag1; hCrcBuf->crcState <<= 1; - if (flag) - hCrcBuf->crcState ^= hCrcBuf->crcPoly; + if (flag) hCrcBuf->crcState ^= hCrcBuf->crcPoly; } return (hCrcBuf->crcState); } - /*! \brief crc */ -static int -getCrc (HANDLE_FDK_BITSTREAM hBs, ULONG NrBits) -{ +static int getCrc(HANDLE_FDK_BITSTREAM hBs, ULONG NrBits) { int i; CRC_BUFFER CrcBuf; CrcBuf.crcState = SBR_CRC_START; - CrcBuf.crcPoly = SBR_CRC_POLY; - CrcBuf.crcMask = SBR_CRC_MASK; + CrcBuf.crcPoly = SBR_CRC_POLY; + CrcBuf.crcMask = SBR_CRC_MASK; - int CrcStep = NrBits>>MAXCRCSTEP_LD; + int CrcStep = NrBits >> MAXCRCSTEP_LD; int CrcNrBitsRest = (NrBits - CrcStep * MAXCRCSTEP); ULONG bValue; for (i = 0; i < CrcStep; i++) { - bValue = FDKreadBits (hBs, MAXCRCSTEP); - calcCRC (&CrcBuf, bValue, MAXCRCSTEP); + bValue = FDKreadBits(hBs, MAXCRCSTEP); + calcCRC(&CrcBuf, bValue, MAXCRCSTEP); } - bValue = FDKreadBits (hBs, CrcNrBitsRest); - calcCRC (&CrcBuf, bValue, CrcNrBitsRest); + bValue = FDKreadBits(hBs, CrcNrBitsRest); + calcCRC(&CrcBuf, bValue, CrcNrBitsRest); return (CrcBuf.crcState & SBR_CRC_RANGE); - } - /*! \brief crc interface \return 1: CRC OK, 0: CRC check failure */ -int -SbrCrcCheck (HANDLE_FDK_BITSTREAM hBs, /*!< handle to bit-buffer */ - LONG NrBits) /*!< max. CRC length */ +int SbrCrcCheck(HANDLE_FDK_BITSTREAM hBs, /*!< handle to bit-buffer */ + LONG NrBits) /*!< max. CRC length */ { int crcResult = 1; ULONG NrCrcBits; @@ -162,18 +172,17 @@ SbrCrcCheck (HANDLE_FDK_BITSTREAM hBs, /*!< handle to bit-buffer */ LONG NrBitsAvailable; ULONG crcCheckSum; - crcCheckSum = FDKreadBits (hBs, 10); + crcCheckSum = FDKreadBits(hBs, 10); NrBitsAvailable = FDKgetValidBits(hBs); - if (NrBitsAvailable <= 0){ + if (NrBitsAvailable <= 0) { return 0; } - NrCrcBits = fixMin ((INT)NrBits, (INT)NrBitsAvailable); - - crcCheckResult = getCrc (hBs, NrCrcBits); - FDKpushBack(hBs, (NrBitsAvailable - FDKgetValidBits(hBs)) ); + NrCrcBits = fixMin((INT)NrBits, (INT)NrBitsAvailable); + crcCheckResult = getCrc(hBs, NrCrcBits); + FDKpushBack(hBs, (NrBitsAvailable - FDKgetValidBits(hBs))); if (crcCheckResult != crcCheckSum) { crcResult = 0; diff --git a/libSBRdec/src/sbr_crc.h b/libSBRdec/src/sbr_crc.h index 30b8329..9633717 100644 --- a/libSBRdec/src/sbr_crc.h +++ b/libSBRdec/src/sbr_crc.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,14 +90,22 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief CRC checking routines + \brief CRC checking routines */ -#ifndef __SBR_CRC_H -#define __SBR_CRC_H +#ifndef SBR_CRC_H +#define SBR_CRC_H #include "sbrdecoder.h" @@ -100,24 +119,20 @@ crc7: x^7+x^6+x^2+1 crc8: x^8+x^2+x+x+1 */ -/* default SBR CRC */ /* G(x) = x^10 + x^9 + x^5 + x^4 + x + 1 */ -#define SBR_CRC_POLY 0x0233 -#define SBR_CRC_MASK 0x0200 -#define SBR_CRC_START 0x0000 -#define SBR_CRC_RANGE 0x03FF +/* default SBR CRC */ /* G(x) = x^10 + x^9 + x^5 + x^4 + x + 1 */ +#define SBR_CRC_POLY 0x0233 +#define SBR_CRC_MASK 0x0200 +#define SBR_CRC_START 0x0000 +#define SBR_CRC_RANGE 0x03FF -typedef struct -{ +typedef struct { USHORT crcState; USHORT crcMask; USHORT crcPoly; -} -CRC_BUFFER; +} CRC_BUFFER; typedef CRC_BUFFER *HANDLE_CRC; -int SbrCrcCheck (HANDLE_FDK_BITSTREAM hBitBuf, - LONG NrCrcBits); - +int SbrCrcCheck(HANDLE_FDK_BITSTREAM hBitBuf, LONG NrCrcBits); #endif diff --git a/libSBRdec/src/sbr_deb.cpp b/libSBRdec/src/sbr_deb.cpp index 9baff2e..13cd211 100644 --- a/libSBRdec/src/sbr_deb.cpp +++ b/libSBRdec/src/sbr_deb.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,12 +90,19 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief Print selected debug messages + \brief Print selected debug messages */ #include "sbr_deb.h" - diff --git a/libSBRdec/src/sbr_deb.h b/libSBRdec/src/sbr_deb.h index cb954ba..97d572a 100644 --- a/libSBRdec/src/sbr_deb.h +++ b/libSBRdec/src/sbr_deb.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,15 +90,23 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief Debugging aids + \brief Debugging aids */ -#ifndef __SBR_DEB_H -#define __SBR_DEB_H +#ifndef SBR_DEB_H +#define SBR_DEB_H #include "sbrdecoder.h" diff --git a/libSBRdec/src/sbr_dec.cpp b/libSBRdec/src/sbr_dec.cpp index 0864348..2e18e6c 100644 --- a/libSBRdec/src/sbr_dec.cpp +++ b/libSBRdec/src/sbr_dec.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,19 +90,28 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief Sbr decoder - This module provides the actual decoder implementation. The SBR data (side information) is already - decoded. Only three functions are provided: + \brief Sbr decoder + This module provides the actual decoder implementation. The SBR data (side + information) is already decoded. Only three functions are provided: \li 1.) createSbrDec(): One time initialization - \li 2.) resetSbrDec(): Called by sbr_Apply() when the information contained in an SBR_HEADER_ELEMENT requires a reset - and recalculation of important SBR structures. - \li 3.) sbr_dec(): The actual decoder. Calls the different tools such as filterbanks, lppTransposer(), and calculateSbrEnvelope() - [the envelope adjuster]. + \li 2.) resetSbrDec(): Called by sbr_Apply() when the information contained in + an SBR_HEADER_ELEMENT requires a reset and recalculation of important SBR + structures. \li 3.) sbr_dec(): The actual decoder. Calls the different tools + such as filterbanks, lppTransposer(), and calculateSbrEnvelope() [the envelope + adjuster]. \sa sbr_dec(), \ref documentationOverview */ @@ -102,178 +122,90 @@ amm-info@iis.fraunhofer.de #include "env_extr.h" #include "env_calc.h" #include "scale.h" +#include "FDK_matrixCalloc.h" +#include "hbe.h" #include "genericStds.h" #include "sbrdec_drc.h" +static void copyHarmonicSpectrum(int *xOverQmf, FIXP_DBL **qmfReal, + FIXP_DBL **qmfImag, int noCols, int overlap, + KEEP_STATES_SYNCED_MODE keepStatesSynced) { + int patchBands; + int patch, band, col, target, sourceBands, i; + int numPatches = 0; + int slotOffset = 0; + FIXP_DBL **ppqmfReal = qmfReal + overlap; + FIXP_DBL **ppqmfImag = qmfImag + overlap; -static void assignLcTimeSlots( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ - FIXP_DBL **QmfBufferReal, - int noCols ) -{ - int slot, i; - FIXP_DBL *ptr; - - /* Number of QMF timeslots in the overlap buffer: */ - ptr = hSbrDec->pSbrOverlapBuffer; - for(slot=0; slot<hSbrDec->LppTrans.pSettings->overlap; slot++) { - QmfBufferReal[slot] = ptr; ptr += (64); - } - - /* Assign timeslots to Workbuffer1 */ - ptr = hSbrDec->WorkBuffer1; - for(i=0; i<noCols; i++) { - QmfBufferReal[slot] = ptr; ptr += (64); - slot++; - } -} - - -static void assignHqTimeSlots( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ - FIXP_DBL **QmfBufferReal, - FIXP_DBL **QmfBufferImag, - int noCols ) -{ - FIXP_DBL *ptr; - int slot; - - /* Number of QMF timeslots in one half of a frame (size of Workbuffer1 or 2): */ - int halflen = (noCols >> 1) + hSbrDec->LppTrans.pSettings->overlap; - int totCols = noCols + hSbrDec->LppTrans.pSettings->overlap; - - /* Number of QMF timeslots in the overlap buffer: */ - ptr = hSbrDec->pSbrOverlapBuffer; - for(slot=0; slot<hSbrDec->LppTrans.pSettings->overlap; slot++) { - QmfBufferReal[slot] = ptr; ptr += (64); - QmfBufferImag[slot] = ptr; ptr += (64); - } - - /* Assign first half of timeslots to Workbuffer1 */ - ptr = hSbrDec->WorkBuffer1; - for(; slot<halflen; slot++) { - QmfBufferReal[slot] = ptr; ptr += (64); - QmfBufferImag[slot] = ptr; ptr += (64); - } - - /* Assign second half of timeslots to Workbuffer2 */ - ptr = hSbrDec->WorkBuffer2; - for(; slot<totCols; slot++) { - QmfBufferReal[slot] = ptr; ptr += (64); - QmfBufferImag[slot] = ptr; ptr += (64); + if (keepStatesSynced == KEEP_STATES_SYNCED_NORMAL) { + slotOffset = noCols - overlap - LPC_ORDER; } -} - -static void assignTimeSlots( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ - int noCols, - int useLP ) -{ - /* assign qmf time slots */ - hSbrDec->useLP = useLP; - if (useLP) { - hSbrDec->SynthesisQMF.flags |= QMF_FLAG_LP; - hSbrDec->AnalysiscQMF.flags |= QMF_FLAG_LP; - } else { - hSbrDec->SynthesisQMF.flags &= ~QMF_FLAG_LP; - hSbrDec->AnalysiscQMF.flags &= ~QMF_FLAG_LP; - } - if (!useLP) - assignHqTimeSlots( hSbrDec, hSbrDec->QmfBufferReal, hSbrDec->QmfBufferImag, noCols ); - else - { - assignLcTimeSlots( hSbrDec, hSbrDec->QmfBufferReal, noCols ); + if (keepStatesSynced == KEEP_STATES_SYNCED_OUTDIFF) { + ppqmfReal = qmfReal; + ppqmfImag = qmfImag; } -} -static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ - int useLdTimeAlign ) -{ - UINT synQmfFlags = hSbrDec->SynthesisQMF.flags; - UINT anaQmfFlags = hSbrDec->AnalysiscQMF.flags; - int resetSynQmf = 0; - int resetAnaQmf = 0; - - /* assign qmf type */ - if (useLdTimeAlign) { - if (synQmfFlags & QMF_FLAG_CLDFB) { - /* change the type to MPSLD */ - synQmfFlags &= ~QMF_FLAG_CLDFB; - synQmfFlags |= QMF_FLAG_MPSLDFB; - resetSynQmf = 1; - } - if (anaQmfFlags & QMF_FLAG_CLDFB) { - /* change the type to MPSLD */ - anaQmfFlags &= ~QMF_FLAG_CLDFB; - anaQmfFlags |= QMF_FLAG_MPSLDFB; - resetAnaQmf = 1; - } - } else { - if (synQmfFlags & QMF_FLAG_MPSLDFB) { - /* change the type to CLDFB */ - synQmfFlags &= ~QMF_FLAG_MPSLDFB; - synQmfFlags |= QMF_FLAG_CLDFB; - resetSynQmf = 1; - } - if (anaQmfFlags & QMF_FLAG_MPSLDFB) { - /* change the type to CLDFB */ - anaQmfFlags &= ~QMF_FLAG_MPSLDFB; - anaQmfFlags |= QMF_FLAG_CLDFB; - resetAnaQmf = 1; + for (i = 1; i < MAX_NUM_PATCHES; i++) { + if (xOverQmf[i] != 0) { + numPatches++; } } - if (resetAnaQmf) { - QMF_FILTER_BANK prvAnaQmf; - int qmfErr; - - /* Store current configuration */ - FDKmemcpy(&prvAnaQmf, &hSbrDec->AnalysiscQMF, sizeof(QMF_FILTER_BANK)); - - /* Reset analysis QMF */ - qmfErr = qmfInitAnalysisFilterBank ( - &hSbrDec->AnalysiscQMF, - hSbrDec->anaQmfStates, - hSbrDec->AnalysiscQMF.no_col, - hSbrDec->AnalysiscQMF.lsb, - hSbrDec->AnalysiscQMF.usb, - hSbrDec->AnalysiscQMF.no_channels, - anaQmfFlags | QMF_FLAG_KEEP_STATES - ); - - if (qmfErr != 0) { - /* Restore old configuration of analysis QMF */ - FDKmemcpy(&hSbrDec->AnalysiscQMF, &prvAnaQmf, sizeof(QMF_FILTER_BANK)); - } - } + for (patch = (MAX_STRETCH_HBE - 1); patch < numPatches; patch++) { + patchBands = xOverQmf[patch + 1] - xOverQmf[patch]; + target = xOverQmf[patch]; + sourceBands = xOverQmf[MAX_STRETCH_HBE - 1] - xOverQmf[MAX_STRETCH_HBE - 2]; - if (resetSynQmf) { - QMF_FILTER_BANK prvSynQmf; - int qmfErr; - - /* Store current configuration */ - FDKmemcpy(&prvSynQmf, &hSbrDec->SynthesisQMF, sizeof(QMF_FILTER_BANK)); - - /* Reset synthesis QMF */ - qmfErr = qmfInitSynthesisFilterBank ( - &hSbrDec->SynthesisQMF, - hSbrDec->pSynQmfStates, - hSbrDec->SynthesisQMF.no_col, - hSbrDec->SynthesisQMF.lsb, - hSbrDec->SynthesisQMF.usb, - hSbrDec->SynthesisQMF.no_channels, - synQmfFlags | QMF_FLAG_KEEP_STATES - ); - - if (qmfErr != 0) { - /* Restore old configuration of synthesis QMF */ - FDKmemcpy(&hSbrDec->SynthesisQMF, &prvSynQmf, sizeof(QMF_FILTER_BANK)); + while (patchBands > 0) { + int numBands = sourceBands; + int startBand = xOverQmf[MAX_STRETCH_HBE - 1] - 1; + if (target + numBands >= xOverQmf[patch + 1]) { + numBands = xOverQmf[patch + 1] - target; + } + if ((((target + numBands - 1) % 2) + + ((xOverQmf[MAX_STRETCH_HBE - 1] - 1) % 2)) % + 2) { + if (numBands == sourceBands) { + numBands--; + } else { + startBand--; + } + } + if (keepStatesSynced == KEEP_STATES_SYNCED_OUTDIFF) { + for (col = slotOffset; col < overlap + LPC_ORDER; col++) { + i = 0; + for (band = numBands; band > 0; band--) { + if ((target + band - 1 < 64) && + (target + band - 1 < xOverQmf[patch + 1])) { + ppqmfReal[col][target + band - 1] = ppqmfReal[col][startBand - i]; + ppqmfImag[col][target + band - 1] = ppqmfImag[col][startBand - i]; + i++; + } + } + } + } else { + for (col = slotOffset; col < noCols; col++) { + i = 0; + for (band = numBands; band > 0; band--) { + if ((target + band - 1 < 64) && + (target + band - 1 < xOverQmf[patch + 1])) { + ppqmfReal[col][target + band - 1] = ppqmfReal[col][startBand - i]; + ppqmfImag[col][target + band - 1] = ppqmfImag[col][startBand - i]; + i++; + } + } + } + } + target += numBands; + patchBands -= numBands; } } } - /*! \brief SBR decoder core function for one channel @@ -283,26 +215,26 @@ static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< hand the LPP-Transposer, processing is mainly based on four buffers: #timeIn, #timeOut, #WorkBuffer2 and #OverlapBuffer. The #WorkBuffer2 is reused for all channels and might be used by the core decoder, a - static overlap buffer is required for each channel. Du to in-place + static overlap buffer is required for each channel. Due to in-place processing, #timeIn and #timeOut point to identical locations. - The spectral data is organized in so-called slots, each slot - containing 64 bands of complex data. The number of slots per frame is - dependend on the frame size. For mp3PRO, there are 18 slots per frame + The spectral data is organized in so-called slots. Each slot + contains 64 bands of complex data. The number of slots per frame + depends on the frame size. For mp3PRO, there are 18 slots per frame and 6 slots per #OverlapBuffer. It is not necessary to have the slots in located consecutive address ranges. To optimize memory usage and to minimize the number of memory - accesses, the memory management is organized as follows (Slot numbers + accesses, the memory management is organized as follows (slot numbers based on mp3PRO): - 1.) Input time domain signal is located in #timeIn, the last slots + 1.) Input time domain signal is located in #timeIn. The last slots (0..5) of the spectral data of the previous frame are located in the #OverlapBuffer. In addition, #frameData of the current frame resides in the upper part of #timeIn. - 2.) During the cplxAnalysisQmfFiltering(), 32 samples from #timeIn are transformed - into a slot of up to 32 complex spectral low band values at a + 2.) During the cplxAnalysisQmfFiltering(), 32 samples from #timeIn are + transformed into a slot of up to 32 complex spectral low band values at a time. The first spectral slot -- nr. 6 -- is written at slot number zero of #WorkBuffer2. #WorkBuffer2 will be completely filled with spectral data. @@ -325,73 +257,77 @@ static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< hand */ -void -sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ - INT_PCM *timeIn, /*!< pointer to input time signal */ - INT_PCM *timeOut, /*!< pointer to output time signal */ - HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ - INT_PCM *timeOutRight, /*!< pointer to output time signal */ - const int strideIn, /*!< Time data traversal strideIn */ - const int strideOut, /*!< Time data traversal strideOut */ - HANDLE_SBR_HEADER_DATA hHeaderData,/*!< Static control data */ - HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ - HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */ - const int applyProcessing, /*!< Flag for SBR operation */ - HANDLE_PS_DEC h_ps_d, - const UINT flags, - const int codecFrameSize - ) -{ +void sbr_dec( + HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ + INT_PCM *timeIn, /*!< pointer to input time signal */ + INT_PCM *timeOut, /*!< pointer to output time signal */ + HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ + INT_PCM *timeOutRight, /*!< pointer to output time signal */ + const int strideOut, /*!< Time data traversal strideOut */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ + HANDLE_SBR_PREV_FRAME_DATA + hPrevFrameData, /*!< Some control data of last frame */ + const int applyProcessing, /*!< Flag for SBR operation */ + HANDLE_PS_DEC h_ps_d, const UINT flags, const int codecFrameSize) { int i, slot, reserve; int saveLbScale; - int ov_len; int lastSlotOffs; FIXP_DBL maxVal; - /* 1+1/3 frames of spectral data: */ - FIXP_DBL **QmfBufferReal = hSbrDec->QmfBufferReal; - FIXP_DBL **QmfBufferImag = hSbrDec->QmfBufferImag; + /* temporary pointer / variable for QMF; + required as we want to use temporary buffer + creating one frame delay for HBE in LP mode */ + INT_PCM *pTimeInQmf = timeIn; - /* Number of QMF timeslots in the overlap buffer: */ - ov_len = hSbrDec->LppTrans.pSettings->overlap; + /* Number of QMF timeslots in the overlap buffer: */ + int ov_len = hSbrDec->LppTrans.pSettings->overlap; - /* Number of QMF slots per frame */ + /* Number of QMF slots per frame */ int noCols = hHeaderData->numberTimeSlots * hHeaderData->timeStep; - /* assign qmf time slots */ - if ( ((flags & SBRDEC_LOW_POWER ) ? 1 : 0) != ((hSbrDec->SynthesisQMF.flags & QMF_FLAG_LP) ? 1 : 0) ) { - assignTimeSlots( hSbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, flags & SBRDEC_LOW_POWER); + /* create pointer array for data to use for HBE and legacy sbr */ + FIXP_DBL *pLowBandReal[(3 * 4) + 2 * ((1024) / (32) * (4) / 2)]; + FIXP_DBL *pLowBandImag[(3 * 4) + 2 * ((1024) / (32) * (4) / 2)]; + + /* set pReal to where QMF analysis writes in case of legacy SBR */ + FIXP_DBL **pReal = pLowBandReal + ov_len; + FIXP_DBL **pImag = pLowBandImag + ov_len; + + /* map QMF buffer to pointer array (Overlap + Frame)*/ + for (i = 0; i < noCols + ov_len; i++) { + pLowBandReal[i] = hSbrDec->qmfDomainInCh->hQmfSlotsReal[i]; + pLowBandImag[i] = hSbrDec->qmfDomainInCh->hQmfSlotsImag[i]; } - if (flags & SBRDEC_ELD_GRID) { - /* Choose the right low delay filter bank */ - changeQmfType( hSbrDec, (flags & SBRDEC_LD_MPS_QMF) ? 1 : 0 ); + if ((flags & SBRDEC_USAC_HARMONICSBR)) { + /* in case of harmonic SBR and no HBE_LP map additional buffer for + one more frame to pointer arry */ + for (i = 0; i < noCols; i++) { + pLowBandReal[i + noCols + ov_len] = hSbrDec->hQmfHBESlotsReal[i]; + pLowBandImag[i + noCols + ov_len] = hSbrDec->hQmfHBESlotsImag[i]; + } - /* If the LD-MPS QMF is not available delay the signal by (96-48*ldSbrSamplingRate) - * samples according to ISO/IEC 14496-3:2009/FDAM 2:2010(E) chapter 4.5.2.13. */ - if ( (flags & SBRDEC_LD_MPS_QMF) - && (hSbrDec->AnalysiscQMF.flags & QMF_FLAG_CLDFB) ) - { - INT_PCM *pDlyBuf = hSbrDec->coreDelayBuf; /* DLYBUF */ - int smpl, delay = 96 >> (!(flags & SBRDEC_DOWNSAMPLE) ? 1 : 0); - /* Create TMPBUF */ - C_AALLOC_SCRATCH_START(pcmTemp, INT_PCM, (96)); - /* Copy delay samples from INBUF to TMPBUF */ - for (smpl = 0; smpl < delay; smpl += 1) { - pcmTemp[smpl] = timeIn[(codecFrameSize-delay+smpl)*strideIn]; - } - /* Move input signal remainder to the very end of INBUF */ - for (smpl = (codecFrameSize-delay-1)*strideIn; smpl >= 0; smpl -= strideIn) { - timeIn[smpl+delay] = timeIn[smpl]; - } - /* Copy delayed samples from last frame from DLYBUF to the very beginning of INBUF */ - for (smpl = 0; smpl < delay; smpl += 1) { - timeIn[smpl*strideIn] = pDlyBuf[smpl]; + /* shift scale values according to buffer */ + hSbrDec->scale_ov = hSbrDec->scale_lb; + hSbrDec->scale_lb = hSbrDec->scale_hbe; + + /* set pReal to where QMF analysis writes in case of HBE */ + pReal += noCols; + pImag += noCols; + if (flags & SBRDEC_SKIP_QMF_ANA) { + /* stereoCfgIndex3 with HBE */ + FDK_QmfDomain_QmfData2HBE(hSbrDec->qmfDomainInCh, + hSbrDec->hQmfHBESlotsReal, + hSbrDec->hQmfHBESlotsImag); + } else { + /* We have to move old hbe frame data to lb area of buffer */ + for (i = 0; i < noCols; i++) { + FDKmemcpy(pLowBandReal[ov_len + i], hSbrDec->hQmfHBESlotsReal[i], + hHeaderData->numberOfAnalysisBands * sizeof(FIXP_DBL)); + FDKmemcpy(pLowBandImag[ov_len + i], hSbrDec->hQmfHBESlotsImag[i], + hHeaderData->numberOfAnalysisBands * sizeof(FIXP_DBL)); } - /* Copy TMPBUF to DLYBUF */ - FDKmemcpy(pDlyBuf, pcmTemp, delay*sizeof(INT_PCM)); - /* Destory TMPBUF */ - C_AALLOC_SCRATCH_END(pcmTemp, INT_PCM, (96)); } } @@ -399,234 +335,437 @@ sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ low band codec signal subband filtering */ - { - C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2*(64)); - - qmfAnalysisFiltering( &hSbrDec->AnalysiscQMF, - QmfBufferReal + ov_len, - QmfBufferImag + ov_len, - &hSbrDec->sbrScaleFactor, - timeIn, - strideIn, - qmfTemp - ); - - C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2*(64)); + if (flags & SBRDEC_SKIP_QMF_ANA) { + if (!(flags & SBRDEC_USAC_HARMONICSBR)) /* stereoCfgIndex3 w/o HBE */ + FDK_QmfDomain_WorkBuffer2ProcChannel(hSbrDec->qmfDomainInCh); + } else { + C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2 * (64)); + qmfAnalysisFiltering(&hSbrDec->qmfDomainInCh->fb, pReal, pImag, + &hSbrDec->qmfDomainInCh->scaling, pTimeInQmf, 0, 1, + qmfTemp); + + C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2 * (64)); } /* Clear upper half of spectrum */ - { + if (!((flags & SBRDEC_USAC_HARMONICSBR) && + (hFrameData->sbrPatchingMode == 0))) { int nAnalysisBands = hHeaderData->numberOfAnalysisBands; - if (! (flags & SBRDEC_LOW_POWER)) { - for (slot = ov_len; slot < noCols+ov_len; slot++) { - FDKmemclear(&QmfBufferReal[slot][nAnalysisBands],((64)-nAnalysisBands)*sizeof(FIXP_DBL)); - FDKmemclear(&QmfBufferImag[slot][nAnalysisBands],((64)-nAnalysisBands)*sizeof(FIXP_DBL)); + if (!(flags & SBRDEC_LOW_POWER)) { + for (slot = ov_len; slot < noCols + ov_len; slot++) { + FDKmemclear(&pLowBandReal[slot][nAnalysisBands], + ((64) - nAnalysisBands) * sizeof(FIXP_DBL)); + FDKmemclear(&pLowBandImag[slot][nAnalysisBands], + ((64) - nAnalysisBands) * sizeof(FIXP_DBL)); + } + } else { + for (slot = ov_len; slot < noCols + ov_len; slot++) { + FDKmemclear(&pLowBandReal[slot][nAnalysisBands], + ((64) - nAnalysisBands) * sizeof(FIXP_DBL)); } - } else - for (slot = ov_len; slot < noCols+ov_len; slot++) { - FDKmemclear(&QmfBufferReal[slot][nAnalysisBands],((64)-nAnalysisBands)*sizeof(FIXP_DBL)); } } - - /* Shift spectral data left to gain accuracy in transposer and adjustor */ - maxVal = maxSubbandSample( QmfBufferReal, - (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag, - 0, - hSbrDec->AnalysiscQMF.lsb, - ov_len, - noCols+ov_len ); + /* Range was increased from lsb to no_channels because in some cases (e.g. + USAC conf eSbr_4_Pvc.mp4 and some HBE cases) it could be observed that the + signal between lsb and no_channels is used for the patching process. + */ + maxVal = maxSubbandSample(pReal, (flags & SBRDEC_LOW_POWER) ? NULL : pImag, 0, + hSbrDec->qmfDomainInCh->fb.no_channels, 0, noCols); - reserve = fixMax(0,CntLeadingZeros(maxVal)-1) ; - reserve = fixMin(reserve,DFRACT_BITS-1-hSbrDec->sbrScaleFactor.lb_scale); + reserve = fixMax(0, CntLeadingZeros(maxVal) - 1); + reserve = fixMin(reserve, + DFRACT_BITS - 1 - hSbrDec->qmfDomainInCh->scaling.lb_scale); /* If all data is zero, lb_scale could become too large */ - rescaleSubbandSamples( QmfBufferReal, - (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag, - 0, - hSbrDec->AnalysiscQMF.lsb, - ov_len, - noCols+ov_len, - reserve); + rescaleSubbandSamples(pReal, (flags & SBRDEC_LOW_POWER) ? NULL : pImag, 0, + hSbrDec->qmfDomainInCh->fb.no_channels, 0, noCols, + reserve); - hSbrDec->sbrScaleFactor.lb_scale += reserve; + hSbrDec->qmfDomainInCh->scaling.lb_scale += reserve; + if ((flags & SBRDEC_USAC_HARMONICSBR)) { + /* actually this is our hbe_scale */ + hSbrDec->scale_hbe = hSbrDec->qmfDomainInCh->scaling.lb_scale; + /* the real lb_scale is stored in scale_lb from sbr */ + hSbrDec->qmfDomainInCh->scaling.lb_scale = hSbrDec->scale_lb; + } /* save low band scale, wavecoding or parametric stereo may modify it */ - saveLbScale = hSbrDec->sbrScaleFactor.lb_scale; + saveLbScale = hSbrDec->qmfDomainInCh->scaling.lb_scale; - - if (applyProcessing) - { - UCHAR * borders = hFrameData->frameInfo.borders; - lastSlotOffs = borders[hFrameData->frameInfo.nEnvelopes] - hHeaderData->numberTimeSlots; + if (applyProcessing) { + UCHAR *borders = hFrameData->frameInfo.borders; + lastSlotOffs = borders[hFrameData->frameInfo.nEnvelopes] - + hHeaderData->numberTimeSlots; FIXP_DBL degreeAlias[(64)]; + PVC_DYNAMIC_DATA pvcDynamicData; + pvcInitFrame( + &hSbrDec->PvcStaticData, &pvcDynamicData, + (hHeaderData->frameErrorFlag ? 0 : hHeaderData->bs_info.pvc_mode), + hFrameData->ns, hHeaderData->timeStep, + hHeaderData->freqBandData.lowSubband, + hFrameData->frameInfo.pvcBorders[0], hFrameData->pvcID); + + if (!hHeaderData->frameErrorFlag && (hHeaderData->bs_info.pvc_mode > 0)) { + pvcDecodeFrame(&hSbrDec->PvcStaticData, &pvcDynamicData, pLowBandReal, + pLowBandImag, ov_len, + SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale), + SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.lb_scale)); + } + pvcEndFrame(&hSbrDec->PvcStaticData, &pvcDynamicData); /* The transposer will override most values in degreeAlias[]. - The array needs to be cleared at least from lowSubband to highSubband before. */ + The array needs to be cleared at least from lowSubband to highSubband + before. */ if (flags & SBRDEC_LOW_POWER) - FDKmemclear(°reeAlias[hHeaderData->freqBandData.lowSubband], (hHeaderData->freqBandData.highSubband-hHeaderData->freqBandData.lowSubband)*sizeof(FIXP_DBL)); + FDKmemclear(°reeAlias[hHeaderData->freqBandData.lowSubband], + (hHeaderData->freqBandData.highSubband - + hHeaderData->freqBandData.lowSubband) * + sizeof(FIXP_DBL)); /* - Inverse filtering of lowband and transposition into the SBR-frequency range + Inverse filtering of lowband and transposition into the SBR-frequency + range */ - lppTransposer ( &hSbrDec->LppTrans, - &hSbrDec->sbrScaleFactor, - QmfBufferReal, - degreeAlias, // only used if useLP = 1 - QmfBufferImag, - flags & SBRDEC_LOW_POWER, - hHeaderData->timeStep, - borders[0], - lastSlotOffs, - hHeaderData->freqBandData.nInvfBands, - hFrameData->sbr_invf_mode, - hPrevFrameData->sbr_invf_mode ); + { + KEEP_STATES_SYNCED_MODE keepStatesSyncedMode = + ((flags & SBRDEC_USAC_HARMONICSBR) && + (hFrameData->sbrPatchingMode != 0)) + ? KEEP_STATES_SYNCED_NORMAL + : KEEP_STATES_SYNCED_OFF; + + if (flags & SBRDEC_USAC_HARMONICSBR) { + if (flags & SBRDEC_QUAD_RATE) { + pReal -= 32; + pImag -= 32; + } + + if ((hSbrDec->savedStates == 0) && (hFrameData->sbrPatchingMode == 1)) { + /* copy saved states from previous frame to legacy SBR lpc filterstate + * buffer */ + for (i = 0; i < LPC_ORDER + ov_len; i++) { + FDKmemcpy( + hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], + hSbrDec->codecQMFBufferReal[noCols - LPC_ORDER - ov_len + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + FDKmemcpy( + hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], + hSbrDec->codecQMFBufferImag[noCols - LPC_ORDER - ov_len + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + } + } + + /* saving unmodified QMF states in case we are switching from legacy SBR + * to HBE */ + for (i = 0; i < hSbrDec->hHBE->noCols; i++) { + FDKmemcpy(hSbrDec->codecQMFBufferReal[i], pLowBandReal[ov_len + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->codecQMFBufferImag[i], pLowBandImag[ov_len + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + } + + QmfTransposerApply( + hSbrDec->hHBE, pReal, pImag, noCols, pLowBandReal, pLowBandImag, + hSbrDec->LppTrans.lpcFilterStatesRealHBE, + hSbrDec->LppTrans.lpcFilterStatesImagHBE, + hFrameData->sbrPitchInBins, hSbrDec->scale_lb, hSbrDec->scale_hbe, + &hSbrDec->qmfDomainInCh->scaling.hb_scale, hHeaderData->timeStep, + borders[0], ov_len, keepStatesSyncedMode); + + if (flags & SBRDEC_QUAD_RATE) { + int *xOverQmf = GetxOverBandQmfTransposer(hSbrDec->hHBE); + + copyHarmonicSpectrum(xOverQmf, pLowBandReal, pLowBandImag, noCols, + ov_len, keepStatesSyncedMode); + } + } + } + if ((flags & SBRDEC_USAC_HARMONICSBR) && + (hFrameData->sbrPatchingMode == 0)) { + hSbrDec->prev_frame_lSbr = 0; + hSbrDec->prev_frame_hbeSbr = 1; + lppTransposerHBE( + &hSbrDec->LppTrans, hSbrDec->hHBE, &hSbrDec->qmfDomainInCh->scaling, + pLowBandReal, pLowBandImag, hHeaderData->timeStep, borders[0], + lastSlotOffs, hHeaderData->freqBandData.nInvfBands, + hFrameData->sbr_invf_mode, hPrevFrameData->sbr_invf_mode); + } else { + if (flags & SBRDEC_USAC_HARMONICSBR) { + for (i = 0; i < LPC_ORDER + hSbrDec->LppTrans.pSettings->overlap; i++) { + /* + Store the unmodified qmf Slots values for upper part of spectrum + (required for LPC filtering) required if next frame is a HBE frame + */ + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesRealHBE[i], + hSbrDec->qmfDomainInCh + ->hQmfSlotsReal[hSbrDec->hHBE->noCols - LPC_ORDER + i], + (64) * sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesImagHBE[i], + hSbrDec->qmfDomainInCh + ->hQmfSlotsImag[hSbrDec->hHBE->noCols - LPC_ORDER + i], + (64) * sizeof(FIXP_DBL)); + } + } + { + hSbrDec->prev_frame_lSbr = 1; + hSbrDec->prev_frame_hbeSbr = 0; + } + lppTransposer( + &hSbrDec->LppTrans, &hSbrDec->qmfDomainInCh->scaling, pLowBandReal, + degreeAlias, // only used if useLP = 1 + pLowBandImag, flags & SBRDEC_LOW_POWER, + hHeaderData->bs_info.sbr_preprocessing, + hHeaderData->freqBandData.v_k_master[0], hHeaderData->timeStep, + borders[0], lastSlotOffs, hHeaderData->freqBandData.nInvfBands, + hFrameData->sbr_invf_mode, hPrevFrameData->sbr_invf_mode); + } /* Adjust envelope of current frame. */ - calculateSbrEnvelope (&hSbrDec->sbrScaleFactor, - &hSbrDec->SbrCalculateEnvelope, - hHeaderData, - hFrameData, - QmfBufferReal, - QmfBufferImag, - flags & SBRDEC_LOW_POWER, + if ((hFrameData->sbrPatchingMode != + hSbrDec->SbrCalculateEnvelope.sbrPatchingMode)) { + ResetLimiterBands(hHeaderData->freqBandData.limiterBandTable, + &hHeaderData->freqBandData.noLimiterBands, + hHeaderData->freqBandData.freqBandTable[0], + hHeaderData->freqBandData.nSfb[0], + hSbrDec->LppTrans.pSettings->patchParam, + hSbrDec->LppTrans.pSettings->noOfPatches, + hHeaderData->bs_data.limiterBands, + hFrameData->sbrPatchingMode, + (flags & SBRDEC_USAC_HARMONICSBR) && + (hFrameData->sbrPatchingMode == 0) + ? GetxOverBandQmfTransposer(hSbrDec->hHBE) + : NULL, + Get41SbrQmfTransposer(hSbrDec->hHBE)); + + hSbrDec->SbrCalculateEnvelope.sbrPatchingMode = + hFrameData->sbrPatchingMode; + } + + calculateSbrEnvelope( + &hSbrDec->qmfDomainInCh->scaling, &hSbrDec->SbrCalculateEnvelope, + hHeaderData, hFrameData, &pvcDynamicData, pLowBandReal, pLowBandImag, + flags & SBRDEC_LOW_POWER, - degreeAlias, - flags, - (hHeaderData->frameErrorFlag || hPrevFrameData->frameErrorFlag)); + degreeAlias, flags, + (hHeaderData->frameErrorFlag || hPrevFrameData->frameErrorFlag)); +#if (SBRDEC_MAX_HB_FADE_FRAMES > 0) + /* Avoid hard onsets of high band */ + if (hHeaderData->frameErrorFlag) { + if (hSbrDec->highBandFadeCnt < SBRDEC_MAX_HB_FADE_FRAMES) { + hSbrDec->highBandFadeCnt += 1; + } + } else { + if (hSbrDec->highBandFadeCnt > + 0) { /* Manipulate high band scale factor to get a smooth fade-in */ + hSbrDec->qmfDomainInCh->scaling.hb_scale += hSbrDec->highBandFadeCnt; + hSbrDec->qmfDomainInCh->scaling.hb_scale = + fMin(hSbrDec->qmfDomainInCh->scaling.hb_scale, DFRACT_BITS - 1); + hSbrDec->highBandFadeCnt -= 1; + } + } +#endif /* Update hPrevFrameData (to be used in the next frame) */ - for (i=0; i<hHeaderData->freqBandData.nInvfBands; i++) { + for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) { hPrevFrameData->sbr_invf_mode[i] = hFrameData->sbr_invf_mode[i]; } hPrevFrameData->coupling = hFrameData->coupling; hPrevFrameData->stopPos = borders[hFrameData->frameInfo.nEnvelopes]; hPrevFrameData->ampRes = hFrameData->ampResolutionCurrentFrame; - } - else { - /* Reset hb_scale if no highband is present, because hb_scale is considered in the QMF-synthesis */ - hSbrDec->sbrScaleFactor.hb_scale = saveLbScale; + hPrevFrameData->prevSbrPitchInBins = hFrameData->sbrPitchInBins; + /* could be done in extractFrameInfo_pvc() but hPrevFrameData is not + * available there */ + FDKmemcpy(&hPrevFrameData->prevFrameInfo, &hFrameData->frameInfo, + sizeof(FRAME_INFO)); + } else { + /* rescale from lsb to nAnalysisBands in order to compensate scaling with + * hb_scale in this area, done by synthesisFiltering*/ + int rescale; + int lsb; + int length; + + /* Reset hb_scale if no highband is present, because hb_scale is considered + * in the QMF-synthesis */ + hSbrDec->qmfDomainInCh->scaling.hb_scale = saveLbScale; + + rescale = hSbrDec->qmfDomainInCh->scaling.hb_scale - + hSbrDec->qmfDomainInCh->scaling.ov_lb_scale; + lsb = hSbrDec->qmfDomainOutCh->fb.lsb; + length = (hSbrDec->qmfDomainInCh->fb.no_channels - lsb); + + if ((rescale < 0) && (length > 0)) { + if (!(flags & SBRDEC_LOW_POWER)) { + for (i = 0; i < ov_len; i++) { + scaleValues(&pLowBandReal[i][lsb], length, rescale); + scaleValues(&pLowBandImag[i][lsb], length, rescale); + } + } else { + for (i = 0; i < ov_len; i++) { + scaleValues(&pLowBandReal[i][lsb], length, rescale); + } + } + } } + if (!(flags & SBRDEC_USAC_HARMONICSBR)) { + int length = hSbrDec->qmfDomainInCh->fb.lsb; + if (flags & SBRDEC_SYNTAX_USAC) { + length = hSbrDec->qmfDomainInCh->fb.no_channels; + } - for (i=0; i<LPC_ORDER; i++){ - /* - Store the unmodified qmf Slots values (required for LPC filtering) - */ - if (! (flags & SBRDEC_LOW_POWER)) { - FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesReal[i], QmfBufferReal[noCols-LPC_ORDER+i], hSbrDec->AnalysiscQMF.lsb*sizeof(FIXP_DBL)); - FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesImag[i], QmfBufferImag[noCols-LPC_ORDER+i], hSbrDec->AnalysiscQMF.lsb*sizeof(FIXP_DBL)); - } else - FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesReal[i], QmfBufferReal[noCols-LPC_ORDER+i], hSbrDec->AnalysiscQMF.lsb*sizeof(FIXP_DBL)); + /* in case of legacy sbr saving of filter states here */ + for (i = 0; i < LPC_ORDER + ov_len; i++) { + /* + Store the unmodified qmf Slots values (required for LPC filtering) + */ + if (!(flags & SBRDEC_LOW_POWER)) { + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], + pLowBandReal[noCols - LPC_ORDER + i], + length * sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], + pLowBandImag[noCols - LPC_ORDER + i], + length * sizeof(FIXP_DBL)); + } else + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], + pLowBandReal[noCols - LPC_ORDER + i], + length * sizeof(FIXP_DBL)); + } } /* Synthesis subband filtering. */ - if ( ! (flags & SBRDEC_PS_DECODED) ) { - - { + if (!(flags & SBRDEC_PS_DECODED)) { + if (!(flags & SBRDEC_SKIP_QMF_SYN)) { int outScalefactor = 0; if (h_ps_d != NULL) { - h_ps_d->procFrameBased = 1; /* we here do frame based processing */ + h_ps_d->procFrameBased = 1; /* we here do frame based processing */ } + sbrDecoder_drcApply(&hSbrDec->sbrDrcChannel, pLowBandReal, + (flags & SBRDEC_LOW_POWER) ? NULL : pLowBandImag, + hSbrDec->qmfDomainOutCh->fb.no_col, &outScalefactor); - sbrDecoder_drcApply(&hSbrDec->sbrDrcChannel, - QmfBufferReal, - (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag, - hSbrDec->SynthesisQMF.no_col, - &outScalefactor - ); - - - - qmfChangeOutScalefactor(&hSbrDec->SynthesisQMF, outScalefactor ); + qmfChangeOutScalefactor(&hSbrDec->qmfDomainOutCh->fb, outScalefactor); { - C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2*(64)); - - qmfSynthesisFiltering( &hSbrDec->SynthesisQMF, - QmfBufferReal, - (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag, - &hSbrDec->sbrScaleFactor, - hSbrDec->LppTrans.pSettings->overlap, - timeOut, - strideOut, - qmfTemp); - - C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2*(64)); + HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; + int save_usb = hSbrDec->qmfDomainOutCh->fb.usb; + +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#else + C_AALLOC_STACK_START(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#endif + if (hSbrDec->qmfDomainOutCh->fb.usb < hFreq->ov_highSubband) { + /* we need to patch usb for this frame as overlap may contain higher + frequency range if headerchange occured; fb. usb is always limited + to maximum fb.no_channels; In case of wrongly decoded headers it + might be that ov_highSubband is higher than the number of synthesis + channels (fb.no_channels), which is forbidden, therefore we need to + limit ov_highSubband with fMin function to avoid not allowed usb in + synthesis filterbank. */ + hSbrDec->qmfDomainOutCh->fb.usb = + fMin((UINT)hFreq->ov_highSubband, + (UINT)hSbrDec->qmfDomainOutCh->fb.no_channels); + } + { + qmfSynthesisFiltering( + &hSbrDec->qmfDomainOutCh->fb, pLowBandReal, + (flags & SBRDEC_LOW_POWER) ? NULL : pLowBandImag, + &hSbrDec->qmfDomainInCh->scaling, + hSbrDec->LppTrans.pSettings->overlap, timeOut, strideOut, + qmfTemp); + } + /* restore saved value */ + hSbrDec->qmfDomainOutCh->fb.usb = save_usb; + hFreq->ov_highSubband = save_usb; +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#else + C_AALLOC_STACK_END(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#endif } - } } else { /* (flags & SBRDEC_PS_DECODED) */ - INT i, sdiff, outScalefactor, scaleFactorLowBand, scaleFactorHighBand; - SCHAR scaleFactorLowBand_ov, scaleFactorLowBand_no_ov; + INT sdiff; + INT scaleFactorHighBand, scaleFactorLowBand_ov, scaleFactorLowBand_no_ov; - HANDLE_QMF_FILTER_BANK synQmf = &hSbrDec->SynthesisQMF; - HANDLE_QMF_FILTER_BANK synQmfRight = &hSbrDecRight->SynthesisQMF; + HANDLE_QMF_FILTER_BANK synQmf = &hSbrDec->qmfDomainOutCh->fb; + HANDLE_QMF_FILTER_BANK synQmfRight = &hSbrDecRight->qmfDomainOutCh->fb; /* adapt scaling */ - sdiff = hSbrDec->sbrScaleFactor.lb_scale - reserve; /* Scaling difference */ - scaleFactorHighBand = sdiff - hSbrDec->sbrScaleFactor.hb_scale; /* Scale of current high band */ - scaleFactorLowBand_ov = sdiff - hSbrDec->sbrScaleFactor.ov_lb_scale; /* Scale of low band overlapping QMF data */ - scaleFactorLowBand_no_ov = sdiff - hSbrDec->sbrScaleFactor.lb_scale; /* Scale of low band current QMF data */ - outScalefactor = 0; /* Initial output scale */ - - if (h_ps_d->procFrameBased == 1) /* If we have switched from frame to slot based processing copy filter states */ - { /* procFrameBased will be unset later */ + sdiff = hSbrDec->qmfDomainInCh->scaling.lb_scale - + reserve; /* Scaling difference */ + scaleFactorHighBand = sdiff - hSbrDec->qmfDomainInCh->scaling.hb_scale; + scaleFactorLowBand_ov = sdiff - hSbrDec->qmfDomainInCh->scaling.ov_lb_scale; + scaleFactorLowBand_no_ov = sdiff - hSbrDec->qmfDomainInCh->scaling.lb_scale; + + /* Scale of low band overlapping QMF data */ + scaleFactorLowBand_ov = + fMin(DFRACT_BITS - 1, fMax(-(DFRACT_BITS - 1), scaleFactorLowBand_ov)); + /* Scale of low band current QMF data */ + scaleFactorLowBand_no_ov = fMin( + DFRACT_BITS - 1, fMax(-(DFRACT_BITS - 1), scaleFactorLowBand_no_ov)); + /* Scale of current high band */ + scaleFactorHighBand = + fMin(DFRACT_BITS - 1, fMax(-(DFRACT_BITS - 1), scaleFactorHighBand)); + + if (h_ps_d->procFrameBased == 1) /* If we have switched from frame to slot + based processing copy filter states */ + { /* procFrameBased will be unset later */ /* copy filter states from left to right */ - FDKmemcpy(synQmfRight->FilterStates, synQmf->FilterStates, ((640)-(64))*sizeof(FIXP_QSS)); + /* was ((640)-(64))*sizeof(FIXP_QSS) + flexible amount of synthesis bands needed for QMF based resampling + */ + FDK_ASSERT(hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis <= + QMF_MAX_SYNTHESIS_BANDS); + FDKmemcpy(synQmfRight->FilterStates, synQmf->FilterStates, + 9 * hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis * + sizeof(FIXP_QSS)); } - /* scale ALL qmf vales ( real and imag ) of mono / left channel to the - same scale factor ( ov_lb_sf, lb_sf and hq_sf ) */ - scalFilterBankValues( h_ps_d, /* parametric stereo decoder handle */ - QmfBufferReal, /* qmf filterbank values */ - QmfBufferImag, /* qmf filterbank values */ - synQmf->lsb, /* sbr start subband */ - hSbrDec->sbrScaleFactor.ov_lb_scale, - hSbrDec->sbrScaleFactor.lb_scale, - &scaleFactorLowBand_ov, /* adapt scaling values */ - &scaleFactorLowBand_no_ov, /* adapt scaling values */ - hSbrDec->sbrScaleFactor.hb_scale, /* current frame ( highband ) */ - &scaleFactorHighBand, - synQmf->no_col); + /* Feed delaylines when parametric stereo is switched on. */ + PreparePsProcessing(h_ps_d, pLowBandReal, pLowBandImag, + scaleFactorLowBand_ov); /* use the same synthese qmf values for left and right channel */ synQmfRight->no_col = synQmf->no_col; - synQmfRight->lsb = synQmf->lsb; - synQmfRight->usb = synQmf->usb; + synQmfRight->lsb = synQmf->lsb; + synQmfRight->usb = synQmf->usb; - int env=0; - - outScalefactor += (SCAL_HEADROOM+1); /* psDiffScale! */ + int env = 0; { - C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, 2*(64)); +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, + 2 * QMF_MAX_SYNTHESIS_BANDS); +#else + C_AALLOC_STACK_START(pWorkBuffer, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#endif int maxShift = 0; @@ -642,99 +781,80 @@ sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ } } - /* copy DRC data to right channel (with PS both channels use the same DRC gains) */ - FDKmemcpy(&hSbrDecRight->sbrDrcChannel, &hSbrDec->sbrDrcChannel, sizeof(SBRDEC_DRC_CHANNEL)); + /* copy DRC data to right channel (with PS both channels use the same DRC + * gains) */ + FDKmemcpy(&hSbrDecRight->sbrDrcChannel, &hSbrDec->sbrDrcChannel, + sizeof(SBRDEC_DRC_CHANNEL)); - for (i = 0; i < synQmf->no_col; i++) { /* ----- no_col loop ----- */ + for (i = 0; i < synQmf->no_col; i++) { /* ----- no_col loop ----- */ INT outScalefactorR, outScalefactorL; - outScalefactorR = outScalefactorL = outScalefactor; /* qmf timeslot of right channel */ - FIXP_DBL* rQmfReal = pWorkBuffer; - FIXP_DBL* rQmfImag = pWorkBuffer + 64; - + FIXP_DBL *rQmfReal = pWorkBuffer; + FIXP_DBL *rQmfImag = pWorkBuffer + synQmf->no_channels; { - if ( i == h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env] ) { - initSlotBasedRotation( h_ps_d, env, hHeaderData->freqBandData.highSubband ); + if (i == + h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env]) { + initSlotBasedRotation(h_ps_d, env, + hHeaderData->freqBandData.highSubband); env++; } - ApplyPsSlot( h_ps_d, /* parametric stereo decoder handle */ - (QmfBufferReal + i), /* one timeslot of left/mono channel */ - (QmfBufferImag + i), /* one timeslot of left/mono channel */ - rQmfReal, /* one timeslot or right channel */ - rQmfImag); /* one timeslot or right channel */ + ApplyPsSlot( + h_ps_d, /* parametric stereo decoder handle */ + (pLowBandReal + i), /* one timeslot of left/mono channel */ + (pLowBandImag + i), /* one timeslot of left/mono channel */ + rQmfReal, /* one timeslot or right channel */ + rQmfImag, /* one timeslot or right channel */ + scaleFactorLowBand_no_ov, + (i < hSbrDec->LppTrans.pSettings->overlap) + ? scaleFactorLowBand_ov + : scaleFactorLowBand_no_ov, + scaleFactorHighBand, synQmf->lsb, synQmf->usb); + + outScalefactorL = outScalefactorR = 1; /* psDiffScale! (MPEG-PS) */ } - - scaleFactorLowBand = (i<(6)) ? scaleFactorLowBand_ov : scaleFactorLowBand_no_ov; - - - sbrDecoder_drcApplySlot ( /* right channel */ - &hSbrDecRight->sbrDrcChannel, - rQmfReal, - rQmfImag, - i, - synQmfRight->no_col, - maxShift - ); + sbrDecoder_drcApplySlot(/* right channel */ + &hSbrDecRight->sbrDrcChannel, rQmfReal, + rQmfImag, i, synQmfRight->no_col, maxShift); outScalefactorR += maxShift; - sbrDecoder_drcApplySlot ( /* left channel */ - &hSbrDec->sbrDrcChannel, - *(QmfBufferReal + i), - *(QmfBufferImag + i), - i, - synQmf->no_col, - maxShift - ); + sbrDecoder_drcApplySlot(/* left channel */ + &hSbrDec->sbrDrcChannel, *(pLowBandReal + i), + *(pLowBandImag + i), i, synQmf->no_col, + maxShift); outScalefactorL += maxShift; - - /* scale filter states for left and right channel */ - qmfChangeOutScalefactor( synQmf, outScalefactorL ); - qmfChangeOutScalefactor( synQmfRight, outScalefactorR ); - - { - - qmfSynthesisFilteringSlot( synQmfRight, - rQmfReal, /* QMF real buffer */ - rQmfImag, /* QMF imag buffer */ - scaleFactorLowBand, - scaleFactorHighBand, - timeOutRight+(i*synQmf->no_channels*strideOut), - strideOut, - pWorkBuffer); - - qmfSynthesisFilteringSlot( synQmf, - *(QmfBufferReal + i), /* QMF real buffer */ - *(QmfBufferImag + i), /* QMF imag buffer */ - scaleFactorLowBand, - scaleFactorHighBand, - timeOut+(i*synQmf->no_channels*strideOut), - strideOut, - pWorkBuffer); - + if (!(flags & SBRDEC_SKIP_QMF_SYN)) { + qmfSynthesisFilteringSlot( + synQmfRight, rQmfReal, /* QMF real buffer */ + rQmfImag, /* QMF imag buffer */ + outScalefactorL, outScalefactorL, + timeOutRight + (i * synQmf->no_channels * strideOut), strideOut, + pWorkBuffer); + + qmfSynthesisFilteringSlot( + synQmf, *(pLowBandReal + i), /* QMF real buffer */ + *(pLowBandImag + i), /* QMF imag buffer */ + outScalefactorR, outScalefactorR, + timeOut + (i * synQmf->no_channels * strideOut), strideOut, + pWorkBuffer); } } /* no_col loop i */ - - /* scale back (6) timeslots look ahead for hybrid filterbank to original value */ - rescalFilterBankValues( h_ps_d, - QmfBufferReal, - QmfBufferImag, - synQmf->lsb, - synQmf->no_col ); - - C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, 2*(64)); +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#else + C_AALLOC_STACK_END(pWorkBuffer, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#endif } } - sbrDecoder_drcUpdateChannel( &hSbrDec->sbrDrcChannel ); - + sbrDecoder_drcUpdateChannel(&hSbrDec->sbrDrcChannel); /* Update overlap buffer @@ -742,150 +862,127 @@ sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ the stop frequency raises. */ - if (hSbrDec->LppTrans.pSettings->overlap > 0) - { - if (! (flags & SBRDEC_LOW_POWER)) { - for ( i=0; i<hSbrDec->LppTrans.pSettings->overlap; i++ ) { - FDKmemcpy(QmfBufferReal[i], QmfBufferReal[i+noCols], (64)*sizeof(FIXP_DBL)); - FDKmemcpy(QmfBufferImag[i], QmfBufferImag[i+noCols], (64)*sizeof(FIXP_DBL)); - } - } else - for ( i=0; i<hSbrDec->LppTrans.pSettings->overlap; i++ ) { - FDKmemcpy(QmfBufferReal[i], QmfBufferReal[i+noCols], (64)*sizeof(FIXP_DBL)); - } + if (!(flags & SBRDEC_SKIP_QMF_SYN)) { + { + FDK_QmfDomain_SaveOverlap(hSbrDec->qmfDomainInCh, 0); + FDK_ASSERT(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale == saveLbScale); + } } - hSbrDec->sbrScaleFactor.ov_lb_scale = saveLbScale; + hSbrDec->savedStates = 0; /* Save current frame status */ hPrevFrameData->frameErrorFlag = hHeaderData->frameErrorFlag; + hSbrDec->applySbrProc_old = applyProcessing; -} // sbr_dec() - +} /* sbr_dec() */ /*! \brief Creates sbr decoder structure \return errorCode, 0 if successful */ SBR_ERROR -createSbrDec (SBR_CHANNEL * hSbrChannel, - HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ - TRANSPOSER_SETTINGS *pSettings, - const int downsampleFac, /*!< Downsampling factor */ - const UINT qmfFlags, /*!< flags -> 1: HQ/LP selector, 2: CLDFB */ - const UINT flags, - const int overlap, - int chan) /*!< Channel for which to assign buffers etc. */ +createSbrDec(SBR_CHANNEL *hSbrChannel, + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + TRANSPOSER_SETTINGS *pSettings, + const int downsampleFac, /*!< Downsampling factor */ + const UINT qmfFlags, /*!< flags -> 1: HQ/LP selector, 2: CLDFB */ + const UINT flags, const int overlap, + int chan, /*!< Channel for which to assign buffers etc. */ + int codecFrameSize) { SBR_ERROR err = SBRDEC_OK; - int timeSlots = hHeaderData->numberTimeSlots; /* Number of SBR slots per frame */ - int noCols = timeSlots * hHeaderData->timeStep; /* Number of QMF slots per frame */ + int timeSlots = + hHeaderData->numberTimeSlots; /* Number of SBR slots per frame */ + int noCols = + timeSlots * hHeaderData->timeStep; /* Number of QMF slots per frame */ HANDLE_SBR_DEC hs = &(hSbrChannel->SbrDec); - /* Initialize scale factors */ - hs->sbrScaleFactor.ov_lb_scale = 0; - hs->sbrScaleFactor.ov_hb_scale = 0; - hs->sbrScaleFactor.hb_scale = 0; +#if (SBRDEC_MAX_HB_FADE_FRAMES > 0) + hs->highBandFadeCnt = SBRDEC_MAX_HB_FADE_FRAMES; + +#endif + hs->scale_hbe = 15; + hs->scale_lb = 15; + hs->scale_ov = 15; + hs->prev_frame_lSbr = 0; + hs->prev_frame_hbeSbr = 0; + + hs->codecFrameSize = codecFrameSize; /* create envelope calculator */ - err = createSbrEnvelopeCalc (&hs->SbrCalculateEnvelope, - hHeaderData, - chan, - flags); + err = createSbrEnvelopeCalc(&hs->SbrCalculateEnvelope, hHeaderData, chan, + flags); if (err != SBRDEC_OK) { return err; } - /* - create QMF filter banks - */ - { - int qmfErr; - /* Adapted QMF analysis post-twiddles for down-sampled HQ SBR */ - const UINT downSampledFlag = (flags & SBRDEC_DOWNSAMPLE) ? QMF_FLAG_DOWNSAMPLED : 0; - - qmfErr = qmfInitAnalysisFilterBank ( - &hs->AnalysiscQMF, - hs->anaQmfStates, - noCols, - hHeaderData->freqBandData.lowSubband, - hHeaderData->freqBandData.highSubband, - hHeaderData->numberOfAnalysisBands, - (qmfFlags & (~QMF_FLAG_KEEP_STATES)) | downSampledFlag - ); - if (qmfErr != 0) { - return SBRDEC_UNSUPPORTED_CONFIG; - } - } - if (hs->pSynQmfStates == NULL) { - hs->pSynQmfStates = GetRam_sbr_QmfStatesSynthesis(chan); - if (hs->pSynQmfStates == NULL) - return SBRDEC_MEM_ALLOC_FAILED; - } - - { - int qmfErr; - - qmfErr = qmfInitSynthesisFilterBank ( - &hs->SynthesisQMF, - hs->pSynQmfStates, - noCols, - hHeaderData->freqBandData.lowSubband, - hHeaderData->freqBandData.highSubband, - (64) / downsampleFac, - qmfFlags & (~QMF_FLAG_KEEP_STATES) - ); - - if (qmfErr != 0) { - return SBRDEC_UNSUPPORTED_CONFIG; - } - } - initSbrPrevFrameData (&hSbrChannel->prevFrameData, timeSlots); + initSbrPrevFrameData(&hSbrChannel->prevFrameData, timeSlots); /* create transposer */ - err = createLppTransposer (&hs->LppTrans, - pSettings, - hHeaderData->freqBandData.lowSubband, - hHeaderData->freqBandData.v_k_master, - hHeaderData->freqBandData.numMaster, - hs->SynthesisQMF.usb, - timeSlots, - hs->AnalysiscQMF.no_col, - hHeaderData->freqBandData.freqBandTableNoise, - hHeaderData->freqBandData.nNfb, - hHeaderData->sbrProcSmplRate, - chan, - overlap ); + err = createLppTransposer( + &hs->LppTrans, pSettings, hHeaderData->freqBandData.lowSubband, + hHeaderData->freqBandData.v_k_master, hHeaderData->freqBandData.numMaster, + hHeaderData->freqBandData.highSubband, timeSlots, noCols, + hHeaderData->freqBandData.freqBandTableNoise, + hHeaderData->freqBandData.nNfb, hHeaderData->sbrProcSmplRate, chan, + overlap); if (err != SBRDEC_OK) { return err; } - /* The CLDFB does not have overlap */ - if ((qmfFlags & QMF_FLAG_CLDFB) == 0) { - if (hs->pSbrOverlapBuffer == NULL) { - hs->pSbrOverlapBuffer = GetRam_sbr_OverlapBuffer(chan); - if (hs->pSbrOverlapBuffer == NULL) { - return SBRDEC_MEM_ALLOC_FAILED; - } - } else { - /* Clear overlap buffer */ - FDKmemclear( hs->pSbrOverlapBuffer, - sizeof(FIXP_DBL) * 2 * (6) * (64) - ); + if (flags & SBRDEC_USAC_HARMONICSBR) { + int noChannels, bSbr41 = flags & SBRDEC_QUAD_RATE ? 1 : 0; + + noChannels = + QMF_SYNTH_CHANNELS / + ((bSbr41 + 1) * 2); /* 32 for (32:64 and 24:64) and 16 for 16:64 */ + + /* shared memory between hbeLightTimeDelayBuffer and hQmfHBESlotsReal if + * SBRDEC_HBE_ENABLE */ + hSbrChannel->SbrDec.tmp_memory = (FIXP_DBL **)fdkCallocMatrix2D_aligned( + noCols, noChannels, sizeof(FIXP_DBL)); + if (hSbrChannel->SbrDec.tmp_memory == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; } - } - /* Clear input delay line */ - FDKmemclear(hs->coreDelayBuf, (96)*sizeof(INT_PCM)); + hSbrChannel->SbrDec.hQmfHBESlotsReal = hSbrChannel->SbrDec.tmp_memory; + hSbrChannel->SbrDec.hQmfHBESlotsImag = + (FIXP_DBL **)fdkCallocMatrix2D_aligned(noCols, noChannels, + sizeof(FIXP_DBL)); + if (hSbrChannel->SbrDec.hQmfHBESlotsImag == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } - /* assign qmf time slots */ - assignTimeSlots( &hSbrChannel->SbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, qmfFlags & QMF_FLAG_LP); + /* buffers containing unmodified qmf data; required when switching from + * legacy SBR to HBE */ + /* buffer can be used as LPCFilterstates buffer because legacy SBR needs + * exactly these values for LPC filtering */ + hSbrChannel->SbrDec.codecQMFBufferReal = + (FIXP_DBL **)fdkCallocMatrix2D_aligned(noCols, noChannels, + sizeof(FIXP_DBL)); + if (hSbrChannel->SbrDec.codecQMFBufferReal == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + + hSbrChannel->SbrDec.codecQMFBufferImag = + (FIXP_DBL **)fdkCallocMatrix2D_aligned(noCols, noChannels, + sizeof(FIXP_DBL)); + if (hSbrChannel->SbrDec.codecQMFBufferImag == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + + err = QmfTransposerCreate(&hs->hHBE, codecFrameSize, 0, bSbr41); + if (err != SBRDEC_OK) { + return err; + } + } return err; } @@ -894,65 +991,88 @@ createSbrDec (SBR_CHANNEL * hSbrChannel, \brief Delete sbr decoder structure \return errorCode, 0 if successful */ -int -deleteSbrDec (SBR_CHANNEL * hSbrChannel) -{ +int deleteSbrDec(SBR_CHANNEL *hSbrChannel) { HANDLE_SBR_DEC hs = &hSbrChannel->SbrDec; - deleteSbrEnvelopeCalc (&hs->SbrCalculateEnvelope); + deleteSbrEnvelopeCalc(&hs->SbrCalculateEnvelope); - /* delete QMF filter states */ - if (hs->pSynQmfStates != NULL) { - FreeRam_sbr_QmfStatesSynthesis(&hs->pSynQmfStates); + if (hs->tmp_memory != NULL) { + FDK_FREE_MEMORY_2D_ALIGNED(hs->tmp_memory); } + /* modify here */ + FDK_FREE_MEMORY_2D_ALIGNED(hs->hQmfHBESlotsImag); + + if (hs->hHBE != NULL) QmfTransposerClose(hs->hHBE); + + if (hs->codecQMFBufferReal != NULL) { + FDK_FREE_MEMORY_2D_ALIGNED(hs->codecQMFBufferReal); + } - if (hs->pSbrOverlapBuffer != NULL) { - FreeRam_sbr_OverlapBuffer(&hs->pSbrOverlapBuffer); + if (hs->codecQMFBufferImag != NULL) { + FDK_FREE_MEMORY_2D_ALIGNED(hs->codecQMFBufferImag); } return 0; } - /*! \brief resets sbr decoder structure \return errorCode, 0 if successful */ SBR_ERROR -resetSbrDec (HANDLE_SBR_DEC hSbrDec, - HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, - const int useLP, - const int downsampleFac - ) -{ +resetSbrDec(HANDLE_SBR_DEC hSbrDec, HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, const int downsampleFac, + const UINT flags, HANDLE_SBR_FRAME_DATA hFrameData) { SBR_ERROR sbrError = SBRDEC_OK; - - int old_lsb = hSbrDec->SynthesisQMF.lsb; + int i; + FIXP_DBL *pLowBandReal[128]; + FIXP_DBL *pLowBandImag[128]; + int useLP = flags & SBRDEC_LOW_POWER; + + int old_lsb = hSbrDec->qmfDomainInCh->fb.lsb; + int old_usb = hSbrDec->qmfDomainInCh->fb.usb; int new_lsb = hHeaderData->freqBandData.lowSubband; + /* int new_usb = hHeaderData->freqBandData.highSubband; */ int l, startBand, stopBand, startSlot, size; - int source_scale, target_scale, delta_scale, target_lsb, target_usb, reserve; - FIXP_DBL maxVal; - - /* overlapBuffer point to first (6) slots */ - FIXP_DBL **OverlapBufferReal = hSbrDec->QmfBufferReal; - FIXP_DBL **OverlapBufferImag = hSbrDec->QmfBufferImag; - - /* assign qmf time slots */ - assignTimeSlots( hSbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, useLP); - - + FIXP_DBL **OverlapBufferReal = hSbrDec->qmfDomainInCh->hQmfSlotsReal; + FIXP_DBL **OverlapBufferImag = hSbrDec->qmfDomainInCh->hQmfSlotsImag; - resetSbrEnvelopeCalc (&hSbrDec->SbrCalculateEnvelope); - - hSbrDec->SynthesisQMF.lsb = hHeaderData->freqBandData.lowSubband; - hSbrDec->SynthesisQMF.usb = fixMin((INT)hSbrDec->SynthesisQMF.no_channels, (INT)hHeaderData->freqBandData.highSubband); + /* in case the previous frame was not active in terms of SBR processing, the + full band from 0 to no_channels was rescaled and not overwritten. Thats why + the scaling factor lb_scale can be seen as assigned to all bands from 0 to + no_channels in the previous frame. The same states for the current frame if + the current frame is not active in terms of SBR processing + */ + int applySbrProc = (hHeaderData->syncState == SBR_ACTIVE || + (hHeaderData->frameErrorFlag == 0 && + hHeaderData->syncState == SBR_HEADER)); + int applySbrProc_old = hSbrDec->applySbrProc_old; - hSbrDec->AnalysiscQMF.lsb = hSbrDec->SynthesisQMF.lsb; - hSbrDec->AnalysiscQMF.usb = hSbrDec->SynthesisQMF.usb; + if (!applySbrProc) { + new_lsb = (hSbrDec->qmfDomainInCh->fb).no_channels; + } + if (!applySbrProc_old) { + old_lsb = (hSbrDec->qmfDomainInCh->fb).no_channels; + old_usb = old_lsb; + } + resetSbrEnvelopeCalc(&hSbrDec->SbrCalculateEnvelope); + + /* Change lsb and usb */ + /* Synthesis */ + FDK_ASSERT(hSbrDec->qmfDomainOutCh != NULL); + hSbrDec->qmfDomainOutCh->fb.lsb = + fixMin((INT)hSbrDec->qmfDomainOutCh->fb.no_channels, + (INT)hHeaderData->freqBandData.lowSubband); + hSbrDec->qmfDomainOutCh->fb.usb = + fixMin((INT)hSbrDec->qmfDomainOutCh->fb.no_channels, + (INT)hHeaderData->freqBandData.highSubband); + /* Analysis */ + FDK_ASSERT(hSbrDec->qmfDomainInCh != NULL); + hSbrDec->qmfDomainInCh->fb.lsb = hSbrDec->qmfDomainOutCh->fb.lsb; + hSbrDec->qmfDomainInCh->fb.usb = hSbrDec->qmfDomainOutCh->fb.usb; /* The following initialization of spectral data in the overlap buffer @@ -964,135 +1084,397 @@ resetSbrDec (HANDLE_SBR_DEC hSbrDec, must be cleared because the whitening would be affected */ startBand = old_lsb; - stopBand = new_lsb; - startSlot = hHeaderData->timeStep * (hPrevFrameData->stopPos - hHeaderData->numberTimeSlots); - size = fixMax(0,stopBand-startBand); - - /* keep already adjusted data in the x-over-area */ - if (!useLP) { - for (l=startSlot; l<hSbrDec->LppTrans.pSettings->overlap; l++) { - FDKmemclear(&OverlapBufferReal[l][startBand], size*sizeof(FIXP_DBL)); - FDKmemclear(&OverlapBufferImag[l][startBand], size*sizeof(FIXP_DBL)); + stopBand = new_lsb; + startSlot = fMax(0, hHeaderData->timeStep * (hPrevFrameData->stopPos - + hHeaderData->numberTimeSlots)); + size = fMax(0, stopBand - startBand); + + /* in case of USAC we don't want to zero out the memory, as this can lead to + holes in the spectrum; fix shall only be applied for USAC not for MPEG-4 + SBR, in this case setting zero remains */ + if (!(flags & SBRDEC_SYNTAX_USAC)) { + /* keep already adjusted data in the x-over-area */ + if (!useLP) { + for (l = startSlot; l < hSbrDec->LppTrans.pSettings->overlap; l++) { + FDKmemclear(&OverlapBufferReal[l][startBand], size * sizeof(FIXP_DBL)); + FDKmemclear(&OverlapBufferImag[l][startBand], size * sizeof(FIXP_DBL)); + } + } else { + for (l = startSlot; l < hSbrDec->LppTrans.pSettings->overlap; l++) { + FDKmemclear(&OverlapBufferReal[l][startBand], size * sizeof(FIXP_DBL)); + } } - } else - for (l=startSlot; l<hSbrDec->LppTrans.pSettings->overlap ; l++) { - FDKmemclear(&OverlapBufferReal[l][startBand], size*sizeof(FIXP_DBL)); - } - - /* + /* reset LPC filter states - */ - startBand = fixMin(old_lsb,new_lsb); - stopBand = fixMax(old_lsb,new_lsb); - size = fixMax(0,stopBand-startBand); - - FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesReal[0][startBand], size*sizeof(FIXP_DBL)); - FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesReal[1][startBand], size*sizeof(FIXP_DBL)); - if (!useLP) { - FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImag[0][startBand], size*sizeof(FIXP_DBL)); - FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImag[1][startBand], size*sizeof(FIXP_DBL)); + */ + startBand = fixMin(old_lsb, new_lsb); + stopBand = fixMax(old_lsb, new_lsb); + size = fixMax(0, stopBand - startBand); + + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[0][startBand], + size * sizeof(FIXP_DBL)); + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[1][startBand], + size * sizeof(FIXP_DBL)); + if (!useLP) { + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[0][startBand], + size * sizeof(FIXP_DBL)); + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[1][startBand], + size * sizeof(FIXP_DBL)); + } } + if (startSlot != 0) { + int source_exp, target_exp, delta_exp, target_lsb, target_usb, reserve; + FIXP_DBL maxVal; - /* - Rescale already processed spectral data between old and new x-over frequency. - This must be done because of the separate scalefactors for lowband and highband. - */ - startBand = fixMin(old_lsb,new_lsb); - stopBand = fixMax(old_lsb,new_lsb); - - if (new_lsb > old_lsb) { - /* The x-over-area was part of the highband before and will now belong to the lowband */ - source_scale = hSbrDec->sbrScaleFactor.ov_hb_scale; - target_scale = hSbrDec->sbrScaleFactor.ov_lb_scale; - target_lsb = 0; - target_usb = old_lsb; - } - else { - /* The x-over-area was part of the lowband before and will now belong to the highband */ - source_scale = hSbrDec->sbrScaleFactor.ov_lb_scale; - target_scale = hSbrDec->sbrScaleFactor.ov_hb_scale; - /* jdr: The values old_lsb and old_usb might be wrong because the previous frame might have been "upsamling". */ - target_lsb = hSbrDec->SynthesisQMF.lsb; - target_usb = hSbrDec->SynthesisQMF.usb; - } + /* + Rescale already processed spectral data between old and new x-over + frequency. This must be done because of the separate scalefactors for + lowband and highband. + */ + + /* We have four relevant transitions to cover: + 1. old_usb is lower than new_lsb; old SBR area is completely below new SBR + area. + -> entire old area was highband and belongs to lowband now + and has to be rescaled. + 2. old_lsb is higher than new_usb; new SBR area is completely below old SBR + area. + -> old area between new_lsb and old_lsb was lowband and belongs to + highband now and has to be rescaled to match new highband scale. + 3. old_lsb is lower and old_usb is higher than new_lsb; old and new SBR + areas overlap. + -> old area between old_lsb and new_lsb was highband and belongs to + lowband now and has to be rescaled to match new lowband scale. + 4. new_lsb is lower and new_usb_is higher than old_lsb; old and new SBR + areas overlap. + -> old area between new_lsb and old_usb was lowband and belongs to + highband now and has to be rescaled to match new highband scale. + */ - /* Shift left all samples of the x-over-area as much as possible - An unnecessary coarse scale could cause ov_lb_scale or ov_hb_scale to be - adapted and the accuracy in the next frame would seriously suffer! */ + if (new_lsb > old_lsb) { + /* case 1 and 3 */ + source_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_hb_scale); + target_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale); + + startBand = old_lsb; + + if (new_lsb >= old_usb) { + /* case 1 */ + stopBand = old_usb; + } else { + /* case 3 */ + stopBand = new_lsb; + } - maxVal = maxSubbandSample( OverlapBufferReal, - (useLP) ? NULL : OverlapBufferImag, - startBand, - stopBand, - 0, - startSlot); + target_lsb = 0; + target_usb = old_lsb; + } else { + /* case 2 and 4 */ + source_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale); + target_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_hb_scale); - reserve = CntLeadingZeros(maxVal)-1; - reserve = fixMin(reserve,DFRACT_BITS-1-source_scale); + startBand = new_lsb; + stopBand = old_lsb; - rescaleSubbandSamples( OverlapBufferReal, - (useLP) ? NULL : OverlapBufferImag, - startBand, - stopBand, - 0, - startSlot, - reserve); - source_scale += reserve; + target_lsb = old_lsb; + target_usb = old_usb; + } - delta_scale = target_scale - source_scale; + maxVal = + maxSubbandSample(OverlapBufferReal, (useLP) ? NULL : OverlapBufferImag, + startBand, stopBand, 0, startSlot); - if (delta_scale > 0) { /* x-over-area is dominant */ - delta_scale = -delta_scale; - startBand = target_lsb; - stopBand = target_usb; + reserve = ((LONG)maxVal != 0 ? CntLeadingZeros(maxVal) - 1 : 0); + reserve = fixMin( + reserve, + DFRACT_BITS - 1 - + EXP2SCALE( + source_exp)); /* what is this line for, why do we need it? */ - if (new_lsb > old_lsb) { - /* The lowband has to be rescaled */ - hSbrDec->sbrScaleFactor.ov_lb_scale = source_scale; - } - else { - /* The highband has be be rescaled */ - hSbrDec->sbrScaleFactor.ov_hb_scale = source_scale; + /* process only if x-over-area is not dominant after rescale; + otherwise I'm not sure if all buffers are scaled correctly; + */ + if (target_exp - (source_exp - reserve) >= 0) { + rescaleSubbandSamples(OverlapBufferReal, + (useLP) ? NULL : OverlapBufferImag, startBand, + stopBand, 0, startSlot, reserve); + source_exp -= reserve; } - } - FDK_ASSERT(startBand <= stopBand); + delta_exp = target_exp - source_exp; + + if (delta_exp < 0) { /* x-over-area is dominant */ + startBand = target_lsb; + stopBand = target_usb; + delta_exp = -delta_exp; - if (!useLP) { - for (l=0; l<startSlot; l++) { - scaleValues( OverlapBufferReal[l] + startBand, stopBand-startBand, delta_scale ); - scaleValues( OverlapBufferImag[l] + startBand, stopBand-startBand, delta_scale ); + if (new_lsb > old_lsb) { + /* The lowband has to be rescaled */ + hSbrDec->qmfDomainInCh->scaling.ov_lb_scale = EXP2SCALE(source_exp); + } else { + /* The highband has to be rescaled */ + hSbrDec->qmfDomainInCh->scaling.ov_hb_scale = EXP2SCALE(source_exp); + } } - } else - for (l=0; l<startSlot; l++) { - scaleValues( OverlapBufferReal[l] + startBand, stopBand-startBand, delta_scale ); - } + FDK_ASSERT(startBand <= stopBand); + + if (!useLP) { + for (l = 0; l < startSlot; l++) { + scaleValues(OverlapBufferReal[l] + startBand, stopBand - startBand, + -delta_exp); + scaleValues(OverlapBufferImag[l] + startBand, stopBand - startBand, + -delta_exp); + } + } else + for (l = 0; l < startSlot; l++) { + scaleValues(OverlapBufferReal[l] + startBand, stopBand - startBand, + -delta_exp); + } + } /* startSlot != 0 */ /* Initialize transposer and limiter */ - sbrError = resetLppTransposer (&hSbrDec->LppTrans, - hHeaderData->freqBandData.lowSubband, - hHeaderData->freqBandData.v_k_master, - hHeaderData->freqBandData.numMaster, - hHeaderData->freqBandData.freqBandTableNoise, - hHeaderData->freqBandData.nNfb, - hHeaderData->freqBandData.highSubband, - hHeaderData->sbrProcSmplRate); - if (sbrError != SBRDEC_OK) - return sbrError; - - sbrError = ResetLimiterBands ( hHeaderData->freqBandData.limiterBandTable, - &hHeaderData->freqBandData.noLimiterBands, - hHeaderData->freqBandData.freqBandTable[0], - hHeaderData->freqBandData.nSfb[0], - hSbrDec->LppTrans.pSettings->patchParam, - hSbrDec->LppTrans.pSettings->noOfPatches, - hHeaderData->bs_data.limiterBands); + sbrError = resetLppTransposer( + &hSbrDec->LppTrans, hHeaderData->freqBandData.lowSubband, + hHeaderData->freqBandData.v_k_master, hHeaderData->freqBandData.numMaster, + hHeaderData->freqBandData.freqBandTableNoise, + hHeaderData->freqBandData.nNfb, hHeaderData->freqBandData.highSubband, + hHeaderData->sbrProcSmplRate); + if (sbrError != SBRDEC_OK) return sbrError; + + hSbrDec->savedStates = 0; + + if (flags & SBRDEC_USAC_HARMONICSBR) { + sbrError = QmfTransposerReInit(hSbrDec->hHBE, + hHeaderData->freqBandData.freqBandTable, + hHeaderData->freqBandData.nSfb); + if (sbrError != SBRDEC_OK) return sbrError; + + /* copy saved states from previous frame to legacy SBR lpc filterstate + * buffer */ + for (i = 0; i < LPC_ORDER + hSbrDec->LppTrans.pSettings->overlap; i++) { + FDKmemcpy( + hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], + hSbrDec->codecQMFBufferReal[hSbrDec->hHBE->noCols - LPC_ORDER - + hSbrDec->LppTrans.pSettings->overlap + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + FDKmemcpy( + hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], + hSbrDec->codecQMFBufferImag[hSbrDec->hHBE->noCols - LPC_ORDER - + hSbrDec->LppTrans.pSettings->overlap + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + } + hSbrDec->savedStates = 1; + + { + /* map QMF buffer to pointer array (Overlap + Frame)*/ + for (i = 0; i < hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER; i++) { + pLowBandReal[i] = hSbrDec->LppTrans.lpcFilterStatesRealHBE[i]; + pLowBandImag[i] = hSbrDec->LppTrans.lpcFilterStatesImagHBE[i]; + } + + /* map QMF buffer to pointer array (Overlap + Frame)*/ + for (i = 0; i < hSbrDec->hHBE->noCols; i++) { + pLowBandReal[i + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->codecQMFBufferReal[i]; + pLowBandImag[i + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->codecQMFBufferImag[i]; + } + + if (flags & SBRDEC_QUAD_RATE) { + if (hFrameData->sbrPatchingMode == 0) { + int *xOverQmf = GetxOverBandQmfTransposer(hSbrDec->hHBE); + + /* in case of harmonic SBR and no HBE_LP map additional buffer for + one more frame to pointer arry */ + for (i = 0; i < hSbrDec->hHBE->noCols / 2; i++) { + pLowBandReal[i + hSbrDec->hHBE->noCols + + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->hQmfHBESlotsReal[i]; + pLowBandImag[i + hSbrDec->hHBE->noCols + + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->hQmfHBESlotsImag[i]; + } + + QmfTransposerApply( + hSbrDec->hHBE, + pLowBandReal + hSbrDec->LppTrans.pSettings->overlap + + hSbrDec->hHBE->noCols / 2 + LPC_ORDER, + pLowBandImag + hSbrDec->LppTrans.pSettings->overlap + + hSbrDec->hHBE->noCols / 2 + LPC_ORDER, + hSbrDec->hHBE->noCols, pLowBandReal, pLowBandImag, + hSbrDec->LppTrans.lpcFilterStatesRealHBE, + hSbrDec->LppTrans.lpcFilterStatesImagHBE, + hPrevFrameData->prevSbrPitchInBins, hSbrDec->scale_lb, + hSbrDec->scale_hbe, &hSbrDec->qmfDomainInCh->scaling.hb_scale, + hHeaderData->timeStep, hFrameData->frameInfo.borders[0], + hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_OUTDIFF); + + copyHarmonicSpectrum( + xOverQmf, pLowBandReal, pLowBandImag, hSbrDec->hHBE->noCols, + hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_OUTDIFF); + } + } else { + /* in case of harmonic SBR and no HBE_LP map additional buffer for + one more frame to pointer arry */ + for (i = 0; i < hSbrDec->hHBE->noCols; i++) { + pLowBandReal[i + hSbrDec->hHBE->noCols + + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->hQmfHBESlotsReal[i]; + pLowBandImag[i + hSbrDec->hHBE->noCols + + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->hQmfHBESlotsImag[i]; + } + + if (hFrameData->sbrPatchingMode == 0) { + QmfTransposerApply( + hSbrDec->hHBE, + pLowBandReal + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER, + pLowBandImag + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER, + hSbrDec->hHBE->noCols, pLowBandReal, pLowBandImag, + hSbrDec->LppTrans.lpcFilterStatesRealHBE, + hSbrDec->LppTrans.lpcFilterStatesImagHBE, + 0 /* not required for keeping states updated in this frame*/, + hSbrDec->scale_lb, hSbrDec->scale_lb, + &hSbrDec->qmfDomainInCh->scaling.hb_scale, hHeaderData->timeStep, + hFrameData->frameInfo.borders[0], + hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_NOOUT); + } + + QmfTransposerApply( + hSbrDec->hHBE, + pLowBandReal + hSbrDec->LppTrans.pSettings->overlap + + hSbrDec->hHBE->noCols + LPC_ORDER, + pLowBandImag + hSbrDec->LppTrans.pSettings->overlap + + hSbrDec->hHBE->noCols + LPC_ORDER, + hSbrDec->hHBE->noCols, pLowBandReal, pLowBandImag, + hSbrDec->LppTrans.lpcFilterStatesRealHBE, + hSbrDec->LppTrans.lpcFilterStatesImagHBE, + hPrevFrameData->prevSbrPitchInBins, hSbrDec->scale_lb, + hSbrDec->scale_hbe, &hSbrDec->qmfDomainInCh->scaling.hb_scale, + hHeaderData->timeStep, hFrameData->frameInfo.borders[0], + hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_OUTDIFF); + } + + if (hFrameData->sbrPatchingMode == 0) { + for (i = startSlot; i < hSbrDec->LppTrans.pSettings->overlap; i++) { + /* + Store the unmodified qmf Slots values for upper part of spectrum + (required for LPC filtering) required if next frame is a HBE frame + */ + FDKmemcpy(hSbrDec->qmfDomainInCh->hQmfSlotsReal[i], + hSbrDec->LppTrans.lpcFilterStatesRealHBE[i + LPC_ORDER], + (64) * sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->qmfDomainInCh->hQmfSlotsImag[i], + hSbrDec->LppTrans.lpcFilterStatesImagHBE[i + LPC_ORDER], + (64) * sizeof(FIXP_DBL)); + } + + for (i = startSlot; i < hSbrDec->LppTrans.pSettings->overlap; i++) { + /* + Store the unmodified qmf Slots values for upper part of spectrum + (required for LPC filtering) required if next frame is a HBE frame + */ + FDKmemcpy( + hSbrDec->qmfDomainInCh->hQmfSlotsReal[i], + hSbrDec->codecQMFBufferReal[hSbrDec->hHBE->noCols - + hSbrDec->LppTrans.pSettings->overlap + + i], + new_lsb * sizeof(FIXP_DBL)); + FDKmemcpy( + hSbrDec->qmfDomainInCh->hQmfSlotsImag[i], + hSbrDec->codecQMFBufferImag[hSbrDec->hHBE->noCols - + hSbrDec->LppTrans.pSettings->overlap + + i], + new_lsb * sizeof(FIXP_DBL)); + } + } + } + } + + { + int adapt_lb = 0, diff = 0, + new_scale = hSbrDec->qmfDomainInCh->scaling.ov_lb_scale; + + if ((hSbrDec->qmfDomainInCh->scaling.ov_lb_scale != + hSbrDec->qmfDomainInCh->scaling.lb_scale) && + startSlot != 0) { + /* we need to adapt spectrum to have equal scale factor, always larger + * than zero */ + diff = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale) - + SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.lb_scale); + + if (diff > 0) { + adapt_lb = 1; + diff = -diff; + new_scale = hSbrDec->qmfDomainInCh->scaling.ov_lb_scale; + } + + stopBand = new_lsb; + } + + if (hFrameData->sbrPatchingMode == 1) { + /* scale states from LegSBR filterstates buffer */ + for (i = 0; i < hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER; i++) { + scaleValues(hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], new_lsb, + diff); + if (!useLP) { + scaleValues(hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], new_lsb, + diff); + } + } + + if (flags & SBRDEC_SYNTAX_USAC) { + /* get missing states between old and new x_over from LegSBR + * filterstates buffer */ + /* in case of legacy SBR we leave these values zeroed out */ + for (i = startSlot; i < hSbrDec->LppTrans.pSettings->overlap; i++) { + FDKmemcpy(&OverlapBufferReal[i][old_lsb], + &hSbrDec->LppTrans + .lpcFilterStatesRealLegSBR[LPC_ORDER + i][old_lsb], + fMax(new_lsb - old_lsb, 0) * sizeof(FIXP_DBL)); + if (!useLP) { + FDKmemcpy(&OverlapBufferImag[i][old_lsb], + &hSbrDec->LppTrans + .lpcFilterStatesImagLegSBR[LPC_ORDER + i][old_lsb], + fMax(new_lsb - old_lsb, 0) * sizeof(FIXP_DBL)); + } + } + } + + if (new_lsb > old_lsb) { + stopBand = old_lsb; + } + } + if ((adapt_lb == 1) && (stopBand > startBand)) { + for (l = startSlot; l < hSbrDec->LppTrans.pSettings->overlap; l++) { + scaleValues(OverlapBufferReal[l] + startBand, stopBand - startBand, + diff); + if (!useLP) { + scaleValues(OverlapBufferImag[l] + startBand, stopBand - startBand, + diff); + } + } + } + hSbrDec->qmfDomainInCh->scaling.ov_lb_scale = new_scale; + } + sbrError = ResetLimiterBands(hHeaderData->freqBandData.limiterBandTable, + &hHeaderData->freqBandData.noLimiterBands, + hHeaderData->freqBandData.freqBandTable[0], + hHeaderData->freqBandData.nSfb[0], + hSbrDec->LppTrans.pSettings->patchParam, + hSbrDec->LppTrans.pSettings->noOfPatches, + hHeaderData->bs_data.limiterBands, + hFrameData->sbrPatchingMode, + GetxOverBandQmfTransposer(hSbrDec->hHBE), + Get41SbrQmfTransposer(hSbrDec->hHBE)); + + hSbrDec->SbrCalculateEnvelope.sbrPatchingMode = hFrameData->sbrPatchingMode; return sbrError; } diff --git a/libSBRdec/src/sbr_dec.h b/libSBRdec/src/sbr_dec.h index edde637..156da03 100644 --- a/libSBRdec/src/sbr_dec.h +++ b/libSBRdec/src/sbr_dec.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,14 +90,22 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief Sbr decoder + \brief Sbr decoder */ -#ifndef __SBR_DEC_H -#define __SBR_DEC_H +#ifndef SBR_DEC_H +#define SBR_DEC_H #include "sbrdecoder.h" @@ -95,120 +114,91 @@ amm-info@iis.fraunhofer.de #include "env_calc.h" #include "FDK_audio.h" - #include "sbrdec_drc.h" -#define SACDEC_ALIGNMENT_FIX +#include "pvc_dec.h" -typedef struct -{ - QMF_FILTER_BANK AnalysiscQMF; - QMF_FILTER_BANK SynthesisQMF; +#include "hbe.h" - SBR_CALCULATE_ENVELOPE SbrCalculateEnvelope; - SBR_LPP_TRANS LppTrans; +enum SBRDEC_QMF_SKIP { + qmfSkipNothing = 0, + qmfSkipAnalysis = 1 << 0, + qmfSkipSynthesis = 1 << 1 +}; - QMF_SCALE_FACTOR sbrScaleFactor; - QMF_SCALE_FACTOR sbrScaleFactorRight; +typedef struct { + SBR_CALCULATE_ENVELOPE SbrCalculateEnvelope; + SBR_LPP_TRANS LppTrans; + PVC_STATIC_DATA PvcStaticData; - /*! Delayed spectral data needed for the dynamic framing of SBR. Not required in case of CLDFB */ - FIXP_DBL * pSbrOverlapBuffer; + /* do scale handling in sbr an not in qmf */ + SHORT scale_ov; + SHORT scale_lb; + SHORT scale_hbe; - /* References to workbuffers */ - FIXP_DBL * WorkBuffer1; - FIXP_DBL * WorkBuffer2; + SHORT prev_frame_lSbr; + SHORT prev_frame_hbeSbr; - /* Delayed time input signal needed to align CLDFD with LD-MPS QMF. */ - INT_PCM coreDelayBuf[(96)]; + int codecFrameSize; - /* QMF filter states */ - FIXP_QAS anaQmfStates[(320)]; - FIXP_QSS * pSynQmfStates; + HANDLE_HBE_TRANSPOSER hHBE; - /* Reference pointer arrays for QMF time slots, - mixed among overlap and current slots. */ - FIXP_DBL * QmfBufferReal[(((1024)/(32))+(6))]; - FIXP_DBL * QmfBufferImag[(((1024)/(32))+(6))]; - int useLP; + HANDLE_FDK_QMF_DOMAIN_IN qmfDomainInCh; + HANDLE_FDK_QMF_DOMAIN_OUT qmfDomainOutCh; - /* QMF domain extension time slot reference pointer array */ + SBRDEC_DRC_CHANNEL sbrDrcChannel; - SBRDEC_DRC_CHANNEL sbrDrcChannel; +#if (SBRDEC_MAX_HB_FADE_FRAMES > 0) + INT highBandFadeCnt; /* counter for fading in high-band signal smoothly */ +#endif + FIXP_DBL **tmp_memory; /* shared memory between hbeLightTimeDelayBuffer and + hQmfHBESlotsReal */ + + FIXP_DBL **hQmfHBESlotsReal; + FIXP_DBL **hQmfHBESlotsImag; + + FIXP_DBL **codecQMFBufferReal; + FIXP_DBL **codecQMFBufferImag; + UCHAR savedStates; + int applySbrProc_old; } SBR_DEC; typedef SBR_DEC *HANDLE_SBR_DEC; - -typedef struct -{ - SBR_FRAME_DATA frameData[(1)+1]; +typedef struct { + SBR_FRAME_DATA frameData[(1) + 1]; SBR_PREV_FRAME_DATA prevFrameData; SBR_DEC SbrDec; -} -SBR_CHANNEL; +} SBR_CHANNEL; typedef SBR_CHANNEL *HANDLE_SBR_CHANNEL; -void -SbrDecodeAndProcess (HANDLE_SBR_DEC hSbrDec, - INT_PCM *timeIn, - HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_FRAME_DATA hFrameData, - HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, - int applyProcessing, - int channelNr - , UCHAR useLP - ); - - -void -SbrConstructTimeOutput (HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ - INT_PCM *timeOut, /*!< pointer to output time signal */ - HANDLE_SBR_HEADER_DATA hHeaderData,/*!< Static control data */ - HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */ - int channelNr - ,UCHAR useLP - ); - - -void -sbr_dec (HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ - INT_PCM *timeIn, /*!< pointer to input time signal */ - INT_PCM *timeOut, /*!< pointer to output time signal */ - HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ - INT_PCM *timeOutRight, /*!< pointer to output time signal */ - const int strideIn, /*!< Time data traversal strideIn */ - const int strideOut, /*!< Time data traversal strideOut */ - HANDLE_SBR_HEADER_DATA hHeaderData,/*!< Static control data */ - HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ - HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */ - const int applyProcessing, /*!< Flag for SBR operation */ - HANDLE_PS_DEC h_ps_d, - const UINT flags, - const int codecFrameSize - ); - - +void sbr_dec( + HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ + INT_PCM *timeIn, /*!< pointer to input time signal */ + INT_PCM *timeOut, /*!< pointer to output time signal */ + HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ + INT_PCM *timeOutRight, /*!< pointer to output time signal */ + INT strideOut, /*!< Time data traversal strideOut */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ + HANDLE_SBR_PREV_FRAME_DATA + hPrevFrameData, /*!< Some control data of last frame */ + const int applyProcessing, /*!< Flag for SBR operation */ + HANDLE_PS_DEC h_ps_d, const UINT flags, const int codecFrameSize); SBR_ERROR -createSbrDec (SBR_CHANNEL * hSbrChannel, - HANDLE_SBR_HEADER_DATA hHeaderData, - TRANSPOSER_SETTINGS *pSettings, - const int downsampleFac, - const UINT qmfFlags, - const UINT flags, - const int overlap, - int chan); - -int -deleteSbrDec (SBR_CHANNEL * hSbrChannel); +createSbrDec(SBR_CHANNEL *hSbrChannel, HANDLE_SBR_HEADER_DATA hHeaderData, + TRANSPOSER_SETTINGS *pSettings, const int downsampleFac, + const UINT qmfFlags, const UINT flags, const int overlap, int chan, + int codecFrameSize); + +int deleteSbrDec(SBR_CHANNEL *hSbrChannel); SBR_ERROR -resetSbrDec (HANDLE_SBR_DEC hSbrDec, - HANDLE_SBR_HEADER_DATA hHeaderData, - HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, - const int useLP, - const int downsampleFac); +resetSbrDec(HANDLE_SBR_DEC hSbrDec, HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, const int downsampleFac, + const UINT flags, HANDLE_SBR_FRAME_DATA hFrameData); #endif diff --git a/libSBRdec/src/sbr_ram.cpp b/libSBRdec/src/sbr_ram.cpp index c1c2499..8b35fd2 100644 --- a/libSBRdec/src/sbr_ram.cpp +++ b/libSBRdec/src/sbr_ram.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,23 +90,27 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file \brief Memory layout - This module declares all static and dynamic memory spaces */ #include "sbr_ram.h" - - - -#define WORKBUFFER1_TAG 0 -#define WORKBUFFER2_TAG 1 +#define WORKBUFFER1_TAG 2 +#define WORKBUFFER2_TAG 3 /*! \name StaticSbrData @@ -111,24 +126,14 @@ C_ALLOC_MEM(Ram_SbrDecoder, struct SBR_DECODER_INSTANCE, 1) C_ALLOC_MEM2(Ram_SbrDecElement, SBR_DECODER_ELEMENT, 1, (8)) /*! SBR Decoder individual channel data <br> Dimension: (8) */ -C_ALLOC_MEM2(Ram_SbrDecChannel, SBR_CHANNEL, 1, (8)+1) - -/*! Filter states for QMF-synthesis. <br> - Dimension: #(8) * (#QMF_FILTER_STATE_SYN_SIZE-#(64)) */ -C_AALLOC_MEM2_L(Ram_sbr_QmfStatesSynthesis, FIXP_QSS, (640)-(64), (8)+1, SECT_DATA_L1) - -/*! Delayed spectral data needed for the dynamic framing of SBR. - For mp3PRO, 1/3 of a frame is buffered (#(6) 6) */ -C_AALLOC_MEM2(Ram_sbr_OverlapBuffer, FIXP_DBL, 2 * (6) * (64), (8)+1) +C_ALLOC_MEM2(Ram_SbrDecChannel, SBR_CHANNEL, 1, (8) + 1) /*! Static Data of PS */ -C_ALLOC_MEM(Ram_ps_dec, PS_DEC, 1) - +C_ALLOC_MEM(Ram_ps_dec, struct PS_DEC, 1) /* @} */ - /*! \name DynamicSbrData @@ -138,14 +143,12 @@ C_ALLOC_MEM(Ram_ps_dec, PS_DEC, 1) Depending on the mode set by DONT_USE_CORE_WORKBUFFER, workbuffers are defined additionally to the CoreWorkbuffer. <br> - The size of WorkBuffers is ((1024)/(32))*(64) = 2048. - <br> - WorkBuffer2 is a pointer to the CoreWorkBuffer wich is reused here in the SBR part. In case of - DONT_USE_CORE_WORKBUFFER, the CoreWorkbuffer is not used and the according - Workbuffer2 is defined locally in this file. - <br> - WorkBuffer1 is reused in the AAC core (-> aacdecoder.cpp, aac_ram.cpp) + The size of WorkBuffers is ((1024) / (32) * (4) / 2)*(64) = 2048. <br> + WorkBuffer2 is a pointer to the CoreWorkBuffer wich is reused here in the SBR + part. In case of DONT_USE_CORE_WORKBUFFER, the CoreWorkbuffer is not used and + the according Workbuffer2 is defined locally in this file. <br> WorkBuffer1 is + reused in the AAC core (-> aacdecoder.cpp, aac_ram.cpp) <br> Use of WorkBuffers: <pre> @@ -169,26 +172,20 @@ C_ALLOC_MEM(Ram_ps_dec, PS_DEC, 1) |________________| |________________| ---------------------------------------------- - High Quality Mode (!LOW_POWER_SBR_ONLY and useLP=0), see assignHqTimeSlots() + High Quality Mode (!LOW_POWER_SBR_ONLY and useLP=0), see + assignHqTimeSlots() SLOTBASED_PS WorkBuffer1 WorkBuffer2(=CoreWorkbuffer) ________________ ________________ - | Real/Imag | interleaved | Real/Imag | interleaved - |________________| first half actual ch |________________| second half actual ch + | Real/Imag | interleaved | Real/Imag | + interleaved + |________________| first half actual ch |________________| second + half actual ch ------------------------------------------------------------- </pre> */ -/* @{ */ -C_ALLOC_MEM_OVERLAY(Ram_SbrDecWorkBuffer1, FIXP_DBL, ((1024)/(32))*(64), SECT_DATA_L1, WORKBUFFER1_TAG) -C_ALLOC_MEM_OVERLAY(Ram_SbrDecWorkBuffer2, FIXP_DBL, ((1024)/(32))*(64), SECT_DATA_L2, WORKBUFFER2_TAG) - -/* @} */ - - - - diff --git a/libSBRdec/src/sbr_ram.h b/libSBRdec/src/sbr_ram.h index 7ab5044..e00f8b5 100644 --- a/libSBRdec/src/sbr_ram.h +++ b/libSBRdec/src/sbr_ram.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,66 +90,86 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file \brief Memory layout - */ -#ifndef _SBR_RAM_H_ -#define _SBR_RAM_H_ +#ifndef SBR_RAM_H +#define SBR_RAM_H #include "sbrdecoder.h" #include "env_extr.h" #include "sbr_dec.h" - - -#define SBRDEC_MAX_CH_PER_ELEMENT (2) - -typedef struct -{ - SBR_CHANNEL *pSbrChannel[SBRDEC_MAX_CH_PER_ELEMENT]; - TRANSPOSER_SETTINGS transposerSettings; /* Common transport settings for each individual channel of an element */ - HANDLE_FDK_BITSTREAM hBs; - - MP4_ELEMENT_ID elementID; /* Element ID set during initialization. Can be used for concealment */ - int nChannels; /* Number of elements output channels (=2 in case of PS) */ - - UCHAR frameErrorFlag[(1)+1]; /* Frame error status (for every slot in the delay line). - Will be copied into header at the very beginning of decodeElement() routine. */ - - UCHAR useFrameSlot; /* Index which defines which slot will be decoded/filled next (used with additional delay) */ - UCHAR useHeaderSlot[(1)+1]; /* Index array that provides the link between header and frame data - (important when processing with additional delay). */ +#define SBRDEC_MAX_CH_PER_ELEMENT (2) + +#define FRAME_OK (0) +#define FRAME_ERROR (1) +#define FRAME_ERROR_ALLSLOTS (2) + +typedef struct { + SBR_CHANNEL *pSbrChannel[SBRDEC_MAX_CH_PER_ELEMENT]; + TRANSPOSER_SETTINGS + transposerSettings; /* Common transport settings for each individual + channel of an element */ + HANDLE_FDK_BITSTREAM hBs; + + MP4_ELEMENT_ID + elementID; /* Element ID set during initialization. Can be used for + concealment */ + int nChannels; /* Number of elements output channels (=2 in case of PS) */ + + UCHAR frameErrorFlag[(1) + 1]; /* Frame error status (for every slot in the + delay line). Will be copied into header at + the very beginning of decodeElement() + routine. */ + + UCHAR useFrameSlot; /* Index which defines which slot will be decoded/filled + next (used with additional delay) */ + UCHAR useHeaderSlot[(1) + 1]; /* Index array that provides the link between + header and frame data (important when + processing with additional delay). */ } SBR_DECODER_ELEMENT; +struct SBR_DECODER_INSTANCE { + SBR_DECODER_ELEMENT *pSbrElement[(8)]; + SBR_HEADER_DATA sbrHeader[( + 8)][(1) + 1]; /* Sbr header for each individual channel of an element */ -struct SBR_DECODER_INSTANCE -{ - SBR_DECODER_ELEMENT *pSbrElement[(8)]; - SBR_HEADER_DATA sbrHeader[(8)][(1)+1]; /* Sbr header for each individual channel of an element */ - - FIXP_DBL *workBuffer1; - FIXP_DBL *workBuffer2; + HANDLE_FDK_QMF_DOMAIN pQmfDomain; - HANDLE_PS_DEC hParametricStereoDec; + HANDLE_PS_DEC hParametricStereoDec; /* Global parameters */ AUDIO_OBJECT_TYPE coreCodec; /* AOT of core codec */ int numSbrElements; int numSbrChannels; - INT sampleRateIn; /* SBR decoder input sampling rate; might be different than the transposer input sampling rate. */ - INT sampleRateOut; /* Sampling rate of the SBR decoder output audio samples. */ + INT sampleRateIn; /* SBR decoder input sampling rate; might be different than + the transposer input sampling rate. */ + INT sampleRateOut; /* Sampling rate of the SBR decoder output audio samples. + */ USHORT codecFrameSize; UCHAR synDownsampleFac; - UCHAR numDelayFrames; /* The current number of additional delay frames used for processing. */ - UCHAR numFlushedFrames; /* The variable counts the number of frames which are flushed consecutively. */ + INT downscaleFactor; + UCHAR numDelayFrames; /* The current number of additional delay frames used + for processing. */ + UCHAR harmonicSBR; + UCHAR + numFlushedFrames; /* The variable counts the number of frames which are + flushed consecutively. */ UINT flags; - }; H_ALLOC_MEM(Ram_SbrDecElement, SBR_DECODER_ELEMENT) @@ -148,12 +179,8 @@ H_ALLOC_MEM(Ram_SbrDecoder, struct SBR_DECODER_INSTANCE) H_ALLOC_MEM(Ram_sbr_QmfStatesSynthesis, FIXP_QSS) H_ALLOC_MEM(Ram_sbr_OverlapBuffer, FIXP_DBL) +H_ALLOC_MEM(Ram_sbr_HBEOverlapBuffer, FIXP_DBL) H_ALLOC_MEM(Ram_ps_dec, PS_DEC) - -H_ALLOC_MEM_OVERLAY(Ram_SbrDecWorkBuffer1, FIXP_DBL) -H_ALLOC_MEM_OVERLAY(Ram_SbrDecWorkBuffer2, FIXP_DBL) - - -#endif /* _SBR_RAM_H_ */ +#endif /* SBR_RAM_H */ diff --git a/libSBRdec/src/sbr_rom.cpp b/libSBRdec/src/sbr_rom.cpp index 4f2cc48..8a6688a 100644 --- a/libSBRdec/src/sbr_rom.cpp +++ b/libSBRdec/src/sbr_rom.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,41 +90,71 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file \brief Definition of constant tables - This module contains most of the constant data that can be stored in ROM. */ #include "sbr_rom.h" - - - /*! \name StartStopBands \brief Start and stop subbands of the highband. k_o = startMin + offset[bs_start_freq]; - startMin = {3000,4000,5000} * (128/FS_sbr) / FS_sbr < 32Khz, 32Khz <= FS_sbr < 64KHz, 64KHz <= FS_sbr - The stop subband can also be calculated to save memory by defining #CALC_STOP_BAND. + startMin = {3000,4000,5000} * (128/FS_sbr) / FS_sbr < 32Khz, 32Khz <= FS_sbr < + 64KHz, 64KHz <= FS_sbr The stop subband can also be calculated to save memory + by defining #CALC_STOP_BAND. */ //@{ -const UCHAR FDK_sbrDecoder_sbr_start_freq_16[16] = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; -const UCHAR FDK_sbrDecoder_sbr_start_freq_22[16] = {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 28, 30}; -const UCHAR FDK_sbrDecoder_sbr_start_freq_24[16] = {11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27, 29, 32}; -const UCHAR FDK_sbrDecoder_sbr_start_freq_32[16] = {10, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27, 29, 32}; -const UCHAR FDK_sbrDecoder_sbr_start_freq_40[16] = {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 26, 28, 30, 32}; -const UCHAR FDK_sbrDecoder_sbr_start_freq_44[16] = { 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 23, 25, 28, 32}; -const UCHAR FDK_sbrDecoder_sbr_start_freq_48[16] = { 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, 27, 31}; -const UCHAR FDK_sbrDecoder_sbr_start_freq_64[16] = { 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 23, 26, 30}; -const UCHAR FDK_sbrDecoder_sbr_start_freq_88[16] = { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 23, 27, 31}; -//@} +/* tables were created with ../addon/octave/sbr_start_freq_table.m */ +const UCHAR FDK_sbrDecoder_sbr_start_freq_16[][16] = { + {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, + {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_22[][16] = { + {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 28, 30}, + {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_24[][16] = { + {11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27, 29, 32}, + {3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 21, 24}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_32[][16] = { + {10, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27, 29, 32}, + {2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 21, 24}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_40[][16] = { + {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 26, 28, 30, 32}, + {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 21, 23, 25}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_44[][16] = { + {8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 23, 25, 28, 32}, + {2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19, 22, 26}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_48[][16] = { + {7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, 27, 31}, + {1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 21, 25}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_64[][16] = { + {6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 23, 26, 30}, + {1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 21, 25}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_88[][16] = { + {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 23, 27, 31}, + {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 20, 24, 28}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_192[16] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 19, 23, 27}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_176[16] = { + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 20, 24, 28}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_128[16] = { + 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 21, 25}; +//@} /*! \name Whitening @@ -122,16 +163,7 @@ const UCHAR FDK_sbrDecoder_sbr_start_freq_88[16] = { 5, 6, 7, 8, 9, 10, 11, //@{ /*! Assignment of whitening tuning depending on the crossover frequency */ const USHORT FDK_sbrDecoder_sbr_whFactorsIndex[NUM_WHFACTOR_TABLE_ENTRIES] = { - 0, - 5000, - 6000, - 6500, - 7000, - 7500, - 8000, - 9000, - 10000 -}; + 0, 5000, 6000, 6500, 7000, 7500, 8000, 9000, 10000}; /*! \brief Whithening levels tuning table @@ -142,23 +174,31 @@ const USHORT FDK_sbrDecoder_sbr_whFactorsIndex[NUM_WHFACTOR_TABLE_ENTRIES] = { \li the first coloumn can be eliminated. */ -const FIXP_DBL FDK_sbrDecoder_sbr_whFactorsTable[NUM_WHFACTOR_TABLE_ENTRIES][6] = { - /* OFF_LEVEL, TRANSITION_LEVEL, LOW_LEVEL, MID_LEVEL, HIGH_LEVEL */ - { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* < 5000 */ - { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 5000 < 6000 */ - { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 6000 < 6500 */ - { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 6500 < 7000 */ - { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 7000 < 7500 */ - { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 7500 < 8000 */ - { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 8000 < 9000 */ - { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 9000 < 10000 */ - { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* > 10000 */ +const FIXP_DBL + FDK_sbrDecoder_sbr_whFactorsTable[NUM_WHFACTOR_TABLE_ENTRIES][6] = { + /* OFF_LEVEL, TRANSITION_LEVEL, LOW_LEVEL, MID_LEVEL, HIGH_LEVEL */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* < 5000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 5000 < 6000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 6000 < 6500 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 6500 < 7000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 7000 < 7500 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 7500 < 8000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 8000 < 9000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 9000 < 10000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* > 10000 */ }; - //@} - /*! \name EnvAdj \brief Constants and tables used for envelope adjustment @@ -166,565 +206,1065 @@ const FIXP_DBL FDK_sbrDecoder_sbr_whFactorsTable[NUM_WHFACTOR_TABLE_ENTRIES][6] //@{ /*! Mantissas of gain limits */ -const FIXP_SGL FDK_sbrDecoder_sbr_limGains_m[4] = -{ - FL2FXCONST_SGL(0.5011932025f), /*!< -3 dB. Gain limit when limiterGains in frameData is 0 */ - FL2FXCONST_SGL(0.5f), /*!< 0 dB. Gain limit when limiterGains in frameData is 1 */ - FL2FXCONST_SGL(0.9976346258f), /*!< +3 dB. Gain limit when limiterGains in frameData is 2 */ - FL2FXCONST_SGL(0.6776263578f) /*!< Inf. Gain limit when limiterGains in frameData is 3 */ +const FIXP_SGL FDK_sbrDecoder_sbr_limGains_m[4] = { + FL2FXCONST_SGL(0.5011932025f), /*!< -3 dB. Gain limit when limiterGains in + frameData is 0 */ + FL2FXCONST_SGL( + 0.5f), /*!< 0 dB. Gain limit when limiterGains in frameData is 1 */ + FL2FXCONST_SGL(0.9976346258f), /*!< +3 dB. Gain limit when limiterGains in + frameData is 2 */ + FL2FXCONST_SGL(0.6776263578f) /*!< Inf. Gain limit when limiterGains in + frameData is 3 */ }; /*! Exponents of gain limits */ -const UCHAR FDK_sbrDecoder_sbr_limGains_e[4] = -{ - 0, 1, 1, 67 -}; +const UCHAR FDK_sbrDecoder_sbr_limGains_e[4] = {0, 1, 1, 67}; /*! Constants for calculating the number of limiter bands */ -const FIXP_SGL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[4] = -{ - FL2FXCONST_SGL(1.0f / 4.0f), - FL2FXCONST_SGL(1.2f / 4.0f), - FL2FXCONST_SGL(2.0f / 4.0f), - FL2FXCONST_SGL(3.0f / 4.0f) -}; +const FIXP_SGL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[4] = { + FL2FXCONST_SGL(1.0f / 4.0f), FL2FXCONST_SGL(1.2f / 4.0f), + FL2FXCONST_SGL(2.0f / 4.0f), FL2FXCONST_SGL(3.0f / 4.0f)}; /*! Constants for calculating the number of limiter bands */ -const FIXP_DBL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[4] = -{ - FL2FXCONST_DBL(1.0f / 4.0f), - FL2FXCONST_DBL(1.2f / 4.0f), - FL2FXCONST_DBL(2.0f / 4.0f), - FL2FXCONST_DBL(3.0f / 4.0f) -}; +const FIXP_DBL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[4] = { + FL2FXCONST_DBL(1.0f / 4.0f), FL2FXCONST_DBL(1.2f / 4.0f), + FL2FXCONST_DBL(2.0f / 4.0f), FL2FXCONST_DBL(3.0f / 4.0f)}; -/*! Ratio of old gains and noise levels for the first 4 timeslots of an envelope */ +/*! Ratio of old gains and noise levels for the first 4 timeslots of an envelope + */ const FIXP_SGL FDK_sbrDecoder_sbr_smoothFilter[4] = { - FL2FXCONST_SGL(0.66666666666666f), - FL2FXCONST_SGL(0.36516383427084f), - FL2FXCONST_SGL(0.14699433520835f), - FL2FXCONST_SGL(0.03183050093751f) -}; - + FL2FXCONST_SGL(0.66666666666666f), FL2FXCONST_SGL(0.36516383427084f), + FL2FXCONST_SGL(0.14699433520835f), FL2FXCONST_SGL(0.03183050093751f)}; /*! Real and imaginary part of random noise which will be modulated to the desired level. An accuracy of 13 bits is sufficient for these random numbers. */ const FIXP_SGL FDK_sbrDecoder_sbr_randomPhase[SBR_NF_NO_RANDOM_VAL][2] = { - { FL2FXCONST_SGL(-0.99948153278296f / 8.0), FL2FXCONST_SGL(-0.59483417516607f / 8.0) }, - { FL2FXCONST_SGL( 0.97113454393991f / 8.0), FL2FXCONST_SGL(-0.67528515225647f / 8.0) }, - { FL2FXCONST_SGL( 0.14130051758487f / 8.0), FL2FXCONST_SGL(-0.95090983575689f / 8.0) }, - { FL2FXCONST_SGL(-0.47005496701697f / 8.0), FL2FXCONST_SGL(-0.37340549728647f / 8.0) }, - { FL2FXCONST_SGL( 0.80705063769351f / 8.0), FL2FXCONST_SGL( 0.29653668284408f / 8.0) }, - { FL2FXCONST_SGL(-0.38981478896926f / 8.0), FL2FXCONST_SGL( 0.89572605717087f / 8.0) }, - { FL2FXCONST_SGL(-0.01053049862020f / 8.0), FL2FXCONST_SGL(-0.66959058036166f / 8.0) }, - { FL2FXCONST_SGL(-0.91266367957293f / 8.0), FL2FXCONST_SGL(-0.11522938140034f / 8.0) }, - { FL2FXCONST_SGL( 0.54840422910309f / 8.0), FL2FXCONST_SGL( 0.75221367176302f / 8.0) }, - { FL2FXCONST_SGL( 0.40009252867955f / 8.0), FL2FXCONST_SGL(-0.98929400334421f / 8.0) }, - { FL2FXCONST_SGL(-0.99867974711855f / 8.0), FL2FXCONST_SGL(-0.88147068645358f / 8.0) }, - { FL2FXCONST_SGL(-0.95531076805040f / 8.0), FL2FXCONST_SGL( 0.90908757154593f / 8.0) }, - { FL2FXCONST_SGL(-0.45725933317144f / 8.0), FL2FXCONST_SGL(-0.56716323646760f / 8.0) }, - { FL2FXCONST_SGL(-0.72929675029275f / 8.0), FL2FXCONST_SGL(-0.98008272727324f / 8.0) }, - { FL2FXCONST_SGL( 0.75622801399036f / 8.0), FL2FXCONST_SGL( 0.20950329995549f / 8.0) }, - { FL2FXCONST_SGL( 0.07069442601050f / 8.0), FL2FXCONST_SGL(-0.78247898470706f / 8.0) }, - { FL2FXCONST_SGL( 0.74496252926055f / 8.0), FL2FXCONST_SGL(-0.91169004445807f / 8.0) }, - { FL2FXCONST_SGL(-0.96440182703856f / 8.0), FL2FXCONST_SGL(-0.94739918296622f / 8.0) }, - { FL2FXCONST_SGL( 0.30424629369539f / 8.0), FL2FXCONST_SGL(-0.49438267012479f / 8.0) }, - { FL2FXCONST_SGL( 0.66565033746925f / 8.0), FL2FXCONST_SGL( 0.64652935542491f / 8.0) }, - { FL2FXCONST_SGL( 0.91697008020594f / 8.0), FL2FXCONST_SGL( 0.17514097332009f / 8.0) }, - { FL2FXCONST_SGL(-0.70774918760427f / 8.0), FL2FXCONST_SGL( 0.52548653416543f / 8.0) }, - { FL2FXCONST_SGL(-0.70051415345560f / 8.0), FL2FXCONST_SGL(-0.45340028808763f / 8.0) }, - { FL2FXCONST_SGL(-0.99496513054797f / 8.0), FL2FXCONST_SGL(-0.90071908066973f / 8.0) }, - { FL2FXCONST_SGL( 0.98164490790123f / 8.0), FL2FXCONST_SGL(-0.77463155528697f / 8.0) }, - { FL2FXCONST_SGL(-0.54671580548181f / 8.0), FL2FXCONST_SGL(-0.02570928536004f / 8.0) }, - { FL2FXCONST_SGL(-0.01689629065389f / 8.0), FL2FXCONST_SGL( 0.00287506445732f / 8.0) }, - { FL2FXCONST_SGL(-0.86110349531986f / 8.0), FL2FXCONST_SGL( 0.42548583726477f / 8.0) }, - { FL2FXCONST_SGL(-0.98892980586032f / 8.0), FL2FXCONST_SGL(-0.87881132267556f / 8.0) }, - { FL2FXCONST_SGL( 0.51756627678691f / 8.0), FL2FXCONST_SGL( 0.66926784710139f / 8.0) }, - { FL2FXCONST_SGL(-0.99635026409640f / 8.0), FL2FXCONST_SGL(-0.58107730574765f / 8.0) }, - { FL2FXCONST_SGL(-0.99969370862163f / 8.0), FL2FXCONST_SGL( 0.98369989360250f / 8.0) }, - { FL2FXCONST_SGL( 0.55266258627194f / 8.0), FL2FXCONST_SGL( 0.59449057465591f / 8.0) }, - { FL2FXCONST_SGL( 0.34581177741673f / 8.0), FL2FXCONST_SGL( 0.94879421061866f / 8.0) }, - { FL2FXCONST_SGL( 0.62664209577999f / 8.0), FL2FXCONST_SGL(-0.74402970906471f / 8.0) }, - { FL2FXCONST_SGL(-0.77149701404973f / 8.0), FL2FXCONST_SGL(-0.33883658042801f / 8.0) }, - { FL2FXCONST_SGL(-0.91592244254432f / 8.0), FL2FXCONST_SGL( 0.03687901376713f / 8.0) }, - { FL2FXCONST_SGL(-0.76285492357887f / 8.0), FL2FXCONST_SGL(-0.91371867919124f / 8.0) }, - { FL2FXCONST_SGL( 0.79788337195331f / 8.0), FL2FXCONST_SGL(-0.93180971199849f / 8.0) }, - { FL2FXCONST_SGL( 0.54473080610200f / 8.0), FL2FXCONST_SGL(-0.11919206037186f / 8.0) }, - { FL2FXCONST_SGL(-0.85639281671058f / 8.0), FL2FXCONST_SGL( 0.42429854760451f / 8.0) }, - { FL2FXCONST_SGL(-0.92882402971423f / 8.0), FL2FXCONST_SGL( 0.27871809078609f / 8.0) }, - { FL2FXCONST_SGL(-0.11708371046774f / 8.0), FL2FXCONST_SGL(-0.99800843444966f / 8.0) }, - { FL2FXCONST_SGL( 0.21356749817493f / 8.0), FL2FXCONST_SGL(-0.90716295627033f / 8.0) }, - { FL2FXCONST_SGL(-0.76191692573909f / 8.0), FL2FXCONST_SGL( 0.99768118356265f / 8.0) }, - { FL2FXCONST_SGL( 0.98111043100884f / 8.0), FL2FXCONST_SGL(-0.95854459734407f / 8.0) }, - { FL2FXCONST_SGL(-0.85913269895572f / 8.0), FL2FXCONST_SGL( 0.95766566168880f / 8.0) }, - { FL2FXCONST_SGL(-0.93307242253692f / 8.0), FL2FXCONST_SGL( 0.49431757696466f / 8.0) }, - { FL2FXCONST_SGL( 0.30485754879632f / 8.0), FL2FXCONST_SGL(-0.70540034357529f / 8.0) }, - { FL2FXCONST_SGL( 0.85289650925190f / 8.0), FL2FXCONST_SGL( 0.46766131791044f / 8.0) }, - { FL2FXCONST_SGL( 0.91328082618125f / 8.0), FL2FXCONST_SGL(-0.99839597361769f / 8.0) }, - { FL2FXCONST_SGL(-0.05890199924154f / 8.0), FL2FXCONST_SGL( 0.70741827819497f / 8.0) }, - { FL2FXCONST_SGL( 0.28398686150148f / 8.0), FL2FXCONST_SGL( 0.34633555702188f / 8.0) }, - { FL2FXCONST_SGL( 0.95258164539612f / 8.0), FL2FXCONST_SGL(-0.54893416026939f / 8.0) }, - { FL2FXCONST_SGL(-0.78566324168507f / 8.0), FL2FXCONST_SGL(-0.75568541079691f / 8.0) }, - { FL2FXCONST_SGL(-0.95789495447877f / 8.0), FL2FXCONST_SGL(-0.20423194696966f / 8.0) }, - { FL2FXCONST_SGL( 0.82411158711197f / 8.0), FL2FXCONST_SGL( 0.96654618432562f / 8.0) }, - { FL2FXCONST_SGL(-0.65185446735885f / 8.0), FL2FXCONST_SGL(-0.88734990773289f / 8.0) }, - { FL2FXCONST_SGL(-0.93643603134666f / 8.0), FL2FXCONST_SGL( 0.99870790442385f / 8.0) }, - { FL2FXCONST_SGL( 0.91427159529618f / 8.0), FL2FXCONST_SGL(-0.98290505544444f / 8.0) }, - { FL2FXCONST_SGL(-0.70395684036886f / 8.0), FL2FXCONST_SGL( 0.58796798221039f / 8.0) }, - { FL2FXCONST_SGL( 0.00563771969365f / 8.0), FL2FXCONST_SGL( 0.61768196727244f / 8.0) }, - { FL2FXCONST_SGL( 0.89065051931895f / 8.0), FL2FXCONST_SGL( 0.52783352697585f / 8.0) }, - { FL2FXCONST_SGL(-0.68683707712762f / 8.0), FL2FXCONST_SGL( 0.80806944710339f / 8.0) }, - { FL2FXCONST_SGL( 0.72165342518718f / 8.0), FL2FXCONST_SGL(-0.69259857349564f / 8.0) }, - { FL2FXCONST_SGL(-0.62928247730667f / 8.0), FL2FXCONST_SGL( 0.13627037407335f / 8.0) }, - { FL2FXCONST_SGL( 0.29938434065514f / 8.0), FL2FXCONST_SGL(-0.46051329682246f / 8.0) }, - { FL2FXCONST_SGL(-0.91781958879280f / 8.0), FL2FXCONST_SGL(-0.74012716684186f / 8.0) }, - { FL2FXCONST_SGL( 0.99298717043688f / 8.0), FL2FXCONST_SGL( 0.40816610075661f / 8.0) }, - { FL2FXCONST_SGL( 0.82368298622748f / 8.0), FL2FXCONST_SGL(-0.74036047190173f / 8.0) }, - { FL2FXCONST_SGL(-0.98512833386833f / 8.0), FL2FXCONST_SGL(-0.99972330709594f / 8.0) }, - { FL2FXCONST_SGL(-0.95915368242257f / 8.0), FL2FXCONST_SGL(-0.99237800466040f / 8.0) }, - { FL2FXCONST_SGL(-0.21411126572790f / 8.0), FL2FXCONST_SGL(-0.93424819052545f / 8.0) }, - { FL2FXCONST_SGL(-0.68821476106884f / 8.0), FL2FXCONST_SGL(-0.26892306315457f / 8.0) }, - { FL2FXCONST_SGL( 0.91851997982317f / 8.0), FL2FXCONST_SGL( 0.09358228901785f / 8.0) }, - { FL2FXCONST_SGL(-0.96062769559127f / 8.0), FL2FXCONST_SGL( 0.36099095133739f / 8.0) }, - { FL2FXCONST_SGL( 0.51646184922287f / 8.0), FL2FXCONST_SGL(-0.71373332873917f / 8.0) }, - { FL2FXCONST_SGL( 0.61130721139669f / 8.0), FL2FXCONST_SGL( 0.46950141175917f / 8.0) }, - { FL2FXCONST_SGL( 0.47336129371299f / 8.0), FL2FXCONST_SGL(-0.27333178296162f / 8.0) }, - { FL2FXCONST_SGL( 0.90998308703519f / 8.0), FL2FXCONST_SGL( 0.96715662938132f / 8.0) }, - { FL2FXCONST_SGL( 0.44844799194357f / 8.0), FL2FXCONST_SGL( 0.99211574628306f / 8.0) }, - { FL2FXCONST_SGL( 0.66614891079092f / 8.0), FL2FXCONST_SGL( 0.96590176169121f / 8.0) }, - { FL2FXCONST_SGL( 0.74922239129237f / 8.0), FL2FXCONST_SGL(-0.89879858826087f / 8.0) }, - { FL2FXCONST_SGL(-0.99571588506485f / 8.0), FL2FXCONST_SGL( 0.52785521494349f / 8.0) }, - { FL2FXCONST_SGL( 0.97401082477563f / 8.0), FL2FXCONST_SGL(-0.16855870075190f / 8.0) }, - { FL2FXCONST_SGL( 0.72683747733879f / 8.0), FL2FXCONST_SGL(-0.48060774432251f / 8.0) }, - { FL2FXCONST_SGL( 0.95432193457128f / 8.0), FL2FXCONST_SGL( 0.68849603408441f / 8.0) }, - { FL2FXCONST_SGL(-0.72962208425191f / 8.0), FL2FXCONST_SGL(-0.76608443420917f / 8.0) }, - { FL2FXCONST_SGL(-0.85359479233537f / 8.0), FL2FXCONST_SGL( 0.88738125901579f / 8.0) }, - { FL2FXCONST_SGL(-0.81412430338535f / 8.0), FL2FXCONST_SGL(-0.97480768049637f / 8.0) }, - { FL2FXCONST_SGL(-0.87930772356786f / 8.0), FL2FXCONST_SGL( 0.74748307690436f / 8.0) }, - { FL2FXCONST_SGL(-0.71573331064977f / 8.0), FL2FXCONST_SGL(-0.98570608178923f / 8.0) }, - { FL2FXCONST_SGL( 0.83524300028228f / 8.0), FL2FXCONST_SGL( 0.83702537075163f / 8.0) }, - { FL2FXCONST_SGL(-0.48086065601423f / 8.0), FL2FXCONST_SGL(-0.98848504923531f / 8.0) }, - { FL2FXCONST_SGL( 0.97139128574778f / 8.0), FL2FXCONST_SGL( 0.80093621198236f / 8.0) }, - { FL2FXCONST_SGL( 0.51992825347895f / 8.0), FL2FXCONST_SGL( 0.80247631400510f / 8.0) }, - { FL2FXCONST_SGL(-0.00848591195325f / 8.0), FL2FXCONST_SGL(-0.76670128000486f / 8.0) }, - { FL2FXCONST_SGL(-0.70294374303036f / 8.0), FL2FXCONST_SGL( 0.55359910445577f / 8.0) }, - { FL2FXCONST_SGL(-0.95894428168140f / 8.0), FL2FXCONST_SGL(-0.43265504344783f / 8.0) }, - { FL2FXCONST_SGL( 0.97079252950321f / 8.0), FL2FXCONST_SGL( 0.09325857238682f / 8.0) }, - { FL2FXCONST_SGL(-0.92404293670797f / 8.0), FL2FXCONST_SGL( 0.85507704027855f / 8.0) }, - { FL2FXCONST_SGL(-0.69506469500450f / 8.0), FL2FXCONST_SGL( 0.98633412625459f / 8.0) }, - { FL2FXCONST_SGL( 0.26559203620024f / 8.0), FL2FXCONST_SGL( 0.73314307966524f / 8.0) }, - { FL2FXCONST_SGL( 0.28038443336943f / 8.0), FL2FXCONST_SGL( 0.14537913654427f / 8.0) }, - { FL2FXCONST_SGL(-0.74138124825523f / 8.0), FL2FXCONST_SGL( 0.99310339807762f / 8.0) }, - { FL2FXCONST_SGL(-0.01752795995444f / 8.0), FL2FXCONST_SGL(-0.82616635284178f / 8.0) }, - { FL2FXCONST_SGL(-0.55126773094930f / 8.0), FL2FXCONST_SGL(-0.98898543862153f / 8.0) }, - { FL2FXCONST_SGL( 0.97960898850996f / 8.0), FL2FXCONST_SGL(-0.94021446752851f / 8.0) }, - { FL2FXCONST_SGL(-0.99196309146936f / 8.0), FL2FXCONST_SGL( 0.67019017358456f / 8.0) }, - { FL2FXCONST_SGL(-0.67684928085260f / 8.0), FL2FXCONST_SGL( 0.12631491649378f / 8.0) }, - { FL2FXCONST_SGL( 0.09140039465500f / 8.0), FL2FXCONST_SGL(-0.20537731453108f / 8.0) }, - { FL2FXCONST_SGL(-0.71658965751996f / 8.0), FL2FXCONST_SGL(-0.97788200391224f / 8.0) }, - { FL2FXCONST_SGL( 0.81014640078925f / 8.0), FL2FXCONST_SGL( 0.53722648362443f / 8.0) }, - { FL2FXCONST_SGL( 0.40616991671205f / 8.0), FL2FXCONST_SGL(-0.26469008598449f / 8.0) }, - { FL2FXCONST_SGL(-0.67680188682972f / 8.0), FL2FXCONST_SGL( 0.94502052337695f / 8.0) }, - { FL2FXCONST_SGL( 0.86849774348749f / 8.0), FL2FXCONST_SGL(-0.18333598647899f / 8.0) }, - { FL2FXCONST_SGL(-0.99500381284851f / 8.0), FL2FXCONST_SGL(-0.02634122068550f / 8.0) }, - { FL2FXCONST_SGL( 0.84329189340667f / 8.0), FL2FXCONST_SGL( 0.10406957462213f / 8.0) }, - { FL2FXCONST_SGL(-0.09215968531446f / 8.0), FL2FXCONST_SGL( 0.69540012101253f / 8.0) }, - { FL2FXCONST_SGL( 0.99956173327206f / 8.0), FL2FXCONST_SGL(-0.12358542001404f / 8.0) }, - { FL2FXCONST_SGL(-0.79732779473535f / 8.0), FL2FXCONST_SGL(-0.91582524736159f / 8.0) }, - { FL2FXCONST_SGL( 0.96349973642406f / 8.0), FL2FXCONST_SGL( 0.96640458041000f / 8.0) }, - { FL2FXCONST_SGL(-0.79942778496547f / 8.0), FL2FXCONST_SGL( 0.64323902822857f / 8.0) }, - { FL2FXCONST_SGL(-0.11566039853896f / 8.0), FL2FXCONST_SGL( 0.28587846253726f / 8.0) }, - { FL2FXCONST_SGL(-0.39922954514662f / 8.0), FL2FXCONST_SGL( 0.94129601616966f / 8.0) }, - { FL2FXCONST_SGL( 0.99089197565987f / 8.0), FL2FXCONST_SGL(-0.92062625581587f / 8.0) }, - { FL2FXCONST_SGL( 0.28631285179909f / 8.0), FL2FXCONST_SGL(-0.91035047143603f / 8.0) }, - { FL2FXCONST_SGL(-0.83302725605608f / 8.0), FL2FXCONST_SGL(-0.67330410892084f / 8.0) }, - { FL2FXCONST_SGL( 0.95404443402072f / 8.0), FL2FXCONST_SGL( 0.49162765398743f / 8.0) }, - { FL2FXCONST_SGL(-0.06449863579434f / 8.0), FL2FXCONST_SGL( 0.03250560813135f / 8.0) }, - { FL2FXCONST_SGL(-0.99575054486311f / 8.0), FL2FXCONST_SGL( 0.42389784469507f / 8.0) }, - { FL2FXCONST_SGL(-0.65501142790847f / 8.0), FL2FXCONST_SGL( 0.82546114655624f / 8.0) }, - { FL2FXCONST_SGL(-0.81254441908887f / 8.0), FL2FXCONST_SGL(-0.51627234660629f / 8.0) }, - { FL2FXCONST_SGL(-0.99646369485481f / 8.0), FL2FXCONST_SGL( 0.84490533520752f / 8.0) }, - { FL2FXCONST_SGL( 0.00287840603348f / 8.0), FL2FXCONST_SGL( 0.64768261158166f / 8.0) }, - { FL2FXCONST_SGL( 0.70176989408455f / 8.0), FL2FXCONST_SGL(-0.20453028573322f / 8.0) }, - { FL2FXCONST_SGL( 0.96361882270190f / 8.0), FL2FXCONST_SGL( 0.40706967140989f / 8.0) }, - { FL2FXCONST_SGL(-0.68883758192426f / 8.0), FL2FXCONST_SGL( 0.91338958840772f / 8.0) }, - { FL2FXCONST_SGL(-0.34875585502238f / 8.0), FL2FXCONST_SGL( 0.71472290693300f / 8.0) }, - { FL2FXCONST_SGL( 0.91980081243087f / 8.0), FL2FXCONST_SGL( 0.66507455644919f / 8.0) }, - { FL2FXCONST_SGL(-0.99009048343881f / 8.0), FL2FXCONST_SGL( 0.85868021604848f / 8.0) }, - { FL2FXCONST_SGL( 0.68865791458395f / 8.0), FL2FXCONST_SGL( 0.55660316809678f / 8.0) }, - { FL2FXCONST_SGL(-0.99484402129368f / 8.0), FL2FXCONST_SGL(-0.20052559254934f / 8.0) }, - { FL2FXCONST_SGL( 0.94214511408023f / 8.0), FL2FXCONST_SGL(-0.99696425367461f / 8.0) }, - { FL2FXCONST_SGL(-0.67414626793544f / 8.0), FL2FXCONST_SGL( 0.49548221180078f / 8.0) }, - { FL2FXCONST_SGL(-0.47339353684664f / 8.0), FL2FXCONST_SGL(-0.85904328834047f / 8.0) }, - { FL2FXCONST_SGL( 0.14323651387360f / 8.0), FL2FXCONST_SGL(-0.94145598222488f / 8.0) }, - { FL2FXCONST_SGL(-0.29268293575672f / 8.0), FL2FXCONST_SGL( 0.05759224927952f / 8.0) }, - { FL2FXCONST_SGL( 0.43793861458754f / 8.0), FL2FXCONST_SGL(-0.78904969892724f / 8.0) }, - { FL2FXCONST_SGL(-0.36345126374441f / 8.0), FL2FXCONST_SGL( 0.64874435357162f / 8.0) }, - { FL2FXCONST_SGL(-0.08750604656825f / 8.0), FL2FXCONST_SGL( 0.97686944362527f / 8.0) }, - { FL2FXCONST_SGL(-0.96495267812511f / 8.0), FL2FXCONST_SGL(-0.53960305946511f / 8.0) }, - { FL2FXCONST_SGL( 0.55526940659947f / 8.0), FL2FXCONST_SGL( 0.78891523734774f / 8.0) }, - { FL2FXCONST_SGL( 0.73538215752630f / 8.0), FL2FXCONST_SGL( 0.96452072373404f / 8.0) }, - { FL2FXCONST_SGL(-0.30889773919437f / 8.0), FL2FXCONST_SGL(-0.80664389776860f / 8.0) }, - { FL2FXCONST_SGL( 0.03574995626194f / 8.0), FL2FXCONST_SGL(-0.97325616900959f / 8.0) }, - { FL2FXCONST_SGL( 0.98720684660488f / 8.0), FL2FXCONST_SGL( 0.48409133691962f / 8.0) }, - { FL2FXCONST_SGL(-0.81689296271203f / 8.0), FL2FXCONST_SGL(-0.90827703628298f / 8.0) }, - { FL2FXCONST_SGL( 0.67866860118215f / 8.0), FL2FXCONST_SGL( 0.81284503870856f / 8.0) }, - { FL2FXCONST_SGL(-0.15808569732583f / 8.0), FL2FXCONST_SGL( 0.85279555024382f / 8.0) }, - { FL2FXCONST_SGL( 0.80723395114371f / 8.0), FL2FXCONST_SGL(-0.24717418514605f / 8.0) }, - { FL2FXCONST_SGL( 0.47788757329038f / 8.0), FL2FXCONST_SGL(-0.46333147839295f / 8.0) }, - { FL2FXCONST_SGL( 0.96367554763201f / 8.0), FL2FXCONST_SGL( 0.38486749303242f / 8.0) }, - { FL2FXCONST_SGL(-0.99143875716818f / 8.0), FL2FXCONST_SGL(-0.24945277239809f / 8.0) }, - { FL2FXCONST_SGL( 0.83081876925833f / 8.0), FL2FXCONST_SGL(-0.94780851414763f / 8.0) }, - { FL2FXCONST_SGL(-0.58753191905341f / 8.0), FL2FXCONST_SGL( 0.01290772389163f / 8.0) }, - { FL2FXCONST_SGL( 0.95538108220960f / 8.0), FL2FXCONST_SGL(-0.85557052096538f / 8.0) }, - { FL2FXCONST_SGL(-0.96490920476211f / 8.0), FL2FXCONST_SGL(-0.64020970923102f / 8.0) }, - { FL2FXCONST_SGL(-0.97327101028521f / 8.0), FL2FXCONST_SGL( 0.12378128133110f / 8.0) }, - { FL2FXCONST_SGL( 0.91400366022124f / 8.0), FL2FXCONST_SGL( 0.57972471346930f / 8.0) }, - { FL2FXCONST_SGL(-0.99925837363824f / 8.0), FL2FXCONST_SGL( 0.71084847864067f / 8.0) }, - { FL2FXCONST_SGL(-0.86875903507313f / 8.0), FL2FXCONST_SGL(-0.20291699203564f / 8.0) }, - { FL2FXCONST_SGL(-0.26240034795124f / 8.0), FL2FXCONST_SGL(-0.68264554369108f / 8.0) }, - { FL2FXCONST_SGL(-0.24664412953388f / 8.0), FL2FXCONST_SGL(-0.87642273115183f / 8.0) }, - { FL2FXCONST_SGL( 0.02416275806869f / 8.0), FL2FXCONST_SGL( 0.27192914288905f / 8.0) }, - { FL2FXCONST_SGL( 0.82068619590515f / 8.0), FL2FXCONST_SGL(-0.85087787994476f / 8.0) }, - { FL2FXCONST_SGL( 0.88547373760759f / 8.0), FL2FXCONST_SGL(-0.89636802901469f / 8.0) }, - { FL2FXCONST_SGL(-0.18173078152226f / 8.0), FL2FXCONST_SGL(-0.26152145156800f / 8.0) }, - { FL2FXCONST_SGL( 0.09355476558534f / 8.0), FL2FXCONST_SGL( 0.54845123045604f / 8.0) }, - { FL2FXCONST_SGL(-0.54668414224090f / 8.0), FL2FXCONST_SGL( 0.95980774020221f / 8.0) }, - { FL2FXCONST_SGL( 0.37050990604091f / 8.0), FL2FXCONST_SGL(-0.59910140383171f / 8.0) }, - { FL2FXCONST_SGL(-0.70373594262891f / 8.0), FL2FXCONST_SGL( 0.91227665827081f / 8.0) }, - { FL2FXCONST_SGL(-0.34600785879594f / 8.0), FL2FXCONST_SGL(-0.99441426144200f / 8.0) }, - { FL2FXCONST_SGL(-0.68774481731008f / 8.0), FL2FXCONST_SGL(-0.30238837956299f / 8.0) }, - { FL2FXCONST_SGL(-0.26843291251234f / 8.0), FL2FXCONST_SGL( 0.83115668004362f / 8.0) }, - { FL2FXCONST_SGL( 0.49072334613242f / 8.0), FL2FXCONST_SGL(-0.45359708737775f / 8.0) }, - { FL2FXCONST_SGL( 0.38975993093975f / 8.0), FL2FXCONST_SGL( 0.95515358099121f / 8.0) }, - { FL2FXCONST_SGL(-0.97757125224150f / 8.0), FL2FXCONST_SGL( 0.05305894580606f / 8.0) }, - { FL2FXCONST_SGL(-0.17325552859616f / 8.0), FL2FXCONST_SGL(-0.92770672250494f / 8.0) }, - { FL2FXCONST_SGL( 0.99948035025744f / 8.0), FL2FXCONST_SGL( 0.58285545563426f / 8.0) }, - { FL2FXCONST_SGL(-0.64946246527458f / 8.0), FL2FXCONST_SGL( 0.68645507104960f / 8.0) }, - { FL2FXCONST_SGL(-0.12016920576437f / 8.0), FL2FXCONST_SGL(-0.57147322153312f / 8.0) }, - { FL2FXCONST_SGL(-0.58947456517751f / 8.0), FL2FXCONST_SGL(-0.34847132454388f / 8.0) }, - { FL2FXCONST_SGL(-0.41815140454465f / 8.0), FL2FXCONST_SGL( 0.16276422358861f / 8.0) }, - { FL2FXCONST_SGL( 0.99885650204884f / 8.0), FL2FXCONST_SGL( 0.11136095490444f / 8.0) }, - { FL2FXCONST_SGL(-0.56649614128386f / 8.0), FL2FXCONST_SGL(-0.90494866361587f / 8.0) }, - { FL2FXCONST_SGL( 0.94138021032330f / 8.0), FL2FXCONST_SGL( 0.35281916733018f / 8.0) }, - { FL2FXCONST_SGL(-0.75725076534641f / 8.0), FL2FXCONST_SGL( 0.53650549640587f / 8.0) }, - { FL2FXCONST_SGL( 0.20541973692630f / 8.0), FL2FXCONST_SGL(-0.94435144369918f / 8.0) }, - { FL2FXCONST_SGL( 0.99980371023351f / 8.0), FL2FXCONST_SGL( 0.79835913565599f / 8.0) }, - { FL2FXCONST_SGL( 0.29078277605775f / 8.0), FL2FXCONST_SGL( 0.35393777921520f / 8.0) }, - { FL2FXCONST_SGL(-0.62858772103030f / 8.0), FL2FXCONST_SGL( 0.38765693387102f / 8.0) }, - { FL2FXCONST_SGL( 0.43440904467688f / 8.0), FL2FXCONST_SGL(-0.98546330463232f / 8.0) }, - { FL2FXCONST_SGL(-0.98298583762390f / 8.0), FL2FXCONST_SGL( 0.21021524625209f / 8.0) }, - { FL2FXCONST_SGL( 0.19513029146934f / 8.0), FL2FXCONST_SGL(-0.94239832251867f / 8.0) }, - { FL2FXCONST_SGL(-0.95476662400101f / 8.0), FL2FXCONST_SGL( 0.98364554179143f / 8.0) }, - { FL2FXCONST_SGL( 0.93379635304810f / 8.0), FL2FXCONST_SGL(-0.70881994583682f / 8.0) }, - { FL2FXCONST_SGL(-0.85235410573336f / 8.0), FL2FXCONST_SGL(-0.08342347966410f / 8.0) }, - { FL2FXCONST_SGL(-0.86425093011245f / 8.0), FL2FXCONST_SGL(-0.45795025029466f / 8.0) }, - { FL2FXCONST_SGL( 0.38879779059045f / 8.0), FL2FXCONST_SGL( 0.97274429344593f / 8.0) }, - { FL2FXCONST_SGL( 0.92045124735495f / 8.0), FL2FXCONST_SGL(-0.62433652524220f / 8.0) }, - { FL2FXCONST_SGL( 0.89162532251878f / 8.0), FL2FXCONST_SGL( 0.54950955570563f / 8.0) }, - { FL2FXCONST_SGL(-0.36834336949252f / 8.0), FL2FXCONST_SGL( 0.96458298020975f / 8.0) }, - { FL2FXCONST_SGL( 0.93891760988045f / 8.0), FL2FXCONST_SGL(-0.89968353740388f / 8.0) }, - { FL2FXCONST_SGL( 0.99267657565094f / 8.0), FL2FXCONST_SGL(-0.03757034316958f / 8.0) }, - { FL2FXCONST_SGL(-0.94063471614176f / 8.0), FL2FXCONST_SGL( 0.41332338538963f / 8.0) }, - { FL2FXCONST_SGL( 0.99740224117019f / 8.0), FL2FXCONST_SGL(-0.16830494996370f / 8.0) }, - { FL2FXCONST_SGL(-0.35899413170555f / 8.0), FL2FXCONST_SGL(-0.46633226649613f / 8.0) }, - { FL2FXCONST_SGL( 0.05237237274947f / 8.0), FL2FXCONST_SGL(-0.25640361602661f / 8.0) }, - { FL2FXCONST_SGL( 0.36703583957424f / 8.0), FL2FXCONST_SGL(-0.38653265641875f / 8.0) }, - { FL2FXCONST_SGL( 0.91653180367913f / 8.0), FL2FXCONST_SGL(-0.30587628726597f / 8.0) }, - { FL2FXCONST_SGL( 0.69000803499316f / 8.0), FL2FXCONST_SGL( 0.90952171386132f / 8.0) }, - { FL2FXCONST_SGL(-0.38658751133527f / 8.0), FL2FXCONST_SGL( 0.99501571208985f / 8.0) }, - { FL2FXCONST_SGL(-0.29250814029851f / 8.0), FL2FXCONST_SGL( 0.37444994344615f / 8.0) }, - { FL2FXCONST_SGL(-0.60182204677608f / 8.0), FL2FXCONST_SGL( 0.86779651036123f / 8.0) }, - { FL2FXCONST_SGL(-0.97418588163217f / 8.0), FL2FXCONST_SGL( 0.96468523666475f / 8.0) }, - { FL2FXCONST_SGL( 0.88461574003963f / 8.0), FL2FXCONST_SGL( 0.57508405276414f / 8.0) }, - { FL2FXCONST_SGL( 0.05198933055162f / 8.0), FL2FXCONST_SGL( 0.21269661669964f / 8.0) }, - { FL2FXCONST_SGL(-0.53499621979720f / 8.0), FL2FXCONST_SGL( 0.97241553731237f / 8.0) }, - { FL2FXCONST_SGL(-0.49429560226497f / 8.0), FL2FXCONST_SGL( 0.98183865291903f / 8.0) }, - { FL2FXCONST_SGL(-0.98935142339139f / 8.0), FL2FXCONST_SGL(-0.40249159006933f / 8.0) }, - { FL2FXCONST_SGL(-0.98081380091130f / 8.0), FL2FXCONST_SGL(-0.72856895534041f / 8.0) }, - { FL2FXCONST_SGL(-0.27338148835532f / 8.0), FL2FXCONST_SGL( 0.99950922447209f / 8.0) }, - { FL2FXCONST_SGL( 0.06310802338302f / 8.0), FL2FXCONST_SGL(-0.54539587529618f / 8.0) }, - { FL2FXCONST_SGL(-0.20461677199539f / 8.0), FL2FXCONST_SGL(-0.14209977628489f / 8.0) }, - { FL2FXCONST_SGL( 0.66223843141647f / 8.0), FL2FXCONST_SGL( 0.72528579940326f / 8.0) }, - { FL2FXCONST_SGL(-0.84764345483665f / 8.0), FL2FXCONST_SGL( 0.02372316801261f / 8.0) }, - { FL2FXCONST_SGL(-0.89039863483811f / 8.0), FL2FXCONST_SGL( 0.88866581484602f / 8.0) }, - { FL2FXCONST_SGL( 0.95903308477986f / 8.0), FL2FXCONST_SGL( 0.76744927173873f / 8.0) }, - { FL2FXCONST_SGL( 0.73504123909879f / 8.0), FL2FXCONST_SGL(-0.03747203173192f / 8.0) }, - { FL2FXCONST_SGL(-0.31744434966056f / 8.0), FL2FXCONST_SGL(-0.36834111883652f / 8.0) }, - { FL2FXCONST_SGL(-0.34110827591623f / 8.0), FL2FXCONST_SGL( 0.40211222807691f / 8.0) }, - { FL2FXCONST_SGL( 0.47803883714199f / 8.0), FL2FXCONST_SGL(-0.39423219786288f / 8.0) }, - { FL2FXCONST_SGL( 0.98299195879514f / 8.0), FL2FXCONST_SGL( 0.01989791390047f / 8.0) }, - { FL2FXCONST_SGL(-0.30963073129751f / 8.0), FL2FXCONST_SGL(-0.18076720599336f / 8.0) }, - { FL2FXCONST_SGL( 0.99992588229018f / 8.0), FL2FXCONST_SGL(-0.26281872094289f / 8.0) }, - { FL2FXCONST_SGL(-0.93149731080767f / 8.0), FL2FXCONST_SGL(-0.98313162570490f / 8.0) }, - { FL2FXCONST_SGL( 0.99923472302773f / 8.0), FL2FXCONST_SGL(-0.80142993767554f / 8.0) }, - { FL2FXCONST_SGL(-0.26024169633417f / 8.0), FL2FXCONST_SGL(-0.75999759855752f / 8.0) }, - { FL2FXCONST_SGL(-0.35712514743563f / 8.0), FL2FXCONST_SGL( 0.19298963768574f / 8.0) }, - { FL2FXCONST_SGL(-0.99899084509530f / 8.0), FL2FXCONST_SGL( 0.74645156992493f / 8.0) }, - { FL2FXCONST_SGL( 0.86557171579452f / 8.0), FL2FXCONST_SGL( 0.55593866696299f / 8.0) }, - { FL2FXCONST_SGL( 0.33408042438752f / 8.0), FL2FXCONST_SGL( 0.86185953874709f / 8.0) }, - { FL2FXCONST_SGL( 0.99010736374716f / 8.0), FL2FXCONST_SGL( 0.04602397576623f / 8.0) }, - { FL2FXCONST_SGL(-0.66694269691195f / 8.0), FL2FXCONST_SGL(-0.91643611810148f / 8.0) }, - { FL2FXCONST_SGL( 0.64016792079480f / 8.0), FL2FXCONST_SGL( 0.15649530836856f / 8.0) }, - { FL2FXCONST_SGL( 0.99570534804836f / 8.0), FL2FXCONST_SGL( 0.45844586038111f / 8.0) }, - { FL2FXCONST_SGL(-0.63431466947340f / 8.0), FL2FXCONST_SGL( 0.21079116459234f / 8.0) }, - { FL2FXCONST_SGL(-0.07706847005931f / 8.0), FL2FXCONST_SGL(-0.89581437101329f / 8.0) }, - { FL2FXCONST_SGL( 0.98590090577724f / 8.0), FL2FXCONST_SGL( 0.88241721133981f / 8.0) }, - { FL2FXCONST_SGL( 0.80099335254678f / 8.0), FL2FXCONST_SGL(-0.36851896710853f / 8.0) }, - { FL2FXCONST_SGL( 0.78368131392666f / 8.0), FL2FXCONST_SGL( 0.45506999802597f / 8.0) }, - { FL2FXCONST_SGL( 0.08707806671691f / 8.0), FL2FXCONST_SGL( 0.80938994918745f / 8.0) }, - { FL2FXCONST_SGL(-0.86811883080712f / 8.0), FL2FXCONST_SGL( 0.39347308654705f / 8.0) }, - { FL2FXCONST_SGL(-0.39466529740375f / 8.0), FL2FXCONST_SGL(-0.66809432114456f / 8.0) }, - { FL2FXCONST_SGL( 0.97875325649683f / 8.0), FL2FXCONST_SGL(-0.72467840967746f / 8.0) }, - { FL2FXCONST_SGL(-0.95038560288864f / 8.0), FL2FXCONST_SGL( 0.89563219587625f / 8.0) }, - { FL2FXCONST_SGL( 0.17005239424212f / 8.0), FL2FXCONST_SGL( 0.54683053962658f / 8.0) }, - { FL2FXCONST_SGL(-0.76910792026848f / 8.0), FL2FXCONST_SGL(-0.96226617549298f / 8.0) }, - { FL2FXCONST_SGL( 0.99743281016846f / 8.0), FL2FXCONST_SGL( 0.42697157037567f / 8.0) }, - { FL2FXCONST_SGL( 0.95437383549973f / 8.0), FL2FXCONST_SGL( 0.97002324109952f / 8.0) }, - { FL2FXCONST_SGL( 0.99578905365569f / 8.0), FL2FXCONST_SGL(-0.54106826257356f / 8.0) }, - { FL2FXCONST_SGL( 0.28058259829990f / 8.0), FL2FXCONST_SGL(-0.85361420634036f / 8.0) }, - { FL2FXCONST_SGL( 0.85256524470573f / 8.0), FL2FXCONST_SGL(-0.64567607735589f / 8.0) }, - { FL2FXCONST_SGL(-0.50608540105128f / 8.0), FL2FXCONST_SGL(-0.65846015480300f / 8.0) }, - { FL2FXCONST_SGL(-0.97210735183243f / 8.0), FL2FXCONST_SGL(-0.23095213067791f / 8.0) }, - { FL2FXCONST_SGL( 0.95424048234441f / 8.0), FL2FXCONST_SGL(-0.99240147091219f / 8.0) }, - { FL2FXCONST_SGL(-0.96926570524023f / 8.0), FL2FXCONST_SGL( 0.73775654896574f / 8.0) }, - { FL2FXCONST_SGL( 0.30872163214726f / 8.0), FL2FXCONST_SGL( 0.41514960556126f / 8.0) }, - { FL2FXCONST_SGL(-0.24523839572639f / 8.0), FL2FXCONST_SGL( 0.63206633394807f / 8.0) }, - { FL2FXCONST_SGL(-0.33813265086024f / 8.0), FL2FXCONST_SGL(-0.38661779441897f / 8.0) }, - { FL2FXCONST_SGL(-0.05826828420146f / 8.0), FL2FXCONST_SGL(-0.06940774188029f / 8.0) }, - { FL2FXCONST_SGL(-0.22898461455054f / 8.0), FL2FXCONST_SGL( 0.97054853316316f / 8.0) }, - { FL2FXCONST_SGL(-0.18509915019881f / 8.0), FL2FXCONST_SGL( 0.47565762892084f / 8.0) }, - { FL2FXCONST_SGL(-0.10488238045009f / 8.0), FL2FXCONST_SGL(-0.87769947402394f / 8.0) }, - { FL2FXCONST_SGL(-0.71886586182037f / 8.0), FL2FXCONST_SGL( 0.78030982480538f / 8.0) }, - { FL2FXCONST_SGL( 0.99793873738654f / 8.0), FL2FXCONST_SGL( 0.90041310491497f / 8.0) }, - { FL2FXCONST_SGL( 0.57563307626120f / 8.0), FL2FXCONST_SGL(-0.91034337352097f / 8.0) }, - { FL2FXCONST_SGL( 0.28909646383717f / 8.0), FL2FXCONST_SGL( 0.96307783970534f / 8.0) }, - { FL2FXCONST_SGL( 0.42188998312520f / 8.0), FL2FXCONST_SGL( 0.48148651230437f / 8.0) }, - { FL2FXCONST_SGL( 0.93335049681047f / 8.0), FL2FXCONST_SGL(-0.43537023883588f / 8.0) }, - { FL2FXCONST_SGL(-0.97087374418267f / 8.0), FL2FXCONST_SGL( 0.86636445711364f / 8.0) }, - { FL2FXCONST_SGL( 0.36722871286923f / 8.0), FL2FXCONST_SGL( 0.65291654172961f / 8.0) }, - { FL2FXCONST_SGL(-0.81093025665696f / 8.0), FL2FXCONST_SGL( 0.08778370229363f / 8.0) }, - { FL2FXCONST_SGL(-0.26240603062237f / 8.0), FL2FXCONST_SGL(-0.92774095379098f / 8.0) }, - { FL2FXCONST_SGL( 0.83996497984604f / 8.0), FL2FXCONST_SGL( 0.55839849139647f / 8.0) }, - { FL2FXCONST_SGL(-0.99909615720225f / 8.0), FL2FXCONST_SGL(-0.96024605713970f / 8.0) }, - { FL2FXCONST_SGL( 0.74649464155061f / 8.0), FL2FXCONST_SGL( 0.12144893606462f / 8.0) }, - { FL2FXCONST_SGL(-0.74774595569805f / 8.0), FL2FXCONST_SGL(-0.26898062008959f / 8.0) }, - { FL2FXCONST_SGL( 0.95781667469567f / 8.0), FL2FXCONST_SGL(-0.79047927052628f / 8.0) }, - { FL2FXCONST_SGL( 0.95472308713099f / 8.0), FL2FXCONST_SGL(-0.08588776019550f / 8.0) }, - { FL2FXCONST_SGL( 0.48708332746299f / 8.0), FL2FXCONST_SGL( 0.99999041579432f / 8.0) }, - { FL2FXCONST_SGL( 0.46332038247497f / 8.0), FL2FXCONST_SGL( 0.10964126185063f / 8.0) }, - { FL2FXCONST_SGL(-0.76497004940162f / 8.0), FL2FXCONST_SGL( 0.89210929242238f / 8.0) }, - { FL2FXCONST_SGL( 0.57397389364339f / 8.0), FL2FXCONST_SGL( 0.35289703373760f / 8.0) }, - { FL2FXCONST_SGL( 0.75374316974495f / 8.0), FL2FXCONST_SGL( 0.96705214651335f / 8.0) }, - { FL2FXCONST_SGL(-0.59174397685714f / 8.0), FL2FXCONST_SGL(-0.89405370422752f / 8.0) }, - { FL2FXCONST_SGL( 0.75087906691890f / 8.0), FL2FXCONST_SGL(-0.29612672982396f / 8.0) }, - { FL2FXCONST_SGL(-0.98607857336230f / 8.0), FL2FXCONST_SGL( 0.25034911730023f / 8.0) }, - { FL2FXCONST_SGL(-0.40761056640505f / 8.0), FL2FXCONST_SGL(-0.90045573444695f / 8.0) }, - { FL2FXCONST_SGL( 0.66929266740477f / 8.0), FL2FXCONST_SGL( 0.98629493401748f / 8.0) }, - { FL2FXCONST_SGL(-0.97463695257310f / 8.0), FL2FXCONST_SGL(-0.00190223301301f / 8.0) }, - { FL2FXCONST_SGL( 0.90145509409859f / 8.0), FL2FXCONST_SGL( 0.99781390365446f / 8.0) }, - { FL2FXCONST_SGL(-0.87259289048043f / 8.0), FL2FXCONST_SGL( 0.99233587353666f / 8.0) }, - { FL2FXCONST_SGL(-0.91529461447692f / 8.0), FL2FXCONST_SGL(-0.15698707534206f / 8.0) }, - { FL2FXCONST_SGL(-0.03305738840705f / 8.0), FL2FXCONST_SGL(-0.37205262859764f / 8.0) }, - { FL2FXCONST_SGL( 0.07223051368337f / 8.0), FL2FXCONST_SGL(-0.88805001733626f / 8.0) }, - { FL2FXCONST_SGL( 0.99498012188353f / 8.0), FL2FXCONST_SGL( 0.97094358113387f / 8.0) }, - { FL2FXCONST_SGL(-0.74904939500519f / 8.0), FL2FXCONST_SGL( 0.99985483641521f / 8.0) }, - { FL2FXCONST_SGL( 0.04585228574211f / 8.0), FL2FXCONST_SGL( 0.99812337444082f / 8.0) }, - { FL2FXCONST_SGL(-0.89054954257993f / 8.0), FL2FXCONST_SGL(-0.31791913188064f / 8.0) }, - { FL2FXCONST_SGL(-0.83782144651251f / 8.0), FL2FXCONST_SGL( 0.97637632547466f / 8.0) }, - { FL2FXCONST_SGL( 0.33454804933804f / 8.0), FL2FXCONST_SGL(-0.86231516800408f / 8.0) }, - { FL2FXCONST_SGL(-0.99707579362824f / 8.0), FL2FXCONST_SGL( 0.93237990079441f / 8.0) }, - { FL2FXCONST_SGL(-0.22827527843994f / 8.0), FL2FXCONST_SGL( 0.18874759397997f / 8.0) }, - { FL2FXCONST_SGL( 0.67248046289143f / 8.0), FL2FXCONST_SGL(-0.03646211390569f / 8.0) }, - { FL2FXCONST_SGL(-0.05146538187944f / 8.0), FL2FXCONST_SGL(-0.92599700120679f / 8.0) }, - { FL2FXCONST_SGL( 0.99947295749905f / 8.0), FL2FXCONST_SGL( 0.93625229707912f / 8.0) }, - { FL2FXCONST_SGL( 0.66951124390363f / 8.0), FL2FXCONST_SGL( 0.98905825623893f / 8.0) }, - { FL2FXCONST_SGL(-0.99602956559179f / 8.0), FL2FXCONST_SGL(-0.44654715757688f / 8.0) }, - { FL2FXCONST_SGL( 0.82104905483590f / 8.0), FL2FXCONST_SGL( 0.99540741724928f / 8.0) }, - { FL2FXCONST_SGL( 0.99186510988782f / 8.0), FL2FXCONST_SGL( 0.72023001312947f / 8.0) }, - { FL2FXCONST_SGL(-0.65284592392918f / 8.0), FL2FXCONST_SGL( 0.52186723253637f / 8.0) }, - { FL2FXCONST_SGL( 0.93885443798188f / 8.0), FL2FXCONST_SGL(-0.74895312615259f / 8.0) }, - { FL2FXCONST_SGL( 0.96735248738388f / 8.0), FL2FXCONST_SGL( 0.90891816978629f / 8.0) }, - { FL2FXCONST_SGL(-0.22225968841114f / 8.0), FL2FXCONST_SGL( 0.57124029781228f / 8.0) }, - { FL2FXCONST_SGL(-0.44132783753414f / 8.0), FL2FXCONST_SGL(-0.92688840659280f / 8.0) }, - { FL2FXCONST_SGL(-0.85694974219574f / 8.0), FL2FXCONST_SGL( 0.88844532719844f / 8.0) }, - { FL2FXCONST_SGL( 0.91783042091762f / 8.0), FL2FXCONST_SGL(-0.46356892383970f / 8.0) }, - { FL2FXCONST_SGL( 0.72556974415690f / 8.0), FL2FXCONST_SGL(-0.99899555770747f / 8.0) }, - { FL2FXCONST_SGL(-0.99711581834508f / 8.0), FL2FXCONST_SGL( 0.58211560180426f / 8.0) }, - { FL2FXCONST_SGL( 0.77638976371966f / 8.0), FL2FXCONST_SGL( 0.94321834873819f / 8.0) }, - { FL2FXCONST_SGL( 0.07717324253925f / 8.0), FL2FXCONST_SGL( 0.58638399856595f / 8.0) }, - { FL2FXCONST_SGL(-0.56049829194163f / 8.0), FL2FXCONST_SGL( 0.82522301569036f / 8.0) }, - { FL2FXCONST_SGL( 0.98398893639988f / 8.0), FL2FXCONST_SGL( 0.39467440420569f / 8.0) }, - { FL2FXCONST_SGL( 0.47546946844938f / 8.0), FL2FXCONST_SGL( 0.68613044836811f / 8.0) }, - { FL2FXCONST_SGL( 0.65675089314631f / 8.0), FL2FXCONST_SGL( 0.18331637134880f / 8.0) }, - { FL2FXCONST_SGL( 0.03273375457980f / 8.0), FL2FXCONST_SGL(-0.74933109564108f / 8.0) }, - { FL2FXCONST_SGL(-0.38684144784738f / 8.0), FL2FXCONST_SGL( 0.51337349030406f / 8.0) }, - { FL2FXCONST_SGL(-0.97346267944545f / 8.0), FL2FXCONST_SGL(-0.96549364384098f / 8.0) }, - { FL2FXCONST_SGL(-0.53282156061942f / 8.0), FL2FXCONST_SGL(-0.91423265091354f / 8.0) }, - { FL2FXCONST_SGL( 0.99817310731176f / 8.0), FL2FXCONST_SGL( 0.61133572482148f / 8.0) }, - { FL2FXCONST_SGL(-0.50254500772635f / 8.0), FL2FXCONST_SGL(-0.88829338134294f / 8.0) }, - { FL2FXCONST_SGL( 0.01995873238855f / 8.0), FL2FXCONST_SGL( 0.85223515096765f / 8.0) }, - { FL2FXCONST_SGL( 0.99930381973804f / 8.0), FL2FXCONST_SGL( 0.94578896296649f / 8.0) }, - { FL2FXCONST_SGL( 0.82907767600783f / 8.0), FL2FXCONST_SGL(-0.06323442598128f / 8.0) }, - { FL2FXCONST_SGL(-0.58660709669728f / 8.0), FL2FXCONST_SGL( 0.96840773806582f / 8.0) }, - { FL2FXCONST_SGL(-0.17573736667267f / 8.0), FL2FXCONST_SGL(-0.48166920859485f / 8.0) }, - { FL2FXCONST_SGL( 0.83434292401346f / 8.0), FL2FXCONST_SGL(-0.13023450646997f / 8.0) }, - { FL2FXCONST_SGL( 0.05946491307025f / 8.0), FL2FXCONST_SGL( 0.20511047074866f / 8.0) }, - { FL2FXCONST_SGL( 0.81505484574602f / 8.0), FL2FXCONST_SGL(-0.94685947861369f / 8.0) }, - { FL2FXCONST_SGL(-0.44976380954860f / 8.0), FL2FXCONST_SGL( 0.40894572671545f / 8.0) }, - { FL2FXCONST_SGL(-0.89746474625671f / 8.0), FL2FXCONST_SGL( 0.99846578838537f / 8.0) }, - { FL2FXCONST_SGL( 0.39677256130792f / 8.0), FL2FXCONST_SGL(-0.74854668609359f / 8.0) }, - { FL2FXCONST_SGL(-0.07588948563079f / 8.0), FL2FXCONST_SGL( 0.74096214084170f / 8.0) }, - { FL2FXCONST_SGL( 0.76343198951445f / 8.0), FL2FXCONST_SGL( 0.41746629422634f / 8.0) }, - { FL2FXCONST_SGL(-0.74490104699626f / 8.0), FL2FXCONST_SGL( 0.94725911744610f / 8.0) }, - { FL2FXCONST_SGL( 0.64880119792759f / 8.0), FL2FXCONST_SGL( 0.41336660830571f / 8.0) }, - { FL2FXCONST_SGL( 0.62319537462542f / 8.0), FL2FXCONST_SGL(-0.93098313552599f / 8.0) }, - { FL2FXCONST_SGL( 0.42215817594807f / 8.0), FL2FXCONST_SGL(-0.07712787385208f / 8.0) }, - { FL2FXCONST_SGL( 0.02704554141885f / 8.0), FL2FXCONST_SGL(-0.05417518053666f / 8.0) }, - { FL2FXCONST_SGL( 0.80001773566818f / 8.0), FL2FXCONST_SGL( 0.91542195141039f / 8.0) }, - { FL2FXCONST_SGL(-0.79351832348816f / 8.0), FL2FXCONST_SGL(-0.36208897989136f / 8.0) }, - { FL2FXCONST_SGL( 0.63872359151636f / 8.0), FL2FXCONST_SGL( 0.08128252493444f / 8.0) }, - { FL2FXCONST_SGL( 0.52890520960295f / 8.0), FL2FXCONST_SGL( 0.60048872455592f / 8.0) }, - { FL2FXCONST_SGL( 0.74238552914587f / 8.0), FL2FXCONST_SGL( 0.04491915291044f / 8.0) }, - { FL2FXCONST_SGL( 0.99096131449250f / 8.0), FL2FXCONST_SGL(-0.19451182854402f / 8.0) }, - { FL2FXCONST_SGL(-0.80412329643109f / 8.0), FL2FXCONST_SGL(-0.88513818199457f / 8.0) }, - { FL2FXCONST_SGL(-0.64612616129736f / 8.0), FL2FXCONST_SGL( 0.72198674804544f / 8.0) }, - { FL2FXCONST_SGL( 0.11657770663191f / 8.0), FL2FXCONST_SGL(-0.83662833815041f / 8.0) }, - { FL2FXCONST_SGL(-0.95053182488101f / 8.0), FL2FXCONST_SGL(-0.96939905138082f / 8.0) }, - { FL2FXCONST_SGL(-0.62228872928622f / 8.0), FL2FXCONST_SGL( 0.82767262846661f / 8.0) }, - { FL2FXCONST_SGL( 0.03004475787316f / 8.0), FL2FXCONST_SGL(-0.99738896333384f / 8.0) }, - { FL2FXCONST_SGL(-0.97987214341034f / 8.0), FL2FXCONST_SGL( 0.36526129686425f / 8.0) }, - { FL2FXCONST_SGL(-0.99986980746200f / 8.0), FL2FXCONST_SGL(-0.36021610299715f / 8.0) }, - { FL2FXCONST_SGL( 0.89110648599879f / 8.0), FL2FXCONST_SGL(-0.97894250343044f / 8.0) }, - { FL2FXCONST_SGL( 0.10407960510582f / 8.0), FL2FXCONST_SGL( 0.77357793811619f / 8.0) }, - { FL2FXCONST_SGL( 0.95964737821728f / 8.0), FL2FXCONST_SGL(-0.35435818285502f / 8.0) }, - { FL2FXCONST_SGL( 0.50843233159162f / 8.0), FL2FXCONST_SGL( 0.96107691266205f / 8.0) }, - { FL2FXCONST_SGL( 0.17006334670615f / 8.0), FL2FXCONST_SGL(-0.76854025314829f / 8.0) }, - { FL2FXCONST_SGL( 0.25872675063360f / 8.0), FL2FXCONST_SGL( 0.99893303933816f / 8.0) }, - { FL2FXCONST_SGL(-0.01115998681937f / 8.0), FL2FXCONST_SGL( 0.98496019742444f / 8.0) }, - { FL2FXCONST_SGL(-0.79598702973261f / 8.0), FL2FXCONST_SGL( 0.97138411318894f / 8.0) }, - { FL2FXCONST_SGL(-0.99264708948101f / 8.0), FL2FXCONST_SGL(-0.99542822402536f / 8.0) }, - { FL2FXCONST_SGL(-0.99829663752818f / 8.0), FL2FXCONST_SGL( 0.01877138824311f / 8.0) }, - { FL2FXCONST_SGL(-0.70801016548184f / 8.0), FL2FXCONST_SGL( 0.33680685948117f / 8.0) }, - { FL2FXCONST_SGL(-0.70467057786826f / 8.0), FL2FXCONST_SGL( 0.93272777501857f / 8.0) }, - { FL2FXCONST_SGL( 0.99846021905254f / 8.0), FL2FXCONST_SGL(-0.98725746254433f / 8.0) }, - { FL2FXCONST_SGL(-0.63364968534650f / 8.0), FL2FXCONST_SGL(-0.16473594423746f / 8.0) }, - { FL2FXCONST_SGL(-0.16258217500792f / 8.0), FL2FXCONST_SGL(-0.95939125400802f / 8.0) }, - { FL2FXCONST_SGL(-0.43645594360633f / 8.0), FL2FXCONST_SGL(-0.94805030113284f / 8.0) }, - { FL2FXCONST_SGL(-0.99848471702976f / 8.0), FL2FXCONST_SGL( 0.96245166923809f / 8.0) }, - { FL2FXCONST_SGL(-0.16796458968998f / 8.0), FL2FXCONST_SGL(-0.98987511890470f / 8.0) }, - { FL2FXCONST_SGL(-0.87979225745213f / 8.0), FL2FXCONST_SGL(-0.71725725041680f / 8.0) }, - { FL2FXCONST_SGL( 0.44183099021786f / 8.0), FL2FXCONST_SGL(-0.93568974498761f / 8.0) }, - { FL2FXCONST_SGL( 0.93310180125532f / 8.0), FL2FXCONST_SGL(-0.99913308068246f / 8.0) }, - { FL2FXCONST_SGL(-0.93941931782002f / 8.0), FL2FXCONST_SGL(-0.56409379640356f / 8.0) }, - { FL2FXCONST_SGL(-0.88590003188677f / 8.0), FL2FXCONST_SGL( 0.47624600491382f / 8.0) }, - { FL2FXCONST_SGL( 0.99971463703691f / 8.0), FL2FXCONST_SGL(-0.83889954253462f / 8.0) }, - { FL2FXCONST_SGL(-0.75376385639978f / 8.0), FL2FXCONST_SGL( 0.00814643438625f / 8.0) }, - { FL2FXCONST_SGL( 0.93887685615875f / 8.0), FL2FXCONST_SGL(-0.11284528204636f / 8.0) }, - { FL2FXCONST_SGL( 0.85126435782309f / 8.0), FL2FXCONST_SGL( 0.52349251543547f / 8.0) }, - { FL2FXCONST_SGL( 0.39701421446381f / 8.0), FL2FXCONST_SGL( 0.81779634174316f / 8.0) }, - { FL2FXCONST_SGL(-0.37024464187437f / 8.0), FL2FXCONST_SGL(-0.87071656222959f / 8.0) }, - { FL2FXCONST_SGL(-0.36024828242896f / 8.0), FL2FXCONST_SGL( 0.34655735648287f / 8.0) }, - { FL2FXCONST_SGL(-0.93388812549209f / 8.0), FL2FXCONST_SGL(-0.84476541096429f / 8.0) }, - { FL2FXCONST_SGL(-0.65298804552119f / 8.0), FL2FXCONST_SGL(-0.18439575450921f / 8.0) }, - { FL2FXCONST_SGL( 0.11960319006843f / 8.0), FL2FXCONST_SGL( 0.99899346780168f / 8.0) }, - { FL2FXCONST_SGL( 0.94292565553160f / 8.0), FL2FXCONST_SGL( 0.83163906518293f / 8.0) }, - { FL2FXCONST_SGL( 0.75081145286948f / 8.0), FL2FXCONST_SGL(-0.35533223142265f / 8.0) }, - { FL2FXCONST_SGL( 0.56721979748394f / 8.0), FL2FXCONST_SGL(-0.24076836414499f / 8.0) }, - { FL2FXCONST_SGL( 0.46857766746029f / 8.0), FL2FXCONST_SGL(-0.30140233457198f / 8.0) }, - { FL2FXCONST_SGL( 0.97312313923635f / 8.0), FL2FXCONST_SGL(-0.99548191630031f / 8.0) }, - { FL2FXCONST_SGL(-0.38299976567017f / 8.0), FL2FXCONST_SGL( 0.98516909715427f / 8.0) }, - { FL2FXCONST_SGL( 0.41025800019463f / 8.0), FL2FXCONST_SGL( 0.02116736935734f / 8.0) }, - { FL2FXCONST_SGL( 0.09638062008048f / 8.0), FL2FXCONST_SGL( 0.04411984381457f / 8.0) }, - { FL2FXCONST_SGL(-0.85283249275397f / 8.0), FL2FXCONST_SGL( 0.91475563922421f / 8.0) }, - { FL2FXCONST_SGL( 0.88866808958124f / 8.0), FL2FXCONST_SGL(-0.99735267083226f / 8.0) }, - { FL2FXCONST_SGL(-0.48202429536989f / 8.0), FL2FXCONST_SGL(-0.96805608884164f / 8.0) }, - { FL2FXCONST_SGL( 0.27572582416567f / 8.0), FL2FXCONST_SGL( 0.58634753335832f / 8.0) }, - { FL2FXCONST_SGL(-0.65889129659168f / 8.0), FL2FXCONST_SGL( 0.58835634138583f / 8.0) }, - { FL2FXCONST_SGL( 0.98838086953732f / 8.0), FL2FXCONST_SGL( 0.99994349600236f / 8.0) }, - { FL2FXCONST_SGL(-0.20651349620689f / 8.0), FL2FXCONST_SGL( 0.54593044066355f / 8.0) }, - { FL2FXCONST_SGL(-0.62126416356920f / 8.0), FL2FXCONST_SGL(-0.59893681700392f / 8.0) }, - { FL2FXCONST_SGL( 0.20320105410437f / 8.0), FL2FXCONST_SGL(-0.86879180355289f / 8.0) }, - { FL2FXCONST_SGL(-0.97790548600584f / 8.0), FL2FXCONST_SGL( 0.96290806999242f / 8.0) }, - { FL2FXCONST_SGL( 0.11112534735126f / 8.0), FL2FXCONST_SGL( 0.21484763313301f / 8.0) }, - { FL2FXCONST_SGL(-0.41368337314182f / 8.0), FL2FXCONST_SGL( 0.28216837680365f / 8.0) }, - { FL2FXCONST_SGL( 0.24133038992960f / 8.0), FL2FXCONST_SGL( 0.51294362630238f / 8.0) }, - { FL2FXCONST_SGL(-0.66393410674885f / 8.0), FL2FXCONST_SGL(-0.08249679629081f / 8.0) }, - { FL2FXCONST_SGL(-0.53697829178752f / 8.0), FL2FXCONST_SGL(-0.97649903936228f / 8.0) }, - { FL2FXCONST_SGL(-0.97224737889348f / 8.0), FL2FXCONST_SGL( 0.22081333579837f / 8.0) }, - { FL2FXCONST_SGL( 0.87392477144549f / 8.0), FL2FXCONST_SGL(-0.12796173740361f / 8.0) }, - { FL2FXCONST_SGL( 0.19050361015753f / 8.0), FL2FXCONST_SGL( 0.01602615387195f / 8.0) }, - { FL2FXCONST_SGL(-0.46353441212724f / 8.0), FL2FXCONST_SGL(-0.95249041539006f / 8.0) }, - { FL2FXCONST_SGL(-0.07064096339021f / 8.0), FL2FXCONST_SGL(-0.94479803205886f / 8.0) }, - { FL2FXCONST_SGL(-0.92444085484466f / 8.0), FL2FXCONST_SGL(-0.10457590187436f / 8.0) }, - { FL2FXCONST_SGL(-0.83822593578728f / 8.0), FL2FXCONST_SGL(-0.01695043208885f / 8.0) }, - { FL2FXCONST_SGL( 0.75214681811150f / 8.0), FL2FXCONST_SGL(-0.99955681042665f / 8.0) }, - { FL2FXCONST_SGL(-0.42102998829339f / 8.0), FL2FXCONST_SGL( 0.99720941999394f / 8.0) }, - { FL2FXCONST_SGL(-0.72094786237696f / 8.0), FL2FXCONST_SGL(-0.35008961934255f / 8.0) }, - { FL2FXCONST_SGL( 0.78843311019251f / 8.0), FL2FXCONST_SGL( 0.52851398958271f / 8.0) }, - { FL2FXCONST_SGL( 0.97394027897442f / 8.0), FL2FXCONST_SGL(-0.26695944086561f / 8.0) }, - { FL2FXCONST_SGL( 0.99206463477946f / 8.0), FL2FXCONST_SGL(-0.57010120849429f / 8.0) }, - { FL2FXCONST_SGL( 0.76789609461795f / 8.0), FL2FXCONST_SGL(-0.76519356730966f / 8.0) }, - { FL2FXCONST_SGL(-0.82002421836409f / 8.0), FL2FXCONST_SGL(-0.73530179553767f / 8.0) }, - { FL2FXCONST_SGL( 0.81924990025724f / 8.0), FL2FXCONST_SGL( 0.99698425250579f / 8.0) }, - { FL2FXCONST_SGL(-0.26719850873357f / 8.0), FL2FXCONST_SGL( 0.68903369776193f / 8.0) }, - { FL2FXCONST_SGL(-0.43311260380975f / 8.0), FL2FXCONST_SGL( 0.85321815947490f / 8.0) }, - { FL2FXCONST_SGL( 0.99194979673836f / 8.0), FL2FXCONST_SGL( 0.91876249766422f / 8.0) }, - { FL2FXCONST_SGL(-0.80692001248487f / 8.0), FL2FXCONST_SGL(-0.32627540663214f / 8.0) }, - { FL2FXCONST_SGL( 0.43080003649976f / 8.0), FL2FXCONST_SGL(-0.21919095636638f / 8.0) }, - { FL2FXCONST_SGL( 0.67709491937357f / 8.0), FL2FXCONST_SGL(-0.95478075822906f / 8.0) }, - { FL2FXCONST_SGL( 0.56151770568316f / 8.0), FL2FXCONST_SGL(-0.70693811747778f / 8.0) }, - { FL2FXCONST_SGL( 0.10831862810749f / 8.0), FL2FXCONST_SGL(-0.08628837174592f / 8.0) }, - { FL2FXCONST_SGL( 0.91229417540436f / 8.0), FL2FXCONST_SGL(-0.65987351408410f / 8.0) }, - { FL2FXCONST_SGL(-0.48972893932274f / 8.0), FL2FXCONST_SGL( 0.56289246362686f / 8.0) }, - { FL2FXCONST_SGL(-0.89033658689697f / 8.0), FL2FXCONST_SGL(-0.71656563987082f / 8.0) }, - { FL2FXCONST_SGL( 0.65269447475094f / 8.0), FL2FXCONST_SGL( 0.65916004833932f / 8.0) }, - { FL2FXCONST_SGL( 0.67439478141121f / 8.0), FL2FXCONST_SGL(-0.81684380846796f / 8.0) }, - { FL2FXCONST_SGL(-0.47770832416973f / 8.0), FL2FXCONST_SGL(-0.16789556203025f / 8.0) }, - { FL2FXCONST_SGL(-0.99715979260878f / 8.0), FL2FXCONST_SGL(-0.93565784007648f / 8.0) }, - { FL2FXCONST_SGL(-0.90889593602546f / 8.0), FL2FXCONST_SGL( 0.62034397054380f / 8.0) }, - { FL2FXCONST_SGL(-0.06618622548177f / 8.0), FL2FXCONST_SGL(-0.23812217221359f / 8.0) }, - { FL2FXCONST_SGL( 0.99430266919728f / 8.0), FL2FXCONST_SGL( 0.18812555317553f / 8.0) }, - { FL2FXCONST_SGL( 0.97686402381843f / 8.0), FL2FXCONST_SGL(-0.28664534366620f / 8.0) }, - { FL2FXCONST_SGL( 0.94813650221268f / 8.0), FL2FXCONST_SGL(-0.97506640027128f / 8.0) }, - { FL2FXCONST_SGL(-0.95434497492853f / 8.0), FL2FXCONST_SGL(-0.79607978501983f / 8.0) }, - { FL2FXCONST_SGL(-0.49104783137150f / 8.0), FL2FXCONST_SGL( 0.32895214359663f / 8.0) }, - { FL2FXCONST_SGL( 0.99881175120751f / 8.0), FL2FXCONST_SGL( 0.88993983831354f / 8.0) }, - { FL2FXCONST_SGL( 0.50449166760303f / 8.0), FL2FXCONST_SGL(-0.85995072408434f / 8.0) }, - { FL2FXCONST_SGL( 0.47162891065108f / 8.0), FL2FXCONST_SGL(-0.18680204049569f / 8.0) }, - { FL2FXCONST_SGL(-0.62081581361840f / 8.0), FL2FXCONST_SGL( 0.75000676218956f / 8.0) }, - { FL2FXCONST_SGL(-0.43867015250812f / 8.0), FL2FXCONST_SGL( 0.99998069244322f / 8.0) }, - { FL2FXCONST_SGL( 0.98630563232075f / 8.0), FL2FXCONST_SGL(-0.53578899600662f / 8.0) }, - { FL2FXCONST_SGL(-0.61510362277374f / 8.0), FL2FXCONST_SGL(-0.89515019899997f / 8.0) }, - { FL2FXCONST_SGL(-0.03841517601843f / 8.0), FL2FXCONST_SGL(-0.69888815681179f / 8.0) }, - { FL2FXCONST_SGL(-0.30102157304644f / 8.0), FL2FXCONST_SGL(-0.07667808922205f / 8.0) }, - { FL2FXCONST_SGL( 0.41881284182683f / 8.0), FL2FXCONST_SGL( 0.02188098922282f / 8.0) }, - { FL2FXCONST_SGL(-0.86135454941237f / 8.0), FL2FXCONST_SGL( 0.98947480909359f / 8.0) }, - { FL2FXCONST_SGL( 0.67226861393788f / 8.0), FL2FXCONST_SGL(-0.13494389011014f / 8.0) }, - { FL2FXCONST_SGL(-0.70737398842068f / 8.0), FL2FXCONST_SGL(-0.76547349325992f / 8.0) }, - { FL2FXCONST_SGL( 0.94044946687963f / 8.0), FL2FXCONST_SGL( 0.09026201157416f / 8.0) }, - { FL2FXCONST_SGL(-0.82386352534327f / 8.0), FL2FXCONST_SGL( 0.08924768823676f / 8.0) }, - { FL2FXCONST_SGL(-0.32070666698656f / 8.0), FL2FXCONST_SGL( 0.50143421908753f / 8.0) }, - { FL2FXCONST_SGL( 0.57593163224487f / 8.0), FL2FXCONST_SGL(-0.98966422921509f / 8.0) }, - { FL2FXCONST_SGL(-0.36326018419965f / 8.0), FL2FXCONST_SGL( 0.07440243123228f / 8.0) }, - { FL2FXCONST_SGL( 0.99979044674350f / 8.0), FL2FXCONST_SGL(-0.14130287347405f / 8.0) }, - { FL2FXCONST_SGL(-0.92366023326932f / 8.0), FL2FXCONST_SGL(-0.97979298068180f / 8.0) }, - { FL2FXCONST_SGL(-0.44607178518598f / 8.0), FL2FXCONST_SGL(-0.54233252016394f / 8.0) }, - { FL2FXCONST_SGL( 0.44226800932956f / 8.0), FL2FXCONST_SGL( 0.71326756742752f / 8.0) }, - { FL2FXCONST_SGL( 0.03671907158312f / 8.0), FL2FXCONST_SGL( 0.63606389366675f / 8.0) }, - { FL2FXCONST_SGL( 0.52175424682195f / 8.0), FL2FXCONST_SGL(-0.85396826735705f / 8.0) }, - { FL2FXCONST_SGL(-0.94701139690956f / 8.0), FL2FXCONST_SGL(-0.01826348194255f / 8.0) }, - { FL2FXCONST_SGL(-0.98759606946049f / 8.0), FL2FXCONST_SGL( 0.82288714303073f / 8.0) }, - { FL2FXCONST_SGL( 0.87434794743625f / 8.0), FL2FXCONST_SGL( 0.89399495655433f / 8.0) }, - { FL2FXCONST_SGL(-0.93412041758744f / 8.0), FL2FXCONST_SGL( 0.41374052024363f / 8.0) }, - { FL2FXCONST_SGL( 0.96063943315511f / 8.0), FL2FXCONST_SGL( 0.93116709541280f / 8.0) }, - { FL2FXCONST_SGL( 0.97534253457837f / 8.0), FL2FXCONST_SGL( 0.86150930812689f / 8.0) }, - { FL2FXCONST_SGL( 0.99642466504163f / 8.0), FL2FXCONST_SGL( 0.70190043427512f / 8.0) }, - { FL2FXCONST_SGL(-0.94705089665984f / 8.0), FL2FXCONST_SGL(-0.29580042814306f / 8.0) }, - { FL2FXCONST_SGL( 0.91599807087376f / 8.0), FL2FXCONST_SGL(-0.98147830385781f / 8.0) } -}; + {FL2FXCONST_SGL(-0.99948153278296f / 8.0), + FL2FXCONST_SGL(-0.59483417516607f / 8.0)}, + {FL2FXCONST_SGL(0.97113454393991f / 8.0), + FL2FXCONST_SGL(-0.67528515225647f / 8.0)}, + {FL2FXCONST_SGL(0.14130051758487f / 8.0), + FL2FXCONST_SGL(-0.95090983575689f / 8.0)}, + {FL2FXCONST_SGL(-0.47005496701697f / 8.0), + FL2FXCONST_SGL(-0.37340549728647f / 8.0)}, + {FL2FXCONST_SGL(0.80705063769351f / 8.0), + FL2FXCONST_SGL(0.29653668284408f / 8.0)}, + {FL2FXCONST_SGL(-0.38981478896926f / 8.0), + FL2FXCONST_SGL(0.89572605717087f / 8.0)}, + {FL2FXCONST_SGL(-0.01053049862020f / 8.0), + FL2FXCONST_SGL(-0.66959058036166f / 8.0)}, + {FL2FXCONST_SGL(-0.91266367957293f / 8.0), + FL2FXCONST_SGL(-0.11522938140034f / 8.0)}, + {FL2FXCONST_SGL(0.54840422910309f / 8.0), + FL2FXCONST_SGL(0.75221367176302f / 8.0)}, + {FL2FXCONST_SGL(0.40009252867955f / 8.0), + FL2FXCONST_SGL(-0.98929400334421f / 8.0)}, + {FL2FXCONST_SGL(-0.99867974711855f / 8.0), + FL2FXCONST_SGL(-0.88147068645358f / 8.0)}, + {FL2FXCONST_SGL(-0.95531076805040f / 8.0), + FL2FXCONST_SGL(0.90908757154593f / 8.0)}, + {FL2FXCONST_SGL(-0.45725933317144f / 8.0), + FL2FXCONST_SGL(-0.56716323646760f / 8.0)}, + {FL2FXCONST_SGL(-0.72929675029275f / 8.0), + FL2FXCONST_SGL(-0.98008272727324f / 8.0)}, + {FL2FXCONST_SGL(0.75622801399036f / 8.0), + FL2FXCONST_SGL(0.20950329995549f / 8.0)}, + {FL2FXCONST_SGL(0.07069442601050f / 8.0), + FL2FXCONST_SGL(-0.78247898470706f / 8.0)}, + {FL2FXCONST_SGL(0.74496252926055f / 8.0), + FL2FXCONST_SGL(-0.91169004445807f / 8.0)}, + {FL2FXCONST_SGL(-0.96440182703856f / 8.0), + FL2FXCONST_SGL(-0.94739918296622f / 8.0)}, + {FL2FXCONST_SGL(0.30424629369539f / 8.0), + FL2FXCONST_SGL(-0.49438267012479f / 8.0)}, + {FL2FXCONST_SGL(0.66565033746925f / 8.0), + FL2FXCONST_SGL(0.64652935542491f / 8.0)}, + {FL2FXCONST_SGL(0.91697008020594f / 8.0), + FL2FXCONST_SGL(0.17514097332009f / 8.0)}, + {FL2FXCONST_SGL(-0.70774918760427f / 8.0), + FL2FXCONST_SGL(0.52548653416543f / 8.0)}, + {FL2FXCONST_SGL(-0.70051415345560f / 8.0), + FL2FXCONST_SGL(-0.45340028808763f / 8.0)}, + {FL2FXCONST_SGL(-0.99496513054797f / 8.0), + FL2FXCONST_SGL(-0.90071908066973f / 8.0)}, + {FL2FXCONST_SGL(0.98164490790123f / 8.0), + FL2FXCONST_SGL(-0.77463155528697f / 8.0)}, + {FL2FXCONST_SGL(-0.54671580548181f / 8.0), + FL2FXCONST_SGL(-0.02570928536004f / 8.0)}, + {FL2FXCONST_SGL(-0.01689629065389f / 8.0), + FL2FXCONST_SGL(0.00287506445732f / 8.0)}, + {FL2FXCONST_SGL(-0.86110349531986f / 8.0), + FL2FXCONST_SGL(0.42548583726477f / 8.0)}, + {FL2FXCONST_SGL(-0.98892980586032f / 8.0), + FL2FXCONST_SGL(-0.87881132267556f / 8.0)}, + {FL2FXCONST_SGL(0.51756627678691f / 8.0), + FL2FXCONST_SGL(0.66926784710139f / 8.0)}, + {FL2FXCONST_SGL(-0.99635026409640f / 8.0), + FL2FXCONST_SGL(-0.58107730574765f / 8.0)}, + {FL2FXCONST_SGL(-0.99969370862163f / 8.0), + FL2FXCONST_SGL(0.98369989360250f / 8.0)}, + {FL2FXCONST_SGL(0.55266258627194f / 8.0), + FL2FXCONST_SGL(0.59449057465591f / 8.0)}, + {FL2FXCONST_SGL(0.34581177741673f / 8.0), + FL2FXCONST_SGL(0.94879421061866f / 8.0)}, + {FL2FXCONST_SGL(0.62664209577999f / 8.0), + FL2FXCONST_SGL(-0.74402970906471f / 8.0)}, + {FL2FXCONST_SGL(-0.77149701404973f / 8.0), + FL2FXCONST_SGL(-0.33883658042801f / 8.0)}, + {FL2FXCONST_SGL(-0.91592244254432f / 8.0), + FL2FXCONST_SGL(0.03687901376713f / 8.0)}, + {FL2FXCONST_SGL(-0.76285492357887f / 8.0), + FL2FXCONST_SGL(-0.91371867919124f / 8.0)}, + {FL2FXCONST_SGL(0.79788337195331f / 8.0), + FL2FXCONST_SGL(-0.93180971199849f / 8.0)}, + {FL2FXCONST_SGL(0.54473080610200f / 8.0), + FL2FXCONST_SGL(-0.11919206037186f / 8.0)}, + {FL2FXCONST_SGL(-0.85639281671058f / 8.0), + FL2FXCONST_SGL(0.42429854760451f / 8.0)}, + {FL2FXCONST_SGL(-0.92882402971423f / 8.0), + FL2FXCONST_SGL(0.27871809078609f / 8.0)}, + {FL2FXCONST_SGL(-0.11708371046774f / 8.0), + FL2FXCONST_SGL(-0.99800843444966f / 8.0)}, + {FL2FXCONST_SGL(0.21356749817493f / 8.0), + FL2FXCONST_SGL(-0.90716295627033f / 8.0)}, + {FL2FXCONST_SGL(-0.76191692573909f / 8.0), + FL2FXCONST_SGL(0.99768118356265f / 8.0)}, + {FL2FXCONST_SGL(0.98111043100884f / 8.0), + FL2FXCONST_SGL(-0.95854459734407f / 8.0)}, + {FL2FXCONST_SGL(-0.85913269895572f / 8.0), + FL2FXCONST_SGL(0.95766566168880f / 8.0)}, + {FL2FXCONST_SGL(-0.93307242253692f / 8.0), + FL2FXCONST_SGL(0.49431757696466f / 8.0)}, + {FL2FXCONST_SGL(0.30485754879632f / 8.0), + FL2FXCONST_SGL(-0.70540034357529f / 8.0)}, + {FL2FXCONST_SGL(0.85289650925190f / 8.0), + FL2FXCONST_SGL(0.46766131791044f / 8.0)}, + {FL2FXCONST_SGL(0.91328082618125f / 8.0), + FL2FXCONST_SGL(-0.99839597361769f / 8.0)}, + {FL2FXCONST_SGL(-0.05890199924154f / 8.0), + FL2FXCONST_SGL(0.70741827819497f / 8.0)}, + {FL2FXCONST_SGL(0.28398686150148f / 8.0), + FL2FXCONST_SGL(0.34633555702188f / 8.0)}, + {FL2FXCONST_SGL(0.95258164539612f / 8.0), + FL2FXCONST_SGL(-0.54893416026939f / 8.0)}, + {FL2FXCONST_SGL(-0.78566324168507f / 8.0), + FL2FXCONST_SGL(-0.75568541079691f / 8.0)}, + {FL2FXCONST_SGL(-0.95789495447877f / 8.0), + FL2FXCONST_SGL(-0.20423194696966f / 8.0)}, + {FL2FXCONST_SGL(0.82411158711197f / 8.0), + FL2FXCONST_SGL(0.96654618432562f / 8.0)}, + {FL2FXCONST_SGL(-0.65185446735885f / 8.0), + FL2FXCONST_SGL(-0.88734990773289f / 8.0)}, + {FL2FXCONST_SGL(-0.93643603134666f / 8.0), + FL2FXCONST_SGL(0.99870790442385f / 8.0)}, + {FL2FXCONST_SGL(0.91427159529618f / 8.0), + FL2FXCONST_SGL(-0.98290505544444f / 8.0)}, + {FL2FXCONST_SGL(-0.70395684036886f / 8.0), + FL2FXCONST_SGL(0.58796798221039f / 8.0)}, + {FL2FXCONST_SGL(0.00563771969365f / 8.0), + FL2FXCONST_SGL(0.61768196727244f / 8.0)}, + {FL2FXCONST_SGL(0.89065051931895f / 8.0), + FL2FXCONST_SGL(0.52783352697585f / 8.0)}, + {FL2FXCONST_SGL(-0.68683707712762f / 8.0), + FL2FXCONST_SGL(0.80806944710339f / 8.0)}, + {FL2FXCONST_SGL(0.72165342518718f / 8.0), + FL2FXCONST_SGL(-0.69259857349564f / 8.0)}, + {FL2FXCONST_SGL(-0.62928247730667f / 8.0), + FL2FXCONST_SGL(0.13627037407335f / 8.0)}, + {FL2FXCONST_SGL(0.29938434065514f / 8.0), + FL2FXCONST_SGL(-0.46051329682246f / 8.0)}, + {FL2FXCONST_SGL(-0.91781958879280f / 8.0), + FL2FXCONST_SGL(-0.74012716684186f / 8.0)}, + {FL2FXCONST_SGL(0.99298717043688f / 8.0), + FL2FXCONST_SGL(0.40816610075661f / 8.0)}, + {FL2FXCONST_SGL(0.82368298622748f / 8.0), + FL2FXCONST_SGL(-0.74036047190173f / 8.0)}, + {FL2FXCONST_SGL(-0.98512833386833f / 8.0), + FL2FXCONST_SGL(-0.99972330709594f / 8.0)}, + {FL2FXCONST_SGL(-0.95915368242257f / 8.0), + FL2FXCONST_SGL(-0.99237800466040f / 8.0)}, + {FL2FXCONST_SGL(-0.21411126572790f / 8.0), + FL2FXCONST_SGL(-0.93424819052545f / 8.0)}, + {FL2FXCONST_SGL(-0.68821476106884f / 8.0), + FL2FXCONST_SGL(-0.26892306315457f / 8.0)}, + {FL2FXCONST_SGL(0.91851997982317f / 8.0), + FL2FXCONST_SGL(0.09358228901785f / 8.0)}, + {FL2FXCONST_SGL(-0.96062769559127f / 8.0), + FL2FXCONST_SGL(0.36099095133739f / 8.0)}, + {FL2FXCONST_SGL(0.51646184922287f / 8.0), + FL2FXCONST_SGL(-0.71373332873917f / 8.0)}, + {FL2FXCONST_SGL(0.61130721139669f / 8.0), + FL2FXCONST_SGL(0.46950141175917f / 8.0)}, + {FL2FXCONST_SGL(0.47336129371299f / 8.0), + FL2FXCONST_SGL(-0.27333178296162f / 8.0)}, + {FL2FXCONST_SGL(0.90998308703519f / 8.0), + FL2FXCONST_SGL(0.96715662938132f / 8.0)}, + {FL2FXCONST_SGL(0.44844799194357f / 8.0), + FL2FXCONST_SGL(0.99211574628306f / 8.0)}, + {FL2FXCONST_SGL(0.66614891079092f / 8.0), + FL2FXCONST_SGL(0.96590176169121f / 8.0)}, + {FL2FXCONST_SGL(0.74922239129237f / 8.0), + FL2FXCONST_SGL(-0.89879858826087f / 8.0)}, + {FL2FXCONST_SGL(-0.99571588506485f / 8.0), + FL2FXCONST_SGL(0.52785521494349f / 8.0)}, + {FL2FXCONST_SGL(0.97401082477563f / 8.0), + FL2FXCONST_SGL(-0.16855870075190f / 8.0)}, + {FL2FXCONST_SGL(0.72683747733879f / 8.0), + FL2FXCONST_SGL(-0.48060774432251f / 8.0)}, + {FL2FXCONST_SGL(0.95432193457128f / 8.0), + FL2FXCONST_SGL(0.68849603408441f / 8.0)}, + {FL2FXCONST_SGL(-0.72962208425191f / 8.0), + FL2FXCONST_SGL(-0.76608443420917f / 8.0)}, + {FL2FXCONST_SGL(-0.85359479233537f / 8.0), + FL2FXCONST_SGL(0.88738125901579f / 8.0)}, + {FL2FXCONST_SGL(-0.81412430338535f / 8.0), + FL2FXCONST_SGL(-0.97480768049637f / 8.0)}, + {FL2FXCONST_SGL(-0.87930772356786f / 8.0), + FL2FXCONST_SGL(0.74748307690436f / 8.0)}, + {FL2FXCONST_SGL(-0.71573331064977f / 8.0), + FL2FXCONST_SGL(-0.98570608178923f / 8.0)}, + {FL2FXCONST_SGL(0.83524300028228f / 8.0), + FL2FXCONST_SGL(0.83702537075163f / 8.0)}, + {FL2FXCONST_SGL(-0.48086065601423f / 8.0), + FL2FXCONST_SGL(-0.98848504923531f / 8.0)}, + {FL2FXCONST_SGL(0.97139128574778f / 8.0), + FL2FXCONST_SGL(0.80093621198236f / 8.0)}, + {FL2FXCONST_SGL(0.51992825347895f / 8.0), + FL2FXCONST_SGL(0.80247631400510f / 8.0)}, + {FL2FXCONST_SGL(-0.00848591195325f / 8.0), + FL2FXCONST_SGL(-0.76670128000486f / 8.0)}, + {FL2FXCONST_SGL(-0.70294374303036f / 8.0), + FL2FXCONST_SGL(0.55359910445577f / 8.0)}, + {FL2FXCONST_SGL(-0.95894428168140f / 8.0), + FL2FXCONST_SGL(-0.43265504344783f / 8.0)}, + {FL2FXCONST_SGL(0.97079252950321f / 8.0), + FL2FXCONST_SGL(0.09325857238682f / 8.0)}, + {FL2FXCONST_SGL(-0.92404293670797f / 8.0), + FL2FXCONST_SGL(0.85507704027855f / 8.0)}, + {FL2FXCONST_SGL(-0.69506469500450f / 8.0), + FL2FXCONST_SGL(0.98633412625459f / 8.0)}, + {FL2FXCONST_SGL(0.26559203620024f / 8.0), + FL2FXCONST_SGL(0.73314307966524f / 8.0)}, + {FL2FXCONST_SGL(0.28038443336943f / 8.0), + FL2FXCONST_SGL(0.14537913654427f / 8.0)}, + {FL2FXCONST_SGL(-0.74138124825523f / 8.0), + FL2FXCONST_SGL(0.99310339807762f / 8.0)}, + {FL2FXCONST_SGL(-0.01752795995444f / 8.0), + FL2FXCONST_SGL(-0.82616635284178f / 8.0)}, + {FL2FXCONST_SGL(-0.55126773094930f / 8.0), + FL2FXCONST_SGL(-0.98898543862153f / 8.0)}, + {FL2FXCONST_SGL(0.97960898850996f / 8.0), + FL2FXCONST_SGL(-0.94021446752851f / 8.0)}, + {FL2FXCONST_SGL(-0.99196309146936f / 8.0), + FL2FXCONST_SGL(0.67019017358456f / 8.0)}, + {FL2FXCONST_SGL(-0.67684928085260f / 8.0), + FL2FXCONST_SGL(0.12631491649378f / 8.0)}, + {FL2FXCONST_SGL(0.09140039465500f / 8.0), + FL2FXCONST_SGL(-0.20537731453108f / 8.0)}, + {FL2FXCONST_SGL(-0.71658965751996f / 8.0), + FL2FXCONST_SGL(-0.97788200391224f / 8.0)}, + {FL2FXCONST_SGL(0.81014640078925f / 8.0), + FL2FXCONST_SGL(0.53722648362443f / 8.0)}, + {FL2FXCONST_SGL(0.40616991671205f / 8.0), + FL2FXCONST_SGL(-0.26469008598449f / 8.0)}, + {FL2FXCONST_SGL(-0.67680188682972f / 8.0), + FL2FXCONST_SGL(0.94502052337695f / 8.0)}, + {FL2FXCONST_SGL(0.86849774348749f / 8.0), + FL2FXCONST_SGL(-0.18333598647899f / 8.0)}, + {FL2FXCONST_SGL(-0.99500381284851f / 8.0), + FL2FXCONST_SGL(-0.02634122068550f / 8.0)}, + {FL2FXCONST_SGL(0.84329189340667f / 8.0), + FL2FXCONST_SGL(0.10406957462213f / 8.0)}, + {FL2FXCONST_SGL(-0.09215968531446f / 8.0), + FL2FXCONST_SGL(0.69540012101253f / 8.0)}, + {FL2FXCONST_SGL(0.99956173327206f / 8.0), + FL2FXCONST_SGL(-0.12358542001404f / 8.0)}, + {FL2FXCONST_SGL(-0.79732779473535f / 8.0), + FL2FXCONST_SGL(-0.91582524736159f / 8.0)}, + {FL2FXCONST_SGL(0.96349973642406f / 8.0), + FL2FXCONST_SGL(0.96640458041000f / 8.0)}, + {FL2FXCONST_SGL(-0.79942778496547f / 8.0), + FL2FXCONST_SGL(0.64323902822857f / 8.0)}, + {FL2FXCONST_SGL(-0.11566039853896f / 8.0), + FL2FXCONST_SGL(0.28587846253726f / 8.0)}, + {FL2FXCONST_SGL(-0.39922954514662f / 8.0), + FL2FXCONST_SGL(0.94129601616966f / 8.0)}, + {FL2FXCONST_SGL(0.99089197565987f / 8.0), + FL2FXCONST_SGL(-0.92062625581587f / 8.0)}, + {FL2FXCONST_SGL(0.28631285179909f / 8.0), + FL2FXCONST_SGL(-0.91035047143603f / 8.0)}, + {FL2FXCONST_SGL(-0.83302725605608f / 8.0), + FL2FXCONST_SGL(-0.67330410892084f / 8.0)}, + {FL2FXCONST_SGL(0.95404443402072f / 8.0), + FL2FXCONST_SGL(0.49162765398743f / 8.0)}, + {FL2FXCONST_SGL(-0.06449863579434f / 8.0), + FL2FXCONST_SGL(0.03250560813135f / 8.0)}, + {FL2FXCONST_SGL(-0.99575054486311f / 8.0), + FL2FXCONST_SGL(0.42389784469507f / 8.0)}, + {FL2FXCONST_SGL(-0.65501142790847f / 8.0), + FL2FXCONST_SGL(0.82546114655624f / 8.0)}, + {FL2FXCONST_SGL(-0.81254441908887f / 8.0), + FL2FXCONST_SGL(-0.51627234660629f / 8.0)}, + {FL2FXCONST_SGL(-0.99646369485481f / 8.0), + FL2FXCONST_SGL(0.84490533520752f / 8.0)}, + {FL2FXCONST_SGL(0.00287840603348f / 8.0), + FL2FXCONST_SGL(0.64768261158166f / 8.0)}, + {FL2FXCONST_SGL(0.70176989408455f / 8.0), + FL2FXCONST_SGL(-0.20453028573322f / 8.0)}, + {FL2FXCONST_SGL(0.96361882270190f / 8.0), + FL2FXCONST_SGL(0.40706967140989f / 8.0)}, + {FL2FXCONST_SGL(-0.68883758192426f / 8.0), + FL2FXCONST_SGL(0.91338958840772f / 8.0)}, + {FL2FXCONST_SGL(-0.34875585502238f / 8.0), + FL2FXCONST_SGL(0.71472290693300f / 8.0)}, + {FL2FXCONST_SGL(0.91980081243087f / 8.0), + FL2FXCONST_SGL(0.66507455644919f / 8.0)}, + {FL2FXCONST_SGL(-0.99009048343881f / 8.0), + FL2FXCONST_SGL(0.85868021604848f / 8.0)}, + {FL2FXCONST_SGL(0.68865791458395f / 8.0), + FL2FXCONST_SGL(0.55660316809678f / 8.0)}, + {FL2FXCONST_SGL(-0.99484402129368f / 8.0), + FL2FXCONST_SGL(-0.20052559254934f / 8.0)}, + {FL2FXCONST_SGL(0.94214511408023f / 8.0), + FL2FXCONST_SGL(-0.99696425367461f / 8.0)}, + {FL2FXCONST_SGL(-0.67414626793544f / 8.0), + FL2FXCONST_SGL(0.49548221180078f / 8.0)}, + {FL2FXCONST_SGL(-0.47339353684664f / 8.0), + FL2FXCONST_SGL(-0.85904328834047f / 8.0)}, + {FL2FXCONST_SGL(0.14323651387360f / 8.0), + FL2FXCONST_SGL(-0.94145598222488f / 8.0)}, + {FL2FXCONST_SGL(-0.29268293575672f / 8.0), + FL2FXCONST_SGL(0.05759224927952f / 8.0)}, + {FL2FXCONST_SGL(0.43793861458754f / 8.0), + FL2FXCONST_SGL(-0.78904969892724f / 8.0)}, + {FL2FXCONST_SGL(-0.36345126374441f / 8.0), + FL2FXCONST_SGL(0.64874435357162f / 8.0)}, + {FL2FXCONST_SGL(-0.08750604656825f / 8.0), + FL2FXCONST_SGL(0.97686944362527f / 8.0)}, + {FL2FXCONST_SGL(-0.96495267812511f / 8.0), + FL2FXCONST_SGL(-0.53960305946511f / 8.0)}, + {FL2FXCONST_SGL(0.55526940659947f / 8.0), + FL2FXCONST_SGL(0.78891523734774f / 8.0)}, + {FL2FXCONST_SGL(0.73538215752630f / 8.0), + FL2FXCONST_SGL(0.96452072373404f / 8.0)}, + {FL2FXCONST_SGL(-0.30889773919437f / 8.0), + FL2FXCONST_SGL(-0.80664389776860f / 8.0)}, + {FL2FXCONST_SGL(0.03574995626194f / 8.0), + FL2FXCONST_SGL(-0.97325616900959f / 8.0)}, + {FL2FXCONST_SGL(0.98720684660488f / 8.0), + FL2FXCONST_SGL(0.48409133691962f / 8.0)}, + {FL2FXCONST_SGL(-0.81689296271203f / 8.0), + FL2FXCONST_SGL(-0.90827703628298f / 8.0)}, + {FL2FXCONST_SGL(0.67866860118215f / 8.0), + FL2FXCONST_SGL(0.81284503870856f / 8.0)}, + {FL2FXCONST_SGL(-0.15808569732583f / 8.0), + FL2FXCONST_SGL(0.85279555024382f / 8.0)}, + {FL2FXCONST_SGL(0.80723395114371f / 8.0), + FL2FXCONST_SGL(-0.24717418514605f / 8.0)}, + {FL2FXCONST_SGL(0.47788757329038f / 8.0), + FL2FXCONST_SGL(-0.46333147839295f / 8.0)}, + {FL2FXCONST_SGL(0.96367554763201f / 8.0), + FL2FXCONST_SGL(0.38486749303242f / 8.0)}, + {FL2FXCONST_SGL(-0.99143875716818f / 8.0), + FL2FXCONST_SGL(-0.24945277239809f / 8.0)}, + {FL2FXCONST_SGL(0.83081876925833f / 8.0), + FL2FXCONST_SGL(-0.94780851414763f / 8.0)}, + {FL2FXCONST_SGL(-0.58753191905341f / 8.0), + FL2FXCONST_SGL(0.01290772389163f / 8.0)}, + {FL2FXCONST_SGL(0.95538108220960f / 8.0), + FL2FXCONST_SGL(-0.85557052096538f / 8.0)}, + {FL2FXCONST_SGL(-0.96490920476211f / 8.0), + FL2FXCONST_SGL(-0.64020970923102f / 8.0)}, + {FL2FXCONST_SGL(-0.97327101028521f / 8.0), + FL2FXCONST_SGL(0.12378128133110f / 8.0)}, + {FL2FXCONST_SGL(0.91400366022124f / 8.0), + FL2FXCONST_SGL(0.57972471346930f / 8.0)}, + {FL2FXCONST_SGL(-0.99925837363824f / 8.0), + FL2FXCONST_SGL(0.71084847864067f / 8.0)}, + {FL2FXCONST_SGL(-0.86875903507313f / 8.0), + FL2FXCONST_SGL(-0.20291699203564f / 8.0)}, + {FL2FXCONST_SGL(-0.26240034795124f / 8.0), + FL2FXCONST_SGL(-0.68264554369108f / 8.0)}, + {FL2FXCONST_SGL(-0.24664412953388f / 8.0), + FL2FXCONST_SGL(-0.87642273115183f / 8.0)}, + {FL2FXCONST_SGL(0.02416275806869f / 8.0), + FL2FXCONST_SGL(0.27192914288905f / 8.0)}, + {FL2FXCONST_SGL(0.82068619590515f / 8.0), + FL2FXCONST_SGL(-0.85087787994476f / 8.0)}, + {FL2FXCONST_SGL(0.88547373760759f / 8.0), + FL2FXCONST_SGL(-0.89636802901469f / 8.0)}, + {FL2FXCONST_SGL(-0.18173078152226f / 8.0), + FL2FXCONST_SGL(-0.26152145156800f / 8.0)}, + {FL2FXCONST_SGL(0.09355476558534f / 8.0), + FL2FXCONST_SGL(0.54845123045604f / 8.0)}, + {FL2FXCONST_SGL(-0.54668414224090f / 8.0), + FL2FXCONST_SGL(0.95980774020221f / 8.0)}, + {FL2FXCONST_SGL(0.37050990604091f / 8.0), + FL2FXCONST_SGL(-0.59910140383171f / 8.0)}, + {FL2FXCONST_SGL(-0.70373594262891f / 8.0), + FL2FXCONST_SGL(0.91227665827081f / 8.0)}, + {FL2FXCONST_SGL(-0.34600785879594f / 8.0), + FL2FXCONST_SGL(-0.99441426144200f / 8.0)}, + {FL2FXCONST_SGL(-0.68774481731008f / 8.0), + FL2FXCONST_SGL(-0.30238837956299f / 8.0)}, + {FL2FXCONST_SGL(-0.26843291251234f / 8.0), + FL2FXCONST_SGL(0.83115668004362f / 8.0)}, + {FL2FXCONST_SGL(0.49072334613242f / 8.0), + FL2FXCONST_SGL(-0.45359708737775f / 8.0)}, + {FL2FXCONST_SGL(0.38975993093975f / 8.0), + FL2FXCONST_SGL(0.95515358099121f / 8.0)}, + {FL2FXCONST_SGL(-0.97757125224150f / 8.0), + FL2FXCONST_SGL(0.05305894580606f / 8.0)}, + {FL2FXCONST_SGL(-0.17325552859616f / 8.0), + FL2FXCONST_SGL(-0.92770672250494f / 8.0)}, + {FL2FXCONST_SGL(0.99948035025744f / 8.0), + FL2FXCONST_SGL(0.58285545563426f / 8.0)}, + {FL2FXCONST_SGL(-0.64946246527458f / 8.0), + FL2FXCONST_SGL(0.68645507104960f / 8.0)}, + {FL2FXCONST_SGL(-0.12016920576437f / 8.0), + FL2FXCONST_SGL(-0.57147322153312f / 8.0)}, + {FL2FXCONST_SGL(-0.58947456517751f / 8.0), + FL2FXCONST_SGL(-0.34847132454388f / 8.0)}, + {FL2FXCONST_SGL(-0.41815140454465f / 8.0), + FL2FXCONST_SGL(0.16276422358861f / 8.0)}, + {FL2FXCONST_SGL(0.99885650204884f / 8.0), + FL2FXCONST_SGL(0.11136095490444f / 8.0)}, + {FL2FXCONST_SGL(-0.56649614128386f / 8.0), + FL2FXCONST_SGL(-0.90494866361587f / 8.0)}, + {FL2FXCONST_SGL(0.94138021032330f / 8.0), + FL2FXCONST_SGL(0.35281916733018f / 8.0)}, + {FL2FXCONST_SGL(-0.75725076534641f / 8.0), + FL2FXCONST_SGL(0.53650549640587f / 8.0)}, + {FL2FXCONST_SGL(0.20541973692630f / 8.0), + FL2FXCONST_SGL(-0.94435144369918f / 8.0)}, + {FL2FXCONST_SGL(0.99980371023351f / 8.0), + FL2FXCONST_SGL(0.79835913565599f / 8.0)}, + {FL2FXCONST_SGL(0.29078277605775f / 8.0), + FL2FXCONST_SGL(0.35393777921520f / 8.0)}, + {FL2FXCONST_SGL(-0.62858772103030f / 8.0), + FL2FXCONST_SGL(0.38765693387102f / 8.0)}, + {FL2FXCONST_SGL(0.43440904467688f / 8.0), + FL2FXCONST_SGL(-0.98546330463232f / 8.0)}, + {FL2FXCONST_SGL(-0.98298583762390f / 8.0), + FL2FXCONST_SGL(0.21021524625209f / 8.0)}, + {FL2FXCONST_SGL(0.19513029146934f / 8.0), + FL2FXCONST_SGL(-0.94239832251867f / 8.0)}, + {FL2FXCONST_SGL(-0.95476662400101f / 8.0), + FL2FXCONST_SGL(0.98364554179143f / 8.0)}, + {FL2FXCONST_SGL(0.93379635304810f / 8.0), + FL2FXCONST_SGL(-0.70881994583682f / 8.0)}, + {FL2FXCONST_SGL(-0.85235410573336f / 8.0), + FL2FXCONST_SGL(-0.08342347966410f / 8.0)}, + {FL2FXCONST_SGL(-0.86425093011245f / 8.0), + FL2FXCONST_SGL(-0.45795025029466f / 8.0)}, + {FL2FXCONST_SGL(0.38879779059045f / 8.0), + FL2FXCONST_SGL(0.97274429344593f / 8.0)}, + {FL2FXCONST_SGL(0.92045124735495f / 8.0), + FL2FXCONST_SGL(-0.62433652524220f / 8.0)}, + {FL2FXCONST_SGL(0.89162532251878f / 8.0), + FL2FXCONST_SGL(0.54950955570563f / 8.0)}, + {FL2FXCONST_SGL(-0.36834336949252f / 8.0), + FL2FXCONST_SGL(0.96458298020975f / 8.0)}, + {FL2FXCONST_SGL(0.93891760988045f / 8.0), + FL2FXCONST_SGL(-0.89968353740388f / 8.0)}, + {FL2FXCONST_SGL(0.99267657565094f / 8.0), + FL2FXCONST_SGL(-0.03757034316958f / 8.0)}, + {FL2FXCONST_SGL(-0.94063471614176f / 8.0), + FL2FXCONST_SGL(0.41332338538963f / 8.0)}, + {FL2FXCONST_SGL(0.99740224117019f / 8.0), + FL2FXCONST_SGL(-0.16830494996370f / 8.0)}, + {FL2FXCONST_SGL(-0.35899413170555f / 8.0), + FL2FXCONST_SGL(-0.46633226649613f / 8.0)}, + {FL2FXCONST_SGL(0.05237237274947f / 8.0), + FL2FXCONST_SGL(-0.25640361602661f / 8.0)}, + {FL2FXCONST_SGL(0.36703583957424f / 8.0), + FL2FXCONST_SGL(-0.38653265641875f / 8.0)}, + {FL2FXCONST_SGL(0.91653180367913f / 8.0), + FL2FXCONST_SGL(-0.30587628726597f / 8.0)}, + {FL2FXCONST_SGL(0.69000803499316f / 8.0), + FL2FXCONST_SGL(0.90952171386132f / 8.0)}, + {FL2FXCONST_SGL(-0.38658751133527f / 8.0), + FL2FXCONST_SGL(0.99501571208985f / 8.0)}, + {FL2FXCONST_SGL(-0.29250814029851f / 8.0), + FL2FXCONST_SGL(0.37444994344615f / 8.0)}, + {FL2FXCONST_SGL(-0.60182204677608f / 8.0), + FL2FXCONST_SGL(0.86779651036123f / 8.0)}, + {FL2FXCONST_SGL(-0.97418588163217f / 8.0), + FL2FXCONST_SGL(0.96468523666475f / 8.0)}, + {FL2FXCONST_SGL(0.88461574003963f / 8.0), + FL2FXCONST_SGL(0.57508405276414f / 8.0)}, + {FL2FXCONST_SGL(0.05198933055162f / 8.0), + FL2FXCONST_SGL(0.21269661669964f / 8.0)}, + {FL2FXCONST_SGL(-0.53499621979720f / 8.0), + FL2FXCONST_SGL(0.97241553731237f / 8.0)}, + {FL2FXCONST_SGL(-0.49429560226497f / 8.0), + FL2FXCONST_SGL(0.98183865291903f / 8.0)}, + {FL2FXCONST_SGL(-0.98935142339139f / 8.0), + FL2FXCONST_SGL(-0.40249159006933f / 8.0)}, + {FL2FXCONST_SGL(-0.98081380091130f / 8.0), + FL2FXCONST_SGL(-0.72856895534041f / 8.0)}, + {FL2FXCONST_SGL(-0.27338148835532f / 8.0), + FL2FXCONST_SGL(0.99950922447209f / 8.0)}, + {FL2FXCONST_SGL(0.06310802338302f / 8.0), + FL2FXCONST_SGL(-0.54539587529618f / 8.0)}, + {FL2FXCONST_SGL(-0.20461677199539f / 8.0), + FL2FXCONST_SGL(-0.14209977628489f / 8.0)}, + {FL2FXCONST_SGL(0.66223843141647f / 8.0), + FL2FXCONST_SGL(0.72528579940326f / 8.0)}, + {FL2FXCONST_SGL(-0.84764345483665f / 8.0), + FL2FXCONST_SGL(0.02372316801261f / 8.0)}, + {FL2FXCONST_SGL(-0.89039863483811f / 8.0), + FL2FXCONST_SGL(0.88866581484602f / 8.0)}, + {FL2FXCONST_SGL(0.95903308477986f / 8.0), + FL2FXCONST_SGL(0.76744927173873f / 8.0)}, + {FL2FXCONST_SGL(0.73504123909879f / 8.0), + FL2FXCONST_SGL(-0.03747203173192f / 8.0)}, + {FL2FXCONST_SGL(-0.31744434966056f / 8.0), + FL2FXCONST_SGL(-0.36834111883652f / 8.0)}, + {FL2FXCONST_SGL(-0.34110827591623f / 8.0), + FL2FXCONST_SGL(0.40211222807691f / 8.0)}, + {FL2FXCONST_SGL(0.47803883714199f / 8.0), + FL2FXCONST_SGL(-0.39423219786288f / 8.0)}, + {FL2FXCONST_SGL(0.98299195879514f / 8.0), + FL2FXCONST_SGL(0.01989791390047f / 8.0)}, + {FL2FXCONST_SGL(-0.30963073129751f / 8.0), + FL2FXCONST_SGL(-0.18076720599336f / 8.0)}, + {FL2FXCONST_SGL(0.99992588229018f / 8.0), + FL2FXCONST_SGL(-0.26281872094289f / 8.0)}, + {FL2FXCONST_SGL(-0.93149731080767f / 8.0), + FL2FXCONST_SGL(-0.98313162570490f / 8.0)}, + {FL2FXCONST_SGL(0.99923472302773f / 8.0), + FL2FXCONST_SGL(-0.80142993767554f / 8.0)}, + {FL2FXCONST_SGL(-0.26024169633417f / 8.0), + FL2FXCONST_SGL(-0.75999759855752f / 8.0)}, + {FL2FXCONST_SGL(-0.35712514743563f / 8.0), + FL2FXCONST_SGL(0.19298963768574f / 8.0)}, + {FL2FXCONST_SGL(-0.99899084509530f / 8.0), + FL2FXCONST_SGL(0.74645156992493f / 8.0)}, + {FL2FXCONST_SGL(0.86557171579452f / 8.0), + FL2FXCONST_SGL(0.55593866696299f / 8.0)}, + {FL2FXCONST_SGL(0.33408042438752f / 8.0), + FL2FXCONST_SGL(0.86185953874709f / 8.0)}, + {FL2FXCONST_SGL(0.99010736374716f / 8.0), + FL2FXCONST_SGL(0.04602397576623f / 8.0)}, + {FL2FXCONST_SGL(-0.66694269691195f / 8.0), + FL2FXCONST_SGL(-0.91643611810148f / 8.0)}, + {FL2FXCONST_SGL(0.64016792079480f / 8.0), + FL2FXCONST_SGL(0.15649530836856f / 8.0)}, + {FL2FXCONST_SGL(0.99570534804836f / 8.0), + FL2FXCONST_SGL(0.45844586038111f / 8.0)}, + {FL2FXCONST_SGL(-0.63431466947340f / 8.0), + FL2FXCONST_SGL(0.21079116459234f / 8.0)}, + {FL2FXCONST_SGL(-0.07706847005931f / 8.0), + FL2FXCONST_SGL(-0.89581437101329f / 8.0)}, + {FL2FXCONST_SGL(0.98590090577724f / 8.0), + FL2FXCONST_SGL(0.88241721133981f / 8.0)}, + {FL2FXCONST_SGL(0.80099335254678f / 8.0), + FL2FXCONST_SGL(-0.36851896710853f / 8.0)}, + {FL2FXCONST_SGL(0.78368131392666f / 8.0), + FL2FXCONST_SGL(0.45506999802597f / 8.0)}, + {FL2FXCONST_SGL(0.08707806671691f / 8.0), + FL2FXCONST_SGL(0.80938994918745f / 8.0)}, + {FL2FXCONST_SGL(-0.86811883080712f / 8.0), + FL2FXCONST_SGL(0.39347308654705f / 8.0)}, + {FL2FXCONST_SGL(-0.39466529740375f / 8.0), + FL2FXCONST_SGL(-0.66809432114456f / 8.0)}, + {FL2FXCONST_SGL(0.97875325649683f / 8.0), + FL2FXCONST_SGL(-0.72467840967746f / 8.0)}, + {FL2FXCONST_SGL(-0.95038560288864f / 8.0), + FL2FXCONST_SGL(0.89563219587625f / 8.0)}, + {FL2FXCONST_SGL(0.17005239424212f / 8.0), + FL2FXCONST_SGL(0.54683053962658f / 8.0)}, + {FL2FXCONST_SGL(-0.76910792026848f / 8.0), + FL2FXCONST_SGL(-0.96226617549298f / 8.0)}, + {FL2FXCONST_SGL(0.99743281016846f / 8.0), + FL2FXCONST_SGL(0.42697157037567f / 8.0)}, + {FL2FXCONST_SGL(0.95437383549973f / 8.0), + FL2FXCONST_SGL(0.97002324109952f / 8.0)}, + {FL2FXCONST_SGL(0.99578905365569f / 8.0), + FL2FXCONST_SGL(-0.54106826257356f / 8.0)}, + {FL2FXCONST_SGL(0.28058259829990f / 8.0), + FL2FXCONST_SGL(-0.85361420634036f / 8.0)}, + {FL2FXCONST_SGL(0.85256524470573f / 8.0), + FL2FXCONST_SGL(-0.64567607735589f / 8.0)}, + {FL2FXCONST_SGL(-0.50608540105128f / 8.0), + FL2FXCONST_SGL(-0.65846015480300f / 8.0)}, + {FL2FXCONST_SGL(-0.97210735183243f / 8.0), + FL2FXCONST_SGL(-0.23095213067791f / 8.0)}, + {FL2FXCONST_SGL(0.95424048234441f / 8.0), + FL2FXCONST_SGL(-0.99240147091219f / 8.0)}, + {FL2FXCONST_SGL(-0.96926570524023f / 8.0), + FL2FXCONST_SGL(0.73775654896574f / 8.0)}, + {FL2FXCONST_SGL(0.30872163214726f / 8.0), + FL2FXCONST_SGL(0.41514960556126f / 8.0)}, + {FL2FXCONST_SGL(-0.24523839572639f / 8.0), + FL2FXCONST_SGL(0.63206633394807f / 8.0)}, + {FL2FXCONST_SGL(-0.33813265086024f / 8.0), + FL2FXCONST_SGL(-0.38661779441897f / 8.0)}, + {FL2FXCONST_SGL(-0.05826828420146f / 8.0), + FL2FXCONST_SGL(-0.06940774188029f / 8.0)}, + {FL2FXCONST_SGL(-0.22898461455054f / 8.0), + FL2FXCONST_SGL(0.97054853316316f / 8.0)}, + {FL2FXCONST_SGL(-0.18509915019881f / 8.0), + FL2FXCONST_SGL(0.47565762892084f / 8.0)}, + {FL2FXCONST_SGL(-0.10488238045009f / 8.0), + FL2FXCONST_SGL(-0.87769947402394f / 8.0)}, + {FL2FXCONST_SGL(-0.71886586182037f / 8.0), + FL2FXCONST_SGL(0.78030982480538f / 8.0)}, + {FL2FXCONST_SGL(0.99793873738654f / 8.0), + FL2FXCONST_SGL(0.90041310491497f / 8.0)}, + {FL2FXCONST_SGL(0.57563307626120f / 8.0), + FL2FXCONST_SGL(-0.91034337352097f / 8.0)}, + {FL2FXCONST_SGL(0.28909646383717f / 8.0), + FL2FXCONST_SGL(0.96307783970534f / 8.0)}, + {FL2FXCONST_SGL(0.42188998312520f / 8.0), + FL2FXCONST_SGL(0.48148651230437f / 8.0)}, + {FL2FXCONST_SGL(0.93335049681047f / 8.0), + FL2FXCONST_SGL(-0.43537023883588f / 8.0)}, + {FL2FXCONST_SGL(-0.97087374418267f / 8.0), + FL2FXCONST_SGL(0.86636445711364f / 8.0)}, + {FL2FXCONST_SGL(0.36722871286923f / 8.0), + FL2FXCONST_SGL(0.65291654172961f / 8.0)}, + {FL2FXCONST_SGL(-0.81093025665696f / 8.0), + FL2FXCONST_SGL(0.08778370229363f / 8.0)}, + {FL2FXCONST_SGL(-0.26240603062237f / 8.0), + FL2FXCONST_SGL(-0.92774095379098f / 8.0)}, + {FL2FXCONST_SGL(0.83996497984604f / 8.0), + FL2FXCONST_SGL(0.55839849139647f / 8.0)}, + {FL2FXCONST_SGL(-0.99909615720225f / 8.0), + FL2FXCONST_SGL(-0.96024605713970f / 8.0)}, + {FL2FXCONST_SGL(0.74649464155061f / 8.0), + FL2FXCONST_SGL(0.12144893606462f / 8.0)}, + {FL2FXCONST_SGL(-0.74774595569805f / 8.0), + FL2FXCONST_SGL(-0.26898062008959f / 8.0)}, + {FL2FXCONST_SGL(0.95781667469567f / 8.0), + FL2FXCONST_SGL(-0.79047927052628f / 8.0)}, + {FL2FXCONST_SGL(0.95472308713099f / 8.0), + FL2FXCONST_SGL(-0.08588776019550f / 8.0)}, + {FL2FXCONST_SGL(0.48708332746299f / 8.0), + FL2FXCONST_SGL(0.99999041579432f / 8.0)}, + {FL2FXCONST_SGL(0.46332038247497f / 8.0), + FL2FXCONST_SGL(0.10964126185063f / 8.0)}, + {FL2FXCONST_SGL(-0.76497004940162f / 8.0), + FL2FXCONST_SGL(0.89210929242238f / 8.0)}, + {FL2FXCONST_SGL(0.57397389364339f / 8.0), + FL2FXCONST_SGL(0.35289703373760f / 8.0)}, + {FL2FXCONST_SGL(0.75374316974495f / 8.0), + FL2FXCONST_SGL(0.96705214651335f / 8.0)}, + {FL2FXCONST_SGL(-0.59174397685714f / 8.0), + FL2FXCONST_SGL(-0.89405370422752f / 8.0)}, + {FL2FXCONST_SGL(0.75087906691890f / 8.0), + FL2FXCONST_SGL(-0.29612672982396f / 8.0)}, + {FL2FXCONST_SGL(-0.98607857336230f / 8.0), + FL2FXCONST_SGL(0.25034911730023f / 8.0)}, + {FL2FXCONST_SGL(-0.40761056640505f / 8.0), + FL2FXCONST_SGL(-0.90045573444695f / 8.0)}, + {FL2FXCONST_SGL(0.66929266740477f / 8.0), + FL2FXCONST_SGL(0.98629493401748f / 8.0)}, + {FL2FXCONST_SGL(-0.97463695257310f / 8.0), + FL2FXCONST_SGL(-0.00190223301301f / 8.0)}, + {FL2FXCONST_SGL(0.90145509409859f / 8.0), + FL2FXCONST_SGL(0.99781390365446f / 8.0)}, + {FL2FXCONST_SGL(-0.87259289048043f / 8.0), + FL2FXCONST_SGL(0.99233587353666f / 8.0)}, + {FL2FXCONST_SGL(-0.91529461447692f / 8.0), + FL2FXCONST_SGL(-0.15698707534206f / 8.0)}, + {FL2FXCONST_SGL(-0.03305738840705f / 8.0), + FL2FXCONST_SGL(-0.37205262859764f / 8.0)}, + {FL2FXCONST_SGL(0.07223051368337f / 8.0), + FL2FXCONST_SGL(-0.88805001733626f / 8.0)}, + {FL2FXCONST_SGL(0.99498012188353f / 8.0), + FL2FXCONST_SGL(0.97094358113387f / 8.0)}, + {FL2FXCONST_SGL(-0.74904939500519f / 8.0), + FL2FXCONST_SGL(0.99985483641521f / 8.0)}, + {FL2FXCONST_SGL(0.04585228574211f / 8.0), + FL2FXCONST_SGL(0.99812337444082f / 8.0)}, + {FL2FXCONST_SGL(-0.89054954257993f / 8.0), + FL2FXCONST_SGL(-0.31791913188064f / 8.0)}, + {FL2FXCONST_SGL(-0.83782144651251f / 8.0), + FL2FXCONST_SGL(0.97637632547466f / 8.0)}, + {FL2FXCONST_SGL(0.33454804933804f / 8.0), + FL2FXCONST_SGL(-0.86231516800408f / 8.0)}, + {FL2FXCONST_SGL(-0.99707579362824f / 8.0), + FL2FXCONST_SGL(0.93237990079441f / 8.0)}, + {FL2FXCONST_SGL(-0.22827527843994f / 8.0), + FL2FXCONST_SGL(0.18874759397997f / 8.0)}, + {FL2FXCONST_SGL(0.67248046289143f / 8.0), + FL2FXCONST_SGL(-0.03646211390569f / 8.0)}, + {FL2FXCONST_SGL(-0.05146538187944f / 8.0), + FL2FXCONST_SGL(-0.92599700120679f / 8.0)}, + {FL2FXCONST_SGL(0.99947295749905f / 8.0), + FL2FXCONST_SGL(0.93625229707912f / 8.0)}, + {FL2FXCONST_SGL(0.66951124390363f / 8.0), + FL2FXCONST_SGL(0.98905825623893f / 8.0)}, + {FL2FXCONST_SGL(-0.99602956559179f / 8.0), + FL2FXCONST_SGL(-0.44654715757688f / 8.0)}, + {FL2FXCONST_SGL(0.82104905483590f / 8.0), + FL2FXCONST_SGL(0.99540741724928f / 8.0)}, + {FL2FXCONST_SGL(0.99186510988782f / 8.0), + FL2FXCONST_SGL(0.72023001312947f / 8.0)}, + {FL2FXCONST_SGL(-0.65284592392918f / 8.0), + FL2FXCONST_SGL(0.52186723253637f / 8.0)}, + {FL2FXCONST_SGL(0.93885443798188f / 8.0), + FL2FXCONST_SGL(-0.74895312615259f / 8.0)}, + {FL2FXCONST_SGL(0.96735248738388f / 8.0), + FL2FXCONST_SGL(0.90891816978629f / 8.0)}, + {FL2FXCONST_SGL(-0.22225968841114f / 8.0), + FL2FXCONST_SGL(0.57124029781228f / 8.0)}, + {FL2FXCONST_SGL(-0.44132783753414f / 8.0), + FL2FXCONST_SGL(-0.92688840659280f / 8.0)}, + {FL2FXCONST_SGL(-0.85694974219574f / 8.0), + FL2FXCONST_SGL(0.88844532719844f / 8.0)}, + {FL2FXCONST_SGL(0.91783042091762f / 8.0), + FL2FXCONST_SGL(-0.46356892383970f / 8.0)}, + {FL2FXCONST_SGL(0.72556974415690f / 8.0), + FL2FXCONST_SGL(-0.99899555770747f / 8.0)}, + {FL2FXCONST_SGL(-0.99711581834508f / 8.0), + FL2FXCONST_SGL(0.58211560180426f / 8.0)}, + {FL2FXCONST_SGL(0.77638976371966f / 8.0), + FL2FXCONST_SGL(0.94321834873819f / 8.0)}, + {FL2FXCONST_SGL(0.07717324253925f / 8.0), + FL2FXCONST_SGL(0.58638399856595f / 8.0)}, + {FL2FXCONST_SGL(-0.56049829194163f / 8.0), + FL2FXCONST_SGL(0.82522301569036f / 8.0)}, + {FL2FXCONST_SGL(0.98398893639988f / 8.0), + FL2FXCONST_SGL(0.39467440420569f / 8.0)}, + {FL2FXCONST_SGL(0.47546946844938f / 8.0), + FL2FXCONST_SGL(0.68613044836811f / 8.0)}, + {FL2FXCONST_SGL(0.65675089314631f / 8.0), + FL2FXCONST_SGL(0.18331637134880f / 8.0)}, + {FL2FXCONST_SGL(0.03273375457980f / 8.0), + FL2FXCONST_SGL(-0.74933109564108f / 8.0)}, + {FL2FXCONST_SGL(-0.38684144784738f / 8.0), + FL2FXCONST_SGL(0.51337349030406f / 8.0)}, + {FL2FXCONST_SGL(-0.97346267944545f / 8.0), + FL2FXCONST_SGL(-0.96549364384098f / 8.0)}, + {FL2FXCONST_SGL(-0.53282156061942f / 8.0), + FL2FXCONST_SGL(-0.91423265091354f / 8.0)}, + {FL2FXCONST_SGL(0.99817310731176f / 8.0), + FL2FXCONST_SGL(0.61133572482148f / 8.0)}, + {FL2FXCONST_SGL(-0.50254500772635f / 8.0), + FL2FXCONST_SGL(-0.88829338134294f / 8.0)}, + {FL2FXCONST_SGL(0.01995873238855f / 8.0), + FL2FXCONST_SGL(0.85223515096765f / 8.0)}, + {FL2FXCONST_SGL(0.99930381973804f / 8.0), + FL2FXCONST_SGL(0.94578896296649f / 8.0)}, + {FL2FXCONST_SGL(0.82907767600783f / 8.0), + FL2FXCONST_SGL(-0.06323442598128f / 8.0)}, + {FL2FXCONST_SGL(-0.58660709669728f / 8.0), + FL2FXCONST_SGL(0.96840773806582f / 8.0)}, + {FL2FXCONST_SGL(-0.17573736667267f / 8.0), + FL2FXCONST_SGL(-0.48166920859485f / 8.0)}, + {FL2FXCONST_SGL(0.83434292401346f / 8.0), + FL2FXCONST_SGL(-0.13023450646997f / 8.0)}, + {FL2FXCONST_SGL(0.05946491307025f / 8.0), + FL2FXCONST_SGL(0.20511047074866f / 8.0)}, + {FL2FXCONST_SGL(0.81505484574602f / 8.0), + FL2FXCONST_SGL(-0.94685947861369f / 8.0)}, + {FL2FXCONST_SGL(-0.44976380954860f / 8.0), + FL2FXCONST_SGL(0.40894572671545f / 8.0)}, + {FL2FXCONST_SGL(-0.89746474625671f / 8.0), + FL2FXCONST_SGL(0.99846578838537f / 8.0)}, + {FL2FXCONST_SGL(0.39677256130792f / 8.0), + FL2FXCONST_SGL(-0.74854668609359f / 8.0)}, + {FL2FXCONST_SGL(-0.07588948563079f / 8.0), + FL2FXCONST_SGL(0.74096214084170f / 8.0)}, + {FL2FXCONST_SGL(0.76343198951445f / 8.0), + FL2FXCONST_SGL(0.41746629422634f / 8.0)}, + {FL2FXCONST_SGL(-0.74490104699626f / 8.0), + FL2FXCONST_SGL(0.94725911744610f / 8.0)}, + {FL2FXCONST_SGL(0.64880119792759f / 8.0), + FL2FXCONST_SGL(0.41336660830571f / 8.0)}, + {FL2FXCONST_SGL(0.62319537462542f / 8.0), + FL2FXCONST_SGL(-0.93098313552599f / 8.0)}, + {FL2FXCONST_SGL(0.42215817594807f / 8.0), + FL2FXCONST_SGL(-0.07712787385208f / 8.0)}, + {FL2FXCONST_SGL(0.02704554141885f / 8.0), + FL2FXCONST_SGL(-0.05417518053666f / 8.0)}, + {FL2FXCONST_SGL(0.80001773566818f / 8.0), + FL2FXCONST_SGL(0.91542195141039f / 8.0)}, + {FL2FXCONST_SGL(-0.79351832348816f / 8.0), + FL2FXCONST_SGL(-0.36208897989136f / 8.0)}, + {FL2FXCONST_SGL(0.63872359151636f / 8.0), + FL2FXCONST_SGL(0.08128252493444f / 8.0)}, + {FL2FXCONST_SGL(0.52890520960295f / 8.0), + FL2FXCONST_SGL(0.60048872455592f / 8.0)}, + {FL2FXCONST_SGL(0.74238552914587f / 8.0), + FL2FXCONST_SGL(0.04491915291044f / 8.0)}, + {FL2FXCONST_SGL(0.99096131449250f / 8.0), + FL2FXCONST_SGL(-0.19451182854402f / 8.0)}, + {FL2FXCONST_SGL(-0.80412329643109f / 8.0), + FL2FXCONST_SGL(-0.88513818199457f / 8.0)}, + {FL2FXCONST_SGL(-0.64612616129736f / 8.0), + FL2FXCONST_SGL(0.72198674804544f / 8.0)}, + {FL2FXCONST_SGL(0.11657770663191f / 8.0), + FL2FXCONST_SGL(-0.83662833815041f / 8.0)}, + {FL2FXCONST_SGL(-0.95053182488101f / 8.0), + FL2FXCONST_SGL(-0.96939905138082f / 8.0)}, + {FL2FXCONST_SGL(-0.62228872928622f / 8.0), + FL2FXCONST_SGL(0.82767262846661f / 8.0)}, + {FL2FXCONST_SGL(0.03004475787316f / 8.0), + FL2FXCONST_SGL(-0.99738896333384f / 8.0)}, + {FL2FXCONST_SGL(-0.97987214341034f / 8.0), + FL2FXCONST_SGL(0.36526129686425f / 8.0)}, + {FL2FXCONST_SGL(-0.99986980746200f / 8.0), + FL2FXCONST_SGL(-0.36021610299715f / 8.0)}, + {FL2FXCONST_SGL(0.89110648599879f / 8.0), + FL2FXCONST_SGL(-0.97894250343044f / 8.0)}, + {FL2FXCONST_SGL(0.10407960510582f / 8.0), + FL2FXCONST_SGL(0.77357793811619f / 8.0)}, + {FL2FXCONST_SGL(0.95964737821728f / 8.0), + FL2FXCONST_SGL(-0.35435818285502f / 8.0)}, + {FL2FXCONST_SGL(0.50843233159162f / 8.0), + FL2FXCONST_SGL(0.96107691266205f / 8.0)}, + {FL2FXCONST_SGL(0.17006334670615f / 8.0), + FL2FXCONST_SGL(-0.76854025314829f / 8.0)}, + {FL2FXCONST_SGL(0.25872675063360f / 8.0), + FL2FXCONST_SGL(0.99893303933816f / 8.0)}, + {FL2FXCONST_SGL(-0.01115998681937f / 8.0), + FL2FXCONST_SGL(0.98496019742444f / 8.0)}, + {FL2FXCONST_SGL(-0.79598702973261f / 8.0), + FL2FXCONST_SGL(0.97138411318894f / 8.0)}, + {FL2FXCONST_SGL(-0.99264708948101f / 8.0), + FL2FXCONST_SGL(-0.99542822402536f / 8.0)}, + {FL2FXCONST_SGL(-0.99829663752818f / 8.0), + FL2FXCONST_SGL(0.01877138824311f / 8.0)}, + {FL2FXCONST_SGL(-0.70801016548184f / 8.0), + FL2FXCONST_SGL(0.33680685948117f / 8.0)}, + {FL2FXCONST_SGL(-0.70467057786826f / 8.0), + FL2FXCONST_SGL(0.93272777501857f / 8.0)}, + {FL2FXCONST_SGL(0.99846021905254f / 8.0), + FL2FXCONST_SGL(-0.98725746254433f / 8.0)}, + {FL2FXCONST_SGL(-0.63364968534650f / 8.0), + FL2FXCONST_SGL(-0.16473594423746f / 8.0)}, + {FL2FXCONST_SGL(-0.16258217500792f / 8.0), + FL2FXCONST_SGL(-0.95939125400802f / 8.0)}, + {FL2FXCONST_SGL(-0.43645594360633f / 8.0), + FL2FXCONST_SGL(-0.94805030113284f / 8.0)}, + {FL2FXCONST_SGL(-0.99848471702976f / 8.0), + FL2FXCONST_SGL(0.96245166923809f / 8.0)}, + {FL2FXCONST_SGL(-0.16796458968998f / 8.0), + FL2FXCONST_SGL(-0.98987511890470f / 8.0)}, + {FL2FXCONST_SGL(-0.87979225745213f / 8.0), + FL2FXCONST_SGL(-0.71725725041680f / 8.0)}, + {FL2FXCONST_SGL(0.44183099021786f / 8.0), + FL2FXCONST_SGL(-0.93568974498761f / 8.0)}, + {FL2FXCONST_SGL(0.93310180125532f / 8.0), + FL2FXCONST_SGL(-0.99913308068246f / 8.0)}, + {FL2FXCONST_SGL(-0.93941931782002f / 8.0), + FL2FXCONST_SGL(-0.56409379640356f / 8.0)}, + {FL2FXCONST_SGL(-0.88590003188677f / 8.0), + FL2FXCONST_SGL(0.47624600491382f / 8.0)}, + {FL2FXCONST_SGL(0.99971463703691f / 8.0), + FL2FXCONST_SGL(-0.83889954253462f / 8.0)}, + {FL2FXCONST_SGL(-0.75376385639978f / 8.0), + FL2FXCONST_SGL(0.00814643438625f / 8.0)}, + {FL2FXCONST_SGL(0.93887685615875f / 8.0), + FL2FXCONST_SGL(-0.11284528204636f / 8.0)}, + {FL2FXCONST_SGL(0.85126435782309f / 8.0), + FL2FXCONST_SGL(0.52349251543547f / 8.0)}, + {FL2FXCONST_SGL(0.39701421446381f / 8.0), + FL2FXCONST_SGL(0.81779634174316f / 8.0)}, + {FL2FXCONST_SGL(-0.37024464187437f / 8.0), + FL2FXCONST_SGL(-0.87071656222959f / 8.0)}, + {FL2FXCONST_SGL(-0.36024828242896f / 8.0), + FL2FXCONST_SGL(0.34655735648287f / 8.0)}, + {FL2FXCONST_SGL(-0.93388812549209f / 8.0), + FL2FXCONST_SGL(-0.84476541096429f / 8.0)}, + {FL2FXCONST_SGL(-0.65298804552119f / 8.0), + FL2FXCONST_SGL(-0.18439575450921f / 8.0)}, + {FL2FXCONST_SGL(0.11960319006843f / 8.0), + FL2FXCONST_SGL(0.99899346780168f / 8.0)}, + {FL2FXCONST_SGL(0.94292565553160f / 8.0), + FL2FXCONST_SGL(0.83163906518293f / 8.0)}, + {FL2FXCONST_SGL(0.75081145286948f / 8.0), + FL2FXCONST_SGL(-0.35533223142265f / 8.0)}, + {FL2FXCONST_SGL(0.56721979748394f / 8.0), + FL2FXCONST_SGL(-0.24076836414499f / 8.0)}, + {FL2FXCONST_SGL(0.46857766746029f / 8.0), + FL2FXCONST_SGL(-0.30140233457198f / 8.0)}, + {FL2FXCONST_SGL(0.97312313923635f / 8.0), + FL2FXCONST_SGL(-0.99548191630031f / 8.0)}, + {FL2FXCONST_SGL(-0.38299976567017f / 8.0), + FL2FXCONST_SGL(0.98516909715427f / 8.0)}, + {FL2FXCONST_SGL(0.41025800019463f / 8.0), + FL2FXCONST_SGL(0.02116736935734f / 8.0)}, + {FL2FXCONST_SGL(0.09638062008048f / 8.0), + FL2FXCONST_SGL(0.04411984381457f / 8.0)}, + {FL2FXCONST_SGL(-0.85283249275397f / 8.0), + FL2FXCONST_SGL(0.91475563922421f / 8.0)}, + {FL2FXCONST_SGL(0.88866808958124f / 8.0), + FL2FXCONST_SGL(-0.99735267083226f / 8.0)}, + {FL2FXCONST_SGL(-0.48202429536989f / 8.0), + FL2FXCONST_SGL(-0.96805608884164f / 8.0)}, + {FL2FXCONST_SGL(0.27572582416567f / 8.0), + FL2FXCONST_SGL(0.58634753335832f / 8.0)}, + {FL2FXCONST_SGL(-0.65889129659168f / 8.0), + FL2FXCONST_SGL(0.58835634138583f / 8.0)}, + {FL2FXCONST_SGL(0.98838086953732f / 8.0), + FL2FXCONST_SGL(0.99994349600236f / 8.0)}, + {FL2FXCONST_SGL(-0.20651349620689f / 8.0), + FL2FXCONST_SGL(0.54593044066355f / 8.0)}, + {FL2FXCONST_SGL(-0.62126416356920f / 8.0), + FL2FXCONST_SGL(-0.59893681700392f / 8.0)}, + {FL2FXCONST_SGL(0.20320105410437f / 8.0), + FL2FXCONST_SGL(-0.86879180355289f / 8.0)}, + {FL2FXCONST_SGL(-0.97790548600584f / 8.0), + FL2FXCONST_SGL(0.96290806999242f / 8.0)}, + {FL2FXCONST_SGL(0.11112534735126f / 8.0), + FL2FXCONST_SGL(0.21484763313301f / 8.0)}, + {FL2FXCONST_SGL(-0.41368337314182f / 8.0), + FL2FXCONST_SGL(0.28216837680365f / 8.0)}, + {FL2FXCONST_SGL(0.24133038992960f / 8.0), + FL2FXCONST_SGL(0.51294362630238f / 8.0)}, + {FL2FXCONST_SGL(-0.66393410674885f / 8.0), + FL2FXCONST_SGL(-0.08249679629081f / 8.0)}, + {FL2FXCONST_SGL(-0.53697829178752f / 8.0), + FL2FXCONST_SGL(-0.97649903936228f / 8.0)}, + {FL2FXCONST_SGL(-0.97224737889348f / 8.0), + FL2FXCONST_SGL(0.22081333579837f / 8.0)}, + {FL2FXCONST_SGL(0.87392477144549f / 8.0), + FL2FXCONST_SGL(-0.12796173740361f / 8.0)}, + {FL2FXCONST_SGL(0.19050361015753f / 8.0), + FL2FXCONST_SGL(0.01602615387195f / 8.0)}, + {FL2FXCONST_SGL(-0.46353441212724f / 8.0), + FL2FXCONST_SGL(-0.95249041539006f / 8.0)}, + {FL2FXCONST_SGL(-0.07064096339021f / 8.0), + FL2FXCONST_SGL(-0.94479803205886f / 8.0)}, + {FL2FXCONST_SGL(-0.92444085484466f / 8.0), + FL2FXCONST_SGL(-0.10457590187436f / 8.0)}, + {FL2FXCONST_SGL(-0.83822593578728f / 8.0), + FL2FXCONST_SGL(-0.01695043208885f / 8.0)}, + {FL2FXCONST_SGL(0.75214681811150f / 8.0), + FL2FXCONST_SGL(-0.99955681042665f / 8.0)}, + {FL2FXCONST_SGL(-0.42102998829339f / 8.0), + FL2FXCONST_SGL(0.99720941999394f / 8.0)}, + {FL2FXCONST_SGL(-0.72094786237696f / 8.0), + FL2FXCONST_SGL(-0.35008961934255f / 8.0)}, + {FL2FXCONST_SGL(0.78843311019251f / 8.0), + FL2FXCONST_SGL(0.52851398958271f / 8.0)}, + {FL2FXCONST_SGL(0.97394027897442f / 8.0), + FL2FXCONST_SGL(-0.26695944086561f / 8.0)}, + {FL2FXCONST_SGL(0.99206463477946f / 8.0), + FL2FXCONST_SGL(-0.57010120849429f / 8.0)}, + {FL2FXCONST_SGL(0.76789609461795f / 8.0), + FL2FXCONST_SGL(-0.76519356730966f / 8.0)}, + {FL2FXCONST_SGL(-0.82002421836409f / 8.0), + FL2FXCONST_SGL(-0.73530179553767f / 8.0)}, + {FL2FXCONST_SGL(0.81924990025724f / 8.0), + FL2FXCONST_SGL(0.99698425250579f / 8.0)}, + {FL2FXCONST_SGL(-0.26719850873357f / 8.0), + FL2FXCONST_SGL(0.68903369776193f / 8.0)}, + {FL2FXCONST_SGL(-0.43311260380975f / 8.0), + FL2FXCONST_SGL(0.85321815947490f / 8.0)}, + {FL2FXCONST_SGL(0.99194979673836f / 8.0), + FL2FXCONST_SGL(0.91876249766422f / 8.0)}, + {FL2FXCONST_SGL(-0.80692001248487f / 8.0), + FL2FXCONST_SGL(-0.32627540663214f / 8.0)}, + {FL2FXCONST_SGL(0.43080003649976f / 8.0), + FL2FXCONST_SGL(-0.21919095636638f / 8.0)}, + {FL2FXCONST_SGL(0.67709491937357f / 8.0), + FL2FXCONST_SGL(-0.95478075822906f / 8.0)}, + {FL2FXCONST_SGL(0.56151770568316f / 8.0), + FL2FXCONST_SGL(-0.70693811747778f / 8.0)}, + {FL2FXCONST_SGL(0.10831862810749f / 8.0), + FL2FXCONST_SGL(-0.08628837174592f / 8.0)}, + {FL2FXCONST_SGL(0.91229417540436f / 8.0), + FL2FXCONST_SGL(-0.65987351408410f / 8.0)}, + {FL2FXCONST_SGL(-0.48972893932274f / 8.0), + FL2FXCONST_SGL(0.56289246362686f / 8.0)}, + {FL2FXCONST_SGL(-0.89033658689697f / 8.0), + FL2FXCONST_SGL(-0.71656563987082f / 8.0)}, + {FL2FXCONST_SGL(0.65269447475094f / 8.0), + FL2FXCONST_SGL(0.65916004833932f / 8.0)}, + {FL2FXCONST_SGL(0.67439478141121f / 8.0), + FL2FXCONST_SGL(-0.81684380846796f / 8.0)}, + {FL2FXCONST_SGL(-0.47770832416973f / 8.0), + FL2FXCONST_SGL(-0.16789556203025f / 8.0)}, + {FL2FXCONST_SGL(-0.99715979260878f / 8.0), + FL2FXCONST_SGL(-0.93565784007648f / 8.0)}, + {FL2FXCONST_SGL(-0.90889593602546f / 8.0), + FL2FXCONST_SGL(0.62034397054380f / 8.0)}, + {FL2FXCONST_SGL(-0.06618622548177f / 8.0), + FL2FXCONST_SGL(-0.23812217221359f / 8.0)}, + {FL2FXCONST_SGL(0.99430266919728f / 8.0), + FL2FXCONST_SGL(0.18812555317553f / 8.0)}, + {FL2FXCONST_SGL(0.97686402381843f / 8.0), + FL2FXCONST_SGL(-0.28664534366620f / 8.0)}, + {FL2FXCONST_SGL(0.94813650221268f / 8.0), + FL2FXCONST_SGL(-0.97506640027128f / 8.0)}, + {FL2FXCONST_SGL(-0.95434497492853f / 8.0), + FL2FXCONST_SGL(-0.79607978501983f / 8.0)}, + {FL2FXCONST_SGL(-0.49104783137150f / 8.0), + FL2FXCONST_SGL(0.32895214359663f / 8.0)}, + {FL2FXCONST_SGL(0.99881175120751f / 8.0), + FL2FXCONST_SGL(0.88993983831354f / 8.0)}, + {FL2FXCONST_SGL(0.50449166760303f / 8.0), + FL2FXCONST_SGL(-0.85995072408434f / 8.0)}, + {FL2FXCONST_SGL(0.47162891065108f / 8.0), + FL2FXCONST_SGL(-0.18680204049569f / 8.0)}, + {FL2FXCONST_SGL(-0.62081581361840f / 8.0), + FL2FXCONST_SGL(0.75000676218956f / 8.0)}, + {FL2FXCONST_SGL(-0.43867015250812f / 8.0), + FL2FXCONST_SGL(0.99998069244322f / 8.0)}, + {FL2FXCONST_SGL(0.98630563232075f / 8.0), + FL2FXCONST_SGL(-0.53578899600662f / 8.0)}, + {FL2FXCONST_SGL(-0.61510362277374f / 8.0), + FL2FXCONST_SGL(-0.89515019899997f / 8.0)}, + {FL2FXCONST_SGL(-0.03841517601843f / 8.0), + FL2FXCONST_SGL(-0.69888815681179f / 8.0)}, + {FL2FXCONST_SGL(-0.30102157304644f / 8.0), + FL2FXCONST_SGL(-0.07667808922205f / 8.0)}, + {FL2FXCONST_SGL(0.41881284182683f / 8.0), + FL2FXCONST_SGL(0.02188098922282f / 8.0)}, + {FL2FXCONST_SGL(-0.86135454941237f / 8.0), + FL2FXCONST_SGL(0.98947480909359f / 8.0)}, + {FL2FXCONST_SGL(0.67226861393788f / 8.0), + FL2FXCONST_SGL(-0.13494389011014f / 8.0)}, + {FL2FXCONST_SGL(-0.70737398842068f / 8.0), + FL2FXCONST_SGL(-0.76547349325992f / 8.0)}, + {FL2FXCONST_SGL(0.94044946687963f / 8.0), + FL2FXCONST_SGL(0.09026201157416f / 8.0)}, + {FL2FXCONST_SGL(-0.82386352534327f / 8.0), + FL2FXCONST_SGL(0.08924768823676f / 8.0)}, + {FL2FXCONST_SGL(-0.32070666698656f / 8.0), + FL2FXCONST_SGL(0.50143421908753f / 8.0)}, + {FL2FXCONST_SGL(0.57593163224487f / 8.0), + FL2FXCONST_SGL(-0.98966422921509f / 8.0)}, + {FL2FXCONST_SGL(-0.36326018419965f / 8.0), + FL2FXCONST_SGL(0.07440243123228f / 8.0)}, + {FL2FXCONST_SGL(0.99979044674350f / 8.0), + FL2FXCONST_SGL(-0.14130287347405f / 8.0)}, + {FL2FXCONST_SGL(-0.92366023326932f / 8.0), + FL2FXCONST_SGL(-0.97979298068180f / 8.0)}, + {FL2FXCONST_SGL(-0.44607178518598f / 8.0), + FL2FXCONST_SGL(-0.54233252016394f / 8.0)}, + {FL2FXCONST_SGL(0.44226800932956f / 8.0), + FL2FXCONST_SGL(0.71326756742752f / 8.0)}, + {FL2FXCONST_SGL(0.03671907158312f / 8.0), + FL2FXCONST_SGL(0.63606389366675f / 8.0)}, + {FL2FXCONST_SGL(0.52175424682195f / 8.0), + FL2FXCONST_SGL(-0.85396826735705f / 8.0)}, + {FL2FXCONST_SGL(-0.94701139690956f / 8.0), + FL2FXCONST_SGL(-0.01826348194255f / 8.0)}, + {FL2FXCONST_SGL(-0.98759606946049f / 8.0), + FL2FXCONST_SGL(0.82288714303073f / 8.0)}, + {FL2FXCONST_SGL(0.87434794743625f / 8.0), + FL2FXCONST_SGL(0.89399495655433f / 8.0)}, + {FL2FXCONST_SGL(-0.93412041758744f / 8.0), + FL2FXCONST_SGL(0.41374052024363f / 8.0)}, + {FL2FXCONST_SGL(0.96063943315511f / 8.0), + FL2FXCONST_SGL(0.93116709541280f / 8.0)}, + {FL2FXCONST_SGL(0.97534253457837f / 8.0), + FL2FXCONST_SGL(0.86150930812689f / 8.0)}, + {FL2FXCONST_SGL(0.99642466504163f / 8.0), + FL2FXCONST_SGL(0.70190043427512f / 8.0)}, + {FL2FXCONST_SGL(-0.94705089665984f / 8.0), + FL2FXCONST_SGL(-0.29580042814306f / 8.0)}, + {FL2FXCONST_SGL(0.91599807087376f / 8.0), + FL2FXCONST_SGL(-0.98147830385781f / 8.0)}}; //@} /* @@ -734,76 +1274,62 @@ static const FIXP_SGL harmonicPhase [2][4] = { }; */ - -/* The CLDFB-80 is not linear phase (unsymmetric), but the exact - phase difference between adjacent bands, at exact positions - (in this case exactly in the frequency band centre), can of - course be determined anyway. While the standard symmetric QMF - bank has a phase difference of 0.5*pi, the CLDFB-80 - bank has the difference 0.2337*pi. */ -const FIXP_SGL harmonicPhaseX [2][4] = { - { FL2FXCONST_SGL( 7.423735494778151e-001), FL2FXCONST_SGL(-6.699862036159475e-001), - FL2FXCONST_SGL(-7.423735494778152e-001), FL2FXCONST_SGL( 6.699862036159474e-001) }, - { FL2FXCONST_SGL( 7.423735494778151e-001), FL2FXCONST_SGL( 6.699862036159476e-001), - FL2FXCONST_SGL(-7.423735494778151e-001), FL2FXCONST_SGL(-6.699862036159476e-001) } -}; - /* tables for SBR and AAC LD */ /* table for 8 time slot index */ -const int FDK_sbrDecoder_envelopeTable_8 [8][5] = { -/* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ -/* borders from left to right side; -1 = not in use */ - /*[|T-|------]*/ { 2, 0, 0, 1, -1 }, - /*[|-T-|-----]*/ { 2, 0, 0, 2, -1 }, - /*[--|T-|----]*/ { 3, 1, 1, 2, 4 }, - /*[---|T-|---]*/ { 3, 1, 1, 3, 5 }, - /*[----|T-|--]*/ { 3, 1, 1, 4, 6 }, - /*[-----|T--|]*/ { 2, 1, 1, 5, -1 }, - /*[------|T-|]*/ { 2, 1, 1, 6, -1 }, - /*[-------|T|]*/ { 2, 1, 1, 7, -1 }, +const int FDK_sbrDecoder_envelopeTable_8[8][5] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* borders from left to right side; -1 = not in use */ + /*[|T-|------]*/ {2, 0, 0, 1, -1}, + /*[|-T-|-----]*/ {2, 0, 0, 2, -1}, + /*[--|T-|----]*/ {3, 1, 1, 2, 4}, + /*[---|T-|---]*/ {3, 1, 1, 3, 5}, + /*[----|T-|--]*/ {3, 1, 1, 4, 6}, + /*[-----|T--|]*/ {2, 1, 1, 5, -1}, + /*[------|T-|]*/ {2, 1, 1, 6, -1}, + /*[-------|T|]*/ {2, 1, 1, 7, -1}, }; /* table for 15 time slot index */ -const int FDK_sbrDecoder_envelopeTable_15 [15][6] = { +const int FDK_sbrDecoder_envelopeTable_15[15][6] = { /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ /* length from left to right side; -1 = not in use */ - /*[|T---|------------]*/ { 2, 0, 0, 4, -1, -1}, - /*[|-T---|-----------]*/ { 2, 0, 0, 5, -1, -1}, - /*[|--|T---|---------]*/ { 3, 1, 1, 2, 6, -1}, - /*[|---|T---|--------]*/ { 3, 1, 1, 3, 7, -1}, - /*[|----|T---|-------]*/ { 3, 1, 1, 4, 8, -1}, - /*[|-----|T---|------]*/ { 3, 1, 1, 5, 9, -1}, - /*[|------|T---|-----]*/ { 3, 1, 1, 6, 10, -1}, - /*[|-------|T---|----]*/ { 3, 1, 1, 7, 11, -1}, - /*[|--------|T---|---]*/ { 3, 1, 1, 8, 12, -1}, - /*[|---------|T---|--]*/ { 3, 1, 1, 9, 13, -1}, - /*[|----------|T----|]*/ { 2, 1, 1,10, -1, -1}, - /*[|-----------|T---|]*/ { 2, 1, 1,11, -1, -1}, - /*[|------------|T--|]*/ { 2, 1, 1,12, -1, -1}, - /*[|-------------|T-|]*/ { 2, 1, 1,13, -1, -1}, - /*[|--------------|T|]*/ { 2, 1, 1,14, -1, -1}, + /*[|T---|------------]*/ {2, 0, 0, 4, -1, -1}, + /*[|-T---|-----------]*/ {2, 0, 0, 5, -1, -1}, + /*[|--|T---|---------]*/ {3, 1, 1, 2, 6, -1}, + /*[|---|T---|--------]*/ {3, 1, 1, 3, 7, -1}, + /*[|----|T---|-------]*/ {3, 1, 1, 4, 8, -1}, + /*[|-----|T---|------]*/ {3, 1, 1, 5, 9, -1}, + /*[|------|T---|-----]*/ {3, 1, 1, 6, 10, -1}, + /*[|-------|T---|----]*/ {3, 1, 1, 7, 11, -1}, + /*[|--------|T---|---]*/ {3, 1, 1, 8, 12, -1}, + /*[|---------|T---|--]*/ {3, 1, 1, 9, 13, -1}, + /*[|----------|T----|]*/ {2, 1, 1, 10, -1, -1}, + /*[|-----------|T---|]*/ {2, 1, 1, 11, -1, -1}, + /*[|------------|T--|]*/ {2, 1, 1, 12, -1, -1}, + /*[|-------------|T-|]*/ {2, 1, 1, 13, -1, -1}, + /*[|--------------|T|]*/ {2, 1, 1, 14, -1, -1}, }; /* table for 16 time slot index */ -const int FDK_sbrDecoder_envelopeTable_16 [16][6] = { +const int FDK_sbrDecoder_envelopeTable_16[16][6] = { /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ /* length from left to right side; -1 = not in use */ - /*[|T---|------------|]*/ { 2, 0, 0, 4, -1, -1}, - /*[|-T---|-----------|]*/ { 2, 0, 0, 5, -1, -1}, - /*[|--|T---|----------]*/ { 3, 1, 1, 2, 6, -1}, - /*[|---|T---|---------]*/ { 3, 1, 1, 3, 7, -1}, - /*[|----|T---|--------]*/ { 3, 1, 1, 4, 8, -1}, - /*[|-----|T---|-------]*/ { 3, 1, 1, 5, 9, -1}, - /*[|------|T---|------]*/ { 3, 1, 1, 6, 10, -1}, - /*[|-------|T---|-----]*/ { 3, 1, 1, 7, 11, -1}, - /*[|--------|T---|----]*/ { 3, 1, 1, 8, 12, -1}, - /*[|---------|T---|---]*/ { 3, 1, 1, 9, 13, -1}, - /*[|----------|T---|--]*/ { 3, 1, 1,10, 14, -1}, - /*[|-----------|T----|]*/ { 2, 1, 1,11, -1, -1}, - /*[|------------|T---|]*/ { 2, 1, 1,12, -1, -1}, - /*[|-------------|T--|]*/ { 2, 1, 1,13, -1, -1}, - /*[|--------------|T-|]*/ { 2, 1, 1,14, -1, -1}, - /*[|---------------|T|]*/ { 2, 1, 1,15, -1, -1}, + /*[|T---|------------|]*/ {2, 0, 0, 4, -1, -1}, + /*[|-T---|-----------|]*/ {2, 0, 0, 5, -1, -1}, + /*[|--|T---|----------]*/ {3, 1, 1, 2, 6, -1}, + /*[|---|T---|---------]*/ {3, 1, 1, 3, 7, -1}, + /*[|----|T---|--------]*/ {3, 1, 1, 4, 8, -1}, + /*[|-----|T---|-------]*/ {3, 1, 1, 5, 9, -1}, + /*[|------|T---|------]*/ {3, 1, 1, 6, 10, -1}, + /*[|-------|T---|-----]*/ {3, 1, 1, 7, 11, -1}, + /*[|--------|T---|----]*/ {3, 1, 1, 8, 12, -1}, + /*[|---------|T---|---]*/ {3, 1, 1, 9, 13, -1}, + /*[|----------|T---|--]*/ {3, 1, 1, 10, 14, -1}, + /*[|-----------|T----|]*/ {2, 1, 1, 11, -1, -1}, + /*[|------------|T---|]*/ {2, 1, 1, 12, -1, -1}, + /*[|-------------|T--|]*/ {2, 1, 1, 13, -1, -1}, + /*[|--------------|T-|]*/ {2, 1, 1, 14, -1, -1}, + /*[|---------------|T|]*/ {2, 1, 1, 15, -1, -1}, }; /*! @@ -812,22 +1338,53 @@ const int FDK_sbrDecoder_envelopeTable_16 [16][6] = { Predefined envelope positions for the FIX-FIX case (static framing) */ //@{ -const FRAME_INFO FDK_sbrDecoder_sbr_frame_info1_15 = { 0, 1, {0, 15, 0, 0, 0, 0}, {1, 0, 0, 0, 0}, -1, 1, {0, 15, 0} }; -const FRAME_INFO FDK_sbrDecoder_sbr_frame_info2_15 = { 0, 2, {0, 8, 15, 0, 0, 0}, {1, 1, 0, 0, 0}, -1, 2, {0, 8, 15} }; -const FRAME_INFO FDK_sbrDecoder_sbr_frame_info4_15 = { 0, 4, {0, 4, 8, 12, 15, 0}, {1, 1, 1, 1, 0}, -1, 2, {0, 8, 15} }; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info1_15 = { + 0, 1, {0, 15, 0, 0, 0, 0}, {1, 0, 0, 0, 0}, -1, 1, {0, 15, 0}, {0, 0, 0}, + 0, 0}; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info2_15 = { + 0, 2, {0, 8, 15, 0, 0, 0}, {1, 1, 0, 0, 0}, -1, 2, {0, 8, 15}, {0, 0, 0}, + 0, 0}; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info4_15 = { + 0, 4, {0, 4, 8, 12, 15, 0}, {1, 1, 1, 1, 0}, -1, 2, {0, 8, 15}, {0, 0, 0}, + 0, 0}; #if (MAX_ENVELOPES >= 8) -const FRAME_INFO FDK_sbrDecoder_sbr_frame_info8_15 = { 0, 8, {0, 2, 4, 6, 8, 10, 12, 14, 15}, {1, 1, 1, 1, 1, 1, 1, 1}, -1, 2, {0, 8, 15} }; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info8_15 = { + 0, + 8, + {0, 2, 4, 6, 8, 10, 12, 14, 15}, + {1, 1, 1, 1, 1, 1, 1, 1}, + -1, + 2, + {0, 8, 15}, + {0, 0, 0}, + 0, + 0}; #endif -const FRAME_INFO FDK_sbrDecoder_sbr_frame_info1_16 = { 0, 1, {0, 16, 0, 0, 0, 0}, {1, 0, 0, 0, 0}, -1, 1, {0, 16, 0} }; -const FRAME_INFO FDK_sbrDecoder_sbr_frame_info2_16 = { 0, 2, {0, 8, 16, 0, 0, 0}, {1, 1, 0, 0, 0}, -1, 2, {0, 8, 16} }; -const FRAME_INFO FDK_sbrDecoder_sbr_frame_info4_16 = { 0, 4, {0, 4, 8, 12, 16, 0}, {1, 1, 1, 1, 0}, -1, 2, {0, 8, 16} }; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info1_16 = { + 0, 1, {0, 16, 0, 0, 0, 0}, {1, 0, 0, 0, 0}, -1, 1, {0, 16, 0}, {0, 0, 0}, + 0, 0}; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info2_16 = { + 0, 2, {0, 8, 16, 0, 0, 0}, {1, 1, 0, 0, 0}, -1, 2, {0, 8, 16}, {0, 0, 0}, + 0, 0}; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info4_16 = { + 0, 4, {0, 4, 8, 12, 16, 0}, {1, 1, 1, 1, 0}, -1, 2, {0, 8, 16}, {0, 0, 0}, + 0, 0}; #if (MAX_ENVELOPES >= 8) -const FRAME_INFO FDK_sbrDecoder_sbr_frame_info8_16 = { 0, 8, {0, 2, 4, 6, 8, 10, 12, 14, 16}, {1, 1, 1, 1, 1, 1, 1, 1}, -1, 2, {0, 8, 16} }; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info8_16 = { + 0, + 8, + {0, 2, 4, 6, 8, 10, 12, 14, 16}, + {1, 1, 1, 1, 1, 1, 1, 1}, + -1, + 2, + {0, 8, 16}, + {0, 0, 0}, + 0, + 0}; #endif - //@} /*! @@ -864,494 +1421,225 @@ const FRAME_INFO FDK_sbrDecoder_sbr_frame_info8_16 = { 0, 8, {0, 2, 4, 6, 8, 10, */ //@{ const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvLevel10T[120][2] = { - { 1, 2 }, { -64, -65 }, { 3, 4 }, { -63, -66 }, - { 5, 6 }, { -62, -67 }, { 7, 8 }, { -61, -68 }, - { 9, 10 }, { -60, -69 }, { 11, 12 }, { -59, -70 }, - { 13, 14 }, { -58, -71 }, { 15, 16 }, { -57, -72 }, - { 17, 18 }, { -73, -56 }, { 19, 21 }, { -74, 20 }, - { -55, -75 }, { 22, 26 }, { 23, 24 }, { -54, -76 }, - { -77, 25 }, { -53, -78 }, { 27, 34 }, { 28, 29 }, - { -52, -79 }, { 30, 31 }, { -80, -51 }, { 32, 33 }, - { -83, -82 }, { -81, -50 }, { 35, 57 }, { 36, 40 }, - { 37, 38 }, { -88, -84 }, { -48, 39 }, { -90, -85 }, - { 41, 46 }, { 42, 43 }, { -49, -87 }, { 44, 45 }, - { -89, -86 }, {-124,-123 }, { 47, 50 }, { 48, 49 }, - {-122,-121 }, {-120,-119 }, { 51, 54 }, { 52, 53 }, - {-118,-117 }, {-116,-115 }, { 55, 56 }, {-114,-113 }, - {-112,-111 }, { 58, 89 }, { 59, 74 }, { 60, 67 }, - { 61, 64 }, { 62, 63 }, {-110,-109 }, {-108,-107 }, - { 65, 66 }, {-106,-105 }, {-104,-103 }, { 68, 71 }, - { 69, 70 }, {-102,-101 }, {-100, -99 }, { 72, 73 }, - { -98, -97 }, { -96, -95 }, { 75, 82 }, { 76, 79 }, - { 77, 78 }, { -94, -93 }, { -92, -91 }, { 80, 81 }, - { -47, -46 }, { -45, -44 }, { 83, 86 }, { 84, 85 }, - { -43, -42 }, { -41, -40 }, { 87, 88 }, { -39, -38 }, - { -37, -36 }, { 90, 105 }, { 91, 98 }, { 92, 95 }, - { 93, 94 }, { -35, -34 }, { -33, -32 }, { 96, 97 }, - { -31, -30 }, { -29, -28 }, { 99, 102 }, { 100, 101 }, - { -27, -26 }, { -25, -24 }, { 103, 104 }, { -23, -22 }, - { -21, -20 }, { 106, 113 }, { 107, 110 }, { 108, 109 }, - { -19, -18 }, { -17, -16 }, { 111, 112 }, { -15, -14 }, - { -13, -12 }, { 114, 117 }, { 115, 116 }, { -11, -10 }, - { -9, -8 }, { 118, 119 }, { -7, -6 }, { -5, -4 } -}; + {1, 2}, {-64, -65}, {3, 4}, {-63, -66}, {5, 6}, + {-62, -67}, {7, 8}, {-61, -68}, {9, 10}, {-60, -69}, + {11, 12}, {-59, -70}, {13, 14}, {-58, -71}, {15, 16}, + {-57, -72}, {17, 18}, {-73, -56}, {19, 21}, {-74, 20}, + {-55, -75}, {22, 26}, {23, 24}, {-54, -76}, {-77, 25}, + {-53, -78}, {27, 34}, {28, 29}, {-52, -79}, {30, 31}, + {-80, -51}, {32, 33}, {-83, -82}, {-81, -50}, {35, 57}, + {36, 40}, {37, 38}, {-88, -84}, {-48, 39}, {-90, -85}, + {41, 46}, {42, 43}, {-49, -87}, {44, 45}, {-89, -86}, + {-124, -123}, {47, 50}, {48, 49}, {-122, -121}, {-120, -119}, + {51, 54}, {52, 53}, {-118, -117}, {-116, -115}, {55, 56}, + {-114, -113}, {-112, -111}, {58, 89}, {59, 74}, {60, 67}, + {61, 64}, {62, 63}, {-110, -109}, {-108, -107}, {65, 66}, + {-106, -105}, {-104, -103}, {68, 71}, {69, 70}, {-102, -101}, + {-100, -99}, {72, 73}, {-98, -97}, {-96, -95}, {75, 82}, + {76, 79}, {77, 78}, {-94, -93}, {-92, -91}, {80, 81}, + {-47, -46}, {-45, -44}, {83, 86}, {84, 85}, {-43, -42}, + {-41, -40}, {87, 88}, {-39, -38}, {-37, -36}, {90, 105}, + {91, 98}, {92, 95}, {93, 94}, {-35, -34}, {-33, -32}, + {96, 97}, {-31, -30}, {-29, -28}, {99, 102}, {100, 101}, + {-27, -26}, {-25, -24}, {103, 104}, {-23, -22}, {-21, -20}, + {106, 113}, {107, 110}, {108, 109}, {-19, -18}, {-17, -16}, + {111, 112}, {-15, -14}, {-13, -12}, {114, 117}, {115, 116}, + {-11, -10}, {-9, -8}, {118, 119}, {-7, -6}, {-5, -4}}; const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvLevel10F[120][2] = { - { 1, 2 }, { -64, -65 }, { 3, 4 }, { -63, -66 }, - { 5, 6 }, { -67, -62 }, { 7, 8 }, { -68, -61 }, - { 9, 10 }, { -69, -60 }, { 11, 13 }, { -70, 12 }, - { -59, -71 }, { 14, 16 }, { -58, 15 }, { -72, -57 }, - { 17, 19 }, { -73, 18 }, { -56, -74 }, { 20, 23 }, - { 21, 22 }, { -55, -75 }, { -54, -53 }, { 24, 27 }, - { 25, 26 }, { -76, -52 }, { -77, -51 }, { 28, 31 }, - { 29, 30 }, { -50, -78 }, { -79, -49 }, { 32, 36 }, - { 33, 34 }, { -48, -47 }, { -80, 35 }, { -81, -82 }, - { 37, 47 }, { 38, 41 }, { 39, 40 }, { -83, -46 }, - { -45, -84 }, { 42, 44 }, { -85, 43 }, { -44, -43 }, - { 45, 46 }, { -88, -87 }, { -86, -90 }, { 48, 66 }, - { 49, 56 }, { 50, 53 }, { 51, 52 }, { -92, -42 }, - { -41, -39 }, { 54, 55 }, {-105, -89 }, { -38, -37 }, - { 57, 60 }, { 58, 59 }, { -94, -91 }, { -40, -36 }, - { 61, 63 }, { -20, 62 }, {-115,-110 }, { 64, 65 }, - {-108,-107 }, {-101, -97 }, { 67, 89 }, { 68, 75 }, - { 69, 72 }, { 70, 71 }, { -95, -93 }, { -34, -27 }, - { 73, 74 }, { -22, -17 }, { -16,-124 }, { 76, 82 }, - { 77, 79 }, {-123, 78 }, {-122,-121 }, { 80, 81 }, - {-120,-119 }, {-118,-117 }, { 83, 86 }, { 84, 85 }, - {-116,-114 }, {-113,-112 }, { 87, 88 }, {-111,-109 }, - {-106,-104 }, { 90, 105 }, { 91, 98 }, { 92, 95 }, - { 93, 94 }, {-103,-102 }, {-100, -99 }, { 96, 97 }, - { -98, -96 }, { -35, -33 }, { 99, 102 }, { 100, 101 }, - { -32, -31 }, { -30, -29 }, { 103, 104 }, { -28, -26 }, - { -25, -24 }, { 106, 113 }, { 107, 110 }, { 108, 109 }, - { -23, -21 }, { -19, -18 }, { 111, 112 }, { -15, -14 }, - { -13, -12 }, { 114, 117 }, { 115, 116 }, { -11, -10 }, - { -9, -8 }, { 118, 119 }, { -7, -6 }, { -5, -4 } -}; + {1, 2}, {-64, -65}, {3, 4}, {-63, -66}, {5, 6}, + {-67, -62}, {7, 8}, {-68, -61}, {9, 10}, {-69, -60}, + {11, 13}, {-70, 12}, {-59, -71}, {14, 16}, {-58, 15}, + {-72, -57}, {17, 19}, {-73, 18}, {-56, -74}, {20, 23}, + {21, 22}, {-55, -75}, {-54, -53}, {24, 27}, {25, 26}, + {-76, -52}, {-77, -51}, {28, 31}, {29, 30}, {-50, -78}, + {-79, -49}, {32, 36}, {33, 34}, {-48, -47}, {-80, 35}, + {-81, -82}, {37, 47}, {38, 41}, {39, 40}, {-83, -46}, + {-45, -84}, {42, 44}, {-85, 43}, {-44, -43}, {45, 46}, + {-88, -87}, {-86, -90}, {48, 66}, {49, 56}, {50, 53}, + {51, 52}, {-92, -42}, {-41, -39}, {54, 55}, {-105, -89}, + {-38, -37}, {57, 60}, {58, 59}, {-94, -91}, {-40, -36}, + {61, 63}, {-20, 62}, {-115, -110}, {64, 65}, {-108, -107}, + {-101, -97}, {67, 89}, {68, 75}, {69, 72}, {70, 71}, + {-95, -93}, {-34, -27}, {73, 74}, {-22, -17}, {-16, -124}, + {76, 82}, {77, 79}, {-123, 78}, {-122, -121}, {80, 81}, + {-120, -119}, {-118, -117}, {83, 86}, {84, 85}, {-116, -114}, + {-113, -112}, {87, 88}, {-111, -109}, {-106, -104}, {90, 105}, + {91, 98}, {92, 95}, {93, 94}, {-103, -102}, {-100, -99}, + {96, 97}, {-98, -96}, {-35, -33}, {99, 102}, {100, 101}, + {-32, -31}, {-30, -29}, {103, 104}, {-28, -26}, {-25, -24}, + {106, 113}, {107, 110}, {108, 109}, {-23, -21}, {-19, -18}, + {111, 112}, {-15, -14}, {-13, -12}, {114, 117}, {115, 116}, + {-11, -10}, {-9, -8}, {118, 119}, {-7, -6}, {-5, -4}}; const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance10T[48][2] = { - { -64, 1 }, { -63, 2 }, { -65, 3 }, { -62, 4 }, - { -66, 5 }, { -61, 6 }, { -67, 7 }, { -60, 8 }, - { -68, 9 }, { 10, 11 }, { -69, -59 }, { 12, 13 }, - { -70, -58 }, { 14, 28 }, { 15, 21 }, { 16, 18 }, - { -57, 17 }, { -71, -56 }, { 19, 20 }, { -88, -87 }, - { -86, -85 }, { 22, 25 }, { 23, 24 }, { -84, -83 }, - { -82, -81 }, { 26, 27 }, { -80, -79 }, { -78, -77 }, - { 29, 36 }, { 30, 33 }, { 31, 32 }, { -76, -75 }, - { -74, -73 }, { 34, 35 }, { -72, -55 }, { -54, -53 }, - { 37, 41 }, { 38, 39 }, { -52, -51 }, { -50, 40 }, - { -49, -48 }, { 42, 45 }, { 43, 44 }, { -47, -46 }, - { -45, -44 }, { 46, 47 }, { -43, -42 }, { -41, -40 } -}; + {-64, 1}, {-63, 2}, {-65, 3}, {-62, 4}, {-66, 5}, {-61, 6}, + {-67, 7}, {-60, 8}, {-68, 9}, {10, 11}, {-69, -59}, {12, 13}, + {-70, -58}, {14, 28}, {15, 21}, {16, 18}, {-57, 17}, {-71, -56}, + {19, 20}, {-88, -87}, {-86, -85}, {22, 25}, {23, 24}, {-84, -83}, + {-82, -81}, {26, 27}, {-80, -79}, {-78, -77}, {29, 36}, {30, 33}, + {31, 32}, {-76, -75}, {-74, -73}, {34, 35}, {-72, -55}, {-54, -53}, + {37, 41}, {38, 39}, {-52, -51}, {-50, 40}, {-49, -48}, {42, 45}, + {43, 44}, {-47, -46}, {-45, -44}, {46, 47}, {-43, -42}, {-41, -40}}; const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance10F[48][2] = { - { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 }, - { -62, 5 }, { -61, 6 }, { -67, 7 }, { -68, 8 }, - { -60, 9 }, { 10, 11 }, { -69, -59 }, { -70, 12 }, - { -58, 13 }, { 14, 17 }, { -71, 15 }, { -57, 16 }, - { -56, -73 }, { 18, 32 }, { 19, 25 }, { 20, 22 }, - { -72, 21 }, { -88, -87 }, { 23, 24 }, { -86, -85 }, - { -84, -83 }, { 26, 29 }, { 27, 28 }, { -82, -81 }, - { -80, -79 }, { 30, 31 }, { -78, -77 }, { -76, -75 }, - { 33, 40 }, { 34, 37 }, { 35, 36 }, { -74, -55 }, - { -54, -53 }, { 38, 39 }, { -52, -51 }, { -50, -49 }, - { 41, 44 }, { 42, 43 }, { -48, -47 }, { -46, -45 }, - { 45, 46 }, { -44, -43 }, { -42, 47 }, { -41, -40 } -}; + {-64, 1}, {-65, 2}, {-63, 3}, {-66, 4}, {-62, 5}, {-61, 6}, + {-67, 7}, {-68, 8}, {-60, 9}, {10, 11}, {-69, -59}, {-70, 12}, + {-58, 13}, {14, 17}, {-71, 15}, {-57, 16}, {-56, -73}, {18, 32}, + {19, 25}, {20, 22}, {-72, 21}, {-88, -87}, {23, 24}, {-86, -85}, + {-84, -83}, {26, 29}, {27, 28}, {-82, -81}, {-80, -79}, {30, 31}, + {-78, -77}, {-76, -75}, {33, 40}, {34, 37}, {35, 36}, {-74, -55}, + {-54, -53}, {38, 39}, {-52, -51}, {-50, -49}, {41, 44}, {42, 43}, + {-48, -47}, {-46, -45}, {45, 46}, {-44, -43}, {-42, 47}, {-41, -40}}; const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvLevel11T[62][2] = { - { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 }, - { -62, 5 }, { -67, 6 }, { -61, 7 }, { -68, 8 }, - { -60, 9 }, { 10, 11 }, { -69, -59 }, { 12, 14 }, - { -70, 13 }, { -71, -58 }, { 15, 18 }, { 16, 17 }, - { -72, -57 }, { -73, -74 }, { 19, 22 }, { -56, 20 }, - { -55, 21 }, { -54, -77 }, { 23, 31 }, { 24, 25 }, - { -75, -76 }, { 26, 27 }, { -78, -53 }, { 28, 29 }, - { -52, -95 }, { -94, 30 }, { -93, -92 }, { 32, 47 }, - { 33, 40 }, { 34, 37 }, { 35, 36 }, { -91, -90 }, - { -89, -88 }, { 38, 39 }, { -87, -86 }, { -85, -84 }, - { 41, 44 }, { 42, 43 }, { -83, -82 }, { -81, -80 }, - { 45, 46 }, { -79, -51 }, { -50, -49 }, { 48, 55 }, - { 49, 52 }, { 50, 51 }, { -48, -47 }, { -46, -45 }, - { 53, 54 }, { -44, -43 }, { -42, -41 }, { 56, 59 }, - { 57, 58 }, { -40, -39 }, { -38, -37 }, { 60, 61 }, - { -36, -35 }, { -34, -33 } -}; + {-64, 1}, {-65, 2}, {-63, 3}, {-66, 4}, {-62, 5}, {-67, 6}, + {-61, 7}, {-68, 8}, {-60, 9}, {10, 11}, {-69, -59}, {12, 14}, + {-70, 13}, {-71, -58}, {15, 18}, {16, 17}, {-72, -57}, {-73, -74}, + {19, 22}, {-56, 20}, {-55, 21}, {-54, -77}, {23, 31}, {24, 25}, + {-75, -76}, {26, 27}, {-78, -53}, {28, 29}, {-52, -95}, {-94, 30}, + {-93, -92}, {32, 47}, {33, 40}, {34, 37}, {35, 36}, {-91, -90}, + {-89, -88}, {38, 39}, {-87, -86}, {-85, -84}, {41, 44}, {42, 43}, + {-83, -82}, {-81, -80}, {45, 46}, {-79, -51}, {-50, -49}, {48, 55}, + {49, 52}, {50, 51}, {-48, -47}, {-46, -45}, {53, 54}, {-44, -43}, + {-42, -41}, {56, 59}, {57, 58}, {-40, -39}, {-38, -37}, {60, 61}, + {-36, -35}, {-34, -33}}; const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvLevel11F[62][2] = { - { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 }, - { -62, 5 }, { -67, 6 }, { 7, 8 }, { -61, -68 }, - { 9, 10 }, { -60, -69 }, { 11, 12 }, { -59, -70 }, - { 13, 14 }, { -58, -71 }, { 15, 16 }, { -57, -72 }, - { 17, 19 }, { -56, 18 }, { -55, -73 }, { 20, 24 }, - { 21, 22 }, { -74, -54 }, { -53, 23 }, { -75, -76 }, - { 25, 30 }, { 26, 27 }, { -52, -51 }, { 28, 29 }, - { -77, -79 }, { -50, -49 }, { 31, 39 }, { 32, 35 }, - { 33, 34 }, { -78, -46 }, { -82, -88 }, { 36, 37 }, - { -83, -48 }, { -47, 38 }, { -86, -85 }, { 40, 47 }, - { 41, 44 }, { 42, 43 }, { -80, -44 }, { -43, -42 }, - { 45, 46 }, { -39, -87 }, { -84, -40 }, { 48, 55 }, - { 49, 52 }, { 50, 51 }, { -95, -94 }, { -93, -92 }, - { 53, 54 }, { -91, -90 }, { -89, -81 }, { 56, 59 }, - { 57, 58 }, { -45, -41 }, { -38, -37 }, { 60, 61 }, - { -36, -35 }, { -34, -33 } -}; + {-64, 1}, {-65, 2}, {-63, 3}, {-66, 4}, {-62, 5}, {-67, 6}, + {7, 8}, {-61, -68}, {9, 10}, {-60, -69}, {11, 12}, {-59, -70}, + {13, 14}, {-58, -71}, {15, 16}, {-57, -72}, {17, 19}, {-56, 18}, + {-55, -73}, {20, 24}, {21, 22}, {-74, -54}, {-53, 23}, {-75, -76}, + {25, 30}, {26, 27}, {-52, -51}, {28, 29}, {-77, -79}, {-50, -49}, + {31, 39}, {32, 35}, {33, 34}, {-78, -46}, {-82, -88}, {36, 37}, + {-83, -48}, {-47, 38}, {-86, -85}, {40, 47}, {41, 44}, {42, 43}, + {-80, -44}, {-43, -42}, {45, 46}, {-39, -87}, {-84, -40}, {48, 55}, + {49, 52}, {50, 51}, {-95, -94}, {-93, -92}, {53, 54}, {-91, -90}, + {-89, -81}, {56, 59}, {57, 58}, {-45, -41}, {-38, -37}, {60, 61}, + {-36, -35}, {-34, -33}}; const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance11T[24][2] = { - { -64, 1 }, { -63, 2 }, { -65, 3 }, { -66, 4 }, - { -62, 5 }, { -61, 6 }, { -67, 7 }, { -68, 8 }, - { -60, 9 }, { 10, 16 }, { 11, 13 }, { -69, 12 }, - { -76, -75 }, { 14, 15 }, { -74, -73 }, { -72, -71 }, - { 17, 20 }, { 18, 19 }, { -70, -59 }, { -58, -57 }, - { 21, 22 }, { -56, -55 }, { -54, 23 }, { -53, -52 } -}; + {-64, 1}, {-63, 2}, {-65, 3}, {-66, 4}, {-62, 5}, {-61, 6}, + {-67, 7}, {-68, 8}, {-60, 9}, {10, 16}, {11, 13}, {-69, 12}, + {-76, -75}, {14, 15}, {-74, -73}, {-72, -71}, {17, 20}, {18, 19}, + {-70, -59}, {-58, -57}, {21, 22}, {-56, -55}, {-54, 23}, {-53, -52}}; const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance11F[24][2] = { - { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 }, - { -62, 5 }, { -61, 6 }, { -67, 7 }, { -68, 8 }, - { -60, 9 }, { 10, 13 }, { -69, 11 }, { -59, 12 }, - { -58, -76 }, { 14, 17 }, { 15, 16 }, { -75, -74 }, - { -73, -72 }, { 18, 21 }, { 19, 20 }, { -71, -70 }, - { -57, -56 }, { 22, 23 }, { -55, -54 }, { -53, -52 } -}; + {-64, 1}, {-65, 2}, {-63, 3}, {-66, 4}, {-62, 5}, {-61, 6}, + {-67, 7}, {-68, 8}, {-60, 9}, {10, 13}, {-69, 11}, {-59, 12}, + {-58, -76}, {14, 17}, {15, 16}, {-75, -74}, {-73, -72}, {18, 21}, + {19, 20}, {-71, -70}, {-57, -56}, {22, 23}, {-55, -54}, {-53, -52}}; const SCHAR FDK_sbrDecoder_sbr_huffBook_NoiseLevel11T[62][2] = { - { -64, 1 }, { -63, 2 }, { -65, 3 }, { -66, 4 }, - { -62, 5 }, { -67, 6 }, { 7, 8 }, { -61, -68 }, - { 9, 30 }, { 10, 15 }, { -60, 11 }, { -69, 12 }, - { 13, 14 }, { -59, -53 }, { -95, -94 }, { 16, 23 }, - { 17, 20 }, { 18, 19 }, { -93, -92 }, { -91, -90 }, - { 21, 22 }, { -89, -88 }, { -87, -86 }, { 24, 27 }, - { 25, 26 }, { -85, -84 }, { -83, -82 }, { 28, 29 }, - { -81, -80 }, { -79, -78 }, { 31, 46 }, { 32, 39 }, - { 33, 36 }, { 34, 35 }, { -77, -76 }, { -75, -74 }, - { 37, 38 }, { -73, -72 }, { -71, -70 }, { 40, 43 }, - { 41, 42 }, { -58, -57 }, { -56, -55 }, { 44, 45 }, - { -54, -52 }, { -51, -50 }, { 47, 54 }, { 48, 51 }, - { 49, 50 }, { -49, -48 }, { -47, -46 }, { 52, 53 }, - { -45, -44 }, { -43, -42 }, { 55, 58 }, { 56, 57 }, - { -41, -40 }, { -39, -38 }, { 59, 60 }, { -37, -36 }, - { -35, 61 }, { -34, -33 } -}; + {-64, 1}, {-63, 2}, {-65, 3}, {-66, 4}, {-62, 5}, {-67, 6}, + {7, 8}, {-61, -68}, {9, 30}, {10, 15}, {-60, 11}, {-69, 12}, + {13, 14}, {-59, -53}, {-95, -94}, {16, 23}, {17, 20}, {18, 19}, + {-93, -92}, {-91, -90}, {21, 22}, {-89, -88}, {-87, -86}, {24, 27}, + {25, 26}, {-85, -84}, {-83, -82}, {28, 29}, {-81, -80}, {-79, -78}, + {31, 46}, {32, 39}, {33, 36}, {34, 35}, {-77, -76}, {-75, -74}, + {37, 38}, {-73, -72}, {-71, -70}, {40, 43}, {41, 42}, {-58, -57}, + {-56, -55}, {44, 45}, {-54, -52}, {-51, -50}, {47, 54}, {48, 51}, + {49, 50}, {-49, -48}, {-47, -46}, {52, 53}, {-45, -44}, {-43, -42}, + {55, 58}, {56, 57}, {-41, -40}, {-39, -38}, {59, 60}, {-37, -36}, + {-35, 61}, {-34, -33}}; const SCHAR FDK_sbrDecoder_sbr_huffBook_NoiseBalance11T[24][2] = { - { -64, 1 }, { -65, 2 }, { -63, 3 }, { 4, 9 }, - { -66, 5 }, { -62, 6 }, { 7, 8 }, { -76, -75 }, - { -74, -73 }, { 10, 17 }, { 11, 14 }, { 12, 13 }, - { -72, -71 }, { -70, -69 }, { 15, 16 }, { -68, -67 }, - { -61, -60 }, { 18, 21 }, { 19, 20 }, { -59, -58 }, - { -57, -56 }, { 22, 23 }, { -55, -54 }, { -53, -52 } -}; + {-64, 1}, {-65, 2}, {-63, 3}, {4, 9}, {-66, 5}, {-62, 6}, + {7, 8}, {-76, -75}, {-74, -73}, {10, 17}, {11, 14}, {12, 13}, + {-72, -71}, {-70, -69}, {15, 16}, {-68, -67}, {-61, -60}, {18, 21}, + {19, 20}, {-59, -58}, {-57, -56}, {22, 23}, {-55, -54}, {-53, -52}}; //@} - - - /*! \name parametric stereo \brief constants used by the parametric stereo part of the decoder */ - /* constants used in psbitdec.cpp */ /* FIX_BORDER can have 0, 1, 2, 4 envelopes */ const UCHAR FDK_sbrDecoder_aFixNoEnvDecode[4] = {0, 1, 2, 4}; - /* IID & ICC Huffman codebooks */ const SCHAR aBookPsIidTimeDecode[28][2] = { - { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 }, - { -62, 5 }, { -67, 6 }, { -61, 7 }, { -68, 8 }, - { -60, 9 }, { -69, 10 }, { -59, 11 }, { -70, 12 }, - { -58, 13 }, { -57, 14 }, { -71, 15 }, { 16, 17 }, - { -56, -72 }, { 18, 21 }, { 19, 20 }, { -55, -78 }, - { -77, -76 }, { 22, 25 }, { 23, 24 }, { -75, -74 }, - { -73, -54 }, { 26, 27 }, { -53, -52 }, { -51, -50 } -}; + {-64, 1}, {-65, 2}, {-63, 3}, {-66, 4}, {-62, 5}, {-67, 6}, + {-61, 7}, {-68, 8}, {-60, 9}, {-69, 10}, {-59, 11}, {-70, 12}, + {-58, 13}, {-57, 14}, {-71, 15}, {16, 17}, {-56, -72}, {18, 21}, + {19, 20}, {-55, -78}, {-77, -76}, {22, 25}, {23, 24}, {-75, -74}, + {-73, -54}, {26, 27}, {-53, -52}, {-51, -50}}; const SCHAR aBookPsIidFreqDecode[28][2] = { - { -64, 1 }, { 2, 3 }, { -63, -65 }, { 4, 5 }, - { -62, -66 }, { 6, 7 }, { -61, -67 }, { 8, 9 }, - { -68, -60 }, { -59, 10 }, { -69, 11 }, { -58, 12 }, - { -70, 13 }, { -71, 14 }, { -57, 15 }, { 16, 17 }, - { -56, -72 }, { 18, 19 }, { -55, -54 }, { 20, 21 }, - { -73, -53 }, { 22, 24 }, { -74, 23 }, { -75, -78 }, - { 25, 26 }, { -77, -76 }, { -52, 27 }, { -51, -50 } -}; + {-64, 1}, {2, 3}, {-63, -65}, {4, 5}, {-62, -66}, {6, 7}, + {-61, -67}, {8, 9}, {-68, -60}, {-59, 10}, {-69, 11}, {-58, 12}, + {-70, 13}, {-71, 14}, {-57, 15}, {16, 17}, {-56, -72}, {18, 19}, + {-55, -54}, {20, 21}, {-73, -53}, {22, 24}, {-74, 23}, {-75, -78}, + {25, 26}, {-77, -76}, {-52, 27}, {-51, -50}}; const SCHAR aBookPsIccTimeDecode[14][2] = { - { -64, 1 }, { -63, 2 }, { -65, 3 }, { -62, 4 }, - { -66, 5 }, { -61, 6 }, { -67, 7 }, { -60, 8 }, - { -68, 9 }, { -59, 10 }, { -69, 11 }, { -58, 12 }, - { -70, 13 }, { -71, -57 } -}; + {-64, 1}, {-63, 2}, {-65, 3}, {-62, 4}, {-66, 5}, {-61, 6}, {-67, 7}, + {-60, 8}, {-68, 9}, {-59, 10}, {-69, 11}, {-58, 12}, {-70, 13}, {-71, -57}}; const SCHAR aBookPsIccFreqDecode[14][2] = { - { -64, 1 }, { -63, 2 }, { -65, 3 }, { -62, 4 }, - { -66, 5 }, { -61, 6 }, { -67, 7 }, { -60, 8 }, - { -59, 9 }, { -68, 10 }, { -58, 11 }, { -69, 12 }, - { -57, 13 }, { -70, -71 } -}; + {-64, 1}, {-63, 2}, {-65, 3}, {-62, 4}, {-66, 5}, {-61, 6}, {-67, 7}, + {-60, 8}, {-59, 9}, {-68, 10}, {-58, 11}, {-69, 12}, {-57, 13}, {-70, -71}}; /* IID-fine Huffman codebooks */ const SCHAR aBookPsIidFineTimeDecode[60][2] = { - { 1, -64 }, { -63, 2 }, { 3, -65 }, { 4, 59 }, - { 5, 7 }, { 6, -67 }, { -68, -60 }, { -61, 8 }, - { 9, 11 }, { -59, 10 }, { -70, -58 }, { 12, 41 }, - { 13, 20 }, { 14, -71 }, { -55, 15 }, { -53, 16 }, - { 17, -77 }, { 18, 19 }, { -85, -84 }, { -46, -45 }, - { -57, 21 }, { 22, 40 }, { 23, 29 }, { -51, 24 }, - { 25, 26 }, { -83, -82 }, { 27, 28 }, { -90, -38 }, - { -92, -91 }, { 30, 37 }, { 31, 34 }, { 32, 33 }, - { -35, -34 }, { -37, -36 }, { 35, 36 }, { -94, -93 }, - { -89, -39 }, { 38, -79 }, { 39, -81 }, { -88, -40 }, - { -74, -54 }, { 42, -69 }, { 43, 44 }, { -72, -56 }, - { 45, 52 }, { 46, 50 }, { 47, -76 }, { -49, 48 }, - { -47, 49 }, { -87, -41 }, { -52, 51 }, { -78, -50 }, - { 53, -73 }, { 54, -75 }, { 55, 57 }, { 56, -80 }, - { -86, -42 }, { -48, 58 }, { -44, -43 }, { -66, -62 } -}; - + {1, -64}, {-63, 2}, {3, -65}, {4, 59}, {5, 7}, {6, -67}, + {-68, -60}, {-61, 8}, {9, 11}, {-59, 10}, {-70, -58}, {12, 41}, + {13, 20}, {14, -71}, {-55, 15}, {-53, 16}, {17, -77}, {18, 19}, + {-85, -84}, {-46, -45}, {-57, 21}, {22, 40}, {23, 29}, {-51, 24}, + {25, 26}, {-83, -82}, {27, 28}, {-90, -38}, {-92, -91}, {30, 37}, + {31, 34}, {32, 33}, {-35, -34}, {-37, -36}, {35, 36}, {-94, -93}, + {-89, -39}, {38, -79}, {39, -81}, {-88, -40}, {-74, -54}, {42, -69}, + {43, 44}, {-72, -56}, {45, 52}, {46, 50}, {47, -76}, {-49, 48}, + {-47, 49}, {-87, -41}, {-52, 51}, {-78, -50}, {53, -73}, {54, -75}, + {55, 57}, {56, -80}, {-86, -42}, {-48, 58}, {-44, -43}, {-66, -62}}; const SCHAR aBookPsIidFineFreqDecode[60][2] = { - { 1, -64 }, { 2, 4 }, { 3, -65 }, { -66, -62 }, - { -63, 5 }, { 6, 7 }, { -67, -61 }, { 8, 9 }, - { -68, -60 }, { 10, 11 }, { -69, -59 }, { 12, 13 }, - { -70, -58 }, { 14, 18 }, { -57, 15 }, { 16, -72 }, - { -54, 17 }, { -75, -53 }, { 19, 37 }, { -56, 20 }, - { 21, -73 }, { 22, 29 }, { 23, -76 }, { 24, -78 }, - { 25, 28 }, { 26, 27 }, { -85, -43 }, { -83, -45 }, - { -81, -47 }, { -52, 30 }, { -50, 31 }, { 32, -79 }, - { 33, 34 }, { -82, -46 }, { 35, 36 }, { -90, -89 }, - { -92, -91 }, { 38, -71 }, { -55, 39 }, { 40, -74 }, - { 41, 50 }, { 42, -77 }, { -49, 43 }, { 44, 47 }, - { 45, 46 }, { -86, -42 }, { -88, -87 }, { 48, 49 }, - { -39, -38 }, { -41, -40 }, { -51, 51 }, { 52, 59 }, - { 53, 56 }, { 54, 55 }, { -35, -34 }, { -37, -36 }, - { 57, 58 }, { -94, -93 }, { -84, -44 }, { -80, -48 } -}; + {1, -64}, {2, 4}, {3, -65}, {-66, -62}, {-63, 5}, {6, 7}, + {-67, -61}, {8, 9}, {-68, -60}, {10, 11}, {-69, -59}, {12, 13}, + {-70, -58}, {14, 18}, {-57, 15}, {16, -72}, {-54, 17}, {-75, -53}, + {19, 37}, {-56, 20}, {21, -73}, {22, 29}, {23, -76}, {24, -78}, + {25, 28}, {26, 27}, {-85, -43}, {-83, -45}, {-81, -47}, {-52, 30}, + {-50, 31}, {32, -79}, {33, 34}, {-82, -46}, {35, 36}, {-90, -89}, + {-92, -91}, {38, -71}, {-55, 39}, {40, -74}, {41, 50}, {42, -77}, + {-49, 43}, {44, 47}, {45, 46}, {-86, -42}, {-88, -87}, {48, 49}, + {-39, -38}, {-41, -40}, {-51, 51}, {52, 59}, {53, 56}, {54, 55}, + {-35, -34}, {-37, -36}, {57, 58}, {-94, -93}, {-84, -44}, {-80, -48}}; /* constants used in psdec.cpp */ -const FIXP_DBL decayScaleFactTable[64] = { - - FL2FXCONST_DBL(1.000000), FL2FXCONST_DBL(1.000000), FL2FXCONST_DBL(1.000000), FL2FXCONST_DBL(1.000000), - FL2FXCONST_DBL(0.950000), FL2FXCONST_DBL(0.900000), FL2FXCONST_DBL(0.850000), FL2FXCONST_DBL(0.800000), - FL2FXCONST_DBL(0.750000), FL2FXCONST_DBL(0.700000), FL2FXCONST_DBL(0.650000), FL2FXCONST_DBL(0.600000), - FL2FXCONST_DBL(0.550000), FL2FXCONST_DBL(0.500000), FL2FXCONST_DBL(0.450000), FL2FXCONST_DBL(0.400000), - FL2FXCONST_DBL(0.350000), FL2FXCONST_DBL(0.300000), FL2FXCONST_DBL(0.250000), FL2FXCONST_DBL(0.200000), - FL2FXCONST_DBL(0.150000), FL2FXCONST_DBL(0.100000), FL2FXCONST_DBL(0.050000), FL2FXCONST_DBL(0.000000), - FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), - FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), - FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), - FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), - FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), - FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), - FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), - FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), - FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), - FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000) }; - /* the values of the following 3 tables are shiftet right by 1 ! */ const FIXP_DBL ScaleFactors[NO_IID_LEVELS] = { 0x5a5ded00, 0x59cd0400, 0x58c29680, 0x564c2e80, 0x52a3d480, 0x4c8be080, 0x46df3080, 0x40000000, 0x384ba5c0, 0x304c2980, - 0x24e9f640, 0x1b4a2940, 0x11b5c0a0, 0x0b4e2540, 0x0514ea90 -}; + 0x24e9f640, 0x1b4a2940, 0x11b5c0a0, 0x0b4e2540, 0x0514ea90}; const FIXP_DBL ScaleFactorsFine[NO_IID_LEVELS_FINE] = { - 0x5a825c00, 0x5a821c00, 0x5a815100, 0x5a7ed000, 0x5a76e600, - 0x5a5ded00, 0x5a39b880, 0x59f1fd00, 0x5964d680, 0x5852ca00, - 0x564c2e80, 0x54174480, 0x50ea7500, 0x4c8be080, 0x46df3080, - 0x40000000, 0x384ba5c0, 0x304c2980, 0x288dd240, 0x217a2900, - 0x1b4a2940, 0x13c5ece0, 0x0e2b0090, 0x0a178ef0, 0x072ab798, - 0x0514ea90, 0x02dc5944, 0x019bf87c, 0x00e7b173, 0x00824b8b, - 0x00494568 -}; + 0x5a825c00, 0x5a821c00, 0x5a815100, 0x5a7ed000, 0x5a76e600, 0x5a5ded00, + 0x5a39b880, 0x59f1fd00, 0x5964d680, 0x5852ca00, 0x564c2e80, 0x54174480, + 0x50ea7500, 0x4c8be080, 0x46df3080, 0x40000000, 0x384ba5c0, 0x304c2980, + 0x288dd240, 0x217a2900, 0x1b4a2940, 0x13c5ece0, 0x0e2b0090, 0x0a178ef0, + 0x072ab798, 0x0514ea90, 0x02dc5944, 0x019bf87c, 0x00e7b173, 0x00824b8b, + 0x00494568}; const FIXP_DBL Alphas[NO_ICC_LEVELS] = { 0x00000000, 0x0b6b5be0, 0x12485f80, 0x1da2fa40, - 0x2637ebc0, 0x3243f6c0, 0x466b7480, 0x6487ed80 -}; - -#if defined(ARCH_PREFER_MULT_32x16) -#define FIXP_PS FIXP_SGL -#define FXP_CAST(a) FX_DBL2FX_SGL((FIXP_DBL)a) -#define FL2FXCONST_PS FL2FXCONST_SGL -#else -#define FIXP_PS FIXP_DBL -#define FXP_CAST(x) ((FIXP_DBL)(x)) -#define FL2FXCONST_PS FL2FXCONST_DBL -#endif - -const FIXP_PS aAllpassLinkDecaySer[NO_SERIAL_ALLPASS_LINKS] = { -FXP_CAST(0x53625b00), FXP_CAST(0x4848af00), FXP_CAST(0x3ea94d00) }; - -const FIXP_PS aaFractDelayPhaseFactorReQmf[NO_QMF_CHANNELS] = { -FXP_CAST(0x68b92180), FXP_CAST(0xde396900), FXP_CAST(0x80650380), FXP_CAST(0xcb537e40), FXP_CAST(0x5beb8f00), FXP_CAST(0x72f29200), FXP_CAST(0xf1f43c50), FXP_CAST(0x83896280), -FXP_CAST(0xb9b99c00), FXP_CAST(0x4cda8f00), FXP_CAST(0x7a576e00), FXP_CAST(0x060799e0), FXP_CAST(0x89be5280), FXP_CAST(0xa9dab600), FXP_CAST(0x3be51b00), FXP_CAST(0x7eb91900), -FXP_CAST(0x19f4f540), FXP_CAST(0x92dcb380), FXP_CAST(0x9c1ad700), FXP_CAST(0x29761940), FXP_CAST(0x7ffbf500), FXP_CAST(0x2d3eb180), FXP_CAST(0x9eab0a00), FXP_CAST(0x90d0aa80), -FXP_CAST(0x1601bcc0), FXP_CAST(0x7e180e80), FXP_CAST(0x3f6b3940), FXP_CAST(0xacdeeb00), FXP_CAST(0x88435b00), FXP_CAST(0x0202a768), FXP_CAST(0x79194f80), FXP_CAST(0x5007fd00), -FXP_CAST(0xbd1ecf00), FXP_CAST(0x82a8d100), FXP_CAST(0xedf6e5e0), FXP_CAST(0x711f3500), FXP_CAST(0x5eac4480), FXP_CAST(0xcf0447c0), FXP_CAST(0x80245f80), FXP_CAST(0xda5cd4c0), -FXP_CAST(0x665c0800), FXP_CAST(0x6afbc500), FXP_CAST(0xe21e85e0), FXP_CAST(0x80c5e500), FXP_CAST(0xc7b003c0), FXP_CAST(0x59139f80), FXP_CAST(0x74a8e400), FXP_CAST(0xf5f51f40), -FXP_CAST(0x84896680), FXP_CAST(0xb6662b00), FXP_CAST(0x4999b600), FXP_CAST(0x7b76a300), FXP_CAST(0x0a0b0650), FXP_CAST(0x8b572b80), FXP_CAST(0xa6ec4580), FXP_CAST(0x384fda80), -FXP_CAST(0x7f3a1f00), FXP_CAST(0x1de19ec0), FXP_CAST(0x95045000), FXP_CAST(0x99a3e180), FXP_CAST(0x25a30740), FXP_CAST(0x7fdb9e80), FXP_CAST(0x30fbdb00), FXP_CAST(0xa153d500) }; - -const FIXP_PS aaFractDelayPhaseFactorImQmf[NO_QMF_CHANNELS] = { -FXP_CAST(0xb6663a80), FXP_CAST(0x84896200), FXP_CAST(0xf5f50c70), FXP_CAST(0x74a8dc80), FXP_CAST(0x5913ad00), FXP_CAST(0xc7b01480), FXP_CAST(0x80c5e300), FXP_CAST(0xe21e73a0), -FXP_CAST(0x6afbba80), FXP_CAST(0x665c1380), FXP_CAST(0xda5ce6c0), FXP_CAST(0x80246080), FXP_CAST(0xcf043640), FXP_CAST(0x5eac3800), FXP_CAST(0x711f3e00), FXP_CAST(0xedf6f8a0), -FXP_CAST(0x82a8d500), FXP_CAST(0xbd1ebe80), FXP_CAST(0x5007ee00), FXP_CAST(0x79195580), FXP_CAST(0x0202ba40), FXP_CAST(0x88436180), FXP_CAST(0xacdedc80), FXP_CAST(0x3f6b28c0), -FXP_CAST(0x7e181180), FXP_CAST(0x1601cf40), FXP_CAST(0x90d0b380), FXP_CAST(0x9eaafd80), FXP_CAST(0x2d3e9fc0), FXP_CAST(0x7ffbf580), FXP_CAST(0x29762b00), FXP_CAST(0x9c1ae280), -FXP_CAST(0x92dca980), FXP_CAST(0x19f4e2c0), FXP_CAST(0x7eb91680), FXP_CAST(0x3be52b80), FXP_CAST(0xa9dac400), FXP_CAST(0x89be4b80), FXP_CAST(0x06078710), FXP_CAST(0x7a576880), -FXP_CAST(0x4cda9e00), FXP_CAST(0xb9b9ac00), FXP_CAST(0x83895e00), FXP_CAST(0xf1f42990), FXP_CAST(0x72f28a00), FXP_CAST(0x5beb9c00), FXP_CAST(0xcb538f40), FXP_CAST(0x80650200), -FXP_CAST(0xde3956c0), FXP_CAST(0x68b91680), FXP_CAST(0x68b92c00), FXP_CAST(0xde397b40), FXP_CAST(0x80650500), FXP_CAST(0xcb536d00), FXP_CAST(0x5beb8180), FXP_CAST(0x72f29a80), -FXP_CAST(0xf1f44f10), FXP_CAST(0x83896700), FXP_CAST(0xb9b98c80), FXP_CAST(0x4cda8000), FXP_CAST(0x7a577380), FXP_CAST(0x0607acb8), FXP_CAST(0x89be5a00), FXP_CAST(0xa9daa800) }; - -const FIXP_PS aaFractDelayPhaseFactorReSubQmf20[NO_SUB_QMF_CHANNELS] = { -FXP_CAST(0x7e807380), FXP_CAST(0x72b9bb00), FXP_CAST(0x5c44ee80), FXP_CAST(0x3d3938c0), FXP_CAST(0x80000000), FXP_CAST(0x80000000), -FXP_CAST(0x72b9bb00), FXP_CAST(0x7e807380), FXP_CAST(0xba914700), FXP_CAST(0x050677b0), FXP_CAST(0x895cc380), FXP_CAST(0x834e4900) }; - -const FIXP_PS aaFractDelayPhaseFactorImSubQmf20[NO_SUB_QMF_CHANNELS] = { -FXP_CAST(0xec791720), FXP_CAST(0xc73ca080), FXP_CAST(0xa748ea00), FXP_CAST(0x8f976980), FXP_CAST(0x00000000), FXP_CAST(0x00000000), -FXP_CAST(0x38c35f80), FXP_CAST(0x1386e8e0), FXP_CAST(0x9477d000), FXP_CAST(0x80194380), FXP_CAST(0xcff26140), FXP_CAST(0x1ce70d40) }; - -const FIXP_PS aaFractDelayPhaseFactorSerReQmf[NO_QMF_CHANNELS][NO_SERIAL_ALLPASS_LINKS] = { -{FXP_CAST(0x63e52480), FXP_CAST(0x30fbc540), FXP_CAST(0x6d73af00)}, {FXP_CAST(0xc7b01280), FXP_CAST(0x89be5100), FXP_CAST(0xf7c31cb0)}, {FXP_CAST(0x83896200), FXP_CAST(0x7641af00), FXP_CAST(0x8aee2700)}, -{FXP_CAST(0x0202b330), FXP_CAST(0xcf043ac0), FXP_CAST(0x9bfab500)}, {FXP_CAST(0x7d572c80), FXP_CAST(0xcf043ac0), FXP_CAST(0x1893b960)}, {FXP_CAST(0x34ac7fc0), FXP_CAST(0x7641af00), FXP_CAST(0x7abf7980)}, -{FXP_CAST(0x99a3ee00), FXP_CAST(0x89be5100), FXP_CAST(0x58eead80)}, {FXP_CAST(0x9eab0580), FXP_CAST(0x30fbc540), FXP_CAST(0xd77dae40)}, {FXP_CAST(0x3be52140), FXP_CAST(0x30fbc540), FXP_CAST(0x819b8500)}, -{FXP_CAST(0x7b769d80), FXP_CAST(0x89be5100), FXP_CAST(0xb3a12280)}, {FXP_CAST(0xf9f86878), FXP_CAST(0x7641af00), FXP_CAST(0x37c519c0)}, {FXP_CAST(0x81e7ef80), FXP_CAST(0xcf043ac0), FXP_CAST(0x7ff16880)}, -{FXP_CAST(0xcf043cc0), FXP_CAST(0xcf043ac0), FXP_CAST(0x3e8b2340)}, {FXP_CAST(0x68b92280), FXP_CAST(0x7641af00), FXP_CAST(0xb9e4a900)}, {FXP_CAST(0x5eac3980), FXP_CAST(0x89be5100), FXP_CAST(0x80a05200)}, -{FXP_CAST(0xc094cd00), FXP_CAST(0x30fbc540), FXP_CAST(0xd051dc80)}, {FXP_CAST(0x85a89400), FXP_CAST(0x30fbc540), FXP_CAST(0x53483b00)}, {FXP_CAST(0x0a0af5e0), FXP_CAST(0x89be5100), FXP_CAST(0x7cb1b680)}, -{FXP_CAST(0x7eb91900), FXP_CAST(0x7641af00), FXP_CAST(0x2006e8c0)}, {FXP_CAST(0x2d3ea680), FXP_CAST(0xcf043ac0), FXP_CAST(0xa0ec1c00)}, {FXP_CAST(0x95044180), FXP_CAST(0xcf043ac0), FXP_CAST(0x880d2180)}, -{FXP_CAST(0xa4147300), FXP_CAST(0x7641af00), FXP_CAST(0xf0282870)}, {FXP_CAST(0x42e13f80), FXP_CAST(0x89be5100), FXP_CAST(0x694c4a00)}, {FXP_CAST(0x79195200), FXP_CAST(0x30fbc540), FXP_CAST(0x71374780)}, -{FXP_CAST(0xf1f43550), FXP_CAST(0x30fbc540), FXP_CAST(0xff6593ea)}, {FXP_CAST(0x80c5e280), FXP_CAST(0x89be5100), FXP_CAST(0x8e39ec00)}, {FXP_CAST(0xd689e480), FXP_CAST(0x7641af00), FXP_CAST(0x97648100)}, -{FXP_CAST(0x6d235300), FXP_CAST(0xcf043ac0), FXP_CAST(0x110a20c0)}, {FXP_CAST(0x5913a800), FXP_CAST(0xcf043ac0), FXP_CAST(0x785d4f80)}, {FXP_CAST(0xb9b99a00), FXP_CAST(0x7641af00), FXP_CAST(0x5e440880)}, -{FXP_CAST(0x88436100), FXP_CAST(0x89be5100), FXP_CAST(0xdece7000)}, {FXP_CAST(0x12091320), FXP_CAST(0x30fbc540), FXP_CAST(0x8309f800)}, {FXP_CAST(0x7f9afd00), FXP_CAST(0x30fbc540), FXP_CAST(0xada33f00)}, -{FXP_CAST(0x25a31700), FXP_CAST(0x89be5100), FXP_CAST(0x30cc3600)}, {FXP_CAST(0x90d0ab80), FXP_CAST(0x7641af00), FXP_CAST(0x7f7cbe80)}, {FXP_CAST(0xa9dabf00), FXP_CAST(0xcf043ac0), FXP_CAST(0x45182580)}, -{FXP_CAST(0x4999cb80), FXP_CAST(0xcf043ac0), FXP_CAST(0xc0681c80)}, {FXP_CAST(0x7641ac80), FXP_CAST(0x7641af00), FXP_CAST(0x80194380)}, {FXP_CAST(0xe9fe3300), FXP_CAST(0x89be5100), FXP_CAST(0xc95184c0)}, -{FXP_CAST(0x80246000), FXP_CAST(0x30fbc540), FXP_CAST(0x4d55d800)}, {FXP_CAST(0xde396fc0), FXP_CAST(0x30fbc540), FXP_CAST(0x7e324000)}, {FXP_CAST(0x711f3f00), FXP_CAST(0x89be5100), FXP_CAST(0x275ce480)}, -{FXP_CAST(0x53211700), FXP_CAST(0x7641af00), FXP_CAST(0xa6343580)}, {FXP_CAST(0xb3256780), FXP_CAST(0xcf043ac0), FXP_CAST(0x85997b80)}, {FXP_CAST(0x8b572680), FXP_CAST(0xcf043ac0), FXP_CAST(0xe89ba660)}, -{FXP_CAST(0x19f4f780), FXP_CAST(0x7641af00), FXP_CAST(0x64c4e100)}, {FXP_CAST(0x7ffbf580), FXP_CAST(0x89be5100), FXP_CAST(0x7493a380)}, {FXP_CAST(0x1de18100), FXP_CAST(0x30fbc540), FXP_CAST(0x070897f0)}, -{FXP_CAST(0x8d0d6a80), FXP_CAST(0x30fbc540), FXP_CAST(0x91ed6f00)}, {FXP_CAST(0xaff81380), FXP_CAST(0x89be5100), FXP_CAST(0x932db000)}, {FXP_CAST(0x5007fb00), FXP_CAST(0x7641af00), FXP_CAST(0x0970feb0)}, -{FXP_CAST(0x72f28d00), FXP_CAST(0xcf043ac0), FXP_CAST(0x758d6500)}, {FXP_CAST(0xe21e6cc0), FXP_CAST(0xcf043ac0), FXP_CAST(0x63436f80)}, {FXP_CAST(0x80040b00), FXP_CAST(0x7641af00), FXP_CAST(0xe63d7600)}, -{FXP_CAST(0xe60b1ae0), FXP_CAST(0x89be5100), FXP_CAST(0x84ea5c80)}, {FXP_CAST(0x74a8e100), FXP_CAST(0x30fbc540), FXP_CAST(0xa7f07500)}, {FXP_CAST(0x4cda8980), FXP_CAST(0x30fbc540), FXP_CAST(0x29a6d340)}, -{FXP_CAST(0xacdeda80), FXP_CAST(0x89be5100), FXP_CAST(0x7e93d600)}, {FXP_CAST(0x8ee0c980), FXP_CAST(0x7641af00), FXP_CAST(0x4b662680)}, {FXP_CAST(0x21c6a280), FXP_CAST(0xcf043ac0), FXP_CAST(0xc7258c80)}, -{FXP_CAST(0x7fdb9f00), FXP_CAST(0xcf043ac0), FXP_CAST(0x8006d500)}, {FXP_CAST(0x1601ba60), FXP_CAST(0x7641af00), FXP_CAST(0xc2830940)}, {FXP_CAST(0x89be4c80), FXP_CAST(0x89be5100), FXP_CAST(0x471cf100)}, -{FXP_CAST(0xb6664400), FXP_CAST(0x30fbc540), FXP_CAST(0x7f3fb800)}}; - -const FIXP_PS aaFractDelayPhaseFactorSerImQmf[NO_QMF_CHANNELS][NO_SERIAL_ALLPASS_LINKS] = { -{FXP_CAST(0xaff80c80), FXP_CAST(0x89be5100), FXP_CAST(0xbda29e00)}, {FXP_CAST(0x8d0d6f00), FXP_CAST(0x30fbc540), FXP_CAST(0x8043ee80)}, {FXP_CAST(0x1de18a20), FXP_CAST(0x30fbc540), FXP_CAST(0xcc3e7840)}, -{FXP_CAST(0x7ffbf500), FXP_CAST(0x89be5100), FXP_CAST(0x4fdfc180)}, {FXP_CAST(0x19f4ee40), FXP_CAST(0x7641af00), FXP_CAST(0x7d9e4c00)}, {FXP_CAST(0x8b572300), FXP_CAST(0xcf043ac0), FXP_CAST(0x244a2940)}, -{FXP_CAST(0xb3256f00), FXP_CAST(0xcf043ac0), FXP_CAST(0xa3f0a500)}, {FXP_CAST(0x53211e00), FXP_CAST(0x7641af00), FXP_CAST(0x86944500)}, {FXP_CAST(0x711f3a80), FXP_CAST(0x89be5100), FXP_CAST(0xebc72040)}, -{FXP_CAST(0xde3966c0), FXP_CAST(0x30fbc540), FXP_CAST(0x66b87e00)}, {FXP_CAST(0x80246080), FXP_CAST(0x30fbc540), FXP_CAST(0x73362c00)}, {FXP_CAST(0xe9fe3c40), FXP_CAST(0x89be5100), FXP_CAST(0x03d1d110)}, -{FXP_CAST(0x7641b000), FXP_CAST(0x7641af00), FXP_CAST(0x90520c80)}, {FXP_CAST(0x4999c380), FXP_CAST(0xcf043ac0), FXP_CAST(0x94e80a80)}, {FXP_CAST(0xa9dab800), FXP_CAST(0xcf043ac0), FXP_CAST(0x0ca570e0)}, -{FXP_CAST(0x90d0b000), FXP_CAST(0x7641af00), FXP_CAST(0x76c9bc80)}, {FXP_CAST(0x25a32000), FXP_CAST(0x89be5100), FXP_CAST(0x61338500)}, {FXP_CAST(0x7f9afc80), FXP_CAST(0x30fbc540), FXP_CAST(0xe318f060)}, -{FXP_CAST(0x120909c0), FXP_CAST(0x30fbc540), FXP_CAST(0x84124e00)}, {FXP_CAST(0x88435d80), FXP_CAST(0x89be5100), FXP_CAST(0xaa4d2f80)}, {FXP_CAST(0xb9b9a200), FXP_CAST(0x7641af00), FXP_CAST(0x2cae1800)}, -{FXP_CAST(0x5913ae80), FXP_CAST(0xcf043ac0), FXP_CAST(0x7f040680)}, {FXP_CAST(0x6d234e00), FXP_CAST(0xcf043ac0), FXP_CAST(0x48c6a100)}, {FXP_CAST(0xd689db80), FXP_CAST(0x7641af00), FXP_CAST(0xc44860c0)}, -{FXP_CAST(0x80c5e380), FXP_CAST(0x89be5100), FXP_CAST(0x80005d00)}, {FXP_CAST(0xf1f43eb0), FXP_CAST(0x30fbc540), FXP_CAST(0xc55a3a00)}, {FXP_CAST(0x79195500), FXP_CAST(0x30fbc540), FXP_CAST(0x49c3de00)}, -{FXP_CAST(0x42e13700), FXP_CAST(0x89be5100), FXP_CAST(0x7edc5b00)}, {FXP_CAST(0xa4146c80), FXP_CAST(0x7641af00), FXP_CAST(0x2b8c2c00)}, {FXP_CAST(0x95044680), FXP_CAST(0xcf043ac0), FXP_CAST(0xa968c100)}, -{FXP_CAST(0x2d3eaf40), FXP_CAST(0xcf043ac0), FXP_CAST(0x8460fd80)}, {FXP_CAST(0x7eb91780), FXP_CAST(0x7641af00), FXP_CAST(0xe44621e0)}, {FXP_CAST(0x0a0aec80), FXP_CAST(0x89be5100), FXP_CAST(0x61fb5c00)}, -{FXP_CAST(0x85a89100), FXP_CAST(0x30fbc540), FXP_CAST(0x76555780)}, {FXP_CAST(0xc094d500), FXP_CAST(0x30fbc540), FXP_CAST(0x0b71f790)}, {FXP_CAST(0x5eac4000), FXP_CAST(0x89be5100), FXP_CAST(0x94401a80)}, -{FXP_CAST(0x68b91d80), FXP_CAST(0x7641af00), FXP_CAST(0x90ea3980)}, {FXP_CAST(0xcf043440), FXP_CAST(0xcf043ac0), FXP_CAST(0x05067a08)}, {FXP_CAST(0x81e7f180), FXP_CAST(0xcf043ac0), FXP_CAST(0x73bb6d00)}, -{FXP_CAST(0xf9f871e0), FXP_CAST(0x7641af00), FXP_CAST(0x65ff0e00)}, {FXP_CAST(0x7b76a000), FXP_CAST(0x89be5100), FXP_CAST(0xea9664c0)}, {FXP_CAST(0x3be518c0), FXP_CAST(0x30fbc540), FXP_CAST(0x8633e880)}, -{FXP_CAST(0x9eaaff00), FXP_CAST(0x30fbc540), FXP_CAST(0xa4c84500)}, {FXP_CAST(0x99a3f400), FXP_CAST(0x89be5100), FXP_CAST(0x2571eac0)}, {FXP_CAST(0x34ac8840), FXP_CAST(0x7641af00), FXP_CAST(0x7dd82b00)}, -{FXP_CAST(0x7d572a80), FXP_CAST(0xcf043ac0), FXP_CAST(0x4eed8400)}, {FXP_CAST(0x0202a9c4), FXP_CAST(0xcf043ac0), FXP_CAST(0xcb249700)}, {FXP_CAST(0x83896000), FXP_CAST(0x7641af00), FXP_CAST(0x80318200)}, -{FXP_CAST(0xc7b01b00), FXP_CAST(0x89be5100), FXP_CAST(0xbeab7580)}, {FXP_CAST(0x63e52a80), FXP_CAST(0x30fbc540), FXP_CAST(0x4364b700)}, {FXP_CAST(0x63e51f00), FXP_CAST(0x30fbc540), FXP_CAST(0x7fa6bd00)}, -{FXP_CAST(0xc7b00a00), FXP_CAST(0x89be5100), FXP_CAST(0x32a67940)}, {FXP_CAST(0x83896400), FXP_CAST(0x7641af00), FXP_CAST(0xaf2fd200)}, {FXP_CAST(0x0202bc9c), FXP_CAST(0xcf043ac0), FXP_CAST(0x829e6e80)}, -{FXP_CAST(0x7d572e80), FXP_CAST(0xcf043ac0), FXP_CAST(0xdcde6b80)}, {FXP_CAST(0x34ac7700), FXP_CAST(0x7641af00), FXP_CAST(0x5ce4e280)}, {FXP_CAST(0x99a3e880), FXP_CAST(0x89be5100), FXP_CAST(0x79089c00)}, -{FXP_CAST(0x9eab0b80), FXP_CAST(0x30fbc540), FXP_CAST(0x1307ae80)}, {FXP_CAST(0x3be52980), FXP_CAST(0x30fbc540), FXP_CAST(0x98906880)}, {FXP_CAST(0x7b769b00), FXP_CAST(0x89be5100), FXP_CAST(0x8d51b300)}, -{FXP_CAST(0xf9f85f10), FXP_CAST(0x7641af00), FXP_CAST(0xfd62ee24)}, {FXP_CAST(0x81e7ee00), FXP_CAST(0xcf043ac0), FXP_CAST(0x70439680)}, {FXP_CAST(0xcf044580), FXP_CAST(0xcf043ac0), FXP_CAST(0x6a6d9600)}, -{FXP_CAST(0x68b92800), FXP_CAST(0x7641af00), FXP_CAST(0xf2275f80)}}; - -const FIXP_PS aaFractDelayPhaseFactorSerReSubQmf20[NO_SUB_QMF_CHANNELS][NO_SERIAL_ALLPASS_LINKS] = { -{FXP_CAST(0x7e2df000), FXP_CAST(0x7a7d0580), FXP_CAST(0x7ed03e00)}, {FXP_CAST(0x6fec9a80), FXP_CAST(0x5133cc80), FXP_CAST(0x7573df00)}, {FXP_CAST(0x55063900), FXP_CAST(0x0c8bd360), FXP_CAST(0x636c0400)}, -{FXP_CAST(0x3084ca00), FXP_CAST(0xc3a94580), FXP_CAST(0x4a0d6700)}, {FXP_CAST(0x80000000), FXP_CAST(0x80000000), FXP_CAST(0x80000000)}, {FXP_CAST(0x80000000), FXP_CAST(0x80000000), FXP_CAST(0x80000000)}, -{FXP_CAST(0x6fec9a80), FXP_CAST(0x5133cc80), FXP_CAST(0x7573df00)}, {FXP_CAST(0x7e2df000), FXP_CAST(0x7a7d0580), FXP_CAST(0x7ed03e00)}, {FXP_CAST(0xa4c84280), FXP_CAST(0xb8e31300), FXP_CAST(0xd5af0140)}, -{FXP_CAST(0xf0f488a0), FXP_CAST(0x8275a100), FXP_CAST(0x1a72e360)}, {FXP_CAST(0x80aaa680), FXP_CAST(0x471ced00), FXP_CAST(0x9d2ead80)}, {FXP_CAST(0x9477d100), FXP_CAST(0x7d8a5f00), FXP_CAST(0x8151df80)}}; - -const FIXP_PS aaFractDelayPhaseFactorSerImSubQmf20[NO_SUB_QMF_CHANNELS][NO_SERIAL_ALLPASS_LINKS] = { -{FXP_CAST(0xea7d08a0), FXP_CAST(0xdad7f3c0), FXP_CAST(0xee9c9f60)}, {FXP_CAST(0xc1e54140), FXP_CAST(0x9d0dfe80), FXP_CAST(0xcd1e7300)}, {FXP_CAST(0xa051a580), FXP_CAST(0x809dc980), FXP_CAST(0xaf61c400)}, -{FXP_CAST(0x898d4e00), FXP_CAST(0x8f1d3400), FXP_CAST(0x97988280)}, {FXP_CAST(0x00000000), FXP_CAST(0x00000000), FXP_CAST(0x00000000)}, {FXP_CAST(0x00000000), FXP_CAST(0x00000000), FXP_CAST(0x00000000)}, -{FXP_CAST(0x3e1abec0), FXP_CAST(0x62f20180), FXP_CAST(0x32e18d00)}, {FXP_CAST(0x1582f760), FXP_CAST(0x25280c40), FXP_CAST(0x116360a0)}, {FXP_CAST(0xa6343800), FXP_CAST(0x6a6d9880), FXP_CAST(0x87327a00)}, -{FXP_CAST(0x80e32200), FXP_CAST(0xe70747c0), FXP_CAST(0x82c32b00)}, {FXP_CAST(0xf2f42420), FXP_CAST(0x6a6d9880), FXP_CAST(0xaea47080)}, {FXP_CAST(0x456eba00), FXP_CAST(0xe70747c0), FXP_CAST(0xedaa8640)}}; - -const FIXP_PS p8_13_20[13] = -{ - FL2FXCONST_PS(0.00746082949812f), FL2FXCONST_PS(0.02270420949825f), FL2FXCONST_PS(0.04546865930473f), FL2FXCONST_PS(0.07266113929591f), - FL2FXCONST_PS(0.09885108575264f), FL2FXCONST_PS(0.11793710567217f), FL2FXCONST_PS(0.125f ), FL2FXCONST_PS(0.11793710567217f), - FL2FXCONST_PS(0.09885108575264f), FL2FXCONST_PS(0.07266113929591f), FL2FXCONST_PS(0.04546865930473f), FL2FXCONST_PS(0.02270420949825f), - FL2FXCONST_PS(0.00746082949812f) -}; - -const FIXP_PS p2_13_20[13] = -{ - FL2FXCONST_PS(0.0f), FL2FXCONST_PS( 0.01899487526049f), FL2FXCONST_PS(0.0f), FL2FXCONST_PS(-0.07293139167538f), - FL2FXCONST_PS(0.0f), FL2FXCONST_PS( 0.30596630545168f), FL2FXCONST_PS(0.5f), FL2FXCONST_PS( 0.30596630545168f), - FL2FXCONST_PS(0.0f), FL2FXCONST_PS(-0.07293139167538f), FL2FXCONST_PS(0.0f), FL2FXCONST_PS( 0.01899487526049f), - FL2FXCONST_PS(0.0f) -}; - - - -const UCHAR aAllpassLinkDelaySer[] = { 3, 4, 5}; - -const UCHAR delayIndexQmf[NO_QMF_CHANNELS] = { - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 -}; - -const UCHAR groupBorders20[NO_IID_GROUPS + 1] = -{ - 6, 7, 0, 1, 2, 3, /* 6 subqmf subbands - 0th qmf subband */ - 9, 8, /* 2 subqmf subbands - 1st qmf subband */ - 10, 11, /* 2 subqmf subbands - 2nd qmf subband */ - 3, 4, 5, 6, 7, 8, - 9, 11, 14, 18, 23, 35, 64 -}; - -const UCHAR groupBorders34[NO_IID_GROUPS_HI_RES + 1] = -{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, /* 12 subqmf subbands - 0th qmf subband */ - 12, 13, 14, 15, 16, 17, 18, 19, /* 8 subqmf subbands - 1st qmf subband */ - 20, 21, 22, 23, /* 4 subqmf subbands - 2nd qmf subband */ - 24, 25, 26, 27, /* 4 subqmf subbands - 3nd qmf subband */ - 28, 29, 30, 31, /* 4 subqmf subbands - 4nd qmf subband */ - 32-27, 33-27, 34-27, 35-27, 36-27, 37-27, 38-27, - 40-27, 42-27, 44-27, 46-27, 48-27, 51-27, 54-27, - 57-27, 60-27, 64-27, 68-27, 91-27 -}; - -const UCHAR bins2groupMap20[NO_IID_GROUPS] = -{ - 1, 0, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 -}; + 0x2637ebc0, 0x3243f6c0, 0x466b7480, 0x6487ed80}; -const UCHAR quantizedIIDs[NO_IID_STEPS] = -{ - 2, 4, 7, 10, 14, 18, 25 -}; -const UCHAR quantizedIIDsFine[NO_IID_STEPS_FINE] = -{ - 2, 4, 6, 8, 10, 13, 16, 19, 22, 25, 30, 35, 40, 45, 50 -}; - -const UCHAR FDK_sbrDecoder_aNoIidBins[3] = {NO_LOW_RES_IID_BINS, - NO_MID_RES_IID_BINS, - NO_HI_RES_IID_BINS}; - -const UCHAR FDK_sbrDecoder_aNoIccBins[3] = {NO_LOW_RES_ICC_BINS, - NO_MID_RES_ICC_BINS, - NO_HI_RES_ICC_BINS}; +const UCHAR bins2groupMap20[NO_IID_GROUPS] = { + 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; +const UCHAR FDK_sbrDecoder_aNoIidBins[3] = { + NO_LOW_RES_IID_BINS, NO_MID_RES_IID_BINS, NO_HI_RES_IID_BINS}; +const UCHAR FDK_sbrDecoder_aNoIccBins[3] = { + NO_LOW_RES_ICC_BINS, NO_MID_RES_ICC_BINS, NO_HI_RES_ICC_BINS}; /************************************************************************/ /*! @@ -1385,39 +1673,33 @@ const UCHAR FDK_sbrDecoder_aNoIccBins[3] = {NO_LOW_RES_ICC_BINS, invTable[i] = FL2FX_SGL(d); } */ -const FIXP_SGL FDK_sbrDecoder_invTable[INV_TABLE_SIZE] = -{ - 0x7f80, 0x7f01, 0x7e83, 0x7e07, 0x7d8b, 0x7d11, 0x7c97, 0x7c1e, - 0x7ba6, 0x7b2f, 0x7ab9, 0x7a44, 0x79cf, 0x795c, 0x78e9, 0x7878, - 0x7807, 0x7796, 0x7727, 0x76b9, 0x764b, 0x75de, 0x7572, 0x7506, - 0x749c, 0x7432, 0x73c9, 0x7360, 0x72f9, 0x7292, 0x722c, 0x71c6, - 0x7161, 0x70fd, 0x709a, 0x7037, 0x6fd5, 0x6f74, 0x6f13, 0x6eb3, - 0x6e54, 0x6df5, 0x6d97, 0x6d39, 0x6cdc, 0x6c80, 0x6c24, 0x6bc9, - 0x6b6f, 0x6b15, 0x6abc, 0x6a63, 0x6a0b, 0x69b3, 0x695c, 0x6906, - 0x68b0, 0x685a, 0x6806, 0x67b1, 0x675e, 0x670a, 0x66b8, 0x6666, - 0x6614, 0x65c3, 0x6572, 0x6522, 0x64d2, 0x6483, 0x6434, 0x63e6, - 0x6399, 0x634b, 0x62fe, 0x62b2, 0x6266, 0x621b, 0x61d0, 0x6185, - 0x613b, 0x60f2, 0x60a8, 0x6060, 0x6017, 0x5fcf, 0x5f88, 0x5f41, - 0x5efa, 0x5eb4, 0x5e6e, 0x5e28, 0x5de3, 0x5d9f, 0x5d5a, 0x5d17, - 0x5cd3, 0x5c90, 0x5c4d, 0x5c0b, 0x5bc9, 0x5b87, 0x5b46, 0x5b05, - 0x5ac4, 0x5a84, 0x5a44, 0x5a05, 0x59c6, 0x5987, 0x5949, 0x590a, - 0x58cd, 0x588f, 0x5852, 0x5815, 0x57d9, 0x579d, 0x5761, 0x5725, - 0x56ea, 0x56af, 0x5675, 0x563b, 0x5601, 0x55c7, 0x558e, 0x5555, - 0x551c, 0x54e3, 0x54ab, 0x5473, 0x543c, 0x5405, 0x53ce, 0x5397, - 0x5360, 0x532a, 0x52f4, 0x52bf, 0x5289, 0x5254, 0x521f, 0x51eb, - 0x51b7, 0x5183, 0x514f, 0x511b, 0x50e8, 0x50b5, 0x5082, 0x5050, - 0x501d, 0x4feb, 0x4fba, 0x4f88, 0x4f57, 0x4f26, 0x4ef5, 0x4ec4, - 0x4e94, 0x4e64, 0x4e34, 0x4e04, 0x4dd5, 0x4da6, 0x4d77, 0x4d48, - 0x4d19, 0x4ceb, 0x4cbd, 0x4c8f, 0x4c61, 0x4c34, 0x4c07, 0x4bd9, - 0x4bad, 0x4b80, 0x4b54, 0x4b27, 0x4afb, 0x4acf, 0x4aa4, 0x4a78, - 0x4a4d, 0x4a22, 0x49f7, 0x49cd, 0x49a2, 0x4978, 0x494e, 0x4924, - 0x48fa, 0x48d1, 0x48a7, 0x487e, 0x4855, 0x482d, 0x4804, 0x47dc, - 0x47b3, 0x478b, 0x4763, 0x473c, 0x4714, 0x46ed, 0x46c5, 0x469e, - 0x4677, 0x4651, 0x462a, 0x4604, 0x45de, 0x45b8, 0x4592, 0x456c, - 0x4546, 0x4521, 0x44fc, 0x44d7, 0x44b2, 0x448d, 0x4468, 0x4444, - 0x441f, 0x43fb, 0x43d7, 0x43b3, 0x4390, 0x436c, 0x4349, 0x4325, - 0x4302, 0x42df, 0x42bc, 0x4299, 0x4277, 0x4254, 0x4232, 0x4210, - 0x41ee, 0x41cc, 0x41aa, 0x4189, 0x4167, 0x4146, 0x4125, 0x4104, - 0x40e3, 0x40c2, 0x40a1, 0x4081, 0x4060, 0x4040, 0x4020, 0x4000 -}; - +const FIXP_SGL FDK_sbrDecoder_invTable[INV_TABLE_SIZE] = { + 0x7f80, 0x7f01, 0x7e83, 0x7e07, 0x7d8b, 0x7d11, 0x7c97, 0x7c1e, 0x7ba6, + 0x7b2f, 0x7ab9, 0x7a44, 0x79cf, 0x795c, 0x78e9, 0x7878, 0x7807, 0x7796, + 0x7727, 0x76b9, 0x764b, 0x75de, 0x7572, 0x7506, 0x749c, 0x7432, 0x73c9, + 0x7360, 0x72f9, 0x7292, 0x722c, 0x71c6, 0x7161, 0x70fd, 0x709a, 0x7037, + 0x6fd5, 0x6f74, 0x6f13, 0x6eb3, 0x6e54, 0x6df5, 0x6d97, 0x6d39, 0x6cdc, + 0x6c80, 0x6c24, 0x6bc9, 0x6b6f, 0x6b15, 0x6abc, 0x6a63, 0x6a0b, 0x69b3, + 0x695c, 0x6906, 0x68b0, 0x685a, 0x6806, 0x67b1, 0x675e, 0x670a, 0x66b8, + 0x6666, 0x6614, 0x65c3, 0x6572, 0x6522, 0x64d2, 0x6483, 0x6434, 0x63e6, + 0x6399, 0x634b, 0x62fe, 0x62b2, 0x6266, 0x621b, 0x61d0, 0x6185, 0x613b, + 0x60f2, 0x60a8, 0x6060, 0x6017, 0x5fcf, 0x5f88, 0x5f41, 0x5efa, 0x5eb4, + 0x5e6e, 0x5e28, 0x5de3, 0x5d9f, 0x5d5a, 0x5d17, 0x5cd3, 0x5c90, 0x5c4d, + 0x5c0b, 0x5bc9, 0x5b87, 0x5b46, 0x5b05, 0x5ac4, 0x5a84, 0x5a44, 0x5a05, + 0x59c6, 0x5987, 0x5949, 0x590a, 0x58cd, 0x588f, 0x5852, 0x5815, 0x57d9, + 0x579d, 0x5761, 0x5725, 0x56ea, 0x56af, 0x5675, 0x563b, 0x5601, 0x55c7, + 0x558e, 0x5555, 0x551c, 0x54e3, 0x54ab, 0x5473, 0x543c, 0x5405, 0x53ce, + 0x5397, 0x5360, 0x532a, 0x52f4, 0x52bf, 0x5289, 0x5254, 0x521f, 0x51eb, + 0x51b7, 0x5183, 0x514f, 0x511b, 0x50e8, 0x50b5, 0x5082, 0x5050, 0x501d, + 0x4feb, 0x4fba, 0x4f88, 0x4f57, 0x4f26, 0x4ef5, 0x4ec4, 0x4e94, 0x4e64, + 0x4e34, 0x4e04, 0x4dd5, 0x4da6, 0x4d77, 0x4d48, 0x4d19, 0x4ceb, 0x4cbd, + 0x4c8f, 0x4c61, 0x4c34, 0x4c07, 0x4bd9, 0x4bad, 0x4b80, 0x4b54, 0x4b27, + 0x4afb, 0x4acf, 0x4aa4, 0x4a78, 0x4a4d, 0x4a22, 0x49f7, 0x49cd, 0x49a2, + 0x4978, 0x494e, 0x4924, 0x48fa, 0x48d1, 0x48a7, 0x487e, 0x4855, 0x482d, + 0x4804, 0x47dc, 0x47b3, 0x478b, 0x4763, 0x473c, 0x4714, 0x46ed, 0x46c5, + 0x469e, 0x4677, 0x4651, 0x462a, 0x4604, 0x45de, 0x45b8, 0x4592, 0x456c, + 0x4546, 0x4521, 0x44fc, 0x44d7, 0x44b2, 0x448d, 0x4468, 0x4444, 0x441f, + 0x43fb, 0x43d7, 0x43b3, 0x4390, 0x436c, 0x4349, 0x4325, 0x4302, 0x42df, + 0x42bc, 0x4299, 0x4277, 0x4254, 0x4232, 0x4210, 0x41ee, 0x41cc, 0x41aa, + 0x4189, 0x4167, 0x4146, 0x4125, 0x4104, 0x40e3, 0x40c2, 0x40a1, 0x4081, + 0x4060, 0x4040, 0x4020, 0x4000}; diff --git a/libSBRdec/src/sbr_rom.h b/libSBRdec/src/sbr_rom.h index 1f800bc..039743c 100644 --- a/libSBRdec/src/sbr_rom.h +++ b/libSBRdec/src/sbr_rom.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,68 +90,80 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file \brief Declaration of constant tables - */ -#ifndef __rom_H -#define __rom_H +#ifndef SBR_ROM_H +#define SBR_ROM_H #include "sbrdecoder.h" #include "env_extr.h" #include "qmf.h" -#define INV_INT_TABLE_SIZE 49 -#define SBR_NF_NO_RANDOM_VAL 512 /*!< Size of random number array for noise floor */ +#define INV_INT_TABLE_SIZE 49 +#define SBR_NF_NO_RANDOM_VAL \ + 512 /*!< Size of random number array for noise floor */ /* Frequency scales */ -extern const UCHAR FDK_sbrDecoder_sbr_start_freq_16[16]; -extern const UCHAR FDK_sbrDecoder_sbr_start_freq_22[16]; -extern const UCHAR FDK_sbrDecoder_sbr_start_freq_24[16]; -extern const UCHAR FDK_sbrDecoder_sbr_start_freq_32[16]; -extern const UCHAR FDK_sbrDecoder_sbr_start_freq_40[16]; -extern const UCHAR FDK_sbrDecoder_sbr_start_freq_44[16]; -extern const UCHAR FDK_sbrDecoder_sbr_start_freq_48[16]; -extern const UCHAR FDK_sbrDecoder_sbr_start_freq_64[16]; -extern const UCHAR FDK_sbrDecoder_sbr_start_freq_88[16]; + +/* if defined(SBRDEC_RATIO_16_64_ENABLE) ((4) = 4) else ((4) = 2) */ +extern const UCHAR FDK_sbrDecoder_sbr_start_freq_16[(4) / 2][16]; +extern const UCHAR FDK_sbrDecoder_sbr_start_freq_22[(4) / 2][16]; +extern const UCHAR FDK_sbrDecoder_sbr_start_freq_24[(4) / 2][16]; +extern const UCHAR FDK_sbrDecoder_sbr_start_freq_32[(4) / 2][16]; +extern const UCHAR FDK_sbrDecoder_sbr_start_freq_40[(4) / 2][16]; +extern const UCHAR FDK_sbrDecoder_sbr_start_freq_44[(4) / 2][16]; +extern const UCHAR FDK_sbrDecoder_sbr_start_freq_48[(4) / 2][16]; +extern const UCHAR FDK_sbrDecoder_sbr_start_freq_64[(4) / 2][16]; +extern const UCHAR FDK_sbrDecoder_sbr_start_freq_88[(4) / 2][16]; +extern const UCHAR FDK_sbrDecoder_sbr_start_freq_192[16]; +extern const UCHAR FDK_sbrDecoder_sbr_start_freq_176[16]; +extern const UCHAR FDK_sbrDecoder_sbr_start_freq_128[16]; /* Low-Power-Profile Transposer */ -#define NUM_WHFACTOR_TABLE_ENTRIES 9 -extern const USHORT FDK_sbrDecoder_sbr_whFactorsIndex[NUM_WHFACTOR_TABLE_ENTRIES]; -extern const FIXP_DBL FDK_sbrDecoder_sbr_whFactorsTable[NUM_WHFACTOR_TABLE_ENTRIES][6]; - - +#define NUM_WHFACTOR_TABLE_ENTRIES 9 +extern const USHORT + FDK_sbrDecoder_sbr_whFactorsIndex[NUM_WHFACTOR_TABLE_ENTRIES]; +extern const FIXP_DBL + FDK_sbrDecoder_sbr_whFactorsTable[NUM_WHFACTOR_TABLE_ENTRIES][6]; /* Envelope Adjustor */ extern const FIXP_SGL FDK_sbrDecoder_sbr_limGains_m[4]; -extern const UCHAR FDK_sbrDecoder_sbr_limGains_e[4]; +extern const UCHAR FDK_sbrDecoder_sbr_limGains_e[4]; +extern const FIXP_SGL FDK_sbrDecoder_sbr_limGainsPvc_m[4]; +extern const UCHAR FDK_sbrDecoder_sbr_limGainsPvc_e[4]; extern const FIXP_SGL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[4]; extern const FIXP_DBL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[4]; extern const FIXP_SGL FDK_sbrDecoder_sbr_smoothFilter[4]; extern const FIXP_SGL FDK_sbrDecoder_sbr_randomPhase[SBR_NF_NO_RANDOM_VAL][2]; -extern const FIXP_SGL harmonicPhaseX [2][4]; /* Envelope Extractor */ -extern const int FDK_sbrDecoder_envelopeTable_8 [8][5]; -extern const int FDK_sbrDecoder_envelopeTable_15 [15][6]; -extern const int FDK_sbrDecoder_envelopeTable_16 [16][6]; - +extern const int FDK_sbrDecoder_envelopeTable_8[8][5]; +extern const int FDK_sbrDecoder_envelopeTable_15[15][6]; +extern const int FDK_sbrDecoder_envelopeTable_16[16][6]; extern const FRAME_INFO FDK_sbrDecoder_sbr_frame_info1_15; extern const FRAME_INFO FDK_sbrDecoder_sbr_frame_info2_15; extern const FRAME_INFO FDK_sbrDecoder_sbr_frame_info4_15; extern const FRAME_INFO FDK_sbrDecoder_sbr_frame_info8_15; - extern const FRAME_INFO FDK_sbrDecoder_sbr_frame_info1_16; extern const FRAME_INFO FDK_sbrDecoder_sbr_frame_info2_16; extern const FRAME_INFO FDK_sbrDecoder_sbr_frame_info4_16; @@ -157,14 +180,10 @@ extern const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance11F[24][2]; extern const SCHAR FDK_sbrDecoder_sbr_huffBook_NoiseLevel11T[62][2]; extern const SCHAR FDK_sbrDecoder_sbr_huffBook_NoiseBalance11T[24][2]; - /* Parametric stereo */ - -extern const FIXP_DBL decayScaleFactTable[NO_QMF_CHANNELS]; - /* FIX_BORDER can have 0, 1, 2, 4 envelops */ extern const UCHAR FDK_sbrDecoder_aFixNoEnvDecode[4]; @@ -184,52 +203,14 @@ extern const FIXP_DBL ScaleFactors[NO_IID_LEVELS]; extern const FIXP_DBL ScaleFactorsFine[NO_IID_LEVELS_FINE]; extern const FIXP_DBL Alphas[NO_ICC_LEVELS]; -#if defined(ARCH_PREFER_MULT_32x16) -extern const FIXP_SGL aAllpassLinkDecaySer[NO_SERIAL_ALLPASS_LINKS]; -extern const FIXP_SGL aaFractDelayPhaseFactorReQmf[NO_QMF_CHANNELS]; -extern const FIXP_SGL aaFractDelayPhaseFactorImQmf[NO_QMF_CHANNELS]; -extern const FIXP_SGL aaFractDelayPhaseFactorReSubQmf20[NO_SUB_QMF_CHANNELS]; -extern const FIXP_SGL aaFractDelayPhaseFactorImSubQmf20[NO_SUB_QMF_CHANNELS]; - -extern const FIXP_SGL aaFractDelayPhaseFactorSerReQmf[NO_QMF_CHANNELS][NO_SERIAL_ALLPASS_LINKS]; -extern const FIXP_SGL aaFractDelayPhaseFactorSerImQmf[NO_QMF_CHANNELS][NO_SERIAL_ALLPASS_LINKS]; -extern const FIXP_SGL aaFractDelayPhaseFactorSerReSubQmf20[NO_SUB_QMF_CHANNELS][NO_SERIAL_ALLPASS_LINKS]; -extern const FIXP_SGL aaFractDelayPhaseFactorSerImSubQmf20[NO_SUB_QMF_CHANNELS][NO_SERIAL_ALLPASS_LINKS]; - -extern const FIXP_SGL p8_13_20[13]; -extern const FIXP_SGL p2_13_20[13]; - -#else -extern const FIXP_DBL aAllpassLinkDecaySer[NO_SERIAL_ALLPASS_LINKS]; -extern const FIXP_DBL aaFractDelayPhaseFactorReQmf[NO_QMF_CHANNELS]; -extern const FIXP_DBL aaFractDelayPhaseFactorImQmf[NO_QMF_CHANNELS]; -extern const FIXP_DBL aaFractDelayPhaseFactorReSubQmf20[NO_SUB_QMF_CHANNELS]; -extern const FIXP_DBL aaFractDelayPhaseFactorImSubQmf20[NO_SUB_QMF_CHANNELS]; - -extern const FIXP_DBL aaFractDelayPhaseFactorSerReQmf[NO_QMF_CHANNELS][NO_SERIAL_ALLPASS_LINKS]; -extern const FIXP_DBL aaFractDelayPhaseFactorSerImQmf[NO_QMF_CHANNELS][NO_SERIAL_ALLPASS_LINKS]; -extern const FIXP_DBL aaFractDelayPhaseFactorSerReSubQmf20[NO_SUB_QMF_CHANNELS][NO_SERIAL_ALLPASS_LINKS]; -extern const FIXP_DBL aaFractDelayPhaseFactorSerImSubQmf20[NO_SUB_QMF_CHANNELS][NO_SERIAL_ALLPASS_LINKS]; - -extern const FIXP_DBL p8_13_20[13]; -extern const FIXP_DBL p2_13_20[13]; -#endif - -extern const UCHAR aAllpassLinkDelaySer[3]; -extern const UCHAR delayIndexQmf[NO_QMF_CHANNELS]; -extern const UCHAR groupBorders20[NO_IID_GROUPS + 1]; -extern const UCHAR groupBorders34[NO_IID_GROUPS_HI_RES + 1]; extern const UCHAR bins2groupMap20[NO_IID_GROUPS]; -extern const UCHAR quantizedIIDs[NO_IID_STEPS]; -extern const UCHAR quantizedIIDsFine[NO_IID_STEPS_FINE]; extern const UCHAR FDK_sbrDecoder_aNoIidBins[3]; extern const UCHAR FDK_sbrDecoder_aNoIccBins[3]; - /* Lookup tables for some arithmetic functions */ #define INV_TABLE_BITS 8 -#define INV_TABLE_SIZE (1<<INV_TABLE_BITS) +#define INV_TABLE_SIZE (1 << INV_TABLE_BITS) extern const FIXP_SGL FDK_sbrDecoder_invTable[INV_TABLE_SIZE]; -#endif // __rom_H +#endif // SBR_ROM_H diff --git a/libSBRdec/src/sbr_scale.h b/libSBRdec/src/sbr_scale.h deleted file mode 100644 index 5fccd71..0000000 --- a/libSBRdec/src/sbr_scale.h +++ /dev/null @@ -1,123 +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 scaling factors, -To deal with the dynamic range in the different processing stages, a -fixed point specific code has to rely on scaling factors. A floating -point code carries a scaling factor -- the exponent -- for each value, -so scaling is not necessary there. - -The output of the core decoder (low band) is scaled up to cover as much -as possible bits for each value. As high band and low band are processed -in different algorithm sections, they require their own scaling -factors. In addition, any static buffers, e.g. filter states, require a -separate scaling factor as well. The code takes care to do the proper -adjustment, if scaling factors of a filter state and the time signal differ. - -\sa #QMF_SCALE_FACTOR, \ref documentationOverview -*/ - -#ifndef __SBR_SCALE_H -#define __SBR_SCALE_H - -/*! -\verbatim - scale: - 0 left aligned e.g. |max| >=0.5 - FRACT_BITS-1 zero e.g |max| = 0 -\endverbatim - - Dynamic scaling is used to achieve sufficient accuracy even when the signal - energy is low. The dynamic framing of SBR produces a variable overlap area - where samples from the previous QMF-Analysis are stored. Depending on the - start position and stop position of the current SBR envelopes, the processing - buffer consists of differently scaled regions like illustrated in the below - figure. - - \image html scales.png Scale -*/ - - -#endif diff --git a/libSBRdec/src/sbrdec_drc.cpp b/libSBRdec/src/sbrdec_drc.cpp index a834c0b..2d73f32 100644 --- a/libSBRdec/src/sbrdec_drc.cpp +++ b/libSBRdec/src/sbrdec_drc.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,23 +90,28 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -/***************************** MPEG-4 AAC Decoder ************************** +/**************************** SBR decoder library ****************************** Author(s): Christian Griebel + Description: Dynamic range control (DRC) decoder tool for SBR -******************************************************************************/ +*******************************************************************************/ #include "sbrdec_drc.h" - -/* DRC - Offset table for QMF interpolation. */ -static const int offsetTab[2][16] = -{ - { 0, 4, 8, 12, 16, 20, 24, 28, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 1024 framing */ - { 0, 4, 8, 12, 16, 19, 22, 26, 0, 0, 0, 0, 0, 0, 0, 0 } /* 960 framing */ +/* DRC - Offset table for QMF interpolation. Shifted by one index position. + The table defines the (short) window borders rounded to the nearest QMF + timeslot. It has the size 16 because it is accessed with the + drcInterpolationScheme that is read from the bitstream with 4 bit. */ +static const UCHAR winBorderToColMappingTab[2][16] = { + /*-1, 0, 1, 2, 3, 4, 5, 6, 7, 8 */ + {0, 0, 4, 8, 12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32, + 32}, /* 1024 framing */ + {0, 0, 4, 8, 11, 15, 19, 23, 26, 30, 30, 30, 30, 30, 30, + 30} /* 960 framing */ }; /*! @@ -105,9 +121,7 @@ static const int offsetTab[2][16] = \return none */ -void sbrDecoder_drcInitChannel ( - HANDLE_SBR_DRC_CHANNEL hDrcData ) -{ +void sbrDecoder_drcInitChannel(HANDLE_SBR_DRC_CHANNEL hDrcData) { int band; if (hDrcData == NULL) { @@ -139,7 +153,6 @@ void sbrDecoder_drcInitChannel ( hDrcData->enable = 0; } - /*! \brief Swap DRC QMF scaling factors after they have been applied. @@ -147,9 +160,7 @@ void sbrDecoder_drcInitChannel ( \return none */ -void sbrDecoder_drcUpdateChannel ( - HANDLE_SBR_DRC_CHANNEL hDrcData ) -{ +void sbrDecoder_drcUpdateChannel(HANDLE_SBR_DRC_CHANNEL hDrcData) { if (hDrcData == NULL) { return; } @@ -158,24 +169,21 @@ void sbrDecoder_drcUpdateChannel ( } /* swap previous data */ - FDKmemcpy( hDrcData->currFact_mag, - hDrcData->nextFact_mag, - SBRDEC_MAX_DRC_BANDS * sizeof(FIXP_DBL) ); + FDKmemcpy(hDrcData->currFact_mag, hDrcData->nextFact_mag, + SBRDEC_MAX_DRC_BANDS * sizeof(FIXP_DBL)); hDrcData->currFact_exp = hDrcData->nextFact_exp; hDrcData->numBandsCurr = hDrcData->numBandsNext; - FDKmemcpy( hDrcData->bandTopCurr, - hDrcData->bandTopNext, - SBRDEC_MAX_DRC_BANDS * sizeof(USHORT) ); + FDKmemcpy(hDrcData->bandTopCurr, hDrcData->bandTopNext, + SBRDEC_MAX_DRC_BANDS * sizeof(USHORT)); hDrcData->drcInterpolationSchemeCurr = hDrcData->drcInterpolationSchemeNext; hDrcData->winSequenceCurr = hDrcData->winSequenceNext; } - /*! \brief Apply DRC factors slot based. @@ -188,20 +196,15 @@ void sbrDecoder_drcUpdateChannel ( \return None. */ -void sbrDecoder_drcApplySlot ( - HANDLE_SBR_DRC_CHANNEL hDrcData, - FIXP_DBL *qmfRealSlot, - FIXP_DBL *qmfImagSlot, - int col, - int numQmfSubSamples, - int maxShift - ) -{ - const int *offset; +void sbrDecoder_drcApplySlot(HANDLE_SBR_DRC_CHANNEL hDrcData, + FIXP_DBL *qmfRealSlot, FIXP_DBL *qmfImagSlot, + int col, int numQmfSubSamples, int maxShift) { + const UCHAR *winBorderToColMap; int band, bottomMdct, topMdct, bin, useLP; - int indx = numQmfSubSamples - (numQmfSubSamples >> 1) - 10; /* l_border */ + int indx = numQmfSubSamples - (numQmfSubSamples >> 1) - 10; /* l_border */ int frameLenFlag = (numQmfSubSamples == 30) ? 1 : 0; + int frameSize = (frameLenFlag == 1) ? 960 : 1024; const FIXP_DBL *fact_mag = NULL; INT fact_exp = 0; @@ -218,31 +221,28 @@ void sbrDecoder_drcApplySlot ( return; } - offset = offsetTab[frameLenFlag]; + winBorderToColMap = winBorderToColMappingTab[frameLenFlag]; useLP = (qmfImagSlot == NULL) ? 1 : 0; col += indx; bottomMdct = 0; - bin = 0; /* get respective data and calc interpolation factor */ - if (col < (numQmfSubSamples>>1)) { /* first half of current frame */ + if (col < (numQmfSubSamples >> 1)) { /* first half of current frame */ if (hDrcData->winSequenceCurr != 2) { /* long window */ - int j = col + (numQmfSubSamples>>1); + int j = col + (numQmfSubSamples >> 1); if (hDrcData->drcInterpolationSchemeCurr == 0) { - INT k = (frameLenFlag) ? 0x4444444 : 0x4000000; + INT k = (frameLenFlag) ? 0x4444445 : 0x4000000; alphaValue = (FIXP_DBL)(j * k); - } - else { - if (j >= offset[hDrcData->drcInterpolationSchemeCurr - 1]) { + } else { + if (j >= (int)winBorderToColMap[hDrcData->drcInterpolationSchemeCurr]) { alphaValue = (FIXP_DBL)MAXVAL_DBL; } } - } - else { /* short windows */ + } else { /* short windows */ shortDrc = 1; } @@ -250,18 +250,16 @@ void sbrDecoder_drcApplySlot ( fact_exp = hDrcData->currFact_exp; numBands = hDrcData->numBandsCurr; bandTop = hDrcData->bandTopCurr; - } - else if (col < numQmfSubSamples) { /* second half of current frame */ + } else if (col < numQmfSubSamples) { /* second half of current frame */ if (hDrcData->winSequenceNext != 2) { /* next: long window */ - int j = col - (numQmfSubSamples>>1); + int j = col - (numQmfSubSamples >> 1); if (hDrcData->drcInterpolationSchemeNext == 0) { - INT k = (frameLenFlag) ? 0x4444444 : 0x4000000; + INT k = (frameLenFlag) ? 0x4444445 : 0x4000000; alphaValue = (FIXP_DBL)(j * k); - } - else { - if (j >= offset[hDrcData->drcInterpolationSchemeNext - 1]) { + } else { + if (j >= (int)winBorderToColMap[hDrcData->drcInterpolationSchemeNext]) { alphaValue = (FIXP_DBL)MAXVAL_DBL; } } @@ -270,17 +268,15 @@ void sbrDecoder_drcApplySlot ( fact_exp = hDrcData->nextFact_exp; numBands = hDrcData->numBandsNext; bandTop = hDrcData->bandTopNext; - } - else { /* next: short windows */ - if (hDrcData->winSequenceCurr != 2) { /* current: long window */ + } else { /* next: short windows */ + if (hDrcData->winSequenceCurr != 2) { /* current: long window */ alphaValue = (FIXP_DBL)0; fact_mag = hDrcData->nextFact_mag; fact_exp = hDrcData->nextFact_exp; numBands = hDrcData->numBandsNext; bandTop = hDrcData->bandTopNext; - } - else { /* current: short windows */ + } else { /* current: short windows */ shortDrc = 1; fact_mag = hDrcData->currFact_mag; @@ -289,23 +285,20 @@ void sbrDecoder_drcApplySlot ( bandTop = hDrcData->bandTopCurr; } } - } - else { /* first half of next frame */ + } else { /* first half of next frame */ if (hDrcData->winSequenceNext != 2) { /* long window */ - int j = col - (numQmfSubSamples>>1); + int j = col - (numQmfSubSamples >> 1); if (hDrcData->drcInterpolationSchemeNext == 0) { - INT k = (frameLenFlag) ? 0x4444444 : 0x4000000; + INT k = (frameLenFlag) ? 0x4444445 : 0x4000000; alphaValue = (FIXP_DBL)(j * k); - } - else { - if (j >= offset[hDrcData->drcInterpolationSchemeNext - 1]) { + } else { + if (j >= (int)winBorderToColMap[hDrcData->drcInterpolationSchemeNext]) { alphaValue = (FIXP_DBL)MAXVAL_DBL; } } - } - else { /* short windows */ + } else { /* short windows */ shortDrc = 1; } @@ -317,37 +310,33 @@ void sbrDecoder_drcApplySlot ( col -= numQmfSubSamples; } - /* process bands */ for (band = 0; band < (int)numBands; band++) { int bottomQmf, topQmf; FIXP_DBL drcFact_mag = (FIXP_DBL)MAXVAL_DBL; - topMdct = (bandTop[band]+1) << 2; + topMdct = (bandTop[band] + 1) << 2; - if (!shortDrc) { /* long window */ + if (!shortDrc) { /* long window */ if (frameLenFlag) { /* 960 framing */ - bottomMdct = 30 * (bottomMdct / 30); - topMdct = 30 * (topMdct / 30); + bottomQmf = fMultIfloor((FIXP_DBL)0x4444445, bottomMdct); + topQmf = fMultIfloor((FIXP_DBL)0x4444445, topMdct); - bottomQmf = fMultIfloor((FIXP_DBL)0x4444444, bottomMdct); - topQmf = fMultIfloor((FIXP_DBL)0x4444444, topMdct); - } - else { + topMdct = 30 * topQmf; + } else { /* 1024 framing */ - bottomMdct &= ~0x1f; - topMdct &= ~0x1f; + topMdct &= ~0x1f; bottomQmf = bottomMdct >> 5; - topQmf = topMdct >> 5; + topQmf = topMdct >> 5; } - if (band == ((int)numBands-1)) { + if (band == ((int)numBands - 1)) { topQmf = (64); } - + for (bin = bottomQmf; bin < topQmf; bin++) { FIXP_DBL drcFact1_mag = hDrcData->prevFact_mag[bin]; FIXP_DBL drcFact2_mag = fact_mag[band]; @@ -366,7 +355,9 @@ void sbrDecoder_drcApplySlot ( } else if (alphaValue == (FIXP_DBL)MAXVAL_DBL) { drcFact_mag = drcFact2_mag; } else { - drcFact_mag = fMult(alphaValue, drcFact2_mag) + fMult(((FIXP_DBL)MAXVAL_DBL - alphaValue), drcFact1_mag); + drcFact_mag = + fMult(alphaValue, drcFact2_mag) + + fMult(((FIXP_DBL)MAXVAL_DBL - alphaValue), drcFact1_mag); } /* apply scaling */ @@ -376,53 +367,78 @@ void sbrDecoder_drcApplySlot ( } /* save previous factors */ - if (col == (numQmfSubSamples>>1)-1) { + if (col == (numQmfSubSamples >> 1) - 1) { hDrcData->prevFact_mag[bin] = fact_mag[band]; } } - } - else { /* short windows */ - int startSample, stopSample; - FIXP_DBL invFrameSizeDiv8 = (frameLenFlag) ? (FIXP_DBL)0x1111111 : (FIXP_DBL)0x1000000; + } else { /* short windows */ + unsigned startWinIdx, stopWinIdx; + int startCol, stopCol; + FIXP_DBL invFrameSizeDiv8 = + (frameLenFlag) ? (FIXP_DBL)0x1111112 : (FIXP_DBL)0x1000000; + + /* limit top at the frame borders */ + if (topMdct < 0) { + topMdct = 0; + } + if (topMdct >= frameSize) { + topMdct = frameSize - 1; + } if (frameLenFlag) { /* 960 framing */ - bottomMdct = 30/8 * (bottomMdct*8/30); - topMdct = 30/8 * (topMdct*8/30); - } - else { + topMdct = fMultIfloor((FIXP_DBL)0x78000000, + fMultIfloor((FIXP_DBL)0x22222223, topMdct) << 2); + + startWinIdx = fMultIfloor(invFrameSizeDiv8, bottomMdct) + + 1; /* winBorderToColMap table has offset of 1 */ + stopWinIdx = fMultIceil(invFrameSizeDiv8 - (FIXP_DBL)1, topMdct) + 1; + } else { /* 1024 framing */ - bottomMdct &= ~0x03; - topMdct &= ~0x03; + topMdct &= ~0x03; + + startWinIdx = fMultIfloor(invFrameSizeDiv8, bottomMdct) + 1; + stopWinIdx = fMultIceil(invFrameSizeDiv8, topMdct) + 1; } - /* startSample is truncated to the nearest corresponding start subsample in + /* startCol is truncated to the nearest corresponding start subsample in the QMF of the short window bottom is present in:*/ - startSample = ((fMultIfloor( invFrameSizeDiv8, bottomMdct ) & 0x7) * numQmfSubSamples) >> 3; + startCol = (int)winBorderToColMap[startWinIdx]; - /* stopSample is rounded upwards to the nearest corresponding stop subsample + /* stopCol is rounded upwards to the nearest corresponding stop subsample in the QMF of the short window top is present in. */ - stopSample = ((fMultIceil( invFrameSizeDiv8, topMdct ) & 0xf) * numQmfSubSamples) >> 3; + stopCol = (int)winBorderToColMap[stopWinIdx]; - bottomQmf = fMultIfloor( invFrameSizeDiv8, ((bottomMdct%(numQmfSubSamples<<2)) << 5) ); - topQmf = fMultIfloor( invFrameSizeDiv8, ((topMdct%(numQmfSubSamples<<2)) << 5) ); + bottomQmf = fMultIfloor(invFrameSizeDiv8, + ((bottomMdct % (numQmfSubSamples << 2)) << 5)); + topQmf = fMultIfloor(invFrameSizeDiv8, + ((topMdct % (numQmfSubSamples << 2)) << 5)); /* extend last band */ - if (band == ((int)numBands-1)) { + if (band == ((int)numBands - 1)) { topQmf = (64); - stopSample = numQmfSubSamples; + stopCol = numQmfSubSamples; + stopWinIdx = 10; } if (topQmf == 0) { + if (frameLenFlag) { + FIXP_DBL rem = fMult(invFrameSizeDiv8, + (FIXP_DBL)(topMdct << (DFRACT_BITS - 12))); + if ((LONG)rem & (LONG)0x1F) { + stopWinIdx -= 1; + stopCol = (int)winBorderToColMap[stopWinIdx]; + } + } topQmf = (64); } /* save previous factors */ - if (stopSample == numQmfSubSamples) { + if (stopCol == numQmfSubSamples) { int tmpBottom = bottomQmf; - if (((numQmfSubSamples-1) & ~0x03) > startSample) { - tmpBottom = 0; /* band starts in previous short window */ + if ((int)winBorderToColMap[8] > startCol) { + tmpBottom = 0; /* band starts in previous short window */ } for (bin = tmpBottom; bin < topQmf; bin++) { @@ -431,12 +447,12 @@ void sbrDecoder_drcApplySlot ( } /* apply */ - if ((col >= startSample) && (col < stopSample)) { - if ((col & ~0x03) > startSample) { - bottomQmf = 0; /* band starts in previous short window */ + if ((col >= startCol) && (col < stopCol)) { + if (col >= (int)winBorderToColMap[startWinIdx + 1]) { + bottomQmf = 0; /* band starts in previous short window */ } - if (col < ((stopSample-1) & ~0x03)) { - topQmf = (64); /* band ends in next short window */ + if (col < (int)winBorderToColMap[stopWinIdx - 1]) { + topQmf = (64); /* band ends in next short window */ } drcFact_mag = fact_mag[band]; @@ -457,14 +473,13 @@ void sbrDecoder_drcApplySlot ( } bottomMdct = topMdct; - } /* end of bands loop */ + } /* end of bands loop */ - if (col == (numQmfSubSamples>>1)-1) { + if (col == (numQmfSubSamples >> 1) - 1) { hDrcData->prevFact_exp = fact_exp; } } - /*! \brief Apply DRC factors frame based. @@ -476,14 +491,9 @@ void sbrDecoder_drcApplySlot ( \return None. */ -void sbrDecoder_drcApply ( - HANDLE_SBR_DRC_CHANNEL hDrcData, - FIXP_DBL **QmfBufferReal, - FIXP_DBL **QmfBufferImag, - int numQmfSubSamples, - int *scaleFactor - ) -{ +void sbrDecoder_drcApply(HANDLE_SBR_DRC_CHANNEL hDrcData, + FIXP_DBL **QmfBufferReal, FIXP_DBL **QmfBufferImag, + int numQmfSubSamples, int *scaleFactor) { int col; int maxShift = 0; @@ -491,7 +501,8 @@ void sbrDecoder_drcApply ( return; } if (hDrcData->enable == 0) { - return; /* Avoid changing the scaleFactor even though the processing is disabled. */ + return; /* Avoid changing the scaleFactor even though the processing is + disabled. */ } /* get max scale factor */ @@ -505,21 +516,13 @@ void sbrDecoder_drcApply ( maxShift = hDrcData->nextFact_exp; } - for (col = 0; col < numQmfSubSamples; col++) - { + for (col = 0; col < numQmfSubSamples; col++) { FIXP_DBL *qmfSlotReal = QmfBufferReal[col]; FIXP_DBL *qmfSlotImag = (QmfBufferImag == NULL) ? NULL : QmfBufferImag[col]; - sbrDecoder_drcApplySlot ( - hDrcData, - qmfSlotReal, - qmfSlotImag, - col, - numQmfSubSamples, - maxShift - ); + sbrDecoder_drcApplySlot(hDrcData, qmfSlotReal, qmfSlotImag, col, + numQmfSubSamples, maxShift); } *scaleFactor += maxShift; } - diff --git a/libSBRdec/src/sbrdec_drc.h b/libSBRdec/src/sbrdec_drc.h index 7eed53a..2eb0e20 100644 --- a/libSBRdec/src/sbrdec_drc.h +++ b/libSBRdec/src/sbrdec_drc.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,73 +90,60 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ -/***************************** MPEG-4 AAC Decoder ************************** +/**************************** SBR decoder library ****************************** Author(s): Christian Griebel + Description: Dynamic range control (DRC) decoder tool for SBR -******************************************************************************/ +*******************************************************************************/ -#ifndef _SBRDEC_DRC_H_ -#define _SBRDEC_DRC_H_ +#ifndef SBRDEC_DRC_H +#define SBRDEC_DRC_H #include "sbrdecoder.h" +#define SBRDEC_MAX_DRC_CHANNELS (8) +#define SBRDEC_MAX_DRC_BANDS (16) - -#define SBRDEC_MAX_DRC_CHANNELS (8) -#define SBRDEC_MAX_DRC_BANDS ( 16 ) - -typedef struct -{ +typedef struct { FIXP_DBL prevFact_mag[(64)]; - INT prevFact_exp; + INT prevFact_exp; FIXP_DBL currFact_mag[SBRDEC_MAX_DRC_BANDS]; FIXP_DBL nextFact_mag[SBRDEC_MAX_DRC_BANDS]; - INT currFact_exp; - INT nextFact_exp; + INT currFact_exp; + INT nextFact_exp; - UINT numBandsCurr; - UINT numBandsNext; - USHORT bandTopCurr[SBRDEC_MAX_DRC_BANDS]; - USHORT bandTopNext[SBRDEC_MAX_DRC_BANDS]; + UINT numBandsCurr; + UINT numBandsNext; + USHORT bandTopCurr[SBRDEC_MAX_DRC_BANDS]; + USHORT bandTopNext[SBRDEC_MAX_DRC_BANDS]; - SHORT drcInterpolationSchemeCurr; - SHORT drcInterpolationSchemeNext; + SHORT drcInterpolationSchemeCurr; + SHORT drcInterpolationSchemeNext; - SHORT enable; + SHORT enable; - UCHAR winSequenceCurr; - UCHAR winSequenceNext; + UCHAR winSequenceCurr; + UCHAR winSequenceNext; } SBRDEC_DRC_CHANNEL; -typedef SBRDEC_DRC_CHANNEL * HANDLE_SBR_DRC_CHANNEL; - - -void sbrDecoder_drcInitChannel ( - HANDLE_SBR_DRC_CHANNEL hDrcData ); +typedef SBRDEC_DRC_CHANNEL *HANDLE_SBR_DRC_CHANNEL; -void sbrDecoder_drcUpdateChannel ( - HANDLE_SBR_DRC_CHANNEL hDrcData ); +void sbrDecoder_drcInitChannel(HANDLE_SBR_DRC_CHANNEL hDrcData); -void sbrDecoder_drcApplySlot ( - HANDLE_SBR_DRC_CHANNEL hDrcData, - FIXP_DBL *qmfRealSlot, - FIXP_DBL *qmfImagSlot, - int col, - int numQmfSubSamples, - int maxShift ); +void sbrDecoder_drcUpdateChannel(HANDLE_SBR_DRC_CHANNEL hDrcData); -void sbrDecoder_drcApply ( - HANDLE_SBR_DRC_CHANNEL hDrcData, - FIXP_DBL **QmfBufferReal, - FIXP_DBL **QmfBufferImag, - int numQmfSubSamples, - int *scaleFactor ); +void sbrDecoder_drcApplySlot(HANDLE_SBR_DRC_CHANNEL hDrcData, + FIXP_DBL *qmfRealSlot, FIXP_DBL *qmfImagSlot, + int col, int numQmfSubSamples, int maxShift); +void sbrDecoder_drcApply(HANDLE_SBR_DRC_CHANNEL hDrcData, + FIXP_DBL **QmfBufferReal, FIXP_DBL **QmfBufferImag, + int numQmfSubSamples, int *scaleFactor); -#endif /* _SBRDEC_DRC_H_ */ +#endif /* SBRDEC_DRC_H */ diff --git a/libSBRdec/src/sbrdec_freq_sca.cpp b/libSBRdec/src/sbrdec_freq_sca.cpp index 8adfbb1..165f94b 100644 --- a/libSBRdec/src/sbrdec_freq_sca.cpp +++ b/libSBRdec/src/sbrdec_freq_sca.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,11 +90,19 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief Frequency scale calculation + \brief Frequency scale calculation */ #include "sbrdec_freq_sca.h" @@ -92,18 +111,16 @@ amm-info@iis.fraunhofer.de #include "sbr_rom.h" #include "env_extr.h" -#include "genericStds.h" /* need log() for debug-code only */ - -#define MAX_OCTAVE 29 -#define MAX_SECOND_REGION 50 - - -static int numberOfBands(FIXP_SGL bpo_div16, int start, int stop, int warpFlag); -static void CalcBands(UCHAR * diff, UCHAR start, UCHAR stop, UCHAR num_bands); -static SBR_ERROR modifyBands(UCHAR max_band, UCHAR * diff, UCHAR length); -static void cumSum(UCHAR start_value, UCHAR* diff, UCHAR length, UCHAR *start_adress); +#include "genericStds.h" /* need log() for debug-code only */ +#define MAX_OCTAVE 29 +#define MAX_SECOND_REGION 50 +static int numberOfBands(FIXP_SGL bpo_div16, int start, int stop, int warpFlag); +static void CalcBands(UCHAR *diff, UCHAR start, UCHAR stop, UCHAR num_bands); +static SBR_ERROR modifyBands(UCHAR max_band, UCHAR *diff, UCHAR length); +static void cumSum(UCHAR start_value, UCHAR *diff, UCHAR length, + UCHAR *start_adress); /*! \brief Retrieve QMF-band where the SBR range starts @@ -113,41 +130,61 @@ static void cumSum(UCHAR start_value, UCHAR* diff, UCHAR length, UCHAR *start_ad \return Number of start band */ -static UCHAR -getStartBand(UINT fs, /*!< Output sampling frequency */ - UCHAR startFreq, /*!< Index to table of possible start bands */ - UINT headerDataFlags) /*!< Info to SBR mode */ +static UCHAR getStartBand( + UINT fs, /*!< Output sampling frequency */ + UCHAR startFreq, /*!< Index to table of possible start bands */ + UINT headerDataFlags) /*!< Info to SBR mode */ { - INT band; - UINT fsMapped; + INT band; + UINT fsMapped = fs; + SBR_RATE rate = DUAL; + + if (headerDataFlags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) { + if (headerDataFlags & SBRDEC_QUAD_RATE) { + rate = QUAD; + } + fsMapped = sbrdec_mapToStdSampleRate(fs, 1); + } - fsMapped = fs; + FDK_ASSERT(2 * (rate + 1) <= (4)); switch (fsMapped) { + case 192000: + band = FDK_sbrDecoder_sbr_start_freq_192[startFreq]; + break; + case 176400: + band = FDK_sbrDecoder_sbr_start_freq_176[startFreq]; + break; + case 128000: + band = FDK_sbrDecoder_sbr_start_freq_128[startFreq]; + break; case 96000: case 88200: - band = FDK_sbrDecoder_sbr_start_freq_88[startFreq]; + band = FDK_sbrDecoder_sbr_start_freq_88[rate][startFreq]; break; case 64000: - band = FDK_sbrDecoder_sbr_start_freq_64[startFreq]; + band = FDK_sbrDecoder_sbr_start_freq_64[rate][startFreq]; break; case 48000: - band = FDK_sbrDecoder_sbr_start_freq_48[startFreq]; + band = FDK_sbrDecoder_sbr_start_freq_48[rate][startFreq]; break; case 44100: - band = FDK_sbrDecoder_sbr_start_freq_44[startFreq]; + band = FDK_sbrDecoder_sbr_start_freq_44[rate][startFreq]; + break; + case 40000: + band = FDK_sbrDecoder_sbr_start_freq_40[rate][startFreq]; break; case 32000: - band = FDK_sbrDecoder_sbr_start_freq_32[startFreq]; + band = FDK_sbrDecoder_sbr_start_freq_32[rate][startFreq]; break; case 24000: - band = FDK_sbrDecoder_sbr_start_freq_24[startFreq]; + band = FDK_sbrDecoder_sbr_start_freq_24[rate][startFreq]; break; case 22050: - band = FDK_sbrDecoder_sbr_start_freq_22[startFreq]; + band = FDK_sbrDecoder_sbr_start_freq_22[rate][startFreq]; break; case 16000: - band = FDK_sbrDecoder_sbr_start_freq_16[startFreq]; + band = FDK_sbrDecoder_sbr_start_freq_16[rate][startFreq]; break; default: band = 255; @@ -156,7 +193,6 @@ getStartBand(UINT fs, /*!< Output sampling frequency */ return band; } - /*! \brief Retrieve QMF-band where the SBR range starts @@ -165,29 +201,32 @@ getStartBand(UINT fs, /*!< Output sampling frequency */ \return Number of start band */ -static UCHAR -getStopBand(UINT fs, /*!< Output sampling frequency */ - UCHAR stopFreq, /*!< Index to table of possible start bands */ - UINT headerDataFlags, /*!< Info to SBR mode */ - UCHAR k0) /*!< Start freq index */ +static UCHAR getStopBand( + UINT fs, /*!< Output sampling frequency */ + UCHAR stopFreq, /*!< Index to table of possible start bands */ + UINT headerDataFlags, /*!< Info to SBR mode */ + UCHAR k0) /*!< Start freq index */ { UCHAR k2; if (stopFreq < 14) { - INT stopMin; - UCHAR diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; + INT stopMin; + INT num = 2 * (64); + UCHAR diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; UCHAR *diff0 = diff_tot; - UCHAR *diff1 = diff_tot+MAX_OCTAVE; + UCHAR *diff1 = diff_tot + MAX_OCTAVE; - if (fs < 32000) { - stopMin = (((2*6000*2*(64)) / fs) + 1) >> 1; + if (headerDataFlags & SBRDEC_QUAD_RATE) { + num >>= 1; } - else { + + if (fs < 32000) { + stopMin = (((2 * 6000 * num) / fs) + 1) >> 1; + } else { if (fs < 64000) { - stopMin = (((2*8000*2*(64)) / fs) + 1) >> 1; - } - else { - stopMin = (((2*10000*2*(64)) / fs) + 1) >> 1; + stopMin = (((2 * 8000 * num) / fs) + 1) >> 1; + } else { + stopMin = (((2 * 10000 * num) / fs) + 1) >> 1; } } @@ -196,44 +235,49 @@ getStopBand(UINT fs, /*!< Output sampling frequency */ based on a logarithmic scale. The vectors diff0 and diff1 are used temporarily here. */ - CalcBands( diff0, stopMin, 64, 13); - shellsort( diff0, 13); + CalcBands(diff0, stopMin, 64, 13); + shellsort(diff0, 13); cumSum(stopMin, diff0, 13, diff1); k2 = diff1[stopFreq]; - } - else if (stopFreq==14) - k2 = 2*k0; + } else if (stopFreq == 14) + k2 = 2 * k0; else - k2 = 3*k0; + k2 = 3 * k0; /* Limit to Nyquist */ - if (k2 > (64)) - k2 = (64); - + if (k2 > (64)) k2 = (64); /* Range checks */ /* 1 <= difference <= 48; 1 <= fs <= 96000 */ - if ( ((k2 - k0) > MAX_FREQ_COEFFS) || (k2 <= k0) ) { - return 255; + { + UCHAR max_freq_coeffs = (headerDataFlags & SBRDEC_QUAD_RATE) + ? MAX_FREQ_COEFFS_QUAD_RATE + : MAX_FREQ_COEFFS; + if (((k2 - k0) > max_freq_coeffs) || (k2 <= k0)) { + return 255; + } } - if (headerDataFlags & (SBRDEC_SYNTAX_USAC|SBRDEC_SYNTAX_RSVD50)) { + if (headerDataFlags & SBRDEC_QUAD_RATE) { + return k2; /* skip other checks: (k2 - k0) must be <= + MAX_FREQ_COEFFS_QUAD_RATE for all fs */ + } + if (headerDataFlags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) { /* 1 <= difference <= 35; 42000 <= fs <= 96000 */ - if ( (fs >= 42000) && ( (k2 - k0) > MAX_FREQ_COEFFS_FS44100 ) ) { + if ((fs >= 42000) && ((k2 - k0) > MAX_FREQ_COEFFS_FS44100)) { return 255; } /* 1 <= difference <= 32; 46009 <= fs <= 96000 */ - if ( (fs >= 46009) && ( (k2 - k0) > MAX_FREQ_COEFFS_FS48000 ) ) { + if ((fs >= 46009) && ((k2 - k0) > MAX_FREQ_COEFFS_FS48000)) { return 255; } - } - else { + } else { /* 1 <= difference <= 35; fs == 44100 */ - if ( (fs == 44100) && ( (k2 - k0) > MAX_FREQ_COEFFS_FS44100 ) ) { + if ((fs == 44100) && ((k2 - k0) > MAX_FREQ_COEFFS_FS44100)) { return 255; } /* 1 <= difference <= 32; 48000 <= fs <= 96000 */ - if ( (fs >= 48000) && ( (k2 - k0) > MAX_FREQ_COEFFS_FS48000 ) ) { + if ((fs >= 48000) && ((k2 - k0) > MAX_FREQ_COEFFS_FS48000)) { return 255; } } @@ -241,7 +285,6 @@ getStopBand(UINT fs, /*!< Output sampling frequency */ return k2; } - /*! \brief Generates master frequency tables @@ -252,29 +295,33 @@ getStopBand(UINT fs, /*!< Output sampling frequency */ \return errorCode, 0 if successful */ SBR_ERROR -sbrdecUpdateFreqScale(UCHAR * v_k_master, /*!< Master table to be created */ - UCHAR *numMaster, /*!< Number of entries in master table */ - UINT fs, /*!< SBR working sampling rate */ - HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Control data from bitstream */ - UINT flags) -{ - FIXP_SGL bpo_div16; /* bands_per_octave divided by 16 */ - INT dk=0; +sbrdecUpdateFreqScale( + UCHAR *v_k_master, /*!< Master table to be created */ + UCHAR *numMaster, /*!< Number of entries in master table */ + UINT fs, /*!< SBR working sampling rate */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Control data from bitstream */ + UINT flags) { + FIXP_SGL bpo_div16; /* bands_per_octave divided by 16 */ + INT dk = 0; /* Internal variables */ - UCHAR k0, k2, i; - UCHAR num_bands0 = 0; - UCHAR num_bands1 = 0; - UCHAR diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; + UCHAR k0, k2, i; + UCHAR num_bands0 = 0; + UCHAR num_bands1 = 0; + UCHAR diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; UCHAR *diff0 = diff_tot; - UCHAR *diff1 = diff_tot+MAX_OCTAVE; - INT k2_achived; - INT k2_diff; - INT incr=0; + UCHAR *diff1 = diff_tot + MAX_OCTAVE; + INT k2_achived; + INT k2_diff; + INT incr = 0; /* Determine start band */ + if (flags & SBRDEC_QUAD_RATE) { + fs >>= 1; + } + k0 = getStartBand(fs, hHeaderData->bs_data.startFreq, flags); if (k0 == 255) { return SBRDEC_UNSUPPORTED_CONFIG; @@ -288,127 +335,134 @@ sbrdecUpdateFreqScale(UCHAR * v_k_master, /*!< Master table to be created */ return SBRDEC_UNSUPPORTED_CONFIG; } - if(hHeaderData->bs_data.freqScale>0) { /* Bark */ + if (hHeaderData->bs_data.freqScale > 0) { /* Bark */ INT k1; - if(hHeaderData->bs_data.freqScale==1) { - bpo_div16 = FL2FXCONST_SGL(12.0f/16.0f); - } - else if(hHeaderData->bs_data.freqScale==2) { - bpo_div16 = FL2FXCONST_SGL(10.0f/16.0f); - } - else { - bpo_div16 = FL2FXCONST_SGL(8.0f/16.0f); + if (hHeaderData->bs_data.freqScale == 1) { + bpo_div16 = FL2FXCONST_SGL(12.0f / 16.0f); + } else if (hHeaderData->bs_data.freqScale == 2) { + bpo_div16 = FL2FXCONST_SGL(10.0f / 16.0f); + } else { + bpo_div16 = FL2FXCONST_SGL(8.0f / 16.0f); } + /* Ref: ISO/IEC 23003-3, Figure 12 - Flowchart calculation of fMaster for + * 4:1 system when bs_freq_scale > 0 */ + if (flags & SBRDEC_QUAD_RATE) { + if ((SHORT)k0 < (SHORT)(bpo_div16 >> ((FRACT_BITS - 1) - 4))) { + bpo_div16 = (FIXP_SGL)(k0 & (UCHAR)0xfe) + << ((FRACT_BITS - 1) - 4); /* bpo_div16 = floor(k0/2)*2 */ + } + } - if( 1000 * k2 > 2245 * k0 ) { /* Two or more regions */ - k1 = 2*k0; + if (1000 * k2 > 2245 * k0) { /* Two or more regions */ + k1 = 2 * k0; num_bands0 = numberOfBands(bpo_div16, k0, k1, 0); - num_bands1 = numberOfBands(bpo_div16, k1, k2, hHeaderData->bs_data.alterScale ); - if ( num_bands0 < 1) { + num_bands1 = + numberOfBands(bpo_div16, k1, k2, hHeaderData->bs_data.alterScale); + if (num_bands0 < 1) { return SBRDEC_UNSUPPORTED_CONFIG; } - if ( num_bands1 < 1 ) { + if (num_bands1 < 1) { return SBRDEC_UNSUPPORTED_CONFIG; } CalcBands(diff0, k0, k1, num_bands0); - shellsort( diff0, num_bands0); + shellsort(diff0, num_bands0); if (diff0[0] == 0) { -#ifdef DEBUG_TOOLS -#endif return SBRDEC_UNSUPPORTED_CONFIG; } cumSum(k0, diff0, num_bands0, v_k_master); CalcBands(diff1, k1, k2, num_bands1); - shellsort( diff1, num_bands1); - if(diff0[num_bands0-1] > diff1[0]) { + shellsort(diff1, num_bands1); + if (diff0[num_bands0 - 1] > diff1[0]) { SBR_ERROR err; - err = modifyBands(diff0[num_bands0-1],diff1, num_bands1); - if (err) - return SBRDEC_UNSUPPORTED_CONFIG; + err = modifyBands(diff0[num_bands0 - 1], diff1, num_bands1); + if (err) return SBRDEC_UNSUPPORTED_CONFIG; } /* Add 2nd region */ cumSum(k1, diff1, num_bands1, &v_k_master[num_bands0]); - *numMaster = num_bands0 + num_bands1; /* Output nr of bands */ + *numMaster = num_bands0 + num_bands1; /* Output nr of bands */ - } - else { /* Only one region */ - k1=k2; + } else { /* Only one region */ + k1 = k2; num_bands0 = numberOfBands(bpo_div16, k0, k1, 0); - if ( num_bands0 < 1) { + if (num_bands0 < 1) { return SBRDEC_UNSUPPORTED_CONFIG; } CalcBands(diff0, k0, k1, num_bands0); shellsort(diff0, num_bands0); if (diff0[0] == 0) { -#ifdef DEBUG_TOOLS -#endif return SBRDEC_UNSUPPORTED_CONFIG; } cumSum(k0, diff0, num_bands0, v_k_master); - *numMaster = num_bands0; /* Output nr of bands */ - + *numMaster = num_bands0; /* Output nr of bands */ + } + } else { /* Linear mode */ + if (hHeaderData->bs_data.alterScale == 0) { + dk = 1; + /* FLOOR to get to few number of bands (next lower even number) */ + num_bands0 = (k2 - k0) & 254; + } else { + dk = 2; + num_bands0 = (((k2 - k0) >> 1) + 1) & 254; /* ROUND to the closest fit */ } - } - else { /* Linear mode */ - if (hHeaderData->bs_data.alterScale==0) { - dk = 1; - /* FLOOR to get to few number of bands (next lower even number) */ - num_bands0 = (k2 - k0) & 254; - } else { - dk = 2; - num_bands0 = ( ((k2 - k0) >> 1) + 1 ) & 254; /* ROUND to the closest fit */ - } - if (num_bands0 < 1) { - return SBRDEC_UNSUPPORTED_CONFIG; - /* We must return already here because 'i' can become negative below. */ - } + if (num_bands0 < 1) { + return SBRDEC_UNSUPPORTED_CONFIG; + /* We must return already here because 'i' can become negative below. */ + } - k2_achived = k0 + num_bands0*dk; - k2_diff = k2 - k2_achived; + k2_achived = k0 + num_bands0 * dk; + k2_diff = k2 - k2_achived; - for(i=0;i<num_bands0;i++) - diff_tot[i] = dk; + for (i = 0; i < num_bands0; i++) diff_tot[i] = dk; - /* If linear scale wasn't achieved */ - /* and we got too wide SBR area */ - if (k2_diff < 0) { - incr = 1; - i = 0; - } + /* If linear scale wasn't achieved */ + /* and we got too wide SBR area */ + if (k2_diff < 0) { + incr = 1; + i = 0; + } - /* If linear scale wasn't achieved */ - /* and we got too small SBR area */ - if (k2_diff > 0) { - incr = -1; - i = num_bands0-1; - } + /* If linear scale wasn't achieved */ + /* and we got too small SBR area */ + if (k2_diff > 0) { + incr = -1; + i = num_bands0 - 1; + } - /* Adjust diff vector to get sepc. SBR range */ - while (k2_diff != 0) { - diff_tot[i] = diff_tot[i] - incr; - i = i + incr; - k2_diff = k2_diff + incr; - } + /* Adjust diff vector to get sepc. SBR range */ + while (k2_diff != 0) { + diff_tot[i] = diff_tot[i] - incr; + i = i + incr; + k2_diff = k2_diff + incr; + } - cumSum(k0, diff_tot, num_bands0, v_k_master);/* cumsum */ - *numMaster = num_bands0; /* Output nr of bands */ + cumSum(k0, diff_tot, num_bands0, v_k_master); /* cumsum */ + *numMaster = num_bands0; /* Output nr of bands */ } if (*numMaster < 1) { return SBRDEC_UNSUPPORTED_CONFIG; } + /* Ref: ISO/IEC 23003-3 Cor.3, "In 7.5.5.2, add to the requirements:"*/ + if (flags & SBRDEC_QUAD_RATE) { + int k; + for (k = 1; k < *numMaster; k++) { + if (!(v_k_master[k] - v_k_master[k - 1] <= k0 - 2)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + } + } /* Print out the calculated table @@ -417,7 +471,6 @@ sbrdecUpdateFreqScale(UCHAR * v_k_master, /*!< Master table to be created */ return SBRDEC_OK; } - /*! \brief Calculate frequency ratio of one SBR band @@ -427,56 +480,52 @@ sbrdecUpdateFreqScale(UCHAR * v_k_master, /*!< Master table to be created */ \return num_band-th root of k_start/k_stop */ -static FIXP_SGL calcFactorPerBand(int k_start, int k_stop, int num_bands) -{ -/* Scaled bandfactor and step 1 bit right to avoid overflow - * use double data type */ +static FIXP_SGL calcFactorPerBand(int k_start, int k_stop, int num_bands) { + /* Scaled bandfactor and step 1 bit right to avoid overflow + * use double data type */ FIXP_DBL bandfactor = FL2FXCONST_DBL(0.25f); /* Start value */ - FIXP_DBL step = FL2FXCONST_DBL(0.125f); /* Initial increment for factor */ + FIXP_DBL step = FL2FXCONST_DBL(0.125f); /* Initial increment for factor */ - int direction = 1; + int direction = 1; -/* Because saturation can't be done in INT IIS, - * changed start and stop data type from FIXP_SGL to FIXP_DBL */ - FIXP_DBL start = k_start << (DFRACT_BITS-8); - FIXP_DBL stop = k_stop << (DFRACT_BITS-8); + /* Because saturation can't be done in INT IIS, + * changed start and stop data type from FIXP_SGL to FIXP_DBL */ + FIXP_DBL start = k_start << (DFRACT_BITS - 8); + FIXP_DBL stop = k_stop << (DFRACT_BITS - 8); FIXP_DBL temp; - int j, i=0; + int j, i = 0; - while ( step > FL2FXCONST_DBL(0.0f)) { + while (step > FL2FXCONST_DBL(0.0f)) { i++; temp = stop; /* Calculate temp^num_bands: */ - for (j=0; j<num_bands; j++) - //temp = fMult(temp,bandfactor); - temp = fMultDiv2(temp,bandfactor)<<2; + for (j = 0; j < num_bands; j++) + // temp = fMult(temp,bandfactor); + temp = fMultDiv2(temp, bandfactor) << 2; - if (temp<start) { /* Factor too strong, make it weaker */ + if (temp < start) { /* Factor too strong, make it weaker */ if (direction == 0) /* Halfen step. Right shift is not done as fract because otherwise the lowest bit cannot be cleared due to rounding */ step = (FIXP_DBL)((LONG)step >> 1); direction = 1; bandfactor = bandfactor + step; - } - else { /* Factor is too weak: make it stronger */ - if (direction == 1) - step = (FIXP_DBL)((LONG)step >> 1); + } else { /* Factor is too weak: make it stronger */ + if (direction == 1) step = (FIXP_DBL)((LONG)step >> 1); direction = 0; bandfactor = bandfactor - step; } - if (i>100) { + if (i > 100) { step = FL2FXCONST_DBL(0.0f); } } - return FX_DBL2FX_SGL(bandfactor<<1); + return FX_DBL2FX_SGL(bandfactor << 1); } - /*! \brief Calculate number of SBR bands between start and stop band @@ -487,34 +536,35 @@ static FIXP_SGL calcFactorPerBand(int k_start, int k_stop, int num_bands) \return number of bands */ -static int -numberOfBands(FIXP_SGL bpo_div16, /*!< Input: number of bands per octave divided by 16 */ - int start, /*!< First QMF band of SBR frequency range */ - int stop, /*!< Last QMF band of SBR frequency range + 1 */ - int warpFlag) /*!< Stretching flag */ +static int numberOfBands( + FIXP_SGL bpo_div16, /*!< Input: number of bands per octave divided by 16 */ + int start, /*!< First QMF band of SBR frequency range */ + int stop, /*!< Last QMF band of SBR frequency range + 1 */ + int warpFlag) /*!< Stretching flag */ { FIXP_SGL num_bands_div128; - int num_bands; + int num_bands; - num_bands_div128 = FX_DBL2FX_SGL(fMult(FDK_getNumOctavesDiv8(start,stop),bpo_div16)); + num_bands_div128 = + FX_DBL2FX_SGL(fMult(FDK_getNumOctavesDiv8(start, stop), bpo_div16)); if (warpFlag) { /* Apply the warp factor of 1.3 to get wider bands. We use a value of 32768/25200 instead of the exact value to avoid critical cases of rounding. */ - num_bands_div128 = FX_DBL2FX_SGL(fMult(num_bands_div128, FL2FXCONST_SGL(25200.0/32768.0))); + num_bands_div128 = FX_DBL2FX_SGL( + fMult(num_bands_div128, FL2FXCONST_SGL(25200.0 / 32768.0))); } /* add scaled 1 for rounding to even numbers: */ - num_bands_div128 = num_bands_div128 + FL2FXCONST_SGL( 1.0f/128.0f ); + num_bands_div128 = num_bands_div128 + FL2FXCONST_SGL(1.0f / 128.0f); /* scale back to right aligned integer and double the value: */ num_bands = 2 * ((LONG)num_bands_div128 >> (FRACT_BITS - 7)); - return(num_bands); + return (num_bands); } - /*! \brief Calculate width of SBR bands @@ -522,11 +572,10 @@ numberOfBands(FIXP_SGL bpo_div16, /*!< Input: number of bands per octave divided this function calculates the width of each SBR band in QMF channels. The bands get wider from start to stop (bark scale). */ -static void -CalcBands(UCHAR * diff, /*!< Vector of widths to be calculated */ - UCHAR start, /*!< Lower end of subband range */ - UCHAR stop, /*!< Upper end of subband range */ - UCHAR num_bands) /*!< Desired number of bands */ +static void CalcBands(UCHAR *diff, /*!< Vector of widths to be calculated */ + UCHAR start, /*!< Lower end of subband range */ + UCHAR stop, /*!< Upper end of subband range */ + UCHAR num_bands) /*!< Desired number of bands */ { int i; int previous; @@ -535,18 +584,20 @@ CalcBands(UCHAR * diff, /*!< Vector of widths to be calculated */ FIXP_SGL bandfactor = calcFactorPerBand(start, stop, num_bands); previous = stop; /* Start with highest QMF channel */ - exact = (FIXP_SGL)(stop << (FRACT_BITS-8)); /* Shift left to gain some accuracy */ + exact = (FIXP_SGL)( + stop << (FRACT_BITS - 8)); /* Shift left to gain some accuracy */ - for(i=num_bands-1; i>=0; i--) { + for (i = num_bands - 1; i >= 0; i--) { /* Calculate border of next lower sbr band */ - exact = FX_DBL2FX_SGL(fMult(exact,bandfactor)); + exact = FX_DBL2FX_SGL(fMult(exact, bandfactor)); /* Add scaled 0.5 for rounding: - We use a value 128/256 instead of 0.5 to avoid some critical cases of rounding. */ - temp = exact + FL2FXCONST_SGL(128.0/32768.0); + We use a value 128/256 instead of 0.5 to avoid some critical cases of + rounding. */ + temp = exact + FL2FXCONST_SGL(128.0 / 32768.0); /* scale back to right alinged integer: */ - current = (LONG)temp >> (FRACT_BITS-8); + current = (LONG)temp >> (FRACT_BITS - 8); /* Save width of band i */ diff[i] = previous - current; @@ -554,20 +605,17 @@ CalcBands(UCHAR * diff, /*!< Vector of widths to be calculated */ } } - /*! \brief Calculate cumulated sum vector from delta vector */ -static void -cumSum(UCHAR start_value, UCHAR* diff, UCHAR length, UCHAR *start_adress) -{ +static void cumSum(UCHAR start_value, UCHAR *diff, UCHAR length, + UCHAR *start_adress) { int i; - start_adress[0]=start_value; - for(i=1; i<=length; i++) - start_adress[i] = start_adress[i-1] + diff[i-1]; + start_adress[0] = start_value; + for (i = 1; i <= length; i++) + start_adress[i] = start_adress[i - 1] + diff[i - 1]; } - /*! \brief Adapt width of frequency bands in the second region @@ -575,116 +623,96 @@ cumSum(UCHAR start_value, UCHAR* diff, UCHAR length, UCHAR *start_adress) is calculated separately. This function tries to avoid that the second region starts with a band smaller than the highest band of the first region. */ -static SBR_ERROR -modifyBands(UCHAR max_band_previous, UCHAR * diff, UCHAR length) -{ +static SBR_ERROR modifyBands(UCHAR max_band_previous, UCHAR *diff, + UCHAR length) { int change = max_band_previous - diff[0]; - /* Limit the change so that the last band cannot get narrower than the first one */ - if ( change > (diff[length-1]-diff[0])>>1 ) - change = (diff[length-1]-diff[0])>>1; + /* Limit the change so that the last band cannot get narrower than the first + * one */ + if (change > (diff[length - 1] - diff[0]) >> 1) + change = (diff[length - 1] - diff[0]) >> 1; diff[0] += change; - diff[length-1] -= change; + diff[length - 1] -= change; shellsort(diff, length); return SBRDEC_OK; } - /*! \brief Update high resolution frequency band table */ -static void -sbrdecUpdateHiRes(UCHAR * h_hires, - UCHAR * num_hires, - UCHAR * v_k_master, - UCHAR num_bands, - UCHAR xover_band) -{ +static void sbrdecUpdateHiRes(UCHAR *h_hires, UCHAR *num_hires, + UCHAR *v_k_master, UCHAR num_bands, + UCHAR xover_band) { UCHAR i; - *num_hires = num_bands-xover_band; + *num_hires = num_bands - xover_band; - for(i=xover_band; i<=num_bands; i++) { - h_hires[i-xover_band] = v_k_master[i]; + for (i = xover_band; i <= num_bands; i++) { + h_hires[i - xover_band] = v_k_master[i]; } } - /*! \brief Build low resolution table out of high resolution table */ -static void -sbrdecUpdateLoRes(UCHAR * h_lores, - UCHAR * num_lores, - UCHAR * h_hires, - UCHAR num_hires) -{ +static void sbrdecUpdateLoRes(UCHAR *h_lores, UCHAR *num_lores, UCHAR *h_hires, + UCHAR num_hires) { UCHAR i; - if( (num_hires & 1) == 0) { + if ((num_hires & 1) == 0) { /* If even number of hires bands */ *num_lores = num_hires >> 1; /* Use every second lores=hires[0,2,4...] */ - for(i=0; i<=*num_lores; i++) - h_lores[i] = h_hires[i*2]; - } - else { + for (i = 0; i <= *num_lores; i++) h_lores[i] = h_hires[i * 2]; + } else { /* Odd number of hires, which means xover is odd */ - *num_lores = (num_hires+1) >> 1; + *num_lores = (num_hires + 1) >> 1; /* Use lores=hires[0,1,3,5 ...] */ h_lores[0] = h_hires[0]; - for(i=1; i<=*num_lores; i++) { - h_lores[i] = h_hires[i*2-1]; + for (i = 1; i <= *num_lores; i++) { + h_lores[i] = h_hires[i * 2 - 1]; } } } - /*! - \brief Derive a low-resolution frequency-table from the master frequency table + \brief Derive a low-resolution frequency-table from the master frequency + table */ -void -sbrdecDownSampleLoRes(UCHAR *v_result, - UCHAR num_result, - UCHAR *freqBandTableRef, - UCHAR num_Ref) -{ +void sbrdecDownSampleLoRes(UCHAR *v_result, UCHAR num_result, + UCHAR *freqBandTableRef, UCHAR num_Ref) { int step; - int i,j; - int org_length,result_length; - int v_index[MAX_FREQ_COEFFS>>1]; + int i, j; + int org_length, result_length; + int v_index[MAX_FREQ_COEFFS >> 1]; /* init */ org_length = num_Ref; result_length = num_result; - v_index[0] = 0; /* Always use left border */ - i=0; - while(org_length > 0) { + v_index[0] = 0; /* Always use left border */ + i = 0; + while (org_length > 0) { /* Create downsample vector */ i++; step = org_length / result_length; org_length = org_length - step; result_length--; - v_index[i] = v_index[i-1] + step; + v_index[i] = v_index[i - 1] + step; } - for(j=0;j<=i;j++) { + for (j = 0; j <= i; j++) { /* Use downsample vector to index LoResolution vector */ - v_result[j]=freqBandTableRef[v_index[j]]; + v_result[j] = freqBandTableRef[v_index[j]]; } - } - /*! \brief Sorting routine */ -void shellsort(UCHAR *in, UCHAR n) -{ - +void shellsort(UCHAR *in, UCHAR n) { int i, j, v, w; int inc = 1; @@ -697,115 +725,110 @@ void shellsort(UCHAR *in, UCHAR n) for (i = inc; i < n; i++) { v = in[i]; j = i; - while ((w=in[j-inc]) > v) { + while ((w = in[j - inc]) > v) { in[j] = w; j -= inc; - if (j < inc) - break; + if (j < inc) break; } in[j] = v; } } while (inc > 1); - } - - /*! \brief Reset frequency band tables \return errorCode, 0 if successful */ SBR_ERROR -resetFreqBandTables(HANDLE_SBR_HEADER_DATA hHeaderData, const UINT flags) -{ +resetFreqBandTables(HANDLE_SBR_HEADER_DATA hHeaderData, const UINT flags) { SBR_ERROR err = SBRDEC_OK; - int k2,kx, lsb, usb; - int intTemp; - UCHAR nBandsLo, nBandsHi; + int k2, kx, lsb, usb; + int intTemp; + UCHAR nBandsLo, nBandsHi; HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; /* Calculate master frequency function */ - err = sbrdecUpdateFreqScale(hFreq->v_k_master, - &hFreq->numMaster, - hHeaderData->sbrProcSmplRate, - hHeaderData, - flags); + err = sbrdecUpdateFreqScale(hFreq->v_k_master, &hFreq->numMaster, + hHeaderData->sbrProcSmplRate, hHeaderData, flags); - if ( err || (hHeaderData->bs_info.xover_band > hFreq->numMaster) ) { + if (err || (hHeaderData->bs_info.xover_band > hFreq->numMaster)) { return SBRDEC_UNSUPPORTED_CONFIG; } /* Derive Hiresolution from master frequency function */ - sbrdecUpdateHiRes(hFreq->freqBandTable[1], &nBandsHi, hFreq->v_k_master, hFreq->numMaster, hHeaderData->bs_info.xover_band ); + sbrdecUpdateHiRes(hFreq->freqBandTable[1], &nBandsHi, hFreq->v_k_master, + hFreq->numMaster, hHeaderData->bs_info.xover_band); /* Derive Loresolution from Hiresolution */ - sbrdecUpdateLoRes(hFreq->freqBandTable[0], &nBandsLo, hFreq->freqBandTable[1], nBandsHi); - + sbrdecUpdateLoRes(hFreq->freqBandTable[0], &nBandsLo, hFreq->freqBandTable[1], + nBandsHi); hFreq->nSfb[0] = nBandsLo; hFreq->nSfb[1] = nBandsHi; /* Check index to freqBandTable[0] */ - if ( !(nBandsLo > 0) || (nBandsLo > (MAX_FREQ_COEFFS>>1)) ) { + if (!(nBandsLo > 0) || + (nBandsLo > (((hHeaderData->numberOfAnalysisBands == 16) + ? MAX_FREQ_COEFFS_QUAD_RATE + : MAX_FREQ_COEFFS_DUAL_RATE) >> + 1))) { return SBRDEC_UNSUPPORTED_CONFIG; } lsb = hFreq->freqBandTable[0][0]; usb = hFreq->freqBandTable[0][nBandsLo]; - /* Additional check for lsb */ - if ( (lsb > (32)) || (lsb >= usb) ) { + /* Check for start frequency border k_x: + - ISO/IEC 14496-3 4.6.18.3.6 Requirements + - ISO/IEC 23003-3 7.5.5.2 Modifications and additions to the MPEG-4 SBR + tool + */ + /* Note that lsb > as hHeaderData->numberOfAnalysisBands is a valid SBR config + * for 24 band QMF analysis. */ + if ((lsb > ((flags & SBRDEC_QUAD_RATE) ? 16 : (32))) || (lsb >= usb)) { return SBRDEC_UNSUPPORTED_CONFIG; } - /* Calculate number of noise bands */ k2 = hFreq->freqBandTable[1][nBandsHi]; kx = hFreq->freqBandTable[1][0]; - if (hHeaderData->bs_data.noise_bands == 0) - { + if (hHeaderData->bs_data.noise_bands == 0) { hFreq->nNfb = 1; - } - else /* Calculate no of noise bands 1,2 or 3 bands/octave */ + } else /* Calculate no of noise bands 1,2 or 3 bands/octave */ { /* Fetch number of octaves divided by 32 */ - intTemp = (LONG)FDK_getNumOctavesDiv8(kx,k2) >> 2; + intTemp = (LONG)FDK_getNumOctavesDiv8(kx, k2) >> 2; /* Integer-Multiplication with number of bands: */ intTemp = intTemp * hHeaderData->bs_data.noise_bands; /* Add scaled 0.5 for rounding: */ - intTemp = intTemp + (LONG)FL2FXCONST_SGL(0.5f/32.0f); + intTemp = intTemp + (LONG)FL2FXCONST_SGL(0.5f / 32.0f); /* Convert to right-aligned integer: */ intTemp = intTemp >> (FRACT_BITS - 1 /*sign*/ - 5 /* rescale */); - /* Compare with float calculation */ - FDK_ASSERT( intTemp == (int)((hHeaderData->bs_data.noise_bands * FDKlog( (float)k2/kx) / (float)(FDKlog(2.0)))+0.5) ); - - if( intTemp==0) - intTemp=1; + if (intTemp == 0) intTemp = 1; hFreq->nNfb = intTemp; } hFreq->nInvfBands = hFreq->nNfb; - if( hFreq->nNfb > MAX_NOISE_COEFFS ) { + if (hFreq->nNfb > MAX_NOISE_COEFFS) { return SBRDEC_UNSUPPORTED_CONFIG; } /* Get noise bands */ - sbrdecDownSampleLoRes(hFreq->freqBandTableNoise, - hFreq->nNfb, - hFreq->freqBandTable[0], - nBandsLo); - - + sbrdecDownSampleLoRes(hFreq->freqBandTableNoise, hFreq->nNfb, + hFreq->freqBandTable[0], nBandsLo); + /* save old highband; required for overlap in usac + when headerchange occurs at XVAR and VARX frame; */ + hFreq->ov_highSubband = hFreq->highSubband; - hFreq->lowSubband = lsb; + hFreq->lowSubband = lsb; hFreq->highSubband = usb; return SBRDEC_OK; diff --git a/libSBRdec/src/sbrdec_freq_sca.h b/libSBRdec/src/sbrdec_freq_sca.h index cfe4f0e..7e6b8e8 100644 --- a/libSBRdec/src/sbrdec_freq_sca.h +++ b/libSBRdec/src/sbrdec_freq_sca.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,22 +90,31 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief Frequency scale prototypes + \brief Frequency scale prototypes */ -#ifndef __FREQ_SCA_H -#define __FREQ_SCA_H +#ifndef SBRDEC_FREQ_SCA_H +#define SBRDEC_FREQ_SCA_H #include "sbrdecoder.h" #include "env_extr.h" -int -sbrdecUpdateFreqScale(UCHAR * v_k_master, - UCHAR *numMaster, - HANDLE_SBR_HEADER_DATA headerData); +typedef enum { DUAL, QUAD } SBR_RATE; + +SBR_ERROR +sbrdecUpdateFreqScale(UCHAR *v_k_master, UCHAR *numMaster, UINT fs, + HANDLE_SBR_HEADER_DATA headerData, UINT flags); void sbrdecDownSampleLoRes(UCHAR *v_result, UCHAR num_result, UCHAR *freqBandTableRef, UCHAR num_Ref); diff --git a/libSBRdec/src/sbrdecoder.cpp b/libSBRdec/src/sbrdecoder.cpp index f9ded54..e2455da 100644 --- a/libSBRdec/src/sbrdecoder.cpp +++ b/libSBRdec/src/sbrdecoder.cpp @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- Software License for The Fraunhofer FDK AAC Codec Library for Android -© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,38 +90,48 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \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()]. + 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 + \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: + 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() + \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 + \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 */ @@ -134,11 +155,10 @@ amm-info@iis.fraunhofer.de #include "psbitdec.h" - /* Decoder library info */ -#define SBRDECODER_LIB_VL0 2 -#define SBRDECODER_LIB_VL1 2 -#define SBRDECODER_LIB_VL2 12 +#define SBRDECODER_LIB_VL0 3 +#define SBRDECODER_LIB_VL1 0 +#define SBRDECODER_LIB_VL2 0 #define SBRDECODER_LIB_TITLE "SBR Decoder" #ifdef __ANDROID__ #define SBRDECODER_LIB_BUILD_DATE "" @@ -148,20 +168,28 @@ amm-info@iis.fraunhofer.de #define SBRDECODER_LIB_BUILD_TIME __TIME__ #endif +static void setFrameErrorFlag(SBR_DECODER_ELEMENT *pSbrElement, UCHAR value) { + if (pSbrElement != NULL) { + switch (value) { + case FRAME_ERROR_ALLSLOTS: + FDKmemset(pSbrElement->frameErrorFlag, FRAME_ERROR, + sizeof(pSbrElement->frameErrorFlag)); + break; + default: + pSbrElement->frameErrorFlag[pSbrElement->useFrameSlot] = value; + } + } +} - - -static UCHAR getHeaderSlot( UCHAR currentSlot, UCHAR hdrSlotUsage[(1)+1] ) -{ - UINT occupied = 0; - int s; +static UCHAR getHeaderSlot(UCHAR currentSlot, UCHAR hdrSlotUsage[(1) + 1]) { + UINT occupied = 0; + int s; UCHAR slot = hdrSlotUsage[currentSlot]; - FDK_ASSERT((1)+1 < 32); + FDK_ASSERT((1) + 1 < 32); - for (s = 0; s < (1)+1; s++) { - if ( (hdrSlotUsage[s] == slot) - && (s != slot) ) { + for (s = 0; s < (1) + 1; s++) { + if ((hdrSlotUsage[s] == slot) && (s != slot)) { occupied = 1; break; } @@ -170,11 +198,11 @@ static UCHAR getHeaderSlot( UCHAR currentSlot, UCHAR hdrSlotUsage[(1)+1] ) if (occupied) { occupied = 0; - for (s = 0; s < (1)+1; s++) { + for (s = 0; s < (1) + 1; s++) { occupied |= 1 << hdrSlotUsage[s]; } - for (s = 0; s < (1)+1; s++) { - if ( !(occupied & 0x1) ) { + for (s = 0; s < (1) + 1; s++) { + if (!(occupied & 0x1)) { slot = s; break; } @@ -185,18 +213,18 @@ static UCHAR getHeaderSlot( UCHAR currentSlot, UCHAR hdrSlotUsage[(1)+1] ) return slot; } -static void copySbrHeader( HANDLE_SBR_HEADER_DATA hDst, const HANDLE_SBR_HEADER_DATA hSrc ) -{ +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) ); + FDKmemcpy(hDst, hSrc, sizeof(SBR_HEADER_DATA)); /* update pointers */ - hDst->freqBandData.freqBandTable[0] = hDst->freqBandData.freqBandTableLo; + hDst->freqBandData.freqBandTable[0] = hDst->freqBandData.freqBandTableLo; hDst->freqBandData.freqBandTable[1] = hDst->freqBandData.freqBandTableHi; } -static int compareSbrHeader( const HANDLE_SBR_HEADER_DATA hHdr1, const HANDLE_SBR_HEADER_DATA hHdr2 ) -{ +static int compareSbrHeader(const HANDLE_SBR_HEADER_DATA hHdr1, + const HANDLE_SBR_HEADER_DATA hHdr2) { int result = 0; /* compare basic data */ @@ -204,25 +232,38 @@ static int compareSbrHeader( const HANDLE_SBR_HEADER_DATA hHdr1, const HANDLE_SB result |= (hHdr1->status != hHdr2->status) ? 1 : 0; result |= (hHdr1->frameErrorFlag != hHdr2->frameErrorFlag) ? 1 : 0; result |= (hHdr1->numberTimeSlots != hHdr2->numberTimeSlots) ? 1 : 0; - result |= (hHdr1->numberOfAnalysisBands != hHdr2->numberOfAnalysisBands) ? 1 : 0; + result |= + (hHdr1->numberOfAnalysisBands != hHdr2->numberOfAnalysisBands) ? 1 : 0; result |= (hHdr1->timeStep != hHdr2->timeStep) ? 1 : 0; result |= (hHdr1->sbrProcSmplRate != hHdr2->sbrProcSmplRate) ? 1 : 0; /* compare bitstream data */ - result |= FDKmemcmp( &hHdr1->bs_data, &hHdr2->bs_data, sizeof(SBR_HEADER_DATA_BS) ); - result |= FDKmemcmp( &hHdr1->bs_info, &hHdr2->bs_info, sizeof(SBR_HEADER_DATA_BS_INFO) ); + result |= + FDKmemcmp(&hHdr1->bs_data, &hHdr2->bs_data, sizeof(SBR_HEADER_DATA_BS)); + result |= + FDKmemcmp(&hHdr1->bs_dflt, &hHdr2->bs_dflt, sizeof(SBR_HEADER_DATA_BS)); + result |= FDKmemcmp(&hHdr1->bs_info, &hHdr2->bs_info, + sizeof(SBR_HEADER_DATA_BS_INFO)); /* compare frequency band data */ - result |= FDKmemcmp( &hHdr1->freqBandData, &hHdr2->freqBandData, (8+MAX_NUM_LIMITERS+1)*sizeof(UCHAR) ); - result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableLo, hHdr2->freqBandData.freqBandTableLo, (MAX_FREQ_COEFFS/2+1)*sizeof(UCHAR) ); - result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableHi, hHdr2->freqBandData.freqBandTableHi, (MAX_FREQ_COEFFS+1)*sizeof(UCHAR) ); - result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableNoise, hHdr2->freqBandData.freqBandTableNoise, (MAX_NOISE_COEFFS+1)*sizeof(UCHAR) ); - result |= FDKmemcmp( hHdr1->freqBandData.v_k_master, hHdr2->freqBandData.v_k_master, (MAX_FREQ_COEFFS+1)*sizeof(UCHAR) ); + result |= FDKmemcmp(&hHdr1->freqBandData, &hHdr2->freqBandData, + (8 + MAX_NUM_LIMITERS + 1) * sizeof(UCHAR)); + result |= FDKmemcmp(hHdr1->freqBandData.freqBandTableLo, + hHdr2->freqBandData.freqBandTableLo, + (MAX_FREQ_COEFFS / 2 + 1) * sizeof(UCHAR)); + result |= FDKmemcmp(hHdr1->freqBandData.freqBandTableHi, + hHdr2->freqBandData.freqBandTableHi, + (MAX_FREQ_COEFFS + 1) * sizeof(UCHAR)); + result |= FDKmemcmp(hHdr1->freqBandData.freqBandTableNoise, + hHdr2->freqBandData.freqBandTableNoise, + (MAX_NOISE_COEFFS + 1) * sizeof(UCHAR)); + result |= + FDKmemcmp(hHdr1->freqBandData.v_k_master, hHdr2->freqBandData.v_k_master, + (MAX_FREQ_COEFFS + 1) * sizeof(UCHAR)); return result; } - /*! \brief Reset SBR decoder. @@ -231,60 +272,54 @@ static int compareSbrHeader( const HANDLE_SBR_HEADER_DATA hHdr1, const HANDLE_SB \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 - ) -{ +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; + /* USAC: assuming theoretical case 8 kHz output sample rate with 4:1 SBR */ + const int sbr_min_sample_rate_in = IS_USAC(self->coreCodec) ? 2000 : 6400; + /* Check in/out samplerates */ - if ( sampleRateIn < 6400 - || sampleRateIn > 48000 - ) - { + if (sampleRateIn < sbr_min_sample_rate_in || sampleRateIn > (96000)) { sbrError = SBRDEC_UNSUPPORTED_CONFIG; goto bail; } - if ( sampleRateOut > 96000 ) - { + 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->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; + qmfFlags |= QMF_FLAG_MPSLDFB; } else { - qmfFlags |= QMF_FLAG_CLDFB; + qmfFlags |= QMF_FLAG_CLDFB; } } /* Set downsampling factor for synthesis filter bank */ - if (sampleRateOut == 0) - { + if (sampleRateOut == 0) { /* no single rate mode */ - sampleRateOut = sampleRateIn<<1; /* In case of implicit signalling, assume dual rate SBR */ + sampleRateOut = + sampleRateIn + << 1; /* In case of implicit signalling, assume dual rate SBR */ } - if ( sampleRateIn == sampleRateOut ) { + if (sampleRateIn == sampleRateOut) { synDownsampleFac = 2; - self->flags |= SBRDEC_DOWNSAMPLE; + self->flags |= SBRDEC_DOWNSAMPLE; } else { synDownsampleFac = 1; self->flags &= ~SBRDEC_DOWNSAMPLE; @@ -294,20 +329,23 @@ SBR_ERROR sbrDecoder_ResetElement ( self->sampleRateOut = sampleRateOut; { - int i; - - for (i = 0; i < (1)+1; i++) - { + for (i = 0; i < (1) + 1; i++) { + int setDflt; hSbrHeader = &(self->sbrHeader[elementIndex][i]); + setDflt = ((hSbrHeader->syncState == SBR_NOT_INITIALIZED) || + (self->flags & SBRDEC_FORCE_RESET)) + ? 1 + : 0; /* init a default header such that we can at least do upsampling later */ - sbrError = initHeaderData( - hSbrHeader, - sampleRateIn, - sampleRateOut, - samplesPerFrame, - self->flags - ); + sbrError = initHeaderData(hSbrHeader, sampleRateIn, sampleRateOut, + self->downscaleFactor, samplesPerFrame, + self->flags, setDflt); + + /* Set synchState to UPSAMPLING in case it already is initialized */ + hSbrHeader->syncState = hSbrHeader->syncState > UPSAMPLING + ? UPSAMPLING + : hSbrHeader->syncState; } } @@ -315,21 +353,38 @@ SBR_ERROR sbrDecoder_ResetElement ( goto bail; } + if (!self->pQmfDomain->globalConf.qmfDomainExplicitConfig) { + self->pQmfDomain->globalConf.flags_requested |= qmfFlags; + self->pQmfDomain->globalConf.nBandsAnalysis_requested = + self->sbrHeader[elementIndex][0].numberOfAnalysisBands; + self->pQmfDomain->globalConf.nBandsSynthesis_requested = + (synDownsampleFac == 1) ? 64 : 32; /* may be overwritten by MPS */ + self->pQmfDomain->globalConf.nBandsSynthesis_requested /= + self->downscaleFactor; + self->pQmfDomain->globalConf.nQmfTimeSlots_requested = + self->sbrHeader[elementIndex][0].numberTimeSlots * + self->sbrHeader[elementIndex][0].timeStep; + self->pQmfDomain->globalConf.nQmfOvTimeSlots_requested = overlap; + self->pQmfDomain->globalConf.nQmfProcBands_requested = 64; /* always 64 */ + self->pQmfDomain->globalConf.nQmfProcChannels_requested = + 1; /* may be overwritten by MPS */ + } + /* Init SBR channels going to be assigned to a SBR element */ { int ch; + for (ch = 0; ch < self->pSbrElement[elementIndex]->nChannels; ch++) { + int headerIndex = + getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot, + self->pSbrElement[elementIndex]->useHeaderSlot); - 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 ); + sbrError = + createSbrDec(self->pSbrElement[elementIndex]->pSbrChannel[ch], + &self->sbrHeader[elementIndex][headerIndex], + &self->pSbrElement[elementIndex]->transposerSettings, + synDownsampleFac, qmfFlags, self->flags, overlap, ch, + self->codecFrameSize); if (sbrError != SBRDEC_OK) { goto bail; @@ -337,28 +392,29 @@ SBR_ERROR sbrDecoder_ResetElement ( } } - //FDKmemclear(sbr_OverlapBuffer, sizeof(sbr_OverlapBuffer)); + // 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: - if (CreatePsDec ( &self->hParametricStereoDec, samplesPerFrame )) { - sbrError = SBRDEC_CREATE_ERROR; - goto bail; - } - break; - default: - break; + 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++) { + for (i = 0; i < ((1) + 1); i++) { self->pSbrElement[elementIndex]->useHeaderSlot[i] = i; } @@ -367,11 +423,37 @@ bail: return sbrError; } +/*! + \brief Assign QMF domain provided QMF channels to SBR channels. + + \return void +*/ +static void sbrDecoder_AssignQmfChannels2SbrChannels(HANDLE_SBRDECODER self) { + int ch, el, absCh_offset = 0; + for (el = 0; el < self->numSbrElements; el++) { + if (self->pSbrElement[el] != NULL) { + for (ch = 0; ch < self->pSbrElement[el]->nChannels; ch++) { + FDK_ASSERT(((absCh_offset + ch) < ((8) + (1))) && + ((absCh_offset + ch) < ((8) + (1)))); + self->pSbrElement[el]->pSbrChannel[ch]->SbrDec.qmfDomainInCh = + &self->pQmfDomain->QmfDomainIn[absCh_offset + ch]; + self->pSbrElement[el]->pSbrChannel[ch]->SbrDec.qmfDomainOutCh = + &self->pQmfDomain->QmfDomainOut[absCh_offset + ch]; + } + absCh_offset += self->pSbrElement[el]->nChannels; + } + } +} -SBR_ERROR sbrDecoder_Open ( HANDLE_SBRDECODER * pSelf ) -{ - HANDLE_SBRDECODER self = NULL; +SBR_ERROR sbrDecoder_Open(HANDLE_SBRDECODER *pSelf, + HANDLE_FDK_QMF_DOMAIN pQmfDomain) { + HANDLE_SBRDECODER self = NULL; SBR_ERROR sbrError = SBRDEC_OK; + int elIdx; + + if ((pSelf == NULL) || (pQmfDomain == NULL)) { + return SBRDEC_INVALID_ARGUMENT; + } /* Get memory for this instance */ self = GetRam_SbrDecoder(); @@ -380,15 +462,7 @@ SBR_ERROR sbrDecoder_Open ( HANDLE_SBRDECODER * pSelf ) goto bail; } - self->workBuffer1 = GetRam_SbrDecWorkBuffer1(); - self->workBuffer2 = GetRam_SbrDecWorkBuffer2(); - - if ( self->workBuffer1 == NULL - || self->workBuffer2 == NULL ) - { - sbrError = SBRDEC_MEM_ALLOC_FAILED; - goto bail; - } + self->pQmfDomain = pQmfDomain; /* Already zero because of calloc @@ -397,7 +471,15 @@ SBR_ERROR sbrDecoder_Open ( HANDLE_SBRDECODER * pSelf ) self->codecFrameSize = 0; */ - self->numDelayFrames = (1); /* set to the max value by default */ + self->numDelayFrames = (1); /* set to the max value by default */ + + /* Initialize header sync state */ + for (elIdx = 0; elIdx < (8); elIdx += 1) { + int i; + for (i = 0; i < (1) + 1; i += 1) { + self->sbrHeader[elIdx][i].syncState = SBR_NOT_INITIALIZED; + } + } *pSelf = self; @@ -410,9 +492,7 @@ bail: * \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) -{ +static int sbrDecoder_isCoreCodecValid(AUDIO_OBJECT_TYPE coreCodec) { switch (coreCodec) { case AOT_AAC_LC: case AOT_SBR: @@ -420,80 +500,109 @@ int sbrDecoder_isCoreCodecValid(AUDIO_OBJECT_TYPE coreCodec) case AOT_ER_AAC_SCAL: case AOT_ER_AAC_ELD: case AOT_DRM_AAC: + case AOT_DRM_SURROUND: + case AOT_USAC: return 1; default: return 0; } } -static -void sbrDecoder_DestroyElement ( - HANDLE_SBRDECODER self, - const int elementIndex - ) -{ +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++) { + 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] ); + deleteSbrDec(self->pSbrElement[elementIndex]->pSbrChannel[ch]); + FreeRam_SbrDecChannel( + &self->pSbrElement[elementIndex]->pSbrChannel[ch]); self->numSbrChannels -= 1; } } - FreeRam_SbrDecElement( &self->pSbrElement[elementIndex] ); + 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 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, + const UCHAR harmonicSBR, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, const INT downscaleFactor) { SBR_ERROR sbrError = SBRDEC_OK; - int chCnt=0; - int nSbrElementsStart = self->numSbrElements; + int chCnt = 0; + int nSbrElementsStart; + int nSbrChannelsStart; + if (self == NULL) { + return SBRDEC_INVALID_ARGUMENT; + } + + nSbrElementsStart = self->numSbrElements; + nSbrChannelsStart = self->numSbrChannels; /* Check core codec AOT */ - if (! sbrDecoder_isCoreCodecValid(coreCodec) || elementIndex >= (8)) { + if (!sbrDecoder_isCoreCodecValid(coreCodec) || elementIndex >= (8)) { sbrError = SBRDEC_UNSUPPORTED_CONFIG; goto bail; } - if ( elementID != ID_SCE && elementID != ID_CPE && elementID != ID_LFE ) - { + 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 - && !(self->flags & SBRDEC_FORCE_RESET) - ) - { - /* Nothing to do */ - return SBRDEC_OK; + if (self->sampleRateIn == sampleRateIn && + self->codecFrameSize == samplesPerFrame && self->coreCodec == coreCodec && + self->pSbrElement[elementIndex] != NULL && + self->pSbrElement[elementIndex]->elementID == elementID && + !(self->flags & SBRDEC_FORCE_RESET) && + ((sampleRateOut == 0) ? 1 : (self->sampleRateOut == sampleRateOut)) && + ((harmonicSBR == 2) ? 1 + : (self->harmonicSBR == + harmonicSBR)) /* The value 2 signalizes that + harmonicSBR shall be ignored in + the config change detection */ + ) { + /* Nothing to do */ + return SBRDEC_OK; + } else { + if (configMode & AC_CM_DET_CFG_CHANGE) { + *configChanged = 1; + } } - self->sampleRateIn = sampleRateIn; - self->codecFrameSize = samplesPerFrame; - self->coreCodec = coreCodec; + /* reaching this point the SBR-decoder gets (re-)configured */ - self->flags = 0; + /* The flags field is used for all elements! */ + self->flags &= + (SBRDEC_FORCE_RESET | SBRDEC_FLUSH); /* Keep the global flags. They will + be reset after decoding. */ + self->flags |= (downscaleFactor > 1) ? SBRDEC_ELD_DOWNSCALE : 0; self->flags |= (coreCodec == AOT_ER_AAC_ELD) ? SBRDEC_ELD_GRID : 0; self->flags |= (coreCodec == AOT_ER_AAC_SCAL) ? SBRDEC_SYNTAX_SCAL : 0; - self->flags |= (coreCodec == AOT_DRM_AAC) ? SBRDEC_SYNTAX_SCAL|SBRDEC_SYNTAX_DRM : 0; + self->flags |= + (coreCodec == AOT_DRM_AAC) ? SBRDEC_SYNTAX_SCAL | SBRDEC_SYNTAX_DRM : 0; + self->flags |= (coreCodec == AOT_DRM_SURROUND) + ? SBRDEC_SYNTAX_SCAL | SBRDEC_SYNTAX_DRM + : 0; + self->flags |= (coreCodec == AOT_USAC) ? SBRDEC_SYNTAX_USAC : 0; + /* Robustness: Take integer division rounding into consideration. E.g. 22050 + * Hz with 4:1 SBR => 5512 Hz core sampling rate. */ + self->flags |= (sampleRateIn == sampleRateOut / 4) ? SBRDEC_QUAD_RATE : 0; + self->flags |= (harmonicSBR == 1) ? SBRDEC_USAC_HARMONICSBR : 0; + + if (configMode & AC_CM_DET_CFG_CHANGE) { + return SBRDEC_OK; + } + + self->sampleRateIn = sampleRateIn; + self->codecFrameSize = samplesPerFrame; + self->coreCodec = coreCodec; + self->harmonicSBR = harmonicSBR; + self->downscaleFactor = downscaleFactor; /* Init SBR elements */ { @@ -505,34 +614,39 @@ SBR_ERROR sbrDecoder_InitElement ( sbrError = SBRDEC_MEM_ALLOC_FAILED; goto bail; } - self->numSbrElements ++; + self->numSbrElements++; } else { self->numSbrChannels -= self->pSbrElement[elementIndex]->nChannels; } - /* Save element ID for sanity checks and to have a fallback for concealment. */ + /* 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; + case ID_CPE: + elChannels = 2; break; case ID_LFE: - case ID_SCE: elChannels=1; + case ID_SCE: + elChannels = 1; break; - default: elChannels=0; + default: + elChannels = 0; break; } /* Handle case of Parametric Stereo */ - if ( elementIndex == 0 && elementID == ID_SCE ) { + 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: @@ -540,57 +654,76 @@ SBR_ERROR sbrDecoder_InitElement ( } } + /* Sanity check to avoid memory leaks */ + if (elChannels < self->pSbrElement[elementIndex]->nChannels) { + self->numSbrChannels += self->pSbrElement[elementIndex]->nChannels; + sbrError = SBRDEC_PARSE_ERROR; + goto bail; + } + self->pSbrElement[elementIndex]->nChannels = elChannels; - for (ch=0; ch<elChannels; ch++) - { + for (ch = 0; ch < elChannels; ch++) { if (self->pSbrElement[elementIndex]->pSbrChannel[ch] == NULL) { - self->pSbrElement[elementIndex]->pSbrChannel[ch] = GetRam_SbrDecChannel(chCnt); + self->pSbrElement[elementIndex]->pSbrChannel[ch] = + GetRam_SbrDecChannel(chCnt); if (self->pSbrElement[elementIndex]->pSbrChannel[ch] == NULL) { sbrError = SBRDEC_MEM_ALLOC_FAILED; goto bail; } } - self->numSbrChannels ++; + self->numSbrChannels++; - sbrDecoder_drcInitChannel( &self->pSbrElement[elementIndex]->pSbrChannel[ch]->SbrDec.sbrDrcChannel ); + 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)); + if (!self->pQmfDomain->globalConf.qmfDomainExplicitConfig) { + self->pQmfDomain->globalConf.nInputChannels_requested = + self->numSbrChannels; + self->pQmfDomain->globalConf.nOutputChannels_requested = + fMax((INT)self->numSbrChannels, + (INT)self->pQmfDomain->globalConf.nOutputChannels_requested); + } - /* Initialize this instance */ - sbrError = sbrDecoder_ResetElement( - self, - sampleRateIn, - sampleRateOut, - samplesPerFrame, - elementID, - elementIndex, - (coreCodec == AOT_ER_AAC_ELD) ? 0 : (6) - ); + /* Make sure each SBR channel has one QMF channel assigned even if + * numSbrChannels or element set-up has changed. */ + sbrDecoder_AssignQmfChannels2SbrChannels(self); + /* clear error flags for all delay slots */ + FDKmemclear(self->pSbrElement[elementIndex]->frameErrorFlag, + ((1) + 1) * sizeof(UCHAR)); + { + int overlap; + + if (coreCodec == AOT_ER_AAC_ELD) { + overlap = 0; + } else if (self->flags & SBRDEC_QUAD_RATE) { + overlap = (3 * 4); + } else { + overlap = (3 * 2); + } + /* Initialize this instance */ + sbrError = sbrDecoder_ResetElement(self, sampleRateIn, sampleRateOut, + samplesPerFrame, elementID, elementIndex, + overlap); + } bail: if (sbrError != SBRDEC_OK) { - if (nSbrElementsStart < self->numSbrElements) { + if ((nSbrElementsStart < self->numSbrElements) || + (nSbrChannelsStart < self->numSbrChannels)) { /* Free the memory allocated for this element */ - sbrDecoder_DestroyElement( self, elementIndex ); - } else if ( (self->pSbrElement[elementIndex] != NULL) - && (elementIndex < (8))) - { /* Set error flag to trigger concealment */ - self->pSbrElement[elementIndex]->frameErrorFlag[self->pSbrElement[elementIndex]->useFrameSlot] = 1; + sbrDecoder_DestroyElement(self, elementIndex); + } else if ((elementIndex < (8)) && + (self->pSbrElement[elementIndex] != + NULL)) { /* Set error flag to trigger concealment */ + setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_ERROR); } } @@ -598,22 +731,43 @@ bail: } /** + * \brief Free config dependent SBR memory. + * \param self SBR decoder instance handle + */ +SBR_ERROR sbrDecoder_FreeMem(HANDLE_SBRDECODER *self) { + int i; + int elIdx; + + if (self != NULL && *self != NULL) { + for (i = 0; i < (8); i++) { + sbrDecoder_DestroyElement(*self, i); + } + + for (elIdx = 0; elIdx < (8); elIdx += 1) { + for (i = 0; i < (1) + 1; i += 1) { + (*self)->sbrHeader[elIdx][i].syncState = SBR_NOT_INITIALIZED; + } + } + } + + return SBRDEC_OK; +} + +/** * \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 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. + * \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 - ) -{ +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; /* @@ -622,8 +776,14 @@ SBR_ERROR sbrDecoder_HeaderUpdate( errorStatus = resetFreqBandTables(hSbrHeader, self->flags); if (errorStatus == SBRDEC_OK) { - if (hSbrHeader->syncState == UPSAMPLING && headerStatus != HEADER_RESET) - { + if (hSbrHeader->syncState == UPSAMPLING && headerStatus != HEADER_RESET) { +#if (SBRDEC_MAX_HB_FADE_FRAMES > 0) + int ch; + for (ch = 0; ch < numElementChannels; ch += 1) { + hSbrChannel[ch]->SbrDec.highBandFadeCnt = SBRDEC_MAX_HB_FADE_FRAMES; + } + +#endif /* As the default header would limit the frequency range, lowSubband and highSubband must be patched. */ hSbrHeader->freqBandData.lowSubband = hSbrHeader->numberOfAnalysisBands; @@ -637,155 +797,153 @@ SBR_ERROR sbrDecoder_HeaderUpdate( 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 - ) -{ +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, + const UCHAR harmonicSBR, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, + const INT downscaleFactor) { SBR_HEADER_STATUS headerStatus; HANDLE_SBR_HEADER_DATA hSbrHeader; SBR_ERROR sbrError = SBRDEC_OK; int headerIndex; + UINT flagsSaved = + 0; /* flags should not be changed in AC_CM_DET_CFG_CHANGE - mode after + parsing */ - if ( self == NULL || elementIndex > (8) ) - { + if (self == NULL || elementIndex >= (8)) { return SBRDEC_UNSUPPORTED_CONFIG; } - if (! sbrDecoder_isCoreCodecValid(coreCodec)) { + if (!sbrDecoder_isCoreCodecValid(coreCodec)) { return SBRDEC_UNSUPPORTED_CONFIG; } + if (configMode & AC_CM_DET_CFG_CHANGE) { + flagsSaved = self->flags; /* store */ + } + sbrError = sbrDecoder_InitElement( - self, - sampleRateIn, - sampleRateOut, - samplesPerFrame, - coreCodec, - elementID, - elementIndex - ); + self, sampleRateIn, sampleRateOut, samplesPerFrame, coreCodec, elementID, + elementIndex, harmonicSBR, stereoConfigIndex, configMode, configChanged, + downscaleFactor); - if (sbrError != SBRDEC_OK) { + if ((sbrError != SBRDEC_OK) || (elementID == ID_LFE)) { goto bail; } - headerIndex = getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot, - self->pSbrElement[elementIndex]->useHeaderSlot); - hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]); + if (configMode & AC_CM_DET_CFG_CHANGE) { + hSbrHeader = NULL; + } else { + headerIndex = getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot, + self->pSbrElement[elementIndex]->useHeaderSlot); - headerStatus = sbrGetHeaderData ( hSbrHeader, - hBs, - self->flags, - 0); + hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]); + } + headerStatus = sbrGetHeaderData(hSbrHeader, hBs, self->flags, 0, configMode); - { + if (coreCodec == AOT_USAC) { + if (configMode & AC_CM_DET_CFG_CHANGE) { + self->flags = flagsSaved; /* restore */ + } + return sbrError; + } + + if (configMode & AC_CM_ALLOC_MEM) { 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) ) - { + 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 (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; + 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. + Since we already have overwritten the old SBR header the only way out + is UPSAMPLING! This will be prepared in the next step. } */ } } } bail: + if (configMode & AC_CM_DET_CFG_CHANGE) { + self->flags = flagsSaved; /* restore */ + } return sbrError; } - -SBR_ERROR sbrDecoder_SetParam (HANDLE_SBRDECODER self, - const SBRDEC_PARAM param, - const INT value ) -{ +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; + switch (param) { + case SBR_SYSTEM_BITSTREAM_DELAY: + if (value < 0 || value > (1)) { + errorStatus = SBRDEC_SET_PARAM_FAIL; + break; } - } - break; - case SBR_LD_QMF_TIME_ALIGN: - if (self == NULL) { - errorStatus = SBRDEC_NOT_INITIALIZED; - } else { - if (value == 1) { - self->flags |= SBRDEC_LD_MPS_QMF; + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; } else { - self->flags &= ~SBRDEC_LD_MPS_QMF; + self->numDelayFrames = (UCHAR)value; } - } - break; - case SBR_FLUSH_DATA: - if (value != 0) { + break; + case SBR_QMF_MODE: if (self == NULL) { errorStatus = SBRDEC_NOT_INITIALIZED; } else { - self->flags |= SBRDEC_FLUSH; + if (value == 1) { + self->flags |= SBRDEC_LOW_POWER; + } else { + self->flags &= ~SBRDEC_LOW_POWER; + } } - } - break; - case SBR_CLEAR_HISTORY: - if (value != 0) { + break; + case SBR_LD_QMF_TIME_ALIGN: if (self == NULL) { errorStatus = SBRDEC_NOT_INITIALIZED; } else { - self->flags |= SBRDEC_FORCE_RESET; + if (value == 1) { + self->flags |= SBRDEC_LD_MPS_QMF; + } else { + self->flags &= ~SBRDEC_LD_MPS_QMF; + } } - } - break; - case SBR_BS_INTERRUPTION: - { + break; + case SBR_FLUSH_DATA: + if (value != 0) { + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + self->flags |= SBRDEC_FLUSH; + } + } + break; + case SBR_CLEAR_HISTORY: + if (value != 0) { + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + self->flags |= SBRDEC_FORCE_RESET; + } + } + break; + case SBR_BS_INTERRUPTION: { int elementIndex; if (self == NULL) { @@ -794,38 +952,55 @@ SBR_ERROR sbrDecoder_SetParam (HANDLE_SBRDECODER self, } /* Loop over SBR elements */ - for (elementIndex = 0; elementIndex < self->numSbrElements; elementIndex++) { - if (self->pSbrElement[elementIndex] != NULL) - { - HANDLE_SBR_HEADER_DATA hSbrHeader; - int headerIndex = getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot, - self->pSbrElement[elementIndex]->useHeaderSlot); - - hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]); + for (elementIndex = 0; elementIndex < self->numSbrElements; + elementIndex++) { + if (self->pSbrElement[elementIndex] != NULL) { + 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; - /* 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) */ + case SBR_SKIP_QMF: + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + if (value == 1) { + self->flags |= SBRDEC_SKIP_QMF_ANA; + } else { + self->flags &= ~SBRDEC_SKIP_QMF_ANA; + } + if (value == 2) { + self->flags |= SBRDEC_SKIP_QMF_SYN; + } else { + self->flags &= ~SBRDEC_SKIP_QMF_SYN; + } + } + 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 ) -{ +static SBRDEC_DRC_CHANNEL *sbrDecoder_drcGetChannel( + const HANDLE_SBRDECODER self, const INT channel) { SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL; - int elementIndex, elChanIdx=0, numCh=0; + int elementIndex, elChanIdx = 0, numCh = 0; - for (elementIndex = 0; (elementIndex < (8)) && (numCh <= channel); elementIndex++) - { + for (elementIndex = 0; (elementIndex < (8)) && (numCh <= channel); + elementIndex++) { SBR_DECODER_ELEMENT *pSbrElement = self->pSbrElement[elementIndex]; int c, elChannels; @@ -834,18 +1009,21 @@ SBRDEC_DRC_CHANNEL * sbrDecoder_drcGetChannel( const HANDLE_SBRDECODER self, con /* Determine amount of channels for this element */ switch (pSbrElement->elementID) { - case ID_CPE: elChannels = 2; + case ID_CPE: + elChannels = 2; break; case ID_LFE: - case ID_SCE: elChannels = 1; + case ID_SCE: + elChannels = 1; break; case ID_NONE: - default: elChannels = 0; + default: + elChannels = 0; break; } /* Limit with actual allocated element channels */ - elChannels = FDKmin(elChannels, pSbrElement->nChannels); + elChannels = fMin(elChannels, pSbrElement->nChannels); for (c = 0; (c < elChannels) && (numCh <= channel); c++) { if (pSbrElement->pSbrChannel[elChanIdx] != NULL) { @@ -861,25 +1039,22 @@ SBRDEC_DRC_CHANNEL * sbrDecoder_drcGetChannel( const HANDLE_SBRDECODER self, con return NULL; } - if ( self->pSbrElement[elementIndex] != NULL ) { - if ( self->pSbrElement[elementIndex]->pSbrChannel[elChanIdx] != NULL ) - { - pSbrDrcChannelData = &self->pSbrElement[elementIndex]->pSbrChannel[elChanIdx]->SbrDec.sbrDrcChannel; + 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 ) -{ +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; @@ -891,138 +1066,136 @@ SBR_ERROR sbrDecoder_drcFeedChannel ( HANDLE_SBRDECODER self, } /* 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)) ) { + for (band = 0; band < (int)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 ); + pSbrDrcChannelData = sbrDecoder_drcGetChannel(self, ch); - if ( pSbrDrcChannelData != NULL ) { - if ( pSbrDrcChannelData->enable || isValidData ) - { /* Activate processing only with real and valid data */ - int i; + if (pSbrDrcChannelData != NULL) { + if (pSbrDrcChannelData->enable || + isValidData) { /* Activate processing only with real and valid data */ + int i; - pSbrDrcChannelData->enable = 1; - pSbrDrcChannelData->numBandsNext = numBands; + pSbrDrcChannelData->enable = 1; + pSbrDrcChannelData->numBandsNext = numBands; - pSbrDrcChannelData->winSequenceNext = winSequence; - pSbrDrcChannelData->drcInterpolationSchemeNext = drcInterpolationScheme; - pSbrDrcChannelData->nextFact_exp = nextFact_exp; + 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]; + 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 ) -{ +void sbrDecoder_drcDisable(HANDLE_SBRDECODER self, INT ch) { SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL; - if ( (self == NULL) - || (ch > (8)) - || (self->numSbrElements == 0) - || (self->numSbrChannels == 0) ) { + if ((self == NULL) || (ch > (8)) || (self->numSbrElements == 0) || + (self->numSbrChannels == 0)) { return; } /* Find the right SBR channel */ - pSbrDrcChannelData = sbrDecoder_drcGetChannel( self, ch ); + pSbrDrcChannelData = sbrDecoder_drcGetChannel(self, ch); - if ( pSbrDrcChannelData != NULL ) { - sbrDecoder_drcInitChannel( pSbrDrcChannelData ); + 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; +SBR_ERROR sbrDecoder_Parse(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs, + UCHAR *pDrmBsBuffer, USHORT drmBsBufferSize, + int *count, int bsPayLen, int crcFlag, + MP4_ELEMENT_ID prevElement, int elementIndex, + UINT acFlags, UINT acElFlags[]) { + SBR_DECODER_ELEMENT *hSbrElement = NULL; HANDLE_SBR_HEADER_DATA hSbrHeader = NULL; - HANDLE_SBR_CHANNEL *pSbrChannel; + HANDLE_SBR_CHANNEL *pSbrChannel; - SBR_FRAME_DATA *hFrameDataLeft; - SBR_FRAME_DATA *hFrameDataRight; + SBR_FRAME_DATA *hFrameDataLeft = NULL; + SBR_FRAME_DATA *hFrameDataRight = NULL; + SBR_FRAME_DATA frameDataLeftCopy; + SBR_FRAME_DATA frameDataRightCopy; SBR_ERROR errorStatus = SBRDEC_OK; SBR_HEADER_STATUS headerStatus = HEADER_NOT_PRESENT; - INT startPos; - INT CRCLen = 0; + INT startPos = FDKgetValidBits(hBs); + INT CRCLen = 0; HANDLE_FDK_BITSTREAM hBsOriginal = hBs; - FDK_CRCINFO crcInfo; /* shall be used for all other CRCs in the future (TBD) */ - INT crcReg = 0; - USHORT drmSbrCrc = 0; + FDK_BITSTREAM bsBwd; - int stereo; - int fDoDecodeSbrData = 1; + FDK_CRCINFO crcInfo; + INT crcReg = 0; + USHORT drmSbrCrc = 0; + const int fGlobalIndependencyFlag = acFlags & AC_INDEP; + const int bs_pvc = acElFlags[elementIndex] & AC_EL_USAC_PVC; + const int bs_interTes = acElFlags[elementIndex] & AC_EL_USAC_ITES; + int stereo; + int fDoDecodeSbrData = 1; - int lastSlot, lastHdrSlot = 0, thisHdrSlot; + int lastSlot, lastHdrSlot = 0, thisHdrSlot = 0; + + /* SBR sanity checks */ + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + goto bail; + } /* Reverse bits of DRM SBR payload */ - if ( (self->flags & SBRDEC_SYNTAX_DRM) && *count > 0 ) - { - UCHAR *bsBufferDrm = (UCHAR*)self->workBuffer1; - HANDLE_FDK_BITSTREAM hBsBwd = (HANDLE_FDK_BITSTREAM) (bsBufferDrm + (512)); + if ((self->flags & SBRDEC_SYNTAX_DRM) && *count > 0) { int dataBytes, dataBits; + FDK_ASSERT(drmBsBufferSize >= (512)); dataBits = *count; - if (dataBits > ((512)*8)) { + if (dataBits > ((512) * 8)) { /* do not flip more data than needed */ - dataBits = (512)*8; + dataBits = (512) * 8; } - dataBytes = (dataBits+7)>>3; + dataBytes = (dataBits + 7) >> 3; int j; if ((j = (int)FDKgetValidBits(hBs)) != 8) { - FDKpushBiDirectional(hBs, (j-8)); + FDKpushBiDirectional(hBs, (j - 8)); } j = 0; - for ( ; dataBytes > 0; dataBytes--) - { + for (; dataBytes > 0; dataBytes--) { int i; UCHAR tmpByte; UCHAR buffer = 0x00; - tmpByte = (UCHAR) FDKreadBits(hBs, 8); + tmpByte = (UCHAR)FDKreadBits(hBs, 8); for (i = 0; i < 4; i++) { int shift = 2 * i + 1; - buffer |= (tmpByte & (0x08>>i)) << shift; - buffer |= (tmpByte & (0x10<<i)) >> shift; + buffer |= (tmpByte & (0x08 >> i)) << shift; + buffer |= (tmpByte & (0x10 << i)) >> shift; } - bsBufferDrm[j++] = buffer; + pDrmBsBuffer[j++] = buffer; FDKpushBack(hBs, 16); } - FDKinitBitStream(hBsBwd, bsBufferDrm, (512), dataBits, BS_READER); + FDKinitBitStream(&bsBwd, pDrmBsBuffer, (512), dataBits, BS_READER); /* Use reversed data */ - hBs = hBsBwd; + hBs = &bsBwd; bsPayLen = *count; } @@ -1030,16 +1203,19 @@ SBR_ERROR sbrDecoder_Parse( startPos = FDKgetValidBits(hBs); /* SBR sanity checks */ - if ( self == NULL || self->pSbrElement[elementIndex] == NULL ) { + if (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. */ + 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]; @@ -1047,9 +1223,20 @@ SBR_ERROR sbrDecoder_Parse( 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]; + hFrameDataLeft = &self->pSbrElement[elementIndex] + ->pSbrChannel[0] + ->frameData[hSbrElement->useFrameSlot]; + if (stereo) { + hFrameDataRight = &self->pSbrElement[elementIndex] + ->pSbrChannel[1] + ->frameData[hSbrElement->useFrameSlot]; + } + /* store frameData; new parsed frameData possibly corrupted */ + FDKmemcpy(&frameDataLeftCopy, hFrameDataLeft, sizeof(SBR_FRAME_DATA)); + if (stereo) { + FDKmemcpy(&frameDataRightCopy, hFrameDataRight, sizeof(SBR_FRAME_DATA)); + } /* reset PS flag; will be set after PS was found */ self->flags &= ~SBRDEC_PS_DECODED; @@ -1058,23 +1245,23 @@ SBR_ERROR sbrDecoder_Parse( /* Got a new header from extern (e.g. from an ASC) */ headerStatus = HEADER_OK; hSbrHeader->status &= ~SBRDEC_HDR_STAT_UPDATE; - } - else if (thisHdrSlot != lastHdrSlot) { + } 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] ); + 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) */ + 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 (fDoDecodeSbrData) { if ((INT)FDKgetValidBits(hBs) <= 0) { fDoDecodeSbrData = 0; } @@ -1083,29 +1270,29 @@ SBR_ERROR sbrDecoder_Parse( /* SBR CRC-check */ - if (fDoDecodeSbrData) - { + if (fDoDecodeSbrData) { if (crcFlag) { switch (self->coreCodec) { - case AOT_ER_AAC_ELD: - FDKpushFor (hBs, 10); - /* check sbrcrc later: we don't know the payload length now */ - break; - case AOT_DRM_AAC: - drmSbrCrc = (USHORT)FDKreadBits(hBs, 8); - /* Setup CRC decoder */ - FDKcrcInit(&crcInfo, 0x001d, 0xFFFF, 8); - /* Start CRC region */ - crcReg = FDKcrcStartReg(&crcInfo, hBs, 0); - break; - default: - CRCLen = bsPayLen - 10; /* change: 0 => i */ - if (CRCLen < 0) { - fDoDecodeSbrData = 0; - } else { - fDoDecodeSbrData = SbrCrcCheck (hBs, CRCLen); - } - break; + case AOT_ER_AAC_ELD: + FDKpushFor(hBs, 10); + /* check sbrcrc later: we don't know the payload length now */ + break; + case AOT_DRM_AAC: + case AOT_DRM_SURROUND: + drmSbrCrc = (USHORT)FDKreadBits(hBs, 8); + /* Setup CRC decoder */ + FDKcrcInit(&crcInfo, 0x001d, 0xFFFF, 8); + /* Start CRC region */ + crcReg = FDKcrcStartReg(&crcInfo, hBs, 0); + break; + default: + CRCLen = bsPayLen - 10; /* change: 0 => i */ + if (CRCLen < 0) { + fDoDecodeSbrData = 0; + } else { + fDoDecodeSbrData = SbrCrcCheck(hBs, CRCLen); + } + break; } } } /* if (fDoDecodeSbrData) */ @@ -1113,30 +1300,106 @@ SBR_ERROR sbrDecoder_Parse( /* Read in the header data and issue a reset if change occured */ - if (fDoDecodeSbrData) - { + if (fDoDecodeSbrData) { int sbrHeaderPresent; - { + if (self->flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC)) { + SBR_HEADER_DATA_BS_INFO newSbrInfo; + int sbrInfoPresent; + + if (bs_interTes) { + self->flags |= SBRDEC_USAC_ITES; + } else { + self->flags &= ~SBRDEC_USAC_ITES; + } + + if (fGlobalIndependencyFlag) { + self->flags |= SBRDEC_USAC_INDEP; + sbrInfoPresent = 1; + sbrHeaderPresent = 1; + } else { + self->flags &= ~SBRDEC_USAC_INDEP; + sbrInfoPresent = FDKreadBit(hBs); + if (sbrInfoPresent) { + sbrHeaderPresent = FDKreadBit(hBs); + } else { + sbrHeaderPresent = 0; + } + } + + if (sbrInfoPresent) { + newSbrInfo.ampResolution = FDKreadBit(hBs); + newSbrInfo.xover_band = FDKreadBits(hBs, 4); + newSbrInfo.sbr_preprocessing = FDKreadBit(hBs); + if (bs_pvc) { + newSbrInfo.pvc_mode = FDKreadBits(hBs, 2); + /* bs_pvc_mode: 0 -> no PVC, 1 -> PVC mode 1, 2 -> PVC mode 2, 3 -> + * reserved */ + if (newSbrInfo.pvc_mode > 2) { + headerStatus = HEADER_ERROR; + } + if (stereo && newSbrInfo.pvc_mode > 0) { + /* bs_pvc is always transmitted but pvc_mode is set to zero in case + * of stereo SBR. The config might be wrong but we cannot tell for + * sure. */ + newSbrInfo.pvc_mode = 0; + } + } else { + newSbrInfo.pvc_mode = 0; + } + if (headerStatus != HEADER_ERROR) { + if (FDKmemcmp(&hSbrHeader->bs_info, &newSbrInfo, + sizeof(SBR_HEADER_DATA_BS_INFO))) { + /* in case of ampResolution and preprocessing change no full reset + * required */ + /* HEADER reset would trigger HBE transposer reset which breaks + * eSbr_3_Eaa.mp4 */ + if ((hSbrHeader->bs_info.pvc_mode != newSbrInfo.pvc_mode) || + (hSbrHeader->bs_info.xover_band != newSbrInfo.xover_band)) { + headerStatus = HEADER_RESET; + } else { + headerStatus = HEADER_OK; + } + + hSbrHeader->bs_info = newSbrInfo; + } else { + headerStatus = HEADER_OK; + } + } + } + if (headerStatus == HEADER_ERROR) { + /* Corrupt SBR info data, do not decode and switch to UPSAMPLING */ + hSbrHeader->syncState = UPSAMPLING; + fDoDecodeSbrData = 0; + sbrHeaderPresent = 0; + } + + if (sbrHeaderPresent && fDoDecodeSbrData) { + int useDfltHeader; + + useDfltHeader = FDKreadBit(hBs); + + if (useDfltHeader) { + sbrHeaderPresent = 0; + if (FDKmemcmp(&hSbrHeader->bs_data, &hSbrHeader->bs_dflt, + sizeof(SBR_HEADER_DATA_BS)) || + hSbrHeader->syncState != SBR_ACTIVE) { + hSbrHeader->bs_data = hSbrHeader->bs_dflt; + headerStatus = HEADER_RESET; + } + } + } + } else { sbrHeaderPresent = FDKreadBit(hBs); } - if ( sbrHeaderPresent ) { - headerStatus = sbrGetHeaderData (hSbrHeader, - hBs, - self->flags, - 1); + if (sbrHeaderPresent) { + headerStatus = sbrGetHeaderData(hSbrHeader, hBs, self->flags, 1, 0); } - if (headerStatus == HEADER_RESET) - { + if (headerStatus == HEADER_RESET) { errorStatus = sbrDecoder_HeaderUpdate( - self, - hSbrHeader, - headerStatus, - pSbrChannel, - hSbrElement->nChannels - ); + self, hSbrHeader, headerStatus, pSbrChannel, hSbrElement->nChannels); if (errorStatus == SBRDEC_OK) { hSbrHeader->syncState = SBR_HEADER; @@ -1159,31 +1422,22 @@ SBR_ERROR sbrDecoder_Parse( 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 (!stereo && (self->hParametricStereoDec != NULL)) { + /* update slot index for PS bitstream parsing */ + self->hParametricStereoDec->bsLastSlot = + self->hParametricStereoDec->bsReadSlot; + self->hParametricStereoDec->bsReadSlot = hSbrElement->useFrameSlot; } + sbrFrameOk = sbrGetChannelElement( + hSbrHeader, hFrameDataLeft, (stereo) ? hFrameDataRight : NULL, + &pSbrChannel[0]->prevFrameData, + pSbrChannel[0]->SbrDec.PvcStaticData.pvc_mode_last, hBs, + (stereo) ? NULL : self->hParametricStereoDec, self->flags, + self->pSbrElement[elementIndex]->transposerSettings.overlap); + if (!sbrFrameOk) { fDoDecodeSbrData = 0; - } - else { + } else { INT valBits; if (bsPayLen > 0) { @@ -1192,28 +1446,32 @@ SBR_ERROR sbrDecoder_Parse( valBits = (INT)FDKgetValidBits(hBs); } - if ( crcFlag ) { + if (crcFlag) { switch (self->coreCodec) { - case AOT_ER_AAC_ELD: - { + case AOT_ER_AAC_ELD: { /* late crc check for eld */ - INT payloadbits = (INT)startPos - (INT)FDKgetValidBits(hBs) - startPos; - INT crcLen = payloadbits - 10; + INT payloadbits = + (INT)startPos - (INT)FDKgetValidBits(hBs) - startPos; + INT crcLen = payloadbits - 10; FDKpushBack(hBs, payloadbits); - fDoDecodeSbrData = SbrCrcCheck (hBs, crcLen); + fDoDecodeSbrData = SbrCrcCheck(hBs, crcLen); FDKpushFor(hBs, crcLen); - } - break; - case AOT_DRM_AAC: - /* End CRC region */ - FDKcrcEndReg(&crcInfo, hBs, crcReg); - /* Check CRC */ - if ((FDKcrcGetCRC(&crcInfo)^0xFF) != drmSbrCrc) { - fDoDecodeSbrData = 0; - } - break; - default: - break; + } break; + case AOT_DRM_AAC: + case AOT_DRM_SURROUND: + /* End CRC region */ + FDKcrcEndReg(&crcInfo, hBs, crcReg); + /* Check CRC */ + if ((FDKcrcGetCRC(&crcInfo) ^ 0xFF) != drmSbrCrc) { + fDoDecodeSbrData = 0; + if (headerStatus != HEADER_NOT_PRESENT) { + headerStatus = HEADER_ERROR; + hSbrHeader->syncState = SBR_NOT_INITIALIZED; + } + } + break; + default: + break; } } @@ -1222,37 +1480,42 @@ SBR_ERROR sbrDecoder_Parse( 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 */ + 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; + } break; + default: + /* No sanity check available */ + break; } } } } else { - /* The returned bit count will not be the actual payload size since we did not - parse the frame data. Return an error so that the caller can react respectively. */ + /* The returned bit count will not be the actual payload size since we did + not parse the frame data. Return an error so that the caller can react + respectively. */ errorStatus = SBRDEC_PARSE_ERROR; } if (!fDoDecodeSbrData) { /* Set error flag for this slot to trigger concealment */ - self->pSbrElement[elementIndex]->frameErrorFlag[hSbrElement->useFrameSlot] = 1; + setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_ERROR); + /* restore old frameData for concealment */ + FDKmemcpy(hFrameDataLeft, &frameDataLeftCopy, sizeof(SBR_FRAME_DATA)); + if (stereo) { + FDKmemcpy(hFrameDataRight, &frameDataRightCopy, sizeof(SBR_FRAME_DATA)); + } errorStatus = SBRDEC_PARSE_ERROR; } else { /* Everything seems to be ok so clear the error flag */ - self->pSbrElement[elementIndex]->frameErrorFlag[hSbrElement->useFrameSlot] = 0; + setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_OK); } if (!stereo) { @@ -1263,116 +1526,138 @@ SBR_ERROR sbrDecoder_Parse( bail: - if ( self->flags & SBRDEC_SYNTAX_DRM ) - { - hBs = hBsOriginal; - } + if (self != NULL) { + if (self->flags & SBRDEC_SYNTAX_DRM) { + hBs = hBsOriginal; + } - if ( (errorStatus == SBRDEC_OK) - || ( (errorStatus == SBRDEC_PARSE_ERROR) - && (headerStatus != HEADER_ERROR) ) ) - { - int useOldHdr = ( (headerStatus == HEADER_NOT_PRESENT) - || (headerStatus == HEADER_ERROR) ) ? 1 : 0; + if (errorStatus != SBRDEC_NOT_INITIALIZED) { + int useOldHdr = + ((headerStatus == HEADER_NOT_PRESENT) || + (headerStatus == HEADER_ERROR) || + (headerStatus == HEADER_RESET && errorStatus == SBRDEC_PARSE_ERROR)) + ? 1 + : 0; + + if (!useOldHdr && (thisHdrSlot != lastHdrSlot) && (hSbrHeader != NULL)) { + useOldHdr |= + (compareSbrHeader(hSbrHeader, + &self->sbrHeader[elementIndex][lastHdrSlot]) == 0) + ? 1 + : 0; + } - if (!useOldHdr && (thisHdrSlot != lastHdrSlot)) { - useOldHdr |= ( compareSbrHeader( hSbrHeader, - &self->sbrHeader[elementIndex][lastHdrSlot] ) == 0 ) ? 1 : 0; - } + if (hSbrElement != NULL) { + if (useOldHdr != 0) { + /* 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; + } - if (useOldHdr != 0) { - /* 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); + } } - - /* 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); + *count -= startPos - (INT)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 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 numInChannels number of channels from core coder. + * \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 - ) -{ +static SBR_ERROR sbrDecoder_DecodeElement( + HANDLE_SBRDECODER self, QDOM_PCM *input, INT_PCM *timeData, + const int timeDataSize, const FDK_channelMapDescr *const mapDescr, + const int mapIdx, int channelIndex, 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_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_FRAME_DATA *hFrameDataLeft = NULL; + SBR_FRAME_DATA *hFrameDataRight = NULL; SBR_ERROR errorStatus = SBRDEC_OK; + INT strideOut, offset0 = 255, offset0_block = 0, offset1 = 255, + offset1_block = 0; + INT codecFrameSize = self->codecFrameSize; - 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 */ - int stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0; - int numElementChannels = hSbrElement->nChannels; /* Number of channels of the current SBR element */ + hFrameDataLeft = + &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; + if (stereo) { + hFrameDataRight = + &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot]; + } if (self->flags & SBRDEC_FLUSH) { - if ( self->numFlushedFrames > self->numDelayFrames ) { + if (self->numFlushedFrames > self->numDelayFrames) { int hdrIdx; - /* No valid SBR payload available, hence switch to upsampling (in all headers) */ - for (hdrIdx = 0; hdrIdx < ((1)+1); hdrIdx += 1) { + /* No valid SBR payload available, hence switch to upsampling (in all + * headers) */ + for (hdrIdx = 0; hdrIdx < ((1) + 1); hdrIdx += 1) { self->sbrHeader[elementIndex][hdrIdx].syncState = UPSAMPLING; } - } - else { - /* Move frame pointer to the next slot which is up to be decoded/applied next */ - hSbrElement->useFrameSlot = (hSbrElement->useFrameSlot+1) % (self->numDelayFrames+1); - /* Update header and frame data pointer because they have already been set */ - hSbrHeader = &self->sbrHeader[elementIndex][hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]]; - hFrameDataLeft = &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; - hFrameDataRight = &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot]; + } else { + /* Move frame pointer to the next slot which is up to be decoded/applied + * next */ + hSbrElement->useFrameSlot = + (hSbrElement->useFrameSlot + 1) % (self->numDelayFrames + 1); + /* Update header and frame data pointer because they have already been set + */ + hSbrHeader = + &self->sbrHeader[elementIndex] + [hSbrElement + ->useHeaderSlot[hSbrElement->useFrameSlot]]; + hFrameDataLeft = + &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; + if (stereo) { + hFrameDataRight = + &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot]; + } } } /* Update the header error flag */ - hSbrHeader->frameErrorFlag = hSbrElement->frameErrorFlag[hSbrElement->useFrameSlot]; + 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 (hSbrHeader->syncState == SBR_NOT_INITIALIZED) { + errorStatus = + initHeaderData(hSbrHeader, self->sampleRateIn, self->sampleRateOut, + self->downscaleFactor, codecFrameSize, self->flags, + 1 /* SET_DEFAULT_HDR */ + ); if (errorStatus != SBRDEC_OK) { return errorStatus; @@ -1380,13 +1665,8 @@ sbrDecoder_DecodeElement ( hSbrHeader->syncState = UPSAMPLING; - errorStatus = sbrDecoder_HeaderUpdate( - self, - hSbrHeader, - HEADER_NOT_PRESENT, - pSbrChannel, - hSbrElement->nChannels - ); + errorStatus = sbrDecoder_HeaderUpdate(self, hSbrHeader, HEADER_NOT_PRESENT, + pSbrChannel, hSbrElement->nChannels); if (errorStatus != SBRDEC_OK) { hSbrHeader->syncState = SBR_NOT_INITIALIZED; @@ -1397,170 +1677,163 @@ sbrDecoder_DecodeElement ( /* reset */ if (hSbrHeader->status & SBRDEC_HDR_STAT_RESET) { int ch; - for (ch = 0 ; ch < numElementChannels; 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 - ); + errorStatusTmp = resetSbrDec( + &pSbrChannel[ch]->SbrDec, hSbrHeader, &pSbrChannel[ch]->prevFrameData, + self->synDownsampleFac, self->flags, pSbrChannel[ch]->frameData); if (errorStatusTmp != SBRDEC_OK) { - errorStatus = errorStatusTmp; + hSbrHeader->syncState = UPSAMPLING; } } hSbrHeader->status &= ~SBRDEC_HDR_STAT_RESET; } /* decoding */ - if ( (hSbrHeader->syncState == SBR_ACTIVE) - || ((hSbrHeader->syncState == SBR_HEADER) && (hSbrHeader->frameErrorFlag == 0)) ) - { + 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); - + 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; + if (timeDataSize < + hSbrHeader->numberTimeSlots * hSbrHeader->timeStep * + self->pQmfDomain->globalConf.nBandsSynthesis * + (psPossible ? fMax(2, numInChannels) : numInChannels)) { + return SBRDEC_OUTPUT_BUFFER_TOO_SMALL; + } - /* define which frame delay line slot to process */ - h_ps_d->processSlot = hSbrElement->useFrameSlot; + { + self->flags &= ~SBRDEC_PS_DECODED; + C_ALLOC_SCRATCH_START(pPsScratch, struct PS_DEC_COEFFICIENTS, 1) - applyPs = DecodePs(h_ps_d, hSbrHeader->frameErrorFlag); - self->flags |= (applyPs) ? SBRDEC_PS_DECODED : 0; - } + /* decode PS data if available */ + if (h_ps_d != NULL && psPossible && (hSbrHeader->syncState == SBR_ACTIVE)) { + int applyPs = 1; + + /* define which frame delay line slot to process */ + h_ps_d->processSlot = hSbrElement->useFrameSlot; + + applyPs = DecodePs(h_ps_d, hSbrHeader->frameErrorFlag, pPsScratch); + self->flags |= (applyPs) ? SBRDEC_PS_DECODED : 0; + } - /* Set strides for reading and writing */ - if (interleaved) { - strideIn = numInChannels; - if ( psPossible ) + offset0 = FDK_chMapDescr_getMapValue(mapDescr, channelIndex, mapIdx); + offset0_block = offset0 * codecFrameSize; + if (stereo || psPossible) { + /* the value of offset1 only matters if the condition is true, however if + it is not true channelIndex+1 may exceed the channel map resutling in an + error, though the value of offset1 is actually meaningless. This is + prevented here. */ + offset1 = FDK_chMapDescr_getMapValue(mapDescr, channelIndex + 1, mapIdx); + offset1_block = offset1 * codecFrameSize; + } + /* Set strides for reading and writing */ + 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, - codecFrameSize - ); - 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, - codecFrameSize - ); + /* use same buffers for left and right channel and apply PS per timeslot */ + /* Process left channel */ + sbr_dec(&pSbrChannel[0]->SbrDec, input + offset0_block, timeData + offset0, + (self->flags & SBRDEC_PS_DECODED) ? &pSbrChannel[1]->SbrDec : NULL, + timeData + offset1, strideOut, hSbrHeader, hFrameDataLeft, + &pSbrChannel[0]->prevFrameData, + (hSbrHeader->syncState == SBR_ACTIVE), h_ps_d, self->flags, + codecFrameSize); + + if (stereo) { + /* Process right channel */ + sbr_dec(&pSbrChannel[1]->SbrDec, input + offset1_block, + timeData + offset1, NULL, NULL, strideOut, hSbrHeader, + hFrameDataRight, &pSbrChannel[1]->prevFrameData, + (hSbrHeader->syncState == SBR_ACTIVE), NULL, self->flags, + codecFrameSize); + } + + C_ALLOC_SCRATCH_END(pPsScratch, struct PS_DEC_COEFFICIENTS, 1) } if (h_ps_d != NULL) { /* save PS status for next run */ - h_ps_d->psDecodedPrv = (self->flags & SBRDEC_PS_DECODED) ? 1 : 0 ; + h_ps_d->psDecodedPrv = (self->flags & SBRDEC_PS_DECODED) ? 1 : 0; } - if ( psPossible - ) - { + if (psPossible && !(self->flags & SBRDEC_SKIP_QMF_SYN)) { 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. */ - int copyFrameSize = codecFrameSize * 2 / self->synDownsampleFac; - if (interleaved) { - INT_PCM *ptr; - INT i; - FDK_ASSERT(strideOut == 2); - - ptr = timeData; - for (i = copyFrameSize>>1; 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+copyFrameSize, timeData, copyFrameSize*sizeof(INT_PCM) ); + 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 available. */ + /* So copy left channel to right channel. */ + int copyFrameSize = + codecFrameSize * self->pQmfDomain->QmfDomainOut->fb.no_channels; + copyFrameSize /= self->pQmfDomain->QmfDomainIn->fb.no_channels; + INT_PCM *ptr; + INT i; + FDK_ASSERT(strideOut == 2); + + ptr = timeData; + for (i = copyFrameSize >> 1; 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; } } - *numOutChannels = 2; /* Output minimum two channels when PS is enabled. */ + *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[(8)], - const int interleaved, - const int coreDecodedOk, - UCHAR *psDecoded ) -{ +SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, INT_PCM *input, + INT_PCM *timeData, const int timeDataSize, + int *numChannels, int *sampleRate, + const FDK_channelMapDescr *const mapDescr, + const int mapIdx, const int coreDecodedOk, + UCHAR *psDecoded) { SBR_ERROR errorStatus = SBRDEC_OK; - int psPossible = 0; - int sbrElementNum; - int numCoreChannels = *numChannels; - int numSbrChannels = 0; + int psPossible; + int sbrElementNum; + int numCoreChannels; + int numSbrChannels = 0; + + if ((self == NULL) || (timeData == NULL) || (numChannels == NULL) || + (sampleRate == NULL) || (psDecoded == NULL) || + !FDK_chMapDescr_isValid(mapDescr)) { + return SBRDEC_INVALID_ARGUMENT; + } psPossible = *psDecoded; + numCoreChannels = *numChannels; + if (numCoreChannels <= 0) { + return SBRDEC_INVALID_ARGUMENT; + } if (self->numSbrElements < 1) { /* exit immediately to avoid access violations */ - return SBRDEC_CREATE_ERROR; + return SBRDEC_NOT_INITIALIZED; } /* Sanity check of allocated SBR elements. */ - for (sbrElementNum=0; sbrElementNum<self->numSbrElements; sbrElementNum++) { + for (sbrElementNum = 0; sbrElementNum < self->numSbrElements; + sbrElementNum++) { if (self->pSbrElement[sbrElementNum] == NULL) { - return SBRDEC_CREATE_ERROR; + return SBRDEC_NOT_INITIALIZED; } } @@ -1568,69 +1841,68 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self, psPossible = 0; } + /* 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; + } - /* 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)); + /* replaces channel based reset inside sbr_dec() */ + if (((self->flags & SBRDEC_LOW_POWER) ? 1 : 0) != + ((self->pQmfDomain->globalConf.flags & QMF_FLAG_LP) ? 1 : 0)) { + if (self->flags & SBRDEC_LOW_POWER) { + self->pQmfDomain->globalConf.flags |= QMF_FLAG_LP; + self->pQmfDomain->globalConf.flags_requested |= QMF_FLAG_LP; + } else { + self->pQmfDomain->globalConf.flags &= ~QMF_FLAG_LP; + self->pQmfDomain->globalConf.flags_requested &= ~QMF_FLAG_LP; + } + if (FDK_QmfDomain_InitFilterBank(self->pQmfDomain, QMF_FLAG_KEEP_STATES)) { + return SBRDEC_UNSUPPORTED_CONFIG; } } - - - /* 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; + if (self->numSbrChannels > self->pQmfDomain->globalConf.nInputChannels) { + return SBRDEC_UNSUPPORTED_CONFIG; } - if ( self->flags & SBRDEC_FLUSH ) { + if (self->flags & SBRDEC_FLUSH) { /* flushing is signalized, hence increment the flush frame counter */ self->numFlushedFrames++; - } - else { + } else { /* no flushing is signalized, hence reset the flush frame counter */ self->numFlushedFrames = 0; } /* Loop over SBR elements */ - for (sbrElementNum = 0; sbrElementNum<self->numSbrElements; sbrElementNum++) - { + for (sbrElementNum = 0; sbrElementNum < self->numSbrElements; + sbrElementNum++) { int numElementChan; - if (psPossible && self->pSbrElement[sbrElementNum]->pSbrChannel[1] == NULL) { + if (psPossible && + self->pSbrElement[sbrElementNum]->pSbrChannel[1] == NULL) { /* Disable PS and try decoding SBR mono. */ psPossible = 0; } - numElementChan = (self->pSbrElement[sbrElementNum]->elementID == ID_CPE) ? 2 : 1; + 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; + if (!coreDecodedOk) { + setFrameErrorFlag(self->pSbrElement[sbrElementNum], FRAME_ERROR_ALLSLOTS); } - errorStatus = sbrDecoder_DecodeElement ( - self, - timeData, - interleaved, - channelMapping, - sbrElementNum, - numCoreChannels, - &numElementChan, - psPossible - ); + errorStatus = sbrDecoder_DecodeElement( + self, input, timeData, timeDataSize, mapDescr, mapIdx, numSbrChannels, + sbrElementNum, + numCoreChannels, /* is correct even for USC SCI==2 case */ + &numElementChan, psPossible); if (errorStatus != SBRDEC_OK) { goto bail; } numSbrChannels += numElementChan; - channelMapping += numElementChan; if (numSbrChannels >= numCoreChannels) { break; @@ -1638,13 +1910,16 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self, } /* Update numChannels and samplerate */ - *numChannels = numSbrChannels; + /* Do not mess with output channels in case of USAC. numSbrChannels != + * numChannels for stereoConfigIndex == 2 */ + if (!(self->flags & SBRDEC_SYNTAX_USAC)) { + *numChannels = numSbrChannels; + } *sampleRate = self->sampleRateOut; *psDecoded = (self->flags & SBRDEC_PS_DECODED) ? 1 : 0; - - - /* Clear reset and flush flag because everything seems to be done successfully. */ + /* Clear reset and flush flag because everything seems to be done + * successfully. */ self->flags &= ~SBRDEC_FORCE_RESET; self->flags &= ~SBRDEC_FLUSH; @@ -1653,27 +1928,17 @@ bail: return errorStatus; } - -SBR_ERROR sbrDecoder_Close ( HANDLE_SBRDECODER *pSelf ) -{ +SBR_ERROR sbrDecoder_Close(HANDLE_SBRDECODER *pSelf) { HANDLE_SBRDECODER self = *pSelf; int i; - if (self != NULL) - { + 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); + DeletePsDec(&self->hParametricStereoDec); } for (i = 0; i < (8); i++) { - sbrDecoder_DestroyElement( self, i ); + sbrDecoder_DestroyElement(self, i); } FreeRam_SbrDecoder(pSelf); @@ -1682,9 +1947,7 @@ SBR_ERROR sbrDecoder_Close ( HANDLE_SBRDECODER *pSelf ) return SBRDEC_OK; } - -INT sbrDecoder_GetLibInfo( LIB_INFO *info ) -{ +INT sbrDecoder_GetLibInfo(LIB_INFO *info) { int i; if (info == NULL) { @@ -1693,62 +1956,55 @@ INT sbrDecoder_GetLibInfo( LIB_INFO *info ) /* search for next free tab */ for (i = 0; i < FDK_MODULE_LAST; i++) { - if (info[i].module_id == FDK_NONE) - break; + if (info[i].module_id == FDK_NONE) break; } - if (i == FDK_MODULE_LAST) - return -1; + 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); + 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; + info->build_date = SBRDECODER_LIB_BUILD_DATE; + info->build_time = SBRDECODER_LIB_BUILD_TIME; + info->title = SBRDECODER_LIB_TITLE; /* Set flags */ - info->flags = 0 - | CAPF_SBR_HQ - | CAPF_SBR_LP - | CAPF_SBR_PS_MPEG - | CAPF_SBR_DRM_BS - | CAPF_SBR_CONCEALMENT - | CAPF_SBR_DRC - ; + info->flags = 0 | CAPF_SBR_HQ | CAPF_SBR_LP | CAPF_SBR_PS_MPEG | + CAPF_SBR_DRM_BS | CAPF_SBR_CONCEALMENT | CAPF_SBR_DRC | + CAPF_SBR_ELD_DOWNSCALE | CAPF_SBR_HBEHQ; /* End of flags */ return 0; } - -UINT sbrDecoder_GetDelay( const HANDLE_SBRDECODER self ) -{ +UINT sbrDecoder_GetDelay(const HANDLE_SBRDECODER self) { UINT outputDelay = 0; - if ( self != NULL) { + if (self != NULL) { UINT flags = self->flags; /* See chapter 1.6.7.2 of ISO/IEC 14496-3 for the GA-SBR figures below. */ /* Are we initialized? */ - if ( (self->numSbrChannels > 0) - && (self->numSbrElements > 0) ) - { + if ((self->numSbrChannels > 0) && (self->numSbrElements > 0)) { /* Add QMF synthesis delay */ - if ( (flags & SBRDEC_ELD_GRID) - && IS_LOWDELAY(self->coreCodec) ) { + if ((flags & SBRDEC_ELD_GRID) && IS_LOWDELAY(self->coreCodec)) { /* Low delay SBR: */ - { - outputDelay += (flags & SBRDEC_DOWNSAMPLE) ? 32 : 64; /* QMF synthesis */ + if (!(flags & SBRDEC_SKIP_QMF_SYN)) { + outputDelay += + (flags & SBRDEC_DOWNSAMPLE) ? 32 : 64; /* QMF synthesis */ if (flags & SBRDEC_LD_MPS_QMF) { outputDelay += 32; } } - } - else if (!IS_USAC(self->coreCodec)) { - /* By the method of elimination this is the GA (AAC-LC, HE-AAC, ...) branch: */ + } else if (!IS_USAC(self->coreCodec)) { + /* By the method of elimination this is the GA (AAC-LC, HE-AAC, ...) + * branch: */ outputDelay += (flags & SBRDEC_DOWNSAMPLE) ? 481 : 962; + if (flags & SBRDEC_SKIP_QMF_SYN) { + outputDelay -= 257; /* QMF synthesis */ + } } } } diff --git a/libSBRdec/src/transcendent.h b/libSBRdec/src/transcendent.h index ad88bc9..0e815c2 100644 --- a/libSBRdec/src/transcendent.h +++ b/libSBRdec/src/transcendent.h @@ -1,74 +1,85 @@ - -/* ----------------------------------------------------------------------------------------------------------- +/* ----------------------------------------------------------------------------- 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. +© 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. +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: +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 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 +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. +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. +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." +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. +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. +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. +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 @@ -79,15 +90,23 @@ Am Wolfsmantel 33 www.iis.fraunhofer.de/amm amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ /*! \file - \brief FDK Fixed Point Arithmetic Library Interface + \brief FDK Fixed Point Arithmetic Library Interface */ -#ifndef __TRANSCENDENT_H -#define __TRANSCENDENT_H +#ifndef TRANSCENDENT_H +#define TRANSCENDENT_H #include "sbrdecoder.h" #include "sbr_rom.h" @@ -105,10 +124,9 @@ amm-info@iis.fraunhofer.de static inline FIXP_SGL FDK_getNumOctavesDiv8(INT a, /*!< lower band */ INT b) /*!< upper band */ { - return ( (SHORT)((LONG)(CalcLdInt(b) - CalcLdInt(a))>>(FRACT_BITS-3)) ); + return ((SHORT)((LONG)(CalcLdInt(b) - CalcLdInt(a)) >> (FRACT_BITS - 3))); } - /************************************************************************/ /*! \brief Add two values given by mantissa and exponent. @@ -118,15 +136,15 @@ static inline FIXP_SGL FDK_getNumOctavesDiv8(INT a, /*!< lower band */ */ /************************************************************************/ inline void FDK_add_MantExp(FIXP_SGL a_m, /*!< Mantissa of 1st operand a */ - SCHAR a_e, /*!< Exponent of 1st operand a */ - FIXP_SGL b_m, /*!< Mantissa of 2nd operand b */ - SCHAR b_e, /*!< Exponent of 2nd operand b */ - FIXP_SGL *ptrSum_m, /*!< Mantissa of result */ - SCHAR *ptrSum_e) /*!< Exponent of result */ + SCHAR a_e, /*!< Exponent of 1st operand a */ + FIXP_SGL b_m, /*!< Mantissa of 2nd operand b */ + SCHAR b_e, /*!< Exponent of 2nd operand b */ + FIXP_SGL *ptrSum_m, /*!< Mantissa of result */ + SCHAR *ptrSum_e) /*!< Exponent of result */ { FIXP_DBL accu; - int shift; - int shiftAbs; + int shift; + int shiftAbs; FIXP_DBL shiftedMantissa; FIXP_DBL otherMantissa; @@ -137,34 +155,35 @@ inline void FDK_add_MantExp(FIXP_SGL a_m, /*!< Mantissa of 1st operand a */ shift = (int)(a_e - b_e); - shiftAbs = (shift>0)? shift : -shift; - shiftAbs = (shiftAbs < DFRACT_BITS-1)? shiftAbs : DFRACT_BITS-1; - shiftedMantissa = (shift>0)? (FX_SGL2FX_DBL(b_m) >> shiftAbs) : (FX_SGL2FX_DBL(a_m) >> shiftAbs); - otherMantissa = (shift>0)? FX_SGL2FX_DBL(a_m) : FX_SGL2FX_DBL(b_m); - *ptrSum_e = (shift>0)? a_e : b_e; + shiftAbs = (shift > 0) ? shift : -shift; + shiftAbs = (shiftAbs < DFRACT_BITS - 1) ? shiftAbs : DFRACT_BITS - 1; + shiftedMantissa = (shift > 0) ? (FX_SGL2FX_DBL(b_m) >> shiftAbs) + : (FX_SGL2FX_DBL(a_m) >> shiftAbs); + otherMantissa = (shift > 0) ? FX_SGL2FX_DBL(a_m) : FX_SGL2FX_DBL(b_m); + *ptrSum_e = (shift > 0) ? a_e : b_e; accu = (shiftedMantissa >> 1) + (otherMantissa >> 1); /* shift by 1 bit to avoid overflow */ - if ( (accu >= (FL2FXCONST_DBL(0.5f) - (FIXP_DBL)1)) || (accu <= FL2FXCONST_DBL(-0.5f)) ) + if ((accu >= (FL2FXCONST_DBL(0.5f) - (FIXP_DBL)1)) || + (accu <= FL2FXCONST_DBL(-0.5f))) *ptrSum_e += 1; else accu = (shiftedMantissa + otherMantissa); *ptrSum_m = FX_DBL2FX_SGL(accu); - } -inline void FDK_add_MantExp(FIXP_DBL a, /*!< Mantissa of 1st operand a */ - SCHAR a_e, /*!< Exponent of 1st operand a */ - FIXP_DBL b, /*!< Mantissa of 2nd operand b */ - SCHAR b_e, /*!< Exponent of 2nd operand b */ - FIXP_DBL *ptrSum, /*!< Mantissa of result */ - SCHAR *ptrSum_e) /*!< Exponent of result */ +inline void FDK_add_MantExp(FIXP_DBL a, /*!< Mantissa of 1st operand a */ + SCHAR a_e, /*!< Exponent of 1st operand a */ + FIXP_DBL b, /*!< Mantissa of 2nd operand b */ + SCHAR b_e, /*!< Exponent of 2nd operand b */ + FIXP_DBL *ptrSum, /*!< Mantissa of result */ + SCHAR *ptrSum_e) /*!< Exponent of result */ { FIXP_DBL accu; - int shift; - int shiftAbs; + int shift; + int shiftAbs; FIXP_DBL shiftedMantissa; FIXP_DBL otherMantissa; @@ -175,22 +194,22 @@ inline void FDK_add_MantExp(FIXP_DBL a, /*!< Mantissa of 1st operand a */ shift = (int)(a_e - b_e); - shiftAbs = (shift>0)? shift : -shift; - shiftAbs = (shiftAbs < DFRACT_BITS-1)? shiftAbs : DFRACT_BITS-1; - shiftedMantissa = (shift>0)? (b >> shiftAbs) : (a >> shiftAbs); - otherMantissa = (shift>0)? a : b; - *ptrSum_e = (shift>0)? a_e : b_e; + shiftAbs = (shift > 0) ? shift : -shift; + shiftAbs = (shiftAbs < DFRACT_BITS - 1) ? shiftAbs : DFRACT_BITS - 1; + shiftedMantissa = (shift > 0) ? (b >> shiftAbs) : (a >> shiftAbs); + otherMantissa = (shift > 0) ? a : b; + *ptrSum_e = (shift > 0) ? a_e : b_e; accu = (shiftedMantissa >> 1) + (otherMantissa >> 1); /* shift by 1 bit to avoid overflow */ - if ( (accu >= (FL2FXCONST_DBL(0.5f) - (FIXP_DBL)1)) || (accu <= FL2FXCONST_DBL(-0.5f)) ) + if ((accu >= (FL2FXCONST_DBL(0.5f) - (FIXP_DBL)1)) || + (accu <= FL2FXCONST_DBL(-0.5f))) *ptrSum_e += 1; else accu = (shiftedMantissa + otherMantissa); *ptrSum = accu; - } /************************************************************************/ @@ -204,17 +223,18 @@ inline void FDK_add_MantExp(FIXP_DBL a, /*!< Mantissa of 1st operand a */ which limits accuracy. */ /************************************************************************/ -static inline void FDK_divide_MantExp(FIXP_SGL a_m, /*!< Mantissa of dividend a */ - SCHAR a_e, /*!< Exponent of dividend a */ - FIXP_SGL b_m, /*!< Mantissa of divisor b */ - SCHAR b_e, /*!< Exponent of divisor b */ - FIXP_SGL *ptrResult_m, /*!< Mantissa of quotient a/b */ - SCHAR *ptrResult_e) /*!< Exponent of quotient a/b */ +static inline void FDK_divide_MantExp( + FIXP_SGL a_m, /*!< Mantissa of dividend a */ + SCHAR a_e, /*!< Exponent of dividend a */ + FIXP_SGL b_m, /*!< Mantissa of divisor b */ + SCHAR b_e, /*!< Exponent of divisor b */ + FIXP_SGL *ptrResult_m, /*!< Mantissa of quotient a/b */ + SCHAR *ptrResult_e) /*!< Exponent of quotient a/b */ { int preShift, postShift, index, shift; FIXP_DBL ratio_m; - FIXP_SGL bInv_m = FL2FXCONST_SGL(0.0f); + FIXP_SGL bInv_m = FL2FXCONST_SGL(0.0f); preShift = CntLeadingZeros(FX_SGL2FX_DBL(b_m)); @@ -236,41 +256,41 @@ static inline void FDK_divide_MantExp(FIXP_SGL a_m, /*!< Mantissa of d */ shift = (FRACT_BITS - 2 - INV_TABLE_BITS - preShift); - index = (shift<0)? (LONG)b_m << (-shift) : (LONG)b_m >> shift; - + index = (shift < 0) ? (LONG)b_m << (-shift) : (LONG)b_m >> shift; /* The index has INV_TABLE_BITS +1 valid bits here. Clear the other bits. */ - index &= (1 << (INV_TABLE_BITS+1)) - 1; + index &= (1 << (INV_TABLE_BITS + 1)) - 1; - /* Remove offset of half an interval */ + /* Remove offset of half an interval */ index--; - /* Now the lowest bit is shifted out */ + /* Now the lowest bit is shifted out */ index = index >> 1; - /* Fetch inversed mantissa from table: */ - bInv_m = (index<0)? bInv_m : FDK_sbrDecoder_invTable[index]; + /* Fetch inversed mantissa from table: */ + bInv_m = (index < 0) ? bInv_m : FDK_sbrDecoder_invTable[index]; - /* Multiply a with the inverse of b: */ - ratio_m = (index<0)? FX_SGL2FX_DBL(a_m >> 1) : fMultDiv2(bInv_m,a_m); + /* Multiply a with the inverse of b: */ + ratio_m = (index < 0) ? FX_SGL2FX_DBL(a_m >> 1) : fMultDiv2(bInv_m, a_m); - postShift = CntLeadingZeros(ratio_m)-1; + postShift = CntLeadingZeros(ratio_m) - 1; *ptrResult_m = FX_DBL2FX_SGL(ratio_m << postShift); *ptrResult_e = a_e - b_e + 1 + preShift - postShift; } -static inline void FDK_divide_MantExp(FIXP_DBL a_m, /*!< Mantissa of dividend a */ - SCHAR a_e, /*!< Exponent of dividend a */ - FIXP_DBL b_m, /*!< Mantissa of divisor b */ - SCHAR b_e, /*!< Exponent of divisor b */ - FIXP_DBL *ptrResult_m, /*!< Mantissa of quotient a/b */ - SCHAR *ptrResult_e) /*!< Exponent of quotient a/b */ +static inline void FDK_divide_MantExp( + FIXP_DBL a_m, /*!< Mantissa of dividend a */ + SCHAR a_e, /*!< Exponent of dividend a */ + FIXP_DBL b_m, /*!< Mantissa of divisor b */ + SCHAR b_e, /*!< Exponent of divisor b */ + FIXP_DBL *ptrResult_m, /*!< Mantissa of quotient a/b */ + SCHAR *ptrResult_e) /*!< Exponent of quotient a/b */ { int preShift, postShift, index, shift; FIXP_DBL ratio_m; - FIXP_SGL bInv_m = FL2FXCONST_SGL(0.0f); + FIXP_SGL bInv_m = FL2FXCONST_SGL(0.0f); preShift = CntLeadingZeros(b_m); @@ -292,25 +312,24 @@ static inline void FDK_divide_MantExp(FIXP_DBL a_m, /*!< Mantissa of d */ shift = (DFRACT_BITS - 2 - INV_TABLE_BITS - preShift); - index = (shift<0)? (LONG)b_m << (-shift) : (LONG)b_m >> shift; - + index = (shift < 0) ? (LONG)b_m << (-shift) : (LONG)b_m >> shift; /* The index has INV_TABLE_BITS +1 valid bits here. Clear the other bits. */ - index &= (1 << (INV_TABLE_BITS+1)) - 1; + index &= (1 << (INV_TABLE_BITS + 1)) - 1; - /* Remove offset of half an interval */ + /* Remove offset of half an interval */ index--; - /* Now the lowest bit is shifted out */ + /* Now the lowest bit is shifted out */ index = index >> 1; - /* Fetch inversed mantissa from table: */ - bInv_m = (index<0)? bInv_m : FDK_sbrDecoder_invTable[index]; + /* Fetch inversed mantissa from table: */ + bInv_m = (index < 0) ? bInv_m : FDK_sbrDecoder_invTable[index]; - /* Multiply a with the inverse of b: */ - ratio_m = (index<0)? (a_m >> 1) : fMultDiv2(bInv_m,a_m); + /* Multiply a with the inverse of b: */ + ratio_m = (index < 0) ? (a_m >> 1) : fMultDiv2(bInv_m, a_m); - postShift = CntLeadingZeros(ratio_m)-1; + postShift = CntLeadingZeros(ratio_m) - 1; *ptrResult_m = ratio_m << postShift; *ptrResult_e = a_e - b_e + 1 + preShift - postShift; @@ -326,30 +345,28 @@ static inline void FDK_divide_MantExp(FIXP_DBL a_m, /*!< Mantissa of d For performance reasons, the square root is based on a table lookup which limits accuracy. */ -static inline void FDK_sqrt_MantExp(FIXP_DBL *mantissa, /*!< Pointer to mantissa */ - SCHAR *exponent, - const SCHAR *destScale) -{ +static inline void FDK_sqrt_MantExp( + FIXP_DBL *mantissa, /*!< Pointer to mantissa */ + SCHAR *exponent, const SCHAR *destScale) { FIXP_DBL input_m = *mantissa; - int input_e = (int) *exponent; + int input_e = (int)*exponent; FIXP_DBL result = FL2FXCONST_DBL(0.0f); - int result_e = -FRACT_BITS; + int result_e = -FRACT_BITS; /* Call lookup square root, which does internally normalization. */ - result = sqrtFixp_lookup(input_m, &input_e); + result = sqrtFixp_lookup(input_m, &input_e); result_e = input_e; /* Write result */ - if (exponent==destScale) { + if (exponent == destScale) { *mantissa = result; *exponent = result_e; } else { int shift = result_e - *destScale; - *mantissa = (shift>=0) ? result << (INT)fixMin(DFRACT_BITS-1,shift) - : result >> (INT)fixMin(DFRACT_BITS-1,-shift); + *mantissa = (shift >= 0) ? result << (INT)fixMin(DFRACT_BITS - 1, shift) + : result >> (INT)fixMin(DFRACT_BITS - 1, -shift); *exponent = *destScale; } } - #endif |