/****************************************************************************** * 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=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