From 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d Mon Sep 17 00:00:00 2001 From: Jef Date: Tue, 24 Sep 2024 14:54:57 +0200 Subject: Initial community commit --- .../openmpt-trunk/sounddsp/AGC.cpp | 141 +++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 Src/external_dependencies/openmpt-trunk/sounddsp/AGC.cpp (limited to 'Src/external_dependencies/openmpt-trunk/sounddsp/AGC.cpp') 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 -- cgit