mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-09 13:07:03 +03:00
642 lines
20 KiB
C
642 lines
20 KiB
C
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Source last modified: $Id: sbrfreq.c,v 1.2 2005/05/20 18:05:41 jrecker 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
|
|
*
|
|
* sbrfreq.c - frequency band table calculation for SBR
|
|
**************************************************************************************/
|
|
|
|
#include "sbr.h"
|
|
#include "assembly.h"
|
|
|
|
/**************************************************************************************
|
|
* Function: BubbleSort
|
|
*
|
|
* Description: in-place sort of unsigned chars
|
|
*
|
|
* Inputs: buffer of elements to sort
|
|
* number of elements to sort
|
|
*
|
|
* Outputs: sorted buffer
|
|
*
|
|
* Return: none
|
|
**************************************************************************************/
|
|
static void BubbleSort(unsigned char *v, int nItems)
|
|
{
|
|
int i;
|
|
unsigned char t;
|
|
|
|
while (nItems >= 2) {
|
|
for (i = 0; i < nItems-1; i++) {
|
|
if (v[i+1] < v[i]) {
|
|
t = v[i+1];
|
|
v[i+1] = v[i];
|
|
v[i] = t;
|
|
}
|
|
}
|
|
nItems--;
|
|
}
|
|
}
|
|
|
|
/**************************************************************************************
|
|
* Function: VMin
|
|
*
|
|
* Description: find smallest element in a buffer of unsigned chars
|
|
*
|
|
* Inputs: buffer of elements to search
|
|
* number of elements to search
|
|
*
|
|
* Outputs: none
|
|
*
|
|
* Return: smallest element in buffer
|
|
**************************************************************************************/
|
|
static unsigned char VMin(unsigned char *v, int nItems)
|
|
{
|
|
int i;
|
|
unsigned char vMin;
|
|
|
|
vMin = v[0];
|
|
for (i = 1; i < nItems; i++) {
|
|
if (v[i] < vMin)
|
|
vMin = v[i];
|
|
}
|
|
return vMin;
|
|
}
|
|
|
|
/**************************************************************************************
|
|
* Function: VMax
|
|
*
|
|
* Description: find largest element in a buffer of unsigned chars
|
|
*
|
|
* Inputs: buffer of elements to search
|
|
* number of elements to search
|
|
*
|
|
* Outputs: none
|
|
*
|
|
* Return: largest element in buffer
|
|
**************************************************************************************/
|
|
static unsigned char VMax(unsigned char *v, int nItems)
|
|
{
|
|
int i;
|
|
unsigned char vMax;
|
|
|
|
vMax = v[0];
|
|
for (i = 1; i < nItems; i++) {
|
|
if (v[i] > vMax)
|
|
vMax = v[i];
|
|
}
|
|
return vMax;
|
|
}
|
|
|
|
/**************************************************************************************
|
|
* Function: CalcFreqMasterScaleZero
|
|
*
|
|
* Description: calculate master frequency table when freqScale == 0
|
|
* (4.6.18.3.2.1, figure 4.39)
|
|
*
|
|
* Inputs: alterScale flag
|
|
* index of first QMF subband in master freq table (k0)
|
|
* index of last QMF subband (k2)
|
|
*
|
|
* Outputs: master frequency table
|
|
*
|
|
* Return: number of bands in master frequency table
|
|
*
|
|
* Notes: assumes k2 - k0 <= 48 and k2 >= k0 (4.6.18.3.6)
|
|
**************************************************************************************/
|
|
static int CalcFreqMasterScaleZero(unsigned char *freqMaster, int alterScale, int k0, int k2)
|
|
{
|
|
int nMaster, k, nBands, k2Achieved, dk, vDk[64], k2Diff;
|
|
|
|
if (alterScale) {
|
|
dk = 2;
|
|
nBands = 2 * ((k2 - k0 + 2) >> 2);
|
|
} else {
|
|
dk = 1;
|
|
nBands = 2 * ((k2 - k0) >> 1);
|
|
}
|
|
|
|
if (nBands <= 0)
|
|
return 0;
|
|
|
|
k2Achieved = k0 + nBands * dk;
|
|
k2Diff = k2 - k2Achieved;
|
|
for (k = 0; k < nBands; k++)
|
|
vDk[k] = dk;
|
|
|
|
if (k2Diff > 0) {
|
|
k = nBands - 1;
|
|
while (k2Diff) {
|
|
vDk[k]++;
|
|
k--;
|
|
k2Diff--;
|
|
}
|
|
} else if (k2Diff < 0) {
|
|
k = 0;
|
|
while (k2Diff) {
|
|
vDk[k]--;
|
|
k++;
|
|
k2Diff++;
|
|
}
|
|
}
|
|
|
|
nMaster = nBands;
|
|
freqMaster[0] = k0;
|
|
for (k = 1; k <= nBands; k++)
|
|
freqMaster[k] = freqMaster[k-1] + vDk[k-1];
|
|
|
|
return nMaster;
|
|
}
|
|
|
|
/* mBandTab[i] = temp1[i] / 2 */
|
|
static const int mBandTab[3] PROGMEM = {6, 5, 4};
|
|
|
|
/* invWarpTab[i] = 1.0 / temp2[i], Q30 (see 4.6.18.3.2.1) */
|
|
static const int invWarpTab[2] PROGMEM = {0x40000000, 0x313b13b1};
|
|
|
|
/**************************************************************************************
|
|
* Function: CalcFreqMasterScale
|
|
*
|
|
* Description: calculate master frequency table when freqScale > 0
|
|
* (4.6.18.3.2.1, figure 4.39)
|
|
*
|
|
* Inputs: alterScale flag
|
|
* freqScale flag
|
|
* index of first QMF subband in master freq table (k0)
|
|
* index of last QMF subband (k2)
|
|
*
|
|
* Outputs: master frequency table
|
|
*
|
|
* Return: number of bands in master frequency table
|
|
*
|
|
* Notes: assumes k2 - k0 <= 48 and k2 >= k0 (4.6.18.3.6)
|
|
**************************************************************************************/
|
|
static int CalcFreqMaster(unsigned char *freqMaster, int freqScale, int alterScale, int k0, int k2)
|
|
{
|
|
int bands, twoRegions, k, k1, t, vLast, vCurr, pCurr;
|
|
int invWarp, nBands0, nBands1, change;
|
|
unsigned char vDk1Min, vDk0Max;
|
|
unsigned char *vDelta;
|
|
|
|
if (freqScale < 1 || freqScale > 3)
|
|
return -1;
|
|
|
|
bands = mBandTab[freqScale - 1];
|
|
invWarp = invWarpTab[alterScale];
|
|
|
|
/* tested for all k0 = [5, 64], k2 = [k0, 64] */
|
|
if (k2*10000 > 22449*k0) {
|
|
twoRegions = 1;
|
|
k1 = 2*k0;
|
|
} else {
|
|
twoRegions = 0;
|
|
k1 = k2;
|
|
}
|
|
|
|
/* tested for all k0 = [5, 64], k1 = [k0, 64], freqScale = [1,3] */
|
|
t = (log2Tab[k1] - log2Tab[k0]) >> 3; /* log2(k1/k0), Q28 to Q25 */
|
|
nBands0 = 2 * (((bands * t) + (1 << 24)) >> 25); /* multiply by bands/2, round to nearest int (mBandTab has factor of 1/2 rolled in) */
|
|
|
|
/* tested for all valid combinations of k0, k1, nBands (from sampRate, freqScale, alterScale)
|
|
* roundoff error can be a problem with fixpt (e.g. pCurr = 12.499999 instead of 12.50003)
|
|
* because successive multiplication always undershoots a little bit, but this
|
|
* doesn't occur in any of the ratios we encounter from the valid k0/k1 bands in the spec
|
|
*/
|
|
t = RatioPowInv(k1, k0, nBands0);
|
|
pCurr = k0 << 24;
|
|
vLast = k0;
|
|
vDelta = freqMaster + 1; /* operate in-place */
|
|
for (k = 0; k < nBands0; k++) {
|
|
pCurr = MULSHIFT32(pCurr, t) << 8; /* keep in Q24 */
|
|
vCurr = (pCurr + (1 << 23)) >> 24;
|
|
vDelta[k] = (vCurr - vLast);
|
|
vLast = vCurr;
|
|
}
|
|
|
|
/* sort the deltas and find max delta for first region */
|
|
BubbleSort(vDelta, nBands0);
|
|
vDk0Max = VMax(vDelta, nBands0);
|
|
|
|
/* fill master frequency table with bands from first region */
|
|
freqMaster[0] = k0;
|
|
for (k = 1; k <= nBands0; k++)
|
|
freqMaster[k] += freqMaster[k-1];
|
|
|
|
/* if only one region, then the table is complete */
|
|
if (!twoRegions)
|
|
return nBands0;
|
|
|
|
/* tested for all k1 = [10, 64], k2 = [k0, 64], freqScale = [1,3] */
|
|
t = (log2Tab[k2] - log2Tab[k1]) >> 3; /* log2(k1/k0), Q28 to Q25 */
|
|
t = MULSHIFT32(bands * t, invWarp) << 2; /* multiply by bands/2, divide by warp factor, keep Q25 */
|
|
nBands1 = 2 * ((t + (1 << 24)) >> 25); /* round to nearest int */
|
|
|
|
/* see comments above for calculations in first region */
|
|
t = RatioPowInv(k2, k1, nBands1);
|
|
pCurr = k1 << 24;
|
|
vLast = k1;
|
|
vDelta = freqMaster + nBands0 + 1; /* operate in-place */
|
|
for (k = 0; k < nBands1; k++) {
|
|
pCurr = MULSHIFT32(pCurr, t) << 8; /* keep in Q24 */
|
|
vCurr = (pCurr + (1 << 23)) >> 24;
|
|
vDelta[k] = (vCurr - vLast);
|
|
vLast = vCurr;
|
|
}
|
|
|
|
/* sort the deltas, adjusting first and last if the second region has smaller deltas than the first */
|
|
vDk1Min = VMin(vDelta, nBands1);
|
|
if (vDk1Min < vDk0Max) {
|
|
BubbleSort(vDelta, nBands1);
|
|
change = vDk0Max - vDelta[0];
|
|
if (change > ((vDelta[nBands1 - 1] - vDelta[0]) >> 1))
|
|
change = ((vDelta[nBands1 - 1] - vDelta[0]) >> 1);
|
|
vDelta[0] += change;
|
|
vDelta[nBands1-1] -= change;
|
|
}
|
|
BubbleSort(vDelta, nBands1);
|
|
|
|
/* fill master frequency table with bands from second region
|
|
* Note: freqMaster[nBands0] = k1
|
|
*/
|
|
for (k = 1; k <= nBands1; k++)
|
|
freqMaster[k + nBands0] += freqMaster[k + nBands0 - 1];
|
|
|
|
return (nBands0 + nBands1);
|
|
}
|
|
|
|
/**************************************************************************************
|
|
* Function: CalcFreqHigh
|
|
*
|
|
* Description: calculate high resolution frequency table (4.6.18.3.2.2)
|
|
*
|
|
* Inputs: master frequency table
|
|
* number of bands in master frequency table
|
|
* crossover band from header
|
|
*
|
|
* Outputs: high resolution frequency table
|
|
*
|
|
* Return: number of bands in high resolution frequency table
|
|
**************************************************************************************/
|
|
static int CalcFreqHigh(unsigned char *freqHigh, unsigned char *freqMaster, int nMaster, int crossOverBand)
|
|
{
|
|
int k, nHigh;
|
|
|
|
nHigh = nMaster - crossOverBand;
|
|
|
|
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;
|
|
}
|