科技时代新浪首页 > 科技时代 > 学园 > 正文

利用Directsound 3D实现游戏中3D音效(3)


http://www.sina.com.cn 2005年12月13日 11:55 天极yesky

    下面一步一步跟我来做吧。

  第1步 声明一些我们要用到的变量。

LPDIRECTSOUND8 g_pDsd = NULL; //Directsound 对象指针
LPDIRECTSOUNDBUFFER g_pDSBuffer = NULL; //辅助缓冲区指针
LPDIRECTSOUND3DBUFFER g_pDS3DBuffer = NULL; // 3D 声源对象指针
LPDIRECTSOUND3DLISTENER g_pDSListener = NULL; // 3D 听者对象指针
DS3DBUFFER g_dsBufferParams; // 3D buffer properties
DS3DLISTENER g_dsListenerParams; // Listener properties
CWaveFile *g_pWaveFile= NULL; //读写wave文件用到的一个类对象
BOOL g_bPlaying = FALSE; //是否正在播放

  第2步初始化Directsound,创建主缓冲区,设置主缓冲区的音频格式,并通过主缓冲区获取听者(listener)接口,这些工作可以在对话框的初始化中来做。

//初始化Dsound
HRESULT hr;
if(FAILED(hr = DirectSoundCreate8(NULL,&g_pDsd,NULL)))
 return FALSE;
if(FAILED(hr = g_pDsd->SetCooperativeLevel(m_hWnd,DSSCL_PRIORITY)))
 return FALSE;
//初始化Directsound 的主缓冲区,并设置格式
LPDIRECTSOUNDBUFFER pDSBPrimary = NULL;
DSBUFFERDESC dsbdesc ;
ZeroMemory(&dsbdesc,sizeof(DSBUFFERDESC));
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER;//一定不要忘记创建主缓冲区的时候要设置DSBCAPS_CTRL3D标志。只有指定了这个标志,后面你才能从这个辅助缓冲区中请求到3D的buffer指针。
if(FAILED(hr = g_pDsd->CreateSoundBuffer(&dsbdesc,&pDSBPrimary ,NULL)))
 return FALSE;
 //获取3D 模拟世界中的听者指针。
if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, (VOID**)&g_pDSListener ) ) )
 return FALSE;

WAVEFORMATEX wfx;
ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
wfx.wFormatTag = (WORD) WAVE_FORMAT_PCM;
wfx.nChannels = WAVECHANNEL ;
wfx.nSamplesPerSec = WAVESAMPLEPERSEC ;
wfx.wBitsPerSample = WAVEBITSPERSAMPLE ;
wfx.nBlockAlign = (WORD) (wfx.wBitsPerSample / 8 * wfx.nChannels);
wfx.nAvgBytesPerSec = (DWORD) (wfx.nSamplesPerSec * wfx.nBlockAlign);
if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) //设置缓冲区的音频格式。
 return FALSE;

  第3步,创建辅助缓冲区,通过辅助缓冲区获取3dbuffer指针

DSBUFFERDESC dsbd;
ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_CTRL3D| DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY |DSBCAPS_GETCURRENTPOSITION2;
//看看创建辅助缓冲区的buffer时设置的标志,3D的标志自然是需要的,还有一个标志需要注意,DSBCAPS_CTRLPOSITIONNOTIFY,如果你采用的流(stream)buffer的话,就需要边播放,边向buffer中填充数据,就需要设置这个标志,这样,在directsound播放到指定位置时,就会触发事件。
//dsbd.dwBufferBytes =MAX_AUDIO_BUF * BUFFERNOTIFYSIZE ;//如果采用流buffer,可以设置适当的buffer大小。
dsbd.dwBufferBytes =g_pWaveFile->GetSize(); // 如果采用静态buffer,那么buffer的大小就是文件的大小了。
dsbd.guid3DAlgorithm = guid3DAlgorithm;
dsbd.lpwfxFormat = g_pWaveFile->m_pwfx;
if(FAILED(hr = g_pDsd->CreateSoundBuffer(&dsbd,&g_pDSBuffer,NULL)))
 return ;
 //通过辅助缓冲区,来获取3D buffer的指针。
if(FAILED(hr = g_pDSBuffer->QueryInterface(IID_IDirectSound3DBuffer, (VOID**)&g_pDS3DBuffer )))
 return ;

g_dsBufferParams.dwSize = sizeof(DS3DBUFFER);
g_pDS3DBuffer->GetAllParameters( &g_dsBufferParams );

//设置3Dbuffer的属性。
g_dsBufferParams.dwMode = DS3DMODE_HEADRELATIVE;
g_pDS3DBuffer->SetAllParameters( &g_dsBufferParams, DS3D_IMMEDIATE );

  第4步 设置多普勒因子以及最小最大距离。

FLOAT fDopplerFactor;
FLOAT fRolloffFactor;
FLOAT fMinDistance;
FLOAT fMaxDistance;

CSliderCtrl *pDopplerSlider = (CSliderCtrl*)GetDlgItem(IDC_DOPPLER_SLIDER);
fDopplerFactor = pDopplerSlider->GetPos();

CSliderCtrl *pRolloffSlider= (CSliderCtrl*)GetDlgItem(IDC_ROLLOFF_SLIDER);
fRolloffFactor = pRolloffSlider->GetPos();

CSliderCtrl *pMinDistSlider = (CSliderCtrl*)GetDlgItem(IDC_MINDISTANCE_SLIDER );
fMinDistance = pMinDistSlider->GetPos();
CSliderCtrl *pMaxDistSlider = (CSliderCtrl*)GetDlgItem(IDC_MAXDISTANCE_SLIDER );
fMaxDistance = pMaxDistSlider->GetPos();

g_dsListenerParams.flDopplerFactor = fDopplerFactor;
g_dsListenerParams.flRolloffFactor = fRolloffFactor;

if( g_pDSListener )
{
 g_pDSListener->SetAllParameters( &g_dsListenerParams, DS3D_DEFERRED );
 g_pDSListener->CommitDeferredSettings();
}

g_dsBufferParams.flMinDistance = fMinDistance;
g_dsBufferParams.flMaxDistance = fMaxDistance;

if( g_pDS3DBuffer )
 g_pDS3DBuffer->SetAllParameters( &g_dsBufferParams, DS3D_DEFERRED );

  第5步 然后就是通过调用辅助缓冲区的play方法,来进行播放音频文件了。

DWORD res;
LPVOID lplockbuf;
DWORD len;
DWORD dwWrite;

g_pDSBuffer->Lock(0,0,&lplockbuf,&len,NULL,NULL,DSBLOCK_ENTIREBUFFER);
g_pWaveFile->Read((BYTE*)lplockbuf,len,&dwWrite);
g_pDSBuffer->Unlock(lplockbuf,len,NULL,0);
g_pDSBuffer->SetCurrentPosition(0);
g_pDSBuffer->Play(0,0,DSBPLAY_LOOPING);

[上一页] [1] [2] [3] [4] [下一页]

发表评论

爱问(iAsk.com)



评论】【论坛】【收藏此页】【 】【多种方式看新闻】【下载点点通】【打印】【关闭




科技时代意见反馈留言板 电话:010-82628888-5595   欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

Copyright © 1996 - 2005 SINA Inc. All Rights Reserved

版权所有 新浪网