| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 | /* * 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;}#elseMPT_MSVC_WORKAROUND_LNK4221(AGC)#endif // NO_AGCOPENMPT_NAMESPACE_END
 |