mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-29 20:10:22 -04:00 
			
		
		
		
	Corrected Highpass and Bandpass filters normalization. Implements #642
This commit is contained in:
		
							parent
							
								
									71f96aded6
								
							
						
					
					
						commit
						ae60808de8
					
				| @ -189,7 +189,6 @@ void AMDemodSink::processOneSample(Complex &ci) | |||||||
|         if (m_settings.m_bandpassEnable) |         if (m_settings.m_bandpassEnable) | ||||||
|         { |         { | ||||||
|             demod = m_bandpass.filter(demod); |             demod = m_bandpass.filter(demod); | ||||||
|             demod /= 301.0f; |  | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|  | |||||||
| @ -121,7 +121,7 @@ void NFMDemodSink::processOneSample(Complex &ci) | |||||||
| 
 | 
 | ||||||
|     if (m_settings.m_deltaSquelch) |     if (m_settings.m_deltaSquelch) | ||||||
|     { |     { | ||||||
|         if (m_afSquelch.analyze(demod * m_discriCompensation)) |         if (m_afSquelch.analyze(demod)) | ||||||
|         { |         { | ||||||
|             m_afSquelchOpen = m_afSquelch.evaluate(); // ? m_squelchGate + m_squelchDecay : 0;
 |             m_afSquelchOpen = m_afSquelch.evaluate(); // ? m_squelchGate + m_squelchDecay : 0;
 | ||||||
| 
 | 
 | ||||||
| @ -132,7 +132,7 @@ void NFMDemodSink::processOneSample(Complex &ci) | |||||||
| 
 | 
 | ||||||
|         if (m_afSquelchOpen) |         if (m_afSquelchOpen) | ||||||
|         { |         { | ||||||
|             m_squelchDelayLine.write(demod * m_discriCompensation); |             m_squelchDelayLine.write(demod); | ||||||
| 
 | 
 | ||||||
|             if (m_squelchCount < 2*m_squelchGate) { |             if (m_squelchCount < 2*m_squelchGate) { | ||||||
|                 m_squelchCount++; |                 m_squelchCount++; | ||||||
| @ -159,7 +159,7 @@ void NFMDemodSink::processOneSample(Complex &ci) | |||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             m_squelchDelayLine.write(demod * m_discriCompensation); |             m_squelchDelayLine.write(demod); | ||||||
| 
 | 
 | ||||||
|             if (m_squelchCount < 2*m_squelchGate) { |             if (m_squelchCount < 2*m_squelchGate) { | ||||||
|                 m_squelchCount++; |                 m_squelchCount++; | ||||||
| @ -179,7 +179,7 @@ void NFMDemodSink::processOneSample(Complex &ci) | |||||||
|         { |         { | ||||||
|             if (m_settings.m_ctcssOn) |             if (m_settings.m_ctcssOn) | ||||||
|             { |             { | ||||||
|                 Real ctcss_sample = m_ctcssLowpass.filter(demod * m_discriCompensation); |                 Real ctcss_sample = m_ctcssLowpass.filter(demod); | ||||||
| 
 | 
 | ||||||
|                 if ((m_sampleCount & 7) == 7) // decimate 48k -> 6k
 |                 if ((m_sampleCount & 7) == 7) // decimate 48k -> 6k
 | ||||||
|                 { |                 { | ||||||
| @ -224,7 +224,7 @@ void NFMDemodSink::processOneSample(Complex &ci) | |||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 if (m_settings.m_highPass) { |                 if (m_settings.m_highPass) { | ||||||
|                     sample = m_bandpass.filter(m_squelchDelayLine.readBack(m_squelchGate)) * m_settings.m_volume; |                     sample = m_bandpass.filter(m_squelchDelayLine.readBack(m_squelchGate)) * m_settings.m_volume * 301.0f; | ||||||
|                 } else { |                 } else { | ||||||
|                     sample = m_lowpass.filter(m_squelchDelayLine.readBack(m_squelchGate)) * m_settings.m_volume * 301.0f; |                     sample = m_lowpass.filter(m_squelchDelayLine.readBack(m_squelchGate)) * m_settings.m_volume * 301.0f; | ||||||
|                 } |                 } | ||||||
| @ -375,17 +375,13 @@ void NFMDemodSink::applyAudioSampleRate(unsigned int sampleRate) | |||||||
| 
 | 
 | ||||||
|     if (sampleRate < 16000) { |     if (sampleRate < 16000) { | ||||||
|         m_afSquelch.setCoefficients(sampleRate/2000, 600, sampleRate, 200, 0, afSqTones_lowrate); // 0.5ms test period, 300ms average span, audio SR, 100ms attack, no decay
 |         m_afSquelch.setCoefficients(sampleRate/2000, 600, sampleRate, 200, 0, afSqTones_lowrate); // 0.5ms test period, 300ms average span, audio SR, 100ms attack, no decay
 | ||||||
| 
 |  | ||||||
|     } else { |     } else { | ||||||
|         m_afSquelch.setCoefficients(sampleRate/2000, 600, sampleRate, 200, 0, afSqTones); // 0.5ms test period, 300ms average span, audio SR, 100ms attack, no decay
 |         m_afSquelch.setCoefficients(sampleRate/2000, 600, sampleRate, 200, 0, afSqTones); // 0.5ms test period, 300ms average span, audio SR, 100ms attack, no decay
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     m_discriCompensation = (sampleRate/48000.0f); |  | ||||||
|     m_discriCompensation *= sqrt(m_discriCompensation); |  | ||||||
| 
 |  | ||||||
|     m_phaseDiscri.setFMScaling((8.0f*sampleRate) / static_cast<float>(m_settings.m_fmDeviation)); // integrate 4x factor
 |     m_phaseDiscri.setFMScaling((8.0f*sampleRate) / static_cast<float>(m_settings.m_fmDeviation)); // integrate 4x factor
 | ||||||
|     m_audioFifo.setSize(sampleRate); |     m_audioFifo.setSize(sampleRate); | ||||||
|     m_squelchDelayLine.resize(sampleRate/2); |     m_squelchDelayLine.resize(sampleRate/2); | ||||||
| 
 | 
 | ||||||
|     m_audioSampleRate = sampleRate; |     m_audioSampleRate = sampleRate; | ||||||
| } | } | ||||||
|  | |||||||
| @ -104,8 +104,6 @@ private: | |||||||
|     uint m_audioBufferFill; |     uint m_audioBufferFill; | ||||||
|     AudioFifo m_audioFifo; |     AudioFifo m_audioFifo; | ||||||
| 
 | 
 | ||||||
| 	float m_discriCompensation; //!< compensation factor that depends on audio rate (1 for 48 kS/s)
 |  | ||||||
| 
 |  | ||||||
| 	NCO m_nco; | 	NCO m_nco; | ||||||
| 	Interpolator m_interpolator; | 	Interpolator m_interpolator; | ||||||
| 	Real m_interpolatorDistance; | 	Real m_interpolatorDistance; | ||||||
|  | |||||||
| @ -256,7 +256,6 @@ void UDPSinkSink::feed(const SampleVector::const_iterator& begin, const SampleVe | |||||||
|                 { |                 { | ||||||
|                     double demodf = sqrt(inMagSq); |                     double demodf = sqrt(inMagSq); | ||||||
|                     demodf = m_bandpass.filter(demodf); |                     demodf = m_bandpass.filter(demodf); | ||||||
|                     demodf /= 301.0; |  | ||||||
|                     Real amplitude = demodf * agcFactor * m_settings.m_gain; |                     Real amplitude = demodf * agcFactor * m_settings.m_gain; | ||||||
|                     FixReal demod = (FixReal) amplitude; |                     FixReal demod = (FixReal) amplitude; | ||||||
|                     udpWriteMono(demod); |                     udpWriteMono(demod); | ||||||
|  | |||||||
| @ -134,14 +134,11 @@ void NFMModSource::modulateSample() | |||||||
|     calculateLevel(t); |     calculateLevel(t); | ||||||
|     m_audioBufferFill++; |     m_audioBufferFill++; | ||||||
| 
 | 
 | ||||||
|     if (m_settings.m_ctcssOn) |     // 0.625 = 1/1.25 (heuristic)
 | ||||||
|     { |     if (m_settings.m_ctcssOn) { | ||||||
|         m_modPhasor += (m_settings.m_fmDeviation / (float) m_audioSampleRate) * (0.85f * m_bandpass.filter(t) + 0.15f * 189.0f * m_ctcssNco.next()) * (M_PI / 189.0f); |         m_modPhasor += (m_settings.m_fmDeviation / (float) m_audioSampleRate) * (0.85f * m_bandpass.filter(t) + 0.15f * 0.625f * m_ctcssNco.next()) * (M_PI / 0.625f); | ||||||
|     } |     } else { | ||||||
|     else |         m_modPhasor += (m_settings.m_fmDeviation / (float) m_audioSampleRate) * m_bandpass.filter(t) * (M_PI / 0.625f); | ||||||
|     { |  | ||||||
|         // 378 = 302 * 1.25; 302 = number of filter taps (established experimentally) and 189 = 378/2 for 2*PI
 |  | ||||||
|         m_modPhasor += (m_settings.m_fmDeviation / (float) m_audioSampleRate) * m_bandpass.filter(t) * (M_PI / 189.0f); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // limit phasor range to ]-pi,pi]
 |     // limit phasor range to ]-pi,pi]
 | ||||||
| @ -368,4 +365,4 @@ void NFMModSource::applyChannelSettings(int channelSampleRate, int channelFreque | |||||||
| 
 | 
 | ||||||
|     m_channelSampleRate = channelSampleRate; |     m_channelSampleRate = channelSampleRate; | ||||||
|     m_channelFrequencyOffset = channelFrequencyOffset; |     m_channelFrequencyOffset = channelFrequencyOffset; | ||||||
| } | } | ||||||
|  | |||||||
| @ -23,27 +23,34 @@ public: | |||||||
| 		int i; | 		int i; | ||||||
| 
 | 
 | ||||||
| 		// check constraints
 | 		// check constraints
 | ||||||
| 		if(!(nTaps & 1)) { | 		if (!(nTaps & 1)) | ||||||
|  | 		{ | ||||||
| 			qDebug("Bandpass filter has to have an odd number of taps"); | 			qDebug("Bandpass filter has to have an odd number of taps"); | ||||||
| 			nTaps++; | 			nTaps++; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// make room
 | 		// make room
 | ||||||
| 		m_samples.resize(nTaps); | 		m_samples.resize(nTaps); | ||||||
| 		for(int i = 0; i < nTaps; i++) | 
 | ||||||
|  | 		for (int i = 0; i < nTaps; i++) { | ||||||
| 			m_samples[i] = 0; | 			m_samples[i] = 0; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		m_ptr = 0; | 		m_ptr = 0; | ||||||
| 		m_taps.resize(nTaps / 2 + 1); | 		m_taps.resize(nTaps / 2 + 1); | ||||||
| 		taps_lp.resize(nTaps / 2 + 1); | 		taps_lp.resize(nTaps / 2 + 1); | ||||||
| 		taps_hp.resize(nTaps / 2 + 1); | 		taps_hp.resize(nTaps / 2 + 1); | ||||||
| 
 | 
 | ||||||
| 		// generate Sinc filter core
 | 		// generate Sinc filter core
 | ||||||
| 		for(i = 0; i < nTaps / 2 + 1; i++) { | 		for (i = 0; i < nTaps / 2 + 1; i++) | ||||||
| 			if(i == (nTaps - 1) / 2) { | 		{ | ||||||
|  | 			if (i == (nTaps - 1) / 2) | ||||||
|  | 			{ | ||||||
| 				taps_lp[i] = Wch / M_PI; | 				taps_lp[i] = Wch / M_PI; | ||||||
| 				taps_hp[i] = -(Wcl / M_PI); | 				taps_hp[i] = -(Wcl / M_PI); | ||||||
| 			} | 			} | ||||||
| 			else { | 			else | ||||||
|  | 			{ | ||||||
| 				taps_lp[i] = sin(((double)i - ((double)nTaps - 1.0) / 2.0) * Wch) / (((double)i - ((double)nTaps - 1.0) / 2.0) * M_PI); | 				taps_lp[i] = sin(((double)i - ((double)nTaps - 1.0) / 2.0) * Wch) / (((double)i - ((double)nTaps - 1.0) / 2.0) * M_PI); | ||||||
| 				taps_hp[i] = -sin(((double)i - ((double)nTaps - 1.0) / 2.0) * Wcl) / (((double)i - ((double)nTaps - 1.0) / 2.0) * M_PI); | 				taps_hp[i] = -sin(((double)i - ((double)nTaps - 1.0) / 2.0) * Wcl) / (((double)i - ((double)nTaps - 1.0) / 2.0) * M_PI); | ||||||
| 			} | 			} | ||||||
| @ -52,7 +59,8 @@ public: | |||||||
| 		taps_hp[(nTaps - 1) / 2] += 1; | 		taps_hp[(nTaps - 1) / 2] += 1; | ||||||
| 
 | 
 | ||||||
| 		// apply Hamming window and combine lowpass and highpass
 | 		// apply Hamming window and combine lowpass and highpass
 | ||||||
| 		for(i = 0; i < nTaps / 2 + 1; i++) { | 		for (i = 0; i < nTaps / 2 + 1; i++) | ||||||
|  | 		{ | ||||||
| 			taps_lp[i] *= 0.54 + 0.46 * cos((2.0 * M_PI * ((double)i - ((double)nTaps - 1.0) / 2.0)) / (double)nTaps); | 			taps_lp[i] *= 0.54 + 0.46 * cos((2.0 * M_PI * ((double)i - ((double)nTaps - 1.0) / 2.0)) / (double)nTaps); | ||||||
| 			taps_hp[i] *= 0.54 + 0.46 * cos((2.0 * M_PI * ((double)i - ((double)nTaps - 1.0) / 2.0)) / (double)nTaps); | 			taps_hp[i] *= 0.54 + 0.46 * cos((2.0 * M_PI * ((double)i - ((double)nTaps - 1.0) / 2.0)) / (double)nTaps); | ||||||
| 			m_taps[i] = -(taps_lp[i]+taps_hp[i]); | 			m_taps[i] = -(taps_lp[i]+taps_hp[i]); | ||||||
| @ -63,13 +71,13 @@ public: | |||||||
| 		// normalize
 | 		// normalize
 | ||||||
| 		Real sum = 0; | 		Real sum = 0; | ||||||
| 
 | 
 | ||||||
| 		for(i = 0; i < (int)m_taps.size() - 1; i++) { | 		for (i = 0; i < (int)m_taps.size() - 1; i++) { | ||||||
| 			sum += m_taps[i] * 2; | 			sum += m_taps[i] * 2; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		sum += m_taps[i]; | 		sum += m_taps[i] - 1; | ||||||
| 
 | 
 | ||||||
| 		for(i = 0; i < (int)m_taps.size(); i++) { | 		for (i = 0; i < (int)m_taps.size(); i++) { | ||||||
| 			m_taps[i] /= sum; | 			m_taps[i] /= sum; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @ -84,8 +92,7 @@ public: | |||||||
| 		m_samples[m_ptr] = sample; | 		m_samples[m_ptr] = sample; | ||||||
| 		size = m_samples.size(); // Valgrind optim (2)
 | 		size = m_samples.size(); // Valgrind optim (2)
 | ||||||
| 
 | 
 | ||||||
| 		while(b < 0) | 		while (b < 0) { | ||||||
| 		{ |  | ||||||
| 			b += size; | 			b += size; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @ -96,15 +103,13 @@ public: | |||||||
| 			acc += (m_samples[a] + m_samples[b]) * m_taps[i]; | 			acc += (m_samples[a] + m_samples[b]) * m_taps[i]; | ||||||
| 			a++; | 			a++; | ||||||
| 
 | 
 | ||||||
| 			while (a >= size) | 			while (a >= size) { | ||||||
| 			{ |  | ||||||
| 				a -= size; | 				a -= size; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			b--; | 			b--; | ||||||
| 
 | 
 | ||||||
| 			while(b < 0) | 			while(b < 0) { | ||||||
| 			{ |  | ||||||
| 				b += size; | 				b += size; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -113,8 +118,7 @@ public: | |||||||
| 
 | 
 | ||||||
| 		m_ptr++; | 		m_ptr++; | ||||||
| 
 | 
 | ||||||
| 		while (m_ptr >= size) | 		while (m_ptr >= size) { | ||||||
| 		{ |  | ||||||
| 			m_ptr -= size; | 			m_ptr -= size; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -16,39 +16,51 @@ public: | |||||||
| 		int i; | 		int i; | ||||||
| 
 | 
 | ||||||
| 		// check constraints
 | 		// check constraints
 | ||||||
| 		if(!(nTaps & 1)) { | 		if (!(nTaps & 1)) | ||||||
|  | 		{ | ||||||
| 			qDebug("Highpass filter has to have an odd number of taps"); | 			qDebug("Highpass filter has to have an odd number of taps"); | ||||||
| 			nTaps++; | 			nTaps++; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// make room
 | 		// make room
 | ||||||
| 		m_samples.resize(nTaps); | 		m_samples.resize(nTaps); | ||||||
| 		for(int i = 0; i < nTaps; i++) | 
 | ||||||
|  | 		for (int i = 0; i < nTaps; i++) { | ||||||
| 			m_samples[i] = 0; | 			m_samples[i] = 0; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		m_ptr = 0; | 		m_ptr = 0; | ||||||
| 		m_taps.resize(nTaps / 2 + 1); | 		m_taps.resize(nTaps / 2 + 1); | ||||||
| 
 | 
 | ||||||
| 		// generate Sinc filter core for lowpass but inverting every other tap for highpass keeping center tap
 | 		// generate Sinc filter core for lowpass but inverting every other tap for highpass keeping center tap
 | ||||||
| 		for(i = 0; i < nTaps / 2 + 1; i++) { | 		for (i = 0; i < nTaps / 2 + 1; i++) | ||||||
| 			if(i == (nTaps - 1) / 2) | 		{ | ||||||
|  | 			if (i == (nTaps - 1) / 2) { | ||||||
| 				m_taps[i] = -(Wc / M_PI); | 				m_taps[i] = -(Wc / M_PI); | ||||||
| 			else | 			} else { | ||||||
| 				m_taps[i] = -sin(((double)i - ((double)nTaps - 1.0) / 2.0) * Wc) / (((double)i - ((double)nTaps - 1.0) / 2.0) * M_PI); | 				m_taps[i] = -sin(((double)i - ((double)nTaps - 1.0) / 2.0) * Wc) / (((double)i - ((double)nTaps - 1.0) / 2.0) * M_PI); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		m_taps[(nTaps - 1) / 2] += 1; | 		m_taps[(nTaps - 1) / 2] += 1; | ||||||
| 
 | 
 | ||||||
| 		// apply Hamming window
 | 		// apply Hamming window
 | ||||||
| 		for(i = 0; i < nTaps / 2 + 1; i++) | 		for (i = 0; i < nTaps / 2 + 1; i++) { | ||||||
| 			m_taps[i] *= 0.54 + 0.46 * cos((2.0 * M_PI * ((double)i - ((double)nTaps - 1.0) / 2.0)) / (double)nTaps); | 			m_taps[i] *= 0.54 + 0.46 * cos((2.0 * M_PI * ((double)i - ((double)nTaps - 1.0) / 2.0)) / (double)nTaps); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		// normalize
 | 		// normalize
 | ||||||
| 		Real sum = 0; | 		Real sum = 0; | ||||||
| 		for(i = 0; i < (int)m_taps.size() - 1; i++) | 
 | ||||||
|  | 		for (i = 0; i < (int)m_taps.size() - 1; i++) { | ||||||
| 			sum += m_taps[i] * 2; | 			sum += m_taps[i] * 2; | ||||||
| 		sum += m_taps[i]; | 		} | ||||||
| 		for(i = 0; i < (int)m_taps.size(); i++) | 
 | ||||||
|  | 		sum += m_taps[i] - 1; | ||||||
|  | 
 | ||||||
|  | 		for (i = 0; i < (int)m_taps.size(); i++) { | ||||||
| 			m_taps[i] /= sum; | 			m_taps[i] /= sum; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	Type filter(Type sample) | 	Type filter(Type sample) | ||||||
| @ -61,8 +73,7 @@ public: | |||||||
| 		m_samples[m_ptr] = sample; | 		m_samples[m_ptr] = sample; | ||||||
| 		size = m_samples.size(); // Valgrind optim (2)
 | 		size = m_samples.size(); // Valgrind optim (2)
 | ||||||
| 
 | 
 | ||||||
| 		while(b < 0) | 		while (b < 0) { | ||||||
| 		{ |  | ||||||
| 			b += size; | 			b += size; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @ -73,15 +84,13 @@ public: | |||||||
| 			acc +=  (m_samples[a] + m_samples[b]) * m_taps[i]; | 			acc +=  (m_samples[a] + m_samples[b]) * m_taps[i]; | ||||||
| 			a++; | 			a++; | ||||||
| 
 | 
 | ||||||
| 			while (a >= size) | 			while (a >= size) { | ||||||
| 			{ |  | ||||||
| 				a -= size; | 				a -= size; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			b--; | 			b--; | ||||||
| 
 | 
 | ||||||
| 			while (b < 0) | 			while (b < 0) { | ||||||
| 			{ |  | ||||||
| 				b += size; | 				b += size; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -89,8 +98,7 @@ public: | |||||||
| 		acc += m_samples[a] * m_taps[i]; | 		acc += m_samples[a] * m_taps[i]; | ||||||
| 		m_ptr++; | 		m_ptr++; | ||||||
| 
 | 
 | ||||||
| 		while (m_ptr >= size) | 		while (m_ptr >= size) { | ||||||
| 		{ |  | ||||||
| 			m_ptr -= size; | 			m_ptr -= size; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -16,37 +16,49 @@ public: | |||||||
| 		int i; | 		int i; | ||||||
| 
 | 
 | ||||||
| 		// check constraints
 | 		// check constraints
 | ||||||
| 		if(!(nTaps & 1)) { | 		if (!(nTaps & 1)) | ||||||
|  | 		{ | ||||||
| 			qDebug("Lowpass filter has to have an odd number of taps"); | 			qDebug("Lowpass filter has to have an odd number of taps"); | ||||||
| 			nTaps++; | 			nTaps++; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// make room
 | 		// make room
 | ||||||
| 		m_samples.resize(nTaps); | 		m_samples.resize(nTaps); | ||||||
| 		for(int i = 0; i < nTaps; i++) | 
 | ||||||
|  | 		for (int i = 0; i < nTaps; i++) { | ||||||
| 			m_samples[i] = 0; | 			m_samples[i] = 0; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		m_ptr = 0; | 		m_ptr = 0; | ||||||
| 		m_taps.resize(nTaps / 2 + 1); | 		m_taps.resize(nTaps / 2 + 1); | ||||||
| 
 | 
 | ||||||
| 		// generate Sinc filter core
 | 		// generate Sinc filter core
 | ||||||
| 		for(i = 0; i < nTaps / 2 + 1; i++) { | 		for (i = 0; i < nTaps / 2 + 1; i++) | ||||||
| 			if(i == (nTaps - 1) / 2) | 		{ | ||||||
|  | 			if(i == (nTaps - 1) / 2) { | ||||||
| 				m_taps[i] = Wc / M_PI; | 				m_taps[i] = Wc / M_PI; | ||||||
| 			else | 			} else { | ||||||
| 				m_taps[i] = sin(((double)i - ((double)nTaps - 1.0) / 2.0) * Wc) / (((double)i - ((double)nTaps - 1.0) / 2.0) * M_PI); | 				m_taps[i] = sin(((double)i - ((double)nTaps - 1.0) / 2.0) * Wc) / (((double)i - ((double)nTaps - 1.0) / 2.0) * M_PI); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// apply Hamming window
 | 		// apply Hamming window
 | ||||||
| 		for(i = 0; i < nTaps / 2 + 1; i++) | 		for (i = 0; i < nTaps / 2 + 1; i++) { | ||||||
| 			m_taps[i] *= 0.54 + 0.46 * cos((2.0 * M_PI * ((double)i - ((double)nTaps - 1.0) / 2.0)) / (double)nTaps); | 			m_taps[i] *= 0.54 + 0.46 * cos((2.0 * M_PI * ((double)i - ((double)nTaps - 1.0) / 2.0)) / (double)nTaps); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		// normalize
 | 		// normalize
 | ||||||
| 		Real sum = 0; | 		Real sum = 0; | ||||||
| 		for(i = 0; i < (int)m_taps.size() - 1; i++) | 
 | ||||||
|  | 		for (i = 0; i < (int)m_taps.size() - 1; i++) { | ||||||
| 			sum += m_taps[i] * 2; | 			sum += m_taps[i] * 2; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		sum += m_taps[i]; | 		sum += m_taps[i]; | ||||||
| 		for(i = 0; i < (int)m_taps.size(); i++) | 
 | ||||||
|  | 		for (i = 0; i < (int)m_taps.size(); i++) { | ||||||
| 			m_taps[i] /= sum; | 			m_taps[i] /= sum; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	Type filter(Type sample) | 	Type filter(Type sample) | ||||||
| @ -59,8 +71,7 @@ public: | |||||||
| 		m_samples[m_ptr] = sample; | 		m_samples[m_ptr] = sample; | ||||||
| 		size = m_samples.size(); // Valgrind optim (2)
 | 		size = m_samples.size(); // Valgrind optim (2)
 | ||||||
| 
 | 
 | ||||||
| 		while (b < 0) | 		while (b < 0) { | ||||||
| 		{ |  | ||||||
| 			b += size; | 			b += size; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @ -71,15 +82,13 @@ public: | |||||||
| 			acc += (m_samples[a] + m_samples[b]) * m_taps[i]; | 			acc += (m_samples[a] + m_samples[b]) * m_taps[i]; | ||||||
| 			a++; | 			a++; | ||||||
| 
 | 
 | ||||||
| 			while (a >= size) | 			while (a >= size) { | ||||||
| 			{ |  | ||||||
| 				a -= size; | 				a -= size; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			b--; | 			b--; | ||||||
| 
 | 
 | ||||||
| 			while(b < 0) | 			while(b < 0) { | ||||||
| 			{ |  | ||||||
| 				b += size; | 				b += size; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -87,8 +96,7 @@ public: | |||||||
| 		acc += m_samples[a] * m_taps[i]; | 		acc += m_samples[a] * m_taps[i]; | ||||||
| 		m_ptr++; | 		m_ptr++; | ||||||
| 
 | 
 | ||||||
| 		while(m_ptr >= size) | 		while(m_ptr >= size) { | ||||||
| 		{ |  | ||||||
| 			m_ptr -= size; | 			m_ptr -= size; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user