import ctypes import platform import os from pyglet.libs.win32.constants import * from pyglet.libs.win32.types import * from pyglet import com from pyglet.util import debug_print _debug = debug_print('debug_media') def load_xaudio2(dll_name): """This will attempt to load a version of XAudio2. Versions supported: 2.9, 2.8. While Windows 8 ships with 2.8 and Windows 10 ships with version 2.9, it is possible to install 2.9 on 8/8.1. """ xaudio2 = dll_name # System32 and SysWOW64 folders are opposite perception in Windows x64. # System32 = x64 dll's | SysWOW64 = x86 dlls # By default ctypes only seems to look in system32 regardless of Python architecture, which has x64 dlls. if platform.architecture()[0] == '32bit': if platform.machine().endswith('64'): # Machine is 64 bit, Python is 32 bit. xaudio2 = os.path.join(os.environ['WINDIR'], 'SysWOW64', '{}.dll'.format(xaudio2)) xaudio2_lib = ctypes.windll.LoadLibrary(xaudio2) # Somehow x3d uses different calling structure than the rest of the DLL; Only affects 32 bit? Microsoft... x3d_lib = ctypes.cdll.LoadLibrary(xaudio2) return xaudio2_lib, x3d_lib try: xaudio2_lib, x3d_lib = load_xaudio2("xaudio2_9") except OSError: _debug("Could not load XAudio2.9 library") try: xaudio2_lib, x3d_lib = load_xaudio2("xaudio2_8") except OSError: _debug("Could not load XAudio2.8 library") raise ImportError('Could not locate a supported XAudio2 library.') UINT32 = c_uint32 FLOAT32 = c_float class XAUDIO2_DEBUG_CONFIGURATION(ctypes.Structure): _fields_ = [ ('TraceMask', UINT32), ('BreakMask', UINT32), ('LogThreadID', BOOL), ('LogFileline', BOOL), ('LogFunctionName', BOOL), ('LogTiming', BOOL), ] class XAUDIO2_PERFORMANCE_DATA(ctypes.Structure): _fields_ = [ ('AudioCyclesSinceLastQuery', c_uint64), ('TotalCyclesSinceLastQuery', c_uint64), ('MinimumCyclesPerQuantum', UINT32), ('MaximumCyclesPerQuantum', UINT32), ('MemoryUsageInBytes', UINT32), ('CurrentLatencyInSamples', UINT32), ('GlitchesSinceEngineStarted', UINT32), ('ActiveSourceVoiceCount', UINT32), ('TotalSourceVoiceCount', UINT32), ('ActiveSubmixVoiceCount', UINT32), ('ActiveResamplerCount', UINT32), ('ActiveMatrixMixCount', UINT32), ('ActiveXmaSourceVoices', UINT32), ('ActiveXmaStreams', UINT32), ] def __repr__(self): return "XAUDIO2PerformanceData(active_voices={}, total_voices={}, glitches={}, latency={} samples, memory_usage={} bytes)".format(self.ActiveSourceVoiceCount, self.TotalSourceVoiceCount, self.GlitchesSinceEngineStarted, self.CurrentLatencyInSamples, self.MemoryUsageInBytes) class XAUDIO2_VOICE_SENDS(ctypes.Structure): _fields_ = [ ('SendCount', UINT32), ('pSends', c_void_p), ] class XAUDIO2_BUFFER(ctypes.Structure): _fields_ = [ ('Flags', UINT32), ('AudioBytes', UINT32), ('pAudioData', POINTER(c_char)), ('PlayBegin', UINT32), ('PlayLength', UINT32), ('LoopBegin', UINT32), ('LoopLength', UINT32), ('LoopCount', UINT32), ('pContext', c_void_p), ] class XAUDIO2_VOICE_STATE(ctypes.Structure): _fields_ = [ ('pCurrentBufferContext', c_void_p), ('BuffersQueued', UINT32), ('SamplesPlayed', UINT32) ] def __repr__(self): return "XAUDIO2_VOICE_STATE(BuffersQueued={0}, SamplesPlayed={1})".format(self.BuffersQueued, self.SamplesPlayed) 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) XAUDIO2_USE_DEFAULT_PROCESSOR = 0x00000000 # Win 10+ if WINDOWS_10_ANNIVERSARY_UPDATE_OR_GREATER: XAUDIO2_DEFAULT_PROCESSOR = XAUDIO2_USE_DEFAULT_PROCESSOR else: XAUDIO2_DEFAULT_PROCESSOR = 0x00000001 # Windows 8/8.1 XAUDIO2_LOG_ERRORS = 0x0001 # For handled errors with serious effects. XAUDIO2_LOG_WARNINGS = 0x0002 # For handled errors that may be recoverable. XAUDIO2_LOG_INFO = 0x0004 # Informational chit-chat (e.g. state changes). XAUDIO2_LOG_DETAIL = 0x0008 # More detailed chit-chat. XAUDIO2_LOG_API_CALLS = 0x0010 # Public API function entries and exits. XAUDIO2_LOG_FUNC_CALLS = 0x0020 # Internal function entries and exits. XAUDIO2_LOG_TIMING = 0x0040 # Delays detected and other timing data. XAUDIO2_LOG_LOCKS = 0x0080 # Usage of critical sections and mutexes. XAUDIO2_LOG_MEMORY = 0x0100 # Memory heap usage information. XAUDIO2_LOG_STREAMING = 0x1000 # Audio streaming information. # Some XAUDIO2 global settings, most not used, but useful information XAUDIO2_MAX_BUFFER_BYTES = 0x80000000 # Maximum bytes allowed in a source buffer XAUDIO2_MAX_QUEUED_BUFFERS = 64 # Maximum buffers allowed in a voice queue XAUDIO2_MAX_BUFFERS_SYSTEM = 2 # Maximum buffers allowed for system threads (Xbox 360 only) XAUDIO2_MAX_AUDIO_CHANNELS = 64 # Maximum channels in an audio stream XAUDIO2_MIN_SAMPLE_RATE = 1000 # Minimum audio sample rate supported XAUDIO2_MAX_SAMPLE_RATE = 200000 # Maximum audio sample rate supported XAUDIO2_MAX_VOLUME_LEVEL = 16777216.0 # Maximum acceptable volume level (2^24) XAUDIO2_MIN_FREQ_RATIO = (1/1024.0) # Minimum SetFrequencyRatio argument XAUDIO2_MAX_FREQ_RATIO = 1024.0 # Maximum MaxFrequencyRatio argument XAUDIO2_DEFAULT_FREQ_RATIO = 2.0 # Default MaxFrequencyRatio argument XAUDIO2_MAX_FILTER_ONEOVERQ = 1.5 # Maximum XAUDIO2_FILTER_PARAMETERS.OneOverQ XAUDIO2_MAX_FILTER_FREQUENCY = 1.0 # Maximum XAUDIO2_FILTER_PARAMETERS.Frequency XAUDIO2_MAX_LOOP_COUNT = 254 # Maximum non-infinite XAUDIO2_BUFFER.LoopCount XAUDIO2_MAX_INSTANCES = 8 # Maximum simultaneous XAudio2 objects on Xbox 360 XAUDIO2_FILTER_TYPE = UINT LowPassFilter = 0 # Attenuates frequencies above the cutoff frequency (state-variable filter). BandPassFilter = 1 # Attenuates frequencies outside a given range (state-variable filter). HighPassFilter = 2 # Attenuates frequencies below the cutoff frequency (state-variable filter). NotchFilter = 3 # Attenuates frequencies inside a given range (state-variable filter). LowPassOnePoleFilter = 4 # Attenuates frequencies above the cutoff frequency (one-pole filter, XAUDIO2_FILTER_PARAMETERS.OneOverQ has no effect) HighPassOnePoleFilter = 5 # Attenuates frequencies below the cutoff frequency (one-pole filter, XAUDIO2_FILTER_PARAMETERS.OneOverQ has no effect) XAUDIO2_NO_LOOP_REGION = 0 # Used in XAUDIO2_BUFFER.LoopCount XAUDIO2_LOOP_INFINITE = 255 # Used in XAUDIO2_BUFFER.LoopCount XAUDIO2_DEFAULT_CHANNELS = 0 # Used in CreateMasteringVoice XAUDIO2_DEFAULT_SAMPLERATE = 0 # Used in CreateMasteringVoice WAVE_FORMAT_PCM = 1 XAUDIO2_DEBUG_ENGINE = 0x0001 # Used in XAudio2Create XAUDIO2_VOICE_NOPITCH = 0x0002 # Used in IXAudio2::CreateSourceVoice XAUDIO2_VOICE_NOSRC = 0x0004 # Used in IXAudio2::CreateSourceVoice XAUDIO2_VOICE_USEFILTER = 0x0008 # Used in IXAudio2::CreateSource/SubmixVoice XAUDIO2_PLAY_TAILS = 0x0020 # Used in IXAudio2SourceVoice::Stop XAUDIO2_END_OF_STREAM = 0x0040 # Used in XAUDIO2_BUFFER.Flags XAUDIO2_SEND_USEFILTER = 0x0080 # Used in XAUDIO2_SEND_DESCRIPTOR.Flags XAUDIO2_VOICE_NOSAMPLESPLAYED = 0x0100 # Used in IXAudio2SourceVoice::GetState XAUDIO2_STOP_ENGINE_WHEN_IDLE = 0x2000 # Used in XAudio2Create to force the engine to Stop when no source voices are Started, and Start when a voice is Started XAUDIO2_1024_QUANTUM = 0x8000 # Used in XAudio2Create to specify nondefault processing quantum of 21.33 ms (1024 samples at 48KHz) XAUDIO2_NO_VIRTUAL_AUDIO_CLIENT = 0x10000 # Used in CreateMasteringVoice to create a virtual audio client class IXAudio2VoiceCallback(com.Interface): _methods_ = [ ('OnVoiceProcessingPassStart', com.STDMETHOD(UINT32)), ('OnVoiceProcessingPassEnd', com.STDMETHOD()), ('onStreamEnd', com.STDMETHOD()), ('onBufferStart', com.STDMETHOD(ctypes.c_void_p)), ('OnBufferEnd', com.STDMETHOD(ctypes.c_void_p)), ('OnLoopEnd', com.STDMETHOD(ctypes.c_void_p)), ] class XA2SourceCallback(com.COMObject): """Callback class used to trigger when buffers or streams end.. WARNING: Whenever a callback is running, XAudio2 cannot generate audio. Make sure these functions run as fast as possible and do not block/delay more than a few milliseconds. MS Recommendation: At a minimum, callback functions must not do the following: - Access the hard disk or other permanent storage - Make expensive or blocking API calls - Synchronize with other parts of client code - Require significant CPU usage """ _interfaces_ = [IXAudio2VoiceCallback] def __init__(self, xa2_player): self.xa2_player = xa2_player def OnVoiceProcessingPassStart(self, bytesRequired): pass def OnVoiceProcessingPassEnd(self): pass def onStreamEnd(self): pass def onBufferStart(self, pBufferContext): pass def OnBufferEnd(self, pBufferContext): """At the end of playing one buffer, attempt to refill again. Even if the player is out of sources, it needs to be called to purge all buffers. """ if self.xa2_player: self.xa2_player.refill_source_player() def OnLoopEnd(self, this, pBufferContext): pass def onVoiceError(self, this, pBufferContext, hresult): raise Exception("Error occurred during audio playback.", hresult) class XAUDIO2_EFFECT_DESCRIPTOR(Structure): _fields_ = [ ('pEffect', com.pIUnknown), ('InitialState', c_bool), ('OutputChannels', UINT32) ] class XAUDIO2_EFFECT_CHAIN(ctypes.Structure): _fields_ = [ ('EffectCount', UINT32), ('pEffectDescriptors', POINTER(XAUDIO2_EFFECT_DESCRIPTOR)), ] class XAUDIO2_FILTER_PARAMETERS(Structure): _fields_ = [ ('Type', XAUDIO2_FILTER_TYPE), ('Frequency', FLOAT), ('OneOverQ', FLOAT) ] class XAUDIO2_VOICE_DETAILS(Structure): _fields_ = [ ('CreationFlags', UINT32), ('ActiveFlags', UINT32), ('InputChannels', UINT32), ('InputSampleRate', UINT32) ] class IXAudio2Voice(com.pInterface): _methods_ = [ ('GetVoiceDetails', com.STDMETHOD(POINTER(XAUDIO2_VOICE_DETAILS))), ('SetOutputVoices', com.STDMETHOD()), ('SetEffectChain', com.STDMETHOD(POINTER(XAUDIO2_EFFECT_CHAIN))), ('EnableEffect', com.STDMETHOD()), ('DisableEffect', com.STDMETHOD()), ('GetEffectState', com.STDMETHOD()), ('SetEffectParameters', com.STDMETHOD()), ('GetEffectParameters', com.STDMETHOD()), ('SetFilterParameters', com.STDMETHOD(POINTER(XAUDIO2_FILTER_PARAMETERS), UINT32)), ('GetFilterParameters', com.STDMETHOD()), ('SetOutputFilterParameters', com.STDMETHOD()), ('GetOutputFilterParameters', com.STDMETHOD()), ('SetVolume', com.STDMETHOD(ctypes.c_float, UINT32)), ('GetVolume', com.STDMETHOD(POINTER(c_float))), ('SetChannelVolumes', com.STDMETHOD()), ('GetChannelVolumes', com.STDMETHOD()), ('SetOutputMatrix', com.STDMETHOD(c_void_p, UINT32, UINT32, POINTER(FLOAT), UINT32)), ('GetOutputMatrix', com.STDMETHOD()), ('DestroyVoice', com.STDMETHOD()) ] class IXAudio2SubmixVoice(IXAudio2Voice): pass class IXAudio2SourceVoice(IXAudio2Voice): _methods_ = [ ('Start', com.STDMETHOD(UINT32, UINT32)), ('Stop', com.STDMETHOD(UINT32, UINT32)), ('SubmitSourceBuffer', com.STDMETHOD(POINTER(XAUDIO2_BUFFER), c_void_p)), ('FlushSourceBuffers', com.STDMETHOD()), ('Discontinuity', com.STDMETHOD()), ('ExitLoop', com.STDMETHOD()), ('GetState', com.STDMETHOD(POINTER(XAUDIO2_VOICE_STATE), UINT32)), ('SetFrequencyRatio', com.STDMETHOD(FLOAT, UINT32)), ('GetFrequencyRatio', com.STDMETHOD(POINTER(c_float))), ('SetSourceSampleRate', com.STDMETHOD()), ] class IXAudio2MasteringVoice(IXAudio2Voice): _methods_ = [ ('GetChannelMask', com.STDMETHOD(POINTER(DWORD))) ] class IXAudio2EngineCallback(com.Interface): _methods_ = [ ('OnProcessingPassStart', com.METHOD(ctypes.c_void_p)), ('OnProcessingPassEnd', com.METHOD(ctypes.c_void_p)), ('OnCriticalError', com.METHOD(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_ulong)), ] class XA2EngineCallback(com.COMObject): _interfaces_ = [IXAudio2EngineCallback] def OnProcessingPassStart(self): pass def OnProcessingPassEnd(self): pass def OnCriticalError(self, this, hresult): raise Exception("Critical Error:", hresult) # -------------- 3D Audio Positioning---------- class X3DAUDIO_DISTANCE_CURVE_POINT(ctypes.Structure): _fields_ = [ ('Distance', FLOAT32), ('DSPSetting', FLOAT32) ] class X3DAUDIO_DISTANCE_CURVE(ctypes.Structure): _fields_ = [ ('pPoints', POINTER(X3DAUDIO_DISTANCE_CURVE_POINT)), ('PointCount', UINT32) ] class X3DAUDIO_VECTOR(ctypes.Structure): _fields_ = [ ('x', c_float), ('y', c_float), ('z', c_float), ] """Cone: Specifies directionality for a listener or single-channel emitter by modifying DSP behaviour with respect to its front orientation. This is modeled using two sound cones: an inner cone and an outer cone. On/within the inner cone, DSP settings are scaled by the inner values. On/beyond the outer cone, DSP settings are scaled by the outer values. If on both the cones, DSP settings are scaled by the inner values only. Between the two cones, the scaler is linearly interpolated between the inner and outer values. Set both cone angles to 0 or X3DAUDIO_2PI for omnidirectionality using only the outer or inner values respectively.""" class X3DAUDIO_CONE(Structure): _fields_ = [ ('InnerAngle', FLOAT32), # inner cone angle in radians, must be within [0.0f, X3DAUDIO_2PI] ('OuterAngle', FLOAT32), # outer cone angle in radians, must be within [InnerAngle, X3DAUDIO_2PI] ('InnerVolume', FLOAT32), # volume level scaler on/within inner cone, used only for matrix calculations, must be within [0.0f, 2.0f] when used ('OuterVolume', FLOAT32), # volume level scaler on/beyond outer cone, used only for matrix calculations, must be within [0.0f, 2.0f] when used ('InnerLPF', FLOAT32), # LPF (both direct and reverb paths) coefficient subtrahend on/within inner cone, used only for LPF (both direct and reverb paths) calculations, must be within [0.0f, 1.0f] when used ('OuterLPF', FLOAT32), # LPF (both direct and reverb paths) coefficient subtrahend on/beyond outer cone, used only for LPF (both direct and reverb paths) calculations, must be within [0.0f, 1.0f] when used ('InnerReverb', FLOAT32), # reverb send level scaler on/within inner cone, used only for reverb calculations, must be within [0.0f, 2.0f] when used ('OuterReverb', FLOAT32) # reverb send level scaler on/beyond outer cone, used only for reverb calculations, must be within [0.0f, 2.0f] when used ] class X3DAUDIO_LISTENER(Structure): _fields_ = [ ('OrientFront', X3DAUDIO_VECTOR), # orientation of front direction, used only for matrix and delay calculations or listeners with cones for matrix, LPF (both direct and reverb paths), and reverb calculations, must be normalized when used ('OrientTop', X3DAUDIO_VECTOR), # orientation of top direction, used only for matrix and delay calculations, must be orthonormal with OrientFront when used ('Position', X3DAUDIO_VECTOR), # position in user-defined world units, does not affect Velocity ('Velocity', X3DAUDIO_VECTOR), # velocity vector in user-defined world units/second, used only for doppler calculations, does not affect Position ('pCone', POINTER(X3DAUDIO_CONE)) # sound cone, used only for matrix, LPF (both direct and reverb paths), and reverb calculations, NULL specifies omnidirectionality ] class X3DAUDIO_EMITTER(Structure): _fields_ = [ ('pCone', POINTER(X3DAUDIO_CONE)), ('OrientFront', X3DAUDIO_VECTOR), ('OrientTop', X3DAUDIO_VECTOR), ('Position', X3DAUDIO_VECTOR), ('Velocity', X3DAUDIO_VECTOR), ('InnerRadius', FLOAT32), ('InnerRadiusAngle', FLOAT32), ('ChannelCount', UINT32), ('ChannelRadius', FLOAT32), ('pChannelAzimuths', POINTER(FLOAT32)), ('pVolumeCurve', POINTER(X3DAUDIO_DISTANCE_CURVE)), ('pLFECurve', POINTER(X3DAUDIO_DISTANCE_CURVE)), ('pLPFDirectCurve', POINTER(X3DAUDIO_DISTANCE_CURVE)), ('pLPFReverbCurve', POINTER(X3DAUDIO_DISTANCE_CURVE)), ('pReverbCurve', POINTER(X3DAUDIO_DISTANCE_CURVE)), ('CurveDistanceScaler', FLOAT32), ('DopplerScaler', FLOAT32) ] class X3DAUDIO_DSP_SETTINGS(Structure): _fields_ = [ ('pMatrixCoefficients', POINTER(FLOAT)), # float array ('pDelayTimes', POINTER(FLOAT32)), ('SrcChannelCount', UINT32), ('DstChannelCount', UINT32), ('LPFDirectCoefficient', FLOAT32), ('LPFReverbCoefficient', FLOAT32), ('ReverbLevel', FLOAT32), ('DopplerFactor', FLOAT32), ('EmitterToListenerAngle', FLOAT32), ('EmitterToListenerDistance', FLOAT32), ('EmitterVelocityComponent', FLOAT32), ('ListenerVelocityComponent', FLOAT32) ] # Other constants that may or may not be used in X3D. SPEAKER_FRONT_LEFT = 0x00000001 SPEAKER_FRONT_RIGHT = 0x00000002 SPEAKER_FRONT_CENTER = 0x00000004 SPEAKER_LOW_FREQUENCY = 0x00000008 SPEAKER_BACK_LEFT = 0x00000010 SPEAKER_BACK_RIGHT = 0x00000020 SPEAKER_FRONT_LEFT_OF_CENTER = 0x00000040 SPEAKER_FRONT_RIGHT_OF_CENTER = 0x00000080 SPEAKER_BACK_CENTER = 0x00000100 SPEAKER_SIDE_LEFT = 0x00000200 SPEAKER_SIDE_RIGHT = 0x00000400 SPEAKER_TOP_CENTER = 0x00000800 SPEAKER_TOP_FRONT_LEFT = 0x00001000 SPEAKER_TOP_FRONT_CENTER = 0x00002000 SPEAKER_TOP_FRONT_RIGHT = 0x00004000 SPEAKER_TOP_BACK_LEFT = 0x00008000 SPEAKER_TOP_BACK_CENTER = 0x00010000 SPEAKER_TOP_BACK_RIGHT = 0x00020000 SPEAKER_RESERVED = 0x7FFC0000 # bit mask locations reserved for future use SPEAKER_ALL = 0x80000000 # used to specify that any possible permutation of speaker configurations SPEAKER_MONO = SPEAKER_FRONT_CENTER SPEAKER_STEREO = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT) SPEAKER_2POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY) SPEAKER_SURROUND = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER) SPEAKER_QUAD = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT) SPEAKER_4POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT) SPEAKER_5POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT) SPEAKER_7POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER) SPEAKER_5POINT1_SURROUND = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT) SPEAKER_7POINT1_SURROUND = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT) DBL_DECIMAL_DIG = 17 # # of decimal digits of rounding precision DBL_DIG = 15 # # of decimal digits of precision DBL_EPSILON = 2.2204460492503131e-016 # smallest such that 1.0+DBL_EPSILON != 1.0 DBL_HAS_SUBNORM = 1 # type does support subnormal numbers DBL_MANT_DIG = 53 # # of bits in mantissa DBL_MAX = 1.7976931348623158e+308 # max value DBL_MAX_10_EXP = 308 # max decimal exponent DBL_MAX_EXP = 1024 # max binary exponent DBL_MIN = 2.2250738585072014e-308 # min positive value DBL_MIN_10_EXP = (-307) # min decimal exponent DBL_MIN_EXP = (-1021) # min binary exponent _DBL_RADIX = 2 # exponent radix DBL_TRUE_MIN = 4.9406564584124654e-324 # min positive value FLT_DECIMAL_DIG = 9 # # of decimal digits of rounding precision FLT_DIG = 6 # # of decimal digits of precision FLT_EPSILON = 1.192092896e-07 # smallest such that 1.0+FLT_EPSILON != 1.0 FLT_HAS_SUBNORM = 1 # type does support subnormal numbers FLT_GUARD = 0 FLT_MANT_DIG = 24 # # of bits in mantissa FLT_MAX = 3.402823466e+38 # max value FLT_MAX_10_EXP = 38 # max decimal exponent FLT_MAX_EXP = 128 # max binary exponent FLT_MIN = 1.175494351e-38 # min normalized positive value FLT_MIN_10_EXP = (-37) # min decimal exponent FLT_MIN_EXP = (-125) # min binary exponent FLT_NORMALIZE = 0 FLT_RADIX = 2 # exponent radix FLT_TRUE_MIN = 1.401298464e-45 # min positive value LDBL_DIG = DBL_DIG # # of decimal digits of precision LDBL_EPSILON = DBL_EPSILON # smallest such that 1.0+LDBL_EPSILON != 1.0 LDBL_HAS_SUBNORM = DBL_HAS_SUBNORM # type does support subnormal numbers LDBL_MANT_DIG = DBL_MANT_DIG # # of bits in mantissa LDBL_MAX = DBL_MAX # max value LDBL_MAX_10_EXP = DBL_MAX_10_EXP # max decimal exponent LDBL_MAX_EXP = DBL_MAX_EXP # max binary exponent LDBL_MIN = DBL_MIN # min normalized positive value LDBL_MIN_10_EXP = DBL_MIN_10_EXP # min decimal exponent LDBL_MIN_EXP = DBL_MIN_EXP # min binary exponent _LDBL_RADIX = _DBL_RADIX # exponent radix LDBL_TRUE_MIN = DBL_TRUE_MIN # min positive value DECIMAL_DIG = DBL_DECIMAL_DIG X3DAUDIO_HANDLE_BYTESIZE = 20 X3DAUDIO_HANDLE = (BYTE * X3DAUDIO_HANDLE_BYTESIZE) # speed of sound in meters per second for dry air at approximately 20C, used with X3DAudioInitialize X3DAUDIO_SPEED_OF_SOUND = 343.5 X3DAUDIO_CALCULATE_MATRIX = 0x00000001 # enable matrix coefficient table calculation X3DAUDIO_CALCULATE_DELAY = 0x00000002 # enable delay time array calculation (stereo final mix only) X3DAUDIO_CALCULATE_LPF_DIRECT = 0x00000004 # enable LPF direct-path coefficient calculation X3DAUDIO_CALCULATE_LPF_REVERB = 0x00000008 # enable LPF reverb-path coefficient calculation X3DAUDIO_CALCULATE_REVERB = 0x00000010 # enable reverb send level calculation X3DAUDIO_CALCULATE_DOPPLER = 0x00000020 # enable doppler shift factor calculation X3DAUDIO_CALCULATE_EMITTER_ANGLE = 0x00000040 # enable emitter-to-listener interior angle calculation X3DAUDIO_CALCULATE_ZEROCENTER = 0x00010000 # do not position to front center speaker, signal positioned to remaining speakers instead, front center destination channel will be zero in returned matrix coefficient table, valid only for matrix calculations with final mix formats that have a front center channel X3DAUDIO_CALCULATE_REDIRECT_TO_LFE = 0x00020000 # apply equal mix of all source channels to LFE destination channel, valid only for matrix calculations with sources that have no LFE channel and final mix formats that have an LFE channel default_dsp_calculation = X3DAUDIO_CALCULATE_MATRIX | X3DAUDIO_CALCULATE_DOPPLER X3DAudioInitialize = x3d_lib.X3DAudioInitialize X3DAudioInitialize.restype = HRESULT X3DAudioInitialize.argtypes = [c_int, c_float, c_void_p] X3DAudioCalculate = x3d_lib.X3DAudioCalculate X3DAudioCalculate.restype = c_void X3DAudioCalculate.argtypes = [POINTER(X3DAUDIO_HANDLE), POINTER(X3DAUDIO_LISTENER), POINTER(X3DAUDIO_EMITTER), UINT32, POINTER(X3DAUDIO_DSP_SETTINGS)] AudioCategory_Other = 0 AudioCategory_ForegroundOnlyMedia = 1 AudioCategory_Communications = 3 AudioCategory_Alerts = 4 AudioCategory_SoundEffects = 5 AudioCategory_GameEffects = 6 AudioCategory_GameMedia = 7 AudioCategory_GameChat = 8 AudioCategory_Speech = 9 AudioCategory_Movie = 10 AudioCategory_Media = 11 # Reverb not implemented but if someone wants to take a stab at it. class XAUDIO2FX_REVERB_PARAMETERS(Structure): _fields_ = [ ('WetDryMix', c_float), # ratio of wet (processed) signal to dry (original) signal # Delay times ('ReflectionsDelay', UINT32), # [0, 300] in ms ('ReverbDelay', BYTE), # [0, 85] in ms ('RearDelay', UINT32), # 7.1: [0, 20] in ms, all other: [0, 5] in ms ('SideDelay', UINT32), # .1: [0, 5] in ms, all other: not used, but still validated # WIN 10 only. # Indexed Paremeters ('PositionLeft', BYTE), # [0, 30] no units ('PositionRight', BYTE), # 0, 30] no units, ignored when configured to mono ('PositionMatrixLeft', BYTE), # [0, 30] no units ('PositionMatrixRight', BYTE), # [0, 30] no units, ignored when configured to mono ('EarlyDiffusion', BYTE), # [0, 15] no units ('LateDiffusion', BYTE), # [0, 15] no units ('LowEQGain', BYTE), # [0, 12] no units ('LowEQCutoff', BYTE), # [0, 9] no units ('LowEQCutoff', BYTE), # [0, 8] no units ('HighEQCutoff', BYTE), # [0, 14] no units # Direct parameters ('RoomFilterFreq', c_float), # [20, 20000] in Hz ('RoomFilterMain', c_float), # [-100, 0] in dB ('RoomFilterHF', c_float), # [-100, 0] in dB ('ReflectionsGain', c_float), # [-100, 20] in dB ('ReverbGain', c_float), # [-100, 20] in dB ('DecayTime', c_float), # [0.1, inf] in seconds ('Density', c_float), # [0, 100] (percentage) ('RoomSize', c_float), # [1, 100] in feet # component control ('DisableLateField', c_bool), # TRUE to disable late field reflections ] class IXAudio2(com.pIUnknown): _methods_ = [ ('RegisterForCallbacks', com.STDMETHOD(POINTER(IXAudio2EngineCallback))), ('UnregisterForCallbacks', com.METHOD(ctypes.c_void_p, POINTER(IXAudio2EngineCallback))), ('CreateSourceVoice', com.STDMETHOD(POINTER(IXAudio2SourceVoice), POINTER(WAVEFORMATEX), UINT32, c_float, POINTER(IXAudio2VoiceCallback), POINTER(XAUDIO2_VOICE_SENDS), POINTER(XAUDIO2_EFFECT_CHAIN))), ('CreateSubmixVoice', com.STDMETHOD(POINTER(IXAudio2SubmixVoice), UINT32, UINT32, UINT32, UINT32, POINTER(XAUDIO2_VOICE_SENDS), POINTER(XAUDIO2_EFFECT_CHAIN))), ('CreateMasteringVoice', com.STDMETHOD(POINTER(IXAudio2MasteringVoice), UINT32, UINT32, UINT32, LPCWSTR, POINTER(XAUDIO2_EFFECT_CHAIN), UINT32)), ('StartEngine', com.STDMETHOD()), ('StopEngine', com.STDMETHOD()), ('CommitChanges', com.STDMETHOD(UINT32)), ('GetPerformanceData', com.METHOD(c_void, POINTER(XAUDIO2_PERFORMANCE_DATA))), ('SetDebugConfiguration', com.STDMETHOD(POINTER(XAUDIO2_DEBUG_CONFIGURATION), c_void_p)), ] XAudio2Create = xaudio2_lib.XAudio2Create XAudio2Create.restype = HRESULT XAudio2Create.argtypes = [POINTER(IXAudio2), UINT32, UINT32] CreateAudioReverb = xaudio2_lib.CreateAudioReverb CreateAudioReverb.restype = HRESULT CreateAudioReverb.argtypes = [POINTER(com.pIUnknown)]