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。
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方法
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 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的辅助缓冲区。