
    \
j'Y                         d dl Z d dlmZmZ d dlmZ d dlZd dlT d dlm	Z	 d dl
mZ ddlmZ  e	d	          Z G d
 d          Z G d d          Z G d d          ZdS )    N)
namedtupledefaultdict)
DeviceFlow)*)debug_print)get_audio_device_manager   )lib_xaudio2debug_mediac                   b   e Zd ZdZej        Zej        ZdZ	dZ
d Zd ZdefdZd"dZed	             Zed
             Zed             Zd Zd Zd Zd Zd Zd Zed             Zej        d             Zd Zd Zd Zd#dZd Z d Z!d Z"d Z#d Z$d Z%d Z&e'd              Z(e'd!             Z)dS )$XAudio2DriverTg       @c                    t          d          sJ d| _        d| _        d| _        g | _        t          t                    | _        g | _        g | _	        | 
                                 | j        rt                      }|rrt          d          sJ |                    |            |                                t          d          t           j                            | j        d           dS dS dS )a.  Creates an XAudio2 master voice and sets up 3D audio if specified. This attaches to the default audio
        device and will create a virtual audio endpoint that changes with the system. It will not recover if a
        critical error is encountered such as no more audio devices are present.
        zConstructing XAudio2DriverNFzAudio device instance found.z5No default audio device found, can not create driver.g      ?)_debug	_listener_xaudio2_dead_emitting_voicesr   list_voice_pool_in_use_players_create_xa2restart_on_errorr   push_handlersget_default_outputImportErrorpygletclockschedule_interval_soft_check_state)selfaudio_devicess     `/DATA/AppData/hermes/venv/lib/python3.11/site-packages/pyglet/media/drivers/xaudio2/interface.py__init__zXAudio2Driver.__init__A   s	   
 233333
 "&t,,  		L466M L<=====++D111 3355=%&]^^^33D4EsKKKKK		L 		LL L    c                     | j         du r| j        r|                                  dS dS | j        sN|                                  | j        D ]}|                    d           | j                                         dS dS )zeHack/workaround, you cannot shutdown/create XA2 within a COM callback, set a schedule to check state.Ton_driver_resetN)r   r   _shutdown_xaudio2r   r   dispatch_eventclear)r!   dtplayers      r#   r    zXAudio2Driver._check_state^   s    :} )&&((((() ) = &  """"m = =F))*;<<<<##%%%%%& &r%   flowc                     |t           j        k    r>	 |t          d          sJ d| _        d S | j        rt          d          sJ d| _        d S d S d S )Nz8Error: Default audio device was removed or went missing.Tz8Warning: Default audio device added after going missing.F)r   OUTPUTr   r   )r!   devicer-   s      r#   on_default_changedz XAudio2Driver.on_default_changedl   st    :$$$t~XYYYYY!


: '!"\]]]]]!&DJJJ %$' 'r%   Nc           	         t          j                    | _        	 t          j        t                              | j                  d| j                   n# t          $ r t          d          w xY wt          r|t          j
                    }d|_        t           j        t           j        z  |_        t           j        |_        | j                            t                              |          d            t          j                    | _        | j                            t          | j                  t           j        t           j        d|d | j                   | j        r|                                  d S d S )Nr   z(XAudio2 driver could not be initialized.T)libIXAudio2r   XAudio2Createctypesbyref	processorOSErrorr   r   XAUDIO2_DEBUG_CONFIGURATIONLogThreadIDXAUDIO2_LOG_ERRORSXAUDIO2_LOG_WARNINGS	TraceMask	BreakMaskSetDebugConfigurationIXAudio2MasteringVoice_master_voiceCreateMasteringVoiceXAUDIO2_DEFAULT_CHANNELSXAUDIO2_DEFAULT_SAMPLERATEcategoryallow_3d	enable_3d)r!   	device_iddebugs      r#   r   zXAudio2Driver._create_xa2w   sL   	Jfll4=991dnMMMM 	J 	J 	JHIII	J  		K 355E $E!4s7OOEO!6EOM//U0C0CTJJJ 799**51C+D+D+.+G+.+I+,it}	N 	N 	N
 = 	NN	 	s   8A A-c                     | j         S N)r   r!   s    r#   active_voiceszXAudio2Driver.active_voices   s
    |r%   c                 H    d | j                                         D             S )Nc                     g | ]	}|D ]}|
S  rQ   ).0voicesvoices      r#   
<listcomp>z/XAudio2Driver.pooled_voices.<locals>.<listcomp>   s%    RRR&6RR%RRRRr%   )r   valuesrM   s    r#   pooled_voiceszXAudio2Driver.pooled_voices   s%    RRD$4$;$;$=$=RRRRr%   c                      | j         | j        z   S )zAll pooled and active voices.)rN   
all_voicesrM   s    r#   rY   zXAudio2Driver.all_voices   s     !DO33r%   c                     | j         D ]}|                                 | j        D ]!}| j        |                                          "dS )z)Destroy and then clear the pool of voicesN)rW   destroyr   r*   r!   rT   	voice_keys      r#   
clear_poolzXAudio2Driver.clear_pool   s\    ' 	 	EMMOOOO) 	0 	0IY'--////	0 	0r%   c                 t    | j         D ]}|                                 | j                                          dS )z(Destroy and then clear all active voicesN)r   r[   r*   r!   rT   s     r#   clear_activezXAudio2Driver.clear_active   s<    \ 	 	EMMOOOOr%   c                     |                                   |                     |j                   | j        D ]}|                    d           | j                                         dS )zAAttach XA2 with a specific device rather than the virtual device.r'   N)r(   r   idr   r)   r*   )r!   r0   r,   s      r#   
set_devicezXAudio2Driver.set_device   so       ### m 	5 	5F!!"34444r%   c                     | j         D ]?}|j                                         | j                            |j        j                   @|                                  dS )zAStops and destroys all active voices, then destroys XA2 instance.N)rN   r,   on_driver_destroyr   append_delete_driverr`   s     r#   r(   zXAudio2Driver._shutdown_xaudio2   s^    ' 	6 	6EL**,,,M  !45555r%   c                 0   | j         r| j        r$t          j                            | j                   |                                  |                                  | j                                          | j         	                                 d | _         d S d S rL   )
r   rG   r   r   
unschedule_calculate_3d_sourcesr^   ra   
StopEngineReleaserM   s    r#   rh   zXAudio2Driver._delete_driver   s    = 	!} D''(BCCC OOM$$&&&M!!### DMMM	! 	!r%   c                    t                      }| j                            t          |                     t	          j                    | _        t	          j        |j        t          j	        | j                   t	          j
                    | _        | j                            t          | j                             t          | j        j        z              }t	          j                    | _        d| j        _        | j        j        | j        _        || j        _        t(          j                            | j        d           dS )z`Initializes the prerequisites for 3D positional audio and initializes with default DSP settings.r	   g?N)DWORDrB   GetChannelMaskr7   r3   X3DAUDIO_HANDLE_x3d_handleX3DAudioInitializevalueX3DAUDIO_SPEED_OF_SOUNDXAUDIO2_VOICE_DETAILS_mvoice_detailsGetVoiceDetailsFLOATInputChannelsX3DAUDIO_DSP_SETTINGS_dsp_settingsSrcChannelCountDstChannelCountpMatrixCoefficientsr   r   r   rk   )r!   channel_maskmatrixs      r#   rH   zXAudio2Driver.enable_3d   s    ww))%*=*=>>>.00|133NPTP`aaa"8::**51E+F+FGGG$.<<?? 688-.*-1-A-O*17.++D,FQQQQQr%   c                     t                      }| j                            t                              |                     |j        S rL   )c_floatrB   	GetVolumer6   r7   rt   r!   vols     r#   volumezXAudio2Driver.volume   s6    ii$$V\\#%6%6777yr%   c                 <    | j                             |d           dS )z'Sets global volume of the master voice.r   N)rB   	SetVolumer!   rt   s     r#   r   zXAudio2Driver.volume   s#     	$$UA.....r%   c                 x    | j         D ]}|                     |           | j                            d           dS )ziWe calculate the 3d emitters and sources every 15 fps, committing everything after deferring all changes.r   N)r   apply3dr   CommitChanges)r!   r+   source_voices      r#   rk   z#XAudio2Driver._calculate_3d_sources   sE     1 	' 	'LLL&&&&##A&&&&&r%   c                 ^    t          j        | j        ||t           j        | j                   d S rL   )r3   X3DAudioCalculaterr   default_dsp_calculationr|   )r!   listeneremitters      r#   _calculate3dzXAudio2Driver._calculate3d   s9    '	
 	
 	
 	
 	
r%   c                     |                     | j        d| j        j        | j        j        |           |                    | j        j        |           dS )zCalculates the output channels based on the listener and emitter and default DSP settings.
           Commit determines if the settings are applied immediately (0) or committed at once through the xaudio driver.
        r	   N)SetOutputMatrixrB   rw   rz   r|   r   SetFrequencyRatioDopplerFactor)r!   rT   commits      r#   _apply3dzXAudio2Driver._apply3d   s]     	d0"2@"0D$		& 	& 	& 	 2 @&IIIIIr%   r	   c                     |                      | j        j        |j                   |                     |j        |           d S rL   )r   r   r   _emitterr   _voice)r!   r   r   s      r#   r   zXAudio2Driver.apply3d
  s=    $.1<3HIIIl)622222r%   c                     	 |                                   t          j                            | j                   d S # t
          $ r Y d S w xY wrL   )rh   r   r   rj   r    AttributeErrorrM   s    r#   __del__zXAudio2Driver.__del__  sZ    	!!!L##D$566666 	 	 	DD	s   8< 
A
	A
c                     t          j                    }| j                            t                              |                     |S )zTRetrieve some basic XAudio2 performance data such as memory usage and source counts.)r3   XAUDIO2_PERFORMANCE_DATAr   GetPerformanceDatar6   r7   )r!   pfs     r#   get_performancezXAudio2Driver.get_performance  s7    )++((b)9)9:::	r%   c                 Z    | j         
J d            t          |           | _         | j         S )Nz!You can only create one listener.)r   XAudio2ListenerrM   s    r#   create_listenerzXAudio2Driver.create_listener  s0    ~%%'J%%%(..~r%   c                    |j         j        |j         j        |j         j        f}t	          | j        |                   dk    r6| j        |                             d          }|                    |           n|                     ||          }|j	        r| j
                            |           | j                            |           |S )a*   Get a source voice from the pool. Source voice creation can be slow to create/destroy. So pooling is
            recommended. We pool based on audio channels as channels must be the same as well as frequency.
            Source voice handles all of the audio playing and state for a single source.r   )audio_formatchannelssample_sizesample_ratelenr   popacquired
