📄 sbrhfadj.c
字号:
/* ***** BEGIN LICENSE BLOCK *****
*
* Portions Copyright (c) 1995-2005 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file,
* are subject to the current version of the RealNetworks Public
* Source License (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the current version of the RealNetworks Community
* Source License (the "RCSL") available at
* http://www.helixcommunity.org/content/rcsl, in which case the RCSL
* will apply. You may also obtain the license terms directly from
* RealNetworks. You may not use this file except in compliance with
* the RPSL or, if you have a valid RCSL with RealNetworks applicable
* to this file, the RCSL. Please see the applicable RPSL or RCSL for
* the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the
* portions it created.
*
* This file, and the files included with this file, is distributed
* and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
* ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
/**************************************************************************************
* Fixed-point HE-AAC decoder
* Jon Recker (jrecker@real.com)
* February 2005
*
* sbrhfadj.c - high frequency adjustment for SBR
**************************************************************************************/
#include "sbr.h"
#include "assembly.h"
/* invBandTab[i] = 1.0 / (i + 1), Q31 */
static const int invBandTab[64] = {
0x7fffffff, 0x40000000, 0x2aaaaaab, 0x20000000, 0x1999999a, 0x15555555, 0x12492492, 0x10000000,
0x0e38e38e, 0x0ccccccd, 0x0ba2e8ba, 0x0aaaaaab, 0x09d89d8a, 0x09249249, 0x08888889, 0x08000000,
0x07878788, 0x071c71c7, 0x06bca1af, 0x06666666, 0x06186186, 0x05d1745d, 0x0590b216, 0x05555555,
0x051eb852, 0x04ec4ec5, 0x04bda12f, 0x04924925, 0x0469ee58, 0x04444444, 0x04210842, 0x04000000,
0x03e0f83e, 0x03c3c3c4, 0x03a83a84, 0x038e38e4, 0x03759f23, 0x035e50d8, 0x03483483, 0x03333333,
0x031f3832, 0x030c30c3, 0x02fa0be8, 0x02e8ba2f, 0x02d82d83, 0x02c8590b, 0x02b93105, 0x02aaaaab,
0x029cbc15, 0x028f5c29, 0x02828283, 0x02762762, 0x026a439f, 0x025ed098, 0x0253c825, 0x02492492,
0x023ee090, 0x0234f72c, 0x022b63cc, 0x02222222, 0x02192e2a, 0x02108421, 0x02082082, 0x02000000,
};
/**************************************************************************************
* Function: EstimateEnvelope
*
* Description: estimate power of generated HF QMF bands in one time-domain envelope
* (4.6.18.7.3)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRHeader struct for this SCE/CPE block
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* index of current envelope
*
* Outputs: power of each QMF subband, stored as integer (Q0) * 2^N, N >= 0
*
* Return: none
**************************************************************************************/
static void EstimateEnvelope(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, int env)
{
int i, m, iStart, iEnd, xre, xim, nScale, expMax;
int p, n, mStart, mEnd, invFact, t;
int *XBuf;
U64 eCurr;
unsigned char *freqBandTab;
/* estimate current envelope */
iStart = sbrGrid->envTimeBorder[env] + HF_ADJ;
iEnd = sbrGrid->envTimeBorder[env+1] + HF_ADJ;
if (sbrGrid->freqRes[env]) {
n = sbrFreq->nHigh;
freqBandTab = sbrFreq->freqHigh;
} else {
n = sbrFreq->nLow;
freqBandTab = sbrFreq->freqLow;
}
/* ADS should inline MADD64 (smlal) properly, but check to make sure */
expMax = 0;
if (sbrHdr->interpFreq) {
for (m = 0; m < sbrFreq->numQMFBands; m++) {
eCurr.w64 = 0;
XBuf = psi->XBuf[iStart][sbrFreq->kStart + m];
for (i = iStart; i < iEnd; i++) {
/* scale to int before calculating power (precision not critical, and avoids overflow) */
xre = (*XBuf) >> FBITS_OUT_QMFA; XBuf += 1;
xim = (*XBuf) >> FBITS_OUT_QMFA; XBuf += (2*64 - 1);
eCurr.w64 = MADD64(eCurr.w64, xre, xre);
eCurr.w64 = MADD64(eCurr.w64, xim, xim);
}
/* eCurr.w64 is now Q(64 - 2*FBITS_OUT_QMFA) (64-bit word)
* if energy is too big to fit in 32-bit word (> 2^31) scale down by power of 2
*/
nScale = 0;
if (eCurr.r.hi32) {
nScale = (32 - CLZ(eCurr.r.hi32)) + 1;
t = (int)(eCurr.r.lo32 >> nScale); /* logical (unsigned) >> */
t |= eCurr.r.hi32 << (32 - nScale);
} else if (eCurr.r.lo32 >> 31) {
nScale = 1;
t = (int)(eCurr.r.lo32 >> nScale); /* logical (unsigned) >> */
} else {
t = (int)eCurr.r.lo32;
}
invFact = invBandTab[(iEnd - iStart)-1];
psi->eCurr[m] = MULSHIFT32(t, invFact);
psi->eCurrExp[m] = nScale + 1; /* +1 for invFact = Q31 */
if (psi->eCurrExp[m] > expMax)
expMax = psi->eCurrExp[m];
}
} else {
for (p = 0; p < n; p++) {
mStart = freqBandTab[p];
mEnd = freqBandTab[p+1];
eCurr.w64 = 0;
for (i = iStart; i < iEnd; i++) {
XBuf = psi->XBuf[i][mStart];
for (m = mStart; m < mEnd; m++) {
xre = (*XBuf++) >> FBITS_OUT_QMFA;
xim = (*XBuf++) >> FBITS_OUT_QMFA;
eCurr.w64 = MADD64(eCurr.w64, xre, xre);
eCurr.w64 = MADD64(eCurr.w64, xim, xim);
}
}
nScale = 0;
if (eCurr.r.hi32) {
nScale = (32 - CLZ(eCurr.r.hi32)) + 1;
t = (int)(eCurr.r.lo32 >> nScale); /* logical (unsigned) >> */
t |= eCurr.r.hi32 << (32 - nScale);
} else if (eCurr.r.lo32 >> 31) {
nScale = 1;
t = (int)(eCurr.r.lo32 >> nScale); /* logical (unsigned) >> */
} else {
t = (int)eCurr.r.lo32;
}
invFact = invBandTab[(iEnd - iStart)-1];
invFact = MULSHIFT32(invBandTab[(mEnd - mStart)-1], invFact) << 1;
t = MULSHIFT32(t, invFact);
for (m = mStart; m < mEnd; m++) {
psi->eCurr[m - sbrFreq->kStart] = t;
psi->eCurrExp[m - sbrFreq->kStart] = nScale + 1; /* +1 for invFact = Q31 */
}
if (psi->eCurrExp[mStart - sbrFreq->kStart] > expMax)
expMax = psi->eCurrExp[mStart - sbrFreq->kStart];
}
}
psi->eCurrExpMax = expMax;
}
/**************************************************************************************
* Function: GetSMapped
*
* Description: calculate SMapped (4.6.18.7.2)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* initialized SBRChan struct for this channel
* index of current envelope
* index of current QMF band
* la flag for this envelope
*
* Outputs: none
*
* Return: 1 if a sinusoid is present in this band, 0 if not
**************************************************************************************/
static int GetSMapped(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int env, int band, int la)
{
int bandStart, bandEnd, oddFlag, r;
if (sbrGrid->freqRes[env]) {
/* high resolution */
bandStart = band;
bandEnd = band+1;
} else {
/* low resolution (see CalcFreqLow() for mapping) */
oddFlag = sbrFreq->nHigh & 0x01;
bandStart = (band > 0 ? 2*band - oddFlag : 0); /* starting index for freqLow[band] */
bandEnd = 2*(band+1) - oddFlag; /* ending index for freqLow[band+1] */
}
/* sMapped = 1 if sIndexMapped == 1 for any frequency in this band */
for (band = bandStart; band < bandEnd; band++) {
if (sbrChan->addHarmonic[1][band]) {
r = ((sbrFreq->freqHigh[band+1] + sbrFreq->freqHigh[band]) >> 1);
if (env >= la || sbrChan->addHarmonic[0][r] == 1)
return 1;
}
}
return 0;
}
#define GBOOST_MAX 0x2830afd3 /* Q28, 1.584893192 squared */
#define ACC_SCALE 6
/* squared version of table in 4.6.18.7.5 */
static const int limGainTab[4] = {0x20138ca7, 0x40000000, 0x7fb27dce, 0x80000000}; /* Q30 (0x80000000 = sentinel for GMAX) */
/**************************************************************************************
* Function: CalcMaxGain
*
* Description: calculate max gain in one limiter band (4.6.18.7.5)
*
* Inputs: initialized PSInfoSBR struct
* initialized SBRHeader struct for this SCE/CPE block
* initialized SBRGrid struct for this channel
* initialized SBRFreq struct for this SCE/CPE block
* index of current channel (0 for SCE, 0 or 1 for CPE)
* index of current envelope
* index of current limiter band
* number of fraction bits in dequantized envelope
* (max = Q(FBITS_OUT_DQ_ENV - 6) = Q23, can go negative)
*
* Outputs: updated gainMax, gainMaxFBits, and sumEOrigMapped in PSInfoSBR struct
*
* Return: none
**************************************************************************************/
static void CalcMaxGain(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, int ch, int env, int lim, int fbitsDQ)
{
int m, mStart, mEnd, q, z, r;
int sumEOrigMapped, sumECurr, gainMax, eOMGainMax, envBand;
unsigned char eCurrExpMax;
unsigned char *freqBandTab;
mStart = sbrFreq->freqLimiter[lim]; /* these are offsets from kStart */
mEnd = sbrFreq->freqLimiter[lim + 1];
freqBandTab = (sbrGrid->freqRes[env] ? sbrFreq->freqHigh : sbrFreq->freqLow);
/* calculate max gain to apply to signal in this limiter band */
sumECurr = 0;
sumEOrigMapped = 0;
eCurrExpMax = psi->eCurrExpMax;
eOMGainMax = psi->eOMGainMax;
envBand = psi->envBand;
for (m = mStart; m < mEnd; m++) {
/* map current QMF band to appropriate envelope band */
if (m == freqBandTab[envBand + 1] - sbrFreq->kStart) {
envBand++;
eOMGainMax = psi->envDataDequant[ch][env][envBand] >> ACC_SCALE; /* summing max 48 bands */
}
sumEOrigMapped += eOMGainMax;
/* easy test for overflow on ARM */
sumECurr += (psi->eCurr[m] >> (eCurrExpMax - psi->eCurrExp[m]));
if (sumECurr >> 30) {
sumECurr >>= 1;
eCurrExpMax++;
}
}
psi->eOMGainMax = eOMGainMax;
psi->envBand = envBand;
psi->gainMaxFBits = 30; /* Q30 tables */
if (sumECurr == 0) {
/* any non-zero numerator * 1/EPS_0 is > G_MAX */
gainMax = (sumEOrigMapped == 0 ? limGainTab[sbrHdr->limiterGains] : 0x80000000);
} else if (sumEOrigMapped == 0) {
/* 1/(any non-zero denominator) * EPS_0 * limGainTab[x] is appx. 0 */
gainMax = 0;
} else {
/* sumEOrigMapped = Q(fbitsDQ - ACC_SCALE), sumECurr = Q(-eCurrExpMax) */
gainMax = limGainTab[sbrHdr->limiterGains];
if (sbrHdr->limiterGains != 3) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -