Merge remote-tracking branch 'aosp/master'
This commit is contained in:
commit
6ccecbc4b0
@ -53,6 +53,11 @@ LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/libSBRdec/include \
|
||||
$(LOCAL_PATH)/libSBRenc/include
|
||||
|
||||
# In tpdec_asc.cpp: address of array 'pPce->FrontElementIsCpe'
|
||||
# will always evaluate to 'true'.
|
||||
LOCAL_CLANG_CPPFLAGS += \
|
||||
-Wno-pointer-bool-conversion
|
||||
|
||||
LOCAL_MODULE:= libFraunhoferAAC
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
File diff suppressed because one or more lines are too long
@ -144,10 +144,9 @@ to allocate memory for the required structures, and the corresponding mpegFileRe
|
||||
files and to de-allocate associated structures. mpegFileRead_Open() tries to detect the bitstream format and
|
||||
in case of MPEG-4 file format or Raw Packets file format (a Fraunhofer IIS proprietary format) reads the Audio
|
||||
Specific Config data (ASC). An unsuccessful attempt to recognize the bitstream format requires the user to
|
||||
provide this information manually (see \ref CommandLineUsage). For any other bitstream formats that are
|
||||
usually applicable in streaming applications, the decoder itself will try to synchronize and parse the given
|
||||
bitstream fragment using the FDK transport library. Hence, for streaming applications (without file access)
|
||||
this step is not necessary.
|
||||
provide this information manually. For any other bitstream formats that are usually applicable in streaming
|
||||
applications, the decoder itself will try to synchronize and parse the given bitstream fragment using the
|
||||
FDK transport library. Hence, for streaming applications (without file access) this step is not necessary.
|
||||
|
||||
-# Call aacDecoder_Open() to open and retrieve a handle to a new AAC decoder instance.
|
||||
\dontinclude main.cpp
|
||||
@ -430,21 +429,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
|
||||
@ -485,18 +531,18 @@ typedef enum
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/* These three members are the only really relevant ones for the user. */
|
||||
/* These five members are the only really relevant ones for the user. */
|
||||
INT sampleRate; /*!< The samplerate in Hz of the fully decoded PCM audio signal (after SBR processing). */
|
||||
INT frameSize; /*!< The frame size of the decoded PCM audio signal. \n
|
||||
1024 or 960 for AAC-LC \n
|
||||
2048 or 1920 for HE-AAC (v2) \n
|
||||
512 or 480 for AAC-LD and AAC-ELD */
|
||||
INT numChannels; /*!< The number of output audio channels in the decoded and interleaved PCM audio signal. */
|
||||
AUDIO_CHANNEL_TYPE *pChannelType; /*!< Audio channel type of each output audio channel. */
|
||||
UCHAR *pChannelIndices; /*!< Audio channel index for each output audio channel.
|
||||
AUDIO_CHANNEL_TYPE *pChannelType; /*!< Audio channel type of each output audio channel. */
|
||||
UCHAR *pChannelIndices; /*!< Audio channel index for each output audio channel.
|
||||
See ISO/IEC 13818-7:2005(E), 8.5.3.2 Explicit channel mapping using a program_config_element() */
|
||||
/* Decoder internal members. */
|
||||
INT aacSampleRate; /*!< sampling rate in Hz without SBR (from configuration info). */
|
||||
INT aacSampleRate; /*!< Sampling rate in Hz without SBR (from configuration info). */
|
||||
INT profile; /*!< MPEG-2 profile (from file header) (-1: not applicable (e. g. MPEG-4)). */
|
||||
AUDIO_OBJECT_TYPE aot; /*!< Audio Object Type (from ASC): is set to the appropriate value for MPEG-2 bitstreams (e. g. 2 for AAC-LC). */
|
||||
INT channelConfig; /*!< Channel configuration (0: PCE defined, 1: mono, 2: stereo, ... */
|
||||
@ -509,7 +555,9 @@ typedef struct
|
||||
AUDIO_OBJECT_TYPE extAot; /*!< Extension Audio Object Type (from ASC) */
|
||||
INT extSamplingRate; /*!< Extension sampling rate in Hz (from ASC) */
|
||||
|
||||
UINT flags; /*!< Copy if internal flags. Only to be written by the decoder, and only to be read externally. */
|
||||
UINT outputDelay; /*!< The number of samples the output is additionally delayed by the decoder. */
|
||||
|
||||
UINT flags; /*!< Copy of internal flags. Only to be written by the decoder, and only to be read externally. */
|
||||
|
||||
SCHAR epConfig; /*!< epConfig level (from ASC): only level 0 supported, -1 means no ER (e. g. AOT=2, MPEG-2 AAC, etc.) */
|
||||
|
||||
@ -522,10 +570,25 @@ typedef struct
|
||||
UINT numTotalAccessUnits; /*!< This is the number of total access units that have passed through the decoder. */
|
||||
UINT numBadAccessUnits; /*!< This is the number of total access units that were considered with errors from numTotalBytes. */
|
||||
|
||||
/* Metadata */
|
||||
SCHAR drcProgRefLev; /*!< DRC program reference level. Defines the reference level below full-scale.
|
||||
It is quantized in steps of 0.25dB. The valid values range from 0 (0 dBFS) to 127 (-31.75 dBFS).
|
||||
It is used to reflect the average loudness of the audio in LKFS accoring to ITU-R BS 1770.
|
||||
If no level has been found in the bitstream the value is -1. */
|
||||
SCHAR drcPresMode; /*!< DRC presentation mode. According to ETSI TS 101 154, this field indicates whether
|
||||
light (MPEG-4 Dynamic Range Control tool) or heavy compression (DVB heavy compression)
|
||||
dynamic range control shall take priority on the outputs.
|
||||
For details, see ETSI TS 101 154, table C.33. Possible values are: \n
|
||||
-1: No corresponding metadata found in the bitstream \n
|
||||
0: DRC presentation mode not indicated \n
|
||||
1: DRC presentation mode 1 \n
|
||||
2: DRC presentation mode 2 \n
|
||||
3: Reserved */
|
||||
|
||||
} CStreamInfo;
|
||||
|
||||
|
||||
typedef struct AAC_DECODER_INSTANCE *HANDLE_AACDECODER;
|
||||
typedef struct AAC_DECODER_INSTANCE *HANDLE_AACDECODER; /*!< Pointer to a AAC decoder instance. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
@ -634,11 +697,15 @@ aacDecoder_Fill ( HANDLE_AACDECODER self,
|
||||
const UINT bufferSize[],
|
||||
UINT *bytesValid );
|
||||
|
||||
#define AACDEC_CONCEAL 1 /*!< Flag for aacDecoder_DecodeFrame(): do not consider new input data. Do concealment. */
|
||||
#define AACDEC_FLUSH 2 /*!< Flag for aacDecoder_DecodeFrame(): Do not consider new input data. Flush filterbanks (output delayed audio). */
|
||||
#define AACDEC_INTR 4 /*!< Flag for aacDecoder_DecodeFrame(): Signal an input bit stream data discontinuity. Resync any internals as necessary. */
|
||||
#define AACDEC_CLRHIST 8 /*!< Flag for aacDecoder_DecodeFrame(): Clear all signal delay lines and history buffers.
|
||||
Caution: This can cause discontinuities in the output signal. */
|
||||
#define AACDEC_CONCEAL 1 /*!< Flag for aacDecoder_DecodeFrame(): Trigger the built-in error concealment module \
|
||||
to generate a substitute signal for one lost frame. New input data will not be
|
||||
considered. */
|
||||
#define AACDEC_FLUSH 2 /*!< Flag for aacDecoder_DecodeFrame(): Flush all filterbanks to get all delayed audio \
|
||||
without having new input data. Thus new input data will not be considered.*/
|
||||
#define AACDEC_INTR 4 /*!< Flag for aacDecoder_DecodeFrame(): Signal an input bit stream data discontinuity. \
|
||||
Resync any internals as necessary. */
|
||||
#define AACDEC_CLRHIST 8 /*!< Flag for aacDecoder_DecodeFrame(): Clear all signal delay lines and history buffers.\
|
||||
CAUTION: This can cause discontinuities in the output signal. */
|
||||
|
||||
/**
|
||||
* \brief Decode one audio frame
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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,12 +138,15 @@ 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 */
|
||||
self->progRefLevel = pParams->targetRefLevel;
|
||||
self->progRefLevelPresent = 0;
|
||||
self->presMode = -1;
|
||||
}
|
||||
|
||||
|
||||
@ -222,11 +224,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 +237,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 +291,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 +552,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 */
|
||||
@ -561,8 +574,9 @@ static int aacDecoder_drcReadCompression (
|
||||
return 0;
|
||||
}
|
||||
FDKreadBits(bs, 2); /* dolby_surround_mode */
|
||||
FDKreadBits(bs, 2); /* presentation_mode */
|
||||
if (FDKreadBits(bs, 2) != 0) { /* reserved, set to 0 */
|
||||
pDrcBs->presMode = FDKreadBits(bs, 2); /* presentation_mode */
|
||||
FDKreadBits(bs, 1); /* stereo_downmix_mode */
|
||||
if (FDKreadBits(bs, 1) != 0) { /* reserved, set to 0 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -571,9 +585,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 +643,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);
|
||||
}
|
||||
|
||||
@ -780,9 +805,15 @@ static int aacDecoder_drcExtractAndMap (
|
||||
*/
|
||||
if (pThreadBs->progRefLevel >= 0) {
|
||||
self->progRefLevel = pThreadBs->progRefLevel;
|
||||
self->progRefLevelPresent = 1;
|
||||
self->prlExpiryCount = 0; /* Got a new value -> Reset counter */
|
||||
}
|
||||
|
||||
if (drcPayloadType == DVB_DRC_ANC_DATA) {
|
||||
/* Announce the presentation mode of this valid thread. */
|
||||
self->presMode = pThreadBs->presMode;
|
||||
}
|
||||
|
||||
/* SCE, CPE and LFE */
|
||||
for (ch = 0; ch < validChannels; ch++) {
|
||||
int mapedChannel = channelMapping[ch];
|
||||
@ -802,6 +833,7 @@ static int aacDecoder_drcExtractAndMap (
|
||||
if ( (pParams->expiryFrame > 0)
|
||||
&& (self->prlExpiryCount++ > pParams->expiryFrame) )
|
||||
{ /* The program reference level is too old, so set it back to the target level. */
|
||||
self->progRefLevelPresent = 0;
|
||||
self->progRefLevel = pParams->targetRefLevel;
|
||||
self->prlExpiryCount = 0;
|
||||
}
|
||||
@ -815,6 +847,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 +859,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 +882,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 +906,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 +916,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;
|
||||
}
|
||||
@ -1112,3 +1165,24 @@ int aacDecoder_drcEpilog (
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Export relevant metadata info from bitstream payload.
|
||||
*/
|
||||
void aacDecoder_drcGetInfo (
|
||||
HANDLE_AAC_DRC self,
|
||||
SCHAR *pPresMode,
|
||||
SCHAR *pProgRefLevel )
|
||||
{
|
||||
if (self != NULL) {
|
||||
if (pPresMode != NULL) {
|
||||
*pPresMode = self->presMode;
|
||||
}
|
||||
if (pProgRefLevel != NULL) {
|
||||
if (self->progRefLevelPresent) {
|
||||
*pProgRefLevel = self->progRefLevel;
|
||||
} else {
|
||||
*pProgRefLevel = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 );
|
||||
@ -170,5 +173,17 @@ int aacDecoder_drcEpilog (
|
||||
UCHAR channelMapping[],
|
||||
int validChannels );
|
||||
|
||||
/**
|
||||
* \brief Get metadata information found in bitstream.
|
||||
* \param self DRC module instance handle.
|
||||
* \param pPresMode Pointer to field where the presentation mode will be written to.
|
||||
* \param pProgRefLevel Pointer to field where the program reference level will be written to.
|
||||
* \return Nothing.
|
||||
*/
|
||||
void aacDecoder_drcGetInfo (
|
||||
HANDLE_AAC_DRC self,
|
||||
SCHAR *pPresMode,
|
||||
SCHAR *pProgRefLevel );
|
||||
|
||||
|
||||
#endif /* AACDEC_DRC_H */
|
||||
|
@ -124,6 +124,7 @@ typedef struct
|
||||
{
|
||||
UINT excludedChnsMask;
|
||||
SCHAR progRefLevel;
|
||||
SCHAR presMode; /* Presentation mode: 0 (not indicated), 1, 2, and 3 (reserved). */
|
||||
SCHAR pceInstanceTag;
|
||||
|
||||
CDrcChannelData channelData;
|
||||
@ -140,6 +141,7 @@ typedef struct
|
||||
UINT expiryFrame;
|
||||
SCHAR targetRefLevel;
|
||||
UCHAR bsDelayEnable;
|
||||
UCHAR applyDigitalNorm;
|
||||
UCHAR applyHeavyCompression;
|
||||
|
||||
} CDrcParams;
|
||||
@ -155,9 +157,11 @@ typedef struct
|
||||
USHORT numPayloads; /* The number of DRC data payload elements found within frame */
|
||||
USHORT numThreads; /* The number of DRC data threads extracted from the found payload elements */
|
||||
SCHAR progRefLevel; /* Program reference level for all channels */
|
||||
UCHAR progRefLevelPresent; /* Program reference level found in bitstream */
|
||||
|
||||
UINT prlExpiryCount; /* Counter that can be used to monitor the life time of the program reference level. */
|
||||
|
||||
SCHAR presMode; /* Presentation mode as defined in ETSI TS 101 154 */
|
||||
UCHAR dvbAncDataAvailable; /* Flag that indicates whether DVB ancillary data is present or not */
|
||||
UINT dvbAncDataPosition; /* Used to store the DVB ancillary data payload position in the bitstream (only one per frame) */
|
||||
UINT drcPayloadPosition[MAX_DRC_THREADS]; /* Used to store the DRC payload positions in the bitstream */
|
||||
|
@ -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,20 +378,30 @@ 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 );
|
||||
|
||||
if (readBits != dataBits) {
|
||||
/* Move to the end again. */
|
||||
FDKpushBiDirectional(bs, FDKgetValidBits(bs)-dataStart+dataBits);
|
||||
}
|
||||
aacDecoder_drcMarkPayload( self->hDrcInfo, bs, DVB_DRC_ANC_DATA );
|
||||
}
|
||||
|
||||
{
|
||||
PCMDMX_ERROR dmxErr = PCMDMX_OK;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -701,6 +717,12 @@ void CStreamInfoInit(CStreamInfo *pStreamInfo)
|
||||
pStreamInfo->numChannels = 0;
|
||||
pStreamInfo->sampleRate = 0;
|
||||
pStreamInfo->frameSize = 0;
|
||||
|
||||
pStreamInfo->outputDelay = 0;
|
||||
|
||||
/* DRC */
|
||||
pStreamInfo->drcProgRefLev = -1; /* set program reference level to not indicated */
|
||||
pStreamInfo->drcPresMode = -1; /* default: presentation mode not indicated */
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -774,7 +796,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 +873,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 +897,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 +940,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 +1124,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 +1148,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;
|
||||
}
|
||||
}
|
||||
@ -1161,11 +1190,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
|
||||
CConcealment_InitChannelData(&self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo,
|
||||
&self->concealCommonData,
|
||||
self->streamInfo.aacSamplesPerFrame );
|
||||
/* Clear concealment buffers to get rid of the complete history */
|
||||
FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo.spectralCoefficient, 1024 * sizeof(FIXP_CNCL));
|
||||
FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo.specScale, 8 * sizeof(SHORT));
|
||||
/* Clear overlap-add buffers to avoid clicks. */
|
||||
FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->IMdct.overlap.freq, OverlapBufferSize*sizeof(FIXP_DBL));
|
||||
FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer, OverlapBufferSize*sizeof(FIXP_DBL));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1378,10 +1404,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 +1425,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 +1443,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 */
|
||||
@ -1510,10 +1511,19 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (err == SBRDEC_OK) {
|
||||
switch (err) {
|
||||
case SBRDEC_PARSE_ERROR:
|
||||
/* Can not go on parsing because we do not
|
||||
know the length of the SBR extension data. */
|
||||
FDKpushFor(bs, bitCnt);
|
||||
bitCnt = 0;
|
||||
break;
|
||||
case SBRDEC_OK:
|
||||
self->sbrEnabled = 1;
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
self->frameOK = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1603,13 +1613,17 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
|
||||
self->frameOK=0;
|
||||
}
|
||||
|
||||
/* store or restore the number of channels */
|
||||
/* store or restore the number of channels and the corresponding info */
|
||||
if ( self->frameOK && !(flags &(AACDEC_CONCEAL|AACDEC_FLUSH)) ) {
|
||||
self->concealChannels = aacChannels; /* store */
|
||||
self->aacChannelsPrev = aacChannels; /* store */
|
||||
FDKmemcpy(self->channelTypePrev, self->channelType, (8)*sizeof(AUDIO_CHANNEL_TYPE)); /* store */
|
||||
FDKmemcpy(self->channelIndicesPrev, self->channelIndices, (8)*sizeof(UCHAR)); /* store */
|
||||
self->sbrEnabledPrev = self->sbrEnabled;
|
||||
} else {
|
||||
if (self->aacChannels > 0) {
|
||||
aacChannels = self->concealChannels; /* restore */
|
||||
aacChannels = self->aacChannelsPrev; /* restore */
|
||||
FDKmemcpy(self->channelType, self->channelTypePrev, (8)*sizeof(AUDIO_CHANNEL_TYPE)); /* restore */
|
||||
FDKmemcpy(self->channelIndices, self->channelIndicesPrev, (8)*sizeof(UCHAR)); /* restore */
|
||||
self->sbrEnabled = self->sbrEnabledPrev;
|
||||
}
|
||||
}
|
||||
@ -1632,12 +1646,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,13 +1696,18 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
if ( flags&AACDEC_FLUSH ) {
|
||||
/* Clear pAacDecoderChannelInfo->pSpectralCoefficient because with AACDEC_FLUSH set it contains undefined data. */
|
||||
FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, sizeof(FIXP_DBL)*self->streamInfo.aacSamplesPerFrame);
|
||||
}
|
||||
|
||||
/*
|
||||
Conceal defective spectral data
|
||||
*/
|
||||
@ -1688,12 +1726,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 +1752,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 +1762,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;
|
||||
@ -1743,11 +1786,20 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
|
||||
);
|
||||
}
|
||||
|
||||
/* Add additional concealment delay */
|
||||
self->streamInfo.outputDelay += CConcealment_GetDelay(&self->concealCommonData) * self->streamInfo.aacSamplesPerFrame;
|
||||
|
||||
/* Map DRC data to StreamInfo structure */
|
||||
aacDecoder_drcGetInfo (
|
||||
self->hDrcInfo,
|
||||
&self->streamInfo.drcPresMode,
|
||||
&self->streamInfo.drcProgRefLev
|
||||
);
|
||||
|
||||
/* 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 +1809,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];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,6 +111,7 @@ amm-info@iis.fraunhofer.de
|
||||
#include "aacdec_drc.h"
|
||||
|
||||
#include "pcmutils_lib.h"
|
||||
#include "limiter.h"
|
||||
|
||||
|
||||
/* Capabilities flags */
|
||||
@ -176,27 +177,31 @@ 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 */
|
||||
|
||||
CConcealParams concealCommonData;
|
||||
INT concealChannels;
|
||||
|
||||
INT aacChannelsPrev; /*!< The amount of AAC core channels of the last successful decode call. */
|
||||
AUDIO_CHANNEL_TYPE channelTypePrev[(8)]; /*!< Array holding the channelType values of the last successful decode call. */
|
||||
UCHAR channelIndicesPrev[(8)]; /*!< Array holding the channelIndices values of the last successful decode call. */
|
||||
|
||||
|
||||
HANDLE_SBRDECODER hSbrDecoder; /*!< SBR decoder handle. */
|
||||
@ -214,6 +219,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. */
|
||||
|
||||
};
|
||||
|
||||
|
@ -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 10
|
||||
#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 */
|
||||
@ -768,6 +842,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
|
||||
/* Signal bit stream interruption to other modules if required. */
|
||||
if ( fTpInterruption || (flags & (AACDEC_INTR|AACDEC_CLRHIST)) )
|
||||
{
|
||||
sbrDecoder_SetParam(self->hSbrDecoder, SBR_CLEAR_HISTORY, (flags&AACDEC_CLRHIST));
|
||||
aacDecoder_SignalInterruption(self);
|
||||
if ( ! (flags & AACDEC_INTR) ) {
|
||||
ErrorStatus = AAC_DEC_TRANSPORT_SYNC_ERROR;
|
||||
@ -783,6 +858,19 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
|
||||
self->streamInfo.numBadBytes = 0;
|
||||
self->streamInfo.numTotalBytes = 0;
|
||||
}
|
||||
/* Reset the output delay field. The modules will add their figures one after another. */
|
||||
self->streamInfo.outputDelay = 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,
|
||||
@ -825,11 +913,15 @@ 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,
|
||||
SBR_SYSTEM_BITSTREAM_DELAY,
|
||||
self->sbrParams.bsDelay);
|
||||
sbrDecoder_SetParam ( self->hSbrDecoder,
|
||||
SBR_FLUSH_DATA,
|
||||
(flags & AACDEC_FLUSH) );
|
||||
|
||||
if ( self->streamInfo.aot == AOT_ER_AAC_ELD ) {
|
||||
/* Configure QMF */
|
||||
@ -838,7 +930,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,23 +947,29 @@ 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);
|
||||
|
||||
|
||||
if (sbrError == SBRDEC_OK) {
|
||||
#define UPS_SCALE 2 /* Maximum upsampling factor is 4 (CELP+SBR) */
|
||||
FIXP_DBL upsampleFactor = FL2FXCONST_DBL(1.0f/(1<<UPS_SCALE));
|
||||
|
||||
/* Update data in streaminfo structure. Assume that the SBR upsampling factor is either 1 or 2 */
|
||||
self->flags |= AC_SBR_PRESENT;
|
||||
if (self->streamInfo.aacSampleRate != self->streamInfo.sampleRate) {
|
||||
if (self->streamInfo.frameSize == 768) {
|
||||
self->streamInfo.frameSize = (self->streamInfo.aacSamplesPerFrame * 8) / 3;
|
||||
upsampleFactor = FL2FXCONST_DBL(8.0f/(3<<UPS_SCALE));
|
||||
} else {
|
||||
self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame << 1;
|
||||
upsampleFactor = FL2FXCONST_DBL(2.0f/(1<<UPS_SCALE));
|
||||
}
|
||||
}
|
||||
/* Apply upsampling factor to both the core frame length and the core delay */
|
||||
self->streamInfo.frameSize = (INT)fMult((FIXP_DBL)self->streamInfo.aacSamplesPerFrame<<UPS_SCALE, upsampleFactor);
|
||||
self->streamInfo.outputDelay = (UINT)(INT)fMult((FIXP_DBL)self->streamInfo.outputDelay<<UPS_SCALE, upsampleFactor);
|
||||
self->streamInfo.outputDelay += sbrDecoder_GetDelay( self->hSbrDecoder );
|
||||
|
||||
if (self->psPossible) {
|
||||
self->flags |= AC_PS_PRESENT;
|
||||
@ -870,19 +977,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 +998,39 @@ 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
|
||||
);
|
||||
|
||||
/* Announce the additional limiter output delay */
|
||||
self->streamInfo.outputDelay += getLimiterDelay(self->hLimiter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Signal interruption to take effect in next frame. */
|
||||
@ -917,6 +1055,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 );
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ amm-info@iis.fraunhofer.de
|
||||
|
||||
#else
|
||||
|
||||
#error >>>> Please set architecture characterization defines for your platform (FDK_HIGH_PERFORMANCE)! <<<<
|
||||
#warning >>>> Please set architecture characterization defines for your platform (FDK_HIGH_PERFORMANCE)! <<<<
|
||||
|
||||
#endif /* Architecture switches */
|
||||
|
||||
|
@ -96,7 +96,7 @@ amm-info@iis.fraunhofer.de
|
||||
#if defined(__CC_ARM) || defined(__arm__) || defined(_M_ARM) /* cppp replaced: elif */
|
||||
#include "arm/cplx_mul.h"
|
||||
|
||||
#elif defined(__GNUC__) && defined(__mips__) /* cppp replaced: elif */
|
||||
#elif defined(__GNUC__) && defined(__mips__) && __mips_isa_rev < 6
|
||||
#include "mips/cplx_mul.h"
|
||||
|
||||
#endif /* #if defined all cores: bfin, arm, etc. */
|
||||
|
@ -89,7 +89,7 @@ amm-info@iis.fraunhofer.de
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#if defined(__GNUC__) && defined(__mips__)
|
||||
#if defined(__GNUC__) && defined(__mips__) && __mips_isa_rev < 6
|
||||
|
||||
|
||||
//#define FUNCTION_cplxMultDiv2_32x16
|
||||
|
@ -146,12 +146,15 @@ typedef struct
|
||||
|
||||
UCHAR FrontElementIsCpe[PC_FSB_CHANNELS_MAX];
|
||||
UCHAR FrontElementTagSelect[PC_FSB_CHANNELS_MAX];
|
||||
UCHAR FrontElementHeightInfo[PC_FSB_CHANNELS_MAX];
|
||||
|
||||
UCHAR SideElementIsCpe[PC_FSB_CHANNELS_MAX];
|
||||
UCHAR SideElementTagSelect[PC_FSB_CHANNELS_MAX];
|
||||
UCHAR SideElementHeightInfo[PC_FSB_CHANNELS_MAX];
|
||||
|
||||
UCHAR BackElementIsCpe[PC_FSB_CHANNELS_MAX];
|
||||
UCHAR BackElementTagSelect[PC_FSB_CHANNELS_MAX];
|
||||
UCHAR BackElementHeightInfo[PC_FSB_CHANNELS_MAX];
|
||||
|
||||
UCHAR LfeElementTagSelect[PC_LFE_CHANNELS_MAX];
|
||||
|
||||
@ -324,16 +327,23 @@ int getSamplingRateIndex( UINT samplingRate )
|
||||
*/
|
||||
static inline int getNumberOfTotalChannels(int channelConfig)
|
||||
{
|
||||
if (channelConfig > 0 && channelConfig < 8)
|
||||
return (channelConfig == 7)?8:channelConfig;
|
||||
else
|
||||
switch (channelConfig) {
|
||||
case 1: case 2: case 3:
|
||||
case 4: case 5: case 6:
|
||||
return channelConfig;
|
||||
case 7: case 12: case 14:
|
||||
return 8;
|
||||
case 11:
|
||||
return 7;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline
|
||||
int getNumberOfEffectiveChannels(const int channelConfig)
|
||||
{
|
||||
const int n[] = {0,1,2,3,4,5,5,7};
|
||||
{ /* index: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 */
|
||||
const int n[] = {0,1,2,3,4,5,5,7,0,0, 0, 6, 7, 0, 7, 0};
|
||||
return n[channelConfig];
|
||||
}
|
||||
|
||||
|
@ -151,6 +151,7 @@ typedef enum {
|
||||
#define PC_ASSOCDATA_MAX 8
|
||||
#define PC_CCEL_MAX 16 /* CC elements */
|
||||
#define PC_COMMENTLENGTH 256
|
||||
#define PC_NUM_HEIGHT_LAYER 3
|
||||
|
||||
|
||||
/*!
|
||||
@ -239,14 +240,20 @@ int CProgramConfig_LookupElement(
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Get table of elements in canonical order.
|
||||
* \param pPce A valid program config structure.
|
||||
* \param table An array where the element IDs are stored.
|
||||
* \return Total element count including all SCE, CPE and LFE.
|
||||
* \brief Get table of elements in canonical order from a
|
||||
* give program config field.
|
||||
* \param pPce A valid program config structure.
|
||||
* \param table An array where the element IDs are stored.
|
||||
* \param elListSize The length of the table array.
|
||||
* \param pChMapIdx Pointer to a field receiving the corresponding
|
||||
* implicit channel configuration index of the given
|
||||
* PCE. If none can be found it receives the value 0.
|
||||
* \return Total element count including all SCE, CPE and LFE.
|
||||
*/
|
||||
int CProgramConfig_GetElementTable( const CProgramConfig *pPce,
|
||||
MP4_ELEMENT_ID table[],
|
||||
const INT elListSize );
|
||||
const INT elListSize,
|
||||
UCHAR *pChMapIdx );
|
||||
|
||||
/**
|
||||
* \brief Initialize a given AudioSpecificConfig structure.
|
||||
|
@ -90,6 +90,9 @@ amm-info@iis.fraunhofer.de
|
||||
|
||||
#include "tpdec_lib.h"
|
||||
#include "tp_data.h"
|
||||
#ifdef TP_PCE_ENABLE
|
||||
#include "FDK_crc.h"
|
||||
#endif
|
||||
|
||||
|
||||
void CProgramConfig_Reset(CProgramConfig *pPce)
|
||||
@ -111,13 +114,75 @@ int CProgramConfig_IsValid ( const CProgramConfig *pPce )
|
||||
}
|
||||
|
||||
#ifdef TP_PCE_ENABLE
|
||||
#define PCE_HEIGHT_EXT_SYNC ( 0xAC )
|
||||
|
||||
/*
|
||||
* Read the extension for height info.
|
||||
* return 0 if successfull or -1 if the CRC failed.
|
||||
*/
|
||||
static
|
||||
int CProgramConfig_ReadHeightExt(
|
||||
CProgramConfig *pPce,
|
||||
HANDLE_FDK_BITSTREAM bs,
|
||||
int * const bytesAvailable,
|
||||
const UINT alignmentAnchor
|
||||
)
|
||||
{
|
||||
int err = 0;
|
||||
FDK_CRCINFO crcInfo; /* CRC state info */
|
||||
INT crcReg;
|
||||
FDKcrcInit(&crcInfo, 0x07, 0xFF, 8);
|
||||
crcReg = FDKcrcStartReg(&crcInfo, bs, 0);
|
||||
UINT startAnchor = FDKgetValidBits(bs);
|
||||
|
||||
FDK_ASSERT(pPce != NULL);
|
||||
FDK_ASSERT(bs != NULL);
|
||||
FDK_ASSERT(bytesAvailable != NULL);
|
||||
|
||||
if ( (startAnchor >= 24) && (*bytesAvailable >= 3)
|
||||
&& (FDKreadBits(bs,8) == PCE_HEIGHT_EXT_SYNC) )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < pPce->NumFrontChannelElements; i++)
|
||||
{
|
||||
pPce->FrontElementHeightInfo[i] = (UCHAR) FDKreadBits(bs,2);
|
||||
}
|
||||
for (i=0; i < pPce->NumSideChannelElements; i++)
|
||||
{
|
||||
pPce->SideElementHeightInfo[i] = (UCHAR) FDKreadBits(bs,2);
|
||||
}
|
||||
for (i=0; i < pPce->NumBackChannelElements; i++)
|
||||
{
|
||||
pPce->BackElementHeightInfo[i] = (UCHAR) FDKreadBits(bs,2);
|
||||
}
|
||||
FDKbyteAlign(bs, alignmentAnchor);
|
||||
|
||||
FDKcrcEndReg(&crcInfo, bs, crcReg);
|
||||
if ((USHORT)FDKreadBits(bs,8) != FDKcrcGetCRC(&crcInfo)) {
|
||||
/* CRC failed */
|
||||
err = -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* No valid extension data found -> restore the initial bitbuffer state */
|
||||
FDKpushBack(bs, startAnchor - FDKgetValidBits(bs));
|
||||
}
|
||||
|
||||
/* Always report the bytes read. */
|
||||
*bytesAvailable -= (startAnchor - FDKgetValidBits(bs)) >> 3;
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
void CProgramConfig_Read(
|
||||
CProgramConfig *pPce,
|
||||
HANDLE_FDK_BITSTREAM bs,
|
||||
UINT alignmentAnchor
|
||||
)
|
||||
{
|
||||
int i;
|
||||
int i, err = 0;
|
||||
int commentBytes;
|
||||
|
||||
pPce->NumEffectiveChannels = 0;
|
||||
pPce->NumChannels = 0;
|
||||
@ -190,8 +255,12 @@ void CProgramConfig_Read(
|
||||
FDKbyteAlign(bs, alignmentAnchor);
|
||||
|
||||
pPce->CommentFieldBytes = (UCHAR) FDKreadBits(bs,8);
|
||||
commentBytes = pPce->CommentFieldBytes;
|
||||
|
||||
for (i=0; i < pPce->CommentFieldBytes; i++)
|
||||
/* Search for height info extension and read it if available */
|
||||
err = CProgramConfig_ReadHeightExt( pPce, bs, &commentBytes, alignmentAnchor );
|
||||
|
||||
for (i=0; i < commentBytes; i++)
|
||||
{
|
||||
UCHAR text;
|
||||
|
||||
@ -203,7 +272,7 @@ void CProgramConfig_Read(
|
||||
}
|
||||
}
|
||||
|
||||
pPce->isValid = 1;
|
||||
pPce->isValid = (err) ? 0 : 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -235,6 +304,10 @@ int CProgramConfig_Compare ( const CProgramConfig * const pPce1,
|
||||
} else {
|
||||
int el, numCh1 = 0, numCh2 = 0;
|
||||
for (el = 0; el < pPce1->NumFrontChannelElements; el += 1) {
|
||||
if (pPce1->FrontElementHeightInfo[el] != pPce2->FrontElementHeightInfo[el]) {
|
||||
result = 2; /* different height info */
|
||||
break;
|
||||
}
|
||||
numCh1 += pPce1->FrontElementIsCpe[el] ? 2 : 1;
|
||||
numCh2 += pPce2->FrontElementIsCpe[el] ? 2 : 1;
|
||||
}
|
||||
@ -248,6 +321,10 @@ int CProgramConfig_Compare ( const CProgramConfig * const pPce1,
|
||||
} else {
|
||||
int el, numCh1 = 0, numCh2 = 0;
|
||||
for (el = 0; el < pPce1->NumSideChannelElements; el += 1) {
|
||||
if (pPce1->SideElementHeightInfo[el] != pPce2->SideElementHeightInfo[el]) {
|
||||
result = 2; /* different height info */
|
||||
break;
|
||||
}
|
||||
numCh1 += pPce1->SideElementIsCpe[el] ? 2 : 1;
|
||||
numCh2 += pPce2->SideElementIsCpe[el] ? 2 : 1;
|
||||
}
|
||||
@ -261,6 +338,10 @@ int CProgramConfig_Compare ( const CProgramConfig * const pPce1,
|
||||
} else {
|
||||
int el, numCh1 = 0, numCh2 = 0;
|
||||
for (el = 0; el < pPce1->NumBackChannelElements; el += 1) {
|
||||
if (pPce1->BackElementHeightInfo[el] != pPce2->BackElementHeightInfo[el]) {
|
||||
result = 2; /* different height info */
|
||||
break;
|
||||
}
|
||||
numCh1 += pPce1->BackElementIsCpe[el] ? 2 : 1;
|
||||
numCh2 += pPce2->BackElementIsCpe[el] ? 2 : 1;
|
||||
}
|
||||
@ -290,6 +371,44 @@ void CProgramConfig_GetDefault( CProgramConfig *pPce,
|
||||
|
||||
switch (channelConfig) {
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
case 32: /* 7.1 side channel configuration as defined in FDK_audio.h */
|
||||
pPce->NumFrontChannelElements = 2;
|
||||
pPce->FrontElementIsCpe[0] = 0;
|
||||
pPce->FrontElementIsCpe[1] = 1;
|
||||
pPce->NumSideChannelElements = 1;
|
||||
pPce->SideElementIsCpe[0] = 1;
|
||||
pPce->NumBackChannelElements = 1;
|
||||
pPce->BackElementIsCpe[0] = 1;
|
||||
pPce->NumLfeChannelElements = 1;
|
||||
pPce->NumChannels = 8;
|
||||
pPce->NumEffectiveChannels = 7;
|
||||
pPce->isValid = 1;
|
||||
break;
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
case 12: /* 3/0/4.1ch surround back */
|
||||
pPce->BackElementIsCpe[1] = 1;
|
||||
pPce->NumChannels += 1;
|
||||
pPce->NumEffectiveChannels += 1;
|
||||
case 11: /* 3/0/3.1ch */
|
||||
pPce->NumFrontChannelElements += 2;
|
||||
pPce->FrontElementIsCpe[0] = 0;
|
||||
pPce->FrontElementIsCpe[1] = 1;
|
||||
pPce->NumBackChannelElements += 2;
|
||||
pPce->BackElementIsCpe[0] = 1;
|
||||
pPce->BackElementIsCpe[1] += 0;
|
||||
pPce->NumLfeChannelElements += 1;
|
||||
pPce->NumChannels += 7;
|
||||
pPce->NumEffectiveChannels += 6;
|
||||
pPce->isValid = 1;
|
||||
break;
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
case 14: /* 2/0/0-3/0/2-0.1ch front height */
|
||||
pPce->FrontElementHeightInfo[2] = 1; /* Top speaker */
|
||||
case 7: /* 5/0/2.1ch front */
|
||||
pPce->NumFrontChannelElements += 1;
|
||||
pPce->FrontElementIsCpe[2] = 1;
|
||||
pPce->NumChannels += 2;
|
||||
pPce->NumEffectiveChannels += 2;
|
||||
case 6: /* 3/0/2.1ch */
|
||||
pPce->NumLfeChannelElements += 1;
|
||||
pPce->NumChannels += 1;
|
||||
@ -348,10 +467,11 @@ void CProgramConfig_GetDefault( CProgramConfig *pPce,
|
||||
|
||||
/**
|
||||
* \brief get implicit audio channel type for given channelConfig and MPEG ordered channel index
|
||||
* \param channelConfig MPEG channelConfiguration from 1 upto 7
|
||||
* \param channelConfig MPEG channelConfiguration from 1 upto 14
|
||||
* \param index MPEG channel order index
|
||||
* \return audio channel type.
|
||||
*/
|
||||
static
|
||||
void getImplicitAudioChannelTypeAndIndex(
|
||||
AUDIO_CHANNEL_TYPE *chType,
|
||||
UCHAR *chIndex,
|
||||
@ -364,9 +484,9 @@ void getImplicitAudioChannelTypeAndIndex(
|
||||
*chIndex = index;
|
||||
} else {
|
||||
switch (channelConfig) {
|
||||
case MODE_1_2_1:
|
||||
case MODE_1_2_2:
|
||||
case MODE_1_2_2_1:
|
||||
case 4: /* SCE, CPE, SCE */
|
||||
case 5: /* SCE, CPE, CPE */
|
||||
case 6: /* SCE, CPE, CPE, LFE */
|
||||
switch (index) {
|
||||
case 3:
|
||||
case 4:
|
||||
@ -379,12 +499,12 @@ void getImplicitAudioChannelTypeAndIndex(
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MODE_1_2_2_2_1:
|
||||
case 7: /* SCE,CPE,CPE,CPE,LFE */
|
||||
switch (index) {
|
||||
case 3:
|
||||
case 4:
|
||||
*chType = ACT_SIDE;
|
||||
*chIndex = index - 3;
|
||||
*chType = ACT_FRONT;
|
||||
*chIndex = index;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
@ -397,6 +517,42 @@ void getImplicitAudioChannelTypeAndIndex(
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 11: /* SCE,CPE,CPE,SCE,LFE */
|
||||
if (index < 6) {
|
||||
*chType = ACT_BACK;
|
||||
*chIndex = index - 3;
|
||||
} else {
|
||||
*chType = ACT_LFE;
|
||||
*chIndex = 0;
|
||||
}
|
||||
break;
|
||||
case 12: /* SCE,CPE,CPE,CPE,LFE */
|
||||
if (index < 7) {
|
||||
*chType = ACT_BACK;
|
||||
*chIndex = index - 3;
|
||||
} else {
|
||||
*chType = ACT_LFE;
|
||||
*chIndex = 0;
|
||||
}
|
||||
break;
|
||||
case 14: /* SCE,CPE,CPE,LFE,CPE */
|
||||
switch (index) {
|
||||
case 3:
|
||||
case 4:
|
||||
*chType = ACT_BACK;
|
||||
*chIndex = index - 3;
|
||||
break;
|
||||
case 5:
|
||||
*chType = ACT_LFE;
|
||||
*chIndex = 0;
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
*chType = ACT_FRONT_TOP;
|
||||
*chIndex = index - 6; /* handle the top layer independently */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*chType = ACT_NONE;
|
||||
break;
|
||||
@ -467,7 +623,24 @@ int CProgramConfig_LookupElement(
|
||||
else {
|
||||
/* Accept the additional channel(s), only if the tag is in the lists */
|
||||
int isCpe = 0, i;
|
||||
int cc = 0, fc = 0, sc = 0, bc = 0, lc = 0, ec = 0; /* Channel and element counters */
|
||||
/* Element counter */
|
||||
int ec[PC_NUM_HEIGHT_LAYER] = {0};
|
||||
/* Channel counters */
|
||||
int cc[PC_NUM_HEIGHT_LAYER] = {0};
|
||||
int fc[PC_NUM_HEIGHT_LAYER] = {0};
|
||||
int sc[PC_NUM_HEIGHT_LAYER] = {0};
|
||||
int bc[PC_NUM_HEIGHT_LAYER] = {0};
|
||||
int lc = 0;;
|
||||
|
||||
/* General MPEG (PCE) composition rules:
|
||||
- Over all:
|
||||
<normal height channels><top height channels><bottom height channels>
|
||||
- Within each height layer:
|
||||
<front channels><side channels><back channels>
|
||||
- Exception:
|
||||
The LFE channels have no height info and thus they are arranged at the very
|
||||
end of the normal height layer channels.
|
||||
*/
|
||||
|
||||
switch (elType)
|
||||
{
|
||||
@ -476,87 +649,206 @@ int CProgramConfig_LookupElement(
|
||||
case ID_SCE:
|
||||
/* search in front channels */
|
||||
for (i = 0; i < pPce->NumFrontChannelElements; i++) {
|
||||
int heightLayer = pPce->FrontElementHeightInfo[i];
|
||||
if (isCpe == pPce->FrontElementIsCpe[i] && pPce->FrontElementTagSelect[i] == tag) {
|
||||
chMapping[cc] = channelIdx;
|
||||
chType[cc] = ACT_FRONT;
|
||||
chIndex[cc] = fc;
|
||||
if (isCpe) {
|
||||
chMapping[cc+1] = channelIdx+1;
|
||||
chType[cc+1] = ACT_FRONT;
|
||||
chIndex[cc+1] = fc+1;
|
||||
int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer];
|
||||
AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_FRONT);
|
||||
for (h = heightLayer-1; h >= 0; h-=1) {
|
||||
int el;
|
||||
/* Count front channels/elements */
|
||||
for (el = 0; el < pPce->NumFrontChannelElements; el+=1) {
|
||||
if (pPce->FrontElementHeightInfo[el] == h) {
|
||||
elIdx += 1;
|
||||
chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1;
|
||||
}
|
||||
}
|
||||
/* Count side channels/elements */
|
||||
for (el = 0; el < pPce->NumSideChannelElements; el+=1) {
|
||||
if (pPce->SideElementHeightInfo[el] == h) {
|
||||
elIdx += 1;
|
||||
chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1;
|
||||
}
|
||||
}
|
||||
/* Count back channels/elements */
|
||||
for (el = 0; el < pPce->NumBackChannelElements; el+=1) {
|
||||
if (pPce->BackElementHeightInfo[el] == h) {
|
||||
elIdx += 1;
|
||||
chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1;
|
||||
}
|
||||
}
|
||||
if (h == 0) { /* normal height */
|
||||
elIdx += pPce->NumLfeChannelElements;
|
||||
chIdx += pPce->NumLfeChannelElements;
|
||||
}
|
||||
}
|
||||
*elMapping = ec;
|
||||
chMapping[chIdx] = channelIdx;
|
||||
chType[chIdx] = aChType;
|
||||
chIndex[chIdx] = fc[heightLayer];
|
||||
if (isCpe) {
|
||||
chMapping[chIdx+1] = channelIdx+1;
|
||||
chType[chIdx+1] = aChType;
|
||||
chIndex[chIdx+1] = fc[heightLayer]+1;
|
||||
}
|
||||
*elMapping = elIdx;
|
||||
return 1;
|
||||
}
|
||||
ec++;
|
||||
ec[heightLayer] += 1;
|
||||
if (pPce->FrontElementIsCpe[i]) {
|
||||
cc+=2; fc+=2;
|
||||
cc[heightLayer] += 2;
|
||||
fc[heightLayer] += 2;
|
||||
} else {
|
||||
cc++; fc++;
|
||||
cc[heightLayer] += 1;
|
||||
fc[heightLayer] += 1;
|
||||
}
|
||||
}
|
||||
/* search in side channels */
|
||||
for (i = 0; i < pPce->NumSideChannelElements; i++) {
|
||||
int heightLayer = pPce->SideElementHeightInfo[i];
|
||||
if (isCpe == pPce->SideElementIsCpe[i] && pPce->SideElementTagSelect[i] == tag) {
|
||||
chMapping[cc] = channelIdx;
|
||||
chType[cc] = ACT_SIDE;
|
||||
chIndex[cc] = sc;
|
||||
if (isCpe) {
|
||||
chMapping[cc+1] = channelIdx+1;
|
||||
chType[cc+1] = ACT_SIDE;
|
||||
chIndex[cc+1] = sc+1;
|
||||
int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer];
|
||||
AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_SIDE);
|
||||
for (h = heightLayer-1; h >= 0; h-=1) {
|
||||
int el;
|
||||
/* Count front channels/elements */
|
||||
for (el = 0; el < pPce->NumFrontChannelElements; el+=1) {
|
||||
if (pPce->FrontElementHeightInfo[el] == h) {
|
||||
elIdx += 1;
|
||||
chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1;
|
||||
}
|
||||
}
|
||||
/* Count side channels/elements */
|
||||
for (el = 0; el < pPce->NumSideChannelElements; el+=1) {
|
||||
if (pPce->SideElementHeightInfo[el] == h) {
|
||||
elIdx += 1;
|
||||
chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1;
|
||||
}
|
||||
}
|
||||
/* Count back channels/elements */
|
||||
for (el = 0; el < pPce->NumBackChannelElements; el+=1) {
|
||||
if (pPce->BackElementHeightInfo[el] == h) {
|
||||
elIdx += 1;
|
||||
chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1;
|
||||
}
|
||||
}
|
||||
if (h == 0) { /* LFE channels belong to the normal height layer */
|
||||
elIdx += pPce->NumLfeChannelElements;
|
||||
chIdx += pPce->NumLfeChannelElements;
|
||||
}
|
||||
}
|
||||
*elMapping = ec;
|
||||
chMapping[chIdx] = channelIdx;
|
||||
chType[chIdx] = aChType;
|
||||
chIndex[chIdx] = sc[heightLayer];
|
||||
if (isCpe) {
|
||||
chMapping[chIdx+1] = channelIdx+1;
|
||||
chType[chIdx+1] = aChType;
|
||||
chIndex[chIdx+1] = sc[heightLayer]+1;
|
||||
}
|
||||
*elMapping = elIdx;
|
||||
return 1;
|
||||
}
|
||||
ec++;
|
||||
ec[heightLayer] += 1;
|
||||
if (pPce->SideElementIsCpe[i]) {
|
||||
cc+=2; sc+=2;
|
||||
cc[heightLayer] += 2;
|
||||
sc[heightLayer] += 2;
|
||||
} else {
|
||||
cc++; sc++;
|
||||
cc[heightLayer] += 1;
|
||||
sc[heightLayer] += 1;
|
||||
}
|
||||
}
|
||||
/* search in back channels */
|
||||
for (i = 0; i < pPce->NumBackChannelElements; i++) {
|
||||
int heightLayer = pPce->BackElementHeightInfo[i];
|
||||
if (isCpe == pPce->BackElementIsCpe[i] && pPce->BackElementTagSelect[i] == tag) {
|
||||
chMapping[cc] = channelIdx;
|
||||
chType[cc] = ACT_BACK;
|
||||
chIndex[cc] = bc;
|
||||
if (isCpe) {
|
||||
chMapping[cc+1] = channelIdx+1;
|
||||
chType[cc+1] = ACT_BACK;
|
||||
chIndex[cc+1] = bc+1;
|
||||
int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer];
|
||||
AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_BACK);
|
||||
for (h = heightLayer-1; h >= 0; h-=1) {
|
||||
int el;
|
||||
/* Count front channels/elements */
|
||||
for (el = 0; el < pPce->NumFrontChannelElements; el+=1) {
|
||||
if (pPce->FrontElementHeightInfo[el] == h) {
|
||||
elIdx += 1;
|
||||
chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1;
|
||||
}
|
||||
}
|
||||
/* Count side channels/elements */
|
||||
for (el = 0; el < pPce->NumSideChannelElements; el+=1) {
|
||||
if (pPce->SideElementHeightInfo[el] == h) {
|
||||
elIdx += 1;
|
||||
chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1;
|
||||
}
|
||||
}
|
||||
/* Count back channels/elements */
|
||||
for (el = 0; el < pPce->NumBackChannelElements; el+=1) {
|
||||
if (pPce->BackElementHeightInfo[el] == h) {
|
||||
elIdx += 1;
|
||||
chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1;
|
||||
}
|
||||
}
|
||||
if (h == 0) { /* normal height */
|
||||
elIdx += pPce->NumLfeChannelElements;
|
||||
chIdx += pPce->NumLfeChannelElements;
|
||||
}
|
||||
}
|
||||
*elMapping = ec;
|
||||
chMapping[chIdx] = channelIdx;
|
||||
chType[chIdx] = aChType;
|
||||
chIndex[chIdx] = bc[heightLayer];
|
||||
if (isCpe) {
|
||||
chMapping[chIdx+1] = channelIdx+1;
|
||||
chType[chIdx+1] = aChType;
|
||||
chIndex[chIdx+1] = bc[heightLayer]+1;
|
||||
}
|
||||
*elMapping = elIdx;
|
||||
return 1;
|
||||
}
|
||||
ec++;
|
||||
ec[heightLayer] += 1;
|
||||
if (pPce->BackElementIsCpe[i]) {
|
||||
cc+=2; bc+=2;
|
||||
cc[heightLayer] += 2;
|
||||
bc[heightLayer] += 2;
|
||||
} else {
|
||||
cc++; bc++;
|
||||
cc[heightLayer] += 1;
|
||||
bc[heightLayer] += 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_LFE:
|
||||
/* Initialize channel counter and element counter */
|
||||
cc = pPce->NumEffectiveChannels;
|
||||
ec = pPce->NumFrontChannelElements+ pPce->NumSideChannelElements + pPce->NumBackChannelElements;
|
||||
{ /* Unfortunately we have to go through all normal height
|
||||
layer elements to get the position of the LFE channels.
|
||||
Start with counting the front channels/elements at normal height */
|
||||
for (i = 0; i < pPce->NumFrontChannelElements; i+=1) {
|
||||
int heightLayer = pPce->FrontElementHeightInfo[i];
|
||||
ec[heightLayer] += 1;
|
||||
cc[heightLayer] += (pPce->FrontElementIsCpe[i]) ? 2 : 1;
|
||||
}
|
||||
/* Count side channels/elements at normal height */
|
||||
for (i = 0; i < pPce->NumSideChannelElements; i+=1) {
|
||||
int heightLayer = pPce->SideElementHeightInfo[i];
|
||||
ec[heightLayer] += 1;
|
||||
cc[heightLayer] += (pPce->SideElementIsCpe[i]) ? 2 : 1;
|
||||
}
|
||||
/* Count back channels/elements at normal height */
|
||||
for (i = 0; i < pPce->NumBackChannelElements; i+=1) {
|
||||
int heightLayer = pPce->BackElementHeightInfo[i];
|
||||
ec[heightLayer] += 1;
|
||||
cc[heightLayer] += (pPce->BackElementIsCpe[i]) ? 2 : 1;
|
||||
}
|
||||
|
||||
/* search in lfe channels */
|
||||
for (i = 0; i < pPce->NumLfeChannelElements; i++) {
|
||||
int elIdx = ec[0]; /* LFE channels belong to the normal height layer */
|
||||
int chIdx = cc[0];
|
||||
if ( pPce->LfeElementTagSelect[i] == tag ) {
|
||||
chMapping[cc] = channelIdx;
|
||||
*elMapping = ec;
|
||||
chType[cc] = ACT_LFE;
|
||||
chIndex[cc] = lc;
|
||||
chMapping[chIdx] = channelIdx;
|
||||
*elMapping = elIdx;
|
||||
chType[chIdx] = ACT_LFE;
|
||||
chIndex[chIdx] = lc;
|
||||
return 1;
|
||||
}
|
||||
ec++;
|
||||
cc++;
|
||||
lc++;
|
||||
ec[0] += 1;
|
||||
cc[0] += 1;
|
||||
lc += 1;
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
/* Non audio elements */
|
||||
case ID_CCE:
|
||||
@ -590,13 +882,19 @@ int CProgramConfig_LookupElement(
|
||||
int CProgramConfig_GetElementTable(
|
||||
const CProgramConfig *pPce,
|
||||
MP4_ELEMENT_ID elList[],
|
||||
const INT elListSize
|
||||
const INT elListSize,
|
||||
UCHAR *pChMapIdx
|
||||
)
|
||||
{
|
||||
int i, el = 0;
|
||||
|
||||
if ( elListSize
|
||||
< pPce->NumFrontChannelElements + pPce->NumSideChannelElements + pPce->NumBackChannelElements + pPce->NumLfeChannelElements
|
||||
FDK_ASSERT(elList != NULL);
|
||||
FDK_ASSERT(pChMapIdx != NULL);
|
||||
|
||||
*pChMapIdx = 0;
|
||||
|
||||
if ( elListSize
|
||||
< pPce->NumFrontChannelElements + pPce->NumSideChannelElements + pPce->NumBackChannelElements + pPce->NumLfeChannelElements
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
@ -623,6 +921,47 @@ int CProgramConfig_GetElementTable(
|
||||
}
|
||||
|
||||
|
||||
/* Find an corresponding channel configuration if possible */
|
||||
switch (pPce->NumChannels) {
|
||||
case 1: case 2: case 3: case 4: case 5: case 6:
|
||||
/* One and two channels have no alternatives. The other ones are mapped directly to the
|
||||
corresponding channel config. Because of legacy reasons or for lack of alternative mappings. */
|
||||
*pChMapIdx = pPce->NumChannels;
|
||||
break;
|
||||
case 7:
|
||||
{
|
||||
C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1);
|
||||
/* Create a PCE for the config to test ... */
|
||||
CProgramConfig_GetDefault(tmpPce, 11);
|
||||
/* ... and compare it with the given one. */
|
||||
*pChMapIdx = (!(CProgramConfig_Compare(pPce, tmpPce)&0xE)) ? 11 : 0;
|
||||
/* If compare result is 0 or 1 we can be sure that it is channel config 11. */
|
||||
C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1);
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
{ /* Try the four possible 7.1ch configurations. One after the other. */
|
||||
UCHAR testCfg[4] = { 32, 14, 12, 7};
|
||||
C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1);
|
||||
for (i=0; i<4; i+=1) {
|
||||
/* Create a PCE for the config to test ... */
|
||||
CProgramConfig_GetDefault(tmpPce, testCfg[i]);
|
||||
/* ... and compare it with the given one. */
|
||||
if (!(CProgramConfig_Compare(pPce, tmpPce)&0xE)) {
|
||||
/* If the compare result is 0 or 1 than the two channel configurations match. */
|
||||
/* Explicit mapping of 7.1 side channel configuration to 7.1 rear channel mapping. */
|
||||
*pChMapIdx = (testCfg[i]==32) ? 12 : testCfg[i];
|
||||
}
|
||||
}
|
||||
C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* The PCE does not match any predefined channel configuration. */
|
||||
*pChMapIdx = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return el;
|
||||
}
|
||||
#endif
|
||||
@ -714,7 +1053,7 @@ TRANSPORTDEC_ERROR GaSpecificConfig_Parse( CSGaSpecificConfig *self,
|
||||
#ifdef TP_ELD_ENABLE
|
||||
|
||||
static INT ld_sbr_header( const CSAudioSpecificConfig *asc,
|
||||
HANDLE_FDK_BITSTREAM hBs,
|
||||
HANDLE_FDK_BITSTREAM hBs,
|
||||
CSTpCallBacks *cb )
|
||||
{
|
||||
const int channelConfiguration = asc->m_channelConfiguration;
|
||||
@ -728,6 +1067,8 @@ static INT ld_sbr_header( const CSAudioSpecificConfig *asc,
|
||||
}
|
||||
|
||||
switch ( channelConfiguration ) {
|
||||
case 14:
|
||||
case 12:
|
||||
case 7:
|
||||
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++);
|
||||
case 6:
|
||||
@ -737,6 +1078,8 @@ static INT ld_sbr_header( const CSAudioSpecificConfig *asc,
|
||||
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++);
|
||||
break;
|
||||
|
||||
case 11:
|
||||
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++);
|
||||
case 4:
|
||||
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++);
|
||||
error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_SCE, i++);
|
||||
@ -802,24 +1145,6 @@ TRANSPORTDEC_ERROR EldSpecificConfig_Parse(
|
||||
}
|
||||
|
||||
switch (eldExtType) {
|
||||
case ELDEXT_LDSAC:
|
||||
esc->m_useLdQmfTimeAlign = 1;
|
||||
if (cb->cbSsc != NULL) {
|
||||
ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbSsc(
|
||||
cb->cbSscData,
|
||||
hBs,
|
||||
asc->m_aot,
|
||||
asc->m_samplingFrequency,
|
||||
1, /* muxMode */
|
||||
len
|
||||
);
|
||||
} else {
|
||||
ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT;
|
||||
}
|
||||
if (ErrorStatus != TRANSPORTDEC_OK) {
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
for(cnt=0; cnt<len; cnt++) {
|
||||
FDKreadBits(hBs, 8 );
|
||||
|
@ -2,7 +2,7 @@
|
||||
/* library info */
|
||||
#define TP_LIB_VL0 2
|
||||
#define TP_LIB_VL1 3
|
||||
#define TP_LIB_VL2 3
|
||||
#define TP_LIB_VL2 4
|
||||
#define TP_LIB_TITLE "MPEG Transport"
|
||||
#define TP_LIB_BUILD_DATE __DATE__
|
||||
#define TP_LIB_BUILD_TIME __TIME__
|
||||
|
@ -146,12 +146,15 @@ typedef struct
|
||||
|
||||
UCHAR FrontElementIsCpe[PC_FSB_CHANNELS_MAX];
|
||||
UCHAR FrontElementTagSelect[PC_FSB_CHANNELS_MAX];
|
||||
UCHAR FrontElementHeightInfo[PC_FSB_CHANNELS_MAX];
|
||||
|
||||
UCHAR SideElementIsCpe[PC_FSB_CHANNELS_MAX];
|
||||
UCHAR SideElementTagSelect[PC_FSB_CHANNELS_MAX];
|
||||
UCHAR SideElementHeightInfo[PC_FSB_CHANNELS_MAX];
|
||||
|
||||
UCHAR BackElementIsCpe[PC_FSB_CHANNELS_MAX];
|
||||
UCHAR BackElementTagSelect[PC_FSB_CHANNELS_MAX];
|
||||
UCHAR BackElementHeightInfo[PC_FSB_CHANNELS_MAX];
|
||||
|
||||
UCHAR LfeElementTagSelect[PC_LFE_CHANNELS_MAX];
|
||||
|
||||
@ -324,16 +327,23 @@ int getSamplingRateIndex( UINT samplingRate )
|
||||
*/
|
||||
static inline int getNumberOfTotalChannels(int channelConfig)
|
||||
{
|
||||
if (channelConfig > 0 && channelConfig < 8)
|
||||
return (channelConfig == 7)?8:channelConfig;
|
||||
else
|
||||
switch (channelConfig) {
|
||||
case 1: case 2: case 3:
|
||||
case 4: case 5: case 6:
|
||||
return channelConfig;
|
||||
case 7: case 12: case 14:
|
||||
return 8;
|
||||
case 11:
|
||||
return 7;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline
|
||||
int getNumberOfEffectiveChannels(const int channelConfig)
|
||||
{
|
||||
const int n[] = {0,1,2,3,4,5,5,7};
|
||||
{ /* index: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 */
|
||||
const int n[] = {0,1,2,3,4,5,5,7,0,0, 0, 6, 7, 0, 7, 0};
|
||||
return n[channelConfig];
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
/* library info */
|
||||
#define TP_LIB_VL0 2
|
||||
#define TP_LIB_VL1 3
|
||||
#define TP_LIB_VL2 3
|
||||
#define TP_LIB_VL2 4
|
||||
#define TP_LIB_TITLE "MPEG Transport"
|
||||
#define TP_LIB_BUILD_DATE __DATE__
|
||||
#define TP_LIB_BUILD_TIME __TIME__
|
||||
|
233
libPCMutils/include/limiter.h
Normal file
233
libPCMutils/include/limiter.h
Normal file
@ -0,0 +1,233 @@
|
||||
|
||||
/* -----------------------------------------------------------------------------------------------------------
|
||||
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
|
||||
----------------------------------------------------------------------------------------------------------- */
|
||||
|
||||
/************************ FDK PCM postprocessor module *********************
|
||||
|
||||
Author(s): Matthias Neusinger
|
||||
Description: Hard limiter for clipping prevention
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _LIMITER_H_
|
||||
#define _LIMITER_H_
|
||||
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#define TDL_ATTACK_DEFAULT_MS (15) /* default attack time in ms */
|
||||
#define TDL_RELEASE_DEFAULT_MS (50) /* default release time in ms */
|
||||
|
||||
#define TDL_GAIN_SCALING (15) /* scaling of gain value. */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum {
|
||||
TDLIMIT_OK = 0,
|
||||
|
||||
__error_codes_start = -100,
|
||||
|
||||
TDLIMIT_INVALID_HANDLE,
|
||||
TDLIMIT_INVALID_PARAMETER,
|
||||
|
||||
__error_codes_end
|
||||
} TDLIMITER_ERROR;
|
||||
|
||||
struct TDLimiter;
|
||||
typedef struct TDLimiter* TDLimiterPtr;
|
||||
|
||||
/******************************************************************************
|
||||
* createLimiter *
|
||||
* maxAttackMs: maximum and initial attack/lookahead time in milliseconds *
|
||||
* releaseMs: release time in milliseconds (90% time constant) *
|
||||
* threshold: limiting threshold *
|
||||
* maxChannels: maximum and initial number of channels *
|
||||
* maxSampleRate: maximum and initial sampling rate in Hz *
|
||||
* returns: limiter handle *
|
||||
******************************************************************************/
|
||||
TDLimiterPtr createLimiter(unsigned int maxAttackMs,
|
||||
unsigned int releaseMs,
|
||||
INT_PCM threshold,
|
||||
unsigned int maxChannels,
|
||||
unsigned int maxSampleRate);
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* resetLimiter *
|
||||
* limiter: limiter handle *
|
||||
* returns: error code *
|
||||
******************************************************************************/
|
||||
TDLIMITER_ERROR resetLimiter(TDLimiterPtr limiter);
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* destroyLimiter *
|
||||
* limiter: limiter handle *
|
||||
* returns: error code *
|
||||
******************************************************************************/
|
||||
TDLIMITER_ERROR destroyLimiter(TDLimiterPtr limiter);
|
||||
|
||||
/******************************************************************************
|
||||
* applyLimiter *
|
||||
* limiter: limiter handle *
|
||||
* pGain : pointer to gains to be applied to the signal before limiting, *
|
||||
* which are downscaled by TDL_GAIN_SCALING bit. *
|
||||
* These gains are delayed by gain_delay, and smoothed. *
|
||||
* Smoothing is done by a butterworth lowpass filter with a cutoff *
|
||||
* frequency which is fixed with respect to the sampling rate. *
|
||||
* It is a substitute for the smoothing due to windowing and *
|
||||
* overlap/add, if a gain is applied in frequency domain. *
|
||||
* gain_scale: pointer to scaling exponents to be applied to the signal before *
|
||||
* limiting, without delay and without smoothing *
|
||||
* gain_size: number of elements in pGain, currently restricted to 1 *
|
||||
* gain_delay: delay [samples] with which the gains in pGain shall be applied *
|
||||
* gain_delay <= nSamples *
|
||||
* samples: input/output buffer containing interleaved samples *
|
||||
* precision of output will be DFRACT_BITS-TDL_GAIN_SCALING bits *
|
||||
* nSamples: number of samples per channel *
|
||||
* returns: error code *
|
||||
******************************************************************************/
|
||||
TDLIMITER_ERROR applyLimiter(TDLimiterPtr limiter,
|
||||
INT_PCM* samples,
|
||||
FIXP_DBL* pGain,
|
||||
const INT* gain_scale,
|
||||
const UINT gain_size,
|
||||
const UINT gain_delay,
|
||||
const UINT nSamples);
|
||||
|
||||
/******************************************************************************
|
||||
* getLimiterDelay *
|
||||
* limiter: limiter handle *
|
||||
* returns: exact delay caused by the limiter in samples *
|
||||
******************************************************************************/
|
||||
unsigned int getLimiterDelay(TDLimiterPtr limiter);
|
||||
|
||||
/******************************************************************************
|
||||
* setLimiterNChannels *
|
||||
* limiter: limiter handle *
|
||||
* nChannels: number of channels ( <= maxChannels specified on create) *
|
||||
* returns: error code *
|
||||
******************************************************************************/
|
||||
TDLIMITER_ERROR setLimiterNChannels(TDLimiterPtr limiter, unsigned int nChannels);
|
||||
|
||||
/******************************************************************************
|
||||
* setLimiterSampleRate *
|
||||
* limiter: limiter handle *
|
||||
* sampleRate: sampling rate in Hz ( <= maxSampleRate specified on create) *
|
||||
* returns: error code *
|
||||
******************************************************************************/
|
||||
TDLIMITER_ERROR setLimiterSampleRate(TDLimiterPtr limiter, unsigned int sampleRate);
|
||||
|
||||
/******************************************************************************
|
||||
* setLimiterAttack *
|
||||
* limiter: limiter handle *
|
||||
* attackMs: attack time in ms ( <= maxAttackMs specified on create) *
|
||||
* returns: error code *
|
||||
******************************************************************************/
|
||||
TDLIMITER_ERROR setLimiterAttack(TDLimiterPtr limiter, unsigned int attackMs);
|
||||
|
||||
/******************************************************************************
|
||||
* setLimiterRelease *
|
||||
* limiter: limiter handle *
|
||||
* releaseMs: release time in ms *
|
||||
* returns: error code *
|
||||
******************************************************************************/
|
||||
TDLIMITER_ERROR setLimiterRelease(TDLimiterPtr limiter, unsigned int releaseMs);
|
||||
|
||||
/******************************************************************************
|
||||
* setLimiterThreshold *
|
||||
* limiter: limiter handle *
|
||||
* threshold: limiter threshold *
|
||||
* returns: error code *
|
||||
******************************************************************************/
|
||||
TDLIMITER_ERROR setLimiterThreshold(TDLimiterPtr limiter, INT_PCM threshold);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif //#ifndef _LIMITER_H_
|
@ -95,69 +95,88 @@ amm-info@iis.fraunhofer.de
|
||||
#include "machine_type.h"
|
||||
#include "common_fix.h"
|
||||
#include "FDK_audio.h"
|
||||
#include "FDK_bitstream.h"
|
||||
|
||||
/* ------------------------ *
|
||||
* MODULE SETTINGS: *
|
||||
* ------------------------ */
|
||||
/* #define PCM_UPMIX_ENABLE */ /*!< Generally enable up mixing. */
|
||||
#define PCM_DOWNMIX_ENABLE /*!< Generally enable down mixing. */
|
||||
#define DVB_MIXDOWN_ENABLE /*!< Enable this to support DVB ancillary data for encoder
|
||||
assisted downmixing of MPEG-4 AAC and
|
||||
MPEG-1/2 layer 2 streams. PCM_DOWNMIX_ENABLE has to
|
||||
be enabled, too! */
|
||||
#define MPEG_PCE_MIXDOWN_ENABLE /*!< Enable this to support MPEG matrix mixdown with a
|
||||
coefficient carried in the PCE. PCM_DOWNMIX_ENABLE
|
||||
has to be enabled, too! */
|
||||
/* #define ARIB_MIXDOWN_ENABLE */ /*!< Enable modifications to the MPEG PCE mixdown method
|
||||
to fulfill ARIB standard. MPEG_PCE_MIXDOWN_ENABLE has
|
||||
to be set. */
|
||||
|
||||
/* ------------------------ *
|
||||
* ERROR CODES: *
|
||||
* ------------------------ */
|
||||
typedef enum
|
||||
{
|
||||
PCMDMX_OK = 0x0, /*!< No error happened. */
|
||||
PCMDMX_OUT_OF_MEMORY = 0x2, /*!< Not enough memory to set up an instance of the module. */
|
||||
PCMDMX_UNKNOWN = 0x5, /*!< Error condition is of unknown reason, or from a third
|
||||
party module. */
|
||||
PCMDMX_INVALID_HANDLE, /*!< The given instance handle is not valid. */
|
||||
PCMDMX_INVALID_ARGUMENT, /*!< One of the parameters handed over is invalid. */
|
||||
PCMDMX_INVALID_CH_CONFIG, /*!< The given channel configuration is not supported and
|
||||
thus no processing was performed. */
|
||||
PCMDMX_INVALID_MODE, /*!< The set configuration/mode is not applicable. */
|
||||
PCMDMX_UNKNOWN_PARAM, /*!< The handed parameter is not known/supported. */
|
||||
PCMDMX_UNABLE_TO_SET_PARAM, /*!< Unable to set the specific parameter. Most probably
|
||||
the value ist out of range. */
|
||||
PCMDMX_CORRUPT_ANC_DATA /*!< The read ancillary data was corrupt. */
|
||||
PCMDMX_OK = 0x0, /*!< No error happened. */
|
||||
|
||||
pcm_dmx_fatal_error_start,
|
||||
PCMDMX_OUT_OF_MEMORY = 0x2, /*!< Not enough memory to set up an instance of the module. */
|
||||
PCMDMX_UNKNOWN = 0x5, /*!< Error condition is of unknown reason, or from a third
|
||||
party module. */
|
||||
pcm_dmx_fatal_error_end,
|
||||
|
||||
PCMDMX_INVALID_HANDLE, /*!< The given instance handle is not valid. */
|
||||
PCMDMX_INVALID_ARGUMENT, /*!< One of the parameters handed over is invalid. */
|
||||
PCMDMX_INVALID_CH_CONFIG, /*!< The given channel configuration is not supported and thus
|
||||
no processing was performed. */
|
||||
PCMDMX_INVALID_MODE, /*!< The set configuration/mode is not applicable. */
|
||||
PCMDMX_UNKNOWN_PARAM, /*!< The handed parameter is not known/supported. */
|
||||
PCMDMX_UNABLE_TO_SET_PARAM, /*!< Unable to set the specific parameter. Most probably the
|
||||
value ist out of range. */
|
||||
PCMDMX_CORRUPT_ANC_DATA /*!< The read ancillary data was corrupt. */
|
||||
|
||||
} PCMDMX_ERROR;
|
||||
|
||||
/** Macro to identify fatal errors. */
|
||||
#define PCMDMX_IS_FATAL_ERROR(err) ( (((err)>=pcm_dmx_fatal_error_start) && ((err)<=pcm_dmx_fatal_error_end)) ? 1 : 0)
|
||||
|
||||
/* ------------------------ *
|
||||
* RUNTIME PARAMS: *
|
||||
* ------------------------ */
|
||||
typedef enum
|
||||
{
|
||||
DMX_BS_DATA_EXPIRY_FRAME, /*!< The number of frames without new metadata that have to
|
||||
go by before the bitstream data expires. The value 0
|
||||
disables expiry. */
|
||||
DMX_BS_DATA_DELAY, /*!< The number of delay frames of the output samples
|
||||
compared to the bitstream data. */
|
||||
NUMBER_OF_OUTPUT_CHANNELS , /*!< The number of output channels (equals the number of
|
||||
channels processed by the audio output setup). */
|
||||
DUAL_CHANNEL_DOWNMIX_MODE /*!< Downmix mode for two channel audio data. */
|
||||
|
||||
DMX_BS_DATA_EXPIRY_FRAME, /*!< The number of frames without new metadata that have to go
|
||||
by before the bitstream data expires. The value 0 disables
|
||||
expiry. */
|
||||
DMX_BS_DATA_DELAY, /*!< The number of delay frames of the output samples compared
|
||||
to the bitstream data. */
|
||||
MIN_NUMBER_OF_OUTPUT_CHANNELS, /*!< The minimum number of output channels. For all input
|
||||
configurations that have less than the given channels the
|
||||
module will modify the output automatically to obtain the
|
||||
given number of output channels. Mono signals will be
|
||||
duplicated. If more than two output channels are desired
|
||||
the module just adds empty channels. The parameter value
|
||||
must be either -1, 0, 1, 2, 6 or 8. If the value is
|
||||
greater than zero and exceeds the value of parameter
|
||||
MAX_NUMBER_OF_OUTPUT_CHANNELS the latter will be set to
|
||||
the same value. Both values -1 and 0 disable the feature. */
|
||||
MAX_NUMBER_OF_OUTPUT_CHANNELS, /*!< The maximum number of output channels. For all input
|
||||
configurations that have more than the given channels the
|
||||
module will apply a mixdown automatically to obtain the
|
||||
given number of output channels. The value must be either
|
||||
-1, 0, 1, 2, 6 or 8. If it is greater than zero and lower
|
||||
or equal than the value of MIN_NUMBER_OF_OUTPUT_CHANNELS
|
||||
parameter the latter will be set to the same value.
|
||||
The values -1 and 0 disable the feature. */
|
||||
DMX_DUAL_CHANNEL_MODE, /*!< Downmix mode for two channel audio data. */
|
||||
DMX_PSEUDO_SURROUND_MODE /*!< Defines how module handles pseudo surround compatible
|
||||
signals. See PSEUDO_SURROUND_MODE type for details. */
|
||||
} PCMDMX_PARAM;
|
||||
|
||||
/* Parameter value types */
|
||||
typedef enum
|
||||
{
|
||||
NEVER_DO_PS_DMX = -1, /*!< Never create a pseudo surround compatible downmix. */
|
||||
AUTO_PS_DMX = 0, /*!< Create a pseudo surround compatible downmix only if
|
||||
signalled in bitstreams meta data. (Default) */
|
||||
FORCE_PS_DMX = 1 /*!< Always create a pseudo surround compatible downmix.
|
||||
CAUTION: This can lead to excessive signal cancellations
|
||||
and signal level differences for non-compatible signals. */
|
||||
} PSEUDO_SURROUND_MODE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STEREO_MODE = 0x0, /*!< Leave stereo signals as they are. */
|
||||
CH1_MODE = 0x1, /*!< Create a dual mono output signal from channel 1. */
|
||||
CH2_MODE = 0x2, /*!< Create a dual mono output signal from channel 2. */
|
||||
MIXED_MODE = 0x3 /*!< Create a dual mono output signal by mixing the two channels. */
|
||||
|
||||
STEREO_MODE = 0x0, /*!< Leave stereo signals as they are. */
|
||||
CH1_MODE = 0x1, /*!< Create a dual mono output signal from channel 1. */
|
||||
CH2_MODE = 0x2, /*!< Create a dual mono output signal from channel 2. */
|
||||
MIXED_MODE = 0x3 /*!< Create a dual mono output signal by mixing the two
|
||||
channels. */
|
||||
} DUAL_CHANNEL_MODE;
|
||||
|
||||
|
||||
@ -178,7 +197,7 @@ extern "C"
|
||||
|
||||
/** Open and initialize an instance of the PCM downmix module
|
||||
* @param [out] Pointer to a buffer receiving the handle of the new instance.
|
||||
* @returns Returns an error code.
|
||||
* @returns Returns an error code.
|
||||
**/
|
||||
PCMDMX_ERROR pcmDmx_Open (
|
||||
HANDLE_PCM_DOWNMIX *pSelf
|
||||
@ -188,20 +207,46 @@ PCMDMX_ERROR pcmDmx_Open (
|
||||
* @param [in] Handle of PCM downmix instance.
|
||||
* @param [in] Parameter to be set.
|
||||
* @param [in] Parameter value.
|
||||
* @returns Returns an error code.
|
||||
* @returns Returns an error code.
|
||||
**/
|
||||
PCMDMX_ERROR pcmDmx_SetParam (
|
||||
HANDLE_PCM_DOWNMIX self,
|
||||
PCMDMX_PARAM param,
|
||||
UINT value
|
||||
const PCMDMX_PARAM param,
|
||||
const INT value
|
||||
);
|
||||
|
||||
/** Read the ancillary data transported in DSEs of DVB streams with MPEG-4 content
|
||||
/** Get one parameter value of one PCM downmix module instance.
|
||||
* @param [in] Handle of PCM downmix module instance.
|
||||
* @param [in] Parameter to be set.
|
||||
* @param [out] Pointer to buffer receiving the parameter value.
|
||||
* @returns Returns an error code.
|
||||
**/
|
||||
PCMDMX_ERROR pcmDmx_GetParam (
|
||||
HANDLE_PCM_DOWNMIX self,
|
||||
const PCMDMX_PARAM param,
|
||||
INT * const pValue
|
||||
);
|
||||
|
||||
/** Read downmix meta-data directly from a given bitstream.
|
||||
* @param [in] Handle of PCM downmix instance.
|
||||
* @param [in] Handle of FDK bitstream buffer.
|
||||
* @param [in] Length of ancillary data in bits.
|
||||
* @param [in] Flag indicating wheter the ancillary data is from a MPEG-1/2 or an MPEG-4 stream.
|
||||
* @returns Returns an error code.
|
||||
**/
|
||||
PCMDMX_ERROR pcmDmx_Parse (
|
||||
HANDLE_PCM_DOWNMIX self,
|
||||
HANDLE_FDK_BITSTREAM hBitStream,
|
||||
UINT ancDataBits,
|
||||
int isMpeg2
|
||||
);
|
||||
|
||||
/** Read downmix meta-data from a given data buffer.
|
||||
* @param [in] Handle of PCM downmix instance.
|
||||
* @param [in] Pointer to ancillary data buffer.
|
||||
* @param [in] Size of ancillary data.
|
||||
* @param [in] Size of ancillary data in bytes.
|
||||
* @param [in] Flag indicating wheter the ancillary data is from a MPEG-1/2 or an MPEG-4 stream.
|
||||
* @returns Returns an error code.
|
||||
* @returns Returns an error code.
|
||||
**/
|
||||
PCMDMX_ERROR pcmDmx_ReadDvbAncData (
|
||||
HANDLE_PCM_DOWNMIX self,
|
||||
@ -211,12 +256,11 @@ PCMDMX_ERROR pcmDmx_ReadDvbAncData (
|
||||
);
|
||||
|
||||
/** Set the matrix mixdown information extracted from the PCE of an AAC bitstream.
|
||||
* Note: Call only if matrix_mixdown_idx_present is true.
|
||||
* @param [in] Handle of PCM downmix instance.
|
||||
* @param [in] Matrix mixdown index present flag extracted from PCE.
|
||||
* @param [in] The 2 bit matrix mixdown index extracted from PCE.
|
||||
* @param [in] The pseudo surround enable flag extracted from PCE.
|
||||
* @returns Returns an error code.
|
||||
* @returns Returns an error code.
|
||||
**/
|
||||
PCMDMX_ERROR pcmDmx_SetMatrixMixdownFromPce (
|
||||
HANDLE_PCM_DOWNMIX self,
|
||||
@ -235,34 +279,42 @@ PCMDMX_ERROR pcmDmx_Reset (
|
||||
UINT flags
|
||||
);
|
||||
|
||||
/** Apply down or up mixing.
|
||||
/** Create a mixdown, bypass or extend the output signal depending on the modules settings and the
|
||||
* respective given input configuration.
|
||||
*
|
||||
* \param [in] Handle of PCM downmix module instance.
|
||||
* \param [inout] Pointer to time buffer with decoded PCM samples.
|
||||
* \param [in] Pointer where the amount of output samples is returned into.
|
||||
* \param [inout] Pointer where the amount of output channels is returned into.
|
||||
* \param [in] Flag which indicates if output time data are writtern interleaved or as subsequent blocks.
|
||||
* \param [inout] Array were the corresponding channel type for each output audio channel is stored into.
|
||||
* \param [inout] Array were the corresponding channel type index for each output audio channel is stored into.
|
||||
* \param [in] Array containing the output channel mapping to be used (From MPEG PCE ordering to whatever is required).
|
||||
*
|
||||
* @returns Returns an error code.
|
||||
* \param [in] The I/O block size which is the number of samples per channel.
|
||||
* \param [inout] Pointer to buffer that holds the number of input channels and where the
|
||||
* amount of output channels is written to.
|
||||
* \param [in] Flag which indicates if output time data is writtern interleaved or as
|
||||
* subsequent blocks.
|
||||
* \param [inout] Array were the corresponding channel type for each output audio channel is
|
||||
* stored into.
|
||||
* \param [inout] Array were the corresponding channel type index for each output audio channel
|
||||
* is stored into.
|
||||
* \param [in] Array containing the output channel mapping to be used (from MPEG PCE ordering
|
||||
* to whatever is required).
|
||||
* \param [out] Pointer on a field receiving the scale factor that has to be applied on all
|
||||
* samples afterwards. If the handed pointer is NULL the final scaling is done
|
||||
* internally.
|
||||
* @returns Returns an error code.
|
||||
**/
|
||||
PCMDMX_ERROR pcmDmx_ApplyFrame (
|
||||
HANDLE_PCM_DOWNMIX self,
|
||||
INT_PCM *pPcmBuf,
|
||||
UINT frameSize,
|
||||
INT *nChannels,
|
||||
|
||||
int fInterleaved,
|
||||
AUDIO_CHANNEL_TYPE channelType[],
|
||||
UCHAR channelIndices[],
|
||||
const UCHAR channelMapping[][8]
|
||||
const UCHAR channelMapping[][8],
|
||||
INT *pDmxOutScale
|
||||
);
|
||||
|
||||
/** Close an instance of the PCM downmix module.
|
||||
* @param [inout] Pointer to a buffer containing the handle of the instance.
|
||||
* @returns Returns an error code.
|
||||
* @returns Returns an error code.
|
||||
**/
|
||||
PCMDMX_ERROR pcmDmx_Close (
|
||||
HANDLE_PCM_DOWNMIX *pSelf
|
||||
@ -270,7 +322,7 @@ PCMDMX_ERROR pcmDmx_Close (
|
||||
|
||||
/** Get library info for this module.
|
||||
* @param [out] Pointer to an allocated LIB_INFO structure.
|
||||
* @returns Returns an error code.
|
||||
* @returns Returns an error code.
|
||||
*/
|
||||
PCMDMX_ERROR pcmDmx_GetLibInfo( LIB_INFO *info );
|
||||
|
||||
|
498
libPCMutils/src/limiter.cpp
Normal file
498
libPCMutils/src/limiter.cpp
Normal file
@ -0,0 +1,498 @@
|
||||
|
||||
/* -----------------------------------------------------------------------------------------------------------
|
||||
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
|
||||
----------------------------------------------------------------------------------------------------------- */
|
||||
|
||||
/************************ FDK PCM postprocessor module *********************
|
||||
|
||||
Author(s): Matthias Neusinger
|
||||
Description: Hard limiter for clipping prevention
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include "limiter.h"
|
||||
|
||||
|
||||
struct TDLimiter {
|
||||
unsigned int attack;
|
||||
FIXP_DBL attackConst, releaseConst;
|
||||
unsigned int attackMs, releaseMs, maxAttackMs;
|
||||
FIXP_PCM threshold;
|
||||
unsigned int channels, maxChannels;
|
||||
unsigned int sampleRate, maxSampleRate;
|
||||
FIXP_DBL cor, max;
|
||||
FIXP_DBL* maxBuf;
|
||||
FIXP_DBL* delayBuf;
|
||||
unsigned int maxBufIdx, delayBufIdx;
|
||||
FIXP_DBL smoothState0;
|
||||
FIXP_DBL minGain;
|
||||
|
||||
FIXP_DBL additionalGainPrev;
|
||||
FIXP_DBL additionalGainFilterState;
|
||||
FIXP_DBL additionalGainFilterState1;
|
||||
};
|
||||
|
||||
/* create limiter */
|
||||
TDLimiterPtr createLimiter(
|
||||
unsigned int maxAttackMs,
|
||||
unsigned int releaseMs,
|
||||
INT_PCM threshold,
|
||||
unsigned int maxChannels,
|
||||
unsigned int maxSampleRate
|
||||
)
|
||||
{
|
||||
TDLimiterPtr limiter = NULL;
|
||||
unsigned int attack, release;
|
||||
FIXP_DBL attackConst, releaseConst, exponent;
|
||||
INT e_ans;
|
||||
|
||||
/* calc attack and release time in samples */
|
||||
attack = (unsigned int)(maxAttackMs * maxSampleRate / 1000);
|
||||
release = (unsigned int)(releaseMs * maxSampleRate / 1000);
|
||||
|
||||
/* alloc limiter struct */
|
||||
limiter = (TDLimiterPtr)FDKcalloc(1, sizeof(struct TDLimiter));
|
||||
if (!limiter) return NULL;
|
||||
|
||||
/* alloc max and delay buffers */
|
||||
limiter->maxBuf = (FIXP_DBL*)FDKcalloc(attack + 1, sizeof(FIXP_DBL));
|
||||
limiter->delayBuf = (FIXP_DBL*)FDKcalloc(attack * maxChannels, sizeof(FIXP_DBL));
|
||||
|
||||
if (!limiter->maxBuf || !limiter->delayBuf) {
|
||||
destroyLimiter(limiter);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* attackConst = pow(0.1, 1.0 / (attack + 1)) */
|
||||
exponent = invFixp(attack+1);
|
||||
attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
|
||||
attackConst = scaleValue(attackConst, e_ans);
|
||||
|
||||
/* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */
|
||||
exponent = invFixp(release + 1);
|
||||
releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
|
||||
releaseConst = scaleValue(releaseConst, e_ans);
|
||||
|
||||
/* init parameters */
|
||||
limiter->attackMs = maxAttackMs;
|
||||
limiter->maxAttackMs = maxAttackMs;
|
||||
limiter->releaseMs = releaseMs;
|
||||
limiter->attack = attack;
|
||||
limiter->attackConst = attackConst;
|
||||
limiter->releaseConst = releaseConst;
|
||||
limiter->threshold = (FIXP_PCM)threshold;
|
||||
limiter->channels = maxChannels;
|
||||
limiter->maxChannels = maxChannels;
|
||||
limiter->sampleRate = maxSampleRate;
|
||||
limiter->maxSampleRate = maxSampleRate;
|
||||
|
||||
resetLimiter(limiter);
|
||||
|
||||
return limiter;
|
||||
}
|
||||
|
||||
|
||||
/* reset limiter */
|
||||
TDLIMITER_ERROR resetLimiter(TDLimiterPtr limiter)
|
||||
{
|
||||
if (limiter != NULL) {
|
||||
|
||||
limiter->maxBufIdx = 0;
|
||||
limiter->delayBufIdx = 0;
|
||||
limiter->max = (FIXP_DBL)0;
|
||||
limiter->cor = FL2FXCONST_DBL(1.0f/(1<<1));
|
||||
limiter->smoothState0 = FL2FXCONST_DBL(1.0f/(1<<1));
|
||||
limiter->minGain = FL2FXCONST_DBL(1.0f/(1<<1));
|
||||
|
||||
limiter->additionalGainPrev = FL2FXCONST_DBL(1.0f/(1<<TDL_GAIN_SCALING));
|
||||
limiter->additionalGainFilterState = FL2FXCONST_DBL(1.0f/(1<<TDL_GAIN_SCALING));
|
||||
limiter->additionalGainFilterState1 = FL2FXCONST_DBL(1.0f/(1<<TDL_GAIN_SCALING));
|
||||
|
||||
FDKmemset(limiter->maxBuf, 0, (limiter->attack + 1) * sizeof(FIXP_DBL) );
|
||||
FDKmemset(limiter->delayBuf, 0, limiter->attack * limiter->channels * sizeof(FIXP_DBL) );
|
||||
}
|
||||
else {
|
||||
return TDLIMIT_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
return TDLIMIT_OK;
|
||||
}
|
||||
|
||||
|
||||
/* destroy limiter */
|
||||
TDLIMITER_ERROR destroyLimiter(TDLimiterPtr limiter)
|
||||
{
|
||||
if (limiter != NULL) {
|
||||
FDKfree(limiter->maxBuf);
|
||||
FDKfree(limiter->delayBuf);
|
||||
|
||||
FDKfree(limiter);
|
||||
}
|
||||
else {
|
||||
return TDLIMIT_INVALID_HANDLE;
|
||||
}
|
||||
return TDLIMIT_OK;
|
||||
}
|
||||
|
||||
/* apply limiter */
|
||||
TDLIMITER_ERROR applyLimiter(TDLimiterPtr limiter,
|
||||
INT_PCM* samples,
|
||||
FIXP_DBL* pGain,
|
||||
const INT* gain_scale,
|
||||
const UINT gain_size,
|
||||
const UINT gain_delay,
|
||||
const UINT nSamples)
|
||||
{
|
||||
unsigned int i, j;
|
||||
FIXP_PCM tmp1, tmp2;
|
||||
FIXP_DBL tmp, old, gain, additionalGain, additionalGainUnfiltered;
|
||||
FIXP_DBL minGain = FL2FXCONST_DBL(1.0f/(1<<1));
|
||||
|
||||
FDK_ASSERT(gain_size == 1);
|
||||
FDK_ASSERT(gain_delay <= nSamples);
|
||||
|
||||
if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE;
|
||||
|
||||
{
|
||||
unsigned int channels = limiter->channels;
|
||||
unsigned int attack = limiter->attack;
|
||||
FIXP_DBL attackConst = limiter->attackConst;
|
||||
FIXP_DBL releaseConst = limiter->releaseConst;
|
||||
FIXP_DBL threshold = FX_PCM2FX_DBL(limiter->threshold)>>TDL_GAIN_SCALING;
|
||||
|
||||
FIXP_DBL max = limiter->max;
|
||||
FIXP_DBL* maxBuf = limiter->maxBuf;
|
||||
unsigned int maxBufIdx = limiter->maxBufIdx;
|
||||
FIXP_DBL cor = limiter->cor;
|
||||
FIXP_DBL* delayBuf = limiter->delayBuf;
|
||||
unsigned int delayBufIdx = limiter->delayBufIdx;
|
||||
|
||||
FIXP_DBL smoothState0 = limiter->smoothState0;
|
||||
FIXP_DBL additionalGainSmoothState = limiter->additionalGainFilterState;
|
||||
FIXP_DBL additionalGainSmoothState1 = limiter->additionalGainFilterState1;
|
||||
|
||||
for (i = 0; i < nSamples; i++) {
|
||||
|
||||
if (i < gain_delay) {
|
||||
additionalGainUnfiltered = limiter->additionalGainPrev;
|
||||
} else {
|
||||
additionalGainUnfiltered = pGain[0];
|
||||
}
|
||||
|
||||
/* Smooth additionalGain */
|
||||
/* [b,a] = butter(1, 0.01) */
|
||||
static const FIXP_SGL b[] = { FL2FXCONST_SGL(0.015466*2.0), FL2FXCONST_SGL( 0.015466*2.0) };
|
||||
static const FIXP_SGL a[] = { FL2FXCONST_SGL(1.000000), FL2FXCONST_SGL(-0.96907) };
|
||||
/* [b,a] = butter(1, 0.001) */
|
||||
//static const FIXP_SGL b[] = { FL2FXCONST_SGL(0.0015683*2.0), FL2FXCONST_SGL( 0.0015683*2.0) };
|
||||
//static const FIXP_SGL a[] = { FL2FXCONST_SGL(1.0000000), FL2FXCONST_SGL(-0.99686) };
|
||||
additionalGain = - fMult(additionalGainSmoothState, a[1]) + fMultDiv2( additionalGainUnfiltered, b[0]) + fMultDiv2(additionalGainSmoothState1, b[1]);
|
||||
additionalGainSmoothState1 = additionalGainUnfiltered;
|
||||
additionalGainSmoothState = additionalGain;
|
||||
|
||||
/* Apply the additional scaling that has no delay and no smoothing */
|
||||
if (gain_scale[0] > 0) {
|
||||
additionalGain <<= gain_scale[0];
|
||||
} else {
|
||||
additionalGain >>= gain_scale[0];
|
||||
}
|
||||
|
||||
/* get maximum absolute sample value of all channels, including the additional gain. */
|
||||
tmp1 = (FIXP_PCM)0;
|
||||
for (j = 0; j < channels; j++) {
|
||||
tmp2 = (FIXP_PCM)samples[i * channels + j];
|
||||
if (tmp2 == (FIXP_PCM)SAMPLE_MIN) /* protect fAbs from -1.0 value */
|
||||
tmp2 = (FIXP_PCM)(SAMPLE_MIN+1);
|
||||
tmp1 = fMax(tmp1, fAbs(tmp2));
|
||||
}
|
||||
tmp = SATURATE_LEFT_SHIFT(fMultDiv2(tmp1, additionalGain), 1, DFRACT_BITS);
|
||||
|
||||
/* set threshold as lower border to save calculations in running maximum algorithm */
|
||||
tmp = fMax(tmp, threshold);
|
||||
|
||||
/* running maximum */
|
||||
old = maxBuf[maxBufIdx];
|
||||
maxBuf[maxBufIdx] = tmp;
|
||||
|
||||
if (tmp >= max) {
|
||||
/* new sample is greater than old maximum, so it is the new maximum */
|
||||
max = tmp;
|
||||
}
|
||||
else if (old < max) {
|
||||
/* maximum does not change, as the sample, which has left the window was
|
||||
not the maximum */
|
||||
}
|
||||
else {
|
||||
/* the old maximum has left the window, we have to search the complete
|
||||
buffer for the new max */
|
||||
max = maxBuf[0];
|
||||
for (j = 1; j <= attack; j++) {
|
||||
if (maxBuf[j] > max) max = maxBuf[j];
|
||||
}
|
||||
}
|
||||
maxBufIdx++;
|
||||
if (maxBufIdx >= attack+1) maxBufIdx = 0;
|
||||
|
||||
/* calc gain */
|
||||
/* gain is downscaled by one, so that gain = 1.0 can be represented */
|
||||
if (max > threshold) {
|
||||
gain = fDivNorm(threshold, max)>>1;
|
||||
}
|
||||
else {
|
||||
gain = FL2FXCONST_DBL(1.0f/(1<<1));
|
||||
}
|
||||
|
||||
/* gain smoothing, method: TDL_EXPONENTIAL */
|
||||
/* first order IIR filter with attack correction to avoid overshoots */
|
||||
|
||||
/* correct the 'aiming' value of the exponential attack to avoid the remaining overshoot */
|
||||
if (gain < smoothState0) {
|
||||
cor = fMin(cor, fMultDiv2((gain - fMultDiv2(FL2FXCONST_SGL(0.1f*(1<<1)),smoothState0)), FL2FXCONST_SGL(1.11111111f/(1<<1)))<<2);
|
||||
}
|
||||
else {
|
||||
cor = gain;
|
||||
}
|
||||
|
||||
/* smoothing filter */
|
||||
if (cor < smoothState0) {
|
||||
smoothState0 = fMult(attackConst,(smoothState0 - cor)) + cor; /* attack */
|
||||
smoothState0 = fMax(smoothState0, gain); /* avoid overshooting target */
|
||||
}
|
||||
else {
|
||||
/* sign inversion twice to round towards +infinity,
|
||||
so that gain can converge to 1.0 again,
|
||||
for bit-identical output when limiter is not active */
|
||||
smoothState0 = -fMult(releaseConst,-(smoothState0 - cor)) + cor; /* release */
|
||||
}
|
||||
|
||||
gain = smoothState0;
|
||||
|
||||
/* lookahead delay, apply gain */
|
||||
for (j = 0; j < channels; j++) {
|
||||
|
||||
tmp = delayBuf[delayBufIdx * channels + j];
|
||||
delayBuf[delayBufIdx * channels + j] = fMult((FIXP_PCM)samples[i * channels + j], additionalGain);
|
||||
|
||||
/* Apply gain to delayed signal */
|
||||
if (gain < FL2FXCONST_DBL(1.0f/(1<<1)))
|
||||
tmp = fMult(tmp,gain<<1);
|
||||
|
||||
samples[i * channels + j] = FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT(tmp,TDL_GAIN_SCALING,DFRACT_BITS));
|
||||
}
|
||||
delayBufIdx++;
|
||||
if (delayBufIdx >= attack) delayBufIdx = 0;
|
||||
|
||||
/* save minimum gain factor */
|
||||
if (gain < minGain) minGain = gain;
|
||||
}
|
||||
|
||||
|
||||
limiter->max = max;
|
||||
limiter->maxBufIdx = maxBufIdx;
|
||||
limiter->cor = cor;
|
||||
limiter->delayBufIdx = delayBufIdx;
|
||||
|
||||
limiter->smoothState0 = smoothState0;
|
||||
limiter->additionalGainFilterState = additionalGainSmoothState;
|
||||
limiter->additionalGainFilterState1 = additionalGainSmoothState1;
|
||||
|
||||
limiter->minGain = minGain;
|
||||
|
||||
limiter->additionalGainPrev = pGain[0];
|
||||
|
||||
return TDLIMIT_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* get delay in samples */
|
||||
unsigned int getLimiterDelay(TDLimiterPtr limiter)
|
||||
{
|
||||
FDK_ASSERT(limiter != NULL);
|
||||
return limiter->attack;
|
||||
}
|
||||
|
||||
/* set number of channels */
|
||||
TDLIMITER_ERROR setLimiterNChannels(TDLimiterPtr limiter, unsigned int nChannels)
|
||||
{
|
||||
if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE;
|
||||
|
||||
if (nChannels > limiter->maxChannels) return TDLIMIT_INVALID_PARAMETER;
|
||||
|
||||
limiter->channels = nChannels;
|
||||
//resetLimiter(limiter);
|
||||
|
||||
return TDLIMIT_OK;
|
||||
}
|
||||
|
||||
/* set sampling rate */
|
||||
TDLIMITER_ERROR setLimiterSampleRate(TDLimiterPtr limiter, unsigned int sampleRate)
|
||||
{
|
||||
unsigned int attack, release;
|
||||
FIXP_DBL attackConst, releaseConst, exponent;
|
||||
INT e_ans;
|
||||
|
||||
if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE;
|
||||
|
||||
if (sampleRate > limiter->maxSampleRate) return TDLIMIT_INVALID_PARAMETER;
|
||||
|
||||
/* update attack and release time in samples */
|
||||
attack = (unsigned int)(limiter->attackMs * sampleRate / 1000);
|
||||
release = (unsigned int)(limiter->releaseMs * sampleRate / 1000);
|
||||
|
||||
/* attackConst = pow(0.1, 1.0 / (attack + 1)) */
|
||||
exponent = invFixp(attack+1);
|
||||
attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
|
||||
attackConst = scaleValue(attackConst, e_ans);
|
||||
|
||||
/* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */
|
||||
exponent = invFixp(release + 1);
|
||||
releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
|
||||
releaseConst = scaleValue(releaseConst, e_ans);
|
||||
|
||||
limiter->attack = attack;
|
||||
limiter->attackConst = attackConst;
|
||||
limiter->releaseConst = releaseConst;
|
||||
limiter->sampleRate = sampleRate;
|
||||
|
||||
/* reset */
|
||||
//resetLimiter(limiter);
|
||||
|
||||
return TDLIMIT_OK;
|
||||
}
|
||||
|
||||
/* set attack time */
|
||||
TDLIMITER_ERROR setLimiterAttack(TDLimiterPtr limiter, unsigned int attackMs)
|
||||
{
|
||||
unsigned int attack;
|
||||
FIXP_DBL attackConst, exponent;
|
||||
INT e_ans;
|
||||
|
||||
if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE;
|
||||
|
||||
if (attackMs > limiter->maxAttackMs) return TDLIMIT_INVALID_PARAMETER;
|
||||
|
||||
/* calculate attack time in samples */
|
||||
attack = (unsigned int)(attackMs * limiter->sampleRate / 1000);
|
||||
|
||||
/* attackConst = pow(0.1, 1.0 / (attack + 1)) */
|
||||
exponent = invFixp(attack+1);
|
||||
attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
|
||||
attackConst = scaleValue(attackConst, e_ans);
|
||||
|
||||
limiter->attack = attack;
|
||||
limiter->attackConst = attackConst;
|
||||
limiter->attackMs = attackMs;
|
||||
|
||||
return TDLIMIT_OK;
|
||||
}
|
||||
|
||||
/* set release time */
|
||||
TDLIMITER_ERROR setLimiterRelease(TDLimiterPtr limiter, unsigned int releaseMs)
|
||||
{
|
||||
unsigned int release;
|
||||
FIXP_DBL releaseConst, exponent;
|
||||
INT e_ans;
|
||||
|
||||
if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE;
|
||||
|
||||
/* calculate release time in samples */
|
||||
release = (unsigned int)(releaseMs * limiter->sampleRate / 1000);
|
||||
|
||||
/* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */
|
||||
exponent = invFixp(release + 1);
|
||||
releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans);
|
||||
releaseConst = scaleValue(releaseConst, e_ans);
|
||||
|
||||
limiter->releaseConst = releaseConst;
|
||||
limiter->releaseMs = releaseMs;
|
||||
|
||||
return TDLIMIT_OK;
|
||||
}
|
||||
|
||||
/* set limiter threshold */
|
||||
TDLIMITER_ERROR setLimiterThreshold(TDLimiterPtr limiter, INT_PCM threshold)
|
||||
{
|
||||
if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE;
|
||||
|
||||
limiter->threshold = (FIXP_PCM)threshold;
|
||||
|
||||
return TDLIMIT_OK;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -145,6 +145,8 @@ typedef enum
|
||||
SBR_SYSTEM_BITSTREAM_DELAY, /*!< System: Switch to enable an additional SBR bitstream delay of one frame. */
|
||||
SBR_QMF_MODE, /*!< Set QMF mode, either complex or low power. */
|
||||
SBR_LD_QMF_TIME_ALIGN, /*!< Set QMF type, either LD-MPS or CLDFB. Relevant for ELD streams only. */
|
||||
SBR_FLUSH_DATA, /*!< Set internal state to flush the decoder with the next process call. */
|
||||
SBR_CLEAR_HISTORY, /*!< Clear all internal states (delay lines, QMF states, ...). */
|
||||
SBR_BS_INTERRUPTION /*!< Signal bit stream interruption. Value is ignored. */
|
||||
} SBRDEC_PARAM;
|
||||
|
||||
@ -308,7 +310,7 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self,
|
||||
INT_PCM *timeData,
|
||||
int *numChannels,
|
||||
int *sampleRate,
|
||||
const UCHAR channelMapping[(6)],
|
||||
const UCHAR channelMapping[(8)],
|
||||
const int interleaved,
|
||||
const int coreDecodedOk,
|
||||
UCHAR *psDecoded );
|
||||
@ -329,6 +331,13 @@ SBR_ERROR sbrDecoder_Close ( HANDLE_SBRDECODER *self );
|
||||
*/
|
||||
INT sbrDecoder_GetLibInfo( LIB_INFO *info );
|
||||
|
||||
/**
|
||||
* \brief Determine the modules output signal delay in samples.
|
||||
* \param self SBR decoder handle.
|
||||
* \return The number of samples signal delay added by the module.
|
||||
*/
|
||||
UINT sbrDecoder_GetDelay( const HANDLE_SBRDECODER self );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -179,6 +179,9 @@ typedef FREQ_BAND_DATA *HANDLE_FREQ_BAND_DATA;
|
||||
#define SBRDEC_LOW_POWER 16 /* Flag indicating that Low Power QMF mode shall be used. */
|
||||
#define SBRDEC_PS_DECODED 32 /* Flag indicating that PS was decoded and rendered. */
|
||||
#define SBRDEC_LD_MPS_QMF 512 /* Flag indicating that the LD-MPS QMF shall be used. */
|
||||
#define SBRDEC_DOWNSAMPLE 8192 /* Flag indicating that the downsampling mode is used. */
|
||||
#define SBRDEC_FLUSH 16384 /* Flag is used to flush all elements in use. */
|
||||
#define SBRDEC_FORCE_RESET 32768 /* Flag is used to force a reset of all elements in use. */
|
||||
|
||||
#define SBRDEC_HDR_STAT_RESET 1
|
||||
#define SBRDEC_HDR_STAT_UPDATE 2
|
||||
|
@ -107,19 +107,19 @@ amm-info@iis.fraunhofer.de
|
||||
/*! SBR Decoder main structure */
|
||||
C_ALLOC_MEM(Ram_SbrDecoder, struct SBR_DECODER_INSTANCE, 1)
|
||||
/*! SBR Decoder element data <br>
|
||||
Dimension: (4) */
|
||||
C_ALLOC_MEM2(Ram_SbrDecElement, SBR_DECODER_ELEMENT, 1, (4))
|
||||
Dimension: (8) */
|
||||
C_ALLOC_MEM2(Ram_SbrDecElement, SBR_DECODER_ELEMENT, 1, (8))
|
||||
/*! SBR Decoder individual channel data <br>
|
||||
Dimension: (6) */
|
||||
C_ALLOC_MEM2(Ram_SbrDecChannel, SBR_CHANNEL, 1, (6)+1)
|
||||
Dimension: (8) */
|
||||
C_ALLOC_MEM2(Ram_SbrDecChannel, SBR_CHANNEL, 1, (8)+1)
|
||||
|
||||
/*! Filter states for QMF-synthesis. <br>
|
||||
Dimension: #(6) * (#QMF_FILTER_STATE_SYN_SIZE-#(64)) */
|
||||
C_AALLOC_MEM2_L(Ram_sbr_QmfStatesSynthesis, FIXP_QSS, (640)-(64), (6)+1, SECT_DATA_L1)
|
||||
Dimension: #(8) * (#QMF_FILTER_STATE_SYN_SIZE-#(64)) */
|
||||
C_AALLOC_MEM2_L(Ram_sbr_QmfStatesSynthesis, FIXP_QSS, (640)-(64), (8)+1, SECT_DATA_L1)
|
||||
|
||||
/*! Delayed spectral data needed for the dynamic framing of SBR.
|
||||
For mp3PRO, 1/3 of a frame is buffered (#(6) 6) */
|
||||
C_AALLOC_MEM2(Ram_sbr_OverlapBuffer, FIXP_DBL, 2 * (6) * (64), (6)+1)
|
||||
C_AALLOC_MEM2(Ram_sbr_OverlapBuffer, FIXP_DBL, 2 * (6) * (64), (8)+1)
|
||||
|
||||
/*! Static Data of PS */
|
||||
|
||||
|
@ -118,8 +118,8 @@ typedef struct
|
||||
|
||||
struct SBR_DECODER_INSTANCE
|
||||
{
|
||||
SBR_DECODER_ELEMENT *pSbrElement[(4)];
|
||||
SBR_HEADER_DATA sbrHeader[(4)][(1)+1]; /* Sbr header for each individual channel of an element */
|
||||
SBR_DECODER_ELEMENT *pSbrElement[(8)];
|
||||
SBR_HEADER_DATA sbrHeader[(8)][(1)+1]; /* Sbr header for each individual channel of an element */
|
||||
|
||||
FIXP_DBL *workBuffer1;
|
||||
FIXP_DBL *workBuffer2;
|
||||
|
@ -95,7 +95,7 @@ amm-info@iis.fraunhofer.de
|
||||
|
||||
|
||||
|
||||
#define SBRDEC_MAX_DRC_CHANNELS (6)
|
||||
#define SBRDEC_MAX_DRC_CHANNELS (8)
|
||||
#define SBRDEC_MAX_DRC_BANDS ( 16 )
|
||||
|
||||
typedef struct
|
||||
|
@ -137,7 +137,7 @@ amm-info@iis.fraunhofer.de
|
||||
/* Decoder library info */
|
||||
#define SBRDECODER_LIB_VL0 2
|
||||
#define SBRDECODER_LIB_VL1 2
|
||||
#define SBRDECODER_LIB_VL2 3
|
||||
#define SBRDECODER_LIB_VL2 6
|
||||
#define SBRDECODER_LIB_TITLE "SBR Decoder"
|
||||
#define SBRDECODER_LIB_BUILD_DATE __DATE__
|
||||
#define SBRDECODER_LIB_BUILD_TIME __TIME__
|
||||
@ -251,8 +251,10 @@ SBR_ERROR sbrDecoder_ResetElement (
|
||||
|
||||
if ( sampleRateIn == sampleRateOut ) {
|
||||
synDownsampleFac = 2;
|
||||
self->flags |= SBRDEC_DOWNSAMPLE;
|
||||
} else {
|
||||
synDownsampleFac = 1;
|
||||
self->flags &= ~SBRDEC_DOWNSAMPLE;
|
||||
}
|
||||
|
||||
self->synDownsampleFac = synDownsampleFac;
|
||||
@ -428,7 +430,7 @@ SBR_ERROR sbrDecoder_InitElement (
|
||||
int nSbrElementsStart = self->numSbrElements;
|
||||
|
||||
/* Check core codec AOT */
|
||||
if (! sbrDecoder_isCoreCodecValid(coreCodec) || elementIndex >= (4)) {
|
||||
if (! sbrDecoder_isCoreCodecValid(coreCodec) || elementIndex >= (8)) {
|
||||
sbrError = SBRDEC_UNSUPPORTED_CONFIG;
|
||||
goto bail;
|
||||
}
|
||||
@ -444,6 +446,7 @@ SBR_ERROR sbrDecoder_InitElement (
|
||||
&& self->coreCodec == coreCodec
|
||||
&& self->pSbrElement[elementIndex] != NULL
|
||||
&& self->pSbrElement[elementIndex]->elementID == elementID
|
||||
&& !(self->flags & SBRDEC_FORCE_RESET)
|
||||
)
|
||||
{
|
||||
/* Nothing to do */
|
||||
@ -550,8 +553,9 @@ bail:
|
||||
if (nSbrElementsStart < self->numSbrElements) {
|
||||
/* Free the memory allocated for this element */
|
||||
sbrDecoder_DestroyElement( self, elementIndex );
|
||||
} else if (self->pSbrElement[elementIndex] != NULL) {
|
||||
/* Set error flag to trigger concealment */
|
||||
} else if ( (self->pSbrElement[elementIndex] != NULL)
|
||||
&& (elementIndex < (8)))
|
||||
{ /* Set error flag to trigger concealment */
|
||||
self->pSbrElement[elementIndex]->frameErrorFlag[self->pSbrElement[elementIndex]->useFrameSlot] = 1;
|
||||
}
|
||||
}
|
||||
@ -615,7 +619,7 @@ INT sbrDecoder_Header (
|
||||
SBR_ERROR sbrError = SBRDEC_OK;
|
||||
int headerIndex;
|
||||
|
||||
if ( self == NULL || elementIndex > (4) )
|
||||
if ( self == NULL || elementIndex > (8) )
|
||||
{
|
||||
return SBRDEC_UNSUPPORTED_CONFIG;
|
||||
}
|
||||
@ -728,6 +732,24 @@ SBR_ERROR sbrDecoder_SetParam (HANDLE_SBRDECODER self,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SBR_FLUSH_DATA:
|
||||
if (value != 0) {
|
||||
if (self == NULL) {
|
||||
errorStatus = SBRDEC_NOT_INITIALIZED;
|
||||
} else {
|
||||
self->flags |= SBRDEC_FLUSH;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SBR_CLEAR_HISTORY:
|
||||
if (value != 0) {
|
||||
if (self == NULL) {
|
||||
errorStatus = SBRDEC_NOT_INITIALIZED;
|
||||
} else {
|
||||
self->flags |= SBRDEC_FORCE_RESET;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SBR_BS_INTERRUPTION:
|
||||
{
|
||||
int elementIndex;
|
||||
@ -738,7 +760,8 @@ SBR_ERROR sbrDecoder_SetParam (HANDLE_SBRDECODER self,
|
||||
}
|
||||
|
||||
/* Loop over SBR elements */
|
||||
for (elementIndex = 0; elementIndex < self->numSbrElements; elementIndex++)
|
||||
for (elementIndex = 0; elementIndex < self->numSbrElements; elementIndex++) {
|
||||
if (self->pSbrElement[elementIndex] != NULL)
|
||||
{
|
||||
HANDLE_SBR_HEADER_DATA hSbrHeader;
|
||||
int headerIndex = getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot,
|
||||
@ -750,7 +773,7 @@ SBR_ERROR sbrDecoder_SetParam (HANDLE_SBRDECODER self,
|
||||
This switches off bitstream parsing until a new header arrives. */
|
||||
hSbrHeader->syncState = UPSAMPLING;
|
||||
hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE;
|
||||
}
|
||||
} }
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -767,7 +790,7 @@ SBRDEC_DRC_CHANNEL * sbrDecoder_drcGetChannel( const HANDLE_SBRDECODER self, con
|
||||
SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL;
|
||||
int elementIndex, elChanIdx=0, numCh=0;
|
||||
|
||||
for (elementIndex = 0; (elementIndex < (4)) && (numCh <= channel); elementIndex++)
|
||||
for (elementIndex = 0; (elementIndex < (8)) && (numCh <= channel); elementIndex++)
|
||||
{
|
||||
SBR_DECODER_ELEMENT *pSbrElement = self->pSbrElement[elementIndex];
|
||||
int c, elChannels;
|
||||
@ -829,7 +852,7 @@ SBR_ERROR sbrDecoder_drcFeedChannel ( HANDLE_SBRDECODER self,
|
||||
if (self == NULL) {
|
||||
return SBRDEC_NOT_INITIALIZED;
|
||||
}
|
||||
if (ch > (6) || pNextFact_mag == NULL) {
|
||||
if (ch > (8) || pNextFact_mag == NULL) {
|
||||
return SBRDEC_SET_PARAM_FAIL;
|
||||
}
|
||||
|
||||
@ -874,7 +897,7 @@ void sbrDecoder_drcDisable ( HANDLE_SBRDECODER self,
|
||||
SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL;
|
||||
|
||||
if ( (self == NULL)
|
||||
|| (ch > (6))
|
||||
|| (ch > (8))
|
||||
|| (self->numSbrElements == 0)
|
||||
|| (self->numSbrChannels == 0) ) {
|
||||
return;
|
||||
@ -1119,6 +1142,10 @@ SBR_ERROR sbrDecoder_Parse(
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* The returned bit count will not be the actual payload size since we did not
|
||||
parse the frame data. Return an error so that the caller can react respectively. */
|
||||
errorStatus = SBRDEC_PARSE_ERROR;
|
||||
}
|
||||
|
||||
if (!fDoDecodeSbrData) {
|
||||
@ -1198,6 +1225,15 @@ sbrDecoder_DecodeElement (
|
||||
int stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0;
|
||||
int numElementChannels = hSbrElement->nChannels; /* Number of channels of the current SBR element */
|
||||
|
||||
if (self->flags & SBRDEC_FLUSH) {
|
||||
/* Move frame pointer to the next slot which is up to be decoded/applied next */
|
||||
hSbrElement->useFrameSlot = (hSbrElement->useFrameSlot+1) % (self->numDelayFrames+1);
|
||||
/* Update header and frame data pointer because they have already been set */
|
||||
hSbrHeader = &self->sbrHeader[elementIndex][hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]];
|
||||
hFrameDataLeft = &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot];
|
||||
hFrameDataRight = &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot];
|
||||
}
|
||||
|
||||
/* Update the header error flag */
|
||||
hSbrHeader->frameErrorFlag = hSbrElement->frameErrorFlag[hSbrElement->useFrameSlot];
|
||||
|
||||
@ -1375,7 +1411,7 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self,
|
||||
INT_PCM *timeData,
|
||||
int *numChannels,
|
||||
int *sampleRate,
|
||||
const UCHAR channelMapping[(6)],
|
||||
const UCHAR channelMapping[(8)],
|
||||
const int interleaved,
|
||||
const int coreDecodedOk,
|
||||
UCHAR *psDecoded )
|
||||
@ -1472,6 +1508,10 @@ SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self,
|
||||
|
||||
|
||||
|
||||
/* Clear reset and flush flag because everything seems to be done successfully. */
|
||||
self->flags &= ~SBRDEC_FORCE_RESET;
|
||||
self->flags &= ~SBRDEC_FLUSH;
|
||||
|
||||
bail:
|
||||
|
||||
return errorStatus;
|
||||
@ -1496,7 +1536,7 @@ SBR_ERROR sbrDecoder_Close ( HANDLE_SBRDECODER *pSelf )
|
||||
FreeRam_SbrDecWorkBuffer2(&self->workBuffer2);
|
||||
}
|
||||
|
||||
for (i = 0; i < (4); i++) {
|
||||
for (i = 0; i < (8); i++) {
|
||||
sbrDecoder_DestroyElement( self, i );
|
||||
}
|
||||
|
||||
@ -1544,3 +1584,34 @@ INT sbrDecoder_GetLibInfo( LIB_INFO *info )
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
UINT sbrDecoder_GetDelay( const HANDLE_SBRDECODER self )
|
||||
{
|
||||
UINT outputDelay = 0;
|
||||
|
||||
if ( self != NULL) {
|
||||
UINT flags = self->flags;
|
||||
|
||||
/* See chapter 1.6.7.2 of ISO/IEC 14496-3 for the GA-SBR figures below. */
|
||||
|
||||
/* Are we initialized? */
|
||||
if ( (self->numSbrChannels > 0)
|
||||
&& (self->numSbrElements > 0) )
|
||||
{
|
||||
/* Add QMF synthesis delay */
|
||||
if ( (flags & SBRDEC_ELD_GRID)
|
||||
&& IS_LOWDELAY(self->coreCodec) ) {
|
||||
/* Low delay SBR: */
|
||||
{
|
||||
outputDelay += (flags & SBRDEC_DOWNSAMPLE) ? 32 : 64; /* QMF synthesis */
|
||||
}
|
||||
}
|
||||
else if (!IS_USAC(self->coreCodec)) {
|
||||
/* By the method of elimination this is the GA (AAC-LC, HE-AAC, ...) branch: */
|
||||
outputDelay += (flags & SBRDEC_DOWNSAMPLE) ? 481 : 962;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (outputDelay);
|
||||
}
|
||||
|
@ -232,6 +232,14 @@ typedef enum
|
||||
|
||||
} AUDIO_OBJECT_TYPE;
|
||||
|
||||
#define IS_USAC(aot) \
|
||||
((aot) == AOT_USAC \
|
||||
|| (aot) == AOT_RSVD50)
|
||||
|
||||
#define IS_LOWDELAY(aot) \
|
||||
((aot) == AOT_ER_AAC_LD \
|
||||
|| (aot) == AOT_ER_AAC_ELD)
|
||||
|
||||
/** Channel Mode ( 1-7 equals MPEG channel configurations, others are arbitrary). */
|
||||
typedef enum {
|
||||
MODE_INVALID = -1,
|
||||
@ -263,17 +271,29 @@ typedef enum {
|
||||
|
||||
} CHANNEL_MODE;
|
||||
|
||||
/** Speaker description tags */
|
||||
/**
|
||||
* Speaker description tags.
|
||||
* Do not change the enumeration values unless it keeps the following segmentation:
|
||||
* - Bit 0-3: Horizontal postion (0: none, 1: front, 2: side, 3: back, 4: lfe)
|
||||
* - Bit 4-7: Vertical position (0: normal, 1: top, 2: bottom)
|
||||
*/
|
||||
typedef enum {
|
||||
ACT_NONE,
|
||||
ACT_FRONT,
|
||||
ACT_SIDE,
|
||||
ACT_BACK,
|
||||
ACT_LFE,
|
||||
ACT_FRONT_TOP,
|
||||
ACT_SIDE_TOP,
|
||||
ACT_BACK_TOP,
|
||||
ACT_TOP /* Ts */
|
||||
ACT_NONE = 0x00,
|
||||
ACT_FRONT = 0x01, /*!< Front speaker position (at normal height) */
|
||||
ACT_SIDE = 0x02, /*!< Side speaker position (at normal height) */
|
||||
ACT_BACK = 0x03, /*!< Back speaker position (at normal height) */
|
||||
ACT_LFE = 0x04, /*!< Low frequency effect speaker postion (front) */
|
||||
|
||||
ACT_TOP = 0x10, /*!< Top speaker area (for combination with speaker positions) */
|
||||
ACT_FRONT_TOP = 0x11, /*!< Top front speaker = (ACT_FRONT|ACT_TOP) */
|
||||
ACT_SIDE_TOP = 0x12, /*!< Top side speaker = (ACT_SIDE |ACT_TOP) */
|
||||
ACT_BACK_TOP = 0x13, /*!< Top back speaker = (ACT_BACK |ACT_TOP) */
|
||||
|
||||
ACT_BOTTOM = 0x20, /*!< Bottom speaker area (for combination with speaker positions) */
|
||||
ACT_FRONT_BOTTOM = 0x21, /*!< Bottom front speaker = (ACT_FRONT|ACT_BOTTOM) */
|
||||
ACT_SIDE_BOTTOM = 0x22, /*!< Bottom side speaker = (ACT_SIDE |ACT_BOTTOM) */
|
||||
ACT_BACK_BOTTOM = 0x23 /*!< Bottom back speaker = (ACT_BACK |ACT_BOTTOM) */
|
||||
|
||||
} AUDIO_CHANNEL_TYPE;
|
||||
|
||||
typedef enum
|
||||
|
@ -99,7 +99,7 @@ amm-info@iis.fraunhofer.de
|
||||
/* library info */
|
||||
#define SYS_LIB_VL0 1
|
||||
#define SYS_LIB_VL1 3
|
||||
#define SYS_LIB_VL2 4
|
||||
#define SYS_LIB_VL2 6
|
||||
#define SYS_LIB_TITLE "System Integration Library"
|
||||
#define SYS_LIB_BUILD_DATE __DATE__
|
||||
#define SYS_LIB_BUILD_TIME __TIME__
|
||||
|
Loading…
Reference in New Issue
Block a user