www.pudn.com > DirectDraw.rar > DirectSound.cpp, change:2007-06-08,size:5660b


// DirectSound.cpp: implementation of the CDirectSound class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "DirectSound.h" 
#include "../Mutex.h" 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
#pragma comment(lib,"dsound.lib") 
 
CDirectSound::CDirectSound() 
{ 
	m_lpDS = NULL; 
	m_lpDSBuffer = NULL; 
	m_bPlaying = FALSE; 
	m_dwLastPlayPos = 0; 
	m_dwWriteOffset = 0; 
	m_nSamples = 44100; 
	m_wChannels=1; 
	m_wBitsPerSample=16; 
	m_nVolume = 0; 
	m_hMutex = CreateMutex(NULL,FALSE,NULL); 
} 
 
CDirectSound::~CDirectSound() 
{ 
	Close(); 
	CloseHandle(m_hMutex); 
} 
 
BOOL CDirectSound::Start() 
{ 
	return Open(); 
} 
 
void CDirectSound::Stop() 
{ 
	CMutex mutex(m_hMutex); 
	if(m_bPlaying) 
	{ 
		if(m_lpDSBuffer) 
		{ 
			m_lpDSBuffer->Stop(); 
			m_lpDSBuffer->SetCurrentPosition(0); 
//			m_lpDSBuffer->Release(); 
//			m_lpDSBuffer = NULL; 
		} 
		m_bPlaying = FALSE; 
	} 
//	if(m_lpDS) 
//	{ 
//		m_lpDS->Release(); 
//		m_lpDS = NULL; 
//	} 
	m_dwLastPlayPos = 0; 
	m_dwWriteOffset = 0; 
} 
 
//void CDirectSound::Pause() 
//{ 
//    if(m_lpDSBuffer) 
//		m_lpDSBuffer->Stop(); 
//} 
 
/*void CDirectSound::Resume() 
{ 
	if(m_bPlaying) 
	{ 
		DWORD CurPos,WritePos; 
		m_lpDSBuffer->GetCurrentPosition(&CurPos,&WritePos); 
		m_lpDSBuffer->SetCurrentPosition(CurPos); 
		m_lpDSBuffer->Play(0,0,DSBPLAY_LOOPING); 
	} 
}*/ 
 
BOOL CDirectSound::Open() 
{ 
	SetAudioFormat(m_nSamples,m_wChannels,m_wBitsPerSample); 
	return TRUE; 
} 
 
void CDirectSound::Close() 
{ 
	CMutex mutex(m_hMutex); 
	Stop(); 
} 
 
void CDirectSound::ClearBuffer() 
{ 
	CMutex mutex(m_hMutex); 
	if(m_lpDSBuffer) 
	{ 
		void *lpBuffer1 = NULL,*lpBuffer2 = NULL; 
		DWORD dwBytes1 = 0,dwBytes2  = 0; 
		m_lpDSBuffer->SetCurrentPosition(0); 
		m_lpDSBuffer->Lock(0,m_dwBufSize,&lpBuffer1,&dwBytes1,&lpBuffer2,&dwBytes2,0); 
		if(lpBuffer1) 
		{ 
			ZeroMemory(lpBuffer1,dwBytes1); 
		} 
		if(lpBuffer2) 
		{ 
			ZeroMemory(lpBuffer2,dwBytes2); 
		} 
		m_lpDSBuffer->Unlock(lpBuffer1,dwBytes1,lpBuffer2,dwBytes2); 
	} 
} 
 
BOOL CDirectSound::SetVolume(LONG nVolume) 
{ 
	CMutex mutex(m_hMutex); 
	nVolume -= 10000; 
	m_nVolume = nVolume; 
	if(m_lpDSBuffer) 
	{ 
		if(DS_OK == m_lpDSBuffer->SetVolume(m_nVolume)) 
			return TRUE; 
	} 
	return FALSE; 
} 
 
BOOL CDirectSound::GetVolume(LONG *pnVolume) 
{ 
	CMutex mutex(m_hMutex); 
	if(m_lpDSBuffer) 
	{ 
		if(DS_OK == m_lpDSBuffer->GetVolume(pnVolume)) 
		{ 
			*pnVolume += 10000; 
			return TRUE;	 
		} 
	} 
	*pnVolume = m_nVolume + 10000; 
	return TRUE; 
} 
 
