【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 3324|回复: 4

用DirectSound实现增强的音频特技效果

[复制链接]
发表于 2006-5-29 17:48:49 | 显示全部楼层 |阅读模式
摘要 :本文介绍了DirectSound提供的几个基本的音频特技以及其应用方法,并通过一个程序实例演示了如何应用这些特技为你的程序实现增强的音频效果。

  关键词: DirectSound 音频特技

  前段时间写三篇关于DirectSound的文档,包括录音混音,以及3D音效,也基本上将DirectSound的开发主要内容涉及到了,因为关于特技这部分在DirectSound的开发文档中介绍的就很简单,加上应用起来也不是很难,本来不想介绍这部分的内容,但是,当我体验过DirectSound的音频特技后,我改变了想法,我觉得DirectSound提供的几个音频特技效果很好,很有震撼力,如果你将这些特技添加到你的程序中,肯定能为你的程序增色不少,况且,接口这么简单,应用起来这么容易。所以这篇文档我给大家介绍一下DirectSound的基本特技。

  DirectSound提供8个基本的音频特技。

  1、Chorus 和声,这里说的和声不是指很多人合唱,而是指声音的重叠,即通过原声和回声的重叠,使得声音加宽,加厚。

  2、Compression 压限,是针对声音不同部分的音量进行增减也就是说,可以对某段音频中音量低于某一限度的部分进行平滑的音量提升(其余部分不变);对音量高于某一限度的部分进行平滑的音量衰减(其余部分不变),或二者同时作用,简单说,就是平衡音量。

  3、Distortion 失真。

  4、Echo 回声,模拟声音被远处的平面反射回来的效果。

  5、Environmental Reverberation反射(混响),简单说就是声音余韵,音源在空间反射出来的声音。适当设置混响,可以更真实、更有现场感的再现声音源,也可以起到修饰、美化的作用。表现宽阔的,传声真实的效果。

  6、Flange,一般翻译为波浪特技,用于设置变调效果,通过拷贝失调的声音,或者把某个频率点改变,调节声音分离的时间、音调深度。可以用来产生颤动、急促的声音。

  7、Gargle ,咕噜效果处理。一种可以试音源产生咕噜声的调幅处理模式。

  8、Parametric Equalizer参数平衡,用于为音频设置参数均衡器。强化或衰减指定的频率。对于增强音乐的效果特别有效。

  DiectSound对于每一种特技,都提供了一个接口 ,通过这个接口,我们可以调整特技的参数,接口定义如下:

  ·IDirectSoundFXChorus8 和声特技接口

  ·IDirectSoundFXCompressor8 压限特技接口

  ·IDirectSoundFXDistortion8 失真特技接口

  ·IDirectSoundFXEcho8 回声特技接口

  ·IDirectSoundFXWavesReverb8混响特技接口
 
  ·IDirectSoundFXFlanger8 波浪特技接口

  ·IDirectSoundFXGargle8 咕噜特技接口

  ·IDirectSoundFXParamEq8 参数平衡特技接口

  我们可以通过DirectSound缓冲区接口,即IDirectSoundBuffer8的GetObjectInPath方法获得所支持音频特技的接口。

  下面先说一下DirectSound中的音频特技实现的过程。

  1、首先创建 DirectSound对象和辅助缓冲区,辅助缓冲区一定要设置DSBCAPS_CTRLFX标志。

  2、通过辅助缓冲区buffer即IDirectSoundBuffer8的SetFX方法设置特效;

  3、IDirectSoundBuffer8的GetObjectInPath方法获得特效的接口;

  4、特效接口的SetAllParameters方法设置参数;

  5、然后就是通过缓冲区的play方法来播放音频文件。在播放音频的同时我们也可以调整特技的参数。

  下面开始我们的例子吧,关于例子的界面很简单,都是通过MFC 自动提供的,我没有做什么修饰,呵呵,我们只关心功能,所以其他的我就不详细讲,具体你可以参见例子代码,例子的源码会随着本文一起发布,例子的界面如下


图 音频特技的示例

  界面很简单,流程也不复杂,我在这里主要是用来演示如何来实现音频特技的,所以下面我们一起看看如何来实现音频的特技。这里我要说明一下,因为8个特技实现过程基本是一样,所以我这里只是以chorus(回声)特技 举例,其他特技的实现和chorus类似,避免代码重复,就不一一列出,具体的可以参见例子的源码。

  第1步: 首先要定义我们用到的一些变量,这里我定义的全是全局的变量,你可以根据自己的情况来定义这些变量。

