o
    0i@                     @  sP  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	m
Z
 ddlZddlZddlmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZ ddlm Z m!Z!m"Z" dd	l#m$Z$ e%e&Z'd8d9ddZ(d:ddZ)d;ddZ*d8d<ddZ+d=ddZ,		d>d?d"d#Z-d@d%d&Z.			dAdBd)d*Z/dCd+d,Z0dDd.d/Z1dEd2d3Z2dFd6d7Z3dS )GzModel loading and voice style management utilities.

This module handles downloading, loading, and managing Supertonic TTS models
and voice styles from HuggingFace Hub.
    )annotationsN)Path)OptionalUnion   )CFG_REL_PATHDEFAULT_CACHE_DIRDEFAULT_INTER_OP_NUM_THREADSDEFAULT_INTRA_OP_NUM_THREADSDEFAULT_MODEL_REPODEFAULT_MODEL_REVISIONDEFAULT_ONNX_PROVIDERSDP_ONNX_REL_PATHTEXT_ENC_ONNX_REL_PATHUNICODE_INDEXER_REL_PATHVECTOR_EST_ONNX_REL_PATHVOCODER_ONNX_REL_PATHVOICE_STYLES_DIRget_model_cache_dirget_model_repo)Style
SupertonicUnicodeProcessor)validate_voice_style_format
model_nameOptional[str]returnr   c                 C  s<   | dur	t | }ntt}|jddd td|  |S )a  Get or create the cache directory for Supertonic models.

    Args:
        model_name: Model name ("supertonic" or "supertonic-2").
            If None, uses default cache directory.

    Returns:
        Path object pointing to the cache directory

    Note:
        Default location is ~/.cache/supertonic2, but can be overridden
        with SUPERTONIC_CACHE_DIR environment variable
    NT)parentsexist_okzUsing cache directory: )r   r   r   mkdirloggerdebug)r   	cache_dir r#   K/home/kim/smarthome/.venv/lib/python3.10/site-packages/supertonic/loader.pyget_cache_dir)   s   
r%   
list[Path]c                   C  s   t tttgS )zGet list of all required ONNX model file paths.

    Returns:
        List of Path objects for each required ONNX model file
    )r   r   r   r   r#   r#   r#   r$   "get_all_onnx_module_relative_paths@   s
   r'   	model_dirUnion[Path, str]boolc                   s\   t  tr	t n  t }t fdd|D }|s, fdd|D }td|  |S )zCheck if all required ONNX model files exist in the directory.

    Args:
        model_dir: Directory to check for model files (str or Path)

    Returns:
        True if all required ONNX files exist, False otherwise
    c                 3  s    | ]	} |   V  qd S N)exists.0pathr(   r#   r$   	<genexpr>Y   s    z'has_all_onnx_modules.<locals>.<genexpr>c                   s    g | ]} |   st|qS r#   )r,   strr-   r0   r#   r$   
<listcomp>\   s     z(has_all_onnx_modules.<locals>.<listcomp>zMissing ONNX files: )
isinstancer2   r   r'   allr    r!   )r(   Zmodule_rel_pathsZ	all_existmissingr#   r0   r$   has_all_onnx_modulesN   s   	r7   Nonec                 C  sz  t | tr	t| n| } |durt|}nt}| jd| j d }z=ddlm} t	
d| d|  ||t|td |  rLt	
d	|   t|  tt|t|  t	
d
 W dS  tys } z
t	d td|d}~w ty } z>t	d|  | rt	
d zt| W n ty } zt	d|  W Y d}~nd}~ww td| d| |d}~ww )a  Download Supertonic model from HuggingFace Hub.

    Args:
        model_dir: Directory where the model should be downloaded (str or Path)
        model_name: Model name ("supertonic" or "supertonic-2").
            If None, uses default model repository.
    N.z.tmpr   )snapshot_downloadzDownloading model from z to temporary location: )repo_idZ	local_dirrevisionz#Removing existing model directory: z%Model download completed successfullyzhuggingface_hub not installedzUFailed to import huggingface_hub. Please install it with: pip install huggingface-hubzModel download failed: zCleaning up temporary files...z$Failed to clean up temporary files: zFailed to download model from z>. Please check your internet connection and try again. Error: )r4   r2   r   r   r   parentnameZhuggingface_hubr:   r    infor   r,   shutilrmtreemoveImportErrorerrorRuntimeError	Exceptionwarning)r(   r   r;   temp_dirr:   eZcleanup_errorr#   r#   r$   download_modelb   sR   



rJ   dictc              
   C  s   t | tr	t| n| } | t }| s#td|  td| dz%t|d}t	
