cmVectOpsTemplateHdr.h/Code.h : Added optional window function arg. and fixed high-pass filter generation in LP_Sinc().

Added use of cmAbs() generic to NormToAbsMax().
This commit is contained in:
Kevin Larke 2015-05-22 14:10:24 -07:00
parent 172b562022
commit 834b6f421f
2 changed files with 31 additions and 11 deletions

View File

@ -332,13 +332,13 @@ unsigned VECT_OP_FUNC(NormToAbsMax)( VECT_OP_TYPE* dp, unsigned dn, VECT_OP_TY
unsigned i = 0; unsigned i = 0;
unsigned mi = 0; unsigned mi = 0;
VECT_OP_TYPE mx = fabs(dp[0]); VECT_OP_TYPE mx = cmAbs(dp[0]);
for(i=1; i<dn; ++i) for(i=1; i<dn; ++i)
if( fabs(dp[i])>mx ) if( cmAbs(dp[i])>mx )
{ {
mi = i; mi = i;
mx = fabs(dp[i]); mx = cmAbs(dp[i]);
} }
VECT_OP_FUNC(MultVS)(dp,dn,fact/mx); VECT_OP_FUNC(MultVS)(dp,dn,fact/mx);
@ -2339,33 +2339,51 @@ VECT_OP_TYPE* VECT_OP_FUNC(FilterFilter)(struct cmFilter_str* f, cmRC_t (*fun
VECT_OP_TYPE* VECT_OP_FUNC(LP_Sinc)(VECT_OP_TYPE* dp, unsigned dn, double srate, double fcHz, unsigned flags ) VECT_OP_TYPE* VECT_OP_FUNC(LP_Sinc)(VECT_OP_TYPE* dp, unsigned dn, const VECT_OP_TYPE* wndV, double srate, double fcHz, unsigned flags )
{ {
VECT_OP_TYPE* rp = dp; VECT_OP_TYPE* rp = dp;
int dM = dn % 2; // dM is used to handle odd length windows int dM = dn % 2; // dM is used to handle odd length windows
int M = (dn - dM)/2; int M = (dn - dM)/2;
int Mi = -M; int Mi = -M;
double signFact = cmIsFlag(flags, kHighPass_LPSincFl) ? -0.5 : 0.5;
double phsFact = 2.0 * M_PI * fcHz / srate; double phsFact = 2.0 * M_PI * fcHz / srate;
double sum = 0; double sum = 0;
VECT_OP_TYPE noWndV[ dn ];
// if no window was given then create a unity window
if( wndV == NULL )
{
VECT_OP_FUNC(Fill)(noWndV,dn,1);
wndV = noWndV;
}
M += dM; M += dM;
//printf("M=%i Mi=%i sign:%f phs:%f\n",M,Mi,signFact,phsFact); //printf("M=%i Mi=%i sign:%f phs:%f\n",M,Mi,signFact,phsFact);
for(; Mi<M; ++Mi,++dp,++wndV)
for(; Mi<M; ++Mi,++dp)
{ {
double phs = phsFact * Mi; double phs = phsFact * Mi;
*dp = Mi == 0 ? 0.5 : signFact * sin(phs)/phs; if( Mi != 0 )
*dp = *wndV * 0.5 * sin(phs)/phs;
else
*dp = *wndV * 0.5;
sum += *dp; sum += *dp;
} }
// normalize the filter to produce unity gain.
if( cmIsFlag(flags,kNormalize_LPSincFl) ) if( cmIsFlag(flags,kNormalize_LPSincFl) )
VECT_OP_FUNC(DivVS)(rp,dn,sum); VECT_OP_FUNC(DivVS)(rp,dn,fabs(sum));
// Convert low-pass filter to high-pass filter
// Note that this can only be done after the filter is normalized.
if( cmIsFlag(flags,kHighPass_LPSincFl) )
{
VECT_OP_FUNC(MultVS)(rp,dn,-1);
rp[M-1] = 1.0 + rp[M-1];
}
return rp; return rp;
} }

View File

@ -443,8 +443,10 @@ struct cmFilter_str;
VECT_OP_TYPE* VECT_OP_FUNC(FilterFilter)(struct cmFilter_str* f, cmRC_t (*func)( struct cmFilter_str* f, const VECT_OP_TYPE* x, unsigned xn, VECT_OP_TYPE* y, unsigned yn ), const cmReal_t bb[], unsigned bn, const cmReal_t aa[], unsigned an, const VECT_OP_TYPE* x, unsigned xn, VECT_OP_TYPE* y, unsigned yn ); VECT_OP_TYPE* VECT_OP_FUNC(FilterFilter)(struct cmFilter_str* f, cmRC_t (*func)( struct cmFilter_str* f, const VECT_OP_TYPE* x, unsigned xn, VECT_OP_TYPE* y, unsigned yn ), const cmReal_t bb[], unsigned bn, const cmReal_t aa[], unsigned an, const VECT_OP_TYPE* x, unsigned xn, VECT_OP_TYPE* y, unsigned yn );
/// Compute the coefficients of a low/high pass FIR filter /// Compute the coefficients of a low/high pass FIR filter
/// See enum { kHighPass_LPSincFl=0x01, kNormalize_LPSincFl=0x02 } in acVectOps.h /// wndV[dn] gives the window function used to truncate the ideal low-pass impulse response.
VECT_OP_TYPE* VECT_OP_FUNC(LP_Sinc)(VECT_OP_TYPE* dp, unsigned dn, double srate, double fcHz, unsigned flags ); /// Set wndV to NULL to use a unity window.
/// See enum { kHighPass_LPSincFl=0x01, kNormalize_LPSincFl=0x02 } in cmVectOps.h
VECT_OP_TYPE* VECT_OP_FUNC(LP_Sinc)(VECT_OP_TYPE* dp, unsigned dn, const VECT_OP_TYPE* wndV, double srate, double fcHz, unsigned flags );
/// Compute the complex transient detection function from successive spectral frames. /// Compute the complex transient detection function from successive spectral frames.
/// The spectral magntidue mag0V precedes mag1V and the phase (radians) spectrum phs0V precedes the phs1V which precedes phs2V. /// The spectral magntidue mag0V precedes mag1V and the phase (radians) spectrum phs0V precedes the phs1V which precedes phs2V.