summaryrefslogtreecommitdiff
path: root/utils/voice_tweak/waveout.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/voice_tweak/waveout.cpp
downloadarchived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz
archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip
Diffstat (limited to 'utils/voice_tweak/waveout.cpp')
-rw-r--r--utils/voice_tweak/waveout.cpp205
1 files changed, 205 insertions, 0 deletions
diff --git a/utils/voice_tweak/waveout.cpp b/utils/voice_tweak/waveout.cpp
new file mode 100644
index 0000000..2f58e76
--- /dev/null
+++ b/utils/voice_tweak/waveout.cpp
@@ -0,0 +1,205 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "stdafx.h"
+#include <windows.h>
+#include <assert.h>
+#include <mmsystem.h>
+#include "waveout.h"
+#include "ivoicecodec.h"
+
+
+class CWaveOutHdr
+{
+public:
+ WAVEHDR m_Hdr;
+ CWaveOutHdr *m_pNext;
+ char m_Data[1];
+};
+
+
+class CWaveOut : public IWaveOut
+{
+// IWaveOut overrides.
+public:
+ CWaveOut();
+ virtual ~CWaveOut();
+ virtual void Release();
+ virtual bool PutSamples(short *pSamples, int nSamples);
+ virtual void Idle();
+ virtual int GetNumBufferedSamples();
+
+
+public:
+ bool Init(int sampleRate);
+ void Term();
+
+
+private:
+ void KillOldHeaders();
+
+
+private:
+ HWAVEOUT m_hWaveOut;
+ CWaveOutHdr m_Headers; // Head of a linked list of WAVEHDRs.
+ int m_nBufferedSamples;
+};
+
+
+CWaveOut::CWaveOut()
+{
+ m_hWaveOut = NULL;
+ m_Headers.m_pNext = NULL;
+ m_nBufferedSamples = 0;
+}
+
+CWaveOut::~CWaveOut()
+{
+ Term();
+}
+
+void CWaveOut::Release()
+{
+ delete this;
+}
+
+bool CWaveOut::PutSamples(short *pInSamples, int nInSamples)
+{
+ int granularity = 2048;
+ while( nInSamples )
+ {
+ int nSamples = (nInSamples > granularity) ? granularity : nInSamples;
+ short *pSamples = pInSamples;
+ nInSamples -= nSamples;
+ pInSamples += nSamples;
+
+ if(!m_hWaveOut)
+ return false;
+
+ // Kill any old headers..
+ KillOldHeaders();
+
+ // Allocate a header..
+ CWaveOutHdr *pHdr;
+ if(!(pHdr = (CWaveOutHdr*)malloc(sizeof(CWaveOutHdr) - 1 + nSamples*2)))
+ return false;
+
+ // Make a new one.
+ memset(&pHdr->m_Hdr, 0, sizeof(pHdr->m_Hdr));
+ pHdr->m_Hdr.lpData = pHdr->m_Data;
+ pHdr->m_Hdr.dwBufferLength = nSamples * 2;
+ memcpy(pHdr->m_Data, pSamples, nSamples*2);
+
+ MMRESULT mmr = waveOutPrepareHeader(m_hWaveOut, &pHdr->m_Hdr, sizeof(pHdr->m_Hdr));
+ if(mmr != MMSYSERR_NOERROR)
+ return false;
+
+ mmr = waveOutWrite(m_hWaveOut, &pHdr->m_Hdr, sizeof(pHdr->m_Hdr));
+ if(mmr != MMSYSERR_NOERROR)
+ {
+ delete pHdr;
+ waveOutUnprepareHeader(m_hWaveOut, &pHdr->m_Hdr, sizeof(pHdr->m_Hdr));
+ return false;
+ }
+
+ m_nBufferedSamples += nSamples;
+
+ // Queue up this header until waveOut is done with it.
+ pHdr->m_pNext = m_Headers.m_pNext;
+ m_Headers.m_pNext = pHdr;
+ }
+
+ return true;
+}
+
+void CWaveOut::Idle()
+{
+ KillOldHeaders();
+}
+
+int CWaveOut::GetNumBufferedSamples()
+{
+ return m_nBufferedSamples;
+}
+
+bool CWaveOut::Init(int sampleRate)
+{
+ Term();
+
+
+ WAVEFORMATEX format =
+ {
+ WAVE_FORMAT_PCM, // wFormatTag
+ 1, // nChannels
+ sampleRate, // nSamplesPerSec
+ sampleRate*BYTES_PER_SAMPLE,// nAvgBytesPerSec
+ BYTES_PER_SAMPLE, // nBlockAlign
+ BYTES_PER_SAMPLE * 8, // wBitsPerSample
+ sizeof(WAVEFORMATEX)
+ };
+
+ MMRESULT mmr = waveOutOpen(
+ &m_hWaveOut,
+ 0,
+ &format,
+ 0,
+ 0,
+ CALLBACK_NULL);
+
+ return mmr == MMSYSERR_NOERROR;
+}
+
+void CWaveOut::Term()
+{
+ if(m_hWaveOut)
+ {
+ waveOutClose(m_hWaveOut);
+ m_hWaveOut = NULL;
+ }
+}
+
+void CWaveOut::KillOldHeaders()
+{
+ // Look for any headers windows is done with.
+ CWaveOutHdr *pNext;
+ CWaveOutHdr **ppPrev = &m_Headers.m_pNext;
+ for(CWaveOutHdr *pCur=m_Headers.m_pNext; pCur; pCur=pNext)
+ {
+ pNext = pCur->m_pNext;
+
+ if(pCur->m_Hdr.dwFlags & WHDR_DONE)
+ {
+ m_nBufferedSamples -= (int)(pCur->m_Hdr.dwBufferLength / 2);
+ assert(m_nBufferedSamples >= 0);
+ waveOutUnprepareHeader(m_hWaveOut, &pCur->m_Hdr, sizeof(pCur->m_Hdr));
+ *ppPrev = pCur->m_pNext;
+ free(pCur);
+ }
+ else
+ {
+ ppPrev = &pCur->m_pNext;
+ }
+ }
+}
+
+
+
+IWaveOut* CreateWaveOut(int sampleRate)
+{
+ CWaveOut *pRet = new CWaveOut;
+ if(pRet && pRet->Init(sampleRate))
+ {
+ return pRet;
+ }
+ else
+ {
+ delete pRet;
+ return NULL;
+ }
+}
+
+