📄 sbrfreq.c
字号:
for (k = 0; k <= nHigh; k++)
freqHigh[k] = freqMaster[k + crossOverBand];
return nHigh;
}
/**************************************************************************************
* Function: CalcFreqLow
*
* Description: calculate low resolution frequency table (4.6.18.3.2.2)
*
* Inputs: high resolution frequency table
* number of bands in high resolution frequency table
*
* Outputs: low resolution frequency table
*
* Return: number of bands in low resolution frequency table
**************************************************************************************/
static int CalcFreqLow(unsigned char *freqLow, unsigned char *freqHigh, int nHigh)
{
int k, nLow, oddFlag;
nLow = nHigh - (nHigh >> 1);
freqLow[0] = freqHigh[0];
oddFlag = nHigh & 0x01;
for (k = 1; k <= nLow; k++)
freqLow[k] = freqHigh[2*k - oddFlag];
return nLow;
}
/**************************************************************************************
* Function: CalcFreqNoise
*
* Description: calculate noise floor frequency table (4.6.18.3.2.2)
*
* Inputs: low resolution frequency table
* number of bands in low resolution frequency table
* index of starting QMF subband for SBR (kStart)
* index of last QMF subband (k2)
* number of noise bands
*
* Outputs: noise floor frequency table
*
* Return: number of bands in noise floor frequency table
**************************************************************************************/
static int CalcFreqNoise(unsigned char *freqNoise, unsigned char *freqLow, int nLow, int kStart, int k2, int noiseBands)
{
int i, iLast, k, nQ, lTop, lBottom;
lTop = log2Tab[k2];
lBottom = log2Tab[kStart];
nQ = noiseBands*((lTop - lBottom) >> 2); /* Q28 to Q26, noiseBands = [0,3] */
nQ = (nQ + (1 << 25)) >> 26;
if (nQ < 1)
nQ = 1;
ASSERT(nQ <= MAX_NUM_NOISE_FLOOR_BANDS); /* required from 4.6.18.3.6 */
iLast = 0;
freqNoise[0] = freqLow[0];
for (k = 1; k <= nQ; k++) {
i = iLast + (nLow - iLast) / (nQ + 1 - k); /* truncating division */
freqNoise[k] = freqLow[i];
iLast = i;
}
return nQ;
}
/**************************************************************************************
* Function: BuildPatches
*
* Description: build high frequency patches (4.6.18.6.3)
*
* Inputs: master frequency table
* number of bands in low resolution frequency table
* index of first QMF subband in master freq table (k0)
* index of starting QMF subband for SBR (kStart)
* number of QMF bands in high resolution frequency table
* sample rate index
*
* Outputs: starting subband for each patch
* number of subbands in each patch
*
* Return: number of patches
**************************************************************************************/
static int BuildPatches(unsigned char *patchNumSubbands, unsigned char *patchStartSubband, unsigned char *freqMaster,
int nMaster, int k0, int kStart, int numQMFBands, int sampRateIdx)
{
int i, j, k;
int msb, sb, usb, numPatches, goalSB, oddFlag;
msb = k0;
usb = kStart;
numPatches = 0;
goalSB = goalSBTab[sampRateIdx];
if (nMaster == 0) {
patchNumSubbands[0] = 0;
patchStartSubband[0] = 0;
return 0;
}
if (goalSB < kStart + numQMFBands) {
k = 0;
for (i = 0; freqMaster[i] < goalSB; i++)
k = i+1;
} else {
k = nMaster;
}
do {
j = k+1;
do {
j--;
sb = freqMaster[j];
oddFlag = (sb - 2 + k0) & 0x01;
} while (sb > k0 - 1 + msb - oddFlag);
patchNumSubbands[numPatches] = MAX(sb - usb, 0);
patchStartSubband[numPatches] = k0 - oddFlag - patchNumSubbands[numPatches];
/* from MPEG reference code - slightly different from spec */
if ((patchNumSubbands[numPatches] < 3) && (numPatches > 0))
break;
if (patchNumSubbands[numPatches] > 0) {
usb = sb;
msb = sb;
numPatches++;
} else {
msb = kStart;
}
if (freqMaster[k] - sb < 3)
k = nMaster;
} while (sb != (kStart + numQMFBands) && numPatches <= MAX_NUM_PATCHES);
return numPatches;
}
/**************************************************************************************
* Function: FindFreq
*
* Description: search buffer of unsigned chars for a specific value
*
* Inputs: buffer of elements to search
* number of elements to search
* value to search for
*
* Outputs: none
*
* Return: non-zero if the value is found anywhere in the buffer, zero otherwise
**************************************************************************************/
static int FindFreq(unsigned char *freq, int nFreq, unsigned char val)
{
int k;
for (k = 0; k < nFreq; k++) {
if (freq[k] == val)
return 1;
}
return 0;
}
/**************************************************************************************
* Function: RemoveFreq
*
* Description: remove one element from a buffer of unsigned chars
*
* Inputs: buffer of elements
* number of elements
* index of element to remove
*
* Outputs: new buffer of length nFreq-1
*
* Return: none
**************************************************************************************/
static void RemoveFreq(unsigned char *freq, int nFreq, int removeIdx)
{
int k;
if (removeIdx >= nFreq)
return;
for (k = removeIdx; k < nFreq - 1; k++)
freq[k] = freq[k+1];
}
/**************************************************************************************
* Function: CalcFreqLimiter
*
* Description: calculate limiter frequency table (4.6.18.3.2.3)
*
* Inputs: number of subbands in each patch
* low resolution frequency table
* number of bands in low resolution frequency table
* index of starting QMF subband for SBR (kStart)
* number of limiter bands
* number of patches
*
* Outputs: limiter frequency table
*
* Return: number of bands in limiter frequency table
**************************************************************************************/
static int CalcFreqLimiter(unsigned char *freqLimiter, unsigned char *patchNumSubbands, unsigned char *freqLow,
int nLow, int kStart, int limiterBands, int numPatches)
{
int k, bands, nLimiter, nOctaves;
int limBandsPerOctave[3] = {120, 200, 300}; /* [1.2, 2.0, 3.0] * 100 */
unsigned char patchBorders[MAX_NUM_PATCHES + 1];
/* simple case */
if (limiterBands == 0) {
freqLimiter[0] = freqLow[0] - kStart;
freqLimiter[1] = freqLow[nLow] - kStart;
return 1;
}
bands = limBandsPerOctave[limiterBands - 1];
patchBorders[0] = kStart;
/* from MPEG reference code - slightly different from spec (top border) */
for (k = 1; k < numPatches; k++)
patchBorders[k] = patchBorders[k-1] + patchNumSubbands[k-1];
patchBorders[k] = freqLow[nLow];
for (k = 0; k <= nLow; k++)
freqLimiter[k] = freqLow[k];
for (k = 1; k < numPatches; k++)
freqLimiter[k+nLow] = patchBorders[k];
k = 1;
nLimiter = nLow + numPatches - 1;
BubbleSort(freqLimiter, nLimiter + 1);
while (k <= nLimiter) {
nOctaves = log2Tab[freqLimiter[k]] - log2Tab[freqLimiter[k-1]]; /* Q28 */
nOctaves = (nOctaves >> 9) * bands; /* Q19, max bands = 300 < 2^9 */
if (nOctaves < (49 << 19)) { /* compare with 0.49*100, in Q19 */
if (freqLimiter[k] == freqLimiter[k-1] || FindFreq(patchBorders, numPatches + 1, freqLimiter[k]) == 0) {
RemoveFreq(freqLimiter, nLimiter + 1, k);
nLimiter--;
} else if (FindFreq(patchBorders, numPatches + 1, freqLimiter[k-1]) == 0) {
RemoveFreq(freqLimiter, nLimiter + 1, k-1);
nLimiter--;
} else {
k++;
}
} else {
k++;
}
}
/* store limiter boundaries as offsets from kStart */
for (k = 0; k <= nLimiter; k++)
freqLimiter[k] -= kStart;
return nLimiter;
}
/**************************************************************************************
* Function: CalcFreqTables
*
* Description: calulate master and derived frequency tables, and patches
*
* Inputs: initialized SBRHeader struct for this SCE/CPE block
* initialized SBRFreq struct for this SCE/CPE block
* sample rate index of output sample rate (after SBR)
*
* Outputs: master and derived frequency tables, and patches
*
* Return: non-zero if error, zero otherwise
**************************************************************************************/
int CalcFreqTables(SBRHeader *sbrHdr, SBRFreq *sbrFreq, int sampRateIdx)
{
int k0, k2;
k0 = k0Tab[sampRateIdx][sbrHdr->startFreq];
if (sbrHdr->stopFreq == 14)
k2 = 2*k0;
else if (sbrHdr->stopFreq == 15)
k2 = 3*k0;
else
k2 = k2Tab[sampRateIdx][sbrHdr->stopFreq];
if (k2 > 64)
k2 = 64;
/* calculate master frequency table */
if (sbrHdr->freqScale == 0)
sbrFreq->nMaster = CalcFreqMasterScaleZero(sbrFreq->freqMaster, sbrHdr->alterScale, k0, k2);
else
sbrFreq->nMaster = CalcFreqMaster(sbrFreq->freqMaster, sbrHdr->freqScale, sbrHdr->alterScale, k0, k2);
/* calculate high frequency table and related parameters */
sbrFreq->nHigh = CalcFreqHigh(sbrFreq->freqHigh, sbrFreq->freqMaster, sbrFreq->nMaster, sbrHdr->crossOverBand);
sbrFreq->numQMFBands = sbrFreq->freqHigh[sbrFreq->nHigh] - sbrFreq->freqHigh[0];
sbrFreq->kStart = sbrFreq->freqHigh[0];
/* calculate low frequency table */
sbrFreq->nLow = CalcFreqLow(sbrFreq->freqLow, sbrFreq->freqHigh, sbrFreq->nHigh);
/* calculate noise floor frequency table */
sbrFreq->numNoiseFloorBands = CalcFreqNoise(sbrFreq->freqNoise, sbrFreq->freqLow, sbrFreq->nLow, sbrFreq->kStart, k2, sbrHdr->noiseBands);
/* calculate limiter table */
sbrFreq->numPatches = BuildPatches(sbrFreq->patchNumSubbands, sbrFreq->patchStartSubband, sbrFreq->freqMaster,
sbrFreq->nMaster, k0, sbrFreq->kStart, sbrFreq->numQMFBands, sampRateIdx);
sbrFreq->nLimiter = CalcFreqLimiter(sbrFreq->freqLimiter, sbrFreq->patchNumSubbands, sbrFreq->freqLow, sbrFreq->nLow, sbrFreq->kStart,
sbrHdr->limiterBands, sbrFreq->numPatches);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -