summaryrefslogtreecommitdiff
path: root/engine/audio/private/voice_gain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engine/audio/private/voice_gain.cpp')
-rw-r--r--engine/audio/private/voice_gain.cpp92
1 files changed, 92 insertions, 0 deletions
diff --git a/engine/audio/private/voice_gain.cpp b/engine/audio/private/voice_gain.cpp
new file mode 100644
index 0000000..bf14671
--- /dev/null
+++ b/engine/audio/private/voice_gain.cpp
@@ -0,0 +1,92 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+
+#include "audio_pch.h"
+#include "minmax.h"
+#include "voice_gain.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+CAutoGain::CAutoGain()
+{
+ Reset(128, 5.0f, 0.5f, 1);
+}
+
+
+void CAutoGain::Reset(int blockSize, float maxGain, float avgToMaxVal, float scale)
+{
+ m_BlockSize = blockSize;
+ m_MaxGain = maxGain;
+ m_AvgToMaxVal = avgToMaxVal;
+
+ m_CurBlockOffset = 0;
+ m_CurTotal = 0;
+ m_CurMax = 0;
+
+ m_CurrentGain = 1;
+ m_NextGain = 1;
+
+ m_Scale = scale;
+
+ m_GainMultiplier = 0;
+ m_FixedCurrentGain = 1 << AG_FIX_SHIFT;
+}
+
+
+void CAutoGain::ProcessSamples(
+ short *pSamples,
+ int nSamples)
+{
+ short *pCurPos = pSamples;
+ int nSamplesLeft = nSamples;
+
+ // Continue until we hit the end of this block.
+ while(nSamplesLeft)
+ {
+ int nToProcess = min(nSamplesLeft, (m_BlockSize - m_CurBlockOffset));
+ for(int iSample=0; iSample < nToProcess; iSample++)
+ {
+ // Update running totals..
+ m_CurTotal += abs( pCurPos[iSample] );
+ m_CurMax = max( m_CurMax, (int)abs( pCurPos[iSample] ) );
+
+ // Apply gain on this sample.
+ AGFixed gain = m_FixedCurrentGain + m_CurBlockOffset * m_GainMultiplier;
+ m_CurBlockOffset++;
+
+ int newval = ((int)pCurPos[iSample] * gain) >> AG_FIX_SHIFT;
+ newval = min(32767, max(newval, -32768));
+ pCurPos[iSample] = (short)newval;
+ }
+ pCurPos += nToProcess;
+ nSamplesLeft -= nToProcess;
+
+ // Did we just end a block? Update our next gain.
+ if((m_CurBlockOffset % m_BlockSize) == 0)
+ {
+ // Now we've interpolated to our next gain, make it our current gain.
+ m_CurrentGain = m_NextGain * m_Scale;
+ m_FixedCurrentGain = (int)((double)m_CurrentGain * (1 << AG_FIX_SHIFT));
+
+ // Figure out the next gain (the gain we'll interpolate to).
+ int avg = m_CurTotal / m_BlockSize;
+ float modifiedMax = avg + (m_CurMax - avg) * m_AvgToMaxVal;
+ m_NextGain = min(32767.0f / modifiedMax, m_MaxGain) * m_Scale;
+
+ // Setup the interpolation multiplier.
+ float fGainMultiplier = (m_NextGain - m_CurrentGain) / (m_BlockSize - 1);
+ m_GainMultiplier = (AGFixed)((double)fGainMultiplier * (1 << AG_FIX_SHIFT));
+
+ // Reset counters.
+ m_CurTotal = 0;
+ m_CurMax = 0;
+ m_CurBlockOffset = 0;
+ }
+ }
+}