用DirectSound实现增强的音频特技效果.docx
- 文档编号:1718174
- 上传时间:2023-05-01
- 格式:DOCX
- 页数:20
- 大小:270.36KB
用DirectSound实现增强的音频特技效果.docx
《用DirectSound实现增强的音频特技效果.docx》由会员分享,可在线阅读,更多相关《用DirectSound实现增强的音频特技效果.docx(20页珍藏版)》请在冰点文库上搜索。
用DirectSound实现增强的音频特技效果
摘要:
本文介绍了DirectSound提供的几个基本的音频特技以及其应用方法,并通过一个程序实例演示了如何应用这些特技为你的程序实现增强的音频效果。
关键词:
DirectSound音频特技
前段时间写三篇关于DirectSound的文档,包括录音,混音,以及3D音效,也基本上将DirectSound的开发主要内容涉及到了,因为关于特技这部分在DirectSound的开发文档中介绍的就很简单,加上应用起来也不是很难,本来不想介绍这部分的内容,但是,当我体验过DirectSound的音频特技后,我改变了想法,我觉得DirectSound提供的几个音频特技效果很好,很有震撼力,如果你将这些特技添加到你的程序中,肯定能为你的程序增色不少,况且,接口这么简单,应用起来这么容易。
所以这篇文档我给大家介绍一下DirectSound的基本特技。
DirectSound提供8个基本的音频特技。
1、Chorus和声,这里说的和声不是指很多人合唱,而是指声音的重叠,即通过原声和回声的重叠,使得声音加宽,加厚。
2、Compression压限,是针对声音不同部分的音量进行增减也就是说,可以对某段音频中音量低于某一限度的部分进行平滑的音量提升(其余部分不变);对音量高于某一限度的部分进行平滑的音量衰减(其余部分不变),或二者同时作用,简单说,就是平衡音量。
3、Distortion失真。
4、Echo回声,模拟声音被远处的平面反射回来的效果。
5、EnvironmentalReverberation反射(混响),简单说就是声音余韵,音源在空间反射出来的声音。
适当设置混响,可以更真实、更有现场感的再现声音源,也可以起到修饰、美化的作用。
表现宽阔的,传声真实的效果。
6、Flange,一般翻译为波浪特技,用于设置变调效果,通过拷贝失调的声音,或者把某个频率点改变,调节声音分离的时间、音调深度。
可以用来产生颤动、急促的声音。
7、Gargle,咕噜效果处理。
一种可以试音源产生咕噜声的调幅处理模式。
8、ParametricEqualizer参数平衡,用于为音频设置参数均衡器。
强化或衰减指定的频率。
对于增强音乐的效果特别有效。
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步:
首先要定义我们用到的一些变量,这里我定义的全是全局的变量,你可以根据自己的情况来定义这些变量。
LPDIRECTSOUNDBUFFER8g_pDSBuffer8=NULL;//缓冲区对象
LPDIRECTSOUND8g_pDsd=NULL;///Directsound对象
CWaveFile*g_pWaveFile=NULL;//操作wave文件的对象
//下面的8个指针接口对应着8个音频特技
LPDIRECTSOUNDFXCHORUS8g_pChorus=NULL;
LPDIRECTSOUNDFXCOMPRESSOR8g_pCompressor=NULL;
LPDIRECTSOUNDFXDISTORTION8g_pDistortion=NULL;
LPDIRECTSOUNDFXECHO8g_pEcho=NULL;
LPDIRECTSOUNDFXFLANGER8g_pFlanger=NULL;
LPDIRECTSOUNDFXGARGLE8g_pGargle=NULL;
LPDIRECTSOUNDFXPARAMEQ8g_pParamEq=NULL;
LPDIRECTSOUNDFXWAVESREVERB8g_pReverb=NULL;
//用于设置特技的参数,每种音频特技对应着一个参数。
DSFXChorusg_paramsChorus;
DSFXCompressorg_paramsCompressor;
DSFXDistortiong_paramsDistortion;
DSFXEchog_paramsEcho;
DSFXFlangerg_paramsFlanger;
DSFXGargleg_paramsGargle;
DSFXParamEqg_paramsParamEq;
DSFXWavesReverbg_paramsReverb;
定义完这些变量,就可以开始我们的工作了
第2步初始化Directsound,获取IDrectSoundBuffer8的接口。
这一步骤的工作可以放到程序的初始化的地方。
CoInitialize(NULL);
HRESULThr;
if(FAILED(hr=DirectSoundCreate8(NULL,&g_pDsd,NULL)))
returnFALSE;
if(FAILED(hr=g_pDsd->SetCooperativeLevel(m_hWnd,DSSCL_PRIORITY)))
returnFALSE;
//
for(inti=0;i g_event[i]=CreateEvent(NULL,FALSE,FALSE,NULL); //设置音频的格式 WAVEFORMATEXwaveformat; 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; DSBUFFERDESCdsbd; 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; LPDIRECTSOUNDBUFFERlpbuffer; if(FAILED(hr=g_pDsd->CreateSoundBuffer(&dsbd,&lpbuffer,NULL))) returnFALSE; if(FAILED(hr=lpbuffer->QueryInterface(IID_IDirectSoundBuffer8,(LPVOID*)&g_pDSBuffer8))) returnFALSE; lpbuffer->Release(); 需要注意的几个地方: ·DirectX通过DirectXMediaObjects(DMOs)来支持在声音中添加特技。 因为特技使用到了COM组件,所以首先要通过CoInitialize()来初始化Com库,当然,你别忘了在退出程序时调用CoUninitialize()。 ·创建缓冲区的时候,一定不要忘了对DSBUFFERDESC结构的dwFlages设置DSBCAPS_CTRLFX标志,如果忘了设置这个标志,那么你后面的音频特技全是无效的。 但是,在设置这个标志时,buffer一定要处于停止状态并且没有被锁定。 在DiectX9.0中,特技不是依靠硬件来实现的。 当然也可以在硬件缓冲区中设置特技,但这样做没有任何的好处。 ·最后一个要注意的问题,就是缓冲区的大小,缓冲区的size过小,特技并不能好好工作,DirectSound建议缓冲区的大小应该在小于150毫秒的数据数据量,缓冲区中使用特技,这个值被定义为DSBSIZ_FX_MIN。 在上面的例子中,waveformat.nAvgBytesPerSec=waveformat.nBlockAlign*waveformat.nSamplesPerSec;=2*16*4800/8=19200bytes/m 那么dsbd.dwBufferBytes的最小值应该大于19200*0.15=2880字节。 我刚开始就没有注意这个问题,结果后面总是出错,我一直纳闷不已,因为代码没有问题的,后来重新看了一下帮助才发现这个问题。 第3步通过缓冲区对象IDirectSoundBuffer8设置缓冲区支持的具体特技,并通过IDirectSoundBuffer8对象的GetObjectInPath方法获得具体的音频特技的接口;这里以chorus特技为例: 如下 DSEFFECTDESCeffectdesc; ZeroMemory(&effectdesc,sizeof(DSEFFECTDESC)); effectdesc.dwSize=sizeof(DSEFFECTDESC); effectdesc.dwFlags=0; effectdesc.guidDSFXClass=GUID_DSFX_STANDARD_CHORUS; DWORDdwResult; 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为例: voidCDsoundEffectDemoDlg: : OnEffectChanged() { switch(g_dwCurrentFXType) { caseeSFX_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; elseif(((CButton*)GetDlgItem(IDC_RADIO_NEG_90))->GetCheck()==BST_CHECKED) g_paramsChorus.lPhase=DSFXCHORUS_PHASE_NEG_90; elseif(((CButton*)GetDlgItem(IDC_RADIO_ZERO))->GetCheck()==BST_CHECKED) g_paramsChorus.lPhase=DSFXCHORUS_PHASE_ZERO; elseif(((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函数来播放音频文件了。 DWORDres; LPVOIDlplockbuf; DWORDlen; DWORDdwWrite; 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很类似,唯一不同的就是参数结构的不同,限于篇幅,对于其他特技的代码就不一一列出了,具体的可一参看本文实例的代码。 下面我们看看每个特技的参数都需要设置什么。 1、和声(Chorus)特技,参数设置的界面如下: 合声特技的参数通过下面的结构来调整: typedefstruct_DSFXChorus{ FLOATfWetDryMix;//压缩信号和未压缩信号的比率,缺省值50 FLOATfDepth;//低频率振荡器调制信号的延迟时间的百分比,缺省是10% FLOATfFeedback;//输出信号对特技输入信号的反馈百分比,缺省25% FLOATfFrequency;//LFO的频率,缺省是1.1 LONGlWaveform;//LFO的波形类型,缺省是正弦波 FLOATfDelay;//音频播放时的延迟时间,缺省是16ms LONGlPhase;//左右声道声波的相位差别,取值为-180,-90,0,90,180度 }DSFXChorus,*LPDSFXChorus; 我们在程序中可以定义这个结构的对象,如下: DSFXChorusg_paramsChorus; LPDIRECTSOUNDFXCHORUS8g_pChorus=NULL; 然后通过通过滑动条来设置g_paramsChorus对象的值,设置后可以调用: DSEFFECTDESCeffectdesc; ZeroMemory(&effectdesc,sizeof(DSEFFECTDESC)); effectdesc.dwSize=sizeof(DSEFFECTDESC); effectdesc.dwFlags=0; effectdesc.guidDSFXClass=GUID_DSFX_STANDARD_CHORUS; DWORDdwResult; 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) 压限特技的参数通过下面的结构来调整,参数调整界面如上: typedefstruct_DSFXCompressor { FLOATfGain;//压限后输出信号的强度,缺省值是0db FLOATfAttack;//压限达到最大值的时间,缺省是10ms FLOATfRelease;//输入小于fThreshold后,压缩停止的时间,缺省是200ms FLOATfThreshold;//压缩开始的临界点的db值,缺省是-20db FLOATfRatio;//压缩的比率,缺省是3,即3: 1 FLOATfPredelay;//lThreshold达到临界点,attackphase开始前的延迟时间 }DSFXCompressor,*LPDSFXCompressor; 我们在程序中可以定义这个结构的对象,如下: LPDIRECTSOUNDFXCOMPRESSOR8g_pCompressor=NULL; DSFXCompressorg_paramsCompressor; 通过拖动滑动条,我们可以用下面的代码调整参数: DSEFFECTDESCeffectdesc; ZeroMemory(&effectdesc,sizeof(DSEFFECTDESC)); effectdesc.dwSize=sizeof(DSEFFECTDESC); effectdesc.dwFlags=0; effectdesc.guidDSFXClass=GUID_DSFX_STANDARD_COMPRESSOR; DWORDdwResult; 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); } 3、失真特技(Distorion) 失真特技的参数通过下面的结构来调整: typedefstruct_DSFXDistorti
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- DirectSound 实现 增强 音频 特技 效果