
    @i                     D   d Z ddlZddlZddlmZ ddlmZmZ ddlZ	ddl
mZ ddlmZ  ee                                          j        d         dz  Zd	efd
Zdeded	efdZ	 ddedededed	ef
dZdededededed	eee         ee         f         fdZded	efdZdS )u   说话人匹配服务。

职责概览：
- 对单段 PCM 音频执行 speaker 匹配/注册并返回 rl 与相似度。
- 提供 AudioSegment 到 PCM 原始字节的转换方法，供流水线调用。
    N)Path)OptionalTuple)AudioSegment   )SpeakerRegistryzgzzm_config.jsonreturnc                      	 t                               dd          5 } t          j        |           cd d d            S # 1 swxY w Y   d S # t          $ r i cY S w xY w)Nrzutf-8)encoding)_config_pathopenjsonload	Exception)_fs    $src\gzzm\services\speaker_matcher.py_load_gzzm_configr      s    sW55 	!9R==	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	! 	!   			s1   A ?A AA AA AAvaluedefaultc                    t          | t                    r| S t          | t                    r2|                                                                 }|dv rdS |dv rdS t          | t
          t          f          rt          |           S |S )N)1trueyesonT)0falsenooffF)
isinstanceboolstrstriplowerintfloat)r   r   vs      r   _to_boolr(      s    % % KKMM!!***4+++5%#u&& E{{N          @	pcm_bytessample_ratechannelstarget_secondsc           
         | s| S |dk    s|dk    r| S t          dt          |                    }t          t          |t          |          z                      }t	          j        | t          j                  }|j        |z  |z  }|dk    r| S ||j        k    r
|d|         }||z  }||k    r|                                S |	                    d|          
                    t          j                                      d          dz  }t          dt          t          t          |          d	z                                }	|j        |	z  }
|
d
k     r|                                S |d|
|	z           }|	                    |
|	          }t	          j        t	          j        t	          j        |          d          dz             }t          t	          j        |d                    }t          t	          j        |d                    }t          d|dt          d||z
            z  z             }||k    
                    t          j                  }t          d||	z            }||
k    r|                                S t	          j        dgt	          j        |          f          }t	          j        dgt	          j        |          f          }||d         |d|          z
  t          |          z  }||d         |d|          z
  t          |          z  }t	          j        |t          |d          z  dd          }d|z  d|z  z   }t          t	          j        |                    }||	z  }t)          |||z             }||z  }||z  }||k    r|                                S |||                                         S )ub   从完整 PCM 中选择信息量更高的窗口（优先配置时长，不足则返回全段）。r   g?)dtypeN   )axisg      @g{Gz?r   g-q=   _   g-C6?g?g        g:0yE>g      ?gffffff?g333333?)maxr&   r%   roundnp
