📄 sbrhfadj.c
字号:
}
q = MULSHIFT32(psi->smBuf[m], gBoost) << 2; /* Q(fbitsDQ) * Q(28) --> Q(fbitsDQ-2) */
r = SqrtFix(q, fbitsDQ - 2, &z);
z -= FBITS_OUT_QMFA; /* justify for adding to signal (xBuf) later */
if (z >= 0) {
psi->smBoost[m] = r >> MIN(31, z);
} else {
z = MIN(30, -z);
CLIP_2N_SHIFT30(r, z);
psi->smBoost[m] = r;
}
}
}
/**************************************************************************************
* Function: CalcGain
*
* Description: calculate and apply proper gain to HF components in one envelope
* (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
* initialized SBRChan struct for this channel
* index of current channel (0 for SCE, 0 or 1 for CPE)
* index of current envelope
*
* Outputs: envelope gain, sinusoids and noise after scaling
*
* Return: none
**************************************************************************************/
static void CalcGain(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch, int env)
{
int lim, fbitsDQ;
/* initialize to -1 so that mapping limiter bands to env/noise bands works right on first pass */
psi->envBand = -1;
psi->noiseFloorBand = -1;
psi->sBand = -1;
psi->highBand = -1;
fbitsDQ = (FBITS_OUT_DQ_ENV - psi->envDataDequantScale[ch][env]); /* Q(29 - optional scalefactor) */
for (lim = 0; lim < sbrFreq->nLimiter; lim++) {
/* the QMF bands are divided into lim regions (consecutive, non-overlapping) */
CalcMaxGain(psi, sbrHdr, sbrGrid, sbrFreq, ch, env, lim, fbitsDQ);
CalcComponentGains(psi, sbrGrid, sbrFreq, sbrChan, ch, env, lim, fbitsDQ);
ApplyBoost(psi, sbrFreq, lim, fbitsDQ);
}
}
/* hSmooth table from 4.7.18.7.6, format = Q31 */
static const int hSmoothCoef[MAX_NUM_SMOOTH_COEFS] = {
0x2aaaaaab, 0x2697a512, 0x1becfa68, 0x0ebdb043, 0x04130598,
};
/**************************************************************************************
* Function: MapHF
*
* Description: map HF components to proper QMF bands, with optional gain smoothing
* filter (4.6.18.7.6)
*
* 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
* initialized SBRChan struct for this channel
* index of current envelope
* reset flag (can be non-zero for first envelope only)
*
* Outputs: complete reconstructed subband QMF samples for this envelope
*
* Return: none
*
* Notes: ensures that output has >= MIN_GBITS_IN_QMFS guard bits,
* so it's not necessary to check anything in the synth QMF
**************************************************************************************/
static void MapHF(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int env, int hfReset)
{
int noiseTabIndex, sinIndex, gainNoiseIndex, hSL;
int i, iStart, iEnd, m, idx, j, s, n, smre, smim;
int gFilt, qFilt, xre, xim, gbMask, gbIdx;
int *XBuf;
noiseTabIndex = sbrChan->noiseTabIndex;
sinIndex = sbrChan->sinIndex;
gainNoiseIndex = sbrChan->gainNoiseIndex; /* oldest entries in filter delay buffer */
if (hfReset)
noiseTabIndex = 2; /* starts at 1, double since complex */
hSL = (sbrHdr->smoothMode ? 0 : 4);
if (hfReset) {
for (i = 0; i < hSL; i++) {
for (m = 0; m < sbrFreq->numQMFBands; m++) {
sbrChan->gTemp[gainNoiseIndex][m] = psi->gLimBoost[m];
sbrChan->qTemp[gainNoiseIndex][m] = psi->qmLimBoost[m];
}
gainNoiseIndex++;
if (gainNoiseIndex == MAX_NUM_SMOOTH_COEFS)
gainNoiseIndex = 0;
}
ASSERT(env == 0); /* should only be reset when env == 0 */
}
iStart = sbrGrid->envTimeBorder[env];
iEnd = sbrGrid->envTimeBorder[env+1];
for (i = iStart; i < iEnd; i++) {
/* save new values in temp buffers (delay)
* we only store MAX_NUM_SMOOTH_COEFS most recent values,
* so don't keep storing the same value over and over
*/
if (i - iStart < MAX_NUM_SMOOTH_COEFS) {
for (m = 0; m < sbrFreq->numQMFBands; m++) {
sbrChan->gTemp[gainNoiseIndex][m] = psi->gLimBoost[m];
sbrChan->qTemp[gainNoiseIndex][m] = psi->qmLimBoost[m];
}
}
/* see 4.6.18.7.6 */
XBuf = psi->XBuf[i + HF_ADJ][sbrFreq->kStart];
gbMask = 0;
for (m = 0; m < sbrFreq->numQMFBands; m++) {
if (env == psi->la || env == sbrChan->laPrev) {
/* no smoothing filter for gain, and qFilt = 0 (only need to do once) */
if (i == iStart) {
psi->gFiltLast[m] = sbrChan->gTemp[gainNoiseIndex][m];
psi->qFiltLast[m] = 0;
}
} else if (hSL == 0) {
/* no smoothing filter for gain, (only need to do once) */
if (i == iStart) {
psi->gFiltLast[m] = sbrChan->gTemp[gainNoiseIndex][m];
psi->qFiltLast[m] = sbrChan->qTemp[gainNoiseIndex][m];
}
} else {
/* apply smoothing filter to gain and noise (after MAX_NUM_SMOOTH_COEFS, it's always the same) */
if (i - iStart < MAX_NUM_SMOOTH_COEFS) {
gFilt = 0;
qFilt = 0;
idx = gainNoiseIndex;
for (j = 0; j < MAX_NUM_SMOOTH_COEFS; j++) {
/* sum(abs(hSmoothCoef[j])) for all j < 1.0 */
gFilt += MULSHIFT32(sbrChan->gTemp[idx][m], hSmoothCoef[j]);
qFilt += MULSHIFT32(sbrChan->qTemp[idx][m], hSmoothCoef[j]);
idx--;
if (idx < 0)
idx += MAX_NUM_SMOOTH_COEFS;
}
psi->gFiltLast[m] = gFilt << 1; /* restore to Q(FBITS_GLIM_BOOST) (gain of filter < 1.0, so no overflow) */
psi->qFiltLast[m] = qFilt << 1; /* restore to Q(FBITS_QLIM_BOOST) */
}
}
if (psi->smBoost[m] != 0) {
/* add scaled signal and sinusoid, don't add noise (qFilt = 0) */
smre = psi->smBoost[m];
smim = smre;
/* sinIndex: [0] xre += sm [1] xim += sm*s [2] xre -= sm [3] xim -= sm*s */
s = (sinIndex >> 1); /* if 2 or 3, flip sign to subtract sm */
s <<= 31;
smre ^= (s >> 31);
smre -= (s >> 31);
s ^= ((m + sbrFreq->kStart) << 31);
smim ^= (s >> 31);
smim -= (s >> 31);
/* if sinIndex == 0 or 2, smim = 0; if sinIndex == 1 or 3, smre = 0 */
s = sinIndex << 31;
smim &= (s >> 31);
s ^= 0x80000000;
smre &= (s >> 31);
noiseTabIndex += 2; /* noise filtered by 0, but still need to bump index */
} else {
/* add scaled signal and scaled noise */
qFilt = psi->qFiltLast[m];
n = noiseTab[noiseTabIndex++];
smre = MULSHIFT32(n, qFilt) >> (FBITS_QLIM_BOOST - 1 - FBITS_OUT_QMFA);
n = noiseTab[noiseTabIndex++];
smim = MULSHIFT32(n, qFilt) >> (FBITS_QLIM_BOOST - 1 - FBITS_OUT_QMFA);
}
noiseTabIndex &= 1023; /* 512 complex numbers */
gFilt = psi->gFiltLast[m];
xre = MULSHIFT32(gFilt, XBuf[0]);
xim = MULSHIFT32(gFilt, XBuf[1]);
CLIP_2N_SHIFT30(xre, 32 - FBITS_GLIM_BOOST);
CLIP_2N_SHIFT30(xim, 32 - FBITS_GLIM_BOOST);
xre += smre; *XBuf++ = xre;
xim += smim; *XBuf++ = xim;
gbMask |= FASTABS(xre);
gbMask |= FASTABS(xim);
}
/* update circular buffer index */
gainNoiseIndex++;
if (gainNoiseIndex == MAX_NUM_SMOOTH_COEFS)
gainNoiseIndex = 0;
sinIndex++;
sinIndex &= 3;
/* ensure MIN_GBITS_IN_QMFS guard bits in output
* almost never occurs in practice, but checking here makes synth QMF logic very simple
*/
if (gbMask >> (31 - MIN_GBITS_IN_QMFS)) {
XBuf = psi->XBuf[i + HF_ADJ][sbrFreq->kStart];
for (m = 0; m < sbrFreq->numQMFBands; m++) {
xre = XBuf[0]; xim = XBuf[1];
CLIP_2N(xre, (31 - MIN_GBITS_IN_QMFS));
CLIP_2N(xim, (31 - MIN_GBITS_IN_QMFS));
*XBuf++ = xre; *XBuf++ = xim;
}
CLIP_2N(gbMask, (31 - MIN_GBITS_IN_QMFS));
}
gbIdx = ((i + HF_ADJ) >> 5) & 0x01;
sbrChan->gbMask[gbIdx] |= gbMask;
}
sbrChan->noiseTabIndex = noiseTabIndex;
sbrChan->sinIndex = sinIndex;
sbrChan->gainNoiseIndex = gainNoiseIndex;
}
/**************************************************************************************
* Function: AdjustHighFreq
*
* Description: adjust high frequencies and add noise and sinusoids (4.6.18.7)
*
* 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
* initialized SBRChan struct for this channel
* index of current channel (0 for SCE, 0 or 1 for CPE)
*
* Outputs: complete reconstructed subband QMF samples for this channel
*
* Return: none
**************************************************************************************/
void AdjustHighFreq(PSInfoSBR *psi, SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch)
{
int i, env, hfReset;
unsigned char frameClass, pointer;
frameClass = sbrGrid->frameClass;
pointer = sbrGrid->pointer;
/* derive la from table 4.159 */
if ((frameClass == SBR_GRID_FIXVAR || frameClass == SBR_GRID_VARVAR) && pointer > 0)
psi->la = sbrGrid->numEnv + 1 - pointer;
else if (frameClass == SBR_GRID_VARFIX && pointer > 1)
psi->la = pointer - 1;
else
psi->la = -1;
/* for each envelope, estimate gain and adjust SBR QMF bands */
hfReset = sbrChan->reset;
for (env = 0; env < sbrGrid->numEnv; env++) {
EstimateEnvelope(psi, sbrHdr, sbrGrid, sbrFreq, env);
CalcGain(psi, sbrHdr, sbrGrid, sbrFreq, sbrChan, ch, env);
MapHF(psi, sbrHdr, sbrGrid, sbrFreq, sbrChan, env, hfReset);
hfReset = 0; /* only set for first envelope after header reset */
}
/* set saved sine flags to 0 for QMF bands outside of current frequency range */
for (i = 0; i < sbrFreq->freqLimiter[0] + sbrFreq->kStart; i++)
sbrChan->addHarmonic[0][i] = 0;
for (i = sbrFreq->freqLimiter[sbrFreq->nLimiter] + sbrFreq->kStart; i < 64; i++)
sbrChan->addHarmonic[0][i] = 0;
sbrChan->addHarmonicFlag[0] = sbrChan->addHarmonicFlag[1];
/* save la for next frame */
if (psi->la == sbrGrid->numEnv)
sbrChan->laPrev = 0;
else
sbrChan->laPrev = -1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -