From 461de8e5361648ac77f3dd27ddf73d45ef7dd2a6 Mon Sep 17 00:00:00 2001 From: Vort Date: Mon, 20 Jul 2020 09:34:11 +0300 Subject: [PATCH] ATV Demodulator: bug fixes and performance improvements --- plugins/channelrx/demodatv/atvdemodgui.cpp | 4 ++-- plugins/channelrx/demodatv/atvdemodsink.cpp | 21 +++++++++------------ plugins/channelrx/demodatv/atvdemodsink.h | 2 ++ sdrbase/util/movingaverage.h | 18 +++++++++++++----- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/plugins/channelrx/demodatv/atvdemodgui.cpp b/plugins/channelrx/demodatv/atvdemodgui.cpp index db581a553..b03c7bb50 100644 --- a/plugins/channelrx/demodatv/atvdemodgui.cpp +++ b/plugins/channelrx/demodatv/atvdemodgui.cpp @@ -565,17 +565,17 @@ void ATVDemodGUI::on_fmDeviation_valueChanged(int value) void ATVDemodGUI::on_amScaleFactor_valueChanged(int value) { + m_settings.m_amScalingFactor = value; ui->amScaleFactor->setValue(m_settings.m_amScalingFactor); ui->amScaleFactorText->setText(QString("%1").arg(m_settings.m_amScalingFactor)); - m_settings.m_amScalingFactor = value; applySettings(); } void ATVDemodGUI::on_amScaleOffset_valueChanged(int value) { + m_settings.m_amOffsetFactor = value; ui->amScaleOffset->setValue(m_settings.m_amOffsetFactor); ui->amScaleOffsetText->setText(QString("%1").arg(m_settings.m_amOffsetFactor)); - m_settings.m_amOffsetFactor = value; applySettings(); } diff --git a/plugins/channelrx/demodatv/atvdemodsink.cpp b/plugins/channelrx/demodatv/atvdemodsink.cpp index 301952cd1..cf55f3e0d 100644 --- a/plugins/channelrx/demodatv/atvdemodsink.cpp +++ b/plugins/channelrx/demodatv/atvdemodsink.cpp @@ -87,20 +87,13 @@ ATVDemodSink::~ATVDemodSink() void ATVDemodSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end) { - float fltI; - float fltQ; - Complex ci; - //********** Let's rock and roll buddy ! ********** //********** Accessing ATV Screen context ********** for (SampleVector::const_iterator it = begin; it != end; ++it /* ++it **/) { - - fltI = it->real(); - fltQ = it->imag(); - Complex c(fltI, fltQ); + Complex c(it->real(), it->imag()); if (m_settings.m_inputFrequencyOffset != 0) { c *= m_nco.nextIQ(); @@ -112,6 +105,7 @@ void ATVDemodSink::feed(const SampleVector::const_iterator& begin, const SampleV } else { + Complex ci; if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci)) { demod(ci); @@ -129,7 +123,6 @@ void ATVDemodSink::feed(const SampleVector::const_iterator& begin, const SampleV void ATVDemodSink::demod(Complex& c) { - float divSynchroBlack = 1.0f - m_settings.m_levelBlack; float sampleNormI; float sampleNormQ; float sampleNorm; @@ -226,7 +219,7 @@ void ATVDemodSink::demod(Complex& c) sampleNorm = sqrt(magSq); float sampleRaw = sampleNorm / SDR_RX_SCALEF; m_ampAverage(sampleRaw); - sample = sampleRaw / (2.0 * m_ampAverage.asFloat()); // AGC + sample = sampleRaw / (2.0f * m_ampAverage.asFloat()); // AGC } else if ((m_settings.m_atvModulation == ATVDemodSettings::ATV_USB) || (m_settings.m_atvModulation == ATVDemodSettings::ATV_LSB)) { @@ -318,12 +311,12 @@ void ATVDemodSink::demod(Complex& c) sample = (sample < 0.0f) ? 0.0f : (sample > 1.0f) ? 1.0f : sample; if ((m_videoTabIndex == 1) && (m_scopeSink != 0)) { // feed scope buffer only if scope is present and visible - m_scopeSampleBuffer.push_back(Sample(sample*SDR_RX_SCALEF, 0.0f)); + m_scopeSampleBuffer.push_back(Sample(sample * (SDR_RX_SCALEF - 1.0f), 0.0f)); } //********** gray level ********** // -0.3 -> 0.7 / 0.7 - sampleVideo = (int) (255.0*(sample - m_settings.m_levelBlack) / (1.0f - m_settings.m_levelBlack)); + sampleVideo = (int) ((sample - m_settings.m_levelBlack) * m_sampleRangeCorrection); // 0 -> 255 sampleVideo = (sampleVideo < 0) ? 0 : (sampleVideo > 255) ? 255 : sampleVideo; @@ -605,5 +598,9 @@ void ATVDemodSink::applySettings(const ATVDemodSettings& settings, bool force) m_objPhaseDiscri.setFMScaling(1.0f / settings.m_fmDeviation); } + if ((settings.m_levelBlack != m_settings.m_levelBlack) || force) { + m_sampleRangeCorrection = 255.0f / (1.0f - m_settings.m_levelBlack); + } + m_settings = settings; } diff --git a/plugins/channelrx/demodatv/atvdemodsink.h b/plugins/channelrx/demodatv/atvdemodsink.h index d541af7a4..d39fff5fa 100644 --- a/plugins/channelrx/demodatv/atvdemodsink.h +++ b/plugins/channelrx/demodatv/atvdemodsink.h @@ -165,6 +165,8 @@ private: SampleVector m_sampleBuffer; + float m_sampleRangeCorrection; + //*************** RF *************** MovingAverageUtil m_magSqAverage; diff --git a/sdrbase/util/movingaverage.h b/sdrbase/util/movingaverage.h index f5c9eedda..b37afd1e2 100644 --- a/sdrbase/util/movingaverage.h +++ b/sdrbase/util/movingaverage.h @@ -75,7 +75,9 @@ class MovingAverageUtilVar : m_num_samples(0), m_index(0), m_total(0) { m_samples.resize(size); - } + m_samplesSizeInvF = 1.0f / size; + m_samplesSizeInvD = 1.0 / size; + } void reset() { @@ -88,7 +90,9 @@ class MovingAverageUtilVar { reset(); m_samples.resize(size); - } + m_samplesSizeInvF = 1.0f / size; + m_samplesSizeInvD = 1.0 / size; + } unsigned int size() const { @@ -107,12 +111,14 @@ class MovingAverageUtilVar T& oldest = m_samples[m_index]; m_total += sample - oldest; oldest = sample; - m_index = (m_index + 1) % m_samples.size(); + m_index++; + if (m_index == m_samples.size()) + m_index = 0; } } - double asDouble() const { return ((double)m_total) / m_samples.size(); } - float asFloat() const { return ((float)m_total) / m_samples.size(); } + double asDouble() const { return m_total * m_samplesSizeInvD; } + float asFloat() const { return m_total * m_samplesSizeInvF; } operator T() const { return m_total / m_samples.size(); } private: @@ -120,6 +126,8 @@ class MovingAverageUtilVar unsigned int m_num_samples; unsigned int m_index; Total m_total; + float m_samplesSizeInvF; + double m_samplesSizeInvD; };