http://bbs.gameres.com/showthread.asp?threadid=42827
DirectSound8 声音特效
2005/12 by WalkingAlone,源码可以任意拷贝、修改作为任何用途,转载请注明出处。
声明:翻译因涉及专业知识未必准确,请读者自行斟酌。
运行界面
近日一直在看网友“智慧的鱼”在csdn的博客(http://blog.csdn.net/aoosang/),他对DirectSound和DirectShow的认识比较深,同时翻译了部分相关的MSDN,受益匪浅。DirectSound的特效(Effects)部分他还没完善,遗憾之余经过一番Google总算略有收获,姑且记录下来帮助后来者少走点弯路,同时亦希望抛砖引玉,高手指点。
下文引用MSDN部分:
DirectX provides support for effects processing of sounds by DirectX Media Objects (DMOs). A standard set of effects is available to every DirectX application. Other DMOs can be registered on the system.
DirectX使用DirectX Media Objects(DMOs)提供对声音的特效处理,每个DirectX应用程序都可以使用一组标准的特效,系统也可以注册其他特效。
All the standard DMOs except Waves reverberation can process 8- or 16-bit PCM data with one or two channels at any sample rate supported by DirectSound. Waves reverberation does not support 8-bit samples.
除声波回响(Waves reverberation)外,DirectSound所有标准DMOs都支持8或16bit的PCM(脉冲编码调制,Pulse Code Modulation),单声道或双声道,所有采样率。声波回响不支持8bit采样。
标准特效有9种:
Chorus(合唱),对应的接口 IDirectSoundFXChorus8;
Compression(压缩),对应的接口 IDirectSoundFXCompressor8;
Distortion(扭曲),对应的接口 IDirectSoundFXDistortion8;
Echo(回声),对应的接口 IDirectSoundFXEcho8;
Environmental Reverberation(环境回声),对应的接口 IDirectSoundFXI3DL2Reverb8;
Flange(凸缘),对应的接口 IDirectSoundFXFlanger8;
Gargle(漱口?),对应的接口 IDirectSoundFXGargle8;
Parametric Equalizer(参数平衡?),对应的接口 IDirectSoundFXParamEq8;
Waves Reverberation(声波回响),对应的接口 IDirectSoundFXWavesReverb8。
创建特效的过程如下:
1、创建IDirectSound8和主缓冲区,不再累赘,记得CoInitialize;
2、创建IDirectSoundBuffer8接口作为第二缓冲区(SecondaryBuffer),注意三点:一是先用IDirectSound8的CreateSoundBuffer方法创建一个IDirectSoundBuffer,再QueryInterface才能获得IDirectSoundBuffer8接口;二是DSBUFFERDESC中必须有DSBCAPS_CTRLFX标记,以下引用MSDN部分:You can set any number of effects on a secondary buffer that was created with the DSBCAPS_CTRLFX flag in the DSBUFFERDESC structure;三是该缓冲区不能正在播放(可以用GetStatus方法获得当前缓冲区状态,或者简单的用Stop方法不管当前状态先停止)或被锁定的(用unlock解锁);
3、使用IDirectSoundBuffer8的SetFX方法设置特效;
4、使用IDirectSoundBuffer8的GetObjectInPath方法获得特效的接口;
5、特效接口的SetAllParameters方法设置参数,GetAllParameters获取参数,IDirectSoundFXI3DL2Reverb8比较特殊,多了GetQuality,SetQuality,GetPreset,SetPreset 4个方法。
完成上述工作后,调用IDirectSoundBuffer8的Play方法播放音效就可以测试效果了。
清除特效:同样使用SetFX方法,把dwEffectsCount设成0,pDSFXDesc设成NULL(C++)或Nil(Delphi),因为图方便在例子里我并没有这么做,而是把接口释放再重新创建。
下面连接是DirectSound8 声音特效测试Demo,使用Delphi + Jedi DirectX8 Header,并在Windows2000(2003) + Delphi7下编译通过,仅供参考,对于IDirectSoundFXI3DL2Reverb8接口的4个额外方法没有作测试,也没有尝试一次生成多个特效。压缩包中还有vb(VBeffects.rtf)和c++(LunaSound_cpp.htm,日语)两个源码。
不知是我耳朵太背,还是乐理太差,抑或硬件太烂,回声以外的特效都不是很明显,参数的作用也未能理解,希望试过的朋友交流一下。
附1:细心的朋友可能看见源程序中有一句Set8087CW($133f);这是笔者花了一晚时间换回来的血泪教训。在使用SetFX方法调用Environmental Reverberation特效时,会返回一个系统级的“invalid floating point operation”异常(其他特效不会),而不是interface返回的出错代码,根本无法调试。查了几遍google之后才找到问题症结,这是Delphi7帮助的说明,可以查找关键字Set8087CW获得:
The floating-point unit control word controls the precision of floating point calculations, the rounding mode, and whether certain floating-point operations trigger exceptions. See Intel's processor documentation for details.
This routine allows the programmer to have direct access to the CW. Be aware that using this routine to change the value of the 8087CW will change the behavior of the program's FP calculations. It is the programmer's responsibility to reset it.
It is recommended that you disable all floating-point exceptions when using OpenGL to render 3D graphics. To do this, call Set8087CW(0x133f) in your main form's OnCreate event before calling any OpenGL functions.
虽然帮助里说的是OpenGL,想想Directx和OpenGL是殊途同归的东西,死马当活马医终于解决问题。
附2:合唱特效的DSFXChorus纪录参数翻译
Syntax
typedef struct _DSFXChorus {
FLOAT fWetDryMix;
FLOAT fDepth;
FLOAT fFeedback;
FLOAT fFrequency;
LONG lWaveform;
FLOAT fDelay;
LONG lPhase;
} DSFXChorus, *LPDSFXChorus;
typedef const DSFXChorus *LPCDSFXChorus;
fWetDryMix(干湿混合)
Ratio of wet (processed) signal to dry (unprocessed) signal. Must be in the range from DSFXCHORUS_WETDRYMIX_MIN through DSFXCHORUS_WETDRYMIX_MAX (all wet). The default value is 50.
湿信号(wet signal,处理过的信号)对干信号(dry signal,未处理的信号)的比率,取值范围在 DSFXCHORUS_WETDRYMIX_MIN(0)和 DSFXCHORUS_WETDRYMIX_MAX(100.0,全湿)之间,缺省值50。
fDepth(深度)
Percentage by which the delay time is modulated by the low-frequency oscillator, in hundredths of a percentage point. Must be in the range from DSFXCHORUS_DEPTH_MIN through DSFXCHORUS_DEPTH_MAX. The default value is 10.
低频振荡器(LFO,Low Frequency Oscillator)调整延迟的百分比,取值范围在 DSFXCHORUS_DEPTH_MIN(0)和 DSFXCHORUS_DEPTH_MAX(100.0)之间,缺省值是10。
fFeedback(反馈)
Percentage of output signal to feed back into the effect's input, in the range from DSFXCHORUS_FEEDBACK_MIN to DSFXCHORUS_FEEDBACK_MAX. The default value is 25.
输出信号反馈到输入信号的百分比,取值范围在 DSFXCHORUS_FEEDBACK_MIN(-99.0)和 DSFXCHORUS_FEEDBACK_MAX(99.0)之间,缺省值25。
fFrequency(频率)
Frequency of the LFO, in the range from DSFXCHORUS_FREQUENCY_MIN to DSFXCHORUS_FREQUENCY_MAX. The default value is 1.1.
低频振荡器(LFO,Low Frequency Oscillator)的频率,取值范围在DSFXCHORUS_FREQUENCY_MIN(0)和 DSFXCHORUS_FREQUENCY_MAX(10.0)之间,缺省值1.1。
lWaveform(波形)
Waveform shape of the LFO. Defined values are DSFXCHORUS_WAVE_TRIANGLE and DSFXCHORUS_WAVE_SIN. By default, the waveform is a sine.
低频振荡器(LFO,Low Frequency Oscillator)的波形,取值范围是 DSFXCHORUS_WAVE_TRIANGLE(0)和 DSFXCHORUS_WAVE_SIN(1),缺省值DSFXCHORUS_WAVE_SIN。
fDelay(延迟)
Number of milliseconds the input is delayed before it is played back, in the range from DSFXCHORUS_DELAY_MIN to DSFXCHORUS_DELAY_MAX. The default value is 16 ms.
播放之前的延迟,以毫秒作单位,取值范围在 DSFXCHORUS_DELAY_MIN(0)和 DSFXCHORUS_DELAY_MAX(20.0)之间,缺省值16毫秒。
lPhase(相位)
Phase differential between left and right LFOs, in the range from DSFXCHORUS_PHASE_MIN through DSFXCHORUS_PHASE_MAX. Possible values are defined as follows.
左右低频振荡器(LFO,Low Frequency Oscillator)之间的微分相位,取值范围在DSFXCHORUS_PHASE_MIN(0)和 DSFXCHORUS_PHASE_MAX(4)之间,可选值如下:
DSFXCHORUS_PHASE_NEG_180 (0)
DSFXCHORUS_PHASE_NEG_90 (1)
DSFXCHORUS_PHASE_ZERO (2)
DSFXCHORUS_PHASE_90 (3)
DSFXCHORUS_PHASE_180 (4)
The default value is DSFXCHORUS_PHASE_90.
缺省值 DSFXCHORUS_PHASE_90。