⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wavefilesource.cxx

📁 rtp在linux下的实现
💻 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 + -