1、配置DirectDound的開發(fā)環(huán)境
包含以下
#include <mmsystem.h>
#include <dsound.h>
添加Dsound.lib庫
comctl32.lib dxerr9.lib winmm.lib dsound.lib dxguid.lib odbc32.lib odbccp32.lib,
2 DiectDound幾個對象
創(chuàng)建一個設(shè)備對象,后通過設(shè)備對象創(chuàng)建緩沖區(qū)對象。
輔助緩沖區(qū)由應(yīng)用程序創(chuàng)建和管理,DirectSound會自動地創(chuàng)建和管理主緩沖區(qū),
3 播放音頻文件開發(fā)的基本流程
a 創(chuàng)建一個設(shè)備對象,設(shè)置設(shè)備對象的協(xié)作度。
調(diào)用DirectSoundCreat8創(chuàng)建一個支持IDirectSound8接口的對象,
這個對象通常代表缺省的播放設(shè)備。
如果沒有聲音輸出設(shè)備,這個函數(shù)就返回error,或者,在VXD驅(qū)動程序下,
如果聲音輸出設(shè)備正被某個應(yīng)用程序通過waveform格式的api函數(shù)所控制,
該函數(shù)也返回error。
LPDIRECTSOUND8 lpDirectSound;
HRESULT hr = DirectSoundCreate8(NULL,&lpDirectSound, NULL));
當創(chuàng)建完設(shè)備對象后,調(diào)用IDirectSound8::SetCooperativeLevel來設(shè)置
協(xié)作度,否則聽不到聲音.
b.創(chuàng)建一個輔助Buffer,也叫后備緩沖區(qū)
(IDirectSound8::CreateSoundBuffer)
創(chuàng)建的buffer稱作輔助緩沖區(qū),Direcsound通過把幾個后備緩沖區(qū)的聲音
混合到主緩沖區(qū)中,然后輸出到聲音輸出設(shè)備上,達到混音的效果。
c. 獲取PCM類型的數(shù)據(jù)
將WAV文件或者其他資源的數(shù)據(jù)讀取到緩沖區(qū)中。
d. 將數(shù)據(jù)讀取到緩沖區(qū)
其中用到以下來鎖緩沖區(qū)。
IDirectSoundBuffer8::Lock
IDirectSoundBuffer8::Unlock.
e. 播放緩沖區(qū)中的數(shù)據(jù)
IDirectSoundBuffer8::Play 播放緩沖區(qū)中的音頻數(shù)據(jù),
IDirectSoundBuffer8::Stop 暫停播放數(shù)據(jù),
獲取或者設(shè)置正在播放的音頻的音量的大小
IDirectSoundBuffer8::GetVolume
IDirectSoundBuffer8::SetVolume
獲取設(shè)置音頻播放的頻率
IDirectSoundBuffer8::GetFrequency
IDirectSoundBuffer8::SetFrequency
主緩沖區(qū)的頻率不允許改動,
設(shè)置音頻在左右聲道播放的位置
IDirectSoundBuffer8::GetPan
IDirectSoundBuffer8::SetPan
包含全部音頻數(shù)據(jù)的緩沖區(qū)我們稱為靜態(tài)的緩沖區(qū),
盡管不同的聲音可能會反復使用同一個內(nèi)存buffer,但靜態(tài)緩沖區(qū)的數(shù)據(jù)只寫入一次。
靜態(tài)緩沖區(qū)只填充一次數(shù)據(jù),然后就可以play,
給靜態(tài)緩沖區(qū)加載數(shù)據(jù)分下面幾個步驟
1、用IDirectSoundBuffer8::Lock函數(shù)來鎖定所有的內(nèi)存,
指定你鎖定內(nèi)存中你開始寫入數(shù)據(jù)的偏移位置,并且取回該偏移位置的地址。
2、采用標準的數(shù)據(jù)copy方法,將音頻數(shù)據(jù)復制到返回的地址。
3、調(diào)用IDirectSoundBuffer8::Unlock.,解鎖該地址。
用static buffer 播放wav方法
LPDIRECTSOUNDBUFFER8 g_pDSBuffer8 = NULL; //buffer
LPDIRECTSOUND8 g_pDsd = NULL; //dsound
CWaveFile *g_pWaveFile= NULL;

