| 
									
										
										
										
											2015-09-07 23:31:34 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * agc.cpp | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  Created on: Sep 7, 2015 | 
					
						
							|  |  |  |  *      Author: f4exb | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-26 08:39:20 +02:00
										 |  |  | #include <algorithm>
 | 
					
						
							| 
									
										
										
										
											2015-09-07 23:31:34 +02:00
										 |  |  | #include "dsp/agc.h"
 | 
					
						
							| 
									
										
										
										
											2017-07-27 11:24:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "util/stepfunctions.h"
 | 
					
						
							| 
									
										
										
										
											2015-09-07 23:31:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-05 23:11:05 +02:00
										 |  |  | AGC::AGC(int historySize, double R) : | 
					
						
							| 
									
										
										
										
											2015-09-07 23:31:34 +02:00
										 |  |  | 	m_u0(1.0), | 
					
						
							|  |  |  | 	m_R(R), | 
					
						
							|  |  |  | 	m_moving_average(historySize, m_R), | 
					
						
							|  |  |  | 	m_historySize(historySize), | 
					
						
							|  |  |  | 	m_count(0) | 
					
						
							|  |  |  | {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AGC::~AGC() | 
					
						
							|  |  |  | {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-05 23:11:05 +02:00
										 |  |  | void AGC::resize(int historySize, double R) | 
					
						
							| 
									
										
										
										
											2015-09-07 23:31:34 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	m_R = R; | 
					
						
							|  |  |  | 	m_moving_average.resize(historySize, R); | 
					
						
							|  |  |  | 	m_historySize = historySize; | 
					
						
							|  |  |  | 	m_count = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Real AGC::getValue() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return m_u0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-12 16:34:57 +02:00
										 |  |  | Real AGC::getAverage() | 
					
						
							| 
									
										
										
										
											2015-09-07 23:31:34 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-09-12 16:34:57 +02:00
										 |  |  | 	return m_moving_average.average(); | 
					
						
							| 
									
										
										
										
											2015-09-07 23:31:34 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-25 00:58:16 +02:00
										 |  |  | MagAGC::MagAGC(int historySize, double R, double threshold) : | 
					
						
							| 
									
										
										
										
											2015-10-04 06:26:06 +02:00
										 |  |  | 	AGC(historySize, R), | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  | 	m_squared(false), | 
					
						
							| 
									
										
										
										
											2017-07-25 00:58:16 +02:00
										 |  |  | 	m_magsq(0.0), | 
					
						
							| 
									
										
										
										
											2017-07-25 21:21:48 +02:00
										 |  |  | 	m_threshold(threshold), | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  | 	m_thresholdEnable(true), | 
					
						
							| 
									
										
										
										
											2017-07-25 23:39:27 +02:00
										 |  |  | 	m_gate(0), | 
					
						
							| 
									
										
										
										
											2018-05-06 02:39:39 +02:00
										 |  |  | 	m_stepLength(std::min(2400, historySize/2)), // max 50 ms (at 48 kHz)
 | 
					
						
							| 
									
										
										
										
											2017-07-26 16:23:34 +02:00
										 |  |  |     m_stepDelta(1.0/m_stepLength), | 
					
						
							| 
									
										
										
										
											2017-07-26 08:39:20 +02:00
										 |  |  | 	m_stepUpCounter(0), | 
					
						
							| 
									
										
										
										
											2019-06-09 09:25:18 +02:00
										 |  |  |     m_stepDownCounter(0), | 
					
						
							| 
									
										
										
										
											2017-08-05 19:08:33 +02:00
										 |  |  | 	m_gateCounter(0), | 
					
						
							|  |  |  | 	m_stepDownDelay(historySize), | 
					
						
							|  |  |  | 	m_clamping(false), | 
					
						
							|  |  |  | 	m_R2(R*R), | 
					
						
							| 
									
										
										
										
											2019-05-07 02:50:05 +02:00
										 |  |  | 	m_clampMax(1.0), | 
					
						
							|  |  |  |     m_hardLimiting(false) | 
					
						
							| 
									
										
										
										
											2015-09-07 23:31:34 +02:00
										 |  |  | {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MagAGC::~MagAGC() | 
					
						
							|  |  |  | {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-06 02:39:39 +02:00
										 |  |  | void MagAGC::resize(int historySize, int stepLength, Real R) | 
					
						
							| 
									
										
										
										
											2017-07-26 08:39:20 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-08-05 19:08:33 +02:00
										 |  |  |     m_R2 = R*R; | 
					
						
							| 
									
										
										
										
											2018-05-06 02:39:39 +02:00
										 |  |  |     m_stepLength = stepLength; | 
					
						
							| 
									
										
										
										
											2017-07-26 16:23:34 +02:00
										 |  |  |     m_stepDelta = 1.0 / m_stepLength; | 
					
						
							|  |  |  |     m_stepUpCounter = 0; | 
					
						
							| 
									
										
										
										
											2019-06-09 09:25:18 +02:00
										 |  |  |     m_stepDownCounter = 0; | 
					
						
							| 
									
										
										
										
											2017-07-26 08:39:20 +02:00
										 |  |  |     AGC::resize(historySize, R); | 
					
						
							| 
									
										
										
										
											2017-08-06 00:02:16 +02:00
										 |  |  |     m_moving_average.fill(0); | 
					
						
							| 
									
										
										
										
											2017-07-26 08:39:20 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-05 23:11:05 +02:00
										 |  |  | void MagAGC::setOrder(double R) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_R2 = R*R; | 
					
						
							|  |  |  |     AGC::setOrder(R); | 
					
						
							| 
									
										
										
										
											2017-08-06 00:02:16 +02:00
										 |  |  |     m_moving_average.fill(0); | 
					
						
							| 
									
										
										
										
											2017-08-05 23:11:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  | void MagAGC::setThresholdEnable(bool enable) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_thresholdEnable != enable) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_stepUpCounter = 0; | 
					
						
							| 
									
										
										
										
											2019-06-09 09:25:18 +02:00
										 |  |  |         m_stepDownCounter = 0; | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_thresholdEnable = enable; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-07 23:31:34 +02:00
										 |  |  | void MagAGC::feed(Complex& ci) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-07-26 16:23:34 +02:00
										 |  |  | 	ci *= feedAndGetValue(ci); | 
					
						
							| 
									
										
										
										
											2015-09-07 23:31:34 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 02:50:05 +02:00
										 |  |  | double MagAGC::hardLimiter(double multiplier, double magsq) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if ((m_hardLimiting) && (multiplier*multiplier*magsq > 1.0)) { | 
					
						
							|  |  |  |         return 1.0 / (multiplier*sqrt(magsq)); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         return multiplier; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-25 00:58:16 +02:00
										 |  |  | double MagAGC::feedAndGetValue(const Complex& ci) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_magsq = ci.real()*ci.real() + ci.imag()*ci.imag(); | 
					
						
							|  |  |  |     m_moving_average.feed(m_magsq); | 
					
						
							| 
									
										
										
										
											2017-08-05 19:08:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (m_clamping) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (m_squared) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2018-05-28 02:40:26 +02:00
										 |  |  |             if (m_magsq > m_clampMax) { | 
					
						
							|  |  |  |                 m_u0 = m_clampMax / m_magsq; | 
					
						
							| 
									
										
										
										
											2018-05-21 14:43:11 +02:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2018-05-28 02:40:26 +02:00
										 |  |  |                 m_u0 = m_R / m_moving_average.average(); | 
					
						
							| 
									
										
										
										
											2018-05-21 14:43:11 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-08-05 19:08:33 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2018-05-28 02:40:26 +02:00
										 |  |  |             if (sqrt(m_magsq) > m_clampMax) { | 
					
						
							|  |  |  |                 m_u0 = m_clampMax / sqrt(m_magsq); | 
					
						
							| 
									
										
										
										
											2018-05-21 14:43:11 +02:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2018-05-28 02:40:26 +02:00
										 |  |  |                 m_u0 = m_R / sqrt(m_moving_average.average()); | 
					
						
							| 
									
										
										
										
											2018-05-21 14:43:11 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-08-05 19:08:33 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_u0 = m_R / (m_squared ? m_moving_average.average() : sqrt(m_moving_average.average())); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-07-25 21:21:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  |     if (m_thresholdEnable) | 
					
						
							| 
									
										
										
										
											2017-07-25 21:21:48 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2019-06-09 09:25:18 +02:00
										 |  |  |         bool open = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  |         if (m_magsq > m_threshold) | 
					
						
							| 
									
										
										
										
											2017-07-25 23:39:27 +02:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2019-06-09 09:25:18 +02:00
										 |  |  |             if (m_gateCounter < m_gate) { | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  |                 m_gateCounter++; | 
					
						
							| 
									
										
										
										
											2019-06-09 09:25:18 +02:00
										 |  |  |             } else { | 
					
						
							|  |  |  |                 open = true; | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-07-25 23:39:27 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  |             m_gateCounter = 0; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-07-26 08:39:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-09 09:25:18 +02:00
										 |  |  |         if (open) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_count = m_stepDownDelay; // delay before step down (grace delay)
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else | 
					
						
							| 
									
										
										
										
											2017-07-26 16:23:34 +02:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2019-06-09 09:25:18 +02:00
										 |  |  |             m_count--; | 
					
						
							|  |  |  |             m_gateCounter = m_gate; // keep gate open during grace
 | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-09 09:25:18 +02:00
										 |  |  |         if (m_count > 0) // up phase
 | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             m_stepDownCounter = m_stepUpCounter; // prepare for step down
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (m_stepUpCounter < m_stepLength) // step up
 | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  |             { | 
					
						
							|  |  |  |                 m_stepUpCounter++; | 
					
						
							| 
									
										
										
										
											2019-05-07 02:50:05 +02:00
										 |  |  |                 return hardLimiter(m_u0 * StepFunctions::smootherstep(m_stepUpCounter * m_stepDelta), m_magsq); | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-06-09 09:25:18 +02:00
										 |  |  |             else // steady open
 | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2019-05-07 02:50:05 +02:00
										 |  |  |                 return hardLimiter(m_u0, m_magsq); | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-07-26 16:23:34 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-06-09 09:25:18 +02:00
										 |  |  |         else // down phase
 | 
					
						
							| 
									
										
										
										
											2017-07-26 16:23:34 +02:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2019-06-09 09:25:18 +02:00
										 |  |  |             m_stepUpCounter = m_stepDownCounter; // prepare for step up
 | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-09 09:25:18 +02:00
										 |  |  |             if (m_stepDownCounter > 0) // step down
 | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  |             { | 
					
						
							|  |  |  |                 m_stepDownCounter--; | 
					
						
							| 
									
										
										
										
											2019-05-07 02:50:05 +02:00
										 |  |  |                 return hardLimiter(m_u0 * StepFunctions::smootherstep(m_stepDownCounter * m_stepDelta), m_magsq); | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-06-09 09:25:18 +02:00
										 |  |  |             else // steady closed
 | 
					
						
							| 
									
										
										
										
											2017-07-27 10:50:41 +02:00
										 |  |  |             { | 
					
						
							|  |  |  |                 return 0.0; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-07-25 23:39:27 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2019-05-07 02:50:05 +02:00
										 |  |  |         return hardLimiter(m_u0, m_magsq); | 
					
						
							| 
									
										
										
										
											2017-07-25 21:21:48 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-07-25 00:58:16 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-04-22 09:37:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-06 02:39:39 +02:00
										 |  |  | float MagAGC::getStepValue() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-06-09 09:25:18 +02:00
										 |  |  |     if (m_count > 0) // up phase
 | 
					
						
							| 
									
										
										
										
											2018-05-06 02:39:39 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         return StepFunctions::smootherstep(m_stepUpCounter * m_stepDelta); // step up
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-09 09:25:18 +02:00
										 |  |  |     else // down phase
 | 
					
						
							| 
									
										
										
										
											2018-05-06 02:39:39 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         return StepFunctions::smootherstep(m_stepDownCounter * m_stepDelta); // step down
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |