# ---------------------------------------------------------------------------- # pyglet # Copyright (c) 2006-2008 Alex Holkner # Copyright (c) 2008-2021 pyglet contributors # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of pyglet nor the names of its # contributors may be used to endorse or promote products # derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # ---------------------------------------------------------------------------- import ctypes from pyglet import com lib = ctypes.oledll.dsound DWORD = ctypes.c_uint32 LPDWORD = ctypes.POINTER(DWORD) LONG = ctypes.c_long LPLONG = ctypes.POINTER(LONG) WORD = ctypes.c_uint16 HWND = DWORD LPUNKNOWN = ctypes.c_void_p D3DVALUE = ctypes.c_float PD3DVALUE = ctypes.POINTER(D3DVALUE) class D3DVECTOR(ctypes.Structure): _fields_ = [ ('x', ctypes.c_float), ('y', ctypes.c_float), ('z', ctypes.c_float), ] PD3DVECTOR = ctypes.POINTER(D3DVECTOR) class WAVEFORMATEX(ctypes.Structure): _fields_ = [ ('wFormatTag', WORD), ('nChannels', WORD), ('nSamplesPerSec', DWORD), ('nAvgBytesPerSec', DWORD), ('nBlockAlign', WORD), ('wBitsPerSample', WORD), ('cbSize', WORD), ] def __repr__(self): return 'WAVEFORMATEX(wFormatTag={}, nChannels={}, nSamplesPerSec={}, nAvgBytesPersec={}' \ ', nBlockAlign={}, wBitsPerSample={}, cbSize={})'.format( self.wFormatTag, self.nChannels, self.nSamplesPerSec, self.nAvgBytesPerSec, self.nBlockAlign, self.wBitsPerSample, self.cbSize) LPWAVEFORMATEX = ctypes.POINTER(WAVEFORMATEX) WAVE_FORMAT_PCM = 1 class DSCAPS(ctypes.Structure): _fields_ = [ ('dwSize', DWORD), ('dwFlags', DWORD), ('dwMinSecondarySampleRate', DWORD), ('dwMaxSecondarySampleRate', DWORD), ('dwPrimaryBuffers', DWORD), ('dwMaxHwMixingAllBuffers', DWORD), ('dwMaxHwMixingStaticBuffers', DWORD), ('dwMaxHwMixingStreamingBuffers', DWORD), ('dwFreeHwMixingAllBuffers', DWORD), ('dwFreeHwMixingStaticBuffers', DWORD), ('dwFreeHwMixingStreamingBuffers', DWORD), ('dwMaxHw3DAllBuffers', DWORD), ('dwMaxHw3DStaticBuffers', DWORD), ('dwMaxHw3DStreamingBuffers', DWORD), ('dwFreeHw3DAllBuffers', DWORD), ('dwFreeHw3DStaticBuffers', DWORD), ('dwFreeHw3DStreamingBuffers', DWORD), ('dwTotalHwMemBytes', DWORD), ('dwFreeHwMemBytes', DWORD), ('dwMaxContigFreeHwMemBytes', DWORD), ('dwUnlockTransferRateHwBuffers', DWORD), ('dwPlayCpuOverheadSwBuffers', DWORD), ('dwReserved1', DWORD), ('dwReserved2', DWORD) ] LPDSCAPS = ctypes.POINTER(DSCAPS) class DSBCAPS(ctypes.Structure): _fields_ = [ ('dwSize', DWORD), ('dwFlags', DWORD), ('dwBufferBytes', DWORD), ('dwUnlockTransferRate', DWORD), ('dwPlayCpuOverhead', DWORD), ] LPDSBCAPS = ctypes.POINTER(DSBCAPS) class DSBUFFERDESC(ctypes.Structure): _fields_ = [ ('dwSize', DWORD), ('dwFlags', DWORD), ('dwBufferBytes', DWORD), ('dwReserved', DWORD), ('lpwfxFormat', LPWAVEFORMATEX), ] def __repr__(self): return 'DSBUFFERDESC(dwSize={}, dwFlags={}, dwBufferBytes={}, lpwfxFormat={})'.format( self.dwSize, self.dwFlags, self.dwBufferBytes, self.lpwfxFormat.contents if self.lpwfxFormat else None) LPDSBUFFERDESC = ctypes.POINTER(DSBUFFERDESC) class DS3DBUFFER(ctypes.Structure): _fields_ = [ ('dwSize', DWORD), ('vPosition', D3DVECTOR), ('vVelocity', D3DVECTOR), ('dwInsideConeAngle', DWORD), ('dwOutsideConeAngle', DWORD), ('vConeOrientation', D3DVECTOR), ('lConeOutsideVolume', LONG), ('flMinDistance', D3DVALUE), ('flMaxDistance', D3DVALUE), ('dwMode', DWORD), ] LPDS3DBUFFER = ctypes.POINTER(DS3DBUFFER) class DS3DLISTENER(ctypes.Structure): _fields_ = [ ('dwSize', DWORD), ('vPosition', D3DVECTOR), ('vVelocity', D3DVECTOR), ('vOrientFront', D3DVECTOR), ('vOrientTop', D3DVECTOR), ('flDistanceFactor', D3DVALUE), ('flRolloffFactor', D3DVALUE), ('flDopplerFactor', D3DVALUE), ] LPDS3DLISTENER = ctypes.POINTER(DS3DLISTENER) class IDirectSoundBuffer(com.pIUnknown): _methods_ = [ ('GetCaps', com.STDMETHOD(LPDSBCAPS)), ('GetCurrentPosition', com.STDMETHOD(LPDWORD, LPDWORD)), ('GetFormat', com.STDMETHOD(LPWAVEFORMATEX, DWORD, LPDWORD)), ('GetVolume', com.STDMETHOD(LPLONG)), ('GetPan', com.STDMETHOD(LPLONG)), ('GetFrequency', com.STDMETHOD(LPDWORD)), ('GetStatus', com.STDMETHOD(LPDWORD)), ('Initialize', com.STDMETHOD(ctypes.c_void_p, LPDSBUFFERDESC)), ('Lock', com.STDMETHOD(DWORD, DWORD, ctypes.POINTER(ctypes.c_void_p), LPDWORD, ctypes.POINTER(ctypes.c_void_p), LPDWORD, DWORD)), ('Play', com.STDMETHOD(DWORD, DWORD, DWORD)), ('SetCurrentPosition', com.STDMETHOD(DWORD)), ('SetFormat', com.STDMETHOD(LPWAVEFORMATEX)), ('SetVolume', com.STDMETHOD(LONG)), ('SetPan', com.STDMETHOD(LONG)), ('SetFrequency', com.STDMETHOD(DWORD)), ('Stop', com.STDMETHOD()), ('Unlock', com.STDMETHOD(ctypes.c_void_p, DWORD, ctypes.c_void_p, DWORD)), ('Restore', com.STDMETHOD()), ] IID_IDirectSound3DListener = com.GUID( 0x279AFA84, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60) class IDirectSound3DListener(com.pIUnknown): _methods_ = [ ('GetAllParameters', com.STDMETHOD(LPDS3DLISTENER)), ('GetDistanceFactor', com.STDMETHOD(PD3DVALUE)), ('GetDopplerFactor', com.STDMETHOD(PD3DVALUE)), ('GetOrientation', com.STDMETHOD(PD3DVECTOR, PD3DVECTOR)), ('GetPosition', com.STDMETHOD(PD3DVECTOR)), ('GetRolloffFactor', com.STDMETHOD(PD3DVALUE)), ('GetVelocity', com.STDMETHOD(PD3DVECTOR)), ('SetAllParameters', com.STDMETHOD(LPDS3DLISTENER)), ('SetDistanceFactor', com.STDMETHOD(D3DVALUE, DWORD)), ('SetDopplerFactor', com.STDMETHOD(D3DVALUE, DWORD)), ('SetOrientation', com.STDMETHOD(D3DVALUE, D3DVALUE, D3DVALUE, D3DVALUE, D3DVALUE, D3DVALUE, DWORD)), ('SetPosition', com.STDMETHOD(D3DVALUE, D3DVALUE, D3DVALUE, DWORD)), ('SetRolloffFactor', com.STDMETHOD(D3DVALUE, DWORD)), ('SetVelocity', com.STDMETHOD(D3DVALUE, D3DVALUE, D3DVALUE, DWORD)), ('CommitDeferredSettings', com.STDMETHOD()), ] IID_IDirectSound3DBuffer = com.GUID( 0x279AFA86, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60) class IDirectSound3DBuffer(com.pIUnknown): _methods_ = [ ('GetAllParameters', com.STDMETHOD(LPDS3DBUFFER)), ('GetConeAngles', com.STDMETHOD(LPDWORD, LPDWORD)), ('GetConeOrientation', com.STDMETHOD(PD3DVECTOR)), ('GetConeOutsideVolume', com.STDMETHOD(LPLONG)), ('GetMaxDistance', com.STDMETHOD(PD3DVALUE)), ('GetMinDistance', com.STDMETHOD(PD3DVALUE)), ('GetMode', com.STDMETHOD(LPDWORD)), ('GetPosition', com.STDMETHOD(PD3DVECTOR)), ('GetVelocity', com.STDMETHOD(PD3DVECTOR)), ('SetAllParameters', com.STDMETHOD(LPDS3DBUFFER, DWORD)), ('SetConeAngles', com.STDMETHOD(DWORD, DWORD, DWORD)), ('SetConeOrientation', com.STDMETHOD(D3DVALUE, D3DVALUE, D3DVALUE, DWORD)), ('SetConeOutsideVolume', com.STDMETHOD(LONG, DWORD)), ('SetMaxDistance', com.STDMETHOD(D3DVALUE, DWORD)), ('SetMinDistance', com.STDMETHOD(D3DVALUE, DWORD)), ('SetMode', com.STDMETHOD(DWORD, DWORD)), ('SetPosition', com.STDMETHOD(D3DVALUE, D3DVALUE, D3DVALUE, DWORD)), ('SetVelocity', com.STDMETHOD(D3DVALUE, D3DVALUE, D3DVALUE, DWORD)), ] class IDirectSound(com.pIUnknown): _methods_ = [ ('CreateSoundBuffer', com.STDMETHOD(LPDSBUFFERDESC, ctypes.POINTER(IDirectSoundBuffer), LPUNKNOWN)), ('GetCaps', com.STDMETHOD(LPDSCAPS)), ('DuplicateSoundBuffer', com.STDMETHOD(IDirectSoundBuffer, ctypes.POINTER(IDirectSoundBuffer))), ('SetCooperativeLevel', com.STDMETHOD(HWND, DWORD)), ('Compact', com.STDMETHOD()), ('GetSpeakerConfig', com.STDMETHOD(LPDWORD)), ('SetSpeakerConfig', com.STDMETHOD(DWORD)), ('Initialize', com.STDMETHOD(com.LPGUID)), ] _type_ = com.COMInterface DirectSoundCreate = lib.DirectSoundCreate DirectSoundCreate.argtypes = \ [com.LPGUID, ctypes.POINTER(IDirectSound), ctypes.c_void_p] DSCAPS_PRIMARYMONO = 0x00000001 DSCAPS_PRIMARYSTEREO = 0x00000002 DSCAPS_PRIMARY8BIT = 0x00000004 DSCAPS_PRIMARY16BIT = 0x00000008 DSCAPS_CONTINUOUSRATE = 0x00000010 DSCAPS_EMULDRIVER = 0x00000020 DSCAPS_CERTIFIED = 0x00000040 DSCAPS_SECONDARYMONO = 0x00000100 DSCAPS_SECONDARYSTEREO = 0x00000200 DSCAPS_SECONDARY8BIT = 0x00000400 DSCAPS_SECONDARY16BIT = 0x00000800 DSSCL_NORMAL = 0x00000001 DSSCL_PRIORITY = 0x00000002 DSSCL_EXCLUSIVE = 0x00000003 DSSCL_WRITEPRIMARY = 0x00000004 DSSPEAKER_DIRECTOUT = 0x00000000 DSSPEAKER_HEADPHONE = 0x00000001 DSSPEAKER_MONO = 0x00000002 DSSPEAKER_QUAD = 0x00000003 DSSPEAKER_STEREO = 0x00000004 DSSPEAKER_SURROUND = 0x00000005 DSSPEAKER_5POINT1 = 0x00000006 DSSPEAKER_7POINT1 = 0x00000007 DSSPEAKER_GEOMETRY_MIN = 0x00000005 # 5 degrees DSSPEAKER_GEOMETRY_NARROW = 0x0000000A # 10 degrees DSSPEAKER_GEOMETRY_WIDE = 0x00000014 # 20 degrees DSSPEAKER_GEOMETRY_MAX = 0x000000B4 # 180 degrees DSBCAPS_PRIMARYBUFFER = 0x00000001 DSBCAPS_STATIC = 0x00000002 DSBCAPS_LOCHARDWARE = 0x00000004 DSBCAPS_LOCSOFTWARE = 0x00000008 DSBCAPS_CTRL3D = 0x00000010 DSBCAPS_CTRLFREQUENCY = 0x00000020 DSBCAPS_CTRLPAN = 0x00000040 DSBCAPS_CTRLVOLUME = 0x00000080 DSBCAPS_CTRLPOSITIONNOTIFY = 0x00000100 DSBCAPS_CTRLFX = 0x00000200 DSBCAPS_STICKYFOCUS = 0x00004000 DSBCAPS_GLOBALFOCUS = 0x00008000 DSBCAPS_GETCURRENTPOSITION2 = 0x00010000 DSBCAPS_MUTE3DATMAXDISTANCE = 0x00020000 DSBCAPS_LOCDEFER = 0x00040000 DSBPLAY_LOOPING = 0x00000001 DSBPLAY_LOCHARDWARE = 0x00000002 DSBPLAY_LOCSOFTWARE = 0x00000004 DSBPLAY_TERMINATEBY_TIME = 0x00000008 DSBPLAY_TERMINATEBY_DISTANCE = 0x000000010 DSBPLAY_TERMINATEBY_PRIORITY = 0x000000020 DSBSTATUS_PLAYING = 0x00000001 DSBSTATUS_BUFFERLOST = 0x00000002 DSBSTATUS_LOOPING = 0x00000004 DSBSTATUS_LOCHARDWARE = 0x00000008 DSBSTATUS_LOCSOFTWARE = 0x00000010 DSBSTATUS_TERMINATED = 0x00000020 DSBLOCK_FROMWRITECURSOR = 0x00000001 DSBLOCK_ENTIREBUFFER = 0x00000002 DSBFREQUENCY_MIN = 100 DSBFREQUENCY_MAX = 100000 DSBFREQUENCY_ORIGINAL = 0 DSBPAN_LEFT = -10000 DSBPAN_CENTER = 0 DSBPAN_RIGHT = 10000 DSBVOLUME_MIN = -10000 DSBVOLUME_MAX = 0 DSBSIZE_MIN = 4 DSBSIZE_MAX = 0x0FFFFFFF DSBSIZE_FX_MIN = 150 # NOTE: Milliseconds, not bytes DS3DMODE_NORMAL = 0x00000000 DS3DMODE_HEADRELATIVE = 0x00000001 DS3DMODE_DISABLE = 0x00000002 DS3D_IMMEDIATE = 0x00000000 DS3D_DEFERRED = 0x00000001 DS3D_MINDISTANCEFACTOR = -1000000.0 # XXX FLT_MIN DS3D_MAXDISTANCEFACTOR = 1000000.0 # XXX FLT_MAX DS3D_DEFAULTDISTANCEFACTOR = 1.0 DS3D_MINROLLOFFFACTOR = 0.0 DS3D_MAXROLLOFFFACTOR = 10.0 DS3D_DEFAULTROLLOFFFACTOR = 1.0 DS3D_MINDOPPLERFACTOR = 0.0 DS3D_MAXDOPPLERFACTOR = 10.0 DS3D_DEFAULTDOPPLERFACTOR = 1.0 DS3D_DEFAULTMINDISTANCE = 1.0 DS3D_DEFAULTMAXDISTANCE = 1000000000.0 DS3D_MINCONEANGLE = 0 DS3D_MAXCONEANGLE = 360 DS3D_DEFAULTCONEANGLE = 360 DS3D_DEFAULTCONEOUTSIDEVOLUME = DSBVOLUME_MAX # Return codes DS_OK = 0x00000000 DSERR_OUTOFMEMORY = 0x00000007 DSERR_NOINTERFACE = 0x000001AE DS_NO_VIRTUALIZATION = 0x0878000A DS_INCOMPLETE = 0x08780014 DSERR_UNSUPPORTED = 0x80004001 DSERR_GENERIC = 0x80004005 DSERR_ACCESSDENIED = 0x80070005 DSERR_INVALIDPARAM = 0x80070057 DSERR_ALLOCATED = 0x8878000A DSERR_CONTROLUNAVAIL = 0x8878001E DSERR_INVALIDCALL = 0x88780032 DSERR_PRIOLEVELNEEDED = 0x88780046 DSERR_BADFORMAT = 0x88780064 DSERR_NODRIVER = 0x88780078 DSERR_ALREADYINITIALIZED = 0x88780082 DSERR_BUFFERLOST = 0x88780096 DSERR_OTHERAPPHASPRIO = 0x887800A0 DSERR_UNINITALIZED = 0x887800AA DSERR_BUFFERTOOSMALL = 0x887810B4 DSERR_DS8_REQUIRED = 0x887810BE DSERR_SENDLOOP = 0x887810C8 DSERR_BADSENDBUFFERGUID = 0x887810D2 DSERR_FXUNAVAILABLE = 0x887810DC DSERR_OBJECTNOTFOUND = 0x88781161 # Buffer status DSBSTATUS_PLAYING = 0x00000001 DSBSTATUS_BUFFERLOST = 0x00000002 DSBSTATUS_LOOPING = 0x00000004