o
    y	i1                     @   s   d Z ddlZddlZddlZddlmZmZmZ ddl	m
Z
 ddlmZ ddlmZ e
G dd dZG d	d
 d
ZG dd dZdS )zf
Audio Noise Processing Service
Handles background noise detection, filtering, and speech enhancement
    N)OptionalTupleList)	dataclass)Log)Configc                   @   sB   e Zd ZU dZeed< eed< eed< eed< eed< eed< dS )	AudioAnalysiszAudio analysis resultsvolume_level	is_speech
confidencenoise_leveldurationhas_background_noiseN)__name__
__module____qualname____doc__float__annotations__bool r   r   services/audio_noise_service.pyr      s   
 r   c                   @   s  e Zd ZdZdd Zd'dededefdd	Zd
ede	fddZ
ded
edefddZdedejfddZdejdefddZdejdefddZdejdedee	ef fddZdejdefddZdejdedede	fddZd(dejdedejfd d!Zd)dejd#edejfd$d%Zd&S )*AudioNoiseProcessorz
    Handles audio noise detection and basic filtering.
    Provides volume analysis, speech detection, and noise level assessment.
    c                 C   s6   t j| _t j| _t j| _t j| _t	
d| j  d S )Nu2   🔇 Audio Noise Processor initialized - Enabled: )r   AUDIO_NOISE_REDUCTION_ENABLEDenabledZAUDIO_VOLUME_THRESHOLDvolume_thresholdZBACKGROUND_NOISE_TOLERANCEnoise_thresholdZNOISE_CONFIDENCE_THRESHOLDconfidence_thresholdr   infoselfr   r   r   __init__    s
   zAudioNoiseProcessor.__init__@  audio_bytessample_ratereturnc                 C   s   | j stddddt||d  ddS z/| |}t|| }| |}| ||\}}| |}| |||}	t||||||	dW S  tyf }
 zt	
d|
  tdddddddW  Y d}
~
S d}
~
ww )	a  
        Analyze audio for noise, volume, and speech characteristics.
        
        Args:
            audio_bytes: Raw audio bytes
            sample_rate: Sample rate in Hz
            
        Returns:
            AudioAnalysis object with analysis results
              ?T           F)r	   r
   r   r   r   r   u   ❌ Error analyzing audio: N)r   r   len_bytes_to_numpy_calculate_volume_detect_speech_calculate_noise_level_detect_background_noise	Exceptionr   error)r    r#   r$   
audio_datar   r	   r
   r   r   r   er   r   r   analyze_audio(   sH   	


	z!AudioNoiseProcessor.analyze_audioanalysisc                 C   s   | j sdS |j| jk rtd|jdd| j  dS |js*td|jd dS |jrC|j| j	krCtd|jdd| j	  dS dS )	z
        Determine if audio should be processed based on analysis.
        
        Args:
            analysis: Audio analysis results
            
        Returns:
            True if audio should be processed
        Tu   🔇 Audio volume too low: .3fz < Fu.   🔇 Audio not detected as speech: confidence u    🔇 Too much background noise: z > )
r   r	   r   r   debugr
   r   r   r   r   )r    r4   r   r   r   should_process_audiob   s   
z(AudioNoiseProcessor.should_process_audioc              
   C   sx   | j r|js|S z| |}| |}| ||j}| |W S  ty; } zt	d|  |W  Y d}~S d}~ww )z
        Apply basic audio filtering based on analysis.
        
        Args:
            audio_bytes: Raw audio bytes
            analysis: Audio analysis results
            
        Returns:
            Filtered audio bytes
        u   ❌ Error filtering audio: N)
r   r   r*   _apply_high_pass_filter_normalize_volumer	   _numpy_to_bytesr/   r   r0   )r    r#   r4   r1   Zfiltered_datar2   r   r   r   filter_audio   s   

z AudioNoiseProcessor.filter_audioc                 C   s,   t dt|d  d|}tj|tjdS )z#Convert audio bytes to numpy array.<r(   h)Zdtype)structunpackr)   npZarrayZfloat32)r    r#   r1   r   r   r   r*      s   z#AudioNoiseProcessor._bytes_to_numpyr1   c                 C   s4   t |ddt j}tjdt| dg|R  S )z(Convert numpy array back to audio bytes.   r<   r=   )r@   clipZastypeZint16r>   Zpackr)   )r    r1   r   r   r   r:      s   z#AudioNoiseProcessor._numpy_to_bytesc                 C   s2   t |dkrdS tt|d }t|d dS )zCalculate RMS volume level.r   r'   r(   g      @r&   )r)   r@   Zsqrtmeanmin)r    r1   Zrmsr   r   r   r+      s   z%AudioNoiseProcessor._calculate_volumer	   c                 C   s   t |dkrdS d}|| jkr|d7 }tj|}tjt |}t|dkt|dk@ }tt|| }tt|}|dkrQ|| }	|	dkrQ|d7 }|| jk}
|
|fS )	zy
        Detect if audio contains speech.
        
        Returns:
            Tuple of (is_speech, confidence)
        r   )Fr'   r'   g?g333333?g333333?g333333?g333333?)r)   r   r@   fftfftfreqabssumr   )r    r1   r	   r   rF   freqsZspeech_freq_maskZspeech_energytotal_energyZspeech_ratior
   r   r   r   r,      s    

z"AudioNoiseProcessor._detect_speechc                 C   sr   t |dkrdS tj|}tjt |}t|dk}tt|| }tt|}|dkr7|| S dS )z!Calculate background noise level.r   r'         ?)r)   r@   rF   rG   rH   rI   )r    r1   rF   rJ   Znoise_freq_maskZnoise_energyrK   r   r   r   r-      s   z*AudioNoiseProcessor._calculate_noise_levelr   c           	      C   s   |dkrdS |dkr|dkrdS t j|}t jt|}t |}g }tdt|d D ](}|| ||d  krV|| ||d  krV|| t |d krV|||  q.t|dkS )z1Detect if audio has significant background noise.g?TrL   g?   r(      )r@   rF   rG   r)   rH   rangerD   append)	r    r1   r	   r   rF   rJ   Z	magnitudeZpeaksir   r   r   r.      s   
(z,AudioNoiseProcessor._detect_background_noise     r@cutoff_freqc                 C   sn   t dt j | d }t |}|d |d< tdt|D ]}|||d  ||  ||d    ||< q|S )z<Apply simple high-pass filter to reduce low-frequency noise.r"   r   rM   )r@   ZexpZpiZ
zeros_likerO   r)   )r    r1   rS   ZalphaZfilteredrQ   r   r   r   r8     s   
*z+AudioNoiseProcessor._apply_high_pass_filterrL   target_volumec                 C   sD   t |dkr|S | |}|dkr|S || }|| }t|ddS )z'Normalize audio volume to target level.r   rA   rB   )r)   r+   r@   rC   )r    r1   rU   Zcurrent_volumeZscale_factorZ
normalizedr   r   r   r9     s   
z%AudioNoiseProcessor._normalize_volumeN)r"   )rR   )rL   )r   r   r   r   r!   bytesintr   r3   r   r7   r;   r@   Zndarrayr*   r:   r   r+   r   r,   r-   r.   r8   r9   r   r   r   r   r      s    : 
" r   c                   @   s2   e Zd ZdZdd Zdededee fddZd	S )
AudioNoiseServicezl
    Main service for handling audio noise processing.
    Integrates with the existing audio pipeline.
    c                 C   s&   t  | _tj| _td| j  d S )Nu0   🔇 Audio Noise Service initialized - Enabled: )r   	processorr   r   r   r   r   r   r   r   r   r!   *  s   zAudioNoiseService.__init__r#   
session_idr%   c                 C   s   | j s|S zO| j|}td| d|jdd|j d|jdd|jdd|j	  | j
|s=td| d	 W d
S |j	rR| j||}td|  |W S |W S  tys } ztd| d|  |W  Y d
}~S d
}~ww )a  
        Process audio chunk for noise reduction.
        
        Args:
            audio_bytes: Raw audio bytes
            session_id: Session ID for logging
            
        Returns:
            Processed audio bytes or None if should be skipped
        u    🔇 Audio analysis for session z
: Volume: r5   z
, Speech: z, Confidence: z	, Noise: z, Background: u&   🔇 Skipping audio chunk for session z - failed quality checksNu)   🔇 Applied noise filtering for session u-   ❌ Error processing audio chunk for session z: )r   rY   r3   r   r6   r	   r
   r   r   r   r7   r;   r/   r0   )r    r#   rZ   r4   Zfiltered_audior2   r   r   r   process_audio_chunk0  s8   z%AudioNoiseService.process_audio_chunkN)	r   r   r   r   r!   rV   strr   r[   r   r   r   r   rX   $  s    rX   )r   ior>   Znumpyr@   typingr   r   r   Zdataclassesr   Zservices.log_utilsr   Zconfigr   r   r   rX   r   r   r   r   <module>   s    
  