|}W d   n1 s9w   Y  td|  |W S  t	jyf } ztd|  td| d	|d}~ww )
zLoad model configuration from JSON file.

    Args:
        model_dir: Directory containing the model files (str or Path)

    Returns:
        Dictionary containing model configuration
    zConfig file not found: z&Model configuration file not found at 1. Please ensure the model is properly downloaded.rNzLoaded config from zInvalid config format: z)Model configuration file is malformed at z. Please re-download the model.)r4   r2   r   r   r,   r    rD   FileNotFoundErroropenjsonloadr!   JSONDecodeError
ValueError)r(   Zcfg_pathfcfgsrI   r#   r#   r$   load_configs   s,   	

rV   intra_op_num_threadsOptional[int]inter_op_num_threads]tuple[ort.InferenceSession, ort.InferenceSession, ort.InferenceSession, ort.InferenceSession]c                   s\  dd	d
}t  }t jj|_t jj|_|dur|nt}|dur!|nt	}|dur*||_
|dur1||_t}t    fdd|D }|sOtd| d dg}ntd|  d|dur^|nd d|durg|nd }	td|	  | t }
| t }| t }| t }td|  ||
||}||||}||||}||||}td ||||fS )a0  Load all ONNX model modules for TTS synthesis.

    Args:
        model_dir: Directory containing the ONNX model files (str or Path)
        intra_op_num_threads: Number of threads for intra-op parallelism.
            None (default) lets ONNX Runtime auto-detect optimal value
        inter_op_num_threads: Number of threads for inter-op parallelism.
            None (default) lets ONNX Runtime auto-detect optimal value

    Returns:
        Tuple of (duration_predictor, text_encoder, vector_estimator, vocoder)
        ONNX Runtime inference sessions
    	onnx_pathr   optsort.SessionOptions	providers	list[str]r   ort.InferenceSessionc                 S  s8   |   std|  dtd|   tj| ||dS )zLoad a single ONNX model file.zONNX model file not found: rL   zLoading ONNX model: )Zsess_optionsr^   )r,   rN   r    r!   ortZInferenceSession)r[   r\   r^   r#   r#   r$   
_load_onnx   s   
z%load_onnx_modules.<locals>._load_onnxNc                   s   g | ]}| v r|qS r#   r#   )r.   pZavailable_providersr#   r$   r3      s    z%load_onnx_modules.<locals>.<listcomp>zRequested providers z4 not available. Falling back to CPUExecutionProviderZCPUExecutionProviderzUsing ONNX providers: zintra_threads=autoz, inter_threads=zONNX Runtime config: z$Loading ONNX models with providers: z#Successfully loaded all ONNX models)r[   r   r\   r]   r^   r_   r   r`   )ra   ZSessionOptionsZGraphOptimizationLevelZORT_ENABLE_ALLZgraph_optimization_levelZExecutionModeZORT_SEQUENTIALZexecution_moder
   r	   rW   rY   r   Zget_available_providersr    rG   r?   r   r   r   r   )r(   rW   rY   rb   r\   Zintra_threadsZinter_threadsr^   Zvalid_providersthread_infoZdp_onnx_pathZtext_enc_onnx_pathZvector_est_onnx_pathZvocoder_onnx_pathdp_orttext_enc_ortvector_est_ortvocoder_ortr#   rd   r$   load_onnx_modules   sJ   




rk   r   c                 C  s>   t | tr	t| n| } | t }td|  tt|}|S )zLoad the unicode text processor for the model.

    Args:
        model_dir: Directory containing the model files (str or Path)

    Returns:
        Initialized UnicodeProcessor instance
    zLoading text processor from )r4   r2   r   r   r    r!   r   )r(   Zunicode_indexer_pathtext_processorr#   r#   r$   load_text_processor  s
   	rm   auto_downloadr   c                 C  s   t d|   t| trt| n| } t| s.|s)t d|   td|  dt| | t	| }t
