
    qi_3                       d dl mZ d dlZd dlZd dlmZ d dlmZmZm	Z	 ddl
mZmZ ddlmZ ddlmZ dd	lmZ dd
lmZmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlm Z  e G d d             Z!e G d d             Z" G d d      Z#y)    )annotationsN)	dataclass)AnyAsyncIteratorOptional   )	FfiClient	FfiHandle)audio_frame_pb2)ffi_pb2)TrackSource)	RingQueuetask_done_logger)
AudioFrame)logger)Participant)Track)FrameProcessorc                      e Zd ZU dZded<   y)AudioFrameEventzyAn event representing a received audio frame.

    Attributes:
        frame (AudioFrame): The received audio frame.
    r   frameN)__name__
__module____qualname____doc____annotations__     J/opt/pipecat/venv/lib/python3.12/site-packages/livekit/rtc/audio_stream.pyr   r   "   s     r   r   c                  "    e Zd ZU ded<   ded<   y)NoiseCancellationOptionsstr	module_idzdict[str, Any]optionsN)r   r   r   r   r   r   r   r!   r!   -   s    Nr   r!   c                     e Zd ZdZ	 	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZeddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd       Zeddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd	       Zdd
ZddZ		 	 	 	 	 	 ddZ
d ZddZddZddZddZy)AudioStreamaO  An asynchronous audio stream for receiving audio frames from a participant or track.

    The `AudioStream` class provides an asynchronous iterator over audio frames received from
    a specific track or participant. It allows you to receive audio frames in real-time with
    customizable sample rates and channel configurations.
    Nr   逻  r   c                .   || _         || _        || _        || _        |xs t	        j
                         | _        t        j                  j                  j                  | j                  d       | _        t        |      | _        d| _        d| _        d| _        t#        |t$              r#|j&                  | _        |j(                  | _        nt#        |t*              r|| _        | j                  j-                  | j/                               | _        | j0                  j3                  t4               d}	d|v r| j7                  |d   |d         }	n| j9                         }	t;        |	j<                  j>                        | _         |	jB                  | _"        y)aR  Initialize an `AudioStream` instance.

        Args:
            track (Optional[Track]): The audio track from which to receive audio. If not provided,
                you must specify `participant` and `track_source` in `kwargs`.
            loop (Optional[asyncio.AbstractEventLoop], optional): The event loop to use.
                Defaults to the current event loop.
            capacity (int, optional): The capacity of the internal frame queue. Defaults to 0 (unbounded).
            sample_rate (int, optional): The sample rate for the audio stream in Hz.
                Defaults to 48000.
            num_channels (int, optional): The number of audio channels. Defaults to 1.
            noise_cancellation (Optional[NoiseCancellationOptions | FrameProcessor[AudioFrame]], optional):
                If noise cancellation is used, pass a `NoiseCancellationOptions` or `FrameProcessor[AudioFrame]` instance
                created by the noise cancellation module.

        Example:
            ```python
            audio_stream = AudioStream(
                track=audio_track,
                sample_rate=44100,
                num_channels=2,
            )

            audio_stream = AudioStream.from_track(
                track=audio_track,
                sample_rate=44100,
                num_channels=2,
            )
            ```
        c                *    | j                  d      dk(  S )Nmessageaudio_stream_event)
WhichOneof)es    r   <lambda>z&AudioStream.__init__.<locals>.<lambda>m   s    Y 7;O O r   )	filter_fnNparticipanttrack_source)r0   r1   )#_track_sample_rate_num_channels_frame_size_msasyncioget_event_loop_loopr	   instancequeue	subscribe
_ffi_queuer   _queue_audio_filter_module_audio_filter_options
_processor
isinstancer!   r#   r$   r   create_task_run_taskadd_done_callbackr   %_create_owned_stream_from_participant_create_owned_streamr
   handleid_ffi_handleinfo_info)
