mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-29 11:18:56 -05:00
Merge pull request #690 from kasper93/rf_filter
NFMDemod: Add RF filter for freq deviation
This commit is contained in:
commit
a47416041f
@ -11,6 +11,8 @@ set(CMAKE_CXX_STANDARD 11)
|
|||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
# configure version
|
# configure version
|
||||||
set(sdrangel_VERSION_MAJOR "4")
|
set(sdrangel_VERSION_MAJOR "4")
|
||||||
set(sdrangel_VERSION_MINOR "21")
|
set(sdrangel_VERSION_MINOR "21")
|
||||||
@ -207,7 +209,7 @@ elseif (WIN32)
|
|||||||
|
|
||||||
# compile with full multicore
|
# compile with full multicore
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
add_compile_definitions(/MP)
|
add_compile_options(/MP)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# in alternative we can use ExternalProject
|
# in alternative we can use ExternalProject
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
|
|
||||||
const double NFMDemodSink::afSqTones[] = {1000.0, 6000.0}; // {1200.0, 8000.0};
|
const double NFMDemodSink::afSqTones[] = {1000.0, 6000.0}; // {1200.0, 8000.0};
|
||||||
const double NFMDemodSink::afSqTones_lowrate[] = {1000.0, 3500.0};
|
const double NFMDemodSink::afSqTones_lowrate[] = {1000.0, 3500.0};
|
||||||
|
const unsigned NFMDemodSink::FFT_FILTER_LENGTH = 1024;
|
||||||
|
const unsigned NFMDemodSink::CTCSS_DETECTOR_RATE = 6000;
|
||||||
|
|
||||||
NFMDemodSink::NFMDemodSink() :
|
NFMDemodSink::NFMDemodSink() :
|
||||||
m_channelSampleRate(48000),
|
m_channelSampleRate(48000),
|
||||||
@ -42,13 +44,15 @@ NFMDemodSink::NFMDemodSink() :
|
|||||||
m_audioSampleRate(48000),
|
m_audioSampleRate(48000),
|
||||||
m_audioBufferFill(0),
|
m_audioBufferFill(0),
|
||||||
m_audioFifo(48000),
|
m_audioFifo(48000),
|
||||||
|
m_rfFilter(FFT_FILTER_LENGTH),
|
||||||
m_ctcssIndex(0),
|
m_ctcssIndex(0),
|
||||||
m_sampleCount(0),
|
m_sampleCount(0),
|
||||||
m_squelchCount(0),
|
m_squelchCount(0),
|
||||||
m_squelchGate(4800),
|
m_squelchGate(4800),
|
||||||
m_filterTaps(48000 / 48 + 1),
|
m_filterTaps((48000 / 48) | 1),
|
||||||
m_squelchLevel(-990),
|
m_squelchLevel(-990),
|
||||||
m_squelchOpen(false),
|
m_squelchOpen(false),
|
||||||
|
m_afSquelchOpen(false),
|
||||||
m_magsq(0.0f),
|
m_magsq(0.0f),
|
||||||
m_magsqSum(0.0f),
|
m_magsqSum(0.0f),
|
||||||
m_magsqPeak(0.0f),
|
m_magsqPeak(0.0f),
|
||||||
@ -57,55 +61,57 @@ NFMDemodSink::NFMDemodSink() :
|
|||||||
m_squelchDelayLine(24000),
|
m_squelchDelayLine(24000),
|
||||||
m_messageQueueToGUI(nullptr)
|
m_messageQueueToGUI(nullptr)
|
||||||
{
|
{
|
||||||
m_agcLevel = 1.0;
|
|
||||||
m_audioBuffer.resize(1<<16);
|
m_audioBuffer.resize(1<<16);
|
||||||
m_phaseDiscri.setFMScaling(0.5f);
|
|
||||||
|
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, true);
|
||||||
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
|
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
NFMDemodSink::~NFMDemodSink()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void NFMDemodSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
|
void NFMDemodSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
|
||||||
{
|
{
|
||||||
Complex ci;
|
for (SampleVector::const_iterator it = begin; it != end; ++it)
|
||||||
|
{
|
||||||
|
Complex c(it->real(), it->imag());
|
||||||
|
c *= m_nco.nextIQ();
|
||||||
|
|
||||||
for (SampleVector::const_iterator it = begin; it != end; ++it)
|
Complex ci;
|
||||||
{
|
fftfilt::cmplx *rf;
|
||||||
Complex c(it->real(), it->imag());
|
int rf_out = m_rfFilter.runFilt(c, &rf); // filter RF before demod
|
||||||
c *= m_nco.nextIQ();
|
for (int i = 0 ; i < rf_out; i++)
|
||||||
|
|
||||||
if (m_interpolatorDistance < 1.0f) // interpolate
|
|
||||||
{
|
{
|
||||||
while (!m_interpolator.interpolate(&m_interpolatorDistanceRemain, c, &ci))
|
if (m_interpolatorDistance == 1.0f)
|
||||||
{
|
{
|
||||||
processOneSample(ci);
|
processOneSample(rf[i]);
|
||||||
m_interpolatorDistanceRemain += m_interpolatorDistance;
|
|
||||||
}
|
}
|
||||||
}
|
else if (m_interpolatorDistance < 1.0f) // interpolate
|
||||||
else // decimate
|
|
||||||
{
|
|
||||||
if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci))
|
|
||||||
{
|
{
|
||||||
processOneSample(ci);
|
while (!m_interpolator.interpolate(&m_interpolatorDistanceRemain, rf[i], &ci))
|
||||||
m_interpolatorDistanceRemain += m_interpolatorDistance;
|
{
|
||||||
|
processOneSample(ci);
|
||||||
|
m_interpolatorDistanceRemain += m_interpolatorDistance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // decimate
|
||||||
|
{
|
||||||
|
if (m_interpolator.decimate(&m_interpolatorDistanceRemain, rf[i], &ci))
|
||||||
|
{
|
||||||
|
processOneSample(ci);
|
||||||
|
m_interpolatorDistanceRemain += m_interpolatorDistance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_audioBufferFill > 0)
|
if (m_audioBufferFill > 0)
|
||||||
{
|
{
|
||||||
uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill);
|
uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill);
|
||||||
|
|
||||||
if (res != m_audioBufferFill) {
|
if (res != m_audioBufferFill) {
|
||||||
qDebug("NFMDemodSink::feed: %u/%u tail samples written", res, m_audioBufferFill);
|
qDebug("NFMDemodSink::feed: %u/%u tail samples written", res, m_audioBufferFill);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_audioBufferFill = 0;
|
m_audioBufferFill = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NFMDemodSink::processOneSample(Complex &ci)
|
void NFMDemodSink::processOneSample(Complex &ci)
|
||||||
@ -124,12 +130,12 @@ void NFMDemodSink::processOneSample(Complex &ci)
|
|||||||
m_magsqCount++;
|
m_magsqCount++;
|
||||||
m_sampleCount++;
|
m_sampleCount++;
|
||||||
|
|
||||||
bool squelchOpen = false;
|
bool squelchOpen = m_afSquelchOpen && m_settings.m_deltaSquelch;
|
||||||
if (m_settings.m_deltaSquelch)
|
if (m_settings.m_deltaSquelch)
|
||||||
{
|
{
|
||||||
if (m_afSquelch.analyze(demod))
|
if (m_afSquelch.analyze(demod))
|
||||||
{
|
{
|
||||||
squelchOpen = m_afSquelch.evaluate();
|
m_afSquelchOpen = squelchOpen = m_afSquelch.evaluate();
|
||||||
|
|
||||||
if (!squelchOpen) {
|
if (!squelchOpen) {
|
||||||
m_squelchDelayLine.zeroBack(m_audioSampleRate/10); // zero out evaluation period
|
m_squelchDelayLine.zeroBack(m_audioSampleRate/10); // zero out evaluation period
|
||||||
@ -164,12 +170,15 @@ void NFMDemodSink::processOneSample(Complex &ci)
|
|||||||
{
|
{
|
||||||
if (m_settings.m_ctcssOn)
|
if (m_settings.m_ctcssOn)
|
||||||
{
|
{
|
||||||
Real ctcssSample = m_ctcssLowpass.filter(demod);
|
int factor = (m_audioSampleRate / CTCSS_DETECTOR_RATE) - 1; // decimate -> 6k
|
||||||
int factor = (m_audioSampleRate / 6000) - 1; // decimate -> 6k
|
if ((m_sampleCount & factor) == factor)
|
||||||
if ((m_sampleCount & factor) == factor && m_ctcssDetector.analyze(&ctcssSample))
|
|
||||||
{
|
{
|
||||||
int maxToneIndex;
|
Real ctcssSample = m_ctcssLowpass.filter(demod);
|
||||||
ctcssIndex = m_ctcssDetector.getDetectedTone(maxToneIndex) ? maxToneIndex + 1 : 0;
|
if (m_ctcssDetector.analyze(&ctcssSample))
|
||||||
|
{
|
||||||
|
int maxToneIndex;
|
||||||
|
ctcssIndex = m_ctcssDetector.getDetectedTone(maxToneIndex) ? maxToneIndex + 1 : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,9 +236,13 @@ void NFMDemodSink::applyChannelSettings(int channelSampleRate, int channelFreque
|
|||||||
|
|
||||||
if ((channelSampleRate != m_channelSampleRate) || force)
|
if ((channelSampleRate != m_channelSampleRate) || force)
|
||||||
{
|
{
|
||||||
m_interpolator.create(16, channelSampleRate, m_settings.m_rfBandwidth / 2.2);
|
m_interpolator.create(16, channelSampleRate, m_settings.m_fmDeviation);
|
||||||
m_interpolatorDistanceRemain = 0;
|
m_interpolatorDistance = Real(channelSampleRate) / Real(m_audioSampleRate);
|
||||||
m_interpolatorDistance = (Real) channelSampleRate / (Real) m_audioSampleRate;
|
m_interpolatorDistanceRemain = m_interpolatorDistance;
|
||||||
|
|
||||||
|
Real lowCut = -Real(m_settings.m_fmDeviation) / channelSampleRate;
|
||||||
|
Real hiCut = Real(m_settings.m_fmDeviation) / channelSampleRate;
|
||||||
|
m_rfFilter.create_filter(lowCut, hiCut);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_channelSampleRate = channelSampleRate;
|
m_channelSampleRate = channelSampleRate;
|
||||||
@ -256,14 +269,16 @@ void NFMDemodSink::applySettings(const NFMDemodSettings& settings, bool force)
|
|||||||
|
|
||||||
if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force)
|
if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force)
|
||||||
{
|
{
|
||||||
m_interpolator.create(16, m_channelSampleRate, settings.m_rfBandwidth / 2.2);
|
m_interpolator.create(16, m_channelSampleRate, settings.m_fmDeviation);
|
||||||
m_interpolatorDistanceRemain = 0;
|
m_interpolatorDistance = Real(m_channelSampleRate) / Real(m_audioSampleRate);
|
||||||
m_interpolatorDistance = (Real) m_channelSampleRate / (Real) m_audioSampleRate;
|
m_interpolatorDistanceRemain = m_interpolatorDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((settings.m_fmDeviation != m_settings.m_fmDeviation) || force)
|
if ((settings.m_fmDeviation != m_settings.m_fmDeviation) || force) {
|
||||||
{
|
Real lowCut = -Real(settings.m_fmDeviation) / m_channelSampleRate;
|
||||||
m_phaseDiscri.setFMScaling((0.5f *m_audioSampleRate) / static_cast<float>(settings.m_fmDeviation)); // integrate 4x factor
|
Real hiCut = Real(settings.m_fmDeviation) / m_channelSampleRate;
|
||||||
|
m_rfFilter.create_filter(lowCut, hiCut);
|
||||||
|
m_phaseDiscri.setFMScaling(Real(m_audioSampleRate) / (2.0f * settings.m_fmDeviation));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((settings.m_afBandwidth != m_settings.m_afBandwidth) || force)
|
if ((settings.m_afBandwidth != m_settings.m_afBandwidth) || force)
|
||||||
@ -313,24 +328,25 @@ void NFMDemodSink::applyAudioSampleRate(unsigned int sampleRate)
|
|||||||
|
|
||||||
qDebug("NFMDemodSink::applyAudioSampleRate: %u m_channelSampleRate: %d", sampleRate, m_channelSampleRate);
|
qDebug("NFMDemodSink::applyAudioSampleRate: %u m_channelSampleRate: %d", sampleRate, m_channelSampleRate);
|
||||||
|
|
||||||
m_filterTaps = sampleRate / 48 + 1;
|
m_filterTaps = (sampleRate / 48) | 1;
|
||||||
m_ctcssLowpass.create(m_filterTaps, sampleRate, 250.0);
|
m_ctcssLowpass.create((CTCSS_DETECTOR_RATE / 48) | 1, CTCSS_DETECTOR_RATE, 250.0);
|
||||||
m_bandpass.create(m_filterTaps, sampleRate, 300.0, m_settings.m_afBandwidth);
|
m_bandpass.create(m_filterTaps, sampleRate, 300.0, m_settings.m_afBandwidth);
|
||||||
m_lowpass.create(m_filterTaps, sampleRate, m_settings.m_afBandwidth);
|
m_lowpass.create(m_filterTaps, sampleRate, m_settings.m_afBandwidth);
|
||||||
m_squelchGate = (sampleRate / 100) * m_settings.m_squelchGate; // gate is given in 10s of ms at 48000 Hz audio sample rate
|
m_squelchGate = (sampleRate / 100) * m_settings.m_squelchGate; // gate is given in 10s of ms at 48000 Hz audio sample rate
|
||||||
m_squelchCount = 0; // reset squelch open counter
|
m_squelchCount = 0; // reset squelch open counter
|
||||||
m_ctcssDetector.setCoefficients(sampleRate/16, sampleRate/8.0f); // 0.5s / 2 Hz resolution
|
m_ctcssDetector.setCoefficients(sampleRate/16, CTCSS_DETECTOR_RATE); // 0.5s / 2 Hz resolution
|
||||||
|
|
||||||
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_afSquelch.setThreshold(m_squelchLevel);
|
||||||
|
|
||||||
m_phaseDiscri.setFMScaling((0.5f * sampleRate) / static_cast<float>(m_settings.m_fmDeviation));
|
m_phaseDiscri.setFMScaling(Real(sampleRate) / (2.0f * m_settings.m_fmDeviation));
|
||||||
m_audioFifo.setSize(sampleRate);
|
m_audioFifo.setSize(sampleRate);
|
||||||
m_squelchDelayLine.resize(sampleRate/2);
|
m_squelchDelayLine.resize(sampleRate/2);
|
||||||
m_interpolatorDistanceRemain = 0;
|
|
||||||
m_interpolatorDistance = Real(m_channelSampleRate) / Real(sampleRate);
|
m_interpolatorDistance = Real(m_channelSampleRate) / Real(sampleRate);
|
||||||
|
m_interpolatorDistanceRemain = m_interpolatorDistance;
|
||||||
m_audioSampleRate = sampleRate;
|
m_audioSampleRate = sampleRate;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "dsp/phasediscri.h"
|
#include "dsp/phasediscri.h"
|
||||||
#include "dsp/nco.h"
|
#include "dsp/nco.h"
|
||||||
#include "dsp/interpolator.h"
|
#include "dsp/interpolator.h"
|
||||||
|
#include "dsp/fftfilt.h"
|
||||||
#include "dsp/firfilter.h"
|
#include "dsp/firfilter.h"
|
||||||
#include "dsp/afsquelch.h"
|
#include "dsp/afsquelch.h"
|
||||||
#include "dsp/agc.h"
|
#include "dsp/agc.h"
|
||||||
@ -37,20 +38,19 @@
|
|||||||
class NFMDemodSink : public ChannelSampleSink {
|
class NFMDemodSink : public ChannelSampleSink {
|
||||||
public:
|
public:
|
||||||
NFMDemodSink();
|
NFMDemodSink();
|
||||||
~NFMDemodSink();
|
|
||||||
|
|
||||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
|
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
|
||||||
|
|
||||||
const Real *getCtcssToneSet(int& nbTones) const {
|
const Real *getCtcssToneSet(int& nbTones) const {
|
||||||
nbTones = m_ctcssDetector.getNTones();
|
nbTones = m_ctcssDetector.getNTones();
|
||||||
return m_ctcssDetector.getToneSet();
|
return m_ctcssDetector.getToneSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSelectedCtcssIndex(int selectedCtcssIndex) {
|
void setSelectedCtcssIndex(int selectedCtcssIndex) {
|
||||||
m_ctcssIndexSelected = selectedCtcssIndex;
|
m_ctcssIndexSelected = selectedCtcssIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getSquelchOpen() const { return m_squelchOpen; }
|
bool getSquelchOpen() const { return m_squelchOpen; }
|
||||||
|
|
||||||
void getMagSqLevels(double& avg, double& peak, int& nbSamples)
|
void getMagSqLevels(double& avg, double& peak, int& nbSamples)
|
||||||
{
|
{
|
||||||
@ -89,53 +89,56 @@ private:
|
|||||||
double m_magsqPeak;
|
double m_magsqPeak;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RateState {
|
enum RateState {
|
||||||
RSInitialFill,
|
RSInitialFill,
|
||||||
RSRunning
|
RSRunning
|
||||||
};
|
};
|
||||||
|
|
||||||
int m_channelSampleRate;
|
int m_channelSampleRate;
|
||||||
int m_channelFrequencyOffset;
|
int m_channelFrequencyOffset;
|
||||||
NFMDemodSettings m_settings;
|
NFMDemodSettings m_settings;
|
||||||
|
|
||||||
int m_audioSampleRate;
|
int m_audioSampleRate;
|
||||||
AudioVector m_audioBuffer;
|
AudioVector m_audioBuffer;
|
||||||
uint m_audioBufferFill;
|
uint m_audioBufferFill;
|
||||||
AudioFifo m_audioFifo;
|
AudioFifo m_audioFifo;
|
||||||
|
|
||||||
NCO m_nco;
|
NCO m_nco;
|
||||||
Interpolator m_interpolator;
|
Interpolator m_interpolator;
|
||||||
Real m_interpolatorDistance;
|
fftfilt m_rfFilter;
|
||||||
Real m_interpolatorDistanceRemain;
|
Real m_interpolatorDistance;
|
||||||
Lowpass<Real> m_ctcssLowpass;
|
Real m_interpolatorDistanceRemain;
|
||||||
Bandpass<Real> m_bandpass;
|
Lowpass<Real> m_ctcssLowpass;
|
||||||
|
Bandpass<Real> m_bandpass;
|
||||||
Lowpass<Real> m_lowpass;
|
Lowpass<Real> m_lowpass;
|
||||||
CTCSSDetector m_ctcssDetector;
|
CTCSSDetector m_ctcssDetector;
|
||||||
int m_ctcssIndex; // 0 for nothing detected
|
int m_ctcssIndex; // 0 for nothing detected
|
||||||
int m_ctcssIndexSelected;
|
int m_ctcssIndexSelected;
|
||||||
int m_sampleCount;
|
int m_sampleCount;
|
||||||
int m_squelchCount;
|
int m_squelchCount;
|
||||||
int m_squelchGate;
|
int m_squelchGate;
|
||||||
int m_filterTaps;
|
int m_filterTaps;
|
||||||
|
|
||||||
Real m_squelchLevel;
|
Real m_squelchLevel;
|
||||||
bool m_squelchOpen;
|
bool m_squelchOpen;
|
||||||
double m_magsq; //!< displayed averaged value
|
bool m_afSquelchOpen;
|
||||||
double m_magsqSum;
|
double m_magsq; //!< displayed averaged value
|
||||||
double m_magsqPeak;
|
double m_magsqSum;
|
||||||
|
double m_magsqPeak;
|
||||||
int m_magsqCount;
|
int m_magsqCount;
|
||||||
MagSqLevelsStore m_magSqLevelStore;
|
MagSqLevelsStore m_magSqLevelStore;
|
||||||
|
|
||||||
MovingAverageUtil<Real, double, 32> m_movingAverage;
|
MovingAverageUtil<Real, double, 32> m_movingAverage;
|
||||||
AFSquelch m_afSquelch;
|
AFSquelch m_afSquelch;
|
||||||
Real m_agcLevel; // AGC will aim to this level
|
DoubleBufferFIFO<Real> m_squelchDelayLine;
|
||||||
DoubleBufferFIFO<Real> m_squelchDelayLine;
|
|
||||||
|
|
||||||
PhaseDiscriminators m_phaseDiscri;
|
PhaseDiscriminators m_phaseDiscri;
|
||||||
MessageQueue *m_messageQueueToGUI;
|
MessageQueue *m_messageQueueToGUI;
|
||||||
|
|
||||||
static const double afSqTones[];
|
static const double afSqTones[];
|
||||||
static const double afSqTones_lowrate[];
|
static const double afSqTones_lowrate[];
|
||||||
|
static const unsigned FFT_FILTER_LENGTH;
|
||||||
|
static const unsigned CTCSS_DETECTOR_RATE;
|
||||||
|
|
||||||
void processOneSample(Complex &ci);
|
void processOneSample(Complex &ci);
|
||||||
MessageQueue *getMessageQueueToGUI() { return m_messageQueueToGUI; }
|
MessageQueue *getMessageQueueToGUI() { return m_messageQueueToGUI; }
|
||||||
|
@ -214,9 +214,9 @@ bool AFSquelch::evaluate()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// m_isOpen = ((minPower/maxPower < m_threshold) && (minIndex > maxIndex));
|
// m_isOpen = ((minPower/maxPower < m_threshold) && (minIndex > maxIndex));
|
||||||
|
|
||||||
if ((minPower/maxPower < m_threshold) && (minIndex > maxIndex)) // open condition
|
if ((minPower/maxPower < m_threshold) && (minIndex > maxIndex)) // open condition
|
||||||
{
|
{
|
||||||
|
|
||||||
if (m_squelchCount < m_samplesAttack + m_samplesDecay)
|
if (m_squelchCount < m_samplesAttack + m_samplesDecay)
|
||||||
{
|
{
|
||||||
m_squelchCount++;
|
m_squelchCount++;
|
||||||
|
@ -75,6 +75,14 @@ void fftfilt::init_filter()
|
|||||||
// f1 == 0 ==> low pass filter
|
// f1 == 0 ==> low pass filter
|
||||||
// f2 == 0 ==> high pass filter
|
// f2 == 0 ==> high pass filter
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
fftfilt::fftfilt(int len)
|
||||||
|
{
|
||||||
|
flen = len;
|
||||||
|
pass = 0;
|
||||||
|
window = 0;
|
||||||
|
init_filter();
|
||||||
|
}
|
||||||
|
|
||||||
fftfilt::fftfilt(float f1, float f2, int len)
|
fftfilt::fftfilt(float f1, float f2, int len)
|
||||||
{
|
{
|
||||||
flen = len;
|
flen = len;
|
||||||
|
@ -19,6 +19,7 @@ enum {NONE, BLACKMAN, HAMMING, HANNING};
|
|||||||
public:
|
public:
|
||||||
typedef std::complex<float> cmplx;
|
typedef std::complex<float> cmplx;
|
||||||
|
|
||||||
|
fftfilt(int len);
|
||||||
fftfilt(float f1, float f2, int len);
|
fftfilt(float f1, float f2, int len);
|
||||||
fftfilt(float f2, int len);
|
fftfilt(float f2, int len);
|
||||||
~fftfilt();
|
~fftfilt();
|
||||||
|
@ -42,24 +42,17 @@ public:
|
|||||||
|
|
||||||
m_samples[m_ptr] = sample;
|
m_samples[m_ptr] = sample;
|
||||||
|
|
||||||
for (size_t i = 0; i < n_taps; ++i)
|
for (int i = 0; i < n_taps; ++i)
|
||||||
{
|
{
|
||||||
acc += (m_samples[a++] + m_samples[b--]) * m_taps[i];
|
acc += (m_samples[a] + m_samples[b]) * m_taps[i];
|
||||||
|
|
||||||
if (a == n_samples) {
|
a = (a == n_samples - 1) ? 0 : a + 1;
|
||||||
a = 0;
|
b = (b == 0) ? n_samples - 1 : b - 1;
|
||||||
}
|
|
||||||
|
|
||||||
if (b == -1) {
|
|
||||||
b = n_samples - 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
acc += m_samples[a] * m_taps[n_taps];
|
acc += m_samples[a] * m_taps[n_taps];
|
||||||
|
|
||||||
if (++m_ptr == n_samples) {
|
m_ptr = (m_ptr == n_samples - 1) ? 0 : m_ptr + 1;
|
||||||
m_ptr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user