Code: Select all
;
; Example of playing a sound buffer with DirectX 8
; (Danilo and www.MasterCreating.de)
; and apply DirectX effects on it.
; (Zapman)
;
#DD_OK = 0
#DS_OK = 0
#DSBPLAY_DEFAULT = $0
#DSBPLAY_LOOPING = $1
#DSBLOCK_ENTIREBUFFER = 2
#DSBCAPS_LOCSOFTWARE = $8
#DSBCAPS_CTRLFREQUENCY = $20
#DSBCAPS_CTRLVOLUME = $80
#DSBCAPS_CTRLPAN = $40
#DSFXECHO_WETDRYMIX_MIN =0
#DSFXECHO_WETDRYMIX_MAX =100
#DSFXECHO_FEEDBACK_MIN =0
#DSFXECHO_FEEDBACK_MAX =100
#DSFXECHO_LEFTDELAY_MIN =1
#DSFXECHO_LEFTDELAY_MAX =2000
#DSFXECHO_RIGHTDELAY_MIN=1
#DSFXECHO_RIGHTDELAY_MAX=2000
#DSFXECHO_PANDELAY_MIN =0
#DSFXECHO_PANDELAY_MAX =1
GUID_DSFX_STANDARD_ECHO.GUID
GUID_DSFX_STANDARD_ECHO\Data1 = $ef3e932c
GUID_DSFX_STANDARD_ECHO\Data2 = $d40b
GUID_DSFX_STANDARD_ECHO\Data3 = $4f51
GUID_DSFX_STANDARD_ECHO\Data4[0] = $8c
GUID_DSFX_STANDARD_ECHO\Data4[1] = $cf
GUID_DSFX_STANDARD_ECHO\Data4[2] = $3f
GUID_DSFX_STANDARD_ECHO\Data4[3] = $98
GUID_DSFX_STANDARD_ECHO\Data4[4] = $f1
GUID_DSFX_STANDARD_ECHO\Data4[5] = $b2
GUID_DSFX_STANDARD_ECHO\Data4[6] = $9d
GUID_DSFX_STANDARD_ECHO\Data4[7] = $5d
IID_IDirectSoundFXEcho.GUID
IID_IDirectSoundFXEcho\Data1 = $8bd28edf
IID_IDirectSoundFXEcho\Data2 = $50db
IID_IDirectSoundFXEcho\Data3 = $4e92
IID_IDirectSoundFXEcho\Data4[0]= $a2
IID_IDirectSoundFXEcho\Data4[1]= $bd
IID_IDirectSoundFXEcho\Data4[2]= $44
IID_IDirectSoundFXEcho\Data4[3]= $54
IID_IDirectSoundFXEcho\Data4[4]= $88
IID_IDirectSoundFXEcho\Data4[5]= $d1
IID_IDirectSoundFXEcho\Data4[6]= $ed
IID_IDirectSoundFXEcho\Data4[7]= $42
#DSBCAPS_CTRLFX = $00000200
Structure DSBUFFERDESC
dwSize.l ; Size of the Structure
dwFlags.l ; Flags specifying the capabilities of the buffer
dwBufferBytes.l ; Size of the new buffer, in bytes. This value must be 0 when creating a buffer with the DSBCAPS_PRIMARYBUFFER flag. For secondary buffers, the minimum and maximum sizes allowed are specified by DSBSIZE_MIN and DSBSIZE_MAX, defined in Dsound.h.
dwReserved.l ; Must be 0
*lpwfxFormat ; Address of a WAVEFORMATEX or WAVEFORMATEXTENSIBLE structure specifying the waveform format for the buffer.
guid3DAlgorithm.GUID; Unique identifier of the two-speaker virtualization algorithm to be used by DirectSound3D hardware emulation. If DSBCAPS_CTRL3D is not set in dwFlags, this member must be GUID_NULL (DS3DALG_DEFAULT).
EndStructure
Structure DSEFFECTDESC
dwSize.l ; Size of the Structure
dwFlags.l ; Can be 0 or one of the following values: DSFX_LOCHARDWARE (Effect must be in hardware) DSFX_LOCSOFTWARE (Effect must be in software)
guidDSFXClass.GUID ; Class identifier of the effect. The following standard effect classes are defined :
; GUID_DSFX_STANDARD_CHORUS
; GUID_DSFX_STANDARD_COMPRESSOR
; GUID_DSFX_STANDARD_DISTORTION
; GUID_DSFX_STANDARD_ECHO
; GUID_DSFX_STANDARD_FLANGER
; GUID_DSFX_STANDARD_GARGLE
; GUID_DSFX_STANDARD_I3DL2REVERB
; GUID_DSFX_STANDARD_PARAMEQ
; GUID_DSFX_STANDARD_WAVES_REVERB
dwReserved1.i
dwReserved2.i
EndStructure
Structure DSFXEcho
fWetDryMix.f
fFeedback.f
fLeftDelay.f
fRightDelay.f
lPanDelay.l
EndStructure
Procedure Delete(*obj.IUnknown)
ProcedureReturn *Obj\Release()
EndProcedure
Procedure.s DecodeError (errorNb )
; This fonction retrieve the text corresponding to errorNb
; Cette fonction récupère le text correspondant à ErrorNb
If errorNb
*memAdr=AllocateMemory (255)
length = FormatMessage_ (#FORMAT_MESSAGE_FROM_SYSTEM, #Null, errorNb, 0, *memAdr, 255, #Null)
If length > 1
e$ = PeekS (*memAdr, length - 2)
Else
Select ErrorNb
Case #E_INVALIDARG
e$ = "INVALIDARG"
Case #E_FAIL
e$ = "FAIL"
Case #DS_OK
e$ = "OK"
Case #E_OUTOFMEMORY
e$ = "OUTOFMEMORY"
Case #E_NOTIMPL
e$ = "NOTIMPL"
Case #E_NOINTERFACE
e$ = "NOINTERFACE"
Case $88780046 ; DSERR_PRIOLEVELNEEDED
e$ = "PRIOLEVELNEEDED"
Case $88780064 ; DSERR_BADFORMAT
e$ = "BADFORMAT"
Case $88780032 ; DSERR_INVALIDCALL
e$ = "INVALIDCALL"
Case $8878001E ; DSERR_CONTROLUNAVAIL
e$ = "CONTROLUNAVAIL"
Case $8878000A ; DSERR_ALLOCATED
e$ = "ALLOCATED"
Case $88781161 ; DSERR_OBJECTNOTFOUND
e$ = "OBJECTNOTFOUND"
Default
e$ = "Erreur N° / Error N# "+Str(errorNb)
EndSelect
EndIf
FreeMemory (*memAdr)
ProcedureReturn e$
Else
ProcedureReturn ""
EndIf
EndProcedure
Procedure.s TextError ()
; When an error occure, this fonction retrieve the text of it
; Quand une erreur survient, cette fonction récupère le text correspondant
errorNb = GetLastError_ ()
ProcedureReturn DecodeError (errorNb)
EndProcedure
Procedure ShowError()
Err$=TextError()
If Err$<>""
MessageRequester("Erreur / Error", Err$, 0)
EndIf
EndProcedure
Procedure Error_Msg(String.s)
MessageRequester("Error",String.s,0)
End
EndProcedure
Procedure lpDSEnumCallback(lpGuid,lpcstrDescription.s,lpcstrModule.s,lpContext)
Debug lpcstrDescription
Debug lpcstrModule
ProcedureReturn #True
EndProcedure
DirectSoundCaptureEnumerate_(@lpDSEnumCallback(),0)
hwnd = OpenWindow(0,0,0,200,200,"Sound",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
TextGadget (1,10,10,180,15,"Echo Wet/Dry: 100")
TrackBarGadget(2,10,25,180,20,0,100)
SetGadgetState(2,100)
TextGadget (3,10,50,180,15,"Pan: 0")
TrackBarGadget(4,10,65,180,20,0,200)
SetGadgetState(4,100)
TextGadget (5,10,90,180,15,"Volume: 10000")
TrackBarGadget(6,10,105,180,20,0,10000)
SetGadgetState(6,10000)
Result = OpenLibrary(0,"DSOUND.DLL")
If result = 0
Error_Msg("Can't open Direct Sound Library : "+TextError())
EndIf
;*RA_DirectSound2.IDropSourceVtb
*RA_DirectSound.IDirectSound8
; create DS8 Sound Object
Result = CallFunction(0,"DirectSoundCreate8",0,@*RA_DirectSound,0)
If Result <> #DD_OK
Error_Msg("Can't do DirectSoundCreate8 : " + DecodeError(Result))
EndIf
; Set Coop Level
Result = *RA_DirectSound\SetCooperativeLevel(hwnd,1)
If Result <> #DD_OK
Error_Msg("Can't Set Coop Level : " + DecodeError(Result))
EndIf
; Setting up Primary Buffer
dsbd.DSBUFFERDESC ; Set up structure
dsbd\dwSize = SizeOf(DSBUFFERDESC) ; Save structure size
dsbd\dwFlags = 1 ; It is the primary Buffer (see DSound.h)
dsbd\dwBufferBytes = 0 ; NULL ? Because primary Buffer must be Null
dsbd\lpwfxFormat = 0 ; NULL ? ? ? <- it's a Pointer
Result = *RA_DirectSound\CreateSoundBuffer(@dsbd,@*pDSBPrimary.IDirectSoundBuffer,0)
If Result <> #DD_OK
Error_Msg("Can't Set up primary sound buffer : " + DecodeError(Result))
EndIf
#channels = 2
wfx.WAVEFORMATEX ; Wave Format Structure
RtlZeroMemory_(@wfx,SizeOf(WAVEFORMATEX));
wfx\wFormatTag = #WAVE_FORMAT_PCM;
wfx\nChannels = #channels ;dwPrimaryChannels;
wfx\nSamplesPerSec = 44100 ;dwPrimaryFreq;
wfx\wBitsPerSample = 16 ;dwPrimaryBitRate;
wfx\nBlockAlign = (wfx\wBitsPerSample / 8 * wfx\nChannels)
wfx\nAvgBytesPerSec = (wfx\nSamplesPerSec * wfx\nBlockAlign)
; secondary Buffer (see DSound.h)
dsbd\dwFlags = #DSBCAPS_LOCSOFTWARE|#DSBCAPS_CTRLVOLUME|#DSBCAPS_CTRLPAN |#DSBCAPS_CTRLFX ; |#DSBCAPS_CTRLFREQUENCY
dsbd\dwBufferBytes = 4 * wfx\nAvgBytesPerSec ; alloc 3 Seconds
dsbd\lpwfxFormat = @wfx
; CREATE Secondary Buffer
Result = *RA_DirectSound\CreateSoundBuffer(@dsbd,@*pDSB.IDirectSoundBuffer,0)
If Result <> #DD_OK
Error_Msg("Can't Set up secondary sound buffer : " + DecodeError(Result))
EndIf
; ASK for DirectSoundBuffer8 Interface
*DSB8.IDirectSoundBuffer8 = 0
*pDSB\QueryInterface(?IID_DirectSoundBuffer8,@*DSB8)
Delete(*pDSB)
If *DSB8 = 0
Error_Msg("Can't get DirectSoundBuffer8 Interface")
EndIf
#DSBLOCK_ENTIREBUFFER = $2
If *DSB8\Lock(0,0,@lpvWrite,@dwLength,0,0,#DSBLOCK_ENTIREBUFFER) = #DS_OK
; OK, now copy data in buffer...
Structure SOUND_BUFFER ; channels, each 16 bit
channel.w[#channels]
EndStructure
*Buffer.SOUND_BUFFER = lpvWrite
; GENERATE SOUND DATA ;)
l = dwLength/SizeOf(SOUND_BUFFER)
s = 1
s2 = 1
s3.f = 200
For a = 0 To l
If b < -50000
s = 1
EndIf
If b > 50000
s = -1
EndIf
If c < -40000
s2 = 1
EndIf
If c > 40000
s2 = -1
EndIf
s3 +1/20
If s3>4000
s3 = 200
EndIf
b + s*s3
c + (s2*500) + (s3/20)
*Buffer\channel[0] = b
*Buffer\channel[1] = c
*Buffer + SizeOf(SOUND_BUFFER)
Next a
; GENERATE SOUND END
*DSB8\UnLock(lpvWrite,dwLength,0,0)
;- Echo
Echo.DSFXEcho
Echo\fWetDryMix = #DSFXECHO_WETDRYMIX_MAX
Echo\fFeedback = 40
Echo\fLeftDelay = 333
Echo\fRightDelay= 333
Echo\lPanDelay = 0
CoInitialize_(0)
pDSFXDesc.DSEFFECTDESC ; Set up structure
pDSFXDesc\dwSize = SizeOf(DSEFFECTDESC) ; Save structure size
pDSFXDesc\guidDSFXClass\Data1 = GUID_DSFX_STANDARD_ECHO\Data1 ; Set Echo Effect
pDSFXDesc\guidDSFXClass\Data2 = GUID_DSFX_STANDARD_ECHO\Data2
pDSFXDesc\guidDSFXClass\Data3 = GUID_DSFX_STANDARD_ECHO\Data3
For i = 0 To 7
pDSFXDesc\guidDSFXClass\Data4[i] = GUID_DSFX_STANDARD_ECHO\Data4[i]
Next
Result = *DSB8\SetFX(1, @pDSFXDesc ,@pdwResultCodes.l)
If Result <> #DD_OK
Error_Msg("Can't Set effect : " + DecodeError(Result))
EndIf
dwIndex.l = 0
*ppObject.IDirectSoundFXEcho = 0
Result = *DSB8\GetObjectInPath(GUID_DSFX_STANDARD_ECHO,dwIndex, IID_IDirectSoundFXEcho,@*ppObject)
If Result
Error_Msg("Can't GetObjectInPath : "+DecodeError(Result))
Else
Result = *ppObject\SetAllParameters(@Echo)
If Result
Error_Msg("Can't SetAllParameters : "+DecodeError(Result))
EndIf
EndIf
; MemoryID = AllocateMemory(0,dwLength,0)
*DSB8\Play(0,0,#DSBPLAY_LOOPING);#DSBPLAY_DEFAULT);
mlpvWrite = lpvWrite
result = *pDSBPrimary\Lock(0,0,@lpvWrite,@dwLength,0,0,#DSBLOCK_ENTIREBUFFER)
If result = #DS_OK
For i = 1 To 50
a = PeekL(@mlpvWrite+i)-PeekL(@lpvWrite+i)
Debug "*"+Str(PeekL(@mlpvWrite+i))+" - "+Str(PeekL(@lpvWrite+i))
Debug a
Next
Debug "********************"
*pDSBPrimary\UnLock(lpvWrite,dwLength,0,0)
EndIf
EndIf
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Quit = 1
Case #PB_Event_Gadget
Select EventGadget()
Case 2 ; Frequency Control
vEcho = GetGadgetState(2)
SetGadgetText(1,"Echo Wet/Dry : "+Str(vEcho))
;*DSB8\SetFrequency(Frequ*100)
Echo\fWetDryMix = vEcho
*ppObject\SetAllParameters(@Echo)
Case 4 ; Pan: Left <> Right
Pan = GetGadgetState(4)*100-10000
SetGadgetText(3,"Pan: "+Str(Pan))
*DSB8\SetPan(Pan)
Case 6 ; Volume
Vol = GetGadgetState(6)
SetGadgetText(5,"Volume: "+Str(Vol))
*DSB8\SetVolume(Vol-10000)
EndSelect
EndSelect
Until Quit
*DSB8\Stop()
; Release/Delete Objects
; (reversed order of creation)
Delete(*DSB8)
Delete(*pDSBPrimary)
Delete(*RA_DirectSound)
End
DataSection
IID_DirectSoundBuffer8: ; DSOUND.h
Data.l $6825A449
Data.w $7524,$4D82
Data.b $92,$0F,$50,$E3,$6A,$B3,$AB,$1E
EndDataSection