📄 waveaudiosink.cxx
字号:
// WaveAudioSink.cpp: implementation of the WaveAudioSink class.
//
//////////////////////////////////////////////////////////////////////
#ifndef WIN32
#include <stdio.h>
#endif
#include "AudioSample.h"
#include "AudioSource.h"
#include "WaveAudioSink.h"
using namespace std;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
WaveAudioSink::WaveAudioSink()
{
char subFacilityName[100];
sprintf(subFacilityName, "WaveAudioSink:%x", this);
tracer.SetSubFacilityName(subFacilityName);
SetTraceLevel();
tracer.tracef(EE, "Constructor begin\n");
enabled = true;
#ifdef WIN32
waveoutDeviceID = WAVE_MAPPER;
dataEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
pauseEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
#else
//Need a wave mapper equivalent here - TODO
#endif
frameSize = WAVESINK_DEFAULT_WAVEHDR_SIZE;
numFrames = WAVESINK_NUM_WAVEHDR;
InitializeCriticalSection(&dataMutex);
InitializeCriticalSection(&freeBuffersMutex);
InitializeCriticalSection(&filterMutex);
// set default format
wfx.nAvgBytesPerSec = 16000;
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.wBitsPerSample = 16;
wfx.nChannels = 1;
wfx.nBlockAlign = 2;
wfx.nSamplesPerSec = 8000;
wfx.cbSize = 0;
tracer.tracef(EE, "Constructor end\n");
}
WaveAudioSink::~WaveAudioSink()
{
tracer.tracef(EE, "Destructor begin\n");
EnterCriticalSection(&filterMutex);
tracer.tracef(ARB, "WaveAudioSink~ : entered filterMutex\n");
LeaveCriticalSection(&filterMutex);
tracer.tracef(ARB, "WaveAudioSink~ : left filterMutex\n");
DeleteCriticalSection(&dataMutex);
DeleteCriticalSection(&freeBuffersMutex);
DeleteCriticalSection(&filterMutex);
#ifdef WIN32
CloseHandle(dataEvent);
CloseHandle(pauseEvent);
#endif
tracer.tracef(EE, "Destructor end\n");
}
int
WaveAudioSink::SetTraceLevel()
{
#ifdef WIN32
long SystemMask = 0;
if ((SystemMask = GetRegKeyLong(HKEY_CURRENT_USER, "Software\\Cisco Systems\\MTC\\Tracing", "AllComponents", 0x0)) == 0)
{
SystemMask = GetRegKeyLong(HKEY_CURRENT_USER, "Software\\Cisco Systems\\MTC\\Tracing", "WaveAudioSink", 0x100000);
}
tracer.SetSystemMask(SystemMask);
#endif
return 0;
}
int
WaveAudioSink::SetVolume(unsigned long volume)
{
#ifdef WIN32
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "SetVolume %d\n", volume);
volume = min(100, volume);
unsigned long normalizedVolume = (volume * 0xffff) / 100;
unsigned long volumeToSet = (normalizedVolume << 16) + normalizedVolume;
tracer.tracef(SDI_LEVEL_DETAILED, "SetVolume : Entering dataMutex\n");
EnterCriticalSection(&dataMutex);
if (bRunning)
{
tracer.tracef(SDI_LEVEL_ARBITRARY, "SetVolume : waveOutSetVolume\n");
MMRESULT mr = waveOutSetVolume(hWaveOut, volumeToSet);
tracer.tracef(SDI_LEVEL_ARBITRARY, "SetVolume : ~waveOutSetVolume\n");
LeaveCriticalSection(&dataMutex);
tracer.tracef(SDI_LEVEL_DETAILED, "SetVolume : Left dataMutex\n");
if (FAILED(mr))
{
tracer.tracef(SDI_LEVEL_ERROR, "SetVolume : e-waveOutSetVolume : 0x%x\n", mr);
}
}
else
{
LeaveCriticalSection(&dataMutex);
tracer.tracef(SDI_LEVEL_DETAILED, "SetVolume : Left dataMutex\n");
}
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "~SetVolume\n");
return NOERROR;
#else
//Need Linux specific code to set the volume
return 0;
#endif
}
int
WaveAudioSink::SetFrameSize(unsigned long size)
{
tracer.tracef(EE, "SetFrameSize %u\n", size);
#ifdef WIN32
frameSize = min(size, WAVESINK_MAX_WAVEHDR_SIZE);
tracer.tracef(EE, "~SetFrameSize\n");
return NOERROR;
#else
frameSize = (size < WAVESINK_MAX_WAVEHDR_SIZE) ? size : WAVESINK_MAX_WAVEHDR_SIZE;
return 0;
#endif
}
int
WaveAudioSink::SetNumFrames(unsigned long num)
{
tracer.tracef(EE, "SetNumFrames %u\n", num);
#ifdef WIN32
numFrames = min(num, WAVESINK_MAX_WAVEHDR);
tracer.tracef(EE, "~SetNumFrames\n");
return NOERROR;
#else
numFrames = (num < WAVESINK_MAX_WAVEHDR) ? num : WAVESINK_MAX_WAVEHDR;
return 0;
#endif
}
int
WaveAudioSink::BeginAudioRender()
{
#ifdef WIN32
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "BeginAudioRender\n");
HRESULT result = NOERROR;
tracer.tracef(SDI_LEVEL_DETAILED, "BeginAudioRender : Entering freeBuffersMutex\n");
EnterCriticalSection(&freeBuffersMutex);
freeBuffers.clear();
LeaveCriticalSection(&freeBuffersMutex);
tracer.tracef(SDI_LEVEL_DETAILED, "BeginAudioRender : Left freeBuffersMutex\n");
MMRESULT mr = NOERROR;
tracer.tracef(SDI_LEVEL_ARBITRARY, "BeginAudioRender : waveOutOpen\n");
mr = waveOutOpen(&hWaveOut, waveoutDeviceID, &wfx, (DWORD)SpeakerCallback, DWORD(this), CALLBACK_FUNCTION);
tracer.tracef(SDI_LEVEL_ARBITRARY, "BeginAudioRender : ~waveOutOpen\n");
if (mr != NOERROR)
{
tracer.tracef(SDI_LEVEL_ERROR, "BeginAudioRender : e-waveOutOpen : 0x%x\n", mr);
result = -10;
}
else
{
for (int i=0; i<numFrames; i++)
{
memset(&(waveHdr[i]), 0, sizeof(waveHdr[i]));
waveHdr[i].lpData = dataBuffer[i];
waveHdr[i].dwBufferLength = frameSize;
waveHdr[i].dwFlags = 0;
waveHdr[i].dwUser = i;
tracer.tracef(SDI_LEVEL_ARBITRARY, "BeginAudioRender : waveOutPrepareHeader\n");
result = waveOutPrepareHeader(hWaveOut, &(waveHdr[i]), sizeof(waveHdr[i]));
tracer.tracef(SDI_LEVEL_ARBITRARY, "BeginAudioRender : ~waveOutPrepareHeader\n");
if (result != MMSYSERR_NOERROR)
{
tracer.tracef(SDI_LEVEL_ERROR, "BeginAudioRender : e-waveOutPrepareHeader : 0x%x\n", result);
}
else
{
tracer.tracef(SDI_LEVEL_ARBITRARY, "BeginAudioRender : Entering freeBuffersMutex\n");
EnterCriticalSection(&freeBuffersMutex);
freeBuffers.push_back(&(waveHdr[i]));
LeaveCriticalSection(&freeBuffersMutex);
}
}
}
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "~BeginAudioRender : returning %d 0x%x\n", result);
return result;
#else
return 0;
#endif
}
int
WaveAudioSink::EndAudioRender()
{
#ifdef WIN32
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "EndAudioRender\n");
HRESULT result = NOERROR;
tracer.tracef(SDI_LEVEL_ARBITRARY, "EndAudioRender : waveOutReset\n");
result = waveOutReset(hWaveOut);
tracer.tracef(SDI_LEVEL_ARBITRARY, "EndAudioRender : ~waveOutReset\n");
if (result != MMSYSERR_NOERROR)
{
tracer.tracef(SDI_LEVEL_ERROR, "EndAudioRender : e-waveOutReset : 0x%x\n", result);
result = -10;
}
else
{
for (int i=0; i<numFrames; i++)
{
tracer.tracef(SDI_LEVEL_ARBITRARY, "EndAudioRender : waveOutUnprepareHeader\n");
result = waveOutUnprepareHeader(hWaveOut, &(waveHdr[i]), sizeof(waveHdr[i]));
tracer.tracef(SDI_LEVEL_ARBITRARY, "EndAudioRender : ~waveOutUnprepareHeader\n");
if (result != MMSYSERR_NOERROR)
{
tracer.tracef(SDI_LEVEL_ERROR, "EndAudioRender : e-waveOutUnprepareHeader : 0x%x\n", result);
}
}
tracer.tracef(SDI_LEVEL_ARBITRARY, "EndAudioRender : waveOutClose\n");
result = waveOutClose(hWaveOut);
tracer.tracef(SDI_LEVEL_ARBITRARY, "EndAudioRender : ~waveOutClose\n");
if (result != MMSYSERR_NOERROR)
{
tracer.tracef(SDI_LEVEL_ERROR, "EndAudioRender : e-waveOutClose : 0x%x\n", result);
result = -30;
}
}
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "~EndAudioRender : returning %d 0x%x\n", result);
return result;
#else
//Do we do somthing for Linux ? - TODO
return 0;
#endif
}
int
WaveAudioSink::ResetAudioRender()
{
#ifdef WIN32
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "ResetAudioRender\n");
HRESULT result = NOERROR;
result = EndAudioRender();
if (result == MMSYSERR_NOERROR)
{
result = BeginAudioRender();
}
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "~ResetAudioRender : %d 0x%x\n", result, result);
return result;
#else
//Handle for Linux - TODO
return 0;
#endif
}
WAVEHDR *
WaveAudioSink::GetBuffer()
{
tracer.tracef(DET, "GetBuffer\n");
WAVEHDR *wHdr = NULL;
#ifdef WIN32
int bufferLength;
while(true) {
tracer.tracef(SDI_LEVEL_DETAILED, "GetBuffer : Entering dataMutex\n");
EnterCriticalSection(&dataMutex);
bool running = bRunning;
LeaveCriticalSection(&dataMutex);
tracer.tracef(SDI_LEVEL_DETAILED, "GetBuffer : Left dataMutex\n");
if (!running)
{
tracer.tracef(SDI_LEVEL_DETAILED, "GetBuffer : !bRunning\n");
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -