The "special effect" can be set only when the idirectsoundbuffer8 buffer is used. The main buffer zone is mainly responsible for mixing and processing 3D effects.
Idirectsoundbuffer8 (non-idirectsoundbuffer) supports the following delimiters:
Idirectsoundfxchorus8 // chorus; fine tune native and echo delays idirectsoundfxcompressor8 // compression; compress certain amplitude idirectsoundfxdistortion8 // distortion; change the top of the waveform to square or sawing idirectsoundfxecho8 // echo; repeat and attenuation echo idirectsoundfxflanger8 // edge; delayed echo idirectsoundfxgargle8 // gargle; some people call it cool effect; // ambient reverb; room and Hall idirectsoundfxparameq8 // balanced; scales signals of different frequencies. idirectsoundfxwavesreverb8 // reverb. DirectX Media objects (DMOs) is a sound processing technology bought by Microsoft from waves.
Procedure:
1. Associate the special effect using the setfx () method of idirectsoundbuffer8. This process mainly prepares the tdseffectdesc structure array for the parameters of the setfx () method;
2. Get the special effect object through the getobjectinpath () method of idirectsoundbuffer8;
3. Set the special effect parameters through the setallparameters () method of the special effect object.
The nine special effect objects have only two methods: getallparameters () and setallparameters (). The parameters of the two methods are struct (different ).
{Associate idirectsoundbuffer8 with a special effect. You cannot use:} function setfx (dweffectscount: DWORD; // number of special effects during buffer locking or playback, that is, the size of the second parameter pdsfxdesc: pdseffectdesc; // tdseffectdesc structure array pdwresultcodes: pdword // receives the setting result. If this parameter is not required, Nil is returned.): hresult; stdcall; // seffx (0, nil, nil) can be used) delete all effects of the buffer. the struct used by the {setfx () method:} tdseffectdesc = packed record dwsize: DWORD; // structure size: dwflags: DWORD; // processing flag; Generally, 0 guiddsfxclass: tguid is given; // specify the effect dwreserved1: dword_ptr; // dwreserved2: dword_ptr is not used; // end is not used; // dseffectdesc. dwflagsdsfx_lochardware = $00000001; // use hardware processing results; in fact, dsfx_locsoftware = $00000002 is not supported in direct9.0; // use software processing results; same as default 0 // default // dseffectdesc. guiddsfxclass, which is the guid query identifier corresponding to the preceding nine interfaces: Invalid invalid guid_dsfx_standard_echo invalid {method for obtaining the special effect object from idirectsoundbuffer8} function getobjectinpath: tguid; // the ID of the object query, guid_dsfx _... dwindex: DWORD; // The index const rguidinterface: tguid when setfx () arranges the special effect array; // the unique identifier of the object, iid_idirectsoundfx... or idirectsoundfx... out ppobject // return the special effect interface to be obtained): hresult; stdcall; {idirectsoundfxgargle8.setallparameters () required struct} tdsfxgargle = packed record dwratehz: DWORD; // frequency; value range: 1 .. 1000, 20 dwwaveshape by default: DWORD; // waveform; triangle wave (0), square wave (1) end; // tdsfxgargle. dwratehz value range; default value: 20dsfxgargle_ratehz_min = 1; // dsfxgargle_ratehz_max = 1000; // dsfxgargle_wave_triangle = 0; // triangular wave dsfxgargle_wave_square = 1;/square wave
To make the code more concise, and to make the previously customized readwave readwave2 (an opendialog method is added ):
Unit readwave2; interfaceuses windows, classes, sysutils, mmsystem, dialogs; typetreadwave = effecffilehandle: hmmio; fformat: role; fsize: DWORD; function getformatandsize (hfile: hmmio): Boolean; public destructor destroy; override; function open (filename: string): Boolean; // OPEN function openresource (resname: string) from the file: Boolean; // open from the resource, the specified resource format must be wave function opendialog: Boolean; // in the dialog box, OPEN function read (pdest: pointer; Size: DWORD): Boolean; // read the waveform data property format: twaveformatex read fformat; // read the data in the format property size: DWORD read fsize; // read the final size of the waveform data; implementation {treadwave} destructor treadwave. destroy; begin if ffilehandle> 0 then mmioclose (ffilehandle, 0); inherited; end; function treadwave. getformatandsize (hfile: hmmio): Boolean; var ckiriff, ckifmt, ckidata: tmmckinfo; begin result: = false; If hfile = 0 Then exit; zeromemory (@ ckiriff, sizeof (tmmckinfo); mmiodescend (hfile, @ ckiriff, nil, mmio_findriff); If (ckiriff. ckid fourcc_riff) or (ckiriff. fcctype mmiostringtofourcc ('wave ', 0) Then exit; zeromemory (@ fformat, sizeof (twaveformatex); zeromemory (@ ckifmt, sizeof (tmmckinfo); ckifmt. ckid: = mmiostringtofourcc ('fmt', 0); zeromemory (@ ckidata, sizeof (tmmckinfo); ckidata. ckid: = mmiostringtofourcc ('data', 0); If (mmiodescend (hfile, @ ckifmt, @ ckiriff, timeout) = mmsyserr_noerror) Then mmioread (hfile, @ fformat, sizeof (twaveformatex); convert (hfile, @ ckifmt, 0); If (mmiodescend (hfile, @ ckidata, @ ckiriff, timeout) = mmsyserr_noerror) Then fsize: = ckidata. cksize; Result: = fformat. wformattag = wave_format_pcm; end; function treadwave. open (filename: string): Boolean; begin result: = false; if not fileexists (filename) Then exit; If ffilehandle> 0 then mmioclose (ffilehandle, 0); ffilehandle: = mmioopen (pchar (filename), nil, mmio_read); Result: = getformatandsize (ffilehandle); end; function treadwave. opendialog: Boolean; begin with topendialog. create (NiL) Do begin filter: = 'wave file (*. wav) | *. wav '; If execute then result: = open (filename); free; end; function treadwave. openresource (resname: string): Boolean; var Res: tresourcestream; mmioinfo: tmmioinfo; begin result: = false; Res: = tresourcestream. create (hinstance, resname, 'Wave '); zeromemory (@ mmioinfo, sizeof (tmmioinfo); mmioinfo. fccioproc: = fourcc_mem; mmioinfo. cchbuffer: = res. size; mmioinfo. pchbuffer: = res. memory; If ffilehandle> 0 then mmioclose (ffilehandle, 0); ffilehandle: = mmioopen (nil, @ mmioinfo, role or mmio_read); Result: = getformatandsize (ffilehandle); Res. free; end; function treadwave. read (pdest: pointer; Size: DWORD): Boolean; begin result: = mmioread (ffilehandle, pdest, size) = size; end.
Test code:
Unit unit1; interfaceuses windows, messages, sysutils, variants, classes, graphics, controls, forms, dialogs, stdctrls, extctrls, comctrls; Type tform1 = Class (tform) button1: tbutton; // open and play button2: tbutton; // stop trackbar1: ttrackbar; // used to adjust tdsfxgargle. dwratehz radiogroup1: tradiogroup; // used to adjust tdsfxgargle. dwwaveshape procedure formcreate (Sender: tobject); Procedure formdestroy (Sender: tobject); P Rocedure button1click (Sender: tobject); Procedure button2click (Sender: tobject); Procedure trackbar1change (Sender: tobject); // radiogroup1.onclick is also associated with end; var form1: tform1; implementation {$ R *. DFM} uses directsound, readwave2; // readwave2 is the modified custom unit var mydsound: idirectsound8; buf8: idirectsoundbuffer8; fxgargle: idirectsoundfxgargle8; // idirectsoundfxgargle8 effector {create a device object and initialize the interface} procedure tform1.fo Rmcreate (Sender: tobject); begin directsoundcreate8 (nil, mydsound, nil); mydsound. setcooperativelevel (handle, dsscl_normal); trackbar1.min: = success; // 1 trackbar1.max: = success; // 1000 trackbar1.position: = 20; // default value: trackbar1.showselrange: = false; trackbar1.tickstyle: = tsnone; radiogroup1.items. commatext: = 'angle, square '; radiogroup1.columns: = 2; radiogroup1. Itemindex: = 0; radiogroup1.onclick: = trackbar1.onchange; // the code of the two events is the same as that of system. reportmemoryleaksonshutdown: = true; end; {create a buffer, associate a special effect, obtain a special effect object, and play it back} procedure tform1.button1click (Sender: tobject); var Buf: idirectsoundbuffer; // The final requirement is attention. Here idirectsoundbuffer is just a bridge bufdesc: tdsbufferdesc; reffect: tdseffectdesc; // The structure WAV: treadwave; P1: pointer; n1: DWORD; begin {modified on the custom unit, Now it is very convenient to call a wave} WAV: = treadwave. create; if not WAV. opendialog then begin WAV. free; exit; end; {Get idirectsoundbuffer8 interface object} zeromemory (@ bufdesc, sizeof (tdsbufferdesc); bufdesc. dwsize: = sizeof (tdsbufferdesc); bufdesc. dwflags: = dsbcaps_ctrlfx ;//! Bufdesc. dwbufferbytes: = WAV. size; bufdesc. lpwfxformat: = @ WAV. format; mydsound. createsoundbuffer (bufdesc, Buf, nil); Buf. queryInterface (iid_idirectsoundbuffer8, buf8); {loading waveform} buf8.lock (0, 0, @ P1, @ N1, nil, nil, dsblock_entirebuffer); WAV. read (P1, N1); WAV. free; buf8.unlock (P1, N1, nil, 0); {prepare the structure required by setfx ()} zeromemory (@ reffect, sizeof (tdseffectdesc); reffect. dwsize: = sizeof (tdseffectdesc); reffect. dwflags: = 0; reffect. guiddsfxclass: = guid_dsfx_standard_gargle; // specify the idirectsoundfxgargle8 effector {correlated effector} buf8.setfx (1, @ reffect, nil); // The parameter should be an array. Since there is only one element, you have saved {Get effect object} buf8.getobjectinpath (guid_dsfx_standard_gargle, 0, marker, fxgargle); {play} buf8.play (0, 0, dsbplay_looping); // Buf: = nil; // The Local interface will be automatically released. end; {stop playing} procedure tform1.button2click (Sender: tobject); begin if assigned (buf8) Then buf8.stop; end; {special effect conversion} procedure tform1.trackbar1change (Sender: tobject); var rgargle: tdsfxgargle; begin if buf8 = nil then exit; rgargle. dwratehz: = trackbar1.position; rgargle. dwwaveshape: = radiogroup1.itemindex; fxgargle. setallparameters (rgargle); end; Procedure tform1.formdestroy (Sender: tobject); begin buf8: = nil; mydsound: = nil; end.
Run: