diff --git a/include-gpl/dsp/agc.h b/include-gpl/dsp/agc.h
index 684193a98..170dc4682 100644
--- a/include-gpl/dsp/agc.h
+++ b/include-gpl/dsp/agc.h
@@ -80,11 +80,11 @@ private:
 };
 
 
-class EvenSimplerAGC
+class MagSquaredAGC
 {
 public:
 
-	EvenSimplerAGC() :
+	MagSquaredAGC() :
 		m_u0(1.0),
 		m_R(1.0),
 		m_moving_average(),
@@ -92,7 +92,85 @@ public:
 		m_count(0)
 	{}
 
-	EvenSimplerAGC(int historySize, Real R) :
+	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:
+	Real m_u0;
+	Real m_R;       // objective mag
+	MovingAverage<Real> 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; // squelch delay multiplicator
+};
+
+class MagAGC
+{
+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),
diff --git a/plugins/channel/nfm/nfmdemod.cpp b/plugins/channel/nfm/nfmdemod.cpp
index fc36144e1..d6a4f537a 100644
--- a/plugins/channel/nfm/nfmdemod.cpp
+++ b/plugins/channel/nfm/nfmdemod.cpp
@@ -26,7 +26,7 @@
 #include "dsp/pidcontroller.h"
 #include "dsp/dspengine.h"
 
-static const Real afSqTones[2] = {1200.0, 6000.0}; // {1200.0, 8000.0};
+static const Real afSqTones[2] = {1200.0, 8000.0}; // {1200.0, 8000.0};
 
 MESSAGE_CLASS_DEFINITION(NFMDemod::MsgConfigureNFMDemod, Message)
 
@@ -55,7 +55,7 @@ NFMDemod::NFMDemod() :
 	m_audioBufferFill = 0;
 
 	m_movingAverage.resize(16, 0);
-	m_agcLevel = 0.25; // 0.003
+	m_agcLevel = 0.0625; // 0.003
 	//m_AGC.resize(480, m_agcLevel, 0, 0.1*m_agcLevel);
 	m_AGC.resize(600, m_agcLevel*m_agcLevel); //, 0.3);
 
@@ -165,7 +165,7 @@ void NFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
 				Real qp = ci.imag() - m_m2Sample.imag();
 				Real h1 = m_m1Sample.real() * qp;
 				Real h2 = m_m1Sample.imag() * ip;
-				Real demod = (h1 - h2) * 30; // 10000
+				Real demod = (h1 - h2) * 16; // 10000 (multiply by 2^16 after demod)
 
 				m_m2Sample = m_m1Sample;
 				m_m1Sample = ci;
@@ -218,7 +218,7 @@ void NFMDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
 					{
 						demod = m_bandpass.filter(demod);
 						demod *= m_running.m_volume;
-						sample = demod * ((1<<15)/301) * m_AGC.getDelayedValue(); // denominator = bandpass filter number of taps
+						sample = demod * ((1<<16)/301) * m_AGC.getDelayedValue(); // denominator = bandpass filter number of taps
 					}
 
 					m_AGC.openedSquelch();
diff --git a/plugins/channel/nfm/nfmdemod.h b/plugins/channel/nfm/nfmdemod.h
index f31329cad..b7eff886b 100644
--- a/plugins/channel/nfm/nfmdemod.h
+++ b/plugins/channel/nfm/nfmdemod.h
@@ -163,7 +163,7 @@ private:
 	Complex m_m1Sample;
 	Complex m_m2Sample;
 	MovingAverage<Real> m_movingAverage;
-	EvenSimplerAGC m_AGC;
+	MagSquaredAGC m_AGC;
 	Real m_agcLevel; // AGC will aim to  this level
 	Real m_agcFloor; // AGC will not go below this level