LPDIRECTSOUNDBUFFER8 g_pDSBuffer8 = NULL; //缓冲区对象
LPDIRECTSOUND8 g_pDsd = NULL; ///Directsound对象
CWaveFile *g_pWaveFile= NULL; // 操作wave文件的 对象
//下面的8个指针接口对应着8个音频特技
LPDIRECTSOUNDFXCHORUS8 g_pChorus = NULL;
LPDIRECTSOUNDFXCOMPRESSOR8 g_pCompressor = NULL;
LPDIRECTSOUNDFXDISTORTION8 g_pDistortion = NULL;
LPDIRECTSOUNDFXECHO8 g_pEcho = NULL;
LPDIRECTSOUNDFXFLANGER8 g_pFlanger = NULL;
LPDIRECTSOUNDFXGARGLE8 g_pGargle = NULL;
LPDIRECTSOUNDFXPARAMEQ8 g_pParamEq = NULL;
LPDIRECTSOUNDFXWAVESREVERB8 g_pReverb = NULL;
//用于设置特技的参数,每种音频特技对应着一个参数。
DSFXChorus g_paramsChorus;
DSFXCompressor g_paramsCompressor;
DSFXDistortion g_paramsDistortion;
DSFXEcho g_paramsEcho;
DSFXFlanger g_paramsFlanger;
DSFXGargle g_paramsGargle;
DSFXParamEq g_paramsParamEq;
DSFXWavesReverb g_paramsReverb;

  定义完这些变量,就可以开始我们的工作了

  第2步 初始化Directsound,获取IDrectSoundBuffer8的接口。这一步骤的工作可以放到程序的初始化的地方。

CoInitialize( NULL );
HRESULT hr;
if(FAILED(hr = DirectSoundCreate8(NULL,&g_pDsd,NULL)))
 return FALSE;
if(FAILED(hr = g_pDsd->SetCooperativeLevel(m_hWnd,DSSCL_PRIORITY)))
 return FALSE;
//
for(int i =0; i< MAX_AUDIO_BUF; i++)
g_event = CreateEvent(NULL, FALSE, FALSE, NULL);
//设置音频的格式
WAVEFORMATEX waveformat;
waveformat.wFormatTag = WAVE_FORMAT_PCM;
waveformat.nChannels = 2;
waveformat.nSamplesPerSec = 48000;
waveformat.wBitsPerSample = 16;
waveformat.nBlockAlign = waveformat.nChannels * waveformat.wBitsPerSample /8;
waveformat.nAvgBytesPerSec = waveformat.nBlockAlign * waveformat.nSamplesPerSec;

DSBUFFERDESC dsbd;
ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLFX| DSBCAPS_CTRLPOSITIONNOTIFY |DSBCAPS_GETCURRENTPOSITION2;
// 创建缓冲区的时候,一定不要忘了设置DSBCAPS_CTRLFX标志
dsbd.dwBufferBytes = MAX_AUDIO_BUF * BUFFERNOTIFYSIZE ;
dsbd.lpwfxFormat = &waveformat;
LPDIRECTSOUNDBUFFER lpbuffer;
if(FAILED(hr = g_pDsd->CreateSoundBuffer(&dsbd,&lpbuffer,NULL)))
 return FALSE;

if( FAILED( hr = lpbuffer->QueryInterface( IID_IDirectSoundBuffer8, (LPVOID*) &g_pDSBuffer8) ) )
 return FALSE;
lpbuffer->Release();

  需要注意的几个地方:

  ·DirectX通过DirectX Media Objects(DMOs)来支持在声音中添加特技。因为特技使用到了COM组件,所以首先要通过CoInitialize()来初始化Com库,当然,你别忘了在退出程序时调用CoUninitialize() 。

  ·创建缓冲区的时候,一定不要忘了对 DSBUFFERDESC结构的dwFlages设置DSBCAPS_CTRLFX标志,如果忘了设置这个标志,那么你后面的音频特技全是无效的。但是,在设置这个标志时,buffer一定要处于停止状态并且没有被锁定。在DiectX 9.0中,特技不是依靠硬件来实现的。当然也可以在硬件缓冲区中设置特技,但这样做没有任何的好处。

  ·最后一个要注意的问题,就是缓冲区的大小,缓冲区的size过小,特技并不能好好工作,DirectSound建议缓冲区的大小应该在小于150毫秒的数据数据量,缓冲区中使用特技,这个值被定义为DSBSIZ_FX_MIN。

  在上面的例子中,waveformat.nAvgBytesPerSec = waveformat.nBlockAlign * waveformat.nSamplesPerSec; = 2*16*4800/8 = 19200 bytes/m

  那么dsbd.dwBufferBytes 的最小值应该大于 19200*0.15 = 2880字节。

  我刚开始就没有注意这个问题,结果后面总是出错,我一直纳闷不已,因为代码没有问题的,后来重新看了一下帮助才发现这个问题。

  第3步 通过缓冲区对象IDirectSoundBuffer8设置缓冲区支持的具体特技,并通过IDirectSoundBuffer8 对象的GetObjectInPath方法获得具体的音频特技的接口;这里以chorus特技为例:如下

