
    /cjp                     b   d Z ddlZddlZej                            ej                            ej                            e                    dd          Z e	ej
                            dd                    Z e	ej
                            dd                    Zd	 Z G d
 d          ZdS )uw  
Server-side streaming noise suppression (pre-processor for the caller audio
that is forwarded to DashScope). Fully isolated and fail-open:

  - If disabled, or the model / onnxruntime is unavailable, or ANY error
    occurs, audio passes through UNCHANGED — the call is never affected.
  - DashScope's own VAD/turn-detection is untouched; this only improves the
    quality of the audio DashScope receives.

Engine: GTCRN streaming ONNX (16 kHz mono, model-native — no resampling).
The model file is NOT vendored; drop the streaming ONNX into:
    models/gtcrn/  (e.g. models/gtcrn/gtcrn_stream.onnx)
Until it is present, is_active() is False and process() is a pass-through.

The exact frame/hop and cache-tensor names come from the ONNX file itself
(read via onnxruntime introspection at load time), so this wrapper adapts
to the specific artifact rather than hard-coding shapes.
    Nmodelsgtcrn
GTCRN_NFFT512	GTCRN_HOP256c                      t           j                            t                    sd S t	          t          j        t           j                            t          d                              } | r| d         nd S )Nz*.onnxr   )ospathisdir	MODEL_DIRsortedglobjoin)hitss    O/home/m1-ai/DEPLOYMENTS/AI-PHONE/ZACK-UPDATE/fixing_leaked/noise_suppression.py_find_modelr       sW    7==## t$)BGLLH==>>??D$477$    c                   ^    e Zd ZdZdZdZdZdZddZe	d             Z
d Zd Zd	 Zd
 Zd ZdS )NoiseSuppressora(  One instance per session. Streaming, stateful, fail-open.

    Public API:
        is_active()         -> bool  (model loaded & engine enabled)
        process(pcm_bytes)  -> bytes (denoised, or unchanged on any issue)
        reset()             -> None  (clear per-session streaming state)
    NFoffc                     |pd                                 | _        t                      | _        d | _        d| _        d| _        | j        dk    r|                                  d S d S )Nr   Fr   )lowerengine	bytearray_buf_state_active_warned_try_activate)selfr   s     r   __init__zNoiseSuppressor.__init__5   sf    --//KK	;'!!      "!r   c           	         | j         r	| j        duS d| _         	 t                      }|sdt           | _        dS ddl}|                                }d|_        |                    ||dg          }d	 |	                                D             }d
 |
                                D             }d |	                                D             dd         }|| _        |||d         |d         d |D             |dd         |d| _        t          d| d| d| d           dS # t          $ r9}t          |          | _        d| _        t          d| d           Y d}~dS d}~ww xY w)zALoad the ONNX session once, shared across sessions. Never raises.NTzno .onnx in Fr      CPUExecutionProvider)sess_options	providersc                     g | ]	}|j         
