📄 tns.c
字号:
/* Perform filtering for each window */
for(w=0;w<numberOfWindows;w++)
{
TnsWindowData* windowData = &tnsInfo->windowData[w];
TnsFilterData* tnsFilter = windowData->tnsFilter;
startIndex = w * windowSize + sfbOffsetTable[startBand];
length = sfbOffsetTable[stopBand] - sfbOffsetTable[startBand];
if (tnsInfo->tnsDataPresent && windowData->numFilters) { /* Use TNS */
TnsFilter(length,&spec[startIndex],tnsFilter);
}
}
}
/*****************************************************/
/* TnsFilter: */
/* Filter the given spec with specified length */
/* using the coefficients specified in filter. */
/* Not that the order and direction are specified */
/* withing the TNS_FILTER_DATA structure. */
/*****************************************************/
static void TnsFilter(int length,double* spec,TnsFilterData* filter)
{
int i,j,k=0;
int order=filter->order;
double* a=filter->aCoeffs;
/* Determine loop parameters for given direction */
if (filter->direction) {
/* Startup, initial state is zero */
for (i=length-2;i>(length-1-order);i--) {
k++;
for (j=1;j<=k;j++) {
spec[i]-=spec[i+j]*a[j];
}
}
/* Now filter completely inplace */
for (i=length-1-order;i>=0;i--) {
for (j=1;j<=order;j++) {
spec[i]-=spec[i+j]*a[j];
}
}
} else {
/* Startup, initial state is zero */
for (i=1;i<order;i++) {
for (j=1;j<=i;j++) {
spec[i]-=spec[i-j]*a[j];
}
}
/* Now filter completely inplace */
for (i=order;i<length;i++) {
for (j=1;j<=order;j++) {
spec[i]-=spec[i-j]*a[j];
}
}
}
}
/********************************************************/
/* TnsInvFilter: */
/* Inverse filter the given spec with specified */
/* length using the coefficients specified in filter. */
/* Not that the order and direction are specified */
/* withing the TNS_FILTER_DATA structure. */
/********************************************************/
static void TnsInvFilter(int length,double* spec,TnsFilterData* filter)
{
int i,j,k=0;
int order=filter->order;
double* a=filter->aCoeffs;
double* temp;
temp = (double *)AllocMemory(length * sizeof (double));
/* Determine loop parameters for given direction */
if (filter->direction) {
/* Startup, initial state is zero */
temp[length-1]=spec[length-1];
for (i=length-2;i>(length-1-order);i--) {
temp[i]=spec[i];
k++;
for (j=1;j<=k;j++) {
spec[i]+=temp[i+j]*a[j];
}
}
/* Now filter the rest */
for (i=length-1-order;i>=0;i--) {
temp[i]=spec[i];
for (j=1;j<=order;j++) {
spec[i]+=temp[i+j]*a[j];
}
}
} else {
/* Startup, initial state is zero */
temp[0]=spec[0];
for (i=1;i<order;i++) {
temp[i]=spec[i];
for (j=1;j<=i;j++) {
spec[i]+=temp[i-j]*a[j];
}
}
/* Now filter the rest */
for (i=order;i<length;i++) {
temp[i]=spec[i];
for (j=1;j<=order;j++) {
spec[i]+=temp[i-j]*a[j];
}
}
}
if (temp) FreeMemory(temp);
}
/*****************************************************/
/* TruncateCoeffs: */
/* Truncate the given reflection coeffs by zeroing */
/* coefficients in the tail with absolute value */
/* less than the specified threshold. Return the */
/* truncated filter order. */
/*****************************************************/
static int TruncateCoeffs(int fOrder,double threshold,double* kArray)
{
int i;
for (i = fOrder; i >= 0; i--) {
kArray[i] = (fabs(kArray[i])>threshold) ? kArray[i] : 0.0;
if (kArray[i]!=0.0) return i;
}
return 0;
}
/*****************************************************/
/* QuantizeReflectionCoeffs: */
/* Quantize the given array of reflection coeffs */
/* to the specified resolution in bits. */
/*****************************************************/
static void QuantizeReflectionCoeffs(int fOrder,
int coeffRes,
double* kArray,
int* indexArray)
{
double iqfac,iqfac_m;
int i;
iqfac = ((1<<(coeffRes-1))-0.5)/(M_PI/2);
iqfac_m = ((1<<(coeffRes-1))+0.5)/(M_PI/2);
/* Quantize and inverse quantize */
for (i=1;i<=fOrder;i++) {
indexArray[i] = (int)(0.5+(asin(kArray[i])*((kArray[i]>=0)?iqfac:iqfac_m)));
kArray[i] = sin((double)indexArray[i]/((indexArray[i]>=0)?iqfac:iqfac_m));
}
}
/*****************************************************/
/* Autocorrelation, */
/* Compute the autocorrelation function */
/* estimate for the given data. */
/*****************************************************/
static void Autocorrelation(int maxOrder, /* Maximum autocorr order */
int dataSize, /* Size of the data array */
double* data, /* Data array */
double* rArray) /* Autocorrelation array */
{
int order,index;
for (order=0;order<=maxOrder;order++) {
rArray[order]=0.0;
for (index=0;index<dataSize;index++) {
rArray[order]+=data[index]*data[index+order];
}
dataSize--;
}
}
/*****************************************************/
/* LevinsonDurbin: */
/* Compute the reflection coefficients for the */
/* given data using LevinsonDurbin recursion. */
/* Return the prediction gain. */
/*****************************************************/
static double LevinsonDurbin(int fOrder, /* Filter order */
int dataSize, /* Size of the data array */
double* data, /* Data array */
double* kArray) /* Reflection coeff array */
{
int order,i;
double signal;
double error, kTemp; /* Prediction error */
double aArray1[TNS_MAX_ORDER+1]; /* Predictor coeff array */
double aArray2[TNS_MAX_ORDER+1]; /* Predictor coeff array 2 */
double rArray[TNS_MAX_ORDER+1]; /* Autocorrelation coeffs */
double* aPtr = aArray1; /* Ptr to aArray1 */
double* aLastPtr = aArray2; /* Ptr to aArray2 */
double* aTemp;
/* Compute autocorrelation coefficients */
Autocorrelation(fOrder,dataSize,data,rArray);
signal=rArray[0]; /* signal energy */
/* Set up pointers to current and last iteration */
/* predictor coefficients. */
aPtr = aArray1;
aLastPtr = aArray2;
/* If there is no signal energy, return */
if (!signal) {
kArray[0]=1.0;
for (order=1;order<=fOrder;order++) {
kArray[order]=0.0;
}
return 0;
} else {
/* Set up first iteration */
kArray[0]=1.0;
aPtr[0]=1.0; /* Ptr to predictor coeffs, current iteration*/
aLastPtr[0]=1.0; /* Ptr to predictor coeffs, last iteration */
error=rArray[0];
/* Now perform recursion */
for (order=1;order<=fOrder;order++) {
kTemp = aLastPtr[0]*rArray[order-0];
for (i=1;i<order;i++) {
kTemp += aLastPtr[i]*rArray[order-i];
}
kTemp = -kTemp/error;
kArray[order]=kTemp;
aPtr[order]=kTemp;
for (i=1;i<order;i++) {
aPtr[i] = aLastPtr[i] + kTemp*aLastPtr[order-i];
}
error = error * (1 - kTemp*kTemp);
/* Now make current iteration the last one */
aTemp=aLastPtr;
aLastPtr=aPtr; /* Current becomes last */
aPtr=aTemp; /* Last becomes current */
}
return signal/error; /* return the gain */
}
}
/*****************************************************/
/* StepUp: */
/* Convert reflection coefficients into */
/* predictor coefficients. */
/*****************************************************/
static void StepUp(int fOrder,double* kArray,double* aArray)
{
double aTemp[TNS_MAX_ORDER+2];
int i,order;
aArray[0]=1.0;
aTemp[0]=1.0;
for (order=1;order<=fOrder;order++) {
aArray[order]=0.0;
for (i=1;i<=order;i++) {
aTemp[i] = aArray[i] + kArray[order]*aArray[order-i];
}
for (i=1;i<=order;i++) {
aArray[i]=aTemp[i];
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -