1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-04-04 18:48:34 -04:00

BFM demod: implemented phase discriminator in a separate utility class

This commit is contained in:
f4exb 2015-12-17 01:13:42 +01:00
parent 90552271f8
commit bf926ede36
3 changed files with 10 additions and 36 deletions

View File

@ -37,8 +37,7 @@ BFMDemod::BFMDemod(SampleSink* sampleSink, RDSParser *rdsParser) :
m_pilotPLL(19000/384000, 50/384000, 0.01),
m_deemphasisFilterX(default_deemphasis * 48000 * 1.0e-6),
m_deemphasisFilterY(default_deemphasis * 48000 * 1.0e-6),
m_fmExcursion(default_excursion),
m_fmScaling(384000/m_fmExcursion)
m_fmExcursion(default_excursion)
{
setObjectName("BFMDemod");
@ -52,6 +51,7 @@ BFMDemod::BFMDemod(SampleSink* sampleSink, RDSParser *rdsParser) :
m_deemphasisFilterX.configure(default_deemphasis * m_config.m_audioSampleRate * 1.0e-6);
m_deemphasisFilterY.configure(default_deemphasis * m_config.m_audioSampleRate * 1.0e-6);
m_rfFilter = new fftfilt(-50000.0 / 384000.0, 50000.0 / 384000.0, rfFilterFftLength);
m_phaseDiscri.setFMScaling(384000/m_fmExcursion);
apply();
@ -124,7 +124,7 @@ void BFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
m_squelchState--;
//demod = phaseDiscriminator2(rf[i], msq);
demod = phaseDiscriminator(rf[i]);
demod = m_phaseDiscri.phaseDiscriminator(rf[i]);
}
else
{
@ -248,7 +248,7 @@ void BFMDemod::start()
{
m_squelchState = 0;
m_audioFifo.clear();
m_m1Sample = 0;
m_phaseDiscri.reset();
}
void BFMDemod::stop()
@ -354,7 +354,7 @@ void BFMDemod::apply()
Real lowCut = -(m_config.m_rfBandwidth / 2.0) / m_config.m_inputSampleRate;
Real hiCut = (m_config.m_rfBandwidth / 2.0) / m_config.m_inputSampleRate;
m_rfFilter->create_filter(lowCut, hiCut);
m_fmScaling = m_config.m_inputSampleRate / m_fmExcursion;
m_phaseDiscri.setFMScaling(m_config.m_inputSampleRate / m_fmExcursion);
m_settingsMutex.unlock();
qDebug() << "BFMDemod::handleMessage: m_rfFilter->create_filter: sampleRate: "

View File

@ -28,6 +28,7 @@
#include "dsp/fftfilt.h"
#include "dsp/phaselock.h"
#include "dsp/filterrc.h"
#include "dsp/phasediscri.h"
#include "audio/audiofifo.h"
#include "util/message.h"
#include "rdsdemod.h"
@ -184,8 +185,6 @@ private:
Real m_squelchLevel;
int m_squelchState;
Complex m_m1Sample; //!< x^-1 complex sample
Complex m_m2Sample; //!< x^-2 complex sample
Real m_m1Arg; //!> x^-1 real sample
MovingAverage<Real> m_movingAverage;
@ -210,37 +209,9 @@ private:
static const Real default_deemphasis = 50.0; // 50 us
Real m_fmExcursion;
Real m_fmScaling;
static const int default_excursion = 750000; // +/- 75 kHz
/**
* Standard discriminator using atan2. On modern processors this is as efficient as the non atan2 one.
* This is better for high fidelity.
*/
Real phaseDiscriminator(const Complex& sample)
{
Complex d(std::conj(m_m1Sample) * sample);
m_m1Sample = sample;
return (std::atan2(d.imag(), d.real()) / M_PI_2) * m_fmScaling;
}
/**
* Alternative without atan at the expense of a slight distorsion on very wideband signals
* http://www.embedded.com/design/configurable-systems/4212086/DSP-Tricks--Frequency-demodulation-algorithms-
* in addition it needs scaling by instantaneous magnitude squared and volume (0..10) adjustment factor
*/
Real phaseDiscriminator2(const Complex& sample, Real msq)
{
Real ip = sample.real() - m_m2Sample.real();
Real qp = sample.imag() - m_m2Sample.imag();
Real h1 = m_m1Sample.real() * qp;
Real h2 = m_m1Sample.imag() * ip;
m_m2Sample = m_m1Sample;
m_m1Sample = sample;
return ((h1 - h2) / (msq * M_PI)) * m_fmScaling;
}
PhaseDiscriminators m_phaseDiscri;
void apply();
};

View File

@ -243,6 +243,9 @@
<property name="maximum">
<number>100</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>20</number>
</property>