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

📄 audiorenderer.cpp

📁 <VC++视频音频开发>一书的光盘资料。
💻 CPP
字号:
/**************************************************************************************
 *                                                                                    *
 *                                                                                    *
 **************************************************************************************/

#include "AudioRenderer.h"



#define PERIOD 30


MediaAudioRenderer::MediaAudioRenderer()
{
	this->lpDirectSound = NULL;
	this->lpBuffer      = NULL;
}

MediaAudioRenderer::~MediaAudioRenderer()
{
}


media_type_t  MediaAudioRenderer::GetType()
{
	return MEDIA_TYPE_AUDIO_RENDERER;
}

char         *MediaAudioRenderer::GetName()
{
	return "DirectSound Audio Renderer";
}


	
MP_RESULT     MediaAudioRenderer::Connect(MediaItem *item)
{
	return MP_RESULT_ERROR;
}

MP_RESULT     MediaAudioRenderer::ReleaseConnections()
{
	return MP_RESULT_ERROR;
}

DWORD         MediaAudioRenderer::GetCaps()
{
	return 0;
}

MP_RESULT     MediaAudioRenderer::Configure(HINSTANCE hInstance, HWND hwnd)
{
	return MP_RESULT_ERROR;
}


MP_RESULT     MediaAudioRenderer::Open(HWND hwnd, WAVEFORMATEX *inFormat)
{
	if(hwnd && inFormat) {

		this->ourFormat = inFormat;

		HRESULT hr;
			
		if(DirectSoundCreate(NULL, &this->lpDirectSound, NULL) == DS_OK) {



			hr = lpDirectSound->SetCooperativeLevel(hwnd, DSSCL_NORMAL);

			if(hr != DS_OK) {

				this->lpDirectSound->Release();
				this->lpDirectSound = NULL;

				return MP_RESULT_ERROR;
			}

	

			DSBUFFERDESC  dsbdesc;
			WAVEFORMATEX  wf;
			
			memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
			dsbdesc.dwSize = sizeof(DSBUFFERDESC);
    
			ZeroMemory(&wf, sizeof(WAVEFORMATEX));
			memcpy(&wf, this->ourFormat, sizeof(WAVEFORMATEX));

			dsbdesc.lpwfxFormat = (LPWAVEFORMATEX) &wf;
    
			dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS;			
			dsbdesc.dwBufferBytes = 2 * this->ourFormat->nAvgBytesPerSec;

			hr = lpDirectSound->CreateSoundBuffer(&dsbdesc, &lpBuffer, NULL);

			if(hr != DS_OK) {

				this->lpDirectSound->Release();
				this->lpDirectSound = NULL;

				return MP_RESULT_ERROR;
			}
		

			this->dwBufferSize = 2 * this->ourFormat->nAvgBytesPerSec;
			this->lInTimer = FALSE;
		
			return MP_RESULT_OK;
		}
	}

	return MP_RESULT_ERROR;
}




MP_RESULT     MediaAudioRenderer::SetCallback(void *lpData, MediaAudioCallback callback)
{
	this->lpData   = lpData;
	this->callback = callback;

	return MP_RESULT_OK;
}

MP_RESULT     MediaAudioRenderer::SetVolume(unsigned int volume)
{
	if(this->lpBuffer) {

		double vol;

		vol = - ( 70*pow(10, (100.0 - (double) volume)*2.0/100.0) );

		if(this->lpBuffer != NULL)
			this->lpBuffer->SetVolume((int) vol);
	}

	return MP_RESULT_ERROR;
}

unsigned long MediaAudioRenderer::GetAudioTime()
{
	return (unsigned long) (( ((double) this->dwPlayed * (1000/(this->ourFormat->wBitsPerSample*this->ourFormat->nChannels/8)))) / (this->ourFormat->nSamplesPerSec));
}


