mirror of
https://github.com/mstorsjo/fdk-aac.git
synced 2025-02-12 01:20:38 +01:00
Bug: 71430241 Test: CTS DecoderTest and DecoderTestAacDrc original-Change-Id: Iaa20f749b8a04d553b20247cfe1a8930ebbabe30 Apply clang-format also on header files. original-Change-Id: I14de1ef16bbc79ec0283e745f98356a10efeb2e4 Fixes for MPEG-D DRC original-Change-Id: If1de2d74bbbac84b3f67de3b88b83f6a23b8a15c Catch unsupported tw_mdct at an early stage original-Change-Id: Ied9dd00d754162a0e3ca1ae3e6b854315d818afe Fixing PVC transition frames original-Change-Id: Ib75725abe39252806c32d71176308f2c03547a4e Move qmf bands sanity check original-Change-Id: Iab540c3013c174d9490d2ae100a4576f51d8dbc4 Initialize scaling variable original-Change-Id: I3c4087101b70e998c71c1689b122b0d7762e0f9e Add 16 qmf band configuration to getSlotNrgHQ() original-Change-Id: I49a5d30f703a1b126ff163df9656db2540df21f1 Always apply byte alignment at the end of the AudioMuxElement original-Change-Id: I42d560287506d65d4c3de8bfe3eb9a4ebeb4efc7 Setup SBR element only if no parse error exists original-Change-Id: I1915b73704bc80ab882b9173d6bec59cbd073676 Additional array index check in HCR original-Change-Id: I18cc6e501ea683b5009f1bbee26de8ddd04d8267 Fix fade-in index selection in concealment module original-Change-Id: Ibf802ed6ed8c05e9257e1f3b6d0ac1162e9b81c1 Enable explicit backward compatible parser for AAC_LD original-Change-Id: I27e9c678dcb5d40ed760a6d1e06609563d02482d Skip spatial specific config in explicit backward compatible ASC original-Change-Id: Iff7cc365561319e886090cedf30533f562ea4d6e Update flags description in decoder API original-Change-Id: I9a5b4f8da76bb652f5580cbd3ba9760425c43830 Add QMF domain reset function original-Change-Id: I4f89a8a2c0277d18103380134e4ed86996e9d8d6 DRC upgrade v2.1.0 original-Change-Id: I5731c0540139dab220094cd978ef42099fc45b74 Fix integer overflow in sqrtFixp_lookup() original-Change-Id: I429a6f0d19aa2cc957e0f181066f0ca73968c914 Fix integer overflow in invSqrtNorm2() original-Change-Id: I84de5cbf9fb3adeb611db203fe492fabf4eb6155 Fix integer overflow in GenerateRandomVector() original-Change-Id: I3118a641008bd9484d479e5b0b1ee2b5d7d44d74 Fix integer overflow in adjustTimeSlot_EldGrid() original-Change-Id: I29d503c247c5c8282349b79df940416a512fb9d5 Fix integer overflow in FDKsbrEnc_codeEnvelope() original-Change-Id: I6b34b61ebb9d525b0c651ed08de2befc1f801449 Follow-up on: Fix integer overflow in adjustTimeSlot_EldGrid() original-Change-Id: I6f8f578cc7089e5eb7c7b93e580b72ca35ad689a Fix integer overflow in get_pk_v2() original-Change-Id: I63375bed40d45867f6eeaa72b20b1f33e815938c Fix integer overflow in Syn_filt_zero() original-Change-Id: Ie0c02fdfbe03988f9d3b20d10cd9fe4c002d1279 Fix integer overflow in CFac_CalcFacSignal() original-Change-Id: Id2d767c40066c591b51768e978eb8af3b803f0c5 Fix integer overflow in FDKaacEnc_FDKaacEnc_calcPeNoAH() original-Change-Id: Idcbd0f4a51ae2550ed106aa6f3d678d1f9724841 Fix integer overflow in sbrDecoder_calculateGainVec() original-Change-Id: I7081bcbe29c5cede9821b38d93de07c7add2d507 Fix integer overflow in CLpc_SynthesisLattice() original-Change-Id: I4a95ddc18de150102352d4a1845f06094764c881 Fix integer overflow in Pred_Lt4() original-Change-Id: I4dbd012b2de7d07c3e70a47b92e3bfae8dbc750a Fix integer overflow in FDKsbrEnc_InitSbrFastTransientDetector() original-Change-Id: I788cbec1a4a00f44c2f3a72ad7a4afa219807d04 Fix unsigned integer overflow in FDKaacEnc_WriteBitstream() original-Change-Id: I68fc75166e7d2cd5cd45b18dbe3d8c2a92f1822a Fix unsigned integer overflow in FDK_MetadataEnc_Init() original-Change-Id: Ie8d025f9bcdb2442c704bd196e61065c03c10af4 Fix overflow in pseudo random number generators original-Change-Id: I3e2551ee01356297ca14e3788436ede80bd5513c Fix unsigned integer overflow in sbrDecoder_Parse() original-Change-Id: I3f231b2f437e9c37db4d5b964164686710eee971 Fix unsigned integer overflow in longsub() original-Change-Id: I73c2bc50415cac26f1f5a29e125bbe75f9180a6e Fix unsigned integer overflow in CAacDecoder_DecodeFrame() original-Change-Id: Ifce2db4b1454b46fa5f887e9d383f1cc43b291e4 Fix overflow at CLpdChannelStream_Read() original-Change-Id: Idb9d822ce3a4272e4794b643644f5434e2d4bf3f Fix unsigned integer overflow in Hcr_State_BODY_SIGN_ESC__ESC_WORD() original-Change-Id: I1ccf77c0015684b85534c5eb97162740a870b71c Fix unsigned integer overflow in UsacConfig_Parse() original-Change-Id: Ie6d27f84b6ae7eef092ecbff4447941c77864d9f Fix unsigned integer overflow in aacDecoder_drcParse() original-Change-Id: I713f28e883eea3d70b6fa56a7b8f8c22bcf66ca0 Fix unsigned integer overflow in aacDecoder_drcReadCompression() original-Change-Id: Ia34dfeb88c4705c558bce34314f584965cafcf7a Fix unsigned integer overflow in CDataStreamElement_Read() original-Change-Id: Iae896cc1d11f0a893d21be6aa90bd3e60a2c25f0 Fix unsigned integer overflow in transportDec_AdjustEndOfAccessUnit() original-Change-Id: I64cf29a153ee784bb4a16fdc088baabebc0007dc Fix unsigned integer overflow in transportDec_GetAuBitsRemaining() original-Change-Id: I975b3420faa9c16a041874ba0db82e92035962e4 Fix unsigned integer overflow in extractExtendedData() original-Change-Id: I2a59eb09e2053cfb58dfb75fcecfad6b85a80a8f Fix signed integer overflow in CAacDecoder_ExtPayloadParse() original-Change-Id: I4ad5ca4e3b83b5d964f1c2f8c5e7b17c477c7929 Fix unsigned integer overflow in CAacDecoder_DecodeFrame() original-Change-Id: I29a39df77d45c52a0c9c5c83c1ba81f8d0f25090 Follow-up on: Fix integer overflow in CLpc_SynthesisLattice() original-Change-Id: I8fb194ffc073a3432a380845be71036a272d388f Fix signed integer overflow in _interpolateDrcGain() original-Change-Id: I879ec9ab14005069a7c47faf80e8bc6e03d22e60 Fix unsigned integer overflow in FDKreadBits() original-Change-Id: I1f47a6a8037ff70375aa8844947d5681bb4287ad Fix unsigned integer overflow in FDKbyteAlign() original-Change-Id: Id5f3a11a0c9e50fc6f76ed6c572dbd4e9f2af766 Fix unsigned integer overflow in FDK_get32() original-Change-Id: I9d33b8e97e3d38cbb80629cb859266ca0acdce96 Fix unsigned integer overflow in FDK_pushBack() original-Change-Id: Ic87f899bc8c6acf7a377a8ca7f3ba74c3a1e1c19 Fix unsigned integer overflow in FDK_pushForward() original-Change-Id: I3b754382f6776a34be1602e66694ede8e0b8effc Fix unsigned integer overflow in ReadPsData() original-Change-Id: I25361664ba8139e32bbbef2ca8c106a606ce9c37 Fix signed integer overflow in E_UTIL_residu() original-Change-Id: I8c3abd1f437ee869caa8fb5903ce7d3d641b6aad REVERT: Follow-up on: Integer overflow in CLpc_SynthesisLattice(). original-Change-Id: I3d340099acb0414795c8dfbe6362bc0a8f045f9b Follow-up on: Fix integer overflow in CLpc_SynthesisLattice() original-Change-Id: I4aedb8b3a187064e9f4d985175aa55bb99cc7590 Follow-up on: Fix unsigned integer overflow in aacDecoder_drcParse() original-Change-Id: I2aa2e13916213bf52a67e8b0518e7bf7e57fb37d Fix integer overflow in acelp original-Change-Id: Ie6390c136d84055f8b728aefbe4ebef6e029dc77 Fix unsigned integer overflow in aacDecoder_UpdateBitStreamCounters() original-Change-Id: I391ffd97ddb0b2c184cba76139bfb356a3b4d2e2 Adjust concealment default settings original-Change-Id: I6a95db935a327c47df348030bcceafcb29f54b21 Saturate estimatedStartPos original-Change-Id: I27be2085e0ae83ec9501409f65e003f6bcba1ab6 Negative shift exponent in _interpolateDrcGain() original-Change-Id: I18edb26b26d002aafd5e633d4914960f7a359c29 Negative shift exponent in calculateICC() original-Change-Id: I3dcd2ae98d2eb70ee0d59750863cbb2a6f4f8aba Too large shift exponent in FDK_put() original-Change-Id: Ib7d9aaa434d2d8de4a13b720ca0464b31ca9b671 Too large shift exponent in CalcInvLdData() original-Change-Id: I43e6e78d4cd12daeb1dcd5d82d1798bdc2550262 Member access within null pointer of type SBR_CHANNEL original-Change-Id: Idc5e4ea8997810376d2f36bbdf628923b135b097 Member access within null pointer of type CpePersistentData original-Change-Id: Ib6c91cb0d37882768e5baf63324e429589de0d9d Member access within null pointer FDKaacEnc_psyMain() original-Change-Id: I7729b7f4479970531d9dc823abff63ca52e01997 Member access within null pointer FDKaacEnc_GetPnsParam() original-Change-Id: I9aa3b9f3456ae2e0f7483dbd5b3dde95fc62da39 Member access within null pointer FDKsbrEnc_EnvEncodeFrame() original-Change-Id: I67936f90ea714e90b3e81bc0dd1472cc713eb23a Add HCR sanity check original-Change-Id: I6c1d9732ebcf6af12f50b7641400752f74be39f7 Fix memory issue for HBE edge case with 8:3 SBR original-Change-Id: I11ea58a61e69fbe8bf75034b640baee3011e63e9 Additional SBR parametrization sanity check for ELD original-Change-Id: Ie26026fbfe174c2c7b3691f6218b5ce63e322140 Add MPEG-D DRC channel layout check original-Change-Id: Iea70a74f171b227cce636a9eac4ba662777a2f72 Additional out-of-bounds checks in MPEG-D DRC original-Change-Id: Ife4a8c3452c6fde8a0a09e941154a39a769777d4 Change-Id: Ic63cb2f628720f54fe9b572b0cb528e2599c624e
811 lines
32 KiB
C++
811 lines
32 KiB
C++
/* -----------------------------------------------------------------------------
|
|
Software License for The Fraunhofer FDK AAC Codec Library for Android
|
|
|
|
© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
|
|
Forschung e.V. All rights reserved.
|
|
|
|
1. INTRODUCTION
|
|
The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
|
|
that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
|
|
scheme for digital audio. This FDK AAC Codec software is intended to be used on
|
|
a wide variety of Android devices.
|
|
|
|
AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
|
|
general perceptual audio codecs. AAC-ELD is considered the best-performing
|
|
full-bandwidth communications codec by independent studies and is widely
|
|
deployed. AAC has been standardized by ISO and IEC as part of the MPEG
|
|
specifications.
|
|
|
|
Patent licenses for necessary patent claims for the FDK AAC Codec (including
|
|
those of Fraunhofer) may be obtained through Via Licensing
|
|
(www.vialicensing.com) or through the respective patent owners individually for
|
|
the purpose of encoding or decoding bit streams in products that are compliant
|
|
with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
|
|
Android devices already license these patent claims through Via Licensing or
|
|
directly from the patent owners, and therefore FDK AAC Codec software may
|
|
already be covered under those patent licenses when it is used for those
|
|
licensed purposes only.
|
|
|
|
Commercially-licensed AAC software libraries, including floating-point versions
|
|
with enhanced sound quality, are also available from Fraunhofer. Users are
|
|
encouraged to check the Fraunhofer website for additional applications
|
|
information and documentation.
|
|
|
|
2. COPYRIGHT LICENSE
|
|
|
|
Redistribution and use in source and binary forms, with or without modification,
|
|
are permitted without payment of copyright license fees provided that you
|
|
satisfy the following conditions:
|
|
|
|
You must retain the complete text of this software license in redistributions of
|
|
the FDK AAC Codec or your modifications thereto in source code form.
|
|
|
|
You must retain the complete text of this software license in the documentation
|
|
and/or other materials provided with redistributions of the FDK AAC Codec or
|
|
your modifications thereto in binary form. You must make available free of
|
|
charge copies of the complete source code of the FDK AAC Codec and your
|
|
modifications thereto to recipients of copies in binary form.
|
|
|
|
The name of Fraunhofer may not be used to endorse or promote products derived
|
|
from this library without prior written permission.
|
|
|
|
You may not charge copyright license fees for anyone to use, copy or distribute
|
|
the FDK AAC Codec software or your modifications thereto.
|
|
|
|
Your modified versions of the FDK AAC Codec must carry prominent notices stating
|
|
that you changed the software and the date of any change. For modified versions
|
|
of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
|
|
must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
|
|
AAC Codec Library for Android."
|
|
|
|
3. NO PATENT LICENSE
|
|
|
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
|
|
limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
|
|
Fraunhofer provides no warranty of patent non-infringement with respect to this
|
|
software.
|
|
|
|
You may use this FDK AAC Codec software or modifications thereto only for
|
|
purposes that are authorized by appropriate patent licenses.
|
|
|
|
4. DISCLAIMER
|
|
|
|
This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
|
|
holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
including but not limited to the implied warranties of merchantability and
|
|
fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
|
|
or consequential damages, including but not limited to procurement of substitute
|
|
goods or services; loss of use, data, or profits, or business interruption,
|
|
however caused and on any theory of liability, whether in contract, strict
|
|
liability, or tort (including negligence), arising in any way out of the use of
|
|
this software, even if advised of the possibility of such damage.
|
|
|
|
5. CONTACT INFORMATION
|
|
|
|
Fraunhofer Institute for Integrated Circuits IIS
|
|
Attention: Audio and Multimedia Departments - FDK AAC LL
|
|
Am Wolfsmantel 33
|
|
91058 Erlangen, Germany
|
|
|
|
www.iis.fraunhofer.de/amm
|
|
amm-info@iis.fraunhofer.de
|
|
----------------------------------------------------------------------------- */
|
|
|
|
/**************************** AAC encoder library ******************************
|
|
|
|
Author(s): A. Horndasch (code originally from lwr) / Josef Hoepfl (FDK)
|
|
|
|
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);
|
|
|
|
/* 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;
|
|
FIXP_DBL isScaleLast = FL2FXCONST_DBL(0.0f);
|
|
INT isStartValueFound = 0;
|
|
|
|
for (sfboffs = 0; sfboffs < sfbCnt; sfboffs += sfbPerGroup) {
|
|
INT startIsSfb = 0;
|
|
INT inIsBlock = 0;
|
|
INT currentIsSfbCount = 0;
|
|
FIXP_DBL overallHrrError = FL2FXCONST_DBL(0.0f);
|
|
FIXP_DBL isRegionLoudness = FL2FXCONST_DBL(0.0f);
|
|
|
|
for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
|
|
if (isMask[sfboffs + sfb] == 1) {
|
|
if (currentIsSfbCount == 0) {
|
|
startIsSfb = sfboffs + sfb;
|
|
}
|
|
if (isStartValueFound == 0) {
|
|
isScaleLast = realIsScale[sfboffs + sfb];
|
|
isStartValueFound = 1;
|
|
}
|
|
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;
|
|
}
|
|
isScaleLast = FL2FXCONST_DBL(0.0f);
|
|
isStartValueFound = 0;
|
|
for (j = 0; j < startIsSfb; j++) {
|
|
if (isMask[j] != 0) {
|
|
isScaleLast = realIsScale[j];
|
|
isStartValueFound = 1;
|
|
}
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
}
|