Fraunhofer AAC codec.
License boilerplate update to follow. Change-Id: I2810460c11a58b6d148d84673cc031f3685e79b5
This commit is contained in:
parent
a37315fe10
commit
9bf37cc971
1
Android.mk
Normal file
1
Android.mk
Normal file
@ -0,0 +1 @@
|
||||
include $(call all-subdir-makefiles)
|
1
libAACdec/Android.mk
Normal file
1
libAACdec/Android.mk
Normal file
@ -0,0 +1 @@
|
||||
include $(call all-subdir-makefiles)
|
626
libAACdec/include/aacdecoder_lib.h
Normal file
626
libAACdec/include/aacdecoder_lib.h
Normal file
@ -0,0 +1,626 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS 1999-2008
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Manuel Jander
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* \file aacdecoder_lib.h
|
||||
* \brief FDK AAC decoder library interface header file.
|
||||
*
|
||||
|
||||
\page INTRO Introduction
|
||||
|
||||
\section SCOPE Scope
|
||||
|
||||
This document describes the high-level interface and usage of the ISO/MPEG-2/4 AAC Decoder
|
||||
library developed by the Fraunhofer Institute for Integrated Circuits (IIS).
|
||||
Depending on the library configuration, it implements decoding of AAC-LC (Low-Complexity),
|
||||
HE-AAC (High-Efficiency AAC, v1 and v2), AAC-LD (Low-Delay) and AAC-ELD (Enhanced Low-Delay).
|
||||
|
||||
All references to SBR (Spectral Band Replication) are only applicable to HE-AAC and AAC-ELD
|
||||
versions of the library. All references to PS (Parametric Stereo) are only applicable to
|
||||
HE-AAC v2 versions of the library.
|
||||
|
||||
\section DecoderBasics Decoder Basics
|
||||
|
||||
This document can only give a rough overview about the ISO/MPEG-2 and ISO/MPEG-4 AAC audio
|
||||
coding standard. To understand all the terms in this document, you are encouraged to read
|
||||
the following documents.
|
||||
|
||||
- ISO/IEC 13818-7 (MPEG-2 AAC), which defines the syntax of MPEG-2 AAC audio bitstreams.
|
||||
- ISO/IEC 14496-3 (MPEG-4 AAC, subpart 1 and 4), which defines the syntax of MPEG-4 AAC audio bitstreams.
|
||||
- Lutzky, Schuller, Gayer, Krämer, Wabnik, "A guideline to audio codec delay", 116th AES Convention, May 8, 2004
|
||||
|
||||
MPEG Advanced Audio Coding is based on a time-to-frequency mapping of the signal. The signal
|
||||
is partitioned into overlapping portions and transformed into frequency domain. The spectral
|
||||
components are then quantized and coded.\n
|
||||
An MPEG2 or MPEG4 AAC audio bitstream is composed of frames. Contrary to MPEG-1/2 Layer-3 (mp3),
|
||||
the length of individual frames is not restricted to a fixed number of bytes, but can take on
|
||||
any length between 1 and 768 bytes.
|
||||
|
||||
|
||||
\page LIBUSE Library Usage
|
||||
|
||||
\section InterfaceDescritpion API Description
|
||||
|
||||
All API header files are located in the folder /include of the release package. They are described in
|
||||
detail in this document. All header files are provided for usage in C/C++ programs. The AAC decoder library
|
||||
API functions are located at aacdecoder_lib.h.
|
||||
|
||||
In binary releases the decoder core resides in statically linkable libraries called for example libAACdec.a,
|
||||
(Linux) or FDK_aacDec_lib (Microsoft Visual C++).
|
||||
|
||||
\section Calling_Sequence Calling Sequence
|
||||
|
||||
For decoding of ISO/MPEG-2/4 AAC or HE-AAC v2 bitstreams the following sequence is mandatory. Input read
|
||||
and output write functions as well as the corresponding open and close functions are left out, since they
|
||||
may be implemented differently according to the user's specific requirements. The example implementation in
|
||||
main.cpp uses file-based input/output, and in such case call mpegFileRead_Open() to open an input file and
|
||||
to allocate memory for the required structures, and the corresponding mpegFileRead_Close() to close opened
|
||||
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.
|
||||
|
||||
-# Call aacDecoder_Open() to open and retrieve a handle to a new AAC decoder instance.
|
||||
\dontinclude main.cpp
|
||||
\skipline aacDecoder_Open
|
||||
-# If out-of-band config data (Audio Specific Config (ASC) or Stream Mux Config (SMC)) is available, call
|
||||
aacDecoder_ConfigRaw() to pass it to the decoder and before the decoding process starts. If this data is
|
||||
not available in advance, the decoder will get it from the bitstream and configure itself while decoding
|
||||
with aacDecoder_DecodeFrame().
|
||||
-# Begin decoding loop.
|
||||
\skipline do {
|
||||
-# Read data from bitstream file or stream into a client-supplied input buffer ("inBuffer" in main.cpp).
|
||||
If it is very small like just 4, aacDecoder_DecodeFrame() will
|
||||
repeatedly return ::AAC_DEC_NOT_ENOUGH_BITS until enough bits were fed by aacDecoder_Fill(). Only read data
|
||||
when this buffer has completely been processed and is then empty. For file-based input execute
|
||||
mpegFileRead_Read() or any other implementation with similar functionality.
|
||||
-# Call aacDecoder_Fill() to fill the decoder's internal bitstream input buffer with the client-supplied
|
||||
external bitstream input buffer.
|
||||
\skipline aacDecoder_Fill
|
||||
-# Call aacDecoder_DecodeFrame() which writes decoded PCM audio data to a client-supplied buffer. It is the
|
||||
client's responsibility to allocate a buffer which is large enough to hold this output data.
|
||||
\skipline aacDecoder_DecodeFrame
|
||||
If the bitstream's configuration (number of channels, sample rate, frame size) is not known in advance, you may
|
||||
call aacDecoder_GetStreamInfo() to retrieve a structure containing this information and then initialize an audio
|
||||
output device. In the example main.cpp, if the number of channels or the sample rate has changed since program
|
||||
start or since the previously decoded frame, the audio output device will be re-initialized. If WAVE file output
|
||||
is chosen, a new WAVE file for each new configuration will be created.
|
||||
\skipline aacDecoder_GetStreamInfo
|
||||
-# Repeat steps 5 to 7 until no data to decode is available anymore, or if an error occured.
|
||||
\skipline } while
|
||||
-# Call aacDecoder_Close() to de-allocate all AAC decoder and transport layer structures.
|
||||
\skipline aacDecoder_Close
|
||||
|
||||
\section BufferSystem Buffer System
|
||||
|
||||
There are three main buffers in an AAC decoder application. One external input buffer to hold bitstream
|
||||
data from file I/O or elsewhere, one decoder-internal input buffer, and one to hold the decoded output
|
||||
PCM sample data, whereas this output buffer may overlap with the external input buffer.
|
||||
|
||||
The external input buffer is set in the example framework main.cpp and its size is defined by ::IN_BUF_SIZE.
|
||||
You may freely choose different sizes here. To feed the data to the decoder-internal input buffer, use the
|
||||
function aacDecoder_Fill(). This function returns important information about how many bytes in the
|
||||
external input buffer have not yet been copied into the internal input buffer (variable bytesValid).
|
||||
Once the external buffer has been fully copied, it can be re-filled again.
|
||||
In case you want to re-fill it when there are still unprocessed bytes (bytesValid is unequal 0), you
|
||||
would have to additionally perform a memcpy(), so that just means unnecessary computational overhead
|
||||
and therefore we recommend to re-fill the buffer only when bytesValid is 0.
|
||||
|
||||
\image latex dec_buffer.png "Lifecycle of the external input buffer" width=9cm
|
||||
|
||||
The size of the decoder-internal input buffer is set in tpdec_lib.h (see define ::TRANSPORTDEC_INBUF_SIZE).
|
||||
You may choose a smaller size under the following considerations:
|
||||
|
||||
- each input channel requires 768 bytes
|
||||
- the whole buffer must be of size 2^n
|
||||
|
||||
So for example a stereo decoder:
|
||||
|
||||
\f[
|
||||
TRANSPORTDEC\_INBUF\_SIZE = 2 * 768 = 1536 => 2048
|
||||
\f]
|
||||
|
||||
tpdec_lib.h and TRANSPORTDEC_INBUF_SIZE are not part of the decoder's library interface. Therefore
|
||||
only source-code clients may change this setting. If you received a library release, please ask us and
|
||||
we can change this in order to meet your memory requirements.
|
||||
|
||||
\page OutputFormat Decoder audio output
|
||||
|
||||
\section OutputFormatObtaining Obtaining channel mapping information
|
||||
|
||||
The decoded audio output format is indicated by a set of variables of the CStreamInfo structure.
|
||||
While the members sampleRate, frameSize and numChannels might be quite self explaining,
|
||||
pChannelType and pChannelIndices might require some more detailed explanation.
|
||||
|
||||
These two arrays indicate what is each output channel supposed to be. Both array have
|
||||
CStreamInfo::numChannels cells. Each cell of pChannelType indicates the channel type, described in
|
||||
the enum ::AUDIO_CHANNEL_TYPE defined in FDK_audio.h. The cells of pChannelIndices indicate the sub index
|
||||
among the channels starting with 0 among all channels of the same audio channel type.
|
||||
|
||||
The indexing scheme is the same as for MPEG-2/4. Thus indices are counted upwards starting from the front
|
||||
direction (thus a center channel if any, will always be index 0). Then the indices count up, starting always
|
||||
with the left side, pairwise from front toward back. For detailed explanation, please refer to
|
||||
ISO/IEC 13818-7:2005(E), chapter 8.5.3.2.
|
||||
|
||||
In case a Program Config is included in the audio configuration, the channel mapping described within
|
||||
it will be adopted.
|
||||
|
||||
In case of MPEG-D Surround the channel mapping will follow the same criteria described in ISO/IEC 13818-7:2005(E),
|
||||
but adding corresponding top channels to the channel types front, side and back, in order to avoid any
|
||||
loss of information.
|
||||
|
||||
\section OutputFormatChange Changing the audio output format
|
||||
|
||||
The channel interleaving scheme and the actual channel order can be changed at runtime through the
|
||||
parameters ::AAC_PCM_OUTPUT_INTERLEAVED and ::AAC_PCM_OUTPUT_CHANNEL_MAPPING. See the description of those
|
||||
parameters and the decoder library function aacDecoder_SetParam() for more detail.
|
||||
|
||||
\section OutputFormatExample Channel mapping examples
|
||||
|
||||
The following examples illustrate the location of individual audio samples in the audio buffer that
|
||||
is passed to aacDecoder_DecodeFrame() and the expected data in the CStreamInfo structure which can be obtained
|
||||
by calling aacDecoder_GetStreamInfo().
|
||||
|
||||
\subsection ExamplesStereo Stereo
|
||||
|
||||
In case of ::AAC_PCM_OUTPUT_INTERLEAVED set to 0 and ::AAC_PCM_OUTPUT_CHANNEL_MAPPING set to 1,
|
||||
a AAC-LC bit stream which has channelConfiguration = 2 in its audio specific config would lead
|
||||
to the following values in CStreamInfo:
|
||||
|
||||
CStreamInfo::numChannels = 2
|
||||
|
||||
CStreamInfo::pChannelType = { ::ACT_FRONT, ::ACT_FRONT }
|
||||
|
||||
CStreamInfo::pChannelIndices = { 0, 1 }
|
||||
|
||||
Since ::AAC_PCM_OUTPUT_INTERLEAVED is set to 0, the audio channels will be located as contiguous blocks
|
||||
in the output buffer as follows:
|
||||
|
||||
\verbatim
|
||||
<left sample 0> <left sample 1> <left sample 2> ... <left sample N>
|
||||
<right sample 0> <right sample 1> <right sample 2> ... <right sample N>
|
||||
\endverbatim
|
||||
|
||||
Where N equals to CStreamInfo::frameSize .
|
||||
|
||||
\subsection ExamplesSurround Surround 5.1
|
||||
|
||||
In case of ::AAC_PCM_OUTPUT_INTERLEAVED set to 1 and ::AAC_PCM_OUTPUT_CHANNEL_MAPPING set to 1,
|
||||
a AAC-LC bit stream which has channelConfiguration = 6 in its audio specific config, would lead
|
||||
to the following values in CStreamInfo:
|
||||
|
||||
CStreamInfo::numChannels = 6
|
||||
|
||||
CStreamInfo::pChannelType = { ::ACT_FRONT, ::ACT_FRONT, ::ACT_FRONT, ::ACT_LFE, ::ACT_BACK, ::ACT_BACK }
|
||||
|
||||
CStreamInfo::pChannelIndices = { 1, 2, 0, 0, 0, 1 }
|
||||
|
||||
Since ::AAC_PCM_OUTPUT_CHANNEL_MAPPING is 1, WAV file channel ordering will be used. For a 5.1 channel
|
||||
scheme, thus the channels would be: front left, front right, center, LFE, surround left, surround right.
|
||||
Thus the third channel is the center channel, receiving the index 0. The other front channels are
|
||||
front left, front right being placed as first and second channels with indices 1 and 2 correspondingly.
|
||||
There is only one LFE, placed as the fourth channel and index 0. Finally both surround
|
||||
channels get the type definition ACT_BACK, and the indices 0 and 1.
|
||||
|
||||
Since ::AAC_PCM_OUTPUT_INTERLEAVED is set to 1, the audio channels will be placed in the output buffer
|
||||
as follows:
|
||||
|
||||
\verbatim
|
||||
<front left sample 0> <front right sample 0>
|
||||
<center sample 0> <LFE sample 0>
|
||||
<surround left sample 0> <surround right sample 0>
|
||||
|
||||
<front left sample 1> <front right sample 1>
|
||||
<center sample 1> <LFE sample 1>
|
||||
<surround left sample 1> <surround right sample 1>
|
||||
|
||||
...
|
||||
|
||||
<front left sample N> <front right sample N>
|
||||
<center sample N> <LFE sample N>
|
||||
<surround left sample N> <surround right sample N>
|
||||
\endverbatim
|
||||
|
||||
Where N equals to CStreamInfo::frameSize .
|
||||
|
||||
\subsection ExamplesArib ARIB coding mode 2/1
|
||||
|
||||
In case of ::AAC_PCM_OUTPUT_INTERLEAVED set to 1 and ::AAC_PCM_OUTPUT_CHANNEL_MAPPING set to 1,
|
||||
in case of a ARIB bit stream using coding mode 2/1 as described in ARIB STD-B32 Part 2 Version 2.1-E1, page 61,
|
||||
would lead to the following values in CStreamInfo:
|
||||
|
||||
CStreamInfo::numChannels = 3
|
||||
|
||||
CStreamInfo::pChannelType = { ::ACT_FRONT, ::ACT_FRONT,:: ACT_BACK }
|
||||
|
||||
CStreamInfo::pChannelIndices = { 0, 1, 0 }
|
||||
|
||||
The audio channels will be placed as follows in the audio output buffer:
|
||||
|
||||
\verbatim
|
||||
<front left sample 0> <front right sample 0> <mid surround sample 0>
|
||||
|
||||
<front left sample 1> <front right sample 1> <mid surround sample 1>
|
||||
|
||||
...
|
||||
|
||||
<front left sample N> <front right sample N> <mid surround sample N>
|
||||
|
||||
Where N equals to CStreamInfo::frameSize .
|
||||
|
||||
\endverbatim
|
||||
|
||||
*/
|
||||
|
||||
#ifndef AACDECODER_LIB_H
|
||||
#define AACDECODER_LIB_H
|
||||
|
||||
#include "machine_type.h"
|
||||
#include "FDK_audio.h"
|
||||
|
||||
#include "genericStds.h"
|
||||
|
||||
/**
|
||||
* \brief AAC decoder error codes.
|
||||
*/
|
||||
typedef enum {
|
||||
AAC_DEC_OK = 0x0000, /*!< No error occured. Output buffer is valid and error free. */
|
||||
AAC_DEC_OUT_OF_MEMORY = 0x0002, /*!< Heap returned NULL pointer. Output buffer is invalid. */
|
||||
AAC_DEC_UNKNOWN = 0x0005, /*!< Error condition is of unknown reason, or from a another module. Output buffer is invalid. */
|
||||
|
||||
/* Synchronization errors. Output buffer is invalid. */
|
||||
aac_dec_sync_error_start = 0x1000,
|
||||
AAC_DEC_TRANSPORT_SYNC_ERROR = 0x1001, /*!< The transport decoder had syncronisation problems. Do not exit decoding. Just feed new
|
||||
bitstream data. */
|
||||
AAC_DEC_NOT_ENOUGH_BITS = 0x1002, /*!< The input buffer ran out of bits. */
|
||||
aac_dec_sync_error_end = 0x1FFF,
|
||||
|
||||
/* Initialization errors. Output buffer is invalid. */
|
||||
aac_dec_init_error_start = 0x2000,
|
||||
AAC_DEC_INVALID_HANDLE = 0x2001, /*!< The handle passed to the function call was invalid (NULL). */
|
||||
AAC_DEC_UNSUPPORTED_AOT = 0x2002, /*!< The AOT found in the configuration is not supported. */
|
||||
AAC_DEC_UNSUPPORTED_FORMAT = 0x2003, /*!< The bitstream format is not supported. */
|
||||
AAC_DEC_UNSUPPORTED_ER_FORMAT = 0x2004, /*!< The error resilience tool format is not supported. */
|
||||
AAC_DEC_UNSUPPORTED_EPCONFIG = 0x2005, /*!< The error protection format is not supported. */
|
||||
AAC_DEC_UNSUPPORTED_MULTILAYER = 0x2006, /*!< More than one layer for AAC scalable is not supported. */
|
||||
AAC_DEC_UNSUPPORTED_CHANNELCONFIG = 0x2007, /*!< The channel configuration (either number or arrangement) is not supported. */
|
||||
AAC_DEC_UNSUPPORTED_SAMPLINGRATE = 0x2008, /*!< The sample rate specified in the configuration is not supported. */
|
||||
AAC_DEC_INVALID_SBR_CONFIG = 0x2009, /*!< The SBR configuration is not supported. */
|
||||
AAC_DEC_SET_PARAM_FAIL = 0x200A, /*!< The parameter could not be set. Either the value was out of range or the parameter does
|
||||
not exist. */
|
||||
AAC_DEC_NEED_TO_RESTART = 0x200B, /*!< The decoder needs to be restarted, since the requiered configuration change cannot be
|
||||
performed. */
|
||||
aac_dec_init_error_end = 0x2FFF,
|
||||
|
||||
/* Decode errors. Output buffer is valid but concealed. */
|
||||
aac_dec_decode_error_start = 0x4000,
|
||||
AAC_DEC_TRANSPORT_ERROR = 0x4001, /*!< The transport decoder encountered an unexpected error. */
|
||||
AAC_DEC_PARSE_ERROR = 0x4002, /*!< Error while parsing the bitstream. Most probably it is corrupted, or the system crashed. */
|
||||
AAC_DEC_UNSUPPORTED_EXTENSION_PAYLOAD = 0x4003, /*!< Error while parsing the extension payload of the bitstream. The extension payload type
|
||||
found is not supported. */
|
||||
AAC_DEC_DECODE_FRAME_ERROR = 0x4004, /*!< The parsed bitstream value is out of range. Most probably the bitstream is corrupt, or
|
||||
the system crashed. */
|
||||
AAC_DEC_CRC_ERROR = 0x4005, /*!< The embedded CRC did not match. */
|
||||
AAC_DEC_INVALID_CODE_BOOK = 0x4006, /*!< An invalid codebook was signalled. Most probably the bitstream is corrupt, or the system
|
||||
crashed. */
|
||||
AAC_DEC_UNSUPPORTED_PREDICTION = 0x4007, /*!< Predictor found, but not supported in the AAC Low Complexity profile. Most probably the
|
||||
bitstream is corrupt, or has a wrong format. */
|
||||
AAC_DEC_UNSUPPORTED_CCE = 0x4008, /*!< A CCE element was found which is not supported. Most probably the bitstream is corrupt, or
|
||||
has a wrong format. */
|
||||
AAC_DEC_UNSUPPORTED_LFE = 0x4009, /*!< A LFE element was found which is not supported. Most probably the bitstream is corrupt, or
|
||||
has a wrong format. */
|
||||
AAC_DEC_UNSUPPORTED_GAIN_CONTROL_DATA = 0x400A, /*!< Gain control data found but not supported. Most probably the bitstream is corrupt, or has
|
||||
a wrong format. */
|
||||
AAC_DEC_UNSUPPORTED_SBA = 0x400B, /*!< SBA found, but currently not supported in the BSAC profile. */
|
||||
AAC_DEC_TNS_READ_ERROR = 0x400C, /*!< Error while reading TNS data. Most probably the bitstream is corrupt or the system
|
||||
crashed. */
|
||||
AAC_DEC_RVLC_ERROR = 0x400D, /*!< Error while decoding error resillient data. */
|
||||
aac_dec_decode_error_end = 0x4FFF,
|
||||
|
||||
/* Ancillary data errors. Output buffer is valid. */
|
||||
aac_dec_anc_data_error_start = 0x8000,
|
||||
AAC_DEC_ANC_DATA_ERROR = 0x8001, /*!< Non severe error concerning the ancillary data handling. */
|
||||
AAC_DEC_TOO_SMALL_ANC_BUFFER = 0x8002, /*!< The registered ancillary data buffer is too small to receive the parsed data. */
|
||||
AAC_DEC_TOO_MANY_ANC_ELEMENTS = 0x8003, /*!< More than the allowed number of ancillary data elements should be written to buffer. */
|
||||
aac_dec_anc_data_error_end = 0x8FFF
|
||||
|
||||
|
||||
} AAC_DECODER_ERROR;
|
||||
|
||||
|
||||
/** Macro to identify initialization errors. */
|
||||
#define IS_INIT_ERROR(err) ( (((err)>=aac_dec_init_error_start) && ((err)<=aac_dec_init_error_end)) ? 1 : 0)
|
||||
/** Macro to identify decode errors. */
|
||||
#define IS_DECODE_ERROR(err) ( (((err)>=aac_dec_decode_error_start) && ((err)<=aac_dec_decode_error_end)) ? 1 : 0)
|
||||
/** Macro to identify if the audio output buffer contains valid samples after calling aacDecoder_DecodeFrame(). */
|
||||
#define IS_OUTPUT_VALID(err) ( ((err) == AAC_DEC_OK) || IS_DECODE_ERROR(err) )
|
||||
|
||||
/**
|
||||
* \brief AAC decoder setting parameters
|
||||
*/
|
||||
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.
|
||||
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_CONCEAL_METHOD = 0x0100, /*!< Error concealment: Processing method. \n
|
||||
0: Spectral muting. \n
|
||||
1: Noise substitution (see ::CONCEAL_NOISE). \n
|
||||
2: Energy interpolation (adds additional signal delay of one frame, see ::CONCEAL_INTER). \n */
|
||||
|
||||
AAC_DRC_BOOST_FACTOR = 0x0200, /*!< Dynamic Range Control: Scaling factor for boosting gain values.
|
||||
Defines how the boosting DRC factors (conveyed in the bitstream) will be applied to the
|
||||
decoded signal. The valid values range from 0 (don't apply boost factors) to 127 (fully
|
||||
apply all boosting factors). */
|
||||
AAC_DRC_ATTENUATION_FACTOR = 0x0201, /*!< Dynamic Range Control: Scaling factor for attenuating gain values. Same as
|
||||
AAC_DRC_BOOST_FACTOR but for attenuating DRC factors. */
|
||||
AAC_DRC_REFERENCE_LEVEL = 0x0202, /*!< Dynamic Range Control: Target reference level. Defines the level below full-scale
|
||||
(quantized in steps of 0.25dB) to which the output audio signal will be normalized to by
|
||||
the DRC module. The valid values range from 0 (full-scale) to 127 (31.75 dB below
|
||||
full-scale). The value smaller than 0 switches off normalization. */
|
||||
AAC_DRC_HEAVY_COMPRESSION = 0x0203, /*!< Dynamic Range Control: En-/Disable DVB specific heavy compression (aka RF mode).
|
||||
If set to 1, the decoder will apply the compression values from the DVB specific ancillary
|
||||
data field. At the same time the MPEG-4 Dynamic Range Control tool will be disabled. By
|
||||
default heavy compression is disabled. */
|
||||
|
||||
AAC_QMF_LOWPOWER = 0x0300, /*!< Quadrature Mirror Filter (QMF) Bank processing mode. \n
|
||||
-1: Use internal default. Implies MPEG Surround partially complex accordingly. \n
|
||||
0: Use complex QMF data mode. \n
|
||||
1: Use real (low power) QMF data mode. \n */
|
||||
|
||||
AAC_MPEGS_ENABLE = 0x0500, /*!< MPEG Surround: Allow/Disable decoding of MPS content. Available only for decoders with MPEG
|
||||
Surround support. */
|
||||
|
||||
AAC_TPDEC_CLEAR_BUFFER = 0x0603 /*!< Clear internal bit stream buffer of transport layers. The decoder will start decoding
|
||||
at new data passed after this event and any previous data is discarded. */
|
||||
|
||||
} AACDEC_PARAM;
|
||||
|
||||
/**
|
||||
* \brief This structure gives information about the currently decoded audio data.
|
||||
* All fields are read-only.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/* These three 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.
|
||||
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 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, ... */
|
||||
INT bitRate; /*!< Instantaneous bit rate. */
|
||||
INT aacSamplesPerFrame; /*!< Samples per frame for the AAC core (from ASC). \n
|
||||
1024 or 960 for AAC-LC \n
|
||||
512 or 480 for AAC-LD and AAC-ELD */
|
||||
|
||||
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. */
|
||||
|
||||
SCHAR epConfig; /*!< epConfig level (from ASC): only level 0 supported, -1 means no ER (e. g. AOT=2, MPEG-2 AAC, etc.) */
|
||||
|
||||
/* Statistics */
|
||||
INT numLostAccessUnits; /*!< This integer will reflect the estimated amount of lost access units in case aacDecoder_DecodeFrame()
|
||||
returns AAC_DEC_TRANSPORT_SYNC_ERROR. It will be < 0 if the estimation failed. */
|
||||
|
||||
UINT numTotalBytes; /*!< This is the number of total bytes that have passed through the decoder. */
|
||||
UINT numBadBytes; /*!< This is the number of total bytes that were considered with errors from numTotalBytes. */
|
||||
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. */
|
||||
|
||||
} CStreamInfo;
|
||||
|
||||
|
||||
typedef struct AAC_DECODER_INSTANCE *HANDLE_AACDECODER;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Initialize ancillary data buffer.
|
||||
*
|
||||
* \param self AAC decoder handle.
|
||||
* \param buffer Pointer to (external) ancillary data buffer.
|
||||
* \param size Size of the buffer pointed to by buffer.
|
||||
* \return Error code.
|
||||
*/
|
||||
LINKSPEC_H AAC_DECODER_ERROR
|
||||
aacDecoder_AncDataInit ( HANDLE_AACDECODER self,
|
||||
UCHAR *buffer,
|
||||
int size );
|
||||
|
||||
/**
|
||||
* \brief Get one ancillary data element.
|
||||
*
|
||||
* \param self AAC decoder handle.
|
||||
* \param index Index of the ancillary data element to get.
|
||||
* \param ptr Pointer to a buffer receiving a pointer to the requested ancillary data element.
|
||||
* \param size Pointer to a buffer receiving the length of the requested ancillary data element.
|
||||
* \return Error code.
|
||||
*/
|
||||
LINKSPEC_H AAC_DECODER_ERROR
|
||||
aacDecoder_AncDataGet ( HANDLE_AACDECODER self,
|
||||
int index,
|
||||
UCHAR **ptr,
|
||||
int *size );
|
||||
|
||||
/**
|
||||
* \brief Set one single decoder parameter.
|
||||
*
|
||||
* \param self AAC decoder handle.
|
||||
* \param param Parameter to be set.
|
||||
* \param value Parameter value.
|
||||
* \return Error code.
|
||||
*/
|
||||
LINKSPEC_H AAC_DECODER_ERROR
|
||||
aacDecoder_SetParam ( const HANDLE_AACDECODER self,
|
||||
const AACDEC_PARAM param,
|
||||
const INT value );
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get free bytes inside decoder internal buffer
|
||||
* \param self Handle of AAC decoder instance
|
||||
* \param pFreeBytes Pointer to variable receving amount of free bytes inside decoder internal buffer
|
||||
* \return Error code
|
||||
*/
|
||||
LINKSPEC_H AAC_DECODER_ERROR
|
||||
aacDecoder_GetFreeBytes ( const HANDLE_AACDECODER self,
|
||||
UINT *pFreeBytes);
|
||||
|
||||
/**
|
||||
* \brief Open an AAC decoder instance
|
||||
* \param transportFmt The transport type to be used
|
||||
* \return AAC decoder handle
|
||||
*/
|
||||
LINKSPEC_H HANDLE_AACDECODER
|
||||
aacDecoder_Open ( TRANSPORT_TYPE transportFmt, UINT nrOfLayers );
|
||||
|
||||
/**
|
||||
* \brief Explicitly configure the decoder by passing a raw AudioSpecificConfig (ASC) or a StreamMuxConfig (SMC),
|
||||
* contained in a binary buffer. This is required for MPEG-4 and Raw Packets file format bitstreams
|
||||
* as well as for LATM bitstreams with no in-band SMC. If the transport format is LATM with or without
|
||||
* LOAS, configuration is assumed to be an SMC, for all other file formats an ASC.
|
||||
*
|
||||
* \param self AAC decoder handle.
|
||||
* \param conf Pointer to an unsigned char buffer containing the binary configuration buffer (either ASC or SMC).
|
||||
* \param length Length of the configuration buffer in bytes.
|
||||
* \return Error code.
|
||||
*/
|
||||
LINKSPEC_H AAC_DECODER_ERROR
|
||||
aacDecoder_ConfigRaw ( HANDLE_AACDECODER self,
|
||||
UCHAR *conf[],
|
||||
const UINT length[] );
|
||||
|
||||
|
||||
/**
|
||||
* \brief Fill AAC decoder's internal input buffer with bitstream data from the external input buffer.
|
||||
* The function only copies such data as long as the decoder-internal input buffer is not full.
|
||||
* So it grabs whatever it can from pBuffer and returns information (bytesValid) so that at a
|
||||
* subsequent call of %aacDecoder_Fill(), the right position in pBuffer can be determined to
|
||||
* grab the next data.
|
||||
*
|
||||
* \param self AAC decoder handle.
|
||||
* \param pBuffer Pointer to external input buffer.
|
||||
* \param bufferSize Size of external input buffer. This argument is required because decoder-internally
|
||||
* we need the information to calculate the offset to pBuffer, where the next
|
||||
* available data is, which is then fed into the decoder-internal buffer (as much
|
||||
* as possible). Our example framework implementation fills the buffer at pBuffer
|
||||
* again, once it contains no available valid bytes anymore (meaning bytesValid equal 0).
|
||||
* \param bytesValid Number of bitstream bytes in the external bitstream buffer that have not yet been
|
||||
* copied into the decoder's internal bitstream buffer by calling this function.
|
||||
* The value is updated according to the amount of newly copied bytes.
|
||||
* \return Error code.
|
||||
*/
|
||||
LINKSPEC_H AAC_DECODER_ERROR
|
||||
aacDecoder_Fill ( HANDLE_AACDECODER self,
|
||||
UCHAR *pBuffer[],
|
||||
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. */
|
||||
|
||||
/**
|
||||
* \brief Decode one audio frame
|
||||
*
|
||||
* \param self AAC decoder handle.
|
||||
* \param pTimeData Pointer to external output buffer where the decoded PCM samples will be stored into.
|
||||
* \param flags Bit field with flags for the decoder: \n
|
||||
* (flags & AACDEC_CONCEAL) == 1: Do concealment. \n
|
||||
* (flags & AACDEC_FLUSH) == 2: Discard input data. Flush filter banks (output delayed audio). \n
|
||||
* (flags & AACDEC_INTR) == 4: Input data is discontinuous. Resynchronize any internals as necessary.
|
||||
* \return Error code.
|
||||
*/
|
||||
LINKSPEC_H AAC_DECODER_ERROR
|
||||
aacDecoder_DecodeFrame ( HANDLE_AACDECODER self,
|
||||
INT_PCM *pTimeData,
|
||||
const INT timeDataSize,
|
||||
const UINT flags );
|
||||
|
||||
/**
|
||||
* \brief De-allocate all resources of an AAC decoder instance.
|
||||
*
|
||||
* \param self AAC decoder handle.
|
||||
* \return void
|
||||
*/
|
||||
LINKSPEC_H void aacDecoder_Close ( HANDLE_AACDECODER self );
|
||||
|
||||
/**
|
||||
* \brief Get CStreamInfo handle from decoder.
|
||||
*
|
||||
* \param self AAC decoder handle.
|
||||
* \return Reference to requested CStreamInfo.
|
||||
*/
|
||||
LINKSPEC_H CStreamInfo* aacDecoder_GetStreamInfo( HANDLE_AACDECODER self );
|
||||
|
||||
/**
|
||||
* \brief Get decoder library info.
|
||||
*
|
||||
* \param info Pointer to an allocated LIB_INFO structure.
|
||||
* \return 0 on success
|
||||
*/
|
||||
LINKSPEC_H INT aacDecoder_GetLibInfo( LIB_INFO *info );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AACDECODER_LIB_H */
|
39
libAACdec/src/Android.mk
Normal file
39
libAACdec/src/Android.mk
Normal file
@ -0,0 +1,39 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := \
|
||||
aacdec_drc.cpp \
|
||||
aacdec_hcr.cpp \
|
||||
aacdecoder.cpp \
|
||||
aacdec_pns.cpp \
|
||||
aac_ram.cpp \
|
||||
block.cpp \
|
||||
channelinfo.cpp \
|
||||
ldfiltbank.cpp \
|
||||
rvlcbit.cpp \
|
||||
rvlc.cpp \
|
||||
aacdec_hcr_bit.cpp \
|
||||
aacdec_hcrs.cpp \
|
||||
aacdecoder_lib.cpp \
|
||||
aacdec_tns.cpp \
|
||||
aac_rom.cpp \
|
||||
channel.cpp \
|
||||
conceal.cpp \
|
||||
pulsedata.cpp \
|
||||
rvlcconceal.cpp \
|
||||
stereo.cpp
|
||||
|
||||
LOCAL_CFLAGS := -DANDROID
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(LOCAL_PATH) \
|
||||
$(LOCAL_PATH)/../include \
|
||||
$(LOCAL_PATH)/../../libPCMutils/include \
|
||||
$(LOCAL_PATH)/../../libFDK/include \
|
||||
$(LOCAL_PATH)/../../libSYS/include \
|
||||
$(LOCAL_PATH)/../../libMpegTPDec/include \
|
||||
$(LOCAL_PATH)/../../libSBRdec/include
|
||||
|
||||
LOCAL_MODULE:= libAACdec
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
81
libAACdec/src/aac_ram.cpp
Normal file
81
libAACdec/src/aac_ram.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2002)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description:
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "aac_ram.h"
|
||||
#include "aac_rom.h"
|
||||
|
||||
#define WORKBUFFER1_TAG 0
|
||||
#define WORKBUFFER2_TAG 1
|
||||
|
||||
/*! The structure AAC_DECODER_INSTANCE is the top level structure holding all decoder configurations,
|
||||
handles and structs.
|
||||
*/
|
||||
C_ALLOC_MEM(AacDecoder, AAC_DECODER_INSTANCE, 1)
|
||||
|
||||
/*!
|
||||
\name StaticAacData
|
||||
|
||||
Static memory areas, must not be overwritten in other sections of the decoder
|
||||
*/
|
||||
/* @{ */
|
||||
|
||||
/*! 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))
|
||||
|
||||
/*! 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))
|
||||
|
||||
/*! Overlap buffer */
|
||||
C_ALLOC_MEM2(OverlapBuffer, FIXP_DBL, OverlapBufferSize, (6))
|
||||
|
||||
C_ALLOC_MEM(DrcInfo, CDrcInfo, 1)
|
||||
|
||||
/* @} */
|
||||
|
||||
/*!
|
||||
\name DynamicAacData
|
||||
|
||||
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(WorkBufferCore1, CWorkBufferCore1, 1, SECT_DATA_L1, WORKBUFFER1_TAG)
|
||||
|
||||
/* @{ */
|
||||
|
||||
|
||||
/* @} */
|
||||
|
||||
|
||||
|
58
libAACdec/src/aac_ram.h
Normal file
58
libAACdec/src/aac_ram.h
Normal file
@ -0,0 +1,58 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2005)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description:
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef AAC_RAM_H
|
||||
#define AAC_RAM_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "aacdecoder.h"
|
||||
|
||||
#include "channel.h"
|
||||
|
||||
#include "aacdec_hcr_types.h"
|
||||
#include "aacdec_hcr.h"
|
||||
|
||||
/* End of formal fix.h */
|
||||
|
||||
#define MAX_SYNCHS 10
|
||||
#define SAMPL_FREQS 12
|
||||
|
||||
H_ALLOC_MEM(AacDecoder, AAC_DECODER_INSTANCE)
|
||||
|
||||
H_ALLOC_MEM(DrcInfo, CDrcInfo)
|
||||
|
||||
H_ALLOC_MEM(AacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo)
|
||||
H_ALLOC_MEM(AacDecoderChannelInfo, CAacDecoderChannelInfo)
|
||||
H_ALLOC_MEM(OverlapBuffer, FIXP_DBL)
|
||||
|
||||
H_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1)
|
||||
H_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL)
|
||||
|
||||
|
||||
#endif /* #ifndef AAC_RAM_H */
|
1780
libAACdec/src/aac_rom.cpp
Normal file
1780
libAACdec/src/aac_rom.cpp
Normal file
File diff suppressed because it is too large
Load Diff
125
libAACdec/src/aac_rom.h
Normal file
125
libAACdec/src/aac_rom.h
Normal file
@ -0,0 +1,125 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description: Definition of constant tables
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef AAC_ROM_H
|
||||
#define AAC_ROM_H
|
||||
|
||||
#include "common_fix.h"
|
||||
#include "FDK_audio.h"
|
||||
#include "aacdec_hcr_types.h"
|
||||
#include "aacdec_hcrs.h"
|
||||
|
||||
#define AAC_NF_NO_RANDOM_VAL 512 /*!< Size of random number array for noise floor */
|
||||
|
||||
#define INV_QUANT_TABLESIZE 256
|
||||
|
||||
extern const FIXP_DBL InverseQuantTable [INV_QUANT_TABLESIZE + 1] ;
|
||||
extern const FIXP_DBL MantissaTable [4][14] ;
|
||||
extern const SCHAR ExponentTable [4][14] ;
|
||||
|
||||
#define NUM_LD_COEF_512 1536
|
||||
#define NUM_LD_COEF_480 1440
|
||||
/* Window table partition exponents. */
|
||||
#define WTS0 (1)
|
||||
#define WTS1 (0)
|
||||
#define WTS2 (-2)
|
||||
extern const FIXP_WTB LowDelaySynthesis512[1536];
|
||||
extern const FIXP_WTB LowDelaySynthesis480[1440];
|
||||
|
||||
typedef struct {
|
||||
const SHORT *sfbOffsetLong;
|
||||
const SHORT *sfbOffsetShort;
|
||||
UCHAR numberOfSfbLong;
|
||||
UCHAR numberOfSfbShort;
|
||||
} SFB_INFO;
|
||||
|
||||
extern const SFB_INFO sfbOffsetTables[5][16];
|
||||
|
||||
/* Huffman tables */
|
||||
enum {
|
||||
HuffmanBits = 2,
|
||||
HuffmanEntries = (1 << HuffmanBits)
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const USHORT (*CodeBook)[HuffmanEntries];
|
||||
UCHAR Dimension;
|
||||
UCHAR numBits;
|
||||
UCHAR Offset;
|
||||
} CodeBookDescription;
|
||||
|
||||
extern const CodeBookDescription AACcodeBookDescriptionTable[13];
|
||||
extern const CodeBookDescription AACcodeBookDescriptionSCL;
|
||||
|
||||
|
||||
extern const STATEFUNC aStateConstant2State[];
|
||||
|
||||
extern const SCHAR aCodebook2StartInt[];
|
||||
|
||||
extern const UCHAR aMinOfCbPair[];
|
||||
extern const UCHAR aMaxOfCbPair[];
|
||||
|
||||
extern const UCHAR aMaxCwLen[];
|
||||
extern const UCHAR aDimCb[];
|
||||
extern const UCHAR aDimCbShift[];
|
||||
extern const UCHAR aSignCb[];
|
||||
extern const UCHAR aCbPriority[];
|
||||
|
||||
extern const UINT *aHuffTable[];
|
||||
extern const SCHAR *aQuantTable[];
|
||||
|
||||
extern const USHORT aLargestAbsoluteValue[];
|
||||
|
||||
extern const UINT aHuffTreeRvlcEscape[];
|
||||
extern const UINT aHuffTreeRvlCodewds[];
|
||||
|
||||
|
||||
extern const UCHAR tns_max_bands_tbl[13][2];
|
||||
|
||||
extern const UCHAR tns_max_bands_tbl_480[5];
|
||||
extern const UCHAR tns_max_bands_tbl_512[5];
|
||||
|
||||
#define FIXP_TCC FIXP_DBL
|
||||
|
||||
extern const FIXP_TCC FDKaacDec_tnsCoeff3[8];
|
||||
extern const FIXP_TCC FDKaacDec_tnsCoeff4[16];
|
||||
|
||||
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];
|
||||
|
||||
/* Lookup tables for elements in ER bitstream */
|
||||
extern const MP4_ELEMENT_ID elementsTab[8][7];
|
||||
|
||||
#endif /* #ifndef AAC_ROM_H */
|
997
libAACdec/src/aacdec_drc.cpp
Normal file
997
libAACdec/src/aacdec_drc.cpp
Normal file
@ -0,0 +1,997 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Christian Griebel
|
||||
Description: Dynamic range control (DRC) decoder tool for AAC
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "aacdec_drc.h"
|
||||
|
||||
|
||||
#include "channelinfo.h"
|
||||
#include "aac_rom.h"
|
||||
|
||||
#include "sbrdecoder.h"
|
||||
|
||||
/*
|
||||
* Dynamic Range Control
|
||||
*/
|
||||
|
||||
/* For parameter conversion */
|
||||
#define DRC_PARAMETER_BITS ( 7 )
|
||||
#define DRC_MAX_QUANT_STEPS ( 1<<DRC_PARAMETER_BITS )
|
||||
#define DRC_MAX_QUANT_FACTOR ( DRC_MAX_QUANT_STEPS-1 )
|
||||
#define DRC_PARAM_QUANT_STEP ( FL2FXCONST_DBL(1.0f/(float)DRC_MAX_QUANT_STEPS) )
|
||||
#define DRC_PARAM_SCALE ( 1 )
|
||||
|
||||
#define MAX_REFERENCE_LEVEL ( 127 )
|
||||
|
||||
#define DVB_ANC_DATA_SYNC_BYTE ( 0xBC ) /* DVB ancillary data sync byte. */
|
||||
|
||||
/*!
|
||||
\brief Initialize DRC information
|
||||
|
||||
\self Handle of DRC info
|
||||
|
||||
\return none
|
||||
*/
|
||||
void aacDecoder_drcInit (
|
||||
HANDLE_AAC_DRC self )
|
||||
{
|
||||
CDrcParams *pParams;
|
||||
|
||||
if (self == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* init control fields */
|
||||
self->enable = 0;
|
||||
self->numThreads = 0;
|
||||
self->digitalNorm = 0;
|
||||
|
||||
/* init params */
|
||||
pParams = &self->params;
|
||||
pParams->bsDelayEnable = 0;
|
||||
pParams->cut = FL2FXCONST_DBL(0.0f);
|
||||
pParams->boost = FL2FXCONST_DBL(0.0f);
|
||||
pParams->targetRefLevel = AACDEC_DRC_DEFAULT_REF_LEVEL;
|
||||
pParams->expiryFrame = AACDEC_DRC_DFLT_EXPIRY_FRAMES;
|
||||
|
||||
/* initial program ref level = target ref level */
|
||||
self->progRefLevel = pParams->targetRefLevel;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Initialize DRC control data for one channel
|
||||
|
||||
\self Handle of DRC info
|
||||
|
||||
\return none
|
||||
*/
|
||||
void aacDecoder_drcInitChannelData (
|
||||
CDrcChannelData *pDrcChData )
|
||||
{
|
||||
if (pDrcChData != NULL) {
|
||||
pDrcChData->expiryCount = 0;
|
||||
pDrcChData->numBands = 1;
|
||||
pDrcChData->bandTop[0] = (1024 >> 2) - 1;
|
||||
pDrcChData->drcValue[0] = 0;
|
||||
pDrcChData->drcInterpolationScheme = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Set one single DRC parameter
|
||||
|
||||
\self Handle of DRC info.
|
||||
\param Parameter to be set.
|
||||
\value Value to be set.
|
||||
|
||||
\return an error code.
|
||||
*/
|
||||
AAC_DECODER_ERROR aacDecoder_drcSetParam (
|
||||
HANDLE_AAC_DRC self,
|
||||
AACDEC_DRC_PARAM param,
|
||||
INT value )
|
||||
{
|
||||
AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
|
||||
|
||||
switch (param)
|
||||
{
|
||||
case DRC_CUT_SCALE:
|
||||
/* set attenuation scale factor */
|
||||
if ( (value < 0)
|
||||
|| (value > DRC_MAX_QUANT_FACTOR) ) {
|
||||
return AAC_DEC_SET_PARAM_FAIL;
|
||||
}
|
||||
if (self == NULL) {
|
||||
return AAC_DEC_INVALID_HANDLE;
|
||||
}
|
||||
self->params.cut = (FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP>>DRC_PARAM_SCALE) * (INT)(value+1));
|
||||
break;
|
||||
case DRC_BOOST_SCALE:
|
||||
/* set boost factor */
|
||||
if ( (value < 0)
|
||||
|| (value > DRC_MAX_QUANT_FACTOR) ) {
|
||||
return AAC_DEC_SET_PARAM_FAIL;
|
||||
}
|
||||
if (self == NULL) {
|
||||
return AAC_DEC_INVALID_HANDLE;
|
||||
}
|
||||
self->params.boost = (FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP>>DRC_PARAM_SCALE) * (INT)(value+1));
|
||||
break;
|
||||
case TARGET_REF_LEVEL:
|
||||
if ( value > MAX_REFERENCE_LEVEL
|
||||
|| value < -MAX_REFERENCE_LEVEL ) {
|
||||
return AAC_DEC_SET_PARAM_FAIL;
|
||||
}
|
||||
if (self == NULL) {
|
||||
return AAC_DEC_INVALID_HANDLE;
|
||||
}
|
||||
if (value < 0) {
|
||||
self->digitalNorm = 0;
|
||||
}
|
||||
else {
|
||||
/* ref_level must be between 0 and MAX_REFERENCE_LEVEL, inclusive */
|
||||
self->digitalNorm = 1;
|
||||
self->progRefLevel = AACDEC_DRC_DEFAULT_REF_LEVEL;
|
||||
self->params.targetRefLevel = value;
|
||||
}
|
||||
break;
|
||||
case APPLY_HEAVY_COMPRESSION:
|
||||
if (value < 0 || value > 1) {
|
||||
return AAC_DEC_SET_PARAM_FAIL;
|
||||
}
|
||||
if (self == NULL) {
|
||||
return AAC_DEC_INVALID_HANDLE;
|
||||
}
|
||||
self->params.applyHeavyCompression = (UCHAR)value;
|
||||
break;
|
||||
case DRC_BS_DELAY:
|
||||
if (value < 0 || value > 1) {
|
||||
return AAC_DEC_SET_PARAM_FAIL;
|
||||
}
|
||||
if (self == NULL) {
|
||||
return AAC_DEC_INVALID_HANDLE;
|
||||
}
|
||||
self->params.bsDelayEnable = value;
|
||||
break;
|
||||
case DRC_DATA_EXPIRY_FRAME:
|
||||
if (self == NULL) {
|
||||
return AAC_DEC_INVALID_HANDLE;
|
||||
}
|
||||
self->params.expiryFrame = (UINT)value;
|
||||
break;
|
||||
default:
|
||||
return AAC_DEC_SET_PARAM_FAIL;
|
||||
} /* switch(param) */
|
||||
|
||||
/* switch on/off processing */
|
||||
self->enable = ( (self->params.boost > (FIXP_DBL)0)
|
||||
|| (self->params.cut > (FIXP_DBL)0)
|
||||
|| (self->params.applyHeavyCompression != 0)
|
||||
|| (self->digitalNorm == 1) );
|
||||
|
||||
|
||||
return ErrorStatus;
|
||||
}
|
||||
|
||||
|
||||
static int parseExcludedChannels( UINT *excludedChnsMask,
|
||||
HANDLE_FDK_BITSTREAM bs )
|
||||
{
|
||||
UINT excludeMask = 0;
|
||||
UINT i, j;
|
||||
int bitCnt = 9;
|
||||
|
||||
for (i = 0, j = 1; i < 7; i++, j<<=1) {
|
||||
if (FDKreadBits(bs,1)) {
|
||||
excludeMask |= j;
|
||||
}
|
||||
}
|
||||
|
||||
/* additional_excluded_chns */
|
||||
while (FDKreadBits(bs,1)) {
|
||||
for (i = 0; i < 7; i++, j<<=1) {
|
||||
if (FDKreadBits(bs,1)) {
|
||||
excludeMask |= j;
|
||||
}
|
||||
}
|
||||
bitCnt += 9;
|
||||
FDK_ASSERT(j < (UINT)-1);
|
||||
}
|
||||
|
||||
*excludedChnsMask = excludeMask;
|
||||
|
||||
return (bitCnt);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Save DRC payload bitstream position
|
||||
|
||||
\self Handle of DRC info
|
||||
\bs Handle of FDK bitstream
|
||||
|
||||
\return The number of DRC payload bits
|
||||
*/
|
||||
int aacDecoder_drcMarkPayload (
|
||||
HANDLE_AAC_DRC self,
|
||||
HANDLE_FDK_BITSTREAM bs,
|
||||
AACDEC_DRC_PAYLOAD_TYPE type )
|
||||
{
|
||||
UINT bsStartPos;
|
||||
int i, numBands = 1, bitCnt = 0;
|
||||
|
||||
if (self == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bsStartPos = FDKgetValidBits(bs);
|
||||
|
||||
switch (type) {
|
||||
case MPEG_DRC_EXT_DATA:
|
||||
{
|
||||
bitCnt = 4;
|
||||
|
||||
if (FDKreadBits(bs,1)) { /* pce_tag_present */
|
||||
FDKreadBits(bs,8); /* pce_instance_tag + drc_tag_reserved_bits */
|
||||
bitCnt+=8;
|
||||
}
|
||||
|
||||
if (FDKreadBits(bs,1)) { /* excluded_chns_present */
|
||||
FDKreadBits(bs,7); /* exclude mask [0..7] */
|
||||
bitCnt+=8;
|
||||
while (FDKreadBits(bs,1)) { /* additional_excluded_chns */
|
||||
FDKreadBits(bs,7); /* exclude mask [x..y] */
|
||||
bitCnt+=8;
|
||||
}
|
||||
}
|
||||
|
||||
if (FDKreadBits(bs,1)) { /* drc_bands_present */
|
||||
numBands += FDKreadBits(bs, 4); /* drc_band_incr */
|
||||
FDKreadBits(bs,4); /* reserved */
|
||||
bitCnt+=8;
|
||||
for (i = 0; i < numBands; i++) {
|
||||
FDKreadBits(bs,8); /* drc_band_top[i] */
|
||||
bitCnt+=8;
|
||||
}
|
||||
}
|
||||
|
||||
if (FDKreadBits(bs,1)) { /* prog_ref_level_present */
|
||||
FDKreadBits(bs,8); /* prog_ref_level + prog_ref_level_reserved_bits */
|
||||
bitCnt+=8;
|
||||
}
|
||||
|
||||
for (i = 0; i < numBands; i++) {
|
||||
FDKreadBits(bs,8); /* dyn_rng_sgn[i] + dyn_rng_ctl[i] */
|
||||
bitCnt+=8;
|
||||
}
|
||||
|
||||
if ( (self->numPayloads < MAX_DRC_THREADS)
|
||||
&& ((INT)FDKgetValidBits(bs) >= 0) )
|
||||
{
|
||||
self->drcPayloadPosition[self->numPayloads++] = bsStartPos;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DVB_DRC_ANC_DATA:
|
||||
/* check sync word */
|
||||
if (FDKreadBits(bs, 8) == DVB_ANC_DATA_SYNC_BYTE)
|
||||
{
|
||||
int dmxLevelsPresent, compressionPresent;
|
||||
int coarseGrainTcPresent, fineGrainTcPresent;
|
||||
|
||||
bitCnt+=8;
|
||||
|
||||
/* bs_info field */
|
||||
FDKreadBits(bs, 8); /* mpeg_audio_type, dolby_surround_mode, presentation_mode */
|
||||
bitCnt+=8;
|
||||
|
||||
/* Evaluate ancillary_data_status */
|
||||
FDKreadBits(bs, 3); /* reserved, set to 0 */
|
||||
dmxLevelsPresent = FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */
|
||||
FDKreadBits(bs, 1); /* reserved, set to 0 */
|
||||
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 */
|
||||
bitCnt+=8;
|
||||
|
||||
/* MPEG4 downmixing levels */
|
||||
if (dmxLevelsPresent) {
|
||||
FDKreadBits(bs, 8); /* downmixing_levels_MPEG4 */
|
||||
bitCnt+=8;
|
||||
}
|
||||
/* audio coding mode and compression status */
|
||||
if (compressionPresent) {
|
||||
FDKreadBits(bs, 16); /* audio_coding_mode, Compression_value */
|
||||
bitCnt+=16;
|
||||
}
|
||||
/* coarse grain timecode */
|
||||
if (coarseGrainTcPresent) {
|
||||
FDKreadBits(bs, 16); /* coarse_grain_timecode */
|
||||
bitCnt+=16;
|
||||
}
|
||||
/* fine grain timecode */
|
||||
if (fineGrainTcPresent) {
|
||||
FDKreadBits(bs, 16); /* fine_grain_timecode */
|
||||
bitCnt+=16;
|
||||
}
|
||||
if ( !self->dvbAncDataAvailable
|
||||
&& ((INT)FDKgetValidBits(bs) >= 0) )
|
||||
{
|
||||
self->dvbAncDataPosition = bsStartPos;
|
||||
self->dvbAncDataAvailable = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (bitCnt);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Parse DRC parameters from bitstream
|
||||
|
||||
\bs Handle of FDK bitstream (in)
|
||||
\pDrcBs Pointer to DRC payload data container (out)
|
||||
\payloadPosition Bitstream position of MPEG DRC data junk (in)
|
||||
|
||||
\return Number of bits read (0 in case of a parse error)
|
||||
*/
|
||||
static int aacDecoder_drcParse (
|
||||
HANDLE_FDK_BITSTREAM bs,
|
||||
CDrcPayload *pDrcBs,
|
||||
UINT payloadPosition )
|
||||
{
|
||||
int i, numBands, bitCnt = 4;
|
||||
|
||||
/* Move to the beginning of the DRC payload field */
|
||||
FDKpushBiDirectional(bs, FDKgetValidBits(bs)-payloadPosition);
|
||||
|
||||
/* pce_tag_present */
|
||||
if (FDKreadBits(bs,1))
|
||||
{
|
||||
pDrcBs->pceInstanceTag = FDKreadBits(bs, 4); /* pce_instance_tag */
|
||||
/* only one program supported */
|
||||
FDKreadBits(bs, 4); /* drc_tag_reserved_bits */
|
||||
bitCnt += 8;
|
||||
} else {
|
||||
pDrcBs->pceInstanceTag = -1; /* not present */
|
||||
}
|
||||
|
||||
if (FDKreadBits(bs,1)) { /* excluded_chns_present */
|
||||
/* get excluded_chn_mask */
|
||||
bitCnt += parseExcludedChannels(&pDrcBs->excludedChnsMask, bs);
|
||||
} else {
|
||||
pDrcBs->excludedChnsMask = 0;
|
||||
}
|
||||
|
||||
numBands = 1;
|
||||
if (FDKreadBits(bs,1)) /* drc_bands_present */
|
||||
{
|
||||
/* get band_incr */
|
||||
numBands += FDKreadBits(bs, 4); /* drc_band_incr */
|
||||
pDrcBs->channelData.drcInterpolationScheme = FDKreadBits(bs, 4); /* drc_interpolation_scheme */
|
||||
bitCnt += 8;
|
||||
/* band_top */
|
||||
for (i = 0; i < numBands; i++)
|
||||
{
|
||||
pDrcBs->channelData.bandTop[i] = FDKreadBits(bs, 8); /* drc_band_top[i] */
|
||||
bitCnt += 8;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pDrcBs->channelData.bandTop[0] = 255;
|
||||
}
|
||||
|
||||
pDrcBs->channelData.numBands = numBands;
|
||||
|
||||
if (FDKreadBits(bs,1)) /* prog_ref_level_present */
|
||||
{
|
||||
pDrcBs->progRefLevel = FDKreadBits(bs, 7); /* prog_ref_level */
|
||||
FDKreadBits(bs, 1); /* prog_ref_level_reserved_bits */
|
||||
bitCnt += 8;
|
||||
} else {
|
||||
pDrcBs->progRefLevel = -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < numBands; i++)
|
||||
{
|
||||
pDrcBs->channelData.drcValue[i] = FDKreadBits(bs, 1) << 7; /* dyn_rng_sgn[i] */
|
||||
pDrcBs->channelData.drcValue[i] |= FDKreadBits(bs, 7) & 0x7F; /* dyn_rng_ctl[i] */
|
||||
bitCnt += 8;
|
||||
}
|
||||
|
||||
/* Set DRC payload type */
|
||||
pDrcBs->type = MPEG_DRC_EXT_DATA;
|
||||
|
||||
return (bitCnt);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Parse heavy compression value transported in DSEs of DVB streams with MPEG-4 content.
|
||||
|
||||
\bs Handle of FDK bitstream (in)
|
||||
\pDrcBs Pointer to DRC payload data container (out)
|
||||
\payloadPosition Bitstream position of DVB ancillary data junk
|
||||
|
||||
\return Number of bits read (0 in case of a parse error)
|
||||
*/
|
||||
#define DVB_COMPRESSION_SCALE ( 8 ) /* 48,164 dB */
|
||||
|
||||
static int aacDecoder_drcReadCompression (
|
||||
HANDLE_FDK_BITSTREAM bs,
|
||||
CDrcPayload *pDrcBs,
|
||||
UINT payloadPosition )
|
||||
{
|
||||
int bitCnt = 0;
|
||||
int dmxLevelsPresent, compressionPresent;
|
||||
int coarseGrainTcPresent, fineGrainTcPresent;
|
||||
|
||||
/* Move to the beginning of the DRC payload field */
|
||||
FDKpushBiDirectional(bs, FDKgetValidBits(bs)-payloadPosition);
|
||||
|
||||
/* Sanity checks */
|
||||
if ( FDKgetValidBits(bs) < 24 ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check sync word */
|
||||
if (FDKreadBits(bs, 8) != DVB_ANC_DATA_SYNC_BYTE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Evaluate bs_info field */
|
||||
if (FDKreadBits(bs, 2) != 3) { /* mpeg_audio_type */
|
||||
/* No MPEG-4 audio data */
|
||||
return 0;
|
||||
}
|
||||
FDKreadBits(bs, 2); /* dolby_surround_mode */
|
||||
FDKreadBits(bs, 2); /* presentation_mode */
|
||||
if (FDKreadBits(bs, 2) != 0) { /* reserved, set to 0 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Evaluate ancillary_data_status */
|
||||
if (FDKreadBits(bs, 3) != 0) { /* reserved, set to 0 */
|
||||
return 0;
|
||||
}
|
||||
dmxLevelsPresent = FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */
|
||||
if (FDKreadBits(bs, 1) != 0) { /* reserved, set to 0 */
|
||||
return 0;
|
||||
}
|
||||
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 */
|
||||
bitCnt += 24;
|
||||
|
||||
if (dmxLevelsPresent) {
|
||||
FDKreadBits(bs, 8); /* downmixing_levels_MPEG4 */
|
||||
bitCnt += 8;
|
||||
}
|
||||
|
||||
/* audio_coding_mode_and_compression_status */
|
||||
if (compressionPresent)
|
||||
{
|
||||
UCHAR compressionOn, compressionValue;
|
||||
|
||||
/* audio_coding_mode */
|
||||
if ( FDKreadBits(bs, 7) != 0 ) { /* The reserved bits shall be set to "0". */
|
||||
return 0;
|
||||
}
|
||||
compressionOn = (UCHAR)FDKreadBits(bs, 1); /* compression_on */
|
||||
compressionValue = (UCHAR)FDKreadBits(bs, 8); /* Compression_value */
|
||||
bitCnt += 16;
|
||||
|
||||
if ( compressionOn ) {
|
||||
/* A compression value is available so store the data just like MPEG DRC data */
|
||||
pDrcBs->channelData.drcValue[0] = compressionValue;
|
||||
pDrcBs->channelData.numBands = 1; /* one value for all bands */
|
||||
pDrcBs->pceInstanceTag = -1; /* not present */
|
||||
pDrcBs->progRefLevel = -1; /* not present */
|
||||
} else {
|
||||
/* No compression value available */
|
||||
/* CAUTION: It is not clearly defined by standard how to react in this situation. */
|
||||
pDrcBs->channelData.drcValue[0] = 0x7F; /* 0dB */
|
||||
pDrcBs->channelData.bandTop[0] = 0;
|
||||
|
||||
/* If compression_on field is set to "0" the compression_value field shall be "0000 0000". */
|
||||
if (compressionValue != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Set DRC payload type now because the payload seems to be correct. */
|
||||
pDrcBs->type = DVB_DRC_ANC_DATA;
|
||||
}
|
||||
|
||||
/* Read timecodes if available just to get the right amount of bits. */
|
||||
if (coarseGrainTcPresent) {
|
||||
FDKreadBits(bs, 16); /* coarse_grain_timecode */
|
||||
bitCnt += 16;
|
||||
}
|
||||
if (fineGrainTcPresent) {
|
||||
FDKreadBits(bs, 16); /* fine_grain_timecode */
|
||||
bitCnt += 16;
|
||||
}
|
||||
|
||||
return (bitCnt);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prepare DRC processing
|
||||
*/
|
||||
static int aacDecoder_drcExtractAndMap (
|
||||
HANDLE_AAC_DRC self,
|
||||
HANDLE_FDK_BITSTREAM hBs,
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
|
||||
UCHAR pceInstanceTag,
|
||||
UCHAR channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */
|
||||
int validChannels )
|
||||
{
|
||||
CDrcPayload threadBs[MAX_DRC_THREADS];
|
||||
CDrcPayload *validThreadBs[MAX_DRC_THREADS];
|
||||
UINT backupBsPosition;
|
||||
int i, thread, validThreads = 0;
|
||||
int numExcludedChns[MAX_DRC_THREADS];
|
||||
|
||||
self->numThreads = 0;
|
||||
backupBsPosition = FDKgetValidBits(hBs);
|
||||
|
||||
for (i = 0; i < self->numPayloads && self->numThreads < MAX_DRC_THREADS; i++) {
|
||||
int bitsParsed;
|
||||
|
||||
/* Init payload data chunk. The memclear is very important because it initializes
|
||||
the most values. Without it the module wouldn't work properly or crash. */
|
||||
FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload));
|
||||
threadBs[self->numThreads].channelData.bandTop[0] = (1024 >> 2) - 1;
|
||||
|
||||
/* Extract payload */
|
||||
bitsParsed = aacDecoder_drcParse( hBs,
|
||||
&threadBs[self->numThreads],
|
||||
self->drcPayloadPosition[i] );
|
||||
if (bitsParsed > 0) {
|
||||
self->numThreads++;
|
||||
}
|
||||
}
|
||||
self->numPayloads = 0;
|
||||
|
||||
if (self->dvbAncDataAvailable)
|
||||
{ /* Append a DVB heavy compression payload thread if available. */
|
||||
int bitsParsed;
|
||||
|
||||
/* Init payload data chunk. The memclear is very important because it initializes
|
||||
the most values. Without it the module wouldn't work properly or crash. */
|
||||
FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload));
|
||||
threadBs[self->numThreads].channelData.bandTop[0] = (1024 >> 2) - 1;
|
||||
|
||||
/* Extract payload */
|
||||
bitsParsed = aacDecoder_drcReadCompression( hBs,
|
||||
&threadBs[self->numThreads],
|
||||
self->dvbAncDataPosition );
|
||||
if (bitsParsed > 0) {
|
||||
self->numThreads++;
|
||||
}
|
||||
}
|
||||
self->dvbAncDataAvailable = 0;
|
||||
|
||||
/* Reset the bitbufffer */
|
||||
FDKpushBiDirectional(hBs, FDKgetValidBits(hBs) - backupBsPosition);
|
||||
|
||||
/* calculate number of valid bits in excl_chn_mask */
|
||||
|
||||
/* coupling channels not supported */
|
||||
|
||||
/* check for valid threads */
|
||||
for (thread = 0; thread < self->numThreads; thread++) {
|
||||
CDrcPayload *pThreadBs = &threadBs[thread];
|
||||
int numExclChns = 0;
|
||||
|
||||
switch (pThreadBs->type) {
|
||||
default:
|
||||
continue;
|
||||
case MPEG_DRC_EXT_DATA:
|
||||
case DVB_DRC_ANC_DATA:
|
||||
break;
|
||||
}
|
||||
|
||||
if (pThreadBs->pceInstanceTag >= 0) { /* if PCE tag present */
|
||||
if (pThreadBs->pceInstanceTag != pceInstanceTag) {
|
||||
continue; /* don't accept */
|
||||
}
|
||||
}
|
||||
|
||||
/* calculate number of excluded channels */
|
||||
if (pThreadBs->excludedChnsMask > 0) {
|
||||
INT exclMask = pThreadBs->excludedChnsMask;
|
||||
int ch;
|
||||
for (ch = 0; ch < validChannels; ch++) {
|
||||
numExclChns += exclMask & 0x1;
|
||||
exclMask >>= 1;
|
||||
}
|
||||
}
|
||||
if (numExclChns < validChannels) {
|
||||
validThreadBs[validThreads] = pThreadBs;
|
||||
numExcludedChns[validThreads] = numExclChns;
|
||||
validThreads++;
|
||||
}
|
||||
}
|
||||
|
||||
if (validThreads > 1) {
|
||||
int ch;
|
||||
|
||||
/* check consistency of excl_chn_mask amongst valid DRC threads */
|
||||
for (ch = 0; ch < validChannels; ch++) {
|
||||
int present = 0;
|
||||
|
||||
for (thread = 0; thread < validThreads; thread++) {
|
||||
CDrcPayload *pThreadBs = validThreadBs[thread];
|
||||
|
||||
|
||||
/* thread applies to this channel */
|
||||
if ( (pThreadBs->type == MPEG_DRC_EXT_DATA)
|
||||
&& ( (numExcludedChns[thread] == 0)
|
||||
|| (!(pThreadBs->excludedChnsMask & (1<<ch))) ) ) {
|
||||
present++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (present > 1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* map DRC bitstream information onto DRC channel information */
|
||||
for (thread = 0; thread < validThreads; thread++)
|
||||
{
|
||||
CDrcPayload *pThreadBs = validThreadBs[thread];
|
||||
INT exclMask = pThreadBs->excludedChnsMask;
|
||||
int ch;
|
||||
|
||||
/* last progRefLevel transmitted is the one that is used
|
||||
* (but it should really only be transmitted once per block!)
|
||||
*/
|
||||
if (pThreadBs->progRefLevel >= 0) {
|
||||
self->progRefLevel = pThreadBs->progRefLevel;
|
||||
}
|
||||
|
||||
/* SCE, CPE and LFE */
|
||||
for (ch = 0; ch < validChannels; ch++) {
|
||||
int mapedChannel = channelMapping[ch];
|
||||
|
||||
if ( ((exclMask & (1<<mapedChannel)) == 0)
|
||||
&& ( ( self->params.applyHeavyCompression && (pThreadBs->type == DVB_DRC_ANC_DATA))
|
||||
|| (!self->params.applyHeavyCompression && (pThreadBs->type == MPEG_DRC_EXT_DATA)) )
|
||||
) {
|
||||
/* copy thread to channel */
|
||||
pAacDecoderStaticChannelInfo[ch]->drcData = pThreadBs->channelData;
|
||||
}
|
||||
}
|
||||
/* CCEs not supported by now */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void aacDecoder_drcApply (
|
||||
HANDLE_AAC_DRC self,
|
||||
void *pSbrDec,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
CDrcChannelData *pDrcChData,
|
||||
int ch, /* needed only for SBR */
|
||||
int aacFrameSize,
|
||||
int bSbrPresent )
|
||||
{
|
||||
int band, top, bin, numBands;
|
||||
int bottom = 0;
|
||||
|
||||
FIXP_DBL max_mantissa;
|
||||
INT max_exponent;
|
||||
|
||||
FIXP_DBL norm_mantissa = FL2FXCONST_DBL(0.0f);
|
||||
INT norm_exponent = 0;
|
||||
|
||||
FIXP_DBL fact_mantissa[MAX_DRC_BANDS];
|
||||
INT fact_exponent[MAX_DRC_BANDS];
|
||||
|
||||
CDrcParams *pParams = &self->params;
|
||||
|
||||
FIXP_DBL *pSpectralCoefficient = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient);
|
||||
CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo;
|
||||
SHORT *pSpecScale = pAacDecoderChannelInfo->specScale;
|
||||
|
||||
int winSeq = pIcsInfo->WindowSequence;
|
||||
|
||||
/* Increment and check expiry counter */
|
||||
if ( (pParams->expiryFrame > 0)
|
||||
&& (++pDrcChData->expiryCount > pParams->expiryFrame) )
|
||||
{ /* The DRC data is too old, so delete it. */
|
||||
aacDecoder_drcInitChannelData( pDrcChData );
|
||||
}
|
||||
|
||||
if (!self->enable) {
|
||||
sbrDecoder_drcDisable( (HANDLE_SBRDECODER)pSbrDec, ch );
|
||||
return;
|
||||
}
|
||||
|
||||
numBands = pDrcChData->numBands;
|
||||
top = FDKmax(0, numBands-1);
|
||||
|
||||
pDrcChData->bandTop[0] = fixMin(pDrcChData->bandTop[0], (aacFrameSize >> 2) - 1);
|
||||
|
||||
/* If program reference normalization is done in the digital domain,
|
||||
modify factor to perform normalization. prog_ref_level can
|
||||
alternatively be passed to the system for modification of the level in
|
||||
the analog domain. Analog level modification avoids problems with
|
||||
reduced DAC SNR (if signal is attenuated) or clipping (if signal is
|
||||
boosted) */
|
||||
|
||||
if (self->digitalNorm == 1)
|
||||
{
|
||||
/* 0.5^((targetRefLevel - progRefLevel)/24) */
|
||||
norm_mantissa = fLdPow(
|
||||
FL2FXCONST_DBL(-1.0), /* log2(0.5) */
|
||||
0,
|
||||
(FIXP_DBL)((INT)(FL2FXCONST_DBL(1.0f/24.0)>>3) * (INT)(pParams->targetRefLevel-self->progRefLevel)),
|
||||
3,
|
||||
&norm_exponent );
|
||||
}
|
||||
else {
|
||||
norm_mantissa = FL2FXCONST_DBL(0.5f);
|
||||
norm_exponent = 1;
|
||||
}
|
||||
|
||||
|
||||
/* calc scale factors */
|
||||
for (band = 0; band < numBands; band++)
|
||||
{
|
||||
UCHAR drcVal = pDrcChData->drcValue[band];
|
||||
top = fixMin((int)( (pDrcChData->bandTop[band]+1)<<2 ), aacFrameSize);
|
||||
|
||||
if ( pParams->applyHeavyCompression ) {
|
||||
INT compressionFactorVal_e;
|
||||
int valX = drcVal >> 4;
|
||||
int valY = drcVal & 0x0F;
|
||||
|
||||
/* calculate the unscaled heavy compression factor.
|
||||
compressionFactor = 48.164 - 6.0206*valX - 0.4014*valY dB
|
||||
range: -48.166 dB to 48.164 dB */
|
||||
if ( drcVal != 0x7F ) {
|
||||
fact_mantissa[band] =
|
||||
fPowInt( FL2FXCONST_DBL(0.95483867181), /* -0.4014dB = 0.95483867181 */
|
||||
0,
|
||||
valY,
|
||||
&compressionFactorVal_e );
|
||||
|
||||
/* -0.0008dB (48.164 - 6.0206*8 = -0.0008) */
|
||||
fact_mantissa[band] = fMult(FL2FXCONST_DBL(0.99990790084), fact_mantissa[band]);
|
||||
|
||||
fact_exponent[band] = DVB_COMPRESSION_SCALE - valX + compressionFactorVal_e;
|
||||
}
|
||||
else {
|
||||
fact_mantissa[band] = FL2FXCONST_DBL(0.5f);
|
||||
fact_exponent[band] = 1;
|
||||
}
|
||||
} else
|
||||
{
|
||||
/* apply the scaled dynamic range control words to factor.
|
||||
* if scaling drc_cut (or drc_boost), or control word drc_mantissa is 0
|
||||
* then there is no dynamic range compression
|
||||
*
|
||||
* if pDrcChData->drcSgn[band] is
|
||||
* 1 then gain is < 1 : factor = 2^(-self->cut * pDrcChData->drcMag[band] / 24)
|
||||
* 0 then gain is > 1 : factor = 2^( self->boost * pDrcChData->drcMag[band] / 24)
|
||||
*/
|
||||
|
||||
if ((drcVal&0x7F) > 0) {
|
||||
FIXP_DBL tParamVal = (drcVal & 0x80) ? -pParams->cut : pParams->boost;
|
||||
|
||||
fact_mantissa[band] =
|
||||
f2Pow( (FIXP_DBL)((INT)fMult(FL2FXCONST_DBL(1.0f/192.0f), tParamVal) * (drcVal&0x7F)),
|
||||
3+DRC_PARAM_SCALE,
|
||||
&fact_exponent[band] );
|
||||
}
|
||||
else {
|
||||
fact_mantissa[band] = FL2FXCONST_DBL(0.5f);
|
||||
fact_exponent[band] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
fact_mantissa[band] = fMult(fact_mantissa[band], norm_mantissa);
|
||||
fact_exponent[band] += norm_exponent;
|
||||
|
||||
|
||||
bottom = top;
|
||||
|
||||
} /* end loop over bands */
|
||||
|
||||
|
||||
/* normalizations */
|
||||
{
|
||||
int res;
|
||||
|
||||
max_mantissa = FL2FXCONST_DBL(0.0f);
|
||||
max_exponent = 0;
|
||||
for (band = 0; band < numBands; band++) {
|
||||
max_mantissa = fixMax(max_mantissa, fact_mantissa[band]);
|
||||
max_exponent = fixMax(max_exponent, fact_exponent[band]);
|
||||
}
|
||||
|
||||
/* left shift factors to gain accurancy */
|
||||
res = CntLeadingZeros(max_mantissa) - 1;
|
||||
|
||||
/* above topmost DRC band gain factor is 1 */
|
||||
if (((pDrcChData->bandTop[numBands-1]+1)<<2) < aacFrameSize) res = 0;
|
||||
|
||||
if (res > 0) {
|
||||
res = fixMin(res, max_exponent);
|
||||
max_exponent -= res;
|
||||
|
||||
for (band = 0; band < numBands; band++) {
|
||||
fact_mantissa[band] <<= res;
|
||||
fact_exponent[band] -= res;
|
||||
}
|
||||
}
|
||||
|
||||
/* normalize magnitudes to one scale factor */
|
||||
for (band = 0; band < numBands; band++) {
|
||||
if (fact_exponent[band] < max_exponent) {
|
||||
fact_mantissa[band] >>= max_exponent - fact_exponent[band];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* apply factor to spectral lines
|
||||
* short blocks must take care that bands fall on
|
||||
* block boundaries!
|
||||
*/
|
||||
if (!bSbrPresent)
|
||||
{
|
||||
bottom = 0;
|
||||
|
||||
for (band = 0; band < numBands; band++)
|
||||
{
|
||||
top = fixMin((int)( (pDrcChData->bandTop[band]+1)<<2 ), aacFrameSize); /* ... * DRC_BAND_MULT; */
|
||||
|
||||
for (bin = bottom; bin < top; bin++) {
|
||||
pSpectralCoefficient[bin] = fMult(pSpectralCoefficient[bin], fact_mantissa[band]);
|
||||
}
|
||||
|
||||
bottom = top;
|
||||
}
|
||||
|
||||
/* above topmost DRC band gain factor is 1 */
|
||||
if (max_exponent > 0) {
|
||||
FIXP_DBL fact = FL2FXCONST_DBL(0.5f) >> (max_exponent - 1);
|
||||
|
||||
for (bin = top; bin < aacFrameSize; bin++) {
|
||||
pSpectralCoefficient[bin] = fMult(pSpectralCoefficient[bin], fact);
|
||||
}
|
||||
}
|
||||
|
||||
/* adjust scaling */
|
||||
pSpecScale[0] += max_exponent;
|
||||
|
||||
if (winSeq == EightShortSequence) {
|
||||
int win;
|
||||
for (win = 1; win < 8; win++) {
|
||||
pSpecScale[win] += max_exponent;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
HANDLE_SBRDECODER hSbrDecoder = (HANDLE_SBRDECODER)pSbrDec;
|
||||
|
||||
/* feed factors into SBR decoder for application in QMF domain. */
|
||||
sbrDecoder_drcFeedChannel (
|
||||
hSbrDecoder,
|
||||
ch,
|
||||
pDrcChData->numBands,
|
||||
fact_mantissa,
|
||||
max_exponent,
|
||||
pDrcChData->drcInterpolationScheme,
|
||||
winSeq,
|
||||
pDrcChData->bandTop
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prepare DRC processing
|
||||
*/
|
||||
int aacDecoder_drcProlog (
|
||||
HANDLE_AAC_DRC self,
|
||||
HANDLE_FDK_BITSTREAM hBs,
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
|
||||
UCHAR pceInstanceTag,
|
||||
UCHAR channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */
|
||||
int validChannels )
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (self == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!self->params.bsDelayEnable)
|
||||
{
|
||||
err = aacDecoder_drcExtractAndMap (
|
||||
self,
|
||||
hBs,
|
||||
pAacDecoderStaticChannelInfo,
|
||||
pceInstanceTag,
|
||||
channelMapping,
|
||||
validChannels );
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finalize DRC processing
|
||||
*/
|
||||
int aacDecoder_drcEpilog (
|
||||
HANDLE_AAC_DRC self,
|
||||
HANDLE_FDK_BITSTREAM hBs,
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
|
||||
UCHAR pceInstanceTag,
|
||||
UCHAR channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */
|
||||
int validChannels )
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (self == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (self->params.bsDelayEnable)
|
||||
{
|
||||
err = aacDecoder_drcExtractAndMap (
|
||||
self,
|
||||
hBs,
|
||||
pAacDecoderStaticChannelInfo,
|
||||
pceInstanceTag,
|
||||
channelMapping,
|
||||
validChannels );
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
105
libAACdec/src/aacdec_drc.h
Normal file
105
libAACdec/src/aacdec_drc.h
Normal file
@ -0,0 +1,105 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Christian Griebel
|
||||
Description: Dynamic range control (DRC) decoder tool for AAC
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef AACDEC_DRC_H
|
||||
#define AACDEC_DRC_H
|
||||
|
||||
#include "tp_data.h" /* for program config element support */
|
||||
|
||||
|
||||
#include "aacdec_drc_types.h"
|
||||
#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 ( 40 ) /* Default DRC data expiry time in AAC frames */
|
||||
#define MAX_SBR_SYN_CHAN ( 64 )
|
||||
#define MAX_SBR_COLS ( 32 )
|
||||
|
||||
|
||||
/**
|
||||
* \brief DRC module setting parameters
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
DRC_CUT_SCALE = 0,
|
||||
DRC_BOOST_SCALE,
|
||||
TARGET_REF_LEVEL,
|
||||
DRC_BS_DELAY,
|
||||
DRC_DATA_EXPIRY_FRAME,
|
||||
APPLY_HEAVY_COMPRESSION
|
||||
|
||||
} AACDEC_DRC_PARAM;
|
||||
|
||||
|
||||
/**
|
||||
* \brief DRC module interface functions
|
||||
*/
|
||||
void aacDecoder_drcInit (
|
||||
HANDLE_AAC_DRC self );
|
||||
|
||||
void aacDecoder_drcInitChannelData (
|
||||
CDrcChannelData *pDrcChannel );
|
||||
|
||||
AAC_DECODER_ERROR aacDecoder_drcSetParam (
|
||||
HANDLE_AAC_DRC self,
|
||||
AACDEC_DRC_PARAM param,
|
||||
INT value );
|
||||
|
||||
int aacDecoder_drcMarkPayload (
|
||||
HANDLE_AAC_DRC self,
|
||||
HANDLE_FDK_BITSTREAM hBs,
|
||||
AACDEC_DRC_PAYLOAD_TYPE type );
|
||||
|
||||
int aacDecoder_drcProlog (
|
||||
HANDLE_AAC_DRC self,
|
||||
HANDLE_FDK_BITSTREAM hBs,
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
|
||||
UCHAR pceInstanceTag,
|
||||
UCHAR channelMapping[],
|
||||
int numChannels );
|
||||
|
||||
void aacDecoder_drcApply (
|
||||
HANDLE_AAC_DRC self,
|
||||
void *pSbrDec,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
CDrcChannelData *pDrcDat,
|
||||
int ch,
|
||||
int aacFrameSize,
|
||||
int bSbrPresent );
|
||||
|
||||
int aacDecoder_drcEpilog (
|
||||
HANDLE_AAC_DRC self,
|
||||
HANDLE_FDK_BITSTREAM hBs,
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
|
||||
UCHAR pceInstanceTag,
|
||||
UCHAR channelMapping[],
|
||||
int validChannels );
|
||||
|
||||
|
||||
#endif /* AACDEC_DRC_H */
|
104
libAACdec/src/aacdec_drc_types.h
Normal file
104
libAACdec/src/aacdec_drc_types.h
Normal file
@ -0,0 +1,104 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2010)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Christian Griebel
|
||||
Description: Dynamic range control (DRC) global data types
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef AACDEC_DRC_TYPES_H
|
||||
#define AACDEC_DRC_TYPES_H
|
||||
|
||||
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#define MAX_DRC_THREADS ( 3 ) /* Heavy compression value is handled just like MPEG DRC data */
|
||||
#define MAX_DRC_BANDS ( 16 ) /* 2^LEN_DRC_BAND_INCR (LEN_DRC_BAND_INCR = 4) */
|
||||
|
||||
/**
|
||||
* \brief DRC module global data types
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
UNKNOWN_PAYLOAD = 0,
|
||||
MPEG_DRC_EXT_DATA,
|
||||
DVB_DRC_ANC_DATA
|
||||
|
||||
} AACDEC_DRC_PAYLOAD_TYPE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT expiryCount;
|
||||
UINT numBands;
|
||||
USHORT bandTop[MAX_DRC_BANDS];
|
||||
SHORT drcInterpolationScheme;
|
||||
UCHAR drcValue[MAX_DRC_BANDS];
|
||||
|
||||
} CDrcChannelData;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
AACDEC_DRC_PAYLOAD_TYPE type;
|
||||
UINT excludedChnsMask;
|
||||
SCHAR progRefLevel;
|
||||
SCHAR pceInstanceTag;
|
||||
|
||||
CDrcChannelData channelData;
|
||||
|
||||
} CDrcPayload;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FIXP_DBL cut;
|
||||
FIXP_DBL boost;
|
||||
|
||||
UINT expiryFrame;
|
||||
SCHAR targetRefLevel;
|
||||
UCHAR bsDelayEnable;
|
||||
UCHAR applyHeavyCompression;
|
||||
|
||||
} CDrcParams;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CDrcParams params; /* Module parameters that can be set by user (via SetParam API function) */
|
||||
|
||||
UCHAR enable; /* Switch that controls dynamic range processing */
|
||||
UCHAR digitalNorm; /* Switch to en-/disable reference level normalization in digital domain */
|
||||
|
||||
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 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 */
|
||||
|
||||
} CDrcInfo;
|
||||
|
||||
typedef CDrcInfo *HANDLE_AAC_DRC;
|
||||
|
||||
#endif /* AACDEC_DRC_TYPES_H */
|
||||
|
1529
libAACdec/src/aacdec_hcr.cpp
Normal file
1529
libAACdec/src/aacdec_hcr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
64
libAACdec/src/aacdec_hcr.h
Normal file
64
libAACdec/src/aacdec_hcr.h
Normal file
@ -0,0 +1,64 @@
|
||||
/***************************** MPEG-4 AAC Decoder ***************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS 2000-2008
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Robert Weidner (DSP Solutions)
|
||||
Description: HCR Decoder: Interface function declaration; common defines
|
||||
and structures; defines for switching error-generator,
|
||||
-detector, and -concealment
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _AACDEC_HCR_H_
|
||||
#define _AACDEC_HCR_H_
|
||||
|
||||
|
||||
|
||||
#include "channelinfo.h"
|
||||
#include "FDK_bitstream.h"
|
||||
|
||||
void HcrInitRom (H_HCR_INFO hHcr);
|
||||
UINT HcrInit(H_HCR_INFO pHcr,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
const SamplingRateInfo *pSamplingRateInfo,
|
||||
HANDLE_FDK_BITSTREAM bs);
|
||||
UINT HcrDecoder (H_HCR_INFO hHcr,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
const SamplingRateInfo *pSamplingRateInfo,
|
||||
HANDLE_FDK_BITSTREAM bs);
|
||||
void CarryBitToBranchValue(
|
||||
UCHAR carryBit,
|
||||
UINT treeNode,
|
||||
UINT *branchValue,
|
||||
UINT *branchNode
|
||||
);
|
||||
|
||||
void CHcr_Read (HANDLE_FDK_BITSTREAM bs,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo);
|
||||
void HcrMuteErroneousLines(H_HCR_INFO hHcr);
|
||||
|
||||
void setHcrType(H_HCR_INFO hHcr, MP4_ELEMENT_ID type);
|
||||
INT getHcrType(H_HCR_INFO hHcr);
|
||||
|
||||
|
||||
|
||||
#endif /* _AACDEC_HCR_H_ */
|
103
libAACdec/src/aacdec_hcr_bit.cpp
Normal file
103
libAACdec/src/aacdec_hcr_bit.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
/***************************** MPEG-4 AAC Decoder ***************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS 2000-2008
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Robert Weidner (DSP Solutions)
|
||||
Description: HCR Decoder: Bitstream reading
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include "aacdec_hcr_bit.h"
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
description: This function toggles the read direction.
|
||||
-----------------------------------------------------------------------------------------------
|
||||
input: current read direction
|
||||
-----------------------------------------------------------------------------------------------
|
||||
return: new read direction
|
||||
-------------------------------------------------------------------------------------------- */
|
||||
UCHAR ToggleReadDirection(UCHAR readDirection)
|
||||
{
|
||||
if ( readDirection == FROM_LEFT_TO_RIGHT ) {
|
||||
return FROM_RIGHT_TO_LEFT;
|
||||
}
|
||||
else {
|
||||
return FROM_LEFT_TO_RIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
description: This function returns a bit from the bitstream according to read direction.
|
||||
It is called very often, therefore it makes sense to inline it (runtime).
|
||||
-----------------------------------------------------------------------------------------------
|
||||
input: - handle to FDK bitstream
|
||||
- reference value marking start of bitfield
|
||||
- pLeftStartOfSegment
|
||||
- pRightStartOfSegment
|
||||
- readDirection
|
||||
-----------------------------------------------------------------------------------------------
|
||||
return: - bit from bitstream
|
||||
-------------------------------------------------------------------------------------------- */
|
||||
UINT HcrGetABitFromBitstream(HANDLE_FDK_BITSTREAM bs,
|
||||
USHORT *pLeftStartOfSegment,
|
||||
USHORT *pRightStartOfSegment,
|
||||
UCHAR readDirection)
|
||||
{
|
||||
UINT bit;
|
||||
INT readBitOffset;
|
||||
|
||||
if (readDirection == FROM_LEFT_TO_RIGHT) {
|
||||
readBitOffset = *pLeftStartOfSegment-FDKgetBitCnt(bs);
|
||||
if( readBitOffset ) {
|
||||
FDKpushBiDirectional(bs, readBitOffset);
|
||||
}
|
||||
|
||||
bit = FDKreadBits(bs, 1);
|
||||
|
||||
*pLeftStartOfSegment += 1;
|
||||
}
|
||||
else {
|
||||
readBitOffset = *pRightStartOfSegment-FDKgetBitCnt(bs);
|
||||
if( readBitOffset ) {
|
||||
FDKpushBiDirectional(bs, readBitOffset);
|
||||
}
|
||||
|
||||
/* to be replaced with a brother function of FDKreadBits() */
|
||||
bit = FDKreadBits(bs, 1);
|
||||
FDKpushBack(bs, 2);
|
||||
|
||||
*pRightStartOfSegment -= 1;
|
||||
}
|
||||
|
||||
|
||||
#if ERROR_GENERATOR_BIT_STREAM_HCR
|
||||
static int a;
|
||||
if ((++a % MODULO_DIVISOR_HCR) == 0) {
|
||||
bit = (bit == 0) ? 1 : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (bit);
|
||||
}
|
||||
|
44
libAACdec/src/aacdec_hcr_bit.h
Normal file
44
libAACdec/src/aacdec_hcr_bit.h
Normal file
@ -0,0 +1,44 @@
|
||||
/***************************** MPEG-4 AAC Decoder ***************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS 2000-2008
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Robert Weidner (DSP Solutions)
|
||||
Description: HCR Decoder: Bitstream reading prototypes
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _AACDEC_HCR_BIT_H_
|
||||
#define _AACDEC_HCR_BIT_H_
|
||||
|
||||
|
||||
|
||||
#include "aacdec_hcr.h"
|
||||
|
||||
UCHAR ToggleReadDirection(UCHAR readDirection);
|
||||
|
||||
UINT HcrGetABitFromBitstream(HANDLE_FDK_BITSTREAM bs,
|
||||
USHORT *pLeftStartOfSegment,
|
||||
USHORT *pRightStartOfSegment,
|
||||
UCHAR readDirection);
|
||||
|
||||
|
||||
#endif /* _AACDEC_HCR_BIT_H_ */
|
304
libAACdec/src/aacdec_hcr_types.h
Normal file
304
libAACdec/src/aacdec_hcr_types.h
Normal file
@ -0,0 +1,304 @@
|
||||
/***************************** MPEG-4 AAC Decoder ***************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS 2000-2009
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Robert Weidner (DSP Solutions)
|
||||
Description: HCR Decoder: Common defines and structures; defines for
|
||||
switching error-generator, -detector, and -concealment;
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _AACDEC_HCR_TYPES_H_
|
||||
#define _AACDEC_HCR_TYPES_H_
|
||||
|
||||
|
||||
|
||||
#include "FDK_bitstream.h"
|
||||
#include "overlapadd.h"
|
||||
|
||||
/* ------------------------------------------------ */
|
||||
/* ------------------------------------------------ */
|
||||
|
||||
#define LINES_PER_UNIT 4
|
||||
|
||||
/* ------------------------------------------------ */
|
||||
/* ------------------------------------------------ */
|
||||
/* ----------- basic HCR configuration ------------ */
|
||||
|
||||
|
||||
#define MAX_SFB_HCR (((1024/8) / LINES_PER_UNIT) * 8) /* (8 * 16) is not enough because sfbs are split in units for blocktype short */
|
||||
#define NUMBER_OF_UNIT_GROUPS (LINES_PER_UNIT * 8)
|
||||
#define LINES_PER_UNIT_GROUP (1024 / NUMBER_OF_UNIT_GROUPS) /* 15 16 30 32 */
|
||||
|
||||
|
||||
/* ------------------------------------------------ */
|
||||
/* ------------------------------------------------ */
|
||||
/* ------------------------------------------------ */
|
||||
|
||||
#define FROM_LEFT_TO_RIGHT 0
|
||||
#define FROM_RIGHT_TO_LEFT 1
|
||||
|
||||
#define MAX_CB_PAIRS 23
|
||||
#define MAX_HCR_SETS 14
|
||||
|
||||
#define ESCAPE_VALUE 16
|
||||
#define POSITION_OF_FLAG_A 21
|
||||
#define POSITION_OF_FLAG_B 20
|
||||
|
||||
#define MAX_CB 32 /* last used CB is cb #31 when VCB11 is used */
|
||||
|
||||
#define MAX_CB_CHECK 32 /* support for VCB11 available -- is more general, could therefore used in both cases */
|
||||
|
||||
#define NUMBER_OF_BIT_IN_WORD 32
|
||||
|
||||
/* log */
|
||||
#define THIRTYTWO_LOG_DIV_TWO_LOG 5
|
||||
#define EIGHT_LOG_DIV_TWO_LOG 3
|
||||
#define FOUR_LOG_DIV_TWO_LOG 2
|
||||
|
||||
/* borders */
|
||||
#define CPE_TOP_LENGTH 12288
|
||||
#define SCE_TOP_LENGTH 6144
|
||||
#define LEN_OF_LONGEST_CW_TOP_LENGTH 49
|
||||
|
||||
/* qsc's of high level */
|
||||
#define Q_VALUE_INVALID 8192 /* mark a invalid line with this value (to be concealed later on) */
|
||||
#define HCR_DIRAC 500 /* a line of high level */
|
||||
|
||||
/* masks */
|
||||
#define MASK_LEFT 0xFFF000
|
||||
#define MASK_RIGHT 0xFFF
|
||||
#define CLR_BIT_10 0x3FF
|
||||
#define TEST_BIT_10 0x400
|
||||
|
||||
#define LEFT_OFFSET 12
|
||||
|
||||
/* when set HCR is replaced by a dummy-module which just fills the outputbuffer with a dirac sequence */
|
||||
/* use this if HCR is suspected to write in other modules -- if error is stell there, HCR is innocent */
|
||||
#define USE_HCR_DUMMY 0
|
||||
|
||||
|
||||
/* ------------------------------ */
|
||||
/* - insert HCR errors - */
|
||||
/* ------------------------------ */
|
||||
|
||||
/* modify input lengths -- high protected */
|
||||
#define ERROR_LORSD 0 /* offset: error if different from zero */
|
||||
#define ERROR_LOLC 0 /* offset: error if different from zero */
|
||||
|
||||
/* segments are earlier empty as expected when decoding PCWs */
|
||||
#define ERROR_PCW_BODY 0 /* set a positive values to trigger the error (make segments earlyer appear to be empty) */
|
||||
#define ERROR_PCW_BODY_SIGN 0 /* set a positive values to trigger the error (make segments earlyer appear to be empty) */
|
||||
#define ERROR_PCW_BODY_SIGN_ESC 0 /* set a positive values to trigger the error (make segments earlyer appear to be empty) */
|
||||
|
||||
/* pretend there are too many bits decoded (enlarge length of codeword) at PCWs -- use a positive value */
|
||||
#define ERROR_PCW_BODY_ONLY_TOO_LONG 0 /* set a positive values to trigger the error */
|
||||
#define ERROR_PCW_BODY_SIGN_TOO_LONG 0 /* set a positive values to trigger the error */
|
||||
#define ERROR_PCW_BODY_SIGN_ESC_TOO_LONG 0 /* set a positive values to trigger the error */
|
||||
|
||||
/* modify HCR bitstream block */
|
||||
#define ERROR_GENERATOR_BIT_STREAM_HCR 0 /* modify every <MODULO_DIVISOR_HCR>-bit when reading from bitstream */ /* !!! BEWARE!!! if RVLC is active, also RVLC data at ESC2 will be modified !!! */
|
||||
#define MODULO_DIVISOR_HCR 30
|
||||
|
||||
|
||||
/* ------------------------------ */
|
||||
/* - detect HCR errors - */
|
||||
/* ------------------------------ */
|
||||
/* check input data */
|
||||
#define CHECK_VALID_HCR_INPUT 1 /* it is highly recommended to check input data */
|
||||
|
||||
/* during decoding */
|
||||
#define CHECK_SEGMENTATION_IMMEDIATELY 1 /* the 2 or 4 lines of a detected PCW-decoding-error is marked */
|
||||
|
||||
#define CHECK_SEGMENTATION_FINAL 1 /* all the segments are checked -- therefore -- if this check passes, its a kind of evidence that the
|
||||
decoded PCWs and non-PCWs are fine */
|
||||
|
||||
#define DETECT_TOO_LONG_CW_READS 1 /* if a codeword is decoded there exists a border for the number of bits, which are allowed to read for this
|
||||
codeword. This border is the minimum of the length of the longest codeword (for the currently used
|
||||
codebook) and the separately transmitted 'lengthOfLongestCodeword' in this frame and channel. The number
|
||||
of decoded bits is counted (for PCWs only -- there it makes really sense in my opinion). If this number
|
||||
exceeds the border (derived as minimum -- see above), a error is detected. */
|
||||
|
||||
#define STATE_MACHINE_ERROR_CHECK 1 /* test if the number of remaining bits in a segment is _below_ zero. If there are no errors the lowest
|
||||
allowed value for remainingBitsInSegment is zero. This check also could be set to zero (save runtime) */
|
||||
/* other */
|
||||
#define VALID_LAV_ERROR_TRIGGER 1 /* when set to '1', avoid setting the LAV-Flag in errorLog due to a previous-line-marking (at PCW decoder). A little
|
||||
more runtime is needed then when writing values out into output-buffer. */
|
||||
|
||||
#define HCR_LISTEN_TO_MUTED_LINES 0 /* listen to the "error-concealment" for testing */
|
||||
|
||||
/* ------------------------------ */
|
||||
/* - conceal HCR errors - */
|
||||
/* ------------------------------ */
|
||||
|
||||
#define HCR_ERROR_CONCEALMENT 1 /* if set to '1', HCR _mutes_ the erred quantized spectral coefficients */
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------------------
|
||||
// errorLog: A word of 32 bits used for logging possible errors within HCR
|
||||
// in case of distorted bitstreams. Table of all known errors:
|
||||
// ------------------------------------------------------------------------------------------------------------------------
|
||||
// bit fatal location meaning
|
||||
// ----+-----+-----------+--------------------------------------
|
||||
#define SEGMENT_OVERRIDE_ERR_PCW_BODY 0x80000000 // 31 no PCW-Dec During PCW decoding it is checked after every PCW if there are too many bits decoded (immediate check).
|
||||
#define SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN 0x40000000 // 30 no PCW-Dec During PCW decoding it is checked after every PCW if there are too many bits decoded (immediate check).
|
||||
#define SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN_ESC 0x20000000 // 29 no PCW-Dec During PCW decoding it is checked after every PCW if there are too many bits decoded (immediate check).
|
||||
#define EXTENDED_SORTED_COUNTER_OVERFLOW 0x10000000 // 28 yes Init-Dec Error during extending sideinfo (neither a PCW nor a nonPCW was decoded so far)
|
||||
// 0x08000000 // 27 reserved
|
||||
// 0x04000000 // 26 reserved
|
||||
// 0x02000000 // 25 reserved
|
||||
// 0x01000000 // 24 reserved
|
||||
// 0x00800000 // 23 reserved
|
||||
// 0x00400000 // 22 reserved
|
||||
// 0x00200000 // 21 reserved
|
||||
// 0x00100000 // 20 reserved
|
||||
|
||||
/* special errors */
|
||||
#define TOO_MANY_PCW_BODY_BITS_DECODED 0x00080000 // 19 yes PCW-Dec During PCW-body-decoding too many bits have been read from bitstream -- advice: skip non-PCW decoding
|
||||
#define TOO_MANY_PCW_BODY_SIGN_BITS_DECODED 0x00040000 // 18 yes PCW-Dec During PCW-body-sign-decoding too many bits have been read from bitstream -- advice: skip non-PCW decoding
|
||||
#define TOO_MANY_PCW_BODY_SIGN_ESC_BITS_DECODED 0x00020000 // 17 yes PCW-Dec During PCW-body-sign-esc-decoding too many bits have been read from bitstream -- advice: skip non-PCW decoding
|
||||
|
||||
|
||||
// 0x00010000 // 16 reserved
|
||||
#define STATE_ERROR_BODY_ONLY 0x00008000 // 15 no NonPCW-Dec State machine returned with error
|
||||
#define STATE_ERROR_BODY_SIGN__BODY 0x00004000 // 14 no NonPCW-Dec State machine returned with error
|
||||
#define STATE_ERROR_BODY_SIGN__SIGN 0x00002000 // 13 no NonPCW-Dec State machine returned with error
|
||||
#define STATE_ERROR_BODY_SIGN_ESC__BODY 0x00001000 // 12 no NonPCW-Dec State machine returned with error
|
||||
#define STATE_ERROR_BODY_SIGN_ESC__SIGN 0x00000800 // 11 no NonPCW-Dec State machine returned with error
|
||||
#define STATE_ERROR_BODY_SIGN_ESC__ESC_PREFIX 0x00000400 // 10 no NonPCW-Dec State machine returned with error
|
||||
#define STATE_ERROR_BODY_SIGN_ESC__ESC_WORD 0x00000200 // 9 no NonPCW-Dec State machine returned with error
|
||||
#define HCR_SI_LENGTHS_FAILURE 0x00000100 // 8 yes Init-Dec LengthOfLongestCodeword must not be less than lenghtOfReorderedSpectralData
|
||||
#define NUM_SECT_OUT_OF_RANGE_SHORT_BLOCK 0x00000080 // 7 yes Init-Dec The number of sections is not within the allowed range (short block)
|
||||
#define NUM_SECT_OUT_OF_RANGE_LONG_BLOCK 0x00000040 // 6 yes Init-Dec The number of sections is not within the allowed range (long block)
|
||||
#define LINE_IN_SECT_OUT_OF_RANGE_SHORT_BLOCK 0x00000020 // 5 yes Init-Dec The number of lines per section is not within the allowed range (short block)
|
||||
#define CB_OUT_OF_RANGE_SHORT_BLOCK 0x00000010 // 4 yes Init-Dec The codebook is not within the allowed range (short block)
|
||||
#define LINE_IN_SECT_OUT_OF_RANGE_LONG_BLOCK 0x00000008 // 3 yes Init-Dec The number of lines per section is not within the allowed range (long block)
|
||||
#define CB_OUT_OF_RANGE_LONG_BLOCK 0x00000004 // 2 yes Init-Dec The codebook is not within the allowed range (long block)
|
||||
#define LAV_VIOLATION 0x00000002 // 1 no Final The absolute value of at least one decoded line was too high for the according codebook.
|
||||
#define BIT_IN_SEGMENTATION_ERROR 0x00000001 // 0 no Final After PCW and non-PWC-decoding at least one segment is not zero (global check).
|
||||
|
||||
/*----------*/
|
||||
#define HCR_FATAL_PCW_ERROR_MASK 0x100E01FC
|
||||
|
||||
|
||||
typedef enum {
|
||||
PCW_BODY,
|
||||
PCW_BODY_SIGN,
|
||||
PCW_BODY_SIGN_ESC
|
||||
} PCW_TYPE;
|
||||
|
||||
|
||||
/* interface Decoder <---> HCR */
|
||||
typedef struct {
|
||||
UINT errorLog;
|
||||
SPECTRAL_PTR pQuantizedSpectralCoefficientsBase;
|
||||
int quantizedSpectralCoefficientsIdx;
|
||||
SHORT lengthOfReorderedSpectralData;
|
||||
SHORT numSection;
|
||||
SHORT *pNumLineInSect;
|
||||
USHORT bitstreamIndex;
|
||||
SCHAR lengthOfLongestCodeword;
|
||||
UCHAR *pCodebook;
|
||||
} HCR_INPUT_OUTPUT;
|
||||
|
||||
typedef struct {
|
||||
const UCHAR *pMinOfCbPair;
|
||||
const UCHAR *pMaxOfCbPair;
|
||||
} HCR_CB_PAIRS;
|
||||
|
||||
typedef struct{
|
||||
const USHORT *pLargestAbsVal;
|
||||
const UCHAR *pMaxCwLength;
|
||||
const UCHAR *pCbDimension;
|
||||
const UCHAR *pCbDimShift;
|
||||
const UCHAR *pCbSign;
|
||||
const UCHAR *pCbPriority;
|
||||
} HCR_TABLE_INFO;
|
||||
|
||||
typedef struct{
|
||||
UINT numSegment;
|
||||
UINT pSegmentBitfield[((1024>>1)/NUMBER_OF_BIT_IN_WORD+1)];
|
||||
UINT pCodewordBitfield[((1024>>1)/NUMBER_OF_BIT_IN_WORD+1)];
|
||||
UINT segmentOffset;
|
||||
FIXP_DBL pTempValues[1024];
|
||||
USHORT pLeftStartOfSegment[1024>>1];
|
||||
USHORT pRightStartOfSegment[1024>>1];
|
||||
SCHAR pRemainingBitsInSegment[1024>>1];
|
||||
UCHAR readDirection;
|
||||
UCHAR numWordForBitfield;
|
||||
USHORT pNumBitValidInLastWord;
|
||||
} HCR_SEGMENT_INFO;
|
||||
|
||||
typedef struct{
|
||||
|
||||
UINT numCodeword;
|
||||
UINT numSortedSection;
|
||||
USHORT pNumCodewordInSection[MAX_SFB_HCR];
|
||||
USHORT pNumSortedCodewordInSection[MAX_SFB_HCR];
|
||||
USHORT pNumExtendedSortedCodewordInSection[MAX_SFB_HCR+MAX_HCR_SETS];
|
||||
int numExtendedSortedCodewordInSectionIdx;
|
||||
USHORT pNumExtendedSortedSectionsInSets[MAX_HCR_SETS];
|
||||
int numExtendedSortedSectionsInSetsIdx;
|
||||
USHORT pReorderOffset[MAX_SFB_HCR];
|
||||
UCHAR pSortedCodebook[MAX_SFB_HCR];
|
||||
|
||||
UCHAR pExtendedSortedCodebook[MAX_SFB_HCR+MAX_HCR_SETS];
|
||||
int extendedSortedCodebookIdx;
|
||||
#if DETECT_TOO_LONG_CW_READS
|
||||
UCHAR pMaxLenOfCbInExtSrtSec[MAX_SFB_HCR+MAX_HCR_SETS];
|
||||
int maxLenOfCbInExtSrtSecIdx;
|
||||
#endif
|
||||
UCHAR pCodebookSwitch[MAX_SFB_HCR];
|
||||
} HCR_SECTION_INFO;
|
||||
|
||||
typedef UINT (*STATEFUNC)(HANDLE_FDK_BITSTREAM, void*);
|
||||
|
||||
typedef struct{
|
||||
/* worst-case and 1024/4 non-PCWs exist in worst-case */
|
||||
FIXP_DBL *pResultBase; /* Base address for spectral data output target buffer */
|
||||
UINT iNode[1024>>2]; /* Helper indices for code books */
|
||||
USHORT iResultPointer[1024>>2]; /* Helper indices for accessing pResultBase */
|
||||
UINT pEscapeSequenceInfo[1024>>2];
|
||||
UINT codewordOffset;
|
||||
STATEFUNC pState;
|
||||
UCHAR pCodebook[1024>>2];
|
||||
UCHAR pCntSign[1024>>2];
|
||||
/* this array holds the states coded as integer values within the range [0,1,..,7] */
|
||||
SCHAR pSta[1024>>2];
|
||||
} HCR_NON_PCW_SIDEINFO;
|
||||
|
||||
typedef struct{
|
||||
HCR_INPUT_OUTPUT decInOut;
|
||||
HCR_CB_PAIRS cbPairs;
|
||||
HCR_TABLE_INFO tableInfo;
|
||||
HCR_SEGMENT_INFO segmentInfo;
|
||||
HCR_SECTION_INFO sectionInfo;
|
||||
HCR_NON_PCW_SIDEINFO nonPcwSideinfo;
|
||||
|
||||
INT globalHcrType;
|
||||
} CErHcrInfo;
|
||||
|
||||
|
||||
typedef CErHcrInfo *H_HCR_INFO;
|
||||
|
||||
|
||||
#endif /* _AACDEC_HCR_TYPES_H_ */
|
1344
libAACdec/src/aacdec_hcrs.cpp
Normal file
1344
libAACdec/src/aacdec_hcrs.cpp
Normal file
File diff suppressed because it is too large
Load Diff
91
libAACdec/src/aacdec_hcrs.h
Normal file
91
libAACdec/src/aacdec_hcrs.h
Normal file
@ -0,0 +1,91 @@
|
||||
/***************************** MPEG-4 AAC Decoder ***************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS 2000-2008
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Robert Weidner (DSP Solutions)
|
||||
Description: HCR Decoder: Defines of state-constants, masks and
|
||||
state-prototypes
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _AACDEC_HCRS_H_
|
||||
#define _AACDEC_HCRS_H_
|
||||
|
||||
|
||||
|
||||
#include "FDK_bitstream.h"
|
||||
#include "aacdec_hcr_types.h"
|
||||
/* The four different kinds of types of states are: */
|
||||
/* different states are defined as constants */ /* start middle=self next stop */
|
||||
#define STOP_THIS_STATE 0 /* */
|
||||
#define BODY_ONLY 1 /* X X X */
|
||||
#define BODY_SIGN__BODY 2 /* X X X X [stop if no sign] */
|
||||
#define BODY_SIGN__SIGN 3 /* X X [stop if sign bits decoded] */
|
||||
#define BODY_SIGN_ESC__BODY 4 /* X X X X [stop if no sign] */
|
||||
#define BODY_SIGN_ESC__SIGN 5 /* X X X [stop if no escape sequence] */
|
||||
#define BODY_SIGN_ESC__ESC_PREFIX 6 /* X X */
|
||||
#define BODY_SIGN_ESC__ESC_WORD 7 /* X X X [stop if abs(second qsc) != 16] */
|
||||
|
||||
/* examples: */
|
||||
|
||||
/* BODY_ONLY means only the codeword body will be decoded; no sign bits will follow and no escapesequence will follow */
|
||||
|
||||
/* BODY_SIGN__BODY means that the codeword consists of two parts; body and sign part. The part '__BODY' after the two underscores shows */
|
||||
/* that the bits which are currently decoded belong to the '__BODY' of the codeword and not to the sign part. */
|
||||
|
||||
/* BODY_SIGN_ESC__ESC_PB means that the codeword consists of three parts; body, sign and (here: two) escape sequences; */
|
||||
/* P = Prefix = ones */
|
||||
/* W = Escape Word */
|
||||
/* A = first possible (of two) Escape sequeces */
|
||||
/* B = second possible (of two) Escape sequeces */
|
||||
/* The part after the two underscores shows that the current bits which are decoded belong to the '__ESC_PB' - part of the */
|
||||
/* codeword. That means the body and the sign bits are decoded completely and the bits which are decoded now belong to */
|
||||
/* the escape sequence [P = prefix; B=second possible escape sequence] */
|
||||
|
||||
|
||||
#define MSB_31_MASK 0x80000000 /* masks MSB (= Bit 31) in a 32 bit word */
|
||||
#define DIMENSION_OF_ESCAPE_CODEBOOK 2 /* for cb >= 11 is dimension 2 */
|
||||
#define ESCAPE_CODEBOOK 11
|
||||
|
||||
#define MASK_ESCAPE_PREFIX_UP 0x000F0000
|
||||
#define LSB_ESCAPE_PREFIX_UP 16
|
||||
|
||||
#define MASK_ESCAPE_PREFIX_DOWN 0x0000F000
|
||||
#define LSB_ESCAPE_PREFIX_DOWN 12
|
||||
|
||||
#define MASK_ESCAPE_WORD 0x00000FFF
|
||||
#define MASK_FLAG_A 0x00200000
|
||||
#define MASK_FLAG_B 0x00100000
|
||||
|
||||
|
||||
extern void DecodeNonPCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO hHcr);
|
||||
|
||||
UINT Hcr_State_BODY_ONLY (HANDLE_FDK_BITSTREAM, void*);
|
||||
UINT Hcr_State_BODY_SIGN__BODY (HANDLE_FDK_BITSTREAM, void*);
|
||||
UINT Hcr_State_BODY_SIGN__SIGN (HANDLE_FDK_BITSTREAM, void*);
|
||||
UINT Hcr_State_BODY_SIGN_ESC__BODY (HANDLE_FDK_BITSTREAM, void*);
|
||||
UINT Hcr_State_BODY_SIGN_ESC__SIGN (HANDLE_FDK_BITSTREAM, void*);
|
||||
UINT Hcr_State_BODY_SIGN_ESC__ESC_PREFIX (HANDLE_FDK_BITSTREAM, void*);
|
||||
UINT Hcr_State_BODY_SIGN_ESC__ESC_WORD (HANDLE_FDK_BITSTREAM, void*);
|
||||
|
||||
#endif /* _AACDEC_HCRS_H_ */
|
||||
|
320
libAACdec/src/aacdec_pns.cpp
Normal file
320
libAACdec/src/aacdec_pns.cpp
Normal file
@ -0,0 +1,320 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description: perceptual noise substitution tool
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "aacdec_pns.h"
|
||||
|
||||
|
||||
#include "aac_ram.h"
|
||||
#include "aac_rom.h"
|
||||
#include "channelinfo.h"
|
||||
#include "block.h"
|
||||
#include "FDK_bitstream.h"
|
||||
|
||||
#include "genericStds.h"
|
||||
|
||||
|
||||
#define NOISE_OFFSET 90 /* cf. ISO 14496-3 p. 175 */
|
||||
|
||||
/*!
|
||||
\brief Reset InterChannel and PNS data
|
||||
|
||||
The function resets the InterChannel and PNS data
|
||||
*/
|
||||
void CPns_ResetData(
|
||||
CPnsData *pPnsData,
|
||||
CPnsInterChannelData *pPnsInterChannelData
|
||||
)
|
||||
{
|
||||
/* Assign pointer always, since pPnsData is not persistent data */
|
||||
pPnsData->pPnsInterChannelData = pPnsInterChannelData;
|
||||
pPnsData->PnsActive = 0;
|
||||
pPnsData->CurrentEnergy = 0;
|
||||
|
||||
FDKmemclear(pPnsData->pnsUsed,(8*16)*sizeof(UCHAR));
|
||||
FDKmemclear(pPnsInterChannelData->correlated,(8*16)*sizeof(UCHAR));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Initialize PNS data
|
||||
|
||||
The function initializes the PNS data
|
||||
*/
|
||||
void CPns_InitPns(
|
||||
CPnsData *pPnsData,
|
||||
CPnsInterChannelData *pPnsInterChannelData,
|
||||
INT* currentSeed, INT* randomSeed)
|
||||
{
|
||||
/* save pointer to inter channel data */
|
||||
pPnsData->pPnsInterChannelData = pPnsInterChannelData;
|
||||
|
||||
/* use pointer because seed has to be
|
||||
same, left and right channel ! */
|
||||
pPnsData->currentSeed = currentSeed;
|
||||
pPnsData->randomSeed = randomSeed;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Indicates if PNS is used
|
||||
|
||||
The function returns a value indicating whether PNS is used or not
|
||||
acordding to the noise energy
|
||||
|
||||
\return PNS used
|
||||
*/
|
||||
int CPns_IsPnsUsed (const CPnsData *pPnsData,
|
||||
const int group,
|
||||
const int band)
|
||||
{
|
||||
unsigned pns_band = group*16+band;
|
||||
|
||||
return pPnsData->pnsUsed[pns_band] & (UCHAR)1;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Set correlation
|
||||
|
||||
The function activates the noise correlation between the channel pair
|
||||
*/
|
||||
void CPns_SetCorrelation(CPnsData *pPnsData,
|
||||
const int group,
|
||||
const int band,
|
||||
const int outofphase)
|
||||
{
|
||||
CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData;
|
||||
unsigned pns_band = group*16+band;
|
||||
|
||||
pInterChannelData->correlated[pns_band] = (outofphase) ? 3 : 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Indicates if correlation is used
|
||||
|
||||
The function indicates if the noise correlation between the channel pair
|
||||
is activated
|
||||
|
||||
\return PNS is correlated
|
||||
*/
|
||||
static
|
||||
int CPns_IsCorrelated(const CPnsData *pPnsData,
|
||||
const int group,
|
||||
const int band)
|
||||
{
|
||||
CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData;
|
||||
unsigned pns_band = group*16+band;
|
||||
|
||||
return (pInterChannelData->correlated[pns_band] & 0x01) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Indicates if correlated out of phase mode is used.
|
||||
|
||||
The function indicates if the noise correlation between the channel pair
|
||||
is activated in out-of-phase mode.
|
||||
|
||||
\return PNS is out-of-phase
|
||||
*/
|
||||
static
|
||||
int CPns_IsOutOfPhase(const CPnsData *pPnsData,
|
||||
const int group,
|
||||
const int band)
|
||||
{
|
||||
CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData;
|
||||
unsigned pns_band = group*16+band;
|
||||
|
||||
return (pInterChannelData->correlated[pns_band] & 0x02) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Read PNS information
|
||||
|
||||
The function reads the PNS information from the bitstream
|
||||
*/
|
||||
void CPns_Read (CPnsData *pPnsData,
|
||||
HANDLE_FDK_BITSTREAM bs,
|
||||
const CodeBookDescription *hcb,
|
||||
SHORT *pScaleFactor,
|
||||
UCHAR global_gain,
|
||||
int band,
|
||||
int group /* = 0 */)
|
||||
{
|
||||
int delta ;
|
||||
UINT pns_band = group*16+band;
|
||||
|
||||
if (pPnsData->PnsActive) {
|
||||
/* Next PNS band case */
|
||||
delta = CBlock_DecodeHuffmanWord (bs, hcb) - 60;
|
||||
} else {
|
||||
/* First PNS band case */
|
||||
int noiseStartValue = FDKreadBits(bs,9);
|
||||
|
||||
delta = noiseStartValue - 256 ;
|
||||
pPnsData->PnsActive = 1;
|
||||
pPnsData->CurrentEnergy = global_gain - NOISE_OFFSET;
|
||||
}
|
||||
|
||||
pPnsData->CurrentEnergy += delta ;
|
||||
pScaleFactor[pns_band] = pPnsData->CurrentEnergy;
|
||||
|
||||
pPnsData->pnsUsed[pns_band] = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Generate a vector of noise of given length. The noise values are
|
||||
* scaled in order to yield a noise energy of 1.0
|
||||
* \param spec pointer to were the noise values will be written to.
|
||||
* \param size amount of noise values to be generated.
|
||||
* \param pRandomState pointer to the state of the random generator being used.
|
||||
* \return exponent of generated noise vector.
|
||||
*/
|
||||
static int GenerateRandomVector (FIXP_DBL *RESTRICT spec,
|
||||
int size,
|
||||
int *pRandomState)
|
||||
{
|
||||
int i, invNrg_e = 0, nrg_e = 0;
|
||||
FIXP_DBL invNrg_m, nrg_m = FL2FXCONST_DBL(0.0f) ;
|
||||
FIXP_DBL *RESTRICT ptr = spec;
|
||||
int randomState = *pRandomState;
|
||||
|
||||
#define GEN_NOISE_NRG_SCALE 7
|
||||
|
||||
/* Generate noise and calculate energy. */
|
||||
for (i=0; i<size; i++)
|
||||
{
|
||||
randomState = (1664525L * randomState) + 1013904223L; // Numerical Recipes
|
||||
nrg_m = fPow2AddDiv2(nrg_m, (FIXP_DBL)randomState>>GEN_NOISE_NRG_SCALE);
|
||||
*ptr++ = (FIXP_DBL)randomState;
|
||||
}
|
||||
nrg_e = GEN_NOISE_NRG_SCALE*2 + 1;
|
||||
|
||||
/* weight noise with = 1 / sqrt_nrg; */
|
||||
invNrg_m = invSqrtNorm2(nrg_m<<1, &invNrg_e);
|
||||
invNrg_e += -((nrg_e-1)>>1);
|
||||
|
||||
for (i=size; i--; )
|
||||
{
|
||||
spec[i] = fMult(spec[i], invNrg_m);
|
||||
}
|
||||
|
||||
/* Store random state */
|
||||
*pRandomState = randomState;
|
||||
|
||||
return invNrg_e;
|
||||
}
|
||||
|
||||
static void ScaleBand (FIXP_DBL *RESTRICT spec, int size, int scaleFactor, int specScale, int noise_e, int out_of_phase)
|
||||
{
|
||||
int i, shift, sfExponent;
|
||||
FIXP_DBL sfMatissa;
|
||||
|
||||
/* Get gain from scale factor value = 2^(scaleFactor * 0.25) */
|
||||
sfMatissa = MantissaTable[scaleFactor & 0x03][0];
|
||||
/* sfExponent = (scaleFactor >> 2) + ExponentTable[scaleFactor & 0x03][0]; */
|
||||
/* Note: ExponentTable[scaleFactor & 0x03][0] is always 1. */
|
||||
sfExponent = (scaleFactor >> 2) + 1;
|
||||
|
||||
if (out_of_phase != 0) {
|
||||
sfMatissa = -sfMatissa;
|
||||
}
|
||||
|
||||
/* +1 because of fMultDiv2 below. */
|
||||
shift = sfExponent - specScale + 1 + noise_e;
|
||||
|
||||
/* Apply gain to noise values */
|
||||
if (shift>=0) {
|
||||
shift = fixMin( shift, DFRACT_BITS-1 );
|
||||
for (i = size ; i-- != 0; ) {
|
||||
spec [i] = fMultDiv2 (spec [i], sfMatissa) << shift;
|
||||
}
|
||||
} else {
|
||||
shift = fixMin( -shift, DFRACT_BITS-1 );
|
||||
for (i = size ; i-- != 0; ) {
|
||||
spec [i] = fMultDiv2 (spec [i], sfMatissa) >> shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Apply PNS
|
||||
|
||||
The function applies PNS (i.e. it generates noise) on the bands
|
||||
flagged as noisy bands
|
||||
|
||||
*/
|
||||
void CPns_Apply (const CPnsData *pPnsData,
|
||||
const CIcsInfo *pIcsInfo,
|
||||
SPECTRAL_PTR pSpectrum,
|
||||
const SHORT *pSpecScale,
|
||||
const SHORT *pScaleFactor,
|
||||
const SamplingRateInfo *pSamplingRateInfo,
|
||||
const INT granuleLength,
|
||||
const int channel)
|
||||
{
|
||||
if (pPnsData->PnsActive) {
|
||||
const short *BandOffsets = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo);
|
||||
|
||||
int ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(pIcsInfo);
|
||||
|
||||
for (int window = 0, group = 0; group < GetWindowGroups(pIcsInfo); group++) {
|
||||
for (int groupwin = 0; groupwin < GetWindowGroupLength(pIcsInfo, group); groupwin++, window++) {
|
||||
FIXP_DBL *spectrum = SPEC(pSpectrum, window, granuleLength);
|
||||
|
||||
for (int band = 0 ; band < ScaleFactorBandsTransmitted; band++) {
|
||||
if (CPns_IsPnsUsed (pPnsData, group, band)) {
|
||||
UINT pns_band = group*16+band;
|
||||
|
||||
int bandWidth = BandOffsets [band + 1] - BandOffsets [band] ;
|
||||
int noise_e;
|
||||
|
||||
FDK_ASSERT(bandWidth >= 0);
|
||||
|
||||
if (channel > 0 && CPns_IsCorrelated(pPnsData, group, band))
|
||||
{
|
||||
noise_e = GenerateRandomVector (spectrum + BandOffsets [band], bandWidth,
|
||||
&pPnsData->randomSeed [pns_band]) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
pPnsData->randomSeed [pns_band] = *pPnsData->currentSeed ;
|
||||
|
||||
noise_e = GenerateRandomVector (spectrum + BandOffsets [band], bandWidth,
|
||||
pPnsData->currentSeed) ;
|
||||
}
|
||||
|
||||
int outOfPhase = CPns_IsOutOfPhase (pPnsData, group, band);
|
||||
|
||||
ScaleBand (spectrum + BandOffsets [band], bandWidth,
|
||||
pScaleFactor[pns_band],
|
||||
pSpecScale[window], noise_e, outOfPhase) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
58
libAACdec/src/aacdec_pns.h
Normal file
58
libAACdec/src/aacdec_pns.h
Normal file
@ -0,0 +1,58 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description: perceptual noise substitution tool
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef PNS_H
|
||||
#define PNS_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
|
||||
#define NO_OFBANDS ((8*16))
|
||||
|
||||
typedef struct {
|
||||
UCHAR correlated[NO_OFBANDS];
|
||||
} CPnsInterChannelData;
|
||||
|
||||
typedef struct {
|
||||
CPnsInterChannelData *pPnsInterChannelData;
|
||||
UCHAR pnsUsed[NO_OFBANDS];
|
||||
int CurrentEnergy;
|
||||
UCHAR PnsActive;
|
||||
INT *currentSeed;
|
||||
INT *randomSeed;
|
||||
} CPnsData;
|
||||
|
||||
void CPns_InitPns ( CPnsData *pPnsData,
|
||||
CPnsInterChannelData *pPnsInterChannelData,
|
||||
INT* currentSeed,
|
||||
INT* randomSeed );
|
||||
|
||||
void CPns_ResetData ( CPnsData *pPnsData, CPnsInterChannelData *pPnsInterChannelData );
|
||||
|
||||
|
||||
#endif /* #ifndef PNS_H */
|
350
libAACdec/src/aacdec_tns.cpp
Normal file
350
libAACdec/src/aacdec_tns.cpp
Normal file
@ -0,0 +1,350 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description: temporal noise shaping tool
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "aacdec_tns.h"
|
||||
#include "aac_rom.h"
|
||||
#include "FDK_bitstream.h"
|
||||
#include "channelinfo.h"
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
\brief Reset tns data
|
||||
|
||||
The function resets the tns data
|
||||
|
||||
\return none
|
||||
*/
|
||||
void CTns_Reset(CTnsData *pTnsData)
|
||||
{
|
||||
/* Note: the following FDKmemclear should not be required. */
|
||||
FDKmemclear(pTnsData->Filter, TNS_MAX_WINDOWS*TNS_MAXIMUM_FILTERS*sizeof(CFilter));
|
||||
FDKmemclear(pTnsData->NumberOfFilters, TNS_MAX_WINDOWS*sizeof(UCHAR));
|
||||
pTnsData->DataPresent = 0;
|
||||
pTnsData->Active = 0;
|
||||
}
|
||||
|
||||
void CTns_ReadDataPresentFlag(HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */
|
||||
CTnsData *pTnsData) /*!< pointer to aac decoder channel info */
|
||||
{
|
||||
pTnsData->DataPresent = (UCHAR) FDKreadBits(bs,1);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Read tns data from bitstream
|
||||
|
||||
The function reads the elements for tns from
|
||||
the bitstream.
|
||||
|
||||
\return none
|
||||
*/
|
||||
AAC_DECODER_ERROR CTns_Read(HANDLE_FDK_BITSTREAM bs,
|
||||
CTnsData *pTnsData,
|
||||
const CIcsInfo *pIcsInfo,
|
||||
const UINT flags)
|
||||
{
|
||||
UCHAR n_filt,order;
|
||||
UCHAR length,coef_res,coef_compress;
|
||||
UCHAR window;
|
||||
UCHAR wins_per_frame = GetWindowsPerFrame(pIcsInfo);
|
||||
UCHAR isLongFlag = IsLongBlock(pIcsInfo);
|
||||
AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
|
||||
|
||||
if (!pTnsData->DataPresent) {
|
||||
return ErrorStatus;
|
||||
}
|
||||
|
||||
for (window = 0; window < wins_per_frame; window++)
|
||||
{
|
||||
pTnsData->NumberOfFilters[window] = n_filt = (UCHAR) FDKreadBits(bs, isLongFlag ? 2 : 1);
|
||||
|
||||
if (pTnsData->NumberOfFilters[window] > TNS_MAXIMUM_FILTERS){
|
||||
pTnsData->NumberOfFilters[window] = n_filt = TNS_MAXIMUM_FILTERS;
|
||||
}
|
||||
|
||||
if (n_filt)
|
||||
{
|
||||
int index;
|
||||
UCHAR nextstopband;
|
||||
|
||||
coef_res = (UCHAR) FDKreadBits(bs,1);
|
||||
|
||||
nextstopband = GetScaleFactorBandsTotal(pIcsInfo);
|
||||
|
||||
for (index=0; index < n_filt; index++)
|
||||
{
|
||||
CFilter *filter = &pTnsData->Filter[window][index];
|
||||
|
||||
length = (UCHAR)FDKreadBits(bs, isLongFlag ? 6 : 4);
|
||||
|
||||
if (length > nextstopband){
|
||||
length = nextstopband;
|
||||
}
|
||||
|
||||
filter->StartBand = nextstopband - length;
|
||||
filter->StopBand = nextstopband;
|
||||
nextstopband = filter->StartBand;
|
||||
|
||||
{
|
||||
filter->Order = order = (UCHAR) FDKreadBits(bs, isLongFlag ? 5 : 3);
|
||||
}
|
||||
|
||||
if (filter->Order > TNS_MAXIMUM_ORDER){
|
||||
filter->Order = order = TNS_MAXIMUM_ORDER;
|
||||
}
|
||||
|
||||
if (order)
|
||||
{
|
||||
UCHAR coef,s_mask;
|
||||
UCHAR i;
|
||||
SCHAR n_mask;
|
||||
static const UCHAR sgn_mask[] = { 0x2, 0x4, 0x8 };
|
||||
static const SCHAR neg_mask[] = { ~0x3, ~0x7, ~0xF };
|
||||
|
||||
filter->Direction = FDKreadBits(bs,1) ? -1 : 1;
|
||||
|
||||
coef_compress = (UCHAR) FDKreadBits(bs,1);
|
||||
|
||||
filter->Resolution = coef_res + 3;
|
||||
|
||||
s_mask = sgn_mask[coef_res + 1 - coef_compress];
|
||||
n_mask = neg_mask[coef_res + 1 - coef_compress];
|
||||
|
||||
for (i=0; i < order; i++)
|
||||
{
|
||||
coef = (UCHAR) FDKreadBits(bs,filter->Resolution - coef_compress);
|
||||
filter->Coeff[i] = (coef & s_mask) ? (coef | n_mask) : coef;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pTnsData->Active = 1;
|
||||
|
||||
return ErrorStatus;
|
||||
}
|
||||
|
||||
|
||||
static void CTns_Filter (FIXP_DBL *spec, int size, int inc, FIXP_TCC coeff [], int order)
|
||||
{
|
||||
// - Simple all-pole filter of order "order" defined by
|
||||
// y(n) = x(n) - a(2)*y(n-1) - ... - a(order+1)*y(n-order)
|
||||
//
|
||||
// - The state variables of the filter are initialized to zero every time
|
||||
//
|
||||
// - The output data is written over the input data ("in-place operation")
|
||||
//
|
||||
// - An input vector of "size" samples is processed and the index increment
|
||||
// to the next data sample is given by "inc"
|
||||
|
||||
int i,j,N;
|
||||
FIXP_DBL *pSpec;
|
||||
FIXP_DBL maxVal=FL2FXCONST_DBL(0.0);
|
||||
INT s;
|
||||
|
||||
FDK_ASSERT(order <= TNS_MAXIMUM_ORDER);
|
||||
C_ALLOC_SCRATCH_START(state, FIXP_DBL, TNS_MAXIMUM_ORDER);
|
||||
FDKmemclear(state, order*sizeof(FIXP_DBL));
|
||||
|
||||
for (i=0; i<size; i++) {
|
||||
maxVal = fixMax(maxVal,fixp_abs(spec[i]));
|
||||
}
|
||||
|
||||
if ( maxVal > FL2FXCONST_DBL(0.03125*0.70710678118) )
|
||||
s = fixMax(CntLeadingZeros(maxVal)-6,0);
|
||||
else
|
||||
s = fixMax(CntLeadingZeros(maxVal)-5,0);
|
||||
|
||||
s = fixMin(s,2);
|
||||
s = s-1;
|
||||
|
||||
if (inc == -1)
|
||||
pSpec = &spec[size - 1];
|
||||
else
|
||||
pSpec = &spec[0];
|
||||
|
||||
FIXP_TCC *pCoeff;
|
||||
|
||||
#define FIRST_PART_FLTR \
|
||||
FIXP_DBL x, *pState = state; \
|
||||
pCoeff = coeff; \
|
||||
\
|
||||
if (s < 0) \
|
||||
x = (pSpec [0]>>1) + fMultDiv2 (*pCoeff++, pState [0]) ; \
|
||||
else \
|
||||
x = (pSpec [0]<<s) + fMultDiv2 (*pCoeff++, pState [0]) ;
|
||||
|
||||
#define INNER_FLTR_INLINE \
|
||||
x = fMultAddDiv2 (x, *pCoeff, pState [1]); \
|
||||
pState [0] = pState [1] - (fMultDiv2 (*pCoeff++, x) <<2) ; \
|
||||
pState++;
|
||||
|
||||
#define LAST_PART_FLTR \
|
||||
if (s < 0) \
|
||||
*pSpec = x << 1; \
|
||||
else \
|
||||
*pSpec = x >> s; \
|
||||
*pState =(-x) << 1; \
|
||||
pSpec += inc ;
|
||||
|
||||
|
||||
if (order>8)
|
||||
{
|
||||
N = (order-1)&7;
|
||||
|
||||
for (i = size ; i != 0 ; i--)
|
||||
{
|
||||
FIRST_PART_FLTR
|
||||
|
||||
for (j = N; j > 0 ; j--) { INNER_FLTR_INLINE }
|
||||
|
||||
INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE
|
||||
INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE
|
||||
|
||||
LAST_PART_FLTR
|
||||
}
|
||||
|
||||
} else if (order>4) {
|
||||
|
||||
N = (order-1)&3;
|
||||
|
||||
for (i = size ; i != 0 ; i--)
|
||||
{
|
||||
FIRST_PART_FLTR
|
||||
for (j = N; j > 0 ; j--) { INNER_FLTR_INLINE }
|
||||
|
||||
INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE
|
||||
|
||||
LAST_PART_FLTR
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
N = order-1;
|
||||
|
||||
for (i = size ; i != 0 ; i--)
|
||||
{
|
||||
FIRST_PART_FLTR
|
||||
|
||||
for (j = N; j > 0 ; j--) { INNER_FLTR_INLINE }
|
||||
|
||||
LAST_PART_FLTR
|
||||
}
|
||||
}
|
||||
|
||||
C_ALLOC_SCRATCH_END(state, FIXP_DBL, TNS_MAXIMUM_ORDER);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Apply tns to spectral lines
|
||||
|
||||
The function applies the tns to the spectrum,
|
||||
|
||||
\return none
|
||||
*/
|
||||
void CTns_Apply (
|
||||
CTnsData *RESTRICT pTnsData, /*!< pointer to aac decoder info */
|
||||
const CIcsInfo *pIcsInfo,
|
||||
SPECTRAL_PTR pSpectralCoefficient,
|
||||
const SamplingRateInfo *pSamplingRateInfo,
|
||||
const INT granuleLength
|
||||
)
|
||||
{
|
||||
int window,index,start,stop,size;
|
||||
|
||||
|
||||
if (pTnsData->Active)
|
||||
{
|
||||
C_AALLOC_SCRATCH_START(coeff, FIXP_TCC, TNS_MAXIMUM_ORDER);
|
||||
|
||||
for (window=0; window < GetWindowsPerFrame(pIcsInfo); window++)
|
||||
{
|
||||
FIXP_DBL *pSpectrum = SPEC(pSpectralCoefficient, window, granuleLength);
|
||||
|
||||
for (index=0; index < pTnsData->NumberOfFilters[window]; index++)
|
||||
{
|
||||
CFilter *RESTRICT filter = &pTnsData->Filter[window][index];
|
||||
|
||||
if (filter->Order > 0)
|
||||
{
|
||||
FIXP_TCC *pCoeff;
|
||||
int tns_max_bands;
|
||||
|
||||
pCoeff = &coeff[filter->Order-1];
|
||||
if (filter->Resolution == 3)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < filter->Order; i++)
|
||||
*pCoeff-- = FDKaacDec_tnsCoeff3[filter->Coeff[i]+4];
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < filter->Order; i++)
|
||||
*pCoeff-- = FDKaacDec_tnsCoeff4[filter->Coeff[i]+8];
|
||||
}
|
||||
|
||||
switch (granuleLength) {
|
||||
case 480:
|
||||
tns_max_bands = tns_max_bands_tbl_480[pSamplingRateInfo->samplingRateIndex-3];
|
||||
break;
|
||||
case 512:
|
||||
tns_max_bands = tns_max_bands_tbl_512[pSamplingRateInfo->samplingRateIndex-3];
|
||||
break;
|
||||
default:
|
||||
tns_max_bands = GetMaximumTnsBands(pIcsInfo, pSamplingRateInfo->samplingRateIndex);
|
||||
break;
|
||||
}
|
||||
|
||||
start = fixMin( fixMin(filter->StartBand, tns_max_bands),
|
||||
GetScaleFactorBandsTransmitted(pIcsInfo) );
|
||||
|
||||
start = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo)[start];
|
||||
|
||||
stop = fixMin( fixMin(filter->StopBand, tns_max_bands),
|
||||
GetScaleFactorBandsTransmitted(pIcsInfo) );
|
||||
|
||||
stop = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo)[stop];
|
||||
|
||||
size = stop - start;
|
||||
|
||||
if (size > 0) {
|
||||
CTns_Filter(&pSpectrum[start],
|
||||
size,
|
||||
filter->Direction,
|
||||
coeff,
|
||||
filter->Order );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
C_AALLOC_SCRATCH_END(coeff, FIXP_TCC, TNS_MAXIMUM_ORDER);
|
||||
}
|
||||
|
||||
}
|
64
libAACdec/src/aacdec_tns.h
Normal file
64
libAACdec/src/aacdec_tns.h
Normal file
@ -0,0 +1,64 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description: temporal noise shaping tool
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef TNS_H
|
||||
#define TNS_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
enum
|
||||
{
|
||||
TNS_MAX_WINDOWS = 8, /* 8 */
|
||||
TNS_MAXIMUM_ORDER = 12, /* 12 for AAC-LC and AAC-SSR. Set to 20 for AAC-Main (AOT 1). Some broken encoders also do order 20 for AAC-LC :( */
|
||||
TNS_MAXIMUM_FILTERS = 3
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SCHAR Coeff[TNS_MAXIMUM_ORDER];
|
||||
|
||||
UCHAR StartBand;
|
||||
UCHAR StopBand;
|
||||
|
||||
SCHAR Direction;
|
||||
SCHAR Resolution;
|
||||
|
||||
UCHAR Order;
|
||||
} CFilter;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CFilter Filter[TNS_MAX_WINDOWS][TNS_MAXIMUM_FILTERS];
|
||||
UCHAR NumberOfFilters[TNS_MAX_WINDOWS];
|
||||
UCHAR DataPresent;
|
||||
UCHAR Active;
|
||||
} CTnsData;
|
||||
|
||||
void CTns_Reset(CTnsData *pTnsData);
|
||||
|
||||
#endif /* #ifndef TNS_H */
|
1667
libAACdec/src/aacdecoder.cpp
Normal file
1667
libAACdec/src/aacdecoder.cpp
Normal file
File diff suppressed because it is too large
Load Diff
250
libAACdec/src/aacdecoder.h
Normal file
250
libAACdec/src/aacdecoder.h
Normal file
@ -0,0 +1,250 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description:
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef AACDECODER_H
|
||||
#define AACDECODER_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "FDK_bitstream.h"
|
||||
|
||||
#include "channel.h"
|
||||
|
||||
#include "tpdec_lib.h"
|
||||
#include "FDK_audio.h"
|
||||
|
||||
#include "block.h"
|
||||
|
||||
#include "genericStds.h"
|
||||
|
||||
|
||||
#include "sbrdecoder.h"
|
||||
|
||||
|
||||
#include "aacdec_drc.h"
|
||||
|
||||
#include "pcmutils_lib.h"
|
||||
|
||||
|
||||
/* Capabilities flags */
|
||||
#define CAPF_AAC_LC 0x00000001
|
||||
#define CAPF_AAC_LD 0x00000002
|
||||
#define CAPF_AAC_SCAL 0x00000004
|
||||
#define CAPF_AAC_ER 0x00000008
|
||||
#define CAPF_AAC_480 0x00000010
|
||||
#define CAPF_AAC_512 0x00000020
|
||||
#define CAPF_AAC_960 0x00000040
|
||||
#define CAPF_AAC_1024 0x00000080
|
||||
#define CAPF_AAC_HCR 0x00000100
|
||||
#define CAPF_AAC_VCB11 0x00000200
|
||||
#define CAPF_AAC_RVLC 0x00000400
|
||||
#define CAPF_AAC_MPEG4 0x00000800 /* PNS */
|
||||
#define CAPF_AAC_DRC 0x00001000
|
||||
#define CAPF_AAC_CONCEAL 0x00002000
|
||||
#define CAPF_AAC_DRM_BSFORMAT 0x00004000
|
||||
#define CAPF_AAC_BSAC 0x00008000
|
||||
|
||||
typedef struct AAC_DECODER_INSTANCE *HANDLE_AACDECODER;
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
L = 0,
|
||||
R = 1
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned char *buffer;
|
||||
int bufferSize;
|
||||
int offset[8];
|
||||
int nrElements;
|
||||
} CAncData;
|
||||
|
||||
typedef enum {
|
||||
NOT_DEFINED = -1,
|
||||
MODE_HQ = 0,
|
||||
MODE_LP = 1
|
||||
} QMF_MODE;
|
||||
|
||||
typedef struct {
|
||||
int bsDelay;
|
||||
} SBR_PARAMS;
|
||||
|
||||
|
||||
/* AAC decoder (opaque toward userland) struct declaration */
|
||||
struct AAC_DECODER_INSTANCE {
|
||||
INT aacChannels; /*!< Amount of AAC decoder channels allocated. */
|
||||
INT ascChannels; /*!< Amount of AAC decoder channels signalled in ASC. */
|
||||
INT blockNumber; /*!< frame counter */
|
||||
|
||||
INT nrOfLayers;
|
||||
|
||||
INT outputInterleaved; /*!< PCM output format (interleaved/none interleaved). */
|
||||
|
||||
HANDLE_TRANSPORTDEC hInput; /*!< Transport layer handle. */
|
||||
|
||||
SamplingRateInfo samplingRateInfo; /*!< Sampling Rate information table */
|
||||
|
||||
UCHAR frameOK; /*!< Will be unset if a consistency check, e.g. CRC etc. fails */
|
||||
|
||||
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. */
|
||||
|
||||
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). */
|
||||
/* 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. */
|
||||
|
||||
|
||||
CProgramConfig pce;
|
||||
CStreamInfo streamInfo; /*!< pointer to StreamInfo data (read from the bitstream) */
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo[(6)]; /*!< Temporal channel memory */
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[(6)]; /*!< Persistent channel memory */
|
||||
|
||||
CAacDecoderCommonData aacCommonData; /*!< Temporal shared data for all channels hooked into pAacDecoderChannelInfo */
|
||||
|
||||
CConcealParams concealCommonData;
|
||||
INT concealChannels;
|
||||
|
||||
|
||||
HANDLE_SBRDECODER hSbrDecoder; /*!< SBR decoder handle. */
|
||||
UCHAR sbrEnabled; /*!< flag to store if SBR has been detected */
|
||||
UCHAR sbrEnabledPrev; /*!< flag to store if SBR has been detected from previous frame */
|
||||
UCHAR psPossible; /*!< flag to store if PS is possible */
|
||||
SBR_PARAMS sbrParams; /*!< struct to store all sbr parameters */
|
||||
|
||||
QMF_MODE qmfModeCurr; /*!< The current QMF mode */
|
||||
QMF_MODE qmfModeUser; /*!< The QMF mode requested by the library user */
|
||||
|
||||
HANDLE_AAC_DRC hDrcInfo; /*!< handle to DRC data structure */
|
||||
|
||||
|
||||
CAncData ancData; /*!< structure to handle ancillary data */
|
||||
|
||||
HANDLE_PCM_DOWNMIX hPcmUtils; /*!< privat data for the PCM utils. */
|
||||
|
||||
};
|
||||
|
||||
|
||||
#define AAC_DEBUG_EXTHLP "\
|
||||
--- AAC-Core ---\n\
|
||||
0x00010000 Header data\n\
|
||||
0x00020000 CRC data\n\
|
||||
0x00040000 Channel info\n\
|
||||
0x00080000 Section data\n\
|
||||
0x00100000 Scalefactor data\n\
|
||||
0x00200000 Pulse data\n\
|
||||
0x00400000 Tns data\n\
|
||||
0x00800000 Quantized spectrum\n\
|
||||
0x01000000 Requantized spectrum\n\
|
||||
0x02000000 Time output\n\
|
||||
0x04000000 Fatal errors\n\
|
||||
0x08000000 Buffer fullness\n\
|
||||
0x10000000 Average bitrate\n\
|
||||
0x20000000 Synchronization\n\
|
||||
0x40000000 Concealment\n\
|
||||
0x7FFF0000 all AAC-Core-Info\n\
|
||||
"
|
||||
|
||||
/**
|
||||
* \brief Synchronise QMF mode for all modules using QMF data.
|
||||
* \param self decoder handle
|
||||
*/
|
||||
void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self);
|
||||
|
||||
/**
|
||||
* \brief Signal a bit stream interruption to the decoder
|
||||
* \param self decoder handle
|
||||
*/
|
||||
void CAacDecoder_SignalInterruption(HANDLE_AACDECODER self);
|
||||
|
||||
/*!
|
||||
\brief Initialize ancillary buffer
|
||||
|
||||
\ancData Pointer to ancillary data structure
|
||||
\buffer Pointer to (external) anc data buffer
|
||||
\size Size of the buffer pointed on by buffer
|
||||
|
||||
\return Error code
|
||||
*/
|
||||
AAC_DECODER_ERROR CAacDecoder_AncDataInit(CAncData *ancData, unsigned char *buffer, int size);
|
||||
|
||||
/*!
|
||||
\brief Get one ancillary data element
|
||||
|
||||
\ancData Pointer to ancillary data structure
|
||||
\index Index of the anc data element to get
|
||||
\ptr Pointer to a buffer receiving a pointer to the requested anc data element
|
||||
\size Pointer to a buffer receiving the length of the requested anc data element
|
||||
|
||||
\return Error code
|
||||
*/
|
||||
AAC_DECODER_ERROR CAacDecoder_AncDataGet(CAncData *ancData, int index, unsigned char **ptr, int *size);
|
||||
|
||||
|
||||
/* initialization of aac decoder */
|
||||
LINKSPEC_H HANDLE_AACDECODER CAacDecoder_Open(TRANSPORT_TYPE bsFormat);
|
||||
|
||||
/* Initialization of stream-info elements */
|
||||
LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self,
|
||||
const CSAudioSpecificConfig *asc);
|
||||
|
||||
/*!
|
||||
\brief Decodes one aac frame
|
||||
|
||||
The function decodes one aac frame. The decoding of coupling channel
|
||||
elements are not supported. The transport layer might signal, that the
|
||||
data of the current frame is invalid, e.g. as a result of a packet
|
||||
loss in streaming mode.
|
||||
The bitstream position of transportDec_GetBitstream(self->hInput) must
|
||||
be exactly the end of the access unit, including all byte alignment bits.
|
||||
For this purpose, the variable auStartAnchor is used.
|
||||
|
||||
\return error status
|
||||
*/
|
||||
LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
|
||||
HANDLE_AACDECODER self,
|
||||
const UINT flags,
|
||||
INT_PCM *pTimeData,
|
||||
const INT timeDataSize,
|
||||
const INT interleaved
|
||||
);
|
||||
|
||||
/* Destroy aac decoder */
|
||||
LINKSPEC_H void CAacDecoder_Close ( HANDLE_AACDECODER self );
|
||||
|
||||
/* get streaminfo handle from decoder */
|
||||
LINKSPEC_H CStreamInfo* CAacDecoder_GetStreamInfo ( HANDLE_AACDECODER self );
|
||||
|
||||
|
||||
#endif /* #ifndef AACDECODER_H */
|
925
libAACdec/src/aacdecoder_lib.cpp
Normal file
925
libAACdec/src/aacdecoder_lib.cpp
Normal file
@ -0,0 +1,925 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS 1999-2008
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Manuel Jander
|
||||
Description:
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "aacdecoder_lib.h"
|
||||
|
||||
#include "aac_ram.h"
|
||||
#include "aacdecoder.h"
|
||||
#include "tpdec_lib.h"
|
||||
#include "FDK_core.h" /* FDK_tools version info */
|
||||
|
||||
|
||||
#include "sbrdecoder.h"
|
||||
|
||||
|
||||
|
||||
|
||||
#include "conceal.h"
|
||||
|
||||
#include "aacdec_drc.h"
|
||||
|
||||
|
||||
|
||||
/* Decoder library info */
|
||||
#define AACDECODER_LIB_VL0 2
|
||||
#define AACDECODER_LIB_VL1 4
|
||||
#define AACDECODER_LIB_VL2 0
|
||||
#define AACDECODER_LIB_TITLE "AAC Decoder Lib"
|
||||
#define AACDECODER_LIB_BUILD_DATE __DATE__
|
||||
#define AACDECODER_LIB_BUILD_TIME __TIME__
|
||||
|
||||
static AAC_DECODER_ERROR
|
||||
setConcealMethod ( const HANDLE_AACDECODER self,
|
||||
const INT method );
|
||||
|
||||
|
||||
LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_GetFreeBytes ( const HANDLE_AACDECODER self, UINT *pFreeBytes){
|
||||
|
||||
/* reset free bytes */
|
||||
*pFreeBytes = 0;
|
||||
|
||||
/* check handle */
|
||||
if(!self)
|
||||
return AAC_DEC_INVALID_HANDLE;
|
||||
|
||||
/* return nr of free bytes */
|
||||
HANDLE_FDK_BITSTREAM hBs = transportDec_GetBitstream(self->hInput, 0);
|
||||
*pFreeBytes = FDKgetFreeBits(hBs) >> 3;
|
||||
|
||||
/* success */
|
||||
return AAC_DEC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Config Decoder using a CSAudioSpecificConfig struct.
|
||||
*/
|
||||
static
|
||||
LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_Config(HANDLE_AACDECODER self, const CSAudioSpecificConfig *pAscStruct)
|
||||
{
|
||||
AAC_DECODER_ERROR err;
|
||||
|
||||
/* Initialize AAC core decoder, and update self->streaminfo */
|
||||
err = CAacDecoder_Init(self, pAscStruct);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_ConfigRaw (
|
||||
HANDLE_AACDECODER self,
|
||||
UCHAR *conf[],
|
||||
const UINT length[] )
|
||||
{
|
||||
AAC_DECODER_ERROR err = AAC_DEC_OK;
|
||||
TRANSPORTDEC_ERROR errTp;
|
||||
UINT layer, nrOfLayers = self->nrOfLayers;
|
||||
|
||||
for(layer = 0; layer < nrOfLayers; layer++){
|
||||
if(length[layer] > 0){
|
||||
errTp = transportDec_OutOfBandConfig(self->hInput, conf[layer], length[layer], layer);
|
||||
if (errTp != TRANSPORTDEC_OK) {
|
||||
switch (errTp) {
|
||||
case TRANSPORTDEC_NEED_TO_RESTART:
|
||||
err = AAC_DEC_NEED_TO_RESTART;
|
||||
break;
|
||||
case TRANSPORTDEC_UNSUPPORTED_FORMAT:
|
||||
err = AAC_DEC_UNSUPPORTED_FORMAT;
|
||||
break;
|
||||
default:
|
||||
err = AAC_DEC_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
/* if baselayer is OK we continue decoding */
|
||||
if(layer >= 1){
|
||||
self->nrOfLayers = layer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static INT aacDecoder_ConfigCallback(void *handle, const CSAudioSpecificConfig *pAscStruct)
|
||||
{
|
||||
HANDLE_AACDECODER self = (HANDLE_AACDECODER)handle;
|
||||
AAC_DECODER_ERROR err = AAC_DEC_OK;
|
||||
TRANSPORTDEC_ERROR errTp;
|
||||
|
||||
{
|
||||
{
|
||||
err = aacDecoder_Config(self, pAscStruct);
|
||||
}
|
||||
}
|
||||
if (err == AAC_DEC_OK) {
|
||||
if ( self->flags & (AC_USAC|AC_RSVD50|AC_LD|AC_ELD)
|
||||
&& CConcealment_GetDelay(&self->concealCommonData) > 0 )
|
||||
{
|
||||
/* Revert to error concealment method Noise Substitution.
|
||||
Because interpolation is not implemented for USAC/RSVD50 or
|
||||
the additional delay is unwanted for low delay codecs. */
|
||||
setConcealMethod(self, 1);
|
||||
#ifdef DEBUG
|
||||
FDKprintf(" Concealment method was reverted to 1 !\n");
|
||||
#endif
|
||||
}
|
||||
errTp = TRANSPORTDEC_OK;
|
||||
} else {
|
||||
if (IS_INIT_ERROR(err)) {
|
||||
errTp = TRANSPORTDEC_UNSUPPORTED_FORMAT;
|
||||
} /* Fatal errors */
|
||||
else if (err == AAC_DEC_NEED_TO_RESTART) {
|
||||
errTp = TRANSPORTDEC_NEED_TO_RESTART;
|
||||
} else {
|
||||
errTp = TRANSPORTDEC_UNKOWN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return errTp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
LINKSPEC_CPP AAC_DECODER_ERROR
|
||||
aacDecoder_AncDataInit ( HANDLE_AACDECODER self,
|
||||
UCHAR *buffer,
|
||||
int size )
|
||||
{
|
||||
CAncData *ancData = &self->ancData;
|
||||
|
||||
return CAacDecoder_AncDataInit(ancData, buffer, size);
|
||||
}
|
||||
|
||||
|
||||
LINKSPEC_CPP AAC_DECODER_ERROR
|
||||
aacDecoder_AncDataGet ( HANDLE_AACDECODER self,
|
||||
int index,
|
||||
UCHAR **ptr,
|
||||
int *size )
|
||||
{
|
||||
CAncData *ancData = &self->ancData;
|
||||
|
||||
return CAacDecoder_AncDataGet(ancData, index, ptr, size);
|
||||
}
|
||||
|
||||
|
||||
static AAC_DECODER_ERROR
|
||||
setConcealMethod ( const HANDLE_AACDECODER self, /*!< Handle of the decoder instance */
|
||||
const INT method )
|
||||
{
|
||||
AAC_DECODER_ERROR errorStatus = AAC_DEC_OK;
|
||||
CConcealParams *pConcealData = NULL;
|
||||
HANDLE_SBRDECODER hSbrDec = NULL;
|
||||
HANDLE_AAC_DRC hDrcInfo = NULL;
|
||||
HANDLE_PCM_DOWNMIX hPcmDmx = NULL;
|
||||
CConcealmentMethod backupMethod;
|
||||
int backupDelay = 0;
|
||||
int bsDelay = 0;
|
||||
|
||||
/* check decoder handle */
|
||||
if (self != NULL) {
|
||||
pConcealData = &self->concealCommonData;
|
||||
hSbrDec = self->hSbrDecoder;
|
||||
hDrcInfo = self->hDrcInfo;
|
||||
hPcmDmx = self->hPcmUtils;
|
||||
}
|
||||
|
||||
|
||||
/* Get current method/delay */
|
||||
backupMethod = CConcealment_GetMethod(pConcealData);
|
||||
backupDelay = CConcealment_GetDelay(pConcealData);
|
||||
|
||||
/* Be sure to set AAC and SBR concealment method simultaneously! */
|
||||
errorStatus =
|
||||
CConcealment_SetParams(
|
||||
pConcealData,
|
||||
(int)method, // concealMethod
|
||||
AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealFadeOutSlope
|
||||
AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealFadeInSlope
|
||||
AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealMuteRelease
|
||||
AACDEC_CONCEAL_PARAM_NOT_SPECIFIED // concealComfNoiseLevel
|
||||
);
|
||||
if ( (errorStatus != AAC_DEC_OK)
|
||||
&& (errorStatus != AAC_DEC_INVALID_HANDLE) ) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Get new delay */
|
||||
bsDelay = CConcealment_GetDelay(pConcealData);
|
||||
|
||||
{
|
||||
SBR_ERROR sbrErr = SBRDEC_OK;
|
||||
|
||||
/* set SBR bitstream delay */
|
||||
sbrErr = sbrDecoder_SetParam (
|
||||
hSbrDec,
|
||||
SBR_SYSTEM_BITSTREAM_DELAY,
|
||||
bsDelay
|
||||
);
|
||||
|
||||
switch (sbrErr) {
|
||||
case SBRDEC_OK:
|
||||
case SBRDEC_NOT_INITIALIZED:
|
||||
if (self != NULL) {
|
||||
/* save the param value and set later
|
||||
(when SBR has been initialized) */
|
||||
self->sbrParams.bsDelay = bsDelay;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
errorStatus = AAC_DEC_SET_PARAM_FAIL;
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
errorStatus =
|
||||
aacDecoder_drcSetParam (
|
||||
hDrcInfo,
|
||||
DRC_BS_DELAY,
|
||||
bsDelay
|
||||
);
|
||||
if ( (errorStatus != AAC_DEC_OK)
|
||||
&& (errorStatus != AAC_DEC_INVALID_HANDLE) ) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (errorStatus == AAC_DEC_OK) {
|
||||
PCMDMX_ERROR err =
|
||||
pcmDmx_SetParam (
|
||||
hPcmDmx,
|
||||
DMX_BS_DATA_DELAY,
|
||||
bsDelay
|
||||
);
|
||||
switch (err) {
|
||||
case PCMDMX_INVALID_HANDLE:
|
||||
errorStatus = AAC_DEC_INVALID_HANDLE;
|
||||
case PCMDMX_OK:
|
||||
break;
|
||||
default:
|
||||
errorStatus = AAC_DEC_SET_PARAM_FAIL;
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bail:
|
||||
if ( (errorStatus != AAC_DEC_OK)
|
||||
&& (errorStatus != AAC_DEC_INVALID_HANDLE) )
|
||||
{
|
||||
/* Revert to the initial state */
|
||||
CConcealment_SetParams (
|
||||
pConcealData,
|
||||
(int)backupMethod,
|
||||
AACDEC_CONCEAL_PARAM_NOT_SPECIFIED,
|
||||
AACDEC_CONCEAL_PARAM_NOT_SPECIFIED,
|
||||
AACDEC_CONCEAL_PARAM_NOT_SPECIFIED,
|
||||
AACDEC_CONCEAL_PARAM_NOT_SPECIFIED
|
||||
);
|
||||
/* Revert SBR bitstream delay */
|
||||
sbrDecoder_SetParam (
|
||||
hSbrDec,
|
||||
SBR_SYSTEM_BITSTREAM_DELAY,
|
||||
backupDelay
|
||||
);
|
||||
/* Revert DRC bitstream delay */
|
||||
aacDecoder_drcSetParam (
|
||||
hDrcInfo,
|
||||
DRC_BS_DELAY,
|
||||
backupDelay
|
||||
);
|
||||
/* Revert PCM mixdown bitstream delay */
|
||||
pcmDmx_SetParam (
|
||||
hPcmDmx,
|
||||
DMX_BS_DATA_DELAY,
|
||||
backupDelay
|
||||
);
|
||||
}
|
||||
|
||||
return errorStatus;
|
||||
}
|
||||
|
||||
|
||||
LINKSPEC_CPP AAC_DECODER_ERROR
|
||||
aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decoder instance */
|
||||
const AACDEC_PARAM param, /*!< Parameter to set */
|
||||
const INT value) /*!< Parameter valued */
|
||||
{
|
||||
AAC_DECODER_ERROR errorStatus = AAC_DEC_OK;
|
||||
CConcealParams *pConcealData = NULL;
|
||||
HANDLE_AAC_DRC hDrcInfo = NULL;
|
||||
|
||||
/* check decoder handle */
|
||||
if (self != NULL) {
|
||||
pConcealData = &self->concealCommonData;
|
||||
hDrcInfo = self->hDrcInfo;
|
||||
}
|
||||
|
||||
/* configure the subsystems */
|
||||
switch (param)
|
||||
{
|
||||
case AAC_PCM_OUTPUT_INTERLEAVED:
|
||||
if (value < 0 || value > 1) {
|
||||
return AAC_DEC_SET_PARAM_FAIL;
|
||||
}
|
||||
if (self == NULL) {
|
||||
return AAC_DEC_INVALID_HANDLE;
|
||||
}
|
||||
self->outputInterleaved = value;
|
||||
break;
|
||||
|
||||
case AAC_PCM_OUTPUT_CHANNELS:
|
||||
{
|
||||
PCMDMX_ERROR err;
|
||||
|
||||
err = pcmDmx_SetParam (
|
||||
self->hPcmUtils,
|
||||
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_DUAL_CHANNEL_OUTPUT_MODE:
|
||||
{
|
||||
PCMDMX_ERROR err;
|
||||
|
||||
err = pcmDmx_SetParam (
|
||||
self->hPcmUtils,
|
||||
DUAL_CHANNEL_DOWNMIX_MODE,
|
||||
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_OUTPUT_CHANNEL_MAPPING:
|
||||
switch (value) {
|
||||
case 0:
|
||||
self->channelOutputMapping = channelMappingTablePassthrough;
|
||||
break;
|
||||
case 1:
|
||||
self->channelOutputMapping = channelMappingTableWAV;
|
||||
break;
|
||||
default:
|
||||
errorStatus = AAC_DEC_SET_PARAM_FAIL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case AAC_QMF_LOWPOWER:
|
||||
if (self == NULL) {
|
||||
return AAC_DEC_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set QMF mode (might be overriden)
|
||||
* 0:HQ (complex)
|
||||
* 1:LP (partially complex)
|
||||
*/
|
||||
self->qmfModeUser = (QMF_MODE)value;
|
||||
break;
|
||||
|
||||
|
||||
case AAC_DRC_ATTENUATION_FACTOR:
|
||||
/* DRC compression factor (where 0 is no and 127 is max compression) */
|
||||
errorStatus =
|
||||
aacDecoder_drcSetParam (
|
||||
hDrcInfo,
|
||||
DRC_CUT_SCALE,
|
||||
value
|
||||
);
|
||||
break;
|
||||
|
||||
case AAC_DRC_BOOST_FACTOR:
|
||||
/* DRC boost factor (where 0 is no and 127 is max boost) */
|
||||
errorStatus =
|
||||
aacDecoder_drcSetParam (
|
||||
hDrcInfo,
|
||||
DRC_BOOST_SCALE,
|
||||
value
|
||||
);
|
||||
break;
|
||||
|
||||
case AAC_DRC_REFERENCE_LEVEL:
|
||||
/* DRC reference level quantized in 0.25dB steps using values [0..127] it is '-' for analog scaling */
|
||||
errorStatus =
|
||||
aacDecoder_drcSetParam (
|
||||
hDrcInfo,
|
||||
TARGET_REF_LEVEL,
|
||||
value
|
||||
);
|
||||
break;
|
||||
|
||||
case AAC_DRC_HEAVY_COMPRESSION:
|
||||
/* Don't need to overwrite cut/boost values */
|
||||
errorStatus =
|
||||
aacDecoder_drcSetParam (
|
||||
hDrcInfo,
|
||||
APPLY_HEAVY_COMPRESSION,
|
||||
value
|
||||
);
|
||||
break;
|
||||
|
||||
|
||||
case AAC_TPDEC_CLEAR_BUFFER:
|
||||
transportDec_SetParam(self->hInput, TPDEC_PARAM_RESET, 1);
|
||||
self->streamInfo.numLostAccessUnits = 0;
|
||||
self->streamInfo.numBadBytes = 0;
|
||||
self->streamInfo.numTotalBytes = 0;
|
||||
/* aacDecoder_SignalInterruption(self); */
|
||||
break;
|
||||
|
||||
case AAC_CONCEAL_METHOD:
|
||||
/* Changing the concealment method can introduce additional bitstream delay. And
|
||||
that in turn affects sub libraries and modules which makes the whole thing quite
|
||||
complex. So the complete changing routine is packed into a helper function which
|
||||
keeps all modules and libs in a consistent state even in the case an error occures. */
|
||||
errorStatus = setConcealMethod ( self, value );
|
||||
break;
|
||||
|
||||
default:
|
||||
return AAC_DEC_SET_PARAM_FAIL;
|
||||
} /* switch(param) */
|
||||
|
||||
return (errorStatus);
|
||||
}
|
||||
|
||||
|
||||
LINKSPEC_CPP HANDLE_AACDECODER aacDecoder_Open(TRANSPORT_TYPE transportFmt, UINT nrOfLayers)
|
||||
{
|
||||
AAC_DECODER_INSTANCE *aacDec = NULL;
|
||||
HANDLE_TRANSPORTDEC pIn;
|
||||
int err = 0;
|
||||
|
||||
/* Allocate transport layer struct. */
|
||||
pIn = transportDec_Open(transportFmt, TP_FLAG_MPEG4);
|
||||
if (pIn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate AAC decoder core struct. */
|
||||
aacDec = CAacDecoder_Open(transportFmt);
|
||||
|
||||
if (aacDec == NULL) {
|
||||
transportDec_Close(&pIn);
|
||||
goto bail;
|
||||
}
|
||||
aacDec->hInput = pIn;
|
||||
|
||||
aacDec->nrOfLayers = nrOfLayers;
|
||||
|
||||
aacDec->channelOutputMapping = channelMappingTableWAV;
|
||||
|
||||
/* Register Config Update callback. */
|
||||
transportDec_RegisterAscCallback(pIn, aacDecoder_ConfigCallback, (void*)aacDec);
|
||||
|
||||
/* open SBR decoder */
|
||||
if ( SBRDEC_OK != sbrDecoder_Open ( &aacDec->hSbrDecoder )) {
|
||||
err = -1;
|
||||
goto bail;
|
||||
}
|
||||
aacDec->qmfModeUser = NOT_DEFINED;
|
||||
transportDec_RegisterSbrCallback(aacDec->hInput, (cbSbr_t)sbrDecoder_Header, (void*)aacDec->hSbrDecoder);
|
||||
|
||||
|
||||
pcmDmx_Open( &aacDec->hPcmUtils );
|
||||
if (aacDec->hPcmUtils == NULL) {
|
||||
err = -1;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Assure that all modules have same delay */
|
||||
if ( setConcealMethod(aacDec, CConcealment_GetMethod(&aacDec->concealCommonData)) ) {
|
||||
err = -1;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
bail:
|
||||
if (err == -1) {
|
||||
aacDecoder_Close(aacDec);
|
||||
aacDec = NULL;
|
||||
}
|
||||
return aacDec;
|
||||
}
|
||||
|
||||
LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_Fill(
|
||||
HANDLE_AACDECODER self,
|
||||
UCHAR *pBuffer[],
|
||||
const UINT bufferSize[],
|
||||
UINT *pBytesValid
|
||||
)
|
||||
{
|
||||
TRANSPORTDEC_ERROR tpErr;
|
||||
/* loop counter for layers; if not TT_MP4_RAWPACKETS used as index for only
|
||||
available layer */
|
||||
INT layer = 0;
|
||||
INT nrOfLayers = self->nrOfLayers;
|
||||
|
||||
{
|
||||
for (layer = 0; layer < nrOfLayers; layer++){
|
||||
{
|
||||
tpErr = transportDec_FillData( self->hInput, pBuffer[layer], bufferSize[layer], &pBytesValid[layer], layer );
|
||||
if (tpErr != TRANSPORTDEC_OK) {
|
||||
return AAC_DEC_UNKNOWN; /* Must be an internal error */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return AAC_DEC_OK;
|
||||
}
|
||||
|
||||
|
||||
static void aacDecoder_SignalInterruption(HANDLE_AACDECODER self)
|
||||
{
|
||||
CAacDecoder_SignalInterruption(self);
|
||||
|
||||
if ( self->hSbrDecoder != NULL ) {
|
||||
sbrDecoder_SetParam(self->hSbrDecoder, SBR_BS_INTERRUPTION, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void aacDecoder_UpdateBitStreamCounters(CStreamInfo *pSi, HANDLE_FDK_BITSTREAM hBs, int nBits, AAC_DECODER_ERROR ErrorStatus)
|
||||
{
|
||||
/* calculate bit difference (amount of bits moved forward) */
|
||||
nBits = nBits - FDKgetValidBits(hBs);
|
||||
|
||||
/* Note: The amount of bits consumed might become negative when parsing a
|
||||
bit stream with several sub frames, and we find out at the last sub frame
|
||||
that the total frame length does not match the sum of sub frame length.
|
||||
If this happens, the transport decoder might want to rewind to the supposed
|
||||
ending of the transport frame, and this position might be before the last
|
||||
access unit beginning. */
|
||||
|
||||
/* Calc bitrate. */
|
||||
if (pSi->frameSize > 0) {
|
||||
pSi->bitRate = (nBits * pSi->sampleRate)/pSi->frameSize;
|
||||
}
|
||||
|
||||
/* bit/byte counters */
|
||||
{
|
||||
int nBytes;
|
||||
|
||||
nBytes = nBits>>3;
|
||||
pSi->numTotalBytes += nBytes;
|
||||
if (IS_OUTPUT_VALID(ErrorStatus)) {
|
||||
pSi->numTotalAccessUnits++;
|
||||
}
|
||||
if (IS_DECODE_ERROR(ErrorStatus)) {
|
||||
pSi->numBadBytes += nBytes;
|
||||
pSi->numBadAccessUnits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static INT aacDecoder_EstimateNumberOfLostFrames(HANDLE_AACDECODER self)
|
||||
{
|
||||
INT n;
|
||||
|
||||
transportDec_GetMissingAccessUnitCount( &n, self->hInput);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(
|
||||
HANDLE_AACDECODER self,
|
||||
INT_PCM *pTimeData,
|
||||
const INT timeDataSize,
|
||||
const UINT flags)
|
||||
{
|
||||
AAC_DECODER_ERROR ErrorStatus;
|
||||
INT layer;
|
||||
INT nBits;
|
||||
INT interleaved = self->outputInterleaved;
|
||||
HANDLE_FDK_BITSTREAM hBs;
|
||||
int fTpInterruption = 0; /* Transport originated interruption detection. */
|
||||
int fTpConceal = 0; /* Transport originated concealment. */
|
||||
|
||||
|
||||
if (self == NULL) {
|
||||
return AAC_DEC_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (flags & AACDEC_INTR) {
|
||||
self->streamInfo.numLostAccessUnits = 0;
|
||||
}
|
||||
|
||||
hBs = transportDec_GetBitstream(self->hInput, 0);
|
||||
|
||||
/* Get current bits position for bitrate calculation. */
|
||||
nBits = FDKgetValidBits(hBs);
|
||||
if (! (flags & (AACDEC_CONCEAL | AACDEC_FLUSH) ) )
|
||||
{
|
||||
TRANSPORTDEC_ERROR err;
|
||||
|
||||
for(layer = 0; layer < self->nrOfLayers; layer++)
|
||||
{
|
||||
err = transportDec_ReadAccessUnit(self->hInput, layer);
|
||||
if (err != TRANSPORTDEC_OK) {
|
||||
switch (err) {
|
||||
case TRANSPORTDEC_NOT_ENOUGH_BITS:
|
||||
ErrorStatus = AAC_DEC_NOT_ENOUGH_BITS;
|
||||
goto bail;
|
||||
case TRANSPORTDEC_SYNC_ERROR:
|
||||
self->streamInfo.numLostAccessUnits = aacDecoder_EstimateNumberOfLostFrames(self);
|
||||
fTpInterruption = 1;
|
||||
break;
|
||||
case TRANSPORTDEC_NEED_TO_RESTART:
|
||||
ErrorStatus = AAC_DEC_NEED_TO_RESTART;
|
||||
goto bail;
|
||||
case TRANSPORTDEC_CRC_ERROR:
|
||||
fTpConceal = 1;
|
||||
break;
|
||||
default:
|
||||
ErrorStatus = AAC_DEC_UNKNOWN;
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (self->streamInfo.numLostAccessUnits > 0) {
|
||||
self->streamInfo.numLostAccessUnits--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Signal bit stream interruption to other modules if required. */
|
||||
if ( fTpInterruption || (flags & (AACDEC_INTR|AACDEC_CLRHIST)) )
|
||||
{
|
||||
aacDecoder_SignalInterruption(self);
|
||||
if ( ! (flags & AACDEC_INTR) ) {
|
||||
ErrorStatus = AAC_DEC_TRANSPORT_SYNC_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Empty bit buffer in case of flush request. */
|
||||
if (flags & AACDEC_FLUSH)
|
||||
{
|
||||
transportDec_SetParam(self->hInput, TPDEC_PARAM_RESET, 1);
|
||||
self->streamInfo.numLostAccessUnits = 0;
|
||||
self->streamInfo.numBadBytes = 0;
|
||||
self->streamInfo.numTotalBytes = 0;
|
||||
}
|
||||
|
||||
|
||||
ErrorStatus = CAacDecoder_DecodeFrame(self,
|
||||
flags | (fTpConceal ? AACDEC_CONCEAL : 0),
|
||||
pTimeData,
|
||||
timeDataSize,
|
||||
interleaved);
|
||||
|
||||
if (!(flags & (AACDEC_CONCEAL|AACDEC_FLUSH))) {
|
||||
TRANSPORTDEC_ERROR tpErr;
|
||||
tpErr = transportDec_EndAccessUnit(self->hInput);
|
||||
if (tpErr != TRANSPORTDEC_OK) {
|
||||
self->frameOK = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the current pTimeData does not contain a valid signal, there nothing else we can do, so bail. */
|
||||
if ( ! IS_OUTPUT_VALID(ErrorStatus) ) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
{
|
||||
/* Export data into streaminfo structure */
|
||||
self->streamInfo.sampleRate = self->streamInfo.aacSampleRate;
|
||||
self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame;
|
||||
self->streamInfo.numChannels = self->aacChannels;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CAacDecoder_SyncQmfMode(self);
|
||||
|
||||
/* sbr decoder */
|
||||
|
||||
if (ErrorStatus || (flags & AACDEC_CONCEAL) || self->pAacDecoderStaticChannelInfo[0]->concealmentInfo.concealState > ConcealState_FadeIn)
|
||||
{
|
||||
self->frameOK = 0; /* if an error has occured do concealment in the SBR decoder too */
|
||||
}
|
||||
|
||||
if (self->sbrEnabled)
|
||||
{
|
||||
SBR_ERROR sbrError = SBRDEC_OK;
|
||||
|
||||
/* set params */
|
||||
sbrDecoder_SetParam ( self->hSbrDecoder,
|
||||
SBR_SYSTEM_BITSTREAM_DELAY,
|
||||
self->sbrParams.bsDelay);
|
||||
|
||||
if ( self->streamInfo.aot == AOT_ER_AAC_ELD ) {
|
||||
/* Configure QMF */
|
||||
sbrDecoder_SetParam ( self->hSbrDecoder,
|
||||
SBR_LD_QMF_TIME_ALIGN,
|
||||
(self->flags & AC_LD_MPS) ? 1 : 0 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* apply SBR processing */
|
||||
sbrError = sbrDecoder_Apply ( self->hSbrDecoder,
|
||||
pTimeData,
|
||||
&self->streamInfo.numChannels,
|
||||
&self->streamInfo.sampleRate,
|
||||
self->channelOutputMapping[self->aacChannels-1],
|
||||
interleaved,
|
||||
self->frameOK,
|
||||
&self->psPossible);
|
||||
|
||||
|
||||
if (sbrError == SBRDEC_OK) {
|
||||
|
||||
/* 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;
|
||||
} else {
|
||||
self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame << 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->psPossible) {
|
||||
self->flags |= AC_PS_PRESENT;
|
||||
self->channelType[0] = ACT_FRONT;
|
||||
self->channelType[1] = ACT_FRONT;
|
||||
self->channelIndices[0] = 0;
|
||||
self->channelIndices[1] = 1;
|
||||
} else {
|
||||
self->flags &= ~AC_PS_PRESENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 (
|
||||
self->hPcmUtils,
|
||||
pTimeData,
|
||||
self->streamInfo.frameSize,
|
||||
&self->streamInfo.numChannels,
|
||||
interleaved,
|
||||
self->channelType,
|
||||
self->channelIndices,
|
||||
self->channelOutputMapping
|
||||
);
|
||||
|
||||
|
||||
|
||||
/* Signal interruption to take effect in next frame. */
|
||||
if ( flags & AACDEC_FLUSH ) {
|
||||
aacDecoder_SignalInterruption(self);
|
||||
}
|
||||
|
||||
/* Update externally visible copy of flags */
|
||||
self->streamInfo.flags = self->flags;
|
||||
|
||||
bail:
|
||||
|
||||
/* Update Statistics */
|
||||
aacDecoder_UpdateBitStreamCounters(&self->streamInfo, hBs, nBits, ErrorStatus);
|
||||
|
||||
return ErrorStatus;
|
||||
}
|
||||
|
||||
LINKSPEC_CPP void aacDecoder_Close ( HANDLE_AACDECODER self )
|
||||
{
|
||||
if (self == NULL)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
if (self->hPcmUtils != NULL) {
|
||||
pcmDmx_Close( &self->hPcmUtils );
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (self->hSbrDecoder != NULL) {
|
||||
sbrDecoder_Close(&self->hSbrDecoder);
|
||||
}
|
||||
|
||||
if (self->hInput != NULL) {
|
||||
transportDec_Close(&self->hInput);
|
||||
}
|
||||
|
||||
CAacDecoder_Close(self);
|
||||
}
|
||||
|
||||
|
||||
LINKSPEC_CPP CStreamInfo* aacDecoder_GetStreamInfo ( HANDLE_AACDECODER self )
|
||||
{
|
||||
return CAacDecoder_GetStreamInfo(self);
|
||||
}
|
||||
|
||||
LINKSPEC_CPP INT aacDecoder_GetLibInfo ( LIB_INFO *info )
|
||||
{
|
||||
int i;
|
||||
|
||||
if (info == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sbrDecoder_GetLibInfo( info );
|
||||
transportDec_GetLibInfo( info );
|
||||
FDK_toolsGetLibInfo( info );
|
||||
pcmDmx_GetLibInfo( info );
|
||||
|
||||
/* search for next free tab */
|
||||
for (i = 0; i < FDK_MODULE_LAST; i++) {
|
||||
if (info[i].module_id == FDK_NONE) break;
|
||||
}
|
||||
if (i == FDK_MODULE_LAST) {
|
||||
return -1;
|
||||
}
|
||||
info += i;
|
||||
|
||||
info->module_id = FDK_AACDEC;
|
||||
/* build own library info */
|
||||
info->version = LIB_VERSION(AACDECODER_LIB_VL0, AACDECODER_LIB_VL1, AACDECODER_LIB_VL2);
|
||||
LIB_VERSION_STRING(info);
|
||||
info->build_date = AACDECODER_LIB_BUILD_DATE;
|
||||
info->build_time = AACDECODER_LIB_BUILD_TIME;
|
||||
info->title = AACDECODER_LIB_TITLE;
|
||||
|
||||
/* Set flags */
|
||||
info->flags = 0
|
||||
| CAPF_AAC_LC
|
||||
| CAPF_AAC_VCB11
|
||||
| CAPF_AAC_HCR
|
||||
| CAPF_AAC_RVLC
|
||||
| CAPF_ER_AAC_LD
|
||||
| CAPF_ER_AAC_ELD
|
||||
| CAPF_AAC_CONCEALMENT
|
||||
| CAPF_AAC_DRC
|
||||
|
||||
| CAPF_AAC_MPEG4
|
||||
|
||||
|
||||
| CAPF_AAC_1024
|
||||
| CAPF_AAC_960
|
||||
|
||||
| CAPF_AAC_512
|
||||
|
||||
| CAPF_AAC_480
|
||||
|
||||
;
|
||||
/* End of flags */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
77
libAACdec/src/arm/block_arm.cpp
Normal file
77
libAACdec/src/arm/block_arm.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
/******************************** Fraunhofer IIS ***************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2010)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Arthur Tritthart
|
||||
Description: (ARM optimised) Scaling of spectral data
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#define FUNCTION_CBlock_ScaleSpectralData_func1
|
||||
|
||||
/* Note: This loop is only separated for ARM in order to save cycles
|
||||
by loop unrolling. The ARM core provides by default a 5-cycle
|
||||
loop overhead per sample, that goes down to 1-cycle per sample
|
||||
with an optimal 4x-loop construct (do - 4x - while).
|
||||
*/
|
||||
|
||||
FDK_INLINE static void CBlock_ScaleSpectralData_func1(
|
||||
FIXP_DBL *pSpectrum,
|
||||
int max_band,
|
||||
const SHORT * RESTRICT BandOffsets,
|
||||
int SpecScale_window,
|
||||
const SHORT * RESTRICT pSfbScale,
|
||||
int window)
|
||||
{
|
||||
int band_offset = 0;
|
||||
for (int band=0; band < max_band; band++)
|
||||
{
|
||||
int runs = band_offset;
|
||||
band_offset = BandOffsets[band+1];
|
||||
runs = band_offset - runs; /* is always a multiple of 4 */
|
||||
int scale = SpecScale_window-pSfbScale[window*16+band];
|
||||
if (scale)
|
||||
{
|
||||
do
|
||||
{
|
||||
FIXP_DBL tmp0, tmp1, tmp2, tmp3;
|
||||
tmp0 = pSpectrum[0];
|
||||
tmp1 = pSpectrum[1];
|
||||
tmp2 = pSpectrum[2];
|
||||
tmp3 = pSpectrum[3];
|
||||
tmp0 >>= scale;
|
||||
tmp1 >>= scale;
|
||||
tmp2 >>= scale;
|
||||
tmp3 >>= scale;
|
||||
*pSpectrum++ = tmp0;
|
||||
*pSpectrum++ = tmp1;
|
||||
*pSpectrum++ = tmp2;
|
||||
*pSpectrum++ = tmp3;
|
||||
} while ((runs = runs-4) != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pSpectrum+= runs;
|
||||
}
|
||||
}
|
||||
}
|
703
libAACdec/src/block.cpp
Normal file
703
libAACdec/src/block.cpp
Normal file
@ -0,0 +1,703 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description: long/short-block decoding
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "block.h"
|
||||
|
||||
#include "aac_rom.h"
|
||||
#include "FDK_bitstream.h"
|
||||
#include "FDK_tools_rom.h"
|
||||
|
||||
|
||||
|
||||
|
||||
#include "aacdec_hcr.h"
|
||||
#include "rvlc.h"
|
||||
|
||||
|
||||
#if defined(__arm__)
|
||||
#include "arm/block_arm.cpp"
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\brief Read escape sequence of codeword
|
||||
|
||||
The function reads the escape sequence from the bitstream,
|
||||
if the absolute value of the quantized coefficient has the
|
||||
value 16.
|
||||
|
||||
\return quantized coefficient
|
||||
*/
|
||||
LONG CBlock_GetEscape(HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */
|
||||
const LONG q) /*!< quantized coefficient */
|
||||
{
|
||||
LONG i, off, neg ;
|
||||
|
||||
if (q < 0)
|
||||
{
|
||||
if (q != -16) return q;
|
||||
neg = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (q != +16) return q;
|
||||
neg = 0;
|
||||
}
|
||||
|
||||
for (i=4; ; i++)
|
||||
{
|
||||
if (FDKreadBits(bs,1) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i > 16)
|
||||
{
|
||||
if (i - 16 > CACHE_BITS) { /* cannot read more than "CACHE_BITS" bits at once in the function FDKreadBits() */
|
||||
return (MAX_QUANTIZED_VALUE + 1); /* returning invalid value that will be captured later */
|
||||
}
|
||||
|
||||
off = FDKreadBits(bs,i-16) << 16;
|
||||
off |= FDKreadBits(bs,16);
|
||||
}
|
||||
else
|
||||
{
|
||||
off = FDKreadBits(bs,i);
|
||||
}
|
||||
|
||||
i = off + (1 << i);
|
||||
|
||||
if (neg) i = -i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
AAC_DECODER_ERROR CBlock_ReadScaleFactorData(
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
HANDLE_FDK_BITSTREAM bs,
|
||||
UINT flags
|
||||
)
|
||||
{
|
||||
int temp;
|
||||
int band;
|
||||
int group;
|
||||
int position = 0; /* accu for intensity delta coding */
|
||||
int factor = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain; /* accu for scale factor delta coding */
|
||||
UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook;
|
||||
SHORT *pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor;
|
||||
const CodeBookDescription *hcb =&AACcodeBookDescriptionTable[BOOKSCL];
|
||||
|
||||
int ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
|
||||
for (group=0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++)
|
||||
{
|
||||
for (band=0; band < ScaleFactorBandsTransmitted; band++)
|
||||
{
|
||||
switch (pCodeBook[group*16+band]) {
|
||||
|
||||
case ZERO_HCB: /* zero book */
|
||||
pScaleFactor[group*16+band] = 0;
|
||||
break;
|
||||
|
||||
default: /* decode scale factor */
|
||||
{
|
||||
temp = CBlock_DecodeHuffmanWord(bs,hcb);
|
||||
factor += temp - 60; /* MIDFAC 1.5 dB */
|
||||
}
|
||||
pScaleFactor[group*16+band] = factor - 100;
|
||||
break;
|
||||
|
||||
case INTENSITY_HCB: /* intensity steering */
|
||||
case INTENSITY_HCB2:
|
||||
temp = CBlock_DecodeHuffmanWord(bs,hcb);
|
||||
position += temp - 60;
|
||||
pScaleFactor[group*16+band] = position - 100;
|
||||
break;
|
||||
|
||||
case NOISE_HCB: /* PNS */
|
||||
if (flags & (AC_MPS_RES|AC_USAC|AC_RSVD50)) {
|
||||
return AAC_DEC_PARSE_ERROR;
|
||||
}
|
||||
CPns_Read( &pAacDecoderChannelInfo->data.aac.PnsData, bs, hcb, pAacDecoderChannelInfo->pDynData->aScaleFactor, pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain, band, group);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return AAC_DEC_OK;
|
||||
}
|
||||
|
||||
void CBlock_ScaleSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo, SamplingRateInfo *pSamplingRateInfo)
|
||||
{
|
||||
int band;
|
||||
int window;
|
||||
const SHORT * RESTRICT pSfbScale = pAacDecoderChannelInfo->pDynData->aSfbScale;
|
||||
SHORT * RESTRICT pSpecScale = pAacDecoderChannelInfo->specScale;
|
||||
int groupwin,group;
|
||||
const SHORT * RESTRICT BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo);
|
||||
SPECTRAL_PTR RESTRICT pSpectralCoefficient = pAacDecoderChannelInfo->pSpectralCoefficient;
|
||||
|
||||
|
||||
FDKmemclear(pSpecScale, 8*sizeof(SHORT));
|
||||
|
||||
int max_band = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
|
||||
for (window=0, group=0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++)
|
||||
{
|
||||
for (groupwin=0; groupwin < GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); groupwin++, window++)
|
||||
{
|
||||
int SpecScale_window = pSpecScale[window];
|
||||
FIXP_DBL *pSpectrum = SPEC(pSpectralCoefficient, window, pAacDecoderChannelInfo->granuleLength);
|
||||
|
||||
/* find scaling for current window */
|
||||
for (band=0; band < max_band; band++)
|
||||
{
|
||||
SpecScale_window = fMax(SpecScale_window, (int)pSfbScale[window*16+band]);
|
||||
}
|
||||
|
||||
if (pAacDecoderChannelInfo->pDynData->TnsData.Active) {
|
||||
SpecScale_window += TNS_SCALE;
|
||||
}
|
||||
|
||||
/* store scaling of current window */
|
||||
pSpecScale[window] = SpecScale_window;
|
||||
|
||||
#ifdef FUNCTION_CBlock_ScaleSpectralData_func1
|
||||
|
||||
CBlock_ScaleSpectralData_func1(pSpectrum, max_band, BandOffsets, SpecScale_window, pSfbScale, window);
|
||||
|
||||
#else /* FUNCTION_CBlock_ScaleSpectralData_func1 */
|
||||
for (band=0; band < max_band; band++)
|
||||
{
|
||||
int scale = SpecScale_window - pSfbScale[window*16+band];
|
||||
if (scale)
|
||||
{
|
||||
/* following relation can be used for optimizations: (BandOffsets[i]%4) == 0 for all i */
|
||||
int max_index = BandOffsets[band+1];
|
||||
for (int index = BandOffsets[band]; index < max_index; index++)
|
||||
{
|
||||
pSpectrum[index] >>= scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* FUNCTION_CBlock_ScaleSpectralData_func1 */
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AAC_DECODER_ERROR CBlock_ReadSectionData(HANDLE_FDK_BITSTREAM bs,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
const SamplingRateInfo *pSamplingRateInfo,
|
||||
const UINT flags)
|
||||
{
|
||||
int top, band;
|
||||
int sect_len, sect_len_incr;
|
||||
int group;
|
||||
UCHAR sect_cb;
|
||||
UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook;
|
||||
/* HCR input (long) */
|
||||
SHORT *pNumLinesInSec = pAacDecoderChannelInfo->pDynData->specificTo.aac.aNumLineInSec4Hcr;
|
||||
int numLinesInSecIdx = 0;
|
||||
UCHAR *pHcrCodeBook = pAacDecoderChannelInfo->pDynData->specificTo.aac.aCodeBooks4Hcr;
|
||||
const SHORT *BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo);
|
||||
pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection = 0;
|
||||
AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
|
||||
|
||||
FDKmemclear(pCodeBook, sizeof(UCHAR)*(8*16));
|
||||
|
||||
const int nbits = (IsLongBlock(&pAacDecoderChannelInfo->icsInfo) == 1) ? 5 : 3;
|
||||
|
||||
int sect_esc_val = (1 << nbits) - 1 ;
|
||||
|
||||
UCHAR ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
|
||||
for (group=0; group<GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++)
|
||||
{
|
||||
for (band=0; band < ScaleFactorBandsTransmitted; )
|
||||
{
|
||||
sect_len = 0;
|
||||
if ( flags & AC_ER_VCB11 ) {
|
||||
sect_cb = (UCHAR) FDKreadBits(bs,5);
|
||||
}
|
||||
else
|
||||
sect_cb = (UCHAR) FDKreadBits(bs,4);
|
||||
|
||||
if ( ((flags & AC_ER_VCB11) == 0) || ( sect_cb < 11 ) || ((sect_cb > 11) && (sect_cb < 16)) ) {
|
||||
sect_len_incr = FDKreadBits(bs, nbits);
|
||||
while (sect_len_incr == sect_esc_val)
|
||||
{
|
||||
sect_len += sect_esc_val;
|
||||
sect_len_incr = FDKreadBits(bs, nbits);
|
||||
}
|
||||
}
|
||||
else {
|
||||
sect_len_incr = 1;
|
||||
}
|
||||
|
||||
sect_len += sect_len_incr;
|
||||
|
||||
|
||||
top = band + sect_len;
|
||||
|
||||
if (flags & AC_ER_HCR) {
|
||||
/* HCR input (long) -- collecting sideinfo (for HCR-_long_ only) */
|
||||
pNumLinesInSec[numLinesInSecIdx] = BandOffsets[top] - BandOffsets[band];
|
||||
numLinesInSecIdx++;
|
||||
if (numLinesInSecIdx >= MAX_SFB_HCR) {
|
||||
return AAC_DEC_PARSE_ERROR;
|
||||
}
|
||||
if (
|
||||
(sect_cb == BOOKSCL) )
|
||||
{
|
||||
return AAC_DEC_INVALID_CODE_BOOK;
|
||||
} else {
|
||||
*pHcrCodeBook++ = sect_cb;
|
||||
}
|
||||
pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection++;
|
||||
}
|
||||
|
||||
/* Check spectral line limits */
|
||||
if (IsLongBlock( &(pAacDecoderChannelInfo->icsInfo) ))
|
||||
{
|
||||
if (top > 64) {
|
||||
return AAC_DEC_DECODE_FRAME_ERROR;
|
||||
}
|
||||
} else { /* short block */
|
||||
if (top + group*16 > (8 * 16)) {
|
||||
return AAC_DEC_DECODE_FRAME_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if decoded codebook index is feasible */
|
||||
if ( (sect_cb == BOOKSCL)
|
||||
|| ( (sect_cb == INTENSITY_HCB || sect_cb == INTENSITY_HCB2) && pAacDecoderChannelInfo->pDynData->RawDataInfo.CommonWindow == 0)
|
||||
)
|
||||
{
|
||||
return AAC_DEC_INVALID_CODE_BOOK;
|
||||
}
|
||||
|
||||
/* Store codebook index */
|
||||
for (; band < top; band++)
|
||||
{
|
||||
pCodeBook[group*16+band] = sect_cb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ErrorStatus;
|
||||
}
|
||||
|
||||
/* mso: provides a faster way to i-quantize a whole band in one go */
|
||||
|
||||
/**
|
||||
* \brief inverse quantize one sfb. Each value of the sfb is processed according to the
|
||||
* formula: spectrum[i] = Sign(spectrum[i]) * Matissa(spectrum[i])^(4/3) * 2^(lsb/4).
|
||||
* \param spectrum pointer to first line of the sfb to be inverse quantized.
|
||||
* \param noLines number of lines belonging to the sfb.
|
||||
* \param lsb last 2 bits of the scale factor of the sfb.
|
||||
* \param scale max allowed shift scale for the sfb.
|
||||
*/
|
||||
static
|
||||
void InverseQuantizeBand( FIXP_DBL * RESTRICT spectrum,
|
||||
INT noLines,
|
||||
INT lsb,
|
||||
INT scale )
|
||||
{
|
||||
const FIXP_DBL * RESTRICT InverseQuantTabler=(FIXP_DBL *)InverseQuantTable;
|
||||
const FIXP_DBL * RESTRICT MantissaTabler=(FIXP_DBL *)MantissaTable[lsb];
|
||||
const SCHAR* RESTRICT ExponentTabler=(SCHAR*)ExponentTable[lsb];
|
||||
|
||||
FIXP_DBL *ptr = spectrum;
|
||||
FIXP_DBL signedValue;
|
||||
|
||||
FDK_ASSERT(noLines>2);
|
||||
for (INT i=noLines; i--; )
|
||||
{
|
||||
if ((signedValue = *ptr++) != FL2FXCONST_DBL(0))
|
||||
{
|
||||
FIXP_DBL value = fAbs(signedValue);
|
||||
UINT freeBits = CntLeadingZeros(value);
|
||||
UINT exponent = 32 - freeBits;
|
||||
|
||||
UINT x = (UINT) (LONG)value << (INT) freeBits;
|
||||
x <<= 1; /* shift out sign bit to avoid masking later on */
|
||||
UINT tableIndex = x >> 24;
|
||||
x = (x >> 20) & 0x0F;
|
||||
|
||||
UINT r0=(UINT)(LONG)InverseQuantTabler[tableIndex+0];
|
||||
UINT r1=(UINT)(LONG)InverseQuantTabler[tableIndex+1];
|
||||
UINT temp= (r1 - r0)*x + (r0 << 4);
|
||||
|
||||
value = fMultDiv2((FIXP_DBL)temp, MantissaTabler[exponent]);
|
||||
|
||||
/* + 1 compensates fMultDiv2() */
|
||||
scaleValueInPlace(&value, scale + ExponentTabler[exponent] + 1);
|
||||
|
||||
signedValue = (signedValue < (FIXP_DBL)0) ? -value : value;
|
||||
ptr[-1] = signedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AAC_DECODER_ERROR CBlock_InverseQuantizeSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo, SamplingRateInfo *pSamplingRateInfo)
|
||||
{
|
||||
int window, group, groupwin, band;
|
||||
int ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
|
||||
UCHAR *RESTRICT pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook;
|
||||
SHORT *RESTRICT pSfbScale = pAacDecoderChannelInfo->pDynData->aSfbScale;
|
||||
SHORT *RESTRICT pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor;
|
||||
const SHORT *RESTRICT BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo);
|
||||
|
||||
FDKmemclear(pAacDecoderChannelInfo->pDynData->aSfbScale, (8*16)*sizeof(SHORT));
|
||||
|
||||
for (window=0, group=0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++)
|
||||
{
|
||||
for (groupwin=0; groupwin < GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); groupwin++, window++)
|
||||
{
|
||||
/* inverse quantization */
|
||||
for (band=0; band < ScaleFactorBandsTransmitted; band++)
|
||||
{
|
||||
FIXP_DBL *pSpectralCoefficient = SPEC(pAacDecoderChannelInfo->pSpectralCoefficient, window, pAacDecoderChannelInfo->granuleLength) + BandOffsets[band];
|
||||
|
||||
int noLines = BandOffsets[band+1] - BandOffsets[band];
|
||||
int bnds = group*16+band;
|
||||
int i;
|
||||
|
||||
if ((pCodeBook[bnds] == ZERO_HCB)
|
||||
|| (pCodeBook[bnds] == INTENSITY_HCB)
|
||||
|| (pCodeBook[bnds] == INTENSITY_HCB2)
|
||||
)
|
||||
continue;
|
||||
|
||||
if (pCodeBook[bnds] == NOISE_HCB)
|
||||
{
|
||||
/* Leave headroom for PNS values. + 1 because ceil(log2(2^(0.25*3))) = 1,
|
||||
worst case of additional headroom required because of the scalefactor. */
|
||||
pSfbScale[window*16+band] = (pScaleFactor [bnds] >> 2) + 1 ;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find max spectral line value of the current sfb */
|
||||
FIXP_DBL locMax = (FIXP_DBL)0;
|
||||
|
||||
for (i = noLines; i-- ; ) {
|
||||
/* Expensive memory access */
|
||||
locMax = fMax(fixp_abs(pSpectralCoefficient[i]), locMax);
|
||||
}
|
||||
|
||||
/* Cheap robustness improvement - Do not remove!!! */
|
||||
if (fixp_abs(locMax) > (FIXP_DBL)MAX_QUANTIZED_VALUE) {
|
||||
return AAC_DEC_DECODE_FRAME_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
The inverse quantized spectral lines are defined by:
|
||||
pSpectralCoefficient[i] = Sign(pSpectralCoefficient[i]) * 2^(0.25*pScaleFactor[bnds]) * pSpectralCoefficient[i]^(4/3)
|
||||
This is equivalent to:
|
||||
pSpectralCoefficient[i] = Sign(pSpectralCoefficient[i]) * (2^(pScaleFactor[bnds] % 4) * pSpectralCoefficient[i]^(4/3))
|
||||
pSpectralCoefficient_e[i] += pScaleFactor[bnds]/4
|
||||
*/
|
||||
{
|
||||
int msb = pScaleFactor [bnds] >> 2 ;
|
||||
int lsb = pScaleFactor [bnds] & 0x03 ;
|
||||
|
||||
int scale = GetScaleFromValue(locMax, lsb);
|
||||
|
||||
pSfbScale[window*16+band] = msb - scale;
|
||||
InverseQuantizeBand(pSpectralCoefficient, noLines, lsb, scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return AAC_DEC_OK;
|
||||
}
|
||||
|
||||
|
||||
AAC_DECODER_ERROR CBlock_ReadSpectralData(HANDLE_FDK_BITSTREAM bs,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
const SamplingRateInfo *pSamplingRateInfo,
|
||||
const UINT flags)
|
||||
{
|
||||
int i,index;
|
||||
int window,group,groupwin,groupoffset,band;
|
||||
UCHAR *RESTRICT pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook;
|
||||
const SHORT *RESTRICT BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo);
|
||||
|
||||
SPECTRAL_PTR pSpectralCoefficient = pAacDecoderChannelInfo->pSpectralCoefficient;
|
||||
FIXP_DBL locMax;
|
||||
|
||||
int ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
|
||||
|
||||
FDK_ASSERT(BandOffsets != NULL);
|
||||
|
||||
FDKmemclear(pSpectralCoefficient, sizeof(SPECTRUM));
|
||||
|
||||
if ( (flags & AC_ER_HCR) == 0 )
|
||||
{
|
||||
groupoffset = 0;
|
||||
|
||||
/* plain huffman decoder short */
|
||||
for (group=0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++)
|
||||
{
|
||||
for (band=0; band < ScaleFactorBandsTransmitted; band++)
|
||||
{
|
||||
int bnds = group*16+band;
|
||||
UCHAR currentCB = pCodeBook[bnds];
|
||||
|
||||
/* patch to run plain-huffman-decoder with vcb11 input codebooks (LAV-checking might be possible below using the virtual cb and a LAV-table) */
|
||||
if ((currentCB >= 16) && (currentCB <= 31)) {
|
||||
pCodeBook[bnds] = currentCB = 11;
|
||||
}
|
||||
if ( !((currentCB == ZERO_HCB)
|
||||
|| (currentCB == NOISE_HCB)
|
||||
|| (currentCB == INTENSITY_HCB)
|
||||
|| (currentCB == INTENSITY_HCB2)) )
|
||||
{
|
||||
const CodeBookDescription *hcb = &AACcodeBookDescriptionTable[currentCB];
|
||||
int step = hcb->Dimension;
|
||||
int offset = hcb->Offset;
|
||||
int bits = hcb->numBits;
|
||||
int mask = (1<<bits)-1;
|
||||
|
||||
for (groupwin=0; groupwin < GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); groupwin++)
|
||||
{
|
||||
window = groupoffset + groupwin;
|
||||
|
||||
FIXP_DBL *mdctSpectrum = SPEC(pSpectralCoefficient, window, pAacDecoderChannelInfo->granuleLength);
|
||||
|
||||
locMax = (FIXP_DBL)0 ;
|
||||
|
||||
for (index=BandOffsets[band]; index < BandOffsets[band+1]; index+=step)
|
||||
{
|
||||
int idx = CBlock_DecodeHuffmanWord(bs,hcb);
|
||||
|
||||
for (i=0; i<step; i++) {
|
||||
FIXP_DBL tmp;
|
||||
|
||||
tmp = (FIXP_DBL)((idx & mask)-offset);
|
||||
idx >>= bits;
|
||||
|
||||
if (offset == 0) {
|
||||
if (tmp != FIXP_DBL(0))
|
||||
tmp = (FDKreadBits(bs,1))? -tmp : tmp;
|
||||
}
|
||||
mdctSpectrum[index+i] = tmp;
|
||||
}
|
||||
|
||||
if (currentCB == ESCBOOK)
|
||||
{
|
||||
mdctSpectrum[index+0] = (FIXP_DBL)CBlock_GetEscape(bs, (LONG)mdctSpectrum[index+0]);
|
||||
mdctSpectrum[index+1] = (FIXP_DBL)CBlock_GetEscape(bs, (LONG)mdctSpectrum[index+1]);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
groupoffset += GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group);
|
||||
}
|
||||
/* plain huffman decoding (short) finished */
|
||||
}
|
||||
/* HCR - Huffman Codeword Reordering short */
|
||||
else /* if ( flags & AC_ER_HCR ) */
|
||||
{
|
||||
H_HCR_INFO hHcr = &pAacDecoderChannelInfo->pComData->overlay.aac.erHcrInfo;
|
||||
int hcrStatus = 0;
|
||||
int hcrConcealWholeFrame = 0;
|
||||
|
||||
/* advanced Huffman decoding starts here (HCR decoding :) */
|
||||
if ( pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData != 0 ) {
|
||||
|
||||
/* HCR initialization short */
|
||||
hcrStatus = HcrInit(hHcr, pAacDecoderChannelInfo, pSamplingRateInfo, bs);
|
||||
|
||||
if (hcrStatus != 0) {
|
||||
#if HCR_ERROR_CONCEALMENT
|
||||
hcrConcealWholeFrame = 1;
|
||||
return AAC_DEC_DECODE_FRAME_ERROR; /* concealment is muting in the first step, therefore return now */
|
||||
// hcr decoding is not skipped because of returning above
|
||||
#else
|
||||
return AAC_DEC_DECODE_FRAME_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* HCR decoding short */
|
||||
hcrStatus = HcrDecoder(hHcr, pAacDecoderChannelInfo, pSamplingRateInfo, bs);
|
||||
|
||||
|
||||
#if HCR_ERROR_CONCEALMENT
|
||||
HcrMuteErroneousLines(hHcr);
|
||||
#else
|
||||
return AAC_DEC_DECODE_FRAME_ERROR;
|
||||
#endif /* HCR_ERROR_CONCEALMENT */
|
||||
|
||||
FDKpushFor (bs, pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData);
|
||||
}
|
||||
}
|
||||
/* HCR - Huffman Codeword Reordering short finished */
|
||||
|
||||
|
||||
|
||||
if ( IsLongBlock(&pAacDecoderChannelInfo->icsInfo) && !(flags & (AC_ELD|AC_SCALABLE)) )
|
||||
{
|
||||
/* apply pulse data */
|
||||
CPulseData_Apply(&pAacDecoderChannelInfo->pDynData->specificTo.aac.PulseData,
|
||||
GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo),
|
||||
SPEC_LONG(pSpectralCoefficient));
|
||||
}
|
||||
|
||||
|
||||
return AAC_DEC_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ApplyTools ( CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
|
||||
const SamplingRateInfo *pSamplingRateInfo,
|
||||
const UINT flags,
|
||||
const int channel )
|
||||
{
|
||||
|
||||
if ( !(flags & (AC_USAC|AC_RSVD50|AC_MPS_RES)) ) {
|
||||
CPns_Apply(
|
||||
&pAacDecoderChannelInfo[channel]->data.aac.PnsData,
|
||||
&pAacDecoderChannelInfo[channel]->icsInfo,
|
||||
pAacDecoderChannelInfo[channel]->pSpectralCoefficient,
|
||||
pAacDecoderChannelInfo[channel]->specScale,
|
||||
pAacDecoderChannelInfo[channel]->pDynData->aScaleFactor,
|
||||
pSamplingRateInfo,
|
||||
pAacDecoderChannelInfo[channel]->granuleLength,
|
||||
channel
|
||||
);
|
||||
}
|
||||
|
||||
CTns_Apply (
|
||||
&pAacDecoderChannelInfo[channel]->pDynData->TnsData,
|
||||
&pAacDecoderChannelInfo[channel]->icsInfo,
|
||||
pAacDecoderChannelInfo[channel]->pSpectralCoefficient,
|
||||
pSamplingRateInfo,
|
||||
pAacDecoderChannelInfo[channel]->granuleLength
|
||||
);
|
||||
}
|
||||
|
||||
static
|
||||
int getWindow2Nr(int length, int shape)
|
||||
{
|
||||
int nr = 0;
|
||||
|
||||
if (shape == 2) {
|
||||
/* Low Overlap, 3/4 zeroed */
|
||||
nr = (length * 3)>>2;
|
||||
}
|
||||
|
||||
return nr;
|
||||
}
|
||||
|
||||
void CBlock_FrequencyToTime(CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
INT_PCM outSamples[],
|
||||
const SHORT frameLen,
|
||||
const int stride,
|
||||
const int frameOk,
|
||||
FIXP_DBL *pWorkBuffer1 )
|
||||
{
|
||||
int fr, fl, tl, nSamples, nSpec;
|
||||
|
||||
/* Determine left slope length (fl), right slope length (fr) and transform length (tl).
|
||||
USAC: The slope length may mismatch with the previous frame in case of LPD / FD
|
||||
transitions. The adjustment is handled by the imdct implementation.
|
||||
*/
|
||||
tl = frameLen;
|
||||
nSpec = 1;
|
||||
|
||||
switch( pAacDecoderChannelInfo->icsInfo.WindowSequence ) {
|
||||
default:
|
||||
case OnlyLongSequence:
|
||||
fl = frameLen;
|
||||
fr = frameLen - getWindow2Nr(frameLen, GetWindowShape(&pAacDecoderChannelInfo->icsInfo));
|
||||
break;
|
||||
case LongStopSequence:
|
||||
fl = frameLen >> 3;
|
||||
fr = frameLen;
|
||||
break;
|
||||
case LongStartSequence: /* or StopStartSequence */
|
||||
fl = frameLen;
|
||||
fr = frameLen >> 3;
|
||||
break;
|
||||
case EightShortSequence:
|
||||
fl = fr = frameLen >> 3;
|
||||
tl >>= 3;
|
||||
nSpec = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
{
|
||||
FIXP_DBL *tmp = pAacDecoderChannelInfo->pComData->workBufferCore1->mdctOutTemp;
|
||||
|
||||
nSamples = imdct_block(
|
||||
&pAacDecoderStaticChannelInfo->IMdct,
|
||||
tmp,
|
||||
SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient),
|
||||
pAacDecoderChannelInfo->specScale,
|
||||
nSpec,
|
||||
frameLen,
|
||||
tl,
|
||||
FDKgetWindowSlope(fl, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)),
|
||||
fl,
|
||||
FDKgetWindowSlope(fr, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)),
|
||||
fr,
|
||||
(FIXP_DBL)0 );
|
||||
|
||||
for (i=0; i<frameLen; i++) {
|
||||
outSamples[i*stride] = IMDCT_SCALE(tmp[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FDK_ASSERT(nSamples == frameLen);
|
||||
|
||||
}
|
||||
|
||||
#include "ldfiltbank.h"
|
||||
void CBlock_FrequencyToTimeLowDelay( CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
INT_PCM outSamples[],
|
||||
const short frameLen,
|
||||
const char stride )
|
||||
{
|
||||
InvMdctTransformLowDelay_fdk (
|
||||
SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient),
|
||||
pAacDecoderChannelInfo->specScale[0],
|
||||
outSamples,
|
||||
pAacDecoderStaticChannelInfo->pOverlapBuffer,
|
||||
stride,
|
||||
frameLen
|
||||
);
|
||||
}
|
260
libAACdec/src/block.h
Normal file
260
libAACdec/src/block.h
Normal file
@ -0,0 +1,260 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description: long/short-block decoding
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef BLOCK_H
|
||||
#define BLOCK_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "channelinfo.h"
|
||||
#include "FDK_bitstream.h"
|
||||
|
||||
/* PNS (of block) */
|
||||
void CPns_Read (CPnsData *pPnsData,
|
||||
HANDLE_FDK_BITSTREAM bs,
|
||||
const CodeBookDescription *hcb,
|
||||
SHORT *pScaleFactor,
|
||||
UCHAR global_gain,
|
||||
int band,
|
||||
int group);
|
||||
|
||||
|
||||
void CPns_Apply (const CPnsData *pPnsData,
|
||||
const CIcsInfo *pIcsInfo,
|
||||
SPECTRAL_PTR pSpectrum,
|
||||
const SHORT *pSpecScale,
|
||||
const SHORT *pScaleFactor,
|
||||
const SamplingRateInfo *pSamplingRateInfo,
|
||||
const INT granuleLength,
|
||||
const int channel);
|
||||
|
||||
|
||||
|
||||
/* TNS (of block) */
|
||||
/*!
|
||||
\brief Read tns data-present flag from bitstream
|
||||
|
||||
The function reads the data-present flag for tns from
|
||||
the bitstream.
|
||||
|
||||
\return none
|
||||
*/
|
||||
void CTns_ReadDataPresentFlag(HANDLE_FDK_BITSTREAM bs,
|
||||
CTnsData *pTnsData);
|
||||
|
||||
void CTns_ReadDataPresentUsac(
|
||||
HANDLE_FDK_BITSTREAM hBs,
|
||||
CTnsData *pTnsData0,
|
||||
CTnsData *pTnsData1,
|
||||
const CIcsInfo *pIcsInfo,
|
||||
const UINT flags,
|
||||
const int fCommonWindow
|
||||
);
|
||||
|
||||
AAC_DECODER_ERROR CTns_Read(HANDLE_FDK_BITSTREAM bs,
|
||||
CTnsData *pTnsData,
|
||||
const CIcsInfo *pIcsInfo,
|
||||
const UINT flags);
|
||||
|
||||
void CTns_Apply ( CTnsData *RESTRICT pTnsData, /*!< pointer to aac decoder info */
|
||||
const CIcsInfo *pIcsInfo,
|
||||
SPECTRAL_PTR pSpectralCoefficient,
|
||||
const SamplingRateInfo *pSamplingRateInfo,
|
||||
const INT granuleLength);
|
||||
|
||||
/* Block */
|
||||
|
||||
LONG CBlock_GetEscape(HANDLE_FDK_BITSTREAM bs, const LONG q);
|
||||
|
||||
/**
|
||||
* \brief Read scale factor data. See chapter 4.6.2.3.2 of ISO/IEC 14496-3.
|
||||
* The SF_OFFSET = 100 value referenced in chapter 4.6.2.3.3 is already substracted
|
||||
* from the scale factor values. Also includes PNS data reading.
|
||||
* \param bs bit stream handle data source
|
||||
* \param pAacDecoderChannelInfo channel context info were decoded data is stored into.
|
||||
* \param flags the decoder flags.
|
||||
*/
|
||||
AAC_DECODER_ERROR CBlock_ReadScaleFactorData(
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
HANDLE_FDK_BITSTREAM bs,
|
||||
const UINT flags
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Read Huffman encoded spectral data.
|
||||
* \param pAacDecoderChannelInfo channel context info.
|
||||
* \param pSamplingRateInfo sampling rate info (sfb offsets).
|
||||
* \param flags syntax flags.
|
||||
*/
|
||||
AAC_DECODER_ERROR CBlock_ReadSpectralData(HANDLE_FDK_BITSTREAM bs,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
const SamplingRateInfo *pSamplingRateInfo,
|
||||
const UINT flags);
|
||||
|
||||
|
||||
AAC_DECODER_ERROR CBlock_ReadSectionData(HANDLE_FDK_BITSTREAM bs,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
const SamplingRateInfo *pSamplingRateInfo,
|
||||
const UINT flags);
|
||||
|
||||
/**
|
||||
* \brief find a common exponent (shift factor) for all sfb in each Spectral window, and store them into
|
||||
* CAacDecoderChannelInfo::specScale.
|
||||
* \param pAacDecoderChannelInfo channel context info.
|
||||
* \param pSamplingRateInfo sampling rate info (sfb offsets).
|
||||
*/
|
||||
void CBlock_ScaleSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo, SamplingRateInfo *pSamplingRateInfo);
|
||||
|
||||
/**
|
||||
* \brief Apply TNS and PNS tools.
|
||||
*/
|
||||
void ApplyTools ( CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
|
||||
const SamplingRateInfo *pSamplingRateInfo,
|
||||
const UINT flags,
|
||||
const int channel );
|
||||
|
||||
/**
|
||||
* \brief Transform MDCT spectral data into time domain
|
||||
*/
|
||||
void CBlock_FrequencyToTime(CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
INT_PCM outSamples[],
|
||||
const SHORT frameLen,
|
||||
const int stride,
|
||||
const int frameOk,
|
||||
FIXP_DBL *pWorkBuffer1);
|
||||
|
||||
/**
|
||||
* \brief Transform double lapped MDCT (AAC-ELD) spectral data into time domain.
|
||||
*/
|
||||
void CBlock_FrequencyToTimeLowDelay(CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
INT_PCM outSamples[],
|
||||
const short frameLen,
|
||||
const char stride);
|
||||
|
||||
AAC_DECODER_ERROR CBlock_InverseQuantizeSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo, SamplingRateInfo *pSamplingRateInfo);
|
||||
|
||||
/**
|
||||
* \brief Calculate 2^(lsb/4) * value^(4/3)
|
||||
* \param pValue pointer to quantized value. The inverse quantized result is stored back here.
|
||||
* \param lsb 2 LSBs of the scale factor (scaleFactor % 4) applied as power 2 factor to the
|
||||
* resulting inverse quantized value.
|
||||
* \return the exponent of the result (mantissa) stored into *pValue.
|
||||
*/
|
||||
FDK_INLINE
|
||||
int EvaluatePower43 ( FIXP_DBL *pValue,
|
||||
UINT lsb )
|
||||
{
|
||||
FIXP_DBL value;
|
||||
UINT freeBits;
|
||||
UINT exponent;
|
||||
|
||||
value = *pValue;
|
||||
freeBits = fNormz (value) ;
|
||||
exponent = DFRACT_BITS - freeBits ;
|
||||
FDK_ASSERT (exponent < 14);
|
||||
|
||||
UINT x = (((int)value << freeBits) >> 19) ;
|
||||
UINT tableIndex = (x & 0x0FFF) >> 4 ;
|
||||
FIXP_DBL invQVal ;
|
||||
|
||||
x = x & 0x0F;
|
||||
|
||||
UINT r0=(LONG)InverseQuantTable [tableIndex+0];
|
||||
UINT r1=(LONG)InverseQuantTable [tableIndex+1];
|
||||
USHORT nx=16-x;
|
||||
UINT temp=(r0)*nx+(r1)*x;
|
||||
invQVal = (FIXP_DBL)temp;
|
||||
|
||||
FDK_ASSERT(lsb < 4);
|
||||
*pValue = fMultDiv2 (invQVal, MantissaTable [lsb][exponent]) ;
|
||||
|
||||
/* + 1 compensates fMultDiv2(). */
|
||||
return ExponentTable [lsb][exponent] + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief determine the required shift scale for the given quantized value and scale (factor % 4) value.
|
||||
*/
|
||||
FDK_INLINE int GetScaleFromValue (FIXP_DBL value, unsigned int lsb)
|
||||
{
|
||||
if (value!=(FIXP_DBL)0)
|
||||
{
|
||||
int scale = EvaluatePower43 (&value, lsb) ;
|
||||
return CntLeadingZeros (value) - scale - 2 ;
|
||||
}
|
||||
else
|
||||
return 0; /* Return zero, because its useless to scale a zero value, saves workload and avoids scaling overshifts. */
|
||||
}
|
||||
|
||||
|
||||
//#ifdef AACDEC_HUFFMANDECODER_ENABLE
|
||||
|
||||
/*!
|
||||
\brief Read huffman codeword
|
||||
|
||||
The function reads the huffman codeword from the bitstream and
|
||||
returns the index value.
|
||||
|
||||
\return index value
|
||||
*/
|
||||
inline int CBlock_DecodeHuffmanWord( HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */
|
||||
const CodeBookDescription *hcb ) /*!< pointer to codebook description */
|
||||
{
|
||||
UINT val;
|
||||
UINT index = 0;
|
||||
const USHORT (*CodeBook) [HuffmanEntries] = hcb->CodeBook;
|
||||
|
||||
while (1)
|
||||
{
|
||||
val = CodeBook[index][FDKreadBits(bs,HuffmanBits)]; /* Expensive memory access */
|
||||
|
||||
if ((val & 1) == 0)
|
||||
{
|
||||
index = val>>2;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (val & 2)
|
||||
{
|
||||
FDKpushBackCache(bs,1);
|
||||
}
|
||||
|
||||
val >>= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
//#endif /* AACDEC_HUFFMANDECODER_ENABLE */
|
||||
|
||||
#endif /* #ifndef BLOCK_H */
|
389
libAACdec/src/channel.cpp
Normal file
389
libAACdec/src/channel.cpp
Normal file
@ -0,0 +1,389 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description:
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "channel.h"
|
||||
#include "aacdecoder.h"
|
||||
#include "block.h"
|
||||
#include "aacdec_tns.h"
|
||||
#include "FDK_bitstream.h"
|
||||
#include "FDK_tools_rom.h"
|
||||
|
||||
#include "conceal.h"
|
||||
|
||||
#include "rvlc.h"
|
||||
|
||||
#include "aacdec_hcr.h"
|
||||
|
||||
|
||||
static
|
||||
void MapMidSideMaskToPnsCorrelation (CAacDecoderChannelInfo *pAacDecoderChannelInfo[2])
|
||||
{
|
||||
int group;
|
||||
|
||||
for (group = 0 ; group < pAacDecoderChannelInfo[L]->icsInfo.WindowGroups; group++) {
|
||||
UCHAR groupMask = 1 << group;
|
||||
|
||||
for (UCHAR band = 0 ; band < pAacDecoderChannelInfo[L]->icsInfo.MaxSfBands; band++) {
|
||||
if (pAacDecoderChannelInfo[L]->pComData->jointStereoData.MsUsed[band] & groupMask) { /* channels are correlated */
|
||||
CPns_SetCorrelation(&pAacDecoderChannelInfo[L]->data.aac.PnsData, group, band, 0);
|
||||
|
||||
if (CPns_IsPnsUsed(&pAacDecoderChannelInfo[L]->data.aac.PnsData, group, band) &&
|
||||
CPns_IsPnsUsed(&pAacDecoderChannelInfo[R]->data.aac.PnsData, group, band))
|
||||
pAacDecoderChannelInfo[L]->pComData->jointStereoData.MsUsed[band] ^= groupMask; /* clear the groupMask-bit */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Decode channel pair element
|
||||
|
||||
The function decodes a channel pair element.
|
||||
|
||||
\return none
|
||||
*/
|
||||
void CChannelElement_Decode( CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], /*!< pointer to aac decoder channel info */
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2],
|
||||
SamplingRateInfo *pSamplingRateInfo,
|
||||
UINT flags,
|
||||
int el_channels)
|
||||
{
|
||||
int ch, maybe_jstereo = 0;
|
||||
|
||||
maybe_jstereo = (el_channels > 1);
|
||||
|
||||
for (ch = 0; ch < el_channels; ch++) {
|
||||
if ( pAacDecoderChannelInfo[ch]->renderMode == AACDEC_RENDER_IMDCT
|
||||
|| pAacDecoderChannelInfo[ch]->renderMode == AACDEC_RENDER_ELDFB )
|
||||
{
|
||||
CBlock_InverseQuantizeSpectralData(pAacDecoderChannelInfo[ch], pSamplingRateInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (maybe_jstereo) {
|
||||
/* apply ms */
|
||||
if (pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow) {
|
||||
int maxSfBandsL = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[L]->icsInfo);
|
||||
int maxSfBandsR = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[R]->icsInfo);
|
||||
if (pAacDecoderChannelInfo[L]->data.aac.PnsData.PnsActive || pAacDecoderChannelInfo[R]->data.aac.PnsData.PnsActive) {
|
||||
MapMidSideMaskToPnsCorrelation(pAacDecoderChannelInfo);
|
||||
}
|
||||
|
||||
CJointStereo_ApplyMS(pAacDecoderChannelInfo,
|
||||
GetScaleFactorBandOffsets(&pAacDecoderChannelInfo[L]->icsInfo, pSamplingRateInfo),
|
||||
GetWindowGroupLengthTable(&pAacDecoderChannelInfo[L]->icsInfo),
|
||||
GetWindowGroups(&pAacDecoderChannelInfo[L]->icsInfo),
|
||||
maxSfBandsL,
|
||||
maxSfBandsR);
|
||||
}
|
||||
|
||||
/* apply intensity stereo */ /* modifies pAacDecoderChannelInfo[]->aSpecSfb */
|
||||
CJointStereo_ApplyIS(pAacDecoderChannelInfo,
|
||||
GetScaleFactorBandOffsets(&pAacDecoderChannelInfo[L]->icsInfo, pSamplingRateInfo),
|
||||
GetWindowGroupLengthTable(&pAacDecoderChannelInfo[L]->icsInfo),
|
||||
GetWindowGroups(&pAacDecoderChannelInfo[L]->icsInfo),
|
||||
GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[L]->icsInfo),
|
||||
pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow ? 1 : 0);
|
||||
|
||||
}
|
||||
|
||||
for (ch = 0; ch < el_channels; ch++)
|
||||
{
|
||||
{
|
||||
/* write pAacDecoderChannelInfo[ch]->specScale */
|
||||
CBlock_ScaleSpectralData(pAacDecoderChannelInfo[ch], pSamplingRateInfo);
|
||||
|
||||
ApplyTools (pAacDecoderChannelInfo, pSamplingRateInfo, flags, ch);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CRvlc_ElementCheck(
|
||||
pAacDecoderChannelInfo,
|
||||
pAacDecoderStaticChannelInfo,
|
||||
flags,
|
||||
el_channels
|
||||
);
|
||||
}
|
||||
|
||||
void CChannel_CodebookTableInit(CAacDecoderChannelInfo *pAacDecoderChannelInfo)
|
||||
{
|
||||
int b, w, maxBands, maxWindows;
|
||||
int maxSfb = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo);
|
||||
UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook;
|
||||
|
||||
if ( IsLongBlock(&pAacDecoderChannelInfo->icsInfo) ) {
|
||||
maxBands = 64;
|
||||
maxWindows = 1;
|
||||
} else {
|
||||
maxBands = 16;
|
||||
maxWindows = 8;
|
||||
}
|
||||
|
||||
for (w = 0; w<maxWindows; w++) {
|
||||
for (b = 0; b < maxSfb; b++) {
|
||||
pCodeBook[b] = ESCBOOK;
|
||||
}
|
||||
for (; b<maxBands; b++) {
|
||||
pCodeBook[b] = ZERO_HCB;
|
||||
}
|
||||
pCodeBook += maxBands;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Arbitrary order bitstream parser
|
||||
*/
|
||||
|
||||
AAC_DECODER_ERROR CChannelElement_Read(HANDLE_FDK_BITSTREAM hBs,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
|
||||
const AUDIO_OBJECT_TYPE aot,
|
||||
const SamplingRateInfo *pSamplingRateInfo,
|
||||
const UINT flags,
|
||||
const UINT frame_length,
|
||||
const UCHAR numberOfChannels,
|
||||
const SCHAR epConfig,
|
||||
HANDLE_TRANSPORTDEC pTpDec
|
||||
)
|
||||
{
|
||||
AAC_DECODER_ERROR error = AAC_DEC_OK;
|
||||
const element_list_t *list;
|
||||
int i, ch, decision_bit;
|
||||
int crcReg1 = -1, crcReg2 = -1;
|
||||
|
||||
FDK_ASSERT( (numberOfChannels == 1) || (numberOfChannels == 2) );
|
||||
|
||||
/* Get channel element sequence table */
|
||||
list = getBitstreamElementList(aot, epConfig, numberOfChannels, 0);
|
||||
if (list == NULL) {
|
||||
error = AAC_DEC_UNSUPPORTED_FORMAT;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
CTns_Reset(&pAacDecoderChannelInfo[0]->pDynData->TnsData);
|
||||
if (numberOfChannels == 2) {
|
||||
CTns_Reset(&pAacDecoderChannelInfo[1]->pDynData->TnsData);
|
||||
}
|
||||
|
||||
if (flags & (AC_ELD|AC_SCALABLE)) {
|
||||
pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow = 1;
|
||||
if (numberOfChannels == 2) {
|
||||
pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow;
|
||||
}
|
||||
if (numberOfChannels == 2) {
|
||||
pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow;
|
||||
}
|
||||
}
|
||||
|
||||
/* Iterate through sequence table */
|
||||
i = 0;
|
||||
ch = 0;
|
||||
decision_bit = 0;
|
||||
do {
|
||||
switch (list->id[i]) {
|
||||
case element_instance_tag:
|
||||
pAacDecoderChannelInfo[0]->ElementInstanceTag = FDKreadBits(hBs, 4);
|
||||
if (numberOfChannels == 2) {
|
||||
pAacDecoderChannelInfo[1]->ElementInstanceTag = pAacDecoderChannelInfo[0]->ElementInstanceTag;
|
||||
}
|
||||
break;
|
||||
case common_window:
|
||||
decision_bit = pAacDecoderChannelInfo[ch]->pDynData->RawDataInfo.CommonWindow = FDKreadBits(hBs, 1);
|
||||
if (numberOfChannels == 2) {
|
||||
pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow;
|
||||
}
|
||||
break;
|
||||
case ics_info:
|
||||
/* Read individual channel info */
|
||||
error = IcsRead( hBs,
|
||||
&pAacDecoderChannelInfo[ch]->icsInfo,
|
||||
pSamplingRateInfo,
|
||||
flags );
|
||||
|
||||
if (numberOfChannels == 2 && pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow) {
|
||||
pAacDecoderChannelInfo[1]->icsInfo = pAacDecoderChannelInfo[0]->icsInfo;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ltp_data_present:
|
||||
if (FDKreadBits(hBs, 1) != 0) {
|
||||
error = AAC_DEC_UNSUPPORTED_PREDICTION;
|
||||
}
|
||||
break;
|
||||
|
||||
case ms:
|
||||
if ( CJointStereo_Read(
|
||||
hBs,
|
||||
&pAacDecoderChannelInfo[0]->pComData->jointStereoData,
|
||||
GetWindowGroups(&pAacDecoderChannelInfo[0]->icsInfo),
|
||||
GetScaleMaxFactorBandsTransmitted(&pAacDecoderChannelInfo[0]->icsInfo,
|
||||
&pAacDecoderChannelInfo[1]->icsInfo),
|
||||
flags) )
|
||||
{
|
||||
error = AAC_DEC_PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case global_gain:
|
||||
pAacDecoderChannelInfo[ch]->pDynData->RawDataInfo.GlobalGain = (UCHAR) FDKreadBits(hBs,8);
|
||||
break;
|
||||
|
||||
case section_data:
|
||||
error = CBlock_ReadSectionData( hBs,
|
||||
pAacDecoderChannelInfo[ch],
|
||||
pSamplingRateInfo,
|
||||
flags );
|
||||
break;
|
||||
|
||||
|
||||
case scale_factor_data:
|
||||
if (flags & AC_ER_RVLC) {
|
||||
/* read RVLC data from bitstream (error sens. cat. 1) */
|
||||
CRvlc_Read(pAacDecoderChannelInfo[ch], hBs);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = CBlock_ReadScaleFactorData(pAacDecoderChannelInfo[ch], hBs, flags);
|
||||
}
|
||||
break;
|
||||
|
||||
case pulse:
|
||||
if ( CPulseData_Read( hBs,
|
||||
&pAacDecoderChannelInfo[ch]->pDynData->specificTo.aac.PulseData,
|
||||
pSamplingRateInfo->ScaleFactorBands_Long, /* pulse data is only allowed to be present in long blocks! */
|
||||
(void*)&pAacDecoderChannelInfo[ch]->icsInfo,
|
||||
frame_length
|
||||
) != 0 )
|
||||
{
|
||||
error = AAC_DEC_DECODE_FRAME_ERROR;
|
||||
}
|
||||
break;
|
||||
case tns_data_present:
|
||||
CTns_ReadDataPresentFlag(hBs, &pAacDecoderChannelInfo[ch]->pDynData->TnsData);
|
||||
break;
|
||||
case tns_data:
|
||||
/* tns_data_present is checked inside CTns_Read(). */
|
||||
error = CTns_Read(hBs, &pAacDecoderChannelInfo[ch]->pDynData->TnsData, &pAacDecoderChannelInfo[ch]->icsInfo, flags);
|
||||
break;
|
||||
|
||||
case gain_control_data:
|
||||
break;
|
||||
|
||||
case gain_control_data_present:
|
||||
if (FDKreadBits(hBs, 1)) {
|
||||
error = AAC_DEC_UNSUPPORTED_GAIN_CONTROL_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
case esc2_rvlc:
|
||||
if (flags & AC_ER_RVLC) {
|
||||
CRvlc_Decode(
|
||||
pAacDecoderChannelInfo[ch],
|
||||
pAacDecoderStaticChannelInfo[ch],
|
||||
hBs
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case esc1_hcr:
|
||||
if (flags & AC_ER_HCR) {
|
||||
CHcr_Read(hBs, pAacDecoderChannelInfo[ch] );
|
||||
}
|
||||
break;
|
||||
|
||||
case spectral_data:
|
||||
error = CBlock_ReadSpectralData( hBs,
|
||||
pAacDecoderChannelInfo[ch],
|
||||
pSamplingRateInfo,
|
||||
flags );
|
||||
if (flags & AC_ELD) {
|
||||
pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_ELDFB;
|
||||
} else {
|
||||
pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_IMDCT;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
/* CRC handling */
|
||||
case adtscrc_start_reg1:
|
||||
if (pTpDec != NULL) {
|
||||
crcReg1 = transportDec_CrcStartReg(pTpDec, 192);
|
||||
}
|
||||
break;
|
||||
case adtscrc_start_reg2:
|
||||
if (pTpDec != NULL) {
|
||||
crcReg2 = transportDec_CrcStartReg(pTpDec, 128);
|
||||
}
|
||||
break;
|
||||
case adtscrc_end_reg1:
|
||||
case drmcrc_end_reg:
|
||||
if (pTpDec != NULL) {
|
||||
transportDec_CrcEndReg(pTpDec, crcReg1);
|
||||
}
|
||||
break;
|
||||
case adtscrc_end_reg2:
|
||||
if (pTpDec != NULL) {
|
||||
transportDec_CrcEndReg(pTpDec, crcReg2);
|
||||
}
|
||||
break;
|
||||
case drmcrc_start_reg:
|
||||
if (pTpDec != NULL) {
|
||||
crcReg1 = transportDec_CrcStartReg(pTpDec, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Non data cases */
|
||||
case next_channel:
|
||||
ch = (ch + 1) % numberOfChannels;
|
||||
break;
|
||||
case link_sequence:
|
||||
list = list->next[decision_bit];
|
||||
i=-1;
|
||||
break;
|
||||
|
||||
default:
|
||||
error = AAC_DEC_UNSUPPORTED_FORMAT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (error != AAC_DEC_OK) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
} while (list->id[i] != end_of_sequence);
|
||||
|
||||
bail:
|
||||
return error;
|
||||
}
|
86
libAACdec/src/channel.h
Normal file
86
libAACdec/src/channel.h
Normal file
@ -0,0 +1,86 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description:
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef CHANNEL_H
|
||||
#define CHANNEL_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "FDK_bitstream.h"
|
||||
#include "channelinfo.h"
|
||||
#include "tpdec_lib.h"
|
||||
|
||||
/**
|
||||
* \brief Init codeBook SFB indices (section data) with HCB_ESC. Useful for bitstreams
|
||||
* which do not have any section data, but still SFB's (scale factor bands). This has
|
||||
* the effect that upto the amount of transmitted SFB are treated as non-zero.
|
||||
* \param pAacDecoderChannelInfo channel info structure containing a valid icsInfo struct.
|
||||
*/
|
||||
void CChannel_CodebookTableInit(CAacDecoderChannelInfo *pAacDecoderChannelInfo);
|
||||
|
||||
/**
|
||||
* \brief decode a channel element. To be called after CChannelElement_Read()
|
||||
* \param pAacDecoderChannelInfo pointer to channel data struct. Depending on el_channels either one or two.
|
||||
* \param pSamplingRateInfo pointer to sample rate information structure
|
||||
* \param el_channels amount of channels of the element to be decoded.
|
||||
* \param output pointer to time domain output buffer (ACELP)
|
||||
* \param stride factor for accessing output
|
||||
*/
|
||||
void CChannelElement_Decode ( CAacDecoderChannelInfo *pAacDecoderChannelInfo[2],
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2],
|
||||
SamplingRateInfo *pSamplingRateInfo,
|
||||
UINT flags,
|
||||
int el_channels );
|
||||
|
||||
|
||||
/**
|
||||
* \brief Read channel element of given type from bitstream.
|
||||
* \param hBs bitstream handle to access bitstream data.
|
||||
* \param pAacDecoderChannelInfo pointer array to store channel information.
|
||||
* \param aot Audio Object Type
|
||||
* \param pSamplingRateInfo sampling rate info table.
|
||||
* \param flags parser guidance flags
|
||||
* \param numberOfChannels amoun of channels contained in the object to be parsed.
|
||||
* \param epConfig the current epConfig value obtained from the Audio Specific Config.
|
||||
* \param pTp transport decoder handle required for ADTS CRC checking.
|
||||
* ...
|
||||
* \return an AAC_DECODER_ERROR error code.
|
||||
*/
|
||||
AAC_DECODER_ERROR CChannelElement_Read(HANDLE_FDK_BITSTREAM hBs,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
|
||||
const AUDIO_OBJECT_TYPE aot,
|
||||
const SamplingRateInfo *pSamplingRateInfo,
|
||||
const UINT flags,
|
||||
const UINT frame_length,
|
||||
const UCHAR numberOfChannels,
|
||||
const SCHAR epConfig,
|
||||
HANDLE_TRANSPORTDEC pTpDec
|
||||
);
|
||||
|
||||
#endif /* #ifndef CHANNEL_H */
|
214
libAACdec/src/channelinfo.cpp
Normal file
214
libAACdec/src/channelinfo.cpp
Normal file
@ -0,0 +1,214 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description: individual channel stream info
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "channelinfo.h"
|
||||
#include "aac_rom.h"
|
||||
#include "aac_ram.h"
|
||||
#include "FDK_bitstream.h"
|
||||
|
||||
|
||||
AAC_DECODER_ERROR IcsReadMaxSfb (
|
||||
HANDLE_FDK_BITSTREAM bs,
|
||||
CIcsInfo *pIcsInfo,
|
||||
const SamplingRateInfo *pSamplingRateInfo
|
||||
)
|
||||
{
|
||||
AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
|
||||
int nbits;
|
||||
|
||||
if (IsLongBlock(pIcsInfo)) {
|
||||
nbits = 6;
|
||||
pIcsInfo->TotalSfBands = pSamplingRateInfo->NumberOfScaleFactorBands_Long;
|
||||
} else {
|
||||
nbits = 4;
|
||||
pIcsInfo->TotalSfBands = pSamplingRateInfo->NumberOfScaleFactorBands_Short;
|
||||
}
|
||||
pIcsInfo->MaxSfBands = (UCHAR) FDKreadBits(bs, nbits);
|
||||
|
||||
if (pIcsInfo->MaxSfBands > pIcsInfo->TotalSfBands){
|
||||
ErrorStatus = AAC_DEC_PARSE_ERROR;
|
||||
}
|
||||
|
||||
return ErrorStatus;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AAC_DECODER_ERROR IcsRead(HANDLE_FDK_BITSTREAM bs,
|
||||
CIcsInfo *pIcsInfo,
|
||||
const SamplingRateInfo* pSamplingRateInfo,
|
||||
const UINT flags)
|
||||
{
|
||||
AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK;
|
||||
|
||||
pIcsInfo->Valid = 0;
|
||||
|
||||
if (flags & AC_ELD){
|
||||
pIcsInfo->WindowSequence = OnlyLongSequence;
|
||||
pIcsInfo->WindowShape = 0;
|
||||
}
|
||||
else {
|
||||
if ( !(flags & (AC_USAC|AC_RSVD50)) ) {
|
||||
FDKreadBits(bs,1);
|
||||
}
|
||||
pIcsInfo->WindowSequence = (UCHAR) FDKreadBits(bs,2);
|
||||
pIcsInfo->WindowShape = (UCHAR) FDKreadBits(bs,1);
|
||||
if (flags & AC_LD) {
|
||||
if (pIcsInfo->WindowShape) {
|
||||
pIcsInfo->WindowShape = 2; /* select low overlap instead of KBD */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
if ( (flags & (AC_ELD|AC_LD)) && pIcsInfo->WindowSequence != OnlyLongSequence) {
|
||||
pIcsInfo->WindowSequence = OnlyLongSequence;
|
||||
ErrorStatus = AAC_DEC_PARSE_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
ErrorStatus = IcsReadMaxSfb(bs, pIcsInfo, pSamplingRateInfo);
|
||||
if (ErrorStatus != AAC_DEC_OK) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (IsLongBlock(pIcsInfo))
|
||||
{
|
||||
if ( !(flags & (AC_ELD|AC_SCALABLE|AC_BSAC|AC_USAC|AC_RSVD50)) ) /* If not ELD nor Scalable nor BSAC nor USAC syntax then ... */
|
||||
{
|
||||
if ((UCHAR)FDKreadBits(bs,1) != 0 ) /* UCHAR PredictorDataPresent */
|
||||
{
|
||||
ErrorStatus = AAC_DEC_UNSUPPORTED_PREDICTION;
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
pIcsInfo->WindowGroups = 1;
|
||||
pIcsInfo->WindowGroupLength[0] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
INT i;
|
||||
UINT mask;
|
||||
|
||||
pIcsInfo->ScaleFactorGrouping = (UCHAR) FDKreadBits(bs,7);
|
||||
|
||||
pIcsInfo->WindowGroups = 0 ;
|
||||
|
||||
for (i=0; i < (8-1); i++)
|
||||
{
|
||||
mask = 1 << (6 - i);
|
||||
pIcsInfo->WindowGroupLength[i] = 1;
|
||||
|
||||
if (pIcsInfo->ScaleFactorGrouping & mask)
|
||||
{
|
||||
pIcsInfo->WindowGroupLength[pIcsInfo->WindowGroups]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
pIcsInfo->WindowGroups++;
|
||||
}
|
||||
}
|
||||
|
||||
/* loop runs to i < 7 only */
|
||||
pIcsInfo->WindowGroupLength[8-1] = 1;
|
||||
pIcsInfo->WindowGroups++;
|
||||
}
|
||||
|
||||
|
||||
bail:
|
||||
if (ErrorStatus == AAC_DEC_OK)
|
||||
pIcsInfo->Valid = 1;
|
||||
|
||||
return ErrorStatus;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
interleave codebooks the following way
|
||||
|
||||
9 (84w) | 1 (51w)
|
||||
10 (82w) | 2 (39w)
|
||||
SCL (65w) | 4 (38w)
|
||||
3 (39w) | 5 (41w)
|
||||
| 6 (40w)
|
||||
| 7 (31w)
|
||||
| 8 (31w)
|
||||
(270w) (271w)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Table entries are sorted as following:
|
||||
| num_swb_long_window | sfbands_long | num_swb_short_window | sfbands_short |
|
||||
*/
|
||||
AAC_DECODER_ERROR getSamplingRateInfo(
|
||||
SamplingRateInfo *t,
|
||||
UINT samplesPerFrame,
|
||||
UINT samplingRateIndex,
|
||||
UINT samplingRate
|
||||
)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
|
||||
t->samplingRateIndex = samplingRateIndex;
|
||||
t->samplingRate = samplingRate;
|
||||
|
||||
switch (samplesPerFrame) {
|
||||
case 1024:
|
||||
index = 0;
|
||||
break;
|
||||
case 960:
|
||||
index = 1;
|
||||
break;
|
||||
case 512:
|
||||
index = 3;
|
||||
break;
|
||||
case 480:
|
||||
index = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
return AAC_DEC_UNSUPPORTED_FORMAT;
|
||||
}
|
||||
|
||||
t->ScaleFactorBands_Long = sfbOffsetTables[index][samplingRateIndex].sfbOffsetLong;
|
||||
t->ScaleFactorBands_Short = sfbOffsetTables[index][samplingRateIndex].sfbOffsetShort;
|
||||
t->NumberOfScaleFactorBands_Long = sfbOffsetTables[index][samplingRateIndex].numberOfSfbLong;
|
||||
t->NumberOfScaleFactorBands_Short = sfbOffsetTables[index][samplingRateIndex].numberOfSfbShort;
|
||||
|
||||
if (t->ScaleFactorBands_Long == NULL || t->NumberOfScaleFactorBands_Long == 0) {
|
||||
return AAC_DEC_UNSUPPORTED_FORMAT;
|
||||
}
|
||||
|
||||
FDK_ASSERT(t->ScaleFactorBands_Long[t->NumberOfScaleFactorBands_Long] == samplesPerFrame);
|
||||
FDK_ASSERT(t->ScaleFactorBands_Short == NULL || t->ScaleFactorBands_Short[t->NumberOfScaleFactorBands_Short]*8 == samplesPerFrame);
|
||||
|
||||
return AAC_DEC_OK;
|
||||
}
|
388
libAACdec/src/channelinfo.h
Normal file
388
libAACdec/src/channelinfo.h
Normal file
@ -0,0 +1,388 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description: individual channel stream info
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef CHANNELINFO_H
|
||||
#define CHANNELINFO_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "aac_rom.h"
|
||||
#include "aacdecoder_lib.h"
|
||||
#include "FDK_bitstream.h"
|
||||
#include "overlapadd.h"
|
||||
|
||||
#include "mdct.h"
|
||||
#include "stereo.h"
|
||||
#include "pulsedata.h"
|
||||
#include "aacdec_tns.h"
|
||||
|
||||
#include "aacdec_pns.h"
|
||||
|
||||
#include "aacdec_hcr_types.h"
|
||||
#include "rvlc_info.h"
|
||||
|
||||
|
||||
#include "conceal_types.h"
|
||||
|
||||
#include "aacdec_drc_types.h"
|
||||
|
||||
/* Output rendering mode */
|
||||
typedef enum {
|
||||
AACDEC_RENDER_INVALID = 0,
|
||||
AACDEC_RENDER_IMDCT,
|
||||
AACDEC_RENDER_ELDFB,
|
||||
AACDEC_RENDER_LPD,
|
||||
AACDEC_RENDER_INTIMDCT
|
||||
} AACDEC_RENDER_MODE;
|
||||
|
||||
enum {
|
||||
MAX_QUANTIZED_VALUE = 8191
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
OnlyLongSequence = 0,
|
||||
LongStartSequence,
|
||||
EightShortSequence,
|
||||
LongStopSequence
|
||||
};
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const SHORT *ScaleFactorBands_Long;
|
||||
const SHORT *ScaleFactorBands_Short;
|
||||
UCHAR NumberOfScaleFactorBands_Long;
|
||||
UCHAR NumberOfScaleFactorBands_Short;
|
||||
UINT samplingRateIndex;
|
||||
UINT samplingRate;
|
||||
} SamplingRateInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UCHAR CommonWindow;
|
||||
UCHAR GlobalGain;
|
||||
|
||||
} CRawDataInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UCHAR WindowGroupLength[8];
|
||||
UCHAR WindowGroups;
|
||||
UCHAR Valid;
|
||||
|
||||
UCHAR WindowShape; /* 0: sine window, 1: KBD, 2: low overlap */
|
||||
UCHAR WindowSequence; /* See enum above, 0: long, 1: start, 2: short, 3: stop */
|
||||
UCHAR MaxSfBands;
|
||||
UCHAR ScaleFactorGrouping;
|
||||
|
||||
UCHAR TotalSfBands;
|
||||
|
||||
} CIcsInfo;
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
ZERO_HCB = 0,
|
||||
ESCBOOK = 11,
|
||||
NSPECBOOKS = ESCBOOK + 1,
|
||||
BOOKSCL = NSPECBOOKS,
|
||||
NOISE_HCB = 13,
|
||||
INTENSITY_HCB2 = 14,
|
||||
INTENSITY_HCB = 15,
|
||||
LAST_HCB
|
||||
};
|
||||
|
||||
#define TNS_SCALE 3
|
||||
|
||||
/*
|
||||
* This struct must be allocated one for every channel and must be persistent.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
FIXP_DBL *pOverlapBuffer;
|
||||
mdct_t IMdct;
|
||||
|
||||
|
||||
|
||||
CDrcChannelData drcData;
|
||||
CConcealmentInfo concealmentInfo;
|
||||
|
||||
} CAacDecoderStaticChannelInfo;
|
||||
|
||||
|
||||
/*
|
||||
* This union must be allocated for every element (up to 2 channels).
|
||||
*/
|
||||
typedef struct {
|
||||
|
||||
/* Common bit stream data */
|
||||
SHORT aScaleFactor[(8*16)]; /* Spectral scale factors for each sfb in each window. */
|
||||
SHORT aSfbScale[(8*16)]; /* could be free after ApplyTools() */
|
||||
UCHAR aCodeBook[(8*16)]; /* section data: codebook for each window and sfb. */
|
||||
CTnsData TnsData;
|
||||
CRawDataInfo RawDataInfo;
|
||||
|
||||
shouldBeUnion {
|
||||
|
||||
struct {
|
||||
CPulseData PulseData;
|
||||
SHORT aNumLineInSec4Hcr[MAX_SFB_HCR]; /* needed once for all channels except for Drm syntax */
|
||||
UCHAR aCodeBooks4Hcr[MAX_SFB_HCR]; /* needed once for all channels except for Drm syntax. Same as "aCodeBook" ? */
|
||||
SHORT lenOfReorderedSpectralData;
|
||||
SCHAR lenOfLongestCodeword;
|
||||
SCHAR numberSection;
|
||||
SCHAR rvlcCurrentScaleFactorOK;
|
||||
SCHAR rvlcIntensityUsed;
|
||||
} aac;
|
||||
} specificTo;
|
||||
|
||||
} CAacDecoderDynamicData;
|
||||
|
||||
typedef shouldBeUnion {
|
||||
CAacDecoderDynamicData pAacDecoderDynamicData[2];
|
||||
|
||||
/* Common signal data, can be used once the bit stream data from above is not used anymore. */
|
||||
FIXP_DBL mdctOutTemp[1024];
|
||||
FIXP_DBL sbrWorkBuffer[1024*2];
|
||||
|
||||
} CWorkBufferCore1;
|
||||
|
||||
/* Common data referenced by all channels */
|
||||
typedef struct {
|
||||
|
||||
CWorkBufferCore1 *workBufferCore1;
|
||||
FIXP_DBL* workBufferCore2;
|
||||
|
||||
CPnsInterChannelData pnsInterChannelData;
|
||||
INT pnsCurrentSeed;
|
||||
INT pnsRandomSeed[(8*16)];
|
||||
|
||||
CJointStereoData jointStereoData; /* One for one element */
|
||||
|
||||
shouldBeUnion {
|
||||
struct {
|
||||
CErHcrInfo erHcrInfo;
|
||||
CErRvlcInfo erRvlcInfo;
|
||||
SHORT aRvlcScfEsc[RVLC_MAX_SFB]; /* needed once for all channels */
|
||||
SHORT aRvlcScfFwd[RVLC_MAX_SFB]; /* needed once for all channels */
|
||||
SHORT aRvlcScfBwd[RVLC_MAX_SFB]; /* needed once for all channels */
|
||||
} aac;
|
||||
|
||||
} overlay;
|
||||
|
||||
} CAacDecoderCommonData;
|
||||
|
||||
|
||||
/*
|
||||
* This struct must be allocated one for every channels of every element and must be persistent.
|
||||
* Among its members, the following memory areas can be overwritten under the given conditions:
|
||||
* - pSpectralCoefficient The memory pointed to can be overwritten after time signal rendering.
|
||||
* - data can be overwritten after time signal rendering.
|
||||
* - pDynData memory pointed to can be overwritten after each CChannelElement_Decode() call.
|
||||
* - pComData->overlay memory pointed to can be overwritten after each CChannelElement_Decode() call..
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
SPECTRAL_PTR pSpectralCoefficient; /* Spectral coefficients of each window */
|
||||
SHORT specScale[8]; /* Scale shift values of each spectrum window */
|
||||
CIcsInfo icsInfo;
|
||||
INT granuleLength; /* Size of smallest spectrum piece */
|
||||
UCHAR ElementInstanceTag;
|
||||
|
||||
AACDEC_RENDER_MODE renderMode; /* Output signal rendering mode */
|
||||
|
||||
shouldBeUnion {
|
||||
struct {
|
||||
CPnsData PnsData; /* Not required for USAC */
|
||||
} aac;
|
||||
|
||||
struct {
|
||||
} usac;
|
||||
} data;
|
||||
|
||||
CAacDecoderDynamicData *pDynData; /* Data required for one element and discarded after decoding */
|
||||
CAacDecoderCommonData *pComData; /* Data required for one channel at a time during decode */
|
||||
|
||||
} CAacDecoderChannelInfo;
|
||||
|
||||
/* channelinfo.cpp */
|
||||
|
||||
AAC_DECODER_ERROR getSamplingRateInfo(SamplingRateInfo *t, UINT samplesPerFrame, UINT samplingRateIndex, UINT samplingRate);
|
||||
|
||||
/**
|
||||
* \brief Read max SFB from bit stream and assign TotalSfBands according
|
||||
* to the window sequence and sample rate.
|
||||
* \param hBs bit stream handle as data source
|
||||
* \param pIcsInfo IcsInfo structure to read the window sequence and store MaxSfBands and TotalSfBands
|
||||
* \param pSamplingRateInfo read only
|
||||
*/
|
||||
AAC_DECODER_ERROR IcsReadMaxSfb (
|
||||
HANDLE_FDK_BITSTREAM hBs,
|
||||
CIcsInfo *pIcsInfo,
|
||||
const SamplingRateInfo *pSamplingRateInfo
|
||||
);
|
||||
|
||||
AAC_DECODER_ERROR IcsRead(
|
||||
HANDLE_FDK_BITSTREAM bs,
|
||||
CIcsInfo *pIcsInfo,
|
||||
const SamplingRateInfo* SamplingRateInfoTable,
|
||||
const UINT flags
|
||||
);
|
||||
|
||||
/* stereo.cpp, only called from this file */
|
||||
|
||||
/*!
|
||||
\brief Applies MS stereo.
|
||||
|
||||
The function applies MS stereo.
|
||||
|
||||
\param pAacDecoderChannelInfo aac channel info.
|
||||
\param pScaleFactorBandOffsets pointer to scalefactor band offsets.
|
||||
\param pWindowGroupLength pointer to window group length array.
|
||||
\param windowGroups number of window groups.
|
||||
\param scaleFactorBandsTransmittedL number of transmitted scalefactor bands in left channel.
|
||||
\param scaleFactorBandsTransmittedR number of transmitted scalefactor bands in right channel.
|
||||
May differ from scaleFactorBandsTransmittedL only for USAC.
|
||||
\return none
|
||||
*/
|
||||
void CJointStereo_ApplyMS(CAacDecoderChannelInfo *pAacDecoderChannelInfo[2],
|
||||
const short *pScaleFactorBandOffsets,
|
||||
const UCHAR *pWindowGroupLength,
|
||||
const int windowGroups,
|
||||
const int scaleFactorBandsTransmittedL,
|
||||
const int scaleFactorBandsTransmittedR);
|
||||
|
||||
/*!
|
||||
\brief Applies intensity stereo
|
||||
|
||||
The function applies intensity stereo.
|
||||
|
||||
\param pAacDecoderChannelInfo aac channel info.
|
||||
\param pScaleFactorBandOffsets pointer to scalefactor band offsets.
|
||||
\param pWindowGroupLength pointer to window group length array.
|
||||
\param windowGroups number of window groups.
|
||||
\param scaleFactorBandsTransmitted number of transmitted scalefactor bands.
|
||||
\param CommonWindow common window bit.
|
||||
\return none
|
||||
*/
|
||||
void CJointStereo_ApplyIS(CAacDecoderChannelInfo *pAacDecoderChannelInfo[2],
|
||||
const short *pScaleFactorBandOffsets,
|
||||
const UCHAR *pWindowGroupLength,
|
||||
const int windowGroups,
|
||||
const int scaleFactorBandsTransmitted,
|
||||
const UINT CommonWindow);
|
||||
|
||||
|
||||
/* aacdec_pns.cpp */
|
||||
int CPns_IsPnsUsed (const CPnsData *pPnsData,
|
||||
const int group,
|
||||
const int band);
|
||||
|
||||
void CPns_SetCorrelation(CPnsData *pPnsData,
|
||||
const int group,
|
||||
const int band,
|
||||
const int outofphase);
|
||||
|
||||
/****************** inline functions ******************/
|
||||
|
||||
inline UCHAR IsValid(const CIcsInfo *pIcsInfo)
|
||||
{
|
||||
return pIcsInfo->Valid;
|
||||
}
|
||||
|
||||
inline UCHAR IsLongBlock(const CIcsInfo *pIcsInfo)
|
||||
{
|
||||
return (pIcsInfo->WindowSequence != EightShortSequence);
|
||||
}
|
||||
|
||||
inline UCHAR GetWindowShape(const CIcsInfo *pIcsInfo)
|
||||
{
|
||||
return pIcsInfo->WindowShape;
|
||||
}
|
||||
|
||||
inline UCHAR GetWindowSequence(const CIcsInfo *pIcsInfo)
|
||||
{
|
||||
return pIcsInfo->WindowSequence;
|
||||
}
|
||||
|
||||
inline const SHORT *GetScaleFactorBandOffsets(const CIcsInfo *pIcsInfo, const SamplingRateInfo* samplingRateInfo)
|
||||
{
|
||||
if (IsLongBlock(pIcsInfo))
|
||||
{
|
||||
return samplingRateInfo->ScaleFactorBands_Long;
|
||||
}
|
||||
else
|
||||
{
|
||||
return samplingRateInfo->ScaleFactorBands_Short;
|
||||
}
|
||||
}
|
||||
|
||||
inline int GetWindowsPerFrame(const CIcsInfo *pIcsInfo)
|
||||
{
|
||||
return (pIcsInfo->WindowSequence == EightShortSequence) ? 8 : 1;
|
||||
}
|
||||
|
||||
inline UCHAR GetWindowGroups(const CIcsInfo *pIcsInfo)
|
||||
{
|
||||
return pIcsInfo->WindowGroups;
|
||||
}
|
||||
|
||||
inline UCHAR GetWindowGroupLength(const CIcsInfo *pIcsInfo, const INT index)
|
||||
{
|
||||
return pIcsInfo->WindowGroupLength[index];
|
||||
}
|
||||
|
||||
inline const UCHAR *GetWindowGroupLengthTable(const CIcsInfo *pIcsInfo)
|
||||
{
|
||||
return pIcsInfo->WindowGroupLength;
|
||||
}
|
||||
|
||||
inline UCHAR GetScaleFactorBandsTransmitted(const CIcsInfo *pIcsInfo)
|
||||
{
|
||||
return pIcsInfo->MaxSfBands;
|
||||
}
|
||||
|
||||
inline UCHAR GetScaleMaxFactorBandsTransmitted(const CIcsInfo *pIcsInfo0, const CIcsInfo *pIcsInfo1)
|
||||
{
|
||||
return fMax(pIcsInfo0->MaxSfBands, pIcsInfo1->MaxSfBands);
|
||||
}
|
||||
|
||||
inline UCHAR GetScaleFactorBandsTotal(const CIcsInfo *pIcsInfo)
|
||||
{
|
||||
return pIcsInfo->TotalSfBands;
|
||||
}
|
||||
|
||||
/* Note: This function applies to AAC-LC only ! */
|
||||
inline UCHAR GetMaximumTnsBands(const CIcsInfo *pIcsInfo, const int samplingRateIndex)
|
||||
{
|
||||
return tns_max_bands_tbl[samplingRateIndex][!IsLongBlock(pIcsInfo)];
|
||||
}
|
||||
|
||||
#endif /* #ifndef CHANNELINFO_H */
|
||||
|
1763
libAACdec/src/conceal.cpp
Normal file
1763
libAACdec/src/conceal.cpp
Normal file
File diff suppressed because it is too large
Load Diff
86
libAACdec/src/conceal.h
Normal file
86
libAACdec/src/conceal.h
Normal file
@ -0,0 +1,86 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description: independent channel concealment
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _CONCEAL_H_
|
||||
#define _CONCEAL_H_
|
||||
|
||||
#include "aacdecoder_lib.h"
|
||||
|
||||
#include "channelinfo.h"
|
||||
|
||||
#define AACDEC_CONCEAL_PARAM_NOT_SPECIFIED ( 0xFFFE )
|
||||
|
||||
void CConcealment_InitCommonData (CConcealParams *pConcealCommonData);
|
||||
|
||||
void CConcealment_InitChannelData (CConcealmentInfo *hConcealmentInfo,
|
||||
CConcealParams *pConcealCommonData,
|
||||
int samplesPerFrame);
|
||||
|
||||
CConcealmentMethod
|
||||
CConcealment_GetMethod (CConcealParams *pConcealCommonData);
|
||||
|
||||
UINT
|
||||
CConcealment_GetDelay (CConcealParams *pConcealCommonData);
|
||||
|
||||
AAC_DECODER_ERROR
|
||||
CConcealment_SetParams (CConcealParams *concealParams,
|
||||
int method,
|
||||
int fadeOutSlope,
|
||||
int fadeInSlope,
|
||||
int muteRelease,
|
||||
int comfNoiseLevel);
|
||||
|
||||
CConcealmentState
|
||||
CConcealment_GetState (CConcealmentInfo *hConcealmentInfo);
|
||||
|
||||
AAC_DECODER_ERROR
|
||||
CConcealment_SetAttenuation (CConcealParams *concealParams,
|
||||
SHORT *fadeOutAttenuationVector,
|
||||
SHORT *fadeInAttenuationVector);
|
||||
|
||||
void CConcealment_Store (CConcealmentInfo *hConcealmentInfo,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo );
|
||||
|
||||
int CConcealment_Apply (CConcealmentInfo *hConcealmentInfo,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
|
||||
const SamplingRateInfo *pSamplingRateInfo,
|
||||
const int samplesPerFrame,
|
||||
const UCHAR lastLpdMode,
|
||||
const int FrameOk,
|
||||
const UINT flags);
|
||||
|
||||
FIXP_DBL
|
||||
CConcealment_GetFadeFactor (CConcealmentInfo *hConcealmentInfo,
|
||||
const int fPreviousFactor);
|
||||
|
||||
int CConcealment_GetLastFrameOk (CConcealmentInfo *hConcealmentInfo,
|
||||
const int fBeforeApply);
|
||||
|
||||
#endif /* #ifndef _CONCEAL_H_ */
|
116
libAACdec/src/conceal_types.h
Normal file
116
libAACdec/src/conceal_types.h
Normal file
@ -0,0 +1,116 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Christian Griebel
|
||||
Description: Error concealment structs and types
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef CONCEAL_TYPES_H
|
||||
#define CONCEAL_TYPES_H
|
||||
|
||||
|
||||
|
||||
#include "machine_type.h"
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "rvlc_info.h"
|
||||
|
||||
|
||||
#define CONCEAL_MAX_NUM_FADE_FACTORS ( 16 )
|
||||
|
||||
#define FIXP_CNCL FIXP_DBL
|
||||
#define FL2FXCONST_CNCL FL2FXCONST_DBL
|
||||
#define FX_DBL2FX_CNCL
|
||||
#define FX_CNCL2FX_DBL
|
||||
#define CNCL_FRACT_BITS DFRACT_BITS
|
||||
|
||||
/* Warning: Do not ever change these values. */
|
||||
typedef enum
|
||||
{
|
||||
ConcealMethodNone = -1,
|
||||
ConcealMethodMute = 0,
|
||||
ConcealMethodNoise = 1,
|
||||
ConcealMethodInter = 2,
|
||||
ConcealMethodTonal = 3
|
||||
|
||||
} CConcealmentMethod;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ConcealState_Ok,
|
||||
ConcealState_Single,
|
||||
ConcealState_FadeIn,
|
||||
ConcealState_Mute,
|
||||
ConcealState_FadeOut
|
||||
|
||||
} CConcealmentState;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FIXP_SGL fadeOutFactor[CONCEAL_MAX_NUM_FADE_FACTORS];
|
||||
FIXP_SGL fadeInFactor [CONCEAL_MAX_NUM_FADE_FACTORS];
|
||||
|
||||
CConcealmentMethod method;
|
||||
|
||||
int numFadeOutFrames;
|
||||
int numFadeInFrames;
|
||||
int numMuteReleaseFrames;
|
||||
int comfortNoiseLevel;
|
||||
|
||||
} CConcealParams;
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CConcealParams *pConcealParams;
|
||||
|
||||
FIXP_CNCL spectralCoefficient[1024];
|
||||
SHORT specScale[8];
|
||||
|
||||
INT iRandomPhase;
|
||||
INT prevFrameOk[2];
|
||||
INT cntFadeFrames;
|
||||
INT cntValidFrames;
|
||||
|
||||
SHORT aRvlcPreviousScaleFactor[RVLC_MAX_SFB]; /* needed once per channel */
|
||||
UCHAR aRvlcPreviousCodebook[RVLC_MAX_SFB]; /* needed once per channel */
|
||||
SCHAR rvlcPreviousScaleFactorOK;
|
||||
SCHAR rvlcPreviousBlockType;
|
||||
|
||||
|
||||
SCHAR lastRenderMode;
|
||||
|
||||
UCHAR windowShape;
|
||||
UCHAR windowSequence;
|
||||
UCHAR lastWinGrpLen;
|
||||
|
||||
CConcealmentState concealState;
|
||||
|
||||
} CConcealmentInfo;
|
||||
|
||||
|
||||
#endif /* #ifndef CONCEAL_TYPES_H */
|
35
libAACdec/src/debug.h
Normal file
35
libAACdec/src/debug.h
Normal file
@ -0,0 +1,35 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description: debug output
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef DEBUG_H
|
||||
#define DEBUG_H
|
||||
|
||||
#include "machine_type.h"
|
||||
|
||||
|
||||
#endif
|
148
libAACdec/src/ldfiltbank.cpp
Normal file
148
libAACdec/src/ldfiltbank.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
/***************************************************************************\
|
||||
*
|
||||
* (C) copyright Fraunhofer - IIS (2006)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
*
|
||||
* filename: ldfiltbank.c
|
||||
* project : MPEG-4 Audio Decoder
|
||||
* contents/description: low delay filterbank
|
||||
*
|
||||
* This software and/or program is protected by copyright law and
|
||||
* international treaties. Any reproduction or distribution of this
|
||||
* software and/or program, or any portion of it, may result in severe
|
||||
* civil and criminal penalties, and will be prosecuted to the maximum
|
||||
* extent possible under law.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
\***************************************************************************/
|
||||
|
||||
#include "ldfiltbank.h"
|
||||
|
||||
|
||||
#include "aac_rom.h"
|
||||
#include "dct.h"
|
||||
#include "FDK_tools_rom.h"
|
||||
#include "mdct.h"
|
||||
|
||||
#define LDFB_HEADROOM 2
|
||||
|
||||
static void multE2_DinvF_fdk(INT_PCM *output, FIXP_DBL* x, const FIXP_WTB* fb, FIXP_DBL* z, const int N, const int stride)
|
||||
{
|
||||
int i, scale;
|
||||
|
||||
/* scale for FIXP_DBL -> INT_PCM conversion. */
|
||||
scale = (DFRACT_BITS - SAMPLE_BITS) - LDFB_HEADROOM;
|
||||
|
||||
for(i=0;i<N/4;i++)
|
||||
{
|
||||
FIXP_DBL z0, z2, tmp;
|
||||
|
||||
z2 = x[N/2+i];
|
||||
z0 = z2 + ( fMultDiv2(z[N/2+i], fb[2*N + i]) >> (-WTS2-1) );
|
||||
|
||||
z[N/2+i] = x[N/2-1-i] + ( fMultDiv2(z[N + i], fb[2*N + N/2 + i]) >> (-WTS2-1) );
|
||||
|
||||
tmp = ( fMultDiv2(z[N/2+i], fb[N+N/2-1-i]) + fMultDiv2(z[i], fb[N+N/2+i]) ) ;
|
||||
|
||||
#if (SAMPLE_BITS <= 16)
|
||||
FDK_ASSERT( (-WTS1-1 + scale) >= 0);
|
||||
output[(N*3/4-1-i)*stride] = (INT_PCM)SATURATE_RIGHT_SHIFT(tmp, -WTS1-1 + scale, SAMPLE_BITS);
|
||||
#else
|
||||
FDK_ASSERT( (WTS1+1 - scale) >= 0);
|
||||
output[(N*3/4-1-i)*stride] = (INT_PCM)SATURATE_LEFT_SHIFT(tmp, WTS1+1 - scale, SAMPLE_BITS);
|
||||
#endif
|
||||
|
||||
z[i] = z0;
|
||||
z[N + i] = z2;
|
||||
}
|
||||
|
||||
for(i=N/4;i<N/2;i++)
|
||||
{
|
||||
FIXP_DBL z0, z2, tmp0, tmp1;
|
||||
|
||||
z2 = x[N/2+i];
|
||||
z0 = z2 + ( fMultDiv2(z[N/2+i], fb[2*N + i]) >> (-WTS2-1) );
|
||||
|
||||
z[N/2+i] = x[N/2-1-i] + ( fMultDiv2(z[N + i], fb[2*N + N/2 + i]) >> (-WTS2-1) );
|
||||
|
||||
tmp0 = ( fMultDiv2(z[N/2+i], fb[N/2-1-i]) + fMultDiv2(z[i], fb[N/2+i]) ) ;
|
||||
tmp1 = ( fMultDiv2(z[N/2+i], fb[N+N/2-1-i]) + fMultDiv2(z[i], fb[N+N/2+i]) ) ;
|
||||
|
||||
#if (SAMPLE_BITS <= 16)
|
||||
FDK_ASSERT( (-WTS0-1 + scale) >= 0);
|
||||
output[(i-N/4)*stride] = (INT_PCM)SATURATE_RIGHT_SHIFT(tmp0, -WTS0-1 + scale, SAMPLE_BITS);
|
||||
output[(N*3/4-1-i)*stride] = (INT_PCM)SATURATE_RIGHT_SHIFT(tmp1, -WTS1-1 + scale, SAMPLE_BITS);
|
||||
#else
|
||||
FDK_ASSERT( (WTS0+1 - scale) >= 0);
|
||||
output[(i-N/4)*stride] = (INT_PCM)SATURATE_LEFT_SHIFT(tmp0, WTS0+1 - scale, SAMPLE_BITS);
|
||||
output[(N*3/4-1-i)*stride] = (INT_PCM)SATURATE_LEFT_SHIFT(tmp1, WTS1+1 - scale, SAMPLE_BITS);
|
||||
#endif
|
||||
z[i] = z0;
|
||||
z[N + i] = z2;
|
||||
}
|
||||
|
||||
/* Exchange quarter parts of x to bring them in the "right" order */
|
||||
for(i=0;i<N/4;i++)
|
||||
{
|
||||
FIXP_DBL tmp0 = fMultDiv2(z[i], fb[N/2+i]);
|
||||
|
||||
#if (SAMPLE_BITS <= 16)
|
||||
FDK_ASSERT( (-WTS0-1 + scale) >= 0);
|
||||
output[(N*3/4 + i)*stride] = (INT_PCM)SATURATE_RIGHT_SHIFT(tmp0, -WTS0-1 + scale, SAMPLE_BITS);
|
||||
#else
|
||||
FDK_ASSERT( (WTS0+1 - scale) >= 0);
|
||||
output[(N*3/4 + i)*stride] = (INT_PCM)SATURATE_LEFT_SHIFT(tmp0, WTS0+1 - scale, SAMPLE_BITS);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int InvMdctTransformLowDelay_fdk (FIXP_DBL *mdctData, const int mdctData_e, INT_PCM *output, FIXP_DBL *fs_buffer, const int stride, const int N) {
|
||||
|
||||
const FIXP_WTB *coef;
|
||||
FIXP_DBL gain = (FIXP_DBL)0;
|
||||
int scale = mdctData_e + MDCT_OUT_HEADROOM - LDFB_HEADROOM; /* The LDFB_HEADROOM is compensated inside multE2_DinvF_fdk() below */
|
||||
|
||||
/* Select LD window slope */
|
||||
if (N == 512)
|
||||
coef = (FIXP_WTB*)LowDelaySynthesis512;
|
||||
else
|
||||
coef = (FIXP_WTB*)LowDelaySynthesis480;
|
||||
|
||||
/*
|
||||
Apply exponent and 1/N factor.
|
||||
Note: "scale" is off by one because for LD_MDCT the window length is twice
|
||||
the window length of a regular MDCT. This is corrected inside multE2_DinvF_fdk().
|
||||
Refer to ISO/IEC 14496-3:2009 page 277, chapter 4.6.20.2 "Low Delay Window".
|
||||
*/
|
||||
imdct_gain(&gain, &scale, N);
|
||||
|
||||
dct_IV(mdctData, N, &scale);
|
||||
|
||||
if (gain != (FIXP_DBL)0) {
|
||||
scaleValuesWithFactor(mdctData, gain, N, scale);
|
||||
} else {
|
||||
scaleValues(mdctData, N, scale);
|
||||
}
|
||||
|
||||
/* Since all exponent and factors have been applied, current exponent is zero. */
|
||||
multE2_DinvF_fdk(output, mdctData, coef, fs_buffer, N, stride);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
48
libAACdec/src/ldfiltbank.h
Normal file
48
libAACdec/src/ldfiltbank.h
Normal file
@ -0,0 +1,48 @@
|
||||
/***************************************************************************\
|
||||
*
|
||||
* (C) copyright Fraunhofer - IIS (2006)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
*
|
||||
* filename: ldfiltbank.h
|
||||
* project : MPEG-4 Audio Decoder
|
||||
* contents/description: low delay filterbank interface
|
||||
*
|
||||
* This software and/or program is protected by copyright law and
|
||||
* international treaties. Any reproduction or distribution of this
|
||||
* software and/or program, or any portion of it, may result in severe
|
||||
* civil and criminal penalties, and will be prosecuted to the maximum
|
||||
* extent possible under law.
|
||||
*
|
||||
* $Header: /home/cvs/amm/menc/mp4objdec/src/aac_eld/ldfiltbank.h,v 1.3 2006/11/07 22:21:27 haertlml Exp $
|
||||
*
|
||||
\***************************************************************************/
|
||||
|
||||
#ifndef _LDFILTBANK_H
|
||||
#define _LDFILTBANK_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
|
||||
int InvMdctTransformLowDelay_fdk (
|
||||
FIXP_DBL *mdctdata_m,
|
||||
const int mdctdata_e,
|
||||
INT_PCM *mdctOut,
|
||||
FIXP_DBL *fs_buffer,
|
||||
const int stride,
|
||||
const int frameLength
|
||||
);
|
||||
|
||||
|
||||
#endif
|
43
libAACdec/src/overlapadd.h
Normal file
43
libAACdec/src/overlapadd.h
Normal file
@ -0,0 +1,43 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description:
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef OVERLAPADD_H
|
||||
#define OVERLAPADD_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#define OverlapBufferSize (1024*2)
|
||||
|
||||
typedef FIXP_DBL SPECTRUM[1024];
|
||||
typedef FIXP_DBL * SPECTRAL_PTR;
|
||||
|
||||
#define SPEC_LONG(ptr) (ptr)
|
||||
#define SPEC(ptr,w,gl) ((ptr)+((w)*(gl)))
|
||||
|
||||
|
||||
#endif /* #ifndef OVERLAPADD_H */
|
96
libAACdec/src/pulsedata.cpp
Normal file
96
libAACdec/src/pulsedata.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description: pulse data tool
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "pulsedata.h"
|
||||
|
||||
|
||||
#include "channelinfo.h"
|
||||
|
||||
|
||||
INT CPulseData_Read(
|
||||
HANDLE_FDK_BITSTREAM bs,
|
||||
CPulseData *const PulseData,
|
||||
const SHORT *sfb_startlines,
|
||||
const void *pIcsInfo,
|
||||
const SHORT frame_length
|
||||
)
|
||||
{
|
||||
int i, k=0;
|
||||
const UINT MaxSfBands = GetScaleFactorBandsTransmitted((CIcsInfo*)pIcsInfo);
|
||||
|
||||
/* reset pulse data flag */
|
||||
PulseData->PulseDataPresent = 0;
|
||||
|
||||
if ((PulseData->PulseDataPresent = (UCHAR) FDKreadBit(bs)) != 0) {
|
||||
if (!IsLongBlock((CIcsInfo*)pIcsInfo)) {
|
||||
return AAC_DEC_DECODE_FRAME_ERROR;
|
||||
}
|
||||
|
||||
PulseData->NumberPulse = (UCHAR) FDKreadBits(bs,2);
|
||||
PulseData->PulseStartBand = (UCHAR) FDKreadBits(bs,6);
|
||||
|
||||
if (PulseData->PulseStartBand >= MaxSfBands) {
|
||||
return AAC_DEC_DECODE_FRAME_ERROR;
|
||||
}
|
||||
|
||||
k = sfb_startlines[PulseData->PulseStartBand];
|
||||
|
||||
for (i=0; i<=PulseData->NumberPulse; i++) {
|
||||
PulseData->PulseOffset[i] = (UCHAR) FDKreadBits(bs,5);
|
||||
PulseData->PulseAmp[i] = (UCHAR) FDKreadBits(bs,4);
|
||||
k += PulseData->PulseOffset[i];
|
||||
}
|
||||
|
||||
if (k >= frame_length) {
|
||||
return AAC_DEC_DECODE_FRAME_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CPulseData_Apply(CPulseData *PulseData, /*!< pointer to pulse data side info */
|
||||
const short *pScaleFactorBandOffsets, /*!< pointer to scalefactor band offsets */
|
||||
FIXP_DBL *coef) /*!< pointer to spectrum */
|
||||
{
|
||||
int i,k;
|
||||
|
||||
if (PulseData->PulseDataPresent)
|
||||
{
|
||||
k = pScaleFactorBandOffsets[PulseData->PulseStartBand];
|
||||
|
||||
for (i=0; i<=PulseData->NumberPulse; i++)
|
||||
{
|
||||
k += PulseData->PulseOffset[i];
|
||||
if (coef [k] > (FIXP_DBL)0) coef[k] += (FIXP_DBL)(int)PulseData->PulseAmp[i];
|
||||
else coef[k] -= (FIXP_DBL)(int)PulseData->PulseAmp[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
83
libAACdec/src/pulsedata.h
Normal file
83
libAACdec/src/pulsedata.h
Normal file
@ -0,0 +1,83 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description: pulse data tool
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef PULSEDATA_H
|
||||
#define PULSEDATA_H
|
||||
|
||||
|
||||
|
||||
#include "common_fix.h"
|
||||
#include "FDK_bitstream.h"
|
||||
|
||||
#define N_MAX_LINES 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UCHAR PulseDataPresent;
|
||||
UCHAR NumberPulse;
|
||||
UCHAR PulseStartBand;
|
||||
UCHAR PulseOffset[N_MAX_LINES];
|
||||
UCHAR PulseAmp[N_MAX_LINES];
|
||||
} CPulseData;
|
||||
|
||||
/**
|
||||
* \brief Read pulse data from bitstream
|
||||
*
|
||||
* The function reads the elements for pulse data from
|
||||
* the bitstream.
|
||||
*
|
||||
* \param bs bit stream handle data source.
|
||||
* \param PulseData pointer to a CPulseData were the decoded data is stored into.
|
||||
* \param MaxSfBands max number of scale factor bands.
|
||||
* \return 0 on success, != 0 on parse error.
|
||||
*/
|
||||
INT CPulseData_Read(
|
||||
const HANDLE_FDK_BITSTREAM bs,
|
||||
CPulseData *const PulseData,
|
||||
const SHORT *sfb_startlines,
|
||||
const void *pIcsInfo,
|
||||
const SHORT frame_length
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Apply pulse data to spectral lines
|
||||
*
|
||||
* The function applies the pulse data to the
|
||||
* specified spectral lines.
|
||||
*
|
||||
* \param PulseData pointer to the previously decoded pulse data.
|
||||
* \param pScaleFactorBandOffsets scale factor band line offset table.
|
||||
* \param coef pointer to the spectral data were pulse data should be applied to.
|
||||
* \return none
|
||||
*/
|
||||
void CPulseData_Apply(CPulseData *PulseData,
|
||||
const short *pScaleFactorBandOffsets,
|
||||
FIXP_DBL *coef);
|
||||
|
||||
|
||||
#endif /* #ifndef PULSEDATA_H */
|
1157
libAACdec/src/rvlc.cpp
Normal file
1157
libAACdec/src/rvlc.cpp
Normal file
File diff suppressed because it is too large
Load Diff
76
libAACdec/src/rvlc.h
Normal file
76
libAACdec/src/rvlc.h
Normal file
@ -0,0 +1,76 @@
|
||||
/****************************************************************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
|
||||
****************************************************************************/
|
||||
/*!
|
||||
\file
|
||||
\brief Defines structures and prototypes for RVLC
|
||||
\author Robert Weidner
|
||||
*/
|
||||
|
||||
#ifndef RVLC_H
|
||||
#define RVLC_H
|
||||
|
||||
|
||||
|
||||
#include "aacdecoder.h"
|
||||
#include "channel.h"
|
||||
#include "rvlc_info.h"
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
/* errorLogRvlc: A word of 32 bits used for logging possible errors */
|
||||
/* within RVLC in case of distorted bitstreams. */
|
||||
/* ------------------------------------------------------------------- */
|
||||
#define RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID 0x80000000 /* ESC-Dec During RVLC-Escape-decoding there have been more bits decoded as there are available */
|
||||
#define RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_FWD 0x40000000 /* RVL-Dec negative sum-bitcounter during RVL-fwd-decoding (long+shrt) */
|
||||
#define RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_BWD 0x20000000 /* RVL-Dec negative sum-bitcounter during RVL-fwd-decoding (long+shrt) */
|
||||
#define RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD 0x08000000 /* RVL-Dec forbidden codeword detected fwd (long+shrt) */
|
||||
#define RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD 0x04000000 /* RVL-Dec forbidden codeword detected bwd (long+shrt) */
|
||||
|
||||
|
||||
|
||||
void CRvlc_Read (CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
HANDLE_FDK_BITSTREAM bs);
|
||||
|
||||
void CRvlc_Decode (CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo,
|
||||
HANDLE_FDK_BITSTREAM bs);
|
||||
|
||||
/**
|
||||
* \brief performe sanity checks to the channel data corresponding to one channel element.
|
||||
* \param pAacDecoderChannelInfo
|
||||
* \param pAacDecoderStaticChannelInfo
|
||||
* \param elChannels amount of channels of the channel element.
|
||||
*/
|
||||
void CRvlc_ElementCheck (
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo[],
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[],
|
||||
const UINT flags,
|
||||
const INT elChannels
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* RVLC_H */
|
118
libAACdec/src/rvlc_info.h
Normal file
118
libAACdec/src/rvlc_info.h
Normal file
@ -0,0 +1,118 @@
|
||||
/****************************************************************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
|
||||
****************************************************************************/
|
||||
/*!
|
||||
\file
|
||||
\brief Defines structures for RVLC
|
||||
\author Robert Weidner
|
||||
*/
|
||||
#ifndef RVLC_INFO_H
|
||||
#define RVLC_INFO_H
|
||||
|
||||
|
||||
|
||||
#define FWD 0 /* bitstream decoding direction forward (RVL coded part) */
|
||||
#define BWD 1 /* bitstream decoding direction backward (RVL coded part) */
|
||||
|
||||
#define MAX_RVL 7 /* positive RVLC escape */
|
||||
#define MIN_RVL -7 /* negative RVLC escape */
|
||||
#define MAX_ALLOWED_DPCM_INDEX 14 /* the maximum allowed index of a decoded dpcm value (offset 'TABLE_OFFSET' incl --> must be subtracted) */
|
||||
#define TABLE_OFFSET 7 /* dpcm offset of valid output values of rvl table decoding, the rvl table ouly returns positive values, therefore the offset */
|
||||
#define MAX_LEN_RVLC_CODE_WORD 9 /* max length of a RVL codeword in bits */
|
||||
#define MAX_LEN_RVLC_ESCAPE_WORD 20 /* max length of huffman coded RVLC escape word in bits */
|
||||
|
||||
#define DPCM_NOISE_NRG_BITS 9
|
||||
#define SF_OFFSET 100 /* offset for correcting scf value */
|
||||
|
||||
#define CONCEAL_MAX_INIT 1311 /* arbitrary value */
|
||||
#define CONCEAL_MIN_INIT -1311 /* arbitrary value */
|
||||
|
||||
#define RVLC_MAX_SFB ((8) * (16))
|
||||
|
||||
/* sideinfo of RVLC */
|
||||
typedef struct
|
||||
{
|
||||
/* ------- ESC 1 Data: --------- */ /* order of RVLC-bitstream components in bitstream (RVLC-initialization), every component appears only once in bitstream */
|
||||
INT sf_concealment; /* 1 */
|
||||
INT rev_global_gain; /* 2 */
|
||||
SHORT length_of_rvlc_sf; /* 3 */ /* original value, gets modified (subtract 9) in case of noise (PNS); is kept for later use */
|
||||
INT dpcm_noise_nrg; /* 4 optional */
|
||||
INT sf_escapes_present; /* 5 */
|
||||
SHORT length_of_rvlc_escapes; /* 6 optional */
|
||||
INT dpcm_noise_last_position; /* 7 optional */
|
||||
|
||||
INT dpcm_is_last_position;
|
||||
|
||||
SHORT length_of_rvlc_sf_fwd; /* length_of_rvlc_sf used for forward decoding */
|
||||
SHORT length_of_rvlc_sf_bwd; /* length_of_rvlc_sf used for backward decoding */
|
||||
|
||||
/* for RVL-Codeword decoder to distinguish between fwd and bwd decoding */
|
||||
SHORT *pRvlBitCnt_RVL;
|
||||
USHORT *pBitstrIndxRvl_RVL;
|
||||
|
||||
UCHAR numWindowGroups;
|
||||
UCHAR maxSfbTransmitted;
|
||||
UCHAR first_noise_group;
|
||||
UCHAR first_noise_band;
|
||||
UCHAR direction;
|
||||
|
||||
/* bitstream indices */
|
||||
USHORT bitstreamIndexRvlFwd; /* base address of RVL-coded-scalefactor data (ESC 2) for forward decoding */
|
||||
USHORT bitstreamIndexRvlBwd; /* base address of RVL-coded-scalefactor data (ESC 2) for backward decoding */
|
||||
USHORT bitstreamIndexEsc; /* base address where RVLC-escapes start (ESC 2) */
|
||||
|
||||
/* decoding trees */
|
||||
const UINT *pHuffTreeRvlCodewds;
|
||||
const UINT *pHuffTreeRvlcEscape;
|
||||
|
||||
/* escape counters */
|
||||
UCHAR numDecodedEscapeWordsFwd; /* when decoding RVL-codes forward */
|
||||
UCHAR numDecodedEscapeWordsBwd; /* when decoding RVL-codes backward */
|
||||
UCHAR numDecodedEscapeWordsEsc; /* when decoding the escape-Words */
|
||||
|
||||
SCHAR noise_used;
|
||||
SCHAR intensity_used;
|
||||
SCHAR sf_used;
|
||||
|
||||
SHORT firstScf;
|
||||
SHORT lastScf;
|
||||
SHORT firstNrg;
|
||||
SHORT lastNrg;
|
||||
SHORT firstIs;
|
||||
SHORT lastIs;
|
||||
|
||||
/* ------ RVLC error detection ------ */
|
||||
UINT errorLogRvlc; /* store RVLC errors */
|
||||
SHORT conceal_min; /* is set at backward decoding */
|
||||
SHORT conceal_max; /* is set at forward decoding */
|
||||
SHORT conceal_min_esc; /* is set at backward decoding */
|
||||
SHORT conceal_max_esc; /* is set at forward decoding */
|
||||
} CErRvlcInfo;
|
||||
|
||||
typedef CErRvlcInfo RVLC_INFO; /* temp */
|
||||
|
||||
|
||||
|
||||
#endif /* RVLC_INFO_H */
|
73
libAACdec/src/rvlcbit.cpp
Normal file
73
libAACdec/src/rvlcbit.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
/****************************************************************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
|
||||
****************************************************************************/
|
||||
/*!
|
||||
\file
|
||||
\brief RVLC bitstream reading
|
||||
\author Robert Weidner
|
||||
*/
|
||||
|
||||
#include "rvlcbit.h"
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
function: rvlcReadBitFromBitstream
|
||||
|
||||
description: This function returns a bit from the bitstream according to read direction.
|
||||
It is called very often, therefore it makes sense to inline it (runtime).
|
||||
-----------------------------------------------------------------------------------------------
|
||||
input: - bitstream
|
||||
- pPosition
|
||||
- readDirection
|
||||
-----------------------------------------------------------------------------------------------
|
||||
return: - bit from bitstream
|
||||
-------------------------------------------------------------------------------------------- */
|
||||
|
||||
UCHAR rvlcReadBitFromBitstream (HANDLE_FDK_BITSTREAM bs,
|
||||
USHORT *pPosition,
|
||||
UCHAR readDirection)
|
||||
{
|
||||
UINT bit;
|
||||
INT readBitOffset = *pPosition-FDKgetBitCnt(bs);
|
||||
|
||||
if( readBitOffset ) {
|
||||
FDKpushBiDirectional(bs, readBitOffset);
|
||||
}
|
||||
|
||||
if (readDirection == FWD) {
|
||||
bit = FDKreadBits(bs, 1);
|
||||
|
||||
*pPosition += 1;
|
||||
} else {
|
||||
/* to be replaced with a brother function of FDKreadBits() */
|
||||
bit = FDKreadBits(bs, 1);
|
||||
FDKpushBack(bs, 2);
|
||||
|
||||
*pPosition -= 1;
|
||||
}
|
||||
|
||||
return (bit);
|
||||
}
|
||||
|
41
libAACdec/src/rvlcbit.h
Normal file
41
libAACdec/src/rvlcbit.h
Normal file
@ -0,0 +1,41 @@
|
||||
/***************************** MPEG-4 AAC Decoder ***************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS 2000-2008
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Robert Weidner (DSP Solutions)
|
||||
Description: RVLC Decoder: Bitstream reading
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef RVLCBIT_H
|
||||
#define RVLCBIT_H
|
||||
|
||||
|
||||
|
||||
#include "rvlc.h"
|
||||
|
||||
UCHAR rvlcReadBitFromBitstream (HANDLE_FDK_BITSTREAM bs,
|
||||
USHORT *pPosition,
|
||||
UCHAR readDirection);
|
||||
|
||||
|
||||
#endif /* RVLCBIT_H */
|
639
libAACdec/src/rvlcconceal.cpp
Normal file
639
libAACdec/src/rvlcconceal.cpp
Normal file
@ -0,0 +1,639 @@
|
||||
/****************************************************************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
|
||||
****************************************************************************/
|
||||
/*!
|
||||
\file
|
||||
\brief rvlc concealment
|
||||
\author Josef Hoepfl
|
||||
*/
|
||||
|
||||
#include "rvlcconceal.h"
|
||||
|
||||
|
||||
#include "block.h"
|
||||
#include "rvlc.h"
|
||||
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
function: calcRefValFwd
|
||||
|
||||
description: The function determines the scalefactor which is closed to the scalefactorband
|
||||
conceal_min. The same is done for intensity data and noise energies.
|
||||
-----------------------------------------------------------------------------------------------
|
||||
output: - reference value scf
|
||||
- reference value internsity data
|
||||
- reference value noise energy
|
||||
-----------------------------------------------------------------------------------------------
|
||||
return: -
|
||||
-------------------------------------------------------------------------------------------- */
|
||||
|
||||
static
|
||||
void calcRefValFwd (CErRvlcInfo *pRvlc,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
int *refIsFwd,
|
||||
int *refNrgFwd,
|
||||
int *refScfFwd)
|
||||
{
|
||||
int band,bnds,group,startBand;
|
||||
int idIs,idNrg,idScf;
|
||||
int conceal_min,conceal_group_min;
|
||||
int MaximumScaleFactorBands;
|
||||
|
||||
|
||||
if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence)
|
||||
MaximumScaleFactorBands = 16;
|
||||
else
|
||||
MaximumScaleFactorBands = 64;
|
||||
|
||||
conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands;
|
||||
conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands;
|
||||
|
||||
/* calculate first reference value for approach in forward direction */
|
||||
idIs = idNrg = idScf = 1;
|
||||
|
||||
/* set reference values */
|
||||
*refIsFwd = - SF_OFFSET;
|
||||
*refNrgFwd = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET - 90 - 256;
|
||||
*refScfFwd = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET;
|
||||
|
||||
startBand = conceal_min-1;
|
||||
for (group=conceal_group_min; group >= 0; group--) {
|
||||
for (band=startBand; band >= 0; band--) {
|
||||
bnds = 16*group+band;
|
||||
switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
|
||||
case ZERO_HCB:
|
||||
break;
|
||||
case INTENSITY_HCB:
|
||||
case INTENSITY_HCB2:
|
||||
if (idIs) {
|
||||
*refIsFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
|
||||
idIs=0; /* reference value has been set */
|
||||
}
|
||||
break;
|
||||
case NOISE_HCB:
|
||||
if (idNrg) {
|
||||
*refNrgFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
|
||||
idNrg=0; /* reference value has been set */
|
||||
}
|
||||
break ;
|
||||
default:
|
||||
if (idScf) {
|
||||
*refScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
|
||||
idScf=0; /* reference value has been set */
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
startBand = pRvlc->maxSfbTransmitted-1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
function: calcRefValBwd
|
||||
|
||||
description: The function determines the scalefactor which is closed to the scalefactorband
|
||||
conceal_max. The same is done for intensity data and noise energies.
|
||||
-----------------------------------------------------------------------------------------------
|
||||
output: - reference value scf
|
||||
- reference value internsity data
|
||||
- reference value noise energy
|
||||
-----------------------------------------------------------------------------------------------
|
||||
return: -
|
||||
-------------------------------------------------------------------------------------------- */
|
||||
|
||||
static
|
||||
void calcRefValBwd (CErRvlcInfo *pRvlc,
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
int *refIsBwd,
|
||||
int *refNrgBwd,
|
||||
int *refScfBwd)
|
||||
{
|
||||
int band,bnds,group,startBand;
|
||||
int idIs,idNrg,idScf;
|
||||
int conceal_max,conceal_group_max;
|
||||
int MaximumScaleFactorBands;
|
||||
|
||||
if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence)
|
||||
MaximumScaleFactorBands = 16;
|
||||
else
|
||||
MaximumScaleFactorBands = 64;
|
||||
|
||||
conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands;
|
||||
conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands;
|
||||
|
||||
/* calculate first reference value for approach in backward direction */
|
||||
idIs = idNrg = idScf = 1;
|
||||
|
||||
/* set reference values */
|
||||
*refIsBwd = pRvlc->dpcm_is_last_position - SF_OFFSET;
|
||||
*refNrgBwd = pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - SF_OFFSET - 90 - 256 + pRvlc->dpcm_noise_nrg;
|
||||
*refScfBwd = pRvlc->rev_global_gain - SF_OFFSET;
|
||||
|
||||
startBand=conceal_max+1;
|
||||
|
||||
/* if needed, re-set reference values */
|
||||
for (group=conceal_group_max; group < pRvlc->numWindowGroups; group++) {
|
||||
for (band=startBand; band < pRvlc->maxSfbTransmitted; band++) {
|
||||
bnds = 16*group+band;
|
||||
switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
|
||||
case ZERO_HCB:
|
||||
break;
|
||||
case INTENSITY_HCB:
|
||||
case INTENSITY_HCB2:
|
||||
if (idIs) {
|
||||
*refIsBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
|
||||
idIs=0; /* reference value has been set */
|
||||
}
|
||||
break;
|
||||
case NOISE_HCB:
|
||||
if (idNrg) {
|
||||
*refNrgBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
|
||||
idNrg=0; /* reference value has been set */
|
||||
}
|
||||
break ;
|
||||
default:
|
||||
if (idScf) {
|
||||
*refScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
|
||||
idScf=0; /* reference value has been set */
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
startBand=0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
function: BidirectionalEstimation_UseLowerScfOfCurrentFrame
|
||||
|
||||
description: This approach by means of bidirectional estimation is generally performed when
|
||||
a single bit error has been detected, the bit error can be isolated between
|
||||
'conceal_min' and 'conceal_max' and the 'sf_concealment' flag is not set. The
|
||||
sets of scalefactors decoded in forward and backward direction are compared
|
||||
with each other. The smaller scalefactor will be considered as the correct one
|
||||
respectively. The reconstruction of the scalefactors with this approach archieve
|
||||
good results in audio quality. The strategy must be applied to scalefactors,
|
||||
intensity data and noise energy seperately.
|
||||
-----------------------------------------------------------------------------------------------
|
||||
output: Concealed scalefactor, noise energy and intensity data between conceal_min and
|
||||
conceal_max
|
||||
-----------------------------------------------------------------------------------------------
|
||||
return: -
|
||||
-------------------------------------------------------------------------------------------- */
|
||||
|
||||
void BidirectionalEstimation_UseLowerScfOfCurrentFrame (CAacDecoderChannelInfo *pAacDecoderChannelInfo)
|
||||
{
|
||||
CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
|
||||
int band,bnds,startBand,endBand,group;
|
||||
int conceal_min,conceal_max;
|
||||
int conceal_group_min,conceal_group_max;
|
||||
int MaximumScaleFactorBands;
|
||||
|
||||
if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) {
|
||||
MaximumScaleFactorBands = 16;
|
||||
}
|
||||
else {
|
||||
MaximumScaleFactorBands = 64;
|
||||
}
|
||||
|
||||
/* If an error was detected just in forward or backward direction, set the corresponding border for concealment to a
|
||||
appropriate scalefactor band. The border is set to first or last sfb respectively, because the error will possibly
|
||||
not follow directly after the corrupt bit but just after decoding some more (wrong) scalefactors. */
|
||||
if (pRvlc->conceal_min == CONCEAL_MIN_INIT)
|
||||
pRvlc->conceal_min = 0;
|
||||
|
||||
if (pRvlc->conceal_max == CONCEAL_MAX_INIT)
|
||||
pRvlc->conceal_max = (pRvlc->numWindowGroups-1)*16+pRvlc->maxSfbTransmitted-1;
|
||||
|
||||
conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands;
|
||||
conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands;
|
||||
conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands;
|
||||
conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands;
|
||||
|
||||
if (pRvlc->conceal_min == pRvlc->conceal_max) {
|
||||
|
||||
int refIsFwd,refNrgFwd,refScfFwd;
|
||||
int refIsBwd,refNrgBwd,refScfBwd;
|
||||
|
||||
bnds = pRvlc->conceal_min;
|
||||
calcRefValFwd(pRvlc,pAacDecoderChannelInfo,&refIsFwd,&refNrgFwd,&refScfFwd);
|
||||
calcRefValBwd(pRvlc,pAacDecoderChannelInfo,&refIsBwd,&refNrgBwd,&refScfBwd);
|
||||
|
||||
switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
|
||||
case ZERO_HCB:
|
||||
break;
|
||||
case INTENSITY_HCB:
|
||||
case INTENSITY_HCB2:
|
||||
if (refIsFwd < refIsBwd)
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refIsFwd;
|
||||
else
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refIsBwd;
|
||||
break;
|
||||
case NOISE_HCB:
|
||||
if (refNrgFwd < refNrgBwd)
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refNrgFwd;
|
||||
else
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refNrgBwd;
|
||||
break;
|
||||
default:
|
||||
if (refScfFwd < refScfBwd)
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refScfFwd;
|
||||
else
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refScfBwd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[pRvlc->conceal_max] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[pRvlc->conceal_max];
|
||||
pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[pRvlc->conceal_min] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[pRvlc->conceal_min];
|
||||
|
||||
/* consider the smaller of the forward and backward decoded value as the correct one */
|
||||
startBand = conceal_min;
|
||||
if (conceal_group_min == conceal_group_max)
|
||||
endBand = conceal_max;
|
||||
else
|
||||
endBand = pRvlc->maxSfbTransmitted-1;
|
||||
|
||||
for (group=conceal_group_min; group <= conceal_group_max; group++) {
|
||||
for (band=startBand; band <= endBand; band++) {
|
||||
bnds = 16*group+band;
|
||||
if (pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds] < pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds])
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
|
||||
else
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
|
||||
}
|
||||
startBand = 0;
|
||||
if ((group+1) == conceal_group_max)
|
||||
endBand = conceal_max;
|
||||
}
|
||||
}
|
||||
|
||||
/* now copy all data to the output buffer which needs not to be concealed */
|
||||
if (conceal_group_min == 0)
|
||||
endBand = conceal_min;
|
||||
else
|
||||
endBand = pRvlc->maxSfbTransmitted;
|
||||
for (group=0; group <= conceal_group_min; group++) {
|
||||
for (band=0; band < endBand; band++) {
|
||||
bnds = 16*group+band;
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
|
||||
}
|
||||
if ((group+1) == conceal_group_min)
|
||||
endBand = conceal_min;
|
||||
}
|
||||
|
||||
startBand = conceal_max+1;
|
||||
for (group=conceal_group_max; group < pRvlc->numWindowGroups; group++) {
|
||||
for (band=startBand; band < pRvlc->maxSfbTransmitted; band++) {
|
||||
bnds = 16*group+band;
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
|
||||
}
|
||||
startBand = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
function: BidirectionalEstimation_UseScfOfPrevFrameAsReference
|
||||
|
||||
description: This approach by means of bidirectional estimation is generally performed when
|
||||
a single bit error has been detected, the bit error can be isolated between
|
||||
'conceal_min' and 'conceal_max', the 'sf_concealment' flag is set and the
|
||||
previous frame has the same block type as the current frame. The scalefactor
|
||||
decoded in forward and backward direction and the scalefactor of the previous
|
||||
frame are compared with each other. The smaller scalefactor will be considered
|
||||
as the correct one. At this the codebook of the previous and current frame must
|
||||
be of the same set (scf, nrg, is) in each scalefactorband. Otherwise the
|
||||
scalefactor of the previous frame is not considered in the minimum calculation.
|
||||
The reconstruction of the scalefactors with this approach archieve good results
|
||||
in audio quality. The strategy must be applied to scalefactors, intensity data
|
||||
and noise energy seperately.
|
||||
-----------------------------------------------------------------------------------------------
|
||||
output: Concealed scalefactor, noise energy and intensity data between conceal_min and
|
||||
conceal_max
|
||||
-----------------------------------------------------------------------------------------------
|
||||
return: -
|
||||
-------------------------------------------------------------------------------------------- */
|
||||
|
||||
void BidirectionalEstimation_UseScfOfPrevFrameAsReference (
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo
|
||||
)
|
||||
{
|
||||
CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
|
||||
int band,bnds,startBand,endBand,group;
|
||||
int conceal_min,conceal_max;
|
||||
int conceal_group_min,conceal_group_max;
|
||||
int MaximumScaleFactorBands;
|
||||
int commonMin;
|
||||
|
||||
if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) {
|
||||
MaximumScaleFactorBands = 16;
|
||||
}
|
||||
else {
|
||||
MaximumScaleFactorBands = 64;
|
||||
}
|
||||
|
||||
/* If an error was detected just in forward or backward direction, set the corresponding border for concealment to a
|
||||
appropriate scalefactor band. The border is set to first or last sfb respectively, because the error will possibly
|
||||
not follow directly after the corrupt bit but just after decoding some more (wrong) scalefactors. */
|
||||
if (pRvlc->conceal_min == CONCEAL_MIN_INIT)
|
||||
pRvlc->conceal_min = 0;
|
||||
|
||||
if (pRvlc->conceal_max == CONCEAL_MAX_INIT)
|
||||
pRvlc->conceal_max = (pRvlc->numWindowGroups-1)*16+pRvlc->maxSfbTransmitted-1;
|
||||
|
||||
conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands;
|
||||
conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands;
|
||||
conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands;
|
||||
conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands;
|
||||
|
||||
pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[pRvlc->conceal_max] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[pRvlc->conceal_max];
|
||||
pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[pRvlc->conceal_min] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[pRvlc->conceal_min];
|
||||
|
||||
/* consider the smaller of the forward and backward decoded value as the correct one */
|
||||
startBand = conceal_min;
|
||||
if (conceal_group_min == conceal_group_max)
|
||||
endBand = conceal_max;
|
||||
else
|
||||
endBand = pRvlc->maxSfbTransmitted-1;
|
||||
|
||||
for (group=conceal_group_min; group <= conceal_group_max; group++) {
|
||||
for (band=startBand; band <= endBand; band++) {
|
||||
bnds = 16*group+band;
|
||||
switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
|
||||
case ZERO_HCB:
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0;
|
||||
break;
|
||||
|
||||
case INTENSITY_HCB:
|
||||
case INTENSITY_HCB2:
|
||||
if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==INTENSITY_HCB) || (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==INTENSITY_HCB2) ) {
|
||||
commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]);
|
||||
}
|
||||
else {
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
|
||||
}
|
||||
break;
|
||||
|
||||
case NOISE_HCB:
|
||||
if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==NOISE_HCB) ) {
|
||||
commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]);
|
||||
} else {
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=ZERO_HCB)
|
||||
&& (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=NOISE_HCB)
|
||||
&& (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=INTENSITY_HCB)
|
||||
&& (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=INTENSITY_HCB2) )
|
||||
{
|
||||
commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]);
|
||||
} else {
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
startBand = 0;
|
||||
if ((group+1) == conceal_group_max)
|
||||
endBand = conceal_max;
|
||||
}
|
||||
|
||||
/* now copy all data to the output buffer which needs not to be concealed */
|
||||
if (conceal_group_min == 0)
|
||||
endBand = conceal_min;
|
||||
else
|
||||
endBand = pRvlc->maxSfbTransmitted;
|
||||
for (group=0; group <= conceal_group_min; group++) {
|
||||
for (band=0; band < endBand; band++) {
|
||||
bnds = 16*group+band;
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
|
||||
}
|
||||
if ((group+1) == conceal_group_min)
|
||||
endBand = conceal_min;
|
||||
}
|
||||
|
||||
startBand = conceal_max+1;
|
||||
for (group=conceal_group_max; group < pRvlc->numWindowGroups; group++) {
|
||||
for (band=startBand; band < pRvlc->maxSfbTransmitted; band++) {
|
||||
bnds = 16*group+band;
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
|
||||
}
|
||||
startBand = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
function: StatisticalEstimation
|
||||
|
||||
description: This approach by means of statistical estimation is generally performed when
|
||||
both the start value and the end value are different and no further errors have
|
||||
been detected. Considering the forward and backward decoded scalefactors, the
|
||||
set with the lower scalefactors in sum will be considered as the correct one.
|
||||
The scalefactors are differentially encoded. Normally it would reach to compare
|
||||
one pair of the forward and backward decoded scalefactors to specify the lower
|
||||
set. But having detected no further errors does not necessarily mean the absence
|
||||
of errors. Therefore all scalefactors decoded in forward and backward direction
|
||||
are summed up seperately. The set with the lower sum will be used. The strategy
|
||||
must be applied to scalefactors, intensity data and noise energy seperately.
|
||||
-----------------------------------------------------------------------------------------------
|
||||
output: Concealed scalefactor, noise energy and intensity data
|
||||
-----------------------------------------------------------------------------------------------
|
||||
return: -
|
||||
-------------------------------------------------------------------------------------------- */
|
||||
|
||||
void StatisticalEstimation (CAacDecoderChannelInfo *pAacDecoderChannelInfo)
|
||||
{
|
||||
CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
|
||||
int band,bnds,group;
|
||||
int sumIsFwd,sumIsBwd; /* sum of intensity data forward/backward */
|
||||
int sumNrgFwd,sumNrgBwd; /* sum of noise energy data forward/backward */
|
||||
int sumScfFwd,sumScfBwd; /* sum of scalefactor data forward/backward */
|
||||
int useIsFwd,useNrgFwd,useScfFwd; /* the flags signals the elements which are used for the final result */
|
||||
int MaximumScaleFactorBands;
|
||||
|
||||
if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence)
|
||||
MaximumScaleFactorBands = 16;
|
||||
else
|
||||
MaximumScaleFactorBands = 64;
|
||||
|
||||
sumIsFwd = sumIsBwd = sumNrgFwd = sumNrgBwd = sumScfFwd = sumScfBwd = 0;
|
||||
useIsFwd = useNrgFwd = useScfFwd = 0;
|
||||
|
||||
/* calculate sum of each group (scf,nrg,is) of forward and backward direction */
|
||||
for (group=0; group<pRvlc->numWindowGroups; group++) {
|
||||
for (band=0; band < pRvlc->maxSfbTransmitted; band++) {
|
||||
bnds = 16*group+band;
|
||||
switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
|
||||
case ZERO_HCB:
|
||||
break;
|
||||
|
||||
case INTENSITY_HCB:
|
||||
case INTENSITY_HCB2:
|
||||
sumIsFwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
|
||||
sumIsBwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
|
||||
break;
|
||||
|
||||
case NOISE_HCB:
|
||||
sumNrgFwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
|
||||
sumNrgBwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
|
||||
break ;
|
||||
|
||||
default:
|
||||
sumScfFwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
|
||||
sumScfBwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* find for each group (scf,nrg,is) the correct direction */
|
||||
if ( sumIsFwd < sumIsBwd )
|
||||
useIsFwd = 1;
|
||||
|
||||
if ( sumNrgFwd < sumNrgBwd )
|
||||
useNrgFwd = 1;
|
||||
|
||||
if ( sumScfFwd < sumScfBwd )
|
||||
useScfFwd = 1;
|
||||
|
||||
/* conceal each group (scf,nrg,is) */
|
||||
for (group=0; group<pRvlc->numWindowGroups; group++) {
|
||||
for (band=0; band < pRvlc->maxSfbTransmitted; band++) {
|
||||
bnds = 16*group+band;
|
||||
switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
|
||||
case ZERO_HCB:
|
||||
break;
|
||||
|
||||
case INTENSITY_HCB:
|
||||
case INTENSITY_HCB2:
|
||||
if (useIsFwd)
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
|
||||
else
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
|
||||
break;
|
||||
|
||||
case NOISE_HCB:
|
||||
if (useNrgFwd)
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
|
||||
else
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
|
||||
break ;
|
||||
|
||||
default:
|
||||
if (useScfFwd)
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds];
|
||||
else
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
description: Approach by means of predictive interpolation
|
||||
This approach by means of predictive estimation is generally performed when
|
||||
the error cannot be isolated between 'conceal_min' and 'conceal_max', the
|
||||
'sf_concealment' flag is set and the previous frame has the same block type
|
||||
as the current frame. Check for each scalefactorband if the same type of data
|
||||
(scalefactor, internsity data, noise energies) is transmitted. If so use the
|
||||
scalefactor (intensity data, noise energy) in the current frame. Otherwise set
|
||||
the scalefactor (intensity data, noise energy) for this scalefactorband to zero.
|
||||
-----------------------------------------------------------------------------------------------
|
||||
output: Concealed scalefactor, noise energy and intensity data
|
||||
-----------------------------------------------------------------------------------------------
|
||||
return: -
|
||||
-------------------------------------------------------------------------------------------- */
|
||||
|
||||
void PredictiveInterpolation (
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo
|
||||
)
|
||||
{
|
||||
CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo;
|
||||
int band,bnds,group;
|
||||
int MaximumScaleFactorBands;
|
||||
int commonMin;
|
||||
|
||||
if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence)
|
||||
MaximumScaleFactorBands = 16;
|
||||
else
|
||||
MaximumScaleFactorBands = 64;
|
||||
|
||||
for (group=0; group<pRvlc->numWindowGroups; group++) {
|
||||
for (band=0; band < pRvlc->maxSfbTransmitted; band++) {
|
||||
bnds = 16*group+band;
|
||||
switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) {
|
||||
case ZERO_HCB:
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0;
|
||||
break;
|
||||
|
||||
case INTENSITY_HCB:
|
||||
case INTENSITY_HCB2:
|
||||
if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==INTENSITY_HCB) || (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==INTENSITY_HCB2) ) {
|
||||
commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]);
|
||||
}
|
||||
else {
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = -110;
|
||||
}
|
||||
break;
|
||||
|
||||
case NOISE_HCB:
|
||||
if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==NOISE_HCB) ) {
|
||||
commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]);
|
||||
}
|
||||
else {
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = -110;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=ZERO_HCB)
|
||||
&& (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=NOISE_HCB)
|
||||
&& (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=INTENSITY_HCB)
|
||||
&& (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=INTENSITY_HCB2) ) {
|
||||
commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]);
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]);
|
||||
}
|
||||
else {
|
||||
pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
54
libAACdec/src/rvlcconceal.h
Normal file
54
libAACdec/src/rvlcconceal.h
Normal file
@ -0,0 +1,54 @@
|
||||
/****************************************************************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
|
||||
****************************************************************************/
|
||||
/*!
|
||||
\file
|
||||
\brief rvlc concealment
|
||||
\author Josef Hoepfl
|
||||
*/
|
||||
|
||||
#ifndef RVLCCONCEAL_H
|
||||
#define RVLCCONCEAL_H
|
||||
|
||||
|
||||
|
||||
#include "rvlc.h"
|
||||
|
||||
void BidirectionalEstimation_UseLowerScfOfCurrentFrame(CAacDecoderChannelInfo *pAacDecoderChannelInfo);
|
||||
|
||||
void BidirectionalEstimation_UseScfOfPrevFrameAsReference(
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo
|
||||
);
|
||||
|
||||
void StatisticalEstimation (CAacDecoderChannelInfo *pAacDecoderChannelInfo);
|
||||
|
||||
void PredictiveInterpolation (
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo,
|
||||
CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo
|
||||
);
|
||||
|
||||
|
||||
#endif /* RVLCCONCEAL_H */
|
235
libAACdec/src/stereo.cpp
Normal file
235
libAACdec/src/stereo.cpp
Normal file
@ -0,0 +1,235 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description: joint stereo processing
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "stereo.h"
|
||||
|
||||
|
||||
#include "aac_rom.h"
|
||||
#include "FDK_bitstream.h"
|
||||
#include "channelinfo.h"
|
||||
|
||||
enum
|
||||
{
|
||||
L = 0,
|
||||
R = 1
|
||||
};
|
||||
|
||||
|
||||
int CJointStereo_Read(
|
||||
HANDLE_FDK_BITSTREAM bs,
|
||||
CJointStereoData *pJointStereoData,
|
||||
const int windowGroups,
|
||||
const int scaleFactorBandsTransmitted,
|
||||
const UINT flags
|
||||
)
|
||||
{
|
||||
int group,band;
|
||||
|
||||
pJointStereoData->MsMaskPresent = (UCHAR) FDKreadBits(bs,2);
|
||||
|
||||
FDKmemclear(pJointStereoData->MsUsed, scaleFactorBandsTransmitted*sizeof(UCHAR));
|
||||
|
||||
switch (pJointStereoData->MsMaskPresent)
|
||||
{
|
||||
case 0 : /* no M/S */
|
||||
/* all flags are already cleared */
|
||||
break ;
|
||||
|
||||
case 1 : /* read ms_used */
|
||||
|
||||
for (group=0; group<windowGroups; group++)
|
||||
{
|
||||
for (band=0; band<scaleFactorBandsTransmitted; band++)
|
||||
{
|
||||
pJointStereoData->MsUsed[band] |= (FDKreadBits(bs,1) << group);
|
||||
}
|
||||
}
|
||||
break ;
|
||||
|
||||
case 2 : /* full spectrum M/S */
|
||||
|
||||
for (band=0; band<scaleFactorBandsTransmitted; band++)
|
||||
{
|
||||
pJointStereoData->MsUsed[band] = 255 ; /* set all flags to 1 */
|
||||
}
|
||||
break ;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CJointStereo_ApplyMS(
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo[2],
|
||||
const SHORT *pScaleFactorBandOffsets,
|
||||
const UCHAR *pWindowGroupLength,
|
||||
const int windowGroups,
|
||||
const int scaleFactorBandsTransmittedL,
|
||||
const int scaleFactorBandsTransmittedR
|
||||
)
|
||||
{
|
||||
CJointStereoData *pJointStereoData = &pAacDecoderChannelInfo[L]->pComData->jointStereoData;
|
||||
int window, group, scaleFactorBandsTransmitted;
|
||||
|
||||
FDK_ASSERT(scaleFactorBandsTransmittedL == scaleFactorBandsTransmittedR);
|
||||
scaleFactorBandsTransmitted = scaleFactorBandsTransmittedL;
|
||||
for (window = 0, group = 0; group < windowGroups; group++)
|
||||
{
|
||||
UCHAR groupMask = 1 << group;
|
||||
|
||||
for (int groupwin=0; groupwin<pWindowGroupLength[group]; groupwin++, window++)
|
||||
{
|
||||
int band;
|
||||
FIXP_DBL *leftSpectrum, *rightSpectrum;
|
||||
SHORT *leftScale = &pAacDecoderChannelInfo[L]->pDynData->aSfbScale[window*16];
|
||||
SHORT *rightScale = &pAacDecoderChannelInfo[R]->pDynData->aSfbScale[window*16];
|
||||
|
||||
leftSpectrum = SPEC(pAacDecoderChannelInfo[L]->pSpectralCoefficient, window, pAacDecoderChannelInfo[L]->granuleLength);
|
||||
rightSpectrum = SPEC(pAacDecoderChannelInfo[R]->pSpectralCoefficient, window, pAacDecoderChannelInfo[R]->granuleLength);
|
||||
|
||||
for (band=0; band<scaleFactorBandsTransmitted; band++)
|
||||
{
|
||||
if (pJointStereoData->MsUsed[band] & groupMask)
|
||||
{
|
||||
int lScale=leftScale[band];
|
||||
int rScale=rightScale[band];
|
||||
int commonScale=lScale > rScale ? lScale:rScale;
|
||||
|
||||
/* ISO/IEC 14496-3 Chapter 4.6.8.1.1 :
|
||||
M/S joint channel coding can only be used if common_window is ‘1’. */
|
||||
FDK_ASSERT(GetWindowSequence(&pAacDecoderChannelInfo[L]->icsInfo) == GetWindowSequence(&pAacDecoderChannelInfo[R]->icsInfo));
|
||||
FDK_ASSERT(GetWindowShape(&pAacDecoderChannelInfo[L]->icsInfo) == GetWindowShape(&pAacDecoderChannelInfo[R]->icsInfo));
|
||||
|
||||
commonScale++;
|
||||
leftScale[band]=commonScale;
|
||||
rightScale[band]=commonScale;
|
||||
|
||||
lScale = fMin(DFRACT_BITS-1, commonScale - lScale);
|
||||
rScale = fMin(DFRACT_BITS-1, commonScale - rScale);
|
||||
|
||||
FDK_ASSERT(lScale >= 0 && rScale >= 0);
|
||||
|
||||
for (int index=pScaleFactorBandOffsets[band]; index<pScaleFactorBandOffsets[band+1]; index++)
|
||||
{
|
||||
FIXP_DBL leftCoefficient = leftSpectrum [index] ;
|
||||
FIXP_DBL rightCoefficient = rightSpectrum [index] ;
|
||||
|
||||
leftCoefficient >>= lScale ;
|
||||
rightCoefficient >>= rScale ;
|
||||
|
||||
leftSpectrum [index] = leftCoefficient + rightCoefficient ;
|
||||
rightSpectrum [index] = leftCoefficient - rightCoefficient ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset MsUsed flags if no explicit signalling was transmitted. Necessary for intensity coding.
|
||||
PNS correlation signalling was mapped before calling CJointStereo_ApplyMS(). */
|
||||
if (pJointStereoData->MsMaskPresent == 2) {
|
||||
FDKmemclear(pJointStereoData->MsUsed, JointStereoMaximumBands * sizeof(UCHAR));
|
||||
}
|
||||
}
|
||||
|
||||
void CJointStereo_ApplyIS(
|
||||
CAacDecoderChannelInfo *pAacDecoderChannelInfo[2],
|
||||
const SHORT *pScaleFactorBandOffsets,
|
||||
const UCHAR *pWindowGroupLength,
|
||||
const int windowGroups,
|
||||
const int scaleFactorBandsTransmitted,
|
||||
const UINT CommonWindow
|
||||
)
|
||||
{
|
||||
CJointStereoData *pJointStereoData = &pAacDecoderChannelInfo[L]->pComData->jointStereoData;
|
||||
|
||||
for (int window=0,group=0; group<windowGroups; group++)
|
||||
{
|
||||
UCHAR *CodeBook;
|
||||
SHORT *ScaleFactor;
|
||||
UCHAR groupMask = 1 << group;
|
||||
|
||||
CodeBook = &pAacDecoderChannelInfo[R]->pDynData->aCodeBook[group*16];
|
||||
ScaleFactor = &pAacDecoderChannelInfo[R]->pDynData->aScaleFactor[group*16];
|
||||
|
||||
for (int groupwin=0; groupwin<pWindowGroupLength[group]; groupwin++, window++)
|
||||
{
|
||||
FIXP_DBL *leftSpectrum, *rightSpectrum;
|
||||
SHORT *leftScale = &pAacDecoderChannelInfo[L]->pDynData->aSfbScale[window*16];
|
||||
SHORT *rightScale = &pAacDecoderChannelInfo[R]->pDynData->aSfbScale[window*16];
|
||||
int band;
|
||||
|
||||
leftSpectrum = SPEC(pAacDecoderChannelInfo[L]->pSpectralCoefficient, window, pAacDecoderChannelInfo[L]->granuleLength);
|
||||
rightSpectrum = SPEC(pAacDecoderChannelInfo[R]->pSpectralCoefficient, window, pAacDecoderChannelInfo[R]->granuleLength);
|
||||
|
||||
for (band=0; band<scaleFactorBandsTransmitted; band++)
|
||||
{
|
||||
if ((CodeBook [band] == INTENSITY_HCB) ||
|
||||
(CodeBook [band] == INTENSITY_HCB2))
|
||||
{
|
||||
int bandScale = -(ScaleFactor [band] + 100) ;
|
||||
|
||||
int msb = bandScale >> 2 ;
|
||||
int lsb = bandScale & 0x03 ;
|
||||
|
||||
/* exponent of MantissaTable[lsb][0] is 1, thus msb+1 below. */
|
||||
FIXP_DBL scale = MantissaTable[lsb][0];
|
||||
|
||||
/* ISO/IEC 14496-3 Chapter 4.6.8.2.3 :
|
||||
The use of intensity stereo coding is signaled by the use of the pseudo codebooks
|
||||
INTENSITY_HCB and INTENSITY_HCB2 (15 and 14) only in the right channel of a
|
||||
channel_pair_element() having a common ics_info() (common_window == 1). */
|
||||
FDK_ASSERT(GetWindowSequence(&pAacDecoderChannelInfo[L]->icsInfo) == GetWindowSequence(&pAacDecoderChannelInfo[R]->icsInfo));
|
||||
FDK_ASSERT(GetWindowShape(&pAacDecoderChannelInfo[L]->icsInfo) == GetWindowShape(&pAacDecoderChannelInfo[R]->icsInfo));
|
||||
|
||||
rightScale[band] = leftScale[band]+msb+1;
|
||||
|
||||
if (CommonWindow && (pJointStereoData->MsUsed[band] & groupMask))
|
||||
{
|
||||
|
||||
if (CodeBook[band] == INTENSITY_HCB) /* _NOT_ in-phase */
|
||||
{
|
||||
scale = -scale ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CodeBook[band] == INTENSITY_HCB2) /* out-of-phase */
|
||||
{
|
||||
scale = -scale ;
|
||||
}
|
||||
}
|
||||
|
||||
for (int index=pScaleFactorBandOffsets[band]; index<pScaleFactorBandOffsets[band+1]; index++)
|
||||
{
|
||||
rightSpectrum[index] = fMult(leftSpectrum[index],scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
72
libAACdec/src/stereo.h
Normal file
72
libAACdec/src/stereo.h
Normal file
@ -0,0 +1,72 @@
|
||||
/***************************** MPEG-4 AAC Decoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2004)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): Josef Hoepfl
|
||||
Description: joint stereo processing
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef STEREO_H
|
||||
#define STEREO_H
|
||||
|
||||
|
||||
|
||||
#include "machine_type.h"
|
||||
#include "FDK_bitstream.h"
|
||||
|
||||
enum
|
||||
{
|
||||
JointStereoMaximumGroups = 8,
|
||||
JointStereoMaximumBands = 64
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UCHAR MsMaskPresent;
|
||||
UCHAR MsUsed[JointStereoMaximumBands]; /*!< every arry element contains flags for up to 8 groups */
|
||||
} CJointStereoData;
|
||||
|
||||
|
||||
/*!
|
||||
\brief Read joint stereo data from bitstream
|
||||
|
||||
The function reads joint stereo data from bitstream.
|
||||
|
||||
\param bs bit stream handle data source.
|
||||
\param pJointStereoData pointer to stereo data structure to receive decoded data.
|
||||
\param windowGroups number of window groups.
|
||||
\param scaleFactorBandsTransmitted number of transmitted scalefactor bands.
|
||||
\param flags decoder flags
|
||||
|
||||
\return 0 on success, -1 on error.
|
||||
*/
|
||||
int CJointStereo_Read(
|
||||
HANDLE_FDK_BITSTREAM bs,
|
||||
CJointStereoData *pJointStereoData,
|
||||
int windowGroups,
|
||||
int scaleFactorBandsTransmitted,
|
||||
UINT flags
|
||||
);
|
||||
|
||||
|
||||
#endif /* #ifndef STEREO_H */
|
1
libAACenc/Android.mk
Normal file
1
libAACenc/Android.mk
Normal file
@ -0,0 +1 @@
|
||||
include $(call all-subdir-makefiles)
|
1150
libAACenc/include/aacenc_lib.h
Normal file
1150
libAACenc/include/aacenc_lib.h
Normal file
File diff suppressed because it is too large
Load Diff
53
libAACenc/src/Android.mk
Normal file
53
libAACenc/src/Android.mk
Normal file
@ -0,0 +1,53 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := \
|
||||
aacenc.cpp \
|
||||
aacEnc_ram.cpp \
|
||||
band_nrg.cpp \
|
||||
block_switch.cpp \
|
||||
grp_data.cpp \
|
||||
metadata_main.cpp \
|
||||
pre_echo_control.cpp \
|
||||
quantize.cpp \
|
||||
tonality.cpp \
|
||||
aacenc_hcr.cpp \
|
||||
aacEnc_rom.cpp \
|
||||
bandwidth.cpp \
|
||||
channel_map.cpp \
|
||||
intensity.cpp \
|
||||
ms_stereo.cpp \
|
||||
psy_configuration.cpp \
|
||||
sf_estim.cpp \
|
||||
transform.cpp \
|
||||
aacenc_lib.cpp \
|
||||
aacenc_tns.cpp \
|
||||
bit_cnt.cpp \
|
||||
chaosmeasure.cpp \
|
||||
line_pe.cpp \
|
||||
noisedet.cpp \
|
||||
psy_main.cpp \
|
||||
spreading.cpp \
|
||||
aacenc_pns.cpp \
|
||||
adj_thr.cpp \
|
||||
bitenc.cpp \
|
||||
dyn_bits.cpp \
|
||||
metadata_compressor.cpp \
|
||||
pnsparam.cpp \
|
||||
qc_main.cpp \
|
||||
tns_param.cpp
|
||||
|
||||
LOCAL_CFLAGS := -DANDROID
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(LOCAL_PATH) \
|
||||
$(LOCAL_PATH)/../include \
|
||||
$(LOCAL_PATH)/../../libPCMutils/include \
|
||||
$(LOCAL_PATH)/../../libFDK/include \
|
||||
$(LOCAL_PATH)/../../libSYS/include \
|
||||
$(LOCAL_PATH)/../../libMpegTPEnc/include \
|
||||
$(LOCAL_PATH)/../../libSBRenc/include
|
||||
|
||||
LOCAL_MODULE:= libAACenc
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
132
libAACenc/src/aacEnc_ram.cpp
Normal file
132
libAACenc/src/aacEnc_ram.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
/******************************************************************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2005)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id:
|
||||
Initial authors: M. Lohwasser, M. Gayer
|
||||
Contents/description:
|
||||
|
||||
******************************************************************************/
|
||||
/*!
|
||||
\file
|
||||
\brief Memory layout $Revision: 36838 $
|
||||
\author Markus Lohwasser
|
||||
*/
|
||||
|
||||
#include "aacEnc_ram.h"
|
||||
|
||||
C_ALLOC_MEM (AACdynamic_RAM, FIXP_DBL, AAC_ENC_DYN_RAM_SIZE/sizeof(FIXP_DBL))
|
||||
|
||||
/*
|
||||
Static memory areas, must not be overwritten in other sections of the decoder !
|
||||
*/
|
||||
|
||||
/*
|
||||
The structure AacEncoder contains all Encoder structures.
|
||||
*/
|
||||
|
||||
C_ALLOC_MEM (Ram_aacEnc_AacEncoder, AAC_ENC, 1)
|
||||
|
||||
|
||||
/*
|
||||
The structure PSY_INTERNAl contains all psych configuration and data pointer.
|
||||
* PsyStatic holds last and current Psych data.
|
||||
* PsyInputBuffer contains time input. Signal is needed at the beginning of Psych.
|
||||
Memory can be reused after signal is in time domain.
|
||||
* PsyData contains spectral, nrg and threshold information. Necessary data are
|
||||
copied into PsyOut, so memory is available after leaving psych.
|
||||
* TnsData, ChaosMeasure, PnsData are temporarily necessary, e.g. use memory from
|
||||
PsyInputBuffer.
|
||||
*/
|
||||
|
||||
C_ALLOC_MEM2 (Ram_aacEnc_PsyElement, PSY_ELEMENT, 1, (6))
|
||||
|
||||
C_ALLOC_MEM (Ram_aacEnc_PsyInternal, PSY_INTERNAL, 1)
|
||||
C_ALLOC_MEM2 (Ram_aacEnc_PsyStatic, PSY_STATIC, 1, (6))
|
||||
|
||||
C_ALLOC_MEM2 (Ram_aacEnc_PsyInputBuffer, INT_PCM, MAX_INPUT_BUFFER_SIZE, (6))
|
||||
|
||||
PSY_DYNAMIC *GetRam_aacEnc_PsyDynamic (int n, UCHAR* dynamic_RAM) {
|
||||
FDK_ASSERT(dynamic_RAM!=0);
|
||||
return ((PSY_DYNAMIC*) (dynamic_RAM + P_BUF_1 + n*sizeof(PSY_DYNAMIC)));
|
||||
}
|
||||
|
||||
C_ALLOC_MEM (Ram_bsOutbuffer, UCHAR, OUTPUTBUFFER_SIZE)
|
||||
|
||||
/*
|
||||
The structure PSY_OUT holds all psychoaccoustic data needed
|
||||
in quantization module
|
||||
*/
|
||||
C_ALLOC_MEM2 (Ram_aacEnc_PsyOut, PSY_OUT, 1, (1))
|
||||
|
||||
C_ALLOC_MEM2 (Ram_aacEnc_PsyOutElements, PSY_OUT_ELEMENT, 1, (1)*(6))
|
||||
C_ALLOC_MEM2 (Ram_aacEnc_PsyOutChannel, PSY_OUT_CHANNEL, 1, (1)*(6))
|
||||
|
||||
|
||||
/*
|
||||
The structure QC_STATE contains preinitialized settings and quantizer structures.
|
||||
* AdjustThreshold structure contains element-wise settings.
|
||||
* ElementBits contains elemnt-wise bit consumption settings.
|
||||
* When CRC is active, lookup table is necessary for fast crc calculation.
|
||||
* Bitcounter contains buffer to find optimal codebooks and minimal bit consumption.
|
||||
Values are temporarily, so dynamic memory can be used.
|
||||
*/
|
||||
|
||||
C_ALLOC_MEM (Ram_aacEnc_QCstate, QC_STATE, 1)
|
||||
C_ALLOC_MEM (Ram_aacEnc_AdjustThreshold, ADJ_THR_STATE, 1)
|
||||
|
||||
C_ALLOC_MEM2 (Ram_aacEnc_AdjThrStateElement, ATS_ELEMENT, 1, (6))
|
||||
C_ALLOC_MEM2 (Ram_aacEnc_ElementBits, ELEMENT_BITS, 1, (6))
|
||||
C_ALLOC_MEM (Ram_aacEnc_BitCntrState, BITCNTR_STATE, 1)
|
||||
|
||||
INT *GetRam_aacEnc_BitLookUp(int n, UCHAR* dynamic_RAM) {
|
||||
FDK_ASSERT(dynamic_RAM!=0);
|
||||
return ((INT*) (dynamic_RAM + P_BUF_1));
|
||||
}
|
||||
INT *GetRam_aacEnc_MergeGainLookUp(int n, UCHAR* dynamic_RAM) {
|
||||
FDK_ASSERT(dynamic_RAM!=0);
|
||||
return ((INT*) (dynamic_RAM + P_BUF_1 + sizeof(INT)*(MAX_SFB_LONG*(CODE_BOOK_ESC_NDX+1))));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
The structure QC_OUT contains settings and structures holding all necessary information
|
||||
needed in bitstreamwriter.
|
||||
*/
|
||||
|
||||
C_ALLOC_MEM2 (Ram_aacEnc_QCout, QC_OUT, 1, (1))
|
||||
C_ALLOC_MEM2 (Ram_aacEnc_QCelement, QC_OUT_ELEMENT, 1, (1)*(6))
|
||||
QC_OUT_CHANNEL *GetRam_aacEnc_QCchannel (int n, UCHAR* dynamic_RAM) {
|
||||
FDK_ASSERT(dynamic_RAM!=0);
|
||||
return ((QC_OUT_CHANNEL*) (dynamic_RAM + P_BUF_0 + n*sizeof(QC_OUT_CHANNEL)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
163
libAACenc/src/aacEnc_ram.h
Normal file
163
libAACenc/src/aacEnc_ram.h
Normal file
@ -0,0 +1,163 @@
|
||||
/******************************************************************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2005)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id:
|
||||
Initial authors: M. Lohwasser, M. Gayer
|
||||
Contents/description:
|
||||
|
||||
******************************************************************************/
|
||||
/*!
|
||||
\file
|
||||
\brief Memory layout $Revision: 36838 $
|
||||
\author Markus Lohwasser
|
||||
*/
|
||||
|
||||
#ifndef AAC_ENC_RAM_H
|
||||
#define AAC_ENC_RAM_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "aacenc.h"
|
||||
#include "psy_data.h"
|
||||
#include "interface.h"
|
||||
#include "psy_main.h"
|
||||
#include "bitenc.h"
|
||||
#include "bit_cnt.h"
|
||||
#include "psy_const.h"
|
||||
|
||||
#define OUTPUTBUFFER_SIZE (8192) /*!< Output buffer size has to be at least 6144 bits per channel (768 bytes). FDK bitbuffer implementation expects buffer of size 2^n. */
|
||||
|
||||
|
||||
/*
|
||||
Moved AAC_ENC struct definition from aac_enc.cpp into aacEnc_ram.h to get size and respective
|
||||
static memory in aacEnc_ram.cpp.
|
||||
aac_enc.h is the outward visible header file and putting the struct into would cause necessity
|
||||
of additional visible header files outside library.
|
||||
*/
|
||||
|
||||
/* define hBitstream size: max AAC framelength is 6144 bits/channel */
|
||||
/*#define BUFFER_BITSTR_SIZE ((6400*(6)/bbWordSize) +((bbWordSize - 1) / bbWordSize))*/
|
||||
|
||||
struct AAC_ENC {
|
||||
|
||||
AACENC_CONFIG *config;
|
||||
|
||||
INT ancillaryBitsPerFrame; /* ancillary bits per frame calculated from ancillary rate */
|
||||
|
||||
CHANNEL_MAPPING channelMapping;
|
||||
|
||||
QC_STATE *qcKernel;
|
||||
QC_OUT *qcOut[(1)];
|
||||
|
||||
PSY_OUT *psyOut[(1)];
|
||||
PSY_INTERNAL *psyKernel;
|
||||
|
||||
/* lifetime vars */
|
||||
|
||||
CHANNEL_MODE encoderMode;
|
||||
INT bandwidth90dB;
|
||||
AACENC_BITRATE_MODE bitrateMode;
|
||||
|
||||
INT dontWriteAdif; /* use: write ADIF header only before 1st frame */
|
||||
|
||||
FIXP_DBL *dynamic_RAM;
|
||||
|
||||
|
||||
INT maxChannels; /* used while allocation */
|
||||
INT maxElements;
|
||||
INT maxFrames;
|
||||
|
||||
AUDIO_OBJECT_TYPE aot; /* AOT to be used while encoding. */
|
||||
|
||||
} ;
|
||||
|
||||
#define maxSize(a,b) ( ((a)>(b)) ? (a) : (b) )
|
||||
|
||||
#define BIT_LOOK_UP_SIZE ( sizeof(INT)*(MAX_SFB_LONG*(CODE_BOOK_ESC_NDX+1)) )
|
||||
#define MERGE_GAIN_LOOK_UP_SIZE ( sizeof(INT)*MAX_SFB_LONG )
|
||||
|
||||
|
||||
|
||||
/* Dynamic RAM - Allocation */
|
||||
/*
|
||||
++++++++++++++++++++++++++++++++++++++++++++
|
||||
| P_BUF_0 | P_BUF_1 |
|
||||
++++++++++++++++++++++++++++++++++++++++++++
|
||||
| QC_OUT_CH | PSY_DYN |
|
||||
++++++++++++++++++++++++++++++++++++++++++++
|
||||
| | BitLookUp+MergeGainLookUp |
|
||||
++++++++++++++++++++++++++++++++++++++++++++
|
||||
| | Bitstream output buffer |
|
||||
++++++++++++++++++++++++++++++++++++++++++++
|
||||
*/
|
||||
|
||||
#define BUF_SIZE_0 ( ALIGN_SIZE(sizeof(QC_OUT_CHANNEL)*(6)) )
|
||||
#define BUF_SIZE_1 ( ALIGN_SIZE(maxSize(sizeof(PSY_DYNAMIC), \
|
||||
(BIT_LOOK_UP_SIZE+MERGE_GAIN_LOOK_UP_SIZE))) )
|
||||
|
||||
#define P_BUF_0 ( 0 )
|
||||
#define P_BUF_1 ( P_BUF_0 + BUF_SIZE_0 )
|
||||
|
||||
#define AAC_ENC_DYN_RAM_SIZE ( BUF_SIZE_0 + BUF_SIZE_1 )
|
||||
|
||||
|
||||
H_ALLOC_MEM (AACdynamic_RAM, FIXP_DBL)
|
||||
/*
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
END - Dynamic RAM - Allocation */
|
||||
|
||||
/*
|
||||
See further Memory Allocation details in aacEnc_ram.cpp
|
||||
*/
|
||||
H_ALLOC_MEM (Ram_aacEnc_AacEncoder, AAC_ENC)
|
||||
|
||||
H_ALLOC_MEM (Ram_aacEnc_PsyElement, PSY_ELEMENT)
|
||||
|
||||
H_ALLOC_MEM (Ram_aacEnc_PsyInternal, PSY_INTERNAL)
|
||||
H_ALLOC_MEM (Ram_aacEnc_PsyStatic, PSY_STATIC)
|
||||
H_ALLOC_MEM (Ram_aacEnc_PsyInputBuffer, INT_PCM)
|
||||
|
||||
PSY_DYNAMIC *GetRam_aacEnc_PsyDynamic (int n, UCHAR* dynamic_RAM);
|
||||
H_ALLOC_MEM (Ram_bsOutbuffer, UCHAR)
|
||||
|
||||
H_ALLOC_MEM (Ram_aacEnc_PsyOutChannel, PSY_OUT_CHANNEL)
|
||||
|
||||
H_ALLOC_MEM (Ram_aacEnc_PsyOut, PSY_OUT)
|
||||
H_ALLOC_MEM (Ram_aacEnc_PsyOutElements, PSY_OUT_ELEMENT)
|
||||
|
||||
H_ALLOC_MEM (Ram_aacEnc_QCstate, QC_STATE)
|
||||
H_ALLOC_MEM (Ram_aacEnc_AdjustThreshold, ADJ_THR_STATE)
|
||||
|
||||
H_ALLOC_MEM (Ram_aacEnc_AdjThrStateElement, ATS_ELEMENT)
|
||||
H_ALLOC_MEM (Ram_aacEnc_ElementBits, ELEMENT_BITS)
|
||||
H_ALLOC_MEM (Ram_aacEnc_BitCntrState, BITCNTR_STATE)
|
||||
|
||||
INT *GetRam_aacEnc_BitLookUp(int n, UCHAR* dynamic_RAM);
|
||||
INT *GetRam_aacEnc_MergeGainLookUp(int n, UCHAR* dynamic_RAM);
|
||||
QC_OUT_CHANNEL *GetRam_aacEnc_QCchannel (int n, UCHAR* dynamic_RAM);
|
||||
|
||||
H_ALLOC_MEM (Ram_aacEnc_QCout, QC_OUT)
|
||||
H_ALLOC_MEM (Ram_aacEnc_QCelement, QC_OUT_ELEMENT)
|
||||
|
||||
|
||||
#endif /* #ifndef AAC_ENC_RAM_H */
|
||||
|
1170
libAACenc/src/aacEnc_rom.cpp
Normal file
1170
libAACenc/src/aacEnc_rom.cpp
Normal file
File diff suppressed because it is too large
Load Diff
141
libAACenc/src/aacEnc_rom.h
Normal file
141
libAACenc/src/aacEnc_rom.h
Normal file
@ -0,0 +1,141 @@
|
||||
/******************************************************************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2005)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id:
|
||||
Initial authors: M. Lohwasser, M. Gayer
|
||||
Contents/description:
|
||||
|
||||
******************************************************************************/
|
||||
/*!
|
||||
\file
|
||||
\brief Memory layout $Revision: 36838 $
|
||||
\author Markus Lohwasser
|
||||
*/
|
||||
|
||||
#ifndef AAC_ENC_ROM_H
|
||||
#define AAC_ENC_ROM_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "psy_const.h"
|
||||
#include "psy_configuration.h"
|
||||
#include "FDK_tools_rom.h"
|
||||
|
||||
/*
|
||||
Huffman Tables
|
||||
*/
|
||||
extern const INT FDKaacEnc_huff_ltab1_2[3][3][3][3];
|
||||
extern const INT FDKaacEnc_huff_ltab3_4[3][3][3][3];
|
||||
extern const INT FDKaacEnc_huff_ltab5_6[9][9];
|
||||
extern const INT FDKaacEnc_huff_ltab7_8[8][8];
|
||||
extern const INT FDKaacEnc_huff_ltab9_10[13][13];
|
||||
extern const UCHAR FDKaacEnc_huff_ltab11[17][17];
|
||||
extern const UCHAR FDKaacEnc_huff_ltabscf[121];
|
||||
extern const USHORT FDKaacEnc_huff_ctab1[3][3][3][3];
|
||||
extern const USHORT FDKaacEnc_huff_ctab2[3][3][3][3];
|
||||
extern const USHORT FDKaacEnc_huff_ctab3[3][3][3][3];
|
||||
extern const USHORT FDKaacEnc_huff_ctab4[3][3][3][3];
|
||||
extern const USHORT FDKaacEnc_huff_ctab5[9][9];
|
||||
extern const USHORT FDKaacEnc_huff_ctab6[9][9];
|
||||
extern const USHORT FDKaacEnc_huff_ctab7[8][8];
|
||||
extern const USHORT FDKaacEnc_huff_ctab8[8][8];
|
||||
extern const USHORT FDKaacEnc_huff_ctab9[13][13];
|
||||
extern const USHORT FDKaacEnc_huff_ctab10[13][13];
|
||||
extern const USHORT FDKaacEnc_huff_ctab11[21][17];
|
||||
extern const INT FDKaacEnc_huff_ctabscf[121];
|
||||
|
||||
/*
|
||||
quantizer
|
||||
*/
|
||||
#define MANT_DIGITS 9
|
||||
#define MANT_SIZE (1<<MANT_DIGITS)
|
||||
|
||||
#if defined(ARCH_PREFER_MULT_32x16)
|
||||
#define FIXP_QTD FIXP_SGL
|
||||
#define QTC FX_DBL2FXCONST_SGL
|
||||
#else
|
||||
#define FIXP_QTD FIXP_DBL
|
||||
#define QTC
|
||||
#endif
|
||||
|
||||
extern const FIXP_QTD FDKaacEnc_mTab_3_4[MANT_SIZE];
|
||||
extern const FIXP_QTD FDKaacEnc_quantTableQ[4];
|
||||
extern const FIXP_QTD FDKaacEnc_quantTableE[4];
|
||||
|
||||
extern const FIXP_DBL FDKaacEnc_mTab_4_3Elc[512];
|
||||
extern const FIXP_DBL FDKaacEnc_specExpMantTableCombElc[4][14];
|
||||
extern const UCHAR FDKaacEnc_specExpTableComb[4][14];
|
||||
|
||||
|
||||
/*
|
||||
table to count used number of bits
|
||||
*/
|
||||
extern const SHORT FDKaacEnc_sideInfoTabLong[MAX_SFB_LONG + 1];
|
||||
extern const SHORT FDKaacEnc_sideInfoTabShort[MAX_SFB_SHORT + 1];
|
||||
|
||||
|
||||
/*
|
||||
Psy Configuration constants
|
||||
*/
|
||||
extern const SFB_PARAM_LONG p_FDKaacEnc_8000_long_1024;
|
||||
extern const SFB_PARAM_SHORT p_FDKaacEnc_8000_short_128;
|
||||
extern const SFB_PARAM_LONG p_FDKaacEnc_11025_long_1024;
|
||||
extern const SFB_PARAM_SHORT p_FDKaacEnc_11025_short_128;
|
||||
extern const SFB_PARAM_LONG p_FDKaacEnc_12000_long_1024;
|
||||
extern const SFB_PARAM_SHORT p_FDKaacEnc_12000_short_128;
|
||||
extern const SFB_PARAM_LONG p_FDKaacEnc_16000_long_1024;
|
||||
extern const SFB_PARAM_SHORT p_FDKaacEnc_16000_short_128;
|
||||
extern const SFB_PARAM_LONG p_FDKaacEnc_22050_long_1024;
|
||||
extern const SFB_PARAM_SHORT p_FDKaacEnc_22050_short_128;
|
||||
extern const SFB_PARAM_LONG p_FDKaacEnc_24000_long_1024;
|
||||
extern const SFB_PARAM_SHORT p_FDKaacEnc_24000_short_128;
|
||||
extern const SFB_PARAM_LONG p_FDKaacEnc_32000_long_1024;
|
||||
extern const SFB_PARAM_SHORT p_FDKaacEnc_32000_short_128;
|
||||
extern const SFB_PARAM_LONG p_FDKaacEnc_44100_long_1024;
|
||||
extern const SFB_PARAM_SHORT p_FDKaacEnc_44100_short_128;
|
||||
extern const SFB_PARAM_LONG p_FDKaacEnc_48000_long_1024;
|
||||
extern const SFB_PARAM_SHORT p_FDKaacEnc_48000_short_128;
|
||||
extern const SFB_PARAM_LONG p_FDKaacEnc_64000_long_1024;
|
||||
extern const SFB_PARAM_SHORT p_FDKaacEnc_64000_short_128;
|
||||
extern const SFB_PARAM_LONG p_FDKaacEnc_88200_long_1024;
|
||||
extern const SFB_PARAM_SHORT p_FDKaacEnc_88200_short_128;
|
||||
extern const SFB_PARAM_LONG p_FDKaacEnc_96000_long_1024;
|
||||
extern const SFB_PARAM_SHORT p_FDKaacEnc_96000_short_128;
|
||||
|
||||
|
||||
/*
|
||||
TNS filter coefficients
|
||||
*/
|
||||
extern const FIXP_DBL FDKaacEnc_tnsEncCoeff3[8];
|
||||
extern const FIXP_DBL FDKaacEnc_tnsCoeff3Borders[8];
|
||||
extern const FIXP_DBL FDKaacEnc_tnsEncCoeff4[16];
|
||||
extern const FIXP_DBL FDKaacEnc_tnsCoeff4Borders[16];
|
||||
|
||||
#define WTC0 WTC
|
||||
#define WTC1 WTC
|
||||
#define WTC2 WTC
|
||||
|
||||
extern const FIXP_WTB ELDAnalysis512[1536];
|
||||
extern const FIXP_WTB ELDAnalysis480[1440];
|
||||
|
||||
|
||||
#endif /* #ifndef AAC_ENC_ROM_H */
|
952
libAACenc/src/aacenc.cpp
Normal file
952
libAACenc/src/aacenc.cpp
Normal file
@ -0,0 +1,952 @@
|
||||
/*************************** Fast MPEG AAC Audio Encoder **********************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M. Schug / A. Groeschel
|
||||
contents/description: fast aac coder functions
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "aacenc.h"
|
||||
|
||||
#include "bitenc.h"
|
||||
#include "interface.h"
|
||||
#include "psy_configuration.h"
|
||||
#include "psy_main.h"
|
||||
#include "qc_main.h"
|
||||
#include "bandwidth.h"
|
||||
#include "channel_map.h"
|
||||
#include "tns_func.h"
|
||||
#include "aacEnc_ram.h"
|
||||
|
||||
#include "genericStds.h"
|
||||
|
||||
|
||||
|
||||
|
||||
static AAC_ENCODER_ERROR FDKaacEnc_InitCheckAncillary(INT bitRate,
|
||||
INT framelength,
|
||||
INT ancillaryRate,
|
||||
INT *ancillaryBitsPerFrame,
|
||||
INT sampleRate);
|
||||
|
||||
/**
|
||||
* For calculating average bitrate of an access unit 32 bit data width is not sufficient
|
||||
* in worst case. Therefore use scaling of the samplingrate parameter to keep complete information.
|
||||
*/
|
||||
typedef struct {
|
||||
INT samplingRate;
|
||||
UCHAR scalingFactor;
|
||||
} SR_SCALING_TAB;
|
||||
|
||||
static const SR_SCALING_TAB samplingRateScalingTable[] =
|
||||
{
|
||||
{ 8000, 5 }, { 11025, 0 }, { 12000, 5 }, { 16000, 5 },
|
||||
{ 22050, 1 }, { 24000, 5 }, { 32000, 5 }, { 44100, 2 },
|
||||
{ 48000, 5 }, { 64000, 5 }, { 88200, 3 }, { 96000, 5 }
|
||||
};
|
||||
|
||||
/**
|
||||
* Get maximal scaling factor without losing samplingrate accuracy.
|
||||
*
|
||||
* \param samplingRate Samplingrate to be used.
|
||||
* \return scaling value.
|
||||
*/
|
||||
static int GetSrSf(const INT samplingRate)
|
||||
{
|
||||
int i, result = 0;
|
||||
|
||||
for (i=0; i<(int)(sizeof(samplingRateScalingTable)/sizeof(SR_SCALING_TAB)); i++) {
|
||||
if ( samplingRateScalingTable[i].samplingRate == samplingRate ) {
|
||||
result = samplingRateScalingTable[i].scalingFactor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#define MIN_BUFSIZE_PER_EFF_CHAN 6144
|
||||
|
||||
typedef struct
|
||||
{
|
||||
AACENC_BITRATE_MODE bitrateMode;
|
||||
int chanBitrate[2]; /* mono/stereo settings */
|
||||
} CONFIG_TAB_ENTRY_VBR;
|
||||
|
||||
static const CONFIG_TAB_ENTRY_VBR configTabVBR[] = {
|
||||
{AACENC_BR_MODE_CBR, { 0, 0}} ,
|
||||
{AACENC_BR_MODE_VBR_1, { 32000, 20000}} ,
|
||||
{AACENC_BR_MODE_VBR_2, { 40000, 32000}} ,
|
||||
{AACENC_BR_MODE_VBR_3, { 56000, 48000}} ,
|
||||
{AACENC_BR_MODE_VBR_4, { 72000, 64000}} ,
|
||||
{AACENC_BR_MODE_VBR_5, {112000, 96000}}
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
|
||||
functionname: FDKaacEnc_GetVBRBitrate
|
||||
description: Get VBR bitrate from vbr quality
|
||||
input params: int vbrQuality (VBR0, VBR1, VBR2)
|
||||
channelMode
|
||||
returns: vbr bitrate
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
INT FDKaacEnc_GetVBRBitrate(INT bitrateMode, CHANNEL_MODE channelMode)
|
||||
{
|
||||
INT bitrate = 0;
|
||||
INT monoStereoMode = 0; /* default mono */
|
||||
|
||||
if (FDKaacEnc_GetMonoStereoMode(channelMode)==EL_MODE_STEREO) {
|
||||
monoStereoMode = 1;
|
||||
}
|
||||
|
||||
switch((AACENC_BITRATE_MODE)bitrateMode){
|
||||
case AACENC_BR_MODE_VBR_1:
|
||||
case AACENC_BR_MODE_VBR_2:
|
||||
case AACENC_BR_MODE_VBR_3:
|
||||
case AACENC_BR_MODE_VBR_4:
|
||||
case AACENC_BR_MODE_VBR_5:
|
||||
bitrate = configTabVBR[bitrateMode].chanBitrate[monoStereoMode];
|
||||
break;
|
||||
case AACENC_BR_MODE_INVALID:
|
||||
case AACENC_BR_MODE_CBR:
|
||||
case AACENC_BR_MODE_SFR:
|
||||
case AACENC_BR_MODE_FF:
|
||||
default:
|
||||
bitrate = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* convert channel bitrate to overall bitrate*/
|
||||
bitrate *= FDKaacEnc_GetChannelModeConfiguration(channelMode)->nChannelsEff;
|
||||
|
||||
return bitrate;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert encoder bitreservoir value for transport library.
|
||||
*
|
||||
* \param bitrateMode Bitratemode used in current encoder instance. Se ::AACENC_BITRATE_MODE
|
||||
* \param bitresTotal Encoder bitreservoir level in bits.
|
||||
*
|
||||
* \return Corrected bitreservoir level used in transport library.
|
||||
*/
|
||||
static INT FDKaacEnc_EncBitresToTpBitres(
|
||||
const AACENC_BITRATE_MODE bitrateMode,
|
||||
const INT bitresTotal
|
||||
)
|
||||
{
|
||||
INT transporBitreservoir = 0;
|
||||
|
||||
switch (bitrateMode) {
|
||||
case AACENC_BR_MODE_CBR:
|
||||
transporBitreservoir = bitresTotal; /* encoder bitreservoir level */
|
||||
break;
|
||||
case AACENC_BR_MODE_VBR_1:
|
||||
case AACENC_BR_MODE_VBR_2:
|
||||
case AACENC_BR_MODE_VBR_3:
|
||||
case AACENC_BR_MODE_VBR_4:
|
||||
case AACENC_BR_MODE_VBR_5:
|
||||
transporBitreservoir = FDK_INT_MAX; /* signal variable bitrate */
|
||||
break;
|
||||
case AACENC_BR_MODE_FF:
|
||||
case AACENC_BR_MODE_SFR:
|
||||
transporBitreservoir = 0; /* super framing and fixed framing */
|
||||
break; /* without bitreservoir signaling */
|
||||
default:
|
||||
case AACENC_BR_MODE_INVALID:
|
||||
transporBitreservoir = 0; /* invalid configuration*/
|
||||
FDK_ASSERT(0);
|
||||
}
|
||||
|
||||
return transporBitreservoir;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
|
||||
functionname: FDKaacEnc_AacInitDefaultConfig
|
||||
description: gives reasonable default configuration
|
||||
returns: ---
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
void FDKaacEnc_AacInitDefaultConfig(AACENC_CONFIG *config)
|
||||
{
|
||||
/* make thepre initialization of the structs flexible */
|
||||
FDKmemclear(config, sizeof(AACENC_CONFIG));
|
||||
|
||||
/* default ancillary */
|
||||
config->anc_Rate = 0; /* no ancillary data */
|
||||
config->ancDataBitRate = 0; /* no additional consumed bitrate */
|
||||
|
||||
/* default configurations */
|
||||
config->bitRate = -1; /* bitrate must be set*/
|
||||
config->averageBits = -1; /* instead of bitrate/s we can configure bits/superframe */
|
||||
config->bitrateMode = 0;
|
||||
config->bandWidth = 0; /* get bandwidth from table */
|
||||
config->useTns = TNS_ENABLE_MASK; /* tns enabled completly */
|
||||
config->usePns = 1; /* depending on channelBitrate this might be set to 0 later */
|
||||
config->useIS = 1; /* Intensity Stereo Configuration */
|
||||
config->framelength = DEFAULT_FRAMELENGTH; /* used frame size */
|
||||
config->syntaxFlags = 0; /* default syntax with no specialities */
|
||||
config->epConfig = -1; /* no ER syntax -> no additional error protection */
|
||||
config->nSubFrames = 1; /* default, no sub frames */
|
||||
config->channelOrder = CH_ORDER_MPEG; /* Use MPEG channel ordering. */
|
||||
config->channelMode = MODE_UNKNOWN;
|
||||
config->minBitsPerFrame = -1; /* minum number of bits in each AU */
|
||||
config->maxBitsPerFrame = -1; /* minum number of bits in each AU */
|
||||
config->bitreservoir = -1; /* default, uninitialized value */
|
||||
|
||||
/* init tabs in fixpoint_math */
|
||||
InitLdInt();
|
||||
InitInvSqrtTab();
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
functionname: FDKaacEnc_Open
|
||||
description: allocate and initialize a new encoder instance
|
||||
returns: error code
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
AAC_ENCODER_ERROR FDKaacEnc_Open(HANDLE_AAC_ENC *phAacEnc,
|
||||
const INT nElements,
|
||||
const INT nChannels,
|
||||
const INT nSubFrames)
|
||||
{
|
||||
AAC_ENCODER_ERROR ErrorStatus;
|
||||
AAC_ENC *hAacEnc = NULL;
|
||||
UCHAR *dynamicRAM = NULL;
|
||||
|
||||
if (phAacEnc==NULL) {
|
||||
return AAC_ENC_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/* allocate encoder structure */
|
||||
hAacEnc = GetRam_aacEnc_AacEncoder();
|
||||
if (hAacEnc == NULL) {
|
||||
ErrorStatus = AAC_ENC_NO_MEMORY;
|
||||
goto bail;
|
||||
}
|
||||
FDKmemclear(hAacEnc, sizeof(AAC_ENC));
|
||||
|
||||
hAacEnc->dynamic_RAM = GetAACdynamic_RAM();
|
||||
dynamicRAM = (UCHAR*)hAacEnc->dynamic_RAM;
|
||||
|
||||
/* allocate the Psy aud Psy Out structure */
|
||||
ErrorStatus = FDKaacEnc_PsyNew(&hAacEnc->psyKernel,
|
||||
nElements,
|
||||
nChannels
|
||||
,dynamicRAM
|
||||
);
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
goto bail;
|
||||
|
||||
ErrorStatus = FDKaacEnc_PsyOutNew(hAacEnc->psyOut,
|
||||
nElements,
|
||||
nChannels,
|
||||
nSubFrames
|
||||
,dynamicRAM
|
||||
);
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
goto bail;
|
||||
|
||||
/* allocate the Q&C Out structure */
|
||||
ErrorStatus = FDKaacEnc_QCOutNew(hAacEnc->qcOut,
|
||||
nElements,
|
||||
nChannels,
|
||||
nSubFrames
|
||||
,dynamicRAM
|
||||
);
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
goto bail;
|
||||
|
||||
/* allocate the Q&C kernel */
|
||||
ErrorStatus = FDKaacEnc_QCNew(&hAacEnc->qcKernel,
|
||||
nElements
|
||||
,dynamicRAM
|
||||
);
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
goto bail;
|
||||
|
||||
hAacEnc->maxChannels = nChannels;
|
||||
hAacEnc->maxElements = nElements;
|
||||
hAacEnc->maxFrames = nSubFrames;
|
||||
|
||||
bail:
|
||||
*phAacEnc = hAacEnc;
|
||||
return ErrorStatus;
|
||||
}
|
||||
|
||||
|
||||
AAC_ENCODER_ERROR FDKaacEnc_Initialize(HANDLE_AAC_ENC hAacEnc,
|
||||
AACENC_CONFIG *config, /* pre-initialized config struct */
|
||||
HANDLE_TRANSPORTENC hTpEnc,
|
||||
ULONG initFlags)
|
||||
{
|
||||
AAC_ENCODER_ERROR ErrorStatus;
|
||||
INT psyBitrate, tnsMask; //INT profile = 1;
|
||||
CHANNEL_MAPPING *cm = NULL;
|
||||
|
||||
INT qmbfac, qbw;
|
||||
FIXP_DBL mbfac, bw_ratio;
|
||||
QC_INIT qcInit;
|
||||
INT averageBitsPerFrame = 0;
|
||||
|
||||
if (config==NULL)
|
||||
return AAC_ENC_INVALID_HANDLE;
|
||||
|
||||
/******************* sanity checks *******************/
|
||||
|
||||
/* check config structure */
|
||||
if (config->nChannels < 1 || config->nChannels > (6)) {
|
||||
return AAC_ENC_UNSUPPORTED_CHANNELCONFIG;
|
||||
}
|
||||
|
||||
/* check sample rate */
|
||||
switch (config->sampleRate)
|
||||
{
|
||||
case 8000:
|
||||
case 11025:
|
||||
case 12000:
|
||||
case 16000:
|
||||
case 22050:
|
||||
case 24000:
|
||||
case 32000:
|
||||
case 44100:
|
||||
case 48000:
|
||||
case 64000:
|
||||
case 88200:
|
||||
case 96000:
|
||||
break;
|
||||
default:
|
||||
return AAC_ENC_UNSUPPORTED_SAMPLINGRATE;
|
||||
}
|
||||
|
||||
/* bitrate has to be set */
|
||||
if (config->bitRate==-1) {
|
||||
return AAC_ENC_UNSUPPORTED_BITRATE;
|
||||
}
|
||||
|
||||
/* check bit rate */
|
||||
|
||||
/* check if bitRate is not too low or high */
|
||||
averageBitsPerFrame = (config->bitRate*(config->framelength>>GetSrSf(config->sampleRate))) / (config->sampleRate>>GetSrSf(config->sampleRate)) / config->nSubFrames;
|
||||
|
||||
/* assume minimum static bits of 40 in each channel. */
|
||||
if ( (averageBitsPerFrame <= ((40*config->nChannels) + transportEnc_GetStaticBits(hTpEnc, averageBitsPerFrame))) ||
|
||||
( ((config->bitRate*(config->framelength>>GetSrSf(config->sampleRate)))) >
|
||||
((FDKaacEnc_GetChannelModeConfiguration(config->channelMode)->nChannelsEff * MIN_BUFSIZE_PER_EFF_CHAN))*(config->sampleRate>>GetSrSf(config->sampleRate)) )
|
||||
)
|
||||
{
|
||||
return AAC_ENC_UNSUPPORTED_BITRATE;
|
||||
}
|
||||
|
||||
if (config->syntaxFlags & AC_ER_VCB11) {
|
||||
return AAC_ENC_UNSUPPORTED_ER_FORMAT;
|
||||
}
|
||||
if (config->syntaxFlags & AC_ER_HCR) {
|
||||
return AAC_ENC_UNSUPPORTED_ER_FORMAT;
|
||||
}
|
||||
|
||||
/* check frame length */
|
||||
switch (config->framelength)
|
||||
{
|
||||
case 1024:
|
||||
if ( config->audioObjectType != AOT_AAC_LC
|
||||
&& config->audioObjectType != AOT_SBR
|
||||
&& config->audioObjectType != AOT_PS
|
||||
&& config->audioObjectType != AOT_ER_AAC_LC
|
||||
&& config->audioObjectType != AOT_AAC_SCAL )
|
||||
{
|
||||
return AAC_ENC_INVALID_FRAME_LENGTH;
|
||||
}
|
||||
break;
|
||||
case 512:
|
||||
case 480:
|
||||
if ( config->audioObjectType != AOT_ER_AAC_LD
|
||||
&& config->audioObjectType != AOT_ER_AAC_ELD )
|
||||
{
|
||||
return AAC_ENC_INVALID_FRAME_LENGTH;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return AAC_ENC_INVALID_FRAME_LENGTH;
|
||||
}
|
||||
|
||||
if (config->anc_Rate != 0) {
|
||||
|
||||
ErrorStatus = FDKaacEnc_InitCheckAncillary(config->bitRate,
|
||||
config->framelength,
|
||||
config->anc_Rate,
|
||||
&hAacEnc->ancillaryBitsPerFrame,
|
||||
config->sampleRate);
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
goto bail;
|
||||
|
||||
|
||||
/* update estimated consumed bitrate */
|
||||
config->ancDataBitRate += ( (hAacEnc->ancillaryBitsPerFrame * config->sampleRate) / config->framelength );
|
||||
|
||||
}
|
||||
|
||||
/* maximal allowed DSE bytes in frame */
|
||||
{
|
||||
/* fixpoint calculation*/
|
||||
INT q_res, encBitrate, sc;
|
||||
FIXP_DBL tmp = fDivNorm(config->framelength, config->sampleRate, &q_res);
|
||||
encBitrate = (config->bitRate/*-config->ancDataBitRate*/)- (INT)(config->nChannels*8000);
|
||||
sc = CountLeadingBits(encBitrate);
|
||||
config->maxAncBytesPerAU = FDKmin( (256), FDKmax(0,(INT)(fMultDiv2(tmp, (FIXP_DBL)(encBitrate<<sc))>>(-q_res+sc-1+3))) );
|
||||
}
|
||||
|
||||
/* bind config to hAacEnc->config */
|
||||
hAacEnc->config = config;
|
||||
|
||||
/* set hAacEnc->bitrateMode */
|
||||
hAacEnc->bitrateMode = (AACENC_BITRATE_MODE)config->bitrateMode;
|
||||
|
||||
hAacEnc->encoderMode = config->channelMode;
|
||||
|
||||
ErrorStatus = FDKaacEnc_InitChannelMapping(hAacEnc->encoderMode, config->channelOrder, &hAacEnc->channelMapping);
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
goto bail;
|
||||
|
||||
cm = &hAacEnc->channelMapping;
|
||||
|
||||
ErrorStatus = FDKaacEnc_DetermineBandWidth(&hAacEnc->config->bandWidth,
|
||||
config->bandWidth,
|
||||
config->bitRate - config->ancDataBitRate,
|
||||
hAacEnc->bitrateMode,
|
||||
config->sampleRate,
|
||||
config->framelength,
|
||||
cm,
|
||||
hAacEnc->encoderMode);
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
goto bail;
|
||||
|
||||
hAacEnc->bandwidth90dB = (INT)hAacEnc->config->bandWidth;
|
||||
|
||||
tnsMask = config->useTns ? TNS_ENABLE_MASK : 0x0;
|
||||
psyBitrate = config->bitRate - config->ancDataBitRate;
|
||||
|
||||
ErrorStatus = FDKaacEnc_psyInit(hAacEnc->psyKernel,
|
||||
hAacEnc->psyOut,
|
||||
hAacEnc->maxFrames,
|
||||
hAacEnc->maxChannels,
|
||||
config->audioObjectType,
|
||||
cm);
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
goto bail;
|
||||
|
||||
ErrorStatus = FDKaacEnc_psyMainInit(hAacEnc->psyKernel,
|
||||
config->audioObjectType,
|
||||
cm,
|
||||
config->sampleRate,
|
||||
config->framelength,
|
||||
psyBitrate,
|
||||
tnsMask,
|
||||
hAacEnc->bandwidth90dB,
|
||||
config->usePns,
|
||||
config->useIS,
|
||||
config->syntaxFlags,
|
||||
initFlags);
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
goto bail;
|
||||
|
||||
ErrorStatus = FDKaacEnc_QCOutInit(hAacEnc->qcOut, hAacEnc->maxFrames, cm);
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
goto bail;
|
||||
|
||||
|
||||
|
||||
qcInit.channelMapping = &hAacEnc->channelMapping;
|
||||
qcInit.sceCpe = 0;
|
||||
|
||||
{
|
||||
int maxBitres;
|
||||
qcInit.averageBits = (averageBitsPerFrame+7)&~7;
|
||||
maxBitres = (MIN_BUFSIZE_PER_EFF_CHAN*cm->nChannelsEff) - qcInit.averageBits;
|
||||
qcInit.bitRes = (config->bitreservoir!=-1) ? FDKmin(config->bitreservoir, maxBitres) : maxBitres;
|
||||
|
||||
qcInit.maxBits = fixMin(MIN_BUFSIZE_PER_EFF_CHAN*cm->nChannelsEff, ((averageBitsPerFrame+7)&~7)+qcInit.bitRes);
|
||||
qcInit.maxBits = (config->maxBitsPerFrame!=-1) ? fixMin(qcInit.maxBits, config->maxBitsPerFrame) : qcInit.maxBits;
|
||||
|
||||
qcInit.minBits = fixMax(0, ((averageBitsPerFrame-1)&~7)-qcInit.bitRes-transportEnc_GetStaticBits(hTpEnc, ((averageBitsPerFrame+7)&~7)+qcInit.bitRes));
|
||||
qcInit.minBits = (config->minBitsPerFrame!=-1) ? fixMax(qcInit.minBits, config->minBitsPerFrame) : qcInit.minBits;
|
||||
}
|
||||
|
||||
qcInit.nSubFrames = config->nSubFrames;
|
||||
qcInit.padding.paddingRest = config->sampleRate;
|
||||
|
||||
/* Calc meanPe */
|
||||
bw_ratio = fDivNorm((FIXP_DBL)hAacEnc->bandwidth90dB, (FIXP_DBL)(config->sampleRate>>1), &qbw);
|
||||
qbw = DFRACT_BITS-1-qbw;
|
||||
/* qcInit.meanPe = 10.0f * FRAME_LEN_LONG * hAacEnc->bandwidth90dB/(config->sampleRate/2.0f); */
|
||||
qcInit.meanPe = fMult(bw_ratio, (FIXP_DBL)((10*config->framelength)<<16)) >> (qbw-15);
|
||||
|
||||
/* Calc maxBitFac */
|
||||
mbfac = fDivNorm((MIN_BUFSIZE_PER_EFF_CHAN-744)*cm->nChannelsEff, qcInit.averageBits/qcInit.nSubFrames, &qmbfac);
|
||||
qmbfac = DFRACT_BITS-1-qmbfac;
|
||||
qcInit.maxBitFac = (qmbfac > 24) ? (mbfac >> (qmbfac - 24)):(mbfac << (24 - qmbfac));
|
||||
|
||||
switch(config->bitrateMode){
|
||||
case AACENC_BR_MODE_CBR:
|
||||
qcInit.bitrateMode = QCDATA_BR_MODE_CBR;
|
||||
break;
|
||||
case AACENC_BR_MODE_VBR_1:
|
||||
qcInit.bitrateMode = QCDATA_BR_MODE_VBR_1;
|
||||
break;
|
||||
case AACENC_BR_MODE_VBR_2:
|
||||
qcInit.bitrateMode = QCDATA_BR_MODE_VBR_2;
|
||||
break;
|
||||
case AACENC_BR_MODE_VBR_3:
|
||||
qcInit.bitrateMode = QCDATA_BR_MODE_VBR_3;
|
||||
break;
|
||||
case AACENC_BR_MODE_VBR_4:
|
||||
qcInit.bitrateMode = QCDATA_BR_MODE_VBR_4;
|
||||
break;
|
||||
case AACENC_BR_MODE_VBR_5:
|
||||
qcInit.bitrateMode = QCDATA_BR_MODE_VBR_5;
|
||||
break;
|
||||
case AACENC_BR_MODE_SFR:
|
||||
qcInit.bitrateMode = QCDATA_BR_MODE_SFR;
|
||||
break;
|
||||
case AACENC_BR_MODE_FF:
|
||||
qcInit.bitrateMode = QCDATA_BR_MODE_FF;
|
||||
break;
|
||||
default:
|
||||
ErrorStatus = AAC_ENC_UNSUPPORTED_BITRATE_MODE;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
qcInit.invQuant = (config->useRequant)?2:0;
|
||||
|
||||
/* maxIterations should be set to the maximum number of requantization iterations that are
|
||||
* allowed before the crash recovery functionality is activated. This setting should be adjusted
|
||||
* to the processing power available, i.e. to the processing power headroom in one frame that is
|
||||
* still left after normal encoding without requantization. Please note that if activated this
|
||||
* functionality is used most likely only in cases where the encoder is operating beyond
|
||||
* recommended settings, i.e. the audio quality is suboptimal anyway. Activating the crash
|
||||
* recovery does not further reduce audio quality significantly in these cases. */
|
||||
if ( (config->audioObjectType == AOT_ER_AAC_LD) || (config->audioObjectType == AOT_ER_AAC_ELD) ) {
|
||||
qcInit.maxIterations = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
qcInit.maxIterations = 5;
|
||||
}
|
||||
|
||||
qcInit.bitrate = config->bitRate - config->ancDataBitRate;
|
||||
|
||||
qcInit.staticBits = transportEnc_GetStaticBits(hTpEnc, qcInit.averageBits/qcInit.nSubFrames);
|
||||
|
||||
ErrorStatus = FDKaacEnc_QCInit(hAacEnc->qcKernel, &qcInit);
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
goto bail;
|
||||
|
||||
/* Map virtual aot's to intern aot used in bitstream writer. */
|
||||
switch (hAacEnc->config->audioObjectType) {
|
||||
case AOT_MP2_AAC_LC:
|
||||
case AOT_DABPLUS_AAC_LC:
|
||||
hAacEnc->aot = AOT_AAC_LC;
|
||||
break;
|
||||
case AOT_MP2_SBR:
|
||||
case AOT_DABPLUS_SBR:
|
||||
hAacEnc->aot = AOT_SBR;
|
||||
break;
|
||||
case AOT_MP2_PS:
|
||||
case AOT_DABPLUS_PS:
|
||||
hAacEnc->aot = AOT_PS;
|
||||
break;
|
||||
default:
|
||||
hAacEnc->aot = hAacEnc->config->audioObjectType;
|
||||
}
|
||||
|
||||
/* common things */
|
||||
|
||||
return AAC_ENC_OK;
|
||||
|
||||
bail:
|
||||
|
||||
return ErrorStatus;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
functionname: FDKaacEnc_EncodeFrame
|
||||
description: encodes one frame
|
||||
returns: error code
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
AAC_ENCODER_ERROR FDKaacEnc_EncodeFrame( HANDLE_AAC_ENC hAacEnc, /* encoder handle */
|
||||
HANDLE_TRANSPORTENC hTpEnc,
|
||||
INT_PCM* RESTRICT inputBuffer,
|
||||
INT* nOutBytes,
|
||||
AACENC_EXT_PAYLOAD extPayload[MAX_TOTAL_EXT_PAYLOADS]
|
||||
)
|
||||
{
|
||||
AAC_ENCODER_ERROR ErrorStatus;
|
||||
int el, n, c=0;
|
||||
UCHAR extPayloadUsed[MAX_TOTAL_EXT_PAYLOADS];
|
||||
|
||||
CHANNEL_MAPPING *cm = &hAacEnc->channelMapping;
|
||||
|
||||
|
||||
|
||||
PSY_OUT *psyOut = hAacEnc->psyOut[c];
|
||||
QC_OUT *qcOut = hAacEnc->qcOut[c];
|
||||
|
||||
FDKmemclear(extPayloadUsed, MAX_TOTAL_EXT_PAYLOADS * sizeof(UCHAR));
|
||||
|
||||
qcOut->elementExtBits = 0; /* sum up all extended bit of each element */
|
||||
qcOut->staticBits = 0; /* sum up side info bits of each element */
|
||||
qcOut->totalNoRedPe = 0; /* sum up PE */
|
||||
|
||||
/* advance psychoacoustics */
|
||||
for (el=0; el<cm->nElements; el++) {
|
||||
ELEMENT_INFO elInfo = cm->elInfo[el];
|
||||
|
||||
if ( (elInfo.elType == ID_SCE)
|
||||
|| (elInfo.elType == ID_CPE)
|
||||
|| (elInfo.elType == ID_LFE) )
|
||||
{
|
||||
int ch;
|
||||
|
||||
/* update pointer!*/
|
||||
for(ch=0;ch<elInfo.nChannelsInEl;ch++) {
|
||||
PSY_OUT_CHANNEL *psyOutChan = psyOut->psyOutElement[el]->psyOutChannel[ch];
|
||||
QC_OUT_CHANNEL *qcOutChan = qcOut->qcElement[el]->qcOutChannel[ch];
|
||||
|
||||
psyOutChan->mdctSpectrum = qcOutChan->mdctSpectrum;
|
||||
psyOutChan->sfbSpreadEnergy = qcOutChan->sfbSpreadEnergy;
|
||||
psyOutChan->sfbEnergy = qcOutChan->sfbEnergy;
|
||||
psyOutChan->sfbEnergyLdData = qcOutChan->sfbEnergyLdData;
|
||||
psyOutChan->sfbMinSnrLdData = qcOutChan->sfbMinSnrLdData;
|
||||
psyOutChan->sfbThresholdLdData = qcOutChan->sfbThresholdLdData;
|
||||
|
||||
}
|
||||
|
||||
FDKaacEnc_psyMain(elInfo.nChannelsInEl,
|
||||
hAacEnc->psyKernel->psyElement[el],
|
||||
hAacEnc->psyKernel->psyDynamic,
|
||||
hAacEnc->psyKernel->psyConf,
|
||||
psyOut->psyOutElement[el],
|
||||
inputBuffer,
|
||||
cm->elInfo[el].ChannelIndex,
|
||||
cm->nChannels
|
||||
|
||||
);
|
||||
|
||||
/* FormFactor, Pe and staticBitDemand calculation */
|
||||
ErrorStatus = FDKaacEnc_QCMainPrepare(&elInfo,
|
||||
hAacEnc->qcKernel->hAdjThr->adjThrStateElem[el],
|
||||
psyOut->psyOutElement[el],
|
||||
qcOut->qcElement[el],
|
||||
hAacEnc->aot,
|
||||
hAacEnc->config->syntaxFlags,
|
||||
hAacEnc->config->epConfig);
|
||||
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
return ErrorStatus;
|
||||
|
||||
/*-------------------------------------------- */
|
||||
|
||||
qcOut->qcElement[el]->extBitsUsed = 0;
|
||||
qcOut->qcElement[el]->nExtensions = 0;
|
||||
/* reset extension payload */
|
||||
FDKmemclear(&qcOut->qcElement[el]->extension, (1)*sizeof(QC_OUT_EXTENSION));
|
||||
|
||||
for ( n = 0; n < MAX_TOTAL_EXT_PAYLOADS; n++ ) {
|
||||
if ( !extPayloadUsed[n]
|
||||
&& (extPayload[n].associatedChElement == el)
|
||||
&& (extPayload[n].dataSize > 0)
|
||||
&& (extPayload[n].pData != NULL) )
|
||||
{
|
||||
int idx = qcOut->qcElement[el]->nExtensions++;
|
||||
|
||||
qcOut->qcElement[el]->extension[idx].type = extPayload[n].dataType; /* Perform a sanity check on the type? */
|
||||
qcOut->qcElement[el]->extension[idx].nPayloadBits = extPayload[n].dataSize;
|
||||
qcOut->qcElement[el]->extension[idx].pPayload = extPayload[n].pData;
|
||||
/* Now ask the bitstream encoder how many bits we need to encode the data with the current bitstream syntax: */
|
||||
qcOut->qcElement[el]->extBitsUsed +=
|
||||
FDKaacEnc_writeExtensionData( NULL,
|
||||
&qcOut->qcElement[el]->extension[idx],
|
||||
0, 0,
|
||||
hAacEnc->config->syntaxFlags,
|
||||
hAacEnc->aot,
|
||||
hAacEnc->config->epConfig );
|
||||
extPayloadUsed[n] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* sum up extension and static bits for all channel elements */
|
||||
qcOut->elementExtBits += qcOut->qcElement[el]->extBitsUsed;
|
||||
qcOut->staticBits += qcOut->qcElement[el]->staticBitsUsed;
|
||||
|
||||
/* sum up pe */
|
||||
qcOut->totalNoRedPe += qcOut->qcElement[el]->peData.pe;
|
||||
}
|
||||
}
|
||||
|
||||
qcOut->nExtensions = 0;
|
||||
qcOut->globalExtBits = 0;
|
||||
|
||||
/* reset extension payload */
|
||||
FDKmemclear(&qcOut->extension, (2+2)*sizeof(QC_OUT_EXTENSION));
|
||||
|
||||
/* Add extension payload not assigned to an channel element
|
||||
(Ancillary data is the only supported type up to now) */
|
||||
for ( n = 0; n < MAX_TOTAL_EXT_PAYLOADS; n++ ) {
|
||||
if ( !extPayloadUsed[n]
|
||||
&& (extPayload[n].associatedChElement == -1)
|
||||
&& (extPayload[n].pData != NULL) )
|
||||
{
|
||||
UINT payloadBits = 0;
|
||||
|
||||
if (extPayload[n].dataType == EXT_DATA_ELEMENT) {
|
||||
if (hAacEnc->ancillaryBitsPerFrame) {
|
||||
/* granted frame dse bitrate */
|
||||
payloadBits = hAacEnc->ancillaryBitsPerFrame;
|
||||
}
|
||||
else {
|
||||
/* write anc data if bitrate constraint fulfilled */
|
||||
if ((extPayload[n].dataSize>>3) <= hAacEnc->config->maxAncBytesPerAU) {
|
||||
payloadBits = extPayload[n].dataSize;
|
||||
}
|
||||
}
|
||||
payloadBits = fixMin( extPayload[n].dataSize, payloadBits );
|
||||
} else {
|
||||
payloadBits = extPayload[n].dataSize;
|
||||
}
|
||||
|
||||
if (payloadBits > 0)
|
||||
{
|
||||
int idx = qcOut->nExtensions++;
|
||||
|
||||
qcOut->extension[idx].type = extPayload[n].dataType; /* Perform a sanity check on the type? */
|
||||
qcOut->extension[idx].nPayloadBits = payloadBits;
|
||||
qcOut->extension[idx].pPayload = extPayload[n].pData;
|
||||
/* Now ask the bitstream encoder how many bits we need to encode the data with the current bitstream syntax: */
|
||||
qcOut->globalExtBits += FDKaacEnc_writeExtensionData( NULL,
|
||||
&qcOut->extension[idx],
|
||||
0, 0,
|
||||
hAacEnc->config->syntaxFlags,
|
||||
hAacEnc->aot,
|
||||
hAacEnc->config->epConfig );
|
||||
if (extPayload[n].dataType == EXT_DATA_ELEMENT) {
|
||||
/* substract the processed bits */
|
||||
extPayload[n].dataSize -= payloadBits;
|
||||
}
|
||||
extPayloadUsed[n] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(hAacEnc->config->syntaxFlags & (AC_SCALABLE|AC_ER))) {
|
||||
qcOut->globalExtBits += EL_ID_BITS; /* add bits for ID_END */
|
||||
}
|
||||
|
||||
/* build bitstream all nSubFrames */
|
||||
{
|
||||
INT totalBits = 0; /* Total AU bits */;
|
||||
INT avgTotalBits = 0;
|
||||
|
||||
/*-------------------------------------------- */
|
||||
/* Get average total bits */
|
||||
/*-------------------------------------------- */
|
||||
{
|
||||
/* frame wise bitrate adaption */
|
||||
FDKaacEnc_AdjustBitrate(hAacEnc->qcKernel,
|
||||
cm,
|
||||
&avgTotalBits,
|
||||
hAacEnc->config->bitRate,
|
||||
hAacEnc->config->sampleRate,
|
||||
hAacEnc->config->framelength);
|
||||
|
||||
/* adjust super frame bitrate */
|
||||
avgTotalBits *= hAacEnc->config->nSubFrames;
|
||||
}
|
||||
|
||||
/* Make first estimate of transport header overhead.
|
||||
Take maximum possible frame size into account to prevent bitreservoir underrun. */
|
||||
hAacEnc->qcKernel->globHdrBits = transportEnc_GetStaticBits(hTpEnc, avgTotalBits + hAacEnc->qcKernel->bitResTot);
|
||||
|
||||
|
||||
/*-------------------------------------------- */
|
||||
/*-------------------------------------------- */
|
||||
/*-------------------------------------------- */
|
||||
|
||||
ErrorStatus = FDKaacEnc_QCMain(hAacEnc->qcKernel,
|
||||
hAacEnc->psyOut,
|
||||
hAacEnc->qcOut,
|
||||
avgTotalBits,
|
||||
cm
|
||||
,hAacEnc->aot,
|
||||
hAacEnc->config->syntaxFlags,
|
||||
hAacEnc->config->epConfig);
|
||||
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
return ErrorStatus;
|
||||
/*-------------------------------------------- */
|
||||
|
||||
/*-------------------------------------------- */
|
||||
ErrorStatus = FDKaacEnc_updateFillBits(cm,
|
||||
hAacEnc->qcKernel,
|
||||
hAacEnc->qcKernel->elementBits,
|
||||
hAacEnc->qcOut);
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
return ErrorStatus;
|
||||
|
||||
/*-------------------------------------------- */
|
||||
ErrorStatus = FDKaacEnc_FinalizeBitConsumption(cm,
|
||||
hAacEnc->qcKernel,
|
||||
qcOut,
|
||||
qcOut->qcElement,
|
||||
hTpEnc,
|
||||
hAacEnc->aot,
|
||||
hAacEnc->config->syntaxFlags,
|
||||
hAacEnc->config->epConfig);
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
return ErrorStatus;
|
||||
/*-------------------------------------------- */
|
||||
totalBits += qcOut->totalBits;
|
||||
|
||||
|
||||
/*-------------------------------------------- */
|
||||
FDKaacEnc_updateBitres(cm,
|
||||
hAacEnc->qcKernel,
|
||||
hAacEnc->qcOut);
|
||||
|
||||
/*-------------------------------------------- */
|
||||
|
||||
/* for ( all sub frames ) ... */
|
||||
/* write bitstream header */
|
||||
transportEnc_WriteAccessUnit(
|
||||
hTpEnc,
|
||||
totalBits,
|
||||
FDKaacEnc_EncBitresToTpBitres(hAacEnc->bitrateMode, hAacEnc->qcKernel->bitResTot),
|
||||
cm->nChannelsEff);
|
||||
|
||||
/* write bitstream */
|
||||
ErrorStatus = FDKaacEnc_WriteBitstream(
|
||||
hTpEnc,
|
||||
cm,
|
||||
qcOut,
|
||||
psyOut,
|
||||
hAacEnc->qcKernel,
|
||||
hAacEnc->aot,
|
||||
hAacEnc->config->syntaxFlags,
|
||||
hAacEnc->config->epConfig);
|
||||
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
return ErrorStatus;
|
||||
|
||||
/* transportEnc_EndAccessUnit() is being called inside FDKaacEnc_WriteBitstream() */
|
||||
transportEnc_GetFrame(hTpEnc, nOutBytes);
|
||||
|
||||
} /* -end- if (curFrame==hAacEnc->qcKernel->nSubFrames) */
|
||||
|
||||
|
||||
/*-------------------------------------------- */
|
||||
return AAC_ENC_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
functionname:FDKaacEnc_Close
|
||||
description: delete encoder instance
|
||||
returns:
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
void FDKaacEnc_Close( HANDLE_AAC_ENC* phAacEnc) /* encoder handle */
|
||||
{
|
||||
if (*phAacEnc == NULL) {
|
||||
return;
|
||||
}
|
||||
AAC_ENC *hAacEnc = (AAC_ENC*)*phAacEnc;
|
||||
|
||||
if (hAacEnc->dynamic_RAM != NULL)
|
||||
FreeAACdynamic_RAM(&hAacEnc->dynamic_RAM);
|
||||
|
||||
FDKaacEnc_PsyClose(&hAacEnc->psyKernel,hAacEnc->psyOut);
|
||||
|
||||
FDKaacEnc_QCClose(&hAacEnc->qcKernel, hAacEnc->qcOut);
|
||||
|
||||
FreeRam_aacEnc_AacEncoder(phAacEnc);
|
||||
}
|
||||
|
||||
|
||||
/* The following functions are in this source file only for convenience and */
|
||||
/* need not be visible outside of a possible encoder library. */
|
||||
|
||||
/* basic defines for ancillary data */
|
||||
#define MAX_ANCRATE 19200 /* ancillary rate >= 19200 isn't valid */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
functionname: FDKaacEnc_InitCheckAncillary
|
||||
description: initialize and check ancillary data struct
|
||||
return: if success or NULL if error
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
static AAC_ENCODER_ERROR FDKaacEnc_InitCheckAncillary(INT bitRate,
|
||||
INT framelength,
|
||||
INT ancillaryRate,
|
||||
INT *ancillaryBitsPerFrame,
|
||||
INT sampleRate)
|
||||
{
|
||||
INT diffToByteAlign;
|
||||
|
||||
/* don't use negative ancillary rates */
|
||||
if ( ancillaryRate < -1 )
|
||||
return AAC_ENC_UNSUPPORTED_ANC_BITRATE;
|
||||
|
||||
/* check if ancillary rate is ok */
|
||||
if ( (ancillaryRate != (-1)) && (ancillaryRate != 0) ) {
|
||||
/* ancRate <= 15% of bitrate && ancRate < 19200 */
|
||||
if ( ( ancillaryRate >= MAX_ANCRATE ) ||
|
||||
( (ancillaryRate * 20) > (bitRate * 3) ) ) {
|
||||
return AAC_ENC_UNSUPPORTED_ANC_BITRATE;
|
||||
}
|
||||
}
|
||||
else if (ancillaryRate == -1) {
|
||||
/* if no special ancRate is requested but a ancillary file is
|
||||
stated, then generate a ancillary rate matching to the bitrate */
|
||||
if (bitRate >= (MAX_ANCRATE * 10)) {
|
||||
/* ancillary rate is 19199 */
|
||||
ancillaryRate = (MAX_ANCRATE - 1);
|
||||
}
|
||||
else { /* 10% of bitrate */
|
||||
ancillaryRate = bitRate / 10;
|
||||
}
|
||||
}
|
||||
|
||||
/* make ancillaryBitsPerFrame byte align */
|
||||
*ancillaryBitsPerFrame = (ancillaryRate * framelength ) / sampleRate;
|
||||
diffToByteAlign = *ancillaryBitsPerFrame % 8;
|
||||
*ancillaryBitsPerFrame = *ancillaryBitsPerFrame - diffToByteAlign;
|
||||
|
||||
return AAC_ENC_OK;
|
||||
}
|
232
libAACenc/src/aacenc.h
Normal file
232
libAACenc/src/aacenc.h
Normal file
@ -0,0 +1,232 @@
|
||||
/************************* Fast MPEG AAC Audio Encoder **********************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M. Schug / A. Groeschel
|
||||
contents/description: fast aac coder interface library functions
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _aacenc_h_
|
||||
#define _aacenc_h_
|
||||
|
||||
#include "common_fix.h"
|
||||
#include "FDK_audio.h"
|
||||
|
||||
#include "tpenc_lib.h"
|
||||
|
||||
#include "sbr_encoder.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* AAC-LC error codes.
|
||||
*/
|
||||
typedef enum {
|
||||
AAC_ENC_OK = 0x0000, /*!< All fine. */
|
||||
|
||||
AAC_ENC_UNKNOWN = 0x0002, /*!< Error condition is of unknown reason, or from another module. */
|
||||
|
||||
/* initialization errors */
|
||||
aac_enc_init_error_start = 0x2000,
|
||||
AAC_ENC_INVALID_HANDLE = 0x2020, /*!< The handle passed to the function call was invalid (probably NULL). */
|
||||
AAC_ENC_INVALID_FRAME_LENGTH = 0x2080, /*!< Invalid frame length (must be 1024 or 960). */
|
||||
AAC_ENC_INVALID_N_CHANNELS = 0x20e0, /*!< Invalid amount of audio input channels. */
|
||||
AAC_ENC_INVALID_SFB_TABLE = 0x2140, /*!< Internal encoder error. */
|
||||
|
||||
AAC_ENC_UNSUPPORTED_AOT = 0x3000, /*!< The Audio Object Type (AOT) is not supported. */
|
||||
AAC_ENC_UNSUPPORTED_BITRATE = 0x3020, /*!< The chosen bitrate is not supported. */
|
||||
AAC_ENC_UNSUPPORTED_BITRATE_MODE = 0x3028, /*!< Unsupported bit rate mode (CBR or VBR). */
|
||||
AAC_ENC_UNSUPPORTED_ANC_BITRATE = 0x3040, /*!< Unsupported ancillay bitrate. */
|
||||
AAC_ENC_UNSUPPORTED_ANC_MODE = 0x3060,
|
||||
AAC_ENC_UNSUPPORTED_TRANSPORT_TYPE = 0x3080, /*!< The bitstream format is not supported. */
|
||||
AAC_ENC_UNSUPPORTED_ER_FORMAT = 0x30a0, /*!< The error resilience tool format is not supported. */
|
||||
AAC_ENC_UNSUPPORTED_EPCONFIG = 0x30c0, /*!< The error protection format is not supported. */
|
||||
AAC_ENC_UNSUPPORTED_CHANNELCONFIG = 0x30e0, /*!< The channel configuration (either number or arrangement) is not supported. */
|
||||
AAC_ENC_UNSUPPORTED_SAMPLINGRATE = 0x3100, /*!< Sample rate of audio input is not supported. */
|
||||
AAC_ENC_NO_MEMORY = 0x3120, /*!< Could not allocate memory. */
|
||||
AAC_ENC_PE_INIT_TABLE_NOT_FOUND = 0x3140, /*!< Internal encoder error. */
|
||||
|
||||
aac_enc_init_error_end,
|
||||
|
||||
/* encode errors */
|
||||
aac_enc_error_start = 0x4000,
|
||||
AAC_ENC_QUANT_ERROR = 0x4020, /*!< Too many bits used in quantization. */
|
||||
AAC_ENC_WRITTEN_BITS_ERROR = 0x4040, /*!< Unexpected number of written bits, differs to
|
||||
calculated number of bits. */
|
||||
AAC_ENC_PNS_TABLE_ERROR = 0x4060, /*!< PNS level out of range. */
|
||||
AAC_ENC_GLOBAL_GAIN_TOO_HIGH = 0x4080, /*!< Internal quantizer error. */
|
||||
AAC_ENC_BITRES_TOO_LOW = 0x40a0, /*!< Too few bits in bit reservoir. */
|
||||
AAC_ENC_BITRES_TOO_HIGH = 0x40a1, /*!< Too many bits in bit reservoir. */
|
||||
AAC_ENC_INVALID_CHANNEL_BITRATE = 0x4100,
|
||||
AAC_ENC_INVALID_ELEMENTINFO_TYPE = 0x4120, /*!< Internal encoder error. */
|
||||
|
||||
AAC_ENC_WRITE_SCAL_ERROR = 0x41e0, /*!< Error writing scalefacData. */
|
||||
AAC_ENC_WRITE_SEC_ERROR = 0x4200, /*!< Error writing sectionData. */
|
||||
AAC_ENC_WRITE_SPEC_ERROR = 0x4220, /*!< Error writing spectralData. */
|
||||
aac_enc_error_end
|
||||
|
||||
} AAC_ENCODER_ERROR;
|
||||
/*-------------------------- defines --------------------------------------*/
|
||||
|
||||
#define ANC_DATA_BUFFERSIZE 1024 /* ancBuffer size */
|
||||
#define DEFAULT_FRAMELENGTH 1024 /* size of AAC core frame in (new) PCM samples */
|
||||
|
||||
#define MAX_TOTAL_EXT_PAYLOADS (((6) * (1)) + (2+2))
|
||||
|
||||
|
||||
typedef enum {
|
||||
AACENC_BR_MODE_INVALID = -1, /*!< Invalid bitrate mode. */
|
||||
AACENC_BR_MODE_CBR = 0, /*!< Constant bitrate mode. */
|
||||
AACENC_BR_MODE_VBR_1 = 1, /*!< Variable bitrate mode, about 32 kbps/channel. */
|
||||
AACENC_BR_MODE_VBR_2 = 2, /*!< Variable bitrate mode, about 40 kbps/channel. */
|
||||
AACENC_BR_MODE_VBR_3 = 3, /*!< Variable bitrate mode, about 48-56 kbps/channel. */
|
||||
AACENC_BR_MODE_VBR_4 = 4, /*!< Variable bitrate mode, about 64 kbps/channel. */
|
||||
AACENC_BR_MODE_VBR_5 = 5, /*!< Variable bitrate mode, about 80-96 kbps/channel. */
|
||||
AACENC_BR_MODE_FF = 6, /*!< Fixed frame mode. */
|
||||
AACENC_BR_MODE_SFR = 7 /*!< Superframe mode. */
|
||||
|
||||
} AACENC_BITRATE_MODE;
|
||||
|
||||
typedef enum {
|
||||
|
||||
CH_ORDER_MPEG = 0, /*!< MPEG channel ordering (e. g. 5.1: C, L, R, SL, SR, LFE) */
|
||||
CH_ORDER_WAV /*!< WAV fileformat channel ordering (e. g. 5.1: L, R, C, LFE, SL, SR) */
|
||||
|
||||
} CHANNEL_ORDER;
|
||||
|
||||
/*-------------------- structure definitions ------------------------------*/
|
||||
|
||||
struct AACENC_CONFIG {
|
||||
INT sampleRate; /* encoder sample rate */
|
||||
INT bitRate; /* encoder bit rate in bits/sec */
|
||||
INT ancDataBitRate; /* additional bits consumed by anc data or sbr have to be consiedered while configuration */
|
||||
|
||||
INT nSubFrames; /* number of frames in super frame (not ADTS/LATM subframes !) */
|
||||
AUDIO_OBJECT_TYPE audioObjectType; /* Audio Object Type */
|
||||
|
||||
INT averageBits; /* encoder bit rate in bits/superframe */
|
||||
INT bitrateMode; /* encoder bitrate mode (CBR/VBR) */
|
||||
INT nChannels; /* number of channels to process */
|
||||
CHANNEL_ORDER channelOrder; /* Input Channel ordering scheme. */
|
||||
INT bandWidth; /* targeted audio bandwidth in Hz */
|
||||
CHANNEL_MODE channelMode; /* encoder channel mode configuration */
|
||||
INT framelength; /* used frame size */
|
||||
|
||||
UINT syntaxFlags; /* bitstreams syntax configuration */
|
||||
SCHAR epConfig; /* error protection configuration */
|
||||
|
||||
INT anc_Rate; /* ancillary rate, 0 (disabled), -1 (default) else desired rate */
|
||||
UINT maxAncBytesPerAU;
|
||||
INT minBitsPerFrame; /* minimum number of bits in AU */
|
||||
INT maxBitsPerFrame; /* maximum number of bits in AU */
|
||||
INT bitreservoir; /* size of bitreservoir */
|
||||
|
||||
UCHAR useTns; /* flag: use temporal noise shaping */
|
||||
UCHAR usePns; /* flag: use perceptual noise substitution */
|
||||
UCHAR useIS; /* flag: use intensity coding */
|
||||
|
||||
UCHAR useRequant; /* flag: use afterburner */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
UCHAR *pData; /* pointer to extension payload data */
|
||||
UINT dataSize; /* extension payload data size in bits */
|
||||
EXT_PAYLOAD_TYPE dataType; /* extension payload data type */
|
||||
INT associatedChElement; /* number of the channel element the data is assigned to */
|
||||
} AACENC_EXT_PAYLOAD;
|
||||
|
||||
typedef struct AAC_ENC *HANDLE_AAC_ENC;
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
|
||||
functionname: FDKaacEnc_GetVBRBitrate
|
||||
description: Get VBR bitrate from vbr quality
|
||||
input params: int vbrQuality (VBR0, VBR1, VBR2)
|
||||
channelMode
|
||||
returns: vbr bitrate
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
INT FDKaacEnc_GetVBRBitrate(INT bitrateMode, CHANNEL_MODE channelMode);
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
|
||||
functionname: FDKaacEnc_AacInitDefaultConfig
|
||||
description: gives reasonable default configuration
|
||||
returns: ---
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
void FDKaacEnc_AacInitDefaultConfig(AACENC_CONFIG *config);
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
functionname:FDKaacEnc_Open
|
||||
description: allocate and initialize a new encoder instance
|
||||
returns: 0 if success
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
AAC_ENCODER_ERROR FDKaacEnc_Open(HANDLE_AAC_ENC *phAacEnc, /* pointer to an encoder handle, initialized on return */
|
||||
const INT nElements, /* number of maximal elements in instance to support */
|
||||
const INT nChannels, /* number of maximal channels in instance to support */
|
||||
const INT nSubFrames); /* support superframing in instance */
|
||||
|
||||
|
||||
AAC_ENCODER_ERROR FDKaacEnc_Initialize(HANDLE_AAC_ENC hAacEncoder, /* pointer to an encoder handle, initialized on return */
|
||||
AACENC_CONFIG *config, /* pre-initialized config struct */
|
||||
HANDLE_TRANSPORTENC hTpEnc,
|
||||
ULONG initFlags);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
functionname: FDKaacEnc_EncodeFrame
|
||||
description: encode one frame
|
||||
returns: 0 if success
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
AAC_ENCODER_ERROR FDKaacEnc_EncodeFrame( HANDLE_AAC_ENC hAacEnc, /* encoder handle */
|
||||
HANDLE_TRANSPORTENC hTpEnc,
|
||||
INT_PCM* inputBuffer,
|
||||
INT* numOutBytes,
|
||||
AACENC_EXT_PAYLOAD extPayload[MAX_TOTAL_EXT_PAYLOADS]
|
||||
);
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
functionname:FDKaacEnc_Close
|
||||
description: delete encoder instance
|
||||
returns:
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
void FDKaacEnc_Close( HANDLE_AAC_ENC* phAacEnc); /* encoder handle */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _aacenc_h_ */
|
||||
|
31
libAACenc/src/aacenc_hcr.cpp
Normal file
31
libAACenc/src/aacenc_hcr.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
/*************************** MPEG AAC Audio Encoder *************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2000-2005)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Initial author: R. Boehm
|
||||
contents/description: huffman codeword reordering
|
||||
based on source from aacErrRobTrans
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "aacenc_hcr.h"
|
||||
|
33
libAACenc/src/aacenc_hcr.h
Normal file
33
libAACenc/src/aacenc_hcr.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*************************** MPEG AAC Audio Encoder *************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2000-2005)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Initial author: R. Boehm
|
||||
contents/description: huffman codeword reordering
|
||||
based on source from aacErrRobTrans
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef _AACENC_HCR
|
||||
#define _AACENC_HCR_H
|
||||
|
||||
|
||||
#endif /* ifndef _AACENC_HCR */
|
1696
libAACenc/src/aacenc_lib.cpp
Normal file
1696
libAACenc/src/aacenc_lib.cpp
Normal file
File diff suppressed because it is too large
Load Diff
532
libAACenc/src/aacenc_pns.cpp
Normal file
532
libAACenc/src/aacenc_pns.cpp
Normal file
@ -0,0 +1,532 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2001)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
|
||||
Initial author: M. Lohwasser
|
||||
contents/description: pns.c
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#define PNS_CONFORMANCE_TEST 0
|
||||
|
||||
#include "aacenc_pns.h"
|
||||
#include "psy_data.h"
|
||||
#include "pnsparam.h"
|
||||
#include "noisedet.h"
|
||||
#include "bit_cnt.h"
|
||||
#include "interface.h"
|
||||
|
||||
|
||||
/* minCorrelationEnergy = (1.0e-10f)^2 ~ 2^-67 = 2^-47 * 2^-20 */
|
||||
static const FIXP_DBL minCorrelationEnergy = FL2FXCONST_DBL(0.0); /* FL2FXCONST_DBL((float)FDKpow(2.0,-47)); */
|
||||
/* noiseCorrelationThresh = 0.6^2 */
|
||||
static const FIXP_DBL noiseCorrelationThresh = FL2FXCONST_DBL(0.36);
|
||||
|
||||
static void FDKaacEnc_FDKaacEnc_noiseDetection( PNS_CONFIG *pnsConf,
|
||||
PNS_DATA *pnsData,
|
||||
const INT sfbActive,
|
||||
const INT *sfbOffset,
|
||||
INT tnsOrder,
|
||||
INT tnsPredictionGain,
|
||||
INT tnsActive,
|
||||
FIXP_DBL *mdctSpectrum,
|
||||
INT *sfbMaxScaleSpec,
|
||||
FIXP_SGL *sfbtonality );
|
||||
|
||||
static void FDKaacEnc_CalcNoiseNrgs( const INT sfbActive,
|
||||
INT *pnsFlag,
|
||||
FIXP_DBL *sfbEnergyLdData,
|
||||
INT *noiseNrg );
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
functionname: initPnsConfiguration
|
||||
description: fill pnsConf with pns parameters
|
||||
returns: error status
|
||||
input: PNS Config struct (modified)
|
||||
bitrate, samplerate, usePns,
|
||||
number of sfb's, pointer to sfb offset
|
||||
output: error code
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
AAC_ENCODER_ERROR FDKaacEnc_InitPnsConfiguration(PNS_CONFIG *pnsConf,
|
||||
INT bitRate,
|
||||
INT sampleRate,
|
||||
INT usePns,
|
||||
INT sfbCnt,
|
||||
const INT *sfbOffset,
|
||||
const INT numChan,
|
||||
const INT isLC)
|
||||
{
|
||||
AAC_ENCODER_ERROR ErrorStatus;
|
||||
|
||||
/* init noise detection */
|
||||
ErrorStatus = FDKaacEnc_GetPnsParam(&pnsConf->np,
|
||||
bitRate,
|
||||
sampleRate,
|
||||
sfbCnt,
|
||||
sfbOffset,
|
||||
&usePns,
|
||||
numChan,
|
||||
isLC);
|
||||
if (ErrorStatus != AAC_ENC_OK)
|
||||
return ErrorStatus;
|
||||
|
||||
pnsConf->minCorrelationEnergy = minCorrelationEnergy;
|
||||
pnsConf->noiseCorrelationThresh = noiseCorrelationThresh;
|
||||
|
||||
pnsConf->usePns = usePns;
|
||||
|
||||
return AAC_ENC_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
functionname: FDKaacEnc_PnsDetect
|
||||
description: do decision, if PNS shall used or not
|
||||
returns:
|
||||
input: pns config structure
|
||||
pns data structure (modified),
|
||||
lastWindowSequence (long or short blocks)
|
||||
sfbActive
|
||||
pointer to Sfb Energy, Threshold, Offset
|
||||
pointer to mdct Spectrum
|
||||
length of each group
|
||||
pointer to tonality calculated in chaosmeasure
|
||||
tns order and prediction gain
|
||||
calculated noiseNrg at active PNS
|
||||
output: pnsFlag in pns data structure
|
||||
|
||||
*****************************************************************************/
|
||||
void FDKaacEnc_PnsDetect(PNS_CONFIG *pnsConf,
|
||||
PNS_DATA *pnsData,
|
||||
const INT lastWindowSequence,
|
||||
const INT sfbActive,
|
||||
const INT maxSfbPerGroup,
|
||||
FIXP_DBL *sfbThresholdLdData,
|
||||
const INT *sfbOffset,
|
||||
FIXP_DBL *mdctSpectrum,
|
||||
INT *sfbMaxScaleSpec,
|
||||
FIXP_SGL *sfbtonality,
|
||||
INT tnsOrder,
|
||||
INT tnsPredictionGain,
|
||||
INT tnsActive,
|
||||
FIXP_DBL *sfbEnergyLdData,
|
||||
INT *noiseNrg )
|
||||
|
||||
{
|
||||
int sfb;
|
||||
int startNoiseSfb;
|
||||
|
||||
if (pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMLEXITY) {
|
||||
if ( (!pnsConf->usePns) || /* pns enabled? */
|
||||
(lastWindowSequence == SHORT_WINDOW) ) /* currently only long blocks */
|
||||
{
|
||||
FDKmemclear(pnsData->pnsFlag, MAX_GROUPED_SFB*sizeof(INT)); /* clear all pnsFlags */
|
||||
for (sfb=0; sfb<MAX_GROUPED_SFB; sfb++) {
|
||||
noiseNrg[sfb] = NO_NOISE_PNS; /* clear nrg's of previous frame */
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!pnsConf->usePns)
|
||||
return;
|
||||
|
||||
/* PNS only for long Windows */
|
||||
if (pnsConf->np.detectionAlgorithmFlags & JUST_LONG_WINDOW) {
|
||||
if(lastWindowSequence != LONG_WINDOW) {
|
||||
for (sfb = 0; sfb < sfbActive; sfb++) {
|
||||
pnsData->pnsFlag[sfb] = 0; /* clear all pnsFlags */
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
call noise detection
|
||||
*/
|
||||
FDKaacEnc_FDKaacEnc_noiseDetection( pnsConf,
|
||||
pnsData,
|
||||
sfbActive,
|
||||
sfbOffset,
|
||||
tnsOrder,
|
||||
tnsPredictionGain,
|
||||
tnsActive,
|
||||
mdctSpectrum,
|
||||
sfbMaxScaleSpec,
|
||||
sfbtonality );
|
||||
|
||||
/* set startNoiseSfb (long) */
|
||||
startNoiseSfb = pnsConf->np.startSfb;
|
||||
|
||||
/* Set noise substitution status */
|
||||
for(sfb = 0; sfb < sfbActive; sfb++) {
|
||||
|
||||
/* No PNS below startNoiseSfb */
|
||||
if(sfb < startNoiseSfb){
|
||||
pnsData->pnsFlag[sfb] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
do noise substitution if
|
||||
fuzzy measure is high enough
|
||||
sfb freq > minimum sfb freq
|
||||
signal in coder band is not masked
|
||||
*/
|
||||
|
||||
if((pnsData->noiseFuzzyMeasure[sfb] > FL2FXCONST_SGL(0.5)) &&
|
||||
( (sfbThresholdLdData[sfb] + FL2FXCONST_DBL(0.5849625f/64.0f)) /* thr * 1.5 = thrLd +ld(1.5)/64 */
|
||||
< sfbEnergyLdData[sfb] ) )
|
||||
{
|
||||
/*
|
||||
mark in psyout flag array that we will code
|
||||
this band with PNS
|
||||
*/
|
||||
pnsData->pnsFlag[sfb] = 1; /* PNS_ON */
|
||||
}
|
||||
else{
|
||||
pnsData->pnsFlag[sfb] = 0; /* PNS_OFF */
|
||||
}
|
||||
|
||||
/* no PNS if LTP is active */
|
||||
}
|
||||
|
||||
/* avoid PNS holes */
|
||||
if((pnsData->noiseFuzzyMeasure[0]>FL2FXCONST_SGL(0.5f)) && (pnsData->pnsFlag[1])) {
|
||||
pnsData->pnsFlag[0] = 1;
|
||||
}
|
||||
|
||||
for(sfb=1; sfb<maxSfbPerGroup-1; sfb++) {
|
||||
if((pnsData->noiseFuzzyMeasure[sfb]>pnsConf->np.gapFillThr) &&
|
||||
(pnsData->pnsFlag[sfb-1]) && (pnsData->pnsFlag[sfb+1])) {
|
||||
pnsData->pnsFlag[sfb] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(maxSfbPerGroup>0) {
|
||||
/* avoid PNS hole */
|
||||
if((pnsData->noiseFuzzyMeasure[maxSfbPerGroup-1]>pnsConf->np.gapFillThr) && (pnsData->pnsFlag[maxSfbPerGroup-2])) {
|
||||
pnsData->pnsFlag[maxSfbPerGroup-1] = 1;
|
||||
}
|
||||
/* avoid single PNS band */
|
||||
if(pnsData->pnsFlag[maxSfbPerGroup-2]==0) {
|
||||
pnsData->pnsFlag[maxSfbPerGroup-1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* avoid single PNS bands */
|
||||
if(pnsData->pnsFlag[1]==0) {
|
||||
pnsData->pnsFlag[0] = 0;
|
||||
}
|
||||
|
||||
for(sfb=1; sfb<maxSfbPerGroup-1; sfb++) {
|
||||
if((pnsData->pnsFlag[sfb-1]==0)&&(pnsData->pnsFlag[sfb+1]==0)) {
|
||||
pnsData->pnsFlag[sfb] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
calculate noiseNrg's
|
||||
*/
|
||||
FDKaacEnc_CalcNoiseNrgs( sfbActive,
|
||||
pnsData->pnsFlag,
|
||||
sfbEnergyLdData,
|
||||
noiseNrg );
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
functionname:FDKaacEnc_FDKaacEnc_noiseDetection
|
||||
description: wrapper for noisedet.c
|
||||
returns:
|
||||
input: pns config structure
|
||||
pns data structure (modified),
|
||||
sfbActive
|
||||
tns order and prediction gain
|
||||
pointer to mdct Spectrumand Sfb Energy
|
||||
pointer to Sfb tonality
|
||||
output: noiseFuzzyMeasure in structure pnsData
|
||||
flags tonal / nontonal
|
||||
|
||||
*****************************************************************************/
|
||||
static void FDKaacEnc_FDKaacEnc_noiseDetection( PNS_CONFIG *pnsConf,
|
||||
PNS_DATA *pnsData,
|
||||
const INT sfbActive,
|
||||
const INT *sfbOffset,
|
||||
int tnsOrder,
|
||||
INT tnsPredictionGain,
|
||||
INT tnsActive,
|
||||
FIXP_DBL *mdctSpectrum,
|
||||
INT *sfbMaxScaleSpec,
|
||||
FIXP_SGL *sfbtonality )
|
||||
{
|
||||
INT condition = TRUE;
|
||||
if ( !(pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMLEXITY) ) {
|
||||
condition = (tnsOrder > 3);
|
||||
}
|
||||
/*
|
||||
no PNS if heavy TNS activity
|
||||
clear pnsData->noiseFuzzyMeasure
|
||||
*/
|
||||
if((pnsConf->np.detectionAlgorithmFlags & USE_TNS_GAIN_THR) &&
|
||||
(tnsPredictionGain >= pnsConf->np.tnsGainThreshold) && condition &&
|
||||
!((pnsConf->np.detectionAlgorithmFlags & USE_TNS_PNS) && (tnsPredictionGain >= pnsConf->np.tnsPNSGainThreshold) && (tnsActive)) )
|
||||
{
|
||||
/* clear all noiseFuzzyMeasure */
|
||||
FDKmemclear(pnsData->noiseFuzzyMeasure, sfbActive*sizeof(FIXP_SGL));
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
call noise detection, output in pnsData->noiseFuzzyMeasure,
|
||||
use real mdct spectral data
|
||||
*/
|
||||
FDKaacEnc_noiseDetect( mdctSpectrum,
|
||||
sfbMaxScaleSpec,
|
||||
sfbActive,
|
||||
sfbOffset,
|
||||
pnsData->noiseFuzzyMeasure,
|
||||
&pnsConf->np,
|
||||
sfbtonality);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
functionname:FDKaacEnc_CalcNoiseNrgs
|
||||
description: Calculate the NoiseNrg's
|
||||
returns:
|
||||
input: sfbActive
|
||||
if pnsFlag calculate NoiseNrg
|
||||
pointer to sfbEnergy and groupLen
|
||||
pointer to noiseNrg (modified)
|
||||
output: noiseNrg's in pnsFlaged sfb's
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
static void FDKaacEnc_CalcNoiseNrgs( const INT sfbActive,
|
||||
INT *RESTRICT pnsFlag,
|
||||
FIXP_DBL *RESTRICT sfbEnergyLdData,
|
||||
INT *RESTRICT noiseNrg )
|
||||
{
|
||||
int sfb;
|
||||
INT tmp = (-LOG_NORM_PCM)<<2;
|
||||
|
||||
for(sfb = 0; sfb < sfbActive; sfb++) {
|
||||
if(pnsFlag[sfb]) {
|
||||
INT nrg = (-sfbEnergyLdData[sfb]+FL2FXCONST_DBL(0.5f/64.0f))>>(DFRACT_BITS-1-7);
|
||||
noiseNrg[sfb] = tmp - nrg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
functionname:FDKaacEnc_CodePnsChannel
|
||||
description: Execute pns decission
|
||||
returns:
|
||||
input: sfbActive
|
||||
pns config structure
|
||||
use PNS if pnsFlag
|
||||
pointer to Sfb Energy, noiseNrg, Threshold
|
||||
output: set sfbThreshold high to code pe with 0,
|
||||
noiseNrg marks flag for pns coding
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
void FDKaacEnc_CodePnsChannel(const INT sfbActive,
|
||||
PNS_CONFIG *pnsConf,
|
||||
INT *RESTRICT pnsFlag,
|
||||
FIXP_DBL *RESTRICT sfbEnergyLdData,
|
||||
INT *RESTRICT noiseNrg,
|
||||
FIXP_DBL *RESTRICT sfbThresholdLdData)
|
||||
{
|
||||
INT sfb;
|
||||
INT lastiNoiseEnergy = 0;
|
||||
INT firstPNSband = 1; /* TRUE for first PNS-coded band */
|
||||
|
||||
/* no PNS */
|
||||
if(!pnsConf->usePns) {
|
||||
for(sfb = 0; sfb < sfbActive; sfb++) {
|
||||
/* no PNS coding */
|
||||
noiseNrg[sfb] = NO_NOISE_PNS;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* code PNS */
|
||||
for(sfb = 0; sfb < sfbActive; sfb++) {
|
||||
if(pnsFlag[sfb]) {
|
||||
/* high sfbThreshold causes pe = 0 */
|
||||
if(noiseNrg[sfb] != NO_NOISE_PNS)
|
||||
sfbThresholdLdData[sfb] = sfbEnergyLdData[sfb] + FL2FXCONST_DBL(1.0f/LD_DATA_SCALING);
|
||||
|
||||
/* set noiseNrg in valid region */
|
||||
if(!firstPNSband) {
|
||||
INT deltaiNoiseEnergy = noiseNrg[sfb] - lastiNoiseEnergy;
|
||||
|
||||
if(deltaiNoiseEnergy > CODE_BOOK_PNS_LAV)
|
||||
noiseNrg[sfb] -= deltaiNoiseEnergy - CODE_BOOK_PNS_LAV;
|
||||
else if(deltaiNoiseEnergy < -CODE_BOOK_PNS_LAV)
|
||||
noiseNrg[sfb] -= deltaiNoiseEnergy + CODE_BOOK_PNS_LAV;
|
||||
}
|
||||
else {
|
||||
firstPNSband = 0;
|
||||
}
|
||||
lastiNoiseEnergy = noiseNrg[sfb];
|
||||
}
|
||||
else {
|
||||
/* no PNS coding */
|
||||
noiseNrg[sfb] = NO_NOISE_PNS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
functionname:FDKaacEnc_PreProcessPnsChannelPair
|
||||
description: Calculate the correlation of noise in a channel pair
|
||||
|
||||
returns:
|
||||
input: sfbActive
|
||||
pointer to sfb energies left, right and mid channel
|
||||
pns config structure
|
||||
pns data structure left and right (modified)
|
||||
|
||||
output: noiseEnergyCorrelation in pns data structure
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
void FDKaacEnc_PreProcessPnsChannelPair(const INT sfbActive,
|
||||
FIXP_DBL *RESTRICT sfbEnergyLeft,
|
||||
FIXP_DBL *RESTRICT sfbEnergyRight,
|
||||
FIXP_DBL *RESTRICT sfbEnergyLeftLD,
|
||||
FIXP_DBL *RESTRICT sfbEnergyRightLD,
|
||||
FIXP_DBL *RESTRICT sfbEnergyMid,
|
||||
PNS_CONFIG *RESTRICT pnsConf,
|
||||
PNS_DATA *pnsDataLeft,
|
||||
PNS_DATA *pnsDataRight)
|
||||
{
|
||||
INT sfb;
|
||||
FIXP_DBL ccf;
|
||||
|
||||
if(!pnsConf->usePns)
|
||||
return;
|
||||
|
||||
FIXP_DBL *RESTRICT pNoiseEnergyCorrelationL = pnsDataLeft->noiseEnergyCorrelation;
|
||||
FIXP_DBL *RESTRICT pNoiseEnergyCorrelationR = pnsDataRight->noiseEnergyCorrelation;
|
||||
|
||||
for(sfb=0;sfb< sfbActive;sfb++) {
|
||||
FIXP_DBL quot = (sfbEnergyLeftLD[sfb]>>1) + (sfbEnergyRightLD[sfb]>>1);
|
||||
|
||||
if(quot < FL2FXCONST_DBL(-32.0f/(float)LD_DATA_SCALING))
|
||||
ccf = FL2FXCONST_DBL(0.0f);
|
||||
else {
|
||||
FIXP_DBL accu = sfbEnergyMid[sfb]- (((sfbEnergyLeft[sfb]>>1)+(sfbEnergyRight[sfb]>>1))>>1);
|
||||
INT sign = (accu < FL2FXCONST_DBL(0.0f)) ? 1 : 0 ;
|
||||
accu = fixp_abs(accu);
|
||||
|
||||
ccf = CalcLdData(accu) + FL2FXCONST_DBL((float)1.0f/(float)LD_DATA_SCALING) - quot; /* ld(accu*2) = ld(accu) + 1 */
|
||||
ccf = (ccf>=FL2FXCONST_DBL(0.0)) ? ((FIXP_DBL)MAXVAL_DBL) : (sign) ? -CalcInvLdData(ccf) : CalcInvLdData(ccf);
|
||||
}
|
||||
|
||||
pNoiseEnergyCorrelationL[sfb] = ccf;
|
||||
pNoiseEnergyCorrelationR[sfb] = ccf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
functionname:FDKaacEnc_PostProcessPnsChannelPair
|
||||
description: if PNS used at left and right channel,
|
||||
use msMask to flag correlation
|
||||
returns:
|
||||
input: sfbActive
|
||||
pns config structure
|
||||
pns data structure left and right (modified)
|
||||
pointer to msMask, flags correlation by pns coding (modified)
|
||||
Digest of MS coding
|
||||
output: pnsFlag in pns data structure,
|
||||
msFlag in msMask (flags correlation)
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
void FDKaacEnc_PostProcessPnsChannelPair(const INT sfbActive,
|
||||
PNS_CONFIG *pnsConf,
|
||||
PNS_DATA *pnsDataLeft,
|
||||
PNS_DATA *pnsDataRight,
|
||||
INT *RESTRICT msMask,
|
||||
INT *msDigest )
|
||||
{
|
||||
INT sfb;
|
||||
|
||||
if(!pnsConf->usePns)
|
||||
return;
|
||||
|
||||
for(sfb=0;sfb<sfbActive;sfb++) {
|
||||
/*
|
||||
MS post processing
|
||||
*/
|
||||
if( msMask[sfb] ) {
|
||||
if( (pnsDataLeft->pnsFlag[sfb]) &&
|
||||
(pnsDataRight->pnsFlag[sfb]) ) {
|
||||
/* AAC only: Standard */
|
||||
/* do this to avoid ms flags in layers that should not have it */
|
||||
if(pnsDataLeft->noiseEnergyCorrelation[sfb] <= pnsConf->noiseCorrelationThresh){
|
||||
msMask[sfb] = 0;
|
||||
*msDigest = MS_SOME;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
No PNS coding
|
||||
*/
|
||||
pnsDataLeft->pnsFlag[sfb] = 0;
|
||||
pnsDataRight->pnsFlag[sfb] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Use MS flag to signal noise correlation if
|
||||
pns is active in both channels
|
||||
*/
|
||||
if( (pnsDataLeft->pnsFlag[sfb]) && (pnsDataRight->pnsFlag[sfb]) ) {
|
||||
if(pnsDataLeft->noiseEnergyCorrelation[sfb] > pnsConf->noiseCorrelationThresh) {
|
||||
msMask[sfb] = 1;
|
||||
*msDigest = MS_SOME;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
52
libAACenc/src/aacenc_pns.h
Normal file
52
libAACenc/src/aacenc_pns.h
Normal file
@ -0,0 +1,52 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2001)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
|
||||
Initial author: M. Lohwasser
|
||||
contents/description: pns.h
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __PNS_H
|
||||
#define __PNS_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "pnsparam.h"
|
||||
|
||||
#define NO_NOISE_PNS FDK_INT_MIN
|
||||
|
||||
typedef struct{
|
||||
NOISEPARAMS np;
|
||||
FIXP_DBL minCorrelationEnergy;
|
||||
FIXP_DBL noiseCorrelationThresh;
|
||||
INT usePns;
|
||||
} PNS_CONFIG;
|
||||
|
||||
typedef struct{
|
||||
FIXP_SGL noiseFuzzyMeasure[MAX_GROUPED_SFB];
|
||||
FIXP_DBL noiseEnergyCorrelation[MAX_GROUPED_SFB];
|
||||
INT pnsFlag[MAX_GROUPED_SFB];
|
||||
} PNS_DATA;
|
||||
|
||||
#endif
|
1286
libAACenc/src/aacenc_tns.cpp
Normal file
1286
libAACenc/src/aacenc_tns.cpp
Normal file
File diff suppressed because it is too large
Load Diff
135
libAACenc/src/aacenc_tns.h
Normal file
135
libAACenc/src/aacenc_tns.h
Normal file
@ -0,0 +1,135 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: Alex Groeschel
|
||||
contents/description: Temporal noise shaping
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef _TNS_H
|
||||
#define _TNS_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "psy_const.h"
|
||||
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.1415926535897931f
|
||||
#endif
|
||||
|
||||
/**
|
||||
* TNS_ENABLE_MASK
|
||||
* This bitfield defines which TNS features are enabled
|
||||
* The TNS mask is composed of 4 bits.
|
||||
* tnsMask |= 0x1; activate TNS short blocks
|
||||
* tnsMask |= 0x2; activate TNS for long blocks
|
||||
* tnsMask |= 0x4; activate TNS PEAK tool for short blocks
|
||||
* tnsMask |= 0x8; activate TNS PEAK tool for long blocks
|
||||
*/
|
||||
#define TNS_ENABLE_MASK 0xf
|
||||
|
||||
/* TNS max filter order for Low Complexity MPEG4 profile */
|
||||
#define TNS_MAX_ORDER 12
|
||||
|
||||
|
||||
#define MAX_NUM_OF_FILTERS 2
|
||||
|
||||
|
||||
typedef struct{ /*stuff that is tabulated dependent on bitrate etc. */
|
||||
INT filterEnabled[MAX_NUM_OF_FILTERS];
|
||||
INT threshOn[MAX_NUM_OF_FILTERS]; /* min. prediction gain for using tns TABUL*/
|
||||
INT tnsLimitOrder[MAX_NUM_OF_FILTERS]; /* Limit for TNS order TABUL*/
|
||||
INT tnsFilterDirection[MAX_NUM_OF_FILTERS]; /* Filtering direction, 0=up, 1=down TABUL */
|
||||
INT acfSplit[MAX_NUM_OF_FILTERS];
|
||||
INT seperateFiltersAllowed;
|
||||
|
||||
}TNS_CONFIG_TABULATED;
|
||||
|
||||
|
||||
|
||||
typedef struct { /*assigned at InitTime*/
|
||||
TNS_CONFIG_TABULATED confTab;
|
||||
INT tnsActive;
|
||||
INT maxOrder; /* max. order of tns filter */
|
||||
INT coefRes;
|
||||
FIXP_DBL acfWindow[MAX_NUM_OF_FILTERS][TNS_MAX_ORDER+3+1];
|
||||
/* now some things that only probably can be done at Init time;
|
||||
could be they have to be split up for each individual (short) window or
|
||||
even filter. */
|
||||
INT lpcStartBand[MAX_NUM_OF_FILTERS];
|
||||
INT lpcStartLine[MAX_NUM_OF_FILTERS];
|
||||
INT lpcStopBand;
|
||||
INT lpcStopLine;
|
||||
|
||||
}TNS_CONFIG;
|
||||
|
||||
|
||||
typedef struct {
|
||||
INT tnsActive;
|
||||
INT predictionGain;
|
||||
} TNS_SUBBLOCK_INFO;
|
||||
|
||||
typedef struct{ /*changed at runTime*/
|
||||
TNS_SUBBLOCK_INFO subBlockInfo[TRANS_FAC];
|
||||
FIXP_DBL ratioMultTable[TRANS_FAC][MAX_SFB_SHORT];
|
||||
} TNS_DATA_SHORT;
|
||||
|
||||
typedef struct{ /*changed at runTime*/
|
||||
TNS_SUBBLOCK_INFO subBlockInfo;
|
||||
FIXP_DBL ratioMultTable[MAX_SFB_LONG];
|
||||
} TNS_DATA_LONG;
|
||||
|
||||
/* can be implemented as union */
|
||||
typedef shouldBeUnion{
|
||||
TNS_DATA_LONG Long;
|
||||
TNS_DATA_SHORT Short;
|
||||
}TNS_DATA_RAW;
|
||||
|
||||
typedef struct{
|
||||
INT numOfSubblocks;
|
||||
TNS_DATA_RAW dataRaw;
|
||||
INT tnsMaxScaleSpec;
|
||||
INT filtersMerged;
|
||||
}TNS_DATA;
|
||||
|
||||
typedef struct{
|
||||
INT numOfFilters[TRANS_FAC];
|
||||
INT coefRes[TRANS_FAC];
|
||||
INT length[TRANS_FAC][MAX_NUM_OF_FILTERS];
|
||||
INT order[TRANS_FAC][MAX_NUM_OF_FILTERS];
|
||||
INT direction[TRANS_FAC][MAX_NUM_OF_FILTERS];
|
||||
INT coefCompress[TRANS_FAC][MAX_NUM_OF_FILTERS];
|
||||
/* for Long: length TNS_MAX_ORDER (12 for LC) is required -> 12 */
|
||||
/* for Short: length TRANS_FAC*TNS_MAX_ORDER (only 5 for short LC) is required -> 8*5=40 */
|
||||
/* Currently TRANS_FAC*TNS_MAX_ORDER = 8*12 = 96 (for LC) is used (per channel)! Memory could be saved here! */
|
||||
INT coef[TRANS_FAC][MAX_NUM_OF_FILTERS][TNS_MAX_ORDER];
|
||||
}TNS_INFO;
|
||||
|
||||
INT FDKaacEnc_FreqToBandWithRounding(
|
||||
const INT freq,
|
||||
const INT fs,
|
||||
const INT numOfBands,
|
||||
const INT *bandStartOffset
|
||||
);
|
||||
|
||||
#endif /* _TNS_H */
|
2262
libAACenc/src/adj_thr.cpp
Normal file
2262
libAACenc/src/adj_thr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
79
libAACenc/src/adj_thr.h
Normal file
79
libAACenc/src/adj_thr.h
Normal file
@ -0,0 +1,79 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M. Werner
|
||||
contents/description: Threshold compensation
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef __ADJ_THR_H
|
||||
#define __ADJ_THR_H
|
||||
|
||||
|
||||
#include "adj_thr_data.h"
|
||||
#include "qc_data.h"
|
||||
#include "line_pe.h"
|
||||
#include "interface.h"
|
||||
|
||||
|
||||
|
||||
void FDKaacEnc_peCalculation(PE_DATA *peData,
|
||||
PSY_OUT_CHANNEL* psyOutChannel[(2)],
|
||||
QC_OUT_CHANNEL* qcOutChannel[(2)],
|
||||
struct TOOLSINFO *toolsInfo,
|
||||
ATS_ELEMENT* adjThrStateElement,
|
||||
const INT nChannels);
|
||||
|
||||
INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE** phAdjThr,
|
||||
INT nElements);
|
||||
|
||||
void FDKaacEnc_AdjThrInit(ADJ_THR_STATE *hAdjThr,
|
||||
const INT peMean,
|
||||
ELEMENT_BITS* elBits[(6)],
|
||||
INT nElements,
|
||||
FIXP_DBL vbrQualFactor);
|
||||
|
||||
|
||||
void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState,
|
||||
ATS_ELEMENT *AdjThrStateElement,
|
||||
PSY_OUT_CHANNEL *psyOutChannel[(2)],
|
||||
PE_DATA *peData,
|
||||
INT *grantedPe,
|
||||
INT *grantedPeCorr,
|
||||
const INT nChannels,
|
||||
const INT commonWindow,
|
||||
const INT avgBits,
|
||||
const INT bitresBits,
|
||||
const INT maxBitresBits,
|
||||
const FIXP_DBL maxBitFac,
|
||||
const INT bitDistributenMode);
|
||||
|
||||
void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(6)],
|
||||
QC_OUT_ELEMENT* qcElement[(6)],
|
||||
QC_OUT* qcOut,
|
||||
PSY_OUT_ELEMENT* psyOutElement[(6)],
|
||||
INT CBRbitrateMode,
|
||||
CHANNEL_MAPPING* cm);
|
||||
|
||||
void FDKaacEnc_AdjThrClose(ADJ_THR_STATE** hAdjThr);
|
||||
|
||||
#endif
|
88
libAACenc/src/adj_thr_data.h
Normal file
88
libAACenc/src/adj_thr_data.h
Normal file
@ -0,0 +1,88 @@
|
||||
/************************* Fast MPEG AAC Audio Encoder **********************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M. Schug / A. Groeschel
|
||||
contents/description: threshold calculations
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __ADJ_THR_DATA_H
|
||||
#define __ADJ_THR_DATA_H
|
||||
|
||||
|
||||
#include "psy_const.h"
|
||||
|
||||
typedef struct {
|
||||
FIXP_DBL clipSaveLow, clipSaveHigh;
|
||||
FIXP_DBL minBitSave, maxBitSave;
|
||||
FIXP_DBL clipSpendLow, clipSpendHigh;
|
||||
FIXP_DBL minBitSpend, maxBitSpend;
|
||||
} BRES_PARAM;
|
||||
|
||||
typedef struct {
|
||||
INT modifyMinSnr;
|
||||
INT startSfbL, startSfbS;
|
||||
} AH_PARAM;
|
||||
|
||||
typedef struct {
|
||||
FIXP_DBL maxRed;
|
||||
FIXP_DBL startRatio;
|
||||
FIXP_DBL maxRatio;
|
||||
FIXP_DBL redRatioFac;
|
||||
FIXP_DBL redOffs;
|
||||
} MINSNR_ADAPT_PARAM;
|
||||
|
||||
typedef struct {
|
||||
/* parameters for bitreservoir control */
|
||||
INT peMin, peMax;
|
||||
/* constant offset to pe */
|
||||
INT peOffset;
|
||||
/* constant PeFactor */
|
||||
FIXP_DBL bits2PeFactor_m;
|
||||
INT bits2PeFactor_e;
|
||||
/* avoid hole parameters */
|
||||
AH_PARAM ahParam;
|
||||
/* values for correction of pe */
|
||||
/* paramters for adaptation of minSnr */
|
||||
MINSNR_ADAPT_PARAM minSnrAdaptParam;
|
||||
INT peLast;
|
||||
INT dynBitsLast;
|
||||
FIXP_DBL peCorrectionFactor_m;
|
||||
INT peCorrectionFactor_e;
|
||||
|
||||
/* vbr encoding */
|
||||
FIXP_DBL vbrQualFactor;
|
||||
FIXP_DBL chaosMeasureOld;
|
||||
|
||||
/* threshold weighting */
|
||||
FIXP_DBL chaosMeasureEnFac[(2)];
|
||||
INT lastEnFacPatch[(2)];
|
||||
|
||||
} ATS_ELEMENT;
|
||||
|
||||
typedef struct {
|
||||
BRES_PARAM bresParamLong, bresParamShort;
|
||||
ATS_ELEMENT* adjThrStateElem[(6)];
|
||||
} ADJ_THR_STATE;
|
||||
|
||||
#endif
|
297
libAACenc/src/band_nrg.cpp
Normal file
297
libAACenc/src/band_nrg.cpp
Normal file
@ -0,0 +1,297 @@
|
||||
/***************************** MPEG-4 AAC Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Initial author: M. Werner
|
||||
contents/description: Band/Line energy calculations
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "band_nrg.h"
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
functionname: FDKaacEnc_CalcSfbMaxScaleSpec
|
||||
description:
|
||||
input:
|
||||
output:
|
||||
*****************************************************************************/
|
||||
void
|
||||
FDKaacEnc_CalcSfbMaxScaleSpec(const FIXP_DBL *RESTRICT mdctSpectrum,
|
||||
const INT *RESTRICT bandOffset,
|
||||
INT *RESTRICT sfbMaxScaleSpec,
|
||||
const INT numBands)
|
||||
{
|
||||
INT i,j;
|
||||
FIXP_DBL maxSpc, tmp;
|
||||
|
||||
for(i=0; i<numBands; i++) {
|
||||
maxSpc = (FIXP_DBL)0;
|
||||
for (j=bandOffset[i]; j<bandOffset[i+1]; j++) {
|
||||
tmp = fixp_abs(mdctSpectrum[j]);
|
||||
maxSpc = fixMax(maxSpc, tmp);
|
||||
}
|
||||
sfbMaxScaleSpec[i] = (maxSpc==(FIXP_DBL)0) ? (DFRACT_BITS-2) : CntLeadingZeros(maxSpc)-1;
|
||||
/* CountLeadingBits() is not necessary here since test value is always > 0 */
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
functionname: FDKaacEnc_CheckBandEnergyOptim
|
||||
description:
|
||||
input:
|
||||
output:
|
||||
*****************************************************************************/
|
||||
FIXP_DBL
|
||||
FDKaacEnc_CheckBandEnergyOptim(const FIXP_DBL *RESTRICT mdctSpectrum,
|
||||
INT *RESTRICT sfbMaxScaleSpec,
|
||||
const INT *RESTRICT bandOffset,
|
||||
const INT numBands,
|
||||
FIXP_DBL *RESTRICT bandEnergy,
|
||||
FIXP_DBL *RESTRICT bandEnergyLdData,
|
||||
INT minSpecShift)
|
||||
{
|
||||
INT i, j, scale, nr = 0;
|
||||
FIXP_DBL maxNrgLd = FL2FXCONST_DBL(-1.0f);
|
||||
FIXP_DBL maxNrg = 0;
|
||||
FIXP_DBL spec;
|
||||
|
||||
for(i=0; i<numBands; i++) {
|
||||
scale = fixMax(0, sfbMaxScaleSpec[i]-4);
|
||||
FIXP_DBL tmp = 0;
|
||||
for (j=bandOffset[i]; j<bandOffset[i+1]; j++){
|
||||
spec = mdctSpectrum[j]<<scale;
|
||||
tmp = fPow2AddDiv2(tmp, spec);
|
||||
}
|
||||
bandEnergy[i] = tmp<<1;
|
||||
|
||||
/* calculate ld of bandNrg, subtract scaling */
|
||||
bandEnergyLdData[i] = CalcLdData(bandEnergy[i]);
|
||||
if (bandEnergyLdData[i] != FL2FXCONST_DBL(-1.0f)) {
|
||||
bandEnergyLdData[i] -= scale*FL2FXCONST_DBL(2.0/64);
|
||||
}
|
||||
/* find index of maxNrg */
|
||||
if (bandEnergyLdData[i] > maxNrgLd) {
|
||||
maxNrgLd = bandEnergyLdData[i];
|
||||
nr = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* return unscaled maxNrg*/
|
||||
scale = fixMax(0,sfbMaxScaleSpec[nr]-4);
|
||||
scale = fixMax(2*(minSpecShift-scale),-(DFRACT_BITS-1));
|
||||
|
||||
maxNrg = scaleValue(bandEnergy[nr], scale);
|
||||
|
||||
return maxNrg;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
functionname: FDKaacEnc_CalcBandEnergyOptimLong
|
||||
description:
|
||||
input:
|
||||
output:
|
||||
*****************************************************************************/
|
||||
INT
|
||||
FDKaacEnc_CalcBandEnergyOptimLong(const FIXP_DBL *RESTRICT mdctSpectrum,
|
||||
INT *RESTRICT sfbMaxScaleSpec,
|
||||
const INT *RESTRICT bandOffset,
|
||||
const INT numBands,
|
||||
FIXP_DBL *RESTRICT bandEnergy,
|
||||
FIXP_DBL *RESTRICT bandEnergyLdData)
|
||||
{
|
||||
INT i, j, shiftBits = 0;
|
||||
FIXP_DBL maxNrgLd = FL2FXCONST_DBL(0.0f);
|
||||
|
||||
FIXP_DBL spec;
|
||||
|
||||
for(i=0; i<numBands; i++) {
|
||||
INT leadingBits = sfbMaxScaleSpec[i]-4; /* max sfbWidth = 96 ; 2^7=128 => 7/2 = 4 (spc*spc) */
|
||||
FIXP_DBL tmp = FL2FXCONST_DBL(0.0);
|
||||
/* don't use scaleValue() here, it increases workload quite sufficiently... */
|
||||
if (leadingBits>=0) {
|
||||
for (j=bandOffset[i];j<bandOffset[i+1];j++) {
|
||||
spec = mdctSpectrum[j]<<leadingBits;
|
||||
tmp = fPow2AddDiv2(tmp, spec);
|
||||
}
|
||||
} else {
|
||||
INT shift = -leadingBits;
|
||||
for (j=bandOffset[i];j<bandOffset[i+1];j++){
|
||||
spec = mdctSpectrum[j]>>shift;
|
||||
tmp = fPow2AddDiv2(tmp, spec);
|
||||
}
|
||||
}
|
||||
bandEnergy[i] = tmp<<1;
|
||||
}
|
||||
|
||||
/* calculate ld of bandNrg, subtract scaling */
|
||||
LdDataVector(bandEnergy, bandEnergyLdData, numBands);
|
||||
for(i=numBands; i--!=0; ) {
|
||||
FIXP_DBL scaleDiff = (sfbMaxScaleSpec[i]-4)*FL2FXCONST_DBL(2.0/64);
|
||||
|
||||
bandEnergyLdData[i] = (bandEnergyLdData[i] >= ((FL2FXCONST_DBL(-1.f)>>1) + (scaleDiff>>1)))
|
||||
? bandEnergyLdData[i]-scaleDiff : FL2FXCONST_DBL(-1.f);
|
||||
/* find maxNrgLd */
|
||||
maxNrgLd = fixMax(maxNrgLd, bandEnergyLdData[i]);
|
||||
}
|
||||
|
||||
if (maxNrgLd<=(FIXP_DBL)0)
|
||||
{
|
||||
for(i=numBands; i--!=0; )
|
||||
{
|
||||
INT scale = fixMin((sfbMaxScaleSpec[i]-4)<<1,(DFRACT_BITS-1));
|
||||
bandEnergy[i] = scaleValue(bandEnergy[i], -scale);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{ /* scale down NRGs */
|
||||
while (maxNrgLd>FL2FXCONST_DBL(0.0f))
|
||||
{
|
||||
maxNrgLd -= FL2FXCONST_DBL(2.0/64);
|
||||
shiftBits++;
|
||||
}
|
||||
for(i=numBands; i--!=0; )
|
||||
{
|
||||
INT scale = fixMin( ((sfbMaxScaleSpec[i]-4)+shiftBits)<<1, (DFRACT_BITS-1));
|
||||
bandEnergyLdData[i] -= shiftBits*FL2FXCONST_DBL(2.0/64);
|
||||
bandEnergy[i] = scaleValue(bandEnergy[i], -scale);
|
||||
}
|
||||
return shiftBits;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
functionname: FDKaacEnc_CalcBandEnergyOptimShort
|
||||
description:
|
||||
input:
|
||||
output:
|
||||
*****************************************************************************/
|
||||
void
|
||||
FDKaacEnc_CalcBandEnergyOptimShort(const FIXP_DBL *RESTRICT mdctSpectrum,
|
||||
INT *RESTRICT sfbMaxScaleSpec,
|
||||
const INT *RESTRICT bandOffset,
|
||||
const INT numBands,
|
||||
FIXP_DBL *RESTRICT bandEnergy)
|
||||
{
|
||||
INT i, j;
|
||||
|
||||
for(i=0; i<numBands; i++)
|
||||
{
|
||||
int leadingBits = fixMax(0,sfbMaxScaleSpec[i]-4); /* max sfbWidth = 96 ; 2^7=128 => 7/2 = 4 (spc*spc) */
|
||||
FIXP_DBL tmp = FL2FXCONST_DBL(0.0);
|
||||
for (j=bandOffset[i];j<bandOffset[i+1];j++)
|
||||
{
|
||||
FIXP_DBL spec = mdctSpectrum[j]<<leadingBits;
|
||||
tmp = fPow2AddDiv2(tmp, spec);
|
||||
}
|
||||
bandEnergy[i] = tmp<<1;
|
||||
}
|
||||
|
||||
for(i=0; i<numBands; i++)
|
||||
{
|
||||
INT scale = 2*fixMax(0,sfbMaxScaleSpec[i]-4); /* max sfbWidth = 96 ; 2^7=128 => 7/2 = 4 (spc*spc) */
|
||||
scale = fixMin(scale,(DFRACT_BITS-1));
|
||||
bandEnergy[i] >>= scale;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
functionname: FDKaacEnc_CalcBandNrgMSOpt
|
||||
description:
|
||||
input:
|
||||
output:
|
||||
*****************************************************************************/
|
||||
void FDKaacEnc_CalcBandNrgMSOpt(const FIXP_DBL *RESTRICT mdctSpectrumLeft,
|
||||
const FIXP_DBL *RESTRICT mdctSpectrumRight,
|
||||
INT *RESTRICT sfbMaxScaleSpecLeft,
|
||||
INT *RESTRICT sfbMaxScaleSpecRight,
|
||||
const INT *RESTRICT bandOffset,
|
||||
const INT numBands,
|
||||
FIXP_DBL *RESTRICT bandEnergyMid,
|
||||
FIXP_DBL *RESTRICT bandEnergySide,
|
||||
INT calcLdData,
|
||||
FIXP_DBL *RESTRICT bandEnergyMidLdData,
|
||||
FIXP_DBL *RESTRICT bandEnergySideLdData)
|
||||
{
|
||||
INT i, j, minScale;
|
||||
FIXP_DBL NrgMid, NrgSide, specm, specs;
|
||||
|
||||
for (i=0; i<numBands; i++) {
|
||||
|
||||
NrgMid = NrgSide = FL2FXCONST_DBL(0.0);
|
||||
minScale = fixMin(sfbMaxScaleSpecLeft[i], sfbMaxScaleSpecRight[i])-4;
|
||||
minScale = fixMax(0, minScale);
|
||||
|
||||
if (minScale > 0) {
|
||||
for (j=bandOffset[i];j<bandOffset[i+1];j++) {
|
||||
FIXP_DBL specL = mdctSpectrumLeft[j]<<(minScale-1);
|
||||
FIXP_DBL specR = mdctSpectrumRight[j]<<(minScale-1);
|
||||
specm = specL + specR;
|
||||
specs = specL - specR;
|
||||
NrgMid = fPow2AddDiv2(NrgMid, specm);
|
||||
NrgSide = fPow2AddDiv2(NrgSide, specs);
|
||||
}
|
||||
} else {
|
||||
for (j=bandOffset[i];j<bandOffset[i+1];j++) {
|
||||
FIXP_DBL specL = mdctSpectrumLeft[j]>>1;
|
||||
FIXP_DBL specR = mdctSpectrumRight[j]>>1;
|
||||
specm = specL + specR;
|
||||
specs = specL - specR;
|
||||
NrgMid = fPow2AddDiv2(NrgMid, specm);
|
||||
NrgSide = fPow2AddDiv2(NrgSide, specs);
|
||||
}
|
||||
}
|
||||
bandEnergyMid[i] = NrgMid<<1;
|
||||
bandEnergySide[i] = NrgSide<<1;
|
||||
}
|
||||
|
||||
if(calcLdData) {
|
||||
LdDataVector(bandEnergyMid, bandEnergyMidLdData, numBands);
|
||||
LdDataVector(bandEnergySide, bandEnergySideLdData, numBands);
|
||||
}
|
||||
|
||||
for (i=0; i<numBands; i++)
|
||||
{
|
||||
INT minScale = fixMin(sfbMaxScaleSpecLeft[i], sfbMaxScaleSpecRight[i]);
|
||||
INT scale = fixMax(0, 2*(minScale-4));
|
||||
|
||||
if (calcLdData)
|
||||
{
|
||||
/* using the minimal scaling of left and right channel can cause very small energies;
|
||||
check ldNrg before subtract scaling multiplication: fract*INT we don't need fMult */
|
||||
|
||||
int minus = scale*FL2FXCONST_DBL(1.0/64);
|
||||
|
||||
if (bandEnergyMidLdData[i] != FL2FXCONST_DBL(-1.0f))
|
||||
bandEnergyMidLdData[i] -= minus;
|
||||
|
||||
if (bandEnergySideLdData[i] != FL2FXCONST_DBL(-1.0f))
|
||||
bandEnergySideLdData[i] -= minus;
|
||||
}
|
||||
scale = fixMin(scale, (DFRACT_BITS-1));
|
||||
bandEnergyMid[i] >>= scale;
|
||||
bandEnergySide[i] >>= scale;
|
||||
}
|
||||
}
|
86
libAACenc/src/band_nrg.h
Normal file
86
libAACenc/src/band_nrg.h
Normal file
@ -0,0 +1,86 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): M. Werner
|
||||
Description: Band/Line energy calculation
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef _BAND_NRG_H
|
||||
#define _BAND_NRG_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
|
||||
void
|
||||
FDKaacEnc_CalcSfbMaxScaleSpec(
|
||||
const FIXP_DBL *mdctSpectrum,
|
||||
const INT *bandOffset,
|
||||
INT *sfbMaxScaleSpec,
|
||||
const INT numBands
|
||||
);
|
||||
|
||||
FIXP_DBL
|
||||
FDKaacEnc_CheckBandEnergyOptim(
|
||||
const FIXP_DBL *mdctSpectrum,
|
||||
INT *sfbMaxScaleSpec,
|
||||
const INT *bandOffset,
|
||||
const INT numBands,
|
||||
FIXP_DBL *bandEnergy,
|
||||
FIXP_DBL *bandEnergyLdData,
|
||||
INT minSpecShift
|
||||
);
|
||||
|
||||
INT
|
||||
FDKaacEnc_CalcBandEnergyOptimLong(
|
||||
const FIXP_DBL *mdctSpectrum,
|
||||
INT *sfbMaxScaleSpec,
|
||||
const INT *bandOffset,
|
||||
const INT numBands,
|
||||
FIXP_DBL *bandEnergy,
|
||||
FIXP_DBL *bandEnergyLdData
|
||||
);
|
||||
|
||||
void
|
||||
FDKaacEnc_CalcBandEnergyOptimShort(
|
||||
const FIXP_DBL *mdctSpectrum,
|
||||
INT *sfbMaxScaleSpec,
|
||||
const INT *bandOffset,
|
||||
const INT numBands,
|
||||
FIXP_DBL *bandEnergy
|
||||
);
|
||||
|
||||
|
||||
void FDKaacEnc_CalcBandNrgMSOpt(
|
||||
const FIXP_DBL *RESTRICT mdctSpectrumLeft,
|
||||
const FIXP_DBL *RESTRICT mdctSpectrumRight,
|
||||
INT *RESTRICT sfbMaxScaleSpecLeft,
|
||||
INT *RESTRICT sfbMaxScaleSpecRight,
|
||||
const INT *RESTRICT bandOffset,
|
||||
const INT numBands,
|
||||
FIXP_DBL *RESTRICT bandEnergyMid,
|
||||
FIXP_DBL *RESTRICT bandEnergySide,
|
||||
INT calcLdData,
|
||||
FIXP_DBL *RESTRICT bandEnergyMidLdData,
|
||||
FIXP_DBL *RESTRICT bandEnergySideLdData);
|
||||
|
||||
#endif
|
316
libAACenc/src/bandwidth.cpp
Normal file
316
libAACenc/src/bandwidth.cpp
Normal file
@ -0,0 +1,316 @@
|
||||
/************************* Fast MPEG AAC Audio Encoder **********************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M. Schug / A. Groeschel
|
||||
contents/description: bandwidth expert
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "channel_map.h"
|
||||
#include "bandwidth.h"
|
||||
#include "aacEnc_ram.h"
|
||||
|
||||
typedef struct{
|
||||
INT chanBitRate;
|
||||
INT bandWidthMono;
|
||||
INT bandWidth2AndMoreChan;
|
||||
|
||||
} BANDWIDTH_TAB;
|
||||
|
||||
static const BANDWIDTH_TAB bandWidthTable[] = {
|
||||
{0, 3700, 5000},
|
||||
{12000, 5000, 6400},
|
||||
{20000, 6900, 9640},
|
||||
{28000, 9600, 13050},
|
||||
{40000, 12060, 14260},
|
||||
{56000, 13950, 15500},
|
||||
{72000, 14200, 16120},
|
||||
{96000, 17000, 17000},
|
||||
{576001,17000, 17000}
|
||||
};
|
||||
|
||||
|
||||
static const BANDWIDTH_TAB bandWidthTable_LD_22050[] = {
|
||||
{ 8000, 2000, 2400},
|
||||
{12000, 2500, 2700},
|
||||
{16000, 3300, 3100},
|
||||
{24000, 6250, 7200},
|
||||
{32000, 9200, 10500},
|
||||
{40000, 16000, 16000},
|
||||
{48000, 16000, 16000},
|
||||
{360001, 16000, 16000}
|
||||
};
|
||||
|
||||
static const BANDWIDTH_TAB bandWidthTable_LD_24000[] = {
|
||||
{ 8000, 2000, 2000},
|
||||
{12000, 2000, 2300},
|
||||
{16000, 2200, 2500},
|
||||
{24000, 5650, 6400},
|
||||
{32000, 11600, 12000},
|
||||
{40000, 12000, 16000},
|
||||
{48000, 16000, 16000},
|
||||
{64000, 16000, 16000},
|
||||
{360001, 16000, 16000}
|
||||
};
|
||||
|
||||
static const BANDWIDTH_TAB bandWidthTable_LD_32000[] = {
|
||||
{ 8000, 2000, 2000},
|
||||
{12000, 2000, 2000},
|
||||
{24000, 4250, 5200},
|
||||
{32000, 8400, 9000},
|
||||
{40000, 9400, 11300},
|
||||
{48000, 11900, 13700},
|
||||
{64000, 14800, 16000},
|
||||
{76000, 16000, 16000},
|
||||
{360001, 16000, 16000}
|
||||
};
|
||||
|
||||
static const BANDWIDTH_TAB bandWidthTable_LD_44100[] = {
|
||||
{ 8000, 2000, 2000},
|
||||
{24000, 2000, 2000},
|
||||
{32000, 4400, 5700},
|
||||
{40000, 7400, 8800},
|
||||
{48000, 9000, 10700},
|
||||
{56000, 11000, 12900},
|
||||
{64000, 14400, 15500},
|
||||
{80000, 16000, 16200},
|
||||
{96000, 16500, 16000},
|
||||
{128000, 16000, 16000},
|
||||
{360001, 16000, 16000}
|
||||
};
|
||||
|
||||
static const BANDWIDTH_TAB bandWidthTable_LD_48000[] = {
|
||||
{ 8000, 2000, 2000},
|
||||
{24000, 2000, 2000},
|
||||
{32000, 4400, 5700},
|
||||
{40000, 7400, 8800},
|
||||
{48000, 9000, 10700},
|
||||
{56000, 11000, 12800},
|
||||
{64000, 14300, 15400},
|
||||
{80000, 16000, 16200},
|
||||
{96000, 16500, 16000},
|
||||
{128000, 16000, 16000},
|
||||
{360001, 16000, 16000}
|
||||
};
|
||||
|
||||
typedef struct{
|
||||
AACENC_BITRATE_MODE bitrateMode;
|
||||
int bandWidthMono;
|
||||
int bandWidth2AndMoreChan;
|
||||
} BANDWIDTH_TAB_VBR;
|
||||
|
||||
static const BANDWIDTH_TAB_VBR bandWidthTableVBR[]= {
|
||||
{AACENC_BR_MODE_CBR, 0, 0},
|
||||
{AACENC_BR_MODE_VBR_1, 13050, 13050},
|
||||
{AACENC_BR_MODE_VBR_2, 13050, 13050},
|
||||
{AACENC_BR_MODE_VBR_3, 14260, 14260},
|
||||
{AACENC_BR_MODE_VBR_4, 15500, 15500},
|
||||
{AACENC_BR_MODE_VBR_5, 48000, 48000},
|
||||
{AACENC_BR_MODE_SFR, 0, 0},
|
||||
{AACENC_BR_MODE_FF, 0, 0}
|
||||
|
||||
};
|
||||
|
||||
static INT GetBandwidthEntry(
|
||||
const INT frameLength,
|
||||
const INT sampleRate,
|
||||
const INT chanBitRate,
|
||||
const INT entryNo)
|
||||
{
|
||||
INT bandwidth = -1;
|
||||
const BANDWIDTH_TAB *pBwTab = NULL;
|
||||
INT bwTabSize = 0;
|
||||
|
||||
switch (frameLength) {
|
||||
case 960:
|
||||
case 1024:
|
||||
pBwTab = bandWidthTable;
|
||||
bwTabSize = sizeof(bandWidthTable)/sizeof(BANDWIDTH_TAB);
|
||||
break;
|
||||
case 480:
|
||||
case 512:
|
||||
switch (sampleRate) {
|
||||
case 8000:
|
||||
case 11025:
|
||||
case 12000:
|
||||
case 16000:
|
||||
case 22050:
|
||||
pBwTab = bandWidthTable_LD_22050;
|
||||
bwTabSize = sizeof(bandWidthTable_LD_22050)/sizeof(BANDWIDTH_TAB);
|
||||
break;
|
||||
case 24000:
|
||||
pBwTab = bandWidthTable_LD_24000;
|
||||
bwTabSize = sizeof(bandWidthTable_LD_24000)/sizeof(BANDWIDTH_TAB);
|
||||
break;
|
||||
case 32000:
|
||||
pBwTab = bandWidthTable_LD_32000;
|
||||
bwTabSize = sizeof(bandWidthTable_LD_32000)/sizeof(BANDWIDTH_TAB);
|
||||
break;
|
||||
case (44100):
|
||||
pBwTab = bandWidthTable_LD_44100;
|
||||
bwTabSize = sizeof(bandWidthTable_LD_44100)/sizeof(BANDWIDTH_TAB);
|
||||
break;
|
||||
case 48000:
|
||||
case 64000:
|
||||
case 88200:
|
||||
case 96000:
|
||||
pBwTab = bandWidthTable_LD_48000;
|
||||
bwTabSize = sizeof(bandWidthTable_LD_48000)/sizeof(BANDWIDTH_TAB);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pBwTab = NULL;
|
||||
bwTabSize = 0;
|
||||
}
|
||||
|
||||
if (pBwTab!=NULL) {
|
||||
int i;
|
||||
for (i=0; i<bwTabSize-1; i++) {
|
||||
if (chanBitRate >= pBwTab[i].chanBitRate &&
|
||||
chanBitRate < pBwTab[i+1].chanBitRate)
|
||||
{
|
||||
switch (frameLength) {
|
||||
case 960:
|
||||
case 1024:
|
||||
bandwidth = (entryNo==0)
|
||||
? pBwTab[i].bandWidthMono
|
||||
: pBwTab[i].bandWidth2AndMoreChan;
|
||||
break;
|
||||
case 480:
|
||||
case 512:
|
||||
{
|
||||
INT q_res = 0;
|
||||
INT startBw = (entryNo==0) ? pBwTab[i ].bandWidthMono : pBwTab[i ].bandWidth2AndMoreChan;
|
||||
INT endBw = (entryNo==0) ? pBwTab[i+1].bandWidthMono : pBwTab[i+1].bandWidth2AndMoreChan;
|
||||
INT startBr = pBwTab[i].chanBitRate;
|
||||
INT endBr = pBwTab[i+1].chanBitRate;
|
||||
|
||||
FIXP_DBL bwFac_fix = fDivNorm(chanBitRate-startBr, endBr-startBr, &q_res);
|
||||
bandwidth = (INT)scaleValue(fMult(bwFac_fix, (FIXP_DBL)(endBw-startBw)),q_res) + startBw;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
bandwidth = -1;
|
||||
}
|
||||
break;
|
||||
} /* within bitrate range */
|
||||
}
|
||||
} /* pBwTab!=NULL */
|
||||
|
||||
return bandwidth;
|
||||
}
|
||||
|
||||
|
||||
AAC_ENCODER_ERROR FDKaacEnc_DetermineBandWidth(INT* bandWidth,
|
||||
INT proposedBandWidth,
|
||||
INT bitrate,
|
||||
AACENC_BITRATE_MODE bitrateMode,
|
||||
INT sampleRate,
|
||||
INT frameLength,
|
||||
CHANNEL_MAPPING* cm,
|
||||
CHANNEL_MODE encoderMode)
|
||||
{
|
||||
AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK;
|
||||
//FIXP_DBL invBandWidthGain=FL2FXCONST_DBL(1.f);
|
||||
INT chanBitRate = bitrate/cm->nChannels;
|
||||
|
||||
/* vbr */
|
||||
switch(bitrateMode){
|
||||
case AACENC_BR_MODE_VBR_1:
|
||||
case AACENC_BR_MODE_VBR_2:
|
||||
case AACENC_BR_MODE_VBR_3:
|
||||
case AACENC_BR_MODE_VBR_4:
|
||||
case AACENC_BR_MODE_VBR_5:
|
||||
if (proposedBandWidth != 0){
|
||||
/* use given bw */
|
||||
*bandWidth = proposedBandWidth;
|
||||
} else {
|
||||
/* take bw from table */
|
||||
switch(encoderMode){
|
||||
case MODE_1:
|
||||
*bandWidth = bandWidthTableVBR[bitrateMode].bandWidthMono;
|
||||
break;
|
||||
case MODE_2:
|
||||
case MODE_1_2:
|
||||
case MODE_1_2_1:
|
||||
case MODE_1_2_2:
|
||||
case MODE_1_2_2_1:
|
||||
case MODE_1_2_2_2_1:
|
||||
*bandWidth = bandWidthTableVBR[bitrateMode].bandWidth2AndMoreChan;
|
||||
break;
|
||||
default:
|
||||
return AAC_ENC_UNSUPPORTED_CHANNELCONFIG;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AACENC_BR_MODE_CBR:
|
||||
case AACENC_BR_MODE_SFR:
|
||||
case AACENC_BR_MODE_FF:
|
||||
|
||||
/* bandwidth limiting */
|
||||
if (proposedBandWidth != 0) {
|
||||
*bandWidth = FDKmin(proposedBandWidth, FDKmin(20000, sampleRate>>1));
|
||||
}
|
||||
else { /* search reasonable bandwidth */
|
||||
|
||||
int entryNo = 0;
|
||||
|
||||
switch(encoderMode){
|
||||
case MODE_1: /* mono */
|
||||
entryNo = 0; /* use mono bandwith settings */
|
||||
break;
|
||||
|
||||
case MODE_2: /* stereo */
|
||||
case MODE_1_2: /* sce + cpe */
|
||||
case MODE_1_2_1: /* sce + cpe + sce */
|
||||
case MODE_1_2_2: /* sce + cpe + cpe */
|
||||
case MODE_1_2_2_1: /* (5.1) sce + cpe + cpe + lfe */
|
||||
case MODE_1_2_2_2_1: /* (7.1) sce + cpe + cpe + cpe + lfe */
|
||||
entryNo = 1; /* use stereo bandwith settings */
|
||||
break;
|
||||
|
||||
default:
|
||||
return AAC_ENC_UNSUPPORTED_CHANNELCONFIG;
|
||||
}
|
||||
|
||||
*bandWidth = GetBandwidthEntry(
|
||||
frameLength,
|
||||
sampleRate,
|
||||
chanBitRate,
|
||||
entryNo);
|
||||
|
||||
if (*bandWidth==-1) {
|
||||
ErrorStatus = AAC_ENC_INVALID_CHANNEL_BITRATE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*bandWidth = 0;
|
||||
return AAC_ENC_UNSUPPORTED_BITRATE_MODE;
|
||||
}
|
||||
|
||||
*bandWidth = FDKmin(*bandWidth, sampleRate/2);
|
||||
|
||||
return ErrorStatus;;
|
||||
}
|
44
libAACenc/src/bandwidth.h
Normal file
44
libAACenc/src/bandwidth.h
Normal file
@ -0,0 +1,44 @@
|
||||
/************************* Fast MPEG AAC Audio Encoder **********************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M. Schug / A. Groeschel
|
||||
contents/description: bandwidth expert
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _BANDWIDTH_H
|
||||
#define _BANDWIDTH_H
|
||||
|
||||
|
||||
#include "qc_data.h"
|
||||
|
||||
AAC_ENCODER_ERROR FDKaacEnc_DetermineBandWidth(INT* bandWidth,
|
||||
INT proposedBandwidth,
|
||||
INT bitrate,
|
||||
AACENC_BITRATE_MODE bitrateMode,
|
||||
INT sampleRate,
|
||||
INT frameLength,
|
||||
CHANNEL_MAPPING* cm,
|
||||
CHANNEL_MODE encoderMode);
|
||||
|
||||
#endif /* BANDWIDTH_H */
|
1060
libAACenc/src/bit_cnt.cpp
Normal file
1060
libAACenc/src/bit_cnt.cpp
Normal file
File diff suppressed because it is too large
Load Diff
124
libAACenc/src/bit_cnt.h
Normal file
124
libAACenc/src/bit_cnt.h
Normal file
@ -0,0 +1,124 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M.Werner
|
||||
contents/description: Huffman Bitcounter & coder
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef __BITCOUNT_H
|
||||
#define __BITCOUNT_H
|
||||
|
||||
|
||||
#include "common_fix.h"
|
||||
#include "FDK_bitstream.h"
|
||||
#include "aacEnc_rom.h"
|
||||
|
||||
#define INVALID_BITCOUNT (FDK_INT_MAX/4)
|
||||
|
||||
/*
|
||||
code book number table
|
||||
*/
|
||||
|
||||
enum codeBookNo{
|
||||
CODE_BOOK_ZERO_NO= 0,
|
||||
CODE_BOOK_1_NO= 1,
|
||||
CODE_BOOK_2_NO= 2,
|
||||
CODE_BOOK_3_NO= 3,
|
||||
CODE_BOOK_4_NO= 4,
|
||||
CODE_BOOK_5_NO= 5,
|
||||
CODE_BOOK_6_NO= 6,
|
||||
CODE_BOOK_7_NO= 7,
|
||||
CODE_BOOK_8_NO= 8,
|
||||
CODE_BOOK_9_NO= 9,
|
||||
CODE_BOOK_10_NO= 10,
|
||||
CODE_BOOK_ESC_NO= 11,
|
||||
CODE_BOOK_RES_NO= 12,
|
||||
CODE_BOOK_PNS_NO= 13,
|
||||
CODE_BOOK_IS_OUT_OF_PHASE_NO= 14,
|
||||
CODE_BOOK_IS_IN_PHASE_NO= 15
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
code book index table
|
||||
*/
|
||||
|
||||
enum codeBookNdx{
|
||||
CODE_BOOK_ZERO_NDX,
|
||||
CODE_BOOK_1_NDX,
|
||||
CODE_BOOK_2_NDX,
|
||||
CODE_BOOK_3_NDX,
|
||||
CODE_BOOK_4_NDX,
|
||||
CODE_BOOK_5_NDX,
|
||||
CODE_BOOK_6_NDX,
|
||||
CODE_BOOK_7_NDX,
|
||||
CODE_BOOK_8_NDX,
|
||||
CODE_BOOK_9_NDX,
|
||||
CODE_BOOK_10_NDX,
|
||||
CODE_BOOK_ESC_NDX,
|
||||
CODE_BOOK_RES_NDX,
|
||||
CODE_BOOK_PNS_NDX,
|
||||
CODE_BOOK_IS_OUT_OF_PHASE_NDX,
|
||||
CODE_BOOK_IS_IN_PHASE_NDX,
|
||||
NUMBER_OF_CODE_BOOKS
|
||||
};
|
||||
|
||||
/*
|
||||
code book lav table
|
||||
*/
|
||||
|
||||
enum codeBookLav{
|
||||
CODE_BOOK_ZERO_LAV=0,
|
||||
CODE_BOOK_1_LAV=1,
|
||||
CODE_BOOK_2_LAV=1,
|
||||
CODE_BOOK_3_LAV=2,
|
||||
CODE_BOOK_4_LAV=2,
|
||||
CODE_BOOK_5_LAV=4,
|
||||
CODE_BOOK_6_LAV=4,
|
||||
CODE_BOOK_7_LAV=7,
|
||||
CODE_BOOK_8_LAV=7,
|
||||
CODE_BOOK_9_LAV=12,
|
||||
CODE_BOOK_10_LAV=12,
|
||||
CODE_BOOK_ESC_LAV=16,
|
||||
CODE_BOOK_SCF_LAV=60,
|
||||
CODE_BOOK_PNS_LAV=60
|
||||
};
|
||||
|
||||
INT FDKaacEnc_bitCount(const SHORT *aQuantSpectrum,
|
||||
const INT noOfSpecLines,
|
||||
INT maxVal,
|
||||
INT *bitCountLut);
|
||||
|
||||
INT FDKaacEnc_countValues(SHORT *values, INT width, INT codeBook);
|
||||
|
||||
INT FDKaacEnc_codeValues(SHORT *values, INT width, INT codeBook, HANDLE_FDK_BITSTREAM hBitstream);
|
||||
|
||||
INT FDKaacEnc_codeScalefactorDelta(INT scalefactor, HANDLE_FDK_BITSTREAM hBitstream);
|
||||
|
||||
inline INT FDKaacEnc_bitCountScalefactorDelta(const INT delta)
|
||||
{
|
||||
FDK_ASSERT( (0 <= (delta+CODE_BOOK_SCF_LAV)) && ((delta+CODE_BOOK_SCF_LAV)<(int)(sizeof(FDKaacEnc_huff_ltabscf)/sizeof((FDKaacEnc_huff_ltabscf[0])))) );
|
||||
return((INT)FDKaacEnc_huff_ltabscf[delta+CODE_BOOK_SCF_LAV]);
|
||||
}
|
||||
|
||||
#endif
|
1431
libAACenc/src/bitenc.cpp
Normal file
1431
libAACenc/src/bitenc.cpp
Normal file
File diff suppressed because it is too large
Load Diff
120
libAACenc/src/bitenc.h
Normal file
120
libAACenc/src/bitenc.h
Normal file
@ -0,0 +1,120 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M. Werner
|
||||
contents/description: Bitstream encoder
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef _BITENC_H
|
||||
#define _BITENC_H
|
||||
|
||||
|
||||
#include "qc_data.h"
|
||||
#include "aacenc_tns.h"
|
||||
#include "channel_map.h"
|
||||
#include "interface.h" /* obsolete, when PSY_OUT is thrown out of the WritBS-call! */
|
||||
#include "FDK_audio.h"
|
||||
#include "aacenc.h"
|
||||
|
||||
#include "tpenc_lib.h"
|
||||
|
||||
typedef enum{
|
||||
MAX_ENCODER_CHANNELS = 9,
|
||||
MAX_BLOCK_TYPES = 4,
|
||||
MAX_AAC_LAYERS = 9,
|
||||
MAX_LAYERS = MAX_AAC_LAYERS , /* only one core layer if present */
|
||||
FIRST_LAY = 1 /* default layer number for AAC nonscalable */
|
||||
} _MAX_CONST;
|
||||
|
||||
#define BUFFER_MX_HUFFCB_SIZE (32*sizeof(INT)) /* our FDK_bitbuffer needs size of power 2 */
|
||||
|
||||
#define EL_ID_BITS ( 3 )
|
||||
|
||||
|
||||
/**
|
||||
* \brief Arbitrary order bitstream writer. This function can either assemble a bit stream
|
||||
* and write into the bit buffer of hTpEnc or calculate the number of static bits (signal independent)
|
||||
* TpEnc handle must be NULL in this case. Or also Calculate the minimum possible number of
|
||||
* static bits which by disabling all tools e.g. MS, TNS and sbfCnt=0. The minCnt parameter
|
||||
* has to be 1 in this latter case.
|
||||
* \param hTpEnc Transport encoder handle. If NULL, the number of static bits will be returned into
|
||||
* *pBitDemand.
|
||||
* \param pElInfo
|
||||
* \param qcOutChannel
|
||||
* \param hReorderInfo
|
||||
* \param psyOutElement
|
||||
* \param psyOutChannel
|
||||
* \param syntaxFlags Bit stream syntax flags as defined in FDK_audio.h (Audio Codec flags).
|
||||
* \param aot
|
||||
* \param epConfig
|
||||
* \param pBitDemand Pointer to an int where the amount of bits is returned into. The returned value
|
||||
* depends on if hTpEnc is NULL and minCnt.
|
||||
* \param minCnt If non-zero the value returned into *pBitDemand is the absolute minimum required amount of
|
||||
* static bits in order to write a valid bit stream.
|
||||
* \return AAC_ENCODER_ERROR error code
|
||||
*/
|
||||
AAC_ENCODER_ERROR FDKaacEnc_ChannelElementWrite( HANDLE_TRANSPORTENC hTpEnc,
|
||||
ELEMENT_INFO *pElInfo,
|
||||
QC_OUT_CHANNEL *qcOutChannel[(2)],
|
||||
PSY_OUT_ELEMENT *psyOutElement,
|
||||
PSY_OUT_CHANNEL *psyOutChannel[(2)],
|
||||
UINT syntaxFlags,
|
||||
AUDIO_OBJECT_TYPE aot,
|
||||
SCHAR epConfig,
|
||||
INT *pBitDemand,
|
||||
UCHAR minCnt
|
||||
);
|
||||
/**
|
||||
* \brief Write bit stream or account static bits
|
||||
* \param hTpEnc transport encoder handle. If NULL, the function will
|
||||
* not write any bit stream data but only count the amount
|
||||
* of static (signal independent) bits
|
||||
* \param channelMapping Channel mapping info
|
||||
* \param qcOut
|
||||
* \param psyOut
|
||||
* \param qcKernel
|
||||
* \param hBSE
|
||||
* \param aot Audio Object Type being encoded
|
||||
* \param syntaxFlags Flags indicating format specific detail
|
||||
* \param epConfig Error protection config
|
||||
*/
|
||||
AAC_ENCODER_ERROR FDKaacEnc_WriteBitstream (HANDLE_TRANSPORTENC hTpEnc,
|
||||
CHANNEL_MAPPING *channelMapping,
|
||||
QC_OUT* qcOut,
|
||||
PSY_OUT* psyOut,
|
||||
QC_STATE* qcKernel,
|
||||
AUDIO_OBJECT_TYPE aot,
|
||||
UINT syntaxFlags,
|
||||
SCHAR epConfig
|
||||
);
|
||||
|
||||
INT FDKaacEnc_writeExtensionData( HANDLE_TRANSPORTENC hTpEnc,
|
||||
QC_OUT_EXTENSION *pExtension,
|
||||
INT elInstanceTag,
|
||||
UINT alignAnchor,
|
||||
UINT syntaxFlags,
|
||||
AUDIO_OBJECT_TYPE aot,
|
||||
SCHAR epConfig
|
||||
);
|
||||
|
||||
#endif /* _BITENC_H */
|
500
libAACenc/src/block_switch.cpp
Normal file
500
libAACenc/src/block_switch.cpp
Normal file
@ -0,0 +1,500 @@
|
||||
/***************************** MPEG-4 AAC Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): M. Werner
|
||||
Description: Block switching
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
/****************** Includes *****************************/
|
||||
|
||||
#include "block_switch.h"
|
||||
#include "genericStds.h"
|
||||
|
||||
|
||||
#define LOWOV_WINDOW _LOWOV_WINDOW
|
||||
|
||||
/**************** internal function prototypes ***********/
|
||||
|
||||
static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], const INT blSwWndIdx);
|
||||
|
||||
static void FDKaacEnc_CalcWindowEnergy( BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl,
|
||||
INT windowLen);
|
||||
|
||||
|
||||
/****************** Constants *****************************/
|
||||
/* LONG START SHORT STOP LOWOV */
|
||||
static const INT blockType2windowShape[2][5] = { {SINE_WINDOW, KBD_WINDOW, WRONG_WINDOW, SINE_WINDOW, KBD_WINDOW}, /* LD */
|
||||
{KBD_WINDOW, SINE_WINDOW, SINE_WINDOW, KBD_WINDOW, WRONG_WINDOW} }; /* LC */
|
||||
|
||||
/* IIR high pass coeffs */
|
||||
|
||||
#ifndef SINETABLE_16BIT
|
||||
|
||||
static const FIXP_DBL hiPassCoeff[BLOCK_SWITCHING_IIR_LEN]=
|
||||
{
|
||||
FL2FXCONST_DBL(-0.5095),FL2FXCONST_DBL(0.7548)
|
||||
};
|
||||
|
||||
static const FIXP_DBL accWindowNrgFac = FL2FXCONST_DBL(0.3f); /* factor for accumulating filtered window energies */
|
||||
static const FIXP_DBL oneMinusAccWindowNrgFac = FL2FXCONST_DBL(0.7f);
|
||||
/* static const float attackRatio = 10.0; */ /* lower ratio limit for attacks */
|
||||
static const FIXP_DBL invAttackRatio = FL2FXCONST_DBL(0.1f); /* inverted lower ratio limit for attacks */
|
||||
|
||||
/* The next constants are scaled, because they are used for comparison with scaled values*/
|
||||
/* minimum energy for attacks */
|
||||
static const FIXP_DBL minAttackNrg = (FL2FXCONST_DBL(1e+6f*NORM_PCM_ENERGY)>>BLOCK_SWITCH_ENERGY_SHIFT); /* minimum energy for attacks */
|
||||
|
||||
#else
|
||||
|
||||
static const FIXP_SGL hiPassCoeff[BLOCK_SWITCHING_IIR_LEN]=
|
||||
{
|
||||
FL2FXCONST_SGL(-0.5095),FL2FXCONST_SGL(0.7548)
|
||||
};
|
||||
|
||||
static const FIXP_DBL accWindowNrgFac = FL2FXCONST_DBL(0.3f); /* factor for accumulating filtered window energies */
|
||||
static const FIXP_SGL oneMinusAccWindowNrgFac = FL2FXCONST_SGL(0.7f);
|
||||
/* static const float attackRatio = 10.0; */ /* lower ratio limit for attacks */
|
||||
static const FIXP_SGL invAttackRatio = FL2FXCONST_SGL(0.1f); /* inverted lower ratio limit for attacks */
|
||||
/* minimum energy for attacks */
|
||||
static const FIXP_DBL minAttackNrg = (FL2FXCONST_DBL(1e+6f*NORM_PCM_ENERGY)>>BLOCK_SWITCH_ENERGY_SHIFT); /* minimum energy for attacks */
|
||||
|
||||
#endif
|
||||
|
||||
/**************** internal function prototypes ***********/
|
||||
|
||||
static INT FDKaacEnc_GetWindowIndex(INT blockSwWindowIndex);
|
||||
|
||||
static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], const INT shortWndIdx);
|
||||
|
||||
static void FDKaacEnc_CalcWindowEnergy( BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl,
|
||||
INT windowLen);
|
||||
|
||||
|
||||
|
||||
/****************** Routines ****************************/
|
||||
void FDKaacEnc_InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, INT isLowDelay)
|
||||
{
|
||||
/* note: the pointer to timeSignal can be zeroed here, because it is initialized for every call
|
||||
to FDKaacEnc_BlockSwitching anew */
|
||||
FDKmemclear (blockSwitchingControl, sizeof(BLOCK_SWITCHING_CONTROL));
|
||||
|
||||
if (isLowDelay)
|
||||
{
|
||||
blockSwitchingControl->nBlockSwitchWindows = 4;
|
||||
blockSwitchingControl->allowShortFrames = 0;
|
||||
blockSwitchingControl->allowLookAhead = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
blockSwitchingControl->nBlockSwitchWindows = 8;
|
||||
blockSwitchingControl->allowShortFrames = 1;
|
||||
blockSwitchingControl->allowLookAhead = 1;
|
||||
}
|
||||
|
||||
blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS;
|
||||
|
||||
/* Initialize startvalue for blocktype */
|
||||
blockSwitchingControl->lastWindowSequence = LONG_WINDOW;
|
||||
blockSwitchingControl->windowShape = blockType2windowShape[blockSwitchingControl->allowShortFrames][blockSwitchingControl->lastWindowSequence];
|
||||
|
||||
}
|
||||
|
||||
static const INT suggestedGroupingTable[TRANS_FAC][MAX_NO_OF_GROUPS] =
|
||||
{
|
||||
/* Attack in Window 0 */ {1, 3, 3, 1},
|
||||
/* Attack in Window 1 */ {1, 1, 3, 3},
|
||||
/* Attack in Window 2 */ {2, 1, 3, 2},
|
||||
/* Attack in Window 3 */ {3, 1, 3, 1},
|
||||
/* Attack in Window 4 */ {3, 1, 1, 3},
|
||||
/* Attack in Window 5 */ {3, 2, 1, 2},
|
||||
/* Attack in Window 6 */ {3, 3, 1, 1},
|
||||
/* Attack in Window 7 */ {3, 3, 1, 1}
|
||||
};
|
||||
|
||||
/* change block type depending on current blocktype and whether there's an attack */
|
||||
/* assume no look-ahead */
|
||||
static const INT chgWndSq[2][N_BLOCKTYPES] =
|
||||
{
|
||||
/* LONG WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW, LOWOV_WINDOW, WRONG_WINDOW */
|
||||
/*no attack*/ {LONG_WINDOW, STOP_WINDOW, WRONG_WINDOW, LONG_WINDOW, STOP_WINDOW , WRONG_WINDOW },
|
||||
/*attack */ {START_WINDOW, LOWOV_WINDOW, WRONG_WINDOW, START_WINDOW, LOWOV_WINDOW, WRONG_WINDOW }
|
||||
};
|
||||
|
||||
/* change block type depending on current blocktype and whether there's an attack */
|
||||
/* assume look-ahead */
|
||||
static const INT chgWndSqLkAhd[2][2][N_BLOCKTYPES] =
|
||||
{
|
||||
/*attack LONG WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW LOWOV_WINDOW, WRONG_WINDOW */ /* last attack */
|
||||
/*no attack*/ { {LONG_WINDOW, SHORT_WINDOW, STOP_WINDOW, LONG_WINDOW, WRONG_WINDOW, WRONG_WINDOW}, /* no attack */
|
||||
/*attack */ {START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, START_WINDOW, WRONG_WINDOW, WRONG_WINDOW} }, /* no attack */
|
||||
/*no attack*/ { {LONG_WINDOW, SHORT_WINDOW, SHORT_WINDOW, LONG_WINDOW, WRONG_WINDOW, WRONG_WINDOW}, /* attack */
|
||||
/*attack */ {START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, START_WINDOW, WRONG_WINDOW, WRONG_WINDOW} } /* attack */
|
||||
};
|
||||
|
||||
int FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, const INT granuleLength, const int isLFE)
|
||||
{
|
||||
UINT i;
|
||||
FIXP_DBL enM1, enMax;
|
||||
|
||||
UINT nBlockSwitchWindows = blockSwitchingControl->nBlockSwitchWindows;
|
||||
|
||||
/* for LFE : only LONG window allowed */
|
||||
if (isLFE) {
|
||||
|
||||
/* case LFE: */
|
||||
/* only long blocks, always use sine windows (MPEG2 AAC, MPEG4 AAC) */
|
||||
blockSwitchingControl->lastWindowSequence = LONG_WINDOW;
|
||||
blockSwitchingControl->windowShape = SINE_WINDOW;
|
||||
blockSwitchingControl->noOfGroups = 1;
|
||||
blockSwitchingControl->groupLen[0] = 1;
|
||||
|
||||
return(0);
|
||||
};
|
||||
|
||||
/* Save current attack index as last attack index */
|
||||
blockSwitchingControl->lastattack = blockSwitchingControl->attack;
|
||||
blockSwitchingControl->lastAttackIndex = blockSwitchingControl->attackIndex;
|
||||
|
||||
/* Save current window energy as last window energy */
|
||||
FDKmemcpy(blockSwitchingControl->windowNrg[0], blockSwitchingControl->windowNrg[1], sizeof(blockSwitchingControl->windowNrg[0]));
|
||||
FDKmemcpy(blockSwitchingControl->windowNrgF[0], blockSwitchingControl->windowNrgF[1], sizeof(blockSwitchingControl->windowNrgF[0]));
|
||||
|
||||
if (blockSwitchingControl->allowShortFrames)
|
||||
{
|
||||
/* Calculate suggested grouping info for the last frame */
|
||||
|
||||
/* Reset grouping info */
|
||||
FDKmemclear (blockSwitchingControl->groupLen, sizeof(blockSwitchingControl->groupLen));
|
||||
|
||||
/* Set grouping info */
|
||||
blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS;
|
||||
|
||||
FDKmemcpy(blockSwitchingControl->groupLen, suggestedGroupingTable[blockSwitchingControl->lastAttackIndex], sizeof(blockSwitchingControl->groupLen));
|
||||
|
||||
if (blockSwitchingControl->attack == TRUE)
|
||||
blockSwitchingControl->maxWindowNrg = FDKaacEnc_GetWindowEnergy(blockSwitchingControl->windowNrg[0], blockSwitchingControl->lastAttackIndex);
|
||||
else
|
||||
blockSwitchingControl->maxWindowNrg = FL2FXCONST_DBL(0.0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Calculate unfiltered and filtered energies in subwindows and combine to segments */
|
||||
FDKaacEnc_CalcWindowEnergy(blockSwitchingControl, granuleLength>>(nBlockSwitchWindows==4? 2:3 ));
|
||||
|
||||
/* now calculate if there is an attack */
|
||||
|
||||
/* reset attack */
|
||||
blockSwitchingControl->attack = FALSE;
|
||||
|
||||
/* look for attack */
|
||||
enMax = FL2FXCONST_DBL(0.0f);
|
||||
enM1 = blockSwitchingControl->windowNrgF[0][nBlockSwitchWindows-1];
|
||||
|
||||
for (i=0; i<nBlockSwitchWindows; i++) {
|
||||
FIXP_DBL tmp = fMultDiv2(oneMinusAccWindowNrgFac, blockSwitchingControl->accWindowNrg);
|
||||
blockSwitchingControl->accWindowNrg = fMultAdd(tmp, accWindowNrgFac, enM1) ;
|
||||
|
||||
if (fMult(blockSwitchingControl->windowNrgF[1][i],invAttackRatio) > blockSwitchingControl->accWindowNrg ) {
|
||||
blockSwitchingControl->attack = TRUE;
|
||||
blockSwitchingControl->attackIndex = i;
|
||||
}
|
||||
enM1 = blockSwitchingControl->windowNrgF[1][i];
|
||||
enMax = fixMax(enMax, enM1);
|
||||
}
|
||||
|
||||
|
||||
if (enMax < minAttackNrg) blockSwitchingControl->attack = FALSE;
|
||||
|
||||
/* Check if attack spreads over frame border */
|
||||
if((blockSwitchingControl->attack == FALSE) && (blockSwitchingControl->lastattack == TRUE)) {
|
||||
/* if attack is in last window repeat SHORT_WINDOW */
|
||||
if ( ((blockSwitchingControl->windowNrgF[0][nBlockSwitchWindows-1]>>4) > fMult((FIXP_DBL)(10<<(DFRACT_BITS-1-4)), blockSwitchingControl->windowNrgF[1][1]))
|
||||
&& (blockSwitchingControl->lastAttackIndex == (INT)nBlockSwitchWindows-1)
|
||||
)
|
||||
{
|
||||
blockSwitchingControl->attack = TRUE;
|
||||
blockSwitchingControl->attackIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(blockSwitchingControl->allowLookAhead)
|
||||
{
|
||||
|
||||
|
||||
blockSwitchingControl->lastWindowSequence =
|
||||
chgWndSqLkAhd[blockSwitchingControl->lastattack][blockSwitchingControl->attack][blockSwitchingControl->lastWindowSequence];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Low Delay */
|
||||
blockSwitchingControl->lastWindowSequence =
|
||||
chgWndSq[blockSwitchingControl->attack][blockSwitchingControl->lastWindowSequence];
|
||||
}
|
||||
|
||||
|
||||
/* update window shape */
|
||||
blockSwitchingControl->windowShape = blockType2windowShape[blockSwitchingControl->allowShortFrames][blockSwitchingControl->lastWindowSequence];
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], const INT blSwWndIdx)
|
||||
{
|
||||
/* For coherency, change FDKaacEnc_GetWindowEnergy() to calcluate the energy for a block switching analysis windows,
|
||||
not for a short block. The same is done FDKaacEnc_CalcWindowEnergy(). The result of FDKaacEnc_GetWindowEnergy()
|
||||
is used for a comparision of the max energy of left/right channel. */
|
||||
|
||||
return in[blSwWndIdx];
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void FDKaacEnc_CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, INT windowLen)
|
||||
{
|
||||
INT i;
|
||||
UINT w;
|
||||
|
||||
FIXP_SGL hiPassCoeff0 = hiPassCoeff[0];
|
||||
FIXP_SGL hiPassCoeff1 = hiPassCoeff[1];
|
||||
|
||||
INT_PCM *timeSignal = blockSwitchingControl->timeSignal;
|
||||
|
||||
/* sum up scalarproduct of timesignal as windowed Energies */
|
||||
for (w=0; w < blockSwitchingControl->nBlockSwitchWindows; w++) {
|
||||
|
||||
FIXP_DBL temp_windowNrg = FL2FXCONST_DBL(0.0f);
|
||||
FIXP_DBL temp_windowNrgF = FL2FXCONST_DBL(0.0f);
|
||||
FIXP_DBL temp_iirState0 = blockSwitchingControl->iirStates[0];
|
||||
FIXP_DBL temp_iirState1 = blockSwitchingControl->iirStates[1];
|
||||
|
||||
/* windowNrg = sum(timesample^2) */
|
||||
for(i=0;i<windowLen;i++)
|
||||
{
|
||||
|
||||
FIXP_DBL tempUnfiltered, tempFiltred, t1, t2;
|
||||
/* tempUnfiltered is scaled with 1 to prevent overflows during calculation of tempFiltred */
|
||||
#if SAMPLE_BITS == DFRACT_BITS
|
||||
tempUnfiltered = (FIXP_DBL) *timeSignal++ >> 1;
|
||||
#else
|
||||
tempUnfiltered = (FIXP_DBL) *timeSignal++ << (DFRACT_BITS-SAMPLE_BITS-1);
|
||||
#endif
|
||||
t1 = fMultDiv2(hiPassCoeff1, tempUnfiltered-temp_iirState0);
|
||||
t2 = fMultDiv2(hiPassCoeff0, temp_iirState1);
|
||||
tempFiltred = (t1 - t2) << 1;
|
||||
|
||||
temp_iirState0 = tempUnfiltered;
|
||||
temp_iirState1 = tempFiltred;
|
||||
|
||||
/* subtract 2 from overallscaling (BLOCK_SWITCH_ENERGY_SHIFT)
|
||||
* because tempUnfiltered was already scaled with 1 (is 2 after squaring)
|
||||
* subtract 1 from overallscaling (BLOCK_SWITCH_ENERGY_SHIFT)
|
||||
* because of fMultDiv2 is doing a scaling by one */
|
||||
temp_windowNrg += fPow2Div2(tempUnfiltered) >> (BLOCK_SWITCH_ENERGY_SHIFT - 1 - 2);
|
||||
temp_windowNrgF += fPow2Div2(tempFiltred) >> (BLOCK_SWITCH_ENERGY_SHIFT - 1 - 2);
|
||||
}
|
||||
blockSwitchingControl->windowNrg[1][w] = temp_windowNrg;
|
||||
blockSwitchingControl->windowNrgF[1][w] = temp_windowNrgF;
|
||||
blockSwitchingControl->iirStates[0] = temp_iirState0;
|
||||
blockSwitchingControl->iirStates[1] = temp_iirState1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const UCHAR synchronizedBlockTypeTable[5][5] =
|
||||
{
|
||||
/* LONG_WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW LOWOV_WINDOW*/
|
||||
/* LONG_WINDOW */ {LONG_WINDOW, START_WINDOW, SHORT_WINDOW, STOP_WINDOW, LOWOV_WINDOW},
|
||||
/* START_WINDOW */ {START_WINDOW, START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, LOWOV_WINDOW},
|
||||
/* SHORT_WINDOW */ {SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, WRONG_WINDOW},
|
||||
/* STOP_WINDOW */ {STOP_WINDOW, SHORT_WINDOW, SHORT_WINDOW, STOP_WINDOW, LOWOV_WINDOW},
|
||||
/* LOWOV_WINDOW */ {LOWOV_WINDOW, LOWOV_WINDOW, WRONG_WINDOW, LOWOV_WINDOW, LOWOV_WINDOW},
|
||||
};
|
||||
|
||||
int FDKaacEnc_SyncBlockSwitching (
|
||||
BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft,
|
||||
BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight,
|
||||
const INT nChannels,
|
||||
const INT commonWindow )
|
||||
{
|
||||
UCHAR patchType = LONG_WINDOW;
|
||||
|
||||
if( nChannels == 2 && commonWindow == TRUE)
|
||||
{
|
||||
/* could be better with a channel loop (need a handle to psy_data) */
|
||||
/* get suggested Block Types and synchronize */
|
||||
patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlLeft->lastWindowSequence];
|
||||
patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlRight->lastWindowSequence];
|
||||
|
||||
/* sanity check (no change from low overlap window to short winow and vice versa) */
|
||||
if (patchType == WRONG_WINDOW)
|
||||
return -1; /* mixed up AAC-LC and AAC-LD */
|
||||
|
||||
/* Set synchronized Blocktype */
|
||||
blockSwitchingControlLeft->lastWindowSequence = patchType;
|
||||
blockSwitchingControlRight->lastWindowSequence = patchType;
|
||||
|
||||
/* update window shape */
|
||||
blockSwitchingControlLeft->windowShape = blockType2windowShape[blockSwitchingControlLeft->allowShortFrames][blockSwitchingControlLeft->lastWindowSequence];
|
||||
blockSwitchingControlRight->windowShape = blockType2windowShape[blockSwitchingControlLeft->allowShortFrames][blockSwitchingControlRight->lastWindowSequence];
|
||||
}
|
||||
|
||||
if (blockSwitchingControlLeft->allowShortFrames)
|
||||
{
|
||||
int i;
|
||||
|
||||
if( nChannels == 2 )
|
||||
{
|
||||
if (commonWindow == TRUE)
|
||||
{
|
||||
/* Synchronize grouping info */
|
||||
int windowSequenceLeftOld = blockSwitchingControlLeft->lastWindowSequence;
|
||||
int windowSequenceRightOld = blockSwitchingControlRight->lastWindowSequence;
|
||||
|
||||
/* Long Blocks */
|
||||
if(patchType != SHORT_WINDOW) {
|
||||
/* Set grouping info */
|
||||
blockSwitchingControlLeft->noOfGroups = 1;
|
||||
blockSwitchingControlRight->noOfGroups = 1;
|
||||
blockSwitchingControlLeft->groupLen[0] = 1;
|
||||
blockSwitchingControlRight->groupLen[0] = 1;
|
||||
|
||||
for (i = 1; i < MAX_NO_OF_GROUPS; i++)
|
||||
{
|
||||
blockSwitchingControlLeft->groupLen[i] = 0;
|
||||
blockSwitchingControlRight->groupLen[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Short Blocks */
|
||||
else {
|
||||
/* in case all two channels were detected as short-blocks before syncing, use the grouping of channel with higher maxWindowNrg */
|
||||
if( (windowSequenceLeftOld == SHORT_WINDOW) &&
|
||||
(windowSequenceRightOld == SHORT_WINDOW) )
|
||||
{
|
||||
if(blockSwitchingControlLeft->maxWindowNrg > blockSwitchingControlRight->maxWindowNrg) {
|
||||
/* Left Channel wins */
|
||||
blockSwitchingControlRight->noOfGroups = blockSwitchingControlLeft->noOfGroups;
|
||||
for (i = 0; i < MAX_NO_OF_GROUPS; i++){
|
||||
blockSwitchingControlRight->groupLen[i] = blockSwitchingControlLeft->groupLen[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Right Channel wins */
|
||||
blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups;
|
||||
for (i = 0; i < MAX_NO_OF_GROUPS; i++){
|
||||
blockSwitchingControlLeft->groupLen[i] = blockSwitchingControlRight->groupLen[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( (windowSequenceLeftOld == SHORT_WINDOW) &&
|
||||
(windowSequenceRightOld != SHORT_WINDOW) )
|
||||
{
|
||||
/* else use grouping of short-block channel */
|
||||
blockSwitchingControlRight->noOfGroups = blockSwitchingControlLeft->noOfGroups;
|
||||
for (i = 0; i < MAX_NO_OF_GROUPS; i++){
|
||||
blockSwitchingControlRight->groupLen[i] = blockSwitchingControlLeft->groupLen[i];
|
||||
}
|
||||
}
|
||||
else if ( (windowSequenceRightOld == SHORT_WINDOW) &&
|
||||
(windowSequenceLeftOld != SHORT_WINDOW) )
|
||||
{
|
||||
blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups;
|
||||
for (i = 0; i < MAX_NO_OF_GROUPS; i++){
|
||||
blockSwitchingControlLeft->groupLen[i] = blockSwitchingControlRight->groupLen[i];
|
||||
}
|
||||
} else {
|
||||
/* syncing a start and stop window ... */
|
||||
/* use a standard grouping,
|
||||
best grouping still to be determined! rtb 2006 06 07 */
|
||||
blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups = 2;
|
||||
blockSwitchingControlLeft->groupLen[0] = blockSwitchingControlRight->groupLen[0] = 4;
|
||||
blockSwitchingControlLeft->groupLen[1] = blockSwitchingControlRight->groupLen[1] = 4;
|
||||
}
|
||||
} /* Short Blocks */
|
||||
}
|
||||
else {
|
||||
/* stereo, no common window */
|
||||
if (blockSwitchingControlLeft->lastWindowSequence!=SHORT_WINDOW){
|
||||
blockSwitchingControlLeft->noOfGroups = 1;
|
||||
blockSwitchingControlLeft->groupLen[0] = 1;
|
||||
for (i = 1; i < MAX_NO_OF_GROUPS; i++)
|
||||
{
|
||||
blockSwitchingControlLeft->groupLen[i] = 0;
|
||||
}
|
||||
}
|
||||
if (blockSwitchingControlRight->lastWindowSequence!=SHORT_WINDOW){
|
||||
blockSwitchingControlRight->noOfGroups = 1;
|
||||
blockSwitchingControlRight->groupLen[0] = 1;
|
||||
for (i = 1; i < MAX_NO_OF_GROUPS; i++)
|
||||
{
|
||||
blockSwitchingControlRight->groupLen[i] = 0;
|
||||
}
|
||||
}
|
||||
} /* common window */
|
||||
} else {
|
||||
/* Mono */
|
||||
if (blockSwitchingControlLeft->lastWindowSequence!=SHORT_WINDOW){
|
||||
blockSwitchingControlLeft->noOfGroups = 1;
|
||||
blockSwitchingControlLeft->groupLen[0] = 1;
|
||||
|
||||
for (i = 1; i < MAX_NO_OF_GROUPS; i++)
|
||||
{
|
||||
blockSwitchingControlLeft->groupLen[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* allowShortFrames */
|
||||
|
||||
#ifdef BLOCK_SWITCH_DEBUG_INFO
|
||||
FDKprintf("l:%d\tr:%d\n", blockSwitchingControlLeft->lastWindowSequence, blockSwitchingControlRight->lastWindowSequence);
|
||||
#endif
|
||||
|
||||
/* Translate LOWOV_WINDOW block type to a meaningful window shape. */
|
||||
if ( ! blockSwitchingControlLeft->allowShortFrames ) {
|
||||
if ( blockSwitchingControlLeft->lastWindowSequence != LONG_WINDOW
|
||||
&& blockSwitchingControlLeft->lastWindowSequence != STOP_WINDOW )
|
||||
{
|
||||
blockSwitchingControlLeft->lastWindowSequence = LONG_WINDOW;
|
||||
blockSwitchingControlLeft->windowShape = LOL_WINDOW;
|
||||
}
|
||||
}
|
||||
if (nChannels == 2) {
|
||||
if ( ! blockSwitchingControlRight->allowShortFrames ) {
|
||||
if ( blockSwitchingControlRight->lastWindowSequence != LONG_WINDOW
|
||||
&& blockSwitchingControlRight->lastWindowSequence != STOP_WINDOW )
|
||||
{
|
||||
blockSwitchingControlRight->lastWindowSequence = LONG_WINDOW;
|
||||
blockSwitchingControlRight->windowShape = LOL_WINDOW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
85
libAACenc/src/block_switch.h
Normal file
85
libAACenc/src/block_switch.h
Normal file
@ -0,0 +1,85 @@
|
||||
/***************************** MPEG-4 AAC Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): M. Werner
|
||||
Description: Block switching
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _BLOCK_SWITCH_H
|
||||
#define _BLOCK_SWITCH_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "psy_const.h"
|
||||
|
||||
/****************** Defines ******************************/
|
||||
#define BLOCK_SWITCH_WINDOWS 8 /* number of windows for energy calculation */
|
||||
|
||||
#define BLOCK_SWITCHING_IIR_LEN 2 /* Length of HighPass-IIR-Filter for Attack-Detection */
|
||||
#define BLOCK_SWITCH_ENERGY_SHIFT 7 /* should be logDualis(BLOCK_SWITCH_WINDOW_LEN) to avoid overflow in windowNrgs. */
|
||||
|
||||
#define LAST_WINDOW 0
|
||||
#define THIS_WINDOW 1
|
||||
|
||||
|
||||
/****************** Structures ***************************/
|
||||
typedef struct{
|
||||
INT_PCM *timeSignal;
|
||||
INT lastWindowSequence;
|
||||
INT windowShape;
|
||||
INT lastWindowShape;
|
||||
UINT nBlockSwitchWindows; /* number of windows for energy calculation */
|
||||
INT attack;
|
||||
INT lastattack;
|
||||
INT attackIndex;
|
||||
INT lastAttackIndex;
|
||||
INT allowShortFrames; /* for Low Delay, don't allow short frames */
|
||||
INT allowLookAhead; /* for Low Delay, don't do look-ahead */
|
||||
INT noOfGroups;
|
||||
INT groupLen[MAX_NO_OF_GROUPS];
|
||||
FIXP_DBL maxWindowNrg; /* max energy in subwindows */
|
||||
|
||||
FIXP_DBL windowNrg[2][BLOCK_SWITCH_WINDOWS]; /* time signal energy in Subwindows (last and current) */
|
||||
FIXP_DBL windowNrgF[2][BLOCK_SWITCH_WINDOWS]; /* filtered time signal energy in segments (last and current) */
|
||||
FIXP_DBL accWindowNrg; /* recursively accumulated windowNrgF */
|
||||
|
||||
FIXP_DBL iirStates[BLOCK_SWITCHING_IIR_LEN]; /* filter delay-line */
|
||||
|
||||
} BLOCK_SWITCHING_CONTROL;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void FDKaacEnc_InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, INT isLowDelay);
|
||||
|
||||
int FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, const INT granuleLength, const int isLFE);
|
||||
|
||||
int FDKaacEnc_SyncBlockSwitching(
|
||||
BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft,
|
||||
BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight,
|
||||
const INT noOfChannels,
|
||||
const INT commonWindow);
|
||||
|
||||
#endif /* #ifndef _BLOCK_SWITCH_H */
|
499
libAACenc/src/channel_map.cpp
Normal file
499
libAACenc/src/channel_map.cpp
Normal file
@ -0,0 +1,499 @@
|
||||
/************************* Fast MPEG AAC Audio Encoder **********************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2000)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: A. Groeschel
|
||||
contents/description: channel mapping functionality
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "channel_map.h"
|
||||
#include "bitenc.h"
|
||||
#include "psy_const.h"
|
||||
#include "qc_data.h"
|
||||
#include "aacEnc_ram.h"
|
||||
|
||||
|
||||
/* channel_assignment treats the relationship of Input file channels
|
||||
to the encoder channels.
|
||||
This is necessary because the usual order in RIFF files (.wav)
|
||||
is different from the elements order in the coder given
|
||||
by Table 8.1 (implicit speaker mapping) of the AAC standard.
|
||||
|
||||
In mono and stereo case, this is trivial.
|
||||
In mc case, it looks like this:
|
||||
|
||||
Channel Input file coder chan
|
||||
5ch:
|
||||
front center 2 0 (SCE channel)
|
||||
left center 0 1 (1st of 1st CPE)
|
||||
right center 1 2 (2nd of 1st CPE)
|
||||
left surround 3 3 (1st of 2nd CPE)
|
||||
right surround 4 4 (2nd of 2nd CPE)
|
||||
|
||||
5.1ch:
|
||||
front center 2 0 (SCE channel)
|
||||
left center 0 1 (1st of 1st CPE)
|
||||
right center 1 2 (2nd of 1st CPE)
|
||||
left surround 4 3 (1st of 2nd CPE)
|
||||
right surround 5 4 (2nd of 2nd CPE)
|
||||
LFE 3 5 (LFE)
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
|
||||
CHANNEL_MODE encoderMode;
|
||||
INT channel_assignment[/*(6)*/12];
|
||||
|
||||
} CHANNEL_ASSIGNMENT_INFO_TAB;
|
||||
|
||||
|
||||
static const CHANNEL_ASSIGNMENT_INFO_TAB assignmentInfoTabMpeg[] =
|
||||
{
|
||||
{ MODE_INVALID, {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* invalid */
|
||||
{ MODE_1, { 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* mono */
|
||||
{ MODE_2, { 0, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* stereo */
|
||||
{ MODE_1_2, { 0, 1, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* 3ch */
|
||||
{ MODE_1_2_1, { 0, 1, 2, 3,-1,-1,-1,-1,-1,-1,-1,-1} }, /* 4ch */
|
||||
{ MODE_1_2_2, { 0, 1, 2, 3, 4,-1,-1,-1,-1,-1,-1,-1} }, /* 5ch */
|
||||
{ MODE_1_2_2_1, { 0, 1, 2, 3, 4, 5,-1,-1,-1,-1,-1,-1} }, /* 5.1ch */
|
||||
{ MODE_1_2_2_2_1, { 0, 1, 2, 3, 4, 5, 6, 7,-1,-1,-1,-1} }, /* 7.1ch */
|
||||
};
|
||||
|
||||
static const CHANNEL_ASSIGNMENT_INFO_TAB assignmentInfoTabWav[] =
|
||||
{
|
||||
{ MODE_INVALID, {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* invalid */
|
||||
{ MODE_1, { 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* mono */
|
||||
{ MODE_2, { 0, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* stereo */
|
||||
{ MODE_1_2, { 2, 0, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* 3ch */
|
||||
{ MODE_1_2_1, { 2, 0, 1, 3,-1,-1,-1,-1,-1,-1,-1,-1} }, /* 4ch */
|
||||
{ MODE_1_2_2, { 2, 0, 1, 3, 4,-1,-1,-1,-1,-1,-1,-1} }, /* 5ch */
|
||||
{ MODE_1_2_2_1, { 2, 0, 1, 4, 5, 3,-1,-1,-1,-1,-1,-1} }, /* 5.1ch */
|
||||
{ MODE_1_2_2_2_1, { 2, 0, 1, 6, 7, 4, 5, 3,-1,-1,-1,-1} }, /* 7.1ch */
|
||||
};
|
||||
|
||||
/* Channel mode configuration tab provides,
|
||||
corresponding number of channels and elements
|
||||
*/
|
||||
static const CHANNEL_MODE_CONFIG_TAB channelModeConfig[] =
|
||||
{
|
||||
{ MODE_1, 1, 1, 1 }, /* SCE */
|
||||
{ MODE_2, 2, 2, 1 }, /* CPE */
|
||||
{ MODE_1_2, 3, 3, 2 }, /* SCE,CPE */
|
||||
{ MODE_1_2_1, 4, 4, 3 }, /* SCE,CPE,SCE */
|
||||
{ MODE_1_2_2, 5, 5, 3 }, /* SCE,CPE,CPE */
|
||||
{ MODE_1_2_2_1, 6, 5, 4 }, /* SCE,CPE,CPE,LFE */
|
||||
{ MODE_1_2_2_2_1, 8, 7, 5 }, /* SCE,CPE,CPE,CPE,LFE */
|
||||
};
|
||||
|
||||
#define MAX_MODES (sizeof(assignmentInfoTabWav)/sizeof(CHANNEL_ASSIGNMENT_INFO_TAB))
|
||||
|
||||
const INT* FDKaacEnc_getChannelAssignment(CHANNEL_MODE encMode, CHANNEL_ORDER co)
|
||||
{
|
||||
const CHANNEL_ASSIGNMENT_INFO_TAB *pTab;
|
||||
int i;
|
||||
|
||||
if (co == CH_ORDER_MPEG)
|
||||
pTab = assignmentInfoTabMpeg;
|
||||
else
|
||||
pTab = assignmentInfoTabWav;
|
||||
|
||||
for(i=MAX_MODES-1; i>0; i--) {
|
||||
if (encMode== pTab[i].encoderMode) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (pTab[i].channel_assignment);
|
||||
}
|
||||
|
||||
AAC_ENCODER_ERROR FDKaacEnc_DetermineEncoderMode(CHANNEL_MODE* mode, INT nChannels)
|
||||
{
|
||||
INT i;
|
||||
CHANNEL_MODE encMode = MODE_INVALID;
|
||||
|
||||
if (*mode==MODE_UNKNOWN) {
|
||||
for (i=0; i<(INT)sizeof(channelModeConfig)/(INT)sizeof(CHANNEL_MODE_CONFIG_TAB); i++) {
|
||||
if (channelModeConfig[i].nChannels==nChannels) {
|
||||
encMode = channelModeConfig[i].encMode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*mode = encMode;
|
||||
}
|
||||
else {
|
||||
/* check if valid channel configuration */
|
||||
if (FDKaacEnc_GetChannelModeConfiguration(*mode)->nChannels==nChannels) {
|
||||
encMode = *mode;
|
||||
}
|
||||
}
|
||||
|
||||
if (encMode==MODE_INVALID) {
|
||||
return AAC_ENC_UNSUPPORTED_CHANNELCONFIG;
|
||||
}
|
||||
|
||||
return AAC_ENC_OK;
|
||||
}
|
||||
|
||||
static INT FDKaacEnc_initElement (ELEMENT_INFO* elInfo, MP4_ELEMENT_ID elType, INT* cnt, CHANNEL_MODE mode, CHANNEL_ORDER co, INT* it_cnt, const FIXP_DBL relBits) {
|
||||
|
||||
INT error=0;
|
||||
INT counter =*cnt;
|
||||
|
||||
const INT *assign = FDKaacEnc_getChannelAssignment(mode, co);
|
||||
|
||||
elInfo->elType=elType;
|
||||
elInfo->relativeBits = relBits;
|
||||
|
||||
switch(elInfo->elType) {
|
||||
case ID_SCE: case ID_LFE: case ID_CCE:
|
||||
elInfo->nChannelsInEl=1;
|
||||
elInfo->ChannelIndex[0]=assign[counter++];
|
||||
elInfo->instanceTag=it_cnt[elType]++;
|
||||
|
||||
break;
|
||||
case ID_CPE:
|
||||
elInfo->nChannelsInEl=2;
|
||||
elInfo->ChannelIndex[0]=assign[counter++];
|
||||
elInfo->ChannelIndex[1]=assign[counter++];
|
||||
elInfo->instanceTag=it_cnt[elType]++;
|
||||
break;
|
||||
case ID_DSE:
|
||||
elInfo->nChannelsInEl=0;
|
||||
elInfo->ChannelIndex[0]=0;
|
||||
elInfo->ChannelIndex[1]=0;
|
||||
elInfo->instanceTag=it_cnt[elType]++;
|
||||
break;
|
||||
default: error=1;
|
||||
};
|
||||
*cnt = counter;
|
||||
return error;
|
||||
|
||||
}
|
||||
|
||||
AAC_ENCODER_ERROR FDKaacEnc_InitChannelMapping(CHANNEL_MODE mode, CHANNEL_ORDER co, CHANNEL_MAPPING* cm)
|
||||
{
|
||||
INT count=0; /* count through coder channels */
|
||||
INT it_cnt[ID_END+1];
|
||||
INT i;
|
||||
|
||||
for (i=0; i<ID_END; i++)
|
||||
it_cnt[i]=0;
|
||||
|
||||
FDKmemclear(cm, sizeof(CHANNEL_MAPPING));
|
||||
|
||||
/* init channel mapping*/
|
||||
for (i=0; i<(INT)sizeof(channelModeConfig)/(INT)sizeof(CHANNEL_MODE_CONFIG_TAB); i++) {
|
||||
if (channelModeConfig[i].encMode==mode)
|
||||
{
|
||||
cm->encMode = channelModeConfig[i].encMode;
|
||||
cm->nChannels = channelModeConfig[i].nChannels;
|
||||
cm->nChannelsEff = channelModeConfig[i].nChannelsEff;
|
||||
cm->nElements = channelModeConfig[i].nElements;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* init element info struct */
|
||||
switch(mode) {
|
||||
case MODE_1:
|
||||
/* (mono) sce */
|
||||
FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, mode, co, it_cnt, (FIXP_DBL)MAXVAL_DBL);
|
||||
break;
|
||||
case MODE_2:
|
||||
/* (stereo) cpe */
|
||||
FDKaacEnc_initElement(&cm->elInfo[0], ID_CPE, &count, mode, co, it_cnt, (FIXP_DBL)MAXVAL_DBL);
|
||||
break;
|
||||
|
||||
case MODE_1_2:
|
||||
/* sce + cpe */
|
||||
FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.4f));
|
||||
FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.6f));
|
||||
break;
|
||||
|
||||
case MODE_1_2_1:
|
||||
/* sce + cpe + sce */
|
||||
FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.3f));
|
||||
FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.4f));
|
||||
FDKaacEnc_initElement(&cm->elInfo[2], ID_SCE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.3f));
|
||||
break;
|
||||
|
||||
case MODE_1_2_2:
|
||||
/* sce + cpe + cpe */
|
||||
FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.26f));
|
||||
FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.37f));
|
||||
FDKaacEnc_initElement(&cm->elInfo[2], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.37f));
|
||||
break;
|
||||
|
||||
case MODE_1_2_2_1:
|
||||
/* (5.1) sce + cpe + cpe + lfe */
|
||||
FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.24f));
|
||||
FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.35f));
|
||||
FDKaacEnc_initElement(&cm->elInfo[2], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.35f));
|
||||
FDKaacEnc_initElement(&cm->elInfo[3], ID_LFE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.06f));
|
||||
break;
|
||||
|
||||
case MODE_1_2_2_2_1:
|
||||
/* (7.1) sce + cpe + cpe + cpe + lfe */
|
||||
FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.18f));
|
||||
FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.26f));
|
||||
FDKaacEnc_initElement(&cm->elInfo[2], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.26f));
|
||||
FDKaacEnc_initElement(&cm->elInfo[3], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.26f));
|
||||
FDKaacEnc_initElement(&cm->elInfo[4], ID_LFE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.04f));
|
||||
break;
|
||||
|
||||
default:
|
||||
//*chMap=0;
|
||||
return AAC_ENC_UNSUPPORTED_CHANNELCONFIG;
|
||||
};
|
||||
|
||||
/* Prevent additional element and save memory for unused PSY_OUT_ELEMENT,
|
||||
ATS_ELEMENT, QC_OUT_ELEMENT ...
|
||||
DSE signalling is done via elDSE flag.
|
||||
*/
|
||||
// if (dseFlag == 1) {
|
||||
// it_cnt[ID_DSE]++; /* increment DSE */
|
||||
// }
|
||||
// cm->elDSE = it_cnt[ID_DSE]; /* save number of DSE elemts */
|
||||
|
||||
FDK_ASSERT(cm->nElements<=(6));
|
||||
|
||||
//*chMap = cm;
|
||||
|
||||
return AAC_ENC_OK;
|
||||
}
|
||||
|
||||
AAC_ENCODER_ERROR FDKaacEnc_InitElementBits(QC_STATE *hQC,
|
||||
CHANNEL_MAPPING *cm,
|
||||
INT bitrateTot,
|
||||
INT averageBitsTot,
|
||||
INT maxChannelBits)
|
||||
{
|
||||
int sc_brTot = CountLeadingBits(bitrateTot);
|
||||
|
||||
switch(cm->encMode) {
|
||||
case MODE_1:
|
||||
hQC->elementBits[0]->chBitrateEl = bitrateTot;
|
||||
|
||||
hQC->elementBits[0]->maxBitsEl = maxChannelBits;
|
||||
|
||||
hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits;
|
||||
break;
|
||||
|
||||
case MODE_2:
|
||||
hQC->elementBits[0]->chBitrateEl = bitrateTot>>1;
|
||||
|
||||
hQC->elementBits[0]->maxBitsEl = 2*maxChannelBits;
|
||||
|
||||
hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits;
|
||||
break;
|
||||
case MODE_1_2: {
|
||||
hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits;
|
||||
hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits;
|
||||
FIXP_DBL sceRate = cm->elInfo[0].relativeBits;
|
||||
FIXP_DBL cpeRate = cm->elInfo[1].relativeBits;
|
||||
|
||||
hQC->elementBits[0]->chBitrateEl = fMult(sceRate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>sc_brTot;
|
||||
hQC->elementBits[1]->chBitrateEl = fMult(cpeRate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>(sc_brTot+1);
|
||||
|
||||
hQC->elementBits[0]->maxBitsEl = maxChannelBits;
|
||||
hQC->elementBits[1]->maxBitsEl = 2*maxChannelBits;
|
||||
break;
|
||||
}
|
||||
case MODE_1_2_1: {
|
||||
/* sce + cpe + sce */
|
||||
hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits;
|
||||
hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits;
|
||||
hQC->elementBits[2]->relativeBitsEl = cm->elInfo[2].relativeBits;
|
||||
FIXP_DBL sce1Rate = cm->elInfo[0].relativeBits;
|
||||
FIXP_DBL cpeRate = cm->elInfo[1].relativeBits;
|
||||
FIXP_DBL sce2Rate = cm->elInfo[2].relativeBits;
|
||||
|
||||
hQC->elementBits[0]->chBitrateEl = fMult(sce1Rate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>sc_brTot;
|
||||
hQC->elementBits[1]->chBitrateEl = fMult(cpeRate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>(sc_brTot+1);
|
||||
hQC->elementBits[2]->chBitrateEl = fMult(sce2Rate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>sc_brTot;
|
||||
|
||||
hQC->elementBits[0]->maxBitsEl = maxChannelBits;
|
||||
hQC->elementBits[1]->maxBitsEl = 2*maxChannelBits;
|
||||
hQC->elementBits[2]->maxBitsEl = maxChannelBits;
|
||||
break;
|
||||
}
|
||||
case MODE_1_2_2: {
|
||||
/* sce + cpe + cpe */
|
||||
hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits;
|
||||
hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits;
|
||||
hQC->elementBits[2]->relativeBitsEl = cm->elInfo[2].relativeBits;
|
||||
FIXP_DBL sceRate = cm->elInfo[0].relativeBits;
|
||||
FIXP_DBL cpe1Rate = cm->elInfo[1].relativeBits;
|
||||
FIXP_DBL cpe2Rate = cm->elInfo[2].relativeBits;
|
||||
|
||||
hQC->elementBits[0]->chBitrateEl = fMult(sceRate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>sc_brTot;
|
||||
hQC->elementBits[1]->chBitrateEl = fMult(cpe1Rate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>(sc_brTot+1);
|
||||
hQC->elementBits[2]->chBitrateEl = fMult(cpe2Rate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>(sc_brTot+1);
|
||||
|
||||
hQC->elementBits[0]->maxBitsEl = maxChannelBits;
|
||||
hQC->elementBits[1]->maxBitsEl = 2*maxChannelBits;
|
||||
hQC->elementBits[2]->maxBitsEl = 2*maxChannelBits;
|
||||
break;
|
||||
}
|
||||
|
||||
case MODE_1_2_2_1: {
|
||||
/* (5.1) sce + cpe + cpe + lfe */
|
||||
hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits;
|
||||
hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits;
|
||||
hQC->elementBits[2]->relativeBitsEl = cm->elInfo[2].relativeBits;
|
||||
hQC->elementBits[3]->relativeBitsEl = cm->elInfo[3].relativeBits;
|
||||
FIXP_DBL sceRate = cm->elInfo[0].relativeBits;
|
||||
FIXP_DBL cpe1Rate = cm->elInfo[1].relativeBits;
|
||||
FIXP_DBL cpe2Rate = cm->elInfo[2].relativeBits;
|
||||
FIXP_DBL lfeRate = cm->elInfo[3].relativeBits;
|
||||
|
||||
int maxBitsTot = maxChannelBits * 5; /* LFE does not add to bit reservoir */
|
||||
int sc = CountLeadingBits(fixMax(maxChannelBits,averageBitsTot));
|
||||
int maxLfeBits = (int) FDKmax ( (INT)((fMult(lfeRate,(FIXP_DBL)(maxChannelBits<<sc))>>sc)<<1),
|
||||
(INT)((fMult(FL2FXCONST_DBL(1.1f/2.f),fMult(lfeRate,(FIXP_DBL)(averageBitsTot<<sc)))<<1)>>sc) );
|
||||
|
||||
maxChannelBits = (maxBitsTot - maxLfeBits);
|
||||
sc = CountLeadingBits(maxChannelBits);
|
||||
|
||||
maxChannelBits = fMult((FIXP_DBL)maxChannelBits<<sc,GetInvInt(5))>>sc;
|
||||
|
||||
hQC->elementBits[0]->chBitrateEl = fMult(sceRate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>sc_brTot;
|
||||
hQC->elementBits[1]->chBitrateEl = fMult(cpe1Rate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>(sc_brTot+1);
|
||||
hQC->elementBits[2]->chBitrateEl = fMult(cpe2Rate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>(sc_brTot+1);
|
||||
hQC->elementBits[3]->chBitrateEl = fMult(lfeRate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>sc_brTot;
|
||||
|
||||
hQC->elementBits[0]->maxBitsEl = maxChannelBits;
|
||||
hQC->elementBits[1]->maxBitsEl = 2*maxChannelBits;
|
||||
hQC->elementBits[2]->maxBitsEl = 2*maxChannelBits;
|
||||
hQC->elementBits[3]->maxBitsEl = maxLfeBits;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MODE_1_2_2_2_1:{
|
||||
/* (7.1) sce + cpe + cpe + cpe + lfe */
|
||||
hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits;
|
||||
hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits;
|
||||
hQC->elementBits[2]->relativeBitsEl = cm->elInfo[2].relativeBits;
|
||||
hQC->elementBits[3]->relativeBitsEl = cm->elInfo[3].relativeBits;
|
||||
hQC->elementBits[4]->relativeBitsEl = cm->elInfo[4].relativeBits;
|
||||
FIXP_DBL sceRate = cm->elInfo[0].relativeBits;
|
||||
FIXP_DBL cpe1Rate = cm->elInfo[1].relativeBits;
|
||||
FIXP_DBL cpe2Rate = cm->elInfo[2].relativeBits;
|
||||
FIXP_DBL cpe3Rate = cm->elInfo[3].relativeBits;
|
||||
FIXP_DBL lfeRate = cm->elInfo[4].relativeBits;
|
||||
|
||||
int maxBitsTot = maxChannelBits * 7; /* LFE does not add to bit reservoir */
|
||||
int sc = CountLeadingBits(fixMax(maxChannelBits,averageBitsTot));
|
||||
int maxLfeBits = (int) FDKmax ( (INT)((fMult(lfeRate,(FIXP_DBL)(maxChannelBits<<sc))>>sc)<<1),
|
||||
(INT)((fMult(FL2FXCONST_DBL(1.1f/2.f),fMult(lfeRate,(FIXP_DBL)(averageBitsTot<<sc)))<<1)>>sc) );
|
||||
|
||||
maxChannelBits = (maxBitsTot - maxLfeBits) / 7;
|
||||
|
||||
hQC->elementBits[0]->chBitrateEl = fMult(sceRate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>sc_brTot;
|
||||
hQC->elementBits[1]->chBitrateEl = fMult(cpe1Rate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>(sc_brTot+1);
|
||||
hQC->elementBits[2]->chBitrateEl = fMult(cpe2Rate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>(sc_brTot+1);
|
||||
hQC->elementBits[3]->chBitrateEl = fMult(cpe3Rate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>(sc_brTot+1);
|
||||
hQC->elementBits[4]->chBitrateEl = fMult(lfeRate, (FIXP_DBL)(bitrateTot<<sc_brTot))>>sc_brTot;
|
||||
|
||||
hQC->elementBits[0]->maxBitsEl = maxChannelBits;
|
||||
hQC->elementBits[1]->maxBitsEl = 2*maxChannelBits;
|
||||
hQC->elementBits[2]->maxBitsEl = 2*maxChannelBits;
|
||||
hQC->elementBits[3]->maxBitsEl = 2*maxChannelBits;
|
||||
hQC->elementBits[4]->maxBitsEl = maxLfeBits;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return AAC_ENC_UNSUPPORTED_CHANNELCONFIG;
|
||||
}
|
||||
|
||||
return AAC_ENC_OK;
|
||||
}
|
||||
|
||||
/********************************************************************************/
|
||||
/* */
|
||||
/* function: GetMonoStereoMODE(const CHANNEL_MODE mode) */
|
||||
/* */
|
||||
/* description: Determines encoder setting from channel mode. */
|
||||
/* Multichannel modes are mapped to mono or stereo modes */
|
||||
/* returns MODE_MONO in case of mono, */
|
||||
/* MODE_STEREO in case of stereo */
|
||||
/* MODE_INVALID in case of error */
|
||||
/* */
|
||||
/* input: CHANNEL_MODE mode: Encoder mode (see qc_data.h). */
|
||||
/* output: return: CM_STEREO_MODE monoStereoSetting */
|
||||
/* (MODE_INVALID: error, */
|
||||
/* MODE_MONO: mono */
|
||||
/* MODE_STEREO: stereo). */
|
||||
/* */
|
||||
/* misc: No memory is allocated. */
|
||||
/* */
|
||||
/********************************************************************************/
|
||||
|
||||
ELEMENT_MODE FDKaacEnc_GetMonoStereoMode(const CHANNEL_MODE mode){
|
||||
|
||||
ELEMENT_MODE monoStereoSetting = EL_MODE_INVALID;
|
||||
|
||||
switch(mode){
|
||||
case MODE_1: /* mono setups */
|
||||
monoStereoSetting = EL_MODE_MONO;
|
||||
break;
|
||||
case MODE_2: /* stereo setups */
|
||||
case MODE_1_2:
|
||||
case MODE_1_2_1:
|
||||
case MODE_1_2_2:
|
||||
case MODE_1_2_2_1:
|
||||
case MODE_1_2_2_2_1:
|
||||
monoStereoSetting = EL_MODE_STEREO;
|
||||
break;
|
||||
default: /* error */
|
||||
monoStereoSetting = EL_MODE_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
return monoStereoSetting;
|
||||
}
|
||||
|
||||
const CHANNEL_MODE_CONFIG_TAB* FDKaacEnc_GetChannelModeConfiguration(const CHANNEL_MODE mode)
|
||||
{
|
||||
INT i;
|
||||
const CHANNEL_MODE_CONFIG_TAB *cm_config = NULL;
|
||||
|
||||
/* get channel mode config */
|
||||
for (i=0; i<(INT)sizeof(channelModeConfig)/(INT)sizeof(CHANNEL_MODE_CONFIG_TAB); i++) {
|
||||
if (channelModeConfig[i].encMode==mode)
|
||||
{
|
||||
cm_config = &channelModeConfig[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cm_config;
|
||||
}
|
||||
|
||||
/*
|
||||
void FDKaacEnc_CloseChannelMapping (CHANNEL_MAPPING** phchMap) {
|
||||
FreeRam_ChannelMapping(phchMap);
|
||||
}
|
||||
*/
|
||||
|
72
libAACenc/src/channel_map.h
Normal file
72
libAACenc/src/channel_map.h
Normal file
@ -0,0 +1,72 @@
|
||||
/************************* Fast MPEG AAC Audio Encoder **********************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2000)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: A. Groeschel
|
||||
contents/description: channel mapping functionality
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _CHANNEL_MAP_H
|
||||
#define _CHANNEL_MAP_H
|
||||
|
||||
|
||||
#include "aacenc.h"
|
||||
#include "psy_const.h"
|
||||
#include "qc_data.h"
|
||||
|
||||
typedef struct {
|
||||
CHANNEL_MODE encMode;
|
||||
INT nChannels;
|
||||
INT nChannelsEff;
|
||||
INT nElements;
|
||||
} CHANNEL_MODE_CONFIG_TAB;
|
||||
|
||||
|
||||
/* Element mode */
|
||||
typedef enum {
|
||||
EL_MODE_INVALID = 0,
|
||||
EL_MODE_MONO,
|
||||
EL_MODE_STEREO
|
||||
} ELEMENT_MODE;
|
||||
|
||||
|
||||
AAC_ENCODER_ERROR FDKaacEnc_DetermineEncoderMode(CHANNEL_MODE* mode,
|
||||
INT nChannels);
|
||||
|
||||
AAC_ENCODER_ERROR FDKaacEnc_InitChannelMapping(CHANNEL_MODE mode,
|
||||
CHANNEL_ORDER co,
|
||||
CHANNEL_MAPPING* chMap);
|
||||
|
||||
AAC_ENCODER_ERROR FDKaacEnc_InitElementBits(QC_STATE *hQC,
|
||||
CHANNEL_MAPPING *cm,
|
||||
INT bitrateTot,
|
||||
INT averageBitsTot,
|
||||
INT maxChannelBits);
|
||||
|
||||
ELEMENT_MODE FDKaacEnc_GetMonoStereoMode(const CHANNEL_MODE mode);
|
||||
|
||||
const CHANNEL_MODE_CONFIG_TAB* FDKaacEnc_GetChannelModeConfiguration(const CHANNEL_MODE mode);
|
||||
|
||||
//void FDKaacEnc_CloseChannelMapping (CHANNEL_MAPPING** phchMap);
|
||||
|
||||
#endif /* CHANNEL_MAP_H */
|
99
libAACenc/src/chaosmeasure.cpp
Normal file
99
libAACenc/src/chaosmeasure.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1997)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M. Werner
|
||||
contents/description: Chaos measure calculation
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "chaosmeasure.h"
|
||||
|
||||
/*****************************************************************************
|
||||
functionname: FDKaacEnc_FDKaacEnc_CalculateChaosMeasurePeakFast
|
||||
description: Eberlein method of chaos measure calculation by high-pass
|
||||
filtering amplitude spectrum
|
||||
A special case of FDKaacEnc_CalculateChaosMeasureTonalGeneric --
|
||||
highly optimized
|
||||
*****************************************************************************/
|
||||
static void
|
||||
FDKaacEnc_FDKaacEnc_CalculateChaosMeasurePeakFast( FIXP_DBL *RESTRICT paMDCTDataNM0,
|
||||
INT numberOfLines,
|
||||
FIXP_DBL *RESTRICT chaosMeasure )
|
||||
{
|
||||
INT i, j;
|
||||
|
||||
/* calculate chaos measure by "peak filter" */
|
||||
for (i=0; i<2; i++) {
|
||||
/* make even and odd pass through data */
|
||||
FIXP_DBL left,center; /* left, center tap of filter */
|
||||
|
||||
left = (FIXP_DBL)((LONG)paMDCTDataNM0[i]^((LONG)paMDCTDataNM0[i]>>(DFRACT_BITS-1)));
|
||||
center = (FIXP_DBL)((LONG)paMDCTDataNM0[i+2]^((LONG)paMDCTDataNM0[i+2]>>(DFRACT_BITS-1)));
|
||||
|
||||
for (j = i+2; j < numberOfLines - 2; j+=2) {
|
||||
FIXP_DBL right = (FIXP_DBL)((LONG)paMDCTDataNM0[j+2]^((LONG)paMDCTDataNM0[j+2]>>(DFRACT_BITS-1)));
|
||||
FIXP_DBL tmp = (left>>1)+(right>>1);
|
||||
|
||||
if (tmp < center ) {
|
||||
INT leadingBits = CntLeadingZeros(center)-1;
|
||||
tmp = schur_div(tmp<<leadingBits, center<<leadingBits, 8);
|
||||
chaosMeasure[j] = fMult(tmp,tmp);
|
||||
}
|
||||
else {
|
||||
chaosMeasure[j] = (FIXP_DBL)MAXVAL_DBL;
|
||||
}
|
||||
|
||||
left = center;
|
||||
center = right;
|
||||
}
|
||||
}
|
||||
|
||||
/* provide chaos measure for first few lines */
|
||||
chaosMeasure[0] = chaosMeasure[2];
|
||||
chaosMeasure[1] = chaosMeasure[2];
|
||||
|
||||
/* provide chaos measure for last few lines */
|
||||
for (i = (numberOfLines-3); i < numberOfLines; i++)
|
||||
chaosMeasure[i] = FL2FXCONST_DBL(0.5);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
functionname: FDKaacEnc_CalculateChaosMeasure
|
||||
description: calculates a chaosmeasure for every line, different methods
|
||||
are available. 0 means tonal, 1 means noiselike
|
||||
returns:
|
||||
input: MDCT data, number of lines
|
||||
output: chaosMeasure
|
||||
*****************************************************************************/
|
||||
void
|
||||
FDKaacEnc_CalculateChaosMeasure( FIXP_DBL *paMDCTDataNM0,
|
||||
INT numberOfLines,
|
||||
FIXP_DBL *chaosMeasure )
|
||||
|
||||
{
|
||||
FDKaacEnc_FDKaacEnc_CalculateChaosMeasurePeakFast( paMDCTDataNM0,
|
||||
numberOfLines,
|
||||
chaosMeasure );
|
||||
}
|
||||
|
41
libAACenc/src/chaosmeasure.h
Normal file
41
libAACenc/src/chaosmeasure.h
Normal file
@ -0,0 +1,41 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1997)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M. Werner
|
||||
contents/description: Chaos measure calculation
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __CHAOSMEASURE_H
|
||||
#define __CHAOSMEASURE_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "psy_const.h"
|
||||
|
||||
void
|
||||
FDKaacEnc_CalculateChaosMeasure( FIXP_DBL *paMDCTDataNM0,
|
||||
INT numberOfLines,
|
||||
FIXP_DBL *chaosMeasure );
|
||||
|
||||
#endif
|
743
libAACenc/src/dyn_bits.cpp
Normal file
743
libAACenc/src/dyn_bits.cpp
Normal file
@ -0,0 +1,743 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M.Werner
|
||||
contents/description: Noiseless coder module
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "dyn_bits.h"
|
||||
#include "bit_cnt.h"
|
||||
#include "psy_const.h"
|
||||
#include "aacenc_pns.h"
|
||||
#include "aacEnc_ram.h"
|
||||
#include "aacEnc_rom.h"
|
||||
|
||||
typedef INT (*lookUpTable)[CODE_BOOK_ESC_NDX + 1];
|
||||
|
||||
static INT FDKaacEnc_getSideInfoBits(
|
||||
const SECTION_INFO* const huffsection,
|
||||
const SHORT* const sideInfoTab,
|
||||
const INT useHCR
|
||||
)
|
||||
{
|
||||
INT sideInfoBits;
|
||||
|
||||
if ( useHCR && ((huffsection->codeBook == 11) || (huffsection->codeBook >= 16)) ) {
|
||||
sideInfoBits = 5;
|
||||
}
|
||||
else {
|
||||
sideInfoBits = sideInfoTab[huffsection->sfbCnt];
|
||||
}
|
||||
|
||||
return (sideInfoBits);
|
||||
}
|
||||
|
||||
/* count bits using all possible tables */
|
||||
static void FDKaacEnc_buildBitLookUp(
|
||||
const SHORT* const quantSpectrum,
|
||||
const INT maxSfb,
|
||||
const INT* const sfbOffset,
|
||||
const UINT* const sfbMax,
|
||||
INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
|
||||
SECTION_INFO* const huffsection
|
||||
)
|
||||
{
|
||||
INT i, sfbWidth;
|
||||
|
||||
for (i = 0; i < maxSfb; i++)
|
||||
{
|
||||
huffsection[i].sfbCnt = 1;
|
||||
huffsection[i].sfbStart = i;
|
||||
huffsection[i].sectionBits = INVALID_BITCOUNT;
|
||||
huffsection[i].codeBook = -1;
|
||||
sfbWidth = sfbOffset[i + 1] - sfbOffset[i];
|
||||
FDKaacEnc_bitCount(quantSpectrum + sfbOffset[i], sfbWidth, sfbMax[i], bitLookUp[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* essential helper functions */
|
||||
static INT FDKaacEnc_findBestBook(
|
||||
const INT* const bc,
|
||||
INT* const book,
|
||||
const INT useVCB11
|
||||
)
|
||||
{
|
||||
INT minBits = INVALID_BITCOUNT, j;
|
||||
|
||||
int end = CODE_BOOK_ESC_NDX;
|
||||
|
||||
|
||||
for (j = 0; j <= end; j++)
|
||||
{
|
||||
if (bc[j] < minBits)
|
||||
{
|
||||
minBits = bc[j];
|
||||
*book = j;
|
||||
}
|
||||
}
|
||||
return (minBits);
|
||||
}
|
||||
|
||||
static INT FDKaacEnc_findMinMergeBits(
|
||||
const INT* const bc1,
|
||||
const INT* const bc2,
|
||||
const INT useVCB11
|
||||
)
|
||||
{
|
||||
INT minBits = INVALID_BITCOUNT, j;
|
||||
|
||||
int end = CODE_BOOK_ESC_NDX;
|
||||
|
||||
|
||||
for (j = 0; j <= end; j++)
|
||||
{
|
||||
if (bc1[j] + bc2[j] < minBits)
|
||||
{
|
||||
minBits = bc1[j] + bc2[j];
|
||||
}
|
||||
}
|
||||
return (minBits);
|
||||
}
|
||||
|
||||
static void FDKaacEnc_mergeBitLookUp(
|
||||
INT* const bc1,
|
||||
const INT* const bc2
|
||||
)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 0; j <= CODE_BOOK_ESC_NDX; j++)
|
||||
{
|
||||
bc1[j] = fixMin(bc1[j] + bc2[j], INVALID_BITCOUNT);
|
||||
}
|
||||
}
|
||||
|
||||
static INT FDKaacEnc_findMaxMerge(
|
||||
const INT* const mergeGainLookUp,
|
||||
const SECTION_INFO* const huffsection,
|
||||
const INT maxSfb,
|
||||
INT* const maxNdx
|
||||
)
|
||||
{
|
||||
INT i, maxMergeGain = 0;
|
||||
|
||||
for (i = 0; i + huffsection[i].sfbCnt < maxSfb; i += huffsection[i].sfbCnt)
|
||||
{
|
||||
if (mergeGainLookUp[i] > maxMergeGain)
|
||||
{
|
||||
maxMergeGain = mergeGainLookUp[i];
|
||||
*maxNdx = i;
|
||||
}
|
||||
}
|
||||
return (maxMergeGain);
|
||||
}
|
||||
|
||||
static INT FDKaacEnc_CalcMergeGain(
|
||||
const SECTION_INFO* const huffsection,
|
||||
const INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
|
||||
const SHORT* const sideInfoTab,
|
||||
const INT ndx1,
|
||||
const INT ndx2,
|
||||
const INT useVCB11
|
||||
)
|
||||
{
|
||||
INT MergeGain, MergeBits, SplitBits;
|
||||
|
||||
MergeBits = sideInfoTab[huffsection[ndx1].sfbCnt + huffsection[ndx2].sfbCnt] + FDKaacEnc_findMinMergeBits(bitLookUp[ndx1], bitLookUp[ndx2], useVCB11);
|
||||
SplitBits = huffsection[ndx1].sectionBits + huffsection[ndx2].sectionBits; /* Bit amount for splitted huffsections */
|
||||
MergeGain = SplitBits - MergeBits;
|
||||
|
||||
if ( (huffsection[ndx1].codeBook==CODE_BOOK_PNS_NO)||(huffsection[ndx2].codeBook==CODE_BOOK_PNS_NO)
|
||||
|| (huffsection[ndx1].codeBook==CODE_BOOK_IS_OUT_OF_PHASE_NO)||(huffsection[ndx2].codeBook==CODE_BOOK_IS_OUT_OF_PHASE_NO)
|
||||
|| (huffsection[ndx1].codeBook==CODE_BOOK_IS_IN_PHASE_NO)||(huffsection[ndx2].codeBook==CODE_BOOK_IS_IN_PHASE_NO)
|
||||
)
|
||||
{
|
||||
MergeGain = -1;
|
||||
}
|
||||
|
||||
return (MergeGain);
|
||||
}
|
||||
|
||||
|
||||
/* sectioning Stage 0:find minimum codbooks */
|
||||
static void FDKaacEnc_gmStage0(
|
||||
SECTION_INFO* const RESTRICT huffsection,
|
||||
const INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
|
||||
const INT maxSfb,
|
||||
const INT* const noiseNrg,
|
||||
const INT* const isBook
|
||||
)
|
||||
{
|
||||
INT i;
|
||||
|
||||
for (i = 0; i < maxSfb; i++)
|
||||
{
|
||||
/* Side-Info bits will be calculated in Stage 1! */
|
||||
if (huffsection[i].sectionBits == INVALID_BITCOUNT)
|
||||
{
|
||||
/* intensity and pns codebooks are already allocated in bitcount.c */
|
||||
if(noiseNrg[i] != NO_NOISE_PNS){
|
||||
huffsection[i].codeBook=CODE_BOOK_PNS_NO;
|
||||
huffsection[i].sectionBits = 0;
|
||||
}
|
||||
else if( isBook[i] ) {
|
||||
huffsection[i].codeBook=isBook[i];
|
||||
huffsection[i].sectionBits = 0;
|
||||
}
|
||||
else {
|
||||
huffsection[i].sectionBits = FDKaacEnc_findBestBook(bitLookUp[i], &(huffsection[i].codeBook), 0); /* useVCB11 must be 0!!! */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
sectioning Stage 1:merge all connected regions with the same code book and
|
||||
calculate side info
|
||||
*/
|
||||
static void FDKaacEnc_gmStage1(
|
||||
SECTION_INFO* const RESTRICT huffsection,
|
||||
INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
|
||||
const INT maxSfb,
|
||||
const SHORT* const sideInfoTab,
|
||||
const INT useVCB11
|
||||
)
|
||||
{
|
||||
INT mergeStart = 0, mergeEnd;
|
||||
|
||||
do
|
||||
{
|
||||
for (mergeEnd = mergeStart + 1; mergeEnd < maxSfb; mergeEnd++)
|
||||
{
|
||||
if (huffsection[mergeStart].codeBook != huffsection[mergeEnd].codeBook)
|
||||
break;
|
||||
|
||||
|
||||
/* we can merge. update tables, side info bits will be updated outside of this loop */
|
||||
huffsection[mergeStart].sfbCnt++;
|
||||
huffsection[mergeStart].sectionBits += huffsection[mergeEnd].sectionBits;
|
||||
|
||||
/* update bit look up for all code books */
|
||||
FDKaacEnc_mergeBitLookUp(bitLookUp[mergeStart], bitLookUp[mergeEnd]);
|
||||
}
|
||||
|
||||
/* add side info info bits */
|
||||
huffsection[mergeStart].sectionBits += FDKaacEnc_getSideInfoBits(&huffsection[mergeStart], sideInfoTab, useVCB11);
|
||||
huffsection[mergeEnd - 1].sfbStart = huffsection[mergeStart].sfbStart; /* speed up prev search */
|
||||
|
||||
mergeStart = mergeEnd;
|
||||
|
||||
} while (mergeStart < maxSfb);
|
||||
}
|
||||
|
||||
/*
|
||||
sectioning Stage 2:greedy merge algorithm, merge connected sections with
|
||||
maximum bit gain until no more gain is possible
|
||||
*/
|
||||
static void
|
||||
FDKaacEnc_gmStage2(
|
||||
SECTION_INFO* const RESTRICT huffsection,
|
||||
INT* const RESTRICT mergeGainLookUp,
|
||||
INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
|
||||
const INT maxSfb,
|
||||
const SHORT* const sideInfoTab,
|
||||
const INT useVCB11
|
||||
)
|
||||
{
|
||||
INT i;
|
||||
|
||||
for (i = 0; i + huffsection[i].sfbCnt < maxSfb; i += huffsection[i].sfbCnt)
|
||||
{
|
||||
mergeGainLookUp[i] = FDKaacEnc_CalcMergeGain(huffsection,
|
||||
bitLookUp,
|
||||
sideInfoTab,
|
||||
i,
|
||||
i + huffsection[i].sfbCnt,
|
||||
useVCB11);
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
INT maxMergeGain, maxNdx = 0, maxNdxNext, maxNdxLast;
|
||||
|
||||
maxMergeGain = FDKaacEnc_findMaxMerge(mergeGainLookUp, huffsection, maxSfb, &maxNdx);
|
||||
|
||||
/* exit while loop if no more gain is possible */
|
||||
if (maxMergeGain <= 0)
|
||||
break;
|
||||
|
||||
maxNdxNext = maxNdx + huffsection[maxNdx].sfbCnt;
|
||||
|
||||
/* merge sections with maximum bit gain */
|
||||
huffsection[maxNdx].sfbCnt += huffsection[maxNdxNext].sfbCnt;
|
||||
huffsection[maxNdx].sectionBits += huffsection[maxNdxNext].sectionBits - maxMergeGain;
|
||||
|
||||
/* update bit look up table for merged huffsection */
|
||||
FDKaacEnc_mergeBitLookUp(bitLookUp[maxNdx], bitLookUp[maxNdxNext]);
|
||||
|
||||
/* update mergeLookUpTable */
|
||||
if (maxNdx != 0)
|
||||
{
|
||||
maxNdxLast = huffsection[maxNdx - 1].sfbStart;
|
||||
mergeGainLookUp[maxNdxLast] = FDKaacEnc_CalcMergeGain(huffsection,
|
||||
bitLookUp,
|
||||
sideInfoTab,
|
||||
maxNdxLast,
|
||||
maxNdx,
|
||||
useVCB11);
|
||||
|
||||
}
|
||||
maxNdxNext = maxNdx + huffsection[maxNdx].sfbCnt;
|
||||
|
||||
huffsection[maxNdxNext - 1].sfbStart = huffsection[maxNdx].sfbStart;
|
||||
|
||||
if (maxNdxNext < maxSfb)
|
||||
mergeGainLookUp[maxNdx] = FDKaacEnc_CalcMergeGain(huffsection,
|
||||
bitLookUp,
|
||||
sideInfoTab,
|
||||
maxNdx,
|
||||
maxNdxNext,
|
||||
useVCB11);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* count bits used by the noiseless coder */
|
||||
static void FDKaacEnc_noiselessCounter(
|
||||
SECTION_DATA* const RESTRICT sectionData,
|
||||
INT mergeGainLookUp[MAX_SFB_LONG],
|
||||
INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
|
||||
const SHORT* const quantSpectrum,
|
||||
const UINT* const maxValueInSfb,
|
||||
const INT* const sfbOffset,
|
||||
const INT blockType,
|
||||
const INT* const noiseNrg,
|
||||
const INT* const isBook,
|
||||
const INT useVCB11
|
||||
)
|
||||
{
|
||||
INT grpNdx, i;
|
||||
const SHORT *sideInfoTab = NULL;
|
||||
SECTION_INFO *huffsection;
|
||||
|
||||
/* use appropriate side info table */
|
||||
switch (blockType)
|
||||
{
|
||||
case LONG_WINDOW:
|
||||
case START_WINDOW:
|
||||
case STOP_WINDOW:
|
||||
sideInfoTab = FDKaacEnc_sideInfoTabLong;
|
||||
break;
|
||||
case SHORT_WINDOW:
|
||||
sideInfoTab = FDKaacEnc_sideInfoTabShort;
|
||||
break;
|
||||
}
|
||||
|
||||
sectionData->noOfSections = 0;
|
||||
sectionData->huffmanBits = 0;
|
||||
sectionData->sideInfoBits = 0;
|
||||
|
||||
|
||||
if (sectionData->maxSfbPerGroup == 0)
|
||||
return;
|
||||
|
||||
/* loop trough groups */
|
||||
for (grpNdx = 0; grpNdx < sectionData->sfbCnt; grpNdx += sectionData->sfbPerGroup)
|
||||
{
|
||||
huffsection = sectionData->huffsection + sectionData->noOfSections;
|
||||
|
||||
/* count bits in this group */
|
||||
FDKaacEnc_buildBitLookUp(quantSpectrum,
|
||||
sectionData->maxSfbPerGroup,
|
||||
sfbOffset + grpNdx,
|
||||
maxValueInSfb + grpNdx,
|
||||
bitLookUp,
|
||||
huffsection);
|
||||
|
||||
/* 0.Stage :Find minimum Codebooks */
|
||||
FDKaacEnc_gmStage0(huffsection, bitLookUp, sectionData->maxSfbPerGroup, noiseNrg+grpNdx, isBook+grpNdx);
|
||||
|
||||
/* 1.Stage :Merge all connected regions with the same code book */
|
||||
FDKaacEnc_gmStage1(huffsection, bitLookUp, sectionData->maxSfbPerGroup, sideInfoTab, useVCB11);
|
||||
|
||||
|
||||
/*
|
||||
2.Stage
|
||||
greedy merge algorithm, merge connected huffsections with maximum bit
|
||||
gain until no more gain is possible
|
||||
*/
|
||||
|
||||
FDKaacEnc_gmStage2(huffsection,
|
||||
mergeGainLookUp,
|
||||
bitLookUp,
|
||||
sectionData->maxSfbPerGroup,
|
||||
sideInfoTab,
|
||||
useVCB11);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
compress output, calculate total huff and side bits
|
||||
since we did not update the actual codebook in stage 2
|
||||
to save time, we must set it here for later use in bitenc
|
||||
*/
|
||||
|
||||
for (i = 0; i < sectionData->maxSfbPerGroup; i += huffsection[i].sfbCnt)
|
||||
{
|
||||
if ((huffsection[i].codeBook==CODE_BOOK_PNS_NO) ||
|
||||
(huffsection[i].codeBook==CODE_BOOK_IS_OUT_OF_PHASE_NO) ||
|
||||
(huffsection[i].codeBook==CODE_BOOK_IS_IN_PHASE_NO))
|
||||
{
|
||||
huffsection[i].sectionBits=0;
|
||||
} else {
|
||||
/* the sections in the sectionData are now marked with the optimal code book */
|
||||
|
||||
FDKaacEnc_findBestBook(bitLookUp[i], &(huffsection[i].codeBook), useVCB11);
|
||||
|
||||
sectionData->huffmanBits += huffsection[i].sectionBits - FDKaacEnc_getSideInfoBits(&huffsection[i], sideInfoTab, useVCB11);
|
||||
}
|
||||
|
||||
huffsection[i].sfbStart += grpNdx;
|
||||
|
||||
/* sum up side info bits (section data bits) */
|
||||
sectionData->sideInfoBits += FDKaacEnc_getSideInfoBits(&huffsection[i], sideInfoTab, useVCB11);
|
||||
sectionData->huffsection[sectionData->noOfSections++] = huffsection[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
functionname: FDKaacEnc_scfCount
|
||||
returns : ---
|
||||
description : count bits used by scalefactors.
|
||||
|
||||
not in all cases if maxValueInSfb[] == 0 we set deltaScf
|
||||
to zero. only if the difference of the last and future
|
||||
scalefacGain is not greater then CODE_BOOK_SCF_LAV (60).
|
||||
|
||||
example:
|
||||
^
|
||||
scalefacGain |
|
||||
|
|
||||
| last 75
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| | current 50
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
| | | future 5
|
||||
| | | |
|
||||
--- ... ---------------------------- ... --------->
|
||||
sfb
|
||||
|
||||
|
||||
if maxValueInSfb[] of current is zero because of a
|
||||
notfallstrategie, we do not save bits and transmit a
|
||||
deltaScf of 25. otherwise the deltaScf between the last
|
||||
scalfacGain (75) and the future scalefacGain (5) is 70.
|
||||
|
||||
********************************************************************************/
|
||||
static void FDKaacEnc_scfCount(
|
||||
const INT* const scalefacGain,
|
||||
const UINT* const maxValueInSfb,
|
||||
SECTION_DATA* const RESTRICT sectionData,
|
||||
const INT* const isScale
|
||||
)
|
||||
{
|
||||
INT i, j, k, m, n;
|
||||
|
||||
INT lastValScf = 0;
|
||||
INT deltaScf = 0;
|
||||
INT found = 0;
|
||||
INT scfSkipCounter = 0;
|
||||
INT lastValIs = 0;
|
||||
|
||||
sectionData->scalefacBits = 0;
|
||||
|
||||
if (scalefacGain == NULL)
|
||||
return;
|
||||
|
||||
sectionData->firstScf = 0;
|
||||
|
||||
for (i=0; i<sectionData->noOfSections; i++)
|
||||
{
|
||||
if (sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO)
|
||||
{
|
||||
sectionData->firstScf = sectionData->huffsection[i].sfbStart;
|
||||
lastValScf = scalefacGain[sectionData->firstScf];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<sectionData->noOfSections; i++)
|
||||
{
|
||||
if ((sectionData->huffsection[i].codeBook == CODE_BOOK_IS_OUT_OF_PHASE_NO) ||
|
||||
(sectionData->huffsection[i].codeBook == CODE_BOOK_IS_IN_PHASE_NO))
|
||||
{
|
||||
for (j = sectionData->huffsection[i].sfbStart;
|
||||
j < sectionData->huffsection[i].sfbStart + sectionData->huffsection[i].sfbCnt;
|
||||
j++)
|
||||
{
|
||||
INT deltaIs = isScale[j]-lastValIs;
|
||||
lastValIs = isScale[j];
|
||||
sectionData->scalefacBits+=FDKaacEnc_bitCountScalefactorDelta(deltaIs);
|
||||
}
|
||||
} /* Intensity */
|
||||
else if ((sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO) &&
|
||||
(sectionData->huffsection[i].codeBook != CODE_BOOK_PNS_NO))
|
||||
{
|
||||
INT tmp = sectionData->huffsection[i].sfbStart + sectionData->huffsection[i].sfbCnt;
|
||||
for (j = sectionData->huffsection[i].sfbStart; j<tmp; j++)
|
||||
{
|
||||
/* check if we can repeat the last value to save bits */
|
||||
if (maxValueInSfb[j] == 0)
|
||||
{
|
||||
found = 0;
|
||||
/* are scalefactors skipped? */
|
||||
if (scfSkipCounter == 0)
|
||||
{
|
||||
/* end of section */
|
||||
if (j == (tmp - 1) )
|
||||
found = 0; /* search in other sections for maxValueInSfb != 0 */
|
||||
else
|
||||
{
|
||||
/* search in this section for the next maxValueInSfb[] != 0 */
|
||||
for (k = (j+1); k < tmp; k++)
|
||||
{
|
||||
if (maxValueInSfb[k] != 0)
|
||||
{
|
||||
found = 1;
|
||||
if ( (fixp_abs(scalefacGain[k] - lastValScf)) <= CODE_BOOK_SCF_LAV)
|
||||
deltaScf = 0; /* save bits */
|
||||
else
|
||||
{
|
||||
/* do not save bits */
|
||||
deltaScf = lastValScf - scalefacGain[j];
|
||||
lastValScf = scalefacGain[j];
|
||||
scfSkipCounter = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* count scalefactor skip */
|
||||
scfSkipCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
/* search for the next maxValueInSfb[] != 0 in all other sections */
|
||||
for (m=(i+1); (m < sectionData->noOfSections) && (found == 0); m++)
|
||||
{
|
||||
if ((sectionData->huffsection[m].codeBook != CODE_BOOK_ZERO_NO) && (sectionData->huffsection[m].codeBook != CODE_BOOK_PNS_NO))
|
||||
{
|
||||
INT end = sectionData->huffsection[m].sfbStart + sectionData->huffsection[m].sfbCnt;
|
||||
for (n = sectionData->huffsection[m].sfbStart; n<end; n++)
|
||||
{
|
||||
if (maxValueInSfb[n] != 0)
|
||||
{
|
||||
found = 1;
|
||||
if (fixp_abs(scalefacGain[n] - lastValScf) <= CODE_BOOK_SCF_LAV)
|
||||
deltaScf = 0; /* save bits */
|
||||
else
|
||||
{
|
||||
/* do not save bits */
|
||||
deltaScf = lastValScf - scalefacGain[j];
|
||||
lastValScf = scalefacGain[j];
|
||||
scfSkipCounter = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* count scalefactor skip */
|
||||
scfSkipCounter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* no maxValueInSfb[] != 0 found */
|
||||
if (found == 0)
|
||||
{
|
||||
deltaScf = 0;
|
||||
scfSkipCounter = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* consider skipped scalefactors */
|
||||
deltaScf = 0;
|
||||
scfSkipCounter--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
deltaScf = lastValScf - scalefacGain[j];
|
||||
lastValScf = scalefacGain[j];
|
||||
}
|
||||
sectionData->scalefacBits += FDKaacEnc_bitCountScalefactorDelta(deltaScf);
|
||||
}
|
||||
}
|
||||
} /* for (i=0; i<sectionData->noOfSections; i++) */
|
||||
}
|
||||
|
||||
#ifdef PNS_PRECOUNT_ENABLE
|
||||
/*
|
||||
preCount bits used pns
|
||||
*/
|
||||
/* estimate bits used by pns for correction of static bits */
|
||||
/* no codebook switch estimation, see AAC LD FASTENC */
|
||||
INT noisePreCount(const INT *noiseNrg, INT maxSfb)
|
||||
{
|
||||
INT noisePCMFlag = TRUE;
|
||||
INT lastValPns = 0, deltaPns;
|
||||
int i, bits=0;
|
||||
|
||||
for (i = 0; i < maxSfb; i++) {
|
||||
if (noiseNrg[i] != NO_NOISE_PNS) {
|
||||
|
||||
if (noisePCMFlag) {
|
||||
bits+=PNS_PCM_BITS;
|
||||
lastValPns = noiseNrg[i];
|
||||
noisePCMFlag = FALSE;
|
||||
}else {
|
||||
deltaPns = noiseNrg[i]-lastValPns;
|
||||
lastValPns = noiseNrg[i];
|
||||
bits+=FDKaacEnc_bitCountScalefactorDelta(deltaPns);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ( bits );
|
||||
}
|
||||
#endif /* PNS_PRECOUNT_ENABLE */
|
||||
|
||||
/* count bits used by pns */
|
||||
static void FDKaacEnc_noiseCount(
|
||||
SECTION_DATA* const RESTRICT sectionData,
|
||||
const INT* const noiseNrg
|
||||
)
|
||||
{
|
||||
INT noisePCMFlag = TRUE;
|
||||
INT lastValPns = 0, deltaPns;
|
||||
int i, j;
|
||||
|
||||
sectionData->noiseNrgBits = 0;
|
||||
|
||||
for (i = 0; i < sectionData->noOfSections; i++) {
|
||||
if (sectionData->huffsection[i].codeBook == CODE_BOOK_PNS_NO) {
|
||||
int sfbStart = sectionData->huffsection[i].sfbStart;
|
||||
int sfbEnd = sfbStart + sectionData->huffsection[i].sfbCnt;
|
||||
for (j=sfbStart; j<sfbEnd; j++) {
|
||||
|
||||
if (noisePCMFlag) {
|
||||
sectionData->noiseNrgBits+=PNS_PCM_BITS;
|
||||
lastValPns = noiseNrg[j];
|
||||
noisePCMFlag = FALSE;
|
||||
} else {
|
||||
deltaPns = noiseNrg[j]-lastValPns;
|
||||
lastValPns = noiseNrg[j];
|
||||
sectionData->noiseNrgBits+=FDKaacEnc_bitCountScalefactorDelta(deltaPns);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INT FDKaacEnc_dynBitCount(
|
||||
BITCNTR_STATE* const hBC,
|
||||
const SHORT* const quantSpectrum,
|
||||
const UINT* const maxValueInSfb,
|
||||
const INT* const scalefac,
|
||||
const INT blockType,
|
||||
const INT sfbCnt,
|
||||
const INT maxSfbPerGroup,
|
||||
const INT sfbPerGroup,
|
||||
const INT* const sfbOffset,
|
||||
SECTION_DATA* const RESTRICT sectionData,
|
||||
const INT* const noiseNrg,
|
||||
const INT* const isBook,
|
||||
const INT* const isScale,
|
||||
const UINT syntaxFlags
|
||||
)
|
||||
{
|
||||
sectionData->blockType = blockType;
|
||||
sectionData->sfbCnt = sfbCnt;
|
||||
sectionData->sfbPerGroup = sfbPerGroup;
|
||||
sectionData->noOfGroups = sfbCnt / sfbPerGroup;
|
||||
sectionData->maxSfbPerGroup = maxSfbPerGroup;
|
||||
|
||||
FDKaacEnc_noiselessCounter(
|
||||
sectionData,
|
||||
hBC->mergeGainLookUp,
|
||||
(lookUpTable)hBC->bitLookUp,
|
||||
quantSpectrum,
|
||||
maxValueInSfb,
|
||||
sfbOffset,
|
||||
blockType,
|
||||
noiseNrg,
|
||||
isBook,
|
||||
(syntaxFlags & AC_ER_VCB11)?1:0);
|
||||
|
||||
FDKaacEnc_scfCount(
|
||||
scalefac,
|
||||
maxValueInSfb,
|
||||
sectionData,
|
||||
isScale);
|
||||
|
||||
FDKaacEnc_noiseCount(sectionData,
|
||||
noiseNrg);
|
||||
|
||||
return (sectionData->huffmanBits +
|
||||
sectionData->sideInfoBits +
|
||||
sectionData->scalefacBits +
|
||||
sectionData->noiseNrgBits);
|
||||
}
|
||||
|
||||
INT FDKaacEnc_BCNew(BITCNTR_STATE **phBC
|
||||
,UCHAR* dynamic_RAM
|
||||
)
|
||||
{
|
||||
BITCNTR_STATE *hBC = GetRam_aacEnc_BitCntrState();
|
||||
|
||||
if (hBC)
|
||||
{
|
||||
*phBC = hBC;
|
||||
hBC->bitLookUp = GetRam_aacEnc_BitLookUp(0,dynamic_RAM);
|
||||
hBC->mergeGainLookUp = GetRam_aacEnc_MergeGainLookUp(0,dynamic_RAM);
|
||||
if (hBC->bitLookUp == 0 ||
|
||||
hBC->mergeGainLookUp == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return (hBC == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void FDKaacEnc_BCClose(BITCNTR_STATE **phBC)
|
||||
{
|
||||
if (*phBC!=NULL) {
|
||||
|
||||
FreeRam_aacEnc_BitCntrState(phBC);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
104
libAACenc/src/dyn_bits.h
Normal file
104
libAACenc/src/dyn_bits.h
Normal file
@ -0,0 +1,104 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M.Werner
|
||||
contents/description: Noiseless coder module
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef __DYN_BITS_H
|
||||
#define __DYN_BITS_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "psy_const.h"
|
||||
#include "aacenc_tns.h"
|
||||
|
||||
#define MAX_SECTIONS MAX_GROUPED_SFB
|
||||
#define SECT_ESC_VAL_LONG 31
|
||||
#define SECT_ESC_VAL_SHORT 7
|
||||
#define CODE_BOOK_BITS 4
|
||||
#define SECT_BITS_LONG 5
|
||||
#define SECT_BITS_SHORT 3
|
||||
#define PNS_PCM_BITS 9
|
||||
|
||||
typedef struct
|
||||
{
|
||||
INT codeBook;
|
||||
INT sfbStart;
|
||||
INT sfbCnt;
|
||||
INT sectionBits; /* huff + si ! */
|
||||
} SECTION_INFO;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
INT blockType;
|
||||
INT noOfGroups;
|
||||
INT sfbCnt;
|
||||
INT maxSfbPerGroup;
|
||||
INT sfbPerGroup;
|
||||
INT noOfSections;
|
||||
SECTION_INFO huffsection[MAX_SECTIONS];
|
||||
INT sideInfoBits; /* sectioning bits */
|
||||
INT huffmanBits; /* huffman coded bits */
|
||||
INT scalefacBits; /* scalefac coded bits */
|
||||
INT noiseNrgBits; /* noiseEnergy coded bits */
|
||||
INT firstScf; /* first scf to be coded */
|
||||
} SECTION_DATA;
|
||||
|
||||
|
||||
struct BITCNTR_STATE
|
||||
{
|
||||
INT *bitLookUp;
|
||||
INT *mergeGainLookUp;
|
||||
};
|
||||
|
||||
|
||||
INT FDKaacEnc_BCNew(BITCNTR_STATE **phBC
|
||||
,UCHAR* dynamic_RAM
|
||||
);
|
||||
|
||||
void FDKaacEnc_BCClose(BITCNTR_STATE **phBC);
|
||||
|
||||
#if defined(PNS_PRECOUNT_ENABLE)
|
||||
INT noisePreCount(const INT *noiseNrg, INT maxSfb);
|
||||
#endif
|
||||
|
||||
INT FDKaacEnc_dynBitCount(
|
||||
BITCNTR_STATE* const hBC,
|
||||
const SHORT* const quantSpectrum,
|
||||
const UINT* const maxValueInSfb,
|
||||
const INT* const scalefac,
|
||||
const INT blockType,
|
||||
const INT sfbCnt,
|
||||
const INT maxSfbPerGroup,
|
||||
const INT sfbPerGroup,
|
||||
const INT* const sfbOffset,
|
||||
SECTION_DATA* const RESTRICT sectionData,
|
||||
const INT* const noiseNrg,
|
||||
const INT* const isBook,
|
||||
const INT* const isScale,
|
||||
const UINT syntaxFlags
|
||||
);
|
||||
|
||||
#endif
|
206
libAACenc/src/grp_data.cpp
Normal file
206
libAACenc/src/grp_data.cpp
Normal file
@ -0,0 +1,206 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M.Werner
|
||||
contents/description: Short block grouping
|
||||
|
||||
******************************************************************************/
|
||||
#include "psy_const.h"
|
||||
#include "interface.h"
|
||||
|
||||
/*
|
||||
* this routine does not work in-place
|
||||
*/
|
||||
|
||||
void
|
||||
FDKaacEnc_groupShortData(FIXP_DBL *mdctSpectrum, /* in-out */
|
||||
SFB_THRESHOLD *sfbThreshold, /* in-out */
|
||||
SFB_ENERGY *sfbEnergy, /* in-out */
|
||||
SFB_ENERGY *sfbEnergyMS, /* in-out */
|
||||
SFB_ENERGY *sfbSpreadEnergy,
|
||||
const INT sfbCnt,
|
||||
const INT sfbActive,
|
||||
const INT *sfbOffset,
|
||||
const FIXP_DBL *sfbMinSnrLdData,
|
||||
INT *groupedSfbOffset, /* out */
|
||||
INT *maxSfbPerGroup, /* out */
|
||||
FIXP_DBL *groupedSfbMinSnrLdData,
|
||||
const INT noOfGroups,
|
||||
const INT *groupLen,
|
||||
const INT granuleLength)
|
||||
{
|
||||
INT i,j;
|
||||
INT line; /* counts through lines */
|
||||
INT sfb; /* counts through scalefactor bands */
|
||||
INT grp; /* counts through groups */
|
||||
INT wnd; /* counts through windows in a group */
|
||||
INT offset; /* needed in sfbOffset grouping */
|
||||
INT highestSfb;
|
||||
|
||||
INT granuleLength_short = granuleLength/TRANS_FAC;
|
||||
|
||||
/* for short blocks: regroup spectrum and */
|
||||
/* group energies and thresholds according to grouping */
|
||||
C_ALLOC_SCRATCH_START(tmpSpectrum, FIXP_DBL, (1024));
|
||||
|
||||
/* calculate maxSfbPerGroup */
|
||||
highestSfb = 0;
|
||||
for (wnd = 0; wnd < TRANS_FAC; wnd++)
|
||||
{
|
||||
for (sfb = sfbActive-1; sfb >= highestSfb; sfb--)
|
||||
{
|
||||
for (line = sfbOffset[sfb+1]-1; line >= sfbOffset[sfb]; line--)
|
||||
{
|
||||
if ( mdctSpectrum[wnd*granuleLength_short+line] != FL2FXCONST_SPC(0.0) ) break; /* this band is not completely zero */
|
||||
}
|
||||
if (line >= sfbOffset[sfb]) break; /* this band was not completely zero */
|
||||
}
|
||||
highestSfb = fixMax(highestSfb, sfb);
|
||||
}
|
||||
highestSfb = highestSfb > 0 ? highestSfb : 0;
|
||||
*maxSfbPerGroup = highestSfb+1;
|
||||
|
||||
/* calculate groupedSfbOffset */
|
||||
i = 0;
|
||||
offset = 0;
|
||||
for (grp = 0; grp < noOfGroups; grp++)
|
||||
{
|
||||
for (sfb = 0; sfb < sfbActive+1; sfb++)
|
||||
{
|
||||
groupedSfbOffset[i++] = offset + sfbOffset[sfb] * groupLen[grp];
|
||||
}
|
||||
i += sfbCnt-sfb;
|
||||
offset += groupLen[grp] * granuleLength_short;
|
||||
}
|
||||
groupedSfbOffset[i++] = granuleLength;
|
||||
|
||||
/* calculate groupedSfbMinSnr */
|
||||
i = 0;
|
||||
for (grp = 0; grp < noOfGroups; grp++)
|
||||
{
|
||||
for (sfb = 0; sfb < sfbActive; sfb++)
|
||||
{
|
||||
groupedSfbMinSnrLdData[i++] = sfbMinSnrLdData[sfb];
|
||||
}
|
||||
i += sfbCnt-sfb;
|
||||
}
|
||||
|
||||
/* sum up sfbThresholds */
|
||||
wnd = 0;
|
||||
i = 0;
|
||||
for (grp = 0; grp < noOfGroups; grp++)
|
||||
{
|
||||
for (sfb = 0; sfb < sfbActive; sfb++)
|
||||
{
|
||||
FIXP_DBL thresh = sfbThreshold->Short[wnd][sfb];
|
||||
for (j=1; j<groupLen[grp]; j++)
|
||||
{
|
||||
thresh += sfbThreshold->Short[wnd+j][sfb];
|
||||
}
|
||||
sfbThreshold->Long[i++] = thresh;
|
||||
}
|
||||
i += sfbCnt-sfb;
|
||||
wnd += groupLen[grp];
|
||||
}
|
||||
|
||||
/* sum up sfbEnergies left/right */
|
||||
wnd = 0;
|
||||
i = 0;
|
||||
for (grp = 0; grp < noOfGroups; grp++)
|
||||
{
|
||||
for (sfb = 0; sfb < sfbActive; sfb++)
|
||||
{
|
||||
FIXP_DBL energy = sfbEnergy->Short[wnd][sfb];
|
||||
for (j=1; j<groupLen[grp]; j++)
|
||||
{
|
||||
energy += sfbEnergy->Short[wnd+j][sfb];
|
||||
}
|
||||
sfbEnergy->Long[i++] = energy;
|
||||
}
|
||||
i += sfbCnt-sfb;
|
||||
wnd += groupLen[grp];
|
||||
}
|
||||
|
||||
/* sum up sfbEnergies mid/side */
|
||||
wnd = 0;
|
||||
i = 0;
|
||||
for (grp = 0; grp < noOfGroups; grp++)
|
||||
{
|
||||
for (sfb = 0; sfb < sfbActive; sfb++)
|
||||
{
|
||||
FIXP_DBL energy = sfbEnergyMS->Short[wnd][sfb];
|
||||
for (j=1; j<groupLen[grp]; j++)
|
||||
{
|
||||
energy += sfbEnergyMS->Short[wnd+j][sfb];
|
||||
}
|
||||
sfbEnergyMS->Long[i++] = energy;
|
||||
}
|
||||
i += sfbCnt-sfb;
|
||||
wnd += groupLen[grp];
|
||||
}
|
||||
|
||||
/* sum up sfbSpreadEnergies */
|
||||
wnd = 0;
|
||||
i = 0;
|
||||
for (grp = 0; grp < noOfGroups; grp++)
|
||||
{
|
||||
for (sfb = 0; sfb < sfbActive; sfb++)
|
||||
{
|
||||
FIXP_DBL energy = sfbSpreadEnergy->Short[wnd][sfb];
|
||||
for (j=1; j<groupLen[grp]; j++)
|
||||
{
|
||||
energy += sfbSpreadEnergy->Short[wnd+j][sfb];
|
||||
}
|
||||
sfbSpreadEnergy->Long[i++] = energy;
|
||||
}
|
||||
i += sfbCnt-sfb;
|
||||
wnd += groupLen[grp];
|
||||
}
|
||||
|
||||
/* re-group spectrum */
|
||||
wnd = 0;
|
||||
i = 0;
|
||||
for (grp = 0; grp < noOfGroups; grp++)
|
||||
{
|
||||
for (sfb = 0; sfb < sfbActive; sfb++)
|
||||
{
|
||||
int width = sfbOffset[sfb+1]-sfbOffset[sfb];
|
||||
FIXP_DBL *pMdctSpectrum = &mdctSpectrum[sfbOffset[sfb]] + wnd*granuleLength_short;
|
||||
for (j = 0; j < groupLen[grp]; j++)
|
||||
{
|
||||
FIXP_DBL *pTmp = pMdctSpectrum;
|
||||
for (line = width; line > 0; line--)
|
||||
{
|
||||
tmpSpectrum[i++] = *pTmp++;
|
||||
}
|
||||
pMdctSpectrum += granuleLength_short;
|
||||
}
|
||||
}
|
||||
i += (groupLen[grp]*(sfbOffset[sfbCnt]-sfbOffset[sfb]));
|
||||
wnd += groupLen[grp];
|
||||
}
|
||||
|
||||
FDKmemcpy(mdctSpectrum, tmpSpectrum, granuleLength*sizeof(FIXP_DBL));
|
||||
|
||||
C_ALLOC_SCRATCH_END(tmpSpectrum, FIXP_DBL, (1024))
|
||||
}
|
53
libAACenc/src/grp_data.h
Normal file
53
libAACenc/src/grp_data.h
Normal file
@ -0,0 +1,53 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M.Werner
|
||||
contents/description: Short block grouping
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef __GRP_DATA_H__
|
||||
#define __GRP_DATA_H__
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "psy_data.h"
|
||||
|
||||
|
||||
void
|
||||
FDKaacEnc_groupShortData(FIXP_DBL *mdctSpectrum, /* in-out */
|
||||
SFB_THRESHOLD *sfbThreshold, /* in-out */
|
||||
SFB_ENERGY *sfbEnergy, /* in-out */
|
||||
SFB_ENERGY *sfbEnergyMS, /* in-out */
|
||||
SFB_ENERGY *sfbSpreadEnergy,
|
||||
const INT sfbCnt,
|
||||
const INT sfbActive,
|
||||
const INT *sfbOffset,
|
||||
const FIXP_DBL *sfbMinSnrLdData,
|
||||
INT *groupedSfbOffset, /* out */
|
||||
INT *maxSfbPerGroup,
|
||||
FIXP_DBL *groupedSfbMinSnrLdData,
|
||||
const INT noOfGroups,
|
||||
const INT *groupLen,
|
||||
const INT granuleLength);
|
||||
|
||||
#endif /* _INTERFACE_H */
|
691
libAACenc/src/intensity.cpp
Normal file
691
libAACenc/src/intensity.cpp
Normal file
@ -0,0 +1,691 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2010)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
|
||||
Initial author: A. Horndasch (code originally from lwr) / Josef Hoepfl (FDK)
|
||||
contents/description: intensity stereo processing
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "intensity.h"
|
||||
#include "interface.h"
|
||||
#include "psy_configuration.h"
|
||||
#include "psy_const.h"
|
||||
#include "qc_main.h"
|
||||
#include "bit_cnt.h"
|
||||
|
||||
/* only set an IS seed it left/right channel correlation is above IS_CORR_THRESH */
|
||||
#define IS_CORR_THRESH FL2FXCONST_DBL(0.95f)
|
||||
|
||||
/* when expanding the IS region to more SFBs only accept an error that is
|
||||
* not more than IS_TOTAL_ERROR_THRESH overall and
|
||||
* not more than IS_LOCAL_ERROR_THRESH for the current SFB */
|
||||
#define IS_TOTAL_ERROR_THRESH FL2FXCONST_DBL(0.04f)
|
||||
#define IS_LOCAL_ERROR_THRESH FL2FXCONST_DBL(0.01f)
|
||||
|
||||
/* the maximum allowed change of the intensity direction (unit: IS scale) - scaled with factor 0.25 - */
|
||||
#define IS_DIRECTION_DEVIATION_THRESH_SF 2
|
||||
#define IS_DIRECTION_DEVIATION_THRESH FL2FXCONST_DBL(2.0f/(1<<IS_DIRECTION_DEVIATION_THRESH_SF))
|
||||
|
||||
/* IS regions need to have a minimal percentage of the overall loudness, e.g. 0.06 == 6% */
|
||||
#define IS_REGION_MIN_LOUDNESS FL2FXCONST_DBL(0.1f)
|
||||
|
||||
/* only perform IS if IS_MIN_SFBS neighboring SFBs can be processed */
|
||||
#define IS_MIN_SFBS 6
|
||||
|
||||
/* only do IS if
|
||||
* if IS_LEFT_RIGHT_RATIO_THRESH < sfbEnergyLeft[sfb]/sfbEnergyRight[sfb] < 1 / IS_LEFT_RIGHT_RATIO_THRESH
|
||||
* -> no IS if the panning angle is not far from the middle, MS will do */
|
||||
/* this is equivalent to a scale of +/-1.02914634566 */
|
||||
#define IS_LEFT_RIGHT_RATIO_THRESH FL2FXCONST_DBL(0.7f)
|
||||
|
||||
/* scalefactor of realScale */
|
||||
#define REAL_SCALE_SF 1
|
||||
|
||||
/* scalefactor overallLoudness */
|
||||
#define OVERALL_LOUDNESS_SF 6
|
||||
|
||||
/* scalefactor for sum over max samples per goup */
|
||||
#define MAX_SFB_PER_GROUP_SF 6
|
||||
|
||||
/* scalefactor for sum of mdct spectrum */
|
||||
#define MDCT_SPEC_SF 6
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
FIXP_DBL corr_thresh; /*!< Only set an IS seed it left/right channel correlation is above corr_thresh */
|
||||
|
||||
FIXP_DBL total_error_thresh; /*!< When expanding the IS region to more SFBs only accept an error that is
|
||||
not more than 'total_error_thresh' overall. */
|
||||
|
||||
FIXP_DBL local_error_thresh; /*!< When expanding the IS region to more SFBs only accept an error that is
|
||||
not more than 'local_error_thresh' for the current SFB. */
|
||||
|
||||
FIXP_DBL direction_deviation_thresh; /*!< The maximum allowed change of the intensity direction (unit: IS scale) */
|
||||
|
||||
FIXP_DBL is_region_min_loudness; /*!< IS regions need to have a minimal percentage of the overall loudness, e.g. 0.06 == 6% */
|
||||
|
||||
INT min_is_sfbs; /*!< Only perform IS if 'min_is_sfbs' neighboring SFBs can be processed */
|
||||
|
||||
FIXP_DBL left_right_ratio_threshold; /*!< No IS if the panning angle is not far from the middle, MS will do */
|
||||
|
||||
} INTENSITY_PARAMETERS;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
functionname: calcSfbMaxScale
|
||||
|
||||
description: Calc max value in scalefactor band
|
||||
|
||||
input: *mdctSpectrum
|
||||
l1
|
||||
l2
|
||||
|
||||
output: none
|
||||
|
||||
returns: scalefactor
|
||||
|
||||
*****************************************************************************/
|
||||
static INT
|
||||
calcSfbMaxScale(const FIXP_DBL *mdctSpectrum,
|
||||
const INT l1,
|
||||
const INT l2)
|
||||
{
|
||||
INT i;
|
||||
INT sfbMaxScale;
|
||||
FIXP_DBL maxSpc;
|
||||
|
||||
maxSpc = FL2FXCONST_DBL(0.0);
|
||||
for (i=l1; i<l2; i++) {
|
||||
FIXP_DBL tmp = fixp_abs((FIXP_DBL)mdctSpectrum[i]);
|
||||
maxSpc = fixMax(maxSpc, tmp);
|
||||
}
|
||||
sfbMaxScale = (maxSpc==FL2FXCONST_DBL(0.0)) ? (DFRACT_BITS-2) : CntLeadingZeros(maxSpc)-1;
|
||||
|
||||
return sfbMaxScale;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
functionname: FDKaacEnc_initIsParams
|
||||
|
||||
description: Initialization of intensity parameters
|
||||
|
||||
input: isParams
|
||||
|
||||
output: isParams
|
||||
|
||||
returns: none
|
||||
|
||||
*****************************************************************************/
|
||||
static void
|
||||
FDKaacEnc_initIsParams(INTENSITY_PARAMETERS *isParams)
|
||||
{
|
||||
isParams->corr_thresh = IS_CORR_THRESH;
|
||||
isParams->total_error_thresh = IS_TOTAL_ERROR_THRESH;
|
||||
isParams->local_error_thresh = IS_LOCAL_ERROR_THRESH;
|
||||
isParams->direction_deviation_thresh = IS_DIRECTION_DEVIATION_THRESH;
|
||||
isParams->is_region_min_loudness = IS_REGION_MIN_LOUDNESS;
|
||||
isParams->min_is_sfbs = IS_MIN_SFBS;
|
||||
isParams->left_right_ratio_threshold = IS_LEFT_RIGHT_RATIO_THRESH;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
functionname: FDKaacEnc_prepareIntensityDecision
|
||||
|
||||
description: Prepares intensity decision
|
||||
|
||||
input: sfbEnergyLeft
|
||||
sfbEnergyRight
|
||||
sfbEnergyLdDataLeft
|
||||
sfbEnergyLdDataRight
|
||||
mdctSpectrumLeft
|
||||
sfbEnergyLdDataRight
|
||||
isParams
|
||||
|
||||
output: hrrErr scale: none
|
||||
isMask scale: none
|
||||
realScale scale: LD_DATA_SHIFT + REAL_SCALE_SF
|
||||
normSfbLoudness scale: none
|
||||
|
||||
returns: none
|
||||
|
||||
*****************************************************************************/
|
||||
static void
|
||||
FDKaacEnc_prepareIntensityDecision(const FIXP_DBL *sfbEnergyLeft,
|
||||
const FIXP_DBL *sfbEnergyRight,
|
||||
const FIXP_DBL *sfbEnergyLdDataLeft,
|
||||
const FIXP_DBL *sfbEnergyLdDataRight,
|
||||
const FIXP_DBL *mdctSpectrumLeft,
|
||||
const FIXP_DBL *mdctSpectrumRight,
|
||||
const INTENSITY_PARAMETERS *isParams,
|
||||
FIXP_DBL *hrrErr,
|
||||
INT *isMask,
|
||||
FIXP_DBL *realScale,
|
||||
FIXP_DBL *normSfbLoudness,
|
||||
const INT sfbCnt,
|
||||
const INT sfbPerGroup,
|
||||
const INT maxSfbPerGroup,
|
||||
const INT *sfbOffset)
|
||||
{
|
||||
INT j,sfb,sfboffs;
|
||||
INT grpCounter;
|
||||
|
||||
/* temporary variables to compute loudness */
|
||||
FIXP_DBL overallLoudness[MAX_NO_OF_GROUPS];
|
||||
|
||||
/* temporary variables to compute correlation */
|
||||
FIXP_DBL channelCorr[MAX_GROUPED_SFB];
|
||||
FIXP_DBL ml, mr;
|
||||
FIXP_DBL prod_lr;
|
||||
FIXP_DBL square_l, square_r;
|
||||
FIXP_DBL tmp_l, tmp_r;
|
||||
FIXP_DBL inv_n;
|
||||
|
||||
FDKmemclear(channelCorr, MAX_GROUPED_SFB*sizeof(FIXP_DBL));
|
||||
FDKmemclear(normSfbLoudness, MAX_GROUPED_SFB*sizeof(FIXP_DBL));
|
||||
FDKmemclear(overallLoudness, MAX_NO_OF_GROUPS*sizeof(FIXP_DBL));
|
||||
FDKmemclear(realScale, MAX_GROUPED_SFB*sizeof(FIXP_DBL));
|
||||
|
||||
for (grpCounter = 0, sfboffs = 0; sfboffs < sfbCnt; sfboffs += sfbPerGroup, grpCounter++) {
|
||||
overallLoudness[grpCounter] = FL2FXCONST_DBL(0.0f);
|
||||
for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
|
||||
INT sL,sR,s;
|
||||
FIXP_DBL isValue = sfbEnergyLdDataLeft[sfb+sfboffs]-sfbEnergyLdDataRight[sfb+sfboffs];
|
||||
|
||||
/* delimitate intensity scale value to representable range */
|
||||
realScale[sfb + sfboffs] = fixMin(FL2FXCONST_DBL(60.f/(1<<(REAL_SCALE_SF+LD_DATA_SHIFT))), fixMax(FL2FXCONST_DBL(-60.f/(1<<(REAL_SCALE_SF+LD_DATA_SHIFT))), isValue));
|
||||
|
||||
sL = fixMax(0,(CntLeadingZeros(sfbEnergyLeft[sfb + sfboffs])-1));
|
||||
sR = fixMax(0,(CntLeadingZeros(sfbEnergyRight[sfb + sfboffs])-1));
|
||||
s = (fixMin(sL,sR)>>2)<<2;
|
||||
normSfbLoudness[sfb + sfboffs] = sqrtFixp(sqrtFixp(((sfbEnergyLeft[sfb + sfboffs]<<s) >> 1) + ((sfbEnergyRight[sfb + sfboffs]<<s) >> 1))) >> (s>>2);
|
||||
|
||||
overallLoudness[grpCounter] += normSfbLoudness[sfb + sfboffs] >> OVERALL_LOUDNESS_SF;
|
||||
/* don't do intensity if
|
||||
* - panning angle is too close to the middle or
|
||||
* - one channel is non-existent or
|
||||
* - if it is dual mono */
|
||||
if( (sfbEnergyLeft[sfb + sfboffs] >= fMult(isParams->left_right_ratio_threshold,sfbEnergyRight[sfb + sfboffs]))
|
||||
&& (fMult(isParams->left_right_ratio_threshold,sfbEnergyLeft[sfb + sfboffs]) <= sfbEnergyRight[sfb + sfboffs]) ) {
|
||||
|
||||
/* this will prevent post processing from considering this SFB for merging */
|
||||
hrrErr[sfb + sfboffs] = FL2FXCONST_DBL(1.0/8.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (grpCounter = 0, sfboffs = 0; sfboffs < sfbCnt; sfboffs += sfbPerGroup, grpCounter++) {
|
||||
INT invOverallLoudnessSF;
|
||||
FIXP_DBL invOverallLoudness;
|
||||
|
||||
if (overallLoudness[grpCounter] == FL2FXCONST_DBL(0.0)) {
|
||||
invOverallLoudness = FL2FXCONST_DBL(0.0);
|
||||
invOverallLoudnessSF = 0;
|
||||
}
|
||||
else {
|
||||
invOverallLoudness = fDivNorm((FIXP_DBL)MAXVAL_DBL, overallLoudness[grpCounter],&invOverallLoudnessSF);
|
||||
invOverallLoudnessSF = invOverallLoudnessSF - OVERALL_LOUDNESS_SF + 1; /* +1: compensate fMultDiv2() in subsequent loop */
|
||||
}
|
||||
invOverallLoudnessSF = fixMin(fixMax(invOverallLoudnessSF,-(DFRACT_BITS-1)),DFRACT_BITS-1);
|
||||
|
||||
for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
|
||||
FIXP_DBL tmp;
|
||||
|
||||
tmp = fMultDiv2((normSfbLoudness[sfb + sfboffs]>>OVERALL_LOUDNESS_SF)<<OVERALL_LOUDNESS_SF,invOverallLoudness);
|
||||
|
||||
normSfbLoudness[sfb + sfboffs] = scaleValue(tmp, invOverallLoudnessSF);
|
||||
|
||||
channelCorr[sfb + sfboffs] = FL2FXCONST_DBL(0.0f);
|
||||
|
||||
FDK_ASSERT(50 >= 49);
|
||||
/* max width of scalefactorband is 96; width's are always even */
|
||||
/* inv_n is scaled with factor 2 to compensate fMultDiv2() in subsequent loops */
|
||||
inv_n = GetInvInt((sfbOffset[sfb + sfboffs + 1] - sfbOffset[sfb + sfboffs])>>1);
|
||||
|
||||
if (inv_n > FL2FXCONST_DBL(0.0f)) {
|
||||
INT s,sL,sR;
|
||||
|
||||
/* correlation := Pearson's product-moment coefficient */
|
||||
/* compute correlation between channels and check if it is over threshold */
|
||||
ml = FL2FXCONST_DBL(0.0f);
|
||||
mr = FL2FXCONST_DBL(0.0f);
|
||||
prod_lr = FL2FXCONST_DBL(0.0f);
|
||||
square_l = FL2FXCONST_DBL(0.0f);
|
||||
square_r = FL2FXCONST_DBL(0.0f);
|
||||
|
||||
sL = calcSfbMaxScale(mdctSpectrumLeft,sfbOffset[sfb+sfboffs],sfbOffset[sfb+sfboffs+1]);
|
||||
sR = calcSfbMaxScale(mdctSpectrumRight,sfbOffset[sfb+sfboffs],sfbOffset[sfb+sfboffs+1]);
|
||||
s = fixMin(sL,sR);
|
||||
|
||||
for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; j++) {
|
||||
ml += fMultDiv2((mdctSpectrumLeft[j] << s),inv_n); // scaled with mdctScale - s + inv_n
|
||||
mr += fMultDiv2((mdctSpectrumRight[j] << s),inv_n); // scaled with mdctScale - s + inv_n
|
||||
}
|
||||
ml = fMultDiv2(ml,inv_n); // scaled with mdctScale - s + inv_n
|
||||
mr = fMultDiv2(mr,inv_n); // scaled with mdctScale - s + inv_n
|
||||
|
||||
for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; j++) {
|
||||
tmp_l = fMultDiv2((mdctSpectrumLeft[j] << s),inv_n) - ml; // scaled with mdctScale - s + inv_n
|
||||
tmp_r = fMultDiv2((mdctSpectrumRight[j] << s),inv_n) - mr; // scaled with mdctScale - s + inv_n
|
||||
|
||||
prod_lr += fMultDiv2(tmp_l,tmp_r); // scaled with 2*(mdctScale - s + inv_n) + 1
|
||||
square_l += fPow2Div2(tmp_l); // scaled with 2*(mdctScale - s + inv_n) + 1
|
||||
square_r += fPow2Div2(tmp_r); // scaled with 2*(mdctScale - s + inv_n) + 1
|
||||
}
|
||||
prod_lr = prod_lr << 1; // scaled with 2*(mdctScale - s + inv_n)
|
||||
square_l = square_l << 1; // scaled with 2*(mdctScale - s + inv_n)
|
||||
square_r = square_r << 1; // scaled with 2*(mdctScale - s + inv_n)
|
||||
|
||||
if (square_l > FL2FXCONST_DBL(0.0f) && square_r > FL2FXCONST_DBL(0.0f)) {
|
||||
INT channelCorrSF = 0;
|
||||
|
||||
/* local scaling of square_l and square_r is compensated after sqrt calculation */
|
||||
sL = fixMax(0,(CntLeadingZeros(square_l)-1));
|
||||
sR = fixMax(0,(CntLeadingZeros(square_r)-1));
|
||||
s = ((sL + sR)>>1)<<1;
|
||||
sL = fixMin(sL,s);
|
||||
sR = s-sL;
|
||||
tmp = fMult(square_l<<sL,square_r<<sR);
|
||||
tmp = sqrtFixp(tmp);
|
||||
|
||||
FDK_ASSERT(tmp > FL2FXCONST_DBL(0.0f));
|
||||
|
||||
/* numerator and denominator have the same scaling */
|
||||
if (prod_lr < FL2FXCONST_DBL(0.0f) ) {
|
||||
channelCorr[sfb + sfboffs] = -(fDivNorm(-prod_lr,tmp,&channelCorrSF));
|
||||
|
||||
}
|
||||
else {
|
||||
channelCorr[sfb + sfboffs] = (fDivNorm( prod_lr,tmp,&channelCorrSF));
|
||||
}
|
||||
channelCorrSF = fixMin(fixMax(( channelCorrSF + ((sL+sR)>>1)),-(DFRACT_BITS-1)),DFRACT_BITS-1);
|
||||
|
||||
if (channelCorrSF < 0) {
|
||||
channelCorr[sfb + sfboffs] = channelCorr[sfb + sfboffs] >> (-channelCorrSF);
|
||||
}
|
||||
else {
|
||||
/* avoid overflows due to limited computational accuracy */
|
||||
if ( fAbs(channelCorr[sfb + sfboffs]) > (((FIXP_DBL)MAXVAL_DBL)>>channelCorrSF) ) {
|
||||
if (channelCorr[sfb + sfboffs] < FL2FXCONST_DBL(0.0f))
|
||||
channelCorr[sfb + sfboffs] = -(FIXP_DBL) MAXVAL_DBL;
|
||||
else
|
||||
channelCorr[sfb + sfboffs] = (FIXP_DBL) MAXVAL_DBL;
|
||||
}
|
||||
else {
|
||||
channelCorr[sfb + sfboffs] = channelCorr[sfb + sfboffs] << channelCorrSF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* for post processing: hrrErr is the error in terms of (too little) correlation
|
||||
* weighted with the loudness of the SFB; SFBs with small hrrErr can be merged */
|
||||
if (hrrErr[sfb + sfboffs] == FL2FXCONST_DBL(1.0/8.0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hrrErr[sfb + sfboffs] = fMultDiv2((FL2FXCONST_DBL(0.25f)-(channelCorr[sfb + sfboffs]>>2)),normSfbLoudness[sfb + sfboffs]);
|
||||
|
||||
/* set IS mask/vector to 1, if correlation is high enough */
|
||||
if (fAbs(channelCorr[sfb + sfboffs]) >= isParams->corr_thresh) {
|
||||
isMask[sfb + sfboffs] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
functionname: FDKaacEnc_finalizeIntensityDecision
|
||||
|
||||
description: Finalizes intensity decision
|
||||
|
||||
input: isParams scale: none
|
||||
hrrErr scale: none
|
||||
realIsScale scale: LD_DATA_SHIFT + REAL_SCALE_SF
|
||||
normSfbLoudness scale: none
|
||||
|
||||
output: isMask scale: none
|
||||
|
||||
returns: none
|
||||
|
||||
*****************************************************************************/
|
||||
static void
|
||||
FDKaacEnc_finalizeIntensityDecision(const FIXP_DBL *hrrErr,
|
||||
INT *isMask,
|
||||
const FIXP_DBL *realIsScale,
|
||||
const FIXP_DBL *normSfbLoudness,
|
||||
const INTENSITY_PARAMETERS *isParams,
|
||||
const INT sfbCnt,
|
||||
const INT sfbPerGroup,
|
||||
const INT maxSfbPerGroup)
|
||||
{
|
||||
INT sfb,sfboffs, j;
|
||||
INT startIsSfb = 0;
|
||||
INT inIsBlock;
|
||||
INT currentIsSfbCount;
|
||||
FIXP_DBL overallHrrError;
|
||||
FIXP_DBL isScaleLast = FL2FXCONST_DBL(0.0f);
|
||||
FIXP_DBL isRegionLoudness;
|
||||
|
||||
for (sfboffs = 0; sfboffs < sfbCnt; sfboffs += sfbPerGroup) {
|
||||
inIsBlock = 0;
|
||||
currentIsSfbCount = 0;
|
||||
overallHrrError = FL2FXCONST_DBL(0.0f);
|
||||
isRegionLoudness = FL2FXCONST_DBL(0.0f);
|
||||
for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
|
||||
if (isMask[sfboffs + sfb] == 1) {
|
||||
if (currentIsSfbCount == 0) {
|
||||
startIsSfb = sfboffs + sfb;
|
||||
isScaleLast = realIsScale[sfboffs + sfb];
|
||||
}
|
||||
inIsBlock = 1;
|
||||
currentIsSfbCount++;
|
||||
overallHrrError += hrrErr[sfboffs + sfb] >> (MAX_SFB_PER_GROUP_SF-3);
|
||||
isRegionLoudness += normSfbLoudness[sfboffs + sfb] >> MAX_SFB_PER_GROUP_SF;
|
||||
}
|
||||
else {
|
||||
/* based on correlation, IS should not be used
|
||||
* -> use it anyway, if overall error is below threshold
|
||||
* and if local error does not exceed threshold
|
||||
* otherwise: check if there are enough IS SFBs
|
||||
*/
|
||||
if (inIsBlock) {
|
||||
overallHrrError += hrrErr[sfboffs + sfb] >> (MAX_SFB_PER_GROUP_SF-3);
|
||||
isRegionLoudness += normSfbLoudness[sfboffs + sfb] >> MAX_SFB_PER_GROUP_SF;
|
||||
|
||||
if ( (hrrErr[sfboffs + sfb] < (isParams->local_error_thresh>>3)) && (overallHrrError < (isParams->total_error_thresh>>MAX_SFB_PER_GROUP_SF)) ) {
|
||||
currentIsSfbCount++;
|
||||
/* overwrite correlation based decision */
|
||||
isMask[sfboffs + sfb] = 1;
|
||||
} else {
|
||||
inIsBlock = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* check for large direction deviation */
|
||||
if (inIsBlock) {
|
||||
if( fAbs(isScaleLast-realIsScale[sfboffs + sfb]) < (isParams->direction_deviation_thresh>>(REAL_SCALE_SF+LD_DATA_SHIFT-IS_DIRECTION_DEVIATION_THRESH_SF)) ) {
|
||||
isScaleLast = realIsScale[sfboffs + sfb];
|
||||
}
|
||||
else{
|
||||
isMask[sfboffs + sfb] = 0;
|
||||
inIsBlock = 0;
|
||||
currentIsSfbCount--;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentIsSfbCount > 0 && (!inIsBlock || sfb == maxSfbPerGroup - 1)) {
|
||||
/* not enough SFBs -> do not use IS */
|
||||
if (currentIsSfbCount < isParams->min_is_sfbs || (isRegionLoudness < isParams->is_region_min_loudness>>MAX_SFB_PER_GROUP_SF)) {
|
||||
for(j = startIsSfb; j <= sfboffs + sfb; j++) {
|
||||
isMask[j] = 0;
|
||||
}
|
||||
}
|
||||
currentIsSfbCount = 0;
|
||||
overallHrrError = FL2FXCONST_DBL(0.0f);
|
||||
isRegionLoudness = FL2FXCONST_DBL(0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
functionname: FDKaacEnc_IntensityStereoProcessing
|
||||
|
||||
description: Intensity stereo processing tool
|
||||
|
||||
input: sfbEnergyLeft
|
||||
sfbEnergyRight
|
||||
mdctSpectrumLeft
|
||||
mdctSpectrumRight
|
||||
sfbThresholdLeft
|
||||
sfbThresholdRight
|
||||
sfbSpreadEnLeft
|
||||
sfbSpreadEnRight
|
||||
sfbEnergyLdDataLeft
|
||||
sfbEnergyLdDataRight
|
||||
|
||||
output: isBook
|
||||
isScale
|
||||
pnsData->pnsFlag
|
||||
msDigest zeroed from start to sfbCnt
|
||||
msMask zeroed from start to sfbCnt
|
||||
mdctSpectrumRight zeroed where isBook!=0
|
||||
sfbEnergyRight zeroed where isBook!=0
|
||||
sfbSpreadEnRight zeroed where isBook!=0
|
||||
sfbThresholdRight zeroed where isBook!=0
|
||||
sfbEnergyLdDataRight FL2FXCONST_DBL(-1.0) where isBook!=0
|
||||
sfbThresholdLdDataRight FL2FXCONST_DBL(-0.515625f) where isBook!=0
|
||||
|
||||
returns: none
|
||||
|
||||
*****************************************************************************/
|
||||
void FDKaacEnc_IntensityStereoProcessing(
|
||||
FIXP_DBL *sfbEnergyLeft,
|
||||
FIXP_DBL *sfbEnergyRight,
|
||||
FIXP_DBL *mdctSpectrumLeft,
|
||||
FIXP_DBL *mdctSpectrumRight,
|
||||
FIXP_DBL *sfbThresholdLeft,
|
||||
FIXP_DBL *sfbThresholdRight,
|
||||
FIXP_DBL *sfbThresholdLdDataRight,
|
||||
FIXP_DBL *sfbSpreadEnLeft,
|
||||
FIXP_DBL *sfbSpreadEnRight,
|
||||
FIXP_DBL *sfbEnergyLdDataLeft,
|
||||
FIXP_DBL *sfbEnergyLdDataRight,
|
||||
INT *msDigest,
|
||||
INT *msMask,
|
||||
const INT sfbCnt,
|
||||
const INT sfbPerGroup,
|
||||
const INT maxSfbPerGroup,
|
||||
const INT *sfbOffset,
|
||||
const INT allowIS,
|
||||
INT *isBook,
|
||||
INT *isScale,
|
||||
PNS_DATA *RESTRICT pnsData[2]
|
||||
)
|
||||
{
|
||||
INT sfb,sfboffs, j;
|
||||
FIXP_DBL scale;
|
||||
FIXP_DBL lr;
|
||||
FIXP_DBL hrrErr[MAX_GROUPED_SFB];
|
||||
FIXP_DBL normSfbLoudness[MAX_GROUPED_SFB];
|
||||
FIXP_DBL realIsScale[MAX_GROUPED_SFB];
|
||||
INTENSITY_PARAMETERS isParams;
|
||||
INT isMask[MAX_GROUPED_SFB];
|
||||
|
||||
FDKmemclear((void*)isBook,sfbCnt*sizeof(INT));
|
||||
FDKmemclear((void*)isMask,sfbCnt*sizeof(INT));
|
||||
FDKmemclear((void*)realIsScale,sfbCnt*sizeof(FIXP_DBL));
|
||||
FDKmemclear((void*)isScale,sfbCnt*sizeof(INT));
|
||||
FDKmemclear((void*)hrrErr,sfbCnt*sizeof(FIXP_DBL));
|
||||
|
||||
if (!allowIS)
|
||||
return;
|
||||
|
||||
FDKaacEnc_initIsParams(&isParams);
|
||||
|
||||
/* compute / set the following values per SFB:
|
||||
* - left/right ratio between channels
|
||||
* - normalized loudness
|
||||
* + loudness == average of energy in channels to 0.25
|
||||
* + normalization: division by sum of all SFB loudnesses
|
||||
* - isMask (is set to 0 if channels are the same or one is 0)
|
||||
*/
|
||||
FDKaacEnc_prepareIntensityDecision(sfbEnergyLeft,
|
||||
sfbEnergyRight,
|
||||
sfbEnergyLdDataLeft,
|
||||
sfbEnergyLdDataRight,
|
||||
mdctSpectrumLeft,
|
||||
mdctSpectrumRight,
|
||||
&isParams,
|
||||
hrrErr,
|
||||
isMask,
|
||||
realIsScale,
|
||||
normSfbLoudness,
|
||||
sfbCnt,
|
||||
sfbPerGroup,
|
||||
maxSfbPerGroup,
|
||||
sfbOffset);
|
||||
|
||||
FDKaacEnc_finalizeIntensityDecision(hrrErr,
|
||||
isMask,
|
||||
realIsScale,
|
||||
normSfbLoudness,
|
||||
&isParams,
|
||||
sfbCnt,
|
||||
sfbPerGroup,
|
||||
maxSfbPerGroup);
|
||||
|
||||
for (sfb=0; sfb<sfbCnt; sfb+=sfbPerGroup) {
|
||||
for (sfboffs=0; sfboffs<maxSfbPerGroup; sfboffs++) {
|
||||
INT sL, sR;
|
||||
FIXP_DBL inv_n;
|
||||
|
||||
msMask[sfb+sfboffs] = 0;
|
||||
if (isMask[sfb+sfboffs] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( (sfbEnergyLeft[sfb+sfboffs] < sfbThresholdLeft[sfb+sfboffs])
|
||||
&&(fMult(FL2FXCONST_DBL(1.0f/1.5f),sfbEnergyRight[sfb+sfboffs]) > sfbThresholdRight[sfb+sfboffs]) ) {
|
||||
continue;
|
||||
}
|
||||
/* NEW: if there is a big-enough IS region, switch off PNS */
|
||||
if (pnsData[0]) {
|
||||
if(pnsData[0]->pnsFlag[sfb+sfboffs]) {
|
||||
pnsData[0]->pnsFlag[sfb+sfboffs] = 0;
|
||||
}
|
||||
if(pnsData[1]->pnsFlag[sfb+sfboffs]) {
|
||||
pnsData[1]->pnsFlag[sfb+sfboffs] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inv_n = GetInvInt((sfbOffset[sfb + sfboffs + 1] - sfbOffset[sfb + sfboffs])>>1); // scaled with 2 to compensate fMultDiv2() in subsequent loop
|
||||
sL = calcSfbMaxScale(mdctSpectrumLeft,sfbOffset[sfb+sfboffs],sfbOffset[sfb+sfboffs+1]);
|
||||
sR = calcSfbMaxScale(mdctSpectrumRight,sfbOffset[sfb+sfboffs],sfbOffset[sfb+sfboffs+1]);
|
||||
|
||||
lr = FL2FXCONST_DBL(0.0f);
|
||||
for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++)
|
||||
lr += fMultDiv2(fMultDiv2(mdctSpectrumLeft[j]<<sL,mdctSpectrumRight[j]<<sR),inv_n);
|
||||
lr = lr<<1;
|
||||
|
||||
if (lr < FL2FXCONST_DBL(0.0f)) {
|
||||
/* This means OUT OF phase intensity stereo, cf. standard */
|
||||
INT s0, s1, s2;
|
||||
FIXP_DBL tmp, d, ed = FL2FXCONST_DBL(0.0f);
|
||||
|
||||
s0 = fixMin(sL,sR);
|
||||
for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
|
||||
d = ((mdctSpectrumLeft[j]<<s0)>>1) - ((mdctSpectrumRight[j]<<s0)>>1);
|
||||
ed += fMultDiv2(d,d)>>(MDCT_SPEC_SF-1);
|
||||
}
|
||||
msMask[sfb+sfboffs] = 1;
|
||||
tmp = fDivNorm(sfbEnergyLeft[sfb+sfboffs],ed,&s1);
|
||||
s2 = (s1) + (2*s0) - 2 - MDCT_SPEC_SF;
|
||||
if (s2 & 1) {
|
||||
tmp = tmp>>1;
|
||||
s2 = s2+1;
|
||||
}
|
||||
s2 = (s2>>1) + 1; // +1 compensate fMultDiv2() in subsequent loop
|
||||
s2 = fixMin(fixMax(s2,-(DFRACT_BITS-1)),(DFRACT_BITS-1));
|
||||
scale = sqrtFixp(tmp);
|
||||
if (s2 < 0) {
|
||||
s2 = -s2;
|
||||
for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
|
||||
mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j],scale) - fMultDiv2(mdctSpectrumRight[j],scale)) >> s2;
|
||||
mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
|
||||
mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j],scale) - fMultDiv2(mdctSpectrumRight[j],scale)) << s2;
|
||||
mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* This means IN phase intensity stereo, cf. standard */
|
||||
INT s0,s1,s2;
|
||||
FIXP_DBL tmp, s, es = FL2FXCONST_DBL(0.0f);
|
||||
|
||||
s0 = fixMin(sL,sR);
|
||||
for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
|
||||
s = ((mdctSpectrumLeft[j]<<s0)>>1) + ((mdctSpectrumRight[j]<<s0)>>1);
|
||||
es += fMultDiv2(s,s)>>(MDCT_SPEC_SF-1); // scaled 2*(mdctScale - s0 + 1) + MDCT_SPEC_SF
|
||||
}
|
||||
msMask[sfb+sfboffs] = 0;
|
||||
tmp = fDivNorm(sfbEnergyLeft[sfb+sfboffs],es,&s1);
|
||||
s2 = (s1) + (2*s0) - 2 - MDCT_SPEC_SF;
|
||||
if (s2 & 1) {
|
||||
tmp = tmp>>1;
|
||||
s2 = s2 + 1;
|
||||
}
|
||||
s2 = (s2>>1) + 1; // +1 compensate fMultDiv2() in subsequent loop
|
||||
s2 = fixMin(fixMax(s2,-(DFRACT_BITS-1)),(DFRACT_BITS-1));
|
||||
scale = sqrtFixp(tmp);
|
||||
if (s2 < 0) {
|
||||
s2 = -s2;
|
||||
for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
|
||||
mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j],scale) + fMultDiv2(mdctSpectrumRight[j],scale)) >> s2;
|
||||
mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
|
||||
mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j],scale) + fMultDiv2(mdctSpectrumRight[j],scale)) << s2;
|
||||
mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isBook[sfb+sfboffs] = CODE_BOOK_IS_IN_PHASE_NO;
|
||||
|
||||
if ( realIsScale[sfb+sfboffs] < FL2FXCONST_DBL(0.0f) ) {
|
||||
isScale[sfb+sfboffs] = (INT)(((realIsScale[sfb+sfboffs]>>1)-FL2FXCONST_DBL(0.5f/(1<<(REAL_SCALE_SF+LD_DATA_SHIFT+1))))>>(DFRACT_BITS-1-REAL_SCALE_SF-LD_DATA_SHIFT-1)) + 1;
|
||||
}
|
||||
else {
|
||||
isScale[sfb+sfboffs] = (INT)(((realIsScale[sfb+sfboffs]>>1)+FL2FXCONST_DBL(0.5f/(1<<(REAL_SCALE_SF+LD_DATA_SHIFT+1))))>>(DFRACT_BITS-1-REAL_SCALE_SF-LD_DATA_SHIFT-1));
|
||||
}
|
||||
|
||||
sfbEnergyRight[sfb+sfboffs] = FL2FXCONST_DBL(0.0f);
|
||||
sfbEnergyLdDataRight[sfb+sfboffs] = FL2FXCONST_DBL(-1.0f);
|
||||
sfbThresholdRight[sfb+sfboffs] = FL2FXCONST_DBL(0.0f);
|
||||
sfbThresholdLdDataRight[sfb+sfboffs] = FL2FXCONST_DBL(-0.515625f);
|
||||
sfbSpreadEnRight[sfb+sfboffs] = FL2FXCONST_DBL(0.0f);
|
||||
|
||||
*msDigest = MS_SOME;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
61
libAACenc/src/intensity.h
Normal file
61
libAACenc/src/intensity.h
Normal file
@ -0,0 +1,61 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2010)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
|
||||
Initial author: A. Horndasch (code originally from lwr and rtb) / Josef Höpfl (FDK)
|
||||
contents/description: intensity stereo prototype
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _INTENSITY_H
|
||||
#define _INTENSITY_H
|
||||
|
||||
#include "aacenc_pns.h"
|
||||
|
||||
|
||||
void FDKaacEnc_IntensityStereoProcessing(
|
||||
FIXP_DBL *sfbEnergyLeft,
|
||||
FIXP_DBL *sfbEnergyRight,
|
||||
FIXP_DBL *mdctSpectrumLeft,
|
||||
FIXP_DBL *mdctSpectrumRight,
|
||||
FIXP_DBL *sfbThresholdLeft,
|
||||
FIXP_DBL *sfbThresholdRight,
|
||||
FIXP_DBL *sfbThresholdLdDataRight,
|
||||
FIXP_DBL *sfbSpreadEnLeft,
|
||||
FIXP_DBL *sfbSpreadEnRight,
|
||||
FIXP_DBL *sfbEnergyLdDataLeft,
|
||||
FIXP_DBL *sfbEnergyLdDataRight,
|
||||
INT *msDigest,
|
||||
INT *msMask,
|
||||
const INT sfbCnt,
|
||||
const INT sfbPerGroup,
|
||||
const INT maxSfbPerGroup,
|
||||
const INT *sfbOffset,
|
||||
const INT allowIS,
|
||||
INT *isBook,
|
||||
INT *isScale,
|
||||
PNS_DATA *RESTRICT pnsData[2]
|
||||
);
|
||||
|
||||
#endif /* _INTENSITY_H */
|
||||
|
100
libAACenc/src/interface.h
Normal file
100
libAACenc/src/interface.h
Normal file
@ -0,0 +1,100 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M.Werner
|
||||
contents/description: Interface psychoaccoustic/quantizer
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef _INTERFACE_H
|
||||
#define _INTERFACE_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "psy_data.h"
|
||||
#include "aacenc_tns.h"
|
||||
|
||||
enum
|
||||
{
|
||||
MS_NONE = 0,
|
||||
MS_SOME = 1,
|
||||
MS_ALL = 2
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
MS_ON = 1
|
||||
};
|
||||
|
||||
struct TOOLSINFO {
|
||||
INT msDigest; /* 0 = no MS; 1 = some MS, 2 = all MS */
|
||||
INT msMask[MAX_GROUPED_SFB];
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
INT sfbCnt;
|
||||
INT sfbPerGroup;
|
||||
INT maxSfbPerGroup;
|
||||
INT lastWindowSequence;
|
||||
INT windowShape;
|
||||
INT groupingMask;
|
||||
INT sfbOffsets[MAX_GROUPED_SFB+1];
|
||||
|
||||
INT mdctScale; /* number of transform shifts */
|
||||
INT groupLen[MAX_NO_OF_GROUPS];
|
||||
|
||||
TNS_INFO tnsInfo;
|
||||
INT noiseNrg[MAX_GROUPED_SFB];
|
||||
INT isBook[MAX_GROUPED_SFB];
|
||||
INT isScale[MAX_GROUPED_SFB];
|
||||
|
||||
/* memory located in QC_OUT_CHANNEL */
|
||||
FIXP_DBL *mdctSpectrum;
|
||||
FIXP_DBL *sfbEnergy;
|
||||
FIXP_DBL *sfbSpreadEnergy;
|
||||
FIXP_DBL *sfbThresholdLdData;
|
||||
FIXP_DBL *sfbMinSnrLdData;
|
||||
FIXP_DBL *sfbEnergyLdData;
|
||||
|
||||
|
||||
}PSY_OUT_CHANNEL;
|
||||
|
||||
typedef struct {
|
||||
|
||||
/* information specific to each channel */
|
||||
PSY_OUT_CHANNEL* psyOutChannel[(2)];
|
||||
|
||||
/* information shared by both channels */
|
||||
INT commonWindow;
|
||||
struct TOOLSINFO toolsInfo;
|
||||
|
||||
} PSY_OUT_ELEMENT;
|
||||
|
||||
typedef struct {
|
||||
|
||||
PSY_OUT_ELEMENT* psyOutElement[(6)];
|
||||
PSY_OUT_CHANNEL* pPsyOutChannels[(6)];
|
||||
|
||||
}PSY_OUT;
|
||||
|
||||
#endif /* _INTERFACE_H */
|
145
libAACenc/src/line_pe.cpp
Normal file
145
libAACenc/src/line_pe.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M. Werner
|
||||
contents/description: Perceptual entropie module
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "line_pe.h"
|
||||
#include "sf_estim.h"
|
||||
#include "bit_cnt.h"
|
||||
|
||||
#include "genericStds.h"
|
||||
|
||||
static const FIXP_DBL C1LdData = FL2FXCONST_DBL(3.0/LD_DATA_SCALING); /* C1 = 3.0 = log(8.0)/log(2) */
|
||||
static const FIXP_DBL C2LdData = FL2FXCONST_DBL(1.3219281/LD_DATA_SCALING); /* C2 = 1.3219281 = log(2.5)/log(2) */
|
||||
static const FIXP_DBL C3LdData = FL2FXCONST_DBL(0.5593573); /* 1-C2/C1 */
|
||||
|
||||
|
||||
/* constants that do not change during successive pe calculations */
|
||||
void FDKaacEnc_prepareSfbPe(PE_CHANNEL_DATA *peChanData,
|
||||
const FIXP_DBL *sfbEnergyLdData,
|
||||
const FIXP_DBL *sfbThresholdLdData,
|
||||
const FIXP_DBL *sfbFormFactorLdData,
|
||||
const INT *sfbOffset,
|
||||
const INT sfbCnt,
|
||||
const INT sfbPerGroup,
|
||||
const INT maxSfbPerGroup)
|
||||
{
|
||||
INT sfbGrp,sfb;
|
||||
INT sfbWidth;
|
||||
FIXP_DBL avgFormFactorLdData;
|
||||
const FIXP_DBL formFacScaling = FL2FXCONST_DBL((float)FORM_FAC_SHIFT/LD_DATA_SCALING);
|
||||
|
||||
for (sfbGrp = 0;sfbGrp < sfbCnt;sfbGrp+=sfbPerGroup) {
|
||||
for (sfb=0; sfb<maxSfbPerGroup; sfb++) {
|
||||
if ((FIXP_DBL)sfbEnergyLdData[sfbGrp+sfb] > (FIXP_DBL)sfbThresholdLdData[sfbGrp+sfb]) {
|
||||
sfbWidth = sfbOffset[sfbGrp+sfb+1] - sfbOffset[sfbGrp+sfb];
|
||||
/* estimate number of active lines */
|
||||
avgFormFactorLdData = ((-sfbEnergyLdData[sfbGrp+sfb]>>1) + (CalcLdInt(sfbWidth)>>1))>>1;
|
||||
peChanData->sfbNLines[sfbGrp+sfb] =
|
||||
(INT)CalcInvLdData( (sfbFormFactorLdData[sfbGrp+sfb] + formFacScaling) + avgFormFactorLdData);
|
||||
}
|
||||
else {
|
||||
peChanData->sfbNLines[sfbGrp+sfb] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
formula for one sfb:
|
||||
pe = n * ld(en/thr), if ld(en/thr) >= C1
|
||||
pe = n * (C2 + C3 * ld(en/thr)), if ld(en/thr) < C1
|
||||
n: estimated number of lines in sfb,
|
||||
ld(x) = log(x)/log(2)
|
||||
|
||||
constPart is sfbPe without the threshold part n*ld(thr) or n*C3*ld(thr)
|
||||
*/
|
||||
void FDKaacEnc_calcSfbPe(PE_CHANNEL_DATA *RESTRICT peChanData,
|
||||
const FIXP_DBL *RESTRICT sfbEnergyLdData,
|
||||
const FIXP_DBL *RESTRICT sfbThresholdLdData,
|
||||
const INT sfbCnt,
|
||||
const INT sfbPerGroup,
|
||||
const INT maxSfbPerGroup,
|
||||
const INT *isBook,
|
||||
const INT *isScale)
|
||||
{
|
||||
INT sfbGrp,sfb;
|
||||
INT nLines;
|
||||
FIXP_DBL logDataRatio;
|
||||
INT lastValIs = 0;
|
||||
|
||||
peChanData->pe = 0;
|
||||
peChanData->constPart = 0;
|
||||
peChanData->nActiveLines = 0;
|
||||
|
||||
for(sfbGrp = 0;sfbGrp < sfbCnt;sfbGrp+=sfbPerGroup){
|
||||
for (sfb=0; sfb<maxSfbPerGroup; sfb++) {
|
||||
if ((FIXP_DBL)sfbEnergyLdData[sfbGrp+sfb] > (FIXP_DBL)sfbThresholdLdData[sfbGrp+sfb]) {
|
||||
logDataRatio = (FIXP_DBL)(sfbEnergyLdData[sfbGrp+sfb] - sfbThresholdLdData[sfbGrp+sfb]);
|
||||
nLines = peChanData->sfbNLines[sfbGrp+sfb];
|
||||
if (logDataRatio >= C1LdData) {
|
||||
/* scale sfbPe and sfbConstPart with PE_CONSTPART_SHIFT */
|
||||
peChanData->sfbPe[sfbGrp+sfb] = fMultDiv2(logDataRatio, (FIXP_DBL)(nLines<<(LD_DATA_SHIFT+PE_CONSTPART_SHIFT+1)));
|
||||
peChanData->sfbConstPart[sfbGrp+sfb] =
|
||||
fMultDiv2(sfbEnergyLdData[sfbGrp+sfb], (FIXP_DBL)(nLines<<(LD_DATA_SHIFT+PE_CONSTPART_SHIFT+1))); ;
|
||||
|
||||
}
|
||||
else {
|
||||
/* scale sfbPe and sfbConstPart with PE_CONSTPART_SHIFT */
|
||||
peChanData->sfbPe[sfbGrp+sfb] =
|
||||
fMultDiv2(((FIXP_DBL)C2LdData + fMult(C3LdData,logDataRatio)), (FIXP_DBL)(nLines<<(LD_DATA_SHIFT+PE_CONSTPART_SHIFT+1)));
|
||||
|
||||
peChanData->sfbConstPart[sfbGrp+sfb] =
|
||||
fMultDiv2(((FIXP_DBL)C2LdData + fMult(C3LdData,sfbEnergyLdData[sfbGrp+sfb])),
|
||||
(FIXP_DBL)(nLines<<(LD_DATA_SHIFT+PE_CONSTPART_SHIFT+1))) ;
|
||||
|
||||
nLines = fMultI(C3LdData, nLines);
|
||||
}
|
||||
peChanData->sfbNActiveLines[sfbGrp+sfb] = nLines;
|
||||
}
|
||||
else if( isBook[sfb] ) {
|
||||
/* provide for cost of scale factor for Intensity */
|
||||
INT delta = isScale[sfbGrp+sfb] - lastValIs;
|
||||
lastValIs = isScale[sfbGrp+sfb];
|
||||
peChanData->sfbPe[sfbGrp+sfb] = FDKaacEnc_bitCountScalefactorDelta(delta)<<PE_CONSTPART_SHIFT;
|
||||
peChanData->sfbConstPart[sfbGrp+sfb] = 0;
|
||||
peChanData->sfbNActiveLines[sfbGrp+sfb] = 0;
|
||||
}
|
||||
else {
|
||||
peChanData->sfbPe[sfbGrp+sfb] = 0;
|
||||
peChanData->sfbConstPart[sfbGrp+sfb] = 0;
|
||||
peChanData->sfbNActiveLines[sfbGrp+sfb] = 0;
|
||||
}
|
||||
/* sum up peChanData values */
|
||||
peChanData->pe += peChanData->sfbPe[sfbGrp+sfb];
|
||||
peChanData->constPart += peChanData->sfbConstPart[sfbGrp+sfb];
|
||||
peChanData->nActiveLines += peChanData->sfbNActiveLines[sfbGrp+sfb];
|
||||
}
|
||||
}
|
||||
/* correct scaled pe and constPart values */
|
||||
peChanData->pe>>=PE_CONSTPART_SHIFT;
|
||||
peChanData->constPart>>=PE_CONSTPART_SHIFT;
|
||||
}
|
77
libAACenc/src/line_pe.h
Normal file
77
libAACenc/src/line_pe.h
Normal file
@ -0,0 +1,77 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M. Werner
|
||||
contents/description: Perceptual entropie module
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef __LINE_PE_H
|
||||
#define __LINE_PE_H
|
||||
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "psy_const.h"
|
||||
|
||||
#define PE_CONSTPART_SHIFT FRACT_BITS
|
||||
|
||||
typedef struct {
|
||||
/* calculated by FDKaacEnc_prepareSfbPe */
|
||||
INT sfbNLines[MAX_GROUPED_SFB]; /* number of relevant lines in sfb */
|
||||
/* the rest is calculated by FDKaacEnc_calcSfbPe */
|
||||
INT sfbPe[MAX_GROUPED_SFB]; /* pe for each sfb */
|
||||
INT sfbConstPart[MAX_GROUPED_SFB]; /* constant part for each sfb */
|
||||
INT sfbNActiveLines[MAX_GROUPED_SFB]; /* number of active lines in sfb */
|
||||
INT pe; /* sum of sfbPe */
|
||||
INT constPart; /* sum of sfbConstPart */
|
||||
INT nActiveLines; /* sum of sfbNActiveLines */
|
||||
} PE_CHANNEL_DATA;
|
||||
|
||||
typedef struct {
|
||||
PE_CHANNEL_DATA peChannelData[(2)];
|
||||
INT pe;
|
||||
INT constPart;
|
||||
INT nActiveLines;
|
||||
INT offset;
|
||||
} PE_DATA;
|
||||
|
||||
|
||||
void FDKaacEnc_prepareSfbPe(PE_CHANNEL_DATA *peChanData,
|
||||
const FIXP_DBL *sfbEnergyLdData,
|
||||
const FIXP_DBL *sfbThresholdLdData,
|
||||
const FIXP_DBL *sfbFormFactorLdData,
|
||||
const INT *sfbOffset,
|
||||
const INT sfbCnt,
|
||||
const INT sfbPerGroup,
|
||||
const INT maxSfbPerGroup);
|
||||
|
||||
void FDKaacEnc_calcSfbPe(PE_CHANNEL_DATA *RESTRICT peChanData,
|
||||
const FIXP_DBL *RESTRICT sfbEnergyLdData,
|
||||
const FIXP_DBL *RESTRICT sfbThresholdLdData,
|
||||
const INT sfbCnt,
|
||||
const INT sfbPerGroup,
|
||||
const INT maxSfbPerGroup,
|
||||
const INT *isBook,
|
||||
const INT *isScale);
|
||||
|
||||
#endif
|
965
libAACenc/src/metadata_compressor.cpp
Normal file
965
libAACenc/src/metadata_compressor.cpp
Normal file
@ -0,0 +1,965 @@
|
||||
/********************** Fraunhofer IIS FDK AAC Encoder lib ******************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2011)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): M. Neusinger
|
||||
Description: Compressor for AAC Metadata Generator
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#include "metadata_compressor.h"
|
||||
#include "channel_map.h"
|
||||
|
||||
|
||||
#define LOG2 0.69314718056f /* natural logarithm of 2 */
|
||||
#define ILOG2 1.442695041f /* 1/LOG2 */
|
||||
#define FIXP_ILOG2_DIV2 (FL2FXCONST_DBL(ILOG2/2))
|
||||
|
||||
/*----------------- defines ----------------------*/
|
||||
|
||||
#define MAX_DRC_CHANNELS (8) /*!< Max number of audio input channels. */
|
||||
#define DOWNMIX_SHIFT (3) /*!< Max 8 channel. */
|
||||
#define WEIGHTING_FILTER_SHIFT (2) /*!< Scaling used in weighting filter. */
|
||||
|
||||
#define METADATA_INT_BITS 10
|
||||
#define METADATA_LINT_BITS 20
|
||||
#define METADATA_INT_SCALE (INT64(1)<<(METADATA_INT_BITS))
|
||||
#define METADATA_FRACT_BITS (DFRACT_BITS-1-METADATA_INT_BITS)
|
||||
#define METADATA_FRACT_SCALE (INT64(1)<<(METADATA_FRACT_BITS))
|
||||
|
||||
/**
|
||||
* Enum for channel assignment.
|
||||
*/
|
||||
enum {
|
||||
L = 0,
|
||||
R = 1,
|
||||
C = 2,
|
||||
LFE = 3,
|
||||
LS = 4,
|
||||
RS = 5,
|
||||
S = 6,
|
||||
LS2 = 7,
|
||||
RS2 = 8
|
||||
};
|
||||
|
||||
/*--------------- structure definitions --------------------*/
|
||||
|
||||
/**
|
||||
* Structure holds weighting filter filter states.
|
||||
*/
|
||||
struct WEIGHTING_STATES {
|
||||
FIXP_DBL x1;
|
||||
FIXP_DBL x2;
|
||||
FIXP_DBL y1;
|
||||
FIXP_DBL y2;
|
||||
};
|
||||
|
||||
/**
|
||||
* Dynamic Range Control compressor structure.
|
||||
*/
|
||||
struct DRC_COMP {
|
||||
|
||||
FIXP_DBL maxBoostThr[2]; /*!< Max boost threshold. */
|
||||
FIXP_DBL boostThr[2]; /*!< Boost threshold. */
|
||||
FIXP_DBL earlyCutThr[2]; /*!< Early cut threshold. */
|
||||
FIXP_DBL cutThr[2]; /*!< Cut threshold. */
|
||||
FIXP_DBL maxCutThr[2]; /*!< Max cut threshold. */
|
||||
|
||||
FIXP_DBL boostFac[2]; /*!< Precalculated factor for boost compression. */
|
||||
FIXP_DBL earlyCutFac[2]; /*!< Precalculated factor for early cut compression. */
|
||||
FIXP_DBL cutFac[2]; /*!< Precalculated factor for cut compression. */
|
||||
|
||||
FIXP_DBL maxBoost[2]; /*!< Maximum boost. */
|
||||
FIXP_DBL maxCut[2]; /*!< Maximum cut. */
|
||||
FIXP_DBL maxEarlyCut[2]; /*!< Maximum early cut. */
|
||||
|
||||
FIXP_DBL fastAttack[2]; /*!< Fast attack coefficient. */
|
||||
FIXP_DBL fastDecay[2]; /*!< Fast release coefficient. */
|
||||
FIXP_DBL slowAttack[2]; /*!< Slow attack coefficient. */
|
||||
FIXP_DBL slowDecay[2]; /*!< Slow release coefficient. */
|
||||
UINT holdOff[2]; /*!< Hold time in blocks. */
|
||||
|
||||
FIXP_DBL attackThr[2]; /*!< Slow/fast attack threshold. */
|
||||
FIXP_DBL decayThr[2]; /*!< Slow/fast release threshold. */
|
||||
|
||||
DRC_PROFILE profile[2]; /*!< DRC profile. */
|
||||
INT blockLength; /*!< Block length in samples. */
|
||||
UINT sampleRate; /*!< Sample rate. */
|
||||
CHANNEL_MODE chanConfig; /*!< Channel configuration. */
|
||||
|
||||
UCHAR useWeighting; /*!< Use weighting filter. */
|
||||
|
||||
UINT channels; /*!< Number of channels. */
|
||||
UINT fullChannels; /*!< Number of full range channels. */
|
||||
INT channelIdx[9]; /*!< Offsets of interleaved channel samples (L, R, C, LFE, Ls, Rs, S, Ls2, Rs2). */
|
||||
|
||||
FIXP_DBL smoothLevel[2]; /*!< level smoothing states */
|
||||
FIXP_DBL smoothGain[2]; /*!< gain smoothing states */
|
||||
UINT holdCnt[2]; /*!< hold counter */
|
||||
|
||||
FIXP_DBL limGain[2]; /*!< limiter gain */
|
||||
FIXP_DBL limDecay; /*!< limiter decay (linear) */
|
||||
FIXP_DBL prevPeak[2]; /*!< max peak of previous block (stereo/mono)*/
|
||||
|
||||
WEIGHTING_STATES filter[MAX_DRC_CHANNELS]; /*!< array holds weighting filter states */
|
||||
|
||||
};
|
||||
|
||||
/*---------------- constants -----------------------*/
|
||||
|
||||
/**
|
||||
* Profile tables.
|
||||
*/
|
||||
static const FIXP_DBL tabMaxBoostThr[] = {
|
||||
(FIXP_DBL)(-43<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-53<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-55<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-65<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-50<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-40<<METADATA_FRACT_BITS)
|
||||
};
|
||||
static const FIXP_DBL tabBoostThr[] = {
|
||||
(FIXP_DBL)(-31<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-41<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-31<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-41<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-31<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-31<<METADATA_FRACT_BITS)
|
||||
};
|
||||
static const FIXP_DBL tabEarlyCutThr[] = {
|
||||
(FIXP_DBL)(-26<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-21<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-26<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-21<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-26<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-20<<METADATA_FRACT_BITS)
|
||||
};
|
||||
static const FIXP_DBL tabCutThr[] = {
|
||||
(FIXP_DBL)(-16<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-11<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-16<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-21<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-16<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(-10<<METADATA_FRACT_BITS)
|
||||
};
|
||||
static const FIXP_DBL tabMaxCutThr[] = {
|
||||
(FIXP_DBL)(4<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(9<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(4<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(9<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(4<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(4<<METADATA_FRACT_BITS)
|
||||
};
|
||||
static const FIXP_DBL tabBoostRatio[] = {
|
||||
FL2FXCONST_DBL( ((1.f/2.f) - 1.f) ),
|
||||
FL2FXCONST_DBL( ((1.f/2.f) - 1.f) ),
|
||||
FL2FXCONST_DBL( ((1.f/2.f) - 1.f) ),
|
||||
FL2FXCONST_DBL( ((1.f/2.f) - 1.f) ),
|
||||
FL2FXCONST_DBL( ((1.f/5.f) - 1.f) ),
|
||||
FL2FXCONST_DBL( ((1.f/5.f) - 1.f) )
|
||||
};
|
||||
static const FIXP_DBL tabEarlyCutRatio[] = {
|
||||
FL2FXCONST_DBL( ((1.f/2.f) - 1.f) ),
|
||||
FL2FXCONST_DBL( ((1.f/2.f) - 1.f) ),
|
||||
FL2FXCONST_DBL( ((1.f/2.f) - 1.f) ),
|
||||
FL2FXCONST_DBL( ((1.f/1.f) - 1.f) ),
|
||||
FL2FXCONST_DBL( ((1.f/2.f) - 1.f) ),
|
||||
FL2FXCONST_DBL( ((1.f/2.f) - 1.f) )
|
||||
};
|
||||
static const FIXP_DBL tabCutRatio[] = {
|
||||
FL2FXCONST_DBL( ((1.f/20.f) - 1.f) ),
|
||||
FL2FXCONST_DBL( ((1.f/20.f) - 1.f) ),
|
||||
FL2FXCONST_DBL( ((1.f/20.f) - 1.f) ),
|
||||
FL2FXCONST_DBL( ((1.f/ 2.f) - 1.f) ),
|
||||
FL2FXCONST_DBL( ((1.f/20.f) - 1.f) ),
|
||||
FL2FXCONST_DBL( ((1.f/20.f) - 1.f) )
|
||||
};
|
||||
static const FIXP_DBL tabMaxBoost[] = {
|
||||
(FIXP_DBL)( 6<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)( 6<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(12<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(12<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(15<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(15<<METADATA_FRACT_BITS)
|
||||
};
|
||||
static const FIXP_DBL tabMaxCut[] = {
|
||||
(FIXP_DBL)(24<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(24<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(24<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(15<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(24<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(24<<METADATA_FRACT_BITS)
|
||||
};
|
||||
static const FIXP_DBL tabFastAttack[] = {
|
||||
FL2FXCONST_DBL((10.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL((10.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL((10.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL((10.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL((10.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL( (0.f/1000.f)/METADATA_INT_SCALE)
|
||||
};
|
||||
static const FIXP_DBL tabFastDecay[] = {
|
||||
FL2FXCONST_DBL((1000.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL((1000.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL((1000.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL((1000.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL( (200.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL( (0.f/1000.f)/METADATA_INT_SCALE)
|
||||
};
|
||||
static const FIXP_DBL tabSlowAttack[] = {
|
||||
FL2FXCONST_DBL((100.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL((100.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL((100.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL((100.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL((100.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL( (0.f/1000.f)/METADATA_INT_SCALE)
|
||||
};
|
||||
static const FIXP_DBL tabSlowDecay[] = {
|
||||
FL2FXCONST_DBL( (3000.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL( (3000.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL((10000.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL( (3000.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL( (1000.f/1000.f)/METADATA_INT_SCALE),
|
||||
FL2FXCONST_DBL( (0.f/1000.f)/METADATA_INT_SCALE)
|
||||
};
|
||||
|
||||
static const INT tabHoldOff[] = { 10, 10, 10, 10, 10, 0 };
|
||||
|
||||
static const FIXP_DBL tabAttackThr[] = {
|
||||
(FIXP_DBL)(15<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(15<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(15<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(15<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(10<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(0<<METADATA_FRACT_BITS)
|
||||
};
|
||||
static const FIXP_DBL tabDecayThr[] = {
|
||||
(FIXP_DBL)(20<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(20<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(20<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(20<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)(10<<METADATA_FRACT_BITS),
|
||||
(FIXP_DBL)( 0<<METADATA_FRACT_BITS)
|
||||
};
|
||||
|
||||
/**
|
||||
* Weighting filter coefficients (biquad bandpass).
|
||||
*/
|
||||
static const FIXP_DBL b0 = FL2FXCONST_DBL(0.53050662f); /* b1 = 0, b2 = -b0 */
|
||||
static const FIXP_DBL a1 = FL2FXCONST_DBL(-0.95237983f), a2 = FL2FXCONST_DBL(-0.02248836f); /* a0 = 1 */
|
||||
|
||||
|
||||
/*------------- function definitions ----------------*/
|
||||
|
||||
/**
|
||||
* \brief Calculate scaling factor for denoted processing block.
|
||||
*
|
||||
* \param blockLength Length of processing block.
|
||||
*
|
||||
* \return shiftFactor
|
||||
*/
|
||||
static UINT getShiftFactor(
|
||||
const UINT length
|
||||
)
|
||||
{
|
||||
UINT ldN;
|
||||
for(ldN=1;(((UINT)1)<<ldN) < length;ldN++);
|
||||
|
||||
return ldN;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sum up fixpoint values with best possible accuracy.
|
||||
*
|
||||
* \param value1 First input value.
|
||||
* \param q1 Scaling factor of first input value.
|
||||
* \param pValue2 Pointer to second input value, will be modified on return.
|
||||
* \param pQ2 Pointer to second scaling factor, will be modified on return.
|
||||
*
|
||||
* \return void
|
||||
*/
|
||||
static void fixpAdd(
|
||||
const FIXP_DBL value1,
|
||||
const int q1,
|
||||
FIXP_DBL *const pValue2,
|
||||
int *const pQ2
|
||||
)
|
||||
{
|
||||
const int headroom1 = fNormz(fixp_abs(value1))-1;
|
||||
const int headroom2 = fNormz(fixp_abs(*pValue2))-1;
|
||||
int resultScale = fixMax(q1-headroom1, (*pQ2)-headroom2);
|
||||
|
||||
if ( (value1!=FL2FXCONST_DBL(0.f)) && (*pValue2!=FL2FXCONST_DBL(0.f)) ) {
|
||||
resultScale++;
|
||||
}
|
||||
|
||||
*pValue2 = scaleValue(value1, q1-resultScale) + scaleValue(*pValue2, (*pQ2)-resultScale);
|
||||
*pQ2 = (*pValue2!=(FIXP_DBL)0) ? resultScale : DFRACT_BITS-1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Function for converting time constant to filter coefficient.
|
||||
*
|
||||
* \param t Time constant.
|
||||
* \param sampleRate Sampling rate in Hz.
|
||||
* \param blockLength Length of processing block in samples per channel.
|
||||
*
|
||||
* \return result = 1.0 - exp(-1.0/((t) * (f)))
|
||||
*/
|
||||
static FIXP_DBL tc2Coeff(
|
||||
const FIXP_DBL t,
|
||||
const INT sampleRate,
|
||||
const INT blockLength
|
||||
)
|
||||
{
|
||||
FIXP_DBL sampleRateFract;
|
||||
FIXP_DBL blockLengthFract;
|
||||
FIXP_DBL f, product;
|
||||
FIXP_DBL exponent, result;
|
||||
INT e_res;
|
||||
|
||||
/* f = sampleRate/blockLength */
|
||||
sampleRateFract = (FIXP_DBL)(sampleRate<<(DFRACT_BITS-1-METADATA_LINT_BITS));
|
||||
blockLengthFract = (FIXP_DBL)(blockLength<<(DFRACT_BITS-1-METADATA_LINT_BITS));
|
||||
f = fDivNorm(sampleRateFract, blockLengthFract, &e_res);
|
||||
f = scaleValue(f, e_res-METADATA_INT_BITS); /* convert to METADATA_FRACT */
|
||||
|
||||
/* product = t*f */
|
||||
product = fMultNorm(t, f, &e_res);
|
||||
product = scaleValue(product, e_res+METADATA_INT_BITS); /* convert to METADATA_FRACT */
|
||||
|
||||
/* exponent = (-1.0/((t) * (f))) */
|
||||
exponent = fDivNorm(METADATA_FRACT_SCALE, product, &e_res);
|
||||
exponent = scaleValue(exponent, e_res-METADATA_INT_BITS); /* convert to METADATA_FRACT */
|
||||
|
||||
/* exponent * ld(e) */
|
||||
exponent = fMult(exponent,FIXP_ILOG2_DIV2)<<1; /* e^(x) = 2^(x*ld(e)) */
|
||||
|
||||
/* exp(-1.0/((t) * (f))) */
|
||||
result = f2Pow(-exponent, DFRACT_BITS-1-METADATA_FRACT_BITS, &e_res);
|
||||
|
||||
/* result = 1.0 - exp(-1.0/((t) * (f))) */
|
||||
result = FL2FXCONST_DBL(1.0f) - scaleValue(result, e_res);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
INT FDK_DRC_Generator_Open(
|
||||
HDRC_COMP *phDrcComp
|
||||
)
|
||||
{
|
||||
INT err = 0;
|
||||
HDRC_COMP hDcComp = NULL;
|
||||
|
||||
if (phDrcComp == NULL) {
|
||||
err = -1;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* allocate memory */
|
||||
hDcComp = (HDRC_COMP)FDKcalloc(1, sizeof(DRC_COMP));
|
||||
|
||||
if (hDcComp == NULL) {
|
||||
err = -1;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
FDKmemclear(hDcComp, sizeof(DRC_COMP));
|
||||
|
||||
/* Return drc compressor instance */
|
||||
*phDrcComp = hDcComp;
|
||||
return err;
|
||||
bail:
|
||||
FDK_DRC_Generator_Close(&hDcComp);
|
||||
return err;
|
||||
}
|
||||
|
||||
INT FDK_DRC_Generator_Close(
|
||||
HDRC_COMP *phDrcComp
|
||||
)
|
||||
{
|
||||
if (phDrcComp == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (*phDrcComp != NULL) {
|
||||
FDKfree(*phDrcComp);
|
||||
*phDrcComp = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
INT FDK_DRC_Generator_Initialize(
|
||||
HDRC_COMP drcComp,
|
||||
const DRC_PROFILE profileLine,
|
||||
const DRC_PROFILE profileRF,
|
||||
const INT blockLength,
|
||||
const UINT sampleRate,
|
||||
const CHANNEL_MODE channelMode,
|
||||
const CHANNEL_ORDER channelOrder,
|
||||
const UCHAR useWeighting
|
||||
)
|
||||
{
|
||||
int i;
|
||||
CHANNEL_MAPPING channelMapping;
|
||||
|
||||
drcComp->limDecay = FL2FXCONST_DBL( ((0.006f / 256) * blockLength) / METADATA_INT_SCALE );
|
||||
|
||||
/* Save parameters. */
|
||||
drcComp->blockLength = blockLength;
|
||||
drcComp->sampleRate = sampleRate;
|
||||
drcComp->chanConfig = channelMode;
|
||||
drcComp->useWeighting = useWeighting;
|
||||
|
||||
if (FDK_DRC_Generator_setDrcProfile(drcComp, profileLine, profileRF)!=0) { /* expects initialized blockLength and sampleRate */
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Set number of channels and channel offsets. */
|
||||
if (FDKaacEnc_InitChannelMapping(channelMode, channelOrder, &channelMapping)!=AAC_ENC_OK) {
|
||||
return (-2);
|
||||
}
|
||||
|
||||
for (i = 0; i < 9; i++) drcComp->channelIdx[i] = -1;
|
||||
|
||||
switch (channelMode) {
|
||||
case MODE_1: /* mono */
|
||||
drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0];
|
||||
break;
|
||||
case MODE_2: /* stereo */
|
||||
drcComp->channelIdx[L] = channelMapping.elInfo[0].ChannelIndex[0];
|
||||
drcComp->channelIdx[R] = channelMapping.elInfo[0].ChannelIndex[1];
|
||||
break;
|
||||
case MODE_1_2: /* 3ch */
|
||||
drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0];
|
||||
drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1];
|
||||
drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0];
|
||||
break;
|
||||
case MODE_1_2_1: /* 4ch */
|
||||
drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0];
|
||||
drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1];
|
||||
drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0];
|
||||
drcComp->channelIdx[S] = channelMapping.elInfo[2].ChannelIndex[0];
|
||||
break;
|
||||
case MODE_1_2_2: /* 5ch */
|
||||
drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0];
|
||||
drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1];
|
||||
drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0];
|
||||
drcComp->channelIdx[LS] = channelMapping.elInfo[2].ChannelIndex[0];
|
||||
drcComp->channelIdx[RS] = channelMapping.elInfo[2].ChannelIndex[1];
|
||||
break;
|
||||
case MODE_1_2_2_1: /* 5.1 ch */
|
||||
drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0];
|
||||
drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1];
|
||||
drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0];
|
||||
drcComp->channelIdx[LFE] = channelMapping.elInfo[3].ChannelIndex[0];
|
||||
drcComp->channelIdx[LS] = channelMapping.elInfo[2].ChannelIndex[0];
|
||||
drcComp->channelIdx[RS] = channelMapping.elInfo[2].ChannelIndex[1];
|
||||
break;
|
||||
case MODE_1_2_2_2_1: /* 7.1 ch */
|
||||
drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0];
|
||||
drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1];
|
||||
drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0];
|
||||
drcComp->channelIdx[LFE] = channelMapping.elInfo[4].ChannelIndex[0];
|
||||
drcComp->channelIdx[LS] = channelMapping.elInfo[2].ChannelIndex[0];
|
||||
drcComp->channelIdx[RS] = channelMapping.elInfo[2].ChannelIndex[1];
|
||||
drcComp->channelIdx[LS2] = channelMapping.elInfo[3].ChannelIndex[0];
|
||||
drcComp->channelIdx[RS2] = channelMapping.elInfo[3].ChannelIndex[1];
|
||||
break;
|
||||
case MODE_1_1:
|
||||
case MODE_1_1_1_1:
|
||||
case MODE_1_1_1_1_1_1:
|
||||
case MODE_1_1_1_1_1_1_1_1:
|
||||
case MODE_1_1_1_1_1_1_1_1_1_1_1_1:
|
||||
case MODE_2_2:
|
||||
case MODE_2_2_2:
|
||||
case MODE_2_2_2_2:
|
||||
case MODE_2_2_2_2_2_2:
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
|
||||
drcComp->fullChannels = channelMapping.nChannelsEff;
|
||||
drcComp->channels = channelMapping.nChannels;
|
||||
|
||||
/* Init states. */
|
||||
drcComp->smoothLevel[0] = drcComp->smoothLevel[1] = (FIXP_DBL)(-135<<METADATA_FRACT_BITS);
|
||||
|
||||
FDKmemclear(drcComp->smoothGain, sizeof(drcComp->smoothGain));
|
||||
FDKmemclear(drcComp->holdCnt, sizeof(drcComp->holdCnt));
|
||||
FDKmemclear(drcComp->limGain, sizeof(drcComp->limGain));
|
||||
FDKmemclear(drcComp->prevPeak, sizeof(drcComp->prevPeak));
|
||||
FDKmemclear(drcComp->filter, sizeof(drcComp->filter));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
INT FDK_DRC_Generator_setDrcProfile(
|
||||
HDRC_COMP drcComp,
|
||||
const DRC_PROFILE profileLine,
|
||||
const DRC_PROFILE profileRF
|
||||
)
|
||||
{
|
||||
int profileIdx, i;
|
||||
|
||||
drcComp->profile[0] = profileLine;
|
||||
drcComp->profile[1] = profileRF;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
/* get profile index */
|
||||
switch (drcComp->profile[i]) {
|
||||
case DRC_NONE:
|
||||
case DRC_FILMSTANDARD: profileIdx = 0; break;
|
||||
case DRC_FILMLIGHT: profileIdx = 1; break;
|
||||
case DRC_MUSICSTANDARD: profileIdx = 2; break;
|
||||
case DRC_MUSICLIGHT: profileIdx = 3; break;
|
||||
case DRC_SPEECH: profileIdx = 4; break;
|
||||
case DRC_DELAY_TEST: profileIdx = 5; break;
|
||||
default: return (-1);
|
||||
}
|
||||
|
||||
/* get parameters for selected profile */
|
||||
if (profileIdx >= 0) {
|
||||
drcComp->maxBoostThr[i] = tabMaxBoostThr[profileIdx];
|
||||
drcComp->boostThr[i] = tabBoostThr[profileIdx];
|
||||
drcComp->earlyCutThr[i] = tabEarlyCutThr[profileIdx];
|
||||
drcComp->cutThr[i] = tabCutThr[profileIdx];
|
||||
drcComp->maxCutThr[i] = tabMaxCutThr[profileIdx];
|
||||
|
||||
drcComp->boostFac[i] = tabBoostRatio[profileIdx];
|
||||
drcComp->earlyCutFac[i] = tabEarlyCutRatio[profileIdx];
|
||||
drcComp->cutFac[i] = tabCutRatio[profileIdx];
|
||||
|
||||
drcComp->maxBoost[i] = tabMaxBoost[profileIdx];
|
||||
drcComp->maxCut[i] = tabMaxCut[profileIdx];
|
||||
drcComp->maxEarlyCut[i] = - fMult((drcComp->cutThr[i] - drcComp->earlyCutThr[i]), drcComp->earlyCutFac[i]); /* no scaling after mult needed, earlyCutFac is in FIXP_DBL */
|
||||
|
||||
drcComp->fastAttack[i] = tc2Coeff(tabFastAttack[profileIdx], drcComp->sampleRate, drcComp->blockLength);
|
||||
drcComp->fastDecay[i] = tc2Coeff(tabFastDecay[profileIdx], drcComp->sampleRate, drcComp->blockLength);
|
||||
drcComp->slowAttack[i] = tc2Coeff(tabSlowAttack[profileIdx], drcComp->sampleRate, drcComp->blockLength);
|
||||
drcComp->slowDecay[i] = tc2Coeff(tabSlowDecay[profileIdx], drcComp->sampleRate, drcComp->blockLength);
|
||||
drcComp->holdOff[i] = tabHoldOff[profileIdx] * 256 / drcComp->blockLength;
|
||||
|
||||
drcComp->attackThr[i] = tabAttackThr[profileIdx];
|
||||
drcComp->decayThr[i] = tabDecayThr[profileIdx];
|
||||
}
|
||||
|
||||
drcComp->smoothGain[i] = FL2FXCONST_DBL(0.f);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
INT FDK_DRC_Generator_Calc(
|
||||
HDRC_COMP drcComp,
|
||||
const INT_PCM * const inSamples,
|
||||
const INT dialnorm,
|
||||
const INT drc_TargetRefLevel,
|
||||
const INT comp_TargetRefLevel,
|
||||
FIXP_DBL clev,
|
||||
FIXP_DBL slev,
|
||||
INT * const pDynrng,
|
||||
INT * const pCompr
|
||||
)
|
||||
{
|
||||
int i, c;
|
||||
FIXP_DBL peak[2];
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* compressor
|
||||
**************************************************************************/
|
||||
if ((drcComp->profile[0] != DRC_NONE) || (drcComp->profile[1] != DRC_NONE)) {
|
||||
/* Calc loudness level */
|
||||
FIXP_DBL level_b = FL2FXCONST_DBL(0.f);
|
||||
int level_e = DFRACT_BITS-1;
|
||||
|
||||
/* Increase energy time resolution with shorter processing blocks. 32 is an empiric value. */
|
||||
const int granuleLength = fixMin(32, drcComp->blockLength);
|
||||
|
||||
if (drcComp->useWeighting) {
|
||||
FIXP_DBL x1, x2, y, y1, y2;
|
||||
/* sum of filter coefficients about 2.5 -> squared value is 6.25
|
||||
WEIGHTING_FILTER_SHIFT is 2 -> scaling about 16, therefore reduce granuleShift by 1.
|
||||
*/
|
||||
const int granuleShift = getShiftFactor(granuleLength)-1;
|
||||
|
||||
for (c = 0; c < (int)drcComp->channels; c++) {
|
||||
const INT_PCM* pSamples = &inSamples[c];
|
||||
|
||||
if (c == drcComp->channelIdx[LFE]) {
|
||||
continue; /* skip LFE */
|
||||
}
|
||||
|
||||
/* get filter states */
|
||||
x1 = drcComp->filter[c].x1;
|
||||
x2 = drcComp->filter[c].x2;
|
||||
y1 = drcComp->filter[c].y1;
|
||||
y2 = drcComp->filter[c].y2;
|
||||
|
||||
i = 0;
|
||||
|
||||
do {
|
||||
|
||||
int offset = i;
|
||||
FIXP_DBL accu = FL2FXCONST_DBL(0.f);
|
||||
|
||||
for (i=offset; i < fixMin(offset+granuleLength,drcComp->blockLength); i++) {
|
||||
/* apply weighting filter */
|
||||
FIXP_DBL x = FX_PCM2FX_DBL((FIXP_PCM)pSamples[i*drcComp->channels]) >> WEIGHTING_FILTER_SHIFT;
|
||||
|
||||
/* y = b0 * (x - x2) - a1 * y1 - a2 * y2; */
|
||||
y = fMult(b0,x-x2) - fMult(a1,y1) - fMult(a2,y2);
|
||||
|
||||
x2 = x1;
|
||||
x1 = x;
|
||||
y2 = y1;
|
||||
y1 = y;
|
||||
|
||||
accu += fPow2Div2(y)>>(granuleShift-1); /* partial energy */
|
||||
} /* i */
|
||||
|
||||
fixpAdd(accu, granuleShift+2*WEIGHTING_FILTER_SHIFT, &level_b, &level_e); /* sup up partial energies */
|
||||
|
||||
} while ( i < drcComp->blockLength );
|
||||
|
||||
|
||||
/* save filter states */
|
||||
drcComp->filter[c].x1 = x1;
|
||||
drcComp->filter[c].x2 = x2;
|
||||
drcComp->filter[c].y1 = y1;
|
||||
drcComp->filter[c].y2 = y2;
|
||||
} /* c */
|
||||
} /* weighting */
|
||||
else {
|
||||
const int granuleShift = getShiftFactor(granuleLength);
|
||||
|
||||
for (c = 0; c < (int)drcComp->channels; c++) {
|
||||
const INT_PCM* pSamples = &inSamples[c];
|
||||
|
||||
if ((int)c == drcComp->channelIdx[LFE]) {
|
||||
continue; /* skip LFE */
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
do {
|
||||
int offset = i;
|
||||
FIXP_DBL accu = FL2FXCONST_DBL(0.f);
|
||||
|
||||
for (i=offset; i < fixMin(offset+granuleLength,drcComp->blockLength); i++) {
|
||||
/* partial energy */
|
||||
accu += fPow2Div2((FIXP_PCM)pSamples[i*drcComp->channels])>>(granuleShift-1);
|
||||
} /* i */
|
||||
|
||||
fixpAdd(accu, granuleShift, &level_b, &level_e); /* sup up partial energies */
|
||||
|
||||
} while ( i < drcComp->blockLength );
|
||||
}
|
||||
} /* weighting */
|
||||
|
||||
/*
|
||||
* Convert to dBFS, apply dialnorm
|
||||
*/
|
||||
/* level scaling */
|
||||
|
||||
/* descaled level in ld64 representation */
|
||||
FIXP_DBL ldLevel = CalcLdData(level_b) + (FIXP_DBL)((level_e-12)<<(DFRACT_BITS-1-LD_DATA_SHIFT)) - CalcLdData((FIXP_DBL)(drcComp->blockLength<<(DFRACT_BITS-1-12)));
|
||||
|
||||
/* if (level < 1e-10) level = 1e-10f; */
|
||||
ldLevel = FDKmax(ldLevel, FL2FXCONST_DBL(-0.51905126482615036685473741085772f));
|
||||
|
||||
/* level = 10 * log(level)/log(10) + 3;
|
||||
* = 10*log(2)/log(10) * ld(level) + 3;
|
||||
* = 10 * 0.30102999566398119521373889472449 * ld(level) + 3
|
||||
* = 10 * (0.30102999566398119521373889472449 * ld(level) + 0.3)
|
||||
* = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) * 64
|
||||
*
|
||||
* additional scaling with METADATA_FRACT_BITS:
|
||||
* = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) * 64 * 2^(METADATA_FRACT_BITS)
|
||||
* = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) * 2^(METADATA_FRACT_BITS+LD_DATA_SHIFT)
|
||||
* = 10*2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) * ( 0.30102999566398119521373889472449 * ld64(level) + 0.3/64 )
|
||||
* */
|
||||
FIXP_DBL level = fMult((FIXP_DBL)(10<<(METADATA_FRACT_BITS+LD_DATA_SHIFT)), fMult( FL2FXCONST_DBL(0.30102999566398119521373889472449f), ldLevel) + (FIXP_DBL)(FL2FXCONST_DBL(0.3f)>>LD_DATA_SHIFT) );
|
||||
|
||||
/* level -= dialnorm + 31 */ /* this is fixed to Dolby-ReferenceLevel as compressor profiles are defined relative to this */
|
||||
level -= ((FIXP_DBL)(dialnorm<<(METADATA_FRACT_BITS-16)) + (FIXP_DBL)(31<<METADATA_FRACT_BITS));
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (drcComp->profile[i] == DRC_NONE) {
|
||||
/* no compression */
|
||||
drcComp->smoothGain[i] = FL2FXCONST_DBL(0.f);
|
||||
}
|
||||
else {
|
||||
FIXP_DBL gain, alpha, lvl2smthlvl;
|
||||
|
||||
/* calc static gain */
|
||||
if (level <= drcComp->maxBoostThr[i]) {
|
||||
/* max boost */
|
||||
gain = drcComp->maxBoost[i];
|
||||
}
|
||||
else if (level < drcComp->boostThr[i]) {
|
||||
/* boost range */
|
||||
gain = fMult((level - drcComp->boostThr[i]),drcComp->boostFac[i]);
|
||||
}
|
||||
else if (level <= drcComp->earlyCutThr[i]) {
|
||||
/* null band */
|
||||
gain = FL2FXCONST_DBL(0.f);
|
||||
}
|
||||
else if (level <= drcComp->cutThr[i]) {
|
||||
/* early cut range */
|
||||
gain = fMult((level - drcComp->earlyCutThr[i]), drcComp->earlyCutFac[i]);
|
||||
}
|
||||
else if (level < drcComp->maxCutThr[i]) {
|
||||
/* cut range */
|
||||
gain = fMult((level - drcComp->cutThr[i]), drcComp->cutFac[i]) - drcComp->maxEarlyCut[i];
|
||||
}
|
||||
else {
|
||||
/* max cut */
|
||||
gain = -drcComp->maxCut[i];
|
||||
}
|
||||
|
||||
/* choose time constant */
|
||||
lvl2smthlvl = level - drcComp->smoothLevel[i];
|
||||
if (gain < drcComp->smoothGain[i]) {
|
||||
/* attack */
|
||||
if (lvl2smthlvl > drcComp->attackThr[i]) {
|
||||
/* fast attack */
|
||||
alpha = drcComp->fastAttack[i];
|
||||
}
|
||||
else {
|
||||
/* slow attack */
|
||||
alpha = drcComp->slowAttack[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* release */
|
||||
if (lvl2smthlvl < -drcComp->decayThr[i]) {
|
||||
/* fast release */
|
||||
alpha = drcComp->fastDecay[i];
|
||||
}
|
||||
else {
|
||||
/* slow release */
|
||||
alpha = drcComp->slowDecay[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* smooth gain & level */
|
||||
if ((gain < drcComp->smoothGain[i]) || (drcComp->holdCnt[i] == 0)) { /* hold gain unless we have an attack or hold period is over */
|
||||
FIXP_DBL accu;
|
||||
|
||||
/* drcComp->smoothLevel[i] = (1-alpha) * drcComp->smoothLevel[i] + alpha * level; */
|
||||
accu = fMult((FL2FXCONST_DBL(1.f)-alpha), drcComp->smoothLevel[i]);
|
||||
accu += fMult(alpha,level);
|
||||
drcComp->smoothLevel[i] = accu;
|
||||
|
||||
/* drcComp->smoothGain[i] = (1-alpha) * drcComp->smoothGain[i] + alpha * gain; */
|
||||
accu = fMult((FL2FXCONST_DBL(1.f)-alpha), drcComp->smoothGain[i]);
|
||||
accu += fMult(alpha,gain);
|
||||
drcComp->smoothGain[i] = accu;
|
||||
}
|
||||
|
||||
/* hold counter */
|
||||
if (drcComp->holdCnt[i]) {
|
||||
drcComp->holdCnt[i]--;
|
||||
}
|
||||
if (gain < drcComp->smoothGain[i]) {
|
||||
drcComp->holdCnt[i] = drcComp->holdOff[i];
|
||||
}
|
||||
} /* profile != DRC_NONE */
|
||||
} /* for i=1..2 */
|
||||
} else {
|
||||
/* no compression */
|
||||
drcComp->smoothGain[0] = FL2FXCONST_DBL(0.f);
|
||||
drcComp->smoothGain[1] = FL2FXCONST_DBL(0.f);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* limiter
|
||||
**************************************************************************/
|
||||
|
||||
/* find peak level */
|
||||
peak[0] = peak[1] = FL2FXCONST_DBL(0.f);
|
||||
for (i = 0; i < drcComp->blockLength; i++) {
|
||||
FIXP_DBL tmp;
|
||||
const INT_PCM* pSamples = &inSamples[i*drcComp->channels];
|
||||
INT_PCM maxSample = 0;
|
||||
|
||||
/* single channels */
|
||||
for (c = 0; c < (int)drcComp->channels; c++) {
|
||||
maxSample = FDKmax(maxSample, fAbs(pSamples[c]));
|
||||
}
|
||||
peak[0] = fixMax(peak[0], FX_PCM2FX_DBL(maxSample)>>DOWNMIX_SHIFT);
|
||||
|
||||
/* Lt/Rt downmix */
|
||||
if (drcComp->fullChannels > 2) {
|
||||
/* Lt */
|
||||
tmp = FL2FXCONST_DBL(0.f);
|
||||
|
||||
if (drcComp->channelIdx[LS] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[LS]])>>(DOWNMIX_SHIFT-1); /* Ls */
|
||||
if (drcComp->channelIdx[LS2] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]])>>(DOWNMIX_SHIFT-1); /* Ls2 */
|
||||
if (drcComp->channelIdx[RS] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[RS]])>>(DOWNMIX_SHIFT-1); /* Rs */
|
||||
if (drcComp->channelIdx[RS2] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]])>>(DOWNMIX_SHIFT-1); /* Rs2 */
|
||||
if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */
|
||||
if (drcComp->channelIdx[S] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]])>>(DOWNMIX_SHIFT-1); /* S */
|
||||
if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1); /* C */
|
||||
tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]])>>DOWNMIX_SHIFT); /* L */
|
||||
|
||||
peak[0] = fixMax(peak[0], fixp_abs(tmp));
|
||||
|
||||
/* Rt */
|
||||
tmp = FL2FXCONST_DBL(0.f);
|
||||
if (drcComp->channelIdx[LS] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[LS]])>>(DOWNMIX_SHIFT-1); /* Ls */
|
||||
if (drcComp->channelIdx[LS2] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]])>>(DOWNMIX_SHIFT-1); /* Ls2 */
|
||||
if (drcComp->channelIdx[RS] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[RS]])>>(DOWNMIX_SHIFT-1); /* Rs */
|
||||
if (drcComp->channelIdx[RS2] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]])>>(DOWNMIX_SHIFT-1); /* Rs2 */
|
||||
if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */
|
||||
if (drcComp->channelIdx[S] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]])>>(DOWNMIX_SHIFT-1); /* S */
|
||||
if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1); /* C */
|
||||
tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]])>>DOWNMIX_SHIFT); /* R */
|
||||
|
||||
peak[0] = fixMax(peak[0], fixp_abs(tmp));
|
||||
}
|
||||
|
||||
/* Lo/Ro downmix */
|
||||
if (drcComp->fullChannels > 2) {
|
||||
/* Lo */
|
||||
tmp = FL2FXCONST_DBL(0.f);
|
||||
if (drcComp->channelIdx[LS] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS]])>>(DOWNMIX_SHIFT-1); /* Ls */
|
||||
if (drcComp->channelIdx[LS2] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]])>>(DOWNMIX_SHIFT-1); /* Ls2 */
|
||||
if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */
|
||||
if (drcComp->channelIdx[S] >= 0) tmp += fMultDiv2(slev, fMult(FL2FXCONST_DBL(0.7f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]]))>>(DOWNMIX_SHIFT-1); /* S */
|
||||
if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1); /* C */
|
||||
tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]])>>DOWNMIX_SHIFT); /* L */
|
||||
|
||||
peak[0] = fixMax(peak[0], fixp_abs(tmp));
|
||||
|
||||
/* Ro */
|
||||
tmp = FL2FXCONST_DBL(0.f);
|
||||
if (drcComp->channelIdx[RS] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS]])>>(DOWNMIX_SHIFT-1); /* Rs */
|
||||
if (drcComp->channelIdx[RS2] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]])>>(DOWNMIX_SHIFT-1); /* Rs2 */
|
||||
if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */
|
||||
if (drcComp->channelIdx[S] >= 0) tmp += fMultDiv2(slev, fMult(FL2FXCONST_DBL(0.7f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]]))>>(DOWNMIX_SHIFT-1); /* S */
|
||||
if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1); /* C */
|
||||
tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]])>>DOWNMIX_SHIFT); /* R */
|
||||
|
||||
peak[0] = fixMax(peak[0], fixp_abs(tmp));
|
||||
}
|
||||
|
||||
peak[1] = fixMax(peak[0], peak[1]);
|
||||
|
||||
/* Mono Downmix - for comp_val only */
|
||||
if (drcComp->fullChannels > 1) {
|
||||
tmp = FL2FXCONST_DBL(0.f);
|
||||
if (drcComp->channelIdx[LS] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS]])>>(DOWNMIX_SHIFT-1); /* Ls */
|
||||
if (drcComp->channelIdx[LS2] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]])>>(DOWNMIX_SHIFT-1); /* Ls2 */
|
||||
if (drcComp->channelIdx[RS] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS]])>>(DOWNMIX_SHIFT-1); /* Rs */
|
||||
if (drcComp->channelIdx[RS2] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]])>>(DOWNMIX_SHIFT-1); /* Rs2 */
|
||||
if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */
|
||||
/*if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) tmp *=0.707f;*/ /* 7.1ch */
|
||||
if (drcComp->channelIdx[S] >= 0) tmp += fMultDiv2(slev, fMult(FL2FXCONST_DBL(0.7f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]]))>>(DOWNMIX_SHIFT-1); /* S */
|
||||
if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1); /* C */
|
||||
tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]])>>DOWNMIX_SHIFT); /* L */
|
||||
tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]])>>DOWNMIX_SHIFT); /* R */
|
||||
|
||||
peak[1] = fixMax(peak[1], fixp_abs(tmp));
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<2; i++) {
|
||||
FIXP_DBL tmp = drcComp->prevPeak[i];
|
||||
drcComp->prevPeak[i] = peak[i];
|
||||
peak[i] = fixMax(peak[i], tmp);
|
||||
|
||||
/*
|
||||
* Convert to dBFS, apply dialnorm
|
||||
*/
|
||||
/* descaled peak in ld64 representation */
|
||||
FIXP_DBL ld_peak = CalcLdData(peak[i]) + (FIXP_DBL)((LONG)DOWNMIX_SHIFT<<(DFRACT_BITS-1-LD_DATA_SHIFT));
|
||||
|
||||
/* if (peak < 1e-6) level = 1e-6f; */
|
||||
ld_peak = FDKmax(ld_peak, FL2FXCONST_DBL(-0.31143075889569022011284244651463f));
|
||||
|
||||
/* peak[i] = 20 * log(peak[i])/log(10) + 0.2f + (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS)
|
||||
* peak[i] = 20 * log(2)/log(10) * ld(peak[i]) + 0.2f + (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS)
|
||||
* peak[i] = 10 * 2*0.30102999566398119521373889472449 * ld(peak[i]) + 0.2f + (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS)
|
||||
*
|
||||
* additional scaling with METADATA_FRACT_BITS:
|
||||
* peak[i] = (10 * 2*0.30102999566398119521373889472449 * ld64(peak[i]) * 64 + 0.2f + (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS))*2^(-METADATA_FRACT_BITS)
|
||||
* peak[i] = 10*2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) * 2*0.30102999566398119521373889472449 * ld64(peak[i])
|
||||
* + 0.2f*2^(-METADATA_FRACT_BITS) + drcComp->smoothGain[i]
|
||||
*/
|
||||
peak[i] = fMult((FIXP_DBL)(10<<(METADATA_FRACT_BITS+LD_DATA_SHIFT)), fMult( FL2FX_DBL(2*0.30102999566398119521373889472449f), ld_peak));
|
||||
peak[i] += (FL2FX_DBL(0.2f)>>METADATA_INT_BITS); /* add a little bit headroom */
|
||||
peak[i] += drcComp->smoothGain[i];
|
||||
}
|
||||
|
||||
/* peak -= dialnorm + 31; */ /* this is Dolby style only */
|
||||
peak[0] -= (FIXP_DBL)((dialnorm-drc_TargetRefLevel)<<(METADATA_FRACT_BITS-16)); /* peak[0] -= dialnorm - drc_TargetRefLevel */
|
||||
|
||||
/* peak += 11; */ /* this is Dolby style only */ /* RF mode output is 11dB higher */
|
||||
/*peak += comp_TargetRefLevel - drc_TargetRefLevel;*/
|
||||
peak[1] -= (FIXP_DBL)((dialnorm-comp_TargetRefLevel)<<(METADATA_FRACT_BITS-16)); /* peak[1] -= dialnorm - comp_TargetRefLevel */
|
||||
|
||||
/* limiter gain */
|
||||
drcComp->limGain[0] += drcComp->limDecay; /* linear limiter release */
|
||||
drcComp->limGain[0] = fixMin(drcComp->limGain[0], -peak[0]);
|
||||
|
||||
drcComp->limGain[1] += 2*drcComp->limDecay; /* linear limiter release */
|
||||
drcComp->limGain[1] = fixMin(drcComp->limGain[1], -peak[1]);
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
/* apply limiting, return DRC gains*/
|
||||
{
|
||||
FIXP_DBL tmp;
|
||||
|
||||
tmp = drcComp->smoothGain[0];
|
||||
if (drcComp->limGain[0] < FL2FXCONST_DBL(0.f)) {
|
||||
tmp += drcComp->limGain[0];
|
||||
}
|
||||
*pDynrng = (LONG) scaleValue(tmp, -(METADATA_FRACT_BITS-16));
|
||||
|
||||
tmp = drcComp->smoothGain[1];
|
||||
if (drcComp->limGain[1] < FL2FXCONST_DBL(0.f)) {
|
||||
tmp += drcComp->limGain[1];
|
||||
}
|
||||
*pCompr = (LONG) scaleValue(tmp, -(METADATA_FRACT_BITS-16));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
DRC_PROFILE FDK_DRC_Generator_getDrcProfile(const HDRC_COMP drcComp)
|
||||
{
|
||||
return drcComp->profile[0];
|
||||
}
|
||||
|
||||
DRC_PROFILE FDK_DRC_Generator_getCompProfile(const HDRC_COMP drcComp)
|
||||
{
|
||||
return drcComp->profile[1];
|
||||
}
|
||||
|
||||
|
190
libAACenc/src/metadata_compressor.h
Normal file
190
libAACenc/src/metadata_compressor.h
Normal file
@ -0,0 +1,190 @@
|
||||
/********************** Fraunhofer IIS FDK AAC Encoder lib ******************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2011)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): M. Neusinger
|
||||
Description: Compressor for AAC Metadata Generator
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _METADATA_COMPRESSOR_H
|
||||
#define _METADATA_COMPRESSOR_H
|
||||
|
||||
|
||||
#include "FDK_audio.h"
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "aacenc.h"
|
||||
|
||||
|
||||
/**
|
||||
* DRC compression profiles.
|
||||
*/
|
||||
typedef enum DRC_PROFILE {
|
||||
DRC_NONE = 0,
|
||||
DRC_FILMSTANDARD = 1,
|
||||
DRC_FILMLIGHT = 2,
|
||||
DRC_MUSICSTANDARD = 3,
|
||||
DRC_MUSICLIGHT = 4,
|
||||
DRC_SPEECH = 5,
|
||||
DRC_DELAY_TEST = 6
|
||||
|
||||
} DRC_PROFILE;
|
||||
|
||||
|
||||
/**
|
||||
* DRC Compressor handle.
|
||||
*/
|
||||
typedef struct DRC_COMP DRC_COMP, *HDRC_COMP;
|
||||
|
||||
/**
|
||||
* \brief Open a DRC Compressor instance.
|
||||
*
|
||||
* Allocate memory for a compressor instance.
|
||||
*
|
||||
* \param phDrcComp A pointer to a compressor handle. Initialized on return.
|
||||
*
|
||||
* \return
|
||||
* - 0, on succes.
|
||||
* - unequal 0, on failure.
|
||||
*/
|
||||
INT FDK_DRC_Generator_Open(
|
||||
HDRC_COMP *phDrcComp
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Close the DRC Compressor instance.
|
||||
*
|
||||
* Deallocate instance and free whole memory.
|
||||
*
|
||||
* \param phDrcComp Pointer to the compressor handle to be deallocated.
|
||||
*
|
||||
* \return
|
||||
* - 0, on succes.
|
||||
* - unequal 0, on failure.
|
||||
*/
|
||||
INT FDK_DRC_Generator_Close(
|
||||
HDRC_COMP *phDrcComp
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Configure DRC Compressor.
|
||||
*
|
||||
* \param drcComp Compressor handle.
|
||||
* \param profileLine DRC profile for line mode.
|
||||
* \param profileRF DRC profile for RF mode.
|
||||
* \param blockLength Length of processing block in samples per channel.
|
||||
* \param sampleRate Sampling rate in Hz.
|
||||
* \param channelMode Channel configuration.
|
||||
* \param channelOrder Channel order, MPEG or WAV.
|
||||
* \param useWeighting Use weighting filter for loudness calculation
|
||||
*
|
||||
* \return
|
||||
* - 0, on success,
|
||||
* - unequal 0, on failure
|
||||
*/
|
||||
INT FDK_DRC_Generator_Initialize(
|
||||
HDRC_COMP drcComp,
|
||||
const DRC_PROFILE profileLine,
|
||||
const DRC_PROFILE profileRF,
|
||||
const INT blockLength,
|
||||
const UINT sampleRate,
|
||||
const CHANNEL_MODE channelMode,
|
||||
const CHANNEL_ORDER channelOrder,
|
||||
const UCHAR useWeighting
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Calculate DRC Compressor Gain.
|
||||
*
|
||||
* \param drcComp Compressor handle.
|
||||
* \param inSamples Pointer to interleaved input audio samples.
|
||||
* \param dialnorm Dialog Level in dB (typically -31...-1).
|
||||
* \param drc_TargetRefLevel
|
||||
* \param comp_TargetRefLevel
|
||||
* \param clev Downmix center mix factor (typically 0.707, 0.595 or 0.5)
|
||||
* \param slev Downmix surround mix factor (typically 0.707, 0.5, or 0)
|
||||
* \param dynrng Pointer to variable receiving line mode DRC gain in dB
|
||||
* \param compr Pointer to variable receiving RF mode DRC gain in dB
|
||||
*
|
||||
* \return
|
||||
* - 0, on success,
|
||||
* - unequal 0, on failure
|
||||
*/
|
||||
INT FDK_DRC_Generator_Calc(
|
||||
HDRC_COMP drcComp,
|
||||
const INT_PCM * const inSamples,
|
||||
const INT dialnorm,
|
||||
const INT drc_TargetRefLevel,
|
||||
const INT comp_TargetRefLevel,
|
||||
FIXP_DBL clev,
|
||||
FIXP_DBL slev,
|
||||
INT * const dynrng,
|
||||
INT * const compr
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Configure DRC Compressor Profile.
|
||||
*
|
||||
* \param drcComp Compressor handle.
|
||||
* \param profileLine DRC profile for line mode.
|
||||
* \param profileRF DRC profile for RF mode.
|
||||
*
|
||||
* \return
|
||||
* - 0, on success,
|
||||
* - unequal 0, on failure
|
||||
*/
|
||||
INT FDK_DRC_Generator_setDrcProfile(
|
||||
HDRC_COMP drcComp,
|
||||
const DRC_PROFILE profileLine,
|
||||
const DRC_PROFILE profileRF
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get DRC profile for line mode.
|
||||
*
|
||||
* \param drcComp Compressor handle.
|
||||
*
|
||||
* \return Current Profile.
|
||||
*/
|
||||
DRC_PROFILE FDK_DRC_Generator_getDrcProfile(
|
||||
const HDRC_COMP drcComp
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get DRC profile for RF mode.
|
||||
*
|
||||
* \param drcComp Compressor handle.
|
||||
*
|
||||
* \return Current Profile.
|
||||
*/
|
||||
DRC_PROFILE FDK_DRC_Generator_getCompProfile(
|
||||
const HDRC_COMP drcComp
|
||||
);
|
||||
|
||||
|
||||
#endif /* _METADATA_COMPRESSOR_H */
|
||||
|
809
libAACenc/src/metadata_main.cpp
Normal file
809
libAACenc/src/metadata_main.cpp
Normal file
@ -0,0 +1,809 @@
|
||||
/********************** Fraunhofer IIS FDK AAC Encoder lib ******************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2011)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): V. Bacigalupo
|
||||
Description: Metadata Encoder library interface functions
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#include "metadata_main.h"
|
||||
#include "metadata_compressor.h"
|
||||
#include "FDK_bitstream.h"
|
||||
#include "FDK_audio.h"
|
||||
#include "genericStds.h"
|
||||
|
||||
/*----------------- defines ----------------------*/
|
||||
#define MAX_DRC_BANDS (1<<4)
|
||||
#define MAX_DRC_CHANNELS (8)
|
||||
#define MAX_DRC_FRAMELEN (2*1024)
|
||||
|
||||
/*--------------- structure definitions --------------------*/
|
||||
|
||||
typedef struct AAC_METADATA
|
||||
{
|
||||
/* MPEG: Dynamic Range Control */
|
||||
struct {
|
||||
UCHAR prog_ref_level_present;
|
||||
SCHAR prog_ref_level;
|
||||
|
||||
UCHAR dyn_rng_sgn[MAX_DRC_BANDS];
|
||||
UCHAR dyn_rng_ctl[MAX_DRC_BANDS];
|
||||
|
||||
UCHAR drc_bands_present;
|
||||
UCHAR drc_band_incr;
|
||||
UCHAR drc_band_top[MAX_DRC_BANDS];
|
||||
UCHAR drc_interpolation_scheme;
|
||||
AACENC_METADATA_DRC_PROFILE drc_profile;
|
||||
INT drc_TargetRefLevel; /* used for Limiter */
|
||||
|
||||
/* excluded channels */
|
||||
UCHAR excluded_chns_present;
|
||||
UCHAR exclude_mask[2]; /* MAX_NUMBER_CHANNELS/8 */
|
||||
} mpegDrc;
|
||||
|
||||
/* ETSI: addtl ancillary data */
|
||||
struct {
|
||||
/* Heavy Compression */
|
||||
UCHAR compression_on; /* flag, if compression value should be written */
|
||||
UCHAR compression_value; /* compression value */
|
||||
AACENC_METADATA_DRC_PROFILE comp_profile;
|
||||
INT comp_TargetRefLevel; /* used for Limiter */
|
||||
INT timecode_coarse_status;
|
||||
INT timecode_fine_status;
|
||||
} etsiAncData;
|
||||
|
||||
SCHAR centerMixLevel; /* center downmix level (0...7, according to table) */
|
||||
SCHAR surroundMixLevel; /* surround downmix level (0...7, according to table) */
|
||||
UCHAR WritePCEMixDwnIdx; /* flag */
|
||||
UCHAR DmxLvl_On; /* flag */
|
||||
|
||||
UCHAR dolbySurroundMode;
|
||||
|
||||
UCHAR metadataMode; /* indicate meta data mode in current frame (delay line) */
|
||||
|
||||
} AAC_METADATA;
|
||||
|
||||
struct FDK_METADATA_ENCODER
|
||||
{
|
||||
INT metadataMode;
|
||||
HDRC_COMP hDrcComp;
|
||||
AACENC_MetaData submittedMetaData;
|
||||
|
||||
INT nAudioDataDelay;
|
||||
INT nMetaDataDelay;
|
||||
INT nChannels;
|
||||
|
||||
INT_PCM audioDelayBuffer[MAX_DRC_CHANNELS*MAX_DRC_FRAMELEN];
|
||||
int audioDelayIdx;
|
||||
|
||||
AAC_METADATA metaDataBuffer[3];
|
||||
int metaDataDelayIdx;
|
||||
|
||||
UCHAR drcInfoPayload[12];
|
||||
UCHAR drcDsePayload[8];
|
||||
|
||||
INT matrix_mixdown_idx;
|
||||
AACENC_EXT_PAYLOAD exPayload[2];
|
||||
INT nExtensions;
|
||||
|
||||
INT finalizeMetaData; /* Delay switch off by one frame and write default configuration to
|
||||
finalize the metadata setup. */
|
||||
};
|
||||
|
||||
|
||||
/*---------------- constants -----------------------*/
|
||||
static const AACENC_MetaData defaultMetaDataSetup = {
|
||||
AACENC_METADATA_DRC_NONE,
|
||||
AACENC_METADATA_DRC_NONE,
|
||||
-(31<<16),
|
||||
-(31<<16),
|
||||
0,
|
||||
-(31<<16),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
static const FIXP_DBL dmxTable[8] = {
|
||||
((FIXP_DBL)MAXVAL_DBL), FL2FXCONST_DBL(0.841f), FL2FXCONST_DBL(0.707f), FL2FXCONST_DBL(0.596f),
|
||||
FL2FXCONST_DBL(0.500f), FL2FXCONST_DBL(0.422f), FL2FXCONST_DBL(0.355f), FL2FXCONST_DBL(0.000f)
|
||||
};
|
||||
|
||||
static const UCHAR surmix2matrix_mixdown_idx[8] = {
|
||||
0, 0, 0, 1, 1, 2, 2, 3
|
||||
};
|
||||
|
||||
|
||||
/*--------------- function declarations --------------------*/
|
||||
static FDK_METADATA_ERROR WriteMetadataPayload(
|
||||
const HANDLE_FDK_METADATA_ENCODER hMetaData,
|
||||
const AAC_METADATA * const pMetadata
|
||||
);
|
||||
|
||||
static INT WriteDynamicRangeInfoPayload(
|
||||
const AAC_METADATA* const pMetadata,
|
||||
UCHAR* const pExtensionPayload
|
||||
);
|
||||
|
||||
static INT WriteEtsiAncillaryDataPayload(
|
||||
const AAC_METADATA* const pMetadata,
|
||||
UCHAR* const pExtensionPayload
|
||||
);
|
||||
|
||||
static FDK_METADATA_ERROR CompensateAudioDelay(
|
||||
HANDLE_FDK_METADATA_ENCODER hMetaDataEnc,
|
||||
INT_PCM * const pAudioSamples,
|
||||
const INT nAudioSamples
|
||||
);
|
||||
|
||||
static FDK_METADATA_ERROR LoadSubmittedMetadata(
|
||||
const AACENC_MetaData * const hMetadata,
|
||||
const INT nChannels,
|
||||
const INT metadataMode,
|
||||
AAC_METADATA * const pAacMetaData
|
||||
);
|
||||
|
||||
static FDK_METADATA_ERROR ProcessCompressor(
|
||||
AAC_METADATA *pMetadata,
|
||||
HDRC_COMP hDrcComp,
|
||||
const INT_PCM * const pSamples,
|
||||
const INT nSamples
|
||||
);
|
||||
|
||||
/*------------- function definitions ----------------*/
|
||||
|
||||
static DRC_PROFILE convertProfile(AACENC_METADATA_DRC_PROFILE aacProfile)
|
||||
{
|
||||
DRC_PROFILE drcProfile = DRC_NONE;
|
||||
|
||||
switch(aacProfile) {
|
||||
case AACENC_METADATA_DRC_NONE: drcProfile = DRC_NONE; break;
|
||||
case AACENC_METADATA_DRC_FILMSTANDARD: drcProfile = DRC_FILMSTANDARD; break;
|
||||
case AACENC_METADATA_DRC_FILMLIGHT: drcProfile = DRC_FILMLIGHT; break;
|
||||
case AACENC_METADATA_DRC_MUSICSTANDARD: drcProfile = DRC_MUSICSTANDARD; break;
|
||||
case AACENC_METADATA_DRC_MUSICLIGHT: drcProfile = DRC_MUSICLIGHT; break;
|
||||
case AACENC_METADATA_DRC_SPEECH: drcProfile = DRC_SPEECH; break;
|
||||
default: drcProfile = DRC_NONE; break;
|
||||
}
|
||||
return drcProfile;
|
||||
}
|
||||
|
||||
|
||||
/* convert dialog normalization to program reference level */
|
||||
/* NOTE: this only is correct, if the decoder target level is set to -31dB for line mode / -20dB for RF mode */
|
||||
static UCHAR dialnorm2progreflvl(const INT d)
|
||||
{
|
||||
return ((UCHAR)FDKmax(0, FDKmin((-d + (1<<13)) >> 14, 127)));
|
||||
}
|
||||
|
||||
/* convert program reference level to dialog normalization */
|
||||
static INT progreflvl2dialnorm(const UCHAR p)
|
||||
{
|
||||
return -((INT)(p<<(16-2)));
|
||||
}
|
||||
|
||||
/* encode downmix levels to Downmixing_levels_MPEG4 */
|
||||
static SCHAR encodeDmxLvls(const SCHAR cmixlev, const SCHAR surmixlev)
|
||||
{
|
||||
SCHAR dmxLvls = 0;
|
||||
dmxLvls |= 0x80 | (cmixlev << 4); /* center_mix_level_on */
|
||||
dmxLvls |= 0x08 | surmixlev; /* surround_mix_level_on */
|
||||
|
||||
return dmxLvls;
|
||||
}
|
||||
|
||||
/* encode AAC DRC gain (ISO/IEC 14496-3:2005 4.5.2.7) */
|
||||
static void encodeDynrng(INT gain, UCHAR* const dyn_rng_ctl, UCHAR* const dyn_rng_sgn )
|
||||
{
|
||||
if(gain < 0)
|
||||
{
|
||||
*dyn_rng_sgn = 1;
|
||||
gain = -gain;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dyn_rng_sgn = 0;
|
||||
}
|
||||
gain = FDKmin(gain,(127<<14));
|
||||
|
||||
*dyn_rng_ctl = (UCHAR)((gain + (1<<13)) >> 14);
|
||||
}
|
||||
|
||||
/* decode AAC DRC gain (ISO/IEC 14496-3:2005 4.5.2.7) */
|
||||
static INT decodeDynrng(const UCHAR dyn_rng_ctl, const UCHAR dyn_rng_sgn)
|
||||
{
|
||||
INT tmp = ((INT)dyn_rng_ctl << (16-2));
|
||||
if (dyn_rng_sgn) tmp = -tmp;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* encode AAC compression value (ETSI TS 101 154 page 99) */
|
||||
static UCHAR encodeCompr(INT gain)
|
||||
{
|
||||
UCHAR x, y;
|
||||
INT tmp;
|
||||
|
||||
/* tmp = (int)((48.164f - gain) / 6.0206f * 15 + 0.5f); */
|
||||
tmp = ((3156476 - gain) * 15 + 197283) / 394566;
|
||||
|
||||
if (tmp >= 240) {
|
||||
return 0xFF;
|
||||
}
|
||||
else if (tmp < 0) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
x = tmp / 15;
|
||||
y = tmp % 15;
|
||||
}
|
||||
|
||||
return (x << 4) | y;
|
||||
}
|
||||
|
||||
/* decode AAC compression value (ETSI TS 101 154 page 99) */
|
||||
static INT decodeCompr(const UCHAR compr)
|
||||
{
|
||||
INT gain;
|
||||
SCHAR x = compr >> 4; /* 4 MSB of compr */
|
||||
UCHAR y = (compr & 0x0F); /* 4 LSB of compr */
|
||||
|
||||
/* gain = (INT)((48.164f - 6.0206f * x - 0.4014f * y) ); */
|
||||
gain = (INT)( scaleValue(((LONG)FL2FXCONST_DBL(6.0206f/128.f)*(8-x) - (LONG)FL2FXCONST_DBL(0.4014f/128.f)*y), -(DFRACT_BITS-1-7-16)) );
|
||||
|
||||
return gain;
|
||||
}
|
||||
|
||||
|
||||
FDK_METADATA_ERROR FDK_MetadataEnc_Open(
|
||||
HANDLE_FDK_METADATA_ENCODER *phMetaData
|
||||
)
|
||||
{
|
||||
FDK_METADATA_ERROR err = METADATA_OK;
|
||||
HANDLE_FDK_METADATA_ENCODER hMetaData = NULL;
|
||||
|
||||
if (phMetaData == NULL) {
|
||||
err = METADATA_INVALID_HANDLE;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* allocate memory */
|
||||
hMetaData = (HANDLE_FDK_METADATA_ENCODER) FDKcalloc(1, sizeof(FDK_METADATA_ENCODER) );
|
||||
|
||||
if (hMetaData == NULL) {
|
||||
err = METADATA_MEMORY_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
FDKmemclear(hMetaData, sizeof(FDK_METADATA_ENCODER));
|
||||
|
||||
/* Allocate DRC Compressor. */
|
||||
if (FDK_DRC_Generator_Open(&hMetaData->hDrcComp)!=0) {
|
||||
err = METADATA_MEMORY_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Return metadata instance */
|
||||
*phMetaData = hMetaData;
|
||||
|
||||
return err;
|
||||
|
||||
bail:
|
||||
FDK_MetadataEnc_Close(&hMetaData);
|
||||
return err;
|
||||
}
|
||||
|
||||
FDK_METADATA_ERROR FDK_MetadataEnc_Close(
|
||||
HANDLE_FDK_METADATA_ENCODER *phMetaData
|
||||
)
|
||||
{
|
||||
FDK_METADATA_ERROR err = METADATA_OK;
|
||||
|
||||
if (phMetaData == NULL) {
|
||||
err = METADATA_INVALID_HANDLE;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (*phMetaData != NULL) {
|
||||
FDK_DRC_Generator_Close(&(*phMetaData)->hDrcComp);
|
||||
FDKfree(*phMetaData);
|
||||
*phMetaData = NULL;
|
||||
}
|
||||
bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
FDK_METADATA_ERROR FDK_MetadataEnc_Init(
|
||||
HANDLE_FDK_METADATA_ENCODER hMetaData,
|
||||
const INT resetStates,
|
||||
const INT metadataMode,
|
||||
const INT audioDelay,
|
||||
const UINT frameLength,
|
||||
const UINT sampleRate,
|
||||
const UINT nChannels,
|
||||
const CHANNEL_MODE channelMode,
|
||||
const CHANNEL_ORDER channelOrder
|
||||
)
|
||||
{
|
||||
FDK_METADATA_ERROR err = METADATA_OK;
|
||||
int i, nFrames, delay;
|
||||
|
||||
if (hMetaData==NULL) {
|
||||
err = METADATA_INVALID_HANDLE;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Determine values for delay compensation. */
|
||||
for (nFrames=0, delay=audioDelay-frameLength; delay>0; delay-=frameLength, nFrames++);
|
||||
|
||||
if ( (hMetaData->nChannels>MAX_DRC_CHANNELS) || ((-delay)>MAX_DRC_FRAMELEN) ) {
|
||||
err = METADATA_INIT_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Initialize with default setup. */
|
||||
FDKmemcpy(&hMetaData->submittedMetaData, &defaultMetaDataSetup, sizeof(AACENC_MetaData));
|
||||
|
||||
hMetaData->finalizeMetaData = 0; /* finalize meta data only while on/off switching, else disabled */
|
||||
|
||||
/* Reset delay lines. */
|
||||
if ( resetStates || (hMetaData->nAudioDataDelay!=-delay) || (hMetaData->nChannels!=(INT)nChannels) )
|
||||
{
|
||||
FDKmemclear(hMetaData->audioDelayBuffer, sizeof(hMetaData->audioDelayBuffer));
|
||||
FDKmemclear(hMetaData->metaDataBuffer, sizeof(hMetaData->metaDataBuffer));
|
||||
hMetaData->audioDelayIdx = 0;
|
||||
hMetaData->metaDataDelayIdx = 0;
|
||||
}
|
||||
else {
|
||||
/* Enable meta data. */
|
||||
if ( (hMetaData->metadataMode==0) && (metadataMode!=0) ) {
|
||||
/* disable meta data in all delay lines */
|
||||
for (i=0; i<(int)(sizeof(hMetaData->metaDataBuffer)/sizeof(AAC_METADATA)); i++) {
|
||||
LoadSubmittedMetadata(&hMetaData->submittedMetaData, nChannels, 0, &hMetaData->metaDataBuffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable meta data.*/
|
||||
if ( (hMetaData->metadataMode!=0) && (metadataMode==0) ) {
|
||||
hMetaData->finalizeMetaData = hMetaData->metadataMode;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize delay. */
|
||||
hMetaData->nAudioDataDelay = -delay;
|
||||
hMetaData->nMetaDataDelay = nFrames;
|
||||
hMetaData->nChannels = nChannels;
|
||||
hMetaData->metadataMode = metadataMode;
|
||||
|
||||
/* Initialize compressor. */
|
||||
if (metadataMode != 0) {
|
||||
if ( FDK_DRC_Generator_Initialize(
|
||||
hMetaData->hDrcComp,
|
||||
DRC_NONE,
|
||||
DRC_NONE,
|
||||
frameLength,
|
||||
sampleRate,
|
||||
channelMode,
|
||||
channelOrder,
|
||||
1) != 0)
|
||||
{
|
||||
err = METADATA_INIT_ERROR;
|
||||
}
|
||||
}
|
||||
bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
static FDK_METADATA_ERROR ProcessCompressor(
|
||||
AAC_METADATA *pMetadata,
|
||||
HDRC_COMP hDrcComp,
|
||||
const INT_PCM * const pSamples,
|
||||
const INT nSamples
|
||||
)
|
||||
{
|
||||
FDK_METADATA_ERROR err = METADATA_OK;
|
||||
|
||||
INT dynrng, compr;
|
||||
DRC_PROFILE profileDrc = convertProfile(pMetadata->mpegDrc.drc_profile);
|
||||
DRC_PROFILE profileComp = convertProfile(pMetadata->etsiAncData.comp_profile);
|
||||
|
||||
if ( (pMetadata==NULL) || (hDrcComp==NULL) ) {
|
||||
err = METADATA_INVALID_HANDLE;
|
||||
return err;
|
||||
}
|
||||
|
||||
/* first, check if profile is same as last frame
|
||||
* otherwise, update setup */
|
||||
if ( (profileDrc != FDK_DRC_Generator_getDrcProfile(hDrcComp))
|
||||
|| (profileComp != FDK_DRC_Generator_getCompProfile(hDrcComp)) )
|
||||
{
|
||||
FDK_DRC_Generator_setDrcProfile(hDrcComp, profileDrc, profileComp);
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
if (profileComp == DRC_NONE) {
|
||||
pMetadata->etsiAncData.compression_value = 0x80; /* to ensure no external values will be written if not configured */
|
||||
}
|
||||
|
||||
/* in case of embedding external values, copy this now (limiter may overwrite them) */
|
||||
dynrng = decodeDynrng(pMetadata->mpegDrc.dyn_rng_ctl[0], pMetadata->mpegDrc.dyn_rng_sgn[0]);
|
||||
compr = decodeCompr(pMetadata->etsiAncData.compression_value);
|
||||
|
||||
/* Call compressor */
|
||||
if (FDK_DRC_Generator_Calc(hDrcComp,
|
||||
pSamples,
|
||||
progreflvl2dialnorm(pMetadata->mpegDrc.prog_ref_level),
|
||||
pMetadata->mpegDrc.drc_TargetRefLevel,
|
||||
pMetadata->etsiAncData.comp_TargetRefLevel,
|
||||
dmxTable[pMetadata->centerMixLevel],
|
||||
dmxTable[pMetadata->surroundMixLevel],
|
||||
&dynrng,
|
||||
&compr) != 0)
|
||||
{
|
||||
err = METADATA_ENCODE_ERROR;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Write DRC values */
|
||||
pMetadata->mpegDrc.drc_band_incr = 0;
|
||||
encodeDynrng(dynrng, pMetadata->mpegDrc.dyn_rng_ctl, pMetadata->mpegDrc.dyn_rng_sgn);
|
||||
pMetadata->etsiAncData.compression_value = encodeCompr(compr);
|
||||
|
||||
bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
FDK_METADATA_ERROR FDK_MetadataEnc_Process(
|
||||
HANDLE_FDK_METADATA_ENCODER hMetaDataEnc,
|
||||
INT_PCM * const pAudioSamples,
|
||||
const INT nAudioSamples,
|
||||
const AACENC_MetaData * const pMetadata,
|
||||
AACENC_EXT_PAYLOAD ** ppMetaDataExtPayload,
|
||||
UINT * nMetaDataExtensions,
|
||||
INT * matrix_mixdown_idx
|
||||
)
|
||||
{
|
||||
FDK_METADATA_ERROR err = METADATA_OK;
|
||||
int metaDataDelayWriteIdx, metaDataDelayReadIdx, metadataMode;
|
||||
|
||||
/* Where to write new meta data info */
|
||||
metaDataDelayWriteIdx = hMetaDataEnc->metaDataDelayIdx;
|
||||
|
||||
/* How to write the data */
|
||||
metadataMode = hMetaDataEnc->metadataMode;
|
||||
|
||||
/* Compensate meta data delay. */
|
||||
hMetaDataEnc->metaDataDelayIdx++;
|
||||
if (hMetaDataEnc->metaDataDelayIdx > hMetaDataEnc->nMetaDataDelay) hMetaDataEnc->metaDataDelayIdx = 0;
|
||||
|
||||
/* Where to read pending meta data info from. */
|
||||
metaDataDelayReadIdx = hMetaDataEnc->metaDataDelayIdx;
|
||||
|
||||
/* Submit new data if available. */
|
||||
if (pMetadata!=NULL) {
|
||||
FDKmemcpy(&hMetaDataEnc->submittedMetaData, pMetadata, sizeof(AACENC_MetaData));
|
||||
}
|
||||
|
||||
/* Write one additional frame with default configuration of meta data. Ensure defined behaviour on decoder side. */
|
||||
if ( (hMetaDataEnc->finalizeMetaData!=0) && (hMetaDataEnc->metadataMode==0)) {
|
||||
FDKmemcpy(&hMetaDataEnc->submittedMetaData, &defaultMetaDataSetup, sizeof(AACENC_MetaData));
|
||||
metadataMode = hMetaDataEnc->finalizeMetaData;
|
||||
hMetaDataEnc->finalizeMetaData = 0;
|
||||
}
|
||||
|
||||
/* Get last submitted data. */
|
||||
if ( (err = LoadSubmittedMetadata(
|
||||
&hMetaDataEnc->submittedMetaData,
|
||||
hMetaDataEnc->nChannels,
|
||||
metadataMode,
|
||||
&hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx])) != METADATA_OK )
|
||||
{
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Calculate compressor if necessary and updata meta data info */
|
||||
if (hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx].metadataMode != 0) {
|
||||
if ( (err = ProcessCompressor(
|
||||
&hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx],
|
||||
hMetaDataEnc->hDrcComp,
|
||||
pAudioSamples,
|
||||
nAudioSamples)) != METADATA_OK)
|
||||
{
|
||||
/* Get last submitted data again. */
|
||||
LoadSubmittedMetadata(
|
||||
&hMetaDataEnc->submittedMetaData,
|
||||
hMetaDataEnc->nChannels,
|
||||
metadataMode,
|
||||
&hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert Meta Data side info to bitstream data. */
|
||||
if ( (err = WriteMetadataPayload(hMetaDataEnc, &hMetaDataEnc->metaDataBuffer[metaDataDelayReadIdx])) != METADATA_OK ) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Assign meta data to output */
|
||||
*ppMetaDataExtPayload = hMetaDataEnc->exPayload;
|
||||
*nMetaDataExtensions = hMetaDataEnc->nExtensions;
|
||||
*matrix_mixdown_idx = hMetaDataEnc->matrix_mixdown_idx;
|
||||
|
||||
bail:
|
||||
/* Compensate audio delay, reset err status. */
|
||||
err = CompensateAudioDelay(hMetaDataEnc, pAudioSamples, nAudioSamples);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static FDK_METADATA_ERROR CompensateAudioDelay(
|
||||
HANDLE_FDK_METADATA_ENCODER hMetaDataEnc,
|
||||
INT_PCM * const pAudioSamples,
|
||||
const INT nAudioSamples
|
||||
)
|
||||
{
|
||||
FDK_METADATA_ERROR err = METADATA_OK;
|
||||
|
||||
if (hMetaDataEnc->nAudioDataDelay) {
|
||||
int i, delaySamples = hMetaDataEnc->nAudioDataDelay*hMetaDataEnc->nChannels;
|
||||
|
||||
for (i = 0; i < nAudioSamples; i++) {
|
||||
INT_PCM tmp = pAudioSamples[i];
|
||||
pAudioSamples[i] = hMetaDataEnc->audioDelayBuffer[hMetaDataEnc->audioDelayIdx];
|
||||
hMetaDataEnc->audioDelayBuffer[hMetaDataEnc->audioDelayIdx] = tmp;
|
||||
|
||||
hMetaDataEnc->audioDelayIdx++;
|
||||
if (hMetaDataEnc->audioDelayIdx >= delaySamples) hMetaDataEnc->audioDelayIdx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
|
||||
functionname: WriteMetadataPayload
|
||||
description: fills anc data and extension payload
|
||||
returns: Error status
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
static FDK_METADATA_ERROR WriteMetadataPayload(
|
||||
const HANDLE_FDK_METADATA_ENCODER hMetaData,
|
||||
const AAC_METADATA * const pMetadata
|
||||
)
|
||||
{
|
||||
FDK_METADATA_ERROR err = METADATA_OK;
|
||||
|
||||
if ( (hMetaData==NULL) || (pMetadata==NULL) ) {
|
||||
err = METADATA_INVALID_HANDLE;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
hMetaData->nExtensions = 0;
|
||||
hMetaData->matrix_mixdown_idx = -1;
|
||||
|
||||
/* AAC-DRC */
|
||||
if (pMetadata->metadataMode != 0)
|
||||
{
|
||||
hMetaData->exPayload[hMetaData->nExtensions].pData = hMetaData->drcInfoPayload;
|
||||
hMetaData->exPayload[hMetaData->nExtensions].dataType = EXT_DYNAMIC_RANGE;
|
||||
hMetaData->exPayload[hMetaData->nExtensions].associatedChElement = -1;
|
||||
|
||||
hMetaData->exPayload[hMetaData->nExtensions].dataSize =
|
||||
WriteDynamicRangeInfoPayload(pMetadata, hMetaData->exPayload[hMetaData->nExtensions].pData);
|
||||
|
||||
hMetaData->nExtensions++;
|
||||
|
||||
/* Matrix Mixdown Coefficient in PCE */
|
||||
if (pMetadata->WritePCEMixDwnIdx) {
|
||||
hMetaData->matrix_mixdown_idx = surmix2matrix_mixdown_idx[pMetadata->surroundMixLevel];
|
||||
}
|
||||
|
||||
/* ETSI TS 101 154 (DVB) - MPEG4 ancillary_data() */
|
||||
if (pMetadata->metadataMode == 2) /* MP4_METADATA_MPEG_ETSI */
|
||||
{
|
||||
hMetaData->exPayload[hMetaData->nExtensions].pData = hMetaData->drcDsePayload;
|
||||
hMetaData->exPayload[hMetaData->nExtensions].dataType = EXT_DATA_ELEMENT;
|
||||
hMetaData->exPayload[hMetaData->nExtensions].associatedChElement = -1;
|
||||
|
||||
hMetaData->exPayload[hMetaData->nExtensions].dataSize =
|
||||
WriteEtsiAncillaryDataPayload(pMetadata,hMetaData->exPayload[hMetaData->nExtensions].pData);
|
||||
|
||||
hMetaData->nExtensions++;
|
||||
} /* metadataMode == 2 */
|
||||
|
||||
} /* metadataMode != 0 */
|
||||
|
||||
bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
static INT WriteDynamicRangeInfoPayload(
|
||||
const AAC_METADATA* const pMetadata,
|
||||
UCHAR* const pExtensionPayload
|
||||
)
|
||||
{
|
||||
const INT pce_tag_present = 0; /* yet fixed setting! */
|
||||
const INT prog_ref_lev_res_bits = 0;
|
||||
INT i, drc_num_bands = 1;
|
||||
|
||||
FDK_BITSTREAM bsWriter;
|
||||
FDKinitBitStream(&bsWriter, pExtensionPayload, 16, 0, BS_WRITER);
|
||||
|
||||
/* dynamic_range_info() */
|
||||
FDKwriteBits(&bsWriter, pce_tag_present, 1); /* pce_tag_present */
|
||||
if (pce_tag_present) {
|
||||
FDKwriteBits(&bsWriter, 0x0, 4); /* pce_instance_tag */
|
||||
FDKwriteBits(&bsWriter, 0x0, 4); /* drc_tag_reserved_bits */
|
||||
}
|
||||
|
||||
/* Exclude channels */
|
||||
FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.excluded_chns_present) ? 1 : 0, 1); /* excluded_chns_present*/
|
||||
|
||||
/* Multiband DRC */
|
||||
FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.drc_bands_present) ? 1 : 0, 1); /* drc_bands_present */
|
||||
if (pMetadata->mpegDrc.drc_bands_present)
|
||||
{
|
||||
FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_band_incr, 4); /* drc_band_incr */
|
||||
FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_interpolation_scheme, 4); /* drc_interpolation_scheme */
|
||||
drc_num_bands += pMetadata->mpegDrc.drc_band_incr;
|
||||
for (i=0; i<drc_num_bands; i++) {
|
||||
FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_band_top[i], 8); /* drc_band_top */
|
||||
}
|
||||
}
|
||||
|
||||
/* Program Reference Level */
|
||||
FDKwriteBits(&bsWriter, pMetadata->mpegDrc.prog_ref_level_present, 1); /* prog_ref_level_present */
|
||||
if (pMetadata->mpegDrc.prog_ref_level_present)
|
||||
{
|
||||
FDKwriteBits(&bsWriter, pMetadata->mpegDrc.prog_ref_level, 7); /* prog_ref_level */
|
||||
FDKwriteBits(&bsWriter, prog_ref_lev_res_bits, 1); /* prog_ref_level_reserved_bits */
|
||||
}
|
||||
|
||||
/* DRC Values */
|
||||
for (i=0; i<drc_num_bands; i++) {
|
||||
FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.dyn_rng_sgn[i]) ? 1 : 0, 1); /* dyn_rng_sgn[ */
|
||||
FDKwriteBits(&bsWriter, pMetadata->mpegDrc.dyn_rng_ctl[i], 7); /* dyn_rng_ctl */
|
||||
}
|
||||
|
||||
/* return number of valid bits in extension payload. */
|
||||
return FDKgetValidBits(&bsWriter);
|
||||
}
|
||||
|
||||
static INT WriteEtsiAncillaryDataPayload(
|
||||
const AAC_METADATA* const pMetadata,
|
||||
UCHAR* const pExtensionPayload
|
||||
)
|
||||
{
|
||||
FDK_BITSTREAM bsWriter;
|
||||
FDKinitBitStream(&bsWriter, pExtensionPayload, 16, 0, BS_WRITER);
|
||||
|
||||
/* ancillary_data_sync */
|
||||
FDKwriteBits(&bsWriter, 0xBC, 8);
|
||||
|
||||
/* bs_info */
|
||||
FDKwriteBits(&bsWriter, 0x3, 2); /* mpeg_audio_type */
|
||||
FDKwriteBits(&bsWriter, pMetadata->dolbySurroundMode, 2); /* dolby_surround_mode */
|
||||
FDKwriteBits(&bsWriter, 0x0, 4); /* reserved */
|
||||
|
||||
/* ancillary_data_status */
|
||||
FDKwriteBits(&bsWriter, 0, 3); /* 3 bit Reserved, set to "0" */
|
||||
FDKwriteBits(&bsWriter, (pMetadata->DmxLvl_On) ? 1 : 0, 1); /* downmixing_levels_MPEG4_status */
|
||||
FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */
|
||||
FDKwriteBits(&bsWriter, (pMetadata->etsiAncData.compression_on) ? 1 : 0, 1); /* audio_coding_mode_and_compression status */
|
||||
FDKwriteBits(&bsWriter, (pMetadata->etsiAncData.timecode_coarse_status) ? 1 : 0, 1); /* coarse_grain_timecode_status */
|
||||
FDKwriteBits(&bsWriter, (pMetadata->etsiAncData.timecode_fine_status) ? 1 : 0, 1); /* fine_grain_timecode_status */
|
||||
|
||||
/* downmixing_levels_MPEG4_status */
|
||||
if (pMetadata->DmxLvl_On) {
|
||||
FDKwriteBits(&bsWriter, encodeDmxLvls(pMetadata->centerMixLevel, pMetadata->surroundMixLevel), 8);
|
||||
}
|
||||
|
||||
/* audio_coding_mode_and_compression_status */
|
||||
if (pMetadata->etsiAncData.compression_on) {
|
||||
FDKwriteBits(&bsWriter, 0x01, 8); /* audio coding mode */
|
||||
FDKwriteBits(&bsWriter, pMetadata->etsiAncData.compression_value, 8); /* compression value */
|
||||
}
|
||||
|
||||
/* grain-timecode coarse/fine */
|
||||
if (pMetadata->etsiAncData.timecode_coarse_status) {
|
||||
FDKwriteBits(&bsWriter, 0x0, 16); /* not yet supported */
|
||||
}
|
||||
|
||||
if (pMetadata->etsiAncData.timecode_fine_status) {
|
||||
FDKwriteBits(&bsWriter, 0x0, 16); /* not yet supported */
|
||||
}
|
||||
|
||||
return FDKgetValidBits(&bsWriter);
|
||||
}
|
||||
|
||||
|
||||
static FDK_METADATA_ERROR LoadSubmittedMetadata(
|
||||
const AACENC_MetaData * const hMetadata,
|
||||
const INT nChannels,
|
||||
const INT metadataMode,
|
||||
AAC_METADATA * const pAacMetaData
|
||||
)
|
||||
{
|
||||
FDK_METADATA_ERROR err = METADATA_OK;
|
||||
|
||||
if (pAacMetaData==NULL) {
|
||||
err = METADATA_INVALID_HANDLE;
|
||||
}
|
||||
else {
|
||||
/* init struct */
|
||||
FDKmemclear(pAacMetaData, sizeof(AAC_METADATA));
|
||||
|
||||
if (hMetadata!=NULL) {
|
||||
/* convert data */
|
||||
pAacMetaData->mpegDrc.drc_profile = hMetadata->drc_profile;
|
||||
pAacMetaData->etsiAncData.comp_profile = hMetadata->comp_profile;
|
||||
pAacMetaData->mpegDrc.drc_TargetRefLevel = hMetadata->drc_TargetRefLevel;
|
||||
pAacMetaData->etsiAncData.comp_TargetRefLevel= hMetadata->comp_TargetRefLevel;
|
||||
pAacMetaData->mpegDrc.prog_ref_level_present = hMetadata->prog_ref_level_present;
|
||||
pAacMetaData->mpegDrc.prog_ref_level = dialnorm2progreflvl(hMetadata->prog_ref_level);
|
||||
|
||||
pAacMetaData->centerMixLevel = hMetadata->centerMixLevel;
|
||||
pAacMetaData->surroundMixLevel = hMetadata->surroundMixLevel;
|
||||
pAacMetaData->WritePCEMixDwnIdx = hMetadata->PCE_mixdown_idx_present;
|
||||
pAacMetaData->DmxLvl_On = hMetadata->ETSI_DmxLvl_present;
|
||||
|
||||
pAacMetaData->etsiAncData.compression_on = 1;
|
||||
|
||||
|
||||
if (nChannels == 2) {
|
||||
pAacMetaData->dolbySurroundMode = hMetadata->dolbySurroundMode; /* dolby_surround_mode */
|
||||
} else {
|
||||
pAacMetaData->dolbySurroundMode = 0;
|
||||
}
|
||||
|
||||
pAacMetaData->etsiAncData.timecode_coarse_status = 0; /* not yet supported - attention: Update GetEstMetadataBytesPerFrame() if enable this! */
|
||||
pAacMetaData->etsiAncData.timecode_fine_status = 0; /* not yet supported - attention: Update GetEstMetadataBytesPerFrame() if enable this! */
|
||||
|
||||
pAacMetaData->metadataMode = metadataMode;
|
||||
}
|
||||
else {
|
||||
pAacMetaData->metadataMode = 0; /* there is no configuration available */
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
INT FDK_MetadataEnc_GetDelay(
|
||||
HANDLE_FDK_METADATA_ENCODER hMetadataEnc
|
||||
)
|
||||
{
|
||||
INT delay = 0;
|
||||
|
||||
if (hMetadataEnc!=NULL) {
|
||||
delay = hMetadataEnc->nAudioDataDelay;
|
||||
}
|
||||
|
||||
return delay;
|
||||
}
|
||||
|
||||
|
161
libAACenc/src/metadata_main.h
Normal file
161
libAACenc/src/metadata_main.h
Normal file
@ -0,0 +1,161 @@
|
||||
/********************** Fraunhofer IIS FDK AAC Encoder lib ******************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2011)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
$Id$
|
||||
Author(s): V. Bacigalupo
|
||||
Description: Metadata Encoder library interface functions
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef _METADATA_MAIN_H
|
||||
#define _METADATA_MAIN_H
|
||||
|
||||
|
||||
/* Includes ******************************************************************/
|
||||
#include "aacenc_lib.h"
|
||||
#include "aacenc.h"
|
||||
|
||||
|
||||
/* Defines *******************************************************************/
|
||||
|
||||
/* Data Types ****************************************************************/
|
||||
|
||||
typedef enum {
|
||||
METADATA_OK = 0x0000, /*!< No error happened. All fine. */
|
||||
METADATA_INVALID_HANDLE = 0x0020, /*!< Handle passed to function call was invalid. */
|
||||
METADATA_MEMORY_ERROR = 0x0021, /*!< Memory allocation failed. */
|
||||
METADATA_INIT_ERROR = 0x0040, /*!< General initialization error. */
|
||||
METADATA_ENCODE_ERROR = 0x0060 /*!< The encoding process was interrupted by an unexpected error. */
|
||||
|
||||
} FDK_METADATA_ERROR;
|
||||
|
||||
/**
|
||||
* Meta Data handle.
|
||||
*/
|
||||
typedef struct FDK_METADATA_ENCODER *HANDLE_FDK_METADATA_ENCODER;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Open a Meta Data instance.
|
||||
*
|
||||
* \param phMetadataEnc A pointer to a Meta Data handle to be allocated. Initialized on return.
|
||||
*
|
||||
* \return
|
||||
* - METADATA_OK, on succes.
|
||||
* - METADATA_INVALID_HANDLE, METADATA_MEMORY_ERROR, on failure.
|
||||
*/
|
||||
FDK_METADATA_ERROR FDK_MetadataEnc_Open(
|
||||
HANDLE_FDK_METADATA_ENCODER *phMetadataEnc
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialize a Meta Data instance.
|
||||
*
|
||||
* \param hMetadataEnc Meta Data handle.
|
||||
* \param resetStates Indication for full reset of all states.
|
||||
* \param metadataMode Configures metat data output format (0,1,2).
|
||||
* \param audioDelay Delay cause by the audio encoder.
|
||||
* \param frameLength Number of samples to be processes within one frame.
|
||||
* \param sampleRate Sampling rat in Hz of audio input signal.
|
||||
* \param nChannels Number of audio input channels.
|
||||
* \param channelMode Channel configuration which is used by the encoder.
|
||||
* \param channelOrder Channel order of the input data. (WAV, MPEG)
|
||||
*
|
||||
* \return
|
||||
* - METADATA_OK, on succes.
|
||||
* - METADATA_INVALID_HANDLE, METADATA_INIT_ERROR, on failure.
|
||||
*/
|
||||
FDK_METADATA_ERROR FDK_MetadataEnc_Init(
|
||||
HANDLE_FDK_METADATA_ENCODER hMetadataEnc,
|
||||
const INT resetStates,
|
||||
const INT metadataMode,
|
||||
const INT audioDelay,
|
||||
const UINT frameLength,
|
||||
const UINT sampleRate,
|
||||
const UINT nChannels,
|
||||
const CHANNEL_MODE channelMode,
|
||||
const CHANNEL_ORDER channelOrder
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate Meta Data processing.
|
||||
*
|
||||
* This function treats all step necessary for meta data processing.
|
||||
* - Receive new meta data and make usable.
|
||||
* - Calculate DRC compressor and extract meta data info.
|
||||
* - Make meta data available for extern use.
|
||||
* - Apply audio data and meta data delay compensation.
|
||||
*
|
||||
* \param hMetadataEnc Meta Data handle.
|
||||
* \param pAudioSamples Pointer to audio input data. Existing function overwrites audio data with delayed audio samples.
|
||||
* \param nAudioSamples Number of input audio samples to be prcessed.
|
||||
* \param pMetadata Pointer to Metat Data input.
|
||||
* \param ppMetaDataExtPayload Pointer to extension payload array. Filled on return.
|
||||
* \param nMetaDataExtensions Pointer to variable to describe number of available extension payloads. Filled on return.
|
||||
* \param matrix_mixdown_idx Pointer to variable for matrix mixdown coefficient. Filled on return.
|
||||
*
|
||||
* \return
|
||||
* - METADATA_OK, on succes.
|
||||
* - METADATA_INVALID_HANDLE, METADATA_ENCODE_ERROR, on failure.
|
||||
*/
|
||||
FDK_METADATA_ERROR FDK_MetadataEnc_Process(
|
||||
HANDLE_FDK_METADATA_ENCODER hMetadataEnc,
|
||||
INT_PCM * const pAudioSamples,
|
||||
const INT nAudioSamples,
|
||||
const AACENC_MetaData * const pMetadata,
|
||||
AACENC_EXT_PAYLOAD ** ppMetaDataExtPayload,
|
||||
UINT * nMetaDataExtensions,
|
||||
INT * matrix_mixdown_idx
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Close the Meta Data instance.
|
||||
*
|
||||
* Deallocate instance and free whole memory.
|
||||
*
|
||||
* \param phMetaData Pointer to the Meta Data handle to be deallocated.
|
||||
*
|
||||
* \return
|
||||
* - METADATA_OK, on succes.
|
||||
* - METADATA_INVALID_HANDLE, on failure.
|
||||
*/
|
||||
FDK_METADATA_ERROR FDK_MetadataEnc_Close(
|
||||
HANDLE_FDK_METADATA_ENCODER *phMetaData
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get Meta Data Encoder delay.
|
||||
*
|
||||
* \param hMetadataEnc Meta Data Encoder handle.
|
||||
*
|
||||
* \return Delay caused by Meta Data module.
|
||||
*/
|
||||
INT FDK_MetadataEnc_GetDelay(
|
||||
HANDLE_FDK_METADATA_ENCODER hMetadataEnc
|
||||
);
|
||||
|
||||
|
||||
#endif /* _METADATA_MAIN_H */
|
||||
|
189
libAACenc/src/ms_stereo.cpp
Normal file
189
libAACenc/src/ms_stereo.cpp
Normal file
@ -0,0 +1,189 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M.Werner
|
||||
contents/description: MS stereo processing
|
||||
|
||||
******************************************************************************/
|
||||
#include "ms_stereo.h"
|
||||
|
||||
#include "psy_const.h"
|
||||
|
||||
/* static const float scaleMinThres = 1.0f; */ /* 0.75f for 3db boost */
|
||||
|
||||
void FDKaacEnc_MsStereoProcessing(PSY_DATA *RESTRICT psyData[(2)],
|
||||
PSY_OUT_CHANNEL* psyOutChannel[2],
|
||||
const INT *isBook,
|
||||
INT *msDigest, /* output */
|
||||
INT *msMask, /* output */
|
||||
const INT sfbCnt,
|
||||
const INT sfbPerGroup,
|
||||
const INT maxSfbPerGroup,
|
||||
const INT *sfbOffset)
|
||||
{
|
||||
FIXP_DBL *sfbEnergyLeft = psyData[0]->sfbEnergy.Long; /* modified where msMask==1 */
|
||||
FIXP_DBL *sfbEnergyRight = psyData[1]->sfbEnergy.Long; /* modified where msMask==1 */
|
||||
const FIXP_DBL *sfbEnergyMid = psyData[0]->sfbEnergyMS.Long;
|
||||
const FIXP_DBL *sfbEnergySide = psyData[1]->sfbEnergyMS.Long;
|
||||
FIXP_DBL *sfbThresholdLeft = psyData[0]->sfbThreshold.Long; /* modified where msMask==1 */
|
||||
FIXP_DBL *sfbThresholdRight = psyData[1]->sfbThreshold.Long; /* modified where msMask==1 */
|
||||
|
||||
FIXP_DBL *sfbSpreadEnLeft = psyData[0]->sfbSpreadEnergy.Long;
|
||||
FIXP_DBL *sfbSpreadEnRight = psyData[1]->sfbSpreadEnergy.Long;
|
||||
|
||||
FIXP_DBL *sfbEnergyLeftLdData = psyOutChannel[0]->sfbEnergyLdData; /* modified where msMask==1 */
|
||||
FIXP_DBL *sfbEnergyRightLdData = psyOutChannel[1]->sfbEnergyLdData; /* modified where msMask==1 */
|
||||
FIXP_DBL *sfbEnergyMidLdData = psyData[0]->sfbEnergyMSLdData;
|
||||
FIXP_DBL *sfbEnergySideLdData = psyData[1]->sfbEnergyMSLdData;
|
||||
FIXP_DBL *sfbThresholdLeftLdData = psyOutChannel[0]->sfbThresholdLdData; /* modified where msMask==1 */
|
||||
FIXP_DBL *sfbThresholdRightLdData = psyOutChannel[1]->sfbThresholdLdData; /* modified where msMask==1 */
|
||||
|
||||
FIXP_DBL *mdctSpectrumLeft = psyData[0]->mdctSpectrum; /* modified where msMask==1 */
|
||||
FIXP_DBL *mdctSpectrumRight = psyData[1]->mdctSpectrum; /* modified where msMask==1 */
|
||||
|
||||
INT sfb,sfboffs, j; /* loop counters */
|
||||
FIXP_DBL pnlrLdData, pnmsLdData;
|
||||
FIXP_DBL minThresholdLdData;
|
||||
FIXP_DBL minThreshold;
|
||||
INT useMS;
|
||||
|
||||
INT msMaskTrueSomewhere = 0; /* to determine msDigest */
|
||||
INT numMsMaskFalse = 0; /* number of non-intensity bands where L/R coding is used */
|
||||
|
||||
for(sfb=0; sfb<sfbCnt; sfb+=sfbPerGroup) {
|
||||
for(sfboffs=0;sfboffs<maxSfbPerGroup;sfboffs++) {
|
||||
|
||||
if ( (isBook==NULL) ? 1 : (isBook[sfb+sfboffs] == 0) ) {
|
||||
FIXP_DBL tmp;
|
||||
|
||||
/*
|
||||
minThreshold=min(sfbThresholdLeft[sfb+sfboffs], sfbThresholdRight[sfb+sfboffs])*scaleMinThres;
|
||||
pnlr = (sfbThresholdLeft[sfb+sfboffs]/
|
||||
max(sfbEnergyLeft[sfb+sfboffs],sfbThresholdLeft[sfb+sfboffs]))*
|
||||
(sfbThresholdRight[sfb+sfboffs]/
|
||||
max(sfbEnergyRight[sfb+sfboffs],sfbThresholdRight[sfb+sfboffs]));
|
||||
pnms = (minThreshold/max(sfbEnergyMid[sfb+sfboffs],minThreshold))*
|
||||
(minThreshold/max(sfbEnergySide[sfb+sfboffs],minThreshold));
|
||||
useMS = (pnms > pnlr);
|
||||
*/
|
||||
|
||||
/* we assume that scaleMinThres == 1.0f and we can drop it */
|
||||
minThresholdLdData = fixMin(sfbThresholdLeftLdData[sfb+sfboffs], sfbThresholdRightLdData[sfb+sfboffs]);
|
||||
|
||||
/* pnlrLdData = sfbThresholdLeftLdData[sfb+sfboffs] -
|
||||
max(sfbEnergyLeftLdData[sfb+sfboffs], sfbThresholdLeftLdData[sfb+sfboffs]) +
|
||||
sfbThresholdRightLdData[sfb+sfboffs] -
|
||||
max(sfbEnergyRightLdData[sfb+sfboffs], sfbThresholdRightLdData[sfb+sfboffs]); */
|
||||
tmp = fixMax(sfbEnergyLeftLdData[sfb+sfboffs], sfbThresholdLeftLdData[sfb+sfboffs]);
|
||||
pnlrLdData = (sfbThresholdLeftLdData[sfb+sfboffs]>>1) - (tmp>>1);
|
||||
pnlrLdData = pnlrLdData + (sfbThresholdRightLdData[sfb+sfboffs]>>1);
|
||||
tmp = fixMax(sfbEnergyRightLdData[sfb+sfboffs], sfbThresholdRightLdData[sfb+sfboffs]);
|
||||
pnlrLdData = pnlrLdData - (tmp>>1);
|
||||
|
||||
/* pnmsLdData = minThresholdLdData - max(sfbEnergyMidLdData[sfb+sfboffs], minThresholdLdData) +
|
||||
minThresholdLdData - max(sfbEnergySideLdData[sfb+sfboffs], minThresholdLdData); */
|
||||
tmp = fixMax(sfbEnergyMidLdData[sfb+sfboffs], minThresholdLdData);
|
||||
pnmsLdData = minThresholdLdData - (tmp>>1);
|
||||
tmp = fixMax(sfbEnergySideLdData[sfb+sfboffs], minThresholdLdData);
|
||||
pnmsLdData = pnmsLdData - (tmp>>1);
|
||||
useMS = (pnmsLdData > (pnlrLdData));
|
||||
|
||||
|
||||
if (useMS) {
|
||||
msMask[sfb+sfboffs] = 1;
|
||||
msMaskTrueSomewhere = 1;
|
||||
for(j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
|
||||
FIXP_DBL specL, specR;
|
||||
specL = mdctSpectrumLeft[j]>>1;
|
||||
specR = mdctSpectrumRight[j]>>1;
|
||||
mdctSpectrumLeft[j] = specL + specR;
|
||||
mdctSpectrumRight[j] = specL - specR;
|
||||
}
|
||||
minThreshold = fixMin(sfbThresholdLeft[sfb+sfboffs], sfbThresholdRight[sfb+sfboffs]);
|
||||
sfbThresholdLeft[sfb+sfboffs] = sfbThresholdRight[sfb+sfboffs] = minThreshold;
|
||||
sfbThresholdLeftLdData[sfb+sfboffs] = sfbThresholdRightLdData[sfb+sfboffs] = minThresholdLdData;
|
||||
sfbEnergyLeft[sfb+sfboffs] = sfbEnergyMid[sfb+sfboffs];
|
||||
sfbEnergyRight[sfb+sfboffs] = sfbEnergySide[sfb+sfboffs];
|
||||
sfbEnergyLeftLdData[sfb+sfboffs] = sfbEnergyMidLdData[sfb+sfboffs];
|
||||
sfbEnergyRightLdData[sfb+sfboffs] = sfbEnergySideLdData[sfb+sfboffs];
|
||||
|
||||
sfbSpreadEnLeft[sfb+sfboffs] = sfbSpreadEnRight[sfb+sfboffs] =
|
||||
fixMin( sfbSpreadEnLeft[sfb+sfboffs],
|
||||
sfbSpreadEnRight[sfb+sfboffs] ) >> 1;
|
||||
|
||||
}
|
||||
else {
|
||||
msMask[sfb+sfboffs] = 0;
|
||||
numMsMaskFalse++;
|
||||
} /* useMS */
|
||||
} /* isBook */
|
||||
else {
|
||||
/* keep mDigest from IS module */
|
||||
if (msMask[sfb+sfboffs]) {
|
||||
msMaskTrueSomewhere = 1;
|
||||
}
|
||||
/* prohibit MS_MASK_ALL in combination with IS */
|
||||
numMsMaskFalse = 9;
|
||||
} /* isBook */
|
||||
} /* sfboffs */
|
||||
} /* sfb */
|
||||
|
||||
|
||||
if(msMaskTrueSomewhere == 1) {
|
||||
if ((numMsMaskFalse == 0) || ((numMsMaskFalse < maxSfbPerGroup) && (numMsMaskFalse < 9))) {
|
||||
*msDigest = SI_MS_MASK_ALL;
|
||||
/* loop through M/S bands; if msMask==0, set it to 1 and apply M/S */
|
||||
for (sfb = 0; sfb < sfbCnt; sfb += sfbPerGroup) {
|
||||
for (sfboffs = 0; sfboffs < maxSfbPerGroup; sfboffs++) {
|
||||
if (( (isBook == NULL) ? 1 : (isBook[sfb+sfboffs] == 0) ) && (msMask[sfb+sfboffs] == 0)) {
|
||||
msMask[sfb+sfboffs] = 1;
|
||||
/* apply M/S coding */
|
||||
for(j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
|
||||
FIXP_DBL specL, specR;
|
||||
specL = mdctSpectrumLeft[j]>>1;
|
||||
specR = mdctSpectrumRight[j]>>1;
|
||||
mdctSpectrumLeft[j] = specL + specR;
|
||||
mdctSpectrumRight[j] = specL - specR;
|
||||
}
|
||||
minThreshold = fixMin(sfbThresholdLeft[sfb+sfboffs], sfbThresholdRight[sfb+sfboffs]);
|
||||
sfbThresholdLeft[sfb+sfboffs] = sfbThresholdRight[sfb+sfboffs] = minThreshold;
|
||||
minThresholdLdData = fixMin(sfbThresholdLeftLdData[sfb+sfboffs], sfbThresholdRightLdData[sfb+sfboffs]);
|
||||
sfbThresholdLeftLdData[sfb+sfboffs] = sfbThresholdRightLdData[sfb+sfboffs] = minThresholdLdData;
|
||||
sfbEnergyLeft[sfb+sfboffs] = sfbEnergyMid[sfb+sfboffs];
|
||||
sfbEnergyRight[sfb+sfboffs] = sfbEnergySide[sfb+sfboffs];
|
||||
sfbEnergyLeftLdData[sfb+sfboffs] = sfbEnergyMidLdData[sfb+sfboffs];
|
||||
sfbEnergyRightLdData[sfb+sfboffs] = sfbEnergySideLdData[sfb+sfboffs];
|
||||
|
||||
sfbSpreadEnLeft[sfb+sfboffs] = sfbSpreadEnRight[sfb+sfboffs] =
|
||||
fixMin( sfbSpreadEnLeft[sfb+sfboffs],
|
||||
sfbSpreadEnRight[sfb+sfboffs] ) >> 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*msDigest = SI_MS_MASK_SOME;
|
||||
}
|
||||
} else {
|
||||
*msDigest = SI_MS_MASK_NONE;
|
||||
}
|
||||
}
|
44
libAACenc/src/ms_stereo.h
Normal file
44
libAACenc/src/ms_stereo.h
Normal file
@ -0,0 +1,44 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (1999)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
Initial author: M.Werner
|
||||
contents/description: MS stereo processing
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef __MS_STEREO_H__
|
||||
#define __MS_STEREO_H__
|
||||
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
void FDKaacEnc_MsStereoProcessing(PSY_DATA *RESTRICT psyData[(2)],
|
||||
PSY_OUT_CHANNEL* psyOutChannel[2],
|
||||
const INT *isBook,
|
||||
INT *msDigest, /* output */
|
||||
INT *msMask, /* output */
|
||||
const INT sfbCnt,
|
||||
const INT sfbPerGroup,
|
||||
const INT maxSfbPerGroup,
|
||||
const INT *sfbOffset);
|
||||
|
||||
#endif
|
170
libAACenc/src/noisedet.cpp
Normal file
170
libAACenc/src/noisedet.cpp
Normal file
@ -0,0 +1,170 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2001)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
|
||||
Initial author: M. Lohwasser
|
||||
contents/description: noisedet.c
|
||||
Routines for Noise Detection
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "noisedet.h"
|
||||
|
||||
#include "aacenc_pns.h"
|
||||
#include "pnsparam.h"
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
functionname: FDKaacEnc_fuzzyIsSmaller
|
||||
description: Fuzzy value calculation for "testVal is smaller than refVal"
|
||||
returns: fuzzy value
|
||||
input: test and ref Value,
|
||||
low and high Lim
|
||||
output: return fuzzy value
|
||||
|
||||
*****************************************************************************/
|
||||
static FIXP_SGL FDKaacEnc_fuzzyIsSmaller( FIXP_DBL testVal,
|
||||
FIXP_DBL refVal,
|
||||
FIXP_DBL loLim,
|
||||
FIXP_DBL hiLim )
|
||||
{
|
||||
if (refVal <= FL2FXCONST_DBL(0.0))
|
||||
return( FL2FXCONST_SGL(0.0f) );
|
||||
else if (testVal >= fMult((hiLim>>1)+(loLim>>1), refVal))
|
||||
return( FL2FXCONST_SGL(0.0f) );
|
||||
else return( (FIXP_SGL)MAXVAL_SGL );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
functionname: FDKaacEnc_noiseDetect
|
||||
description: detect tonal sfb's; two tests
|
||||
Powerdistribution:
|
||||
sfb splittet in four regions,
|
||||
compare the energy in all sections
|
||||
PsychTonality:
|
||||
compare tonality from chaosmeasure with reftonality
|
||||
returns:
|
||||
input: spectrum of one large mdct
|
||||
number of sfb's
|
||||
pointer to offset of sfb's
|
||||
pointer to noiseFuzzyMeasure (modified)
|
||||
noiseparams struct
|
||||
pointer to sfb energies
|
||||
pointer to tonality calculated in chaosmeasure
|
||||
output: noiseFuzzy Measure
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
void FDKaacEnc_noiseDetect(FIXP_DBL *RESTRICT mdctSpectrum,
|
||||
INT *RESTRICT sfbMaxScaleSpec,
|
||||
INT sfbActive,
|
||||
const INT *RESTRICT sfbOffset,
|
||||
FIXP_SGL *RESTRICT noiseFuzzyMeasure,
|
||||
NOISEPARAMS *np,
|
||||
FIXP_SGL *RESTRICT sfbtonality )
|
||||
|
||||
{
|
||||
int i, k, sfb, sfbWidth;
|
||||
FIXP_SGL fuzzy, fuzzyTotal;
|
||||
FIXP_DBL refVal, testVal;
|
||||
|
||||
#define ALL_SFB_TONAL 0
|
||||
#define ALL_SFB_NONTONAL 0
|
||||
|
||||
/***** Start detection phase *****/
|
||||
/* Start noise detection for each band based on a number of checks */
|
||||
for (sfb=0; sfb<sfbActive; sfb++) {
|
||||
|
||||
fuzzyTotal = (FIXP_SGL)MAXVAL_SGL;
|
||||
sfbWidth = sfbOffset[sfb+1] - sfbOffset[sfb];
|
||||
|
||||
/* Reset output for lower bands or too small bands */
|
||||
if (sfb < np->startSfb || sfbWidth < np->minSfbWidth) {
|
||||
noiseFuzzyMeasure[sfb] = FL2FXCONST_SGL(0.0f);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( (np->detectionAlgorithmFlags & USE_POWER_DISTRIBUTION) && (fuzzyTotal > FL2FXCONST_SGL(0.5f)) ) {
|
||||
FIXP_DBL fhelp1, fhelp2, fhelp3, fhelp4, maxVal, minVal;
|
||||
INT leadingBits = fixMax(0,(sfbMaxScaleSpec[sfb] - 3)); /* max sfbWidth = 96/4 ; 2^5=32 => 5/2 = 3 (spc*spc) */
|
||||
|
||||
/* check power distribution in four regions */
|
||||
fhelp1 = fhelp2 = fhelp3 = fhelp4 = FL2FXCONST_DBL(0.0f);
|
||||
k = sfbWidth >>2; /* Width of a quarter band */
|
||||
|
||||
for (i=sfbOffset[sfb]; i<sfbOffset[sfb]+k; i++) {
|
||||
fhelp1 = fPow2AddDiv2(fhelp1, mdctSpectrum[i]<<leadingBits);
|
||||
fhelp2 = fPow2AddDiv2(fhelp2, mdctSpectrum[i+k]<<leadingBits);
|
||||
fhelp3 = fPow2AddDiv2(fhelp3, mdctSpectrum[i+2*k]<<leadingBits);
|
||||
fhelp4 = fPow2AddDiv2(fhelp4, mdctSpectrum[i+3*k]<<leadingBits);
|
||||
}
|
||||
|
||||
/* get max into fhelp: */
|
||||
maxVal = fixMax(fhelp1, fhelp2);
|
||||
maxVal = fixMax(maxVal, fhelp3);
|
||||
maxVal = fixMax(maxVal, fhelp4);
|
||||
|
||||
/* get min into fhelp1: */
|
||||
minVal = fixMin(fhelp1, fhelp2);
|
||||
minVal = fixMin(minVal, fhelp3);
|
||||
minVal = fixMin(minVal, fhelp4);
|
||||
|
||||
/* Normalize min and max Val */
|
||||
leadingBits = CountLeadingBits(maxVal);
|
||||
testVal = maxVal << leadingBits;
|
||||
refVal = minVal << leadingBits;
|
||||
|
||||
/* calculate fuzzy value for power distribution */
|
||||
testVal = fMultDiv2(testVal, np->powDistPSDcurve[sfb]);
|
||||
|
||||
fuzzy = FDKaacEnc_fuzzyIsSmaller(testVal, /* 1/2 * maxValue * PSDcurve */
|
||||
refVal, /* 1 * minValue */
|
||||
FL2FXCONST_DBL(0.495), /* 1/2 * loLim (0.99f/2) */
|
||||
FL2FXCONST_DBL(0.505)); /* 1/2 * hiLim (1.01f/2) */
|
||||
|
||||
fuzzyTotal = fixMin(fuzzyTotal, fuzzy);
|
||||
}
|
||||
|
||||
if ( (np->detectionAlgorithmFlags & USE_PSYCH_TONALITY) && (fuzzyTotal > FL2FXCONST_SGL(0.5f)) ) {
|
||||
/* Detection with tonality-value of psych. acoustic (here: 1 is tonal!)*/
|
||||
|
||||
testVal = FX_SGL2FX_DBL(sfbtonality[sfb])>>1; /* 1/2 * sfbTonality */
|
||||
refVal = np->refTonality;
|
||||
|
||||
fuzzy = FDKaacEnc_fuzzyIsSmaller(testVal,
|
||||
refVal,
|
||||
FL2FXCONST_DBL(0.45f), /* 1/2 * loLim (0.9f/2) */
|
||||
FL2FXCONST_DBL(0.55f)); /* 1/2 * hiLim (1.1f/2) */
|
||||
|
||||
fuzzyTotal = fixMin(fuzzyTotal, fuzzy);
|
||||
}
|
||||
|
||||
|
||||
/* Output of final result */
|
||||
noiseFuzzyMeasure[sfb] = fuzzyTotal;
|
||||
}
|
||||
}
|
47
libAACenc/src/noisedet.h
Normal file
47
libAACenc/src/noisedet.h
Normal file
@ -0,0 +1,47 @@
|
||||
/******************************** MPEG Audio Encoder **************************
|
||||
|
||||
(C) Copyright Fraunhofer IIS (2001)
|
||||
All Rights Reserved
|
||||
|
||||
Please be advised that this software and/or program delivery is
|
||||
Confidential Information of Fraunhofer and subject to and covered by the
|
||||
|
||||
Fraunhofer IIS Software Evaluation Agreement
|
||||
between Google Inc. and Fraunhofer
|
||||
effective and in full force since March 1, 2012.
|
||||
|
||||
You may use this software and/or program only under the terms and
|
||||
conditions described in the above mentioned Fraunhofer IIS Software
|
||||
Evaluation Agreement. Any other and/or further use requires a separate agreement.
|
||||
|
||||
|
||||
This software and/or program is protected by copyright law and international
|
||||
treaties. Any reproduction or distribution of this software and/or program,
|
||||
or any portion of it, may result in severe civil and criminal penalties, and
|
||||
will be prosecuted to the maximum extent possible under law.
|
||||
|
||||
$Id$
|
||||
|
||||
Initial author: M. Lohwasser
|
||||
contents/description: noisedet.h
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __NOISEDET_H
|
||||
#define __NOISEDET_H
|
||||
|
||||
#include "common_fix.h"
|
||||
|
||||
#include "pnsparam.h"
|
||||
#include "psy_data.h"
|
||||
|
||||
|
||||
void FDKaacEnc_noiseDetect( FIXP_DBL *mdctSpectrum,
|
||||
INT *sfbMaxScaleSpec,
|
||||
INT sfbActive,
|
||||
const INT *sfbOffset,
|
||||
FIXP_SGL noiseFuzzyMeasure[],
|
||||
NOISEPARAMS *np,
|
||||
FIXP_SGL *sfbtonality );
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user