📄 sbrfreq.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
*
* 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] = {6, 5, 4};
/* invWarpTab[i] = 1.0 / temp2[i], Q30 (see 4.6.18.3.2.1) */
static const int invWarpTab[2] = {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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -