📄 sbrhfadj.c
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: sbrhfadj.c,v 1.1.2.3 2005/05/24 20:34:40 albertofloyd Exp $ * * 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];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -