o
    ia                     @   sp   d Z ddlZddlmZ ddlmZmZ ddlmZm	Z	m
Z
mZmZ ddlmZ ddlmZ G dd	 d	eZdS )
zVoice Activity Detection controller for managing speech state transitions.

This module provides a controller that wraps a VADAnalyzer to track speech state
and emit events when speech starts, stops, or is actively detected.
    N)Type)VADAnalyzerVADState)FrameInputAudioRawFrameSpeechControlParamsFrame
StartFrameVADParamsUpdateFrame)FrameDirection)
BaseObjectc                       s   e Zd ZdZdddedef fddZdefd	d
Zde	fddZ
defddZdededefddZdd ZejfdedefddZdee fddZ  ZS )VADControllera(  Manages voice activity detection state and emits speech events.

    Wraps a `VADAnalyzer` to process audio and trigger events based on speech
    state transitions. Tracks whether the user is speaking, quiet, or
    transitioning between states.

    Event handlers available:

    - on_speech_started: Called when speech begins.
    - on_speech_stopped: Called when speech ends.
    - on_speech_activity: Called periodically while speech is detected.
    - on_push_frame: Called when the controller wants to push a frame.
    - on_broadcast_frame: Called when the controller wants to broadcast a frame.

    Example::

        @vad_controller.event_handler("on_speech_started")
        async def on_speech_started(controller):
            ...

        @vad_controller.event_handler("on_speech_stopped")
        async def on_speech_stopped(controller):
            ...

        @vad_controller.event_handler("on_speech_activity")
        async def on_speech_activity(controller):
            ...

        @vad_controller.event_handler("on_push_frame")
        async def on_push_frame(controller, frame: Frame, direction: FrameDirection):
            ...

        @vad_controller.event_handler("on_broadcast_frame")
        async def on_broadcast_frame(controller, frame_cls: Type[Frame], **kwargs):
            ...
    g?)speech_activity_periodvad_analyzerr   c                   sn   t    || _tj| _d| _|| _| jddd | jddd | jddd | jddd | jddd d	S )
a  Initialize the VAD controller.

        Args:
            vad_analyzer: The `VADAnalyzer` instance for processing audio.
            speech_activity_period: Minimum interval in seconds between
                `on_speech_activity` events. Defaults to 0.2.
        r   on_speech_startedT)syncon_speech_stoppedon_speech_activityon_push_frameon_broadcast_frameN)	super__init___vad_analyzerr   QUIET
_vad_state_speech_activity_time_speech_activity_period_register_event_handler)selfr   r   	__class__ T/home/ubuntu/.local/lib/python3.10/site-packages/pipecat/audio/vad/vad_controller.pyr   B   s   
zVADController.__init__framec                    st   t |tr| |I dH  dS t |tr| |I dH  dS t |tr8| j|j | j	t
|jdI dH  dS dS )zProcess a frame and handle VAD-related events.

        Handles `StartFrame` to initialize the sample rate and `InputAudioRawFrame`
        to analyze audio for voice activity.

        Args:
            frame: The frame to process.
        N
vad_params)
isinstancer   _startr   _handle_audior	   r   
set_paramsparamsbroadcast_framer   r   r"   r    r    r!   process_frameZ   s   
	

zVADController.process_framec                    s,   | j |j | jt| j jdI d H  d S )Nr#   )r   set_sample_rateaudio_in_sample_rater*   r   r)   r+   r    r    r!   r&   k   s   zVADController._startc                    s>   |  |j| jI dH | _| jtjkr| dI dH  dS dS )a   Process an audio chunk and emit speech events as needed.

        Analyzes the audio for voice activity and triggers `on_speech_started`,
        `on_speech_stopped`, or `on_speech_activity` events based on state changes.

        Args:
            frame: Audio frame to process.
        Nr   )_handle_vadaudior   r   SPEAKING_call_event_handlerr+   r    r    r!   r'   p   s
   	zVADController._handle_audior0   	vad_statereturnc                    sn   | j |I dH }||kr5|tjkr5|tjkr5|tjkr&| dI dH  n|tjkr3| dI dH  |}|S )zGHandle Voice Activity Detection results and trigger appropriate events.Nr   r   )r   analyze_audior   STARTINGSTOPPINGr1   r2   r   )r   r0   r3   new_vad_stater    r    r!   r/   ~   s   



zVADController._handle_vadc                    s<   t   | j }|| jkrt   | _| dI dH  dS dS )zHandle user speaking frame.r   N)timer   r   r2   )r   	diff_timer    r    r!   _maybe_speech_activity   s   

z$VADController._maybe_speech_activity	directionc                    s   |  d||I dH  dS )a-  Request a frame to be pushed through the pipeline.

        This emits an on_push_frame event that must be handled by a processor
        to actually push the frame into the pipeline.

        Args:
            frame: The frame to push.
            direction: The direction to push the frame.
        r   Nr2   )r   r"   r<   r    r    r!   
push_frame   s   
zVADController.push_frame	frame_clsc                    s    | j d|fi |I dH  dS )a[  Request a frame to be broadcast upstream and downstream.

        This emits an on_broadcast_frame event that must be handled by a processor
        to actually broadcast the frame in the pipeline.

        Args:
            frame_cls: The class of the frame to broadcast.
            **kwargs: Arguments to pass to the frame constructor.
        r   Nr=   )r   r?   kwargsr    r    r!   r*      s   
zVADController.broadcast_frame)__name__
__module____qualname____doc__r   floatr   r   r,   r   r&   r   r'   bytesr   r/   r;   r
   
DOWNSTREAMr>   r   r*   __classcell__r    r    r   r!   r      s    %r   )rD   r9   typingr   pipecat.audio.vad.vad_analyzerr   r   pipecat.frames.framesr   r   r   r   r	   "pipecat.processors.frame_processorr
   pipecat.utils.base_objectr   r   r    r    r    r!   <module>   s   