_get_voice
is_emitterr   rg   r   )r!   sourcer,   r]   r   s        r#   get_source_voicezXAudio2Driver.get_source_voice!  s     (163F3RTZTgTst	t	*++a//+I6::1==L!!&))))??66::L" 	7!((666L)))r%   c           	      6   t          j                    }|                     |j                  }t          j        |          }| j                            t                              |          t                              |          d| j	        |dd           ||fS )z8Has the driver create a new source voice for the source.r   N)
r3   IXAudio2SourceVoicecreate_wave_formatr   XA2SourceCallbackr   CreateSourceVoicer6   r7   max_frequency_ratio)r!   r   r,   rT   
wfx_formatcallbacks         r#   _create_new_voicezXAudio2Driver._create_new_voice2  s    ')),,V-@AA
(00''U(;(;(.Z(@(@()(,(@(0(,d	4 	4 	4 hr%   c                 `    |                      ||          \  }}t          |||j                  S )zKCreates a new source voice and puts it into XA2SourceVoice high level wrap.)r   XA2SourceVoicer   )r!   r   r,   rT   r   s        r#   r   zXAudio2Driver._get_voiceA  s0    00@@xeXv/BCCCr%   c                     |                                  |j        j        |j        j        |j        j        f}| j        |                             |           |j        r| j        	                    |           dS dS )z(Reset a voice and return it to the pool.N)
resetr   r   r   r   r   rg   r   r   remover\   s      r#   return_voicezXAudio2Driver.return_voiceF  s|    '0%2D2PRWRdRpq	#**5111 	0!((/////	0 	0r%   c                    t          | j                  t          k    rBt          j        | j        z              }t                              || j        | j                   n| j        }t          j                    }| j        |_	        ||_
        |S )a  Creates a XAUDIO2_BUFFER to be used with a source voice.
            Audio data cannot be purged until the source voice has played it; doing so will cause glitches.
            Furthermore, if the data is not in a string buffer, such as pure bytes, it must be converted.)typedatabytesr6   c_charlengthmemmover3   XAUDIO2_BUFFER
AudioBytes
pAudioData)
audio_datar   buffs      r#   create_bufferzXAudio2Driver.create_bufferO  sw    
 
  E))MJ$5588DNN4*2CDDDD?D!##$+r%   c                     t          j                    }t           j        |_        | j        |_        | j        |_        | j        |_	        |j	        |j        z  dz  |_
        |j        |j
        z  |_        |S )N   )r3   WAVEFORMATEXWAVE_FORMAT_PCM
wFormatTagr   	nChannelsr   nSamplesPerSecr   wBitsPerSamplenBlockAlignnAvgBytesPerSec)r   wfxs     r#   r   z XAudio2Driver.create_wave_format_  sg      ,$-)5)5,s}<A!03?B
r%   rL   )r	   )*__name__
__module____qualname__rG   r3   XAUDIO2_DEFAULT_PROCESSORr8   AudioCategory_GameEffectsrF   r   r   r$   r    r   r1   r   propertyrN   rW   rY   r^   ra   rd   r(   rh   rH   r   setterrk   r   r   r   r   r   r   r   r   r   r   staticmethodr   r   rQ   r%   r#   r   r   1   s\       H -I ,H  L L L:& & &	'z 	' 	' 	' 	'   8   X S S XS 4 4 X40 0 0  	 	 	  ! ! !R R R&   X
 ]/ / ]/' ' '
 
 

J 
J 
J3 3 3 3      
  "  D D D
0 0 0   \   \  r%   r   c                   >   e Zd Zd Zed             Zd Zd Zd Zd Z	d Z
ed             Zed	             Zej        d
             Zed             Zed             Zej        d             Zed             Zej        d             Zed             Zej        d             Zed             Zej        d             Z edddg          Zed             Zd Zed             Zej        d             Zed             Zej        d             Zd Zd Zd Zd  Zd!S )"r   c                 t   t          j                    | _        || _        || _        || _        ||j        dk    rvt          j                    | _        |j        | j        _	        d| j        _
        t          j                    }d|_        t          |          | j        _        d | j        _        d S d | _        d S )Nr	   g      ?)r3   XAUDIO2_VOICE_STATE_voice_stater   	_callbackr   r   X3DAUDIO_EMITTERr   ChannelCountCurveDistanceScalerX3DAUDIO_CONEInnerVolumepointerpConepVolumeCurve)r!   rT   r   r   cones        r#   r$   zXA2SourceVoice.__init__m  s    355!( #(=(B(B022DM)5)>DM&03DM- $&&D  #D #*$--DM)-DM&&& DMMMr%   c                     | j         j        S )z5Returns the player class, stored within the callback.r   
xa2_playerrM   s    r#   r,   zXA2SourceVoice.player  s     ~((r%   c                     d | _         | j                            dd           | j                                         d | _        d | j        _        d S Nr   )r   r   StopFlushSourceBuffersr   r   rM   s    r#   deletezXA2SourceVoice.delete  sL    A&&((($(!!!r%   c                 .    |                                   d S rL   )r[   rM   s    r#   r   zXA2SourceVoice.__del__  s    r%   c                 
   d| _         | j        m	 | j                            dd           | j                                         | j                                         n# t
          t          f$ r Y nw xY wd| _        d| _        dS )zCompletely destroy the voice.Nr   )r   r   r   r   DestroyVoice	TypeErrorr9   r   rM   s    r#   r[   zXA2SourceVoice.destroy  s    ;"  A&&&..000((****w'    DKs   AA A21A2c                     || j         _        dS )z9A voice has been reacquired, set the player for callback.Nr   )r!   r,   s     r#   r   zXA2SourceVoice.acquired  s    $*!!!r%   c                     | j         d| _        | j                            dd           | j                                         d| j        _        dS )z@When a voice is returned to the pool, reset position on emitter.Nr   r   r   r   )r   positionr   r   r   r   r   rM   s    r#   r   zXA2SourceVoice.reset  sM    =$%DMA&&((($(!!!r%   c                     | j                             t                              | j                  t
          j                   | j        j        S )z_Get the amount of buffers in the current voice. Adding flag for no samples played is 3x faster.)r   GetStater6   r7   r   r3   XAUDIO2_VOICE_NOSAMPLESPLAYEDBuffersQueuedrM   s    r#   buffers_queuedzXA2SourceVoice.buffers_queued  s:     	V\\$*;<<c>_``` ..r%   c                     t                      }| j                            t                              |                     |j        S rL   )r   r   r   r6   r7   rt   r   s     r#   r   zXA2SourceVoice.volume  s5    iifll3//000yr%   c                 <    | j                             |d           d S r   )r   r   r   s     r#   r   zXA2SourceVoice.volume  s     eQ'''''r%   c                     | j         d uS rL   )r   rM   s    r#   r   zXA2SourceVoice.is_emitter  s    }D((r%   c                 x    | j         r2| j        j        j        | j        j        j        | j        j        j        fS dS )Nr   r   r   PositionxyzrM   s    r#   r  zXA2SourceVoice.position  s6    ? 	=)+T]-C-Et}G]G___7r%   c                     | j         r;|\  }}}|| j        j        _        || j        j        _        || j        j        _        d S d S rL   r  )r!   r  r  r  r  s        r#   r  zXA2SourceVoice.position  sN    ? 	)GAq!'(DM"$'(DM"$'(DM"$$$		) 	)r%   c                 ,    | j         r| j        j        S dS )zCurve distance scaler that is used to scale normalized distance curves to user-defined world units,
        and/or to exaggerate their effect.r   )r   r   r   rM   s    r#   min_distancezXA2SourceVoice.min_distance  s     ? 	=441r%   c                     | j         r6| j        j        |k    r(t          |t          j                  | j        _        d S d S d S rL   )r   r   r   minr3   FLT_MAXr   s     r#   r  zXA2SourceVoice.min_distance  sK    ? 	L}0E9947s{4K4K111	L 	L99r%   c                 z    t                      }| j                            t          |                     |j        S )z[The actual frequency ratio. If voice is 3d enabled, will be overwritten next apply3d cycle.)r   r   GetFrequencyRatior7   rt   r   s     r#   	frequencyzXA2SourceVoice.frequency  s1     		%%eEll333{r%   c                 V    | j         |k    rd S | j                            |d           d S r   )r  r   r   r   s     r#   r  zXA2SourceVoice.frequency  s2    >U""F%%eQ/////r%   c                 x    | j         r2| j        j        j        | j        j        j        | j        j        j        fS dS )z%The orientation of the sound emitter.r   r   r   OrientFrontr  r  r  rM   s    r#   cone_orientationzXA2SourceVoice.cone_orientation  s8     ? 	=,.0I0KT]MfMhhh7r%   c                     | j         r;|\  }}}|| j        j        _        || j        j        _        || j        j        _        d S d S rL   r  r!   rt   r  r  r  s        r#   r  zXA2SourceVoice.cone_orientation  sN    ? 	,GAq!*+DM%'*+DM%'*+DM%'''		, 	,r%   _ConeAnglesinsideoutsidec                     | j         r>|                     | j        j        j        j        | j        j        j        j                  S |                     dd          S );The inside and outside angles of the sound projection cone.r   )r   r   r   r   contents
InnerAngle
OuterAnglerM   s    r#   cone_angleszXA2SourceVoice.cone_angles  sP     ? 	*##DM$7$@$KT]M`MiMtuuu##Aq)))r%   c                 p    | j         r.|| j        j        j        _        || j        j        j        _        dS dS )r$  N)r   r   r   r%  r&  r'  )r!   r!  r"  s      r#   set_cone_angleszXA2SourceVoice.set_cone_angles  s<    ? 	>6<DM(36=DM(333	> 	>r%   c                 @    | j         r| j        j        j        j        S dS )z5The volume scaler of the sound beyond the outer cone.r   r   r   r   r%  OuterVolumerM   s    r#   cone_outside_volumez"XA2SourceVoice.cone_outside_volume  $     ? 	=&/;;1r%   c                 D    | j         r|| j        j        j        _        d S d S rL   r,  r   s     r#   r.  z"XA2SourceVoice.cone_outside_volume  ,    ? 	=7<DM(444	= 	=r%   c                 @    | j         r| j        j        j        j        S dS )z5The volume scaler of the sound within the inner cone.r   r   r   r   r%  r   rM   s    r#   cone_inside_volumez!XA2SourceVoice.cone_inside_volume   r/  r%   c                 D    | j         r|| j        j        j        _        d S d S rL   r3  r   s     r#   r4  z!XA2SourceVoice.cone_inside_volume(  r1  r%   c                 n    | j                             dd           | j                                          dS )zLStop and removes all buffers already queued. OnBufferEnd is called for each.r   N)r   r   r   rM   s    r#   flushzXA2SourceVoice.flush-  s4    A&&(((((r%   c                 <    | j                             dd           d S r   )r   StartrM   s    r#   playzXA2SourceVoice.play2  s     !Qr%   c                 <    | j                             dd           d S r   )r   r   rM   s    r#   stopzXA2SourceVoice.stop5  s     Ar%   c                 l    | j                             t                              |          d            d S rL   )r   SubmitSourceBufferr6   r7   )r!   	x2_buffers     r#   submit_bufferzXA2SourceVoice.submit_buffer8  s,    &&v||I'>'>EEEEEr%   N)r   r   r   r$   r   r,   r   r   r[   r   r   r  r   r   r   r  r  r  r  r   r   r(  r*  r.  r4  r7  r:  r<  r@  rQ   r%   r#   r   r   k  s       ! ! !4 ) ) X)) ) )     + + +) ) ) / / X/
   X
 ]( ( ]( ) ) X)   X _) ) _)   X L L L
   X 0 0 0   X , , , *]Xy,ABBK* * X*> > >   X = =  =   X = = =) ) )
       F F F F Fr%   r   c                       e Zd Zd Zd Zd Zed             Zej        d             Zed             Z	e	j        d             Z	dS )	r   c                 4   t          j        |          | _        t          j                    | _        d| j        j        _        d| j        j        _        d| j        j        _	        d| j        j
        _        d| j        j
        _        d| j        j
        _	        d S )Nr   r	   )weakrefproxy
