mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 04:50:29 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			194 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			194 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * kissagc.h
 | |
|  *
 | |
|  *  Created on: May 12, 2015
 | |
|  *      Author: f4exb
 | |
|  */
 | |
| 
 | |
| #ifndef INCLUDE_GPL_DSP_AGC_H_
 | |
| #define INCLUDE_GPL_DSP_AGC_H_
 | |
| 
 | |
| #include "movingaverage.h"
 | |
| 
 | |
| class SimpleAGC
 | |
| {
 | |
| public:
 | |
| 
 | |
| 	SimpleAGC() :
 | |
| 		m_squelch(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_squelch(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);
 | |
| 		}
 | |
| 
 | |
| 		m_squelch = true;
 | |
| 	}
 | |
| 
 | |
| 	void close()
 | |
| 	{
 | |
| 		if (m_squelch)
 | |
| 		{
 | |
| 			m_moving_average.fill(m_fill);
 | |
| 			m_squelch = false;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| private:
 | |
| 	bool m_squelch; // 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<Real> m_moving_average; // Averaging engine. The stack length conditions the smoothness of AGC.
 | |
| };
 | |
| 
 | |
| 
 | |
| class EvenSimplerAGC
 | |
| {
 | |
| public:
 | |
| 
 | |
| 	EvenSimplerAGC() :
 | |
| 		m_u0(1.0),
 | |
| 		m_R(1.0),
 | |
| 		m_moving_average()
 | |
| 	{}
 | |
| 
 | |
| 	EvenSimplerAGC(int historySize, Real R) :
 | |
| 		m_u0(1.0),
 | |
| 		m_R(R),
 | |
| 		m_moving_average(historySize, m_R)
 | |
| 	{}
 | |
| 
 | |
| 	void resize(int historySize, Real R)
 | |
| 	{
 | |
| 		m_R = R;
 | |
| 		m_moving_average.resize(historySize, R);
 | |
| 	}
 | |
| 
 | |
| 	Real getValue()
 | |
| 	{
 | |
| 		return m_u0;
 | |
| 	}
 | |
| 
 | |
| 	void feed(Complex& ci)
 | |
| 	{
 | |
| 		ci *= m_u0;
 | |
| 		Real magsq = ci.real()*ci.real() + ci.imag()*ci.imag();
 | |
| 		m_moving_average.feed(magsq);
 | |
| 		m_u0 = m_R / m_moving_average.average();
 | |
| 	}
 | |
| 
 | |
| 	void close()
 | |
| 	{
 | |
| 		m_moving_average.fill(m_R);
 | |
| 		m_u0 = 1.0;
 | |
| 	}
 | |
| 
 | |
| private:
 | |
| 	Real m_u0;
 | |
| 	Real m_R;       // objective magsq
 | |
| 	MovingAverage<Real> m_moving_average; // Averaging engine. The stack length conditions the smoothness of AGC.
 | |
| };
 | |
| 
 | |
| class AlphaAGC
 | |
| {
 | |
| public:
 | |
| 
 | |
| 	AlphaAGC() :
 | |
| 		m_u0(1.0),
 | |
| 		m_R(1.0),
 | |
| 		m_alpha(0.1),
 | |
| 		m_squelch(false),
 | |
| 		m_moving_average()
 | |
| 	{}
 | |
| 
 | |
| 	AlphaAGC(int historySize, Real R, Real alpha) :
 | |
| 		m_u0(1.0),
 | |
| 		m_R(R),
 | |
| 		m_alpha(alpha),
 | |
| 		m_squelch(false),
 | |
| 		m_moving_average(historySize, m_R)
 | |
| 	{}
 | |
| 
 | |
| 	void resize(int historySize, Real R, Real alpha)
 | |
| 	{
 | |
| 		m_R = R;
 | |
| 		m_alpha = alpha;
 | |
| 		m_squelch = false;
 | |
| 		m_moving_average.resize(historySize, R);
 | |
| 	}
 | |
| 
 | |
| 	Real getValue()
 | |
| 	{
 | |
| 		return m_u0;
 | |
| 	}
 | |
| 
 | |
| 	void feed(Complex& ci)
 | |
| 	{
 | |
| 		ci *= m_u0;
 | |
| 		Real magsq = ci.real()*ci.real() + ci.imag()*ci.imag();
 | |
| 
 | |
| 		if (m_squelch && (magsq < m_moving_average.average()))
 | |
| 		{
 | |
| 			m_moving_average.feed(m_moving_average.average() - m_alpha*(m_moving_average.average() - magsq));
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			m_squelch = true;
 | |
| 			m_moving_average.feed(magsq);
 | |
| 		}
 | |
| 
 | |
| 		m_u0 = m_R / m_moving_average.average();
 | |
| 	}
 | |
| 
 | |
| 	void close()
 | |
| 	{
 | |
| 		m_moving_average.fill(m_R);
 | |
| 		m_u0 = 1.0;
 | |
| 		m_squelch = false;
 | |
| 	}
 | |
| 
 | |
| private:
 | |
| 	Real m_u0;
 | |
| 	Real m_R;       // objective magsq
 | |
| 	Real m_alpha;
 | |
| 	bool m_squelch;
 | |
| 	MovingAverage<Real> m_moving_average; // Averaging engine. The stack length conditions the smoothness of AGC.
 | |
| };
 | |
| 
 | |
| 
 | |
| 
 | |
| #endif /* INCLUDE_GPL_DSP_AGC_H_ */
 |