diff --git a/plugins/channelrx/demodfreedv/freedvdemod.cpp b/plugins/channelrx/demodfreedv/freedvdemod.cpp
index d3a84a9f3..8219f7068 100644
--- a/plugins/channelrx/demodfreedv/freedvdemod.cpp
+++ b/plugins/channelrx/demodfreedv/freedvdemod.cpp
@@ -91,8 +91,31 @@ void FreeDVDemod::FreeDVStats::collect(struct freedv *freeDV)
m_berFrameCount++;
m_frameCount++;
+}
+FreeDVDemod::FreeDVSNR::FreeDVSNR()
+{
+ m_sum = 0.0f;
+ m_peak = 0.0f;
+ m_n = 0;
+ m_reset = true;
+}
+void FreeDVDemod::FreeDVSNR::accumulate(float snrdB)
+{
+ if (m_reset)
+ {
+ m_sum = CalcDb::powerFromdB(snrdB);
+ m_peak = snrdB;
+ m_n = 1;
+ m_reset = false;
+ }
+ else
+ {
+ m_sum += CalcDb::powerFromdB(snrdB);
+ m_peak = std::max(m_peak, snrdB);
+ m_n++;
+ }
}
FreeDVDemod::FreeDVDemod(DeviceSourceAPI *deviceAPI) :
@@ -382,6 +405,7 @@ void FreeDVDemod::pushSampleToDV(int16_t sample)
{
int nout = freedv_rx(m_freeDV, m_speechOut, m_modIn);
m_freeDVStats.collect(m_freeDV);
+ m_freeDVSNR.accumulate(m_freeDVStats.m_snrEst);
for (int i = 0; i < nout; i++)
{
@@ -726,6 +750,23 @@ void FreeDVDemod::applySettings(const FreeDVDemodSettings& settings, bool force)
m_settings = settings;
}
+void FreeDVDemod::getSNRLevels(double& avg, double& peak, int& nbSamples)
+{
+ if (m_freeDVSNR.m_n > 0)
+ {
+ avg = CalcDb::dbPower(m_freeDVSNR.m_sum / m_freeDVSNR.m_n);
+ peak = m_freeDVSNR.m_peak;
+ nbSamples = m_freeDVSNR.m_n;
+ m_freeDVSNR.m_reset = true;
+ }
+ else
+ {
+ avg = 0.0;
+ peak = 0.0;
+ nbSamples = 1;
+ }
+}
+
QByteArray FreeDVDemod::serialize() const
{
return m_settings.serialize();
diff --git a/plugins/channelrx/demodfreedv/freedvdemod.h b/plugins/channelrx/demodfreedv/freedvdemod.h
index f2ad1a5d0..5300f5fc5 100644
--- a/plugins/channelrx/demodfreedv/freedvdemod.h
+++ b/plugins/channelrx/demodfreedv/freedvdemod.h
@@ -162,6 +162,8 @@ public:
m_magsqCount = 0;
}
+ void getSNRLevels(double& avg, double& peak, int& nbSamples);
+
virtual int webapiSettingsGet(
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage);
@@ -209,6 +211,17 @@ private:
uint32_t m_fps; //!< frames per second
};
+ struct FreeDVSNR
+ {
+ FreeDVSNR();
+ void accumulate(float snrdB);
+
+ double m_sum;
+ float m_peak;
+ int m_n;
+ bool m_reset;
+ };
+
class MsgConfigureFreeDVDemodPrivate : public Message {
MESSAGE_CLASS_DECLARATION
@@ -359,6 +372,7 @@ private:
int16_t *m_modIn;
AudioResampler m_audioResampler;
FreeDVStats m_freeDVStats;
+ FreeDVSNR m_freeDVSNR;
QMutex m_settingsMutex;
diff --git a/plugins/channelrx/demodfreedv/freedvdemodgui.cpp b/plugins/channelrx/demodfreedv/freedvdemodgui.cpp
index b8c6b2ee9..aff6599c0 100644
--- a/plugins/channelrx/demodfreedv/freedvdemodgui.cpp
+++ b/plugins/channelrx/demodfreedv/freedvdemodgui.cpp
@@ -153,6 +153,7 @@ void FreeDVDemodGUI::on_deltaFrequency_changed(qint64 value)
void FreeDVDemodGUI::on_reSync_clicked(bool checked)
{
+ (void) checked;
FreeDVDemod::MsgResyncFreeDVDemod* message = FreeDVDemod::MsgResyncFreeDVDemod::create();
m_freeDVDemod->getInputMessageQueue()->push(message);
}
@@ -298,6 +299,7 @@ FreeDVDemodGUI::FreeDVDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, B
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
ui->channelPowerMeter->setColorTheme(LevelMeterSignalDB::ColorGreenAndBlue);
+ ui->snrMeter->setRange(-20, 30);
m_channelMarker.setVisible(true); // activate signal on the last setting only
diff --git a/plugins/channelrx/demodfreedv/freedvdemodgui.ui b/plugins/channelrx/demodfreedv/freedvdemodgui.ui
index 561860fcb..4701b3f15 100644
--- a/plugins/channelrx/demodfreedv/freedvdemodgui.ui
+++ b/plugins/channelrx/demodfreedv/freedvdemodgui.ui
@@ -509,6 +509,81 @@
+ -
+
+
-
+
+
+ SNR
+
+
+
+ -
+
+
+
+ 180
+ 0
+
+
+
+
+ Liberation Mono
+ 8
+
+
+
+
+ -
+
+
+ dB
+
+
+
+ -
+
+
+ BER
+
+
+
+ -
+
+
+ 00
+
+
+
+ -
+
+
+ Syn
+
+
+
+ -
+
+
+ 00
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
-
-