mirror of https://github.com/mstorsjo/fdk-aac.git
452 lines
16 KiB
C++
452 lines
16 KiB
C++
|
|
/* -----------------------------------------------------------------------------------------------------------
|
|
Software License for The Fraunhofer FDK AAC Codec Library for Android
|
|
|
|
© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
|
|
All rights reserved.
|
|
|
|
1. INTRODUCTION
|
|
The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
|
|
the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
|
|
This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
|
|
|
|
AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
|
|
audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
|
|
independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
|
|
of the MPEG specifications.
|
|
|
|
Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
|
|
may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
|
|
individually for the purpose of encoding or decoding bit streams in products that are compliant with
|
|
the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
|
|
these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
|
|
software may already be covered under those patent licenses when it is used for those licensed purposes only.
|
|
|
|
Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
|
|
are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
|
|
applications information and documentation.
|
|
|
|
2. COPYRIGHT LICENSE
|
|
|
|
Redistribution and use in source and binary forms, with or without modification, are permitted without
|
|
payment of copyright license fees provided that you satisfy the following conditions:
|
|
|
|
You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
|
|
your modifications thereto in source code form.
|
|
|
|
You must retain the complete text of this software license in the documentation and/or other materials
|
|
provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
|
|
You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
|
|
modifications thereto to recipients of copies in binary form.
|
|
|
|
The name of Fraunhofer may not be used to endorse or promote products derived from this library without
|
|
prior written permission.
|
|
|
|
You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
|
|
software or your modifications thereto.
|
|
|
|
Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
|
|
and the date of any change. For modified versions of the FDK AAC Codec, the term
|
|
"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
|
|
"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
|
|
|
|
3. NO PATENT LICENSE
|
|
|
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
|
|
ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
|
|
respect to this software.
|
|
|
|
You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
|
|
by appropriate patent licenses.
|
|
|
|
4. DISCLAIMER
|
|
|
|
This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
|
|
"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
|
|
of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
|
|
including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
|
|
or business interruption, however caused and on any theory of liability, whether in contract, strict
|
|
liability, or tort (including negligence), arising in any way out of the use of this software, even if
|
|
advised of the possibility of such damage.
|
|
|
|
5. CONTACT INFORMATION
|
|
|
|
Fraunhofer Institute for Integrated Circuits IIS
|
|
Attention: Audio and Multimedia Departments - FDK AAC LL
|
|
Am Wolfsmantel 33
|
|
91058 Erlangen, Germany
|
|
|
|
www.iis.fraunhofer.de/amm
|
|
amm-info@iis.fraunhofer.de
|
|
----------------------------------------------------------------------------------------------------------- */
|
|
|
|
/***************************** MPEG-4 AAC Decoder **************************
|
|
|
|
Author(s): Josef Hoepfl
|
|
Description:
|
|
|
|
******************************************************************************/
|
|
|
|
#include "channel.h"
|
|
#include "aacdecoder.h"
|
|
#include "block.h"
|
|
#include "aacdec_tns.h"
|
|
#include "FDK_bitstream.h"
|
|
#include "FDK_tools_rom.h"
|
|
|
|
#include "conceal.h"
|
|
|
|
#include "rvlc.h"
|
|
|
|
#include "aacdec_hcr.h"
|
|
|
|
|
|
static
|
|
void MapMidSideMaskToPnsCorrelation (CAacDecoderChannelInfo *pAacDecoderChannelInfo[2])
|
|
{
|
|
int group;
|
|
|
|
for (group = 0 ; group < pAacDecoderChannelInfo[L]->icsInfo.WindowGroups; group++) {
|
|
UCHAR groupMask = 1 << group;
|
|
|
|
for (UCHAR band = 0 ; band < pAacDecoderChannelInfo[L]->icsInfo.MaxSfBands; band++) {
|
|
if (pAacDecoderChannelInfo[L]->pComData->jointStereoData.MsUsed[band] & groupMask) { /* channels are correlated */
|
|
CPns_SetCorrelation(&pAacDecoderChannelInfo[L]->data.aac.PnsData, group, band, 0);
|
|
|
|
if (CPns_IsPnsUsed(&pAacDecoderChannelInfo[L]->data.aac.PnsData, group, band) &&
|
|
CPns_IsPnsUsed(&pAacDecoderChannelInfo[R]->data.aac.PnsData, group, band))
|
|
pAacDecoderChannelInfo[L]->pComData->jointStereoData.MsUsed[band] ^= groupMask; /* clear the groupMask-bit */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief Decode channel pair element
|
|
|
|
The function decodes a channel pair element.
|
|
|
|
\return none
|
|
*/
|
|
void CChannelElement_Decode( CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], /*!< pointer to aac decoder channel info */
|
|
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2],
|
|
SamplingRateInfo *pSamplingRateInfo,
|
|
UINT flags,
|
|
int el_channels)
|
|
{
|
|
int ch, maybe_jstereo = 0;
|
|
|
|
maybe_jstereo = (el_channels > 1);
|
|
|
|
for (ch = 0; ch < el_channels; ch++) {
|
|
if ( pAacDecoderChannelInfo[ch]->renderMode == AACDEC_RENDER_IMDCT
|
|
|| pAacDecoderChannelInfo[ch]->renderMode == AACDEC_RENDER_ELDFB )
|
|
{
|
|
CBlock_InverseQuantizeSpectralData(pAacDecoderChannelInfo[ch], pSamplingRateInfo);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (maybe_jstereo) {
|
|
/* apply ms */
|
|
if (pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow) {
|
|
int maxSfBandsL = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[L]->icsInfo);
|
|
int maxSfBandsR = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[R]->icsInfo);
|
|
if (pAacDecoderChannelInfo[L]->data.aac.PnsData.PnsActive || pAacDecoderChannelInfo[R]->data.aac.PnsData.PnsActive) {
|
|
MapMidSideMaskToPnsCorrelation(pAacDecoderChannelInfo);
|
|
}
|
|
|
|
CJointStereo_ApplyMS(pAacDecoderChannelInfo,
|
|
GetScaleFactorBandOffsets(&pAacDecoderChannelInfo[L]->icsInfo, pSamplingRateInfo),
|
|
GetWindowGroupLengthTable(&pAacDecoderChannelInfo[L]->icsInfo),
|
|
GetWindowGroups(&pAacDecoderChannelInfo[L]->icsInfo),
|
|
maxSfBandsL,
|
|
maxSfBandsR);
|
|
}
|
|
|
|
/* apply intensity stereo */ /* modifies pAacDecoderChannelInfo[]->aSpecSfb */
|
|
CJointStereo_ApplyIS(pAacDecoderChannelInfo,
|
|
GetScaleFactorBandOffsets(&pAacDecoderChannelInfo[L]->icsInfo, pSamplingRateInfo),
|
|
GetWindowGroupLengthTable(&pAacDecoderChannelInfo[L]->icsInfo),
|
|
GetWindowGroups(&pAacDecoderChannelInfo[L]->icsInfo),
|
|
GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[L]->icsInfo),
|
|
pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow ? 1 : 0);
|
|
|
|
}
|
|
|
|
for (ch = 0; ch < el_channels; ch++)
|
|
{
|
|
{
|
|
/* write pAacDecoderChannelInfo[ch]->specScale */
|
|
CBlock_ScaleSpectralData(pAacDecoderChannelInfo[ch], pSamplingRateInfo);
|
|
|
|
ApplyTools (pAacDecoderChannelInfo, pSamplingRateInfo, flags, ch);
|
|
}
|
|
|
|
}
|
|
|
|
CRvlc_ElementCheck(
|
|
pAacDecoderChannelInfo,
|
|
pAacDecoderStaticChannelInfo,
|
|
flags,
|
|
el_channels
|
|
);
|
|
}
|
|
|
|
void CChannel_CodebookTableInit(CAacDecoderChannelInfo *pAacDecoderChannelInfo)
|
|
{
|
|
int b, w, maxBands, maxWindows;
|
|
int maxSfb = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
|
|
UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook;
|
|
|
|
if ( IsLongBlock(&pAacDecoderChannelInfo->icsInfo) ) {
|
|
maxBands = 64;
|
|
maxWindows = 1;
|
|
} else {
|
|
maxBands = 16;
|
|
maxWindows = 8;
|
|
}
|
|
|
|
for (w = 0; w<maxWindows; w++) {
|
|
for (b = 0; b < maxSfb; b++) {
|
|
pCodeBook[b] = ESCBOOK;
|
|
}
|
|
for (; b<maxBands; b++) {
|
|
pCodeBook[b] = ZERO_HCB;
|
|
}
|
|
pCodeBook += maxBands;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Arbitrary order bitstream parser
|
|
*/
|
|
|
|
AAC_DECODER_ERROR CChannelElement_Read(HANDLE_FDK_BITSTREAM hBs,
|
|
CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
|
|
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
|
|
const AUDIO_OBJECT_TYPE aot,
|
|
const SamplingRateInfo *pSamplingRateInfo,
|
|
const UINT flags,
|
|
const UINT frame_length,
|
|
const UCHAR numberOfChannels,
|
|
const SCHAR epConfig,
|
|
HANDLE_TRANSPORTDEC pTpDec
|
|
)
|
|
{
|
|
AAC_DECODER_ERROR error = AAC_DEC_OK;
|
|
const element_list_t *list;
|
|
int i, ch, decision_bit;
|
|
int crcReg1 = -1, crcReg2 = -1;
|
|
|
|
FDK_ASSERT( (numberOfChannels == 1) || (numberOfChannels == 2) );
|
|
|
|
/* Get channel element sequence table */
|
|
list = getBitstreamElementList(aot, epConfig, numberOfChannels, 0);
|
|
if (list == NULL) {
|
|
error = AAC_DEC_UNSUPPORTED_FORMAT;
|
|
goto bail;
|
|
}
|
|
|
|
CTns_Reset(&pAacDecoderChannelInfo[0]->pDynData->TnsData);
|
|
if (numberOfChannels == 2) {
|
|
CTns_Reset(&pAacDecoderChannelInfo[1]->pDynData->TnsData);
|
|
}
|
|
|
|
if (flags & (AC_ELD|AC_SCALABLE)) {
|
|
pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow = 1;
|
|
if (numberOfChannels == 2) {
|
|
pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow;
|
|
}
|
|
if (numberOfChannels == 2) {
|
|
pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow;
|
|
}
|
|
}
|
|
|
|
/* Iterate through sequence table */
|
|
i = 0;
|
|
ch = 0;
|
|
decision_bit = 0;
|
|
do {
|
|
switch (list->id[i]) {
|
|
case element_instance_tag:
|
|
pAacDecoderChannelInfo[0]->ElementInstanceTag = FDKreadBits(hBs, 4);
|
|
if (numberOfChannels == 2) {
|
|
pAacDecoderChannelInfo[1]->ElementInstanceTag = pAacDecoderChannelInfo[0]->ElementInstanceTag;
|
|
}
|
|
break;
|
|
case common_window:
|
|
decision_bit = pAacDecoderChannelInfo[ch]->pDynData->RawDataInfo.CommonWindow = FDKreadBits(hBs, 1);
|
|
if (numberOfChannels == 2) {
|
|
pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow;
|
|
}
|
|
break;
|
|
case ics_info:
|
|
/* Read individual channel info */
|
|
error = IcsRead( hBs,
|
|
&pAacDecoderChannelInfo[ch]->icsInfo,
|
|
pSamplingRateInfo,
|
|
flags );
|
|
|
|
if (numberOfChannels == 2 && pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow) {
|
|
pAacDecoderChannelInfo[1]->icsInfo = pAacDecoderChannelInfo[0]->icsInfo;
|
|
}
|
|
break;
|
|
|
|
|
|
case ltp_data_present:
|
|
if (FDKreadBits(hBs, 1) != 0) {
|
|
error = AAC_DEC_UNSUPPORTED_PREDICTION;
|
|
}
|
|
break;
|
|
|
|
case ms:
|
|
if ( CJointStereo_Read(
|
|
hBs,
|
|
&pAacDecoderChannelInfo[0]->pComData->jointStereoData,
|
|
GetWindowGroups(&pAacDecoderChannelInfo[0]->icsInfo),
|
|
GetScaleMaxFactorBandsTransmitted(&pAacDecoderChannelInfo[0]->icsInfo,
|
|
&pAacDecoderChannelInfo[1]->icsInfo),
|
|
flags) )
|
|
{
|
|
error = AAC_DEC_PARSE_ERROR;
|
|
}
|
|
break;
|
|
|
|
case global_gain:
|
|
pAacDecoderChannelInfo[ch]->pDynData->RawDataInfo.GlobalGain = (UCHAR) FDKreadBits(hBs,8);
|
|
break;
|
|
|
|
case section_data:
|
|
error = CBlock_ReadSectionData( hBs,
|
|
pAacDecoderChannelInfo[ch],
|
|
pSamplingRateInfo,
|
|
flags );
|
|
break;
|
|
|
|
|
|
case scale_factor_data:
|
|
if (flags & AC_ER_RVLC) {
|
|
/* read RVLC data from bitstream (error sens. cat. 1) */
|
|
CRvlc_Read(pAacDecoderChannelInfo[ch], hBs);
|
|
}
|
|
else
|
|
{
|
|
error = CBlock_ReadScaleFactorData(pAacDecoderChannelInfo[ch], hBs, flags);
|
|
}
|
|
break;
|
|
|
|
case pulse:
|
|
if ( CPulseData_Read( hBs,
|
|
&pAacDecoderChannelInfo[ch]->pDynData->specificTo.aac.PulseData,
|
|
pSamplingRateInfo->ScaleFactorBands_Long, /* pulse data is only allowed to be present in long blocks! */
|
|
(void*)&pAacDecoderChannelInfo[ch]->icsInfo,
|
|
frame_length
|
|
) != 0 )
|
|
{
|
|
error = AAC_DEC_DECODE_FRAME_ERROR;
|
|
}
|
|
break;
|
|
case tns_data_present:
|
|
CTns_ReadDataPresentFlag(hBs, &pAacDecoderChannelInfo[ch]->pDynData->TnsData);
|
|
break;
|
|
case tns_data:
|
|
/* tns_data_present is checked inside CTns_Read(). */
|
|
error = CTns_Read(hBs, &pAacDecoderChannelInfo[ch]->pDynData->TnsData, &pAacDecoderChannelInfo[ch]->icsInfo, flags);
|
|
break;
|
|
|
|
case gain_control_data:
|
|
break;
|
|
|
|
case gain_control_data_present:
|
|
if (FDKreadBits(hBs, 1)) {
|
|
error = AAC_DEC_UNSUPPORTED_GAIN_CONTROL_DATA;
|
|
}
|
|
break;
|
|
|
|
case esc2_rvlc:
|
|
if (flags & AC_ER_RVLC) {
|
|
CRvlc_Decode(
|
|
pAacDecoderChannelInfo[ch],
|
|
pAacDecoderStaticChannelInfo[ch],
|
|
hBs
|
|
);
|
|
}
|
|
break;
|
|
|
|
case esc1_hcr:
|
|
if (flags & AC_ER_HCR) {
|
|
CHcr_Read(hBs, pAacDecoderChannelInfo[ch] );
|
|
}
|
|
break;
|
|
|
|
case spectral_data:
|
|
error = CBlock_ReadSpectralData( hBs,
|
|
pAacDecoderChannelInfo[ch],
|
|
pSamplingRateInfo,
|
|
flags );
|
|
if (flags & AC_ELD) {
|
|
pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_ELDFB;
|
|
} else {
|
|
pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_IMDCT;
|
|
}
|
|
break;
|
|
|
|
|
|
/* CRC handling */
|
|
case adtscrc_start_reg1:
|
|
if (pTpDec != NULL) {
|
|
crcReg1 = transportDec_CrcStartReg(pTpDec, 192);
|
|
}
|
|
break;
|
|
case adtscrc_start_reg2:
|
|
if (pTpDec != NULL) {
|
|
crcReg2 = transportDec_CrcStartReg(pTpDec, 128);
|
|
}
|
|
break;
|
|
case adtscrc_end_reg1:
|
|
case drmcrc_end_reg:
|
|
if (pTpDec != NULL) {
|
|
transportDec_CrcEndReg(pTpDec, crcReg1);
|
|
}
|
|
break;
|
|
case adtscrc_end_reg2:
|
|
if (pTpDec != NULL) {
|
|
transportDec_CrcEndReg(pTpDec, crcReg2);
|
|
}
|
|
break;
|
|
case drmcrc_start_reg:
|
|
if (pTpDec != NULL) {
|
|
crcReg1 = transportDec_CrcStartReg(pTpDec, 0);
|
|
}
|
|
break;
|
|
|
|
/* Non data cases */
|
|
case next_channel:
|
|
ch = (ch + 1) % numberOfChannels;
|
|
break;
|
|
case link_sequence:
|
|
list = list->next[decision_bit];
|
|
i=-1;
|
|
break;
|
|
|
|
default:
|
|
error = AAC_DEC_UNSUPPORTED_FORMAT;
|
|
break;
|
|
}
|
|
|
|
if (error != AAC_DEC_OK) {
|
|
goto bail;
|
|
}
|
|
|
|
i++;
|
|
|
|
} while (list->id[i] != end_of_sequence);
|
|
|
|
bail:
|
|
return error;
|
|
}
|