selftrackloopcapacitysample_ratenum_channelsframe_size_msnoise_cancellationkwargsstreams
             r   __init__zAudioStream.__init__;   s[   R %*')+5W335
 $,,22<<JJO = 
 :C89L04!<@"=A(*BC(:(D(DD%);)C)CD&*N;0DOZZ++DIIK8


$$%56F"??"=1~@V @ F ..0F$V]]%5%56[[
r   )rO   rP   rQ   rR   rS   rT   c               *    t        ||||d||||	      S )a2  Create an `AudioStream` from a participant's audio track.

        Args:
            participant (Participant): The participant from whom to receive audio.
            track_source (TrackSource.ValueType): The source of the audio track (e.g., microphone, screen share).
            loop (Optional[asyncio.AbstractEventLoop], optional): The event loop to use. Defaults to the current event loop.
            capacity (int, optional): The capacity of the internal frame queue. Defaults to 0 (unbounded).
            sample_rate (int, optional): The sample rate for the audio stream in Hz. Defaults to 48000.
            num_channels (int, optional): The number of audio channels. Defaults to 1.
            noise_cancellation (Optional[NoiseCancellationOptions], optional):
                If noise cancellation is used, pass a `NoiseCancellationOptions` instance
                created by the noise cancellation module.

        Returns:
            AudioStream: An instance of `AudioStream` that can be used to receive audio frames.

        Example:
            ```python
            audio_stream = AudioStream.from_participant(
                participant=participant,
                track_source=TrackSource.MICROPHONE,
                sample_rate=24000,
                num_channels=1,
            )
            ```
        N)	r0   r1   rO   rP   rN   rQ   rR   rT   rS   r&   )	clsr0   r1   rO   rP   rQ   rR   rS   rT   s	            r   from_participantzAudioStream.from_participant   s-    N #%#%1'

 
	
r   c          	     &    t        |||||||      S )ap  Create an `AudioStream` from an existing audio track.

        Args:
            track (Track): The audio track from which to receive audio.
            loop (Optional[asyncio.AbstractEventLoop], optional): The event loop to use. Defaults to the current event loop.
            capacity (int, optional): The capacity of the internal frame queue. Defaults to 0 (unbounded).
            sample_rate (int, optional): The sample rate for the audio stream in Hz. Defaults to 48000.
            num_channels (int, optional): The number of audio channels. Defaults to 1.
            noise_cancellation (Optional[NoiseCancellationOptions], optional):
                If noise cancellation is used, pass a `NoiseCancellationOptions` instance
                created by the noise cancellation module.

        Returns:
            AudioStream: An instance of `AudioStream` that can be used to receive audio frames.

        Example:
            ```python
            audio_stream = AudioStream.from_track(
                track=audio_track,
                sample_rate=44100,
                num_channels=2,
            )
            ```
        )rN   rO   rP   rQ   rR   rT   rS   rY   )rZ   rN   rO   rP   rQ   rR   rS   rT   s           r   
from_trackzAudioStream.from_track   s'    H #%1'
 	
r   c                j    t         j                  j                  j                  | j                         y N)r	   r9   r:   unsubscriber<   rM   s    r   __del__zAudioStream.__del__   s       ,,T__=r   c                h   | j                   J t        j                         }|j                  }| j                   j                  j
                  |_        | j                  |_        | j                  |_
        | j                  r| j                  |_        t        j                  j                  |_        | j"                  | j"                  |_        | j&                  $t)        j*                  | j&                        |_        t.        j0                  j3                  |      }|j                  j4                  S r_   )r2   	proto_ffi
