Using directsound (9) in Delphi: preliminary effect and idirectsoundfxgargle8 Effect

Source: Internet
Author: User
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:


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.