void CDirectSound::AddAudioData(LPVOID pData,DWORD dwSize) 
{ 
	CMutex mutex(m_hMutex); 
	HRESULT hr; 
	if(dwSize > m_dwBufSize) 
		return; 
	if(NULL == m_lpDSBuffer) 
	{ 
		SetAudioFormat(m_nSamples,m_wChannels); 
	} 
	if(NULL == m_lpDSBuffer) 
		return ; 
	LPVOID lpAudioPtr1 = NULL,lpAudioPtr2 = NULL; 
	DWORD dwAudioBytes1 = 0, dwAudioBytes2 = 0; 
	if(DS_OK != (hr = m_lpDSBuffer->Lock(m_dwLastPlayPos,dwSize,&lpAudioPtr1,&dwAudioBytes1,&lpAudioPtr2,&dwAudioBytes2,0))) 
	{ 
		return ; 
	} 
	if(lpAudioPtr1) 
		memcpy(lpAudioPtr1,pData,dwAudioBytes1); 
	if(lpAudioPtr2) 
		memcpy(lpAudioPtr2,(PBYTE)pData+dwAudioBytes1,dwAudioBytes2); 
	m_lpDSBuffer->Unlock(lpAudioPtr1,dwAudioBytes1,lpAudioPtr2,dwAudioBytes2); 
	m_dwLastPlayPos += dwSize; 
	if(m_dwLastPlayPos >= m_dwBufSize) 
		m_dwLastPlayPos -= m_dwBufSize; 
	if(!m_bPlaying && (m_dwLastPlayPos >= m_dwBufSize / 15)) 
	{ 
		m_dwWriteOffset = m_dwLastPlayPos; 
		m_bPlaying = TRUE; 
		HRESULT nRet = m_lpDSBuffer->Play(0,0,DSBPLAY_LOOPING); 
	} 
} 
 
void CDirectSound::SetAudioFormat(DWORD dwSamples, WORD wChannels, WORD wBitsPerSample) 
{ 
	CMutex mutex(m_hMutex); 
	if(NULL != m_lpDS && 
		NULL != m_lpDSBuffer && 
		dwSamples == m_nSamples && 
		wChannels == m_wChannels && 
		wBitsPerSample == m_wBitsPerSample) 
	{ 
		return; 
	} 
	Stop(); 
	if(NULL == m_lpDS) 
	{ 
		HWND hWnd = GetDesktopWindow(); 
		if(NULL == hWnd) 
			return ; 
		if(DS_OK != DirectSoundCreate(NULL, &m_lpDS , NULL)) 
			return; 
		if(DS_OK != m_lpDS->SetCooperativeLevel(hWnd,DSSCL_NORMAL)) 
		{ 
			Close(); 
			return ; 
		} 
	} 
	if(NULL == m_lpDS) 
		return ; 
	WAVEFORMATEX wfe; 
	ZeroMemory(&wfe,sizeof(WAVEFORMATEX)); 
	wfe.wFormatTag = WAVE_FORMAT_PCM; 
	wfe.nChannels = wChannels; 
	wfe.nSamplesPerSec = dwSamples; 
	wfe.wBitsPerSample = wBitsPerSample; 
	wfe.nBlockAlign=(wfe.wBitsPerSample/8) * wfe.nChannels; 
	wfe.nAvgBytesPerSec=wfe.nBlockAlign * wfe.nSamplesPerSec; 
	DSBUFFERDESC  dsbdesc; 
	memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); 
	dsbdesc.dwSize = sizeof(DSBUFFERDESC); 
	dsbdesc.lpwfxFormat = &wfe; 
	dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS; 
	dsbdesc.dwBufferBytes = wfe.nAvgBytesPerSec * 3; 
	if(DS_OK != m_lpDS->CreateSoundBuffer(&dsbdesc,&m_lpDSBuffer,NULL)) 
	{ 
		Close(); 
		return ; 
	} 
	m_dwBufSize = dsbdesc.dwBufferBytes; 
	m_nSamples = dwSamples; 
	m_wChannels = wChannels; 
	m_wBitsPerSample = wBitsPerSample; 
//	WriteSilenceData(); 
	SetVolume(m_nVolume + 10000); 
} 
 
void CDirectSound::WriteSilenceData() 
{ 
	if(m_lpDSBuffer == NULL) 
		return ; 
	void *buffer1 = NULL, *buffer2 = NULL; 
	DWORD bytes1 = 0, bytes2 = 0; 
	 
	HRESULT hr = m_lpDSBuffer->Lock(0, 
		m_dwBufSize, 
		&buffer1, &bytes1, 
		&buffer2, &bytes2, 0L); 
	if(hr == S_OK) 
	{ 
		BYTE bSilence = (m_wBitsPerSample == 8) ? 0x80 : 0; 
		if(buffer1) 
			memset(buffer1,bSilence,bytes1); 
		if(buffer2) 
			memset(buffer2,bSilence,bytes2); 
		m_lpDSBuffer->Unlock(buffer1, bytes1, buffer2, bytes2); 
	} 
}