o
    ìcj                     @  s   U d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	 e
eZde	 ZG dd dZdddZdddZdddZi Zded< dddZdS ) z@Ambiente de oficina (loop) mezclado en el RTP hacia el llamante.    )annotationsN)Path)SAMPLES_PER_PACKET   c                   @  sB   e Zd ZdZdddd
dZedddZdddZdddZdS )AmbienceLoopu:   Audio µ-law 8 kHz en loop, con ganancia y mezcla con TTS.g
ףp=
?gainulawbytesr   floatreturnNonec                C  s\   |st dt|t }|r|dt|   }|| _tdtdt|| _d| _t|| _	d S )Nu   Ambience vacíor   g        g      ?r   )

ValueErrorlenr   _ulawmaxminr   _gain_offset_n)selfr	   r   rem r   8/var/www/html/bot-asterisk-ari/backend/media/ambiance.py__init__   s   zAmbienceLoop.__init__c                 C  s
   | j d S )N     @@)r   )r   r   r   r   
duration_s!   s   
zAmbienceLoop.duration_sc                 C  s   | j t }|| jkr| j| j | }|| j | _ n| j| j d }tt| }| jd| }|| }|| _ | jdkr<|S | jdkrCtS t|| jS )z-Siguiente frame de ambiente atenuado (20 ms).Ng+?gMbP?)r   r   r   r   r   r   _SILENCE_FRAMEattenuate_ulaw)r   endchunkfirstneedsecondr   r   r   
next_frame%   s   



zAmbienceLoop.next_frametts_ulawc                 C  sL   t |tk r|dtt |   }nt |tkr|dt }|  }t||S )z7Mezcla un frame TTS con el siguiente frame de ambiente.r   N)r   r   r$   mix_ulaw)r   r%   bgr   r   r   mix_with_tts8   s   
zAmbienceLoop.mix_with_ttsN)r	   r
   r   r   r   r   )r   r   )r   r
   )r%   r
   r   r
   )	__name__
__module____qualname____doc__r   propertyr   r$   r(   r   r   r   r   r      s    
r   r	   r
   r   r   r   c                 C  s&   t | d}t |d|}t |dS )N   )audioopulaw2linmullin2ulaw)r	   r   pcmr   r   r   r   B   s   r   abc                 C  s   t t| t|}t| |k r| d|t|    } t||k r)|d|t|   }t| d}t|d}z	t||d}W n tjy]   t|dd}t|dd}t||d}Y nw t|dS )u,   Suma PCM con recorte suave vía audioop.add.r   r.   gffffff?)r   r   r/   r0   adderrorr1   r2   )r4   r5   npapbmixedr   r   r   r&   H   s   r&   pathr   c                 C  sP  |   } |  std|  | j dkr%|  }|s#td|  |S | | jd }| rP| j	|  j	krP| j
dkrPtd|| j
 | S td|  tjddd	t| d
dddddt|gdddd}|jdks~| r~| j
dkr|jp|jpddd }td|  d| | }td| j|jt|d  |S )uF   Carga µ-law 8 kHz; convierte con ffmpeg si hace falta y cachea .ulaw.zAmbience no encontrado: z.ulawu   Archivo ulaw vacío: r   z"Ambience cache ulaw: %s (%d bytes)u(   Convirtiendo ambience a µ-law 8 kHz: %sffmpegz-yz-iz-ar8000z-ac1z-fmulawTF)capture_outputtextcheck iNu   ffmpeg falló al convertir z: u"   Ambience listo: %s → %s (%.1f s)r   )resolveis_fileFileNotFoundErrorsuffixlower
read_bytesr   with_suffixstatst_mtimest_sizeloggerinfo
subprocessrunstr
returncodestderrstdoutRuntimeErrornamer   )r<   datacacheresulterrr   r   r   load_ambience_ulaw[   sX    
r]   zdict[str, bytes]_cachedc                C  s0   t |  }|tvrt| t|< tt| |dS )Nr   )rS   rE   r^   r]   r   )r<   r   keyr   r   r   get_ambience_loop   s   r`   )r	   r
   r   r   r   r
   )r4   r
   r5   r
   r   r
   )r<   r   r   r
   )r<   r   r   r   r   r   )r,   
__future__r   r/   loggingrQ   pathlibr   media.rtp_sessionr   	getLoggerr)   rO   r   r   r   r&   r]   r^   __annotations__r`   r   r   r   r   <module>   s    

0

6