mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-23 01:55:48 -05:00
SSB demod: implemented basic AGC not optional
This commit is contained in:
parent
0ad14d3acf
commit
94704ab7b2
6
debian/changelog
vendored
6
debian/changelog
vendored
@ -1,3 +1,9 @@
|
|||||||
|
sdrangel (3.5.3-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* SSB demod: anded optional AGC
|
||||||
|
|
||||||
|
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sat, 28 Jul 2017 09:14:18 +0200
|
||||||
|
|
||||||
sdrangel (3.5.2-1) unstable; urgency=medium
|
sdrangel (3.5.2-1) unstable; urgency=medium
|
||||||
|
|
||||||
* HackRF: stop Rx before start Tx automatically and vice versa
|
* HackRF: stop Rx before start Tx automatically and vice versa
|
||||||
|
@ -43,7 +43,6 @@ NFMDemod::NFMDemod() :
|
|||||||
m_magsqSum(0.0f),
|
m_magsqSum(0.0f),
|
||||||
m_magsqPeak(0.0f),
|
m_magsqPeak(0.0f),
|
||||||
m_magsqCount(0),
|
m_magsqCount(0),
|
||||||
m_AGC(40, 0),
|
|
||||||
m_movingAverage(40, 0),
|
m_movingAverage(40, 0),
|
||||||
m_afSquelch(2, afSqTones),
|
m_afSquelch(2, afSqTones),
|
||||||
m_fmExcursion(2400),
|
m_fmExcursion(2400),
|
||||||
@ -71,7 +70,6 @@ NFMDemod::NFMDemod() :
|
|||||||
m_audioBufferFill = 0;
|
m_audioBufferFill = 0;
|
||||||
|
|
||||||
m_agcLevel = 1.0;
|
m_agcLevel = 1.0;
|
||||||
m_AGC.resize(m_squelchGate, m_agcLevel);
|
|
||||||
m_movingAverage.resize(32, 0);
|
m_movingAverage.resize(32, 0);
|
||||||
|
|
||||||
m_ctcssDetector.setCoefficients(3000, 6000.0); // 0.5s / 2 Hz resolution
|
m_ctcssDetector.setCoefficients(3000, 6000.0); // 0.5s / 2 Hz resolution
|
||||||
|
@ -231,7 +231,6 @@ private:
|
|||||||
Real m_lastArgument;
|
Real m_lastArgument;
|
||||||
//Complex m_m1Sample;
|
//Complex m_m1Sample;
|
||||||
//Complex m_m2Sample;
|
//Complex m_m2Sample;
|
||||||
MagAGC m_AGC;
|
|
||||||
MovingAverage<double> m_movingAverage;
|
MovingAverage<double> m_movingAverage;
|
||||||
AFSquelch m_afSquelch;
|
AFSquelch m_afSquelch;
|
||||||
Real m_agcLevel; // AGC will aim to this level
|
Real m_agcLevel; // AGC will aim to this level
|
||||||
|
@ -32,6 +32,7 @@ SSBDemod::SSBDemod(BasebandSampleSink* sampleSink) :
|
|||||||
m_audioFlipChannels(false),
|
m_audioFlipChannels(false),
|
||||||
m_dsb(false),
|
m_dsb(false),
|
||||||
m_audioMute(false),
|
m_audioMute(false),
|
||||||
|
m_agc(12000, 4.0, 1e-2),
|
||||||
m_sampleSink(sampleSink),
|
m_sampleSink(sampleSink),
|
||||||
m_audioFifo(4, 24000),
|
m_audioFifo(4, 24000),
|
||||||
m_settingsMutex(QMutex::Recursive)
|
m_settingsMutex(QMutex::Recursive)
|
||||||
@ -166,23 +167,25 @@ void SSBDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
double agcVal = m_agc.feedAndGetValue(sideband[i]);
|
||||||
|
|
||||||
if (m_audioBinaual)
|
if (m_audioBinaual)
|
||||||
{
|
{
|
||||||
if (m_audioFlipChannels)
|
if (m_audioFlipChannels)
|
||||||
{
|
{
|
||||||
m_audioBuffer[m_audioBufferFill].r = (qint16)(sideband[i].imag() * m_volume * 100);
|
m_audioBuffer[m_audioBufferFill].r = (qint16)(sideband[i].imag() * m_volume * agcVal * 100);
|
||||||
m_audioBuffer[m_audioBufferFill].l = (qint16)(sideband[i].real() * m_volume * 100);
|
m_audioBuffer[m_audioBufferFill].l = (qint16)(sideband[i].real() * m_volume * agcVal * 100);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_audioBuffer[m_audioBufferFill].r = (qint16)(sideband[i].real() * m_volume * 100);
|
m_audioBuffer[m_audioBufferFill].r = (qint16)(sideband[i].real() * m_volume * agcVal * 100);
|
||||||
m_audioBuffer[m_audioBufferFill].l = (qint16)(sideband[i].imag() * m_volume * 100);
|
m_audioBuffer[m_audioBufferFill].l = (qint16)(sideband[i].imag() * m_volume * agcVal * 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Real demod = (sideband[i].real() + sideband[i].imag()) * 0.7;
|
Real demod = (sideband[i].real() + sideband[i].imag()) * 0.7;
|
||||||
qint16 sample = (qint16)(demod * m_volume * 100);
|
qint16 sample = (qint16)(demod * m_volume * agcVal * 100);
|
||||||
m_audioBuffer[m_audioBufferFill].l = sample;
|
m_audioBuffer[m_audioBufferFill].l = sample;
|
||||||
m_audioBuffer[m_audioBufferFill].r = sample;
|
m_audioBuffer[m_audioBufferFill].r = sample;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "dsp/ncof.h"
|
#include "dsp/ncof.h"
|
||||||
#include "dsp/interpolator.h"
|
#include "dsp/interpolator.h"
|
||||||
#include "dsp/fftfilt.h"
|
#include "dsp/fftfilt.h"
|
||||||
|
#include "dsp/agc.h"
|
||||||
#include "audio/audiofifo.h"
|
#include "audio/audiofifo.h"
|
||||||
#include "util/message.h"
|
#include "util/message.h"
|
||||||
|
|
||||||
@ -142,6 +143,7 @@ private:
|
|||||||
double m_magsqSum;
|
double m_magsqSum;
|
||||||
double m_magsqPeak;
|
double m_magsqPeak;
|
||||||
int m_magsqCount;
|
int m_magsqCount;
|
||||||
|
MagAGC m_agc;
|
||||||
|
|
||||||
NCOF m_nco;
|
NCOF m_nco;
|
||||||
Interpolator m_interpolator;
|
Interpolator m_interpolator;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
const PluginDescriptor SSBPlugin::m_pluginDescriptor = {
|
const PluginDescriptor SSBPlugin::m_pluginDescriptor = {
|
||||||
QString("SSB Demodulator"),
|
QString("SSB Demodulator"),
|
||||||
QString("3.5.2"),
|
QString("3.5.3"),
|
||||||
QString("(c) Edouard Griffiths, F4EXB"),
|
QString("(c) Edouard Griffiths, F4EXB"),
|
||||||
QString("https://github.com/f4exb/sdrangel"),
|
QString("https://github.com/f4exb/sdrangel"),
|
||||||
true,
|
true,
|
||||||
|
@ -42,9 +42,10 @@ Real AGC::getAverage()
|
|||||||
// m_magsq(0.0)
|
// m_magsq(0.0)
|
||||||
//{}
|
//{}
|
||||||
|
|
||||||
MagSquaredAGC::MagSquaredAGC(int historySize, Real R) :
|
MagSquaredAGC::MagSquaredAGC(int historySize, double R, double threshold) :
|
||||||
AGC(historySize, R),
|
AGC(historySize, R),
|
||||||
m_magsq(0.0)
|
m_magsq(0.0),
|
||||||
|
m_threshold(threshold)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
MagSquaredAGC::~MagSquaredAGC()
|
MagSquaredAGC::~MagSquaredAGC()
|
||||||
@ -58,15 +59,23 @@ void MagSquaredAGC::feed(Complex& ci)
|
|||||||
ci *= m_u0;
|
ci *= m_u0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double MagSquaredAGC::feedAndGetValue(const Complex& ci)
|
||||||
|
{
|
||||||
|
m_magsq = ci.real()*ci.real() + ci.imag()*ci.imag();
|
||||||
|
m_moving_average.feed(m_magsq);
|
||||||
|
m_u0 = m_R / m_moving_average.average();
|
||||||
|
return m_magsq > m_threshold ? m_u0 : 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
//MagAGC::MagAGC() :
|
//MagAGC::MagAGC() :
|
||||||
// AGC(),
|
// AGC(),
|
||||||
// m_magsq(0.0)
|
// m_magsq(0.0)
|
||||||
//{}
|
//{}
|
||||||
|
|
||||||
MagAGC::MagAGC(int historySize, Real R) :
|
MagAGC::MagAGC(int historySize, double R, double threshold) :
|
||||||
AGC(historySize, R),
|
AGC(historySize, R),
|
||||||
m_magsq(0.0)
|
m_magsq(0.0),
|
||||||
|
m_threshold(threshold)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
MagAGC::~MagAGC()
|
MagAGC::~MagAGC()
|
||||||
@ -80,6 +89,13 @@ void MagAGC::feed(Complex& ci)
|
|||||||
ci *= m_u0;
|
ci *= m_u0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double MagAGC::feedAndGetValue(const Complex& ci)
|
||||||
|
{
|
||||||
|
m_magsq = ci.real()*ci.real() + ci.imag()*ci.imag();
|
||||||
|
m_moving_average.feed(m_magsq);
|
||||||
|
m_u0 = m_R / sqrt(m_moving_average.average());
|
||||||
|
return m_magsq > m_threshold ? m_u0 : 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
//AlphaAGC::AlphaAGC() :
|
//AlphaAGC::AlphaAGC() :
|
||||||
// AGC(),
|
// AGC(),
|
||||||
|
@ -22,8 +22,8 @@ public:
|
|||||||
virtual void feed(Complex& ci) = 0;
|
virtual void feed(Complex& ci) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Real m_u0;
|
double m_u0;
|
||||||
Real m_R; // objective mag
|
double m_R; // objective mag
|
||||||
MovingAverage<double> m_moving_average; // Averaging engine. The stack length conditions the smoothness of AGC.
|
MovingAverage<double> m_moving_average; // Averaging engine. The stack length conditions the smoothness of AGC.
|
||||||
int m_historySize;
|
int m_historySize;
|
||||||
int m_count;
|
int m_count;
|
||||||
@ -32,23 +32,27 @@ protected:
|
|||||||
class MagSquaredAGC : public AGC
|
class MagSquaredAGC : public AGC
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MagSquaredAGC(int historySize, Real R);
|
MagSquaredAGC(int historySize, double R, double threshold);
|
||||||
virtual ~MagSquaredAGC();
|
virtual ~MagSquaredAGC();
|
||||||
virtual void feed(Complex& ci);
|
virtual void feed(Complex& ci);
|
||||||
Real getMagSq() const { return m_magsq; }
|
double feedAndGetValue(const Complex& ci);
|
||||||
|
double getMagSq() const { return m_magsq; }
|
||||||
private:
|
private:
|
||||||
Real m_magsq;
|
double m_magsq;
|
||||||
|
double m_threshold;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MagAGC : public AGC
|
class MagAGC : public AGC
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MagAGC(int historySize, Real R);
|
MagAGC(int historySize, double R, double threshold);
|
||||||
virtual ~MagAGC();
|
virtual ~MagAGC();
|
||||||
virtual void feed(Complex& ci);
|
virtual void feed(Complex& ci);
|
||||||
|
double feedAndGetValue(const Complex& ci);
|
||||||
Real getMagSq() const { return m_magsq; }
|
Real getMagSq() const { return m_magsq; }
|
||||||
private:
|
private:
|
||||||
Real m_magsq;
|
double m_magsq;
|
||||||
|
double m_threshold;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AlphaAGC : public AGC
|
class AlphaAGC : public AGC
|
||||||
|
@ -84,7 +84,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string><html><head/><body><p>Version 3.5.2 - Copyright (C) 2015-2017 Edouard Griffiths, F4EXB. </p><p>Code at <a href="https://github.com/f4exb/sdrangel"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/f4exb/sdrangel</span></a></p><p>Many thanks to the original developers:</p><p>The osmocom developer team - especially horizon, Hoernchen &amp; tnt.</p><p>Christian Daniel from maintech GmbH.</p><p>John Greb (hexameron) for the contributions in <a href="https://github.com/hexameron/rtl-sdrangelove"><span style=" text-decoration: underline; color:#0000ff;">RTL-SDRangelove</span></a></p><p>The following rules apply to the SDRangel main application and libsdrbase:<br/>This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. You should have received a copy of the GNU General Public License along with this program. If not, see <a href="http://www.gnu.org/licenses/"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/</span></a>.</p><p>For the license of installed plugins, look into the plugin list.</p></body></html></string>
|
<string><html><head/><body><p>Version 3.5.3 - Copyright (C) 2015-2017 Edouard Griffiths, F4EXB. </p><p>Code at <a href="https://github.com/f4exb/sdrangel"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/f4exb/sdrangel</span></a></p><p>Many thanks to the original developers:</p><p>The osmocom developer team - especially horizon, Hoernchen &amp; tnt.</p><p>Christian Daniel from maintech GmbH.</p><p>John Greb (hexameron) for the contributions in <a href="https://github.com/hexameron/rtl-sdrangelove"><span style=" text-decoration: underline; color:#0000ff;">RTL-SDRangelove</span></a></p><p>The following rules apply to the SDRangel main application and libsdrbase:<br/>This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. You should have received a copy of the GNU General Public License along with this program. If not, see <a href="http://www.gnu.org/licenses/"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/</span></a>.</p><p>For the license of installed plugins, look into the plugin list.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="wordWrap">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
@ -455,9 +455,9 @@ void MainWindow::createStatusBar()
|
|||||||
{
|
{
|
||||||
QString qtVersionStr = QString("Qt %1 ").arg(QT_VERSION_STR);
|
QString qtVersionStr = QString("Qt %1 ").arg(QT_VERSION_STR);
|
||||||
#if QT_VERSION >= 0x050400
|
#if QT_VERSION >= 0x050400
|
||||||
m_showSystemWidget = new QLabel("SDRangel v3.5.2 " + qtVersionStr + QSysInfo::prettyProductName(), this);
|
m_showSystemWidget = new QLabel("SDRangel v3.5.3 " + qtVersionStr + QSysInfo::prettyProductName(), this);
|
||||||
#else
|
#else
|
||||||
m_showSystemWidget = new QLabel("SDRangel v3.5.2 " + qtVersionStr, this);
|
m_showSystemWidget = new QLabel("SDRangel v3.5.3 " + qtVersionStr, this);
|
||||||
#endif
|
#endif
|
||||||
statusBar()->addPermanentWidget(m_showSystemWidget);
|
statusBar()->addPermanentWidget(m_showSystemWidget);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user