; PlayDirectSound8 ; ; This allows you to play more than one sound at a time - See the demo proc ; Ces fonctions vous permettent de jouer plusieurs sons simultanément - Voir la procédure démo ; ; Authors: Zapman from a Danilo program "example of playing a sound buffer with DirectX 8 by Danilo in co-operation with www.MasterCreating.de" ; #DD_OK = 0 #DS_OK = 0 ; #DSBCAPS_LOCSOFTWARE = $8 #DSBCAPS_CTRLFREQUENCY = $20 #DSBCAPS_CTRLVOLUME = $80 #DSBCAPS_CTRLPAN = $40 ; #DSSCL_EXCLUSIVE = 3 ; Accorde l'usage exclusif du periférique de son. Les autres apps sont muettes. #DSSCL_NORMAL = 1 ; Coopération maximale avec les autres apps. (à ne pas utiliser avec les jeux) #DSSCL_PRIORITY = 2 ; Permet de modifier le format principal (c'est le meilleur mode) #DSSCL_WRITEPRIMARY = 4 ; Accorde l'accès au tampon principal pour faire du mixage personnalisé (expert) ; #DSBPLAY_LOOPING = $1 #DSBLOCK_ENTIREBUFFER = $2 ; Global Sound_Frequency ; to give to the main application the frequency of the opened sound ; Structure WAVEFORMATEX wFormatTag.w ; Waveform-audio format type. A complete list of format tags can be found in the Mmreg.h header file. For one- Or two-channel PCM data, this value should be WAVE_FORMAT_PCM. nChannels.w ; Number of channels in the waveform-audio data. Monaural data uses one channel and stereo data uses two channels. nSamplesPerSec.l ; Sample rate, in samples per second (hertz). If wFormatTag is WAVE_FORMAT_PCM, then common values for nSamplesPerSec are 8.0 kHz, 11.025 kHz, 22.05 kHz, and 44.1 kHz. For non-PCM formats, this member must be computed according to the manufacturer's specification of the format tag. nAvgBytesPerSec.l ; Required average data-transfer rate, in bytes per second, for the format tag. If wFormatTag is WAVE_FORMAT_PCM, nAvgBytesPerSec should be equal to the product of nSamplesPerSec and nBlockAlign. For non-PCM formats, this member must be computed according to the manufacturer's specification of the format tag. nBlockAlign.w ; Block alignment, in bytes. The block alignment is the minimum atomic unit of data for the wFormatTag format type. If wFormatTag is WAVE_FORMAT_PCM or WAVE_FORMAT_EXTENSIBLE, nBlockAlign must be equal to the product of nChannels and wBitsPerSample divided by 8 (bits per byte). For non-PCM formats, this member must be computed according to the manufacturer's specification of the format tag. :Software must process a multiple of nBlockAlign bytes of Data at a time. Data written To And Read from a device must always start at the beginning of a block. For example, it is illegal To start playback of PCM Data in the middle of a sample (that is, on a non-block-aligned boundary). wBitsPerSample.w ; Bits per sample for the wFormatTag format type. If wFormatTag is WAVE_FORMAT_PCM, then wBitsPerSample should be equal to 8 or 16. For non-PCM formats, this member must be set according to the manufacturer's specification of the format tag. If wFormatTag is WAVE_FORMAT_EXTENSIBLE, this value can be any integer multiple of 8. Some compression schemes cannot define a value for wBitsPerSample, so this member can be zero. cbSize.w ; Size, in bytes, of extra format information appended to the end of the WAVEFORMATEX structure. This information can be used by non-PCM formats to store extra attributes for the wFormatTag. If no extra information is required by the wFormatTag, this member must be set to zero. For WAVE_FORMAT_PCM formats (and only WAVE_FORMAT_PCM formats), this member is ignored. EndStructure ; 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 DirectSoundAndInterface Sound.l pDSBPrimary.l RA_DirectSound.l EndStructure ; Procedure Delete(*obj.IUnknown) ProcedureReturn *Obj\Release() EndProcedure ; Procedure Error_Msg(String.s) MessageRequester("Error",String.s,0) End EndProcedure ; Structure bbyte contenu.b EndStructure ; Procedure.s ReadStringlFM(*pointer,Length.l) ; by Zapman ; (Read string Length from memory) ; Lit "Length" caractères en mémoire à partir de "*pointer" et retourne le résultat ; sous forme d'une chaine de caractere ; Read "Length" caracteres from "*pointer" and return the result ; as a string. *bbyte.bbyte = *pointer compt.l=0 s$="" While compt #DD_OK Error_Msg("Can't do DirectSoundCreate8 : " + Str(Result.l)) Else ; ; Set Coop Level Result.l = *RA_DirectSound\SetCooperativeLevel(WindowID(),#DSSCL_NORMAL) ; hwnd is the WindowID If Result.l <> #DD_OK Error_Msg("Can't Set Coop Level : " + Str(Result.l)) Delete(*RA_DirectSound) Else ; ; 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 ? ? ? <- ist ein Pointer ; Result.l = *RA_DirectSound\CreateSoundBuffer(@dsbd,@*pDSBPrimary.IDirectSoundBuffer,0) If Result.l <> #DD_OK Error_Msg("Can't Set up primary sound buffer : " + Str(Result)) Delete(*RA_DirectSound) Else wfx.WAVEFORMATEX ; Wave Format Structure s$ = ReadStringlFM(*mem,4) If s$<>"RIFF" Error_Msg("Unknown format! ('RIFF' not found:"+s$+")") ProcedureReturn 0 EndIf TSize.l=PeekL(*mem+4) PosInFile = 12 s$ = ReadStringlFM((*mem+PosInFile),4) vl.l = PeekL(*mem+PosInFile+4) While s$<>"fmt " And PosInFile < TSize PosInFile + 8 + vl If PosInFile < TSize s$ = ReadStringlFM((*mem+PosInFile),4) vl.l = PeekL(*mem+PosInFile+4) EndIf Wend If s$<>"fmt " Error_Msg("Unknown format! ('fmt ' not found: "+s$+")") ProcedureReturn 0 EndIf PosInFile + 8 CopyMemory(*mem+PosInFile,@wfx,16) PosInFile + vl s$ = ReadStringlFM((*mem+PosInFile),4) vl.l = PeekL(*mem+PosInFile+4) While s$<>"data" And PosInFile < TSize PosInFile + 8 + vl If PosInFile < TSize s$ = ReadStringlFM((*mem+PosInFile),4) vl.l = PeekL(*mem+PosInFile+4) EndIf Wend If s$<>"data" Error_Msg("Unknown format! ('data' not found: "+s$+")") ProcedureReturn 0 EndIf Sound_Frequency = wfx\nSamplesPerSec wfx\cbSize = vl ; ; secondary Buffer (see DSound.h) dsbd\dwFlags = #DSBCAPS_LOCSOFTWARE|#DSBCAPS_CTRLVOLUME|#DSBCAPS_CTRLFREQUENCY|#DSBCAPS_CTRLPAN dsbd\dwBufferBytes = vl;10 * wfx\nAvgBytesPerSec ; alloc 10 Seconds dsbd\lpwfxFormat = @wfx ; ; CREATE Secondary Buffer Result.l = *RA_DirectSound\CreateSoundBuffer(@dsbd,@*pDSB.IDirectSoundBuffer,0) If Result.l <> #DD_OK Error_Msg("Can't Set up secondary sound buffer : " + Str(Result)) Delete(*RA_DirectSound) Delete(*pDSBPrimary) 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") Delete(*RA_DirectSound) Delete(*pDSBPrimary) Else ; If *DSB8\Lock(0,0,@lpvWrite,@dwLength,0,0,#DSBLOCK_ENTIREBUFFER) = #DS_OK CopyMemory(*mem+44,lpvWrite,dwLength) ; ; LOAD SOUND END *DSB8\UnLock(lpvWrite,dwLength,0,0) ; *DSAI.DirectSoundAndInterface = AllocateMemory(SizeOf(DirectSoundAndInterface)) *DSAI\Sound = *DSB8 *DSAI\pDSBPrimary = *pDSBPrimary *DSAI\RA_DirectSound = *RA_DirectSound FResult = *DSAI EndIf EndIf EndIf EndIf EndIf ProcedureReturn FResult EndProcedure ; Procedure LoadFromFileDX8Sound (FileName$) Result = 0 If FileName$ FSize = FileSize(FileName$) If FSize>0 *mem=AllocateMemory(FSize ) If ReadFile(0,FileName$) RSize = ReadData(*mem,FSize) CloseFile(0) If RSize = FSize Result = LoadFromMemDX8Sound (*mem) EndIf FreeMemory(*mem) EndIf EndIf EndIf ProcedureReturn Result EndProcedure ; Procedure PlayDX8Sound (*DX8Sound.DirectSoundAndInterface,mode) If *DX8Sound *Sound.IDirectSoundBuffer8 = *DX8Sound\Sound *Sound\SetCurrentPosition(0) *Sound\Play(0,0,mode) EndIf EndProcedure ; Procedure SetFrequencyDX8Sound (*DX8Sound.DirectSoundAndInterface,Frequ) If *DX8Sound *Sound.IDirectSoundBuffer8 = *DX8Sound\Sound *Sound\SetFrequency(Frequ) EndIf EndProcedure ; Procedure SetPanDX8Sound (*DX8Sound.DirectSoundAndInterface,Pan) If *DX8Sound *Sound.IDirectSoundBuffer8 = *DX8Sound\Sound *Sound\SetPan(Pan) EndIf EndProcedure ; Procedure SetVolumeDX8Sound (*DX8Sound.DirectSoundAndInterface,Volume) If *DX8Sound *Sound.IDirectSoundBuffer8 = *DX8Sound\Sound *Sound\SetVolume(Volume) EndIf EndProcedure ; Procedure StopDX8Sound (*DX8Sound.DirectSoundAndInterface) If *DX8Sound *Sound.IDirectSoundBuffer8 = *DX8Sound\Sound *Sound\Stop () EndIf EndProcedure ; Procedure ReleaseDX8Sound (*DX8Sound.DirectSoundAndInterface) ; Release/Delete Objects ; (reversed order of creation) If *DX8Sound *Sound.IDirectSoundBuffer8 = *DX8Sound\Sound *Sound\Stop () Delete(*DX8Sound\Sound) Delete(*DX8Sound\pDSBPrimary) Delete(*DX8Sound\RA_DirectSound) FreeMemory(*DX8Sound) EndIf EndProcedure ; Procedure Demo() hwnd = OpenWindow(0,0,0,200,200,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"Sound") If hwnd CreateGadgetList(hwnd) TextGadget (1,10,10,180,15,"Frequency: 44100") TrackBarGadget(2,10,25,180,20,0,441) SetGadgetState(2,441) 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) ButtonGadget(7,10,135,180,20,"Play") ButtonGadget(8,10,155,180,20,"Stop") ; If OpenLibrary(0,"DSOUND.DLL") = 0 Error_Msg("Can't open direct Sound DLL") Else FileName$ = OpenFileRequester("","","*.wav",1) DX8Sound = LoadFromFileDX8Sound (FileName$) PlayDX8Sound (DX8Sound,0) ; #DSBPLAY_LOOPING can be used as second parametre If DX8Sound Repeat Select WaitWindowEvent() Case #PB_Event_CloseWindow Quit = 1 Case #PB_Event_Gadget Select EventGadgetID() Case 2 ; Frequency Control Frequ = GetGadgetState(2) SetGadgetText(1,"Frequency: "+Str(Frequ*100)) SetFrequencyDX8Sound (DX8Sound,Frequ*100) Case 4 ; Pan: Left <> Right Pan = GetGadgetState(4)*100-10000 SetGadgetText(3,"Pan: "+Str(Pan)) SetPanDX8Sound (DX8Sound,Pan) Case 6 ; Volume Vol = GetGadgetState(6) SetGadgetText(5,"Volume: "+Str(Vol)) SetVolumeDX8Sound (DX8Sound,Vol-10000) Case 7 ; Play PlayDX8Sound (DX8Sound,0) Case 8 ; Stop StopDX8Sound (DX8Sound) EndSelect EndSelect Until Quit ReleaseDX8Sound (DX8Sound) ReleaseDX8Sound (DX8Sound2) EndIf EndIf EndIf EndProcedure ; Demo() ; End DataSection IID_DirectSoundBuffer8: ; DSOUND.h Data.l $6825A449 Data.w $7524,$4D82 Data.b $92,$0F,$50,$E3,$6A,$B3,$AB,$1E EndDataSection ; ExecutableFormat=Windows ; CursorPosition=3 ; FirstLine=286 ; EnableXP ; EOF