| ||\}}}}	t| }
t d t||
||||	S )a  Load the complete Supertonic TTS model.

    This function loads all model components including ONNX modules,
    configuration, and text processor. If model files are missing and
    auto_download is enabled, it will download them from HuggingFace Hub.

    Args:
        model_dir: Directory containing (or to contain) the model files (str or Path)
        auto_download: If True, automatically download missing model files
        intra_op_num_threads: Number of threads for intra-op parallelism.
            None (default) lets ONNX Runtime auto-detect optimal value
        inter_op_num_threads: Number of threads for inter-op parallelism.
            None (default) lets ONNX Runtime auto-detect optimal value
        model_name: Model name ("supertonic" or "supertonic-2").
            Used for downloading the correct model if auto_download is True.

    Returns:
        Initialized Supertonic TTS engine
    zLoading model from zONNX models not found in zONNX model files not found in zz. Set auto_download=True to automatically download from HuggingFace Hub, or manually download the model to this directory.zModel loaded successfully)r    r?   r4   r2   r   r7   rD   rN   rJ   rV   rk   rm   r   )r(   rn   rW   rY   r   rU   rg   rh   ri   rj   rl   r#   r#   r$   
load_model'  s    


ro   c                 C  sv   t | tr	t| n| } | t }| s#td|  td| dtt	|
d}tdt| d|  |S )zList all available voice style JSON files in the model directory.

    Args:
        model_dir: Directory containing the model files (str or Path)

    Returns:
        Sorted list of paths to voice style JSON files
    z"Voice styles directory not found: z$Voice styles directory not found at rL   z*.jsonzFound z voice styles in )r4   r2   r   r   r,   r    rD   rN   sortedlistglobr!   len)r(   Zvoice_styles_dirpathsr#   r#   r$    list_available_voice_style_pathsX  s   	
ru   r_   c                 C  s   t | }dd |D }|S )zList names of all available voice styles.

    Args:
        model_dir: Directory containing the model files (str or Path)

    Returns:
        List of voice style names (without .json extension)
    c                 S  s   g | ]}|j qS r#   )stemr-   r#   r#   r$   r3   z  s    z4list_available_voice_style_names.<locals>.<listcomp>)ru   )r(   Zvoice_style_pathsnamesr#   r#   r$    list_available_voice_style_namesp  s   	rx   voice_style_pathr   c              
   C  s&  t | } ddd}|  std|  z@t| d}t|}W d	   n1 s*w   Y  t|s;td
|  dt	d|   ||d }||d }t
||W S  tjyr } ztd|  td|  d|d	}~w ttfy } ztd|  td|  d| |d	}~ww )zLoad a voice style from a JSON file.

    Args:
        voice_style_path: Path to the voice style JSON file (str or Path)

    Returns:
        Style object with loaded style vectors
    	json_datarK   r   
np.ndarrayc              
   S  sR   z| d }| d }t j|t jdj| W S  ty( } ztd| |d}~ww )z"Parse style vector from JSON data.dimsdata)Zdtypez"Invalid style format: missing key N)nparrayZfloat32ZreshapeKeyErrorrS   )rz   r|   r}   rI   r#   r#   r$   _load_style_from_json  s   z>load_voice_style_from_json_file.<locals>._load_style_from_jsonzVoice style file not found: rM   NzInvalid voice style format in zD. Expected 'style_ttl' and 'style_dp' with 'dims' and 'data' fields.zLoading voice style from Z	style_ttlZstyle_dpz"Invalid JSON in voice style file: z!Voice style file is malformed at z. Please check the file format.zInvalid voice style format: z'Voice style file has invalid format at z5. Expected 'style_ttl' and 'style_dp' fields. Error: )rz   rK   r   r{   )r   r,   rN   rO   rP   rQ   r   rS   r    r!   r   rR   rD   r   )ry   r   rT   Zvoice_style_jsonZ	ttl_styleZdp_stylerI   r#   r#   r$   load_voice_style_from_json_file~  sF   

	

r   
voice_namer2   c                 C  sl   t | tr	t| n| } | t | d }| s2t| }td| d td| dd	| t
|S )a  Load a voice style by name from the model directory.

    Args:
        model_dir: Directory containing the model files (str or Path)
        voice_name: Name of the voice style (without .json extension)

    Returns:
        Style object with loaded style vectors
    z.jsonzVoice style 'z' not foundz%' not found. Available voice styles: z, )r4   r2   r   r   r,   rx   r    rD   rN   joinr   )r(   r   ry   	availabler#   r#   r$   load_voice_style_from_name  s   
r   r+   )r   r   r   r   )r   r&   )r(   r)   r   r*   )r(   r)   r   r   r   r8   )r(   r)   r   rK   )NN)r(   r)   rW   rX   rY   rX   r   rZ   )r(   r)   r   r   )NNN)r(   r)   rn   r*   rW   rX   rY   rX   r   r   r   r   )r(   r)   r   r&   )r(   r)   r   r_   )ry   r)   r   r   )r(   r)   r   r2   r   r   )4__doc__
__future__r   rP   loggingr@   pathlibr   typingr   r   numpyr~   Zonnxruntimera   configr   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   corer   r   r   utilsr   	getLogger__name__r    r%   r'   r7   rJ   rV   rk   rm   ro   ru   rx   r   r   r#   r#   r#   r$   <module>   s<    D



9"
\
1

7