以文本方式查看主题

-  计算机科学论坛  (http://bbs.xml.org.cn/index.asp)
--  『 C/C++编程思想 』  (http://bbs.xml.org.cn/list.asp?boardid=61)
----  用DirectSound实现增强的音频特技效果  (http://bbs.xml.org.cn/dispbbs.asp?boardid=61&rootid=&id=37684)


--  作者:卷积内核
--  发布时间:9/7/2006 3:39:00 PM

--  用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[i] = 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->Play(0,0,DSBPLAY_LOOPING);

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

  下面我们看看每个特技的参数都需要设置什么。


--  作者:卷积内核
--  发布时间:9/7/2006 3:40:00 PM

--  
1、和声(Chorus)特技,参数设置的界面如下:

按此在新窗口浏览图片

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

typedef struct _DSFXChorus {
 FLOAT fWetDryMix;//压缩信号和未压缩信号的比率,缺省值50
 FLOAT fDepth; //低频率振荡器调制信号的延迟时间的百分比,缺省是10%
 FLOAT fFeedback;//输出信号对特技输入信号的反馈百分比,缺省25%
 FLOAT fFrequency;//LFO的频率,缺省是1.1
 LONG lWaveform;//LFO的波形类型,缺省是正弦波
 FLOAT fDelay;//音频播放时的延迟时间,缺省是16ms
 LONG lPhase; //左右声道声波的相位差别,取值为-180,-90,0,90,180 度
} DSFXChorus, *LPDSFXChorus;

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

DSFXChorus g_paramsChorus;
LPDIRECTSOUNDFXCHORUS8 g_pChorus = NULL;

  然后通过通过滑动条来设置g_paramsChorus对象的值,设置后可以调用:

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( SUCCEED( hr = g_pDSBuffer8->GetObjectInPath( GUID_DSFX_STANDARD_CHORUS, 0, IID_IDirectSoundFXChorus8,(LPVOID*) &g_pChorus ) ) )
  return ;
 g_pChorus->SetAllParameters (&g_paramsChorus);
}

  2、压限特技(Compressor )

按此在新窗口浏览图片

  压限特技的参数通过下面的结构来调整,参数调整界面如上:

typedef struct _DSFXCompressor
{
 FLOAT fGain; //压限后输出信号的强度,缺省值是0db
 FLOAT fAttack;//压限达到最大值的时间,缺省是10ms
 FLOAT fRelease;//输入小于fThreshold后,压缩停止的时间,缺省是200ms
 FLOAT fThreshold;//压缩开始的临界点的db值,缺省是-20db
 FLOAT fRatio;//压缩的比率,缺省是3,即3:1
 FLOAT fPredelay;//lThreshold 达到临界点,attack phase开始前的延迟时间
} DSFXCompressor, *LPDSFXCompressor;

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

LPDIRECTSOUNDFXCOMPRESSOR8 g_pCompressor = NULL;
DSFXCompressor g_paramsCompressor;

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

DSEFFECTDESC effectdesc;
ZeroMemory( &effectdesc, sizeof( DSEFFECTDESC ) );
effectdesc.dwSize = sizeof(DSEFFECTDESC);
effectdesc.dwFlags = 0;
effectdesc.guidDSFXClass = GUID_DSFX_STANDARD_COMPRESSOR;
DWORD dwResult;
if(g_pDSBuffer8)
{
 hr = g_pDSBuffer8->SetFX(1,&effectdesc,&dwResult);
 if(FAILED(hr= _pDSBuffer8->GetObjectInPath( GUID_DSFX_STANDARD_COMPRESSOR, 0, IID_IDirectSoundFXCompressor8,(LPVOID*) &g_pCompressor ) ) )
  return ;
 g_pCompressor->SetAllParameters (&g_paramsCompressor);
}


--  作者:卷积内核
--  发布时间:9/7/2006 3:41:00 PM

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


--  作者:卷积内核
--  发布时间:9/7/2006 3:42:00 PM

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


--  作者:卷积内核
--  发布时间:9/7/2006 3:43:00 PM

--  
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下调试通过。


W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
250.000ms