diff options
Diffstat (limited to 'libSACenc/src')
26 files changed, 12286 insertions, 0 deletions
diff --git a/libSACenc/src/sacenc_bitstream.cpp b/libSACenc/src/sacenc_bitstream.cpp new file mode 100644 index 0000000..dacfc27 --- /dev/null +++ b/libSACenc/src/sacenc_bitstream.cpp @@ -0,0 +1,826 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): + + Description: Encoder Library Interface + Bitstream Writer + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_bitstream.h" +#include "sacenc_const.h" + +#include "genericStds.h" +#include "common_fix.h" + +#include "FDK_matrixCalloc.h" +#include "sacenc_nlc_enc.h" + +/* Defines *******************************************************************/ +#define MAX_FREQ_RES_INDEX 8 +#define MAX_SAMPLING_FREQUENCY_INDEX 13 +#define SAMPLING_FREQUENCY_INDEX_ESCAPE 15 + +/* Data Types ****************************************************************/ +typedef struct { + SCHAR cld_old[SACENC_MAX_NUM_BOXES][MAX_NUM_BINS]; + SCHAR icc_old[SACENC_MAX_NUM_BOXES][MAX_NUM_BINS]; + UCHAR quantCoarseCldPrev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + UCHAR quantCoarseIccPrev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + +} PREV_OTTDATA; + +typedef struct { + PREV_OTTDATA prevOttData; + +} STATIC_SPATIALFRAME; + +typedef struct BSF_INSTANCE { + SPATIALSPECIFICCONFIG spatialSpecificConfig; + SPATIALFRAME frame; + STATIC_SPATIALFRAME prevFrameData; + +} BSF_INSTANCE; + +/* Constants *****************************************************************/ +static const INT SampleRateTable[MAX_SAMPLING_FREQUENCY_INDEX] = { + 96000, 88200, 64000, 48000, 44100, 32000, 24000, + 22050, 16000, 12000, 11025, 8000, 7350}; + +static const UCHAR FreqResBinTable_LD[MAX_FREQ_RES_INDEX] = {0, 23, 15, 12, + 9, 7, 5, 4}; +static const UCHAR FreqResStrideTable_LD[] = {1, 2, 5, 23}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static FDK_SACENC_ERROR DuplicateLosslessData( + const INT startBox, const INT stopBox, + const LOSSLESSDATA *const hLosslessDataFrom, const INT setFrom, + LOSSLESSDATA *const hLosslessDataTo, const INT setTo) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hLosslessDataFrom) || (NULL == hLosslessDataTo)) { + error = SACENC_INVALID_HANDLE; + } else { + int i; + + for (i = startBox; i < stopBox; i++) { + hLosslessDataTo->bsXXXDataMode[i][setTo] = + hLosslessDataFrom->bsXXXDataMode[i][setFrom]; + hLosslessDataTo->bsDataPair[i][setTo] = + hLosslessDataFrom->bsDataPair[i][setFrom]; + hLosslessDataTo->bsQuantCoarseXXX[i][setTo] = + hLosslessDataFrom->bsQuantCoarseXXX[i][setFrom]; + hLosslessDataTo->bsFreqResStrideXXX[i][setTo] = + hLosslessDataFrom->bsFreqResStrideXXX[i][setFrom]; + } + } + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_duplicateParameterSet( + const SPATIALFRAME *const hFrom, const INT setFrom, SPATIALFRAME *const hTo, + const INT setTo) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hFrom) || (NULL == hTo)) { + error = SACENC_INVALID_HANDLE; + } else { + int box; + /* Only Copy Parameter Set selective stuff */ + + /* OTT-Data */ + for (box = 0; box < SACENC_MAX_NUM_BOXES; box++) { + FDKmemcpy(hTo->ottData.cld[box][setTo], hFrom->ottData.cld[box][setFrom], + sizeof(hFrom->ottData.cld[0][0])); + FDKmemcpy(hTo->ottData.icc[box][setTo], hFrom->ottData.icc[box][setFrom], + sizeof(hFrom->ottData.icc[0][0])); + } + + /* LOSSLESSDATA */ + DuplicateLosslessData(0, SACENC_MAX_NUM_BOXES, &hFrom->CLDLosslessData, + setFrom, &hTo->CLDLosslessData, setTo); + DuplicateLosslessData(0, SACENC_MAX_NUM_BOXES, &hFrom->ICCLosslessData, + setFrom, &hTo->ICCLosslessData, setTo); + + } /* valid handle */ + + return error; +} + +/* set frame defaults */ +static void clearFrame(SPATIALFRAME *const pFrame) { + FDKmemclear(pFrame, sizeof(SPATIALFRAME)); + + pFrame->bsIndependencyFlag = 1; + pFrame->framingInfo.numParamSets = 1; +} + +static void fine2coarse(SCHAR *const data, const DATA_TYPE dataType, + const INT startBand, const INT numBands) { + int i; + if (dataType == t_CLD) { + for (i = startBand; i < startBand + numBands; i++) { + data[i] /= 2; + } + } else { + for (i = startBand; i < startBand + numBands; i++) { + data[i] >>= 1; + } + } +} + +static void coarse2fine(SCHAR *const data, const DATA_TYPE dataType, + const INT startBand, const INT numBands) { + int i; + + for (i = startBand; i < startBand + numBands; i++) { + data[i] <<= 1; + } + + if (dataType == t_CLD) { + for (i = startBand; i < startBand + numBands; i++) { + if (data[i] == -14) { + data[i] = -15; + } else if (data[i] == 14) { + data[i] = 15; + } + } + } /* (dataType == t_CLD) */ +} + +static UCHAR getBsFreqResStride(const INT index) { + const UCHAR *pFreqResStrideTable = NULL; + int freqResStrideTableSize = 0; + + pFreqResStrideTable = FreqResStrideTable_LD; + freqResStrideTableSize = + sizeof(FreqResStrideTable_LD) / sizeof(*FreqResStrideTable_LD); + + return (((NULL != pFreqResStrideTable) && (index >= 0) && + (index < freqResStrideTableSize)) + ? pFreqResStrideTable[index] + : 1); +} + +/* write data to bitstream */ +static void ecData(HANDLE_FDK_BITSTREAM bitstream, + SCHAR data[MAX_NUM_PARAMS][MAX_NUM_BINS], + SCHAR oldData[MAX_NUM_BINS], + UCHAR quantCoarseXXXprev[MAX_NUM_PARAMS], + LOSSLESSDATA *const losslessData, const DATA_TYPE dataType, + const INT paramIdx, const INT numParamSets, + const INT independencyFlag, const INT startBand, + const INT stopBand, const INT defaultValue) { + int ps, pb, strOffset, pbStride, dataBands, i; + int aStrides[MAX_NUM_BINS + 1] = {0}; + SHORT cmpIdxData[2][MAX_NUM_BINS] = {{0}}; + SHORT cmpOldData[MAX_NUM_BINS] = {0}; + + /* bsXXXDataMode */ + if (independencyFlag || (losslessData->bsQuantCoarseXXX[paramIdx][0] != + quantCoarseXXXprev[paramIdx])) { + losslessData->bsXXXDataMode[paramIdx][0] = FINECOARSE; + } else { + losslessData->bsXXXDataMode[paramIdx][0] = KEEP; + for (i = startBand; i < stopBand; i++) { + if (data[0][i] != oldData[i]) { + losslessData->bsXXXDataMode[paramIdx][0] = FINECOARSE; + break; + } + } + } + + FDKwriteBits(bitstream, losslessData->bsXXXDataMode[paramIdx][0], 2); + + for (ps = 1; ps < numParamSets; ps++) { + if (losslessData->bsQuantCoarseXXX[paramIdx][ps] != + losslessData->bsQuantCoarseXXX[paramIdx][ps - 1]) { + losslessData->bsXXXDataMode[paramIdx][ps] = FINECOARSE; + } else { + losslessData->bsXXXDataMode[paramIdx][ps] = KEEP; + for (i = startBand; i < stopBand; i++) { + if (data[ps][i] != data[ps - 1][i]) { + losslessData->bsXXXDataMode[paramIdx][ps] = FINECOARSE; + break; + } + } + } + + FDKwriteBits(bitstream, losslessData->bsXXXDataMode[paramIdx][ps], 2); + } /* for ps */ + + /* Create data pairs if possible */ + for (ps = 0; ps < (numParamSets - 1); ps++) { + if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE) { + /* Check if next parameter set is FINCOARSE */ + if (losslessData->bsXXXDataMode[paramIdx][ps + 1] == FINECOARSE) { + /* We have to check if ps and ps+1 use the same bsXXXQuantMode */ + /* and also have the same stride */ + if ((losslessData->bsQuantCoarseXXX[paramIdx][ps + 1] == + losslessData->bsQuantCoarseXXX[paramIdx][ps]) && + (losslessData->bsFreqResStrideXXX[paramIdx][ps + 1] == + losslessData->bsFreqResStrideXXX[paramIdx][ps])) { + losslessData->bsDataPair[paramIdx][ps] = 1; + losslessData->bsDataPair[paramIdx][ps + 1] = 1; + + /* We have a data pair -> Jump to the ps after next ps*/ + ps++; + continue; + } + } + /* dataMode of next ps is not FINECOARSE or does not use the same + * bsXXXQuantMode/stride */ + /* -> no dataPair possible */ + losslessData->bsDataPair[paramIdx][ps] = 0; + + /* Initialize ps after next ps to Zero (only important for the last + * parameter set) */ + losslessData->bsDataPair[paramIdx][ps + 1] = 0; + } else { + /* No FINECOARSE -> no data pair possible */ + losslessData->bsDataPair[paramIdx][ps] = 0; + + /* Initialize ps after next ps to Zero (only important for the last + * parameter set) */ + losslessData->bsDataPair[paramIdx][ps + 1] = 0; + } + } /* for ps */ + + for (ps = 0; ps < numParamSets; ps++) { + if (losslessData->bsXXXDataMode[paramIdx][ps] == DEFAULT) { + /* Prepare old data */ + for (i = startBand; i < stopBand; i++) { + oldData[i] = defaultValue; + } + quantCoarseXXXprev[paramIdx] = 0; /* Default data are always fine */ + } + + if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE) { + FDKwriteBits(bitstream, losslessData->bsDataPair[paramIdx][ps], 1); + FDKwriteBits(bitstream, losslessData->bsQuantCoarseXXX[paramIdx][ps], 1); + FDKwriteBits(bitstream, losslessData->bsFreqResStrideXXX[paramIdx][ps], + 2); + + if (losslessData->bsQuantCoarseXXX[paramIdx][ps] != + quantCoarseXXXprev[paramIdx]) { + if (quantCoarseXXXprev[paramIdx]) { + coarse2fine(oldData, dataType, startBand, stopBand - startBand); + } else { + fine2coarse(oldData, dataType, startBand, stopBand - startBand); + } + } + + /* Handle strides */ + pbStride = + getBsFreqResStride(losslessData->bsFreqResStrideXXX[paramIdx][ps]); + dataBands = (stopBand - startBand - 1) / pbStride + 1; + + aStrides[0] = startBand; + for (pb = 1; pb <= dataBands; pb++) { + aStrides[pb] = aStrides[pb - 1] + pbStride; + } + + strOffset = 0; + while (aStrides[dataBands] > stopBand) { + if (strOffset < dataBands) { + strOffset++; + } + for (i = strOffset; i <= dataBands; i++) { + aStrides[i]--; + } + } /* while */ + + for (pb = 0; pb < dataBands; pb++) { + cmpOldData[startBand + pb] = oldData[aStrides[pb]]; + cmpIdxData[0][startBand + pb] = data[ps][aStrides[pb]]; + + if (losslessData->bsDataPair[paramIdx][ps]) { + cmpIdxData[1][startBand + pb] = data[ps + 1][aStrides[pb]]; + } + } /* for pb*/ + + /* Finally encode */ + if (losslessData->bsDataPair[paramIdx][ps]) { + fdk_sacenc_ecDataPairEnc(bitstream, cmpIdxData, cmpOldData, dataType, 0, + startBand, dataBands, + losslessData->bsQuantCoarseXXX[paramIdx][ps], + independencyFlag && (ps == 0)); + } else { + fdk_sacenc_ecDataSingleEnc(bitstream, cmpIdxData, cmpOldData, dataType, + 0, startBand, dataBands, + losslessData->bsQuantCoarseXXX[paramIdx][ps], + independencyFlag && (ps == 0)); + } + + /* Overwrite old data */ + for (i = startBand; i < stopBand; i++) { + if (losslessData->bsDataPair[paramIdx][ps]) { + oldData[i] = data[ps + 1][i]; + } else { + oldData[i] = data[ps][i]; + } + } + + quantCoarseXXXprev[paramIdx] = + losslessData->bsQuantCoarseXXX[paramIdx][ps]; + + /* Jump forward if we have encoded a data pair */ + if (losslessData->bsDataPair[paramIdx][ps]) { + ps++; + } + + } /* if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE ) */ + } /* for ps */ +} + +/****************************************************************************/ +/* Bitstream formatter interface functions */ +/****************************************************************************/ +static FDK_SACENC_ERROR getBsFreqResIndex(const INT numBands, + INT *const pbsFreqResIndex) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pbsFreqResIndex) { + error = SACENC_INVALID_HANDLE; + } else { + const UCHAR *pFreqResBinTable = FreqResBinTable_LD; + int i; + *pbsFreqResIndex = -1; + + for (i = 0; i < MAX_FREQ_RES_INDEX; i++) { + if (numBands == pFreqResBinTable[i]) { + *pbsFreqResIndex = i; + break; + } + } + if (*pbsFreqResIndex < 0 || *pbsFreqResIndex >= MAX_FREQ_RES_INDEX) { + error = SACENC_INVALID_CONFIG; + } + } + return error; +} + +static FDK_SACENC_ERROR getSamplingFrequencyIndex( + const INT bsSamplingFrequency, INT *const pbsSamplingFrequencyIndex) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pbsSamplingFrequencyIndex) { + error = SACENC_INVALID_HANDLE; + } else { + int i; + *pbsSamplingFrequencyIndex = SAMPLING_FREQUENCY_INDEX_ESCAPE; + + for (i = 0; i < MAX_SAMPLING_FREQUENCY_INDEX; i++) { + if (bsSamplingFrequency == SampleRateTable[i]) { /*spatial sampling rate*/ + *pbsSamplingFrequencyIndex = i; + break; + } + } + } + return error; +} + +/* destroy encoder instance */ +FDK_SACENC_ERROR fdk_sacenc_destroySpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE *selfPtr) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((selfPtr == NULL) || (*selfPtr == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + if (*selfPtr != NULL) { + FDK_FREE_MEMORY_1D(*selfPtr); + } + } + return error; +} + +/* create encoder instance */ +FDK_SACENC_ERROR fdk_sacenc_createSpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE *selfPtr) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == selfPtr) { + error = SACENC_INVALID_HANDLE; + } else { + /* allocate encoder struct */ + FDK_ALLOCATE_MEMORY_1D(*selfPtr, 1, BSF_INSTANCE); + } + return error; + +bail: + fdk_sacenc_destroySpatialBitstreamEncoder(selfPtr); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +/* init encoder instance */ +FDK_SACENC_ERROR fdk_sacenc_initSpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE selfPtr) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (selfPtr == NULL) { + error = SACENC_INVALID_HANDLE; + } else { + /* init/clear */ + clearFrame(&selfPtr->frame); + + } /* valid handle */ + return error; +} + +/* get SpatialSpecificConfig struct */ +SPATIALSPECIFICCONFIG *fdk_sacenc_getSpatialSpecificConfig( + HANDLE_BSF_INSTANCE selfPtr) { + return ((selfPtr == NULL) ? NULL : &(selfPtr->spatialSpecificConfig)); +} + +/* write SpatialSpecificConfig to stream */ +FDK_SACENC_ERROR fdk_sacenc_writeSpatialSpecificConfig( + SPATIALSPECIFICCONFIG *const spatialSpecificConfig, + UCHAR *const pOutputBuffer, const INT outputBufferSize, + INT *const pnOutputBits) { + FDK_SACENC_ERROR error = SACENC_OK; + INT bsSamplingFrequencyIndex = 0; + INT bsFreqRes = 0; + + if ((spatialSpecificConfig == NULL) || (pOutputBuffer == NULL) || + (pnOutputBits == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDK_BITSTREAM bitstream; + + /* Find FreqRes */ + if (SACENC_OK != (error = getBsFreqResIndex(spatialSpecificConfig->numBands, + &bsFreqRes))) + goto bail; + + /* Find SamplingFrequencyIndex */ + if (SACENC_OK != (error = getSamplingFrequencyIndex( + spatialSpecificConfig->bsSamplingFrequency, + &bsSamplingFrequencyIndex))) + goto bail; + + /* bind extern buffer to bitstream handle */ + FDKinitBitStream(&bitstream, pOutputBuffer, outputBufferSize, 0, BS_WRITER); + + /****************************************************************************/ + /* write to bitstream */ + + FDKwriteBits(&bitstream, bsSamplingFrequencyIndex, 4); + + if (bsSamplingFrequencyIndex == 15) { + FDKwriteBits(&bitstream, spatialSpecificConfig->bsSamplingFrequency, 24); + } + + FDKwriteBits(&bitstream, spatialSpecificConfig->bsFrameLength, 5); + + FDKwriteBits(&bitstream, bsFreqRes, 3); + FDKwriteBits(&bitstream, spatialSpecificConfig->bsTreeConfig, 4); + FDKwriteBits(&bitstream, spatialSpecificConfig->bsQuantMode, 2); + + FDKwriteBits(&bitstream, 0, 1); /* bsArbitraryDownmix */ + + FDKwriteBits(&bitstream, spatialSpecificConfig->bsFixedGainDMX, 3); + + FDKwriteBits(&bitstream, TEMPSHAPE_OFF, 2); + FDKwriteBits(&bitstream, spatialSpecificConfig->bsDecorrConfig, 2); + + FDKbyteAlign(&bitstream, 0); /* byte alignment */ + + /* return number of valid bits in bitstream */ + if ((*pnOutputBits = FDKgetValidBits(&bitstream)) > + (outputBufferSize * 8)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* terminate buffer with alignment */ + FDKbyteAlign(&bitstream, 0); + + } /* valid handle */ + +bail: + return error; +} + +/* get SpatialFrame struct */ +SPATIALFRAME *fdk_sacenc_getSpatialFrame(HANDLE_BSF_INSTANCE selfPtr, + const SPATIALFRAME_TYPE frameType) { + int idx = -1; + + switch (frameType) { + case READ_SPATIALFRAME: + case WRITE_SPATIALFRAME: + idx = 0; + break; + default: + idx = -1; /* invalid configuration */ + } /* switch frameType */ + + return (((selfPtr == NULL) || (idx == -1)) ? NULL : &selfPtr->frame); +} + +static FDK_SACENC_ERROR writeFramingInfo(HANDLE_FDK_BITSTREAM hBitstream, + const FRAMINGINFO *const pFramingInfo, + const INT frameLength) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hBitstream == NULL) || (pFramingInfo == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDKwriteBits(hBitstream, pFramingInfo->bsFramingType, 1); + FDKwriteBits(hBitstream, pFramingInfo->numParamSets - 1, 1); + + if (pFramingInfo->bsFramingType) { + int ps = 0; + int numParamSets = pFramingInfo->numParamSets; + + { + for (ps = 0; ps < numParamSets; ps++) { + int bitsParamSlot = 0; + while ((1 << bitsParamSlot) < (frameLength + 1)) bitsParamSlot++; + if (bitsParamSlot > 0) + FDKwriteBits(hBitstream, pFramingInfo->bsParamSlots[ps], + bitsParamSlot); + } + } + } /* pFramingInfo->bsFramingType */ + } /* valid handle */ + + return error; +} + +static FDK_SACENC_ERROR writeSmgData(HANDLE_FDK_BITSTREAM hBitstream, + const SMGDATA *const pSmgData, + const INT numParamSets, + const INT dataBands) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hBitstream == NULL) || (pSmgData == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int i, j; + + for (i = 0; i < numParamSets; i++) { + FDKwriteBits(hBitstream, pSmgData->bsSmoothMode[i], 2); + + if (pSmgData->bsSmoothMode[i] >= 2) { + FDKwriteBits(hBitstream, pSmgData->bsSmoothTime[i], 2); + } + if (pSmgData->bsSmoothMode[i] == 3) { + const int stride = getBsFreqResStride(pSmgData->bsFreqResStride[i]); + FDKwriteBits(hBitstream, pSmgData->bsFreqResStride[i], 2); + for (j = 0; j < dataBands; j += stride) { + FDKwriteBits(hBitstream, pSmgData->bsSmgData[i][j], 1); + } + } + } /* for i */ + } /* valid handle */ + + return error; +} + +static FDK_SACENC_ERROR writeOttData( + HANDLE_FDK_BITSTREAM hBitstream, PREV_OTTDATA *const pPrevOttData, + OTTDATA *const pOttData, const OTTCONFIG ottConfig[SACENC_MAX_NUM_BOXES], + LOSSLESSDATA *const pCLDLosslessData, LOSSLESSDATA *const pICCLosslessData, + const INT numOttBoxes, const INT numBands, const INT numParamSets, + const INT bsIndependencyFlag) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hBitstream == NULL) || (pPrevOttData == NULL) || (pOttData == NULL) || + (ottConfig == NULL) || (pCLDLosslessData == NULL) || + (pICCLosslessData == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int i; + for (i = 0; i < numOttBoxes; i++) { + ecData(hBitstream, pOttData->cld[i], pPrevOttData->cld_old[i], + pPrevOttData->quantCoarseCldPrev[i], pCLDLosslessData, t_CLD, i, + numParamSets, bsIndependencyFlag, 0, ottConfig[i].bsOttBands, 15); + } + { + for (i = 0; i < numOttBoxes; i++) { + { + ecData(hBitstream, pOttData->icc[i], pPrevOttData->icc_old[i], + pPrevOttData->quantCoarseIccPrev[i], pICCLosslessData, t_ICC, + i, numParamSets, bsIndependencyFlag, 0, numBands, 0); + } + } /* for i */ + } + } /* valid handle */ + + return error; +} + +/* write extension frame data to stream */ +static FDK_SACENC_ERROR WriteSpatialExtensionFrame( + HANDLE_FDK_BITSTREAM bitstream, HANDLE_BSF_INSTANCE self) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((bitstream == NULL) || (self == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDKbyteAlign(bitstream, 0); + } /* valid handle */ + + return error; +} + +/* write frame data to stream */ +FDK_SACENC_ERROR fdk_sacenc_writeSpatialFrame(UCHAR *const pOutputBuffer, + const INT outputBufferSize, + INT *const pnOutputBits, + HANDLE_BSF_INSTANCE selfPtr) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((pOutputBuffer == NULL) || (pnOutputBits == NULL) || (selfPtr == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + SPATIALFRAME *frame = NULL; + SPATIALSPECIFICCONFIG *config = NULL; + FDK_BITSTREAM bitstream; + + int i, j, numParamSets, numOttBoxes; + + if ((NULL == + (frame = fdk_sacenc_getSpatialFrame(selfPtr, READ_SPATIALFRAME))) || + (NULL == (config = &(selfPtr->spatialSpecificConfig)))) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + numOttBoxes = selfPtr->spatialSpecificConfig.treeDescription.numOttBoxes; + + numParamSets = frame->framingInfo.numParamSets; + + if (frame->bUseBBCues) { + for (i = 0; i < SACENC_MAX_NUM_BOXES; i++) { + /* If a transient was detected, force only the second ps broad band */ + if (numParamSets == 1) { + frame->CLDLosslessData.bsFreqResStrideXXX[i][0] = 3; + frame->ICCLosslessData.bsFreqResStrideXXX[i][0] = 3; + } else { + for (j = 1; j < MAX_NUM_PARAMS; j++) { + frame->CLDLosslessData.bsFreqResStrideXXX[i][j] = 3; + frame->ICCLosslessData.bsFreqResStrideXXX[i][j] = 3; + } + } + } + } /* frame->bUseBBCues */ + + /* bind extern buffer to bitstream handle */ + FDKinitBitStream(&bitstream, pOutputBuffer, outputBufferSize, 0, BS_WRITER); + + if (SACENC_OK != (error = writeFramingInfo( + &bitstream, &(frame->framingInfo), + selfPtr->spatialSpecificConfig.bsFrameLength))) { + goto bail; + } + + /* write bsIndependencyFlag */ + FDKwriteBits(&bitstream, frame->bsIndependencyFlag, 1); + + /* write spatial data to bitstream */ + if (SACENC_OK != + (error = writeOttData(&bitstream, &selfPtr->prevFrameData.prevOttData, + &frame->ottData, config->ottConfig, + &frame->CLDLosslessData, &frame->ICCLosslessData, + numOttBoxes, config->numBands, numParamSets, + frame->bsIndependencyFlag))) { + goto bail; + } + if (SACENC_OK != (error = writeSmgData(&bitstream, &frame->smgData, + numParamSets, config->numBands))) { + goto bail; + } + + /* byte alignment */ + FDKbyteAlign(&bitstream, 0); + + /* Write SpatialExtensionFrame */ + if (SACENC_OK != + (error = WriteSpatialExtensionFrame(&bitstream, selfPtr))) { + goto bail; + } + + if (NULL == + (frame = fdk_sacenc_getSpatialFrame(selfPtr, WRITE_SPATIALFRAME))) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + clearFrame(frame); + + /* return number of valid bits in bitstream */ + if ((*pnOutputBits = FDKgetValidBits(&bitstream)) > + (outputBufferSize * 8)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* terminate buffer with alignment */ + FDKbyteAlign(&bitstream, 0); + + } /* valid handle */ + +bail: + return error; +} diff --git a/libSACenc/src/sacenc_bitstream.h b/libSACenc/src/sacenc_bitstream.h new file mode 100644 index 0000000..67b7b5a --- /dev/null +++ b/libSACenc/src/sacenc_bitstream.h @@ -0,0 +1,296 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): + + Description: Encoder Library Interface + Bitstream Writer + +*******************************************************************************/ + +#ifndef SACENC_BITSTREAM_H +#define SACENC_BITSTREAM_H + +/* Includes ******************************************************************/ +#include "FDK_bitstream.h" +#include "FDK_matrixCalloc.h" +#include "sacenc_lib.h" +#include "sacenc_const.h" + +/* Defines *******************************************************************/ +#define MAX_NUM_BINS 23 +#define MAX_NUM_PARAMS 2 +#define MAX_NUM_OUTPUTCHANNELS SACENC_MAX_OUTPUT_CHANNELS +#define MAX_TIME_SLOTS 32 + +typedef enum { + TREE_212 = 7, + TREE_ESCAPE = 15 + +} TREECONFIG; + +typedef enum { + FREQ_RES_40 = 0, + FREQ_RES_20 = 1, + FREQ_RES_10 = 2, + FREQ_RES_5 = 3 + +} FREQ; + +typedef enum { + QUANTMODE_INVALID = -1, + QUANTMODE_FINE = 0, + QUANTMODE_EBQ1 = 1, + QUANTMODE_EBQ2 = 2 + +} QUANTMODE; + +typedef enum { + TEMPSHAPE_OFF = 0 + +} TEMPSHAPECONFIG; + +typedef enum { + FIXEDGAINDMX_INVALID = -1, + FIXEDGAINDMX_0 = 0, + FIXEDGAINDMX_1 = 1, + FIXEDGAINDMX_2 = 2, + FIXEDGAINDMX_3 = 3, + FIXEDGAINDMX_4 = 4, + FIXEDGAINDMX_5 = 5, + FIXEDGAINDMX_6 = 6, + FIXEDGAINDMX_7 = 7 + +} FIXEDGAINDMXCONFIG; + +typedef enum { + DECORR_INVALID = -1, + DECORR_QMFSPLIT0 = 0, /* QMF splitfreq: 3, 15, 24, 65 */ + DECORR_QMFSPLIT1 = 1, /* QMF splitfreq: 3, 50, 65, 65 */ + DECORR_QMFSPLIT2 = 2 /* QMF splitfreq: 0, 15, 65, 65 */ + +} DECORRCONFIG; + +typedef enum { + DEFAULT = 0, + KEEP = 1, + INTERPOLATE = 2, + FINECOARSE = 3 + +} DATA_MODE; + +typedef enum { + READ_SPATIALFRAME = 0, + WRITE_SPATIALFRAME = 1 + +} SPATIALFRAME_TYPE; + +/* Data Types ****************************************************************/ +typedef struct { + INT numOttBoxes; + INT numInChan; + INT numOutChan; + +} TREEDESCRIPTION; + +typedef struct { + INT bsOttBands; + +} OTTCONFIG; + +typedef struct { + INT bsSamplingFrequency; /* for bsSamplingFrequencyIndex */ + INT bsFrameLength; + INT numBands; /* for bsFreqRes */ + TREECONFIG bsTreeConfig; + QUANTMODE bsQuantMode; + FIXEDGAINDMXCONFIG bsFixedGainDMX; + int bsEnvQuantMode; + DECORRCONFIG bsDecorrConfig; + TREEDESCRIPTION treeDescription; + OTTCONFIG ottConfig[SACENC_MAX_NUM_BOXES]; + +} SPATIALSPECIFICCONFIG; + +typedef struct { + UCHAR bsFramingType; + UCHAR numParamSets; + UCHAR bsParamSlots[MAX_NUM_PARAMS]; + +} FRAMINGINFO; + +typedef struct { + SCHAR cld[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS][MAX_NUM_BINS]; + SCHAR icc[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS][MAX_NUM_BINS]; + +} OTTDATA; + +typedef struct { + UCHAR bsSmoothMode[MAX_NUM_PARAMS]; + UCHAR bsSmoothTime[MAX_NUM_PARAMS]; + UCHAR bsFreqResStride[MAX_NUM_PARAMS]; + UCHAR bsSmgData[MAX_NUM_PARAMS][MAX_NUM_BINS]; + +} SMGDATA; + +typedef struct { + UCHAR bsEnvShapeChannel[MAX_NUM_OUTPUTCHANNELS]; + UCHAR bsEnvShapeData[MAX_NUM_OUTPUTCHANNELS][MAX_TIME_SLOTS]; + +} TEMPSHAPEDATA; + +typedef struct { + UCHAR bsXXXDataMode[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + UCHAR bsDataPair[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + UCHAR bsQuantCoarseXXX[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + UCHAR bsFreqResStrideXXX[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + +} LOSSLESSDATA; + +typedef struct { + FRAMINGINFO framingInfo; + UCHAR bsIndependencyFlag; + OTTDATA ottData; + SMGDATA smgData; + TEMPSHAPEDATA tempShapeData; + LOSSLESSDATA CLDLosslessData; + LOSSLESSDATA ICCLosslessData; + UCHAR bUseBBCues; + +} SPATIALFRAME; + +typedef struct BSF_INSTANCE *HANDLE_BSF_INSTANCE; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +/* destroy encoder instance */ +FDK_SACENC_ERROR fdk_sacenc_destroySpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE *selfPtr); + +/* create encoder instance */ +FDK_SACENC_ERROR fdk_sacenc_createSpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE *selfPtr); + +FDK_SACENC_ERROR fdk_sacenc_initSpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE selfPtr); + +/* get SpatialSpecificConfig struct */ +SPATIALSPECIFICCONFIG *fdk_sacenc_getSpatialSpecificConfig( + HANDLE_BSF_INSTANCE selfPtr); + +/* write SpatialSpecificConfig to stream */ +FDK_SACENC_ERROR fdk_sacenc_writeSpatialSpecificConfig( + SPATIALSPECIFICCONFIG *const spatialSpecificConfig, + UCHAR *const pOutputBuffer, const INT outputBufferSize, + INT *const pnOutputBits); + +/* get SpatialFrame struct */ +SPATIALFRAME *fdk_sacenc_getSpatialFrame(HANDLE_BSF_INSTANCE selfPtr, + const SPATIALFRAME_TYPE frameType); + +/* write frame data to stream */ +FDK_SACENC_ERROR fdk_sacenc_writeSpatialFrame(UCHAR *const pOutputBuffer, + const INT outputBufferSize, + INT *const pnOutputBits, + HANDLE_BSF_INSTANCE selfPtr); + +/* Copy/Save spatial frame data for one parameter set */ +FDK_SACENC_ERROR fdk_sacenc_duplicateParameterSet( + const SPATIALFRAME *const hFrom, const INT setFrom, SPATIALFRAME *const hTo, + const INT setTo); + +#endif /* SACENC_BITSTREAM_H */ diff --git a/libSACenc/src/sacenc_const.h b/libSACenc/src/sacenc_const.h new file mode 100644 index 0000000..c86e765 --- /dev/null +++ b/libSACenc/src/sacenc_const.h @@ -0,0 +1,126 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Markus Multrus + + Description: Encoder Library Interface + constants to MPEG-4 spatial encoder lib + +*******************************************************************************/ + +#ifndef SACENC_CONST_H +#define SACENC_CONST_H + +/* Includes ******************************************************************/ +#include "machine_type.h" + +/* Defines *******************************************************************/ +#define NUM_QMF_BANDS 64 +#define MAX_QMF_BANDS 128 + +#define SACENC_MAX_NUM_BOXES 1 +#define SACENC_MAX_INPUT_CHANNELS 2 +#define SACENC_MAX_OUTPUT_CHANNELS 1 + +#define SACENC_FLOAT_EPSILON (1e-9f) + +/* Data Types ****************************************************************/ + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +#endif /* SACENC_CONST_H */ diff --git a/libSACenc/src/sacenc_delay.cpp b/libSACenc/src/sacenc_delay.cpp new file mode 100644 index 0000000..f2ed6b0 --- /dev/null +++ b/libSACenc/src/sacenc_delay.cpp @@ -0,0 +1,472 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Christian Goettlinger + + Description: Encoder Library Interface + delay management of the encoder + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + This file contains all delay infrastructure + ******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_delay.h" +#include "sacenc_const.h" +#include "FDK_matrixCalloc.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ +struct DELAY { + struct DELAY_CONFIG { + /* Routing Config Switches*/ + INT bDmxAlign; + INT bTimeDomDmx; + INT bMinimizeDelay; + INT bSacTimeAlignmentDynamicOut; + + /* Needed Input Variables*/ + INT nQmfLen; + INT nFrameLen; + INT nSurroundDelay; + INT nArbDmxDelay; + INT nLimiterDelay; + INT nCoreCoderDelay; + INT nSacStreamMuxDelay; + INT nSacTimeAlignment; /* Overwritten, if bSacTimeAlignmentDynamicOut */ + } config; + + /* Variable Delaybuffers -> Delays */ + INT nDmxAlignBuffer; + INT nSurroundAnalysisBuffer; + INT nArbDmxAnalysisBuffer; + INT nOutputAudioBuffer; + INT nBitstreamFrameBuffer; + INT nOutputAudioQmfFrameBuffer; + INT nDiscardOutFrames; + + /* Variable Delaybuffers Computation Variables */ + INT nBitstreamFrameBufferSize; + + /* Output: Infos */ + INT nInfoDmxDelay; /* Delay of the downmixed signal after the space encoder */ + INT nInfoCodecDelay; /* Delay of the whole en-/decoder including CoreCoder */ + INT nInfoDecoderDelay; /* Delay of the Mpeg Surround decoder */ +}; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_delay_Open() +description: initializes Delays +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_delay_Open(HANDLE_DELAY *phDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == phDelay) { + error = SACENC_INVALID_HANDLE; + } else { + FDK_ALLOCATE_MEMORY_1D(*phDelay, 1, struct DELAY); + } + return error; + +bail: + fdk_sacenc_delay_Close(phDelay); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_delay_Close() +description: destructs Delay +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_delay_Close(HANDLE_DELAY *phDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == phDelay) { + error = SACENC_INVALID_HANDLE; + } else { + if (NULL != *phDelay) { + FDK_FREE_MEMORY_1D(*phDelay); + } + } + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_delay_Init(HANDLE_DELAY hDelay, const INT nQmfLen, + const INT nFrameLen, + const INT nCoreCoderDelay, + const INT nSacStreamMuxDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hDelay) { + error = SACENC_INVALID_HANDLE; + } else { + /* Fill structure before calculation */ + FDKmemclear(&hDelay->config, sizeof(hDelay->config)); + + hDelay->config.nQmfLen = nQmfLen; + hDelay->config.nFrameLen = nFrameLen; + hDelay->config.nCoreCoderDelay = nCoreCoderDelay; + hDelay->config.nSacStreamMuxDelay = nSacStreamMuxDelay; + } + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_delay_SubCalulateBufferDelays() +description: Calculates the Delays of the buffers +returns: Error Code +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_delay_SubCalulateBufferDelays(HANDLE_DELAY hDel) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hDel) { + error = SACENC_INVALID_HANDLE; + } else { + int nEncoderAnDelay, nEncoderSynDelay, nEncoderWinDelay, nDecoderAnDelay, + nDecoderSynDelay, nResidualCoderFrameDelay, + nArbDmxResidualCoderFrameDelay; + + if (hDel->config.bSacTimeAlignmentDynamicOut > 0) { + hDel->config.nSacTimeAlignment = 0; + } + + { + nEncoderAnDelay = + 2 * hDel->config.nQmfLen + + hDel->config.nQmfLen / 2; /* Only Ld-QMF Delay, no hybrid */ + nEncoderSynDelay = 1 * hDel->config.nQmfLen + hDel->config.nQmfLen / 2; + nDecoderAnDelay = 2 * hDel->config.nQmfLen + hDel->config.nQmfLen / 2; + nDecoderSynDelay = 1 * hDel->config.nQmfLen + hDel->config.nQmfLen / 2; + nEncoderWinDelay = + hDel->config.nFrameLen / 2; /* WindowLookahead is just half a frame */ + } + + { nResidualCoderFrameDelay = 0; } + + { nArbDmxResidualCoderFrameDelay = 0; } + + /* Calculate variable Buffer-Delays */ + if (hDel->config.bTimeDomDmx == 0) { + /* ArbitraryDmx and TdDmx off */ + int tempDelay; + + hDel->nSurroundAnalysisBuffer = 0; + hDel->nArbDmxAnalysisBuffer = 0; + tempDelay = nEncoderSynDelay + hDel->config.nLimiterDelay + + hDel->config.nCoreCoderDelay + + hDel->config.nSacTimeAlignment + nDecoderAnDelay; + tempDelay = (nResidualCoderFrameDelay * hDel->config.nFrameLen) + + hDel->config.nSacStreamMuxDelay - tempDelay; + + if (tempDelay > 0) { + hDel->nBitstreamFrameBuffer = 0; + hDel->nOutputAudioBuffer = tempDelay; + } else { + tempDelay = -tempDelay; + hDel->nBitstreamFrameBuffer = + (tempDelay + hDel->config.nFrameLen - 1) / hDel->config.nFrameLen; + hDel->nOutputAudioBuffer = + (hDel->nBitstreamFrameBuffer * hDel->config.nFrameLen) - tempDelay; + } + + hDel->nOutputAudioQmfFrameBuffer = + (hDel->nOutputAudioBuffer + (hDel->config.nQmfLen / 2) - 1) / + hDel->config.nQmfLen; + + if (hDel->config.bDmxAlign > 0) { + tempDelay = nEncoderWinDelay + nEncoderAnDelay + nEncoderSynDelay + + hDel->nOutputAudioBuffer + hDel->config.nLimiterDelay + + hDel->config.nCoreCoderDelay; + hDel->nDiscardOutFrames = + (tempDelay + hDel->config.nFrameLen - 1) / hDel->config.nFrameLen; + hDel->nDmxAlignBuffer = + hDel->nDiscardOutFrames * hDel->config.nFrameLen - tempDelay; + } else { + hDel->nDiscardOutFrames = 0; + hDel->nDmxAlignBuffer = 0; + } + + /* Output: Info-Variables */ + hDel->nInfoDmxDelay = hDel->nSurroundAnalysisBuffer + nEncoderAnDelay + + nEncoderWinDelay + nEncoderSynDelay + + hDel->nOutputAudioBuffer + + hDel->config.nLimiterDelay; + hDel->nInfoCodecDelay = + hDel->nInfoDmxDelay + hDel->config.nCoreCoderDelay + + hDel->config.nSacTimeAlignment + nDecoderAnDelay + nDecoderSynDelay; + + } else { + /* ArbitraryDmx or TdDmx on */ + int tempDelay1, tempDelay2, tempDelay12, tempDelay3; + + tempDelay1 = hDel->config.nArbDmxDelay - hDel->config.nSurroundDelay; + + if (tempDelay1 >= 0) { + hDel->nSurroundAnalysisBuffer = tempDelay1; + hDel->nArbDmxAnalysisBuffer = 0; + } else { + hDel->nSurroundAnalysisBuffer = 0; + hDel->nArbDmxAnalysisBuffer = -tempDelay1; + } + + tempDelay1 = nEncoderWinDelay + hDel->config.nSurroundDelay + + hDel->nSurroundAnalysisBuffer + + nEncoderAnDelay; /*Surround Path*/ + tempDelay2 = nEncoderWinDelay + hDel->config.nArbDmxDelay + + hDel->nArbDmxAnalysisBuffer + + nEncoderAnDelay; /* ArbDmx Compare Path */ + tempDelay3 = hDel->config.nArbDmxDelay + hDel->config.nLimiterDelay + + hDel->config.nCoreCoderDelay + + hDel->config.nSacTimeAlignment + + nDecoderAnDelay; /* ArbDmx Passthrough*/ + + tempDelay12 = + FDKmax(nResidualCoderFrameDelay, nArbDmxResidualCoderFrameDelay) * + hDel->config.nFrameLen; + tempDelay12 += hDel->config.nSacStreamMuxDelay; + + if (tempDelay1 > tempDelay2) { + tempDelay12 += tempDelay1; + } else { + tempDelay12 += tempDelay2; + } + + if (tempDelay3 > tempDelay12) { + if (hDel->config.bMinimizeDelay > 0) { + hDel->nBitstreamFrameBuffer = + (tempDelay3 - tempDelay12) / hDel->config.nFrameLen; /*floor*/ + hDel->nOutputAudioBuffer = 0; + hDel->nSurroundAnalysisBuffer += + (tempDelay3 - tempDelay12 - + (hDel->nBitstreamFrameBuffer * hDel->config.nFrameLen)); + hDel->nArbDmxAnalysisBuffer += + (tempDelay3 - tempDelay12 - + (hDel->nBitstreamFrameBuffer * hDel->config.nFrameLen)); + } else { + hDel->nBitstreamFrameBuffer = + ((tempDelay3 - tempDelay12) + hDel->config.nFrameLen - 1) / + hDel->config.nFrameLen; + hDel->nOutputAudioBuffer = + hDel->nBitstreamFrameBuffer * hDel->config.nFrameLen + + tempDelay12 - tempDelay3; + } + } else { + hDel->nBitstreamFrameBuffer = 0; + hDel->nOutputAudioBuffer = tempDelay12 - tempDelay3; + } + + if (hDel->config.bDmxAlign > 0) { + int tempDelay = hDel->config.nArbDmxDelay + hDel->nOutputAudioBuffer + + hDel->config.nLimiterDelay + + hDel->config.nCoreCoderDelay; + hDel->nDiscardOutFrames = + (tempDelay + hDel->config.nFrameLen - 1) / hDel->config.nFrameLen; + hDel->nDmxAlignBuffer = + hDel->nDiscardOutFrames * hDel->config.nFrameLen - tempDelay; + } else { + hDel->nDiscardOutFrames = 0; + hDel->nDmxAlignBuffer = 0; + } + + /* Output: Info-Variables */ + hDel->nInfoDmxDelay = hDel->config.nArbDmxDelay + + hDel->nOutputAudioBuffer + + hDel->config.nLimiterDelay; + hDel->nInfoCodecDelay = + hDel->nInfoDmxDelay + hDel->config.nCoreCoderDelay + + hDel->config.nSacTimeAlignment + nDecoderAnDelay + nDecoderSynDelay; + hDel->nInfoDecoderDelay = nDecoderAnDelay + nDecoderSynDelay; + + } /* ArbitraryDmx or TdDmx on */ + + /* Additonal Variables needed for Computation Issues */ + hDel->nBitstreamFrameBufferSize = hDel->nBitstreamFrameBuffer + 1; + } + + return error; +} + +static FDK_SACENC_ERROR assignParameterInRange( + const INT startRange, /* including startRange */ + const INT stopRange, /* including stopRange */ + const INT value, /* value to write*/ + INT *const ptr /* destination pointer*/ +) { + FDK_SACENC_ERROR error = SACENC_INVALID_CONFIG; + + if ((startRange <= value) && (value <= stopRange)) { + *ptr = value; + error = SACENC_OK; + } + + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_delay_SetDmxAlign(HANDLE_DELAY hDelay, + const INT bDmxAlignIn) { + return (assignParameterInRange(0, 1, bDmxAlignIn, &hDelay->config.bDmxAlign)); +} + +FDK_SACENC_ERROR fdk_sacenc_delay_SetTimeDomDmx(HANDLE_DELAY hDelay, + const INT bTimeDomDmxIn) { + return ( + assignParameterInRange(0, 1, bTimeDomDmxIn, &hDelay->config.bTimeDomDmx)); +} + +FDK_SACENC_ERROR fdk_sacenc_delay_SetSacTimeAlignmentDynamicOut( + HANDLE_DELAY hDelay, const INT bSacTimeAlignmentDynamicOutIn) { + return (assignParameterInRange(0, 1, bSacTimeAlignmentDynamicOutIn, + &hDelay->config.bSacTimeAlignmentDynamicOut)); +} + +FDK_SACENC_ERROR fdk_sacenc_delay_SetNSacTimeAlignment( + HANDLE_DELAY hDelay, const INT nSacTimeAlignmentIn) { + return (assignParameterInRange(-32768, 32767, nSacTimeAlignmentIn, + &hDelay->config.nSacTimeAlignment)); +} + +FDK_SACENC_ERROR fdk_sacenc_delay_SetMinimizeDelay(HANDLE_DELAY hDelay, + const INT bMinimizeDelay) { + return (assignParameterInRange(0, 1, bMinimizeDelay, + &hDelay->config.bMinimizeDelay)); +} + +INT fdk_sacenc_delay_GetOutputAudioBufferDelay(HANDLE_DELAY hDelay) { + return (hDelay->nOutputAudioBuffer); +} + +INT fdk_sacenc_delay_GetSurroundAnalysisBufferDelay(HANDLE_DELAY hDelay) { + return (hDelay->nSurroundAnalysisBuffer); +} + +INT fdk_sacenc_delay_GetArbDmxAnalysisBufferDelay(HANDLE_DELAY hDelay) { + return (hDelay->nArbDmxAnalysisBuffer); +} + +INT fdk_sacenc_delay_GetBitstreamFrameBufferSize(HANDLE_DELAY hDelay) { + return (hDelay->nBitstreamFrameBufferSize); +} + +INT fdk_sacenc_delay_GetDmxAlignBufferDelay(HANDLE_DELAY hDelay) { + return (hDelay->nDmxAlignBuffer); +} + +INT fdk_sacenc_delay_GetDiscardOutFrames(HANDLE_DELAY hDelay) { + return (hDelay->nDiscardOutFrames); +} + +INT fdk_sacenc_delay_GetInfoDmxDelay(HANDLE_DELAY hDelay) { + return (hDelay->nInfoDmxDelay); +} + +INT fdk_sacenc_delay_GetInfoCodecDelay(HANDLE_DELAY hDelay) { + return (hDelay->nInfoCodecDelay); +} + +INT fdk_sacenc_delay_GetInfoDecoderDelay(HANDLE_DELAY hDelay) { + return (hDelay->nInfoDecoderDelay); +} diff --git a/libSACenc/src/sacenc_delay.h b/libSACenc/src/sacenc_delay.h new file mode 100644 index 0000000..38bfbc5 --- /dev/null +++ b/libSACenc/src/sacenc_delay.h @@ -0,0 +1,175 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Christian Goettlinger + + Description: Encoder Library Interface + delay management of the encoder + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + ******************************************************************************/ +#ifndef SACENC_DELAY_H +#define SACENC_DELAY_H + +/* Includes ******************************************************************/ +#include "sacenc_lib.h" +#include "machine_type.h" +#include "FDK_matrixCalloc.h" + +/* Defines *******************************************************************/ +#define MAX_DELAY_INPUT 1024 +#define MAX_DELAY_OUTPUT 4096 +/* bumped from 0 to 5. this should be equal or larger to the dualrate sbr + * resampler filter length */ +#define MAX_DELAY_SURROUND_ANALYSIS 5 +#define MAX_BITSTREAM_DELAY 1 + +/* Data Types ****************************************************************/ +typedef struct DELAY *HANDLE_DELAY; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_delay_Open(HANDLE_DELAY *phDelay); + +FDK_SACENC_ERROR fdk_sacenc_delay_Close(HANDLE_DELAY *phDelay); + +FDK_SACENC_ERROR fdk_sacenc_delay_Init(HANDLE_DELAY hDelay, const INT nQmfLen, + const INT nFrameLen, + const INT nCoreCoderDelay, + const INT nSacStreamMuxDelay); + +FDK_SACENC_ERROR fdk_sacenc_delay_SubCalulateBufferDelays(HANDLE_DELAY hDel); + +/* Set Expert Config Parameters */ +FDK_SACENC_ERROR fdk_sacenc_delay_SetDmxAlign(HANDLE_DELAY hDelay, + const INT bDmxAlignIn); + +FDK_SACENC_ERROR fdk_sacenc_delay_SetTimeDomDmx(HANDLE_DELAY hDelay, + const INT bTimeDomDmxIn); + +FDK_SACENC_ERROR fdk_sacenc_delay_SetSacTimeAlignmentDynamicOut( + HANDLE_DELAY hDelay, const INT bSacTimeAlignmentDynamicOutIn); + +FDK_SACENC_ERROR fdk_sacenc_delay_SetNSacTimeAlignment( + HANDLE_DELAY hDelay, const INT nSacTimeAlignmentIn); + +FDK_SACENC_ERROR fdk_sacenc_delay_SetMinimizeDelay(HANDLE_DELAY hDelay, + const INT bMinimizeDelay); + +/* Get Internal Variables */ +INT fdk_sacenc_delay_GetOutputAudioBufferDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetSurroundAnalysisBufferDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetArbDmxAnalysisBufferDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetBitstreamFrameBufferSize(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetDmxAlignBufferDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetDiscardOutFrames(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetInfoDmxDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetInfoCodecDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetInfoDecoderDelay(HANDLE_DELAY hDelay); + +#endif /* SACENC_DELAY_H */ diff --git a/libSACenc/src/sacenc_dmx_tdom_enh.cpp b/libSACenc/src/sacenc_dmx_tdom_enh.cpp new file mode 100644 index 0000000..be66c83 --- /dev/null +++ b/libSACenc/src/sacenc_dmx_tdom_enh.cpp @@ -0,0 +1,639 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Luis Valero + + Description: Enhanced Time Domain Downmix + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_dmx_tdom_enh.h" + +#include "FDK_matrixCalloc.h" +#include "FDK_trigFcts.h" +#include "fixpoint_math.h" + +/* Defines *******************************************************************/ +#define PI_FLT 3.1415926535897931f +#define ALPHA_FLT 0.0001f + +#define PI_E (2) +#define PI_M (FL2FXCONST_DBL(PI_FLT / (1 << PI_E))) + +#define ALPHA_E (13) +#define ALPHA_M (FL2FXCONST_DBL(ALPHA_FLT * (1 << ALPHA_E))) + +enum { L = 0, R = 1 }; + +/* Data Types ****************************************************************/ +typedef struct T_ENHANCED_TIME_DOMAIN_DMX { + int maxFramelength; + + int framelength; + + FIXP_DBL prev_gain_m[2]; + INT prev_gain_e; + FIXP_DBL prev_H1_m[2]; + INT prev_H1_e; + + FIXP_DBL *sinusWindow_m; + SCHAR sinusWindow_e; + + FIXP_DBL prev_Left_m; + INT prev_Left_e; + FIXP_DBL prev_Right_m; + INT prev_Right_e; + FIXP_DBL prev_XNrg_m; + INT prev_XNrg_e; + + FIXP_DBL lin_bbCld_weight_m; + INT lin_bbCld_weight_e; + FIXP_DBL gain_weight_m[2]; + INT gain_weight_e; + +} ENHANCED_TIME_DOMAIN_DMX; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +static void calculateRatio(const FIXP_DBL sqrt_linCld_m, + const INT sqrt_linCld_e, const FIXP_DBL lin_Cld_m, + const INT lin_Cld_e, const FIXP_DBL Icc_m, + const INT Icc_e, FIXP_DBL G_m[2], INT *G_e); + +static void calculateDmxGains(const FIXP_DBL lin_Cld_m, const INT lin_Cld_e, + const FIXP_DBL lin_Cld2_m, const INT lin_Cld2_e, + const FIXP_DBL Icc_m, const INT Icc_e, + const FIXP_DBL G_m[2], const INT G_e, + FIXP_DBL H1_m[2], INT *pH1_e); + +/* Function / Class Definition ***********************************************/ +static FIXP_DBL invSqrtNorm2(const FIXP_DBL op_m, const INT op_e, + INT *const result_e) { + FIXP_DBL src_m = op_m; + int src_e = op_e; + + if (src_e & 1) { + src_m >>= 1; + src_e += 1; + } + + src_m = invSqrtNorm2(src_m, result_e); + *result_e = (*result_e) - (src_e >> 1); + + return src_m; +} + +static FIXP_DBL sqrtFixp(const FIXP_DBL op_m, const INT op_e, + INT *const result_e) { + FIXP_DBL src_m = op_m; + int src_e = op_e; + + if (src_e & 1) { + src_m >>= 1; + src_e += 1; + } + + *result_e = (src_e >> 1); + return sqrtFixp(src_m); +} + +static FIXP_DBL fixpAdd(const FIXP_DBL src1_m, const INT src1_e, + const FIXP_DBL src2_m, const INT src2_e, + INT *const dst_e) { + FIXP_DBL dst_m; + + if (src1_m == FL2FXCONST_DBL(0.f)) { + *dst_e = src2_e; + dst_m = src2_m; + } else if (src2_m == FL2FXCONST_DBL(0.f)) { + *dst_e = src1_e; + dst_m = src1_m; + } else { + *dst_e = fixMax(src1_e, src2_e) + 1; + dst_m = + scaleValue(src1_m, fixMax((src1_e - (*dst_e)), -(DFRACT_BITS - 1))) + + scaleValue(src2_m, fixMax((src2_e - (*dst_e)), -(DFRACT_BITS - 1))); + } + return dst_m; +} + +/** + * \brief Sum up fixpoint values with best possible accuracy. + * + * \param value1 First input value. + * \param q1 Scaling factor of first input value. + * \param pValue2 Pointer to second input value, will be modified on + * return. + * \param pQ2 Pointer to second scaling factor, will be modified on + * return. + * + * \return void + */ +static void fixpAddNorm(const FIXP_DBL value1, const INT q1, + FIXP_DBL *const pValue2, INT *const pQ2) { + const int headroom1 = fNormz(fixp_abs(value1)) - 1; + const int headroom2 = fNormz(fixp_abs(*pValue2)) - 1; + int resultScale = fixMax(q1 - headroom1, (*pQ2) - headroom2); + + if ((value1 != FL2FXCONST_DBL(0.f)) && (*pValue2 != FL2FXCONST_DBL(0.f))) { + resultScale++; + } + + *pValue2 = + scaleValue(value1, q1 - resultScale) + + scaleValue(*pValue2, fixMax(-(DFRACT_BITS - 1), ((*pQ2) - resultScale))); + *pQ2 = (*pValue2 != (FIXP_DBL)0) ? resultScale : DFRACT_BITS - 1; +} + +FDK_SACENC_ERROR fdk_sacenc_open_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX *phEnhancedTimeDmx, const INT framelength) { + FDK_SACENC_ERROR error = SACENC_OK; + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx = NULL; + + if (NULL == phEnhancedTimeDmx) { + error = SACENC_INVALID_HANDLE; + } else { + FDK_ALLOCATE_MEMORY_1D(hEnhancedTimeDmx, 1, ENHANCED_TIME_DOMAIN_DMX); + FDK_ALLOCATE_MEMORY_1D(hEnhancedTimeDmx->sinusWindow_m, 1 + framelength, + FIXP_DBL); + hEnhancedTimeDmx->maxFramelength = framelength; + *phEnhancedTimeDmx = hEnhancedTimeDmx; + } + return error; + +bail: + fdk_sacenc_close_enhancedTimeDomainDmx(&hEnhancedTimeDmx); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_init_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx, + const FIXP_DBL *const pInputGain_m, const INT inputGain_e, + const FIXP_DBL outputGain_m, const INT outputGain_e, + const INT framelength) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (hEnhancedTimeDmx == NULL) { + error = SACENC_INVALID_HANDLE; + } else { + int smp; + if (framelength > hEnhancedTimeDmx->maxFramelength) { + error = SACENC_INIT_ERROR; + goto bail; + } + + hEnhancedTimeDmx->framelength = framelength; + + INT deltax_e; + FIXP_DBL deltax_m; + + deltax_m = fDivNormHighPrec( + PI_M, (FIXP_DBL)(2 * hEnhancedTimeDmx->framelength), &deltax_e); + deltax_m = scaleValue(deltax_m, PI_E + deltax_e - (DFRACT_BITS - 1) - 1); + deltax_e = 1; + + for (smp = 0; smp < hEnhancedTimeDmx->framelength + 1; smp++) { + hEnhancedTimeDmx->sinusWindow_m[smp] = + fMult(ALPHA_M, fPow2(fixp_sin(smp * deltax_m, deltax_e))); + } + hEnhancedTimeDmx->sinusWindow_e = -ALPHA_E; + + hEnhancedTimeDmx->prev_Left_m = hEnhancedTimeDmx->prev_Right_m = + hEnhancedTimeDmx->prev_XNrg_m = FL2FXCONST_DBL(0.f); + hEnhancedTimeDmx->prev_Left_e = hEnhancedTimeDmx->prev_Right_e = + hEnhancedTimeDmx->prev_XNrg_e = DFRACT_BITS - 1; + + hEnhancedTimeDmx->lin_bbCld_weight_m = + fDivNormHighPrec(fPow2(pInputGain_m[L]), fPow2(pInputGain_m[R]), + &hEnhancedTimeDmx->lin_bbCld_weight_e); + + hEnhancedTimeDmx->gain_weight_m[L] = fMult(pInputGain_m[L], outputGain_m); + hEnhancedTimeDmx->gain_weight_m[R] = fMult(pInputGain_m[R], outputGain_m); + hEnhancedTimeDmx->gain_weight_e = + -fNorm(fixMax(hEnhancedTimeDmx->gain_weight_m[L], + hEnhancedTimeDmx->gain_weight_m[R])); + + hEnhancedTimeDmx->gain_weight_m[L] = scaleValue( + hEnhancedTimeDmx->gain_weight_m[L], -hEnhancedTimeDmx->gain_weight_e); + hEnhancedTimeDmx->gain_weight_m[R] = scaleValue( + hEnhancedTimeDmx->gain_weight_m[R], -hEnhancedTimeDmx->gain_weight_e); + hEnhancedTimeDmx->gain_weight_e += inputGain_e + outputGain_e; + + hEnhancedTimeDmx->prev_gain_m[L] = hEnhancedTimeDmx->gain_weight_m[L] >> 1; + hEnhancedTimeDmx->prev_gain_m[R] = hEnhancedTimeDmx->gain_weight_m[R] >> 1; + hEnhancedTimeDmx->prev_gain_e = hEnhancedTimeDmx->gain_weight_e + 1; + + hEnhancedTimeDmx->prev_H1_m[L] = + scaleValue(hEnhancedTimeDmx->gain_weight_m[L], -4); + hEnhancedTimeDmx->prev_H1_m[R] = + scaleValue(hEnhancedTimeDmx->gain_weight_m[R], -4); + hEnhancedTimeDmx->prev_H1_e = 2 + 2 + hEnhancedTimeDmx->gain_weight_e; + } +bail: + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_apply_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx, + const INT_PCM *const *const inputTime, INT_PCM *const outputTimeDmx, + const INT InputDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hEnhancedTimeDmx) || (NULL == inputTime) || + (NULL == inputTime[L]) || (NULL == inputTime[R]) || + (NULL == outputTimeDmx)) { + error = SACENC_INVALID_HANDLE; + } else { + int smp; + FIXP_DBL lin_bbCld_m, lin_Cld_m, bbCorr_m, sqrt_linCld_m, G_m[2], H1_m[2], + gainLeft_m, gainRight_m; + FIXP_DBL bbNrgLeft_m, bbNrgRight_m, bbXNrg_m, nrgLeft_m, nrgRight_m, nrgX_m; + INT lin_bbCld_e, lin_Cld_e, bbCorr_e, sqrt_linCld_e, G_e, H1_e; + INT bbNrgLeft_e, bbNrgRight_e, bbXNrg_e, nrgLeft_e, nrgRight_e, nrgX_e; + + /* Increase energy time resolution with shorter processing blocks. 128 is an + * empiric value. */ + const int granuleLength = fixMin(128, hEnhancedTimeDmx->framelength); + int granuleShift = + (granuleLength > 1) + ? ((DFRACT_BITS - 1) - fNorm((FIXP_DBL)(granuleLength - 1))) + : 0; + granuleShift = fixMax( + 3, granuleShift + + 1); /* one bit more headroom for worst case accumulation */ + + smp = 0; + + /* Prevent division by zero. */ + bbNrgLeft_m = bbNrgRight_m = bbXNrg_m = (FIXP_DBL)(1); + bbNrgLeft_e = bbNrgRight_e = bbXNrg_e = 0; + + do { + const int offset = smp; + FIXP_DBL partialL, partialR, partialX; + partialL = partialR = partialX = FL2FXCONST_DBL(0.f); + + int in_margin = FDKmin( + getScalefactorPCM( + &inputTime[L][offset], + fixMin(offset + granuleLength, hEnhancedTimeDmx->framelength) - + offset, + 1), + getScalefactorPCM( + &inputTime[R][offset], + fixMin(offset + granuleLength, hEnhancedTimeDmx->framelength) - + offset, + 1)); + + /* partial energy */ + for (smp = offset; + smp < fixMin(offset + granuleLength, hEnhancedTimeDmx->framelength); + smp++) { + FIXP_PCM inputL = + scaleValue((FIXP_PCM)inputTime[L][smp], in_margin - 1); + FIXP_PCM inputR = + scaleValue((FIXP_PCM)inputTime[R][smp], in_margin - 1); + + partialL += fPow2Div2(inputL) >> (granuleShift - 3); + partialR += fPow2Div2(inputR) >> (granuleShift - 3); + partialX += fMultDiv2(inputL, inputR) >> (granuleShift - 3); + } + + fixpAddNorm(partialL, granuleShift - 2 * in_margin, &bbNrgLeft_m, + &bbNrgLeft_e); + fixpAddNorm(partialR, granuleShift - 2 * in_margin, &bbNrgRight_m, + &bbNrgRight_e); + fixpAddNorm(partialX, granuleShift - 2 * in_margin, &bbXNrg_m, &bbXNrg_e); + } while (smp < hEnhancedTimeDmx->framelength); + + nrgLeft_m = + fixpAdd(hEnhancedTimeDmx->prev_Left_m, hEnhancedTimeDmx->prev_Left_e, + bbNrgLeft_m, bbNrgLeft_e, &nrgLeft_e); + nrgRight_m = + fixpAdd(hEnhancedTimeDmx->prev_Right_m, hEnhancedTimeDmx->prev_Right_e, + bbNrgRight_m, bbNrgRight_e, &nrgRight_e); + nrgX_m = + fixpAdd(hEnhancedTimeDmx->prev_XNrg_m, hEnhancedTimeDmx->prev_XNrg_e, + bbXNrg_m, bbXNrg_e, &nrgX_e); + + lin_bbCld_m = fMult(hEnhancedTimeDmx->lin_bbCld_weight_m, + fDivNorm(nrgLeft_m, nrgRight_m, &lin_bbCld_e)); + lin_bbCld_e += + hEnhancedTimeDmx->lin_bbCld_weight_e + nrgLeft_e - nrgRight_e; + + bbCorr_m = fMult(nrgX_m, invSqrtNorm2(fMult(nrgLeft_m, nrgRight_m), + nrgLeft_e + nrgRight_e, &bbCorr_e)); + bbCorr_e += nrgX_e; + + hEnhancedTimeDmx->prev_Left_m = bbNrgLeft_m; + hEnhancedTimeDmx->prev_Left_e = bbNrgLeft_e; + hEnhancedTimeDmx->prev_Right_m = bbNrgRight_m; + hEnhancedTimeDmx->prev_Right_e = bbNrgRight_e; + hEnhancedTimeDmx->prev_XNrg_m = bbXNrg_m; + hEnhancedTimeDmx->prev_XNrg_e = bbXNrg_e; + + /* + bbCld = 10.f*log10(lin_bbCld) + + lin_Cld = pow(10,bbCld/20) + = pow(10,10.f*log10(lin_bbCld)/20.f) + = sqrt(lin_bbCld) + + lin_Cld2 = lin_Cld*lin_Cld + = sqrt(lin_bbCld)*sqrt(lin_bbCld) + = lin_bbCld + */ + lin_Cld_m = sqrtFixp(lin_bbCld_m, lin_bbCld_e, &lin_Cld_e); + sqrt_linCld_m = sqrtFixp(lin_Cld_m, lin_Cld_e, &sqrt_linCld_e); + + /*calculate how much right and how much left signal, to avoid signal + * cancellations*/ + calculateRatio(sqrt_linCld_m, sqrt_linCld_e, lin_Cld_m, lin_Cld_e, bbCorr_m, + bbCorr_e, G_m, &G_e); + + /*calculate downmix gains*/ + calculateDmxGains(lin_Cld_m, lin_Cld_e, lin_bbCld_m, lin_bbCld_e, bbCorr_m, + bbCorr_e, G_m, G_e, H1_m, &H1_e); + + /*adapt output gains*/ + H1_m[L] = fMult(H1_m[L], hEnhancedTimeDmx->gain_weight_m[L]); + H1_m[R] = fMult(H1_m[R], hEnhancedTimeDmx->gain_weight_m[R]); + H1_e += hEnhancedTimeDmx->gain_weight_e; + + gainLeft_m = hEnhancedTimeDmx->prev_gain_m[L]; + gainRight_m = hEnhancedTimeDmx->prev_gain_m[R]; + + INT intermediate_gain_e = + +hEnhancedTimeDmx->sinusWindow_e + H1_e - hEnhancedTimeDmx->prev_gain_e; + + for (smp = 0; smp < hEnhancedTimeDmx->framelength; smp++) { + const INT N = hEnhancedTimeDmx->framelength; + FIXP_DBL intermediate_gainLeft_m, intermediate_gainRight_m, tmp; + + intermediate_gainLeft_m = + scaleValue((fMult(hEnhancedTimeDmx->sinusWindow_m[smp], H1_m[L]) + + fMult(hEnhancedTimeDmx->sinusWindow_m[N - smp], + hEnhancedTimeDmx->prev_H1_m[L])), + intermediate_gain_e); + intermediate_gainRight_m = + scaleValue((fMult(hEnhancedTimeDmx->sinusWindow_m[smp], H1_m[R]) + + fMult(hEnhancedTimeDmx->sinusWindow_m[N - smp], + hEnhancedTimeDmx->prev_H1_m[R])), + intermediate_gain_e); + + gainLeft_m = intermediate_gainLeft_m + + fMult(FL2FXCONST_DBL(1.f - ALPHA_FLT), gainLeft_m); + gainRight_m = intermediate_gainRight_m + + fMult(FL2FXCONST_DBL(1.f - ALPHA_FLT), gainRight_m); + + tmp = fMultDiv2(gainLeft_m, (FIXP_PCM)inputTime[L][smp + InputDelay]) + + fMultDiv2(gainRight_m, (FIXP_PCM)inputTime[R][smp + InputDelay]); + outputTimeDmx[smp] = (INT_PCM)SATURATE_SHIFT( + tmp, + -(hEnhancedTimeDmx->prev_gain_e + 1 - (DFRACT_BITS - SAMPLE_BITS)), + SAMPLE_BITS); + } + + hEnhancedTimeDmx->prev_gain_m[L] = gainLeft_m; + hEnhancedTimeDmx->prev_gain_m[R] = gainRight_m; + + hEnhancedTimeDmx->prev_H1_m[L] = H1_m[L]; + hEnhancedTimeDmx->prev_H1_m[R] = H1_m[R]; + hEnhancedTimeDmx->prev_H1_e = H1_e; + } + + return error; +} + +static void calculateRatio(const FIXP_DBL sqrt_linCld_m, + const INT sqrt_linCld_e, const FIXP_DBL lin_Cld_m, + const INT lin_Cld_e, const FIXP_DBL Icc_m, + const INT Icc_e, FIXP_DBL G_m[2], INT *G_e) { +#define G_SCALE_FACTOR (2) + + if (Icc_m >= FL2FXCONST_DBL(0.f)) { + G_m[0] = G_m[1] = FL2FXCONST_DBL(1.f / (float)(1 << G_SCALE_FACTOR)); + G_e[0] = G_SCALE_FACTOR; + } else { + const FIXP_DBL max_gain_factor = + FL2FXCONST_DBL(2.f / (float)(1 << G_SCALE_FACTOR)); + FIXP_DBL tmp1_m, tmp2_m, numerator_m, denominator_m, r_m, r4_m, q; + INT tmp1_e, tmp2_e, numerator_e, denominator_e, r_e, r4_e; + + /* r = (lin_Cld + 1 + 2*Icc*sqrt_linCld) / (lin_Cld + 1 - + * 2*Icc*sqrt_linCld) = (tmp1 + tmp2) / (tmp1 - tmp2) + */ + tmp1_m = + fixpAdd(lin_Cld_m, lin_Cld_e, FL2FXCONST_DBL(1.f / 2.f), 1, &tmp1_e); + + tmp2_m = fMult(Icc_m, sqrt_linCld_m); + tmp2_e = 1 + Icc_e + sqrt_linCld_e; + numerator_m = fixpAdd(tmp1_m, tmp1_e, tmp2_m, tmp2_e, &numerator_e); + denominator_m = fixpAdd(tmp1_m, tmp1_e, -tmp2_m, tmp2_e, &denominator_e); + + if ((numerator_m > FL2FXCONST_DBL(0.f)) && + (denominator_m > FL2FXCONST_DBL(0.f))) { + r_m = fDivNorm(numerator_m, denominator_m, &r_e); + r_e += numerator_e - denominator_e; + + /* r_4 = sqrt( sqrt( r ) ) */ + r4_m = sqrtFixp(r_m, r_e, &r4_e); + r4_m = sqrtFixp(r4_m, r4_e, &r4_e); + + r4_e -= G_SCALE_FACTOR; + + /* q = min(r4_m, max_gain_factor) */ + q = ((r4_e >= 0) && (r4_m >= (max_gain_factor >> r4_e))) + ? max_gain_factor + : scaleValue(r4_m, r4_e); + } else { + q = FL2FXCONST_DBL(0.f); + } + + G_m[0] = max_gain_factor - q; + G_m[1] = q; + + *G_e = G_SCALE_FACTOR; + } +} + +static void calculateDmxGains(const FIXP_DBL lin_Cld_m, const INT lin_Cld_e, + const FIXP_DBL lin_Cld2_m, const INT lin_Cld2_e, + const FIXP_DBL Icc_m, const INT Icc_e, + const FIXP_DBL G_m[2], const INT G_e, + FIXP_DBL H1_m[2], INT *pH1_e) { +#define H1_SCALE_FACTOR (2) + const FIXP_DBL max_gain_factor = + FL2FXCONST_DBL(2.f / (float)(1 << H1_SCALE_FACTOR)); + + FIXP_DBL nrgRight_m, nrgLeft_m, crossNrg_m, inv_weight_num_m, + inv_weight_denom_m, inverse_weight_m, inverse_weight_limited; + INT nrgRight_e, nrgLeft_e, crossNrg_e, inv_weight_num_e, inv_weight_denom_e, + inverse_weight_e; + + /* nrgRight = sqrt(1/(lin_Cld2 + 1) */ + nrgRight_m = fixpAdd(lin_Cld2_m, lin_Cld2_e, FL2FXCONST_DBL(1.f / 2.f), 1, + &nrgRight_e); + nrgRight_m = invSqrtNorm2(nrgRight_m, nrgRight_e, &nrgRight_e); + + /* nrgLeft = lin_Cld * nrgRight */ + nrgLeft_m = fMult(lin_Cld_m, nrgRight_m); + nrgLeft_e = lin_Cld_e + nrgRight_e; + + /* crossNrg = sqrt(nrgLeft*nrgRight) */ + crossNrg_m = sqrtFixp(fMult(nrgLeft_m, nrgRight_m), nrgLeft_e + nrgRight_e, + &crossNrg_e); + + /* inverse_weight = sqrt((nrgLeft + nrgRight) / ( (G[0]*G[0]*nrgLeft) + + * (G[1]*G[1]*nrgRight) + 2*G[0]*G[1]*Icc*crossNrg)) = sqrt(inv_weight_num / + * inv_weight_denom) + */ + inv_weight_num_m = + fixpAdd(nrgRight_m, nrgRight_e, nrgLeft_m, nrgLeft_e, &inv_weight_num_e); + + inv_weight_denom_m = + fixpAdd(fMult(fPow2(G_m[0]), nrgLeft_m), 2 * G_e + nrgLeft_e, + fMult(fPow2(G_m[1]), nrgRight_m), 2 * G_e + nrgRight_e, + &inv_weight_denom_e); + + inv_weight_denom_m = + fixpAdd(fMult(fMult(fMult(G_m[0], G_m[1]), crossNrg_m), Icc_m), + 1 + 2 * G_e + crossNrg_e + Icc_e, inv_weight_denom_m, + inv_weight_denom_e, &inv_weight_denom_e); + + if (inv_weight_denom_m > FL2FXCONST_DBL(0.f)) { + inverse_weight_m = + fDivNorm(inv_weight_num_m, inv_weight_denom_m, &inverse_weight_e); + inverse_weight_m = + sqrtFixp(inverse_weight_m, + inverse_weight_e + inv_weight_num_e - inv_weight_denom_e, + &inverse_weight_e); + inverse_weight_e -= H1_SCALE_FACTOR; + + /* inverse_weight_limited = min(max_gain_factor, inverse_weight) */ + inverse_weight_limited = + ((inverse_weight_e >= 0) && + (inverse_weight_m >= (max_gain_factor >> inverse_weight_e))) + ? max_gain_factor + : scaleValue(inverse_weight_m, inverse_weight_e); + } else { + inverse_weight_limited = max_gain_factor; + } + + H1_m[0] = fMult(G_m[0], inverse_weight_limited); + H1_m[1] = fMult(G_m[1], inverse_weight_limited); + + *pH1_e = G_e + H1_SCALE_FACTOR; +} + +FDK_SACENC_ERROR fdk_sacenc_close_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX *phEnhancedTimeDmx) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (phEnhancedTimeDmx == NULL) { + error = SACENC_INVALID_HANDLE; + } else { + if (*phEnhancedTimeDmx != NULL) { + if ((*phEnhancedTimeDmx)->sinusWindow_m != NULL) { + FDK_FREE_MEMORY_1D((*phEnhancedTimeDmx)->sinusWindow_m); + } + FDK_FREE_MEMORY_1D(*phEnhancedTimeDmx); + } + } + return error; +} diff --git a/libSACenc/src/sacenc_dmx_tdom_enh.h b/libSACenc/src/sacenc_dmx_tdom_enh.h new file mode 100644 index 0000000..0b39911 --- /dev/null +++ b/libSACenc/src/sacenc_dmx_tdom_enh.h @@ -0,0 +1,134 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Luis Valero + + Description: Enhanced Time Domain Downmix + +*******************************************************************************/ + +#ifndef SACENC_DMX_TDOM_ENH_H +#define SACENC_DMX_TDOM_ENH_H + +/* Includes ******************************************************************/ +#include "sacenc_lib.h" +#include "common_fix.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ +typedef struct T_ENHANCED_TIME_DOMAIN_DMX *HANDLE_ENHANCED_TIME_DOMAIN_DMX; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_open_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX *hEnhancedTimeDmx, const INT framelength); + +FDK_SACENC_ERROR fdk_sacenc_init_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx, + const FIXP_DBL *const pInputGain_m, const INT inputGain_e, + const FIXP_DBL outputGain_m, const INT outputGain_e, const INT framelength); + +FDK_SACENC_ERROR fdk_sacenc_apply_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx, + const INT_PCM *const *const inputTime, INT_PCM *const outputTimeDmx, + const INT InputDelay); + +FDK_SACENC_ERROR fdk_sacenc_close_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX *hEnhancedTimeDmx); + +#endif /* SACENC_DMX_TDOM_ENH_H */ diff --git a/libSACenc/src/sacenc_filter.cpp b/libSACenc/src/sacenc_filter.cpp new file mode 100644 index 0000000..79f0797 --- /dev/null +++ b/libSACenc/src/sacenc_filter.cpp @@ -0,0 +1,207 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Multrus + + Description: Encoder Library + Filter functions + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_filter.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ +typedef struct T_DC_FILTER { + FIXP_DBL c__FDK; + FIXP_DBL state__FDK; + +} DC_FILTER; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +FDK_SACENC_ERROR fdk_sacenc_createDCFilter(HANDLE_DC_FILTER *hDCFilter) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hDCFilter) { + error = SACENC_INVALID_HANDLE; + } else { + FDK_ALLOCATE_MEMORY_1D(*hDCFilter, 1, DC_FILTER); + } + return error; + +bail: + fdk_sacenc_destroyDCFilter(hDCFilter); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_initDCFilter(HANDLE_DC_FILTER hDCFilter, + const UINT sampleRate) { + FDK_SACENC_ERROR error = SACENC_OK; + + FIXP_DBL expC; + int s; + + /* Conversion for use of CalcInvLdData: e^x = 2^(x*log10(e)/log10(2) = + CalcInvLdData(x*log10(e)/log10(2)/64.0) 1.44269504089 = log10(e)/log10(2) + 0.5 = scale constant value with 1 Bits + */ + expC = fDivNormHighPrec((FIXP_DBL)20, (FIXP_DBL)sampleRate, &s); + expC = fMultDiv2(FL2FXCONST_DBL(-1.44269504089 * 0.5), expC) >> + (LD_DATA_SHIFT - 1 - 1); + + if (s < 0) + expC = expC >> (-s); + else + expC = expC << (s); + + expC = CalcInvLdData(expC); + + hDCFilter->c__FDK = expC; + hDCFilter->state__FDK = FL2FXCONST_DBL(0.0f); + + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_destroyDCFilter(HANDLE_DC_FILTER *hDCFilter) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hDCFilter != NULL) && (*hDCFilter != NULL)) { + FDKfree(*hDCFilter); + + *hDCFilter = NULL; + } + + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_applyDCFilter(HANDLE_DC_FILTER hDCFilter, + const INT_PCM *const signalIn, + INT_PCM *const signalOut, + const INT signalLength) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hDCFilter == NULL) || (signalIn == NULL) || (signalOut == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + const INT_PCM *const x = signalIn; + INT_PCM *const y = signalOut; + const FIXP_DBL c = hDCFilter->c__FDK; + FIXP_DBL *const state = &hDCFilter->state__FDK; + int i; + FIXP_DBL x0, x1, y1; + + x1 = x0 = FX_PCM2FX_DBL(x[0]) >> DC_FILTER_SF; + y1 = x0 + (*state); + + for (i = 1; i < signalLength; i++) { + x0 = FX_PCM2FX_DBL(x[i]) >> DC_FILTER_SF; + y[i - 1] = FX_DBL2FX_PCM(y1); + y1 = x0 - x1 + fMult(c, y1); + x1 = x0; + } + + *state = fMult(c, y1) - x1; + y[i - 1] = FX_DBL2FX_PCM(y1); + } + + return error; +} diff --git a/libSACenc/src/sacenc_filter.h b/libSACenc/src/sacenc_filter.h new file mode 100644 index 0000000..10e3abd --- /dev/null +++ b/libSACenc/src/sacenc_filter.h @@ -0,0 +1,133 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Multrus + + Description: Encoder Library Interface + Filter functions + +*******************************************************************************/ + +#ifndef SACENC_FILTER_H +#define SACENC_FILTER_H + +/* Includes ******************************************************************/ +#include "common_fix.h" +#include "sacenc_lib.h" +#include "FDK_matrixCalloc.h" + +/* Defines *******************************************************************/ +#define DC_FILTER_SF 1 + +/* Data Types ****************************************************************/ +typedef struct T_DC_FILTER *HANDLE_DC_FILTER; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_createDCFilter(HANDLE_DC_FILTER *hDCFilter); + +FDK_SACENC_ERROR fdk_sacenc_initDCFilter(HANDLE_DC_FILTER hDCFilter, + const UINT sampleRate); + +FDK_SACENC_ERROR fdk_sacenc_destroyDCFilter(HANDLE_DC_FILTER *hDCFilter); + +FDK_SACENC_ERROR fdk_sacenc_applyDCFilter(HANDLE_DC_FILTER hDCFilter, + const INT_PCM *const signalIn, + INT_PCM *const signalOut, + const INT signalLength); + +#endif /* SACENC_FILTER_H */ diff --git a/libSACenc/src/sacenc_framewindowing.cpp b/libSACenc/src/sacenc_framewindowing.cpp new file mode 100644 index 0000000..15f0f0a --- /dev/null +++ b/libSACenc/src/sacenc_framewindowing.cpp @@ -0,0 +1,568 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Get windows for framing + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + Description of file contents + ******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_framewindowing.h" +#include "sacenc_vectorfunctions.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ +typedef struct T_FRAMEWINDOW { + INT nTimeSlotsMax; + INT bFrameKeep; + INT startSlope; + INT stopSlope; + INT startRect; + INT stopRect; + + INT taperAnaLen; + INT taperSynLen; + FIXP_WIN pTaperAna__FDK[MAX_TIME_SLOTS]; + FIXP_WIN pTaperSyn__FDK[MAX_TIME_SLOTS]; + +} FRAMEWINDOW; + +typedef enum { + FIX_INVALID = -1, + FIX_RECT_SMOOTH = 0, + FIX_SMOOTH_RECT = 1, + FIX_LARGE_SMOOTH = 2, + FIX_RECT_TRIANG = 3 + +} FIX_TYPE; + +typedef enum { + VAR_INVALID = -1, + VAR_HOLD = 0, + VAR_ISOLATE = 1 + +} VAR_TYPE; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static void calcTaperWin(FIXP_WIN *pTaperWin, INT timeSlots) { + FIXP_DBL x; + int i, scale; + + for (i = 0; i < timeSlots; i++) { + x = fDivNormHighPrec((FIXP_DBL)i, (FIXP_DBL)timeSlots, &scale); + + if (scale < 0) { + pTaperWin[i] = FX_DBL2FX_WIN(x >> (-scale)); + } else { + pTaperWin[i] = FX_DBL2FX_WIN(x << (scale)); + } + } + pTaperWin[timeSlots] = FX_DBL2FX_WIN((FIXP_DBL)MAXVAL_DBL); +} + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Create( + HANDLE_FRAMEWINDOW *phFrameWindow) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == phFrameWindow) { + error = SACENC_INVALID_HANDLE; + } else { + /* Memory Allocation */ + FDK_ALLOCATE_MEMORY_1D(*phFrameWindow, 1, FRAMEWINDOW); + } + return error; + +bail: + fdk_sacenc_frameWindow_Destroy(phFrameWindow); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Init( + HANDLE_FRAMEWINDOW hFrameWindow, + const FRAMEWINDOW_CONFIG *const pFrameWindowConfig) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hFrameWindow == NULL) || (pFrameWindowConfig == NULL)) { + error = SACENC_INVALID_HANDLE; + } else if (pFrameWindowConfig->nTimeSlotsMax < 0) { + error = SACENC_INIT_ERROR; + } else { + int ts; + hFrameWindow->bFrameKeep = pFrameWindowConfig->bFrameKeep; + hFrameWindow->nTimeSlotsMax = pFrameWindowConfig->nTimeSlotsMax; + + FIXP_WIN winMaxVal = FX_DBL2FX_WIN((FIXP_DBL)MAXVAL_DBL); + int timeSlots = pFrameWindowConfig->nTimeSlotsMax; + { + hFrameWindow->startSlope = 0; + hFrameWindow->stopSlope = ((3 * timeSlots) >> 1) - 1; + hFrameWindow->startRect = timeSlots >> 1; + hFrameWindow->stopRect = timeSlots; + calcTaperWin(hFrameWindow->pTaperSyn__FDK, timeSlots >> 1); + hFrameWindow->taperSynLen = timeSlots >> 1; + } + + /* Calculate Taper for non-rect. ana. windows */ + hFrameWindow->taperAnaLen = + hFrameWindow->startRect - hFrameWindow->startSlope; + for (ts = 0; ts < hFrameWindow->taperAnaLen; ts++) { + { hFrameWindow->pTaperAna__FDK[ts] = winMaxVal; } + } + } + + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Destroy( + HANDLE_FRAMEWINDOW *phFrameWindow) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL != phFrameWindow) && (NULL != *phFrameWindow)) { + FDKfree(*phFrameWindow); + *phFrameWindow = NULL; + } + return error; +} + +static FDK_SACENC_ERROR FrameWinList_Reset(FRAMEWIN_LIST *const pFrameWinList) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pFrameWinList) { + error = SACENC_INVALID_HANDLE; + } else { + int k = 0; + for (k = 0; k < MAX_NUM_PARAMS; k++) { + pFrameWinList->dat[k].slot = -1; + pFrameWinList->dat[k].hold = FW_INTP; + } + pFrameWinList->n = 0; + } + return error; +} + +static FDK_SACENC_ERROR FrameWindowList_Add(FRAMEWIN_LIST *const pFrameWinList, + const INT slot, + const FW_SLOTTYPE hold) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pFrameWinList) { + error = SACENC_INVALID_HANDLE; + } else { + if (pFrameWinList->n >= MAX_NUM_PARAMS) { /* Place left in List ?*/ + error = SACENC_PARAM_ERROR; + } else if (pFrameWinList->n > 0 && + pFrameWinList->dat[pFrameWinList->n - 1].slot - slot > 0) { + error = SACENC_PARAM_ERROR; + } else { + pFrameWinList->dat[pFrameWinList->n].slot = slot; + pFrameWinList->dat[pFrameWinList->n].hold = hold; + pFrameWinList->n++; + } + } + return error; +} + +static FDK_SACENC_ERROR FrameWindowList_Remove( + FRAMEWIN_LIST *const pFrameWinList, const INT idx) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pFrameWinList) { + error = SACENC_INVALID_HANDLE; + } else { + int k = 0; + if (idx < 0 || idx >= MAX_NUM_PARAMS) { + error = SACENC_PARAM_ERROR; + } else if (pFrameWinList->n > 0) { + if (idx == MAX_NUM_PARAMS - 1) { + pFrameWinList->dat[idx].slot = -1; + pFrameWinList->dat[idx].hold = FW_INTP; + } else { + for (k = idx; k < MAX_NUM_PARAMS - 1; k++) { + pFrameWinList->dat[k] = pFrameWinList->dat[k + 1]; + } + } + pFrameWinList->n--; + } + } + return error; +} + +static FDK_SACENC_ERROR FrameWindowList_Limit( + FRAMEWIN_LIST *const pFrameWinList, const INT ll /*lower limit*/, + const INT ul /*upper limit*/ +) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pFrameWinList) { + error = SACENC_INVALID_HANDLE; + } else { + int k = 0; + for (k = 0; k < pFrameWinList->n; k++) { + if (pFrameWinList->dat[k].slot < ll || pFrameWinList->dat[k].slot > ul) { + FrameWindowList_Remove(pFrameWinList, k); + --k; + } + } + } + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_GetWindow( + HANDLE_FRAMEWINDOW hFrameWindow, INT tr_pos[MAX_NUM_PARAMS], + const INT timeSlots, FRAMINGINFO *const pFramingInfo, + FIXP_WIN *pWindowAna__FDK[MAX_NUM_PARAMS], + FRAMEWIN_LIST *const pFrameWinList, const INT avoid_keep) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hFrameWindow == NULL) || (tr_pos == NULL) || (pFramingInfo == NULL) || + (pFrameWinList == NULL) || (pWindowAna__FDK == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + const VAR_TYPE varType = VAR_HOLD; + const int tranL = 4; + int winCnt = 0; + int w, ps; + + int startSlope = hFrameWindow->startSlope; + int stopSlope = hFrameWindow->stopSlope; + int startRect = hFrameWindow->startRect; + int stopRect = hFrameWindow->stopRect; + int taperAnaLen = hFrameWindow->taperAnaLen; + + FIXP_WIN winMaxVal = FX_DBL2FX_WIN((FIXP_DBL)MAXVAL_DBL); + FIXP_WIN applyRightWindowGain__FDK[MAX_NUM_PARAMS]; + FIXP_WIN *pTaperAna__FDK = hFrameWindow->pTaperAna__FDK; + + /* sanity check */ + for (ps = 0; ps < MAX_NUM_PARAMS; ps++) { + if (pWindowAna__FDK[ps] == NULL) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + } + + if ((timeSlots > hFrameWindow->nTimeSlotsMax) || (timeSlots < 0)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* Reset */ + if (SACENC_OK != (error = FrameWinList_Reset(pFrameWinList))) goto bail; + + FDKmemclear(applyRightWindowGain__FDK, sizeof(applyRightWindowGain__FDK)); + + if (tr_pos[0] > -1) { /* Transients in first (left) half? */ + int p_l = tr_pos[0]; + winCnt = 0; + + /* Create Parameter Positions */ + switch (varType) { + case VAR_HOLD: + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, p_l - 1, FW_HOLD))) + goto bail; + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, p_l, FW_INTP))) + goto bail; + break; + case VAR_ISOLATE: + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, p_l - 1, FW_HOLD))) + goto bail; + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, p_l, FW_INTP))) + goto bail; + if (SACENC_OK != (error = FrameWindowList_Add(pFrameWinList, + p_l + tranL, FW_HOLD))) + goto bail; + if (SACENC_OK != (error = FrameWindowList_Add( + pFrameWinList, p_l + tranL + 1, FW_INTP))) + goto bail; + break; + default: + error = SACENC_INVALID_CONFIG; + break; + } + + /* Outside of frame? => Kick Out */ + if (SACENC_OK != + (error = FrameWindowList_Limit(pFrameWinList, 0, timeSlots - 1))) + goto bail; + + /* Add timeSlots as temporary border for window creation */ + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, timeSlots - 1, FW_HOLD))) + goto bail; + + /* Create Windows */ + for (ps = 0; ps < pFrameWinList->n - 1; ps++) { + if (FW_HOLD != pFrameWinList->dat[ps].hold) { + int const start = pFrameWinList->dat[ps].slot; + int const stop = pFrameWinList->dat[ps + 1].slot; + + /* Analysis Window */ + FDKmemset_flex(pWindowAna__FDK[winCnt], FX_DBL2FX_WIN((FIXP_DBL)0), + start); + FDKmemset_flex(&pWindowAna__FDK[winCnt][start], winMaxVal, + stop - start + 1); + FDKmemset_flex(&pWindowAna__FDK[winCnt][stop + 1], + FX_DBL2FX_WIN((FIXP_DBL)0), timeSlots - stop - 1); + + applyRightWindowGain__FDK[winCnt] = + pWindowAna__FDK[winCnt][timeSlots - 1]; + winCnt++; + } + } /* ps */ + + /* Pop temporary frame border */ + if (SACENC_OK != + (error = FrameWindowList_Remove(pFrameWinList, pFrameWinList->n - 1))) + goto bail; + } else { /* No transient in left half of ana. window */ + winCnt = 0; + + /* Add paramter set at end of frame */ + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, timeSlots - 1, FW_INTP))) + goto bail; + /* Analysis Window */ + FDKmemset_flex(pWindowAna__FDK[winCnt], FX_DBL2FX_WIN((FIXP_DBL)0), + startSlope); + FDKmemcpy_flex(&pWindowAna__FDK[winCnt][startSlope], 1, pTaperAna__FDK, 1, + taperAnaLen); + FDKmemset_flex(&pWindowAna__FDK[winCnt][startRect], winMaxVal, + timeSlots - startRect); + + applyRightWindowGain__FDK[winCnt] = winMaxVal; + winCnt++; + } /* if (tr_pos[0] > -1) */ + + for (w = 0; w < winCnt; w++) { + if (applyRightWindowGain__FDK[w] > (FIXP_WIN)0) { + if (tr_pos[1] > -1) { /* Transients in second (right) half? */ + int p_r = tr_pos[1]; + + /* Analysis Window */ + FDKmemset_flex(&pWindowAna__FDK[w][timeSlots], winMaxVal, + p_r - timeSlots); + FDKmemset_flex(&pWindowAna__FDK[w][p_r], FX_DBL2FX_WIN((FIXP_DBL)0), + 2 * timeSlots - p_r); + + } else { /* No transient in right half of ana. window */ + /* Analysis Window */ + FDKmemset_flex(&pWindowAna__FDK[w][timeSlots], winMaxVal, + stopRect - timeSlots + 1); + FDKmemcpy_flex(&pWindowAna__FDK[w][stopRect], 1, + &pTaperAna__FDK[taperAnaLen - 1], -1, taperAnaLen); + FDKmemset_flex(&pWindowAna__FDK[w][stopSlope + 1], + FX_DBL2FX_WIN((FIXP_DBL)0), + 2 * timeSlots - stopSlope - 1); + + } /* if (tr_pos[1] > -1) */ + + /* Weight */ + if (applyRightWindowGain__FDK[w] < winMaxVal) { + int ts; + for (ts = 0; ts < timeSlots; ts++) { + pWindowAna__FDK[w][timeSlots + ts] = + FX_DBL2FX_WIN(fMult(pWindowAna__FDK[w][timeSlots + ts], + applyRightWindowGain__FDK[w])); + } + } + } /* if (applyRightWindowGain[w] > 0.0f) */ + else { + /* All Zero */ + FDKmemset_flex(&pWindowAna__FDK[w][timeSlots], + FX_DBL2FX_WIN((FIXP_DBL)0), timeSlots); + } + } /* loop over windows */ + + if (hFrameWindow->bFrameKeep == 1) { + FDKmemcpy_flex(&pWindowAna__FDK[0][2 * timeSlots], 1, + &pWindowAna__FDK[0][timeSlots], 1, timeSlots); + FDKmemcpy_flex(&pWindowAna__FDK[0][timeSlots], 1, pWindowAna__FDK[0], 1, + timeSlots); + + if (avoid_keep != 0) { + FDKmemset_flex(pWindowAna__FDK[0], FX_DBL2FX_WIN((FIXP_DBL)0), + timeSlots); + } else { + FDKmemset_flex(pWindowAna__FDK[0], winMaxVal, timeSlots); + } + } /* if (hFrameWindow->bFrameKeep==1) */ + + /* Feed Info to Bitstream Formatter */ + pFramingInfo->numParamSets = pFrameWinList->n; + pFramingInfo->bsFramingType = 1; /* variable framing */ + for (ps = 0; ps < pFramingInfo->numParamSets; ps++) { + pFramingInfo->bsParamSlots[ps] = pFrameWinList->dat[ps].slot; + } + + /* if there is just one param set at last slot, + use fixed framing to save some bits */ + if ((pFramingInfo->numParamSets == 1) && + (pFramingInfo->bsParamSlots[0] == timeSlots - 1)) { + pFramingInfo->bsFramingType = 0; + } + + } /* valid handle */ + +bail: + + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_analysisWindowing( + const INT nTimeSlots, const INT startTimeSlot, + FIXP_WIN *pFrameWindowAna__FDK, const FIXP_DPK *const *const ppDataIn__FDK, + FIXP_DPK *const *const ppDataOut__FDK, const INT nHybridBands, + const INT dim) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((pFrameWindowAna__FDK == NULL) || (ppDataIn__FDK == NULL) || + (ppDataOut__FDK == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int i, ts; + FIXP_WIN maxVal = FX_DBL2FX_WIN((FIXP_DBL)MAXVAL_DBL); + + if (dim == FW_CHANGE_DIM) { + for (ts = startTimeSlot; ts < nTimeSlots; ts++) { + FIXP_WIN win = pFrameWindowAna__FDK[ts]; + if (win == maxVal) { + for (i = 0; i < nHybridBands; i++) { + ppDataOut__FDK[i][ts].v.re = ppDataIn__FDK[ts][i].v.re; + ppDataOut__FDK[i][ts].v.im = ppDataIn__FDK[ts][i].v.im; + } + } else { + for (i = 0; i < nHybridBands; i++) { + ppDataOut__FDK[i][ts].v.re = fMult(win, ppDataIn__FDK[ts][i].v.re); + ppDataOut__FDK[i][ts].v.im = fMult(win, ppDataIn__FDK[ts][i].v.im); + } + } + } /* ts */ + } else { + for (ts = startTimeSlot; ts < nTimeSlots; ts++) { + FIXP_WIN win = pFrameWindowAna__FDK[ts]; + if (win == maxVal) { + for (i = 0; i < nHybridBands; i++) { + ppDataOut__FDK[ts][i].v.re = ppDataIn__FDK[ts][i].v.re; + ppDataOut__FDK[ts][i].v.im = ppDataIn__FDK[ts][i].v.im; + } + } else { + for (i = 0; i < nHybridBands; i++) { + ppDataOut__FDK[ts][i].v.re = fMult(win, ppDataIn__FDK[ts][i].v.re); + ppDataOut__FDK[ts][i].v.im = fMult(win, ppDataIn__FDK[ts][i].v.im); + } + } + } /* ts */ + } + } + + return error; +} diff --git a/libSACenc/src/sacenc_framewindowing.h b/libSACenc/src/sacenc_framewindowing.h new file mode 100644 index 0000000..6b22dc9 --- /dev/null +++ b/libSACenc/src/sacenc_framewindowing.h @@ -0,0 +1,181 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Get windows for framing + +*******************************************************************************/ + +#ifndef SACENC_FRAMEWINDOWING_H +#define SACENC_FRAMEWINDOWING_H + +/**************************************************************************/ /** + \file + Description of file contents + ******************************************************************************/ + +/* Includes ******************************************************************/ +#include "genericStds.h" +#include "common_fix.h" +#include "sacenc_lib.h" +#include "sacenc_bitstream.h" + +/* Defines *******************************************************************/ +#define FIXP_WIN FIXP_DBL +#define FX_DBL2FX_WIN(x) (x) +#define DALDATATYPE_WIN DALDATATYPE_DFRACT + +typedef enum { + FW_INTP = 0, + FW_HOLD = 1 + +} FW_SLOTTYPE; + +typedef enum { + FW_LEAVE_DIM = 0, + FW_CHANGE_DIM = 1 + +} FW_DIMENSION; + +/* Data Types ****************************************************************/ +typedef struct T_FRAMEWINDOW *HANDLE_FRAMEWINDOW; + +typedef struct T_FRAMEWINDOW_CONFIG { + INT nTimeSlotsMax; + INT bFrameKeep; + +} FRAMEWINDOW_CONFIG; + +typedef struct { + INT slot; + FW_SLOTTYPE hold; + +} FRAMEWIN_DATA; + +typedef struct { + FRAMEWIN_DATA dat[MAX_NUM_PARAMS]; + INT n; + +} FRAMEWIN_LIST; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Create( + HANDLE_FRAMEWINDOW *phFrameWindow); + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Init( + HANDLE_FRAMEWINDOW hFrameWindow, + const FRAMEWINDOW_CONFIG *const pFrameWindowConfig); + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Destroy( + HANDLE_FRAMEWINDOW *phFrameWindow); + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_GetWindow( + HANDLE_FRAMEWINDOW hFrameWindow, INT tr_pos[MAX_NUM_PARAMS], + const INT timeSlots, FRAMINGINFO *const pFramingInfo, + FIXP_WIN *pWindowAna__FDK[MAX_NUM_PARAMS], + FRAMEWIN_LIST *const pFrameWinList, const INT avoid_keep); + +FDK_SACENC_ERROR fdk_sacenc_analysisWindowing( + const INT nTimeSlots, const INT startTimeSlot, + FIXP_WIN *pFrameWindowAna__FDK, const FIXP_DPK *const *const ppDataIn__FDK, + FIXP_DPK *const *const ppDataOut__FDK, const INT nHybridBands, + const INT dim); + +#endif /* SACENC_FRAMEWINDOWING_H */ diff --git a/libSACenc/src/sacenc_huff_tab.cpp b/libSACenc/src/sacenc_huff_tab.cpp new file mode 100644 index 0000000..7b28ecd --- /dev/null +++ b/libSACenc/src/sacenc_huff_tab.cpp @@ -0,0 +1,997 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Markus Lohwasser + + Description: SAC-Encoder constant huffman tables + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_huff_tab.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ + +/* Constants *****************************************************************/ +const HUFF_CLD_TABLE fdk_sacenc_huffCLDTab = { + {/* h1D[2][31] */ + {HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000002, 2), + HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x000000fe, 8), + HUFF_PACK(0x000001fe, 9), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x000007fe, 11), HUFF_PACK(0x00000ffe, 12), + HUFF_PACK(0x00001ffe, 13), HUFF_PACK(0x00007ffe, 15), + HUFF_PACK(0x00007ffc, 15), HUFF_PACK(0x0000fffe, 16), + HUFF_PACK(0x0000fffa, 16), HUFF_PACK(0x0001fffe, 17), + HUFF_PACK(0x0001fff6, 17), HUFF_PACK(0x0003fffe, 18), + HUFF_PACK(0x0003ffff, 18), HUFF_PACK(0x0007ffde, 19), + HUFF_PACK(0x0003ffee, 18), HUFF_PACK(0x000fffbe, 20), + HUFF_PACK(0x001fff7e, 21), HUFF_PACK(0x00fffbfc, 24), + HUFF_PACK(0x00fffbfd, 24), HUFF_PACK(0x00fffbfe, 24), + HUFF_PACK(0x00fffbff, 24), HUFF_PACK(0x007ffdfc, 23), + HUFF_PACK(0x007ffdfd, 23)}, + {HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000002, 2), + HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x000001fc, 9), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x000003fa, 10), HUFF_PACK(0x000007fe, 11), + HUFF_PACK(0x000007f6, 11), HUFF_PACK(0x00000ffe, 12), + HUFF_PACK(0x00000fee, 12), HUFF_PACK(0x00001ffe, 13), + HUFF_PACK(0x00001fde, 13), HUFF_PACK(0x00003ffe, 14), + HUFF_PACK(0x00003fbe, 14), HUFF_PACK(0x00003fbf, 14), + HUFF_PACK(0x00007ffe, 15), HUFF_PACK(0x0000fffe, 16), + HUFF_PACK(0x0001fffe, 17), HUFF_PACK(0x0007fffe, 19), + HUFF_PACK(0x0007fffc, 19), HUFF_PACK(0x000ffffa, 20), + HUFF_PACK(0x001ffffc, 21), HUFF_PACK(0x001ffffd, 21), + HUFF_PACK(0x001ffffe, 21), HUFF_PACK(0x001fffff, 21), + HUFF_PACK(0x000ffffb, 20)}}, + { /* HUFF_CLD_TAB_2D */ + { /* HUFF_CLD_TAB_2D[0][] */ + {/* HUFF_CLD_TAB_2D[0][0] */ + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x00000002, 3), + HUFF_PACK(0x00000004, 5), HUFF_PACK(0x0000003e, 8)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000007, 4), + HUFF_PACK(0x0000000e, 6), HUFF_PACK(0x000000fe, 10)}, + {HUFF_PACK(0x0000007e, 9), HUFF_PACK(0x0000001e, 7), + HUFF_PACK(0x0000000c, 6), HUFF_PACK(0x00000005, 5)}, + {HUFF_PACK(0x000000ff, 10), HUFF_PACK(0x0000000d, 6), + HUFF_PACK(0x00000000, 3), HUFF_PACK(0x00000003, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000002, 3), HUFF_PACK(0x00000003, 3), + HUFF_PACK(0x00000010, 5), HUFF_PACK(0x0000007c, 7), + HUFF_PACK(0x000000d6, 8), HUFF_PACK(0x000003ee, 10)}, + {HUFF_PACK(0x0000000a, 4), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x00000016, 5), HUFF_PACK(0x00000034, 6), + HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x00001f7e, 13)}, + {HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x00000036, 6), + HUFF_PACK(0x00000026, 6), HUFF_PACK(0x00000046, 7), + HUFF_PACK(0x0000011e, 9), HUFF_PACK(0x000001f6, 9)}, + {HUFF_PACK(0x0000011f, 9), HUFF_PACK(0x000000d7, 8), + HUFF_PACK(0x0000008e, 8), HUFF_PACK(0x000000ff, 8), + HUFF_PACK(0x0000006a, 7), HUFF_PACK(0x0000004e, 7)}, + {HUFF_PACK(0x00000fbe, 12), HUFF_PACK(0x000007de, 11), + HUFF_PACK(0x0000004f, 7), HUFF_PACK(0x00000037, 6), + HUFF_PACK(0x00000017, 5), HUFF_PACK(0x0000001e, 5)}, + {HUFF_PACK(0x00001f7f, 13), HUFF_PACK(0x000000fa, 8), + HUFF_PACK(0x00000022, 6), HUFF_PACK(0x00000012, 5), + HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x0000007c, 7), + HUFF_PACK(0x000000be, 8), HUFF_PACK(0x0000017a, 9), + HUFF_PACK(0x000000ee, 9), HUFF_PACK(0x000007b6, 11)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x00000016, 5), HUFF_PACK(0x00000026, 6), + HUFF_PACK(0x0000003e, 7), HUFF_PACK(0x0000002e, 7), + HUFF_PACK(0x000001ec, 9), HUFF_PACK(0x000047ce, 15)}, + {HUFF_PACK(0x00000016, 6), HUFF_PACK(0x0000003c, 6), + HUFF_PACK(0x00000022, 6), HUFF_PACK(0x0000004e, 7), + HUFF_PACK(0x0000003f, 7), HUFF_PACK(0x0000005e, 8), + HUFF_PACK(0x000008fa, 12), HUFF_PACK(0x000008fb, 12)}, + {HUFF_PACK(0x0000005f, 8), HUFF_PACK(0x000000fa, 8), + HUFF_PACK(0x000000bf, 8), HUFF_PACK(0x0000003a, 7), + HUFF_PACK(0x000001f6, 9), HUFF_PACK(0x000001de, 10), + HUFF_PACK(0x000003da, 10), HUFF_PACK(0x000007b7, 11)}, + {HUFF_PACK(0x000001df, 10), HUFF_PACK(0x000003ee, 10), + HUFF_PACK(0x0000017b, 9), HUFF_PACK(0x000003ef, 10), + HUFF_PACK(0x000001ee, 9), HUFF_PACK(0x0000008e, 8), + HUFF_PACK(0x000001ef, 9), HUFF_PACK(0x000001fe, 9)}, + {HUFF_PACK(0x000008f8, 12), HUFF_PACK(0x0000047e, 11), + HUFF_PACK(0x0000047f, 11), HUFF_PACK(0x00000076, 8), + HUFF_PACK(0x0000003c, 7), HUFF_PACK(0x00000046, 7), + HUFF_PACK(0x0000007a, 7), HUFF_PACK(0x0000007e, 7)}, + {HUFF_PACK(0x000023e6, 14), HUFF_PACK(0x000011f2, 13), + HUFF_PACK(0x000001ff, 9), HUFF_PACK(0x0000003d, 7), + HUFF_PACK(0x0000004f, 7), HUFF_PACK(0x0000002e, 6), + HUFF_PACK(0x00000012, 5), HUFF_PACK(0x00000004, 4)}, + {HUFF_PACK(0x000047cf, 15), HUFF_PACK(0x0000011e, 9), + HUFF_PACK(0x000000bc, 8), HUFF_PACK(0x000000fe, 8), + HUFF_PACK(0x0000001c, 6), HUFF_PACK(0x00000010, 5), + HUFF_PACK(0x0000000d, 4), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV9_2D */ + {{HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000007, 4), + HUFF_PACK(0x00000006, 5), HUFF_PACK(0x0000007e, 7), + HUFF_PACK(0x0000000a, 7), HUFF_PACK(0x0000001e, 8), + HUFF_PACK(0x0000008a, 9), HUFF_PACK(0x0000004e, 10), + HUFF_PACK(0x00000276, 10), HUFF_PACK(0x000002e2, 11)}, + {HUFF_PACK(0x00000000, 4), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x00000016, 5), HUFF_PACK(0x00000026, 6), + HUFF_PACK(0x00000076, 7), HUFF_PACK(0x000000f2, 8), + HUFF_PACK(0x00000012, 8), HUFF_PACK(0x0000005e, 8), + HUFF_PACK(0x0000008b, 9), HUFF_PACK(0x00002e76, 15)}, + {HUFF_PACK(0x00000012, 6), HUFF_PACK(0x00000007, 5), + HUFF_PACK(0x00000038, 6), HUFF_PACK(0x0000007c, 7), + HUFF_PACK(0x00000008, 7), HUFF_PACK(0x00000046, 8), + HUFF_PACK(0x000000f6, 8), HUFF_PACK(0x000001ca, 9), + HUFF_PACK(0x0000173a, 14), HUFF_PACK(0x00001738, 14)}, + {HUFF_PACK(0x0000009e, 8), HUFF_PACK(0x0000004a, 7), + HUFF_PACK(0x00000026, 7), HUFF_PACK(0x0000000c, 7), + HUFF_PACK(0x0000004e, 8), HUFF_PACK(0x000000f7, 8), + HUFF_PACK(0x0000013a, 9), HUFF_PACK(0x0000009e, 11), + HUFF_PACK(0x000009fe, 12), HUFF_PACK(0x0000013e, 12)}, + {HUFF_PACK(0x00000026, 9), HUFF_PACK(0x0000001a, 8), + HUFF_PACK(0x000001e6, 9), HUFF_PACK(0x000001e2, 9), + HUFF_PACK(0x000000ee, 8), HUFF_PACK(0x000001ce, 9), + HUFF_PACK(0x00000277, 10), HUFF_PACK(0x000003ce, 10), + HUFF_PACK(0x000002e6, 11), HUFF_PACK(0x000004fc, 11)}, + {HUFF_PACK(0x000002e3, 11), HUFF_PACK(0x00000170, 10), + HUFF_PACK(0x00000172, 10), HUFF_PACK(0x000000ba, 9), + HUFF_PACK(0x0000003e, 9), HUFF_PACK(0x000001e3, 9), + HUFF_PACK(0x0000001b, 8), HUFF_PACK(0x0000003f, 9), + HUFF_PACK(0x0000009e, 9), HUFF_PACK(0x0000009f, 9)}, + {HUFF_PACK(0x00000b9e, 13), HUFF_PACK(0x000009ff, 12), + HUFF_PACK(0x000004fd, 11), HUFF_PACK(0x000004fe, 11), + HUFF_PACK(0x000001cf, 9), HUFF_PACK(0x000000ef, 8), + HUFF_PACK(0x00000044, 8), HUFF_PACK(0x0000005f, 8), + HUFF_PACK(0x000000e4, 8), HUFF_PACK(0x000000f0, 8)}, + {HUFF_PACK(0x00002e72, 15), HUFF_PACK(0x0000013f, 12), + HUFF_PACK(0x00000b9f, 13), HUFF_PACK(0x0000013e, 9), + HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x00000047, 8), + HUFF_PACK(0x0000000e, 7), HUFF_PACK(0x0000007d, 7), + HUFF_PACK(0x00000010, 6), HUFF_PACK(0x00000024, 6)}, + {HUFF_PACK(0x00002e77, 15), HUFF_PACK(0x00005ce6, 16), + HUFF_PACK(0x000000bb, 9), HUFF_PACK(0x000000e6, 8), + HUFF_PACK(0x00000016, 8), HUFF_PACK(0x000000ff, 8), + HUFF_PACK(0x0000007a, 7), HUFF_PACK(0x0000003a, 6), + HUFF_PACK(0x00000017, 5), HUFF_PACK(0x00000002, 4)}, + {HUFF_PACK(0x00005ce7, 16), HUFF_PACK(0x000003cf, 10), + HUFF_PACK(0x00000017, 8), HUFF_PACK(0x000001cb, 9), + HUFF_PACK(0x0000009c, 8), HUFF_PACK(0x0000004b, 7), + HUFF_PACK(0x00000016, 6), HUFF_PACK(0x0000000a, 5), + HUFF_PACK(0x00000008, 4), HUFF_PACK(0x00000006, 3)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }}, + {/* HUFF_CLD_TAB_2D[0][1] */ + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000076e, 11), HUFF_PACK(0x00000ede, 12)}, + {HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000003f, 6), + HUFF_PACK(0x000003b6, 10), HUFF_PACK(0x0000003a, 6)}, + {HUFF_PACK(0x0000001c, 5), HUFF_PACK(0x000000ee, 8), + HUFF_PACK(0x000001da, 9), HUFF_PACK(0x0000001e, 5)}, + {HUFF_PACK(0x000000ef, 8), HUFF_PACK(0x00000edf, 12), + HUFF_PACK(0x000000ec, 8), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000001c, 5), + HUFF_PACK(0x0000007e, 8), HUFF_PACK(0x00000efc, 12), + HUFF_PACK(0x0000effe, 16), HUFF_PACK(0x0001dffe, 17)}, + {HUFF_PACK(0x00000004, 3), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x0000003e, 7), HUFF_PACK(0x00000efe, 12), + HUFF_PACK(0x000077fe, 15), HUFF_PACK(0x00000076, 7)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000016, 5), + HUFF_PACK(0x000000be, 8), HUFF_PACK(0x00000efd, 12), + HUFF_PACK(0x000000ee, 8), HUFF_PACK(0x0000000e, 5)}, + {HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x0000002e, 6), + HUFF_PACK(0x000001de, 9), HUFF_PACK(0x000003be, 10), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x0000001e, 5)}, + {HUFF_PACK(0x0000007f, 7), HUFF_PACK(0x0000005e, 7), + HUFF_PACK(0x00003bfe, 14), HUFF_PACK(0x000000fe, 9), + HUFF_PACK(0x0000001e, 6), HUFF_PACK(0x00000002, 3)}, + {HUFF_PACK(0x000000bf, 8), HUFF_PACK(0x0001dfff, 17), + HUFF_PACK(0x00001dfe, 13), HUFF_PACK(0x000000ff, 9), + HUFF_PACK(0x0000003a, 6), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000002, 3), HUFF_PACK(0x0000001c, 5), + HUFF_PACK(0x000000bc, 8), HUFF_PACK(0x000005fc, 11), + HUFF_PACK(0x00005ffe, 15), HUFF_PACK(0x0002ffde, 18), + HUFF_PACK(0x000bff7e, 20), HUFF_PACK(0x0017feff, 21)}, + {HUFF_PACK(0x00000004, 3), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x0000000e, 7), HUFF_PACK(0x000002fa, 10), + HUFF_PACK(0x000001fe, 13), HUFF_PACK(0x0000bff2, 16), + HUFF_PACK(0x0005ffbe, 19), HUFF_PACK(0x000000ee, 8)}, + {HUFF_PACK(0x00000002, 4), HUFF_PACK(0x00000016, 5), + HUFF_PACK(0x000000f6, 8), HUFF_PACK(0x000005fe, 11), + HUFF_PACK(0x000001ff, 13), HUFF_PACK(0x0000bff6, 16), + HUFF_PACK(0x000001de, 9), HUFF_PACK(0x0000007e, 7)}, + {HUFF_PACK(0x00000000, 5), HUFF_PACK(0x0000003c, 6), + HUFF_PACK(0x0000000e, 8), HUFF_PACK(0x0000003e, 10), + HUFF_PACK(0x00002ffe, 14), HUFF_PACK(0x000002fb, 10), + HUFF_PACK(0x000000f7, 8), HUFF_PACK(0x0000002e, 6)}, + {HUFF_PACK(0x00000006, 6), HUFF_PACK(0x0000007a, 7), + HUFF_PACK(0x0000000a, 8), HUFF_PACK(0x0000007e, 11), + HUFF_PACK(0x000000fe, 12), HUFF_PACK(0x00000016, 9), + HUFF_PACK(0x00000006, 7), HUFF_PACK(0x00000002, 5)}, + {HUFF_PACK(0x0000000f, 7), HUFF_PACK(0x00000076, 7), + HUFF_PACK(0x00000017, 9), HUFF_PACK(0x00005ff8, 15), + HUFF_PACK(0x00000bfe, 12), HUFF_PACK(0x0000001e, 9), + HUFF_PACK(0x0000007f, 7), HUFF_PACK(0x00000003, 4)}, + {HUFF_PACK(0x00000004, 7), HUFF_PACK(0x000000bd, 8), + HUFF_PACK(0x0000bff3, 16), HUFF_PACK(0x00005fff, 15), + HUFF_PACK(0x00000bfa, 12), HUFF_PACK(0x0000017c, 9), + HUFF_PACK(0x0000003a, 6), HUFF_PACK(0x00000003, 3)}, + {HUFF_PACK(0x0000017e, 9), HUFF_PACK(0x0017fefe, 21), + HUFF_PACK(0x00017fee, 17), HUFF_PACK(0x00005ffa, 15), + HUFF_PACK(0x00000bfb, 12), HUFF_PACK(0x000001df, 9), + HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x00000006, 3)}}, + HUFF_PACK(0x0017feff, 21) /* escape */ + }, + { + /* LAV9_2D */ + {{HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x00000014, 5), + HUFF_PACK(0x0000008e, 8), HUFF_PACK(0x000004fe, 11), + HUFF_PACK(0x000023fe, 14), HUFF_PACK(0x00008ffe, 16), + HUFF_PACK(0x0005ffbc, 19), HUFF_PACK(0x0017fef7, 21), + HUFF_PACK(0x0017fef7, 21), HUFF_PACK(0x0017fef7, 21)}, + {HUFF_PACK(0x00000002, 3), HUFF_PACK(0x00000002, 4), + HUFF_PACK(0x00000044, 7), HUFF_PACK(0x0000027e, 10), + HUFF_PACK(0x000017fc, 13), HUFF_PACK(0x0000bff6, 16), + HUFF_PACK(0x0005ffbe, 19), HUFF_PACK(0x00011ff8, 17), + HUFF_PACK(0x000bff7a, 20), HUFF_PACK(0x000000bc, 8)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000016, 5), + HUFF_PACK(0x0000001a, 7), HUFF_PACK(0x000000fe, 10), + HUFF_PACK(0x000011f6, 13), HUFF_PACK(0x0000bffe, 16), + HUFF_PACK(0x00011ff9, 17), HUFF_PACK(0x0017fef6, 21), + HUFF_PACK(0x0000011e, 9), HUFF_PACK(0x00000056, 7)}, + {HUFF_PACK(0x00000010, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000009e, 8), HUFF_PACK(0x000007fe, 11), + HUFF_PACK(0x000011f7, 13), HUFF_PACK(0x00005ff8, 15), + HUFF_PACK(0x00017fee, 17), HUFF_PACK(0x000007ff, 11), + HUFF_PACK(0x000000ae, 8), HUFF_PACK(0x0000001e, 7)}, + {HUFF_PACK(0x00000026, 6), HUFF_PACK(0x0000000e, 6), + HUFF_PACK(0x000001ee, 9), HUFF_PACK(0x0000047e, 11), + HUFF_PACK(0x00000bfc, 12), HUFF_PACK(0x0000bfff, 16), + HUFF_PACK(0x000008fa, 12), HUFF_PACK(0x0000006e, 9), + HUFF_PACK(0x000001ef, 9), HUFF_PACK(0x0000007e, 7)}, + {HUFF_PACK(0x0000007a, 7), HUFF_PACK(0x0000004e, 7), + HUFF_PACK(0x0000007e, 9), HUFF_PACK(0x000000de, 10), + HUFF_PACK(0x000011fe, 13), HUFF_PACK(0x00002ffe, 14), + HUFF_PACK(0x000004ff, 11), HUFF_PACK(0x000000ff, 10), + HUFF_PACK(0x000000bd, 8), HUFF_PACK(0x0000002e, 6)}, + {HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x000000af, 8), + HUFF_PACK(0x000001ec, 9), HUFF_PACK(0x000001be, 11), + HUFF_PACK(0x00011ffe, 17), HUFF_PACK(0x00002ffa, 14), + HUFF_PACK(0x000008fe, 12), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x00000046, 7), HUFF_PACK(0x00000012, 5)}, + {HUFF_PACK(0x0000003e, 8), HUFF_PACK(0x00000045, 7), + HUFF_PACK(0x000002fe, 10), HUFF_PACK(0x000bff7e, 20), + HUFF_PACK(0x00005ff9, 15), HUFF_PACK(0x00005ffa, 15), + HUFF_PACK(0x00000bfd, 12), HUFF_PACK(0x0000013e, 9), + HUFF_PACK(0x0000000c, 6), HUFF_PACK(0x00000007, 4)}, + {HUFF_PACK(0x000000be, 8), HUFF_PACK(0x00000036, 8), + HUFF_PACK(0x000bff7f, 20), HUFF_PACK(0x00023ffe, 18), + HUFF_PACK(0x00011ffa, 17), HUFF_PACK(0x00005ffe, 15), + HUFF_PACK(0x000001bf, 11), HUFF_PACK(0x000001ed, 9), + HUFF_PACK(0x0000002a, 6), HUFF_PACK(0x00000000, 3)}, + {HUFF_PACK(0x0000017e, 9), HUFF_PACK(0x0017fef7, 21), + HUFF_PACK(0x00047ffe, 19), HUFF_PACK(0x00047fff, 19), + HUFF_PACK(0x00011ffb, 17), HUFF_PACK(0x00002ffb, 14), + HUFF_PACK(0x0000047c, 11), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x0000003c, 6), HUFF_PACK(0x00000006, 3)}}, + HUFF_PACK(0x0017fef7, 21) /* escape */ + }}}, + { /* HUFF_CLD_TAB_2D[1][] */ + {/* HUFF_CLD_TAB_2D[1][0] */ + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x0000001e, 5), + HUFF_PACK(0x000003be, 10), HUFF_PACK(0x00000efe, 12)}, + {HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000001c, 5), + HUFF_PACK(0x000001de, 9), HUFF_PACK(0x000000ea, 8)}, + {HUFF_PACK(0x00000074, 7), HUFF_PACK(0x000000ee, 8), + HUFF_PACK(0x000000eb, 8), HUFF_PACK(0x0000001f, 5)}, + {HUFF_PACK(0x0000077e, 11), HUFF_PACK(0x00000eff, 12), + HUFF_PACK(0x00000076, 7), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x00000006, 4), + HUFF_PACK(0x00000024, 7), HUFF_PACK(0x0000025e, 11), + HUFF_PACK(0x00003cfe, 14), HUFF_PACK(0x000079fe, 15)}, + {HUFF_PACK(0x00000006, 3), HUFF_PACK(0x00000007, 4), + HUFF_PACK(0x00000078, 7), HUFF_PACK(0x000003ce, 10), + HUFF_PACK(0x00001e7e, 13), HUFF_PACK(0x000000be, 9)}, + {HUFF_PACK(0x00000008, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x00000026, 7), HUFF_PACK(0x0000012e, 10), + HUFF_PACK(0x000000bf, 9), HUFF_PACK(0x0000002e, 7)}, + {HUFF_PACK(0x00000027, 7), HUFF_PACK(0x0000007a, 7), + HUFF_PACK(0x000001e4, 9), HUFF_PACK(0x00000096, 9), + HUFF_PACK(0x0000007b, 7), HUFF_PACK(0x0000003f, 6)}, + {HUFF_PACK(0x000001e6, 9), HUFF_PACK(0x000001e5, 9), + HUFF_PACK(0x00000f3e, 12), HUFF_PACK(0x0000005e, 8), + HUFF_PACK(0x00000016, 6), HUFF_PACK(0x0000000e, 4)}, + {HUFF_PACK(0x0000079e, 11), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x0000025f, 11), HUFF_PACK(0x0000004a, 8), + HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x00000006, 4), + HUFF_PACK(0x000000de, 8), HUFF_PACK(0x0000069e, 11), + HUFF_PACK(0x000034fe, 14), HUFF_PACK(0x0001a7fe, 17), + HUFF_PACK(0x00069ff6, 19), HUFF_PACK(0x00069ff7, 19)}, + {HUFF_PACK(0x00000002, 3), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x0000006a, 7), HUFF_PACK(0x0000034e, 10), + HUFF_PACK(0x00001fde, 13), HUFF_PACK(0x000069fe, 15), + HUFF_PACK(0x0001a7fc, 17), HUFF_PACK(0x00000372, 10)}, + {HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x0000003c, 6), + HUFF_PACK(0x000000df, 8), HUFF_PACK(0x000001ee, 10), + HUFF_PACK(0x00000dde, 12), HUFF_PACK(0x000069fa, 15), + HUFF_PACK(0x00000373, 10), HUFF_PACK(0x0000007a, 8)}, + {HUFF_PACK(0x0000003e, 7), HUFF_PACK(0x00000068, 7), + HUFF_PACK(0x000001ba, 9), HUFF_PACK(0x000003f6, 10), + HUFF_PACK(0x00000d3e, 12), HUFF_PACK(0x0000034c, 10), + HUFF_PACK(0x000001fa, 9), HUFF_PACK(0x000000d2, 8)}, + {HUFF_PACK(0x0000007e, 8), HUFF_PACK(0x0000007f, 8), + HUFF_PACK(0x000001f8, 9), HUFF_PACK(0x000006ee, 11), + HUFF_PACK(0x000003de, 11), HUFF_PACK(0x000001b8, 9), + HUFF_PACK(0x000001fc, 9), HUFF_PACK(0x0000006b, 7)}, + {HUFF_PACK(0x000000f6, 9), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x0000034d, 10), HUFF_PACK(0x00003fbe, 14), + HUFF_PACK(0x000007f6, 11), HUFF_PACK(0x000003fa, 10), + HUFF_PACK(0x0000003c, 7), HUFF_PACK(0x0000003d, 6)}, + {HUFF_PACK(0x000003f7, 10), HUFF_PACK(0x00000376, 10), + HUFF_PACK(0x0001a7ff, 17), HUFF_PACK(0x00003fbf, 14), + HUFF_PACK(0x00000ddf, 12), HUFF_PACK(0x000001f9, 9), + HUFF_PACK(0x00000036, 6), HUFF_PACK(0x0000000e, 4)}, + {HUFF_PACK(0x000003df, 11), HUFF_PACK(0x00034ffa, 18), + HUFF_PACK(0x000069fb, 15), HUFF_PACK(0x000034fc, 14), + HUFF_PACK(0x00000fee, 12), HUFF_PACK(0x000001ff, 9), + HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV9_2D */ + {{HUFF_PACK(0x00000006, 3), HUFF_PACK(0x00000004, 4), + HUFF_PACK(0x00000012, 7), HUFF_PACK(0x000007fe, 11), + HUFF_PACK(0x00001f7e, 13), HUFF_PACK(0x0000fbfe, 16), + HUFF_PACK(0x0001f7fe, 17), HUFF_PACK(0x000b7dfe, 21), + HUFF_PACK(0x000b7dff, 21), HUFF_PACK(0x000b7dff, 21)}, + {HUFF_PACK(0x00000000, 3), HUFF_PACK(0x00000006, 4), + HUFF_PACK(0x0000007c, 7), HUFF_PACK(0x00000046, 9), + HUFF_PACK(0x000007d0, 12), HUFF_PACK(0x00001f4e, 14), + HUFF_PACK(0x0000b7fe, 17), HUFF_PACK(0x00005bee, 16), + HUFF_PACK(0x00016fbe, 18), HUFF_PACK(0x000003ee, 10)}, + {HUFF_PACK(0x00000006, 5), HUFF_PACK(0x0000000a, 5), + HUFF_PACK(0x0000002e, 7), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x000007d2, 12), HUFF_PACK(0x00001f4f, 14), + HUFF_PACK(0x00002dfe, 15), HUFF_PACK(0x0000b7de, 17), + HUFF_PACK(0x000001fe, 10), HUFF_PACK(0x0000002e, 8)}, + {HUFF_PACK(0x0000007a, 7), HUFF_PACK(0x0000007e, 7), + HUFF_PACK(0x0000007a, 8), HUFF_PACK(0x000001fa, 10), + HUFF_PACK(0x000007fe, 12), HUFF_PACK(0x00001f7c, 13), + HUFF_PACK(0x000016fa, 14), HUFF_PACK(0x0000009e, 10), + HUFF_PACK(0x00000020, 8), HUFF_PACK(0x00000021, 8)}, + {HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x00000016, 7), + HUFF_PACK(0x000000fe, 9), HUFF_PACK(0x0000016e, 10), + HUFF_PACK(0x0000009f, 10), HUFF_PACK(0x00000b7c, 13), + HUFF_PACK(0x000003de, 11), HUFF_PACK(0x000000b6, 9), + HUFF_PACK(0x000000be, 9), HUFF_PACK(0x0000007c, 8)}, + {HUFF_PACK(0x0000005a, 8), HUFF_PACK(0x00000078, 8), + HUFF_PACK(0x00000047, 9), HUFF_PACK(0x00000044, 9), + HUFF_PACK(0x000007ff, 12), HUFF_PACK(0x000007d1, 12), + HUFF_PACK(0x000001f6, 10), HUFF_PACK(0x000001f7, 10), + HUFF_PACK(0x0000002f, 8), HUFF_PACK(0x0000002c, 7)}, + {HUFF_PACK(0x000000fc, 9), HUFF_PACK(0x000001f6, 9), + HUFF_PACK(0x000000f6, 9), HUFF_PACK(0x000007ff, 11), + HUFF_PACK(0x000016fe, 14), HUFF_PACK(0x000002de, 11), + HUFF_PACK(0x000003ea, 11), HUFF_PACK(0x000000bf, 9), + HUFF_PACK(0x000000fa, 8), HUFF_PACK(0x0000000a, 6)}, + {HUFF_PACK(0x0000004e, 9), HUFF_PACK(0x00000026, 8), + HUFF_PACK(0x000001ee, 10), HUFF_PACK(0x00005bfe, 16), + HUFF_PACK(0x00003efe, 14), HUFF_PACK(0x00000b7e, 13), + HUFF_PACK(0x000003eb, 11), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x0000007b, 7), HUFF_PACK(0x00000007, 5)}, + {HUFF_PACK(0x000001fb, 10), HUFF_PACK(0x00000045, 9), + HUFF_PACK(0x00016ffe, 18), HUFF_PACK(0x0001f7ff, 17), + HUFF_PACK(0x00002df6, 15), HUFF_PACK(0x00001f7d, 13), + HUFF_PACK(0x000003fe, 11), HUFF_PACK(0x0000005e, 8), + HUFF_PACK(0x0000003c, 6), HUFF_PACK(0x0000000e, 4)}, + {HUFF_PACK(0x000003df, 11), HUFF_PACK(0x0005befe, 20), + HUFF_PACK(0x0002df7e, 19), HUFF_PACK(0x00016fff, 18), + HUFF_PACK(0x00007dfe, 15), HUFF_PACK(0x00000fa6, 13), + HUFF_PACK(0x000007de, 11), HUFF_PACK(0x00000079, 8), + HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x000b7dff, 21) /* escape */ + }}, + {/* HUFF_CLD_TAB_2D[1][1] */ + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x000000fa, 8), HUFF_PACK(0x000007de, 11)}, + {HUFF_PACK(0x0000000c, 4), HUFF_PACK(0x0000001e, 5), + HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x000001f6, 9)}, + {HUFF_PACK(0x000000ff, 8), HUFF_PACK(0x0000007c, 7), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x0000001a, 5)}, + {HUFF_PACK(0x000007df, 11), HUFF_PACK(0x000003ee, 10), + HUFF_PACK(0x0000001b, 5), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000007c, 7), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x00000fbe, 12), HUFF_PACK(0x00003efe, 14)}, + {HUFF_PACK(0x00000000, 3), HUFF_PACK(0x00000001, 3), + HUFF_PACK(0x0000003c, 6), HUFF_PACK(0x0000005e, 8), + HUFF_PACK(0x000007de, 11), HUFF_PACK(0x000007be, 11)}, + {HUFF_PACK(0x0000001e, 6), HUFF_PACK(0x0000000a, 5), + HUFF_PACK(0x0000001f, 6), HUFF_PACK(0x0000005f, 8), + HUFF_PACK(0x000001ee, 9), HUFF_PACK(0x000001f6, 9)}, + {HUFF_PACK(0x000001fe, 9), HUFF_PACK(0x000000fe, 8), + HUFF_PACK(0x000000f6, 8), HUFF_PACK(0x000000fa, 8), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x00000016, 6)}, + {HUFF_PACK(0x000007bf, 11), HUFF_PACK(0x000003de, 10), + HUFF_PACK(0x000003ee, 10), HUFF_PACK(0x0000007a, 7), + HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x00000006, 4)}, + {HUFF_PACK(0x00003eff, 14), HUFF_PACK(0x00001f7e, 13), + HUFF_PACK(0x000003ff, 10), HUFF_PACK(0x0000002e, 7), + HUFF_PACK(0x00000004, 4), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000002, 3), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x0000001a, 6), HUFF_PACK(0x000001be, 9), + HUFF_PACK(0x000006e6, 11), HUFF_PACK(0x0000067a, 12), + HUFF_PACK(0x00000cf2, 13), HUFF_PACK(0x000033de, 15)}, + {HUFF_PACK(0x0000000c, 4), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x000000de, 8), + HUFF_PACK(0x00000372, 10), HUFF_PACK(0x000003d6, 11), + HUFF_PACK(0x00000678, 12), HUFF_PACK(0x00000cf6, 13)}, + {HUFF_PACK(0x00000036, 6), HUFF_PACK(0x00000012, 5), + HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x0000003c, 7), + HUFF_PACK(0x000001b8, 9), HUFF_PACK(0x000003d4, 11), + HUFF_PACK(0x0000033e, 11), HUFF_PACK(0x0000033f, 11)}, + {HUFF_PACK(0x0000007e, 8), HUFF_PACK(0x0000006a, 7), + HUFF_PACK(0x0000004e, 7), HUFF_PACK(0x0000007e, 7), + HUFF_PACK(0x000001ba, 9), HUFF_PACK(0x000000ce, 9), + HUFF_PACK(0x000000f6, 9), HUFF_PACK(0x000001ee, 10)}, + {HUFF_PACK(0x000001ef, 10), HUFF_PACK(0x0000013e, 9), + HUFF_PACK(0x0000007f, 8), HUFF_PACK(0x00000066, 8), + HUFF_PACK(0x000000d6, 8), HUFF_PACK(0x0000003e, 7), + HUFF_PACK(0x000000d7, 8), HUFF_PACK(0x0000009e, 8)}, + {HUFF_PACK(0x000007ae, 12), HUFF_PACK(0x000001e8, 10), + HUFF_PACK(0x000001e9, 10), HUFF_PACK(0x0000027e, 10), + HUFF_PACK(0x00000032, 7), HUFF_PACK(0x00000018, 6), + HUFF_PACK(0x00000026, 6), HUFF_PACK(0x00000034, 6)}, + {HUFF_PACK(0x00000cf3, 13), HUFF_PACK(0x000007aa, 12), + HUFF_PACK(0x000007ab, 12), HUFF_PACK(0x0000027f, 10), + HUFF_PACK(0x000001bf, 9), HUFF_PACK(0x0000001b, 6), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000000b, 4)}, + {HUFF_PACK(0x000033df, 15), HUFF_PACK(0x000019ee, 14), + HUFF_PACK(0x000007af, 12), HUFF_PACK(0x000006e7, 11), + HUFF_PACK(0x000001bb, 9), HUFF_PACK(0x0000007f, 7), + HUFF_PACK(0x00000008, 4), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV9_2D */ + {{HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x00000008, 4), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x000001ba, 10), HUFF_PACK(0x00000dbe, 12), + HUFF_PACK(0x00000d7e, 13), HUFF_PACK(0x00001af6, 14), + HUFF_PACK(0x00007fec, 15), HUFF_PACK(0x0001ffb6, 17)}, + {HUFF_PACK(0x0000000a, 4), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x0000000c, 5), HUFF_PACK(0x00000036, 7), + HUFF_PACK(0x000000de, 9), HUFF_PACK(0x000005fe, 11), + HUFF_PACK(0x000006be, 12), HUFF_PACK(0x00001b7e, 13), + HUFF_PACK(0x00007fee, 15), HUFF_PACK(0x00006dfe, 15)}, + {HUFF_PACK(0x0000001e, 6), HUFF_PACK(0x0000000e, 5), + HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x0000006a, 7), + HUFF_PACK(0x000001ae, 9), HUFF_PACK(0x000006fe, 11), + HUFF_PACK(0x00000376, 11), HUFF_PACK(0x00000dfe, 13), + HUFF_PACK(0x00000dff, 13), HUFF_PACK(0x00000d7f, 13)}, + {HUFF_PACK(0x000000b6, 8), HUFF_PACK(0x0000005e, 7), + HUFF_PACK(0x0000007c, 7), HUFF_PACK(0x0000006e, 7), + HUFF_PACK(0x0000006a, 8), HUFF_PACK(0x0000016a, 9), + HUFF_PACK(0x00000ffe, 12), HUFF_PACK(0x00000dfe, 12), + HUFF_PACK(0x00000ffc, 12), HUFF_PACK(0x00001bfe, 13)}, + {HUFF_PACK(0x0000035e, 10), HUFF_PACK(0x000001b6, 9), + HUFF_PACK(0x0000005e, 8), HUFF_PACK(0x000000b4, 8), + HUFF_PACK(0x0000006c, 7), HUFF_PACK(0x0000017e, 9), + HUFF_PACK(0x0000036e, 10), HUFF_PACK(0x000003ee, 10), + HUFF_PACK(0x0000037e, 11), HUFF_PACK(0x00000377, 11)}, + {HUFF_PACK(0x00000fff, 12), HUFF_PACK(0x000001ae, 10), + HUFF_PACK(0x000001be, 10), HUFF_PACK(0x000001f6, 9), + HUFF_PACK(0x000001be, 9), HUFF_PACK(0x000000da, 8), + HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x0000016b, 9), + HUFF_PACK(0x000000d6, 9), HUFF_PACK(0x0000037e, 10)}, + {HUFF_PACK(0x000017fe, 13), HUFF_PACK(0x00000bfe, 12), + HUFF_PACK(0x000007de, 11), HUFF_PACK(0x000006de, 11), + HUFF_PACK(0x000001b8, 10), HUFF_PACK(0x000000d6, 8), + HUFF_PACK(0x0000002e, 7), HUFF_PACK(0x00000034, 7), + HUFF_PACK(0x000000de, 8), HUFF_PACK(0x000000be, 8)}, + {HUFF_PACK(0x00007fef, 15), HUFF_PACK(0x000006bc, 12), + HUFF_PACK(0x00001bff, 13), HUFF_PACK(0x00001ffa, 13), + HUFF_PACK(0x000001b9, 10), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x000000fa, 8), HUFF_PACK(0x0000002e, 6), + HUFF_PACK(0x00000034, 6), HUFF_PACK(0x0000001f, 6)}, + {HUFF_PACK(0x00006dff, 15), HUFF_PACK(0x00001af7, 14), + HUFF_PACK(0x000036fe, 14), HUFF_PACK(0x000006fe, 12), + HUFF_PACK(0x00000fbe, 12), HUFF_PACK(0x0000035f, 10), + HUFF_PACK(0x000000b7, 8), HUFF_PACK(0x0000002c, 6), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x00000009, 4)}, + {HUFF_PACK(0x0001ffb7, 17), HUFF_PACK(0x0000ffda, 16), + HUFF_PACK(0x00000d7a, 13), HUFF_PACK(0x000017ff, 13), + HUFF_PACK(0x00000fbf, 12), HUFF_PACK(0x000002fe, 10), + HUFF_PACK(0x0000005f, 8), HUFF_PACK(0x00000016, 6), + HUFF_PACK(0x00000004, 4), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }}}}}; + +const HUFF_ICC_TABLE fdk_sacenc_huffICCTab = { + {/* h1D[2][8] */ + {HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000002, 2), + HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x0000007f, 7)}, + {HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000002, 2), + HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x0000007f, 7)}}, + { /* HUFF_ICC_TAB_2D */ + { /* HUFF_ICC_TAB_2D[0][] */ + {/* HUFF_ICC_TAB_2D[0][0] */ + { + /* LAV1_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000006, 3)}, + {HUFF_PACK(0x00000007, 3), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x00000000, 2), + HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x0000007e, 8)}, + {HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x00000004, 4), + HUFF_PACK(0x00000016, 6), HUFF_PACK(0x000003fe, 11)}, + {HUFF_PACK(0x000001fe, 10), HUFF_PACK(0x000000fe, 9), + HUFF_PACK(0x0000003e, 7), HUFF_PACK(0x0000001e, 6)}, + {HUFF_PACK(0x000003ff, 11), HUFF_PACK(0x00000017, 6), + HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000003, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x00000002, 3), + HUFF_PACK(0x0000000c, 5), HUFF_PACK(0x0000006a, 7), + HUFF_PACK(0x000000dc, 8), HUFF_PACK(0x000006ee, 11)}, + {HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x0000000d, 5), HUFF_PACK(0x0000001e, 6), + HUFF_PACK(0x000001ae, 9), HUFF_PACK(0x0000ddff, 16)}, + {HUFF_PACK(0x000000de, 8), HUFF_PACK(0x0000007e, 7), + HUFF_PACK(0x0000001f, 6), HUFF_PACK(0x000001be, 9), + HUFF_PACK(0x00006efe, 15), HUFF_PACK(0x0000ddfe, 16)}, + {HUFF_PACK(0x0000377e, 14), HUFF_PACK(0x00001bbe, 13), + HUFF_PACK(0x00000dde, 12), HUFF_PACK(0x000001bf, 9), + HUFF_PACK(0x000000d6, 8), HUFF_PACK(0x00000376, 10)}, + {HUFF_PACK(0x0000ddff, 16), HUFF_PACK(0x0000ddff, 16), + HUFF_PACK(0x000001ba, 9), HUFF_PACK(0x00000034, 6), + HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x0000000e, 5)}, + {HUFF_PACK(0x0000ddff, 16), HUFF_PACK(0x000001af, 9), + HUFF_PACK(0x0000007f, 7), HUFF_PACK(0x00000036, 6), + HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x0000ddff, 16) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x0000002e, 6), HUFF_PACK(0x00000044, 7), + HUFF_PACK(0x00000086, 8), HUFF_PACK(0x0000069e, 11), + HUFF_PACK(0x0000043e, 11), HUFF_PACK(0x0000087a, 12)}, + {HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000002a, 6), HUFF_PACK(0x00000046, 7), + HUFF_PACK(0x0000015e, 9), HUFF_PACK(0x00000047, 7), + HUFF_PACK(0x0000034a, 10), HUFF_PACK(0x0000087b, 12)}, + {HUFF_PACK(0x000000d6, 8), HUFF_PACK(0x00000026, 6), + HUFF_PACK(0x0000002f, 6), HUFF_PACK(0x000000d7, 8), + HUFF_PACK(0x0000006a, 7), HUFF_PACK(0x0000034e, 10), + HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12)}, + {HUFF_PACK(0x000002be, 10), HUFF_PACK(0x000001a6, 9), + HUFF_PACK(0x000001be, 9), HUFF_PACK(0x00000012, 5), + HUFF_PACK(0x000001bf, 9), HUFF_PACK(0x0000087b, 12), + HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12)}, + {HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12), + HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12), + HUFF_PACK(0x00000036, 6), HUFF_PACK(0x000000d0, 8), + HUFF_PACK(0x0000043c, 11), HUFF_PACK(0x0000043f, 11)}, + {HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12), + HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000034b, 10), + HUFF_PACK(0x00000027, 6), HUFF_PACK(0x00000020, 6), + HUFF_PACK(0x00000042, 7), HUFF_PACK(0x000000d1, 8)}, + {HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12), + HUFF_PACK(0x000002bf, 10), HUFF_PACK(0x000000de, 8), + HUFF_PACK(0x000000ae, 8), HUFF_PACK(0x00000056, 7), + HUFF_PACK(0x00000016, 5), HUFF_PACK(0x00000014, 5)}, + {HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000069f, 11), + HUFF_PACK(0x000001a4, 9), HUFF_PACK(0x0000010e, 9), + HUFF_PACK(0x00000045, 7), HUFF_PACK(0x0000006e, 7), + HUFF_PACK(0x0000001f, 5), HUFF_PACK(0x00000001, 2)}}, + HUFF_PACK(0x0000087b, 12) /* escape */ + }}, + {/* HUFF_ICC_TAB_2D[0][1] */ + { + /* LAV1_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000006, 3)}, + {HUFF_PACK(0x00000007, 3), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x00000004, 4), + HUFF_PACK(0x0000017e, 10), HUFF_PACK(0x000002fe, 11)}, + {HUFF_PACK(0x00000000, 2), HUFF_PACK(0x0000000e, 5), + HUFF_PACK(0x000000be, 9), HUFF_PACK(0x00000016, 6)}, + {HUFF_PACK(0x0000000f, 5), HUFF_PACK(0x00000014, 6), + HUFF_PACK(0x0000005e, 8), HUFF_PACK(0x00000006, 4)}, + {HUFF_PACK(0x0000002e, 7), HUFF_PACK(0x000002ff, 11), + HUFF_PACK(0x00000015, 6), HUFF_PACK(0x00000003, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x0000001e, 5), + HUFF_PACK(0x000003fc, 10), HUFF_PACK(0x0000fffa, 16), + HUFF_PACK(0x000fff9e, 20), HUFF_PACK(0x000fff9f, 20)}, + {HUFF_PACK(0x00000006, 3), HUFF_PACK(0x00000004, 4), + HUFF_PACK(0x000000be, 9), HUFF_PACK(0x00007ffe, 15), + HUFF_PACK(0x0007ffce, 19), HUFF_PACK(0x000000fe, 8)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x0000001e, 6), + HUFF_PACK(0x000003fd, 10), HUFF_PACK(0x0000fffb, 16), + HUFF_PACK(0x00000ffe, 12), HUFF_PACK(0x0000003e, 6)}, + {HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x0000007e, 7), + HUFF_PACK(0x00001ffe, 13), HUFF_PACK(0x00007fff, 15), + HUFF_PACK(0x0000005e, 8), HUFF_PACK(0x0000000e, 5)}, + {HUFF_PACK(0x0000001f, 6), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x0001fff2, 17), HUFF_PACK(0x00000ffc, 12), + HUFF_PACK(0x0000002e, 7), HUFF_PACK(0x0000000e, 4)}, + {HUFF_PACK(0x000000bf, 9), HUFF_PACK(0x0003ffe6, 18), + HUFF_PACK(0x0000fff8, 16), HUFF_PACK(0x00000ffd, 12), + HUFF_PACK(0x00000016, 6), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x0000001e, 6), + HUFF_PACK(0x00000ffe, 12), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000fffe, 16), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000ffff, 16)}, + {HUFF_PACK(0x00000006, 3), HUFF_PACK(0x00000008, 5), + HUFF_PACK(0x000007fe, 11), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000005a, 8)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x0000007a, 7), + HUFF_PACK(0x00000164, 10), HUFF_PACK(0x00007ffa, 15), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x00001fee, 13), HUFF_PACK(0x0000003c, 6)}, + {HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x000000fe, 8), + HUFF_PACK(0x000002ce, 11), HUFF_PACK(0x000002cf, 11), + HUFF_PACK(0x00007ffb, 15), HUFF_PACK(0x00001fec, 13), + HUFF_PACK(0x000000b0, 9), HUFF_PACK(0x0000002e, 7)}, + {HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x00000165, 10), HUFF_PACK(0x00007ffc, 15), + HUFF_PACK(0x00001fef, 13), HUFF_PACK(0x000007fa, 11), + HUFF_PACK(0x000007f8, 11), HUFF_PACK(0x0000001f, 6)}, + {HUFF_PACK(0x0000002f, 7), HUFF_PACK(0x000000f6, 8), + HUFF_PACK(0x00001fed, 13), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x00007ffd, 15), HUFF_PACK(0x00000ff2, 12), + HUFF_PACK(0x000000b1, 9), HUFF_PACK(0x0000000a, 5)}, + {HUFF_PACK(0x00000009, 5), HUFF_PACK(0x00000166, 10), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x00007ffe, 15), HUFF_PACK(0x00003ffc, 14), + HUFF_PACK(0x0000005b, 8), HUFF_PACK(0x0000000e, 4)}, + {HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x00000ff3, 12), + HUFF_PACK(0x000000f7, 8), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x0000ffff, 16) /* escape */ + }}}, + { /* HUFF_ICC_TAB_2D[1][] */ + {/* HUFF_ICC_TAB_2D[1][0] */ + { + /* LAV1_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000006, 3)}, + {HUFF_PACK(0x00000007, 3), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000037e, 10), HUFF_PACK(0x00000dfe, 12)}, + {HUFF_PACK(0x0000000f, 4), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x000001ba, 9), HUFF_PACK(0x000001bb, 9)}, + {HUFF_PACK(0x000000de, 8), HUFF_PACK(0x000000dc, 8), + HUFF_PACK(0x000001be, 9), HUFF_PACK(0x0000001a, 5)}, + {HUFF_PACK(0x000006fe, 11), HUFF_PACK(0x00000dff, 12), + HUFF_PACK(0x00000036, 6), HUFF_PACK(0x00000000, 1)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x000001b6, 9), HUFF_PACK(0x00001b7c, 13), + HUFF_PACK(0x0000dbfe, 16), HUFF_PACK(0x00036fff, 18)}, + {HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x0000001e, 5), + HUFF_PACK(0x000001be, 9), HUFF_PACK(0x00000dfe, 12), + HUFF_PACK(0x00036ffe, 18), HUFF_PACK(0x0000036e, 10)}, + {HUFF_PACK(0x0000006e, 7), HUFF_PACK(0x000000fe, 8), + HUFF_PACK(0x000000d8, 8), HUFF_PACK(0x000036fe, 14), + HUFF_PACK(0x000006de, 11), HUFF_PACK(0x000000de, 8)}, + {HUFF_PACK(0x000001fa, 9), HUFF_PACK(0x000000da, 8), + HUFF_PACK(0x00000dff, 12), HUFF_PACK(0x00001b7e, 13), + HUFF_PACK(0x000000d9, 8), HUFF_PACK(0x000000ff, 8)}, + {HUFF_PACK(0x000003f6, 10), HUFF_PACK(0x000006fe, 11), + HUFF_PACK(0x00006dfe, 15), HUFF_PACK(0x0000037e, 10), + HUFF_PACK(0x000000fc, 8), HUFF_PACK(0x0000001a, 5)}, + {HUFF_PACK(0x000007ee, 11), HUFF_PACK(0x0001b7fe, 17), + HUFF_PACK(0x00001b7d, 13), HUFF_PACK(0x000007ef, 11), + HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00036fff, 18) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x000007ee, 11), HUFF_PACK(0x00001e7e, 13), + HUFF_PACK(0x00003cfe, 14), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x000079ff, 15)}, + {HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x0000001a, 5), + HUFF_PACK(0x000001e6, 9), HUFF_PACK(0x00001fbe, 13), + HUFF_PACK(0x000079fe, 15), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x000006fc, 11)}, + {HUFF_PACK(0x0000006c, 7), HUFF_PACK(0x000000f6, 8), + HUFF_PACK(0x000001ba, 9), HUFF_PACK(0x00000dfc, 12), + HUFF_PACK(0x00000dfd, 12), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x00000f3e, 12), HUFF_PACK(0x000001bb, 9)}, + {HUFF_PACK(0x000000dc, 8), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x0000036e, 10), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x00000fde, 12), + HUFF_PACK(0x000001ee, 9), HUFF_PACK(0x000000f2, 8)}, + {HUFF_PACK(0x000001fa, 9), HUFF_PACK(0x000003f6, 10), + HUFF_PACK(0x000001be, 9), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x00001fbf, 13), HUFF_PACK(0x000003ce, 10), + HUFF_PACK(0x000003ff, 10), HUFF_PACK(0x000000de, 8)}, + {HUFF_PACK(0x00000078, 7), HUFF_PACK(0x000000da, 8), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000006fd, 11), HUFF_PACK(0x0000036c, 10), + HUFF_PACK(0x000001ef, 9), HUFF_PACK(0x000000fe, 8)}, + {HUFF_PACK(0x0000036f, 10), HUFF_PACK(0x00000dfe, 12), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x0000036d, 10), + HUFF_PACK(0x000000fc, 8), HUFF_PACK(0x0000003e, 6)}, + {HUFF_PACK(0x00000dff, 12), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x0000079e, 11), + HUFF_PACK(0x0000007a, 7), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x000079ff, 15) /* escape */ + }}, + {/* HUFF_ICC_TAB_2D[1][1] */ + { + /* LAV1_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000006, 3)}, + {HUFF_PACK(0x00000007, 3), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x000000fc, 8), HUFF_PACK(0x00000fde, 12)}, + {HUFF_PACK(0x0000000c, 4), HUFF_PACK(0x0000000d, 4), + HUFF_PACK(0x000001fe, 9), HUFF_PACK(0x000007ee, 11)}, + {HUFF_PACK(0x000001fa, 9), HUFF_PACK(0x000001ff, 9), + HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x0000003e, 6)}, + {HUFF_PACK(0x00000fdf, 12), HUFF_PACK(0x000003f6, 10), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x00000000, 1)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000003a, 7), HUFF_PACK(0x00000676, 11), + HUFF_PACK(0x000019fe, 13), HUFF_PACK(0x0000cebe, 16)}, + {HUFF_PACK(0x0000000f, 4), HUFF_PACK(0x00000002, 3), + HUFF_PACK(0x0000001e, 6), HUFF_PACK(0x000000fe, 9), + HUFF_PACK(0x000019d6, 13), HUFF_PACK(0x0000675e, 15)}, + {HUFF_PACK(0x0000003e, 7), HUFF_PACK(0x00000032, 6), + HUFF_PACK(0x00000018, 5), HUFF_PACK(0x0000033e, 10), + HUFF_PACK(0x00000cfe, 12), HUFF_PACK(0x00000677, 11)}, + {HUFF_PACK(0x00000674, 11), HUFF_PACK(0x0000019c, 9), + HUFF_PACK(0x000000ff, 9), HUFF_PACK(0x0000003b, 7), + HUFF_PACK(0x0000001c, 6), HUFF_PACK(0x0000007e, 8)}, + {HUFF_PACK(0x000033fe, 14), HUFF_PACK(0x000033ff, 14), + HUFF_PACK(0x00000cea, 12), HUFF_PACK(0x00000066, 7), + HUFF_PACK(0x0000001a, 5), HUFF_PACK(0x00000006, 4)}, + {HUFF_PACK(0x0000cebf, 16), HUFF_PACK(0x000033ae, 14), + HUFF_PACK(0x0000067e, 11), HUFF_PACK(0x0000019e, 9), + HUFF_PACK(0x0000001b, 5), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x00000002, 4), + HUFF_PACK(0x000000fe, 9), HUFF_PACK(0x000007be, 12), + HUFF_PACK(0x00000ffc, 13), HUFF_PACK(0x00000ffd, 13), + HUFF_PACK(0x00001efe, 15), HUFF_PACK(0x00003dfe, 16)}, + {HUFF_PACK(0x00000004, 4), HUFF_PACK(0x00000000, 3), + HUFF_PACK(0x0000003c, 7), HUFF_PACK(0x000000f6, 10), + HUFF_PACK(0x000001da, 11), HUFF_PACK(0x000003fe, 12), + HUFF_PACK(0x00003dfe, 15), HUFF_PACK(0x00003dff, 16)}, + {HUFF_PACK(0x0000003c, 8), HUFF_PACK(0x0000003e, 7), + HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x0000003a, 8), + HUFF_PACK(0x000003de, 11), HUFF_PACK(0x000007be, 13), + HUFF_PACK(0x00000f7e, 14), HUFF_PACK(0x00001efe, 14)}, + {HUFF_PACK(0x000001de, 11), HUFF_PACK(0x000000ec, 10), + HUFF_PACK(0x0000007e, 9), HUFF_PACK(0x0000000c, 5), + HUFF_PACK(0x000001ee, 10), HUFF_PACK(0x00000f7e, 13), + HUFF_PACK(0x000007fc, 12), HUFF_PACK(0x00003dff, 15)}, + {HUFF_PACK(0x00007ffe, 16), HUFF_PACK(0x000003be, 12), + HUFF_PACK(0x000000fe, 10), HUFF_PACK(0x000001fe, 10), + HUFF_PACK(0x0000001a, 6), HUFF_PACK(0x0000001c, 7), + HUFF_PACK(0x000007fd, 12), HUFF_PACK(0x00000ffe, 13)}, + {HUFF_PACK(0x00003dff, 16), HUFF_PACK(0x000003bf, 12), + HUFF_PACK(0x00001ffe, 14), HUFF_PACK(0x000003ff, 12), + HUFF_PACK(0x0000003e, 8), HUFF_PACK(0x0000001b, 6), + HUFF_PACK(0x0000007e, 8), HUFF_PACK(0x000000f6, 9)}, + {HUFF_PACK(0x00007fff, 16), HUFF_PACK(0x00003dff, 16), + HUFF_PACK(0x00003ffe, 15), HUFF_PACK(0x000001db, 11), + HUFF_PACK(0x000000ee, 10), HUFF_PACK(0x0000007a, 8), + HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x0000000b, 5)}, + {HUFF_PACK(0x00003dff, 16), HUFF_PACK(0x00003dff, 16), + HUFF_PACK(0x000003de, 12), HUFF_PACK(0x000001fe, 11), + HUFF_PACK(0x000001ee, 11), HUFF_PACK(0x0000007a, 9), + HUFF_PACK(0x00000006, 5), HUFF_PACK(0x00000003, 2)}}, + HUFF_PACK(0x00003dff, 16) /* escape */ + }}}}}; + +const HUFF_PT0_TABLE fdk_sacenc_huffPart0Tab = { + {/* CLD */ + HUFF_PACK(0x00000052, 8), HUFF_PACK(0x000000ae, 9), + HUFF_PACK(0x000000af, 9), HUFF_PACK(0x00000028, 7), + HUFF_PACK(0x0000006e, 7), HUFF_PACK(0x00000036, 6), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000000c, 4), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x00000002, 4), HUFF_PACK(0x00000016, 5), + HUFF_PACK(0x00000012, 5), HUFF_PACK(0x00000017, 5), + HUFF_PACK(0x00000000, 4), HUFF_PACK(0x00000004, 4), + HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000008, 4), + HUFF_PACK(0x00000007, 4), HUFF_PACK(0x00000003, 4), + HUFF_PACK(0x00000001, 4), HUFF_PACK(0x0000001a, 5), + HUFF_PACK(0x00000013, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x00000016, 6), HUFF_PACK(0x00000017, 6), + HUFF_PACK(0x0000006f, 7), HUFF_PACK(0x0000002a, 7), + HUFF_PACK(0x00000056, 8), HUFF_PACK(0x00000053, 8), + HUFF_PACK(0x0000003f, 6)}, + {/* ICC */ + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x00000006, 3), HUFF_PACK(0x00000000, 2), + HUFF_PACK(0x00000002, 2), HUFF_PACK(0x00000001, 2), + HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x0000003f, 6)}}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ diff --git a/libSACenc/src/sacenc_huff_tab.h b/libSACenc/src/sacenc_huff_tab.h new file mode 100644 index 0000000..7d6c331 --- /dev/null +++ b/libSACenc/src/sacenc_huff_tab.h @@ -0,0 +1,222 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Markus Lohwasser + + Description: SAC-Encoder constant huffman tables + +*******************************************************************************/ + +#ifndef SACENC_HUFF_TAB_H +#define SACENC_HUFF_TAB_H + +/* Includes ******************************************************************/ +#include "machine_type.h" + +/* Defines *******************************************************************/ +#define HUFF_PACK(a, b) \ + { \ + ((((ULONG)a) & 0x00FFFFFF) << 8) | (((ULONG)b) & 0xFF) \ + } /*!< Pack huffman value and length information. */ +#define HUFF_VALUE(a) \ + (((a.packed >> 8) & 0x00FFFFFF)) /*!< Return value from packed table entry. \ + */ +#define HUFF_LENGTH(a) \ + ((a.packed & 0xFF)) /*!< Return length from packed table entry. */ + +/* Data Types ****************************************************************/ +/** + * \brief This struct contains packed huffman entries. + * + * The packed entry consist of hffman value and length information. + * + * |---------------------------------| + * | value | length | + * |---------------------------------| + * |<------- 31...8 ------->|< 7..0 >| + */ +typedef struct { + ULONG packed; /*! Packed huffman entry: + - lower 8 bit are reservoed for length information + - upper 24 bit contains huffman value */ +} HUFF_ENTRY; + +typedef struct { + HUFF_ENTRY entry[2][2]; + HUFF_ENTRY escape; + +} LAV1_2D; + +typedef struct { + HUFF_ENTRY entry[4][4]; + HUFF_ENTRY escape; + +} LAV3_2D; + +typedef struct { + HUFF_ENTRY entry[6][6]; + HUFF_ENTRY escape; + +} LAV5_2D; + +typedef struct { + HUFF_ENTRY entry[7][7]; + HUFF_ENTRY escape; + +} LAV6_2D; + +typedef struct { + HUFF_ENTRY entry[8][8]; + HUFF_ENTRY escape; + +} LAV7_2D; + +typedef struct { + HUFF_ENTRY entry[10][10]; + HUFF_ENTRY escape; + +} LAV9_2D; + +typedef struct { + HUFF_ENTRY entry[13][13]; + HUFF_ENTRY escape; + +} LAV12_2D; + +typedef struct { + LAV3_2D lav3; + LAV5_2D lav5; + LAV7_2D lav7; + LAV9_2D lav9; + +} HUFF_CLD_TAB_2D; + +typedef struct { + LAV1_2D lav1; + LAV3_2D lav3; + LAV5_2D lav5; + LAV7_2D lav7; + +} HUFF_ICC_TAB_2D; + +typedef struct { + HUFF_ENTRY h1D[2][31]; + HUFF_CLD_TAB_2D h2D[2][2]; + +} HUFF_CLD_TABLE; + +typedef struct { + HUFF_ENTRY h1D[2][8]; + HUFF_ICC_TAB_2D h2D[2][2]; + +} HUFF_ICC_TABLE; + +typedef struct { + HUFF_ENTRY cld[31]; + HUFF_ENTRY icc[8]; + +} HUFF_PT0_TABLE; + +typedef HUFF_ENTRY HUFF_RES_TABLE[5][8]; + +/* Constants *****************************************************************/ +extern const HUFF_CLD_TABLE fdk_sacenc_huffCLDTab; +extern const HUFF_ICC_TABLE fdk_sacenc_huffICCTab; +extern const HUFF_PT0_TABLE fdk_sacenc_huffPart0Tab; + +/* Function / Class Declarations *********************************************/ + +#endif /* SACENC_HUFF_TAB_H */ diff --git a/libSACenc/src/sacenc_lib.cpp b/libSACenc/src/sacenc_lib.cpp new file mode 100644 index 0000000..d6a1658 --- /dev/null +++ b/libSACenc/src/sacenc_lib.cpp @@ -0,0 +1,2042 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Interface to Spacial Audio Coding Encoder lib + +*******************************************************************************/ + +/**************************************************************************** +\file +Description of file contents +******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_lib.h" +#include "sacenc_const.h" +#include "genericStds.h" +#include "FDK_core.h" +#include "sacenc_tree.h" +#include "sacenc_bitstream.h" +#include "sacenc_onsetdetect.h" +#include "sacenc_framewindowing.h" +#include "sacenc_filter.h" +#include "sacenc_paramextract.h" +#include "sacenc_staticgain.h" +#include "sacenc_delay.h" +#include "sacenc_dmx_tdom_enh.h" +#include "sacenc_vectorfunctions.h" +#include "qmf.h" + +/* Defines *******************************************************************/ + +/* Encoder library info */ +#define SACENC_LIB_VL0 2 +#define SACENC_LIB_VL1 0 +#define SACENC_LIB_VL2 0 +#define SACENC_LIB_TITLE "MPEG Surround Encoder" +#ifdef __ANDROID__ +#define SACENC_LIB_BUILD_DATE "" +#define SACENC_LIB_BUILD_TIME "" +#else +#define SACENC_LIB_BUILD_DATE __DATE__ +#define SACENC_LIB_BUILD_TIME __TIME__ +#endif + +#define MAX_MPEGS_BYTES (1 << 14) +#define MAX_SSC_BYTES (1 << 6) + +#define MAX_SPACE_TREE_CHANNELS 2 +#define NUM_KEEP_WINDOWS 3 + +/* Data Types ****************************************************************/ +typedef struct { + MP4SPACEENC_MODE encMode; + MP4SPACEENC_BANDS_CONFIG nParamBands; + MP4SPACEENC_QUANTMODE quantMode; + UCHAR bUseCoarseQuant; + UCHAR bLdMode; + UCHAR bTimeDomainDmx; + UINT sampleRate; + UINT frameTimeSlots; /* e.g. 32 when used with HE-AAC */ + UINT independencyFactor; /* how often should we set the independency flag */ + INT timeAlignment; /* additional delay for downmix */ + +} MP4SPACEENC_SETUP, *HANDLE_MP4SPACEENC_SETUP; + +struct ENC_CONFIG_SETUP { + UCHAR bEncMode_212; + UCHAR maxHybridInStaticSlots; + LONG maxSamplingrate; + INT maxAnalysisLengthTimeSlots; + INT maxHybridBands; + INT maxQmfBands; + INT maxChIn; + INT maxFrameTimeSlots; + INT maxFrameLength; + INT maxChOut; + INT maxChTotOut; +}; + +struct MP4SPACE_ENCODER { + MP4SPACEENC_SETUP user; + + ENC_CONFIG_SETUP setup; /* describe allocated instance */ + + HANDLE_FRAMEWINDOW + hFrameWindow; /* Windowing, only created+updated, but not used */ + INT nSamplesValid; /* Input Buffer Handling */ + + /* Routing Sensible Switches/Variables */ + MP4SPACEENC_BANDS_CONFIG nParamBands; + UCHAR useTimeDomDownmix; + + /* not Routing Sensible Switches/Varibles - must be contained in Check */ + MP4SPACEENC_MODE encMode; + UCHAR bEncMode_212_only; + + /* not Routing Sensible Switches/Varibles + lower Classes */ + UCHAR useFrameKeep; + UINT independencyFactor; + UINT nSampleRate; + UCHAR nInputChannels; + UCHAR nOutputChannels; + UCHAR nFrameTimeSlots; /* e.g. 32 when used with HE-AAC */ + UCHAR nQmfBands; + UCHAR nHybridBands; + UINT nFrameLength; /* number of output waveform samples/channel/frame */ + + /* not Routing Sensible Switches/Varibles + lower Classes, secondary computed + */ + INT nSamplesNext; + INT nAnalysisLengthTimeSlots; + INT nAnalysisLookaheadTimeSlots; + INT nUpdateHybridPositionTimeSlots; + INT *pnOutputBits; + INT nInputDelay; + INT nOutputBufferDelay; + INT nSurroundAnalysisBufferDelay; + INT nBitstreamDelayBuffer; + INT nBitstreamBufferRead; + INT nBitstreamBufferWrite; + INT nDiscardOutFrames; + INT avoid_keep; + + /* not Routing Sensible Switches/Varibles -> moved to lower Classes */ + UCHAR useCoarseQuantCld; /* Only Used in SpaceTreeSetup */ + UCHAR useCoarseQuantIcc; /* Only Used in SpaceTreeSetup */ + UCHAR useCoarseQuantCpc; /* Only Used in SpaceTreeSetup */ + UCHAR useCoarseQuantArbDmx; /* ArbitraryDmx,... not available yet */ + MP4SPACEENC_QUANTMODE + quantMode; /* Used for quanitzation and in bitstream writer */ + INT coreCoderDelay; /* Used in delay compensation */ + INT timeAlignment; /* Used in delay compensation */ + + /* Local Processing Variables */ + INT independencyCount; + INT independencyFlag; + INT **ppTrCurrPos; /* belongs somehow to Onset Detection */ + INT trPrevPos[2 * MAX_NUM_TRANS]; /* belongs somehow to Onset Detection */ + + FRAMEWIN_LIST frameWinList; + SPATIALFRAME saveFrame; + + /* Module-Handles */ + SPACE_TREE_SETUP spaceTreeSetup; + MPEG4SPACEENC_SSCBUF sscBuf; + FIXP_WIN *pFrameWindowAna__FDK[MAX_NUM_PARAMS]; + HANDLE_QMF_FILTER_BANK *phQmfFiltIn__FDK; + HANDLE_DC_FILTER phDCFilterSigIn[SACENC_MAX_INPUT_CHANNELS]; + HANDLE_ONSET_DETECT phOnset[SACENC_MAX_INPUT_CHANNELS]; + HANDLE_SPACE_TREE hSpaceTree; + HANDLE_BSF_INSTANCE hBitstreamFormatter; + HANDLE_STATIC_GAIN_CONFIG hStaticGainConfig; + HANDLE_STATIC_GAIN hStaticGain; + HANDLE_DELAY hDelay; + + /* enhanced time domain downmix (for stereo input) */ + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx; + + /* Data Buffers */ + INT_PCM **ppTimeSigIn__FDK; + INT_PCM **ppTimeSigDelayIn__FDK; + INT_PCM **ppTimeSigOut__FDK; + FIXP_DPK ***pppHybridIn__FDK; + FIXP_DPK ***pppHybridInStatic__FDK; + FIXP_DPK ***pppProcDataIn__FDK; + INT_PCM *pOutputDelayBuffer__FDK; + + UCHAR **ppBitstreamDelayBuffer; + + UCHAR *pParameterBand2HybridBandOffset; + INT staticGainScale; + + INT *pEncoderInputChScale; + INT *staticTimeDomainDmxInScale; +}; + +/* Constants *****************************************************************/ +static const UCHAR pValidBands_Ld[8] = {4, 5, 7, 9, 12, 15, 23, 40}; + +static const UCHAR qmf2qmf[] = /* Bypass the HybridAnylyis/Synthesis*/ + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127}; + +/* Function / Class Declarations *********************************************/ +static FDK_SACENC_ERROR mp4SpaceEnc_create( + HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc); + +static FDK_SACENC_ERROR FillSpatialSpecificConfig( + const HANDLE_MP4SPACE_ENCODER hEnc, SPATIALSPECIFICCONFIG *const hSsc); + +static FDK_SACENC_ERROR mp4SpaceEnc_FillSpaceTreeSetup( + const HANDLE_MP4SPACE_ENCODER hEnc, + SPACE_TREE_SETUP *const hSpaceTreeSetup); + +static FDK_SACENC_ERROR mp4SpaceEnc_InitDelayCompensation( + HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, const INT coreCoderDelay); + +static FDK_SACENC_ERROR mp4SpaceEnc_InitDefault( + HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc); + +static DECORRCONFIG mp4SpaceEnc_GetDecorrConfig(const MP4SPACEENC_MODE encMode); + +static FDK_SACENC_ERROR mp4SpaceEnc_InitNumParamBands( + HANDLE_MP4SPACE_ENCODER hEnc, const MP4SPACEENC_BANDS_CONFIG nParamBands); + +/* Function / Class Definition ***********************************************/ +static UINT mp4SpaceEnc_GetNumQmfBands(const UINT nSampleRate) { + UINT nQmfBands = 0; + + if (nSampleRate < 27713) + nQmfBands = 32; + else if (nSampleRate < 55426) + nQmfBands = 64; + + return nQmfBands; +} + +static UINT updateQmfFlags(const UINT flags, const INT keepStates) { + UINT qmfFlags = flags; + + qmfFlags = (qmfFlags & (~(UINT)QMF_FLAG_LP)); + qmfFlags = (qmfFlags | QMF_FLAG_MPSLDFB); + qmfFlags = (keepStates) ? (qmfFlags | QMF_FLAG_KEEP_STATES) + : (qmfFlags & (~(UINT)QMF_FLAG_KEEP_STATES)); + + return qmfFlags; +} + +static INT freq2HybridBand(const UINT nFrequency, const UINT nSampleRate, + const UINT nQmfBands) { + /* + nQmfSlotWidth = (nSampleRate/2) / nQmfBands; + nQmfBand = nFrequency / nQmfSlotWidth; + */ + int nHybridBand = -1; + int scale = 0; + const FIXP_DBL temp = fDivNorm((FIXP_DBL)(2 * nFrequency * nQmfBands), + (FIXP_DBL)nSampleRate, &scale); + const int nQmfBand = scaleValue(temp, scale - (DFRACT_BITS - 1)); + + if ((nQmfBand > -1) && (nQmfBand < (int)nQmfBands)) { + nHybridBand = qmf2qmf[nQmfBand]; + } + + return nHybridBand; +} + +/* + * Examine buffer descriptor regarding choosen type. + * + * \param pBufDesc Pointer to buffer descriptor + * \param type Buffer type to look for. + + * \return - Buffer descriptor index. + * -1, if there is no entry available. + */ +static INT getBufDescIdx(const FDK_bufDescr *pBufDesc, const UINT type) { + INT i, idx = -1; + + for (i = 0; i < (int)pBufDesc->numBufs; i++) { + if (pBufDesc->pBufType[i] == type) { + idx = i; + break; + } + } + return idx; +} + +FDK_SACENC_ERROR FDK_sacenc_open(HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc) { + return mp4SpaceEnc_create(phMp4SpaceEnc); +} + +static FDK_SACENC_ERROR mp4SpaceEnc_create( + HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc) { + FDK_SACENC_ERROR error = SACENC_OK; + HANDLE_MP4SPACE_ENCODER hEnc = NULL; + ENC_CONFIG_SETUP setup; + + if (NULL == phMp4SpaceEnc) { + error = SACENC_INVALID_HANDLE; + } else { + int i, ch; + FDKmemclear(&setup, sizeof(ENC_CONFIG_SETUP)); + + /* Allocate Encoder Instance */ + FDK_ALLOCATE_MEMORY_1D(hEnc, 1, struct MP4SPACE_ENCODER); + + /* Clear everything, also pointers. */ + if (NULL != hEnc) { + FDKmemclear(hEnc, sizeof(struct MP4SPACE_ENCODER)); + } + + setup.maxSamplingrate = 48000; + setup.maxFrameTimeSlots = 16; + + setup.maxAnalysisLengthTimeSlots = 3 * setup.maxFrameTimeSlots; + setup.maxQmfBands = mp4SpaceEnc_GetNumQmfBands(setup.maxSamplingrate); + ; + setup.maxHybridBands = setup.maxQmfBands; + setup.maxFrameLength = setup.maxQmfBands * setup.maxFrameTimeSlots; + + setup.maxChIn = 2; + setup.maxChOut = 1; + setup.maxChTotOut = setup.maxChOut; + setup.bEncMode_212 = 1; + setup.maxHybridInStaticSlots = 24; + + /* Open Static Gain*/ + if (SACENC_OK != + (error = fdk_sacenc_staticGain_OpenConfig(&hEnc->hStaticGainConfig))) { + goto bail; + } + + /* enhanced time domain downmix (for stereo input) */ + if (SACENC_OK != (error = fdk_sacenc_open_enhancedTimeDomainDmx( + &hEnc->hEnhancedTimeDmx, setup.maxFrameLength))) { + goto bail; + } + + FDK_ALLOCATE_MEMORY_1D(hEnc->pParameterBand2HybridBandOffset, + MAX_NUM_PARAM_BANDS, UCHAR); + + /* Create Space Tree first, to get number of in-/output channels */ + if (SACENC_OK != (error = fdk_sacenc_spaceTree_Open(&hEnc->hSpaceTree))) { + goto bail; + } + + FDK_ALLOCATE_MEMORY_1D(hEnc->pEncoderInputChScale, setup.maxChIn, INT); + FDK_ALLOCATE_MEMORY_1D(hEnc->staticTimeDomainDmxInScale, setup.maxChIn, + INT); + + FDK_ALLOCATE_MEMORY_1D(hEnc->phQmfFiltIn__FDK, setup.maxChIn, + HANDLE_QMF_FILTER_BANK); + + /* Allocate Analysis Filterbank Structs */ + for (ch = 0; ch < setup.maxChIn; ch++) { + FDK_ALLOCATE_MEMORY_1D_INT(hEnc->phQmfFiltIn__FDK[ch], 1, + struct QMF_FILTER_BANK, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_1D_INT(hEnc->phQmfFiltIn__FDK[ch]->FilterStates, + 2 * 5 * setup.maxQmfBands, FIXP_QAS, + SECT_DATA_L2) + } + + /* Allocate Synthesis Filterbank Structs for arbitrary downmix */ + + /* Allocate DC Filter Struct for normal signal input */ + for (ch = 0; ch < setup.maxChIn; ch++) { + if (SACENC_OK != + (error = fdk_sacenc_createDCFilter(&hEnc->phDCFilterSigIn[ch]))) { + goto bail; + } + } + + /* Open Onset Detection */ + for (ch = 0; ch < setup.maxChIn; ch++) { + if (SACENC_OK != (error = fdk_sacenc_onsetDetect_Open( + &hEnc->phOnset[ch], setup.maxFrameTimeSlots))) { + goto bail; + } + } + + FDK_ALLOCATE_MEMORY_2D(hEnc->ppTrCurrPos, setup.maxChIn, MAX_NUM_TRANS, + INT); + + /* Create Windowing */ + if (SACENC_OK != + (error = fdk_sacenc_frameWindow_Create(&hEnc->hFrameWindow))) { + goto bail; + } + + /* Open static gain */ + if (SACENC_OK != (error = fdk_sacenc_staticGain_Open(&hEnc->hStaticGain))) { + goto bail; + } + + /* create bitstream encoder */ + if (SACENC_OK != (error = fdk_sacenc_createSpatialBitstreamEncoder( + &hEnc->hBitstreamFormatter))) { + goto bail; + } + + FDK_ALLOCATE_MEMORY_1D(hEnc->sscBuf.pSsc, MAX_SSC_BYTES, UCHAR); + + { + FDK_ALLOCATE_MEMORY_2D(hEnc->ppTimeSigIn__FDK, setup.maxChIn, + setup.maxFrameLength + MAX_DELAY_SURROUND_ANALYSIS, + INT_PCM); + } + FDK_ALLOCATE_MEMORY_2D(hEnc->ppTimeSigDelayIn__FDK, setup.maxChIn, + MAX_DELAY_SURROUND_ANALYSIS, INT_PCM); + + /* Create new buffers for several signals (including arbitrary downmix) */ + if (setup.bEncMode_212 == 0) { + /* pOutputDelayBuffer__FDK buffer is not needed for SACENC_212 mode */ + FDK_ALLOCATE_MEMORY_1D( + hEnc->pOutputDelayBuffer__FDK, + (setup.maxFrameLength + MAX_DELAY_OUTPUT) * setup.maxChOut, INT_PCM); + } + + /* allocate buffers */ + if (setup.bEncMode_212 == 0) { + /* ppTimeSigOut__FDK buffer is not needed for SACENC_212 mode */ + FDK_ALLOCATE_MEMORY_2D(hEnc->ppTimeSigOut__FDK, setup.maxChTotOut, + setup.maxFrameLength, INT_PCM); + } + + if (setup.bEncMode_212 == 1) { + /* pppHybridIn__FDK buffer can be reduced by maxFrameTimeSlots/2 slots for + * SACENC_212 mode */ + FDK_ALLOCATE_MEMORY_3D( + hEnc->pppHybridIn__FDK, setup.maxChIn, + setup.maxAnalysisLengthTimeSlots - (setup.maxFrameTimeSlots >> 1), + setup.maxHybridBands, FIXP_DPK); + FDK_ALLOCATE_MEMORY_3D(hEnc->pppHybridInStatic__FDK, setup.maxChIn, + setup.maxHybridInStaticSlots, setup.maxHybridBands, + FIXP_DPK); + } else { + FDK_ALLOCATE_MEMORY_3D(hEnc->pppHybridIn__FDK, setup.maxChIn, + setup.maxAnalysisLengthTimeSlots, + setup.maxHybridBands, FIXP_DPK); + } + + if (setup.bEncMode_212 == 0) { + /* pppProcDataIn__FDK buffer is not needed for SACENC_212 mode */ + FDK_ALLOCATE_MEMORY_3D(hEnc->pppProcDataIn__FDK, MAX_SPACE_TREE_CHANNELS, + setup.maxAnalysisLengthTimeSlots, + setup.maxHybridBands, FIXP_DPK); + } + for (i = 0; i < MAX_NUM_PARAMS; i++) { + FDK_ALLOCATE_MEMORY_1D(hEnc->pFrameWindowAna__FDK[i], + setup.maxAnalysisLengthTimeSlots, FIXP_WIN); + } /* for i */ + + if (SACENC_OK != (error = fdk_sacenc_delay_Open(&hEnc->hDelay))) { + goto bail; + } + + if (setup.bEncMode_212 == 0) { + /* ppBitstreamDelayBuffer buffer is not needed for SACENC_212 mode */ + FDK_ALLOCATE_MEMORY_2D(hEnc->ppBitstreamDelayBuffer, MAX_BITSTREAM_DELAY, + MAX_MPEGS_BYTES, UCHAR); + } + FDK_ALLOCATE_MEMORY_1D(hEnc->pnOutputBits, MAX_BITSTREAM_DELAY, INT); + + hEnc->setup = setup; /* save configuration used while encoder allocation. */ + mp4SpaceEnc_InitDefault(hEnc); + + if (NULL != phMp4SpaceEnc) { + *phMp4SpaceEnc = hEnc; /* return encoder handle */ + } + + } /* valid handle */ + + return error; + +bail: + if (NULL != hEnc) { + hEnc->setup = setup; + FDK_sacenc_close(&hEnc); + } + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +static FDK_SACENC_ERROR mp4SpaceEnc_InitDefault(HANDLE_MP4SPACE_ENCODER hEnc) { + FDK_SACENC_ERROR err = SACENC_OK; + + /* Get default static gain configuration. */ + if (SACENC_OK != (err = fdk_sacenc_staticGain_InitDefaultConfig( + hEnc->hStaticGainConfig))) { + goto bail; + } + +bail: + return err; +} + +static FDK_SACENC_ERROR FDK_sacenc_configure( + HANDLE_MP4SPACE_ENCODER hEnc, const HANDLE_MP4SPACEENC_SETUP hSetup) { + FDK_SACENC_ERROR error = SACENC_OK; + + hEnc->nSampleRate = hSetup->sampleRate; + hEnc->encMode = hSetup->encMode; + hEnc->nQmfBands = mp4SpaceEnc_GetNumQmfBands(hEnc->nSampleRate); + + /* Make sure that we have set time domain downmix for 212 */ + if (hSetup->encMode == SACENC_212 && hSetup->bTimeDomainDmx == 0) { + error = SACENC_INVALID_CONFIG; + } else { + hEnc->useTimeDomDownmix = hSetup->bTimeDomainDmx; + } + + hEnc->timeAlignment = hSetup->timeAlignment; + hEnc->quantMode = hSetup->quantMode; + + hEnc->useCoarseQuantCld = hSetup->bUseCoarseQuant; + hEnc->useCoarseQuantCpc = hSetup->bUseCoarseQuant; + hEnc->useFrameKeep = (hSetup->bLdMode == 2); + hEnc->useCoarseQuantIcc = 0; /* not available */ + hEnc->useCoarseQuantArbDmx = 0; /* not available for user right now */ + hEnc->independencyFactor = hSetup->independencyFactor; + hEnc->independencyCount = 0; + hEnc->independencyFlag = 1; + + /* set number of Hybrid bands */ + hEnc->nHybridBands = hEnc->nQmfBands; + hEnc->nFrameTimeSlots = hSetup->frameTimeSlots; + mp4SpaceEnc_InitNumParamBands(hEnc, hSetup->nParamBands); + + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_init(HANDLE_MP4SPACE_ENCODER hEnc, + const INT dmxDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + /* Sanity Checks */ + if (NULL == hEnc) { + error = SACENC_INVALID_HANDLE; + } else { + const int initStatesFlag = 1; + + int ch; /* loop counter */ + int nChInArbDmx; + + if (SACENC_OK != (error = FDK_sacenc_configure(hEnc, &hEnc->user))) { + goto bail; + } + + hEnc->bEncMode_212_only = hEnc->setup.bEncMode_212; + + /* Slots per Frame and Frame Length */ + if (hEnc->nFrameTimeSlots < 1) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + hEnc->nFrameLength = hEnc->nQmfBands * hEnc->nFrameTimeSlots; + + if (hEnc->useFrameKeep == 1) { + hEnc->nAnalysisLengthTimeSlots = 3 * hEnc->nFrameTimeSlots; + hEnc->nUpdateHybridPositionTimeSlots = hEnc->nFrameTimeSlots; + } else { + hEnc->nAnalysisLengthTimeSlots = 2 * hEnc->nFrameTimeSlots; + hEnc->nUpdateHybridPositionTimeSlots = 0; + } + + { + hEnc->nAnalysisLookaheadTimeSlots = + hEnc->nAnalysisLengthTimeSlots - 3 * hEnc->nFrameTimeSlots / 2; + } + + /* init parameterBand2hybridBandOffset table */ + fdk_sacenc_calcParameterBand2HybridBandOffset( + (BOX_SUBBAND_CONFIG)hEnc->nParamBands, hEnc->nHybridBands, + hEnc->pParameterBand2HybridBandOffset); + + /* Fill Setup structure for Space Tree */ + if (SACENC_OK != + (error = mp4SpaceEnc_FillSpaceTreeSetup(hEnc, &hEnc->spaceTreeSetup))) { + goto bail; + } + + /* Init space tree configuration */ + if (SACENC_OK != + (error = fdk_sacenc_spaceTree_Init( + hEnc->hSpaceTree, &hEnc->spaceTreeSetup, + hEnc->pParameterBand2HybridBandOffset, hEnc->useFrameKeep))) { + goto bail; + } + + /* Get space tree description and resulting number of input/output channels + */ + { + SPACE_TREE_DESCRIPTION spaceTreeDescription; + + if (SACENC_OK != (error = fdk_sacenc_spaceTree_GetDescription( + hEnc->hSpaceTree, &spaceTreeDescription))) { + goto bail; + } + + hEnc->nInputChannels = + spaceTreeDescription.nOutChannels; /* space tree description + describes decoder + configuration */ + hEnc->nOutputChannels = + spaceTreeDescription.nInChannels; /* space tree description + describes decoder + configuration */ + } + + nChInArbDmx = 0; + + /* INITIALIZATION */ + for (ch = 0; ch < hEnc->nInputChannels; ch++) { + /* scaling in analysis qmf filterbank (7) */ + hEnc->pEncoderInputChScale[ch] = 7; + + { + /* additional scaling in qmf prototype filter for low delay */ + hEnc->pEncoderInputChScale[ch] += 1; + } + + { hEnc->pEncoderInputChScale[ch] += DC_FILTER_SF; } + } /* nInputChannels */ + + /* Init analysis filterbank */ + for (ch = 0; ch < hEnc->nInputChannels; ch++) { + hEnc->phQmfFiltIn__FDK[ch]->flags = + updateQmfFlags(hEnc->phQmfFiltIn__FDK[ch]->flags, !initStatesFlag); + + if (0 != qmfInitAnalysisFilterBank( + hEnc->phQmfFiltIn__FDK[ch], + (FIXP_QAS *)hEnc->phQmfFiltIn__FDK[ch]->FilterStates, 1, + hEnc->nQmfBands, hEnc->nQmfBands, hEnc->nQmfBands, + hEnc->phQmfFiltIn__FDK[ch]->flags)) { + error = SACENC_INIT_ERROR; + goto bail; + } + } + + /* Initialize DC Filter. */ + { + for (ch = 0; ch < hEnc->nInputChannels; ch++) { + if (SACENC_OK != (error = fdk_sacenc_initDCFilter( + hEnc->phDCFilterSigIn[ch], hEnc->nSampleRate))) { + goto bail; + } + } + } + + /* Init onset detect. */ + { + /* init onset detect configuration struct */ + ONSET_DETECT_CONFIG onsetDetectConfig; + onsetDetectConfig.maxTimeSlots = hEnc->nFrameTimeSlots; + onsetDetectConfig.lowerBoundOnsetDetection = + freq2HybridBand(1725, hEnc->nSampleRate, hEnc->nQmfBands); + onsetDetectConfig.upperBoundOnsetDetection = hEnc->nHybridBands; + + for (ch = 0; ch < hEnc->nInputChannels; ch++) { + if (SACENC_OK != (error = fdk_sacenc_onsetDetect_Init( + hEnc->phOnset[ch], &onsetDetectConfig, 1))) { + goto bail; + } + } + } + + { + /* init windowing */ + FRAMEWINDOW_CONFIG framewindowConfig; + framewindowConfig.nTimeSlotsMax = hEnc->nFrameTimeSlots; + framewindowConfig.bFrameKeep = hEnc->useFrameKeep; + + if (SACENC_OK != (error = fdk_sacenc_frameWindow_Init( + hEnc->hFrameWindow, &framewindowConfig))) { + goto bail; + } + } + + /* Set encoder mode for static gain initialization. */ + if (SACENC_OK != (error = fdk_sacenc_staticGain_SetEncMode( + hEnc->hStaticGainConfig, hEnc->encMode))) { + goto bail; + } + + /* Init static gain. */ + if (SACENC_OK != (error = fdk_sacenc_staticGain_Init( + hEnc->hStaticGain, hEnc->hStaticGainConfig, + &(hEnc->staticGainScale)))) { + goto bail; + } + + for (ch = 0; ch < hEnc->nInputChannels; ch++) { + hEnc->pEncoderInputChScale[ch] += hEnc->staticGainScale; + } + + /* enhanced downmix for stereo input*/ + if (hEnc->useTimeDomDownmix != 0) { + if (SACENC_OK != (error = fdk_sacenc_init_enhancedTimeDomainDmx( + hEnc->hEnhancedTimeDmx, + fdk_sacenc_getPreGainPtrFDK(hEnc->hStaticGain), + hEnc->staticGainScale, + fdk_sacenc_getPostGainFDK(hEnc->hStaticGain), + hEnc->staticGainScale, hEnc->nFrameLength))) { + goto bail; + } + } + + /* Create config structure for bitstream formatter including arbitrary + * downmix residual */ + if (SACENC_OK != (error = fdk_sacenc_initSpatialBitstreamEncoder( + hEnc->hBitstreamFormatter))) { + goto bail; + } + + if (SACENC_OK != (error = FillSpatialSpecificConfig( + hEnc, fdk_sacenc_getSpatialSpecificConfig( + hEnc->hBitstreamFormatter)))) { + goto bail; + } + + if (SACENC_OK != + (error = fdk_sacenc_writeSpatialSpecificConfig( + fdk_sacenc_getSpatialSpecificConfig(hEnc->hBitstreamFormatter), + hEnc->sscBuf.pSsc, MAX_SSC_BYTES, &hEnc->sscBuf.nSscSizeBits))) { + goto bail; + } + + /* init delay compensation with dmx core coder delay; if no core coder is + * used, many other buffers are initialized nevertheless */ + if (SACENC_OK != + (error = mp4SpaceEnc_InitDelayCompensation(hEnc, dmxDelay))) { + goto bail; + } + + /* How much input do we need? */ + hEnc->nSamplesNext = + hEnc->nFrameLength * (hEnc->nInputChannels + nChInArbDmx); + hEnc->nSamplesValid = 0; + } /* valid handle */ + +bail: + return error; +} + +static INT getAnalysisLengthTimeSlots(FIXP_WIN *pFrameWindowAna, + INT nTimeSlots) { + int i; + for (i = nTimeSlots - 1; i >= 0; i--) { + if (pFrameWindowAna[i] != (FIXP_WIN)0) { + break; + } + } + nTimeSlots = i + 1; + return nTimeSlots; +} + +static INT getAnalysisStartTimeSlot(FIXP_WIN *pFrameWindowAna, INT nTimeSlots) { + int startTimeSlot = 0; + int i; + for (i = 0; i < nTimeSlots; i++) { + if (pFrameWindowAna[i] != (FIXP_WIN)0) { + break; + } + } + startTimeSlot = i; + return startTimeSlot; +} + +static FDK_SACENC_ERROR __FeedDeinterPreScale( + HANDLE_MP4SPACE_ENCODER hEnc, INT_PCM const *const pSamples, + INT_PCM *const pOutputSamples, INT const nSamples, + UINT const isInputInterleaved, UINT const inputBufferSizePerChannel, + UINT *const pnSamplesFed) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hEnc == NULL) || (pSamples == NULL) || (pnSamplesFed == NULL)) { + error = SACENC_INVALID_HANDLE; + } else if (nSamples == 0) { + error = SACENC_INVALID_CONFIG; /* Flushing not implemented */ + } else { + int ch; + const INT nChIn = hEnc->nInputChannels; + const INT nChInWithDmx = nChIn; + const INT samplesToFeed = + FDKmin(nSamples, hEnc->nSamplesNext - hEnc->nSamplesValid); + const INT nSamplesPerChannel = samplesToFeed / nChInWithDmx; + + if ((samplesToFeed < 0) || (samplesToFeed % nChInWithDmx != 0) || + (samplesToFeed > nChInWithDmx * (INT)hEnc->nFrameLength)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + int i; + + const INT_PCM *pInput__FDK; + const INT_PCM *pInput2__FDK; + + { /* no dmx align = default*/ + pInput__FDK = pSamples; + pInput2__FDK = pSamples + (hEnc->nInputDelay * nChInWithDmx); + } + + for (i = 0; i < hEnc->nInputChannels; i++) { + hEnc->staticTimeDomainDmxInScale[i] = hEnc->staticGainScale; + } + + /***** N-channel-input *****/ + for (ch = 0; ch < nChIn; ch++) { + /* Write delayed time signal into time signal buffer */ + FDKmemcpy(&(hEnc->ppTimeSigIn__FDK[ch][0]), + &(hEnc->ppTimeSigDelayIn__FDK[ch][0]), + hEnc->nSurroundAnalysisBufferDelay * sizeof(INT_PCM)); + + if (isInputInterleaved) { + /* Add the new frame de-interleaved. Apply nSurroundAnalysisBufferDelay. + */ + FDKmemcpy_flex( + &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nSurroundAnalysisBufferDelay]), + 1, pInput__FDK + ch, nChInWithDmx, hEnc->nInputDelay); + FDKmemcpy_flex( + &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nSurroundAnalysisBufferDelay + + hEnc->nInputDelay]), + 1, pInput2__FDK + ch, nChInWithDmx, + nSamplesPerChannel - hEnc->nInputDelay); + } else { + /* Input is already deinterleaved, just copy */ + FDKmemcpy( + &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nSurroundAnalysisBufferDelay]), + pInput__FDK + ch * inputBufferSizePerChannel, + hEnc->nInputDelay * sizeof(INT_PCM)); + FDKmemcpy( + &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nSurroundAnalysisBufferDelay + + hEnc->nInputDelay]), + pInput2__FDK + ch * inputBufferSizePerChannel, + (nSamplesPerChannel - hEnc->nInputDelay) * sizeof(INT_PCM)); + } + + /* Update time signal delay buffer */ + FDKmemcpy(&(hEnc->ppTimeSigDelayIn__FDK[ch][0]), + &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nFrameLength]), + hEnc->nSurroundAnalysisBufferDelay * sizeof(INT_PCM)); + } /* for ch */ + + /***** No Arbitrary Downmix *****/ + /* "Crude TD Dmx": Time DomainDownmix + NO Arbitrary Downmix, Delay Added at + * pOutputBuffer */ + if ((hEnc->useTimeDomDownmix > 0)) { + if ((hEnc->useTimeDomDownmix == 1) || (hEnc->nInputChannels != 2)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } else { + /* enhanced time domain downmix (for stereo input) */ + if (hEnc->encMode == SACENC_212) { + if (pOutputSamples == NULL) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + fdk_sacenc_apply_enhancedTimeDomainDmx( + hEnc->hEnhancedTimeDmx, hEnc->ppTimeSigIn__FDK, pOutputSamples, + hEnc->nSurroundAnalysisBufferDelay); + } else { + if (&hEnc->ppTimeSigOut__FDK[0][0] == NULL) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + fdk_sacenc_apply_enhancedTimeDomainDmx( + hEnc->hEnhancedTimeDmx, hEnc->ppTimeSigIn__FDK, + &hEnc->ppTimeSigOut__FDK[0][0], + hEnc->nSurroundAnalysisBufferDelay); + } + } + } + + /* update number of samples still to process */ + hEnc->nSamplesValid += samplesToFeed; + + /*return number of fed samples */ + *pnSamplesFed = samplesToFeed; + } +bail: + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_encode(const HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + const FDK_bufDescr *inBufDesc, + const FDK_bufDescr *outBufDesc, + const SACENC_InArgs *inargs, + SACENC_OutArgs *outargs) { + FDK_SACENC_ERROR error = SACENC_OK; + + const INT_PCM *pInputSamples = + (const INT_PCM *)inBufDesc->ppBase[getBufDescIdx( + inBufDesc, (FDK_BUF_TYPE_INPUT | FDK_BUF_TYPE_PCM_DATA))]; + + INT_PCM *const pOutputSamples = (INT_PCM *)outBufDesc->ppBase[getBufDescIdx( + outBufDesc, (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_PCM_DATA))]; + + const int nOutputSamplesBufferSize = + outBufDesc->pBufSize[getBufDescIdx( + outBufDesc, (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_PCM_DATA))] / + outBufDesc->pEleSize[getBufDescIdx( + outBufDesc, (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_PCM_DATA))]; + + if ((hMp4SpaceEnc == NULL) || (pInputSamples == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int nOutputSamples; + int i, ch, ps, winCnt, ts, slot; + INT currTransPos = -1; + SPATIALFRAME *pFrameData = NULL; + + /* Improve Code Readability */ + const int nChIn = hMp4SpaceEnc->nInputChannels; + const int nChInWithDmx = nChIn; + const int nChOut = hMp4SpaceEnc->nOutputChannels; + const int nSamplesPerChannel = inargs->nInputSamples / nChInWithDmx; + const int nOutputSamplesMax = nSamplesPerChannel * nChOut; + const int nFrameTimeSlots = hMp4SpaceEnc->nFrameTimeSlots; + + INT encoderInputChScale[SACENC_MAX_INPUT_CHANNELS]; + INT nFrameTimeSlotsReduction = 0; + + if (hMp4SpaceEnc->encMode == SACENC_212) { + nFrameTimeSlotsReduction = hMp4SpaceEnc->nFrameTimeSlots >> 1; + } + + for (i = 0; i < nChIn; i++) + encoderInputChScale[i] = hMp4SpaceEnc->pEncoderInputChScale[i]; + + /* Sanity Check */ + if ((0 != inargs->nInputSamples % nChInWithDmx)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* + * Get Frame Data Handle. + */ + + /* get bitstream handle (for storage of cld's, icc's and so on) + * get spatialframe 2 frames in the future; NOTE: this is necessary to + * synchronise spatial data and audio data */ + if (NULL == (pFrameData = fdk_sacenc_getSpatialFrame( + hMp4SpaceEnc->hBitstreamFormatter, WRITE_SPATIALFRAME))) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + /* Independent Frames Counters*/ + if (hMp4SpaceEnc->nDiscardOutFrames > + 0) { /* Independent Frames if they should be discarded, Reset Counter*/ + hMp4SpaceEnc->independencyCount = + 0; /* Reset the counter, first valid frame is an independent one*/ + hMp4SpaceEnc->independencyFlag = 1; + } else { /*hMp4SpaceEnc->nDiscardOutFrames == 0*/ + hMp4SpaceEnc->independencyFlag = + (hMp4SpaceEnc->independencyCount == 0) ? 1 : 0; + if (hMp4SpaceEnc->independencyFactor > 0) { + hMp4SpaceEnc->independencyCount++; + hMp4SpaceEnc->independencyCount = + hMp4SpaceEnc->independencyCount % + ((int)hMp4SpaceEnc->independencyFactor); + } else { /* independencyFactor == 0 */ + hMp4SpaceEnc->independencyCount = -1; + } + } + + /* + * Time signal preprocessing: + * - Feed input buffer + * - Prescale time signal + * - Apply DC filter on input signal + */ + + /* Feed, Deinterleave, Pre-Scale the input time signals */ + if (SACENC_OK != + (error = __FeedDeinterPreScale( + hMp4SpaceEnc, pInputSamples, pOutputSamples, inargs->nInputSamples, + inargs->isInputInterleaved, inargs->inputBufferSizePerChannel, + &outargs->nSamplesConsumed))) { + goto bail; + } + + if (hMp4SpaceEnc->nSamplesNext != hMp4SpaceEnc->nSamplesValid) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + if (hMp4SpaceEnc->encMode == SACENC_212 && + hMp4SpaceEnc->bEncMode_212_only) { + for (ch = 0; ch < nChIn; ch++) { + for (slot = 0; slot < nFrameTimeSlots; slot++) { + setCplxVec( + hMp4SpaceEnc->pppHybridIn__FDK + [ch][hMp4SpaceEnc->nUpdateHybridPositionTimeSlots + + nFrameTimeSlots - nFrameTimeSlotsReduction + slot], + (FIXP_DBL)0, hMp4SpaceEnc->nHybridBands); + } + } + } + + /* + * Time / Frequency: + * - T/F audio input channels + * - T/F arbitrary downmix input channels + */ + for (ch = 0; ch < nChIn; ch++) { + C_AALLOC_SCRATCH_START(pQmfInReal, FIXP_DBL, MAX_QMF_BANDS) + C_AALLOC_SCRATCH_START(pQmfInImag, FIXP_DBL, MAX_QMF_BANDS) + FIXP_GAIN *pPreGain = + fdk_sacenc_getPreGainPtrFDK(hMp4SpaceEnc->hStaticGain); + + for (ts = 0; ts < nFrameTimeSlots; ts++) { + FIXP_DBL *pSpecReal; + FIXP_DBL *pSpecImag; + + INT_PCM *pTimeIn = + &hMp4SpaceEnc->ppTimeSigIn__FDK[ch][(ts * hMp4SpaceEnc->nQmfBands)]; + + { + /* Apply DC filter on input channels */ + if (SACENC_OK != (error = fdk_sacenc_applyDCFilter( + hMp4SpaceEnc->phDCFilterSigIn[ch], pTimeIn, + pTimeIn, hMp4SpaceEnc->nQmfBands))) { + goto bail; + } + } + + /* QMF filterbank */ + C_ALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, (MAX_QMF_BANDS << 1)); + + qmfAnalysisFilteringSlot(hMp4SpaceEnc->phQmfFiltIn__FDK[ch], pQmfInReal, + pQmfInImag, pTimeIn, 1, pWorkBuffer); + + C_ALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (MAX_QMF_BANDS << 1)); + + pSpecReal = pQmfInReal; + pSpecImag = pQmfInImag; + + /* Apply pre-scale after filterbank */ + if (MAXVAL_GAIN != pPreGain[ch]) { + for (i = 0; i < hMp4SpaceEnc->nHybridBands; i++) { + hMp4SpaceEnc + ->pppHybridIn__FDK[ch] + [hMp4SpaceEnc->nAnalysisLookaheadTimeSlots + + ts][i] + .v.re = fMult(pSpecReal[i], pPreGain[ch]); + hMp4SpaceEnc + ->pppHybridIn__FDK[ch] + [hMp4SpaceEnc->nAnalysisLookaheadTimeSlots + + ts][i] + .v.im = fMult(pSpecImag[i], pPreGain[ch]); + } + } else { + for (i = 0; i < hMp4SpaceEnc->nHybridBands; i++) { + hMp4SpaceEnc + ->pppHybridIn__FDK[ch] + [hMp4SpaceEnc->nAnalysisLookaheadTimeSlots + + ts][i] + .v.re = pSpecReal[i]; + hMp4SpaceEnc + ->pppHybridIn__FDK[ch] + [hMp4SpaceEnc->nAnalysisLookaheadTimeSlots + + ts][i] + .v.im = pSpecImag[i]; + } + } + } /* ts */ + C_AALLOC_SCRATCH_END(pQmfInImag, FIXP_DBL, MAX_QMF_BANDS) + C_AALLOC_SCRATCH_END(pQmfInReal, FIXP_DBL, MAX_QMF_BANDS) + + if (SACENC_OK != error) { + goto bail; + } + } /* ch */ + + if (hMp4SpaceEnc->encMode == SACENC_212 && + hMp4SpaceEnc->bEncMode_212_only) { + for (ch = 0; ch < nChIn; ch++) { + for (slot = 0; + slot < (int)(hMp4SpaceEnc->nUpdateHybridPositionTimeSlots + + nFrameTimeSlots - nFrameTimeSlotsReduction); + slot++) { + copyCplxVec(hMp4SpaceEnc->pppHybridIn__FDK[ch][slot], + hMp4SpaceEnc->pppHybridInStatic__FDK[ch][slot], + hMp4SpaceEnc->nHybridBands); + } + } + for (ch = 0; ch < nChIn; ch++) { + for (slot = 0; + slot < (int)(hMp4SpaceEnc->nUpdateHybridPositionTimeSlots + + nFrameTimeSlots - nFrameTimeSlotsReduction); + slot++) { + copyCplxVec( + hMp4SpaceEnc->pppHybridInStatic__FDK[ch][slot], + hMp4SpaceEnc->pppHybridIn__FDK[ch][nFrameTimeSlots + slot], + hMp4SpaceEnc->nHybridBands); + } + } + } + + /* + * Onset Detection: + * - detection of transients + * - build framing + */ + for (ch = 0; ch < nChIn; ch++) { + if (ch != 3) { /* !LFE */ + if (SACENC_OK != + (error = fdk_sacenc_onsetDetect_Apply( + hMp4SpaceEnc->phOnset[ch], nFrameTimeSlots, + hMp4SpaceEnc->nHybridBands, + &hMp4SpaceEnc->pppHybridIn__FDK + [ch][hMp4SpaceEnc->nAnalysisLookaheadTimeSlots], + encoderInputChScale[ch], + hMp4SpaceEnc->trPrevPos[1], /* contains previous Transient */ + hMp4SpaceEnc->ppTrCurrPos[ch]))) { + goto bail; + } + + if ((1) && (hMp4SpaceEnc->useFrameKeep == 0)) { + hMp4SpaceEnc->ppTrCurrPos[ch][0] = -1; + } + + /* Find first Transient Position */ + if ((hMp4SpaceEnc->ppTrCurrPos[ch][0] >= 0) && + ((currTransPos < 0) || + (hMp4SpaceEnc->ppTrCurrPos[ch][0] < currTransPos))) { + currTransPos = hMp4SpaceEnc->ppTrCurrPos[ch][0]; + } + } /* !LFE */ + } /* ch */ + + if (hMp4SpaceEnc->useFrameKeep == 1) { + if ((currTransPos != -1) || (hMp4SpaceEnc->independencyFlag == 1)) { + hMp4SpaceEnc->avoid_keep = NUM_KEEP_WINDOWS; + currTransPos = -1; + } + } + + /* Save previous Transient Position */ + hMp4SpaceEnc->trPrevPos[0] = + FDKmax(-1, hMp4SpaceEnc->trPrevPos[1] - (INT)nFrameTimeSlots); + hMp4SpaceEnc->trPrevPos[1] = currTransPos; + + /* Update Onset Detection Energy Buffer */ + for (ch = 0; ch < nChIn; ch++) { + if (SACENC_OK != (error = fdk_sacenc_onsetDetect_Update( + hMp4SpaceEnc->phOnset[ch], nFrameTimeSlots))) { + goto bail; + } + } + + /* Framing */ + if (SACENC_OK != + (error = fdk_sacenc_frameWindow_GetWindow( + hMp4SpaceEnc->hFrameWindow, hMp4SpaceEnc->trPrevPos, + nFrameTimeSlots, &pFrameData->framingInfo, + hMp4SpaceEnc->pFrameWindowAna__FDK, &hMp4SpaceEnc->frameWinList, + hMp4SpaceEnc->avoid_keep))) { + goto bail; + } + + /* + * MPS Processing: + */ + for (ps = 0, winCnt = 0; ps < hMp4SpaceEnc->frameWinList.n; ++ps) { + /* Analysis Windowing */ + if (hMp4SpaceEnc->frameWinList.dat[ps].hold == FW_HOLD) { + /* ************************************** */ + /* ONLY COPY AND HOLD PREVIOUS PARAMETERS */ + if (SACENC_OK != (error = fdk_sacenc_duplicateParameterSet( + &hMp4SpaceEnc->saveFrame, 0, pFrameData, ps))) { + goto bail; + } + + } else { /* !FW_HOLD */ + /* ************************************** */ + /* NEW WINDOW */ + + INT nAnalysisLengthTimeSlots, analysisStartTimeSlot; + + nAnalysisLengthTimeSlots = getAnalysisLengthTimeSlots( + hMp4SpaceEnc->pFrameWindowAna__FDK[winCnt], + hMp4SpaceEnc->nAnalysisLengthTimeSlots); + + analysisStartTimeSlot = + getAnalysisStartTimeSlot(hMp4SpaceEnc->pFrameWindowAna__FDK[winCnt], + hMp4SpaceEnc->nAnalysisLengthTimeSlots); + + /* perform main signal analysis windowing in + * fdk_sacenc_spaceTree_Apply() */ + FIXP_WIN *pFrameWindowAna__FDK = + hMp4SpaceEnc->pFrameWindowAna__FDK[winCnt]; + FIXP_DPK ***pppHybridIn__FDK = hMp4SpaceEnc->pppHybridIn__FDK; + FIXP_DPK ***pppProcDataIn__FDK = hMp4SpaceEnc->pppProcDataIn__FDK; + + if (hMp4SpaceEnc->encMode == SACENC_212 && + hMp4SpaceEnc->bEncMode_212_only) { + pppProcDataIn__FDK = pppHybridIn__FDK; + } + + if (SACENC_OK != + (error = fdk_sacenc_spaceTree_Apply( + hMp4SpaceEnc->hSpaceTree, ps, nChIn, nAnalysisLengthTimeSlots, + analysisStartTimeSlot, hMp4SpaceEnc->nHybridBands, + pFrameWindowAna__FDK, pppHybridIn__FDK, + pppProcDataIn__FDK, /* multi-channel input */ + pFrameData, hMp4SpaceEnc->avoid_keep, encoderInputChScale))) { + goto bail; + } + + /* Save spatial frame for potential hold parameter set */ + if (SACENC_OK != (error = fdk_sacenc_duplicateParameterSet( + pFrameData, ps, &hMp4SpaceEnc->saveFrame, 0))) { + goto bail; + } + + ++winCnt; + } + if (hMp4SpaceEnc->avoid_keep > 0) { + hMp4SpaceEnc->avoid_keep--; + } + } /* Loop over Parameter Sets */ + /* ---- End of Processing Loop ---- */ + + /* + * Update hybridInReal/Imag buffer and do the same for arbDmx + * this means to move the hybrid data of the current frame to the beginning + * of the 2*nFrameLength-long buffer + */ + if (!(hMp4SpaceEnc->encMode == SACENC_212 && + hMp4SpaceEnc->bEncMode_212_only)) { + for (ch = 0; ch < nChIn; ch++) { /* for automatic downmix */ + for (slot = 0; + slot < (int)(hMp4SpaceEnc->nUpdateHybridPositionTimeSlots + + nFrameTimeSlots - nFrameTimeSlotsReduction); + slot++) { + copyCplxVec( + hMp4SpaceEnc->pppHybridIn__FDK[ch][slot], + hMp4SpaceEnc->pppHybridIn__FDK[ch][nFrameTimeSlots + slot], + hMp4SpaceEnc->nHybridBands); + } + for (slot = 0; slot < nFrameTimeSlots; slot++) { + setCplxVec( + hMp4SpaceEnc->pppHybridIn__FDK + [ch][hMp4SpaceEnc->nUpdateHybridPositionTimeSlots + + nFrameTimeSlots - nFrameTimeSlotsReduction + slot], + (FIXP_DBL)0, hMp4SpaceEnc->nHybridBands); + } + } + } + /* + * Spatial Tonality: + */ + { + /* Smooth config off. */ + FDKmemclear(&pFrameData->smgData, sizeof(pFrameData->smgData)); + } + + /* + * Create bitstream + * - control independecy flag + * - write spatial frame + * - return bitstream + */ + UCHAR *pBitstreamDelayBuffer; + + if (hMp4SpaceEnc->encMode == SACENC_212) { + /* no bitstream delay buffer for SACENC_212 mode, write bitstream directly + * into the sacOutBuffer buffer which is provided by the core routine */ + pBitstreamDelayBuffer = (UCHAR *)outBufDesc->ppBase[1]; + } else { + /* bitstream delay is handled in ppBitstreamDelayBuffer buffer */ + pBitstreamDelayBuffer = + hMp4SpaceEnc + ->ppBitstreamDelayBuffer[hMp4SpaceEnc->nBitstreamBufferWrite]; + } + if (pBitstreamDelayBuffer == NULL) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + pFrameData->bsIndependencyFlag = hMp4SpaceEnc->independencyFlag; + + if (SACENC_OK != + (error = fdk_sacenc_writeSpatialFrame( + pBitstreamDelayBuffer, MAX_MPEGS_BYTES, + &hMp4SpaceEnc->pnOutputBits[hMp4SpaceEnc->nBitstreamBufferWrite], + hMp4SpaceEnc->hBitstreamFormatter))) { + goto bail; + } + + /* return bitstream info */ + if ((hMp4SpaceEnc->nDiscardOutFrames == 0) && + (getBufDescIdx(outBufDesc, + (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_BS_DATA)) != -1)) { + const INT idx = getBufDescIdx( + outBufDesc, (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_BS_DATA)); + const INT outBits = + hMp4SpaceEnc->pnOutputBits[hMp4SpaceEnc->nBitstreamBufferRead]; + + if (((outBits + 7) / 8) > + (INT)(outBufDesc->pBufSize[idx] / outBufDesc->pEleSize[idx])) { + outargs->nOutputBits = 0; + error = SACENC_ENCODE_ERROR; + goto bail; + } + + /* return bitstream buffer, copy delayed bitstream for all configurations + * except for the SACENC_212 mode */ + if (hMp4SpaceEnc->encMode != SACENC_212) { + FDKmemcpy( + outBufDesc->ppBase[idx], + hMp4SpaceEnc + ->ppBitstreamDelayBuffer[hMp4SpaceEnc->nBitstreamBufferRead], + (outBits + 7) / 8); + } + + /* return number of valid bits */ + outargs->nOutputBits = outBits; + } else { /* No spatial data should be returned if the current frame is to be + discarded. */ + outargs->nOutputBits = 0; + } + + /* update pointers */ + hMp4SpaceEnc->nBitstreamBufferRead = + (hMp4SpaceEnc->nBitstreamBufferRead + 1) % + hMp4SpaceEnc->nBitstreamDelayBuffer; + hMp4SpaceEnc->nBitstreamBufferWrite = + (hMp4SpaceEnc->nBitstreamBufferWrite + 1) % + hMp4SpaceEnc->nBitstreamDelayBuffer; + + /* Set Output Parameters */ + nOutputSamples = + (hMp4SpaceEnc->nDiscardOutFrames == 0) + ? (nOutputSamplesMax) + : 0; /* don't output samples in case frames to be discarded */ + if (nOutputSamples > nOutputSamplesBufferSize) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + outargs->nOutputSamples = nOutputSamples; + + { /* !bQmfOutput */ + + if (hMp4SpaceEnc->encMode != SACENC_212) { + /* delay output samples and interleave them */ + /* note: in case of arbitrary downmix this will always be processed, + * because nOutputSamples != 0, even if bDMXAlign is switched on */ + /* always run copy-func, so nOutputSamplesMax instead of nOutputSamples + */ + for (ch = 0; ch < nChOut; ch++) { + FDKmemcpy_flex( + &hMp4SpaceEnc->pOutputDelayBuffer__FDK + [ch + (hMp4SpaceEnc->nOutputBufferDelay) * nChOut], + nChOut, hMp4SpaceEnc->ppTimeSigOut__FDK[ch], 1, + nOutputSamplesMax / nChOut); + } + + /* write delayed data in output pcm stream */ + /* always calculate, limiter must have a lookahead!!! */ + FDKmemcpy(pOutputSamples, hMp4SpaceEnc->pOutputDelayBuffer__FDK, + nOutputSamplesMax * sizeof(INT_PCM)); + + /* update delay buffer (move back end to the beginning of the buffer) */ + FDKmemmove( + hMp4SpaceEnc->pOutputDelayBuffer__FDK, + &hMp4SpaceEnc->pOutputDelayBuffer__FDK[nOutputSamplesMax], + nChOut * (hMp4SpaceEnc->nOutputBufferDelay) * sizeof(INT_PCM)); + } + + if (hMp4SpaceEnc->useTimeDomDownmix <= 0) { + if (SACENC_OK != (error = fdk_sacenc_staticPostGain_ApplyFDK( + hMp4SpaceEnc->hStaticGain, pOutputSamples, + nOutputSamplesMax, 0))) { + goto bail; + } + } + + } /* !bQmfOutput */ + + if (hMp4SpaceEnc->nDiscardOutFrames > 0) { + hMp4SpaceEnc->nDiscardOutFrames--; + } + + /* Invalidate Input Buffer */ + hMp4SpaceEnc->nSamplesValid = 0; + + } /* valid handle */ +bail: + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_close(HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL != phMp4SpaceEnc) { + if (NULL != *phMp4SpaceEnc) { + int ch, i; + HANDLE_MP4SPACE_ENCODER const hEnc = *phMp4SpaceEnc; + + if (hEnc->pParameterBand2HybridBandOffset != NULL) { + FDK_FREE_MEMORY_1D(hEnc->pParameterBand2HybridBandOffset); + } + /* Free Analysis Filterbank Structs */ + if (hEnc->pEncoderInputChScale != NULL) { + FDK_FREE_MEMORY_1D(hEnc->pEncoderInputChScale); + } + if (hEnc->staticTimeDomainDmxInScale != NULL) { + FDK_FREE_MEMORY_1D(hEnc->staticTimeDomainDmxInScale); + } + if (hEnc->phQmfFiltIn__FDK != NULL) { + for (ch = 0; ch < hEnc->setup.maxChIn; ch++) { + if (hEnc->phQmfFiltIn__FDK[ch] != NULL) { + if (hEnc->phQmfFiltIn__FDK[ch]->FilterStates != NULL) { + FDK_FREE_MEMORY_1D(hEnc->phQmfFiltIn__FDK[ch]->FilterStates); + } + FDK_FREE_MEMORY_1D(hEnc->phQmfFiltIn__FDK[ch]); + } + } + FDK_FREE_MEMORY_1D(hEnc->phQmfFiltIn__FDK); + } + for (ch = 0; ch < hEnc->setup.maxChIn; ch++) { + if (NULL != hEnc->phDCFilterSigIn[ch]) { + fdk_sacenc_destroyDCFilter(&hEnc->phDCFilterSigIn[ch]); + } + } + /* Close Onset Detection */ + for (ch = 0; ch < hEnc->setup.maxChIn; ch++) { + if (NULL != hEnc->phOnset[ch]) { + fdk_sacenc_onsetDetect_Close(&hEnc->phOnset[ch]); + } + } + if (hEnc->ppTrCurrPos) { + FDK_FREE_MEMORY_2D(hEnc->ppTrCurrPos); + } + if (hEnc->hFrameWindow) { + fdk_sacenc_frameWindow_Destroy(&hEnc->hFrameWindow); + } + /* Close Space Tree */ + if (NULL != hEnc->hSpaceTree) { + fdk_sacenc_spaceTree_Close(&hEnc->hSpaceTree); + } + if (NULL != hEnc->hEnhancedTimeDmx) { + fdk_sacenc_close_enhancedTimeDomainDmx(&hEnc->hEnhancedTimeDmx); + } + /* Close Static Gain */ + if (NULL != hEnc->hStaticGain) { + fdk_sacenc_staticGain_Close(&hEnc->hStaticGain); + } + if (NULL != hEnc->hStaticGainConfig) { + fdk_sacenc_staticGain_CloseConfig(&hEnc->hStaticGainConfig); + } + /* Close Delay*/ + if (NULL != hEnc->hDelay) { + fdk_sacenc_delay_Close(&hEnc->hDelay); + } + /* Delete Bitstream Stuff */ + if (NULL != hEnc->hBitstreamFormatter) { + fdk_sacenc_destroySpatialBitstreamEncoder(&(hEnc->hBitstreamFormatter)); + } + if (hEnc->pppHybridIn__FDK != NULL) { + if (hEnc->setup.bEncMode_212 == 1) { + FDK_FREE_MEMORY_3D(hEnc->pppHybridIn__FDK); + FDK_FREE_MEMORY_3D(hEnc->pppHybridInStatic__FDK); + } else { + FDK_FREE_MEMORY_3D(hEnc->pppHybridIn__FDK); + } + } + if (hEnc->pppProcDataIn__FDK != NULL) { + FDK_FREE_MEMORY_3D(hEnc->pppProcDataIn__FDK); + } + if (hEnc->pOutputDelayBuffer__FDK != NULL) { + FDK_FREE_MEMORY_1D(hEnc->pOutputDelayBuffer__FDK); + } + if (hEnc->ppTimeSigIn__FDK != NULL) { + { FDK_FREE_MEMORY_2D(hEnc->ppTimeSigIn__FDK); } + } + if (hEnc->ppTimeSigDelayIn__FDK != NULL) { + FDK_FREE_MEMORY_2D(hEnc->ppTimeSigDelayIn__FDK); + } + if (hEnc->ppTimeSigOut__FDK != NULL) { + FDK_FREE_MEMORY_2D(hEnc->ppTimeSigOut__FDK); + } + for (i = 0; i < MAX_NUM_PARAMS; i++) { + if (hEnc->pFrameWindowAna__FDK[i] != NULL) { + FDK_FREE_MEMORY_1D(hEnc->pFrameWindowAna__FDK[i]); + } + } + if (hEnc->pnOutputBits != NULL) { + FDK_FREE_MEMORY_1D(hEnc->pnOutputBits); + } + if (hEnc->ppBitstreamDelayBuffer != NULL) { + FDK_FREE_MEMORY_2D(hEnc->ppBitstreamDelayBuffer); + } + if (hEnc->sscBuf.pSsc != NULL) { + FDK_FREE_MEMORY_1D(hEnc->sscBuf.pSsc); + } + FDK_FREE_MEMORY_1D(*phMp4SpaceEnc); + } + } + + return error; +} + +/*----------------------------------------------------------------------------- + functionname: mp4SpaceEnc_InitDelayCompensation() + description: initialzes delay compensation + returns: noError on success, an apropriate error code else + -----------------------------------------------------------------------------*/ +static FDK_SACENC_ERROR mp4SpaceEnc_InitDelayCompensation( + HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, const INT coreCoderDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + /* Sanity Check */ + if (hMp4SpaceEnc == NULL) { + error = SACENC_INVALID_HANDLE; + } else { + hMp4SpaceEnc->coreCoderDelay = coreCoderDelay; + + if (SACENC_OK != (error = fdk_sacenc_delay_Init( + hMp4SpaceEnc->hDelay, hMp4SpaceEnc->nQmfBands, + hMp4SpaceEnc->nFrameLength, coreCoderDelay, + hMp4SpaceEnc->timeAlignment))) { + goto bail; + } + + fdk_sacenc_delay_SetDmxAlign(hMp4SpaceEnc->hDelay, 0); + fdk_sacenc_delay_SetTimeDomDmx( + hMp4SpaceEnc->hDelay, (hMp4SpaceEnc->useTimeDomDownmix >= 1) ? 1 : 0); + fdk_sacenc_delay_SetMinimizeDelay(hMp4SpaceEnc->hDelay, 1); + + if (SACENC_OK != (error = fdk_sacenc_delay_SubCalulateBufferDelays( + hMp4SpaceEnc->hDelay))) { + goto bail; + } + + /* init output delay compensation */ + hMp4SpaceEnc->nBitstreamDelayBuffer = + fdk_sacenc_delay_GetBitstreamFrameBufferSize(hMp4SpaceEnc->hDelay); + hMp4SpaceEnc->nOutputBufferDelay = + fdk_sacenc_delay_GetOutputAudioBufferDelay(hMp4SpaceEnc->hDelay); + hMp4SpaceEnc->nSurroundAnalysisBufferDelay = + fdk_sacenc_delay_GetSurroundAnalysisBufferDelay(hMp4SpaceEnc->hDelay); + hMp4SpaceEnc->nBitstreamBufferRead = 0; + hMp4SpaceEnc->nBitstreamBufferWrite = + hMp4SpaceEnc->nBitstreamDelayBuffer - 1; + + if (hMp4SpaceEnc->encMode == SACENC_212) { + /* mode 212 expects no bitstream delay */ + if (hMp4SpaceEnc->nBitstreamBufferWrite != + hMp4SpaceEnc->nBitstreamBufferRead) { + error = SACENC_PARAM_ERROR; + goto bail; + } + + /* mode 212 expects no output buffer delay */ + if (hMp4SpaceEnc->nOutputBufferDelay != 0) { + error = SACENC_PARAM_ERROR; + goto bail; + } + } + + /*** Input delay to obtain a net encoder delay that is a multiple + of the used framelength to ensure synchronization of framing + in artistic down-mix with the corresponding spatial data. ***/ + hMp4SpaceEnc->nDiscardOutFrames = + fdk_sacenc_delay_GetDiscardOutFrames(hMp4SpaceEnc->hDelay); + hMp4SpaceEnc->nInputDelay = + fdk_sacenc_delay_GetDmxAlignBufferDelay(hMp4SpaceEnc->hDelay); + + /* reset independency Flag counter */ + hMp4SpaceEnc->independencyCount = 0; + hMp4SpaceEnc->independencyFlag = 1; + + int i; + + /* write some parameters to bitstream */ + for (i = 0; i < hMp4SpaceEnc->nBitstreamDelayBuffer - 1; i++) { + SPATIALFRAME *pFrameData = NULL; + + if (NULL == (pFrameData = fdk_sacenc_getSpatialFrame( + hMp4SpaceEnc->hBitstreamFormatter, READ_SPATIALFRAME))) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + pFrameData->bsIndependencyFlag = 1; + pFrameData->framingInfo.numParamSets = 1; + pFrameData->framingInfo.bsFramingType = 0; + + fdk_sacenc_writeSpatialFrame( + hMp4SpaceEnc->ppBitstreamDelayBuffer[i], MAX_MPEGS_BYTES, + &hMp4SpaceEnc->pnOutputBits[i], hMp4SpaceEnc->hBitstreamFormatter); + } + + if ((hMp4SpaceEnc->nInputDelay > MAX_DELAY_INPUT) || + (hMp4SpaceEnc->nOutputBufferDelay > MAX_DELAY_OUTPUT) || + (hMp4SpaceEnc->nSurroundAnalysisBufferDelay > + MAX_DELAY_SURROUND_ANALYSIS) || + (hMp4SpaceEnc->nBitstreamDelayBuffer > MAX_BITSTREAM_DELAY)) { + error = SACENC_INIT_ERROR; + goto bail; + } + } + +bail: + + return error; +} + +static QUANTMODE __mapQuantMode(const MP4SPACEENC_QUANTMODE quantMode) { + QUANTMODE bsQuantMode = QUANTMODE_INVALID; + + switch (quantMode) { + case SACENC_QUANTMODE_FINE: + bsQuantMode = QUANTMODE_FINE; + break; + case SACENC_QUANTMODE_EBQ1: + bsQuantMode = QUANTMODE_EBQ1; + break; + case SACENC_QUANTMODE_EBQ2: + bsQuantMode = QUANTMODE_EBQ2; + break; + case SACENC_QUANTMODE_RSVD3: + case SACENC_QUANTMODE_INVALID: + default: + bsQuantMode = QUANTMODE_INVALID; + } /* switch hEnc->quantMode */ + + return bsQuantMode; +} + +static FDK_SACENC_ERROR FillSpatialSpecificConfig( + const HANDLE_MP4SPACE_ENCODER hEnc, SPATIALSPECIFICCONFIG *const hSsc) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hEnc) || (NULL == hSsc)) { + error = SACENC_INVALID_HANDLE; + } else { + SPACE_TREE_DESCRIPTION spaceTreeDescription; + int i; + + /* Get tree description */ + if (SACENC_OK != (error = fdk_sacenc_spaceTree_GetDescription( + hEnc->hSpaceTree, &spaceTreeDescription))) { + goto bail; + } + + /* Fill SSC */ + FDKmemclear(hSsc, sizeof(SPATIALSPECIFICCONFIG)); /* reset */ + + hSsc->numBands = hEnc->spaceTreeSetup.nParamBands; /* for bsFreqRes */ + + /* Fill tree configuration */ + hSsc->treeDescription.numOttBoxes = spaceTreeDescription.nOttBoxes; + hSsc->treeDescription.numInChan = spaceTreeDescription.nInChannels; + hSsc->treeDescription.numOutChan = spaceTreeDescription.nOutChannels; + + for (i = 0; i < SACENC_MAX_NUM_BOXES; i++) { + hSsc->ottConfig[i].bsOttBands = hSsc->numBands; + } + + switch (hEnc->encMode) { + case SACENC_212: + hSsc->bsTreeConfig = TREE_212; + break; + case SACENC_INVALID_MODE: + default: + error = SACENC_INVALID_CONFIG; + goto bail; + } + + hSsc->bsSamplingFrequency = + hEnc->nSampleRate; /* for bsSamplingFrequencyIndex */ + hSsc->bsFrameLength = hEnc->nFrameTimeSlots - 1; + + /* map decorr type */ + if (DECORR_INVALID == + (hSsc->bsDecorrConfig = mp4SpaceEnc_GetDecorrConfig(hEnc->encMode))) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* map quantMode */ + if (QUANTMODE_INVALID == + (hSsc->bsQuantMode = __mapQuantMode(hEnc->quantMode))) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* Configure Gains*/ + hSsc->bsFixedGainDMX = fdk_sacenc_staticGain_GetDmxGain(hEnc->hStaticGain); + hSsc->bsEnvQuantMode = 0; + + } /* valid handle */ + +bail: + return error; +} + +static FDK_SACENC_ERROR mp4SpaceEnc_FillSpaceTreeSetup( + const HANDLE_MP4SPACE_ENCODER hEnc, + SPACE_TREE_SETUP *const hSpaceTreeSetup) { + FDK_SACENC_ERROR error = SACENC_OK; + + /* Sanity Check */ + if (NULL == hEnc || NULL == hSpaceTreeSetup) { + error = SACENC_INVALID_HANDLE; + } else { + QUANTMODE tmpQuantmode = QUANTMODE_INVALID; + + /* map quantMode */ + if (QUANTMODE_INVALID == (tmpQuantmode = __mapQuantMode(hEnc->quantMode))) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + hSpaceTreeSetup->nParamBands = hEnc->nParamBands; + hSpaceTreeSetup->bUseCoarseQuantTtoCld = hEnc->useCoarseQuantCld; + hSpaceTreeSetup->bUseCoarseQuantTtoIcc = hEnc->useCoarseQuantIcc; + hSpaceTreeSetup->quantMode = tmpQuantmode; + hSpaceTreeSetup->nHybridBandsMax = hEnc->nHybridBands; + + switch (hEnc->encMode) { + case SACENC_212: + hSpaceTreeSetup->mode = SPACETREE_212; + hSpaceTreeSetup->nChannelsInMax = 2; + break; + case SACENC_INVALID_MODE: + default: + error = SACENC_INVALID_CONFIG; + goto bail; + } /* switch hEnc->encMode */ + + } /* valid handle */ +bail: + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_getInfo(const HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + MP4SPACEENC_INFO *const pInfo) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hMp4SpaceEnc) || (NULL == pInfo)) { + error = SACENC_INVALID_HANDLE; + } else { + pInfo->nSampleRate = hMp4SpaceEnc->nSampleRate; + pInfo->nSamplesFrame = hMp4SpaceEnc->nFrameLength; + pInfo->nTotalInputChannels = hMp4SpaceEnc->nInputChannels; + pInfo->nDmxDelay = fdk_sacenc_delay_GetInfoDmxDelay(hMp4SpaceEnc->hDelay); + pInfo->nCodecDelay = + fdk_sacenc_delay_GetInfoCodecDelay(hMp4SpaceEnc->hDelay); + pInfo->nDecoderDelay = + fdk_sacenc_delay_GetInfoDecoderDelay(hMp4SpaceEnc->hDelay); + pInfo->nPayloadDelay = + fdk_sacenc_delay_GetBitstreamFrameBufferSize(hMp4SpaceEnc->hDelay) - 1; + pInfo->nDiscardOutFrames = hMp4SpaceEnc->nDiscardOutFrames; + + pInfo->pSscBuf = &hMp4SpaceEnc->sscBuf; + } + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_setParam(HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + const SPACEENC_PARAM param, + const UINT value) { + FDK_SACENC_ERROR error = SACENC_OK; + + /* check encoder handle */ + if (hMp4SpaceEnc == NULL) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + /* apply param value */ + switch (param) { + case SACENC_LOWDELAY: + if (!((value == 0) || (value == 1) || (value == 2))) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.bLdMode = value; + break; + + case SACENC_ENC_MODE: + switch ((MP4SPACEENC_MODE)value) { + case SACENC_212: + hMp4SpaceEnc->user.encMode = (MP4SPACEENC_MODE)value; + break; + default: + error = SACENC_INVALID_CONFIG; + } + break; + + case SACENC_SAMPLERATE: + if (((int)value < 0) || + ((int)value > hMp4SpaceEnc->setup.maxSamplingrate)) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.sampleRate = value; + break; + + case SACENC_FRAME_TIME_SLOTS: + if (((int)value < 0) || + ((int)value > hMp4SpaceEnc->setup.maxFrameTimeSlots)) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.frameTimeSlots = value; + break; + + case SACENC_PARAM_BANDS: + switch ((MP4SPACEENC_BANDS_CONFIG)value) { + case SACENC_BANDS_4: + case SACENC_BANDS_5: + case SACENC_BANDS_7: + case SACENC_BANDS_9: + case SACENC_BANDS_12: + case SACENC_BANDS_15: + case SACENC_BANDS_23: + hMp4SpaceEnc->user.nParamBands = (MP4SPACEENC_BANDS_CONFIG)value; + break; + default: + error = SACENC_INVALID_CONFIG; + } + break; + + case SACENC_TIME_DOM_DMX: + if (!((value == 0) || (value == 2))) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.bTimeDomainDmx = value; + break; + + case SACENC_DMX_GAIN: + if (!((value == 0) || (value == 1) || (value == 2) || (value == 3) || + (value == 4) || (value == 5) || (value == 6) || (value == 7))) { + error = SACENC_INVALID_CONFIG; + break; + } + error = fdk_sacenc_staticGain_SetDmxGain(hMp4SpaceEnc->hStaticGainConfig, + (MP4SPACEENC_DMX_GAIN)value); + break; + + case SACENC_COARSE_QUANT: + if (!((value == 0) || (value == 1))) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.bUseCoarseQuant = value; + break; + + case SACENC_QUANT_MODE: + switch ((MP4SPACEENC_QUANTMODE)value) { + case SACENC_QUANTMODE_FINE: + case SACENC_QUANTMODE_EBQ1: + case SACENC_QUANTMODE_EBQ2: + hMp4SpaceEnc->user.quantMode = (MP4SPACEENC_QUANTMODE)value; + break; + default: + error = SACENC_INVALID_CONFIG; + } + break; + + case SACENC_TIME_ALIGNMENT: + if ((INT)value < -32768 || (INT)value > 32767) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.timeAlignment = value; + break; + + case SACENC_INDEPENDENCY_COUNT: + hMp4SpaceEnc->independencyCount = value; + break; + + case SACENC_INDEPENDENCY_FACTOR: + hMp4SpaceEnc->user.independencyFactor = value; + break; + + default: + error = SACENC_UNSUPPORTED_PARAMETER; + break; + } /* switch(param) */ +bail: + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_getLibInfo(LIB_INFO *info) { + int i = 0; + + if (info == NULL) { + return SACENC_INVALID_HANDLE; + } + + FDK_toolsGetLibInfo(info); + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return SACENC_INIT_ERROR; + } + + info[i].module_id = FDK_MPSENC; + info[i].build_date = SACENC_LIB_BUILD_DATE; + info[i].build_time = SACENC_LIB_BUILD_TIME; + info[i].title = SACENC_LIB_TITLE; + info[i].version = LIB_VERSION(SACENC_LIB_VL0, SACENC_LIB_VL1, SACENC_LIB_VL2); + LIB_VERSION_STRING(&info[i]); + + /* Capability flags */ + info[i].flags = 0; + /* End of flags */ + + return SACENC_OK; +} + +static DECORRCONFIG mp4SpaceEnc_GetDecorrConfig( + const MP4SPACEENC_MODE encMode) { + DECORRCONFIG decorrConfig = DECORR_INVALID; + + /* set decorrConfig dependent on tree mode */ + switch (encMode) { + case SACENC_212: + decorrConfig = DECORR_QMFSPLIT0; + break; + case SACENC_INVALID_MODE: + default: + decorrConfig = DECORR_INVALID; + } + return decorrConfig; +} + +static FDK_SACENC_ERROR mp4SpaceEnc_InitNumParamBands( + HANDLE_MP4SPACE_ENCODER hEnc, const MP4SPACEENC_BANDS_CONFIG nParamBands) { + FDK_SACENC_ERROR error = SACENC_OK; + + /* Set/Check nParamBands */ + int k = 0; + const int n = sizeof(pValidBands_Ld) / sizeof(UCHAR); + const UCHAR *pBands = pValidBands_Ld; + + while (k < n && pBands[k] != (UCHAR)nParamBands) ++k; + if (k == n) { + hEnc->nParamBands = SACENC_BANDS_INVALID; + } else { + hEnc->nParamBands = nParamBands; + } + return error; +} diff --git a/libSACenc/src/sacenc_nlc_enc.cpp b/libSACenc/src/sacenc_nlc_enc.cpp new file mode 100644 index 0000000..ecb89b7 --- /dev/null +++ b/libSACenc/src/sacenc_nlc_enc.cpp @@ -0,0 +1,1436 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Karsten Linzmeier + + Description: Noiseless Coding + Huffman encoder + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_nlc_enc.h" + +#include "genericStds.h" +#include "fixpoint_math.h" + +#include "sacenc_const.h" +#include "sacenc_huff_tab.h" +#include "sacenc_paramextract.h" + +/* Defines *******************************************************************/ +#define PAIR_SHIFT 4 +#define PAIR_MASK 0xf + +#define PBC_MIN_BANDS 5 + +typedef enum { + BACKWARDS = 0x0, + FORWARDS = 0x1 + +} DIRECTION; + +typedef enum { + DIFF_FREQ = 0x0, + DIFF_TIME = 0x1 + +} DIFF_TYPE; + +typedef enum { + HUFF_1D = 0x0, + HUFF_2D = 0x1 + +} CODING_SCHEME; + +typedef enum { + FREQ_PAIR = 0x0, + TIME_PAIR = 0x1 + +} PAIRING; + +/* Data Types ****************************************************************/ + +/* Constants *****************************************************************/ +static const UCHAR lavHuffVal[4] = {0, 2, 6, 7}; +static const UCHAR lavHuffLen[4] = {1, 2, 3, 3}; + +static const UCHAR lav_step_CLD[] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3}; +static const UCHAR lav_step_ICC[] = {0, 0, 1, 1, 2, 2, 3, 3}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static void split_lsb(const SHORT *const in_data, SHORT offset, + const INT num_val, SHORT *const out_data_lsb, + SHORT *const out_data_msb) { + int i; + + for (i = 0; i < num_val; i++) { + SHORT val = in_data[i] + offset; + if (out_data_lsb != NULL) out_data_lsb[i] = val & 0x0001; + if (out_data_msb != NULL) out_data_msb[i] = val >> 1; + } +} + +static void apply_lsb_coding(HANDLE_FDK_BITSTREAM strm, + const SHORT *const in_data_lsb, const UINT num_lsb, + const INT num_val) { + int i; + + for (i = 0; i < num_val; i++) { + FDKwriteBits(strm, in_data_lsb[i], num_lsb); + } +} + +static void calc_diff_freq(const SHORT *const in_data, SHORT *const out_data, + const INT num_val) { + int i; + out_data[0] = in_data[0]; + + for (i = 1; i < num_val; i++) { + out_data[i] = in_data[i] - in_data[i - 1]; + } +} + +static void calc_diff_time(const SHORT *const in_data, + const SHORT *const prev_data, SHORT *const out_data, + const INT num_val) { + int i; + out_data[0] = in_data[0]; + out_data[1] = prev_data[0]; + + for (i = 0; i < num_val; i++) { + out_data[i + 2] = in_data[i] - prev_data[i]; + } +} + +static INT sym_check(SHORT data[2], const INT lav, SHORT *const pSym_bits) { + UCHAR symBits = 0; + int sum_val = data[0] + data[1]; + int diff_val = data[0] - data[1]; + int num_sbits = 0; + + if (sum_val != 0) { + int sum_neg = (sum_val < 0) ? 1 : 0; + if (sum_neg) { + sum_val = -sum_val; + diff_val = -diff_val; + } + symBits = (symBits << 1) | sum_neg; + num_sbits++; + } + + if (diff_val != 0) { + int diff_neg = (diff_val < 0) ? 1 : 0; + if (diff_neg) { + diff_val = -diff_val; + } + symBits = (symBits << 1) | diff_neg; + num_sbits++; + } + + if (pSym_bits != NULL) { + *pSym_bits = symBits; + } + + if (sum_val % 2) { + data[0] = lav - sum_val / 2; + data[1] = lav - diff_val / 2; + } else { + data[0] = sum_val / 2; + data[1] = diff_val / 2; + } + + return num_sbits; +} + +static INT ilog2(UINT i) { + int l = 0; + + if (i) i--; + while (i > 0) { + i >>= 1; + l++; + } + + return l; +} + +static SHORT calc_pcm_bits(const SHORT num_val, const SHORT num_levels) { + SHORT num_complete_chunks = 0, rest_chunk_size = 0; + SHORT max_grp_len = 0, bits_pcm = 0; + int chunk_levels, i; + + switch (num_levels) { + case 3: + max_grp_len = 5; + break; + case 6: + max_grp_len = 5; + break; + case 7: + max_grp_len = 6; + break; + case 11: + max_grp_len = 2; + break; + case 13: + max_grp_len = 4; + break; + case 19: + max_grp_len = 4; + break; + case 25: + max_grp_len = 3; + break; + case 51: + max_grp_len = 4; + break; + default: + max_grp_len = 1; + } + + num_complete_chunks = num_val / max_grp_len; + rest_chunk_size = num_val % max_grp_len; + + chunk_levels = 1; + for (i = 1; i <= max_grp_len; i++) { + chunk_levels *= num_levels; + } + + bits_pcm = (SHORT)(ilog2(chunk_levels) * num_complete_chunks); + bits_pcm += (SHORT)(ilog2(num_levels) * rest_chunk_size); + + return bits_pcm; +} + +static void apply_pcm_coding(HANDLE_FDK_BITSTREAM strm, + const SHORT *const in_data_1, + const SHORT *const in_data_2, const SHORT offset, + const SHORT num_val, const SHORT num_levels) { + SHORT i = 0, j = 0, idx = 0; + SHORT max_grp_len = 0, grp_len = 0, next_val = 0; + int grp_val = 0, chunk_levels = 0; + + SHORT pcm_chunk_size[7] = {0}; + + switch (num_levels) { + case 3: + max_grp_len = 5; + break; + case 5: + max_grp_len = 3; + break; + case 6: + max_grp_len = 5; + break; + case 7: + max_grp_len = 6; + break; + case 9: + max_grp_len = 5; + break; + case 11: + max_grp_len = 2; + break; + case 13: + max_grp_len = 4; + break; + case 19: + max_grp_len = 4; + break; + case 25: + max_grp_len = 3; + break; + case 51: + max_grp_len = 4; + break; + default: + max_grp_len = 1; + } + + chunk_levels = 1; + for (i = 1; i <= max_grp_len; i++) { + chunk_levels *= num_levels; + pcm_chunk_size[i] = ilog2(chunk_levels); + } + + for (i = 0; i < num_val; i += max_grp_len) { + grp_len = FDKmin(max_grp_len, num_val - i); + grp_val = 0; + for (j = 0; j < grp_len; j++) { + idx = i + j; + if (in_data_2 == NULL) { + next_val = in_data_1[idx]; + } else if (in_data_1 == NULL) { + next_val = in_data_2[idx]; + } else { + next_val = ((idx % 2) ? in_data_2[idx / 2] : in_data_1[idx / 2]); + } + next_val += offset; + grp_val = grp_val * num_levels + next_val; + } + + FDKwriteBits(strm, grp_val, pcm_chunk_size[grp_len]); + } +} + +static UINT huff_enc_1D(HANDLE_FDK_BITSTREAM strm, const DATA_TYPE data_type, + const INT dim1, SHORT *const in_data, + const SHORT num_val, const SHORT p0_flag) { + int i, offset = 0; + UINT huffBits = 0; + + HUFF_ENTRY part0 = {0}; + const HUFF_ENTRY *pHuffTab = NULL; + + switch (data_type) { + case t_CLD: + part0 = fdk_sacenc_huffPart0Tab.cld[in_data[0]]; + pHuffTab = fdk_sacenc_huffCLDTab.h1D[dim1]; + break; + case t_ICC: + part0 = fdk_sacenc_huffPart0Tab.icc[in_data[0]]; + pHuffTab = fdk_sacenc_huffICCTab.h1D[dim1]; + break; + } + + if (p0_flag) { + huffBits += FDKwriteBits(strm, HUFF_VALUE(part0), HUFF_LENGTH(part0)); + offset = 1; + } + + for (i = offset; i < num_val; i++) { + int id_sign = 0; + int id = in_data[i]; + + if (id != 0) { + id_sign = 0; + if (id < 0) { + id = -id; + id_sign = 1; + } + } + + huffBits += + FDKwriteBits(strm, HUFF_VALUE(pHuffTab[id]), HUFF_LENGTH(pHuffTab[id])); + + if (id != 0) { + huffBits += FDKwriteBits(strm, id_sign, 1); + } + } /* for i */ + + return huffBits; +} + +static void getHuffEntry(const INT lav, const DATA_TYPE data_type, const INT i, + const SHORT tab_idx_2D[2], const SHORT in_data[][2], + HUFF_ENTRY *const pEntry, HUFF_ENTRY *const pEscape) { + const HUFF_CLD_TAB_2D *pCLD2dTab = + &fdk_sacenc_huffCLDTab.h2D[tab_idx_2D[0]][tab_idx_2D[1]]; + const HUFF_ICC_TAB_2D *pICC2dTab = + &fdk_sacenc_huffICCTab.h2D[tab_idx_2D[0]][tab_idx_2D[1]]; + + switch (lav) { + case 1: { + const LAV1_2D *pLav1 = NULL; + switch (data_type) { + case t_CLD: + pLav1 = NULL; + break; + case t_ICC: + pLav1 = &pICC2dTab->lav1; + break; + } + if (pLav1 != NULL) { + *pEntry = pLav1->entry[in_data[i][0]][in_data[i][1]]; + *pEscape = pLav1->escape; + } + } break; + case 3: { + const LAV3_2D *pLav3 = NULL; + switch (data_type) { + case t_CLD: + pLav3 = &pCLD2dTab->lav3; + break; + case t_ICC: + pLav3 = &pICC2dTab->lav3; + break; + } + if (pLav3 != NULL) { + *pEntry = pLav3->entry[in_data[i][0]][in_data[i][1]]; + *pEscape = pLav3->escape; + } + } break; + case 5: { + const LAV5_2D *pLav5 = NULL; + switch (data_type) { + case t_CLD: + pLav5 = &pCLD2dTab->lav5; + break; + case t_ICC: + pLav5 = &pICC2dTab->lav5; + break; + } + if (pLav5 != NULL) { + *pEntry = pLav5->entry[in_data[i][0]][in_data[i][1]]; + *pEscape = pLav5->escape; + } + } break; + case 7: { + const LAV7_2D *pLav7 = NULL; + switch (data_type) { + case t_CLD: + pLav7 = &pCLD2dTab->lav7; + break; + case t_ICC: + pLav7 = &pICC2dTab->lav7; + break; + } + if (pLav7 != NULL) { + *pEntry = pLav7->entry[in_data[i][0]][in_data[i][1]]; + *pEscape = pLav7->escape; + } + } break; + case 9: { + const LAV9_2D *pLav9 = NULL; + switch (data_type) { + case t_CLD: + pLav9 = &pCLD2dTab->lav9; + break; + case t_ICC: + pLav9 = NULL; + break; + } + if (pLav9 != NULL) { + *pEntry = pLav9->entry[in_data[i][0]][in_data[i][1]]; + *pEscape = pLav9->escape; + } + } break; + } +} + +static UINT huff_enc_2D(HANDLE_FDK_BITSTREAM strm, const DATA_TYPE data_type, + SHORT tab_idx_2D[2], SHORT lav_idx, SHORT in_data[][2], + SHORT num_val, SHORT stride, SHORT *p0_data[2]) { + SHORT i = 0, lav = 0, num_sbits = 0, sym_bits = 0, escIdx = 0; + SHORT esc_data[2][MAXBANDS] = {{0}}; + + UINT huffBits = 0; + + const HUFF_ENTRY *pHuffEntry = NULL; + + switch (data_type) { + case t_CLD: + lav = 2 * lav_idx + 3; /* LAV */ + pHuffEntry = fdk_sacenc_huffPart0Tab.cld; + break; + case t_ICC: + lav = 2 * lav_idx + 1; /* LAV */ + pHuffEntry = fdk_sacenc_huffPart0Tab.icc; + break; + } + + /* Partition 0 */ + if (p0_data[0] != NULL) { + HUFF_ENTRY entry = pHuffEntry[*p0_data[0]]; + huffBits += FDKwriteBits(strm, HUFF_VALUE(entry), HUFF_LENGTH(entry)); + } + if (p0_data[1] != NULL) { + HUFF_ENTRY entry = pHuffEntry[*p0_data[1]]; + huffBits += FDKwriteBits(strm, HUFF_VALUE(entry), HUFF_LENGTH(entry)); + } + + for (i = 0; i < num_val; i += stride) { + HUFF_ENTRY entry = {0}; + HUFF_ENTRY escape = {0}; + + esc_data[0][escIdx] = in_data[i][0] + lav; + esc_data[1][escIdx] = in_data[i][1] + lav; + + num_sbits = sym_check(in_data[i], lav, &sym_bits); + + getHuffEntry(lav, data_type, i, tab_idx_2D, in_data, &entry, &escape); + + huffBits += FDKwriteBits(strm, HUFF_VALUE(entry), HUFF_LENGTH(entry)); + + if ((HUFF_VALUE(entry) == HUFF_VALUE(escape)) && + (HUFF_LENGTH(entry) == HUFF_LENGTH(escape))) { + escIdx++; + } else { + huffBits += FDKwriteBits(strm, sym_bits, num_sbits); + } + } /* for i */ + + if (escIdx > 0) { + huffBits += calc_pcm_bits(2 * escIdx, (2 * lav + 1)); + if (strm != NULL) { + apply_pcm_coding(strm, esc_data[0], esc_data[1], 0 /*offset*/, 2 * escIdx, + (2 * lav + 1)); + } + } + + return huffBits; +} + +static SCHAR get_next_lav_step(const INT lav, const DATA_TYPE data_type) { + SCHAR lav_step = 0; + + switch (data_type) { + case t_CLD: + lav_step = (lav > 9) ? -1 : lav_step_CLD[lav]; + break; + case t_ICC: + lav_step = (lav > 7) ? -1 : lav_step_ICC[lav]; + break; + } + + return lav_step; +} + +static INT diff_type_offset(const DIFF_TYPE diff_type) { + int offset = 0; + switch (diff_type) { + case DIFF_FREQ: + offset = 0; + break; + case DIFF_TIME: + offset = 2; + break; + } + return offset; +} + +static SHORT calc_huff_bits(SHORT *in_data_1, SHORT *in_data_2, + const DATA_TYPE data_type, + const DIFF_TYPE diff_type_1, + const DIFF_TYPE diff_type_2, const SHORT num_val, + SHORT *const lav_idx, SHORT *const cdg_scheme) { + SHORT tab_idx_2D[2][2] = {{0}}; + SHORT tab_idx_1D[2] = {0}; + SHORT df_rest_flag[2] = {0}; + SHORT p0_flag[2] = {0}; + + SHORT pair_vec[MAXBANDS][2] = {{0}}; + + SHORT *p0_data_1[2] = {NULL}; + SHORT *p0_data_2[2] = {NULL}; + + SHORT i = 0; + SHORT lav_fp[2] = {0}; + + SHORT bit_count_1D = 0; + SHORT bit_count_2D_freq = 0; + SHORT bit_count_min = 0; + + SHORT num_val_1_short = 0; + SHORT num_val_2_short = 0; + + SHORT *in_data_1_short = NULL; + SHORT *in_data_2_short = NULL; + + /* 1D Huffman coding */ + bit_count_1D = 1; /* HUFF_1D */ + + num_val_1_short = num_val; + num_val_2_short = num_val; + + if (in_data_1 != NULL) { + in_data_1_short = in_data_1 + diff_type_offset(diff_type_1); + } + if (in_data_2 != NULL) { + in_data_2_short = in_data_2 + diff_type_offset(diff_type_2); + } + + p0_flag[0] = (diff_type_1 == DIFF_FREQ); + p0_flag[1] = (diff_type_2 == DIFF_FREQ); + + tab_idx_1D[0] = (diff_type_1 == DIFF_FREQ) ? 0 : 1; + tab_idx_1D[1] = (diff_type_2 == DIFF_FREQ) ? 0 : 1; + + if (in_data_1 != NULL) { + bit_count_1D += huff_enc_1D(NULL, data_type, tab_idx_1D[0], in_data_1_short, + num_val_1_short, p0_flag[0]); + } + if (in_data_2 != NULL) { + bit_count_1D += huff_enc_1D(NULL, data_type, tab_idx_1D[1], in_data_2_short, + num_val_2_short, p0_flag[1]); + } + + bit_count_min = bit_count_1D; + *cdg_scheme = HUFF_1D << PAIR_SHIFT; + lav_idx[0] = lav_idx[1] = -1; + + /* Huffman 2D frequency pairs */ + bit_count_2D_freq = 1; /* HUFF_2D */ + + num_val_1_short = num_val; + num_val_2_short = num_val; + + if (in_data_1 != NULL) { + in_data_1_short = in_data_1 + diff_type_offset(diff_type_1); + } + if (in_data_2 != NULL) { + in_data_2_short = in_data_2 + diff_type_offset(diff_type_2); + } + + lav_fp[0] = lav_fp[1] = 0; + + p0_data_1[0] = NULL; + p0_data_1[1] = NULL; + p0_data_2[0] = NULL; + p0_data_2[1] = NULL; + + if (in_data_1 != NULL) { + if (diff_type_1 == DIFF_FREQ) { + p0_data_1[0] = &in_data_1[0]; + p0_data_1[1] = NULL; + + num_val_1_short -= 1; + in_data_1_short += 1; + } + + df_rest_flag[0] = num_val_1_short % 2; + + if (df_rest_flag[0]) num_val_1_short -= 1; + + for (i = 0; i < num_val_1_short - 1; i += 2) { + pair_vec[i][0] = in_data_1_short[i]; + pair_vec[i][1] = in_data_1_short[i + 1]; + + lav_fp[0] = FDKmax(lav_fp[0], fAbs(pair_vec[i][0])); + lav_fp[0] = FDKmax(lav_fp[0], fAbs(pair_vec[i][1])); + } + + tab_idx_2D[0][0] = (diff_type_1 == DIFF_TIME) ? 1 : 0; + tab_idx_2D[0][1] = 0; + + tab_idx_1D[0] = (diff_type_1 == DIFF_FREQ) ? 0 : 1; + + lav_fp[0] = get_next_lav_step(lav_fp[0], data_type); + + if (lav_fp[0] != -1) bit_count_2D_freq += lavHuffLen[lav_fp[0]]; + } + + if (in_data_2 != NULL) { + if (diff_type_2 == DIFF_FREQ) { + p0_data_2[0] = NULL; + p0_data_2[1] = &in_data_2[0]; + + num_val_2_short -= 1; + in_data_2_short += 1; + } + + df_rest_flag[1] = num_val_2_short % 2; + + if (df_rest_flag[1]) num_val_2_short -= 1; + + for (i = 0; i < num_val_2_short - 1; i += 2) { + pair_vec[i + 1][0] = in_data_2_short[i]; + pair_vec[i + 1][1] = in_data_2_short[i + 1]; + + lav_fp[1] = FDKmax(lav_fp[1], fAbs(pair_vec[i + 1][0])); + lav_fp[1] = FDKmax(lav_fp[1], fAbs(pair_vec[i + 1][1])); + } + + tab_idx_2D[1][0] = (diff_type_2 == DIFF_TIME) ? 1 : 0; + tab_idx_2D[1][1] = 0; + + tab_idx_1D[1] = (diff_type_2 == DIFF_FREQ) ? 0 : 1; + + lav_fp[1] = get_next_lav_step(lav_fp[1], data_type); + + if (lav_fp[1] != -1) bit_count_2D_freq += lavHuffLen[lav_fp[1]]; + } + + if ((lav_fp[0] != -1) && (lav_fp[1] != -1)) { + if (in_data_1 != NULL) { + bit_count_2D_freq += + huff_enc_2D(NULL, data_type, tab_idx_2D[0], lav_fp[0], pair_vec, + num_val_1_short, 2, p0_data_1); + } + if (in_data_2 != NULL) { + bit_count_2D_freq += + huff_enc_2D(NULL, data_type, tab_idx_2D[1], lav_fp[1], pair_vec + 1, + num_val_2_short, 2, p0_data_2); + } + if (in_data_1 != NULL) { + if (df_rest_flag[0]) + bit_count_2D_freq += + huff_enc_1D(NULL, data_type, tab_idx_1D[0], + in_data_1_short + num_val_1_short, 1, 0); + } + if (in_data_2 != NULL) { + if (df_rest_flag[1]) + bit_count_2D_freq += + huff_enc_1D(NULL, data_type, tab_idx_1D[1], + in_data_2_short + num_val_2_short, 1, 0); + } + + if (bit_count_2D_freq < bit_count_min) { + bit_count_min = bit_count_2D_freq; + *cdg_scheme = HUFF_2D << PAIR_SHIFT | FREQ_PAIR; + lav_idx[0] = lav_fp[0]; + lav_idx[1] = lav_fp[1]; + } + } + + return bit_count_min; +} + +static void apply_huff_coding(HANDLE_FDK_BITSTREAM strm, SHORT *const in_data_1, + SHORT *const in_data_2, const DATA_TYPE data_type, + const DIFF_TYPE diff_type_1, + const DIFF_TYPE diff_type_2, const SHORT num_val, + const SHORT *const lav_idx, + const SHORT cdg_scheme) { + SHORT tab_idx_2D[2][2] = {{0}}; + SHORT tab_idx_1D[2] = {0}; + SHORT df_rest_flag[2] = {0}; + SHORT p0_flag[2] = {0}; + + SHORT pair_vec[MAXBANDS][2] = {{0}}; + + SHORT *p0_data_1[2] = {NULL}; + SHORT *p0_data_2[2] = {NULL}; + + SHORT i = 0; + + SHORT num_val_1_short = num_val; + SHORT num_val_2_short = num_val; + + SHORT *in_data_1_short = NULL; + SHORT *in_data_2_short = NULL; + + /* Offset */ + if (in_data_1 != NULL) { + in_data_1_short = in_data_1 + diff_type_offset(diff_type_1); + } + if (in_data_2 != NULL) { + in_data_2_short = in_data_2 + diff_type_offset(diff_type_2); + } + + /* Signalize coding scheme */ + FDKwriteBits(strm, cdg_scheme >> PAIR_SHIFT, 1); + + switch (cdg_scheme >> PAIR_SHIFT) { + case HUFF_1D: + + p0_flag[0] = (diff_type_1 == DIFF_FREQ); + p0_flag[1] = (diff_type_2 == DIFF_FREQ); + + tab_idx_1D[0] = (diff_type_1 == DIFF_FREQ) ? 0 : 1; + tab_idx_1D[1] = (diff_type_2 == DIFF_FREQ) ? 0 : 1; + + if (in_data_1 != NULL) { + huff_enc_1D(strm, data_type, tab_idx_1D[0], in_data_1_short, + num_val_1_short, p0_flag[0]); + } + if (in_data_2 != NULL) { + huff_enc_1D(strm, data_type, tab_idx_1D[1], in_data_2_short, + num_val_2_short, p0_flag[1]); + } + break; /* HUFF_1D */ + + case HUFF_2D: + + switch (cdg_scheme & PAIR_MASK) { + case FREQ_PAIR: + + if (in_data_1 != NULL) { + if (diff_type_1 == DIFF_FREQ) { + p0_data_1[0] = &in_data_1[0]; + p0_data_1[1] = NULL; + + num_val_1_short -= 1; + in_data_1_short += 1; + } + + df_rest_flag[0] = num_val_1_short % 2; + + if (df_rest_flag[0]) num_val_1_short -= 1; + + for (i = 0; i < num_val_1_short - 1; i += 2) { + pair_vec[i][0] = in_data_1_short[i]; + pair_vec[i][1] = in_data_1_short[i + 1]; + } + + tab_idx_2D[0][0] = (diff_type_1 == DIFF_TIME) ? 1 : 0; + tab_idx_2D[0][1] = 0; + + tab_idx_1D[0] = (diff_type_1 == DIFF_FREQ) ? 0 : 1; + } /* if( in_data_1 != NULL ) */ + + if (in_data_2 != NULL) { + if (diff_type_2 == DIFF_FREQ) { + p0_data_2[0] = NULL; + p0_data_2[1] = &in_data_2[0]; + + num_val_2_short -= 1; + in_data_2_short += 1; + } + + df_rest_flag[1] = num_val_2_short % 2; + + if (df_rest_flag[1]) num_val_2_short -= 1; + + for (i = 0; i < num_val_2_short - 1; i += 2) { + pair_vec[i + 1][0] = in_data_2_short[i]; + pair_vec[i + 1][1] = in_data_2_short[i + 1]; + } + + tab_idx_2D[1][0] = (diff_type_2 == DIFF_TIME) ? 1 : 0; + tab_idx_2D[1][1] = 0; + + tab_idx_1D[1] = (diff_type_2 == DIFF_FREQ) ? 0 : 1; + } /* if( in_data_2 != NULL ) */ + + if (in_data_1 != NULL) { + FDKwriteBits(strm, lavHuffVal[lav_idx[0]], lavHuffLen[lav_idx[0]]); + huff_enc_2D(strm, data_type, tab_idx_2D[0], lav_idx[0], pair_vec, + num_val_1_short, 2, p0_data_1); + if (df_rest_flag[0]) { + huff_enc_1D(strm, data_type, tab_idx_1D[0], + in_data_1_short + num_val_1_short, 1, 0); + } + } + if (in_data_2 != NULL) { + FDKwriteBits(strm, lavHuffVal[lav_idx[1]], lavHuffLen[lav_idx[1]]); + huff_enc_2D(strm, data_type, tab_idx_2D[1], lav_idx[1], + pair_vec + 1, num_val_2_short, 2, p0_data_2); + if (df_rest_flag[1]) { + huff_enc_1D(strm, data_type, tab_idx_1D[1], + in_data_2_short + num_val_2_short, 1, 0); + } + } + break; /* FREQ_PAIR */ + + case TIME_PAIR: + + if ((diff_type_1 == DIFF_FREQ) || (diff_type_2 == DIFF_FREQ)) { + p0_data_1[0] = &in_data_1[0]; + p0_data_1[1] = &in_data_2[0]; + + in_data_1_short += 1; + in_data_2_short += 1; + + num_val_1_short -= 1; + } + + for (i = 0; i < num_val_1_short; i++) { + pair_vec[i][0] = in_data_1_short[i]; + pair_vec[i][1] = in_data_2_short[i]; + } + + tab_idx_2D[0][0] = + ((diff_type_1 == DIFF_TIME) || (diff_type_2 == DIFF_TIME)) ? 1 + : 0; + tab_idx_2D[0][1] = 1; + + FDKwriteBits(strm, lavHuffVal[lav_idx[0]], lavHuffLen[lav_idx[0]]); + + huff_enc_2D(strm, data_type, tab_idx_2D[0], lav_idx[0], pair_vec, + num_val_1_short, 1, p0_data_1); + + break; /* TIME_PAIR */ + } /* switch( cdg_scheme & PAIR_MASK ) */ + + break; /* HUFF_2D */ + + default: + break; + } /* switch( cdg_scheme >> PAIR_SHIFT ) */ +} + +INT fdk_sacenc_ecDataPairEnc(HANDLE_FDK_BITSTREAM strm, + SHORT aaInData[][MAXBANDS], + SHORT aHistory[MAXBANDS], + const DATA_TYPE data_type, const INT setIdx, + const INT startBand, const INT dataBands, + const INT coarse_flag, + const INT independency_flag) { + SHORT reset = 0, pb = 0; + SHORT quant_levels = 0, quant_offset = 0, num_pcm_val = 0; + + SHORT splitLsb_flag = 0; + SHORT pcmCoding_flag = 0; + + SHORT allowDiffTimeBack_flag = !independency_flag || (setIdx > 0); + + SHORT num_lsb_bits = -1; + SHORT num_pcm_bits = -1; + + SHORT quant_data_lsb[2][MAXBANDS]; + SHORT quant_data_msb[2][MAXBANDS]; + + SHORT quant_data_hist_lsb[MAXBANDS]; + SHORT quant_data_hist_msb[MAXBANDS]; + + SHORT data_diff_freq[2][MAXBANDS]; + SHORT data_diff_time[2][MAXBANDS + 2]; + + SHORT *p_quant_data_msb[2]; + SHORT *p_quant_data_hist_msb = NULL; + + SHORT min_bits_all = 0; + SHORT min_found = 0; + + SHORT min_bits_df_df = -1; + SHORT min_bits_df_dt = -1; + SHORT min_bits_dtbw_df = -1; + SHORT min_bits_dt_dt = -1; + + SHORT lav_df_df[2] = {-1, -1}; + SHORT lav_df_dt[2] = {-1, -1}; + SHORT lav_dtbw_df[2] = {-1, -1}; + SHORT lav_dt_dt[2] = {-1, -1}; + + SHORT coding_scheme_df_df = 0; + SHORT coding_scheme_df_dt = 0; + SHORT coding_scheme_dtbw_df = 0; + SHORT coding_scheme_dt_dt = 0; + + switch (data_type) { + case t_CLD: + if (coarse_flag) { + splitLsb_flag = 0; + quant_levels = 15; + quant_offset = 7; + } else { + splitLsb_flag = 0; + quant_levels = 31; + quant_offset = 15; + } + break; + case t_ICC: + if (coarse_flag) { + splitLsb_flag = 0; + quant_levels = 4; + quant_offset = 0; + } else { + splitLsb_flag = 0; + quant_levels = 8; + quant_offset = 0; + } + break; + } /* switch( data_type ) */ + + /* Split off LSB */ + if (splitLsb_flag) { + split_lsb(aaInData[setIdx] + startBand, quant_offset, dataBands, + quant_data_lsb[0], quant_data_msb[0]); + + split_lsb(aaInData[setIdx + 1] + startBand, quant_offset, dataBands, + quant_data_lsb[1], quant_data_msb[1]); + + p_quant_data_msb[0] = quant_data_msb[0]; + p_quant_data_msb[1] = quant_data_msb[1]; + + num_lsb_bits = 2 * dataBands; + } else if (quant_offset != 0) { + for (pb = 0; pb < dataBands; pb++) { + quant_data_msb[0][pb] = aaInData[setIdx][startBand + pb] + quant_offset; + quant_data_msb[1][pb] = + aaInData[setIdx + 1][startBand + pb] + quant_offset; + } + + p_quant_data_msb[0] = quant_data_msb[0]; + p_quant_data_msb[1] = quant_data_msb[1]; + + num_lsb_bits = 0; + } else { + p_quant_data_msb[0] = aaInData[setIdx] + startBand; + p_quant_data_msb[1] = aaInData[setIdx + 1] + startBand; + + num_lsb_bits = 0; + } + + if (allowDiffTimeBack_flag) { + if (splitLsb_flag) { + split_lsb(aHistory + startBand, quant_offset, dataBands, + quant_data_hist_lsb, quant_data_hist_msb); + + p_quant_data_hist_msb = quant_data_hist_msb; + } else if (quant_offset != 0) { + for (pb = 0; pb < dataBands; pb++) { + quant_data_hist_msb[pb] = aHistory[startBand + pb] + quant_offset; + } + p_quant_data_hist_msb = quant_data_hist_msb; + } else { + p_quant_data_hist_msb = aHistory + startBand; + } + } + + /* Calculate frequency differences */ + calc_diff_freq(p_quant_data_msb[0], data_diff_freq[0], dataBands); + + calc_diff_freq(p_quant_data_msb[1], data_diff_freq[1], dataBands); + + /* Calculate time differences */ + if (allowDiffTimeBack_flag) { + calc_diff_time(p_quant_data_msb[0], p_quant_data_hist_msb, + data_diff_time[0], dataBands); + } + + calc_diff_time(p_quant_data_msb[1], p_quant_data_msb[0], data_diff_time[1], + dataBands); + + /* Calculate coding scheme with minumum bit consumption */ + + /**********************************************************/ + num_pcm_bits = calc_pcm_bits(2 * dataBands, quant_levels); + num_pcm_val = 2 * dataBands; + + /**********************************************************/ + + min_bits_all = num_pcm_bits; + + /**********************************************************/ + /**********************************************************/ + + /**********************************************************/ + min_bits_df_df = + calc_huff_bits(data_diff_freq[0], data_diff_freq[1], data_type, DIFF_FREQ, + DIFF_FREQ, dataBands, lav_df_df, &coding_scheme_df_df); + + min_bits_df_df += 2; + + min_bits_df_df += num_lsb_bits; + + if (min_bits_df_df < min_bits_all) { + min_bits_all = min_bits_df_df; + } + /**********************************************************/ + + /**********************************************************/ + min_bits_df_dt = + calc_huff_bits(data_diff_freq[0], data_diff_time[1], data_type, DIFF_FREQ, + DIFF_TIME, dataBands, lav_df_dt, &coding_scheme_df_dt); + + min_bits_df_dt += 2; + + min_bits_df_dt += num_lsb_bits; + + if (min_bits_df_dt < min_bits_all) { + min_bits_all = min_bits_df_dt; + } + /**********************************************************/ + + /**********************************************************/ + /**********************************************************/ + + if (allowDiffTimeBack_flag) { + /**********************************************************/ + min_bits_dtbw_df = calc_huff_bits( + data_diff_time[0], data_diff_freq[1], data_type, DIFF_TIME, DIFF_FREQ, + dataBands, lav_dtbw_df, &coding_scheme_dtbw_df); + + min_bits_dtbw_df += 2; + + min_bits_dtbw_df += num_lsb_bits; + + if (min_bits_dtbw_df < min_bits_all) { + min_bits_all = min_bits_dtbw_df; + } + /**********************************************************/ + + /**********************************************************/ + min_bits_dt_dt = calc_huff_bits(data_diff_time[0], data_diff_time[1], + data_type, DIFF_TIME, DIFF_TIME, dataBands, + lav_dt_dt, &coding_scheme_dt_dt); + + min_bits_dt_dt += 2; + + min_bits_dt_dt += num_lsb_bits; + + if (min_bits_dt_dt < min_bits_all) { + min_bits_all = min_bits_dt_dt; + } + /**********************************************************/ + + } /* if( allowDiffTimeBack_flag ) */ + + /***************************/ + /* Start actual coding now */ + /***************************/ + + /* PCM or Diff/Huff Coding? */ + pcmCoding_flag = (min_bits_all == num_pcm_bits); + + FDKwriteBits(strm, pcmCoding_flag, 1); + + if (pcmCoding_flag) { + /* Grouped PCM Coding */ + apply_pcm_coding(strm, aaInData[setIdx] + startBand, + aaInData[setIdx + 1] + startBand, quant_offset, + num_pcm_val, quant_levels); + } else { + /* Diff/Huff Coding */ + + min_found = 0; + + /*******************************************/ + if (min_bits_all == min_bits_df_df) { + FDKwriteBits(strm, DIFF_FREQ, 1); + FDKwriteBits(strm, DIFF_FREQ, 1); + + apply_huff_coding(strm, data_diff_freq[0], data_diff_freq[1], data_type, + DIFF_FREQ, DIFF_FREQ, dataBands, lav_df_df, + coding_scheme_df_df); + + min_found = 1; + } + /*******************************************/ + + /*******************************************/ + if (!min_found && (min_bits_all == min_bits_df_dt)) { + FDKwriteBits(strm, DIFF_FREQ, 1); + FDKwriteBits(strm, DIFF_TIME, 1); + + apply_huff_coding(strm, data_diff_freq[0], data_diff_time[1], data_type, + DIFF_FREQ, DIFF_TIME, dataBands, lav_df_dt, + coding_scheme_df_dt); + + min_found = 1; + } + /*******************************************/ + + /*******************************************/ + /*******************************************/ + + if (allowDiffTimeBack_flag) { + /*******************************************/ + if (!min_found && (min_bits_all == min_bits_dtbw_df)) { + FDKwriteBits(strm, DIFF_TIME, 1); + FDKwriteBits(strm, DIFF_FREQ, 1); + + apply_huff_coding(strm, data_diff_time[0], data_diff_freq[1], data_type, + DIFF_TIME, DIFF_FREQ, dataBands, lav_dtbw_df, + coding_scheme_dtbw_df); + + min_found = 1; + } + /*******************************************/ + + /*******************************************/ + if (!min_found && (min_bits_all == min_bits_dt_dt)) { + FDKwriteBits(strm, DIFF_TIME, 1); + FDKwriteBits(strm, DIFF_TIME, 1); + + apply_huff_coding(strm, data_diff_time[0], data_diff_time[1], data_type, + DIFF_TIME, DIFF_TIME, dataBands, lav_dt_dt, + coding_scheme_dt_dt); + } + /*******************************************/ + + } /* if( allowDiffTimeBack_flag ) */ + + /* LSB coding */ + if (splitLsb_flag) { + apply_lsb_coding(strm, quant_data_lsb[0], 1, dataBands); + + apply_lsb_coding(strm, quant_data_lsb[1], 1, dataBands); + } + + } /* Diff/Huff/LSB coding */ + + return reset; +} + +INT fdk_sacenc_ecDataSingleEnc(HANDLE_FDK_BITSTREAM strm, + SHORT aaInData[][MAXBANDS], + SHORT aHistory[MAXBANDS], + const DATA_TYPE data_type, const INT setIdx, + const INT startBand, const INT dataBands, + const INT coarse_flag, + const INT independency_flag) { + SHORT reset = 0, pb = 0; + SHORT quant_levels = 0, quant_offset = 0, num_pcm_val = 0; + + SHORT splitLsb_flag = 0; + SHORT pcmCoding_flag = 0; + + SHORT allowDiffTimeBack_flag = !independency_flag || (setIdx > 0); + + SHORT num_lsb_bits = -1; + SHORT num_pcm_bits = -1; + + SHORT quant_data_lsb[MAXBANDS]; + SHORT quant_data_msb[MAXBANDS]; + + SHORT quant_data_hist_lsb[MAXBANDS]; + SHORT quant_data_hist_msb[MAXBANDS]; + + SHORT data_diff_freq[MAXBANDS]; + SHORT data_diff_time[MAXBANDS + 2]; + + SHORT *p_quant_data_msb; + SHORT *p_quant_data_hist_msb = NULL; + + SHORT min_bits_all = 0; + SHORT min_found = 0; + + SHORT min_bits_df = -1; + SHORT min_bits_dt = -1; + + SHORT lav_df[2] = {-1, -1}; + SHORT lav_dt[2] = {-1, -1}; + + SHORT coding_scheme_df = 0; + SHORT coding_scheme_dt = 0; + + switch (data_type) { + case t_CLD: + if (coarse_flag) { + splitLsb_flag = 0; + quant_levels = 15; + quant_offset = 7; + } else { + splitLsb_flag = 0; + quant_levels = 31; + quant_offset = 15; + } + break; + case t_ICC: + if (coarse_flag) { + splitLsb_flag = 0; + quant_levels = 4; + quant_offset = 0; + } else { + splitLsb_flag = 0; + quant_levels = 8; + quant_offset = 0; + } + break; + } /* switch( data_type ) */ + + /* Split off LSB */ + if (splitLsb_flag) { + split_lsb(aaInData[setIdx] + startBand, quant_offset, dataBands, + quant_data_lsb, quant_data_msb); + + p_quant_data_msb = quant_data_msb; + num_lsb_bits = dataBands; + } else if (quant_offset != 0) { + for (pb = 0; pb < dataBands; pb++) { + quant_data_msb[pb] = aaInData[setIdx][startBand + pb] + quant_offset; + } + + p_quant_data_msb = quant_data_msb; + num_lsb_bits = 0; + } else { + p_quant_data_msb = aaInData[setIdx] + startBand; + num_lsb_bits = 0; + } + + if (allowDiffTimeBack_flag) { + if (splitLsb_flag) { + split_lsb(aHistory + startBand, quant_offset, dataBands, + quant_data_hist_lsb, quant_data_hist_msb); + + p_quant_data_hist_msb = quant_data_hist_msb; + } else if (quant_offset != 0) { + for (pb = 0; pb < dataBands; pb++) { + quant_data_hist_msb[pb] = aHistory[startBand + pb] + quant_offset; + } + p_quant_data_hist_msb = quant_data_hist_msb; + } else { + p_quant_data_hist_msb = aHistory + startBand; + } + } + + /* Calculate frequency differences */ + calc_diff_freq(p_quant_data_msb, data_diff_freq, dataBands); + + /* Calculate time differences */ + if (allowDiffTimeBack_flag) { + calc_diff_time(p_quant_data_msb, p_quant_data_hist_msb, data_diff_time, + dataBands); + } + + /* Calculate coding scheme with minumum bit consumption */ + + /**********************************************************/ + num_pcm_bits = calc_pcm_bits(dataBands, quant_levels); + num_pcm_val = dataBands; + + /**********************************************************/ + + min_bits_all = num_pcm_bits; + + /**********************************************************/ + /**********************************************************/ + + /**********************************************************/ + min_bits_df = calc_huff_bits(data_diff_freq, NULL, data_type, DIFF_FREQ, + DIFF_FREQ, dataBands, lav_df, &coding_scheme_df); + + if (allowDiffTimeBack_flag) min_bits_df += 1; + + min_bits_df += num_lsb_bits; + + if (min_bits_df < min_bits_all) { + min_bits_all = min_bits_df; + } + /**********************************************************/ + + /**********************************************************/ + if (allowDiffTimeBack_flag) { + min_bits_dt = + calc_huff_bits(data_diff_time, NULL, data_type, DIFF_TIME, DIFF_TIME, + dataBands, lav_dt, &coding_scheme_dt); + + min_bits_dt += 1; + min_bits_dt += num_lsb_bits; + + if (min_bits_dt < min_bits_all) { + min_bits_all = min_bits_dt; + } + } /* if( allowDiffTimeBack_flag ) */ + + /***************************/ + /* Start actual coding now */ + /***************************/ + + /* PCM or Diff/Huff Coding? */ + pcmCoding_flag = (min_bits_all == num_pcm_bits); + + FDKwriteBits(strm, pcmCoding_flag, 1); + + if (pcmCoding_flag) { + /* Grouped PCM Coding */ + apply_pcm_coding(strm, aaInData[setIdx] + startBand, NULL, quant_offset, + num_pcm_val, quant_levels); + } else { + /* Diff/Huff Coding */ + + min_found = 0; + + /*******************************************/ + if (min_bits_all == min_bits_df) { + if (allowDiffTimeBack_flag) { + FDKwriteBits(strm, DIFF_FREQ, 1); + } + + apply_huff_coding(strm, data_diff_freq, NULL, data_type, DIFF_FREQ, + DIFF_FREQ, dataBands, lav_df, coding_scheme_df); + + min_found = 1; + } /* if( min_bits_all == min_bits_df ) */ + /*******************************************/ + + /*******************************************/ + if (allowDiffTimeBack_flag) { + /*******************************************/ + if (!min_found && (min_bits_all == min_bits_dt)) { + FDKwriteBits(strm, DIFF_TIME, 1); + + apply_huff_coding(strm, data_diff_time, NULL, data_type, DIFF_TIME, + DIFF_TIME, dataBands, lav_dt, coding_scheme_dt); + } + /*******************************************/ + + } /* if( allowDiffTimeBack_flag ) */ + + /* LSB coding */ + if (splitLsb_flag) { + apply_lsb_coding(strm, quant_data_lsb, 1, dataBands); + } + + } /* Diff/Huff/LSB coding */ + + return reset; +} diff --git a/libSACenc/src/sacenc_nlc_enc.h b/libSACenc/src/sacenc_nlc_enc.h new file mode 100644 index 0000000..506b308 --- /dev/null +++ b/libSACenc/src/sacenc_nlc_enc.h @@ -0,0 +1,141 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Karsten Linzmeier + + Description: Noiseless Coding + Huffman encoder + +*******************************************************************************/ + +#ifndef SACENC_NLC_ENC_H +#define SACENC_NLC_ENC_H + +/* Includes ******************************************************************/ +#include "sacenc_const.h" +#include "FDK_bitstream.h" +#include "sacenc_bitstream.h" + +/* Defines *******************************************************************/ +#define MAXBANDS MAX_NUM_BINS /* maximum number of frequency bands */ + +/* Data Types ****************************************************************/ +typedef enum { + t_CLD, + t_ICC + +} DATA_TYPE; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +INT fdk_sacenc_ecDataPairEnc(HANDLE_FDK_BITSTREAM strm, + SHORT aaInData[][MAXBANDS], + SHORT aHistory[MAXBANDS], + const DATA_TYPE data_type, const INT setIdx, + const INT startBand, const INT dataBands, + const INT coarse_flag, + const INT independency_flag); + +INT fdk_sacenc_ecDataSingleEnc(HANDLE_FDK_BITSTREAM strm, + SHORT aaInData[][MAXBANDS], + SHORT aHistory[MAXBANDS], + const DATA_TYPE data_type, const INT setIdx, + const INT startBand, const INT dataBands, + const INT coarse_flag, + const INT independency_flag); + +#endif /* SACENC_NLC_ENC_H */ diff --git a/libSACenc/src/sacenc_onsetdetect.cpp b/libSACenc/src/sacenc_onsetdetect.cpp new file mode 100644 index 0000000..7e9aee1 --- /dev/null +++ b/libSACenc/src/sacenc_onsetdetect.cpp @@ -0,0 +1,381 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Detect Onset in current frame + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + Description of file contents + ******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_onsetdetect.h" +#include "genericStds.h" +#include "sacenc_vectorfunctions.h" + +/* Defines *******************************************************************/ +#define SPACE_ONSET_THRESHOLD (3.0) +#define SPACE_ONSET_THRESHOLD_SF (3) +#define SPACE_ONSET_THRESHOLD_SQUARE \ + (FL2FXCONST_DBL((1.0 / (SPACE_ONSET_THRESHOLD * SPACE_ONSET_THRESHOLD)) * \ + (float)(1 << SPACE_ONSET_THRESHOLD_SF))) + +/* Data Types ****************************************************************/ +struct ONSET_DETECT { + INT maxTimeSlots; + INT minTransientDistance; + INT avgEnergyDistance; + INT lowerBoundOnsetDetection; + INT upperBoundOnsetDetection; + FIXP_DBL *pEnergyHist__FDK; + SCHAR *pEnergyHistScale; + SCHAR avgEnergyDistanceScale; +}; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Open(HANDLE_ONSET_DETECT *phOnset, + const UINT maxTimeSlots) { + FDK_SACENC_ERROR error = SACENC_OK; + HANDLE_ONSET_DETECT hOnset = NULL; + + if (NULL == phOnset) { + error = SACENC_INVALID_HANDLE; + } else { + /* Memory Allocation */ + FDK_ALLOCATE_MEMORY_1D(hOnset, 1, struct ONSET_DETECT); + FDK_ALLOCATE_MEMORY_1D(hOnset->pEnergyHist__FDK, 16 + maxTimeSlots, + FIXP_DBL); + FDK_ALLOCATE_MEMORY_1D(hOnset->pEnergyHistScale, 16 + maxTimeSlots, SCHAR); + + hOnset->maxTimeSlots = maxTimeSlots; + hOnset->minTransientDistance = + 8; /* minimum distance between detected transients */ + hOnset->avgEnergyDistance = 16; /* average energy distance */ + + hOnset->avgEnergyDistanceScale = 4; + *phOnset = hOnset; + } + return error; + +bail: + fdk_sacenc_onsetDetect_Close(&hOnset); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Init( + HANDLE_ONSET_DETECT hOnset, + const ONSET_DETECT_CONFIG *const pOnsetDetectConfig, const UINT initFlags) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hOnset) || (pOnsetDetectConfig == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + if ((pOnsetDetectConfig->maxTimeSlots > hOnset->maxTimeSlots) || + (pOnsetDetectConfig->upperBoundOnsetDetection < + hOnset->lowerBoundOnsetDetection)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + hOnset->maxTimeSlots = pOnsetDetectConfig->maxTimeSlots; + hOnset->lowerBoundOnsetDetection = + pOnsetDetectConfig->lowerBoundOnsetDetection; + hOnset->upperBoundOnsetDetection = + pOnsetDetectConfig->upperBoundOnsetDetection; + + hOnset->minTransientDistance = + 8; /* minimum distance between detected transients */ + hOnset->avgEnergyDistance = 16; /* average energy distance */ + + hOnset->avgEnergyDistanceScale = 4; + + /* Init / Reset */ + if (initFlags) { + int i; + for (i = 0; i < hOnset->avgEnergyDistance + hOnset->maxTimeSlots; i++) + hOnset->pEnergyHistScale[i] = -(DFRACT_BITS - 3); + + FDKmemset_flex( + hOnset->pEnergyHist__FDK, + FL2FXCONST_DBL(SACENC_FLOAT_EPSILON * (1 << (DFRACT_BITS - 3))), + hOnset->avgEnergyDistance + hOnset->maxTimeSlots); + } + } + +bail: + return error; +} + +/**************************************************************************/ + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Close(HANDLE_ONSET_DETECT *phOnset) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL != phOnset) && (NULL != *phOnset)) { + if (NULL != (*phOnset)->pEnergyHist__FDK) { + FDKfree((*phOnset)->pEnergyHist__FDK); + } + (*phOnset)->pEnergyHist__FDK = NULL; + + if (NULL != (*phOnset)->pEnergyHistScale) { + FDKfree((*phOnset)->pEnergyHistScale); + } + (*phOnset)->pEnergyHistScale = NULL; + FDKfree(*phOnset); + *phOnset = NULL; + } + return error; +} + +/**************************************************************************/ + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Update(HANDLE_ONSET_DETECT hOnset, + const INT timeSlots) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hOnset) { + error = SACENC_INVALID_HANDLE; + } else { + if (timeSlots > hOnset->maxTimeSlots) { + error = SACENC_INVALID_CONFIG; + } else { + int i; + /* Shift old data */ + for (i = 0; i < hOnset->avgEnergyDistance; i++) { + hOnset->pEnergyHist__FDK[i] = hOnset->pEnergyHist__FDK[i + timeSlots]; + hOnset->pEnergyHistScale[i] = hOnset->pEnergyHistScale[i + timeSlots]; + } + + /* Clear for new data */ + FDKmemset_flex(&hOnset->pEnergyHist__FDK[hOnset->avgEnergyDistance], + FL2FXCONST_DBL(SACENC_FLOAT_EPSILON), timeSlots); + } + } + return error; +} + +/**************************************************************************/ + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Apply( + HANDLE_ONSET_DETECT hOnset, const INT nTimeSlots, const INT nHybridBands, + FIXP_DPK *const *const ppHybridData__FDK, const INT hybridDataScale, + const INT prevPos, INT pTransientPos[MAX_NUM_TRANS]) { + FDK_SACENC_ERROR error = SACENC_OK; + + C_ALLOC_SCRATCH_START(envs, FIXP_DBL, (16 + MAX_TIME_SLOTS)) + FDKmemclear(envs, (16 + MAX_TIME_SLOTS) * sizeof(FIXP_DBL)); + + if ((hOnset == NULL) || (pTransientPos == NULL) || + (ppHybridData__FDK == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int i, ts, trCnt, currPos; + + if ((nTimeSlots < 0) || (nTimeSlots > hOnset->maxTimeSlots) || + (hOnset->lowerBoundOnsetDetection < -1) || + (hOnset->upperBoundOnsetDetection > nHybridBands)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + const int lowerBoundOnsetDetection = hOnset->lowerBoundOnsetDetection; + const int upperBoundOnsetDetection = hOnset->upperBoundOnsetDetection; + const int M = hOnset->avgEnergyDistance; + + { + SCHAR *envScale = hOnset->pEnergyHistScale; + FIXP_DBL *env = hOnset->pEnergyHist__FDK; + const FIXP_DBL threshold_square = SPACE_ONSET_THRESHOLD_SQUARE; + + trCnt = 0; + + /* reset transient array */ + FDKmemset_flex(pTransientPos, -1, MAX_NUM_TRANS); + + /* minimum transient distance of minTransDist QMF samples */ + if (prevPos > 0) { + currPos = FDKmax(nTimeSlots, + prevPos - nTimeSlots + hOnset->minTransientDistance); + } else { + currPos = nTimeSlots; + } + + /* get energy and scalefactor for each time slot */ + int outScale; + int inScale = 3; /* scale factor determined empirically */ + for (ts = 0; ts < nTimeSlots; ts++) { + env[M + ts] = sumUpCplxPow2( + &ppHybridData__FDK[ts][lowerBoundOnsetDetection + 1], + SUM_UP_DYNAMIC_SCALE, inScale, &outScale, + upperBoundOnsetDetection - lowerBoundOnsetDetection - 1); + envScale[M + ts] = outScale + (hybridDataScale << 1); + } + + /* calculate common scale for all time slots */ + SCHAR maxScale = -(DFRACT_BITS - 1); + for (i = 0; i < (nTimeSlots + M); i++) { + maxScale = fixMax(maxScale, envScale[i]); + } + + /* apply common scale and store energy in temporary buffer */ + for (i = 0; i < (nTimeSlots + M); i++) { + envs[i] = env[i] >> fixMin((maxScale - envScale[i]), (DFRACT_BITS - 1)); + } + + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + for (i = 0; i < (nTimeSlots + M); i++) { + maxVal |= fAbs(envs[i]); + } + + int s = fixMax(0, CntLeadingZeros(maxVal) - 1); + + for (i = 0; i < (nTimeSlots + M); i++) { + envs[i] = envs[i] << s; + } + + int currPosPrev = currPos; + FIXP_DBL p1, p2; + p2 = FL2FXCONST_DBL(0.0f); + for (; (currPos < (nTimeSlots << 1)) && (trCnt < MAX_NUM_TRANS); + currPos++) { + p1 = fMultDiv2(envs[currPos - nTimeSlots + M], threshold_square) >> + (SPACE_ONSET_THRESHOLD_SF - 1); + + /* Calculate average of past M energy values */ + if (currPosPrev == (currPos - 1)) { + /* remove last and add new element */ + p2 -= (envs[currPosPrev - nTimeSlots] >> + (int)hOnset->avgEnergyDistanceScale); + p2 += (envs[currPos - nTimeSlots + M - 1] >> + (int)hOnset->avgEnergyDistanceScale); + } else { + /* calculate complete vector */ + p2 = FL2FXCONST_DBL(0.0f); + for (ts = 0; ts < M; ts++) { + p2 += (envs[currPos - nTimeSlots + ts] >> + (int)hOnset->avgEnergyDistanceScale); + } + } + currPosPrev = currPos; + + { + /* save position if transient found */ + if (p1 > p2) { + pTransientPos[trCnt++] = currPos; + currPos += hOnset->minTransientDistance; + } + } + } /* for currPos */ + } + + } /* valid handle*/ +bail: + + C_ALLOC_SCRATCH_END(envs, FIXP_DBL, (16 + MAX_TIME_SLOTS)) + + return error; +} + +/**************************************************************************/ diff --git a/libSACenc/src/sacenc_onsetdetect.h b/libSACenc/src/sacenc_onsetdetect.h new file mode 100644 index 0000000..5f3f0bd --- /dev/null +++ b/libSACenc/src/sacenc_onsetdetect.h @@ -0,0 +1,154 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Determine TES flags + +*******************************************************************************/ + +#ifndef SACENC_ONSETDETECT_H +#define SACENC_ONSETDETECT_H + +/**************************************************************************/ /** + \file + Description of file contents + ******************************************************************************/ + +/* Includes ******************************************************************/ +#include "common_fix.h" +#include "FDK_matrixCalloc.h" +#include "sacenc_lib.h" +#include "sacenc_bitstream.h" /* for def. of MAX_NUM_PARAMS */ + +/* Defines *******************************************************************/ +#define MAX_NUM_TRANS (MAX_NUM_PARAMS / 2) + +/* Data Types ****************************************************************/ +typedef struct T_ONSET_DETECT_CONFIG { + INT maxTimeSlots; + + /* calc transien detection in ]lowerBoundOnsetDetection; + * upperBoundOnsetDetection[ */ + INT lowerBoundOnsetDetection; + INT upperBoundOnsetDetection; + +} ONSET_DETECT_CONFIG; + +typedef struct ONSET_DETECT *HANDLE_ONSET_DETECT; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Open(HANDLE_ONSET_DETECT *phOnset, + const UINT maxTimeSlots); + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Init( + HANDLE_ONSET_DETECT hOnset, + const ONSET_DETECT_CONFIG *const pOnsetDetectConfig, const UINT initFlags); + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Close(HANDLE_ONSET_DETECT *phOnset); + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Update(HANDLE_ONSET_DETECT hOnset, + const INT timeSlots); + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Apply( + HANDLE_ONSET_DETECT hOnset, const INT nTimeSlots, const INT nHybridBands, + FIXP_DPK *const *const ppHybridData__FDK, const INT hybridDataScale, + const INT prevPos, INT pTransientPos[MAX_NUM_TRANS]); + +#endif /* SACENC_ONSETDETECT_H */ diff --git a/libSACenc/src/sacenc_paramextract.cpp b/libSACenc/src/sacenc_paramextract.cpp new file mode 100644 index 0000000..dcbce1e --- /dev/null +++ b/libSACenc/src/sacenc_paramextract.cpp @@ -0,0 +1,725 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Multrus + + Description: Parameter Extraction + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_paramextract.h" +#include "sacenc_tree.h" +#include "sacenc_vectorfunctions.h" + +/* Defines *******************************************************************/ +#define LOG10_2_10 (3.01029995664f) /* 10.0f*log10(2.f) */ +#define SCALE_CLDE_SF (7) /* maxVal in Quant tab is +/- 50 */ +#define SCALE_CLDD_SF (8) /* maxVal in Quant tab is +/- 150 */ + +/* Data Types ****************************************************************/ +typedef struct T_TTO_BOX { + FIXP_DBL pCld__FDK[MAX_NUM_PARAM_BANDS]; + FIXP_DBL pIcc__FDK[MAX_NUM_PARAM_BANDS]; + FIXP_DBL pCldQuant__FDK[MAX_NUM_PARAM_BANDS]; + + const FIXP_DBL *pIccQuantTable__FDK; + const FIXP_DBL *pCldQuantTableDec__FDK; + const FIXP_DBL *pCldQuantTableEnc__FDK; + + SCHAR pCldEbQIdx[MAX_NUM_PARAM_BANDS]; + SCHAR pIccDownmixIdx[MAX_NUM_PARAM_BANDS]; + + UCHAR *pParameterBand2HybridBandOffset; + const INT *pSubbandImagSign; + UCHAR nHybridBandsMax; + UCHAR nParameterBands; + UCHAR bFrameKeep; + + UCHAR iccCorrelationCoherenceBorder; + BOX_QUANTMODE boxQuantMode; + + UCHAR nIccQuantSteps; + UCHAR nIccQuantOffset; + + UCHAR nCldQuantSteps; + UCHAR nCldQuantOffset; + + UCHAR bUseCoarseQuantCld; + UCHAR bUseCoarseQuantIcc; + +} TTO_BOX; + +struct BOX_SUBBAND_SETUP { + BOX_SUBBAND_CONFIG subbandConfig; + UCHAR nParameterBands; + const UCHAR *pSubband2ParameterIndexLd; + UCHAR iccCorrelationCoherenceBorder; +}; + +/* Constants *****************************************************************/ +static const UCHAR subband2Parameter4_Ld[NUM_QMF_BANDS] = { + 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}; + +static const UCHAR subband2Parameter5_Ld[NUM_QMF_BANDS] = { + 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; + +static const UCHAR subband2Parameter7_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6}; + +static const UCHAR subband2Parameter9_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; + +static const UCHAR subband2Parameter12_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, + 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}; + +static const UCHAR subband2Parameter15_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 10, 10, 11, 11, + 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 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}; + +static const UCHAR subband2Parameter23_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, + 14, 14, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, 19, 19, + 19, 19, 19, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22}; + +static const INT subbandImagSign_Ld[NUM_QMF_BANDS] = { + 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, 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, 1, 1, 1, 1, 1, 1, +}; + +#define SCALE_CLDE(a) (FL2FXCONST_DBL(a / (float)(1 << SCALE_CLDE_SF))) +static const FIXP_DBL cldQuantTableFineEnc__FDK[MAX_CLD_QUANT_FINE] = { + SCALE_CLDE(-50.0), SCALE_CLDE(-45.0), SCALE_CLDE(-40.0), SCALE_CLDE(-35.0), + SCALE_CLDE(-30.0), SCALE_CLDE(-25.0), SCALE_CLDE(-22.0), SCALE_CLDE(-19.0), + SCALE_CLDE(-16.0), SCALE_CLDE(-13.0), SCALE_CLDE(-10.0), SCALE_CLDE(-8.0), + SCALE_CLDE(-6.0), SCALE_CLDE(-4.0), SCALE_CLDE(-2.0), SCALE_CLDE(0.0), + SCALE_CLDE(2.0), SCALE_CLDE(4.0), SCALE_CLDE(6.0), SCALE_CLDE(8.0), + SCALE_CLDE(10.0), SCALE_CLDE(13.0), SCALE_CLDE(16.0), SCALE_CLDE(19.0), + SCALE_CLDE(22.0), SCALE_CLDE(25.0), SCALE_CLDE(30.0), SCALE_CLDE(35.0), + SCALE_CLDE(40.0), SCALE_CLDE(45.0), SCALE_CLDE(50.0)}; + +static const FIXP_DBL cldQuantTableCoarseEnc__FDK[MAX_CLD_QUANT_COARSE] = { + SCALE_CLDE(-50.0), SCALE_CLDE(-35.0), SCALE_CLDE(-25.0), SCALE_CLDE(-19.0), + SCALE_CLDE(-13.0), SCALE_CLDE(-8.0), SCALE_CLDE(-4.0), SCALE_CLDE(0.0), + SCALE_CLDE(4.0), SCALE_CLDE(8.0), SCALE_CLDE(13.0), SCALE_CLDE(19.0), + SCALE_CLDE(25.0), SCALE_CLDE(35.0), SCALE_CLDE(50.0)}; + +#define SCALE_CLDD(a) (FL2FXCONST_DBL(a / (float)(1 << SCALE_CLDD_SF))) +static const FIXP_DBL cldQuantTableFineDec__FDK[MAX_CLD_QUANT_FINE] = { + SCALE_CLDD(-150.0), SCALE_CLDD(-45.0), SCALE_CLDD(-40.0), SCALE_CLDD(-35.0), + SCALE_CLDD(-30.0), SCALE_CLDD(-25.0), SCALE_CLDD(-22.0), SCALE_CLDD(-19.0), + SCALE_CLDD(-16.0), SCALE_CLDD(-13.0), SCALE_CLDD(-10.0), SCALE_CLDD(-8.0), + SCALE_CLDD(-6.0), SCALE_CLDD(-4.0), SCALE_CLDD(-2.0), SCALE_CLDD(0.0), + SCALE_CLDD(2.0), SCALE_CLDD(4.0), SCALE_CLDD(6.0), SCALE_CLDD(8.0), + SCALE_CLDD(10.0), SCALE_CLDD(13.0), SCALE_CLDD(16.0), SCALE_CLDD(19.0), + SCALE_CLDD(22.0), SCALE_CLDD(25.0), SCALE_CLDD(30.0), SCALE_CLDD(35.0), + SCALE_CLDD(40.0), SCALE_CLDD(45.0), SCALE_CLDD(150.0)}; + +static const FIXP_DBL cldQuantTableCoarseDec__FDK[MAX_CLD_QUANT_COARSE] = { + SCALE_CLDD(-150.0), SCALE_CLDD(-35.0), SCALE_CLDD(-25.0), SCALE_CLDD(-19.0), + SCALE_CLDD(-13.0), SCALE_CLDD(-8.0), SCALE_CLDD(-4.0), SCALE_CLDD(0.0), + SCALE_CLDD(4.0), SCALE_CLDD(8.0), SCALE_CLDD(13.0), SCALE_CLDD(19.0), + SCALE_CLDD(25.0), SCALE_CLDD(35.0), SCALE_CLDD(150.0)}; + +#define SCALE_ICC(a) (FL2FXCONST_DBL(a)) +static const FIXP_DBL iccQuantTableFine__FDK[MAX_ICC_QUANT_FINE] = { + SCALE_ICC(0.99999999953), SCALE_ICC(0.937f), SCALE_ICC(0.84118f), + SCALE_ICC(0.60092f), SCALE_ICC(0.36764f), SCALE_ICC(0.0f), + SCALE_ICC(-0.589f), SCALE_ICC(-0.99f)}; + +static const FIXP_DBL iccQuantTableCoarse__FDK[MAX_ICC_QUANT_COARSE] = { + SCALE_ICC(0.99999999953), SCALE_ICC(0.84118f), SCALE_ICC(0.36764f), + SCALE_ICC(-0.5890f)}; + +static const BOX_SUBBAND_SETUP boxSubbandSetup[] = { + {BOX_SUBBANDS_4, 4, subband2Parameter4_Ld, 1}, + {BOX_SUBBANDS_5, 5, subband2Parameter5_Ld, 2}, + {BOX_SUBBANDS_7, 7, subband2Parameter7_Ld, 3}, + {BOX_SUBBANDS_9, 9, subband2Parameter9_Ld, 4}, + {BOX_SUBBANDS_12, 12, subband2Parameter12_Ld, 4}, + {BOX_SUBBANDS_15, 15, subband2Parameter15_Ld, 5}, + {BOX_SUBBANDS_23, 23, subband2Parameter23_Ld, 8}}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static const BOX_SUBBAND_SETUP *getBoxSubbandSetup( + const BOX_SUBBAND_CONFIG subbandConfig) { + int i; + const BOX_SUBBAND_SETUP *setup = NULL; + + for (i = 0; i < (int)(sizeof(boxSubbandSetup) / sizeof(BOX_SUBBAND_SETUP)); + i++) { + if (boxSubbandSetup[i].subbandConfig == subbandConfig) { + setup = &boxSubbandSetup[i]; + break; + } + } + return setup; +} + +static inline void ApplyBBCuesFDK(FIXP_DBL *const pData, + const INT nParamBands) { + int i, s; + FIXP_DBL tmp, invParamBands; + + invParamBands = fDivNormHighPrec((FIXP_DBL)1, (FIXP_DBL)nParamBands, &s); + s = -s; + + tmp = fMult(pData[0], invParamBands) >> s; + for (i = 1; i < nParamBands; i++) { + tmp += fMult(pData[i], invParamBands) >> s; + } + + for (i = 0; i < nParamBands; i++) { + pData[i] = tmp; + } +} + +static INT getNumberParameterBands(const BOX_SUBBAND_CONFIG subbandConfig) { + const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); + return ((setup == NULL) ? 0 : setup->nParameterBands); +} + +static const UCHAR *getSubband2ParameterIndex( + const BOX_SUBBAND_CONFIG subbandConfig) { + const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); + + return ((setup == NULL) ? NULL : (setup->pSubband2ParameterIndexLd)); +} + +void fdk_sacenc_calcParameterBand2HybridBandOffset( + const BOX_SUBBAND_CONFIG subbandConfig, const INT nHybridBands, + UCHAR *pParameterBand2HybridBandOffset) { + const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); + const UCHAR *pSubband2ParameterIndex; + + int i, pb; + + pSubband2ParameterIndex = setup->pSubband2ParameterIndexLd; + + for (pb = 0, i = 0; i < nHybridBands - 1; i++) { + if (pSubband2ParameterIndex[i + 1] - pSubband2ParameterIndex[i]) { + pParameterBand2HybridBandOffset[pb++] = (i + 1); + } + } + pParameterBand2HybridBandOffset[pb++] = (i + 1); +} + +const INT *fdk_sacenc_getSubbandImagSign() { + const INT *pImagSign = NULL; + + pImagSign = subbandImagSign_Ld; + + return (pImagSign); +} + +static INT getIccCorrelationCoherenceBorder( + const BOX_SUBBAND_CONFIG subbandConfig, const INT bUseCoherenceOnly) { + const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); + return ( + (setup == NULL) + ? 0 + : ((bUseCoherenceOnly) ? 0 : setup->iccCorrelationCoherenceBorder)); +} + +FDK_SACENC_ERROR fdk_sacenc_createTtoBox(HANDLE_TTO_BOX *hTtoBox) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hTtoBox) { + error = SACENC_INVALID_HANDLE; + } else { + FDK_ALLOCATE_MEMORY_1D(*hTtoBox, 1, TTO_BOX); + } + return error; + +bail: + fdk_sacenc_destroyTtoBox(hTtoBox); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_initTtoBox(HANDLE_TTO_BOX hTtoBox, + const TTO_BOX_CONFIG *const ttoBoxConfig, + UCHAR *pParameterBand2HybridBandOffset) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hTtoBox == NULL) || (ttoBoxConfig == NULL) || + (pParameterBand2HybridBandOffset == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDKmemclear(hTtoBox, sizeof(TTO_BOX)); + + hTtoBox->bUseCoarseQuantCld = ttoBoxConfig->bUseCoarseQuantCld; + hTtoBox->bUseCoarseQuantIcc = ttoBoxConfig->bUseCoarseQuantIcc; + hTtoBox->boxQuantMode = ttoBoxConfig->boxQuantMode; + hTtoBox->iccCorrelationCoherenceBorder = getIccCorrelationCoherenceBorder( + ttoBoxConfig->subbandConfig, ttoBoxConfig->bUseCoherenceIccOnly); + hTtoBox->nHybridBandsMax = ttoBoxConfig->nHybridBandsMax; + hTtoBox->nParameterBands = + getNumberParameterBands(ttoBoxConfig->subbandConfig); + hTtoBox->bFrameKeep = ttoBoxConfig->bFrameKeep; + + hTtoBox->nIccQuantSteps = + fdk_sacenc_getNumberIccQuantLevels(hTtoBox->bUseCoarseQuantIcc); + hTtoBox->nIccQuantOffset = + fdk_sacenc_getIccQuantOffset(hTtoBox->bUseCoarseQuantIcc); + + hTtoBox->pIccQuantTable__FDK = hTtoBox->bUseCoarseQuantIcc + ? iccQuantTableCoarse__FDK + : iccQuantTableFine__FDK; + hTtoBox->pCldQuantTableDec__FDK = hTtoBox->bUseCoarseQuantCld + ? cldQuantTableCoarseDec__FDK + : cldQuantTableFineDec__FDK; + hTtoBox->pCldQuantTableEnc__FDK = hTtoBox->bUseCoarseQuantCld + ? cldQuantTableCoarseEnc__FDK + : cldQuantTableFineEnc__FDK; + + hTtoBox->nCldQuantSteps = + fdk_sacenc_getNumberCldQuantLevels(hTtoBox->bUseCoarseQuantCld); + hTtoBox->nCldQuantOffset = + fdk_sacenc_getCldQuantOffset(hTtoBox->bUseCoarseQuantCld); + + /* sanity */ + if (NULL == (hTtoBox->pParameterBand2HybridBandOffset = + pParameterBand2HybridBandOffset)) { + error = SACENC_INIT_ERROR; + goto bail; + } + + if (NULL == (hTtoBox->pSubbandImagSign = fdk_sacenc_getSubbandImagSign())) { + error = SACENC_INIT_ERROR; + } + + if ((hTtoBox->boxQuantMode != BOX_QUANTMODE_FINE) && + (hTtoBox->boxQuantMode != BOX_QUANTMODE_EBQ1) && + (hTtoBox->boxQuantMode != BOX_QUANTMODE_EBQ2)) { + error = SACENC_INIT_ERROR; + goto bail; + } + } +bail: + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_destroyTtoBox(HANDLE_TTO_BOX *hTtoBox) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (*hTtoBox != NULL) { + FDKfree(*hTtoBox); + *hTtoBox = NULL; + } + + return error; +} + +static FDK_SACENC_ERROR calculateIccFDK(const INT nParamBand, + const INT correlationCoherenceBorder, + const FIXP_DBL *const pPwr1, + const FIXP_DBL *const pPwr2, + const FIXP_DBL *const pProdReal, + FIXP_DBL const *const pProdImag, + FIXP_DBL *const pIcc) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((pPwr1 == NULL) || (pPwr2 == NULL) || (pProdReal == NULL) || + (pProdImag == NULL) || (pIcc == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + /* sanity check border */ + if (correlationCoherenceBorder > nParamBand) { + error = SACENC_INVALID_CONFIG; + } else { + /* correlation */ + FDKcalcCorrelationVec(pIcc, pProdReal, pPwr1, pPwr2, + correlationCoherenceBorder); + + /* coherence */ + calcCoherenceVec(&pIcc[correlationCoherenceBorder], + &pProdReal[correlationCoherenceBorder], + &pProdImag[correlationCoherenceBorder], + &pPwr1[correlationCoherenceBorder], + &pPwr2[correlationCoherenceBorder], 0, 0, + nParamBand - correlationCoherenceBorder); + + } /* valid configuration */ + } /* valid handle */ + + return error; +} + +static void QuantizeCoefFDK(const FIXP_DBL *const input, const INT nBands, + const FIXP_DBL *const quantTable, + const INT idxOffset, const INT nQuantSteps, + SCHAR *const quantOut) { + int band; + const int reverse = (quantTable[0] > quantTable[1]); + + for (band = 0; band < nBands; band++) { + FIXP_DBL qVal; + FIXP_DBL curVal = input[band]; + + int lower = 0; + int upper = nQuantSteps - 1; + + if (reverse) { + while (upper - lower > 1) { + int idx = (lower + upper) >> 1; + qVal = quantTable[idx]; + if (curVal >= qVal) { + upper = idx; + } else { + lower = idx; + } + } /* while */ + + if ((curVal - quantTable[lower]) >= (quantTable[upper] - curVal)) { + quantOut[band] = lower - idxOffset; + } else { + quantOut[band] = upper - idxOffset; + } + } /* if reverse */ + else { + while (upper - lower > 1) { + int idx = (lower + upper) >> 1; + qVal = quantTable[idx]; + if (curVal <= qVal) { + upper = idx; + } else { + lower = idx; + } + } /* while */ + + if ((curVal - quantTable[lower]) <= (quantTable[upper] - curVal)) { + quantOut[band] = lower - idxOffset; + } else { + quantOut[band] = upper - idxOffset; + } + } /* else reverse */ + } /* for band */ +} + +static void deQuantizeCoefFDK(const SCHAR *const input, const INT nBands, + const FIXP_DBL *const quantTable, + const INT idxOffset, FIXP_DBL *const dequantOut) { + int band; + + for (band = 0; band < nBands; band++) { + dequantOut[band] = quantTable[input[band] + idxOffset]; + } +} + +static void CalculateCldFDK(FIXP_DBL *const pCld, const FIXP_DBL *const pPwr1, + const FIXP_DBL *const pPwr2, const INT scaleCh1, + const INT *const pbScaleCh1, const INT scaleCh2, + const INT *const pbScaleCh2, const int nParamBand) { + INT i; + FIXP_DBL ldPwr1, ldPwr2, cld; + FIXP_DBL maxPwr = FL2FXCONST_DBL( + 30.0f / + (1 << (LD_DATA_SHIFT + + 1))); /* consider SACENC_FLOAT_EPSILON in power calculation */ + + for (i = 0; i < nParamBand; i++) { + ldPwr1 = + (CalcLdData(pPwr1[i]) >> 1) + ((FIXP_DBL)(scaleCh1 + pbScaleCh1[i]) + << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); + ldPwr2 = + (CalcLdData(pPwr2[i]) >> 1) + ((FIXP_DBL)(scaleCh2 + pbScaleCh2[i]) + << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); + + ldPwr1 = fixMax(fixMin(ldPwr1, maxPwr), -maxPwr); + ldPwr2 = fixMax(fixMin(ldPwr2, maxPwr), -maxPwr); + + /* ldPwr1 and ldPwr2 are scaled by LD_DATA_SHIFT and additional 1 bit; 1 bit + * scale by fMultDiv2() */ + cld = fMultDiv2(FL2FXCONST_DBL(LOG10_2_10 / (1 << SCALE_CLDE_SF)), + ldPwr1 - ldPwr2); + + cld = + fixMin(cld, (FIXP_DBL)(((FIXP_DBL)MAXVAL_DBL) >> (LD_DATA_SHIFT + 2))); + cld = + fixMax(cld, (FIXP_DBL)(((FIXP_DBL)MINVAL_DBL) >> (LD_DATA_SHIFT + 2))); + pCld[i] = cld << (LD_DATA_SHIFT + 2); + } +} + +FDK_SACENC_ERROR fdk_sacenc_applyTtoBox( + HANDLE_TTO_BOX hTtoBox, const INT nTimeSlots, const INT startTimeSlot, + const INT nHybridBands, const FIXP_DPK *const *const ppHybridData1__FDK, + const FIXP_DPK *const *const ppHybridData2__FDK, SCHAR *const pIccIdx, + UCHAR *const pbIccQuantCoarse, SCHAR *const pCldIdx, + UCHAR *const pbCldQuantCoarse, const INT bUseBBCues, INT *scaleCh1, + INT *scaleCh2) { + FDK_SACENC_ERROR error = SACENC_OK; + + C_ALLOC_SCRATCH_START(powerHybridData1__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(powerHybridData2__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(prodHybridDataReal__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(prodHybridDataImag__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + + C_ALLOC_SCRATCH_START(IccDownmix__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(IccDownmixQuant__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(pbScaleCh1, INT, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(pbScaleCh2, INT, MAX_NUM_PARAM_BANDS) + + if ((hTtoBox == NULL) || (pCldIdx == NULL) || (pbCldQuantCoarse == NULL) || + (ppHybridData1__FDK == NULL) || (ppHybridData2__FDK == NULL) || + (pIccIdx == NULL) || (pbIccQuantCoarse == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int j, pb; + const int nParamBands = hTtoBox->nParameterBands; + const int bUseEbQ = (hTtoBox->boxQuantMode == BOX_QUANTMODE_EBQ1) || + (hTtoBox->boxQuantMode == BOX_QUANTMODE_EBQ2); + + /* sanity check */ + if ((nHybridBands < 0) || (nHybridBands > hTtoBox->nHybridBandsMax)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + int outScale; /* scalefactor will not be evaluated */ + int inScale = 5; /* scale factor determined empirically */ + + /* calculate the headroom of the hybrid data for each parameter band */ + FDKcalcPbScaleFactor(ppHybridData1__FDK, + hTtoBox->pParameterBand2HybridBandOffset, pbScaleCh1, + startTimeSlot, nTimeSlots, nParamBands); + FDKcalcPbScaleFactor(ppHybridData2__FDK, + hTtoBox->pParameterBand2HybridBandOffset, pbScaleCh2, + startTimeSlot, nTimeSlots, nParamBands); + + for (j = 0, pb = 0; pb < nParamBands; pb++) { + FIXP_DBL data1, data2; + data1 = data2 = (FIXP_DBL)0; + for (; j < hTtoBox->pParameterBand2HybridBandOffset[pb]; j++) { + data1 += sumUpCplxPow2Dim2(ppHybridData1__FDK, SUM_UP_STATIC_SCALE, + inScale + pbScaleCh1[pb], &outScale, + startTimeSlot, nTimeSlots, j, j + 1); + data2 += sumUpCplxPow2Dim2(ppHybridData2__FDK, SUM_UP_STATIC_SCALE, + inScale + pbScaleCh2[pb], &outScale, + startTimeSlot, nTimeSlots, j, j + 1); + } /* for j */ + powerHybridData1__FDK[pb] = data1; + powerHybridData2__FDK[pb] = data2; + } /* pb */ + + { + for (j = 0, pb = 0; pb < nParamBands; pb++) { + FIXP_DBL dataReal, dataImag; + dataReal = dataImag = (FIXP_DBL)0; + for (; j < hTtoBox->pParameterBand2HybridBandOffset[pb]; j++) { + FIXP_DPK scalarProd; + cplx_cplxScalarProduct(&scalarProd, ppHybridData1__FDK, + ppHybridData2__FDK, inScale + pbScaleCh1[pb], + inScale + pbScaleCh2[pb], &outScale, + startTimeSlot, nTimeSlots, j, j + 1); + dataReal += scalarProd.v.re; + if (hTtoBox->pSubbandImagSign[j] < 0) { + dataImag -= scalarProd.v.im; + } else { + dataImag += scalarProd.v.im; + } + } /* for j */ + prodHybridDataReal__FDK[pb] = dataReal; + prodHybridDataImag__FDK[pb] = dataImag; + } /* pb */ + + if (SACENC_OK != (error = calculateIccFDK( + nParamBands, hTtoBox->iccCorrelationCoherenceBorder, + powerHybridData1__FDK, powerHybridData2__FDK, + prodHybridDataReal__FDK, prodHybridDataImag__FDK, + hTtoBox->pIcc__FDK))) { + goto bail; + } + + /* calculate correlation based Icc for downmix */ + if (SACENC_OK != (error = calculateIccFDK( + nParamBands, nParamBands, powerHybridData1__FDK, + powerHybridData2__FDK, prodHybridDataReal__FDK, + prodHybridDataImag__FDK, IccDownmix__FDK))) { + goto bail; + } + } + + if (!bUseEbQ) { + CalculateCldFDK(hTtoBox->pCld__FDK, powerHybridData1__FDK, + powerHybridData2__FDK, *scaleCh1 + inScale + 1, + pbScaleCh1, *scaleCh2 + inScale + 1, pbScaleCh2, + nParamBands); + } + + if (bUseBBCues) { + ApplyBBCuesFDK(&hTtoBox->pCld__FDK[0], nParamBands); + + { ApplyBBCuesFDK(&hTtoBox->pIcc__FDK[0], nParamBands); } + + } /* bUseBBCues */ + + /* quantize/de-quantize icc */ + { + QuantizeCoefFDK(hTtoBox->pIcc__FDK, nParamBands, + hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset, + hTtoBox->nIccQuantSteps, pIccIdx); + QuantizeCoefFDK(IccDownmix__FDK, nParamBands, + hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset, + hTtoBox->nIccQuantSteps, hTtoBox->pIccDownmixIdx); + deQuantizeCoefFDK(hTtoBox->pIccDownmixIdx, nParamBands, + hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset, + IccDownmixQuant__FDK); + + *pbIccQuantCoarse = hTtoBox->bUseCoarseQuantIcc; + } + + /* quantize/de-quantize cld */ + if (!bUseEbQ) { + QuantizeCoefFDK(hTtoBox->pCld__FDK, nParamBands, + hTtoBox->pCldQuantTableEnc__FDK, hTtoBox->nCldQuantOffset, + hTtoBox->nCldQuantSteps, pCldIdx); + deQuantizeCoefFDK(pCldIdx, nParamBands, hTtoBox->pCldQuantTableDec__FDK, + hTtoBox->nCldQuantOffset, hTtoBox->pCldQuant__FDK); + } else { + FDKmemcpy(pCldIdx, hTtoBox->pCldEbQIdx, nParamBands * sizeof(SCHAR)); + } + *pbCldQuantCoarse = hTtoBox->bUseCoarseQuantCld; + + } /* valid handle */ + +bail: + C_ALLOC_SCRATCH_END(pbScaleCh2, INT, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(pbScaleCh1, INT, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(IccDownmixQuant__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(IccDownmix__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + + C_ALLOC_SCRATCH_END(prodHybridDataImag__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(prodHybridDataReal__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(powerHybridData2__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(powerHybridData1__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + + return error; +} + +INT fdk_sacenc_subband2ParamBand(const BOX_SUBBAND_CONFIG boxSubbandConfig, + const INT nSubband) { + INT nParamBand = -1; + const UCHAR *pSubband2ParameterIndex = + getSubband2ParameterIndex(boxSubbandConfig); + + if (pSubband2ParameterIndex != NULL) { + const int hybrid_resolution = 64; + + if ((nSubband > -1) && (nSubband < hybrid_resolution)) { + nParamBand = pSubband2ParameterIndex[nSubband]; + } + } + + return nParamBand; +} diff --git a/libSACenc/src/sacenc_paramextract.h b/libSACenc/src/sacenc_paramextract.h new file mode 100644 index 0000000..9ebb902 --- /dev/null +++ b/libSACenc/src/sacenc_paramextract.h @@ -0,0 +1,214 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Multrus + + Description: Parameter Extraction + +*******************************************************************************/ + +#ifndef SACENC_PARAMEXTRACT_H +#define SACENC_PARAMEXTRACT_H + +/* Includes ******************************************************************/ +#include "common_fix.h" +#include "sacenc_lib.h" +#include "sacenc_const.h" +#include "sacenc_bitstream.h" + +/* Defines *******************************************************************/ +#define MAX_CLD_QUANT_FINE (31) +#define MAX_CLD_QUANT_COARSE (15) +#define OFFSET_CLD_QUANT_COARSE (7) +#define OFFSET_CLD_QUANT_FINE (15) + +#define MAX_ICC_QUANT_COARSE (4) +#define MAX_ICC_QUANT_FINE (8) +#define OFFSET_ICC_QUANT_COARSE (0) +#define OFFSET_ICC_QUANT_FINE (0) + +#define MAX_NUM_PARAM_BANDS (28) + +#define NUM_MAPPED_HYBRID_BANDS (16) + +/* Data Types ****************************************************************/ +typedef struct T_TTO_BOX *HANDLE_TTO_BOX; + +typedef enum { + BOX_SUBBANDS_INVALID = 0, + BOX_SUBBANDS_4 = 4, + BOX_SUBBANDS_5 = 5, + BOX_SUBBANDS_7 = 7, + BOX_SUBBANDS_9 = 9, + BOX_SUBBANDS_12 = 12, + BOX_SUBBANDS_15 = 15, + BOX_SUBBANDS_23 = 23 + +} BOX_SUBBAND_CONFIG; + +typedef enum { + BOX_QUANTMODE_INVALID = -1, + BOX_QUANTMODE_FINE = 0, + BOX_QUANTMODE_EBQ1 = 1, + BOX_QUANTMODE_EBQ2 = 2, + BOX_QUANTMODE_RESERVED3 = 3, + BOX_QUANTMODE_RESERVED4 = 4, + BOX_QUANTMODE_RESERVED5 = 5, + BOX_QUANTMODE_RESERVED6 = 6, + BOX_QUANTMODE_RESERVED7 = 7 + +} BOX_QUANTMODE; + +typedef struct T_TTO_BOX_CONFIG { + UCHAR bUseCoarseQuantCld; + UCHAR bUseCoarseQuantIcc; + UCHAR bUseCoherenceIccOnly; + + BOX_SUBBAND_CONFIG subbandConfig; + BOX_QUANTMODE boxQuantMode; + + UCHAR nHybridBandsMax; + + UCHAR bFrameKeep; + +} TTO_BOX_CONFIG; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_createTtoBox(HANDLE_TTO_BOX *hTtoBox); + +FDK_SACENC_ERROR fdk_sacenc_initTtoBox(HANDLE_TTO_BOX hTtoBox, + const TTO_BOX_CONFIG *const ttoBoxConfig, + UCHAR *pParameterBand2HybridBandOffset); + +FDK_SACENC_ERROR fdk_sacenc_destroyTtoBox(HANDLE_TTO_BOX *hTtoBox); + +FDK_SACENC_ERROR fdk_sacenc_applyTtoBox( + HANDLE_TTO_BOX hTtoBox, const INT nTimeSlots, const INT startTimeSlot, + const INT nHybridBands, const FIXP_DPK *const *const ppHybridData1__FDK, + const FIXP_DPK *const *const ppHybridData2__FDK, SCHAR *const pIccIdx, + UCHAR *const pbIccQuantCoarse, SCHAR *const pCldIdx, + UCHAR *const pbCldQuantCoarse, const INT bUseBBCues, INT *scaleCh0, + INT *scaleCh1); + +INT fdk_sacenc_subband2ParamBand(const BOX_SUBBAND_CONFIG boxSubbandConfig, + const INT nSubband); + +const INT *fdk_sacenc_getSubbandImagSign(); + +void fdk_sacenc_calcParameterBand2HybridBandOffset( + const BOX_SUBBAND_CONFIG subbandConfig, const INT nHybridBands, + UCHAR *pParameterBand2HybridBandOffset); + +/* Function / Class Definition ***********************************************/ +static inline UCHAR fdk_sacenc_getCldQuantOffset(const INT bUseCoarseQuant) { + return ((bUseCoarseQuant) ? OFFSET_CLD_QUANT_COARSE : OFFSET_CLD_QUANT_FINE); +} +static inline UCHAR fdk_sacenc_getIccQuantOffset(const INT bUseCoarseQuant) { + return ((bUseCoarseQuant) ? OFFSET_ICC_QUANT_COARSE : OFFSET_ICC_QUANT_FINE); +} + +static inline UCHAR fdk_sacenc_getNumberCldQuantLevels( + const INT bUseCoarseQuant) { + return ((bUseCoarseQuant) ? MAX_CLD_QUANT_COARSE : MAX_CLD_QUANT_FINE); +} +static inline UCHAR fdk_sacenc_getNumberIccQuantLevels( + const INT bUseCoarseQuant) { + return ((bUseCoarseQuant) ? MAX_ICC_QUANT_COARSE : MAX_ICC_QUANT_FINE); +} + +#endif /* SACENC_PARAMEXTRACT_H */ diff --git a/libSACenc/src/sacenc_staticgain.cpp b/libSACenc/src/sacenc_staticgain.cpp new file mode 100644 index 0000000..fef9f8d --- /dev/null +++ b/libSACenc/src/sacenc_staticgain.cpp @@ -0,0 +1,446 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Christian Goettlinger + + Description: Encoder Library Interface + gain management of the encoder + +*******************************************************************************/ + +/***************************************************************************** +\file +This file contains all static gain infrastructure +******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_staticgain.h" + +/* Defines *******************************************************************/ +#define MP4SPACEENC_DMX_GAIN_DEFAULT SACENC_DMXGAIN_3_dB +#define GAINCF_SF (4) +#define GAINCT1(x) FL2FXCONST_DBL(x) +#define GAINCF(x) FL2FXCONST_DBL(x) + +#define GAINCT2(x) FL2FXCONST_DBL(x) +#define FX_DBL2FX_GAIN(x) (x) + +/* Data Types ****************************************************************/ +struct STATIC_GAIN { + /* External Config Values */ + MP4SPACEENC_MODE encMode; + MP4SPACEENC_DMX_GAIN fixedGainDMX; + INT preGainFactorDb; + + /* Internal Values */ + FIXP_GAIN PostGain__FDK; + FIXP_GAIN pPreGain__FDK[SACENC_MAX_INPUT_CHANNELS]; +}; + +/* Constants *****************************************************************/ +/* + preGainFactorTable: + + pre calculation: (float)pow(10.f,(((float) x)/20.f))/(float)(1<<GAINCF_SF), x + = -20 ... +20 +*/ +static const FIXP_DBL preGainFactorTable__FDK[41] = { + GAINCF(6.2500000931e-003), GAINCF(7.0126154460e-003), + GAINCF(7.8682834283e-003), GAINCF(8.8283596560e-003), + GAINCF(9.9055822939e-003), GAINCF(1.1114246212e-002), + GAINCF(1.2470389716e-002), GAINCF(1.3992006890e-002), + GAINCF(1.5699289739e-002), GAINCF(1.7614893615e-002), + GAINCF(1.9764235243e-002), GAINCF(2.2175837308e-002), + GAINCF(2.4881698191e-002), GAINCF(2.7917724103e-002), + GAINCF(3.1324200332e-002), GAINCF(3.5146333277e-002), + GAINCF(3.9434835315e-002), GAINCF(4.4246610254e-002), + GAINCF(4.9645513296e-002), GAINCF(5.5703181773e-002), + GAINCF(6.2500000000e-002), GAINCF(7.0126153529e-002), + GAINCF(7.8682839870e-002), GAINCF(8.8283598423e-002), + GAINCF(9.9055826664e-002), GAINCF(1.1114246398e-001), + GAINCF(1.2470389158e-001), GAINCF(1.3992007077e-001), + GAINCF(1.5699289739e-001), GAINCF(1.7614893615e-001), + GAINCF(1.9764235616e-001), GAINCF(2.2175836563e-001), + GAINCF(2.4881698191e-001), GAINCF(2.7917724848e-001), + GAINCF(3.1324201822e-001), GAINCF(3.5146331787e-001), + GAINCF(3.9434835315e-001), GAINCF(4.4246610999e-001), + GAINCF(4.9645513296e-001), GAINCF(5.5703181028e-001), + GAINCF(6.2500000000e-001)}; + +static const FIXP_GAIN dmxGainTable__FDK[] = { + /* GAINCT2(1.0), */ GAINCT2(0.84089650f), + GAINCT2(0.70710706f), + GAINCT2(0.59460385f), + GAINCT2(0.50000000f), + GAINCT2(0.42044825f), + GAINCT2(0.35355341f), + GAINCT2(0.25000000f)}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_staticGain_OpenConfig() +description: opens and sets ConfigStruct to Default Values +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_staticGain_OpenConfig( + HANDLE_STATIC_GAIN_CONFIG *phStaticGainConfig) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == phStaticGainConfig) { + error = SACENC_INVALID_HANDLE; + } else { + /* Allocate Instance */ + FDK_ALLOCATE_MEMORY_1D(*phStaticGainConfig, 1, struct STATIC_GAIN_CONFIG); + } + return error; + +bail: + fdk_sacenc_staticGain_CloseConfig(phStaticGainConfig); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_staticGain_InitDefaultConfig( + HANDLE_STATIC_GAIN_CONFIG hStaticGainConfig) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hStaticGainConfig) { + error = SACENC_INVALID_HANDLE; + } else { + /* Necessary Input Variables */ + hStaticGainConfig->encMode = SACENC_INVALID_MODE; + + /* Optional Configs Set to Default Values */ + hStaticGainConfig->fixedGainDMX = MP4SPACEENC_DMX_GAIN_DEFAULT; + hStaticGainConfig->preGainFactorDb = 0; + } + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_staticGain_CloseConfig() +description: destructs Static Gain Config Structure +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_staticGain_CloseConfig( + HANDLE_STATIC_GAIN_CONFIG *phStaticGainConfig) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((phStaticGainConfig == NULL) || (*phStaticGainConfig == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDKfree(*phStaticGainConfig); + *phStaticGainConfig = NULL; + } + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_staticGain_Open() +description: initializes Static Gains +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_staticGain_Open(HANDLE_STATIC_GAIN *phStaticGain) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == phStaticGain) { + error = SACENC_INVALID_HANDLE; + } else { + /* Allocate Instance */ + FDK_ALLOCATE_MEMORY_1D(*phStaticGain, 1, struct STATIC_GAIN); + } + return error; + +bail: + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_staticGain_Init( + HANDLE_STATIC_GAIN hStaticGain, + const HANDLE_STATIC_GAIN_CONFIG hStaticGainConfig, INT *const scale) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hStaticGain == NULL) || (hStaticGainConfig == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + hStaticGain->encMode = hStaticGainConfig->encMode; + hStaticGain->fixedGainDMX = hStaticGainConfig->fixedGainDMX; + hStaticGain->preGainFactorDb = hStaticGainConfig->preGainFactorDb; + + if ((hStaticGain->preGainFactorDb < -20) || + (hStaticGain->preGainFactorDb > 20)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + FIXP_DBL fPreGainFactor__FDK; + + if (hStaticGain->preGainFactorDb == 0) { + fPreGainFactor__FDK = (FIXP_DBL)MAXVAL_DBL; + *scale = 0; + } else { + int s; + fPreGainFactor__FDK = + preGainFactorTable__FDK[hStaticGain->preGainFactorDb + 20]; + s = fixMax(0, CntLeadingZeros(fPreGainFactor__FDK) - 1); + fPreGainFactor__FDK = fPreGainFactor__FDK << (s); + *scale = GAINCF_SF - s; + } + + if (hStaticGain->fixedGainDMX == 0) + hStaticGain->PostGain__FDK = MAXVAL_GAIN; + else + hStaticGain->PostGain__FDK = + dmxGainTable__FDK[hStaticGain->fixedGainDMX - 1]; + + FDKmemclear( + hStaticGain->pPreGain__FDK, + sizeof(hStaticGain->pPreGain__FDK)); /* zero all input channels */ + + /* Configure PreGain-Vector */ + if (hStaticGain->encMode == SACENC_212) { + hStaticGain->pPreGain__FDK[0] = + FX_DBL2FX_GAIN(fPreGainFactor__FDK); /* L */ + hStaticGain->pPreGain__FDK[1] = + FX_DBL2FX_GAIN(fPreGainFactor__FDK); /* R */ + } else { + error = SACENC_INVALID_CONFIG; + } + + } /* valid handle */ + +bail: + + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_staticGain_Close() +description: destructs Static Gains +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_staticGain_Close(HANDLE_STATIC_GAIN *phStaticGain) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((phStaticGain == NULL) || (*phStaticGain == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDKfree(*phStaticGain); + *phStaticGain = NULL; + } + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_staticPostGain_Apply +description: multiply the Output samples with the PostGain +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_staticPostGain_ApplyFDK( + const HANDLE_STATIC_GAIN hStaticGain, INT_PCM *const pOutputSamples, + const INT nOutputSamples, const INT scale) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hStaticGain) { + error = SACENC_INVALID_HANDLE; + } else { + int i; + FIXP_GAIN postGain = hStaticGain->PostGain__FDK; + + if (scale < 0) { + if (postGain == MAXVAL_GAIN) { + for (i = 0; i < nOutputSamples; i++) { + pOutputSamples[i] = pOutputSamples[i] >> (-scale); + } + } else { + for (i = 0; i < nOutputSamples; i++) { + pOutputSamples[i] = FX_DBL2FX_PCM( + fMult(postGain, FX_PCM2FX_DBL(pOutputSamples[i])) >> (-scale)); + } + } + } else { + if (postGain == MAXVAL_GAIN) { + for (i = 0; i < nOutputSamples; i++) { + pOutputSamples[i] = FX_DBL2FX_PCM(SATURATE_LEFT_SHIFT( + FX_PCM2FX_DBL(pOutputSamples[i]), scale, DFRACT_BITS)); + } + } else { + for (i = 0; i < nOutputSamples; i++) { + pOutputSamples[i] = FX_DBL2FX_PCM(SATURATE_LEFT_SHIFT( + fMult(postGain, FX_PCM2FX_DBL(pOutputSamples[i])), scale, + DFRACT_BITS)); + } + } + } + } + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_getPreGainPtr()/ fdk_sacenc_getPostGain() +description: get Gain-Pointers from struct +returns: Pointer to PreGain or postGain +-----------------------------------------------------------------------------*/ +FIXP_GAIN *fdk_sacenc_getPreGainPtrFDK(HANDLE_STATIC_GAIN hStaticGain) { + return ((hStaticGain == NULL) ? NULL : hStaticGain->pPreGain__FDK); +} + +FIXP_GAIN fdk_sacenc_getPostGainFDK(HANDLE_STATIC_GAIN hStaticGain) { + return (hStaticGain->PostGain__FDK); +} + +/* get fixed downmix gain and map it to bitstream enum */ +FIXEDGAINDMXCONFIG fdk_sacenc_staticGain_GetDmxGain( + const HANDLE_STATIC_GAIN hStaticGain) { + FIXEDGAINDMXCONFIG dmxGain = FIXEDGAINDMX_INVALID; + + switch (hStaticGain->fixedGainDMX) { + case 0: + dmxGain = FIXEDGAINDMX_0; + break; + case 1: + dmxGain = FIXEDGAINDMX_1; + break; + case 2: + dmxGain = FIXEDGAINDMX_2; + break; + case 3: + dmxGain = FIXEDGAINDMX_3; + break; + case 4: + dmxGain = FIXEDGAINDMX_4; + break; + case 5: + dmxGain = FIXEDGAINDMX_5; + break; + case 6: + dmxGain = FIXEDGAINDMX_6; + break; + case 7: + dmxGain = FIXEDGAINDMX_7; + break; + default: + dmxGain = FIXEDGAINDMX_INVALID; + } + return dmxGain; +} + +FDK_SACENC_ERROR fdk_sacenc_staticGain_SetDmxGain( + HANDLE_STATIC_GAIN_CONFIG hStaticGainCfg, + const MP4SPACEENC_DMX_GAIN dmxGain) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hStaticGainCfg) { + error = SACENC_INVALID_HANDLE; + } else { + hStaticGainCfg->fixedGainDMX = dmxGain; + } + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_staticGain_SetEncMode( + HANDLE_STATIC_GAIN_CONFIG hStaticGainCfg, const MP4SPACEENC_MODE encMode) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hStaticGainCfg) { + error = SACENC_INVALID_HANDLE; + } else { + hStaticGainCfg->encMode = encMode; + } + return error; +} diff --git a/libSACenc/src/sacenc_staticgain.h b/libSACenc/src/sacenc_staticgain.h new file mode 100644 index 0000000..5db3bec --- /dev/null +++ b/libSACenc/src/sacenc_staticgain.h @@ -0,0 +1,177 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Christian Goettlinger + + Description: Encoder Library Interfac + gain management of the encoder + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + ******************************************************************************/ + +#ifndef SACENC_STATICGAIN_H +#define SACENC_STATICGAIN_H + +/* Includes ******************************************************************/ +#include "common_fix.h" +#include "sacenc_lib.h" +#include "sacenc_const.h" +#include "sacenc_bitstream.h" + +/* Defines *******************************************************************/ +#define FIXP_GAIN FIXP_DBL +#define MAXVAL_GAIN ((FIXP_DBL)MAXVAL_DBL) + +/* Data Types ****************************************************************/ +struct STATIC_GAIN_CONFIG { + MP4SPACEENC_MODE encMode; + MP4SPACEENC_DMX_GAIN fixedGainDMX; + INT preGainFactorDb; +}; + +typedef struct STATIC_GAIN_CONFIG *HANDLE_STATIC_GAIN_CONFIG; +typedef struct STATIC_GAIN *HANDLE_STATIC_GAIN; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Initializes Static Gain Computation Config */ +FDK_SACENC_ERROR fdk_sacenc_staticGain_OpenConfig( + HANDLE_STATIC_GAIN_CONFIG *phStaticGainConfig); + +FDK_SACENC_ERROR fdk_sacenc_staticGain_InitDefaultConfig( + HANDLE_STATIC_GAIN_CONFIG hStaticGainConfig); + +/* Deletes Static Gain Computation Config ~Destructor */ +FDK_SACENC_ERROR fdk_sacenc_staticGain_CloseConfig( + HANDLE_STATIC_GAIN_CONFIG *phStaticGainConfig); + +/* Initializes Static Gain Computation ~Constructor */ +FDK_SACENC_ERROR fdk_sacenc_staticGain_Open(HANDLE_STATIC_GAIN *phStaticGain); + +FDK_SACENC_ERROR fdk_sacenc_staticGain_Init( + HANDLE_STATIC_GAIN hStaticGain, + const HANDLE_STATIC_GAIN_CONFIG hStaticGainConfig, INT *const scale); + +/* Deletes Static Gain Computation Infrastucture ~Destructor */ +FDK_SACENC_ERROR fdk_sacenc_staticGain_Close(HANDLE_STATIC_GAIN *phStaticGain); + +/* Apply PostGain to the output PCM Downmix-Signal */ +FDK_SACENC_ERROR fdk_sacenc_staticPostGain_ApplyFDK( + const HANDLE_STATIC_GAIN hStaticGain, INT_PCM *const pOutputSamples, + const INT nOutputSamples, const INT scale); + +/* Get Pointer to PreGain-vector */ +FIXP_GAIN *fdk_sacenc_getPreGainPtrFDK(HANDLE_STATIC_GAIN hStaticGain); + +/* Get Pointer to PostGain-coef */ +FIXP_GAIN fdk_sacenc_getPostGainFDK(HANDLE_STATIC_GAIN hStaticGain); + +FIXEDGAINDMXCONFIG fdk_sacenc_staticGain_GetDmxGain( + const HANDLE_STATIC_GAIN hStaticGain); + +FDK_SACENC_ERROR fdk_sacenc_staticGain_SetDmxGain( + HANDLE_STATIC_GAIN_CONFIG hStaticGainCfg, + const MP4SPACEENC_DMX_GAIN dmxGain); + +FDK_SACENC_ERROR fdk_sacenc_staticGain_SetEncMode( + HANDLE_STATIC_GAIN_CONFIG hStaticGainCfg, const MP4SPACEENC_MODE encMode); + +#endif /* SACENC_STATICGAIN_H */ diff --git a/libSACenc/src/sacenc_tree.cpp b/libSACenc/src/sacenc_tree.cpp new file mode 100644 index 0000000..c7d3128 --- /dev/null +++ b/libSACenc/src/sacenc_tree.cpp @@ -0,0 +1,488 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Tree Structure for Space Encoder + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_tree.h" +#include "genericStds.h" +#include "sacenc_const.h" +#include "sacenc_paramextract.h" +#include "sacenc_framewindowing.h" +#include "FDK_matrixCalloc.h" + +/* Defines *******************************************************************/ +enum { BOX_0 = 0, BOX_1 = 1 }; + +enum { CH_L = 0, CH_R = 1 }; + +enum { TTO_CH_0 = 0, TTO_CH_1 = 1 }; + +enum { WIN_INACTIV = 0, WIN_ACTIV = 1 }; + +enum { MAX_KEEP_FRAMECOUNT = 100 }; + +/* Data Types ****************************************************************/ +struct SPACE_TREE { + SPACETREE_MODE mode; + SPACE_TREE_DESCRIPTION descr; + HANDLE_TTO_BOX ttoBox[SACENC_MAX_NUM_BOXES]; + UCHAR nParamBands; + UCHAR bUseCoarseQuantTtoIcc; + UCHAR bUseCoarseQuantTtoCld; + QUANTMODE quantMode; + INT frameCount; + UCHAR bFrameKeep; + + /* Intermediate buffers */ + UCHAR pCld_prev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAM_BANDS]; + UCHAR pIcc_prev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAM_BANDS]; + + UCHAR nChannelsInMax; + UCHAR nHybridBandsMax; +}; + +typedef struct { + UCHAR boxId; + UCHAR inCh1; + UCHAR inCh2; + UCHAR inCh3; + UCHAR inCh4; + UCHAR wCh1; + UCHAR wCh2; + +} TTO_DESCRIPTOR; + +typedef struct { + SPACETREE_MODE mode; + SPACE_TREE_DESCRIPTION treeDescription; + +} TREE_CONFIG; + +typedef struct { + SPACETREE_MODE mode; + UCHAR nChannelsIn; + UCHAR nChannelsOut; + UCHAR nTtoBoxes; + TTO_DESCRIPTOR tto_descriptor[1]; + +} TREE_SETUP; + +/* Constants *****************************************************************/ +static const TREE_CONFIG treeConfigTable[] = { + {SPACETREE_INVALID_MODE, {0, 0, 0}}, {SPACETREE_212, {1, 1, 2}}}; + +static const TREE_SETUP treeSetupTable[] = { + {SPACETREE_INVALID_MODE, 0, 0, 0, {{0, 0, 0, 0, 0, 0, 0}}}, + {SPACETREE_212, + 2, + 1, + 1, + {{BOX_0, CH_L, CH_R, TTO_CH_0, TTO_CH_1, WIN_ACTIV, WIN_ACTIV}}}}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static FDK_SACENC_ERROR getTreeConfig( + const SPACETREE_MODE mode, SPACE_TREE_DESCRIPTION *pTreeDescription) { + FDK_SACENC_ERROR error = SACENC_INIT_ERROR; + + if (pTreeDescription == NULL) { + error = SACENC_INVALID_HANDLE; + } else { + int i; + for (i = 0; i < (int)(sizeof(treeConfigTable) / sizeof(TREE_CONFIG)); i++) { + if (treeConfigTable[i].mode == mode) { + *pTreeDescription = treeConfigTable[i].treeDescription; + error = SACENC_OK; + break; + } + } + } /* valid handle */ + return error; +} + +static const TREE_SETUP *getTreeSetup(const SPACETREE_MODE mode) { + int i; + const TREE_SETUP *setup = NULL; + + for (i = 0; i < (int)(sizeof(treeSetupTable) / sizeof(TREE_SETUP)); i++) { + if (treeSetupTable[i].mode == mode) { + setup = &treeSetupTable[i]; + break; + } + } + return setup; +} + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Open(HANDLE_SPACE_TREE *phSpaceTree) { + FDK_SACENC_ERROR error = SACENC_OK; + HANDLE_SPACE_TREE hSpaceTree = NULL; + + if (NULL == phSpaceTree) { + error = SACENC_INVALID_HANDLE; + } else { + int box; + + FDK_ALLOCATE_MEMORY_1D(hSpaceTree, 1, struct SPACE_TREE); + + for (box = 0; box < SACENC_MAX_NUM_BOXES; box++) { + HANDLE_TTO_BOX ttoBox = NULL; + if (SACENC_OK != (error = fdk_sacenc_createTtoBox(&ttoBox))) { + goto bail; + } + if (NULL != hSpaceTree) { + hSpaceTree->ttoBox[box] = ttoBox; + } + } + *phSpaceTree = hSpaceTree; + } + return error; + +bail: + fdk_sacenc_spaceTree_Close(&hSpaceTree); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Init( + HANDLE_SPACE_TREE hST, const SPACE_TREE_SETUP *const hSetup, + UCHAR *pParameterBand2HybridBandOffset, const INT bFrameKeep) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hST == NULL) || (hSetup == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int bTtoBoxFrontBackCombin[SACENC_MAX_NUM_BOXES] = {0}; + int box = 0; + + hST->frameCount = 0; + hST->bFrameKeep = bFrameKeep; + + /* Init */ + hST->mode = hSetup->mode; + hST->nParamBands = hSetup->nParamBands; + hST->bUseCoarseQuantTtoIcc = hSetup->bUseCoarseQuantTtoIcc; + hST->bUseCoarseQuantTtoCld = hSetup->bUseCoarseQuantTtoCld; + hST->quantMode = hSetup->quantMode; + hST->nChannelsInMax = hSetup->nChannelsInMax; + hST->nHybridBandsMax = hSetup->nHybridBandsMax; + + if (SACENC_OK != (error = getTreeConfig(hST->mode, &hST->descr))) { + goto bail; + } + + switch (hST->mode) { + case SPACETREE_212: + bTtoBoxFrontBackCombin[BOX_0] = 0; + break; + case SPACETREE_INVALID_MODE: + default: + error = SACENC_INIT_ERROR; + goto bail; + } /* switch (hST->mode) */ + + if (hST->descr.nOttBoxes > SACENC_MAX_NUM_BOXES) { + error = SACENC_INIT_ERROR; + goto bail; + } + + for (box = 0; box < hST->descr.nOttBoxes; box++) { + TTO_BOX_CONFIG boxConfig; + boxConfig.subbandConfig = (BOX_SUBBAND_CONFIG)hST->nParamBands; + boxConfig.bUseCoarseQuantCld = hST->bUseCoarseQuantTtoCld; + boxConfig.bUseCoarseQuantIcc = hST->bUseCoarseQuantTtoIcc; + boxConfig.bUseCoherenceIccOnly = bTtoBoxFrontBackCombin[box]; + boxConfig.boxQuantMode = (BOX_QUANTMODE)hST->quantMode; + boxConfig.nHybridBandsMax = hST->nHybridBandsMax; + boxConfig.bFrameKeep = hST->bFrameKeep; + + if (SACENC_OK != + (error = fdk_sacenc_initTtoBox(hST->ttoBox[box], &boxConfig, + pParameterBand2HybridBandOffset))) { + goto bail; + } + } /* for box */ + + } /* valid handle */ + +bail: + return error; +} + +static void SpaceTree_FrameKeep212(const HANDLE_SPACE_TREE hST, + SPATIALFRAME *const hSTOut, + const INT avoid_keep) { + int pb; + + if (avoid_keep == 0) { + if (hST->frameCount % 2 == 0) { + for (pb = 0; pb < hST->nParamBands; pb++) { + hST->pIcc_prev[BOX_0][pb] = hSTOut->ottData.icc[BOX_0][0][pb]; + hSTOut->ottData.cld[BOX_0][0][pb] = hST->pCld_prev[BOX_0][pb]; + } + } else { + for (pb = 0; pb < hST->nParamBands; pb++) { + hSTOut->ottData.icc[BOX_0][0][pb] = hST->pIcc_prev[BOX_0][pb]; + hST->pCld_prev[BOX_0][pb] = hSTOut->ottData.cld[BOX_0][0][pb]; + } + } + } else { + for (pb = 0; pb < hST->nParamBands; pb++) { + hST->pIcc_prev[BOX_0][pb] = hSTOut->ottData.icc[BOX_0][0][pb]; + hST->pCld_prev[BOX_0][pb] = hSTOut->ottData.cld[BOX_0][0][pb]; + } + } + hST->frameCount++; + if (hST->frameCount == MAX_KEEP_FRAMECOUNT) { + hST->frameCount = 0; + } +} + +static FDK_SACENC_ERROR SpaceTree_FrameKeep(const HANDLE_SPACE_TREE hST, + SPATIALFRAME *const hSTOut, + const INT avoid_keep) { + FDK_SACENC_ERROR error = SACENC_OK; + + switch (hST->mode) { + case SPACETREE_212: + SpaceTree_FrameKeep212(hST, hSTOut, avoid_keep); + break; + case SPACETREE_INVALID_MODE: + default: + error = SACENC_INVALID_CONFIG; + break; + } + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Apply( + HANDLE_SPACE_TREE hST, const INT paramSet, const INT nChannelsIn, + const INT nTimeSlots, const INT startTimeSlot, const INT nHybridBands, + FIXP_WIN *pFrameWindowAna__FDK, + FIXP_DPK *const *const *const pppHybrid__FDK, + FIXP_DPK *const *const *const pppHybridIn__FDK, SPATIALFRAME *const hSTOut, + const INT avoid_keep, INT *pEncoderInputChScale) { + /** \verbatim + ============================================================================================================================= + TREE_212 + ============================================================================================================================= + _______ + L -- TTO_CH_0 --| | + | TTO_0 |-- TTO_CH_0 + R -- TTO_CH_1 --|_______| + + \endverbatim */ + + FDK_SACENC_ERROR error = SACENC_OK; + int k; + const TREE_SETUP *treeSetup = NULL; + + if ((hST == NULL) || (hSTOut == NULL) || (pppHybrid__FDK == NULL) || + (pppHybridIn__FDK == NULL)) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + if ((treeSetup = getTreeSetup(hST->mode)) == NULL) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* Sanity Checks */ + if ((nChannelsIn != treeSetup->nChannelsIn) || + (nChannelsIn > hST->nChannelsInMax) || + (nHybridBands > hST->nHybridBandsMax)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* Apply all TTO boxes. */ + for (k = 0; k < treeSetup->nTtoBoxes; k++) { + const TTO_DESCRIPTOR *pTTO = &treeSetup->tto_descriptor[k]; + + int i, inCh[2], outCh[2], win[2]; + + inCh[0] = pTTO->inCh1; + outCh[0] = pTTO->inCh3; + win[0] = pTTO->wCh1; + inCh[1] = pTTO->inCh2; + outCh[1] = pTTO->inCh4; + win[1] = pTTO->wCh2; + + for (i = 0; i < 2; i++) { + if (win[i] == WIN_ACTIV) { + fdk_sacenc_analysisWindowing( + nTimeSlots, startTimeSlot, pFrameWindowAna__FDK, + pppHybrid__FDK[inCh[i]], pppHybridIn__FDK[outCh[i]], nHybridBands, + FW_LEAVE_DIM); + } + } + + /* Calculate output downmix within last TTO box, if no TTT box is applied. + */ + if (SACENC_OK != + (error = fdk_sacenc_applyTtoBox( + hST->ttoBox[pTTO->boxId], nTimeSlots, startTimeSlot, nHybridBands, + pppHybridIn__FDK[pTTO->inCh3], pppHybridIn__FDK[pTTO->inCh4], + hSTOut->ottData.icc[pTTO->boxId][paramSet], + &(hSTOut->ICCLosslessData.bsQuantCoarseXXX[pTTO->boxId][paramSet]), + hSTOut->ottData.cld[pTTO->boxId][paramSet], + &(hSTOut->CLDLosslessData.bsQuantCoarseXXX[pTTO->boxId][paramSet]), + hSTOut->bUseBBCues, &pEncoderInputChScale[inCh[0]], + &pEncoderInputChScale[inCh[1]]))) { + goto bail; + } + } + + if (hST->bFrameKeep == 1) { + if (SACENC_OK != (error = SpaceTree_FrameKeep(hST, hSTOut, avoid_keep))) { + goto bail; + } + } + +bail: + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Close(HANDLE_SPACE_TREE *phSpaceTree) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((phSpaceTree == NULL) || (*phSpaceTree == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int box; + HANDLE_SPACE_TREE const hST = *phSpaceTree; + + /* for (box = 0; box < hST->descr.nOttBoxes; ++box) { */ + for (box = 0; box < SACENC_MAX_NUM_BOXES; ++box) { + if (SACENC_OK != (error = fdk_sacenc_destroyTtoBox(&hST->ttoBox[box]))) { + goto bail; + } + } + + FDKfree(*phSpaceTree); + *phSpaceTree = NULL; + } +bail: + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_GetDescription( + const HANDLE_SPACE_TREE hSpaceTree, + SPACE_TREE_DESCRIPTION *pSpaceTreeDescription) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hSpaceTree == NULL) || (pSpaceTreeDescription == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + *pSpaceTreeDescription = hSpaceTree->descr; + } + return error; +} + +INT fdk_sacenc_spaceTree_Hybrid2ParamBand(const INT nParamBands, + const INT nHybridBand) { + return fdk_sacenc_subband2ParamBand((BOX_SUBBAND_CONFIG)nParamBands, + nHybridBand); +} + +/***************************************************************************** +******************************************************************************/ diff --git a/libSACenc/src/sacenc_tree.h b/libSACenc/src/sacenc_tree.h new file mode 100644 index 0000000..09f5b2b --- /dev/null +++ b/libSACenc/src/sacenc_tree.h @@ -0,0 +1,168 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Tree Structure for Space Encoder + +*******************************************************************************/ + +#ifndef SACENC_TREE_H +#define SACENC_TREE_H + +/* Includes ******************************************************************/ +#include "sacenc_framewindowing.h" +#include "sacenc_lib.h" +#include "sacenc_bitstream.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ +typedef enum { + SPACETREE_INVALID_MODE = 0, + SPACETREE_212 = 8 + +} SPACETREE_MODE; + +typedef struct SPACE_TREE *HANDLE_SPACE_TREE; + +typedef struct { + UCHAR nParamBands; + UCHAR bUseCoarseQuantTtoCld; + UCHAR bUseCoarseQuantTtoIcc; + QUANTMODE quantMode; + SPACETREE_MODE mode; + + UCHAR nChannelsInMax; + UCHAR nHybridBandsMax; + +} SPACE_TREE_SETUP; + +typedef struct { + UCHAR nOttBoxes; + UCHAR nInChannels; + UCHAR nOutChannels; + +} SPACE_TREE_DESCRIPTION; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Open(HANDLE_SPACE_TREE *phSpaceTree); + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Init( + HANDLE_SPACE_TREE hST, const SPACE_TREE_SETUP *const hSetup, + UCHAR *pParameterBand2HybridBandOffset, const INT bFrameKeep); + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Apply( + HANDLE_SPACE_TREE hST, const INT paramSet, const INT nChannelsIn, + const INT nTimeSlots, const INT startTimeSlot, const INT nHybridBands, + FIXP_WIN *pFrameWindowAna__FDK, + FIXP_DPK *const *const *const pppHybrid__FDK, + FIXP_DPK *const *const *const pppHybridIn__FDK, SPATIALFRAME *const hSTOut, + const INT avoid_keep, INT *pEncoderInputChScale); + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Close(HANDLE_SPACE_TREE *phSpaceTree); + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_GetDescription( + const HANDLE_SPACE_TREE hSpaceTree, + SPACE_TREE_DESCRIPTION *pSpaceTreeDescription); + +INT fdk_sacenc_spaceTree_Hybrid2ParamBand(const INT nParamBands, + const INT nHybridBand); + +#endif /* SACENC_TREE_H */ diff --git a/libSACenc/src/sacenc_vectorfunctions.cpp b/libSACenc/src/sacenc_vectorfunctions.cpp new file mode 100644 index 0000000..c1e24b7 --- /dev/null +++ b/libSACenc/src/sacenc_vectorfunctions.cpp @@ -0,0 +1,450 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Josef Hoepfl + + Description: Encoder Library Interface + vector functions + +*******************************************************************************/ + +/***************************************************************************** +\file +This file contains vector functions +******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_vectorfunctions.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ + +FIXP_DBL sumUpCplxPow2(const FIXP_DPK *const x, const INT scaleMode, + const INT inScaleFactor, INT *const outScaleFactor, + const INT n) { + int i, cs; + + if (scaleMode == SUM_UP_DYNAMIC_SCALE) { + /* calculate headroom */ + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + for (i = 0; i < n; i++) { + maxVal |= fAbs(x[i].v.re); + maxVal |= fAbs(x[i].v.im); + } + cs = inScaleFactor - fixMax(0, CntLeadingZeros(maxVal) - 1); + } else { + cs = inScaleFactor; + } + + /* consider scaling of energy and scaling in fPow2Div2 and addition */ + *outScaleFactor = 2 * cs + 2; + + /* make sure that the scalefactor is in the range of -(DFRACT_BITS-1), ... , + * (DFRACT_BITS-1) */ + cs = fixMax(fixMin(cs, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); + + /* sum up complex energy samples */ + FIXP_DBL re, im, sum; + + re = im = sum = FL2FXCONST_DBL(0.0); + if (cs < 0) { + cs = -cs; + for (i = 0; i < n; i++) { + re += fPow2Div2(x[i].v.re << cs); + im += fPow2Div2(x[i].v.im << cs); + } + } else { + cs = 2 * cs; + for (i = 0; i < n; i++) { + re += fPow2Div2(x[i].v.re) >> cs; + im += fPow2Div2(x[i].v.im) >> cs; + } + } + + sum = (re >> 1) + (im >> 1); + + return (sum); +} + +FIXP_DBL sumUpCplxPow2Dim2(const FIXP_DPK *const *const x, const INT scaleMode, + const INT inScaleFactor, INT *const outScaleFactor, + const INT sDim1, const INT nDim1, const INT sDim2, + const INT nDim2) { + int i, j, cs; + + if (scaleMode == SUM_UP_DYNAMIC_SCALE) { + /* calculate headroom */ + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + maxVal |= fAbs(x[i][j].v.re); + maxVal |= fAbs(x[i][j].v.im); + } + } + cs = inScaleFactor - fixMax(0, CntLeadingZeros(maxVal) - 1); + } else { + cs = inScaleFactor; + } + + /* consider scaling of energy and scaling in fPow2Div2 and addition */ + *outScaleFactor = 2 * cs + 2; + + /* make sure that the scalefactor is in the range of -(DFRACT_BITS-1), ... , + * (DFRACT_BITS-1) */ + cs = fixMax(fixMin(cs, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); + + /* sum up complex energy samples */ + FIXP_DBL re, im, sum; + + re = im = sum = FL2FXCONST_DBL(0.0); + if (cs < 0) { + cs = -cs; + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + re += fPow2Div2(x[i][j].v.re << cs); + im += fPow2Div2(x[i][j].v.im << cs); + } + } + } else { + cs = 2 * cs; + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + re += fPow2Div2(x[i][j].v.re) >> cs; + im += fPow2Div2(x[i][j].v.im) >> cs; + } + } + } + + sum = (re >> 1) + (im >> 1); + + return (sum); +} + +void copyCplxVec(FIXP_DPK *const Z, const FIXP_DPK *const X, const INT n) { + FDKmemmove(Z, X, sizeof(FIXP_DPK) * n); +} + +void setCplxVec(FIXP_DPK *const Z, const FIXP_DBL a, const INT n) { + int i; + + for (i = 0; i < n; i++) { + Z[i].v.re = a; + Z[i].v.im = a; + } +} + +void cplx_cplxScalarProduct(FIXP_DPK *const Z, const FIXP_DPK *const *const X, + const FIXP_DPK *const *const Y, const INT scaleX, + const INT scaleY, INT *const scaleZ, + const INT sDim1, const INT nDim1, const INT sDim2, + const INT nDim2) { + int i, j, sx, sy; + FIXP_DBL xre, yre, xim, yim, re, im; + + /* make sure that the scalefactor is in the range of -(DFRACT_BITS-1), ... , + * (DFRACT_BITS-1) */ + sx = fixMax(fixMin(scaleX, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); + sy = fixMax(fixMin(scaleY, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); + + /* consider scaling of energy and scaling in fMultDiv2 and shift of result + * values */ + *scaleZ = sx + sy + 2; + + re = (FIXP_DBL)0; + im = (FIXP_DBL)0; + if ((sx < 0) && (sy < 0)) { + sx = -sx; + sy = -sy; + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + xre = X[i][j].v.re << sx; + xim = X[i][j].v.im << sx; + yre = Y[i][j].v.re << sy; + yim = Y[i][j].v.im << sy; + re += fMultDiv2(xre, yre) + fMultDiv2(xim, yim); + im += fMultDiv2(xim, yre) - fMultDiv2(xre, yim); + } + } + } else if ((sx >= 0) && (sy >= 0)) { + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + xre = X[i][j].v.re; + xim = X[i][j].v.im; + yre = Y[i][j].v.re; + yim = Y[i][j].v.im; + re += (fMultDiv2(xre, yre) + fMultDiv2(xim, yim)) >> (sx + sy); + im += (fMultDiv2(xim, yre) - fMultDiv2(xre, yim)) >> (sx + sy); + } + } + } else if ((sx < 0) && (sy >= 0)) { + sx = -sx; + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + xre = X[i][j].v.re << sx; + xim = X[i][j].v.im << sx; + yre = Y[i][j].v.re; + yim = Y[i][j].v.im; + re += (fMultDiv2(xre, yre) + fMultDiv2(xim, yim)) >> sy; + im += (fMultDiv2(xim, yre) - fMultDiv2(xre, yim)) >> sy; + } + } + } else { + sy = -sy; + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + xre = X[i][j].v.re; + xim = X[i][j].v.im; + yre = Y[i][j].v.re << sy; + yim = Y[i][j].v.im << sy; + re += (fMultDiv2(xre, yre) + fMultDiv2(xim, yim)) >> sx; + im += (fMultDiv2(xim, yre) - fMultDiv2(xre, yim)) >> sx; + } + } + } + + Z->v.re = re >> 1; + Z->v.im = im >> 1; +} + +void FDKcalcCorrelationVec(FIXP_DBL *const z, const FIXP_DBL *const pr12, + const FIXP_DBL *const p1, const FIXP_DBL *const p2, + const INT n) { + int i, s; + FIXP_DBL p12, cor; + + /* correlation */ + for (i = 0; i < n; i++) { + p12 = fMult(p1[i], p2[i]); + if (p12 > FL2FXCONST_DBL(0.0f)) { + p12 = invSqrtNorm2(p12, &s); + cor = fMult(pr12[i], p12); + z[i] = SATURATE_LEFT_SHIFT(cor, s, DFRACT_BITS); + } else { + z[i] = (FIXP_DBL)MAXVAL_DBL; + } + } +} + +void calcCoherenceVec(FIXP_DBL *const z, const FIXP_DBL *const p12r, + const FIXP_DBL *const p12i, const FIXP_DBL *const p1, + const FIXP_DBL *const p2, const INT scaleP12, + const INT scaleP, const INT n) { + int i, s, s1, s2; + FIXP_DBL coh, p12, p12ri; + + for (i = 0; i < n; i++) { + s2 = fixMin(fixMax(0, CountLeadingBits(p12r[i]) - 1), + fixMax(0, CountLeadingBits(p12i[i]) - 1)); + p12ri = sqrtFixp(fPow2Div2(p12r[i] << s2) + fPow2Div2(p12i[i] << s2)); + s1 = fixMin(fixMax(0, CountLeadingBits(p1[i]) - 1), + fixMax(0, CountLeadingBits(p2[i]) - 1)); + p12 = fMultDiv2(p1[i] << s1, p2[i] << s1); + + if (p12 > FL2FXCONST_DBL(0.0f)) { + p12 = invSqrtNorm2(p12, &s); + coh = fMult(p12ri, p12); + s = fixMax(fixMin((scaleP12 - scaleP + s + s1 - s2), DFRACT_BITS - 1), + -(DFRACT_BITS - 1)); + if (s < 0) { + z[i] = coh >> (-s); + } else { + z[i] = SATURATE_LEFT_SHIFT(coh, s, DFRACT_BITS); + } + } else { + z[i] = (FIXP_DBL)MAXVAL_DBL; + } + } +} + +void addWeightedCplxVec(FIXP_DPK *const *const Z, const FIXP_DBL *const a, + const FIXP_DPK *const *const X, const FIXP_DBL *const b, + const FIXP_DPK *const *const Y, const INT scale, + INT *const scaleCh1, const INT scaleCh2, + const UCHAR *const pParameterBand2HybridBandOffset, + const INT nParameterBands, const INT nTimeSlots, + const INT startTimeSlot) { + int pb, j, i; + int cs, s1, s2; + + /* determine maximum scale of both channels */ + cs = fixMax(*scaleCh1, scaleCh2); + s1 = cs - (*scaleCh1); + s2 = cs - scaleCh2; + + /* scalefactor 1 is updated with common scale of channel 1 and channel2 */ + *scaleCh1 = cs; + + /* scale of a and b; additional scale for fMultDiv2() */ + for (j = 0, pb = 0; pb < nParameterBands; pb++) { + FIXP_DBL aPb, bPb; + aPb = a[pb], bPb = b[pb]; + for (; j < pParameterBand2HybridBandOffset[pb]; j++) { + for (i = startTimeSlot; i < nTimeSlots; i++) { + Z[j][i].v.re = ((fMultDiv2(aPb, X[j][i].v.re) >> s1) + + (fMultDiv2(bPb, Y[j][i].v.re) >> s2)) + << (scale + 1); + Z[j][i].v.im = ((fMultDiv2(aPb, X[j][i].v.im) >> s1) + + (fMultDiv2(bPb, Y[j][i].v.im) >> s2)) + << (scale + 1); + } + } + } +} + +void FDKcalcPbScaleFactor(const FIXP_DPK *const *const x, + const UCHAR *const pParameterBand2HybridBandOffset, + INT *const outScaleFactor, const INT startTimeSlot, + const INT nTimeSlots, const INT nParamBands) { + int i, j, pb; + + /* calculate headroom */ + for (j = 0, pb = 0; pb < nParamBands; pb++) { + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + for (; j < pParameterBand2HybridBandOffset[pb]; j++) { + for (i = startTimeSlot; i < nTimeSlots; i++) { + maxVal |= fAbs(x[i][j].v.re); + maxVal |= fAbs(x[i][j].v.im); + } + } + outScaleFactor[pb] = -fixMax(0, CntLeadingZeros(maxVal) - 1); + } +} + +INT FDKcalcScaleFactor(const FIXP_DBL *const x, const FIXP_DBL *const y, + const INT n) { + int i; + + /* calculate headroom */ + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + if (x != NULL) { + for (i = 0; i < n; i++) { + maxVal |= fAbs(x[i]); + } + } + + if (y != NULL) { + for (i = 0; i < n; i++) { + maxVal |= fAbs(y[i]); + } + } + + if (maxVal == (FIXP_DBL)0) + return (-(DFRACT_BITS - 1)); + else + return (-CountLeadingBits(maxVal)); +} + +INT FDKcalcScaleFactorDPK(const FIXP_DPK *RESTRICT x, const INT startBand, + const INT bands) { + INT qs, clz; + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + + for (qs = startBand; qs < bands; qs++) { + maxVal |= fAbs(x[qs].v.re); + maxVal |= fAbs(x[qs].v.im); + } + + clz = -fixMax(0, CntLeadingZeros(maxVal) - 1); + + return (clz); +} diff --git a/libSACenc/src/sacenc_vectorfunctions.h b/libSACenc/src/sacenc_vectorfunctions.h new file mode 100644 index 0000000..e9c4abd --- /dev/null +++ b/libSACenc/src/sacenc_vectorfunctions.h @@ -0,0 +1,488 @@ +/* ----------------------------------------------------------------------------- +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 +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Josef Hoepfl + + Description: Encoder Library Interface + vector functions + +*******************************************************************************/ + +/***************************************************************************** +\file +This file contains vector functions +******************************************************************************/ + +#ifndef SACENC_VECTORFUNCTIONS_H +#define SACENC_VECTORFUNCTIONS_H + +/* Includes ******************************************************************/ +#include "common_fix.h" + +/* Defines *******************************************************************/ +#define SUM_UP_STATIC_SCALE 0 +#define SUM_UP_DYNAMIC_SCALE 1 + +/* Data Types ****************************************************************/ + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/** + * \brief Vector function : Sum up complex power + * + * Description : ret = sum( re{X[i]} * re{X[i]} + im{X[i]} * + * im{X[i]} ), i=0,...,n-1 ret is scaled by outScaleFactor + * + * \param const FIXP_DPK x[] + * Input: complex vector of the length n + * + * \param int scaleMode + * Input: choose static or dynamic scaling + * (SUM_UP_DYNAMIC_SCALE/SUM_UP_STATIC_SCALE) + * + * \param int inScaleFactor + * Input: determine headroom bits for the complex input vector + * + * \param int outScaleFactor + * Output: complete scaling in energy calculation + * + * \return FIXP_DBL ret + */ +FIXP_DBL sumUpCplxPow2(const FIXP_DPK *const x, const INT scaleMode, + const INT inScaleFactor, INT *const outScaleFactor, + const INT n); + +/** + * \brief Vector function : Sum up complex power + * + * Description : ret = sum( re{X[i][j]} * re{X[i][]} + + * im{X[i][]} * im{X[i][]} ), i=sDim1,...,nDim1-1 i=sDim2,...,nDim2-1 ret is + * scaled by outScaleFactor + * + * \param const FIXP_DPK x[] + * Input: complex vector of the length n + * + * \param int scaleMode + * Input: choose static or dynamic scaling + * (SUM_UP_DYNAMIC_SCALE/SUM_UP_STATIC_SCALE) + * + * \param int inScaleFactor + * Input: determine headroom bits for the complex input vector + * + * \param int outScaleFactor + * Output: complete scaling in energy calculation + * + * \param int sDim1 + * Input: start index for loop counter in dimension 1 + * + * \param int nDim1 + * Input: loop counter in dimension 1 + * + * \param int sDim2 + * Input: start index for loop counter in dimension 2 + * + * \param int nDim2 + * Input: loop counter in dimension 2 + * + * \return FIXP_DBL ret + */ +FIXP_DBL sumUpCplxPow2Dim2(const FIXP_DPK *const *const x, const INT scaleMode, + const INT inScaleFactor, INT *const outScaleFactor, + const INT sDim1, const INT nDim1, const INT sDim2, + const INT nDim2); + +/** + * \brief Vector function : Z[i] = X[i], i=0,...,n-1 + * + * Description : re{Z[i]} = re{X[i]}, i=0,...,n-1 + * im{Z[i]} = im{X[i]}, i=0,...,n-1 + * + * Copy complex vector X[] to complex vector Z[]. + * It is allowed to overlay X[] with Z[]. + * + * \param FIXP_DPK Z[] + * Output: vector of the length n + * + * \param const FIXP_DPK X[] + * Input: vector of the length n + * + * \param int n + * Input: length of vector Z[] and X[] + * + * \return void + */ +void copyCplxVec(FIXP_DPK *const Z, const FIXP_DPK *const X, const INT n); + +/** + * \brief Vector function : Z[i] = a, i=0,...,n-1 + * + * Description : re{Z[i]} = a, i=0,...,n-1 + * im{Z[i]} = a, i=0,...,n-1 + * + * Set real and imaginary part of the complex value Z to a. + * + * \param FIPX_DPK Z[] + * Output: vector of the length n + * + * \param const FIXP_DBL a + * Input: constant value + * + * \param int n + * Input: length of vector Z[] + * + * \return void + */ +void setCplxVec(FIXP_DPK *const Z, const FIXP_DBL a, const INT n); + +/** + * \brief Vector function : Calculate complex-valued result of complex + * scalar product + * + * Description : re{Z} = sum( re{X[i]} * re{Y[i]} + im{X[i]} * + * im{Y[i]}, i=0,...,n-1 ) im{Z} = sum( im{X[i]} * re{Y[i]} - re{X[i]} * + * im{Y[i]}, i=0,...,n-1 ) + * + * The function returns the complex-valued result of the complex + * scalar product at the address of Z. The result is scaled by scaleZ. + * + * \param FIXP_DPK *Z + * Output: pointer to Z + * + * \param const FIXP_DPK *const *const X + * Input: vector of the length n + * + * \param const FIXP_DPK *const *const Y + * Input: vector of the length n + * + * \param int scaleX + * Input: scalefactor of vector X[] + * + * \param int scaleY + * Input: scalefactor of vector Y[] + * + * \param int scaleZ + * Output: scalefactor of vector Z[] + * + * \param int sDim1 + * Input: start index for loop counter in dimension 1 + * + * \param int nDim1 + * Input: loop counter in dimension 1 + * + * \param int sDim2 + * Input: start index for loop counter in dimension 2 + * + * \param int nDim2 + * Input: loop counter in dimension 2 + * + * \return void + */ +void cplx_cplxScalarProduct(FIXP_DPK *const Z, const FIXP_DPK *const *const X, + const FIXP_DPK *const *const Y, const INT scaleX, + const INT scaleY, INT *const scaleZ, + const INT sDim1, const INT nDim1, const INT sDim2, + const INT nDim2); + +/** + * \brief Vector function : Calculate correlation + * + * Description : z[i] = pr12[i] / sqrt(p1[i]*p2[i]) , + * i=0,...,n-1 + * + * \param FIXP_DBL z[] + * Output: vector of length n + * + * \param const FIXP_DBL pr12[] + * Input: vector of the length n + * + * \param const FIXP_DBL p1[] + * Input: vector of the length n + * + * \param const FIXP_DBL p2[] + * Input: vector of the length n + * + * \param int n + * Input: length of vector pr12[], p1[] and p2[] + * + * \return void + */ +void FDKcalcCorrelationVec(FIXP_DBL *const z, const FIXP_DBL *const pr12, + const FIXP_DBL *const p1, const FIXP_DBL *const p2, + const INT n); + +/** + * \brief Vector function : Calculate coherence + * + * Description : z[i] = sqrt( (p12r[i]*p12r[i] + + * p12i[i]*p12i[i]) / (p1[i]*p2[i]) ), i=0,...,n-1 + * + * \param FIXP_DBL z[] + * Output: vector of length n + * + * \param const FIXP_DBL p12r[] + * Input: vector of the length n + * + * \param const FIXP_DBL p12i[] + * Input: vector of the length n + * + * \param const FIXP_DBL p1[] + * Input: vector of the length n + * + * \param const FIXP_DBL p2[] + * Input: vector of the length n + * + * \param int scaleP12[] + * Input: scalefactor of p12r and p12i + * + * \param int scaleP + * Input: scalefactor of p1 and p2 + * + * \param int n + * Input: length of vector p12r[], p12i[], p1[] and p2[] + * + * \return void + */ +void calcCoherenceVec(FIXP_DBL *const z, const FIXP_DBL *const p12r, + const FIXP_DBL *const p12i, const FIXP_DBL *const p1, + const FIXP_DBL *const p2, const INT scaleP12, + const INT scaleP, const INT n); + +/** + * \brief Vector function : Z[j][i] = a[pb] * X[j][i] + b[pb] * + * Y[j][i], j=0,...,nHybridBands-1; i=startTimeSlot,...,nTimeSlots-1; + * pb=0,...,nParameterBands-1 + * + * Description : re{Z[j][i]} = a[pb] * re{X[j][i]} + b[pb] * + * re{Y[j][i]}, j=0,...,nHybridBands-1; i=startTimeSlot,...,nTimeSlots-1; + * pb=0,...,nParameterBands-1 im{Z[j][i]} = a[pb] * im{X[j][i]} + b[pb] * + * im{Y[j][i]}, j=0,...,nHybridBands-1; + * i=startTimeSlot,...,nTimeSlots-1; pb=0,...,nParameterBands-1 + * + * It is allowed to overlay X[] or Y[] with Z[]. The scalefactor + * of channel 1 is updated with the common scalefactor of channel 1 and + * channel 2. + * + * \param FIXP_DPK **Z + * Output: vector of the length nHybridBands*nTimeSlots + * + * \param const FIXP_DBL *a + * Input: vector of length nParameterBands + * + * \param const FIXP_DPK **X + * Input: vector of the length nHybridBands*nTimeSlots + * + * \param const FIXP_DBL *b + * Input: vector of length nParameterBands + * + * \param const FIXP_DPK **Y + * Input: vector of the length nHybridBands*nTimeSlots + * + * \param int scale + * Input: scale of vector a and b + * + * \param int *scaleCh1 + * Input: scale of ch1 + * + * \param int scaleCh2 + * Input: scale of ch2 + * + * \param UCHAR *pParameterBand2HybridBandOffset + * Input: vector of length nParameterBands + * + * \param int nTimeSlots + * Input: number of time slots + * + * \param int startTimeSlot + * Input: start time slot + * + * \return void + */ +void addWeightedCplxVec(FIXP_DPK *const *const Z, const FIXP_DBL *const a, + const FIXP_DPK *const *const X, const FIXP_DBL *const b, + const FIXP_DPK *const *const Y, const INT scale, + INT *const scaleCh1, const INT scaleCh2, + const UCHAR *const pParameterBand2HybridBandOffset, + const INT nParameterBands, const INT nTimeSlots, + const INT startTimeSlot); + +/** + * \brief Vector function : Calculate the headroom of a complex vector + * in a parameter band grid + * + * \param FIXP_DPK **x + * Input: pointer to complex input vector + * + * \param UCHAR *pParameterBand2HybridBandOffset + * Input: pointer to hybrid band offsets + * + * \param int *outScaleFactor + * Input: pointer to ouput scalefactor + * + * \param int startTimeSlot + * Input: start time slot + * + * \param int nTimeSlots + * Input: number of time slot + * + * \param int nParamBands + * Input: number of parameter bands + * + * \return void + */ +void FDKcalcPbScaleFactor(const FIXP_DPK *const *const x, + const UCHAR *const pParameterBand2HybridBandOffset, + INT *const outScaleFactor, const INT startTimeSlot, + const INT nTimeSlots, const INT nParamBands); + +/** + * \brief Vector function : Calculate the common headroom of two + * sparate vectors + * + * \param FIXP_DBL *x + * Input: pointer to first input vector + * + * \param FIXP_DBL *y + * Input: pointer to second input vector + * + * \param int n + * Input: number of samples + * + * \return int headromm in bits + */ +INT FDKcalcScaleFactor(const FIXP_DBL *const x, const FIXP_DBL *const y, + const INT n); + +/** + * \brief Vector function : Calculate the headroom of a complex vector + * + * \param FIXP_DPK *x + * Input: pointer to complex input vector + * + * \param INT startBand + * Input: start band + * + * \param INT bands + * Input: number of bands + * + * \return int headromm in bits + */ +INT FDKcalcScaleFactorDPK(const FIXP_DPK *RESTRICT x, const INT startBand, + const INT bands); + +/* Function / Class Definition ***********************************************/ +template <class T> +inline void FDKmemcpy_flex(T *const dst, const INT dstStride, + const T *const src, const INT srcStride, + const INT nSamples) { + int i; + + for (i = 0; i < nSamples; i++) { + dst[i * dstStride] = src[i * srcStride]; + } +} + +template <class T> +inline void FDKmemset_flex(T *const x, const T c, const INT nSamples) { + int i; + + for (i = 0; i < nSamples; i++) { + x[i] = c; + } +} + +#endif /* SACENC_VECTORFUNCTIONS_H */ |