S  name.0is     r   
<listcomp>z0NoiseSuppressor._load_shared.<locals>.<listcomp>P   s    888af888r   c                     g | ]	}|j         
S r)   r*   )r-   os     r   r/   z0NoiseSuppressor._load_shared.<locals>.<listcomp>Q   s    :::!qv:::r   c                     g | ]}|S r)   r)   r,   s     r   r/   z0NoiseSuppressor._load_shared.<locals>.<listcomp>T   s    999!A999r   c                 6    g | ]}|j         |j        |j        fS r)   )r+   shapetyper,   s     r   r/   z0NoiseSuppressor._load_shared.<locals>.<listcomp>[   s%     Q Q Qq!&!'16!: Q Q Qr   )input_namesoutput_names
primary_inprimary_outcache_inputscache_out_names
model_pathz$[NoiseSuppress] GTCRN model loaded: z	 (inputs=z
, outputs=)z#[NoiseSuppress] GTCRN unavailable (z%); audio will pass through unchanged.)_load_attempted_shared_sessionr   r   _load_erroronnxruntimeSessionOptionsintra_op_num_threadsInferenceSession
get_inputsget_outputs_shared_metaprint	Exceptionstr)	clsr<   ortsosessinputsoutputsr:   es	            r   _load_sharedzNoiseSuppressor._load_shared?   s     	3&d22""	$J "<"<"<u%%%%##%%B&'B#''12 ( 4 4D 98doo&7&7888F::t'7'7'9'9:::G :9t'8'8999!""=L"&C% '$Qi&qz Q QL Q Q Q#*122;(   C  : : :#: :/6: : : ; ; ;4 	 	 	!!ffCO"&C 8 8 8 8 9 9 955555	s   D# C'D# #
E&-.E!!E&c                     t                                           }t          |          | _        |s-| j        s(d| _        t          dt           j         d           d S d S d S )NTz5[NoiseSuppress] engine=gtcrn requested but inactive (u   ) — pass-through mode.)r   rR   boolr   r   rH   r@   )r!   oks     r   r    zNoiseSuppressor._try_activatei   s    ))++Bxx 	M$, 	MDL L%1L L L M M M M M	M 	M 	M 	Mr   c                 &    | j         o
| j        dk    S )Nr   )r   r   r!   s    r   	is_activezNoiseSuppressor.is_activer   s    |6w 66r   c                 :    t                      | _        d | _        d S )N)r   r   r   rW   s    r   resetzNoiseSuppressor.resetu   s    KK	r   c                     |                                  r|s|S 	 |                     |          S # t          $ r4}| j        sd| _        t	          d| d           d| _        |cY d}~S d}~ww xY w)zDenoise a chunk of 16 kHz mono 16-bit PCM. Returns processed PCM.
        Fail-open: on inactive engine or ANY error, returns pcm_bytes as-is.Tz[NoiseSuppress] runtime error (z&); session falls back to pass-through.FN)rX   _process_streamrI   r   rH   r   )r!   	pcm_bytesrQ   s      r   processzNoiseSuppressor.processy   s     ~~ 	y 			''	222 	 	 	< ># = = = = > > > DL	s   / 
A-)A("A-(A-c                    dd l }t          j        }t          j        }t          dz  }| j                            |           t                      }| j        Fi | _        |d         D ]6\  }}}	d |D             }
|	                    |
|j
                  | j        |<   7t          | j                  |k    rt          | j        d |                   }| j        d |= |                    ||j                                      |j
                  dz  }|d         |                    dd	          i}|                    | j                   |                    |d
         |          }|d                             d	          }t'          |d         d |d         D                       D ]0\  }}|d
                             |          }||         | j        |<   1|                    |dz  dd                              |j                  }|                    |                                           t          | j                  |k    t          |          S )Nr      r:   c                 L    g | ]!}t          |t                    r|d k    rdn|"S )r   r$   )
isinstanceint)r-   ds     r   r/   z3NoiseSuppressor._process_stream.<locals>.<listcomp>   sC     ( ( ( #-Q"4"4FQQ ( ( (r   )dtypeg      @r8   r$   r7   r;   c                     g | ]
}|d          S )r   r)   )r-   cs     r   r/   z3NoiseSuppressor._process_stream.<locals>.<listcomp>   s    )M)M)M1!A$)M)M)Mr   i i  )numpyr   r?   rG   _HOPr   extendr   r   zerosfloat32lenbytes
frombufferint16astypereshapeupdaterunzipindexcliptobytes)r!   r]   nprN   meta	hop_bytesoutr+   r4   _tdimsframesamplesfeedresultsenhancedout_namein_nameidxclippeds                       r   r\   zNoiseSuppressor._process_stream   sJ   .+1H		###kk ;DK#'#7 E EeR( (!&( ( ($&HHTH$D$DD!!$)nn	))$)JYJ/00E	*9*%mmEm::AA"*MMPWWG&2(>(>?DKK$$$hhtN3T::Gqz))"--H%(.?)@)M)M^8L)M)M)M&O &O 4 4!'>*00::'.s|G$$ggh0&%@@GGQQGJJw(())) $)nn	))$ Szzr   )r   )__name__
__module____qualname____doc__r?   rG   r>   r@   r"   classmethodrR   r    rX   rZ   r^   r\   r)   r   r   r   r   '   s          OLOK! ! ! ! ' ' ['RM M M7 7 7    "$ $ $ $ $r   r   )r   r   r
   r   r   dirnameabspath__file__r   rc   environget_N_FFTrj   r   r   r)   r   r   <module>r      s    &  				GLL)B)BCC!7, ,	
 
RZ^^L%00	1	1
s2:>>+u--..% % %G G G G G G G G G Gr   