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); |
第6步最后一个很重要的地方,就是我们在程序中设置了一个时钟,这个时钟事件是用来触发Directsound声源的运动如下:
声源的运动轨迹根据我们设置的fxscale 和fyscale 的大小,就是我们拖动竖直和水平的两个slider,是一个椭圆形状,当然,如果fxscale = fyscale时,就是个圆形轨迹了。我们可以调整,然后通过ontimer事件来不断调整buffer的运动轨迹。
 图7声源运动的轨迹 |
void CDsound3DPlayDemoDlg::OnTimer(UINT nIDEvent ) { FLOAT fXScale; FLOAT fYScale;
fXScale = (((CSliderCtrl*)GetDlgItem(IDC_HORIZONTAL_SLIDER ))->GetPos())/100.0f;
fYScale = (((CSliderCtrl*)GetDlgItem(IDC_VERTICAL_SLIDER ))->GetPos())/100.0f; FLOAT t = timeGetTime()/1000.0f;
// Move the sound object around the listener. The maximum radius of the // orbit is 27.5 units. D3DVECTOR vPosition; vPosition.x = ORBIT_MAX_RADIUS * fXScale * (FLOAT)sin(t); vPosition.y = 0.0f; vPosition.z = ORBIT_MAX_RADIUS * fYScale * (FLOAT)cos(t);
D3DVECTOR vVelocity; vVelocity.x = ORBIT_MAX_RADIUS * fXScale * (FLOAT)sin(t+0.05f); vVelocity.y = 0.0f; vVelocity.z = ORBIT_MAX_RADIUS * fYScale * (FLOAT)cos(t+0.05f);
memcpy( &g_dsBufferParams.vPosition, &vPosition, sizeof(D3DVECTOR) ); memcpy( &g_dsBufferParams.vVelocity, &vVelocity, sizeof(D3DVECTOR) );
UpdateGrid( vPosition.x, vPosition.z );
if( g_pDS3DBuffer ) g_pDS3DBuffer->SetAllParameters( &g_dsBufferParams, DS3D_IMMEDIATE ); //随着模拟buffer的运动,我们要不断地改变3Dbuffer的参数。 } |
好了,介绍到这里,基本上都介绍清楚了,如果你还有什么疑惑的话,请参看demo的代码,对于程序员来说,看代码,比看文章能理解的更清楚些。
结束语 本文通过一个实例来演示了如何利用Directsound 实现游戏开发中的3D立体声音效,随文提供了一个demo源码,你可以下载,本文的demo在windowx xp,2000 + VC.7.0下调试。关于更详细的资料,请参考msdn上directx部分。
最后提醒两个问题:
1 在我的demo程序中,关于播放音频文件,我提供了两种方法,一种是比较简单的静态buffer,适合比较小的wave文件,另一种方法是采用Streaming buffer,开一个比较小的缓存,然后一边播放,一边将向缓冲中填充数据,这个适合比较大的wave文件。当然后一种方法比较麻烦,需要单独起一个线程。我在程序中都作了详尽的注释,如果你足够仔细,你肯定会发现。
2 一定要记住,3D音效只支持单声道的wave文件,不要试图对一个多声道的wave文件实现三维立体声效果,不会成功的。
最后留下email,
aooang@hotmail.com有什么问题联系我。