windows-nt/Source/XPSP1/NT/enduser/speech/tts/common/sigproc/resample.cpp
2020-09-26 16:20:57 +08:00

171 lines
4.5 KiB
C++

/******************************************************************************
* resample.cpp *
*--------------*
*
*------------------------------------------------------------------------------
* Copyright (C) 1999 Entropic, Inc
* Copyright (C) 2000 Microsoft Corporation Date: 03/02/00
* All Rights Reserved
*
********************************************************************* PACOG ***/
#include "sigprocInt.h"
#define FILTER_LEN_2 .005 //(sec)
static double* WindowedLowPass (double dCutOff, double dGain, int iHalfLen);
static void FindResampleFactors (int iInSampFreq, int iOutSampFreq,
int* piUpFactor, int* piDownFactor);
/*****************************************************************************
* Resample *
*----------*
* Description:
*
******************************************************************* PACOG ***/
int Resample (double* pdOriginal, int iNumOrig, int iInSampFreq, int iOutSampFreq,
double** ppdResampled, int* piNumResamp)
{
int iUpFactor;
int iDownFactor;
int iLimitFactor;
double* pdFilterCoef;
int iHalfLen;
int iFilterLen;
double dAcum;
int iPhase;
int i;
int j;
int n;
assert (pdOriginal);
assert (iNumOrig >0);
assert (ppdResampled);
assert (piNumResamp);
assert (iInSampFreq >0);
assert (iOutSampFreq >0);
FindResampleFactors (iInSampFreq, iOutSampFreq, &iUpFactor, &iDownFactor);
iLimitFactor = (iUpFactor>iDownFactor)? iUpFactor: iDownFactor;
iHalfLen = (int)(iInSampFreq * iLimitFactor * FILTER_LEN_2);
iFilterLen = 2 * iHalfLen + 1;
if (! (pdFilterCoef = WindowedLowPass(.5/iLimitFactor, iUpFactor, iHalfLen)))
{
return false;
}
*piNumResamp = (iNumOrig * iUpFactor) / iDownFactor;
*ppdResampled = new double[*piNumResamp];
if (*ppdResampled == 0)
{
fprintf (stderr, "Memory error\n");
return false;
}
for (i=0; i<*piNumResamp; i++)
{
dAcum = 0.0;
n = (int )((i * iDownFactor - iHalfLen) / (double)iUpFactor);
iPhase = (i*iDownFactor) - (n*iUpFactor + iHalfLen);
for (j=0; j<iFilterLen/iUpFactor; j++)
{
if ( (n+j >=0) && (n+j < iNumOrig) && (iUpFactor*j > iPhase))
{
dAcum += pdOriginal[n + j] * pdFilterCoef[iUpFactor * j - iPhase];
}
}
(*ppdResampled)[i] = dAcum;
}
return true;
}
/*****************************************************************************
* WindowedLowPass *
*-----------------*
* Description:
* Creates a low pass filter using the windowing method.
* CutOff is spec. in normalized frequency
******************************************************************* PACOG ***/
double* WindowedLowPass (double dCutOff, double dGain, int iHalfLen)
{
double* pdCoeffs;
double* pdWindow;
double dArg;
double dSinc;
int iFilterLen = iHalfLen*2 +1;
int i;
assert (dCutOff>0.0 && dCutOff<0.5);
pdWindow = ComputeWindow(WINDOW_BLACK, iFilterLen, true);
if (!pdWindow)
{
return 0;
}
pdCoeffs = new double[iFilterLen];
if (pdCoeffs)
{
dArg = 2.0 * M_PI * dCutOff;
pdCoeffs[iHalfLen] = (double)(dGain * 2.0 * dCutOff);
for (i=1; i<=iHalfLen; i++)
{
dSinc = dGain * sin(dArg*i)/(M_PI*i) * pdWindow[iHalfLen- i];
pdCoeffs[iHalfLen+i] = (double)dSinc;
pdCoeffs[iHalfLen-i] = (double)dSinc;
}
}
delete[] pdWindow;
return pdCoeffs;
}
/*****************************************************************************
* FindResampleFactors *
*---------------------*
* Description:
*
******************************************************************* PACOG ***/
void FindResampleFactors (int iInSampFreq, int iOutSampFreq, int* piUpFactor, int* piDownFactor)
{
static int aiPrimes[] = {2,3,5,7,11,13,17,19,23,29,31,37};
static int iNumPrimes = sizeof (aiPrimes) / sizeof(aiPrimes[0]);
int iDiv = 1;
int i;
assert (piUpFactor);
assert (piDownFactor);
while (iDiv)
{
iDiv = 0;
for (i=0; i<iNumPrimes;i++)
{
if ( (iInSampFreq % aiPrimes[i]) == 0 && (iOutSampFreq % aiPrimes[i]) == 0 )
{
iInSampFreq/=aiPrimes[i];
iOutSampFreq/=aiPrimes[i];
iDiv = 1;
break;
}
}
}
*piUpFactor = iOutSampFreq;
*piDownFactor = iInSampFreq;
}