/* -----------------------------------------------------------------------------
|
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
|
----------------------------------------------------------------------------- */
|
|
/*********************** MPEG surround decoder library *************************
|
|
Author(s):
|
|
Description: SAC Dec subband processing
|
|
*******************************************************************************/
|
|
#include "sac_stp.h"
|
#include "sac_calcM1andM2.h"
|
#include "sac_bitdec.h"
|
#include "FDK_matrixCalloc.h"
|
#include "sac_rom.h"
|
|
#define BP_GF_START 6
|
#define BP_GF_SIZE 25
|
#define HP_SIZE 9
|
#define STP_UPDATE_ENERGY_RATE 32
|
|
#define SF_WET 5
|
#define SF_DRY \
|
3 /* SF_DRY == 2 would produce good conformance test results as well */
|
#define SF_PRODUCT_BP_GF 13
|
#define SF_PRODUCT_BP_GF_GF 26
|
#define SF_SCALE 2
|
|
#define SF_SCALE_LD64 FL2FXCONST_DBL(0.03125) /* LD64((1<<SF_SCALE))*/
|
#define STP_LPF_COEFF1__FDK FL2FXCONST_DBL(0.950f) /* 0.95 */
|
#define ONE_MINUS_STP_LPF_COEFF1__FDK FL2FXCONST_DBL(0.05f) /* 1.0 - 0.95 */
|
#define STP_LPF_COEFF2__FDK FL2FXCONST_DBL(0.450f) /* 0.45 */
|
#define ONE_MINUS_STP_LPF_COEFF2__FDK \
|
FL2FXCONST_DBL(1.0f - 0.450f) /* 1.0 - 0.45 */
|
#define STP_SCALE_LIMIT__FDK \
|
FL2FXCONST_DBL(2.82f / (float)(1 << SF_SCALE)) /* scaled by SF_SCALE */
|
#define ONE_DIV_STP_SCALE_LIMIT__FDK \
|
FL2FXCONST_DBL(1.0f / 2.82f / (float)(1 << SF_SCALE)) /* scaled by SF_SCALE \
|
*/
|
#define ABS_THR__FDK \
|
FL2FXCONST_DBL(ABS_THR / \
|
((float)(1 << (22 + 22 - 26)))) /* scaled by 18 bits */
|
#define ABS_THR2__FDK \
|
FL2FXCONST_DBL(ABS_THR * 32.0f * 32.0f / \
|
((float)(1 << (22 + 22 - 26)))) /* scaled by 10 bits */
|
#define STP_SCALE_LIMIT_HI \
|
FL2FXCONST_DBL(3.02222222222 / (1 << SF_SCALE)) /* see 4. below */
|
#define STP_SCALE_LIMIT_LO \
|
FL2FXCONST_DBL(0.28289992119 / (1 << SF_SCALE)) /* see 4. below */
|
#define STP_SCALE_LIMIT_HI_LD64 \
|
FL2FXCONST_DBL(0.04986280452) /* see 4. below \
|
*/
|
#define STP_SCALE_LIMIT_LO_LD64 \
|
FL2FXCONST_DBL(0.05692613500) /* see 4. below \
|
*/
|
|
/* Scale factor calculation for the diffuse signal needs adapted thresholds
|
for STP_SCALE_LIMIT and 1/STP_SCALE_LIMIT:
|
|
1. scale = sqrt(DryNrg/WetNrg)
|
|
2. Damping of scale factor
|
scale2 = 0.1 + 0.9 * scale
|
|
3. Limiting of scale factor
|
STP_SCALE_LIMIT >= scale2 >= 1/STP_SCALE_LIMIT
|
=> STP_SCALE_LIMIT >= (0.1 + 0.9 * scale) >= 1/STP_SCALE_LIMIT
|
=> (STP_SCALE_LIMIT-0.1)/0.9 >= scale >=
|
(1/STP_SCALE_LIMIT-0.1)/0.9
|
|
3. Limiting of scale factor before sqrt calculation
|
((STP_SCALE_LIMIT-0.1)/0.9)^2 >= (scale^2) >=
|
((1/STP_SCALE_LIMIT-0.1)/0.9)^2 (STP_SCALE_LIMIT_HI)^2 >= (scale^2) >=
|
(STP_SCALE_LIMIT_LO)^2
|
|
4. Thresholds for limiting of scale factor
|
STP_SCALE_LIMIT_HI = ((2.82-0.1)/0.9)
|
STP_SCALE_LIMIT_LO = (((1.0/2.82)-0.1)/0.9)
|
STP_SCALE_LIMIT_HI_LD64 = LD64(STP_SCALE_LIMIT_HI*STP_SCALE_LIMIT_HI)
|
STP_SCALE_LIMIT_LO_LD64 = LD64(STP_SCALE_LIMIT_LO*STP_SCALE_LIMIT_LO)
|
*/
|
|
#define DRY_ENER_WEIGHT(DryEner) DryEner = DryEner >> dry_scale_dmx
|
|
#define WET_ENER_WEIGHT(WetEner) WetEner = WetEner << wet_scale_dmx
|
|
#define DRY_ENER_SUM_REAL(DryEner, dmxReal, n) \
|
DryEner += \
|
fMultDiv2(fPow2Div2(dmxReal << SF_DRY), pBP[n]) >> ((2 * SF_DRY) - 2)
|
|
#define DRY_ENER_SUM_CPLX(DryEner, dmxReal, dmxImag, n) \
|
DryEner += fMultDiv2( \
|
fPow2Div2(dmxReal << SF_DRY) + fPow2Div2(dmxImag << SF_DRY), pBP[n])
|
|
#define CALC_WET_SCALE(dryIdx, wetIdx) \
|
if ((DryEnerLD64[dryIdx] - STP_SCALE_LIMIT_HI_LD64) > WetEnerLD64[wetIdx]) { \
|
scale[wetIdx] = STP_SCALE_LIMIT_HI; \
|
} else if (DryEnerLD64[dryIdx] < \
|
(WetEnerLD64[wetIdx] - STP_SCALE_LIMIT_LO_LD64)) { \
|
scale[wetIdx] = STP_SCALE_LIMIT_LO; \
|
} else { \
|
tmp = ((DryEnerLD64[dryIdx] - WetEnerLD64[wetIdx]) >> 1) - SF_SCALE_LD64; \
|
scale[wetIdx] = CalcInvLdData(tmp); \
|
}
|
|
struct STP_DEC {
|
FIXP_DBL runDryEner[MAX_INPUT_CHANNELS];
|
FIXP_DBL runWetEner[MAX_OUTPUT_CHANNELS];
|
FIXP_DBL oldDryEnerLD64[MAX_INPUT_CHANNELS];
|
FIXP_DBL oldWetEnerLD64[MAX_OUTPUT_CHANNELS];
|
FIXP_DBL prev_tp_scale[MAX_OUTPUT_CHANNELS];
|
const FIXP_CFG *BP;
|
const FIXP_CFG *BP_GF;
|
int update_old_ener;
|
};
|
|
inline void combineSignalReal(FIXP_DBL *hybOutputRealDry,
|
FIXP_DBL *hybOutputRealWet, int bands) {
|
int n;
|
|
for (n = bands - 1; n >= 0; n--) {
|
*hybOutputRealDry = *hybOutputRealDry + *hybOutputRealWet;
|
hybOutputRealDry++, hybOutputRealWet++;
|
}
|
}
|
|
inline void combineSignalRealScale1(FIXP_DBL *hybOutputRealDry,
|
FIXP_DBL *hybOutputRealWet, FIXP_DBL scaleX,
|
int bands) {
|
int n;
|
|
for (n = bands - 1; n >= 0; n--) {
|
*hybOutputRealDry =
|
*hybOutputRealDry +
|
(fMultDiv2(*hybOutputRealWet, scaleX) << (SF_SCALE + 1));
|
hybOutputRealDry++, hybOutputRealWet++;
|
}
|
}
|
|
inline void combineSignalCplx(FIXP_DBL *hybOutputRealDry,
|
FIXP_DBL *hybOutputImagDry,
|
FIXP_DBL *hybOutputRealWet,
|
FIXP_DBL *hybOutputImagWet, int bands) {
|
int n;
|
|
for (n = bands - 1; n >= 0; n--) {
|
*hybOutputRealDry = *hybOutputRealDry + *hybOutputRealWet;
|
*hybOutputImagDry = *hybOutputImagDry + *hybOutputImagWet;
|
hybOutputRealDry++, hybOutputRealWet++;
|
hybOutputImagDry++, hybOutputImagWet++;
|
}
|
}
|
|
inline void combineSignalCplxScale1(FIXP_DBL *hybOutputRealDry,
|
FIXP_DBL *hybOutputImagDry,
|
FIXP_DBL *hybOutputRealWet,
|
FIXP_DBL *hybOutputImagWet,
|
const FIXP_CFG *pBP, FIXP_DBL scaleX,
|
int bands) {
|
int n;
|
FIXP_DBL scaleY;
|
for (n = bands - 1; n >= 0; n--) {
|
scaleY = fMultDiv2(scaleX, *pBP);
|
*hybOutputRealDry =
|
*hybOutputRealDry +
|
(fMultDiv2(*hybOutputRealWet, scaleY) << (SF_SCALE + 2));
|
*hybOutputImagDry =
|
*hybOutputImagDry +
|
(fMultDiv2(*hybOutputImagWet, scaleY) << (SF_SCALE + 2));
|
hybOutputRealDry++, hybOutputRealWet++;
|
hybOutputImagDry++, hybOutputImagWet++;
|
pBP++;
|
}
|
}
|
|
inline void combineSignalCplxScale2(FIXP_DBL *hybOutputRealDry,
|
FIXP_DBL *hybOutputImagDry,
|
FIXP_DBL *hybOutputRealWet,
|
FIXP_DBL *hybOutputImagWet, FIXP_DBL scaleX,
|
int bands) {
|
int n;
|
|
for (n = bands - 1; n >= 0; n--) {
|
*hybOutputRealDry =
|
*hybOutputRealDry +
|
(fMultDiv2(*hybOutputRealWet, scaleX) << (SF_SCALE + 1));
|
*hybOutputImagDry =
|
*hybOutputImagDry +
|
(fMultDiv2(*hybOutputImagWet, scaleX) << (SF_SCALE + 1));
|
hybOutputRealDry++, hybOutputRealWet++;
|
hybOutputImagDry++, hybOutputImagWet++;
|
}
|
}
|
|
/*******************************************************************************
|
Functionname: subbandTPCreate
|
******************************************************************************/
|
SACDEC_ERROR subbandTPCreate(HANDLE_STP_DEC *hStpDec) {
|
HANDLE_STP_DEC self = NULL;
|
FDK_ALLOCATE_MEMORY_1D(self, 1, struct STP_DEC)
|
if (hStpDec != NULL) {
|
*hStpDec = self;
|
}
|
|
return MPS_OK;
|
bail:
|
return MPS_OUTOFMEMORY;
|
}
|
|
SACDEC_ERROR subbandTPInit(HANDLE_STP_DEC self) {
|
SACDEC_ERROR err = MPS_OK;
|
int ch;
|
|
for (ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++) {
|
self->prev_tp_scale[ch] = FL2FXCONST_DBL(1.0f / (1 << SF_SCALE));
|
self->oldWetEnerLD64[ch] =
|
FL2FXCONST_DBL(0.34375f); /* 32768.0*32768.0/2^(44-26-10) */
|
}
|
for (ch = 0; ch < MAX_INPUT_CHANNELS; ch++) {
|
self->oldDryEnerLD64[ch] =
|
FL2FXCONST_DBL(0.1875f); /* 32768.0*32768.0/2^(44-26) */
|
}
|
|
self->BP = BP__FDK;
|
self->BP_GF = BP_GF__FDK;
|
|
self->update_old_ener = 0;
|
|
return err;
|
}
|
|
/*******************************************************************************
|
Functionname: subbandTPDestroy
|
******************************************************************************/
|
void subbandTPDestroy(HANDLE_STP_DEC *hStpDec) {
|
if (hStpDec != NULL) {
|
FDK_FREE_MEMORY_1D(*hStpDec);
|
}
|
}
|
|
/*******************************************************************************
|
Functionname: subbandTPApply
|
******************************************************************************/
|
SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame) {
|
FIXP_DBL *qmfOutputRealDry[MAX_OUTPUT_CHANNELS];
|
FIXP_DBL *qmfOutputImagDry[MAX_OUTPUT_CHANNELS];
|
FIXP_DBL *qmfOutputRealWet[MAX_OUTPUT_CHANNELS];
|
FIXP_DBL *qmfOutputImagWet[MAX_OUTPUT_CHANNELS];
|
|
FIXP_DBL DryEner[MAX_INPUT_CHANNELS];
|
FIXP_DBL scale[MAX_OUTPUT_CHANNELS];
|
|
FIXP_DBL DryEnerLD64[MAX_INPUT_CHANNELS];
|
FIXP_DBL WetEnerLD64[MAX_OUTPUT_CHANNELS];
|
|
FIXP_DBL DryEner0 = FL2FXCONST_DBL(0.0f);
|
FIXP_DBL WetEnerX, damp, tmp;
|
FIXP_DBL dmxReal0, dmxImag0;
|
int skipChannels[MAX_OUTPUT_CHANNELS];
|
int n, ch, cplxBands, cplxHybBands;
|
int dry_scale_dmx, wet_scale_dmx;
|
int i_LF, i_RF;
|
HANDLE_STP_DEC hStpDec;
|
const FIXP_CFG *pBP;
|
|
int nrgScale = (2 * self->clipProtectGainSF__FDK);
|
|
hStpDec = self->hStpDec;
|
|
/* set scalefactor and loop counter */
|
FDK_ASSERT(SF_DRY >= 1);
|
{
|
cplxBands = BP_GF_SIZE;
|
cplxHybBands = self->hybridBands;
|
dry_scale_dmx = (2 * SF_DRY) - 2;
|
wet_scale_dmx = 2;
|
}
|
|
/* setup pointer for forming the direct downmix signal */
|
for (ch = 0; ch < self->numOutputChannels; ch++) {
|
qmfOutputRealDry[ch] = &self->hybOutputRealDry__FDK[ch][7];
|
qmfOutputRealWet[ch] = &self->hybOutputRealWet__FDK[ch][7];
|
qmfOutputImagDry[ch] = &self->hybOutputImagDry__FDK[ch][7];
|
qmfOutputImagWet[ch] = &self->hybOutputImagWet__FDK[ch][7];
|
}
|
|
/* clear skipping flag for all output channels */
|
FDKmemset(skipChannels, 0, self->numOutputChannels * sizeof(int));
|
|
/* set scale values to zero */
|
FDKmemset(scale, 0, self->numOutputChannels * sizeof(FIXP_DBL));
|
|
/* update normalisation energy with latest smoothed energy */
|
if (hStpDec->update_old_ener == STP_UPDATE_ENERGY_RATE) {
|
hStpDec->update_old_ener = 1;
|
for (ch = 0; ch < self->numInputChannels; ch++) {
|
hStpDec->oldDryEnerLD64[ch] =
|
CalcLdData(hStpDec->runDryEner[ch] + ABS_THR__FDK);
|
}
|
for (ch = 0; ch < self->numOutputChannels; ch++) {
|
hStpDec->oldWetEnerLD64[ch] =
|
CalcLdData(hStpDec->runWetEner[ch] + ABS_THR2__FDK);
|
}
|
} else {
|
hStpDec->update_old_ener++;
|
}
|
|
/* get channel configuration */
|
switch (self->treeConfig) {
|
case TREE_212:
|
i_LF = 0;
|
i_RF = 1;
|
break;
|
default:
|
return MPS_WRONG_TREECONFIG;
|
}
|
|
/* form the 'direct' downmix signal */
|
pBP = hStpDec->BP_GF - BP_GF_START;
|
switch (self->treeConfig) {
|
case TREE_212:
|
for (n = BP_GF_START; n < cplxBands; n++) {
|
dmxReal0 = qmfOutputRealDry[i_LF][n] + qmfOutputRealDry[i_RF][n];
|
dmxImag0 = qmfOutputImagDry[i_LF][n] + qmfOutputImagDry[i_RF][n];
|
DRY_ENER_SUM_CPLX(DryEner0, dmxReal0, dmxImag0, n);
|
}
|
DRY_ENER_WEIGHT(DryEner0);
|
break;
|
default:;
|
}
|
DryEner[0] = DryEner0;
|
|
/* normalise the 'direct' signals */
|
for (ch = 0; ch < self->numInputChannels; ch++) {
|
DryEner[ch] = DryEner[ch] << (nrgScale);
|
hStpDec->runDryEner[ch] =
|
fMult(STP_LPF_COEFF1__FDK, hStpDec->runDryEner[ch]) +
|
fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, DryEner[ch]);
|
if (DryEner[ch] != FL2FXCONST_DBL(0.0f)) {
|
DryEnerLD64[ch] =
|
fixMax((CalcLdData(DryEner[ch]) - hStpDec->oldDryEnerLD64[ch]),
|
FL2FXCONST_DBL(-0.484375f));
|
} else {
|
DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
|
}
|
}
|
if (self->treeConfig == TREE_212) {
|
for (; ch < MAX_INPUT_CHANNELS; ch++) {
|
DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
|
}
|
}
|
|
/* normalise the 'diffuse' signals */
|
pBP = hStpDec->BP_GF - BP_GF_START;
|
for (ch = 0; ch < self->numOutputChannels; ch++) {
|
if (skipChannels[ch]) {
|
continue;
|
}
|
|
WetEnerX = FL2FXCONST_DBL(0.0f);
|
for (n = BP_GF_START; n < cplxBands; n++) {
|
tmp = fPow2Div2(qmfOutputRealWet[ch][n] << SF_WET);
|
tmp += fPow2Div2(qmfOutputImagWet[ch][n] << SF_WET);
|
WetEnerX += fMultDiv2(tmp, pBP[n]);
|
}
|
WET_ENER_WEIGHT(WetEnerX);
|
|
WetEnerX = WetEnerX << (nrgScale);
|
hStpDec->runWetEner[ch] =
|
fMult(STP_LPF_COEFF1__FDK, hStpDec->runWetEner[ch]) +
|
fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, WetEnerX);
|
|
if (WetEnerX == FL2FXCONST_DBL(0.0f)) {
|
WetEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f);
|
} else {
|
WetEnerLD64[ch] =
|
fixMax((CalcLdData(WetEnerX) - hStpDec->oldWetEnerLD64[ch]),
|
FL2FXCONST_DBL(-0.484375f));
|
}
|
}
|
|
/* compute scale factor for the 'diffuse' signals */
|
switch (self->treeConfig) {
|
case TREE_212:
|
if (DryEner[0] != FL2FXCONST_DBL(0.0f)) {
|
CALC_WET_SCALE(0, i_LF);
|
CALC_WET_SCALE(0, i_RF);
|
}
|
break;
|
default:;
|
}
|
|
damp = FL2FXCONST_DBL(0.1f / (1 << SF_SCALE));
|
for (ch = 0; ch < self->numOutputChannels; ch++) {
|
/* damp the scaling factor */
|
scale[ch] = damp + fMult(FL2FXCONST_DBL(0.9f), scale[ch]);
|
|
/* limiting the scale factor */
|
if (scale[ch] > STP_SCALE_LIMIT__FDK) {
|
scale[ch] = STP_SCALE_LIMIT__FDK;
|
}
|
if (scale[ch] < ONE_DIV_STP_SCALE_LIMIT__FDK) {
|
scale[ch] = ONE_DIV_STP_SCALE_LIMIT__FDK;
|
}
|
|
/* low pass filter the scaling factor */
|
scale[ch] =
|
fMult(STP_LPF_COEFF2__FDK, scale[ch]) +
|
fMult(ONE_MINUS_STP_LPF_COEFF2__FDK, hStpDec->prev_tp_scale[ch]);
|
hStpDec->prev_tp_scale[ch] = scale[ch];
|
}
|
|
/* combine 'direct' and scaled 'diffuse' signal */
|
FDK_ASSERT((HP_SIZE - 3 + 10 - 1) == PC_NUM_HYB_BANDS);
|
const SCHAR *channlIndex = row2channelSTP[self->treeConfig];
|
|
for (ch = 0; ch < self->numOutputChannels; ch++) {
|
int no_scaling;
|
|
no_scaling = !frame->tempShapeEnableChannelSTP[channlIndex[ch]];
|
if (no_scaling) {
|
combineSignalCplx(
|
&self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder],
|
&self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder],
|
&self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder],
|
&self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder],
|
cplxHybBands - self->tp_hybBandBorder);
|
|
} else {
|
FIXP_DBL scaleX;
|
scaleX = scale[ch];
|
pBP = hStpDec->BP - self->tp_hybBandBorder;
|
/* Band[HP_SIZE-3+10-1] needs not to be processed in
|
combineSignalCplxScale1(), because pB[HP_SIZE-3+10-1] would be 1.0 */
|
combineSignalCplxScale1(
|
&self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder],
|
&self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder],
|
&self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder],
|
&self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder],
|
&pBP[self->tp_hybBandBorder], scaleX,
|
(HP_SIZE - 3 + 10 - 1) - self->tp_hybBandBorder);
|
|
{
|
combineSignalCplxScale2(
|
&self->hybOutputRealDry__FDK[ch][HP_SIZE - 3 + 10 - 1],
|
&self->hybOutputImagDry__FDK[ch][HP_SIZE - 3 + 10 - 1],
|
&self->hybOutputRealWet__FDK[ch][HP_SIZE - 3 + 10 - 1],
|
&self->hybOutputImagWet__FDK[ch][HP_SIZE - 3 + 10 - 1], scaleX,
|
cplxHybBands - (HP_SIZE - 3 + 10 - 1));
|
}
|
}
|
}
|
|
return (SACDEC_ERROR)MPS_OK;
|
;
|
}
|