Ejemplo n.º 1
0
//////////////////////////////////////////////////////////////////////
//  Call to setup filter parameters
// SampleRate in Hz
// FLowcut is low cutoff frequency of filter in Hz
// FHicut is high cutoff frequency of filter in Hz
// Offset is the CW tone offset frequency
// cutoff frequencies range from -SampleRate/2 to +SampleRate/2
//  HiCut must be greater than LowCut
//		example to make 2700Hz USB filter:
//	SetupParameters( 100, 2800, 0, 48000);
//////////////////////////////////////////////////////////////////////
void CFastFIR::SetupParameters( TYPEREAL FLoCut, TYPEREAL FHiCut,
								TYPEREAL Offset, TYPEREAL SampleRate)
{
int i;
	if( (FLoCut==m_FLoCut) && (FHiCut==m_FHiCut) &&
		(Offset==m_Offset) && (SampleRate==m_SampleRate) )
	{
		return;		//return if no changes
	}
	m_FLoCut = FLoCut;
	m_FHiCut = FHiCut;
	m_Offset = Offset;
	m_SampleRate = SampleRate;

	FLoCut += Offset;
	FHiCut += Offset;
	//sanity check on filter parameters
	if( (FLoCut >= FHiCut) ||
		(FLoCut >= SampleRate/2.0) ||
		(FLoCut <= -SampleRate/2.0) ||
		(FHiCut >= SampleRate/2.0) ||
		(FHiCut <= -SampleRate/2.0) )
	{
		fprintf(stderr, "Filter Parameter error:\n");
		return;
	}

	//calculate some normalized filter parameters
	TYPEREAL nFL = FLoCut/SampleRate;
	TYPEREAL nFH = FHiCut/SampleRate;
	TYPEREAL nFc = (nFH-nFL)/2.0;		//prototype LP filter cutoff
	TYPEREAL nFs = K_2PI*(nFH+nFL)/2.0;		//2 PI times required frequency shift (FHiCut+FLoCut)/2
	TYPEREAL fCenter = 0.5*(TYPEREAL)(CONV_FIR_SIZE-1);	//floating point center index of FIR filter

	for(i=0; i<CONV_FFT_SIZE; i++)		//zero pad entire coefficient buffer to FFT size
	{
		m_pFilterCoef[i].re = 0.0;
		m_pFilterCoef[i].im = 0.0;
	}

	//create LP FIR windowed sinc, sin(x)/x complex LP filter coefficients
	for(i=0; i<CONV_FIR_SIZE; i++)
	{
		TYPEREAL x = (TYPEREAL)i - fCenter;
		TYPEREAL z;
		if( (TYPEREAL)i == fCenter )	//deal with odd size filter singularity where sin(0)/0==1
			z = 2.0 * nFc;
		else
			z = (TYPEREAL)MSIN(K_2PI*x*nFc)/(K_PI*x) * m_pWindowTbl[i];

		//shift lowpass filter coefficients in frequency by (hicut+lowcut)/2 to form bandpass filter anywhere in range
		// (also scales by 1/FFTsize since inverse FFT routine scales by FFTsize)
		m_pFilterCoef[i].re  =  z * MCOS(nFs * x)/(TYPEREAL)CONV_FFT_SIZE;
		m_pFilterCoef[i].im = z * MSIN(nFs * x)/(TYPEREAL)CONV_FFT_SIZE;
	}

	//convert FIR coefficients to frequency domain by taking forward FFT
	m_Fft.FwdFFT(m_pFilterCoef);

}
Ejemplo n.º 2
0
///////////////////////////////////////////////////////////////////////////
// function to convert LP filter coefficients into complex hilbert bandpass
// filter coefficients.
// Hbpreal(n)= 2*Hlp(n)*MCOS( 2PI*FreqOffset*(n-(N-1)/2)/samplerate );
// Hbpimaj(n)= 2*Hlp(n)*MSIN( 2PI*FreqOffset*(n-(N-1)/2)/samplerate );
void CFir::GenerateHBFilter( TYPEREAL FreqOffset)
{
int n;
	for(n=0; n<m_NumTaps; n++)
	{
		// apply complex frequency shift transform to low pass filter coefficients
		m_ICoef[n] = 2.0 * m_Coef[n] * MCOS( (K_2PI*FreqOffset/m_SampleRate)*((TYPEREAL)n - ( (TYPEREAL)(m_NumTaps-1)/2.0 ) ) );
		m_QCoef[n] = 2.0 * m_Coef[n] * MSIN( (K_2PI*FreqOffset/m_SampleRate)*((TYPEREAL)n - ( (TYPEREAL)(m_NumTaps-1)/2.0 ) ) );
	}
	//make a 2x length array for FIR flat calculation efficiency
	for (n = 0; n < m_NumTaps; n++)
	{
		m_ICoef[n+m_NumTaps] = m_ICoef[n];
		m_QCoef[n+m_NumTaps] = m_QCoef[n];
	}
#if 0		//debug hack to write m_Coef's to a file for analysis
	QDir::setCurrent("d:/");
	QFile File;
	File.setFileName("hbpcoef.txt");
	if(File.open(QIODevice::WriteOnly))
	{
		qDebug()<<"file Opened OK";
		char Buf[256];
		for( n=0; n<m_NumTaps; n++)
		{
			sprintf( Buf, "%19.12g %19.12g\r\n", m_ICoef[n], m_QCoef[n]);
			File.write(Buf);
		}
	}
	else
		qDebug()<<"file Failed to Open";
	qDebug()<<"HBP taps="<<m_NumTaps << m_SampleRate;
#endif
}
Ejemplo n.º 3
0
////////////////////////////////////////////////////////////////////
// Create a FIR high Pass filter with scaled amplitude 'Scale'
// NumTaps if non-zero, forces filter design to be this number of taps
// Astop = Stopband Atenuation in dB (ie 40dB is 40dB stopband attenuation)
// Fpass = Highpass passband frequency in Hz
// Fstop = Highpass stopband frequency in Hz
// Fsamprate = Sample Rate in Hz
//
//  Apass              -------------
//                    /
//                   /
//                  /
//                 /
//  Astop ---------
//            Fstop   Fpass
////////////////////////////////////////////////////////////////////
int CFir::InitHPFilter(int NumTaps, TYPEREAL Scale, TYPEREAL Astop, TYPEREAL Fpass, TYPEREAL Fstop, TYPEREAL Fsamprate)
{
int n;
TYPEREAL Beta;
	//m_Mutex.lock();
	m_SampleRate = Fsamprate;
	//create normalized frequency parameters
	TYPEREAL normFpass = Fpass/Fsamprate;
	TYPEREAL normFstop = Fstop/Fsamprate;
	TYPEREAL normFcut = (normFstop + normFpass)/2.0;	//high pass filter 6dB cutoff

	//calculate Kaiser-Bessel window shape factor, Beta, from stopband attenuation
	if(Astop < 20.96)
		Beta = 0;
	else if(Astop >= 50.0)
		Beta = .1102 * (Astop - 8.71);
	else
		Beta = .5842 * MPOW( (Astop-20.96), 0.4) + .07886 * (Astop - 20.96);

	//Now Estimate number of filter taps required based on filter specs
	m_NumTaps = (Astop - 8.0) / (2.285*K_2PI*(normFpass - normFstop ) ) + 1;

	//clamp range of filter taps
	if(m_NumTaps>(MAX_NUMCOEF-1) )
		m_NumTaps = MAX_NUMCOEF-1;
	if(m_NumTaps < 3)
		m_NumTaps = 3;

	m_NumTaps |= 1;		//force to next odd number

	if(NumTaps)	//if need to force to to a number of taps
		m_NumTaps = NumTaps;

	TYPEREAL izb = Izero(Beta);		//precalculate denominator since is same for all points
	TYPEREAL fCenter = .5*(TYPEREAL)(m_NumTaps-1);
	for( n=0; n < m_NumTaps; n++)
	{
		TYPEREAL x = (TYPEREAL)n - (TYPEREAL)(m_NumTaps-1)/2.0;
		TYPEREAL c;
		// create ideal Sinc() HP filter with normFcut
		if( (TYPEREAL)n == fCenter )	//deal with odd size filter singularity where sin(0)/0==1
			c = 1.0 - 2.0 * normFcut;
		else
			c = (TYPEREAL) (MSIN(K_PI*x)/(K_PI*x) - MSIN(K_2PI*x*normFcut)/(K_PI*x) );

		//calculate Kaiser window and multiply to get coefficient
		x = ((TYPEREAL)n - ((TYPEREAL)m_NumTaps-1.0)/2.0 ) / (((TYPEREAL)m_NumTaps-1.0)/2.0);
		m_Coef[n] = Scale * c * Izero( Beta * MSQRT(1 - (x*x) ) )  / izb;
	}

	//make a 2x length array for FIR flat calculation efficiency
	for (n = 0; n < m_NumTaps; n++)
		m_Coef[n+m_NumTaps] = m_Coef[n];

	//copy into complex coef buffers
	for (n = 0; n < m_NumTaps*2; n++)
	{
		m_ICoef[n] = m_Coef[n];
		m_QCoef[n] = m_Coef[n];
	}

	//Initialize the FIR buffers and state
	for(int i=0; i<m_NumTaps; i++)
	{
		m_rZBuf[i] = 0.0;
		m_cZBuf[i].re = 0.0;
		m_cZBuf[i].im = 0.0;
	}
	m_State = 0;

	//m_Mutex.unlock();


#if 0		//debug hack to write m_Coef to a file for analysis
	QDir::setCurrent("d:/");
	QFile File;
	File.setFileName("hpcoef.txt");
	if(File.open(QIODevice::WriteOnly))
	{
		qDebug()<<"file Opened OK";
		char Buf[256];
		for(n=0; n<m_NumTaps; n++)
		{
			sprintf( Buf, "%g\r\n", m_Coef[n]);
			File.write(Buf);
		}
	}
	else
		qDebug()<<"file Failed to Open";
	qDebug()<<"HP taps="<<m_NumTaps;
#endif
	return m_NumTaps;
}