(DirectX系列01)DirectSound 3D语音特效

简介:        近日正在学习DirectX,主要用于视频监控和流媒体方面应用,学习《Visual C++音视频处理技术和工程实践》已经有大半,一直想写些感受,兴趣所致,今天重新学习了下DirectSound 3D语音特效,并编写一些代码,在此分享出来,希望对大家能有所帮助。

       近日正在学习DirectX,主要用于视频监控和流媒体方面应用,学习《Visual C++音视频处理技术和工程实践》已经有大半,一直想写些感受,兴趣所致,今天重新学习了下DirectSound 3D语音特效,并编写一些代码,在此分享出来,希望对大家能有所帮助。

       大家都有这种感觉,当我们离发声源越来越远的时候,声音越来越小。DirectSound就是模仿这些现象,从数学理论角度加以描述。当然,影响音效的因素不光只有这些,还有如Doppler效应等,但是DirectSound就是这么神奇,它能模仿大多数的声音特效,这就是神奇的3D语音特效,在游戏等方面有着广泛的应用。

       对于DirectSound中的3D声效的播放,在操作之前需要将创建的主缓冲区设置为DSBCAPS_CTRL3D标志,并由主缓冲区创建一个IDirect3DListener8听者对象,然后调用IDirect3DListener8的接口函数设置听着的位置和方向,从而达到3D语音的效果,接下来介绍下整个特效的处理过程。

     创建DSound对象,并初始化主缓冲区

       在DirectSound中对音频的操作之前都需要创建一个Dsound对象,该对象贯穿这个程序始终,一般创建之后立马创建音频主缓冲区,该对象的创建函数是DirectSoundCreate8,返回一个LPDIRECTSOUND8对象。这部分代码具体如下;

 


 

    //创建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;
 if(FAILED(hr = g_pDsd->CreateSoundBuffer(&dsbdesc,&pDSBPrimary ,NULL)))
  return FALSE;


 

 

      获取3D缓冲区对象

        IDirectSound3DBuffer8接口通常从DirectSound的次缓冲区获取,次缓冲区获取通过DSBUFFERDESC结构的dwFlags成员设置DSBCAPS_CTRL3D标志创建,具体代码如下;

 


 

 DSBUFFERDESC dsbd;
 ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
 dsbd.dwSize= sizeof(DSBUFFERDESC);

  // 设置DSBCAPS_CTRL3D标志

 dsbd.dwFlags= DSBCAPS_CTRL3D| DSBCAPS_GLOBALFOCUS |  DSBCAPS_CTRLPOSITIONNOTIFY |DSBCAPS_GETCURRENTPOSITION2;
 //dsbd.dwBufferBytes   =MAX_AUDIO_BUF * BUFFERNOTIFYSIZE  ;//如果采用流buffer,请将此句放开
 dsbd.dwBufferBytes   =g_pWaveFile->GetSize(); // 如果采用流buffer,请屏蔽掉此句
 dsbd.guid3DAlgorithm = guid3DAlgorithm;
 dsbd.lpwfxFormat     = g_pWaveFile->m_pwfx;

  // 创建次缓冲区
 if(FAILED(hr = g_pDsd->CreateSoundBuffer(&dsbd,&g_pDSBuffer,NULL)))
  return ;
 for(int i =0; i< MAX_AUDIO_BUF;i++)
 {
        g_aPosNotify[i].dwOffset = i* BUFFERNOTIFYSIZE  ;
        g_aPosNotify[i].hEventNotify = g_event[i];
 }

 //获取IDirectSound3DBuffer接口

 if(FAILED(hr = g_pDSBuffer->QueryInterface(IID_IDirectSound3DBuffer, (VOID**)&g_pDS3DBuffer )))

 ........

 // 设置3D缓冲区参数
 g_dsBufferParams.dwMode = DS3DMODE_HEADRELATIVE;
 g_pDS3DBuffer->SetAllParameters( &g_dsBufferParams, DS3D_IMMEDIATE );

  return ;
 

    获取听者对象(IDirectSound3DListener8)

 

     获取IDirectSound3DListener8对象其实很简单,首先声明一个LPDIRECTSOUND3DLISTENER对象,然后调用QueryInterface即可。获取的IDirectSound3DListener8后,需要对特效参数进行设置,例如通过SetPosition设置听者的位置,具体的API参照MSDN即可,这部分代码如下;

 


 LPDIRECTSOUND3DLISTENER g_pDSListener = NULL;   // 3D 听者之中呢

 //获取听者对象

 if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, (VOID**)&g_pDSListener ) ) )
    return FALSE;

 ......

    if(FAILED(hr = g_pDSBuffer->QueryInterface(IID_IDirectSoundNotify,(LPVOID *) &g_pDSNotify )))
  return ;
 g_pDSNotify->SetNotificationPositions(MAX_AUDIO_BUF,g_aPosNotify);
 g_pDSNotify->Release();

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

 ......

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

 if( g_pDSListener )
 {

  // 设置全特性
  g_pDSListener->SetAllParameters( &g_dsListenerParams, DS3D_DEFERRED );

  // 提交延时
     g_pDSListener->CommitDeferredSettings();
 }

 


     读取音频数据,播放

 

     读取WAV音频数据,我们可以直接采用Cwavefile类实现,该类是由微软封装的,专门用于操作wav文件。音频数据的播放直接调用Dsound中的Play函数即可,


//打开wav文件

g_pWaveFile = new CWaveFile;
 g_pWaveFile->Open(strFileName,NULL,WAVEFILE_READ);
 WAVEFORMATEX* pwfx  = g_pWaveFile->GetFormat();

....

 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);

    Close

 if(g_pDSListener)
  g_pDSListener->Release();
 if(g_pDsd)
  g_pDsd->Release();
    通过上面的几步3D特效处理也并不是很难,进一步学习可以参考MSDN相关文档,www.codeproject.com相关内容也不错。

 

 


 

   

目录
相关文章
|
5月前
|
C# 图形学
【unity小技巧】Unity音乐和音效管理器
【unity小技巧】Unity音乐和音效管理器
132 0
|
11月前
|
图形学
Unity——音乐、音效
Unity——音乐、音效
|
Android开发 图形学
Unity获取Android平台音量
图片.png https://www.cnblogs.com/Jason-c/p/7766021.html http://blog.csdn.
1677 0
|
算法
【音频处理】Melodyne 导入音频 ( 使用 Adobe Audition 录制音频 | 在 Melodyne 中打开录制的音频 | Melodyne 对音频素材的操作 | 音频分析算法 )
【音频处理】Melodyne 导入音频 ( 使用 Adobe Audition 录制音频 | 在 Melodyne 中打开录制的音频 | Melodyne 对音频素材的操作 | 音频分析算法 )
871 0
【音频处理】Melodyne 导入音频 ( 使用 Adobe Audition 录制音频 | 在 Melodyne 中打开录制的音频 | Melodyne 对音频素材的操作 | 音频分析算法 )
|
Android开发 iOS开发
OpenGL 实现视频编辑中的转场效果
转场效果是什么? 转场效果,简单来说就是两段视频之间的衔接过渡效果。
468 0
OpenGL 实现视频编辑中的转场效果
|
C语言 iOS开发 内存技术