aboutsummaryrefslogtreecommitdiff
path: root/Src/external_dependencies/openmpt-trunk/sounddsp/AGC.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/sounddsp/AGC.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/sounddsp/AGC.cpp')
-rw-r--r--Src/external_dependencies/openmpt-trunk/sounddsp/AGC.cpp141
1 files changed, 141 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/sounddsp/AGC.cpp b/Src/external_dependencies/openmpt-trunk/sounddsp/AGC.cpp
new file mode 100644
index 00000000..fac3408a
--- /dev/null
+++ b/Src/external_dependencies/openmpt-trunk/sounddsp/AGC.cpp
@@ -0,0 +1,141 @@
+/*
+ * AGC.cpp
+ * -------
+ * Purpose: Automatic Gain Control
+ * Notes : Ugh... This should really be removed at some point.
+ * Authors: Olivier Lapicque
+ * OpenMPT Devs
+ * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
+ */
+
+
+#include "stdafx.h"
+#include "../sounddsp/AGC.h"
+
+
+OPENMPT_NAMESPACE_BEGIN
+
+
+//////////////////////////////////////////////////////////////////////////////////
+// Automatic Gain Control
+
+#ifndef NO_AGC
+
+#define AGC_PRECISION 10
+#define AGC_UNITY (1 << AGC_PRECISION)
+
+// Limiter
+#define MIXING_LIMITMAX (0x08100000)
+#define MIXING_LIMITMIN (-MIXING_LIMITMAX)
+
+
+static UINT ProcessAGC(int *pBuffer, int *pRearBuffer, std::size_t nSamples, std::size_t nChannels, int nAGC)
+{
+ if(nChannels == 1)
+ {
+ while(nSamples--)
+ {
+ int val = (int)(((int64)*pBuffer * (int32)nAGC) >> AGC_PRECISION);
+ if(val < MIXING_LIMITMIN || val > MIXING_LIMITMAX) nAGC--;
+ *pBuffer = val;
+ pBuffer++;
+ }
+ } else
+ {
+ if(nChannels == 2)
+ {
+ while(nSamples--)
+ {
+ int fl = (int)(((int64)pBuffer[0] * (int32)nAGC) >> AGC_PRECISION);
+ int fr = (int)(((int64)pBuffer[1] * (int32)nAGC) >> AGC_PRECISION);
+ bool dec = false;
+ dec = dec || (fl < MIXING_LIMITMIN || fl > MIXING_LIMITMAX);
+ dec = dec || (fr < MIXING_LIMITMIN || fr > MIXING_LIMITMAX);
+ if(dec) nAGC--;
+ pBuffer[0] = fl;
+ pBuffer[1] = fr;
+ pBuffer += 2;
+ }
+ } else if(nChannels == 4)
+ {
+ while(nSamples--)
+ {
+ int fl = (int)(((int64)pBuffer[0] * (int32)nAGC) >> AGC_PRECISION);
+ int fr = (int)(((int64)pBuffer[1] * (int32)nAGC) >> AGC_PRECISION);
+ int rl = (int)(((int64)pRearBuffer[0] * (int32)nAGC) >> AGC_PRECISION);
+ int rr = (int)(((int64)pRearBuffer[1] * (int32)nAGC) >> AGC_PRECISION);
+ bool dec = false;
+ dec = dec || (fl < MIXING_LIMITMIN || fl > MIXING_LIMITMAX);
+ dec = dec || (fr < MIXING_LIMITMIN || fr > MIXING_LIMITMAX);
+ dec = dec || (rl < MIXING_LIMITMIN || rl > MIXING_LIMITMAX);
+ dec = dec || (rr < MIXING_LIMITMIN || rr > MIXING_LIMITMAX);
+ if(dec) nAGC--;
+ pBuffer[0] = fl;
+ pBuffer[1] = fr;
+ pRearBuffer[0] = rl;
+ pRearBuffer[1] = rr;
+ pBuffer += 2;
+ pRearBuffer += 2;
+ }
+ }
+ }
+ return nAGC;
+}
+
+
+CAGC::CAGC()
+{
+ Initialize(true, 44100);
+}
+
+
+void CAGC::Process(int *MixSoundBuffer, int *RearSoundBuffer, std::size_t count, std::size_t nChannels)
+{
+ UINT agc = ProcessAGC(MixSoundBuffer, RearSoundBuffer, count, nChannels, m_nAGC);
+ // Some kind custom law, so that the AGC stays quite stable, but slowly
+ // goes back up if the sound level stays below a level inversely proportional
+ // to the AGC level. (J'me comprends)
+ if((agc >= m_nAGC) && (m_nAGC < AGC_UNITY))
+ {
+ m_nAGCRecoverCount += count;
+ if(m_nAGCRecoverCount >= m_Timeout)
+ {
+ m_nAGCRecoverCount = 0;
+ m_nAGC++;
+ }
+ } else
+ {
+ m_nAGC = agc;
+ m_nAGCRecoverCount = 0;
+ }
+}
+
+
+void CAGC::Adjust(UINT oldVol, UINT newVol)
+{
+ m_nAGC = m_nAGC * oldVol / newVol;
+ if (m_nAGC > AGC_UNITY) m_nAGC = AGC_UNITY;
+}
+
+
+void CAGC::Initialize(bool bReset, DWORD MixingFreq)
+{
+ if(bReset)
+ {
+ m_nAGC = AGC_UNITY;
+ m_nAGCRecoverCount = 0;
+ }
+ m_Timeout = (MixingFreq >> (AGC_PRECISION-8)) >> 1;
+}
+
+
+#else
+
+
+MPT_MSVC_WORKAROUND_LNK4221(AGC)
+
+
+#endif // NO_AGC
+
+
+OPENMPT_NAMESPACE_END