FfiRequestnew_audio_streamrJ   rH   track_handler3   rQ   r4   rR   r5   rS   proto_audio_frameAudioStreamTypeAUDIO_STREAM_NATIVEtyper>   audio_filter_module_idr?   jsondumpsaudio_filter_optionsr	   r9   requestrV   )rM   reqrf   resps       r   rG   z AudioStream._create_owned_stream   s    {{&&&""$//(,(?(?(F(F%'+'8'8$(,(:(:%-1-@-@* 1 A A U U$$06:6O6O3%%148JJt?Y?Y4Z1!!))#.$$+++r   c                F   t        j                         }|j                  }|j                  j                  |_        | j                  |_        | j                  |_	        t        j                  j                  |_        ||_        | j                  r| j                  |_        | j"                  | j"                  |_        | j&                  $t)        j*                  | j&                        |_        t.        j0                  j3                  |      }|j                  j4                  S r_   )rd   re   audio_stream_from_participantrJ   rH   participant_handler3   rQ   r4   rR   rh   ri   rj   rk   r1   r5   rS   r>   rl   r?   rm   rn   ro   r	   r9   rp   rV   )rM   r0   r1   rq   rt   rr   s         r   rF   z1AudioStream._create_owned_stream_from_participant   s     ""$(+(I(I%;F;R;R;Y;Y%8484E4E%1595G5G%2->-N-N-b-b%*5A%2:>:M:M)7$$0CGC\C\)@%%1AE**B)> !!))#.11888r   c                  K   	 | j                   j                  | j                         d {   }|j                  }|j	                  d      r|j
                  j                  }t        j                  |      }| j                  2| j                  j                  r	 | j                  j                  |      }t        |      }| j                   j#                  |       n-|j	                  d      r| j                   j#                  d        n	t$        j&                  j(                  j+                  | j                          y 7 # t        $ r t        j                  dd       Y w xY ww)NTframe_receivedz7Frame processing failed, passing through original frame)exc_infoeos)r<   wait_for	_is_eventr+   HasFieldrw   r   r   _from_owned_infor@   enabled_process	Exceptionr   warningr   r=   putr	   r9   r:   r`   )rM   eventaudio_eventowned_buffer_infor   s        r   rC   zAudioStream._run  s    //224>>BBE>C>V>VK##$45$/$>$>$D$D!"334EF??.4??3J3J $ 8 8 ? (.&%%e,%' * 	  ,,T__=) C % U%)s5   *E*EA.E*E 7BE* E'$E*&E''E*c                l   K   | j                   j                          | j                   d{    y7 w)zAsynchronously close the audio stream.

        This method cleans up resources associated with the audio stream and waits for
        any pending operations to complete.
        N)rJ   disposerD   ra   s    r   aclosezAudioStream.aclose*  s'      	  "jjs   *424c                \    |j                   j                  | j                  j                  k(  S r_   )r+   stream_handlerJ   rH   )rM   r-   s     r   r{   zAudioStream._is_event3  s%    ##11T5E5E5L5LLLr   c                    | S r_   r   ra   s    r   	__aiter__zAudioStream.__aiter__6  s    r   c                   K   | j                   j                         rt        | j                  j	                          d {   }|t        |S 7 wr_   )rD   doneStopAsyncIterationr=   get)rM   items     r   	__anext__zAudioStream.__anext__9  sB     ::??$$[[__&&<$$	 's   >A AA)Nr   r'   r   NN)rN   r   rO   #Optional[asyncio.AbstractEventLoop]rP   intrQ   r   rR   r   rS   
int | NonerT   ?Optional[NoiseCancellationOptions | FrameProcessor[AudioFrame]]returnNone)r0   r   r1   TrackSource.ValueTyperO   r   rP   r   rQ   r   rR   r   rS   r   rT   r   r   r&   )rN   r   rO   r   rP   r   rQ   r   rR   r   rS   r   rT   r   r   r&   )r   r   )r   r   )r0   r   r1   r   r   r   )r-   zproto_ffi.FfiEventr   bool)r   zAsyncIterator[AudioFrameEvent])r   r   )r   r   r   r   rW   classmethodr[   r]   rb   rG   rF   rC   r   r{   r   r   r   r   r   r&   r&   3   s    59 $(^bJ!J! 2J! 	J!
 J! J! "J! \J! 
J!X  59 $(^b0
 !0
 ,	0

 20
 0
 0
 0
 "0
 \0
 
0
 0
d 
 59 $(^b+
 +
 2	+

 +
 +
 +
 "+
 \+
 
+
 +
Z>,"9&96K9	9,>0Mr   r&   )$
__future__r   r6   rm   dataclassesr   typingr   r   r   _ffi_clientr	   r
   _protor   rh   r   rd   _proto.track_pb2r   _utilsr   r   audio_framer   logr   r0   r   rN   r   frame_processorr   r   r!   r&   r   r   r   <module>r      su    #   ! / / - 8 ( ) / #  $  +      
N Nr   