Fraunhofer AAC codec.

License boilerplate update to follow.

Change-Id: I2810460c11a58b6d148d84673cc031f3685e79b5
This commit is contained in:
Dave Burke 2012-04-17 09:51:45 -07:00
parent a37315fe10
commit 9bf37cc971
325 changed files with 110807 additions and 0 deletions

1
Android.mk Normal file
View File

@ -0,0 +1 @@
include $(call all-subdir-makefiles)

1
libAACdec/Android.mk Normal file
View File

@ -0,0 +1 @@
include $(call all-subdir-makefiles)

View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

125
libAACdec/src/aac_rom.h Normal file
View 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 */

View 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
View 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 */

View 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

File diff suppressed because it is too large Load Diff

View 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_ */

View 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);
}

View 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_ */

View 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_ */

File diff suppressed because it is too large Load Diff

View 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_ */

View 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) ;
}
}
}
}
}
}

View 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 */

View 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);
}
}

View 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

File diff suppressed because it is too large Load Diff

250
libAACdec/src/aacdecoder.h Normal file
View 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 */

View 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;
}

View 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
View 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
View 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
View 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
View 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 */

View 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
View 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

File diff suppressed because it is too large Load Diff

86
libAACdec/src/conceal.h Normal file
View 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_ */

View 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
View 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

View 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);
}

View 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

View 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 */

View 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
View 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

File diff suppressed because it is too large Load Diff

76
libAACdec/src/rvlc.h Normal file
View 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
View 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
View 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
View 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 */

View 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;
}
}
}
}

View 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
View 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
View 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
View File

@ -0,0 +1 @@
include $(call all-subdir-makefiles)

File diff suppressed because it is too large Load Diff

53
libAACenc/src/Android.mk Normal file
View 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)

View 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
View 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

File diff suppressed because it is too large Load Diff

141
libAACenc/src/aacEnc_rom.h Normal file
View 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
View 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
View 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_ */

View 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"

View 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

File diff suppressed because it is too large Load Diff

View 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;
}
}
}
}

View 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

File diff suppressed because it is too large Load Diff

135
libAACenc/src/aacenc_tns.h Normal file
View 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

File diff suppressed because it is too large Load Diff

79
libAACenc/src/adj_thr.h Normal file
View 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

View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

124
libAACenc/src/bit_cnt.h Normal file
View 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

File diff suppressed because it is too large Load Diff

120
libAACenc/src/bitenc.h Normal file
View 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 */

View 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;
}

View 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 */

View 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);
}
*/

View 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 */

View 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 );
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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];
}

View 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 */

View 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;
}

View 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
View 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
View 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
View 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
View 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