📄 wavefilesource.cxx
字号:
// WaveFileSource.cpp: implementation of the WaveFileSource class.
//
//////////////////////////////////////////////////////////////////////
#include "WaveFileSource.h"
#include "AudioSampleManager.h"
#include "AudioSample.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
WaveFileSource::WaveFileSource()
{
szFileName[0] = '\0';
pFormat = NULL;
bufferDuration = WAVEFILESOURCE_DEFAULT_BUFFERDURATION;
char subFacilityName[100];
sprintf(subFacilityName, "WaveFileSource:%x", this);
tracer.SetSubFacilityName(subFacilityName);
SetTraceLevel();
tracer.tracef(EE, "Constructor - begin\n");
PlayOnce();
bRunning = false;
InitializeCriticalSection(&filterMutex);
tracer.tracef(EE, "Constructor - end\n");
}
WaveFileSource::~WaveFileSource()
{
tracer.tracef(EE, "Destructor - begin\n");
EnterCriticalSection(&filterMutex);
tracer.tracef(ARB, "WaveFileSource~ : entered filterMutex\n");
LeaveCriticalSection(&filterMutex);
tracer.tracef(ARB, "WaveFileSource~ : left filterMutex\n");
CloseMMIO();
DeleteCriticalSection(&filterMutex);
tracer.tracef(EE, "Destructor - end\n");
}
int
WaveFileSource::SetTraceLevel()
{
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", "WaveFileSource", 0x100000);
}
tracer.SetSystemMask(SystemMask);
return 0;
}
int
WaveFileSource::PlayInLoop()
{
looping = true;
return 0;
}
int
WaveFileSource::PlayOnce()
{
looping = false;
return 0;
}
int
WaveFileSource::OpenWaveFile(const char *inputFileName)
{
int result(0);
PlayOnce();
if (strlen(inputFileName) < 128 && !bRunning)
{
do
{
CloseMMIO();
strcpy(szFileName, inputFileName);
// Open the file for reading with buffered I/O
// by using the default internal buffer
if(!(hmmio = mmioOpen(szFileName, NULL, MMIO_READ | MMIO_ALLOCBUF)))
{
tracer.tracef(ERR, "StartSource : mmioOpen(%s) returned 0x%x\n", szFileName, hmmio);
result = -10;
break;
}
MMIOINFO mmInfoStart;
mmioGetInfo(hmmio, &mmInfoStart, 0);
LONG fileStartPosition = (LONG)mmInfoStart.pchNext;
// Locate a "RIFF" chunk with a "WAVE" form type to make
// sure the file is a waveform-audio file.
mmckinfoParent.fccType = mmioFOURCC('W', 'A', 'V', 'E');
if (mmioDescend(hmmio, (LPMMCKINFO) &mmckinfoParent, NULL, MMIO_FINDRIFF))
{
tracer.tracef(ERR, "StartSource : %s not wave file", szFileName);
result = -20;
break;
}
// Find the "FMT" chunk (form type "FMT"); it must be
// a subchunk of the "RIFF" chunk.
mmckinfoSubchunk.ckid = mmioFOURCC('f', 'm', 't', ' ');
if (mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent, MMIO_FINDCHUNK))
{
tracer.tracef(ERR, "StartSource : File %s has no FMT chunk", szFileName);
result = -30;
break;
}
// Get the size of the "FMT" chunk. Allocate
// and lock memory for it.
dwFmtSize = mmckinfoSubchunk.cksize;
pFormat = (WAVEFORMATEX *) new char[dwFmtSize];
// Read the "FMT" chunk.
if (mmioRead(hmmio, (HPSTR) pFormat, dwFmtSize) != dwFmtSize)
{
tracer.tracef(ERR, "StartSource : Failed to read format chunk");
result = -40;
break;
}
// Ascend out of the "FMT" subchunk.
mmioAscend(hmmio, &mmckinfoSubchunk, 0);
// Find the data subchunk. The current file position should be at
// the beginning of the data chunk; however, you should not make
// this assumption. Use mmioDescend to locate the data chunk.
mmckinfoSubchunk.ckid = mmioFOURCC('d', 'a', 't', 'a');
if (mmioDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent, MMIO_FINDCHUNK))
{
tracer.tracef(ERR, "StartSource : File %s has no data chunk", szFileName);
result = -50;
break;
}
// Get the size of the data subchunk.
dwDataSize = mmckinfoSubchunk.cksize;
if (dwDataSize == 0L)
{
tracer.tracef(ERR, "StartSource : Data chunk of %s contains no data", szFileName);
result = -60;
break;
}
MMIOINFO mmInfo;
mmioGetInfo(hmmio, &mmInfo, 0);
dataStartPosition = (LONG)mmInfo.pchNext - fileStartPosition;
}
while(false);
if (result != 0)
{
CloseMMIO();
}
}
else
{
if (bRunning)
{
result = -70;
}
else
{
result = -80;
}
}
return result;
}
int
WaveFileSource::CloseMMIO()
{
if (hmmio)
{
mmioClose(hmmio, 0);
}
hmmio = NULL;
if (pFormat)
{
delete [] (char *)pFormat;
}
pFormat = NULL;
return 0;
}
int
WaveFileSource::StartSource()
{
int result(0);
int returnCode(0);
tracer.tracef(EE, "StartSource\n");
EnterCriticalSection(&filterMutex);
tracer.tracef(ARB, "StartSource : entered filterMutex\n");
do
{
if (bRunning)
{
tracer.tracef(ERR, "StartSource : e-error : already running\n");
result = -10;
break;
}
if (!hmmio || !pFormat)
{
tracer.tracef(ERR, "StartSource : e-error : hmmio = 0x%x, pFormat = 0x%x\n", hmmio, pFormat);
result = -20;
break;
}
returnCode = AudioSource::StartSource();
if (returnCode != 0)
{
tracer.tracef(ERR, "StartSource : e-AudioSource::StartSource : %d 0x%x\n", returnCode, returnCode);
result = -30;
break;
}
bRunning = true;
}
while (false);
LeaveCriticalSection(&filterMutex);
tracer.tracef(ARB, "StartSource : left filterMutex\n");
tracer.tracef(EE, "~StartSource : returning %d\n", result);
return result;
}
int
WaveFileSource::StopSource()
{
int result(0);
int returnCode(0);
tracer.tracef(EE, "StopSource\n");
EnterCriticalSection(&filterMutex);
tracer.tracef(ARB, "StopSource : entered filterMutex\n");
do
{
if (!bRunning)
{
tracer.tracef(ERR, "StopSource : e-error : not running\n");
result = -10;
break;
}
returnCode = CloseMMIO();
if (returnCode != 0)
{
tracer.tracef(ERR, "StopSource : e-CloseMMIO : %d 0x%x\n", returnCode, returnCode);
result = -20;
break;
}
returnCode = AudioSource::StopSource();
if (returnCode != 0)
{
tracer.tracef(ERR, "StopSource : e-AudioSource::StopSource : %d 0x%x\n", returnCode, returnCode);
result = -30;
break;
}
bRunning = false;
}
while (false);
LeaveCriticalSection(&filterMutex);
tracer.tracef(ARB, "StopSource : left filterMutex\n");
tracer.tracef(EE, "~StopSource : returning %d\n", result);
return result;
}
int
WaveFileSource::SourceThreadStarted(HANDLE sourceThreadHandle, DWORD sourceThreadID)
{
int result(0);
int returnCode(0);
tracer.tracef(EE, "SourceThreadStarted\n");
EnterCriticalSection(&filterMutex);
tracer.tracef(ARB, "SourceThreadStarted : entered filterMutex\n");
do
{
if (!hmmio || !pFormat)
{
tracer.tracef(ERR, "SourceThreadStarted : e-error : hmmio = 0x%x, pFormat = 0x%x\n", hmmio, pFormat);
result = -10;
break;
}
bRunning = true;
}
while (false);
tracer.tracef(ARB, "SourceThreadStarted : before firing FILE_STARTED %s\n", szFileName);
FireEvent(FILE_STARTED, szFileName);
tracer.tracef(ARB, "SourceThreadStarted : after firing FILE_STARTED %s\n", szFileName);
LeaveCriticalSection(&filterMutex);
tracer.tracef(ARB, "SourceThreadStarted : left filterMutex\n");
tracer.tracef(EE, "~SourceThreadStarted : returning %d\n", result);
return result;
}
int
WaveFileSource::SourceThreadStopped(HANDLE sourceThreadHandle, DWORD sourceThreadID)
{
int result(0);
int returnCode(0);
tracer.tracef(EE, "SourceThreadStopped\n");
EnterCriticalSection(&filterMutex);
tracer.tracef(ARB, "SourceThreadStopped : entered filterMutex\n");
do
{
returnCode = CloseMMIO();
if (returnCode != 0)
{
tracer.tracef(ERR, "SourceThreadStopped : e-CloseMMIO : %d 0x%x\n", returnCode, returnCode);
result = -10;
break;
}
bRunning = false;
}
while (false);
tracer.tracef(ARB, "SourceThreadStopped : before firing FILE_STOPPED %s\n", szFileName);
FireEvent(FILE_STOPPED, szFileName);
tracer.tracef(ARB, "SourceThreadStopped : after firing FILE_STOPPED %s\n", szFileName);
LeaveCriticalSection(&filterMutex);
tracer.tracef(ARB, "SourceThreadStopped : left filterMutex\n");
tracer.tracef(EE, "~SourceThreadStopped : returning %d\n", result);
return result;
}
int
WaveFileSource::GetFormat(WAVEFORMATEX *waveFormat)
{
if (pFormat)
{
*waveFormat = *pFormat;
}
return 0;
}
int
WaveFileSource::SetBufferDuration(int bufferDurationMillisec)
{
bufferDuration = bufferDurationMillisec;
return 0;
}
int
WaveFileSource::GenerateData(AudioSample **ppAudioSample)
{
tracer.tracef(DET, "GenerateData\n");
int result(0);
AudioSample *audioSample;
result = (AudioSampleManager::GetInstance())->GetAudioSample(&audioSample);
*ppAudioSample = audioSample;
if (audioSample)
{
audioSample->SetDataSize(0);
audioSample->SetSilenceDuration(bufferDuration);
if (bRunning)
{
audioSample->SetFormat(*pFormat);
int nBytesToRead = (pFormat->nAvgBytesPerSec * bufferDuration) / 1000;
if (audioSample->BufferSize() < nBytesToRead)
{
result = -20;
}
else
{
int bytes(0);
if((bytes = mmioRead(hmmio, (HPSTR) audioSample->Data(), nBytesToRead)) != nBytesToRead)
{
if (bytes < 0 || (bytes == 0 && !looping))
{
bytes = 0;
result = -30;
}
else if (looping)
{
mmioSeek(hmmio, dataStartPosition, SEEK_SET);
int nBytes = mmioRead(hmmio, (HPSTR) audioSample->Data(), nBytesToRead - bytes);
if (nBytes <= 0)
{
result = -40;
}
else
{
bytes += nBytes;
}
}
audioSample->SetDataSize(bytes);
}
else
{
audioSample->SetDataSize(nBytesToRead);
}
}
}
}
tracer.tracef(DET, "~GenerateData : data %d bytes, silence %d ms\n", audioSample->DataSize(), audioSample->GetSilenceDuration());
return result;
}
int
WaveFileSource::AddFilePlayListener(WaveFileSourceListener *waveFileSourceListener)
{
return AddListener((void *)waveFileSourceListener);
}
int
WaveFileSource::RemoveFilePlayListener(WaveFileSourceListener *waveFileSourceListener)
{
return RemoveListener((void *)waveFileSourceListener);
}
int
WaveFileSource::FireEvent(int eventType, char *waveFileName)
{
EnterCriticalSection(&listenersMutex);
std::vector<void *>::iterator iter = listeners.begin();
while (iter != listeners.end())
{
switch(eventType)
{
case FILE_STARTED:
((WaveFileSourceListener *)(*iter))->FilePlayStarted(this, waveFileName);
break;
case FILE_STOPPED:
((WaveFileSourceListener *)(*iter))->FilePlayStopped(this, waveFileName);
break;
default:
break;
}
iter++;
}
LeaveCriticalSection(&listenersMutex);
/* FireEventThreadParams *params = new FireEventThreadParams();
params->eventType = eventType;
params->waveFileSource = this;
strncpy(params->waveFileName, waveFileName, min(strlen(waveFileName)+1, 1024));
(params->waveFileName)[1024] = '\0';
DWORD threadID;
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)FireEventThread, (LPVOID)params, 0, &threadID);
*/ return 0;
}
DWORD WINAPI
WaveFileSource::FireEventThread(LPVOID param)
{
FireEventThreadParams *params = (FireEventThreadParams *)param;
WaveFileSource *waveFileSource = params->waveFileSource;
EnterCriticalSection(&(waveFileSource->listenersMutex));
std::vector<void *>::iterator iter = waveFileSource->listeners.begin();
while (iter != waveFileSource->listeners.end())
{
switch(params->eventType)
{
case FILE_STARTED:
((WaveFileSourceListener *)(*iter))->FilePlayStarted(waveFileSource, params->waveFileName);
break;
case FILE_STOPPED:
((WaveFileSourceListener *)(*iter))->FilePlayStopped(waveFileSource, params->waveFileName);
break;
default:
break;
}
iter++;
}
LeaveCriticalSection(&(waveFileSource->listenersMutex));
return 0;
}
void
WaveFileSourceListener::FilePlayStarted(WaveFileSource *waveFileSource, char *waveFileName)
{
// AfxMessageBox("WaveFileSourceListener::FilePlayStarted : ERROR : pure virtual function call !!!\n");
}
void
WaveFileSourceListener::FilePlayStopped(WaveFileSource *waveFileSource, char *waveFileName)
{
// AfxMessageBox("WaveFileSourceListener::FilePlaySopped : ERROR : pure virtual function call !!!\n");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -