有几个地方,破脑袋死也想不通,于是先在这里留个记号,防止被我这破脑袋忘掉了
// TestDirecSound.cpp: implementation of the TestDirecSound class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "TestDirecSound.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//
void CALLBACK TimerProcess(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
CTestDirectSound *pDDS = (CTestDirectSound *)dwUser;
pDDS->TimerCallback();
}
BOOL CALLBACK DSEnumCallBack(GUID *pGuid, LPCSTR strDesc, LPCSTR strDrvName, void *pContext)
{
CTestDirectSound *pDDS = (CTestDirectSound *)pContext;
return pDDS->DSEnumerateCallBack(pGuid, strDesc, strDrvName);
}
CTestDirectSound::CTestDirectSound()
{
m_lpDSB = NULL;
m_lpDS = NULL;
m_lpAudioBuf = NULL;
m_pHEvent[0] = CreateEvent(NULL, FALSE, FALSE, _T("Direct_Sound_Buffer_Notify_0"));
m_pHEvent[1] = CreateEvent(NULL, FALSE, FALSE, _T("Direct_Sound_Buffer_Notify_1"));
m_dwCircles1 = 0;
m_dwCircles2 = 0;
m_fStop = FALSE;
}
CTestDirectSound::~CTestDirectSound()
{
if (m_lpAudioBuf)
delete []m_lpAudioBuf;
}
void CTestDirectSound::Play(LPCSTR lpszFileName)
{
m_fStop = FALSE;
m_WaveFile.Open((char *)lpszFileName, &m_WFE, WAVEFILE_READ);
memcpy(&m_WFE, m_WaveFile.GetFormat(), sizeof(m_WFE));
SetFormat();
//Write the audio data to DirectSoundBuffer
LPVOID lpvAudio1 = NULL, lpvAudio2 = NULL;
DWORD dwBytesAudio1 = 0, dwBytesAudio2 = 0;
//Lock DirectSoundBuffer
HRESULT hr = m_lpDSB->Lock(0, m_WFE.nAvgBytesPerSec, &lpvAudio1, &dwBytesAudio1, &lpvAudio2, &dwBytesAudio2, 0);
if ( FAILED(hr) ) {
OutputDebugString("lock directsound buffer failed");
return;
}
DWORD nRetBytes;
m_WaveFile.Read(m_lpAudioBuf, m_WFE.nSamplesPerSec * m_WFE.nBlockAlign, &nRetBytes);
//Init lpvAudio1
if (NULL != lpvAudio1) {
memset(lpvAudio1, 0, dwBytesAudio1);
}
//Init lpvAudio2
if (NULL != lpvAudio2) {
memset(lpvAudio2, 0, dwBytesAudio2);
}
//Copy Audio Buffer to DirectSoundBuffer
if (NULL == lpvAudio2) {
memcpy(lpvAudio1, m_lpAudioBuf, nRetBytes);
}
else {
memcpy(lpvAudio1, m_lpAudioBuf, dwBytesAudio1);
memcpy(lpvAudio2, m_lpAudioBuf + dwBytesAudio1, dwBytesAudio2);
}
//Unlock DirectSoundBuffer
m_lpDSB->Unlock(lpvAudio1, dwBytesAudio1, lpvAudio2, dwBytesAudio2);
//Beging Play
m_lpDSB->Play(0, 0, DSBPLAY_LOOPING);
//timeSetEvent
m_timerID = timeSetEvent(300, 100, TimerProcess, (DWORD)this, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
}
void CTestDirectSound::Stop()
{
if (NULL != m_lpDSB) {
m_lpDSB->Stop();
timeKillEvent(m_timerID);
//Empty the buffer
LPVOID lpvAudio1 = NULL;
DWORD dwBytesAudio1 = 0;
HRESULT hr = m_lpDSB->Lock(0, 0, &lpvAudio1, &dwBytesAudio1, NULL, NULL, DSBLOCK_ENTIREBUFFER);
if ( FAILED(hr) ) {
OutputDebugString(_T("Lock entirebuffer failed! Stop Failed!"));
return;
}
memset(lpvAudio1, 0, dwBytesAudio1);
m_lpDSB->Unlock(lpvAudio1, dwBytesAudio1, NULL, NULL);
//Move the current play position to begin
m_lpDSB->SetCurrentPosition(0);
//Reset Event
ResetEvent(m_pHEvent[0]);
ResetEvent(m_pHEvent[1]);
//Set Circles1 and Circles2 0
m_dwCircles1 = 0;
m_dwCircles2 = 0;
}
}
void CTestDirectSound::About()
{
HRESULT hr;
hr = DirectSoundEnumerate(DSEnumCallBack, (void *)this);
if (FAILED(hr))
AfxMessageBox("Enumerate DirectSound Failed");
}
void CTestDirectSound::TimerCallback()
{
放在这个地方就是不行,播放的老快
//DWORD nRetBytes = 0;
//m_WaveFile.Read(m_lpAudioBuf, m_WFE.nSamplesPerSec * m_WFE.nBlockAlign, &nRetBytes);
//Write the audio data to DirectSoundBuffer
LPVOID lpvAudio1 = NULL, lpvAudio2 = NULL;
DWORD dwBytesAudio1 = 0, dwBytesAudio2 = 0;
HRESULT hr = WaitForMultipleObjects(2, m_pHEvent, FALSE, 0);
if (m_fStop) {
Stop();
return;
}
if(WAIT_OBJECT_0 == hr) {
m_dwCircles1++;
//Lock DirectSoundBuffer Second Part
HRESULT hr = m_lpDSB->Lock(m_WFE.nAvgBytesPerSec, m_WFE.nAvgBytesPerSec, &lpvAudio1, &dwBytesAudio1, &lpvAudio2, &dwBytesAudio2, 0);
if ( FAILED(hr) ) {
OutputDebugString(_T("Lock DirectSoundBuffer Failed!"));
return;
}
}
else if (WAIT_OBJECT_0 + 1 == hr) {
m_dwCircles2++;
//Lock DirectSoundBuffer First Part
HRESULT hr = m_lpDSB->Lock(0, m_WFE.nAvgBytesPerSec, &lpvAudio1, &dwBytesAudio1, &lpvAudio2, &dwBytesAudio2, 0);
if ( FAILED(hr) ) {
OutputDebugString(_T("Lock DirectSoundBuffer Failed!"));
return;
}
}
else {
return;
}
//就是下面这个东东,放在这个地方才能比较正常的播放
DWORD nRetBytes = 0;
m_WaveFile.Read(m_lpAudioBuf, m_WFE.nSamplesPerSec * m_WFE.nBlockAlign, &nRetBytes);
//If near the end of the audio data
if (nRetBytes / m_WFE.nBlockAlign < m_WFE.nSamplesPerSec) {
m_fStop = TRUE;
memset(m_lpAudioBuf+nRetBytes, 0, m_WFE.nAvgBytesPerSec - nRetBytes);
}
//Init lpvAudio1
if (NULL != lpvAudio1) {
memset(lpvAudio1, 0, dwBytesAudio1);
}
//Init lpvAudio2
if (NULL != lpvAudio2) {
memset(lpvAudio2, 0, dwBytesAudio2);
}
//Copy Audio Buffer to DirectSoundBuffer
if (NULL == lpvAudio2) {
memcpy(lpvAudio1, m_lpAudioBuf, nRetBytes);
}
else {
memcpy(lpvAudio1, m_lpAudioBuf, dwBytesAudio1);
memcpy(lpvAudio2, m_lpAudioBuf + dwBytesAudio1, dwBytesAudio2);
}
//Unlock DirectSoundBuffer
m_lpDSB->Unlock(lpvAudio1, dwBytesAudio1, lpvAudio2, dwBytesAudio2);
}
void CTestDirectSound::SetFormat()
{
//Create DirectSound
if ( FAILED(DirectSoundCreate(NULL, &m_lpDS, NULL)) ) {
OutputDebugString(_T("Create DirectSound Failed!"));
return;
}
//Set Cooperative Level
HWND hWnd = GetForegroundWindow();
if (hWnd == NULL)
{
hWnd = GetDesktopWindow();
}
if ( FAILED(m_lpDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY)) ) {
OutputDebugString(_T("SetCooperativeLevel Failed"));
return;
}
//Create Primary Buffer
DSBUFFERDESC dsbd;
ZeroMemory(&dsbd, sizeof(dsbd));
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
dsbd.dwBufferBytes = 0;
dsbd.lpwfxFormat = NULL;
LPDIRECTSOUNDBUFFER lpDSB = NULL;
if ( FAILED(m_lpDS->CreateSoundBuffer(&dsbd, &lpDSB, NULL)) ) {
OutputDebugString(_T("Create Primary Sound Buffer Failed!"));
return;
}
//Set Primary Buffer Format
if ( FAILED(lpDSB->SetFormat(&m_WFE)) ) {
OutputDebugString(_T("Set Primary Format Failed!"));
return;
}
//Create Second Sound Buffer
dsbd.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS;
dsbd.dwBufferBytes = 2*m_WFE.nAvgBytesPerSec; //2 Seconds Buffer
dsbd.lpwfxFormat = &m_WFE;
if ( FAILED(m_lpDS->CreateSoundBuffer(&dsbd, &m_lpDSB, NULL)) ) {
OutputDebugString(_T("Create Second Sound Buffer Failed!"));
return;
}
//Query DirectSoundNotify
LPDIRECTSOUNDNOTIFY lpDSBNotify;
if ( FAILED(m_lpDSB->QueryInterface(IID_IDirectSoundNotify, (LPVOID *)&lpDSBNotify)) ) {
OutputDebugString(_T("QueryInterface DirectSoundNotify Failed!"));
return;
}
//Set Direct Sound Buffer Notify Position
DSBPOSITIONNOTIFY pPosNotify[2];
pPosNotify[0].dwOffset = m_WFE.nAvgBytesPerSec/2 - 1;
pPosNotify[1].dwOffset = 3*m_WFE.nAvgBytesPerSec/2 - 1;
pPosNotify[0].hEventNotify = m_pHEvent[0];
pPosNotify[1].hEventNotify = m_pHEvent[1];
if ( FAILED(lpDSBNotify->SetNotificationPositions(2, pPosNotify)) ) {
OutputDebugString(_T("Set NotificationPosition Failed!"));
return;
}
//New audio buffer
if (NULL != m_lpAudioBuf) {
delete []m_lpAudioBuf;
m_lpAudioBuf = NULL;
}
m_lpAudioBuf = new BYTE[m_WFE.nAvgBytesPerSec];
//Init Audio Buffer
memset(m_lpAudioBuf, 0, m_WFE.nAvgBytesPerSec);
}
DWORD CTestDirectSound::GetSamplesPlayed()
{
if (NULL == m_lpDSB) {
return 0;
}
//Get curren play position
DWORD dwCurPlayPos = 0, dwCurPlaySample = 0;
m_lpDSB->GetCurrentPosition(&dwCurPlayPos, NULL);
dwCurPlaySample = dwCurPlayPos/m_WFE.nBlockAlign;
//Caculate the samples played
DWORD dwSamplesPlayed = 0;
if (m_dwCircles2 < 1) {
return dwCurPlaySample;
}
dwSamplesPlayed = (m_dwCircles2-1)*2*m_WFE.nSamplesPerSec + 3*m_WFE.nSamplesPerSec/2;
if (dwCurPlaySample > (3*m_WFE.nSamplesPerSec/2)) {
if (m_dwCircles2 < m_dwCircles1) {
dwSamplesPlayed = (m_dwCircles1-1)*2*m_WFE.nSamplesPerSec + 3*m_WFE.nSamplesPerSec/2;
}
dwSamplesPlayed += dwCurPlaySample - 3*m_WFE.nSamplesPerSec/2 + 1;
}
else {
dwSamplesPlayed += dwCurPlaySample + m_WFE.nSamplesPerSec/2;
}
CString strSamplesPlayed;
strSamplesPlayed.Format(_T("Samples Played: %d \n"), dwSamplesPlayed);
OutputDebugString(strSamplesPlayed);
return dwSamplesPlayed;
}
BOOL CTestDirectSound::DSEnumerateCallBack(GUID *pGuid, LPCSTR strDesc, LPCSTR strDrvName)
{
CString tmpStr;
tmpStr = "\nDevice Name = ";
tmpStr += strDesc;
tmpStr += "\nDriver Name = ";
tmpStr += strDrvName;
AfxMessageBox(tmpStr);
return TRUE;
}
//就是下面这个东东,放在这个地方才能比较正常的播放
DWORD nRetBytes = 0;
m_WaveFile.Read(m_lpAudioBuf, m_WFE.nSamplesPerSec * m_WFE.nBlockAlign, &nRetBytes);
放在lock中才可以正常播放,真搞不懂DirectSound是怎么弄得!!
阅读(1140) | 评论(0) | 转发(0) |