summaryrefslogtreecommitdiffstats
path: root/libAACdec
diff options
context:
space:
mode:
Diffstat (limited to 'libAACdec')
-rw-r--r--libAACdec/include/aacdecoder_lib.h73
-rw-r--r--libAACdec/src/aac_ram.cpp8
-rw-r--r--libAACdec/src/aac_rom.cpp50
-rw-r--r--libAACdec/src/aac_rom.h9
-rw-r--r--libAACdec/src/aacdec_drc.cpp72
-rw-r--r--libAACdec/src/aacdec_drc.h5
-rw-r--r--libAACdec/src/aacdec_drc_types.h1
-rw-r--r--libAACdec/src/aacdecoder.cpp140
-rw-r--r--libAACdec/src/aacdecoder.h24
-rw-r--r--libAACdec/src/aacdecoder_lib.cpp146
-rw-r--r--libAACdec/src/conceal.cpp15
11 files changed, 408 insertions, 135 deletions
diff --git a/libAACdec/include/aacdecoder_lib.h b/libAACdec/include/aacdecoder_lib.h
index 60efe8d..a281ab9 100644
--- a/libAACdec/include/aacdecoder_lib.h
+++ b/libAACdec/include/aacdecoder_lib.h
@@ -430,21 +430,68 @@ typedef enum {
typedef enum
{
AAC_PCM_OUTPUT_INTERLEAVED = 0x0000, /*!< PCM output mode (1: interleaved (default); 0: not interleaved). */
- AAC_PCM_OUTPUT_CHANNELS = 0x0001, /*!< Number of PCM output channels (if different from encoded audio channels, downmixing or
- upmixing is applied). \n
- -1: Disable up-/downmixing. The decoder output contains the same number of channels as the
- encoded bitstream. \n
- 1: The decoder performs a mono matrix mix-down if the encoded audio channels are greater
- than one. Thus it ouputs always exact one channel. \n
- 2: The decoder performs a stereo matrix mix-down if the encoded audio channels are greater
- than two. If the encoded audio channels are smaller than two the decoder duplicates the
- output. Thus it ouputs always exact two channels. \n */
- AAC_PCM_DUAL_CHANNEL_OUTPUT_MODE = 0x0002, /*!< Defines how the decoder processes two channel signals:
- 0: Leave both signals as they are (default).
- 1: Create a dual mono output signal from channel 1.
- 2: Create a dual mono output signal from channel 2.
+ AAC_PCM_DUAL_CHANNEL_OUTPUT_MODE = 0x0002, /*!< Defines how the decoder processes two channel signals: \n
+ 0: Leave both signals as they are (default). \n
+ 1: Create a dual mono output signal from channel 1. \n
+ 2: Create a dual mono output signal from channel 2. \n
3: Create a dual mono output signal by mixing both channels (L' = R' = 0.5*Ch1 + 0.5*Ch2). */
AAC_PCM_OUTPUT_CHANNEL_MAPPING = 0x0003, /*!< Output buffer channel ordering. 0: MPEG PCE style order, 1: WAV file channel order (default). */
+ AAC_PCM_LIMITER_ENABLE = 0x0004, /*!< Enable signal level limiting. \n
+ -1: Auto-config. Enable limiter for all non-lowdelay configurations by default. \n
+ 0: Disable limiter in general. \n
+ 1: Enable limiter always.
+ It is recommended to call the decoder with a AACDEC_CLRHIST flag to reset all states when
+ the limiter switch is changed explicitly. */
+ AAC_PCM_LIMITER_ATTACK_TIME = 0x0005, /*!< Signal level limiting attack time in ms.
+ Default confguration is 15 ms. Adjustable range from 1 ms to 15 ms. */
+ AAC_PCM_LIMITER_RELEAS_TIME = 0x0006, /*!< Signal level limiting release time in ms.
+ Default configuration is 50 ms. Adjustable time must be larger than 0 ms. */
+ AAC_PCM_MIN_OUTPUT_CHANNELS = 0x0011, /*!< Minimum number of PCM output channels. If higher than the number of encoded audio channels,
+ a simple channel extension is applied. \n
+ -1, 0: Disable channel extenstion feature. The decoder output contains the same number of
+ channels as the encoded bitstream. \n
+ 1: This value is currently needed only together with the mix-down feature. See
+ ::AAC_PCM_MAX_OUTPUT_CHANNELS and note 2 below. \n
+ 2: Encoded mono signals will be duplicated to achieve a 2/0/0.0 channel output
+ configuration. \n
+ 6: The decoder trys to reorder encoded signals with less than six channels to achieve
+ a 3/0/2.1 channel output signal. Missing channels will be filled with a zero signal.
+ If reordering is not possible the empty channels will simply be appended. Only
+ available if instance is configured to support multichannel output. \n
+ 8: The decoder trys to reorder encoded signals with less than eight channels to
+ achieve a 3/0/4.1 channel output signal. Missing channels will be filled with a
+ zero signal. If reordering is not possible the empty channels will simply be
+ appended. Only available if instance is configured to support multichannel output.\n
+ NOTE: \n
+ 1. The channel signalling (CStreamInfo::pChannelType and CStreamInfo::pChannelIndices)
+ will not be modified. Added empty channels will be signalled with channel type
+ AUDIO_CHANNEL_TYPE::ACT_NONE. \n
+ 2. If the parameter value is greater than that of ::AAC_PCM_MAX_OUTPUT_CHANNELS both will
+ be set to the same value. \n
+ 3. This parameter does not affect MPEG Surround processing. */
+ AAC_PCM_MAX_OUTPUT_CHANNELS = 0x0012, /*!< Maximum number of PCM output channels. If lower than the number of encoded audio channels,
+ downmixing is applied accordingly. If dedicated metadata is available in the stream it
+ will be used to achieve better mixing results. \n
+ -1, 0: Disable downmixing feature. The decoder output contains the same number of channels
+ as the encoded bitstream. \n
+ 1: All encoded audio configurations with more than one channel will be mixed down to
+ one mono output signal. \n
+ 2: The decoder performs a stereo mix-down if the number encoded audio channels is
+ greater than two. \n
+ 6: If the number of encoded audio channels is greater than six the decoder performs a
+ mix-down to meet the target output configuration of 3/0/2.1 channels. Only
+ available if instance is configured to support multichannel output. \n
+ 8: This value is currently needed only together with the channel extension feature.
+ See ::AAC_PCM_MIN_OUTPUT_CHANNELS and note 2 below. Only available if instance is
+ configured to support multichannel output. \n
+ NOTE: \n
+ 1. Down-mixing of any seven or eight channel configuration not defined in ISO/IEC 14496-3
+ PDAM 4 is not supported by this software version. \n
+ 2. If the parameter value is greater than zero but smaller than ::AAC_PCM_MIN_OUTPUT_CHANNELS
+ both will be set to same value. \n
+ 3. The operating mode of the MPEG Surround module will be set accordingly. \n
+ 4. Setting this param with any value will disable the binaural processing of the MPEG
+ Surround module (::AAC_MPEGS_BINAURAL_ENABLE=0). */
AAC_CONCEAL_METHOD = 0x0100, /*!< Error concealment: Processing method. \n
0: Spectral muting. \n
diff --git a/libAACdec/src/aac_ram.cpp b/libAACdec/src/aac_ram.cpp
index a38f57c..1ff289b 100644
--- a/libAACdec/src/aac_ram.cpp
+++ b/libAACdec/src/aac_ram.cpp
@@ -108,15 +108,15 @@ C_ALLOC_MEM(AacDecoder, AAC_DECODER_INSTANCE, 1)
/*! The structure CAacDecoderStaticChannelInfo contains the static sideinfo which is needed
for the decoding of one aac channel. <br>
Dimension: #AacDecoderChannels */
-C_ALLOC_MEM2(AacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo, 1, (6))
+C_ALLOC_MEM2(AacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo, 1, (8))
/*! The structure CAacDecoderChannelInfo contains the dynamic sideinfo which is needed
for the decoding of one aac channel. <br>
Dimension: #AacDecoderChannels */
-C_ALLOC_MEM2(AacDecoderChannelInfo, CAacDecoderChannelInfo, 1, (6))
+C_AALLOC_MEM2(AacDecoderChannelInfo, CAacDecoderChannelInfo, 1, (8))
/*! Overlap buffer */
-C_ALLOC_MEM2(OverlapBuffer, FIXP_DBL, OverlapBufferSize, (6))
+C_ALLOC_MEM2(OverlapBuffer, FIXP_DBL, OverlapBufferSize, (8))
C_ALLOC_MEM(DrcInfo, CDrcInfo, 1)
@@ -128,7 +128,7 @@ C_ALLOC_MEM(DrcInfo, CDrcInfo, 1)
Dynamic memory areas, might be reused in other algorithm sections,
e.g. the sbr decoder
*/
-C_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL, ((6)*1024), SECT_DATA_L2, WORKBUFFER2_TAG)
+C_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL, ((8)*1024), SECT_DATA_L2, WORKBUFFER2_TAG)
C_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1, 1, SECT_DATA_L1, WORKBUFFER1_TAG)
diff --git a/libAACdec/src/aac_rom.cpp b/libAACdec/src/aac_rom.cpp
index fa04c42..607cb3b 100644
--- a/libAACdec/src/aac_rom.cpp
+++ b/libAACdec/src/aac_rom.cpp
@@ -1777,42 +1777,62 @@ const FIXP_TCC FDKaacDec_tnsCoeff4 [16] =
};
/* MPEG like mapping (no change). */
-const UCHAR channelMappingTablePassthrough[8][8] =
+const UCHAR channelMappingTablePassthrough[15][8] =
{
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* fallback */
{ 0, 1,255,255,255,255,255,255}, /* mono / PS */
{ 0, 1,255,255,255,255,255,255}, /* stereo */
{ 0, 1, 2,255,255,255,255,255}, /* 3ch */
{ 0, 1, 2, 3,255,255,255,255}, /* 4ch */
{ 0, 1, 2, 3, 4,255,255,255}, /* 5ch */
{ 0, 1, 2, 3, 4, 5,255,255}, /* 5.1ch */
- { 0, 1, 2, 3, 4, 5, 6, 7}, /* 7ch */
- { 0, 1, 2, 3, 4, 5, 6, 7} /* 7.1ch */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* 7.1 front */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
+ { 0, 1, 2, 3, 4, 5, 6,255}, /* 6.1ch */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* 7.1 rear */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
+ { 0, 1, 2, 3, 4, 5, 6, 7} /* 7.1 top */
};
/* WAV file like mapping (from MPEG mapping). */
-const UCHAR channelMappingTableWAV[8][8] =
+const UCHAR channelMappingTableWAV[15][8] =
{
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* fallback */
{ 0, 1,255,255,255,255,255,255}, /* mono / PS */
{ 0, 1,255,255,255,255,255,255}, /* stereo */
{ 2, 0, 1,255,255,255,255,255}, /* 3ch */
{ 2, 0, 1, 3,255,255,255,255}, /* 4ch */
{ 2, 0, 1, 3, 4,255,255,255}, /* 5ch */
{ 2, 0, 1, 4, 5, 3,255,255}, /* 5.1ch */
- { 0, 1, 2, 3, 4, 5, 6, 7}, /* 7ch */
- { 2, 0, 1, 6, 7, 4, 5, 3} /* 7.1ch */
+ { 2, 6, 7, 0, 1, 4, 5, 3}, /* 7.1 front */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
+ { 2, 0, 1, 4, 5, 6, 3,255}, /* 6.1ch */
+ { 2, 0, 1, 6, 7, 4, 5, 3}, /* 7.1 rear */
+ { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */
+ { 2, 0, 1, 4, 5, 3, 6, 7} /* 7.1 top */
};
/* Lookup tables for elements in ER bitstream */
-const MP4_ELEMENT_ID elementsTab[8][7] =
+const MP4_ELEMENT_ID elementsTab[15][7] =
{
- {ID_SCE, ID_EXT, ID_END, ID_NONE, ID_NONE,ID_NONE,ID_NONE }, /* 1 channel */
- {ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE,ID_NONE,ID_NONE } /* 2 channels */
- ,
- {ID_SCE, ID_CPE, ID_EXT, ID_END, ID_NONE,ID_NONE,ID_NONE }, /* 3 channels */
- {ID_SCE, ID_CPE, ID_SCE, ID_EXT, ID_END, ID_NONE,ID_NONE }, /* 4 channels */
- {ID_SCE, ID_CPE, ID_CPE, ID_EXT, ID_END, ID_NONE,ID_NONE }, /* 5 channels */
- {ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END, ID_NONE }, /* 6 channels */
- {ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END} /* 8 channels */
+ /* 1 */ { ID_SCE, ID_EXT, ID_END, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* 1 channel */
+ /* 2 */ { ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE, ID_NONE, ID_NONE } /* 2 channels */
+ /* 3 */ ,{ ID_SCE, ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE, ID_NONE }, /* 3 channels */
+ /* 4 */ { ID_SCE, ID_CPE, ID_SCE, ID_EXT, ID_END, ID_NONE, ID_NONE }, /* 4 channels */
+ /* 5 */ { ID_SCE, ID_CPE, ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE }, /* 5 channels */
+ /* 6 */ { ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END, ID_NONE } /* 6 channels */
+ /* 7 */ ,{ ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END }, /* 8 channels */
+ /* 8 */ { ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* reserved */
+ /* 9 */ { ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* reserved */
+ /* 10 */ { ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* reserved */
+ /* 11 */ { ID_SCE, ID_CPE, ID_CPE, ID_SCE, ID_LFE, ID_EXT, ID_END }, /* 7 channels */
+ /* 12 */ { ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END }, /* 8 channels */
+ /* 13 */ { ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* reserved */
+ /* 14 */ { ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_CPE, ID_EXT, ID_END } /* 8 channels */
};
/*! Random sign bit used for concealment
diff --git a/libAACdec/src/aac_rom.h b/libAACdec/src/aac_rom.h
index 536d184..f314a2d 100644
--- a/libAACdec/src/aac_rom.h
+++ b/libAACdec/src/aac_rom.h
@@ -177,11 +177,12 @@ extern const USHORT randomSign[AAC_NF_NO_RANDOM_VAL/16];
extern const FIXP_DBL pow2_div24minus1[47];
extern const int offsetTab[2][16];
-/* Channel mapping indices for time domain I/O. First dimension is channel count-1. */
-extern const UCHAR channelMappingTablePassthrough[8][8];
-extern const UCHAR channelMappingTableWAV[8][8];
+/* Channel mapping indices for time domain I/O.
+ The first dimension is the channel configuration index. */
+extern const UCHAR channelMappingTablePassthrough[15][8];
+extern const UCHAR channelMappingTableWAV[15][8];
/* Lookup tables for elements in ER bitstream */
-extern const MP4_ELEMENT_ID elementsTab[8][7];
+extern const MP4_ELEMENT_ID elementsTab[15][7];
#endif /* #ifndef AAC_ROM_H */
diff --git a/libAACdec/src/aacdec_drc.cpp b/libAACdec/src/aacdec_drc.cpp
index 2666454..ba7419d 100644
--- a/libAACdec/src/aacdec_drc.cpp
+++ b/libAACdec/src/aacdec_drc.cpp
@@ -130,7 +130,6 @@ void aacDecoder_drcInit (
/* init control fields */
self->enable = 0;
self->numThreads = 0;
- self->digitalNorm = 0;
/* init params */
pParams = &self->params;
@@ -139,8 +138,9 @@ void aacDecoder_drcInit (
pParams->usrCut = FL2FXCONST_DBL(0.0f);
pParams->boost = FL2FXCONST_DBL(0.0f);
pParams->usrBoost = FL2FXCONST_DBL(0.0f);
- pParams->targetRefLevel = AACDEC_DRC_DEFAULT_REF_LEVEL;
+ pParams->targetRefLevel = -1;
pParams->expiryFrame = AACDEC_DRC_DFLT_EXPIRY_FRAMES;
+ pParams->applyDigitalNorm = 0;
pParams->applyHeavyCompression = 0;
/* initial program ref level = target ref level */
@@ -222,11 +222,12 @@ AAC_DECODER_ERROR aacDecoder_drcSetParam (
return AAC_DEC_INVALID_HANDLE;
}
if (value < 0) {
- self->digitalNorm = 0;
+ self->params.applyDigitalNorm = 0;
+ self->params.targetRefLevel = -1;
}
else {
/* ref_level must be between 0 and MAX_REFERENCE_LEVEL, inclusive */
- self->digitalNorm = 1;
+ self->params.applyDigitalNorm = 1;
if (self->params.targetRefLevel != (SCHAR)value) {
self->params.targetRefLevel = (SCHAR)value;
self->progRefLevel = (SCHAR)value; /* Always set the program reference level equal to the
@@ -234,6 +235,16 @@ AAC_DECODER_ERROR aacDecoder_drcSetParam (
}
}
break;
+ case APPLY_NORMALIZATION:
+ if (value < 0 || value > 1) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ /* Store new parameter value */
+ self->params.applyDigitalNorm = (UCHAR)value;
+ break;
case APPLY_HEAVY_COMPRESSION:
if (value < 0 || value > 1) {
return AAC_DEC_SET_PARAM_FAIL;
@@ -278,7 +289,7 @@ AAC_DECODER_ERROR aacDecoder_drcSetParam (
self->enable = ( (self->params.boost > (FIXP_DBL)0)
|| (self->params.cut > (FIXP_DBL)0)
|| (self->params.applyHeavyCompression != 0)
- || (self->digitalNorm == 1) );
+ || (self->params.targetRefLevel >= 0) );
return ErrorStatus;
@@ -539,7 +550,7 @@ static int aacDecoder_drcReadCompression (
UINT payloadPosition )
{
int bitCnt = 0;
- int dmxLevelsPresent, compressionPresent;
+ int dmxLevelsPresent, extensionPresent, compressionPresent;
int coarseGrainTcPresent, fineGrainTcPresent;
/* Move to the beginning of the DRC payload field */
@@ -562,7 +573,8 @@ static int aacDecoder_drcReadCompression (
}
FDKreadBits(bs, 2); /* dolby_surround_mode */
FDKreadBits(bs, 2); /* presentation_mode */
- if (FDKreadBits(bs, 2) != 0) { /* reserved, set to 0 */
+ FDKreadBits(bs, 1); /* stereo_downmix_mode */
+ if (FDKreadBits(bs, 1) != 0) { /* reserved, set to 0 */
return 0;
}
@@ -571,9 +583,7 @@ static int aacDecoder_drcReadCompression (
return 0;
}
dmxLevelsPresent = FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */
- if (FDKreadBits(bs, 1) != 0) { /* reserved, set to 0 */
- return 0;
- }
+ extensionPresent = FDKreadBits(bs, 1); /* ancillary_data_extension_status; */
compressionPresent = FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */
coarseGrainTcPresent = FDKreadBits(bs, 1); /* coarse_grain_timecode_status */
fineGrainTcPresent = FDKreadBits(bs, 1); /* fine_grain_timecode_status */
@@ -631,6 +641,19 @@ static int aacDecoder_drcReadCompression (
bitCnt += 16;
}
+ /* Read extension just to get the right amount of bits. */
+ if (extensionPresent) {
+ int extBits = 8;
+
+ FDKreadBits(bs, 1); /* reserved, set to 0 */
+ if (FDKreadBits(bs, 1)) extBits += 8; /* ext_downmixing_levels_status */
+ if (FDKreadBits(bs, 1)) extBits += 16; /* ext_downmixing_global_gains_status */
+ if (FDKreadBits(bs, 1)) extBits += 8; /* ext_downmixing_lfe_level_status */
+
+ FDKpushFor(bs, extBits - 4); /* skip the extension payload remainder. */
+ bitCnt += extBits;
+ }
+
return (bitCnt);
}
@@ -815,6 +838,7 @@ void aacDecoder_drcApply (
void *pSbrDec,
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
CDrcChannelData *pDrcChData,
+ FIXP_DBL *extGain,
int ch, /* needed only for SBR */
int aacFrameSize,
int bSbrPresent )
@@ -826,8 +850,8 @@ void aacDecoder_drcApply (
FIXP_DBL max_mantissa;
INT max_exponent;
- FIXP_DBL norm_mantissa = FL2FXCONST_DBL(0.0f);
- INT norm_exponent = 0;
+ FIXP_DBL norm_mantissa = FL2FXCONST_DBL(0.5f);
+ INT norm_exponent = 1;
FIXP_DBL fact_mantissa[MAX_DRC_BANDS];
INT fact_exponent[MAX_DRC_BANDS];
@@ -849,6 +873,15 @@ void aacDecoder_drcApply (
if (!self->enable) {
sbrDecoder_drcDisable( (HANDLE_SBRDECODER)pSbrDec, ch );
+ if (extGain != NULL) {
+ INT gainScale = (INT)*extGain;
+ /* The gain scaling must be passed to the function in the buffer pointed on by extGain. */
+ if (gainScale >= 0 && gainScale <= DFRACT_BITS) {
+ *extGain = scaleValue(norm_mantissa, norm_exponent-gainScale);
+ } else {
+ FDK_ASSERT(0);
+ }
+ }
return;
}
@@ -864,7 +897,7 @@ void aacDecoder_drcApply (
reduced DAC SNR (if signal is attenuated) or clipping (if signal is
boosted) */
- if (self->digitalNorm == 1)
+ if (pParams->targetRefLevel >= 0)
{
/* 0.5^((targetRefLevel - progRefLevel)/24) */
norm_mantissa = fLdPow(
@@ -874,7 +907,18 @@ void aacDecoder_drcApply (
3,
&norm_exponent );
}
- else {
+ /* Always export the normalization gain (if possible). */
+ if (extGain != NULL) {
+ INT gainScale = (INT)*extGain;
+ /* The gain scaling must be passed to the function in the buffer pointed on by extGain. */
+ if (gainScale >= 0 && gainScale <= DFRACT_BITS) {
+ *extGain = scaleValue(norm_mantissa, norm_exponent-gainScale);
+ } else {
+ FDK_ASSERT(0);
+ }
+ }
+ if (self->params.applyDigitalNorm == 0) {
+ /* Reset normalization gain since this module must not apply it */
norm_mantissa = FL2FXCONST_DBL(0.5f);
norm_exponent = 1;
}
diff --git a/libAACdec/src/aacdec_drc.h b/libAACdec/src/aacdec_drc.h
index 2ebae2c..41aac69 100644
--- a/libAACdec/src/aacdec_drc.h
+++ b/libAACdec/src/aacdec_drc.h
@@ -98,7 +98,6 @@ amm-info@iis.fraunhofer.de
#include "channel.h"
#include "FDK_bitstream.h"
-#define AACDEC_DRC_DEFAULT_REF_LEVEL ( 108 ) /* -27 dB below full scale (typical for movies) */
#define AACDEC_DRC_DFLT_EXPIRY_FRAMES ( 50 ) /* Default DRC data expiry time in AAC frames */
/**
@@ -111,6 +110,7 @@ typedef enum
TARGET_REF_LEVEL,
DRC_BS_DELAY,
DRC_DATA_EXPIRY_FRAME,
+ APPLY_NORMALIZATION,
APPLY_HEAVY_COMPRESSION
} AACDEC_DRC_PARAM;
@@ -149,6 +149,8 @@ int aacDecoder_drcProlog (
* \param pSbrDec pointer to SBR decoder instance
* \param pAacDecoderChannelInfo AAC decoder channel instance to be processed
* \param pDrcDat DRC channel data
+ * \param extGain Pointer to a FIXP_DBL where a externally applyable gain will be stored into (independently on whether it will be apply internally or not).
+ * At function call the buffer must hold the scale (0 >= scale < DFRACT_BITS) to be applied on the gain value.
* \param ch channel index
* \param aacFrameSize AAC frame size
* \param bSbrPresent flag indicating that SBR is present, in which case DRC is handed over to the SBR instance pSbrDec
@@ -158,6 +160,7 @@ void aacDecoder_drcApply (
void *pSbrDec,
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
CDrcChannelData *pDrcDat,
+ FIXP_DBL *extGain,
int ch,
int aacFrameSize,
int bSbrPresent );
diff --git a/libAACdec/src/aacdec_drc_types.h b/libAACdec/src/aacdec_drc_types.h
index 1b5cd76..1f595b9 100644
--- a/libAACdec/src/aacdec_drc_types.h
+++ b/libAACdec/src/aacdec_drc_types.h
@@ -140,6 +140,7 @@ typedef struct
UINT expiryFrame;
SCHAR targetRefLevel;
UCHAR bsDelayEnable;
+ UCHAR applyDigitalNorm;
UCHAR applyHeavyCompression;
} CDrcParams;
diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp
index 3a2a561..18c9afa 100644
--- a/libAACdec/src/aacdecoder.cpp
+++ b/libAACdec/src/aacdecoder.cpp
@@ -338,17 +338,22 @@ AAC_DECODER_ERROR CAacDecoder_AncDataParse (
\return Error code
*/
static AAC_DECODER_ERROR CDataStreamElement_Read (
+ HANDLE_AACDECODER self,
HANDLE_FDK_BITSTREAM bs,
- CAncData *ancData,
- HANDLE_AAC_DRC hDrcInfo,
- HANDLE_TRANSPORTDEC pTp,
UCHAR *elementInstanceTag,
UINT alignmentAnchor )
{
+ HANDLE_TRANSPORTDEC pTp;
+ CAncData *ancData;
AAC_DECODER_ERROR error = AAC_DEC_OK;
- UINT dataStart;
+ UINT dataStart, dseBits;
int dataByteAlignFlag, count;
+ FDK_ASSERT(self != NULL);
+
+ ancData = &self->ancData;
+ pTp = self->hInput;
+
int crcReg = transportDec_CrcStartReg(pTp, 0);
/* Element Instance Tag */
@@ -361,6 +366,7 @@ static AAC_DECODER_ERROR CDataStreamElement_Read (
if (count == 255) {
count += FDKreadBits(bs,8); /* EscCount */
}
+ dseBits = count*8;
if (dataByteAlignFlag) {
FDKbyteAlign(bs, alignmentAnchor);
@@ -372,19 +378,29 @@ static AAC_DECODER_ERROR CDataStreamElement_Read (
transportDec_CrcEndReg(pTp, crcReg);
{
- INT readBits, dataBits = count<<3;
-
/* Move to the beginning of the data junk */
FDKpushBack(bs, dataStart-FDKgetValidBits(bs));
/* Read Anc data if available */
- readBits = aacDecoder_drcMarkPayload( hDrcInfo, bs, DVB_DRC_ANC_DATA );
+ aacDecoder_drcMarkPayload( self->hDrcInfo, bs, DVB_DRC_ANC_DATA );
+ }
+
+ {
+ PCMDMX_ERROR dmxErr = PCMDMX_OK;
- if (readBits != dataBits) {
- /* Move to the end again. */
- FDKpushBiDirectional(bs, FDKgetValidBits(bs)-dataStart+dataBits);
+ /* Move to the beginning of the data junk */
+ FDKpushBack(bs, dataStart-FDKgetValidBits(bs));
+
+ /* Read DMX meta-data */
+ dmxErr = pcmDmx_Parse (
+ self->hPcmUtils,
+ bs,
+ dseBits,
+ 0 /* not mpeg2 */ );
}
- }
+
+ /* Move to the very end of the element. */
+ FDKpushBiDirectional(bs, FDKgetValidBits(bs)-dataStart+dseBits);
return error;
}
@@ -774,7 +790,7 @@ LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self)
if (self == NULL)
return;
- for (ch=0; ch<(6); ch++) {
+ for (ch=0; ch<(8); ch++) {
if (self->pAacDecoderStaticChannelInfo[ch] != NULL) {
if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer != NULL) {
FreeOverlapBuffer (&self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer);
@@ -851,18 +867,19 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS
/* valid number of channels -> copy program config element (PCE) from ASC */
FDKmemcpy(&self->pce, &asc->m_progrConfigElement, sizeof(CProgramConfig));
/* Built element table */
- el = CProgramConfig_GetElementTable(&asc->m_progrConfigElement, self->elements, 7);
- for (; el<7; el++) {
+ el = CProgramConfig_GetElementTable(&asc->m_progrConfigElement, self->elements, (8), &self->chMapIndex);
+ for (; el<(8); el++) {
self->elements[el] = ID_NONE;
}
} else {
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
}
} else {
+ self->chMapIndex = 0;
if (transportDec_GetFormat(self->hInput) == TT_MP4_ADTS) {
/* set default max_channels for memory allocation because in implicit channel mapping mode
we don't know the actual number of channels until we processed at least one raw_data_block(). */
- ascChannels = (6);
+ ascChannels = (8);
} else {
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
}
@@ -874,26 +891,34 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS
case 1: case 2: case 3: case 4: case 5: case 6:
ascChannels = asc->m_channelConfiguration;
break;
- case 7:
+ case 11:
+ ascChannels = 7;
+ break;
+ case 7: case 12: case 14:
ascChannels = 8;
break;
default:
return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
}
+ if (ascChannels > (8)) {
+ return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
+ }
+
/* Initialize constant mappings for channel config 1-7 */
if (asc->m_channelConfiguration > 0) {
int el;
- FDKmemcpy(self->elements, elementsTab[asc->m_channelConfiguration-1], sizeof(MP4_ELEMENT_ID)*FDKmin(7,7));
- for (el=7; el<7; el++) {
+ FDKmemcpy(self->elements, elementsTab[asc->m_channelConfiguration-1], sizeof(MP4_ELEMENT_ID)*FDKmin(7,(8)));
+ for (el=7; el<(8); el++) {
self->elements[el] = ID_NONE;
}
for (ch=0; ch<ascChannels; ch++) {
self->chMapping[ch] = ch;
}
- for (; ch<(6); ch++) {
+ for (; ch<(8); ch++) {
self->chMapping[ch] = 255;
}
+ self->chMapIndex = asc->m_channelConfiguration;
}
#ifdef TP_PCE_ENABLE
else {
@@ -909,9 +934,6 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CS
self->streamInfo.channelConfig = asc->m_channelConfiguration;
- if (ascChannels > (6)) {
- return AAC_DEC_UNSUPPORTED_CHANNELCONFIG;
- }
if (self->streamInfo.aot != asc->m_aot) {
self->streamInfo.aot = asc->m_aot;
ascChanged = 1;
@@ -1096,6 +1118,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
MP4_ELEMENT_ID type = ID_NONE; /* Current element type */
INT aacChannels=0; /* Channel counter for channels found in the bitstream */
+ int chOutMapIdx; /* Output channel mapping index (see comment below) */
INT auStartAnchor = (INT)FDKgetValidBits(bs); /* AU start bit buffer position for AU byte alignment */
@@ -1119,12 +1142,12 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
if (self->streamInfo.channelConfig == 0) {
/* Init Channel/Element mapping table */
- for (ch=0; ch<(6); ch++) {
+ for (ch=0; ch<(8); ch++) {
self->chMapping[ch] = 255;
}
if (!CProgramConfig_IsValid(pce)) {
int el;
- for (el=0; el<7; el++) {
+ for (el=0; el<(8); el++) {
self->elements[el] = ID_NONE;
}
}
@@ -1378,10 +1401,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
{
UCHAR element_instance_tag;
- CDataStreamElement_Read( bs,
- &self->ancData,
- self->hDrcInfo,
- self->hInput,
+ CDataStreamElement_Read( self,
+ bs,
&element_instance_tag,
auStartAnchor );
@@ -1401,29 +1422,6 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
//self->frameOK = 0;
}
}
-
- {
- UCHAR *pDvbAncData = NULL;
- AAC_DECODER_ERROR ancErr;
- int ancIndex;
- int dvbAncDataSize = 0;
-
- /* Ask how many anc data elements are in buffer */
- ancIndex = self->ancData.nrElements - 1;
- /* Get the last one (if available) */
- ancErr = CAacDecoder_AncDataGet( &self->ancData,
- ancIndex,
- &pDvbAncData,
- &dvbAncDataSize );
-
- if (ancErr == AAC_DEC_OK) {
- pcmDmx_ReadDvbAncData (
- self->hPcmUtils,
- pDvbAncData,
- dvbAncDataSize,
- 0 /* not mpeg2 */ );
- }
- }
break;
#ifdef TP_PCE_ENABLE
@@ -1442,9 +1440,9 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
}
else if ( result > 1 ) {
/* Built element table */
- int elIdx = CProgramConfig_GetElementTable(pce, self->elements, 7);
+ int elIdx = CProgramConfig_GetElementTable(pce, self->elements, (8), &self->chMapIndex);
/* Reset the remaining tabs */
- for ( ; elIdx<7; elIdx++) {
+ for ( ; elIdx<(8); elIdx++) {
self->elements[elIdx] = ID_NONE;
}
/* Make new number of channel persistant */
@@ -1632,12 +1630,31 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
return ErrorStatus;
}
+ /* Setup the output channel mapping. The table below shows the four possibilities:
+ * # | chCfg | PCE | cChCfg | chOutMapIdx
+ * ---+-------+-----+--------+------------------
+ * 1 | > 0 | no | - | chCfg
+ * 2 | 0 | yes | > 0 | cChCfg
+ * 3 | 0 | yes | 0 | aacChannels || 0
+ * 4 | 0 | no | - | aacChannels || 0
+ * ---+-------+-----+--------+------------------
+ * Where chCfg is the channel configuration index from ASC and cChCfg is a corresponding chCfg
+ * derived from a given PCE. The variable aacChannels represents the number of channel found
+ * during bitstream decoding. Due to the structure of the mapping table it can only be used for
+ * mapping if its value is smaller than 7. Otherwise we use the fallback (0) which is a simple
+ * pass-through. The possibility #4 should appear only with MPEG-2 (ADTS) streams. This is
+ * mode is called "implicit channel mapping".
+ */
+ chOutMapIdx = ((self->chMapIndex==0) && (aacChannels<7)) ? aacChannels : self->chMapIndex;
+
/*
Inverse transform
*/
{
int stride, offset, c;
+ /* Turn on/off DRC modules level normalization in digital domain depending on the limiter status. */
+ aacDecoder_drcSetParam( self->hDrcInfo, APPLY_NORMALIZATION, (self->limiterEnableCurr) ? 0 : 1 );
/* Extract DRC control data and map it to channels (without bitstream delay) */
aacDecoder_drcProlog (
self->hDrcInfo,
@@ -1663,10 +1680,10 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
/* Setup offset and stride for time buffer traversal. */
if (interleaved) {
stride = aacChannels;
- offset = self->channelOutputMapping[aacChannels-1][c];
+ offset = self->channelOutputMapping[chOutMapIdx][c];
} else {
stride = 1;
- offset = self->channelOutputMapping[aacChannels-1][c] * self->streamInfo.aacSamplesPerFrame;
+ offset = self->channelOutputMapping[chOutMapIdx][c] * self->streamInfo.aacSamplesPerFrame;
}
@@ -1688,12 +1705,15 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
/* Reset DRC control data for this channel */
aacDecoder_drcInitChannelData ( &self->pAacDecoderStaticChannelInfo[c]->drcData );
}
+ /* The DRC module demands to be called with the gain field holding the gain scale. */
+ self->extGain[0] = (FIXP_DBL)TDL_GAIN_SCALING;
/* DRC processing */
aacDecoder_drcApply (
self->hDrcInfo,
self->hSbrDecoder,
pAacDecoderChannelInfo,
&self->pAacDecoderStaticChannelInfo[c]->drcData,
+ self->extGain,
c,
self->streamInfo.aacSamplesPerFrame,
self->sbrEnabled
@@ -1711,6 +1731,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
(self->frameOK && !(flags&AACDEC_CONCEAL)),
self->aacCommonData.workBufferCore1->mdctOutTemp
);
+ self->extGainDelay = self->streamInfo.aacSamplesPerFrame;
break;
case AACDEC_RENDER_ELDFB:
CBlock_FrequencyToTimeLowDelay(
@@ -1720,6 +1741,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
self->streamInfo.aacSamplesPerFrame,
stride
);
+ self->extGainDelay = (self->streamInfo.aacSamplesPerFrame*2 - self->streamInfo.aacSamplesPerFrame/2 - 1)/2;
break;
default:
ErrorStatus = AAC_DEC_UNKNOWN;
@@ -1746,8 +1768,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
/* Reorder channel type information tables. */
{
- AUDIO_CHANNEL_TYPE types[(6)];
- UCHAR idx[(6)];
+ AUDIO_CHANNEL_TYPE types[(8)];
+ UCHAR idx[(8)];
int c;
FDK_ASSERT(sizeof(self->channelType) == sizeof(types));
@@ -1757,8 +1779,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
FDKmemcpy(idx, self->channelIndices, sizeof(idx));
for (c=0; c<aacChannels; c++) {
- self->channelType[self->channelOutputMapping[aacChannels-1][c]] = types[c];
- self->channelIndices[self->channelOutputMapping[aacChannels-1][c]] = idx[c];
+ self->channelType[self->channelOutputMapping[chOutMapIdx][c]] = types[c];
+ self->channelIndices[self->channelOutputMapping[chOutMapIdx][c]] = idx[c];
}
}
diff --git a/libAACdec/src/aacdecoder.h b/libAACdec/src/aacdecoder.h
index 16351e6..bcbc040 100644
--- a/libAACdec/src/aacdecoder.h
+++ b/libAACdec/src/aacdecoder.h
@@ -111,6 +111,7 @@ amm-info@iis.fraunhofer.de
#include "aacdec_drc.h"
#include "pcmutils_lib.h"
+ #include "limiter.h"
/* Capabilities flags */
@@ -176,22 +177,23 @@ struct AAC_DECODER_INSTANCE {
UINT flags; /*!< Flags for internal decoder use. DO NOT USE self::streaminfo::flags ! */
- MP4_ELEMENT_ID elements[7]; /*!< Table where the element Id's are listed */
- UCHAR elTags[7]; /*!< Table where the elements id Tags are listed */
- UCHAR chMapping[(6)]; /*!< Table of MPEG canonical order to bitstream channel order mapping. */
+ MP4_ELEMENT_ID elements[(8)]; /*!< Table where the element Id's are listed */
+ UCHAR elTags[(8)]; /*!< Table where the elements id Tags are listed */
+ UCHAR chMapping[(8)]; /*!< Table of MPEG canonical order to bitstream channel order mapping. */
- AUDIO_CHANNEL_TYPE channelType[(6)]; /*!< Audio channel type of each output audio channel (from 0 upto numChannels). */
- UCHAR channelIndices[(6)]; /*!< Audio channel index for each output audio channel (from 0 upto numChannels). */
+ AUDIO_CHANNEL_TYPE channelType[(8)]; /*!< Audio channel type of each output audio channel (from 0 upto numChannels). */
+ UCHAR channelIndices[(8)]; /*!< Audio channel index for each output audio channel (from 0 upto numChannels). */
/* See ISO/IEC 13818-7:2005(E), 8.5.3.2 Explicit channel mapping using a program_config_element() */
const UCHAR (*channelOutputMapping)[8]; /*!< Table for MPEG canonical order to output channel order mapping. */
-
+ UCHAR chMapIndex; /*!< Index to access one line of the channelOutputMapping table. This is required
+ because not all 8 channel configurations have the same output mapping. */
CProgramConfig pce;
CStreamInfo streamInfo; /*!< pointer to StreamInfo data (read from the bitstream) */
- CAacDecoderChannelInfo *pAacDecoderChannelInfo[(6)]; /*!< Temporal channel memory */
- CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[(6)]; /*!< Persistent channel memory */
+ CAacDecoderChannelInfo *pAacDecoderChannelInfo[(8)]; /*!< Temporal channel memory */
+ CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[(8)]; /*!< Persistent channel memory */
CAacDecoderCommonData aacCommonData; /*!< Temporal shared data for all channels hooked into pAacDecoderChannelInfo */
@@ -214,6 +216,12 @@ struct AAC_DECODER_INSTANCE {
CAncData ancData; /*!< structure to handle ancillary data */
HANDLE_PCM_DOWNMIX hPcmUtils; /*!< privat data for the PCM utils. */
+ TDLimiterPtr hLimiter; /*!< Handle of time domain limiter. */
+ UCHAR limiterEnableUser; /*!< The limiter configuration requested by the library user */
+ UCHAR limiterEnableCurr; /*!< The current limiter configuration. */
+
+ FIXP_DBL extGain[1]; /*!< Gain that must be applied to the output signal. */
+ UINT extGainDelay; /*!< Delay that must be accounted for extGain. */
};
diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp
index ec8f41e..98ef0de 100644
--- a/libAACdec/src/aacdecoder_lib.cpp
+++ b/libAACdec/src/aacdecoder_lib.cpp
@@ -110,7 +110,7 @@ amm-info@iis.fraunhofer.de
/* Decoder library info */
#define AACDECODER_LIB_VL0 2
#define AACDECODER_LIB_VL1 5
-#define AACDECODER_LIB_VL2 5
+#define AACDECODER_LIB_VL2 7
#define AACDECODER_LIB_TITLE "AAC Decoder Lib"
#define AACDECODER_LIB_BUILD_DATE __DATE__
#define AACDECODER_LIB_BUILD_TIME __TIME__
@@ -397,12 +397,14 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
CConcealParams *pConcealData = NULL;
HANDLE_AAC_DRC hDrcInfo = NULL;
HANDLE_PCM_DOWNMIX hPcmDmx = NULL;
+ TDLimiterPtr hPcmTdl = NULL;
/* check decoder handle */
if (self != NULL) {
pConcealData = &self->concealCommonData;
hDrcInfo = self->hDrcInfo;
hPcmDmx = self->hPcmUtils;
+ hPcmTdl = self->hLimiter;
} else {
errorStatus = AAC_DEC_INVALID_HANDLE;
}
@@ -420,8 +422,8 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
self->outputInterleaved = value;
break;
- case AAC_PCM_OUTPUT_CHANNELS:
- if (value < -1 || value > (6)) {
+ case AAC_PCM_MIN_OUTPUT_CHANNELS:
+ if (value < -1 || value > (8)) {
return AAC_DEC_SET_PARAM_FAIL;
}
{
@@ -429,7 +431,30 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
err = pcmDmx_SetParam (
hPcmDmx,
- NUMBER_OF_OUTPUT_CHANNELS,
+ MIN_NUMBER_OF_OUTPUT_CHANNELS,
+ value );
+
+ switch (err) {
+ case PCMDMX_OK:
+ break;
+ case PCMDMX_INVALID_HANDLE:
+ return AAC_DEC_INVALID_HANDLE;
+ default:
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ }
+ break;
+
+ case AAC_PCM_MAX_OUTPUT_CHANNELS:
+ if (value < -1 || value > (8)) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ {
+ PCMDMX_ERROR err;
+
+ err = pcmDmx_SetParam (
+ hPcmDmx,
+ MAX_NUMBER_OF_OUTPUT_CHANNELS,
value );
switch (err) {
@@ -449,7 +474,7 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
err = pcmDmx_SetParam (
hPcmDmx,
- DUAL_CHANNEL_DOWNMIX_MODE,
+ DMX_DUAL_CHANNEL_MODE,
value );
switch (err) {
@@ -463,6 +488,47 @@ aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decode
}
break;
+
+ case AAC_PCM_LIMITER_ENABLE:
+ if (value < -1 || value > 1) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ if (self == NULL) {
+ return AAC_DEC_INVALID_HANDLE;
+ }
+ self->limiterEnableUser = value;
+ break;
+
+ case AAC_PCM_LIMITER_ATTACK_TIME:
+ if (value <= 0) { /* module function converts value to unsigned */
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ switch (setLimiterAttack(hPcmTdl, value)) {
+ case TDLIMIT_OK:
+ break;
+ case TDLIMIT_INVALID_HANDLE:
+ return AAC_DEC_INVALID_HANDLE;
+ case TDLIMIT_INVALID_PARAMETER:
+ default:
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ break;
+
+ case AAC_PCM_LIMITER_RELEAS_TIME:
+ if (value <= 0) { /* module function converts value to unsigned */
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ switch (setLimiterRelease(hPcmTdl, value)) {
+ case TDLIMIT_OK:
+ break;
+ case TDLIMIT_INVALID_HANDLE:
+ return AAC_DEC_INVALID_HANDLE;
+ case TDLIMIT_INVALID_PARAMETER:
+ default:
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
+ break;
+
case AAC_PCM_OUTPUT_CHANNEL_MAPPING:
switch (value) {
case 0:
@@ -609,6 +675,14 @@ LINKSPEC_CPP HANDLE_AACDECODER aacDecoder_Open(TRANSPORT_TYPE transportFmt, UINT
goto bail;
}
+ aacDec->hLimiter = createLimiter(TDL_ATTACK_DEFAULT_MS, TDL_RELEASE_DEFAULT_MS, SAMPLE_MAX, (8), 96000);
+ if (NULL == aacDec->hLimiter) {
+ err = -1;
+ goto bail;
+ }
+ aacDec->limiterEnableUser = (UCHAR)-1;
+ aacDec->limiterEnableCurr = 0;
+
/* Assure that all modules have same delay */
@@ -784,6 +858,17 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
self->streamInfo.numTotalBytes = 0;
}
+ if (self->limiterEnableUser==(UCHAR)-1) {
+ /* Enbale limiter for all non-lowdelay AOT's. */
+ self->limiterEnableCurr = ( self->flags & (AC_LD|AC_ELD) ) ? 0 : 1;
+ }
+ else {
+ /* Use limiter configuration as requested. */
+ self->limiterEnableCurr = self->limiterEnableUser;
+ }
+ /* reset limiter gain on a per frame basis */
+ self->extGain[0] = FL2FXCONST_DBL(1.0f/(float)(1<<TDL_GAIN_SCALING));
+
ErrorStatus = CAacDecoder_DecodeFrame(self,
flags | (fTpConceal ? AACDEC_CONCEAL : 0),
@@ -825,6 +910,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
if (self->sbrEnabled)
{
SBR_ERROR sbrError = SBRDEC_OK;
+ int chOutMapIdx = ((self->chMapIndex==0) && (self->streamInfo.numChannels<7)) ? self->streamInfo.numChannels : self->chMapIndex;
/* set params */
sbrDecoder_SetParam ( self->hSbrDecoder,
@@ -838,7 +924,16 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
(self->flags & AC_LD_MPS) ? 1 : 0 );
}
+ {
+ PCMDMX_ERROR dmxErr;
+ INT maxOutCh = 0;
+ dmxErr = pcmDmx_GetParam(self->hPcmUtils, MAX_NUMBER_OF_OUTPUT_CHANNELS, &maxOutCh);
+ if ( (dmxErr == PCMDMX_OK) && (maxOutCh == 1) ) {
+ /* Disable PS processing if we have to create a mono output signal. */
+ self->psPossible = 0;
+ }
+ }
/* apply SBR processing */
@@ -846,7 +941,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
pTimeData,
&self->streamInfo.numChannels,
&self->streamInfo.sampleRate,
- self->channelOutputMapping[self->streamInfo.numChannels-1],
+ self->channelOutputMapping[chOutMapIdx],
interleaved,
self->frameOK,
&self->psPossible);
@@ -870,19 +965,20 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
self->channelType[1] = ACT_FRONT;
self->channelIndices[0] = 0;
self->channelIndices[1] = 1;
- } else {
- self->flags &= ~AC_PS_PRESENT;
}
}
}
+ {
+ INT pcmLimiterScale = 0;
+ PCMDMX_ERROR dmxErr = PCMDMX_OK;
if ( flags & (AACDEC_INTR | AACDEC_CLRHIST) ) {
/* delete data from the past (e.g. mixdown coeficients) */
pcmDmx_Reset( self->hPcmUtils, PCMDMX_RESET_BS_DATA );
}
/* do PCM post processing */
- pcmDmx_ApplyFrame (
+ dmxErr = pcmDmx_ApplyFrame (
self->hPcmUtils,
pTimeData,
self->streamInfo.frameSize,
@@ -890,9 +986,36 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
interleaved,
self->channelType,
self->channelIndices,
- self->channelOutputMapping
+ self->channelOutputMapping,
+ (self->limiterEnableCurr) ? &pcmLimiterScale : NULL
);
+ if (dmxErr == PCMDMX_INVALID_MODE) {
+ /* Announce the framework that the current combination of channel configuration and downmix
+ * settings are not know to produce a predictable behavior and thus maybe produce strange output. */
+ ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
+ }
+ if ( flags & AACDEC_CLRHIST ) {
+ /* Delete the delayed signal. */
+ resetLimiter(self->hLimiter);
+ }
+ if (self->limiterEnableCurr)
+ {
+ /* Set actual signal parameters */
+ setLimiterNChannels(self->hLimiter, self->streamInfo.numChannels);
+ setLimiterSampleRate(self->hLimiter, self->streamInfo.sampleRate);
+
+ applyLimiter(
+ self->hLimiter,
+ pTimeData,
+ self->extGain,
+ &pcmLimiterScale,
+ 1,
+ self->extGainDelay,
+ self->streamInfo.frameSize
+ );
+ }
+ }
/* Signal interruption to take effect in next frame. */
@@ -917,6 +1040,9 @@ LINKSPEC_CPP void aacDecoder_Close ( HANDLE_AACDECODER self )
return;
+ if (self->hLimiter != NULL) {
+ destroyLimiter(self->hLimiter);
+ }
if (self->hPcmUtils != NULL) {
pcmDmx_Close( &self->hPcmUtils );
diff --git a/libAACdec/src/conceal.cpp b/libAACdec/src/conceal.cpp
index c26051c..1c313ef 100644
--- a/libAACdec/src/conceal.cpp
+++ b/libAACdec/src/conceal.cpp
@@ -762,7 +762,6 @@ int
CConcealment_UpdateState( hConcealmentInfo,
frameOk );
- if ( !frameOk )
{
/* Create data for signal rendering according to the selected concealment method and decoder operating mode. */
@@ -775,11 +774,13 @@ int
{
default:
case ConcealMethodMute:
- /* Mute spectral data in case of errors */
- FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL));
- /* Set last window shape */
- pAacDecoderChannelInfo->icsInfo.WindowShape = hConcealmentInfo->windowShape;
- appliedProcessing = 1;
+ if (!frameOk) {
+ /* Mute spectral data in case of errors */
+ FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL));
+ /* Set last window shape */
+ pAacDecoderChannelInfo->icsInfo.WindowShape = hConcealmentInfo->windowShape;
+ appliedProcessing = 1;
+ }
break;
case ConcealMethodNoise:
@@ -801,7 +802,7 @@ int
pSamplingRateInfo,
samplesPerFrame,
0, /* don't use tonal improvement */
- 0);
+ frameOk);
break;
}