void CALLBACK AudioTimeFunc(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
	MediaAudioRenderer *audioRenderer = (MediaAudioRenderer *) dwUser;
	
	if (InterlockedExchange(&audioRenderer->lInTimer, TRUE)) return;

	if(audioRenderer->callback) {
		
			void *buffer1, *buffer2;
			DWORD bytes1 = 0, bytes2 = 0;
			DWORD dwPlay, dwWrite, dwSize;

			audioRenderer->lpBuffer->GetCurrentPosition(&dwPlay, &dwWrite);

			if(audioRenderer->dwLastPlayPos == dwPlay) {
			
				InterlockedExchange(&audioRenderer->lInTimer, FALSE);
				return;
			}

			if(audioRenderer->dwLastPlayPos <= dwPlay) {

				dwSize = dwPlay - audioRenderer->dwLastPlayPos;

				audioRenderer->lpBuffer->Lock(audioRenderer->dwLastPlayPos,
											  dwSize,
											  &buffer1, &bytes1, 
											  &buffer2, &bytes2, 0);

				if(buffer1) {

					bytes1 = audioRenderer->callback(audioRenderer->lpData, buffer1, bytes1);
				}

				audioRenderer->lpBuffer->Unlock(buffer1, bytes1, buffer2, bytes2);

				audioRenderer->dwLastPlayPos += bytes1;
				audioRenderer->dwPlayed += bytes1;
			}
			else {

				DWORD bytes1_ori;

				dwSize = (audioRenderer->dwBufferSize - audioRenderer->dwLastPlayPos) + dwPlay;

				audioRenderer->lpBuffer->Lock(audioRenderer->dwLastPlayPos,
											  dwSize,
											  &buffer1, &bytes1, 
											  &buffer2, &bytes2, 0);

				bytes1_ori = bytes1;

				if(bytes1) {

					bytes1 = audioRenderer->callback(audioRenderer->lpData, buffer1, bytes1);
				}

				if(bytes2) {

					bytes2 = audioRenderer->callback(audioRenderer->lpData, buffer2, bytes2);
				}

				audioRenderer->lpBuffer->Unlock(buffer1, bytes1, buffer2, bytes2);

				audioRenderer->dwPlayed += bytes1 + bytes2;

				if(bytes1_ori == bytes1)
					audioRenderer->dwLastPlayPos = bytes2;
				else 
					audioRenderer->dwLastPlayPos += bytes1;
			}
			
			InterlockedExchange(&audioRenderer->lInTimer, FALSE);
			return;
	}
}



MP_RESULT     MediaAudioRenderer::Bufferize()
{
	if(this->lpBuffer) {

		void *buffer1, *buffer2;
		DWORD bytes1, bytes2, length;


		this->lpBuffer->SetCurrentPosition(0);

		this->lpBuffer->Lock(0, this->dwBufferSize,
							    &buffer1, &bytes1, &buffer2, &bytes2, 0);


		length = this->callback(this->lpData, buffer1, this->dwBufferSize);

		this->lpBuffer->Unlock(buffer1, bytes1, buffer2, bytes2);

		this->dwNextWriteOffset = this->dwProgress = this->dwPlayed = this->dwLastPlayPos = 0;
	}

	return MP_RESULT_OK;
}

MP_RESULT     MediaAudioRenderer::Start()
{
	if(this->lpBuffer) {

		void *buffer1, *buffer2;
		DWORD bytes1, bytes2, length;



		this->lpBuffer->SetCurrentPosition(0);

		this->lpBuffer->Lock(0, this->dwBufferSize,
							    &buffer1, &bytes1, &buffer2, &bytes2, 0);



		length = this->callback(this->lpData, buffer1, this->dwBufferSize);

		this->lpBuffer->Unlock(buffer1, length, buffer2, bytes2);

		this->dwProgress = this->dwPlayed = this->dwLastPlayPos = 0;



		this->paused = 0;
		
		if(this->lpBuffer->Play(0, 0, DSBPLAY_LOOPING) != DS_OK) {

			return MP_RESULT_ERROR;
		}
	
		if( timeBeginPeriod( PERIOD ) != 0 ) {
			
			return MP_RESULT_ERROR;
		}
        else {
			
			this->uTimerID = timeSetEvent( PERIOD, 5, AudioTimeFunc, (DWORD)(LPVOID)this, TIME_PERIODIC );
		}

		return MP_RESULT_OK;
	}

	return MP_RESULT_ERROR;
}

MP_RESULT     MediaAudioRenderer::Pause()
{
	if(this->paused) {

		this->paused = 0;
		this->lpBuffer->Play(0, 0, DSBPLAY_LOOPING);
		
		this->uTimerID = timeSetEvent( PERIOD, 5, AudioTimeFunc, (DWORD)(LPVOID)this, TIME_PERIODIC );
		
	}
	else {

		if(this->uTimerID) {

			timeKillEvent(this->uTimerID); 
 		}

		this->paused = 1;
		this->lpBuffer->Stop();
	}

	return MP_RESULT_OK;
}

MP_RESULT     MediaAudioRenderer::Stop()
{
	if(this->uTimerID) {

		timeKillEvent(this->uTimerID); 
 	}

	if(this->lpBuffer) {
		this->lpBuffer->Stop();
		timeEndPeriod(PERIOD); 
	}
	
	return MP_RESULT_OK;
}

MP_RESULT     MediaAudioRenderer::Close()
{
	this->Stop();

	if(this->lpDirectSound) {

		if(this->lpBuffer)
			this->lpBuffer->Release();

		this->lpBuffer = NULL;

		this->lpDirectSound->Release();

		this->lpDirectSound = NULL;
	}

	return MP_RESULT_OK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -