sdrangel/sdrbase/dsp/agc.h

138 lines
5.3 KiB
C
Raw Permalink Normal View History

///////////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015-2019 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
// //
// 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 as version 3 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. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////////
2015-05-12 06:12:13 -04:00
#ifndef INCLUDE_GPL_DSP_AGC_H_
#define INCLUDE_GPL_DSP_AGC_H_
#include "dsp/dsptypes.h"
2015-05-12 06:12:13 -04:00
#include "movingaverage.h"
#include "export.h"
2015-05-12 06:12:13 -04:00
2018-03-03 14:23:38 -05:00
class SDRBASE_API AGC
2015-06-20 03:28:57 -04:00
{
public:
AGC(int historySize, double R);
2015-09-07 17:31:34 -04:00
virtual ~AGC();
void resize(int historySize, double R);
void setOrder(double R) { m_R = R; }
2015-09-07 17:31:34 -04:00
Real getValue();
2015-09-12 10:34:57 -04:00
Real getAverage();
void reset(double R) { m_moving_average.fill(R); }
2015-09-07 17:31:34 -04:00
virtual void feed(Complex& ci) = 0;
2015-09-07 17:31:34 -04:00
protected:
2017-08-05 13:08:33 -04:00
double m_u0; //!< AGC factor
2017-08-05 18:02:16 -04:00
double m_R; //!< ordered magnitude
2017-08-05 13:08:33 -04:00
MovingAverage<double> m_moving_average; //!< Averaging engine. The stack length conditions the smoothness of AGC.
2023-12-10 19:12:03 -05:00
int m_historySize; //!< Averaging length (the longer the slower the AGC)
2017-08-05 13:08:33 -04:00
int m_count; //!< Samples counter
};
2018-03-03 14:23:38 -05:00
class SDRBASE_API MagAGC : public AGC
2015-09-07 17:31:34 -04:00
{
public:
MagAGC(int historySize, double R, double threshold);
2015-09-07 17:31:34 -04:00
virtual ~MagAGC();
void setSquared(bool squared) { m_squared = squared; }
void resize(int historySize, int stepLength, Real R);
void setOrder(double R);
2015-09-07 17:31:34 -04:00
virtual void feed(Complex& ci);
double feedAndGetValue(const Complex& ci);
double getMagSq() const { return m_magsq; }
2017-07-25 15:21:48 -04:00
void setThreshold(double threshold) { m_threshold = threshold; }
void setThresholdEnable(bool enable);
void setGate(int gate) { m_gate = gate; m_gateCounter = 0; m_count = 0; }
void setStepDownDelay(int stepDownDelay) { m_stepDownDelay = stepDownDelay; m_gateCounter = 0; m_count = 0; }
int getStepDownDelay() const { return m_stepDownDelay; }
float getStepValue() const;
void setHardLimiting(bool hardLimiting) { m_hardLimiting = hardLimiting; }
void resetStepCounters() { m_stepUpCounter = 0; m_stepDownCounter = 0; }
private:
bool m_squared; //!< use squared magnitude (power) to compute AGC value
double m_magsq; //!< current squared magnitude (power)
2017-07-26 02:39:20 -04:00
double m_threshold; //!< squelch on magsq average
bool m_thresholdEnable; //!< enable squelch on power threshold
2017-07-26 02:39:20 -04:00
int m_gate; //!< power threshold gate in number of samples
int m_stepLength; //!< transition step length in number of samples
double m_stepDelta; //!< transition step unit by sample
2017-07-26 02:39:20 -04:00
int m_stepUpCounter; //!< step up transition samples counter
int m_stepDownCounter; //!< step down transition samples counter
int m_gateCounter; //!< threshold gate samples counter
2017-08-05 13:08:33 -04:00
int m_stepDownDelay; //!< delay in samples before cutoff (release)
bool m_hardLimiting; //!< hard limit multiplier so that resulting sample magnitude does not exceed 1.0
double hardLimiter(double multiplier, double magsq);
2015-09-07 17:31:34 -04:00
};
2015-06-20 03:28:57 -04:00
2018-02-03 11:06:16 -05:00
template<uint32_t AvgSize>
2015-09-07 17:31:34 -04:00
class SimpleAGC
2015-06-20 03:28:57 -04:00
{
public:
2018-02-15 18:43:21 -05:00
SimpleAGC(Real initial, Real cutoff=0, Real clip=0) :
2018-02-03 11:06:16 -05:00
m_cutoff(cutoff),
2018-02-15 18:43:21 -05:00
m_clip(clip),
m_moving_average(AvgSize, initial)
{
}
2015-06-20 03:28:57 -04:00
2018-02-15 18:43:21 -05:00
void resize(Real initial, Real cutoff=0, Real clip=0)
{
2018-02-03 11:06:16 -05:00
m_cutoff = cutoff;
m_clip = clip;
2018-02-15 18:43:21 -05:00
m_moving_average.resize(AvgSize, initial);
}
void resizeNew(uint32_t newSize, Real initial, Real cutoff=0, Real clip=0)
{
m_cutoff = cutoff;
m_clip = clip;
m_moving_average.resize(newSize, initial);
}
2018-02-15 18:43:21 -05:00
void fill(double value)
{
m_moving_average.fill(value);
}
2015-06-20 03:28:57 -04:00
Real getValue()
{
2018-02-15 18:43:21 -05:00
if ((Real) m_moving_average.average() > m_clip) {
return (Real) m_moving_average.average();
} else {
2018-02-03 11:06:16 -05:00
return m_clip;
}
2015-09-07 17:31:34 -04:00
}
void feed(Real value)
{
2018-02-15 18:43:21 -05:00
if (value > m_cutoff) {
m_moving_average.feed(value);
2018-02-03 11:06:16 -05:00
}
2015-09-07 17:31:34 -04:00
}
2015-06-20 03:28:57 -04:00
private:
2015-09-07 17:31:34 -04:00
Real m_cutoff; // consider samples only above this level
Real m_clip; // never go below this level
2018-02-15 18:43:21 -05:00
MovingAverage<double> m_moving_average; // Averaging engine. The stack length conditions the smoothness of AGC.
//MovingAverageUtil<Real, double, AvgSize> m_moving_average;
2015-05-12 06:12:13 -04:00
};
#endif /* INCLUDE_GPL_DSP_AGC_H_ */