1、配置DirectDound的开发环境
包含以下
#include <mmsystem.h>
#include <dsound.h>
添加Dsound.lib库
comctl32.lib dxerr9.lib winmm.lib dsound.lib dxguid.lib odbc32.lib odbccp32.lib,
2 DiectDound几个对象
创建一个设备对象,后通过设备对象创建缓冲区对象。
辅助缓冲区由应用程序创建和管理,DirectSound会自动地创建和管理主缓冲区,
3 播放音频文件开发的基本流程
a 创建一个设备对象,设置设备对象的协作度。
调用DirectSoundCreat8创建一个支持IDirectSound8接口的对象,
这个对象通常代表缺省的播放设备。
如果没有声音输出设备,这个函数就返回error,或者,在VXD驱动程序下,
如果声音输出设备正被某个应用程序通过waveform格式的api函数所控制,
该函数也返回error。
LPDIRECTSOUND8 lpDirectSound;
HRESULT hr = DirectSoundCreate8(NULL,&lpDirectSound, NULL));
当创建完设备对象后,调用IDirectSound8::SetCooperativeLevel来设置
协作度,否则听不到声音.
b.创建一个辅助Buffer,也叫后备缓冲区
(IDirectSound8::CreateSoundBuffer)
创建的buffer称作辅助缓冲区,Direcsound通过把几个后备缓冲区的声音
混合到主缓冲区中,然后输出到声音输出设备上,达到混音的效果。
c. 获取PCM类型的数据
将WAV文件或者其他资源的数据读取到缓冲区中。
d. 将数据读取到缓冲区
其中用到以下来锁缓冲区。
IDirectSoundBuffer8::Lock
IDirectSoundBuffer8::Unlock.
e. 播放缓冲区中的数据
IDirectSoundBuffer8::Play 播放缓冲区中的音频数据,
IDirectSoundBuffer8::Stop 暂停播放数据,
获取或者设置正在播放的音频的音量的大小
IDirectSoundBuffer8::GetVolume
IDirectSoundBuffer8::SetVolume
获取设置音频播放的频率
IDirectSoundBuffer8::GetFrequency
IDirectSoundBuffer8::SetFrequency
主缓冲区的频率不允许改动,
设置音频在左右声道播放的位置
IDirectSoundBuffer8::GetPan
IDirectSoundBuffer8::SetPan
包含全部音频数据的缓冲区我们称为静态的缓冲区,
尽管不同的声音可能会反复使用同一个内存buffer,但静态缓冲区的数据只写入一次。
静态缓冲区只填充一次数据,然后就可以play,
给静态缓冲区加载数据分下面几个步骤
1、用IDirectSoundBuffer8::Lock函数来锁定所有的内存,
指定你锁定内存中你开始写入数据的偏移位置,并且取回该偏移位置的地址。
2、采用标准的数据copy方法,将音频数据复制到返回的地址。
3、调用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;
//设置设备的协作度
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 //设置主播
| DSBCAPS_CTRLFX
| DSBCAPS_CTRLPOSITIONNOTIFY
| DSBCAPS_GETCURRENTPOSITION2;
dsbd.dwBufferBytes = g_pWaveFile->GetSize();
dsbd.lpwfxFormat = g_pWaveFile->m_pwfx;
LPDIRECTSOUNDBUFFER lPBuffer;
//创建辅助缓冲区对象
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 流缓冲区播放超大型的wave文件
流缓冲区就是播放那些比较长的音频文件,边播放,边填充DirectSound缓冲区。
DirectSound的通知机制
因为Stream buffer 大小只够容纳一部分数据,在播放完缓冲区中的数据后,
DirectSound就会通知应用程序,将新的数据填充到DirectSound的缓冲区中。
#define MAX_AUDIO_BUF 4 //设置4个buffer
#define BUFFERNOTIFYSIZE 1920 //每个buffer尺寸为1920
BOOL g_bPlaying = FALSE; //是否正在播放
LPDIRECTSOUNDNOTIFY8 g_pDSNotify = NULL;
DSBPOSITIONNOTIFY g_aPosNotify[MAX_AUDIO_BUF]; //设置通知标志的数组
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就会通知应用程序,将g_event,设置为通知态;
应用程序就通过WaitForMultipleObjects 函数等待DirectSound的通知,
将数据填充到DirectSoun的辅助缓冲区。