frombufferint16sizetobytesreshapeastypefloat32meansqrtsquare
percentileconcatenatecumsumclipargmaxmin)r+   r,   r-   r.   target_samplespcmusabletotal_samplesmonoframe_samplesframe_counttrimmedframesrmsnoise_floorpeakactivity_thresholdactivitywindow_frames
c_activityc_rmsactive_ratiomean_rmsnorm_energyscore
best_framestart_sample
end_sample	start_i16end_i16s                                 r   #_select_most_informative_pcm_windowrc   +   s     a8q==eN3344N~k0B0BBCCDDN
-	
2
2
2Ch("h.F{{'6'lh&M&&{{}};;r8$$++BJ77<<!<DDwND3uU;%7%7$%>??@@AAM)},KQ{{}}0[=001G__[-88F
'"'")F++!444u<
=
=Cc2..//KsB''((DT;s3{@R7S7S1S#STT))11"*==H>]:;;M##{{}} #	((;(; <==JNSE29S>>233E}~~.Om^O1LLPUVcPdPddLmnn%o~o(>>%BVBVVH'(St__4c3??K<C+$56ERYu%%&&J-L]L>$ABBJx'I8#G){{}}y !))+++r)   registrydevicec                    | sdS t                      }	 t          |                    dd                    }n# t          $ r d}Y nw xY w	 t          |                    dd                    }n# t          $ r d}Y nw xY wt	          |                    dd          d          }	 t          |                                                    dd	                    }	n# t          $ r d	}	Y nw xY w|	d	k    r|}
d}n|}
|rt          | |||

          }n| }	 |                    ||||d          }n# t          $ r Y dS t          $ r Y dS w xY wt          |t                    st          |          dfS t          |          d	k    r|d	         nd}t          |          dk    r|d         nd}|dv rdS 	 |t          |          nd}n# t          $ r d}Y nw xY wt          |          |fS )u|  为单段 PCM 音频识别或注册说话人 ID。

    参数:
    - pcm_bytes (bytes): 原始 PCM 音频数据（假定 16-bit、每样本 2 字节、交错声道）。
    - sample_rate (int): 采样率（Hz）。
    - channels (int): 声道数。
    - registry (SpeakerRegistry): 用于匹配/注册说话人的注册器实例。
    - device (str): 设备标识（传递给 registry）。

    返回:
    - Tuple[Optional[str], Optional[float]]: (speaker_id, similarity)
      - speaker_id: 匹配或新注册的说话人 ID（字符串），无法匹配或出错时为 None。
      - similarity: 相似度分数（浮点），如果不可用则为 None。

    实现细节:
    - 若 `pcm_bytes` 为空，函数会直接返回 (None, None)。
    - 时长通过 `len(pcm_bytes) / (sample_rate * channels * 2)` 估算（假定每样本 2 字节）。
    - 可通过配置 `speaker_use_informative_window` 开关控制是否启用“信息量窗口挑选”。
    - 当输入长于配置窗口 `speaker_match_window_seconds` 时，会先自动挑选信息量更高的窗口（尽量避开静音）再做匹配。
    - 当输入短于配置窗口时，会使用实际可用的整段音频做匹配（不会因“最短阈值”跳过）。
    - 调用 `registry.register_or_match(...)` 获取匹配结果；若抛出 ImportError 或其他异常，函数会捕获并返回 (None, None)。
    )NNspeaker_match_window_secondsr*    speaker_initial_baseline_secondsg      $@speaker_use_informative_windowTcountr   )r+   r,   r-   r.   )r,   r-   re   
return_simNr2   )Nr1   )r   r&   getr   r(   r%   statsrc   register_or_matchImportErrorr    tupler"   len)r+   r,   r-   rd   re   cfgdefault_match_secondsinitial_baseline_secondsuse_informative	reg_countr.   pcm_for_matchmatchedcand_idcand_simsims                   r   identify_speaker_id_from_pcmr|   m   s   :  z


C$ %cgg.Lc&R&R S S $ $ $ #$(#(1SUY)Z)Z#[#[   ( ( (#'   (sww'GNNPTUUO((,,Wa8899		   			A~~1. ";#)	
 
 
 ",,# - 
 
    zz   zz gu%% "7||T!!LL1,,gajj$G \\A--wqzz4H*z!)!5eHooo4    w<<s]   #8 AA#A/ /A>=A>&5C C+*C+D/ /
E	<	E	E	3G GGsegmentc                 ~    t          j                    }|                     |d           |                                S )u$  将 pydub `AudioSegment` 导出为原始 PCM 字节序列（raw 格式）。

    返回的 bytes 为原始 PCM 数据；调用者可通过 `segment.frame_rate`、`segment.channels`、
    `segment.sample_width` 获取对应的音频元信息（采样率、声道数、样本宽度）。
    raw)format)ioBytesIOexportgetvalue)r}   bufs     r   audio_segment_to_pcm_bytesr      s3     *,,CNN3uN%%%<<>>r)   )r*   )__doc__r   r   pathlibr   typingr   r   numpyr8   pydubr   utils.speaker_idr   __file__resolveparentsr   dictr   objectr!   r(   bytesr%   r&   rc   r"   r|   r    r)   r   <module>r      s    
			        " " " " " " " "           . . . . . .tH~~%%''/25GG4    F T d    (  	?, ?,?,?, ?, 	?,
 ?, ?, ?, ?,D\\\ \ 	\
 \ 8C=(5/)*\ \ \ \~       r)   