xa2_driverr3   X3DAUDIO_LISTENERr   r  r  r  r  	OrientTop)r!   drivers     r#   r$   zXAudio2Listener.__init__=  sy    !-//-// '(!#&'!#&'!#$%!$%!$%!!!r%   c                 .    |                                   d S rL   )r   rM   s    r#   r   zXAudio2Listener.__del__K  s    r%   c                     d | _         d S rL   )r   rM   s    r#   r   zXAudio2Listener.deleteN  s    r%   c                 f    | j         j        j        | j         j        j        | j         j        j        fS rL   r   r  r  r  r  rM   s    r#   r  zXAudio2Listener.positionQ  s'    }%')?)A4=CYC[[[r%   c                 x    |\  }}}|| j         j        _        || j         j        _        || j         j        _        d S rL   rL  r  s        r#   r  zXAudio2Listener.positionU  s:    1a#$ #$ #$   r%   c                     | j         j        j        | j         j        j        | j         j        j        | j         j        j        | j         j        j        | j         j        j        fS rL   r   r  r  r  r  rG  rM   s    r#   orientationzXAudio2Listener.orientation\  sL    }(*DM,E,GIbId}&($-*A*CT]E\E^_ 	_r%   c                     |\  }}}}}}|| j         j        _        || j         j        _        || j         j        _        || j         j        _        || j         j        _        || j         j        _        d S rL   rO  )r!   rP  front_xfront_yfront_ztop_xtop_ytop_zs           r#   rP  zXAudio2Listener.orientationa  sh    9D6'5%&-!#&-!#&-!#$)!$)!$)!!!r%   N)
r   r   r   r$   r   r   r   r  r   rP  rQ   r%   r#   r   r   <  s        & & &     \ \ X\ _% % _% _ _ X_ 	* 	* 	* 	* 	*r%   r   )rC  collectionsr   r   pyglet.media.devices.baser   r   pyglet.libs.win32.typespyglet.utilr   pyglet.media.devicesr    r
   r3   r   r   r   r   rQ   r%   r#   <module>r^     s1  F  / / / / / / / / 0 0 0 0 0 0  % % % % # # # # # # 9 9 9 9 9 9            	]	#	#w w w w w w w wt	NF NF NF NF NF NF NF NFb/* /* /* /* /* /* /* /* /* /*r%   