From f5809b95c0e1e38c6d73782994aefe1bf6b7f989 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 7 Sep 2015 23:31:34 +0200 Subject: [PATCH] AGC in .cpp --- CMakeLists.txt | 1 + include-gpl/dsp/agc.h | 398 +++++++++++------------------------------- sdrbase/dsp/agc.cpp | 167 ++++++++++++++++++ 3 files changed, 267 insertions(+), 299 deletions(-) create mode 100644 sdrbase/dsp/agc.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1df2582d1..513231032 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ set(sdrbase_SOURCES sdrbase/audio/audiofifo.cpp sdrbase/audio/audiooutput.cpp + sdrbase/dsp/agc.cpp sdrbase/dsp/afsquelch.cpp sdrbase/dsp/channelizer.cpp sdrbase/dsp/channelmarker.cpp diff --git a/include-gpl/dsp/agc.h b/include-gpl/dsp/agc.h index 170dc4682..7ed2e9356 100644 --- a/include-gpl/dsp/agc.h +++ b/include-gpl/dsp/agc.h @@ -10,146 +10,22 @@ #include "movingaverage.h" -class SimpleAGC +class AGC { public: - SimpleAGC() : - m_squelchOpen(false), - m_fill(0), - m_cutoff(0), - m_clip(0), - m_moving_average() - {} + AGC(); + AGC(int historySize, Real R); + virtual ~AGC(); - SimpleAGC(int historySize, Real initial, Real cutoff=0, Real clip=0) : - m_squelchOpen(false), - m_fill(initial), - m_cutoff(cutoff), - m_clip(clip), - m_moving_average(historySize, initial) - {} + void resize(int historySize, Real R); + Real getValue(); + Real getDelayedValue(); + virtual void feed(Complex& ci) = 0; + void openedSquelch(); + void closedSquelch(); - void resize(int historySize, Real initial, Real cutoff=0, Real clip=0) - { - m_fill = initial; - m_cutoff = cutoff; - m_clip = clip; - m_moving_average.resize(historySize, initial); - } - - Real getValue() - { - if (m_moving_average.average() > m_clip) - { - return m_moving_average.average(); - } else - { - return m_clip; - } - } - - void feed(Real value) - { - if (value > m_cutoff) - { - m_moving_average.feed(value); - } - } - - void openedSquelch() - { - m_squelchOpen = true; - } - - void closedSquelch() - { - if (m_squelchOpen) - { - //m_moving_average.fill(m_fill); // Valgrind optim - m_squelchOpen = false; - } - } - -private: - bool m_squelchOpen; // open for processing - Real m_fill; // refill average at this level - Real m_cutoff; // consider samples only above this level - Real m_clip; // never go below this level - MovingAverage m_moving_average; // Averaging engine. The stack length conditions the smoothness of AGC. -}; - - -class MagSquaredAGC -{ -public: - - MagSquaredAGC() : - m_u0(1.0), - m_R(1.0), - m_moving_average(), - m_historySize(0), - m_count(0) - {} - - MagSquaredAGC(int historySize, Real R) : - m_u0(1.0), - m_R(R), - m_moving_average(historySize, m_R), - m_historySize(historySize), - m_count(0) - {} - - void resize(int historySize, Real R) - { - m_R = R; - m_moving_average.resize(historySize, R); - m_historySize = historySize; - m_count = 0; - } - - Real getValue() - { - return m_u0; - } - - Real getDelayedValue() - { - if (m_count < m_historySize*m_mult) - { - return 0; - } - else - { - return 1; - } - } - - void feed(Complex& ci) - { - ci *= m_u0; - Real magsq = ci.real()*ci.real() + ci.imag()*ci.imag(); - m_moving_average.feed(magsq); - } - - void openedSquelch() - { - if (m_count < m_historySize*m_mult) - { - m_count++; - } - - m_u0 = m_R / m_moving_average.average(); - } - - void closedSquelch() - { - //m_moving_average.fill(m_R); // Valgrind optim - m_count = 0; - m_u0 = m_R / m_moving_average.average(); - } - -private: +protected: Real m_u0; Real m_R; // objective mag MovingAverage m_moving_average; // Averaging engine. The stack length conditions the smoothness of AGC. @@ -158,182 +34,106 @@ private: static const int m_mult = 4; // squelch delay multiplicator }; -class MagAGC +class MagSquaredAGC : public AGC { public: - - MagAGC() : - m_u0(1.0), - m_R(1.0), - m_moving_average(), - m_historySize(0), - m_count(0) - {} - - MagAGC(int historySize, Real R) : - m_u0(1.0), - m_R(R), - m_moving_average(historySize, m_R), - m_historySize(historySize), - m_count(0) - {} - - void resize(int historySize, Real R) - { - m_R = R; - m_moving_average.resize(historySize, R); - m_historySize = historySize; - m_count = 0; - } - - Real getValue() - { - return m_u0; - } - - Real getDelayedValue() - { - if (m_count < m_historySize*m_mult) - { - return 0; - } - else - { - return m_u0; - } - } - - void feed(Complex& ci) - { - ci *= m_u0; - Real mag = sqrt(ci.real()*ci.real() + ci.imag()*ci.imag()); - m_moving_average.feed(mag); - } - - void openedSquelch() - { - if (m_count < m_historySize*m_mult) - { - m_count++; - } - - m_u0 = m_R / m_moving_average.average(); - } - - void closedSquelch() - { - //m_moving_average.fill(m_R); // Valgrind optim - m_count = 0; - m_u0 = m_R / m_moving_average.average(); - } - -private: - Real m_u0; - Real m_R; // objective mag - MovingAverage m_moving_average; // Averaging engine. The stack length conditions the smoothness of AGC. - int m_historySize; - int m_count; - static const int m_mult = 4; + MagSquaredAGC(); + MagSquaredAGC(int historySize, Real R); + virtual ~MagSquaredAGC(); + virtual void feed(Complex& ci); }; -class AlphaAGC +class MagAGC : public AGC { public: + MagAGC(); + MagAGC(int historySize, Real R); + virtual ~MagAGC(); + virtual void feed(Complex& ci); +}; - AlphaAGC() : - m_u0(1.0), - m_R(1.0), - m_alpha(0.1), - m_squelchOpen(true), - m_moving_average(), - m_historySize(0), - m_count(0) - {} - - AlphaAGC(int historySize, Real R, Real alpha) : - m_u0(1.0), - m_R(R), - m_alpha(alpha), - m_squelchOpen(true), - m_moving_average(historySize, m_R), - m_historySize(historySize), - m_count(0) - {} - - void resize(int historySize, Real R, Real alpha) - { - m_R = R; - m_alpha = alpha; - m_squelchOpen = true; - m_moving_average.resize(historySize, R); - m_historySize = historySize; - m_count = 0; - } - - Real getValue() - { - return m_u0; - } - - Real getDelayedValue() - { - if (m_count < m_historySize) - { - return 0; - } - else - { - return m_u0; - } - } - - void feed(Complex& ci) - { - ci *= m_u0; - Real mag = sqrt(ci.real()*ci.real() + ci.imag()*ci.imag()); - - if (m_squelchOpen && (mag < m_moving_average.average())) - { - m_moving_average.feed(m_moving_average.average() - m_alpha*(m_moving_average.average() - mag)); - } - else - { - //m_squelchOpen = true; - m_moving_average.feed(mag); - } - - } - - void openedSquelch() - { - if (m_count < m_historySize) - { - m_count++; - } - - m_u0 = m_R / m_moving_average.average(); - m_squelchOpen = true; - } - - void closedSquelch() - { - //m_moving_average.fill(m_R); // Valgrind optim - m_count = 0; - //m_u0 = 1.0; - m_u0 = m_R / m_moving_average.average(); - m_squelchOpen = false; - } - +class AlphaAGC : public AGC +{ +public: + AlphaAGC(); + AlphaAGC(int historySize, Real R); + AlphaAGC(int historySize, Real R, Real alpha); + virtual ~AlphaAGC(); + void resize(int historySize, Real R, Real alpha); + virtual void feed(Complex& ci); + void openedSquelch(); + void closedSquelch(); private: - Real m_u0; - Real m_R; // objective magsq Real m_alpha; bool m_squelchOpen; - MovingAverage m_moving_average; // Averaging engine. The stack length conditions the smoothness of AGC. - int m_historySize; - int m_count; }; +class SimpleAGC +{ +public: + SimpleAGC() : + m_squelchOpen(false), + m_fill(0), + m_cutoff(0), + m_clip(0), + m_moving_average() + {} + SimpleAGC(int historySize, Real initial, Real cutoff=0, Real clip=0) : + m_squelchOpen(false), + m_fill(initial), + m_cutoff(cutoff), + m_clip(clip), + m_moving_average(historySize, initial) + {} + + void resize(int historySize, Real initial, Real cutoff=0, Real clip=0) + { + m_fill = initial; + m_cutoff = cutoff; + m_clip = clip; + m_moving_average.resize(historySize, initial); + } + + Real getValue() + { + if (m_moving_average.average() > m_clip) + { + return m_moving_average.average(); + } else + { + return m_clip; + } + } + + void feed(Real value) + { + if (value > m_cutoff) + { + m_moving_average.feed(value); + } + } + + void openedSquelch() + { + m_squelchOpen = true; + } + + void closedSquelch() + { + if (m_squelchOpen) + { + //m_moving_average.fill(m_fill); // Valgrind optim + m_squelchOpen = false; + } + } + +private: + bool m_squelchOpen; // open for processing + Real m_fill; // refill average at this level + Real m_cutoff; // consider samples only above this level + Real m_clip; // never go below this level + MovingAverage m_moving_average; // Averaging engine. The stack length conditions the smoothness of AGC. +}; #endif /* INCLUDE_GPL_DSP_AGC_H_ */ diff --git a/sdrbase/dsp/agc.cpp b/sdrbase/dsp/agc.cpp new file mode 100644 index 000000000..1cd0c0180 --- /dev/null +++ b/sdrbase/dsp/agc.cpp @@ -0,0 +1,167 @@ +/* + * agc.cpp + * + * Created on: Sep 7, 2015 + * Author: f4exb + */ + +#include "dsp/agc.h" + + +AGC::AGC() : + m_u0(1.0), + m_R(1.0), + m_moving_average(), + m_historySize(0), + m_count(0) +{} + +AGC::AGC(int historySize, Real R) : + m_u0(1.0), + m_R(R), + m_moving_average(historySize, m_R), + m_historySize(historySize), + m_count(0) +{} + +AGC::~AGC() +{} + +void AGC::resize(int historySize, Real R) +{ + m_R = R; + m_moving_average.resize(historySize, R); + m_historySize = historySize; + m_count = 0; +} + +Real AGC::getValue() +{ + return m_u0; +} + +Real AGC::getDelayedValue() +{ + if (m_count < m_historySize*m_mult) + { + return 0; + } + else + { + return 1; + } +} + +void AGC::openedSquelch() +{ + if (m_count < m_historySize*m_mult) + { + m_count++; + } + + m_u0 = m_R / m_moving_average.average(); +} + +void AGC::closedSquelch() +{ + //m_moving_average.fill(m_R); // Valgrind optim + m_count = 0; + m_u0 = m_R / m_moving_average.average(); +} + + +MagSquaredAGC::MagSquaredAGC() : + AGC() +{} + +MagSquaredAGC::MagSquaredAGC(int historySize, Real R) : + AGC(historySize, R) +{} + +MagSquaredAGC::~MagSquaredAGC() +{} + +void MagSquaredAGC::feed(Complex& ci) +{ + ci *= m_u0; + Real magsq = ci.real()*ci.real() + ci.imag()*ci.imag(); + m_moving_average.feed(magsq); +} + + +MagAGC::MagAGC() : + AGC() +{} + +MagAGC::MagAGC(int historySize, Real R) : + AGC(historySize, R) +{} + +MagAGC::~MagAGC() +{} + +void MagAGC::feed(Complex& ci) +{ + ci *= m_u0; + Real mag = sqrt(ci.real()*ci.real() + ci.imag()*ci.imag()); + m_moving_average.feed(mag); +} + + +AlphaAGC::AlphaAGC() : + AGC(), + m_alpha(0.5), + m_squelchOpen(true) +{} + +AlphaAGC::AlphaAGC(int historySize, Real R) : + AGC(historySize, R), + m_alpha(0.5), + m_squelchOpen(true) +{} + + +AlphaAGC::AlphaAGC(int historySize, Real R, Real alpha) : + AGC(historySize, R), + m_alpha(alpha), + m_squelchOpen(true) +{} + +AlphaAGC::~AlphaAGC() +{} + +void AlphaAGC::resize(int historySize, Real R, Real alpha) +{ + m_R = R; + m_alpha = alpha; + m_squelchOpen = true; + m_moving_average.resize(historySize, R); +} + +void AlphaAGC::feed(Complex& ci) +{ + ci *= m_u0; + Real magsq = ci.real()*ci.real() + ci.imag()*ci.imag(); + + if (m_squelchOpen && (magsq)) + { + m_moving_average.feed(m_moving_average.average() - m_alpha*(m_moving_average.average() - magsq)); + } + else + { + //m_squelchOpen = true; + m_moving_average.feed(magsq); + } +} + +void AlphaAGC::openedSquelch() +{ + AGC::openedSquelch(); + m_squelchOpen = true; +} + +void AlphaAGC::closedSquelch() +{ + AGC::closedSquelch(); + m_squelchOpen = false; +}