//初始化DirectSound工作
HRESULT hr;
if(FAILED(hr = DirectSoundCreate8(NULL,&g_pDsd,NULL)))
return FALSE;

//設(shè)置設(shè)備的協(xié)作度
if(FAILED(hr = g_pDsd->SetCooperativeLevel(m_hWnd,DSSCL_PRIORITY)))
return FALSE;

g_pWaveFile = new CWaveFile;
g_pWaveFile->Open(_T("c:\\test.wav"), NULL, WAVEFILE_READ);

DSBUFFERDESC dsbd;
ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_GLOBALFOCUS //設(shè)置主播
| DSBCAPS_CTRLFX
| DSBCAPS_CTRLPOSITIONNOTIFY
| DSBCAPS_GETCURRENTPOSITION2;

dsbd.dwBufferBytes = g_pWaveFile->GetSize();
dsbd.lpwfxFormat = g_pWaveFile->m_pwfx;

LPDIRECTSOUNDBUFFER lPBuffer;

//創(chuàng)建輔助緩沖區(qū)對象
if(FAILED(hr = g_pDsd->CreateSoundBuffer(&dsbd,&lpbuffer,NULL)))
return ;
if( FAILED(hr = lpbuffer->QueryInterface( IID_IDirectSoundBuffer8, (LPVOID*) &g_pDSBuffer8) ) )
return ;
lpbuffer->Release();

//播放
LPVOID lplockbuf;
DWORD len;
DWORD dwWrite;

g_pDSBuffer8->Lock(0,0, &lplockbuf, &len, NULL, NULL, DSBLOCK_ENTIREBUFFER);

//g_pWaveFile 聲音寫入到lplockbuf所指地址
g_pWaveFile->Read((BYTE*)lplockbuf, len, &dwWrite);

g_pDSBuffer8->Unlock(lplockbuf,len,NULL,0);

g_pDSBuffer8->SetCurrentPosition(0);

g_pDSBuffer8->Play(0,0,DSBPLAY_LOOPING);
f 流緩沖區(qū)播放超大型的wave文件
流緩沖區(qū)就是播放那些比較長的音頻文件,邊播放,邊填充DirectSound緩沖區(qū)。
DirectSound的通知機制
因為Stream buffer 大小只夠容納一部分數(shù)據(jù),在播放完緩沖區(qū)中的數(shù)據(jù)后,
DirectSound就會通知應(yīng)用程序,將新的數(shù)據(jù)填充到DirectSound的緩沖區(qū)中。
#define MAX_AUDIO_BUF 4 //設(shè)置4個buffer
#define BUFFERNOTIFYSIZE 1920 //每個buffer尺寸為1920
BOOL g_bPlaying = FALSE; //是否正在播放
LPDIRECTSOUNDNOTIFY8 g_pDSNotify = NULL;
DSBPOSITIONNOTIFY g_aPosNotify[MAX_AUDIO_BUF]; //設(shè)置通知標志的數(shù)組
HANDLE g_event[MAX_AUDIO_BUF];
for(int i =0; i< MAX_AUDIO_BUF;i++)
{
g_aPosNotify[i].dwOffset = i* BUFFERNOTIFYSIZE ;
g_aPosNotify[i].hEventNotify = g_event[i];
}
if(FAILED(hr = g_pDSBuffer8->QueryInterface(IID_IDirectSoundNotify,(LPVOID *) &g_pDSNotify )))
return ;
g_pDSNotify->SetNotificationPositions(MAX_AUDIO_BUF,g_aPosNotify);
g_pDSNotify->Release();
當DirectSound播放到buffer的1920,3840,5760,7680等位置時,
Directsound就會通知應(yīng)用程序,將g_event,設(shè)置為通知態(tài);
應(yīng)用程序就通過WaitForMultipleObjects 函數(shù)等待DirectSound的通知,
將數(shù)據(jù)填充到DirectSoun的輔助緩沖區(qū)。