DSEFFECTDESC effectdesc;
ZeroMemory( &effectdesc, sizeof( DSEFFECTDESC ) );
effectdesc.dwSize = sizeof(DSEFFECTDESC);
effectdesc.dwFlags = 0;
effectdesc.guidDSFXClass = GUID_DSFX_STANDARD_CHORUS;
DWORD dwResult;
if(g_pDSBuffer8)
{
 hr = g_pDSBuffer8->SetFX(1,&effectdesc,&dwResult);
 if( FAILED( hr = g_pDSBuffer8->GetObjectInPath( GUID_DSFX_STANDARD_CHORUS, 0, IID_IDirectSoundFXChorus8,(LPVOID*) &g_pChorus ) ) )
  return ;
 g_pChorus->GetAllParameters(&g_paramsChorus);
}

  第4步 通过特效接口的SetAllParameters方法设置参数,手动拖动滑动条,来设置特技参数,可以在例子中看到如下的代码,以chorus为例:

void CDsoundEffectDemoDlg::OnEffectChanged()
{
 switch( g_dwCurrentFXType )
 {
  case eSFX_chorus:
  {
   //下面的代码主要是为了获取滑动条上参数的数值。
   SaveSingleParameter( IDC_PARAM_NAME1, &g_paramsChorus.fWetDryMix, DSFXCHORUS_WETDRYMIX_MIN, DSFXCHORUS_WETDRYMIX_MAX );
   SaveSingleParameter( IDC_PARAM_NAME2, &g_paramsChorus.fDepth, DSFXCHORUS_DEPTH_MIN, DSFXCHORUS_DEPTH_MAX );
   SaveSingleParameter( IDC_PARAM_NAME3, &g_paramsChorus.fFeedback, DSFXCHORUS_FEEDBACK_MIN, DSFXCHORUS_FEEDBACK_MAX );
   SaveSingleParameter( IDC_PARAM_NAME4, &g_paramsChorus.fFrequency, DSFXCHORUS_FREQUENCY_MIN, DSFXCHORUS_FREQUENCY_MAX );
   SaveSingleParameter( IDC_PARAM_NAME5, &g_paramsChorus.fDelay, DSFXCHORUS_DELAY_MIN, DSFXCHORUS_DELAY_MAX );

   if( ((CButton*)GetDlgItem(IDC_RADIO_TRIANGLE ))->GetCheck() == BST_CHECKED )
    g_paramsChorus.lWaveform = DSFXCHORUS_WAVE_TRIANGLE;
   else
    g_paramsChorus.lWaveform = DSFXCHORUS_WAVE_SIN

   if( ((CButton*)GetDlgItem(IDC_RADIO_NEG_180 ))->GetCheck() == BST_CHECKED )
    g_paramsChorus.lPhase = DSFXCHORUS_PHASE_NEG_180;
   else if( ((CButton*)GetDlgItem(IDC_RADIO_NEG_90 ))->GetCheck() == BST_CHECKED )
    g_paramsChorus.lPhase = DSFXCHORUS_PHASE_NEG_90;
   else if( ((CButton*)GetDlgItem( IDC_RADIO_ZERO ))->GetCheck() == BST_CHECKED )
    g_paramsChorus.lPhase = DSFXCHORUS_PHASE_ZERO;
   else if( ((CButton*)GetDlgItem(IDC_RADIO_90))->GetCheck() == BST_CHECKED )
    g_paramsChorus.lPhase = DSFXCHORUS_PHASE_90;
   else
    g_paramsChorus.lPhase = DSFXCHORUS_PHASE_180;

   if( g_pChorus) //设置合生特技的参数
    g_pChorus->SetAllParameters( &g_paramsChorus );

  break;
 }
 ......//下面是其他特技的参数设置 ,略,具体可以见例子中的代码。
}

  注: 在音频播放的同时拖动滑动条调解音频特技的参数,可以随时调整音频特技的效果。

  第5步 一切都ok了,下面就是调用IDRIRECTSOUNDBUFFER8 的play函数来播放音频文件了。

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

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

  上面讲了Directsound音频特技开发的主要流程,其中的设置音频过程我只是用chorus为例,其实其他的几个特技的使用方法跟chorus很类似,唯一不同的就是参数结构的不同,限于篇幅,对于其他特技的代码就不一一列出了,具体的可一参看本文实例的代码。

  下面我们看看每个特技的参数都需要设置什么。
 楼主| 发表于 2006-5-29 17:49:13 | 显示全部楼层
摘要 :本文介绍了DirectSound提供的几个基本的音频特技以及其应用方法,并通过一个程序实例演示了如何应用这些特技为你的程序实现增强的音频效果。

  关键词: DirectSound 音频特技

  前段时间写三篇关于DirectSound的文档,包括录音混音,以及3D音效,也基本上将DirectSound的开发主要内容涉及到了,因为关于特技这部分在DirectSound的开发文档中介绍的就很简单,加上应用起来也不是很难,本来不想介绍这部分的内容,但是,当我体验过DirectSound的音频特技后,我改变了想法,我觉得DirectSound提供的几个音频特技效果很好,很有震撼力,如果你将这些特技添加到你的程序中,肯定能为你的程序增色不少,况且,接口这么简单,应用起来这么容易。所以这篇文档我给大家介绍一下DirectSound的基本特技。

  DirectSound提供8个基本的音频特技。

  1、Chorus 和声,这里说的和声不是指很多人合唱,而是指声音的重叠,即通过原声和回声的重叠,使得声音加宽,加厚。

  2、Compression 压限,是针对声音不同部分的音量进行增减也就是说,可以对某段音频中音量低于某一限度的部分进行平滑的音量提升(其余部分不变);对音量高于某一限度的部分进行平滑的音量衰减(其余部分不变),或二者同时作用,简单说,就是平衡音量。

  3、Distortion 失真。

  4、Echo 回声,模拟声音被远处的平面反射回来的效果。

  5、Environmental Reverberation反射(混响),简单说就是声音余韵,音源在空间反射出来的声音。适当设置混响,可以更真实、更有现场感的再现声音源,也可以起到修饰、美化的作用。表现宽阔的,传声真实的效果。

  6、Flange,一般翻译为波浪特技,用于设置变调效果,通过拷贝失调的声音,或者把某个频率点改变,调节声音分离的时间、音调深度。可以用来产生颤动、急促的声音。

  7、Gargle ,咕噜效果处理。一种可以试音源产生咕噜声的调幅处理模式。

  8、Parametric Equalizer参数平衡,用于为音频设置参数均衡器。强化或衰减指定的频率。对于增强音乐的效果特别有效。

  DiectSound对于每一种特技,都提供了一个接口 ,通过这个接口,我们可以调整特技的参数,接口定义如下:

  ·IDirectSoundFXChorus8 和声特技接口

  ·IDirectSoundFXCompressor8 压限特技接口

  ·IDirectSoundFXDistortion8 失真特技接口

  ·IDirectSoundFXEcho8 回声特技接口

  ·IDirectSoundFXWavesReverb8混响特技接口
 
  ·IDirectSoundFXFlanger8 波浪特技接口

  ·IDirectSoundFXGargle8 咕噜特技接口

  ·IDirectSoundFXParamEq8 参数平衡特技接口

  我们可以通过DirectSound缓冲区接口,即IDirectSoundBuffer8的GetObjectInPath方法获得所支持音频特技的接口。

  下面先说一下DirectSound中的音频特技实现的过程。

  1、首先创建 DirectSound对象和辅助缓冲区,辅助缓冲区一定要设置DSBCAPS_CTRLFX标志。

  2、通过辅助缓冲区buffer即IDirectSoundBuffer8的SetFX方法设置特效;

  3、IDirectSoundBuffer8的GetObjectInPath方法获得特效的接口;

  4、特效接口的SetAllParameters方法设置参数;

  5、然后就是通过缓冲区的play方法来播放音频文件。在播放音频的同时我们也可以调整特技的参数。

  下面开始我们的例子吧,关于例子的界面很简单,都是通过MFC 自动提供的,我没有做什么修饰,呵呵,我们只关心功能,所以其他的我就不详细讲,具体你可以参见例子代码,例子的源码会随着本文一起发布,例子的界面如下


图 音频特技的示例

  界面很简单,流程也不复杂,我在这里主要是用来演示如何来实现音频特技的,所以下面我们一起看看如何来实现音频的特技。这里我要说明一下,因为8个特技实现过程基本是一样,所以我这里只是以chorus(回声)特技 举例,其他特技的实现和chorus类似,避免代码重复,就不一一列出,具体的可以参见例子的源码。

  第1步: 首先要定义我们用到的一些变量,这里我定义的全是全局的变量,你可以根据自己的情况来定义这些变量。

LPDIRECTSOUNDBUFFER8 g_pDSBuffer8 = NULL; //缓冲区对象
LPDIRECTSOUND8 g_pDsd = NULL; ///Directsound对象
CWaveFile *g_pWaveFile= NULL; // 操作wave文件的 对象
//下面的8个指针接口对应着8个音频特技
LPDIRECTSOUNDFXCHORUS8 g_pChorus = NULL;
LPDIRECTSOUNDFXCOMPRESSOR8 g_pCompressor = NULL;
LPDIRECTSOUNDFXDISTORTION8 g_pDistortion = NULL;
LPDIRECTSOUNDFXECHO8 g_pEcho = NULL;
LPDIRECTSOUNDFXFLANGER8 g_pFlanger = NULL;
LPDIRECTSOUNDFXGARGLE8 g_pGargle = NULL;
LPDIRECTSOUNDFXPARAMEQ8 g_pParamEq = NULL;
LPDIRECTSOUNDFXWAVESREVERB8 g_pReverb = NULL;
//用于设置特技的参数,每种音频特技对应着一个参数。
DSFXChorus g_paramsChorus;
DSFXCompressor g_paramsCompressor;
DSFXDistortion g_paramsDistortion;
DSFXEcho g_paramsEcho;
DSFXFlanger g_paramsFlanger;
DSFXGargle g_paramsGargle;
DSFXParamEq g_paramsParamEq;
DSFXWavesReverb g_paramsReverb;

  定义完这些变量,就可以开始我们的工作了

  第2步 初始化Directsound,获取IDrectSoundBuffer8的接口。这一步骤的工作可以放到程序的初始化的地方。

CoInitialize( NULL );
HRESULT hr;
if(FAILED(hr = DirectSoundCreate8(NULL,&g_pDsd,NULL)))
 return FALSE;
if(FAILED(hr = g_pDsd->SetCooperativeLevel(m_hWnd,DSSCL_PRIORITY)))
 return FALSE;
//
for(int i =0; i< MAX_AUDIO_BUF; i++)
g_event = CreateEvent(NULL, FALSE, FALSE, NULL);
//设置音频的格式
WAVEFORMATEX waveformat;
waveformat.wFormatTag = WAVE_FORMAT_PCM;
waveformat.nChannels = 2;
waveformat.nSamplesPerSec = 48000;
waveformat.wBitsPerSample = 16;
waveformat.nBlockAlign = waveformat.nChannels * waveformat.wBitsPerSample /8;
waveformat.nAvgBytesPerSec = waveformat.nBlockAlign * waveformat.nSamplesPerSec;

DSBUFFERDESC dsbd;
ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLFX| DSBCAPS_CTRLPOSITIONNOTIFY |DSBCAPS_GETCURRENTPOSITION2;
// 创建缓冲区的时候,一定不要忘了设置DSBCAPS_CTRLFX标志
dsbd.dwBufferBytes = MAX_AUDIO_BUF * BUFFERNOTIFYSIZE ;
dsbd.lpwfxFormat = &waveformat;
LPDIRECTSOUNDBUFFER lpbuffer;
if(FAILED(hr = g_pDsd->CreateSoundBuffer(&dsbd,&lpbuffer,NULL)))
 return FALSE;

if( FAILED( hr = lpbuffer->QueryInterface( IID_IDirectSoundBuffer8, (LPVOID*) &g_pDSBuffer8) ) )
 return FALSE;
lpbuffer->Release();

  需要注意的几个地方:

  ·DirectX通过DirectX Media Objects(DMOs)来支持在声音中添加特技。因为特技使用到了COM组件,所以首先要通过CoInitialize()来初始化Com库,当然,你别忘了在退出程序时调用CoUninitialize() 。

  ·创建缓冲区的时候,一定不要忘了对 DSBUFFERDESC结构的dwFlages设置DSBCAPS_CTRLFX标志,如果忘了设置这个标志,那么你后面的音频特技全是无效的。但是,在设置这个标志时,buffer一定要处于停止状态并且没有被锁定。在DiectX 9.0中,特技不是依靠硬件来实现的。当然也可以在硬件缓冲区中设置特技,但这样做没有任何的好处。

  ·最后一个要注意的问题,就是缓冲区的大小,缓冲区的size过小,特技并不能好好工作,DirectSound建议缓冲区的大小应该在小于150毫秒的数据数据量,缓冲区中使用特技,这个值被定义为DSBSIZ_FX_MIN。

  在上面的例子中,waveformat.nAvgBytesPerSec = waveformat.nBlockAlign * waveformat.nSamplesPerSec; = 2*16*4800/8 = 19200 bytes/m

  那么dsbd.dwBufferBytes 的最小值应该大于 19200*0.15 = 2880字节。

  我刚开始就没有注意这个问题,结果后面总是出错,我一直纳闷不已,因为代码没有问题的,后来重新看了一下帮助才发现这个问题。

  第3步 通过缓冲区对象IDirectSoundBuffer8设置缓冲区支持的具体特技,并通过IDirectSoundBuffer8 对象的GetObjectInPath方法获得具体的音频特技的接口;这里以chorus特技为例:如下

DSEFFECTDESC effectdesc;
ZeroMemory( &effectdesc, sizeof( DSEFFECTDESC ) );
effectdesc.dwSize = sizeof(DSEFFECTDESC);
effectdesc.dwFlags = 0;
effectdesc.guidDSFXClass = GUID_DSFX_STANDARD_CHORUS;
DWORD dwResult;
if(g_pDSBuffer8)
{
 hr = g_pDSBuffer8->SetFX(1,&effectdesc,&dwResult);
 if( FAILED( hr = g_pDSBuffer8->GetObjectInPath( GUID_DSFX_STANDARD_CHORUS, 0, IID_IDirectSoundFXChorus8,(LPVOID*) &g_pChorus ) ) )
  return ;
 g_pChorus->GetAllParameters(&g_paramsChorus);
}

  第4步 通过特效接口的SetAllParameters方法设置参数,手动拖动滑动条,来设置特技参数,可以在例子中看到如下的代码,以chorus为例:

void CDsoundEffectDemoDlg::OnEffectChanged()
{
 switch( g_dwCurrentFXType )
 {
  case eSFX_chorus:
  {
   //下面的代码主要是为了获取滑动条上参数的数值。
   SaveSingleParameter( IDC_PARAM_NAME1, &g_paramsChorus.fWetDryMix, DSFXCHORUS_WETDRYMIX_MIN, DSFXCHORUS_WETDRYMIX_MAX );
   SaveSingleParameter( IDC_PARAM_NAME2, &g_paramsChorus.fDepth, DSFXCHORUS_DEPTH_MIN, DSFXCHORUS_DEPTH_MAX );
   SaveSingleParameter( IDC_PARAM_NAME3, &g_paramsChorus.fFeedback, DSFXCHORUS_FEEDBACK_MIN, DSFXCHORUS_FEEDBACK_MAX );
   SaveSingleParameter( IDC_PARAM_NAME4, &g_paramsChorus.fFrequency, DSFXCHORUS_FREQUENCY_MIN, DSFXCHORUS_FREQUENCY_MAX );
   SaveSingleParameter( IDC_PARAM_NAME5, &g_paramsChorus.fDelay, DSFXCHORUS_DELAY_MIN, DSFXCHORUS_DELAY_MAX );

   if( ((CButton*)GetDlgItem(IDC_RADIO_TRIANGLE ))->GetCheck() == BST_CHECKED )
    g_paramsChorus.lWaveform = DSFXCHORUS_WAVE_TRIANGLE;
   else
    g_paramsChorus.lWaveform = DSFXCHORUS_WAVE_SIN

   if( ((CButton*)GetDlgItem(IDC_RADIO_NEG_180 ))->GetCheck() == BST_CHECKED )
    g_paramsChorus.lPhase = DSFXCHORUS_PHASE_NEG_180;
   else if( ((CButton*)GetDlgItem(IDC_RADIO_NEG_90 ))->GetCheck() == BST_CHECKED )
    g_paramsChorus.lPhase = DSFXCHORUS_PHASE_NEG_90;
   else if( ((CButton*)GetDlgItem( IDC_RADIO_ZERO ))->GetCheck() == BST_CHECKED )
    g_paramsChorus.lPhase = DSFXCHORUS_PHASE_ZERO;
   else if( ((CButton*)GetDlgItem(IDC_RADIO_90))->GetCheck() == BST_CHECKED )
    g_paramsChorus.lPhase = DSFXCHORUS_PHASE_90;
   else
    g_paramsChorus.lPhase = DSFXCHORUS_PHASE_180;

   if( g_pChorus) //设置合生特技的参数
    g_pChorus->SetAllParameters( &g_paramsChorus );

  break;
 }
 ......//下面是其他特技的参数设置 ,略,具体可以见例子中的代码。
}

  注: 在音频播放的同时拖动滑动条调解音频特技的参数,可以随时调整音频特技的效果。

  第5步 一切都ok了,下面就是调用IDRIRECTSOUNDBUFFER8 的play函数来播放音频文件了。

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

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

  上面讲了Directsound音频特技开发的主要流程,其中的设置音频过程我只是用chorus为例,其实其他的几个特技的使用方法跟chorus很类似,唯一不同的就是参数结构的不同,限于篇幅,对于其他特技的代码就不一一列出了,具体的可一参看本文实例的代码。

  下面我们看看每个特技的参数都需要设置什么。
 楼主| 发表于 2006-5-29 17:49:38 | 显示全部楼层
3、失真特技(Distorion)


  失真特技的参数通过下面的结构来调整:

typedef struct _DSFXDistortion
{
 FLOAT fGain;//信号失真后的音量的强度变化,缺省是比原来衰减 18db。
 FLOAT fEdge;//失真的强度,用百分比来表示,缺省值是15
 FLOAT fPostEQCenterFrequency;//信号叠加的中心频率,缺省是2400hz
 FLOAT fPostEQBandwidth;//信号的带宽 ,缺省是2400hz
 FLOAT fPreLowpassCutoff;//高通滤波的最高值,缺省是8000hz
} DSFXDistortion, *LPDSFXDistortion;

  我们在程序中可以定义这个结构的对象,如下:

LPDIRECTSOUNDFXDISTORTION8 g_pDistortion = NULL;
DSFXDistortion g_paramsDistortion;

  通过拖动滑动条,我们可以用下面的代码调整参数:

DSEFFECTDESC effectdesc;
ZeroMemory( &effectdesc, sizeof( DSEFFECTDESC ) );
effectdesc.dwSize = sizeof(DSEFFECTDESC);
effectdesc.dwFlags = 0;
effectdesc.guidDSFXClass = GUID_DSFX_STANDARD_DISTORTION;
DWORD dwResult;
if(g_pDSBuffer8)
{
 g_pDSBuffer8->SetFX(1,&effectdesc,&dwResult);
 if( FAILED( hr = g_pDSBuffer8->GetObjectInPath( GUID_DSFX_STANDARD_DISTORTION, 0, IID_IDirectSoundFXDistortion8,(LPVOID*) &g_pDistortion ) ) )
  return ;
 g_pDistortion ->SetAllParameters (&g_paramsDistortion);
}

  4、回声特技( Echo)


  回声特技的参数通过下面的结构来调整:

typedef struct _DSFXEcho
{
 FLOAT fWetDryMix;处理过的信号和没有处理的信号的比率,缺省值是50
 FLOAT fFeedback;//输出信号反馈到输入信号的百分比, 缺省值是50
 FLOAT fLeftDelay;//左声道延迟的时间,缺省值500ms
 FLOAT fRightDelay;//右声道延迟的时间,缺省值500ms
 LONG lPanDelay;//是否左右声道交替延迟,缺省值 0,左右声道不交替
} DSFXEcho, *LPDSFXEcho;

  我们在程序中可以定义这个结构的对象,如下:

LPDIRECTSOUNDFXECHO8 g_pEcho = NULL;
DSFXEcho g_paramsEcho;

  通过拖动滑动条,我们可以用下面的代码调整参数:

DSEFFECTDESC effectdesc;
ZeroMemory( &effectdesc, sizeof( DSEFFECTDESC ) );
effectdesc.dwSize = sizeof(DSEFFECTDESC);
effectdesc.dwFlags = 0;
effectdesc.guidDSFXClass = GUID_DSFX_STANDARD_ECHO;
DWORD dwResult;
if(g_pDSBuffer8)
{
 g_pDSBuffer8->SetFX(1,&effectdesc,&dwResult);
 if( FAILED( hr = g_pDSBuffer8->GetObjectInPath( GUID_DSFX_STANDARD_ECHO, 0, IID_IDirectSoundFXEcho8,(LPVOID*) &g_pEcho ) ) )
  return ;
 g_pEcho->SetAllParameters (&g_paramsEcho);
}
 楼主| 发表于 2006-5-29 17:49:54 | 显示全部楼层
5、波浪特技(Flanger)


  波浪特技的参数通过下面的结构来调整:

typedef struct _DSFXFlanger
{
 FLOAT fWetDryMix;//处理过的信号和没有处理的信号的比率,取值范围 0~~100,缺省值是50
 FLOAT fDepth;//低频振荡器调整延迟时间的百分比,取值范围 0~~100,缺省值 是100
 FLOAT fFeedback;//输出信号反馈到输入信号的百分比,取值范围 -99~~99, 缺省值是-50
 FLOAT fFrequency;//低频振荡器的频率, 缺省值是 0.25
 LONG lWaveform;//低频振荡器的波形,分为三角形,和正弦波形
 FLOAT fDelay;//播放之前的延迟,以毫秒作单位,缺省值是2ms
 LONG lPhase;//相位
} DSFXFlanger, *LPDSFXFlanger;

  我们在程序中可以定义这个结构的对象,如下:

LPDIRECTSOUNDFXFLANGER8 g_pFlanger = NULL;
DSFXFlanger g_paramsFlanger;

  通过拖动滑动条,我们可以用下面的代码调整参数:

DSEFFECTDESC effectdesc;
ZeroMemory( &effectdesc, sizeof( DSEFFECTDESC ) );
effectdesc.dwSize = sizeof(DSEFFECTDESC);
effectdesc.dwFlags = 0;
effectdesc.guidDSFXClass = GUID_DSFX_STANDARD_FLANGER;
DWORD dwResult;
if(g_pDSBuffer8)
{
 g_pDSBuffer8->SetFX(1,&effectdesc,&dwResult);
 if( FAILED( hr = g_pDSBuffer8->GetObjectInPath( GUID_DSFX_STANDARD_FLANGER, 0, IID_IDirectSoundFXFlanger8,(LPVOID*) &g_pFlanger ) ) )
  return ;
 g_pFlanger->SetAllParameters (&g_paramsFlanger);
}

  6、咕噜声效特技(Gargle)


  咕噜声效特技的参数通过下面的结构来调整:

typedef struct _DSFXGargle
{
 DWORD dwRateHz;//调制波频率,取值范围 1 ~~1000 hz,缺省值是20 hz
 DWORD dwWaveShape;//调制波形状,分为三角形和正方形两种,DSFXGARGLE_WAVE_TRIANGLE DSFXGARGLE_WAVE_SQUARE
} DSFXGargle, *LPDSFXGargle;

  我们在程序中可以定义这个结构的对象,如下:

LPDIRECTSOUNDFXGARGLE8 g_pGargle = NULL;
DSFXGargle g_paramsGargle;
DSEFFECTDESC effectdesc;
ZeroMemory( &effectdesc, sizeof( DSEFFECTDESC ) );
effectdesc.dwSize = sizeof(DSEFFECTDESC);
effectdesc.dwFlags = 0;
effectdesc.guidDSFXClass = GUID_DSFX_STANDARD_GARGLE;
DWORD dwResult;
if(g_pDSBuffer8)
{
 g_pDSBuffer8->SetFX(1,&effectdesc,&dwResult);
 if( FAILED( hr = g_pDSBuffer8->GetObjectInPath( GUID_DSFX_STANDARD_GARGLE, 0, IID_IDirectSoundFXGargle8,(LPVOID*) &g_pGargle ) ) )
  return ;
 g_pGargle->SetAllParameters (&g_paramsGargle);
}
 楼主| 发表于 2006-5-29 17:50:31 | 显示全部楼层
 7、参数平衡特技(ParamEQ)


  参数平衡特技的参数通过下面的结构来调整:

typedef struct _DSFXParamEq
{
 FLOAT fCenter;//中心的频率 ,单位是hz,取值范围是 80.0f hz~~16000.0f ,缺省值 是 8000hz
 FLOAT fBandwidth;//音的带宽,以半音为单位,取值范围是 1.0f~~36.0f,缺省值 是12
 FLOAT fGain;//音频的音量,以db为单位,取值范围是 -15.0db ~~15.0f db,缺省值是0db
} DSFXParamEq, *LPDSFXParamEq;

  我们在程序中可以定义这个结构的对象,如下:

LPDIRECTSOUNDFXPARAMEQ8 g_pParamEq = NULL;
DSFXParamEq g_paramsParamEq;

  通过拖动滑动条,我们可以用下面的代码调整参数:

DSEFFECTDESC effectdesc;
ZeroMemory( &effectdesc, sizeof( DSEFFECTDESC ) );
effectdesc.dwSize = sizeof(DSEFFECTDESC);
effectdesc.dwFlags = 0;
effectdesc.guidDSFXClass = GUID_DSFX_STANDARD_PARAMEQ;
DWORD dwResult;
if(g_pDSBuffer8)
{
 g_pDSBuffer8->SetFX(1,&effectdesc,&dwResult);
 if( FAILED( hr = g_pDSBuffer8->GetObjectInPath( GUID_DSFX_STANDARD_PARAMEQ, 0, IID_IDirectSoundFXParamEq8,(LPVOID*) &g_pParamEq ) ) )
  return ;
 g_pParamEq ->SetAllParameters (&g_paramsParamEq);
}

  8、混响(Reverb)


  混响特技的参数通过下面的结构来调整:

typedef struct _DSFXWavesReverb
{
 FLOAT fInGain; //输入信号的音量的大小,即db值,缺省值是 0db。
 FLOAT fReverbMix;//回响混合音量强度大小,用db值来表示,缺省值是 0db。
 FLOAT fReverbTime;//回响的时间,单位是ms,缺省值是 1000.0f ms
 FLOAT fHighFreqR//高频回响所占时间的比率 , 缺省值 0.001f 。TRatio;
} DSFXWavesReverb, *LPDSFXWavesReverb;

  我们在程序中可以定义这个结构的对象,如下:

LPDIRECTSOUNDFXWAVESREVERB8 g_pReverb = NULL;
DSFXWavesReverb g_paramsReverb;

  通过拖动滑动条,我们可以用下面的代码调整参数:

DSEFFECTDESC effectdesc;
ZeroMemory( &effectdesc, sizeof( DSEFFECTDESC ) );
effectdesc.dwSize = sizeof(DSEFFECTDESC);
effectdesc.dwFlags = 0;
effectdesc.guidDSFXClass = GUID_DSFX_STANDARD_CHORUS;
DWORD dwResult;
if(g_pDSBuffer8)
{
 g_pDSBuffer8->SetFX(1,&effectdesc,&dwResult);
 if( FAILED( hr = g_pDSBuffer8->GetObjectInPath( GUID_DSFX_STANDARD_CHORUS, 0, IID_IDirectSoundFXChorus8,(LPVOID*) &g_pReverb ) ) )
  return ;
 g_pReverb ->SetAllParameters (&g_paramsReverb);
}

  结束语

  本文通过一个实例演示了如何使用DirectSound提供的基本音频特技。简单的接口,强大的功能,能给你的程序增色不少。本文的示例代码在windowXP +vc.net下调试通过。最后,按照惯例,留下我的email :aooang@hotamil.com,如果有什么问题,可以给我发email。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2024-5-18 22:09

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表