
    rHJja;                         d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	m
Z
mZ ddlmZ ddlmZ  G d d      Zy)zWrapper on espeak-ng library    N)TupleDict)	EspeakAPI)EspeakVoicec                   F   e Zd ZdZdZdZd Zed        Zed        Z	d Z
defdZed	efd
       Zedefd       Zed        Zd Zedeeeef   fd       Zed        Zed        Zed        Z ej4                  d      dd       Zd Zd ZddededefdZdefdZ y)EspeakWrappera  Wrapper on espeak shared library

    The aim of this wrapper is not to be exhaustive but to encapsulate the
    espeak functions required for phonemization. It relies on a espeak shared
    library (*.so on Linux, *.dylib on Mac and *.dll on Windows) that must be
    installed on the system.

    Use the function `EspeakWrapper.set_library()` before instanciation to
    customize the library to use.

    Raises
    ------
    RuntimeError if the espeak shared library cannot be loaded

    Nc                     d | _         d | _        d | _        t        | j	                         | j
                        | _        d | _        d | _        y N)	_version
_data_path_voicer   library	data_path_espeak_libc_
_tempfile_selfs    k/Users/ahmed/devFolder/claude-voice/.venv/lib/python3.12/site-packages/phonemizer/backend/espeak/wrapper.py__init__zEspeakWrapper.__init__5   sC     *. !@     c                    | j                   nt        j                  dk(  rt        j                  j
                  n;t        j                  j                  t        j                  j                  d            | _         | j                   S )Nwin32c)
r   sysplatformctypeswindllmsvcrtcdllLoadLibraryutilfind_libraryr   s    r   _libczEspeakWrapper._libcC   sX    ;;(+(?$$''(@(@(EF K {{r   c                     | j                   Mt        j                         | _         t        j                  | j                   | j                   j
                         | j                   S r
   )r   tempfileNamedTemporaryFileweakreffinalizecloser   s    r   	_tempfilezEspeakWrapper._tempfileK   sF    ??" '99;DOT__doo.C.CDr   c                 J    | j                   | j                  | j                  dS )z/For pickling, when phonemizing on multiple jobs)versionr   voice)r   r   r   r   s    r   __getstate__zEspeakWrapper.__getstate__T   s#     }}[[" 	"r   statec                 F   | j                          |d   | _        |d   | _        |d   | _        | j                  rgd| j                  j                  v r)| j                  | j                  j                  dd        y| j                  | j                  j                         yy)z1For unpickling, when phonemizing on multiple jobsr-   r   r.   mb   N)r   r   r   r   
identifier	set_voicelanguage)r   r0   s     r   __setstate__zEspeakWrapper.__setstate__[   s    i(,Gn;;t{{---t{{55ab9:t{{334	 r   r   c                     || _         y)a`  Sets the espeak backend to use `library`

        If this is not set, the backend uses the default espeak shared library
        from the system installation.

        Parameters
        ----------
        library (str or None) : the path to the espeak shared library to use as
          backend. Set `library` to None to restore the default.

        N)_ESPEAK_LIBRARYclsr   s     r   set_libraryzEspeakWrapper.set_libraryg   s     &r   r   c                     || _         y)af  Sets the path for the data to be used by the espeak backend.

        If this is not set, the backend uses the default data path from the system installation.

        Parameters
        ----------
        data_path : str
            The path to the data to be used by the espeak backend. Set `data_path` to None
            to restore the default.

        N)_ESPEAK_DATA_PATH)r;   r   s     r   set_data_pathzEspeakWrapper.set_data_pathv   s     !*r   c                    | j                   r| j                   S dt        j                  v ryt        j                  t        j                  d         }|j                         r$t        j                  |t        j                        st        d| d      |j                         S t        j                  j                  d      xs t        j                  j                  d      }|st        d      |S )  Returns the espeak library used as backend

        The following precedence rule applies for library lookup:

        1. As specified by BaseEspeakBackend.set_library()
        2. Or as specified by the environment variable
           PHONEMIZER_ESPEAK_LIBRARY
        3. Or the default espeak library found on the system

        Raises
        ------
        RuntimeError if the espeak library cannot be found or if the
          environment variable PHONEMIZER_ESPEAK_LIBRARY is set to a
          non-readable file

        PHONEMIZER_ESPEAK_LIBRARYzPHONEMIZER_ESPEAK_LIBRARY=z is not a readable filez	espeak-ngespeakzfailed to find espeak library)r9   osenvironpathlibPathis_fileaccessR_OKRuntimeErrorresolver   r"   r#   r:   s     r   r   zEspeakWrapper.library   s    $ &&&&"**4ll2::.I#JKGOO%"))GRWW*E"0	 :- ./ / ??$$ ((5 3((2 	 /1 1r   c                    | j                   j                         \  }}t        j                  |j	                               | _        | j
                  j                         st        d      |j	                         j                         j                  d      d   j                  dd      }t        d |j                  d      D              | _        y)	z9Initializes version and dapa path from the espeak libraryz(failed to retrieve espeak data directory r   z-dev c              3   2   K   | ]  }t        |        y wr
   )int).0vs     r   	<genexpr>z8EspeakWrapper._fetch_version_and_path.<locals>.<genexpr>   s     A.@c!f.@s   .N)r   inforF   rG   decoder   is_dirrK   stripsplitreplacetupler   )r   r-   r   s      r   _fetch_version_and_pathz%EspeakWrapper._fetch_version_and_path   s    !\\..0 ",,y'7'7'9:%%'IJJ .."((*005a8@@LAgmmC.@AAr   returnc                 R    | j                   | j                          | j                   S )z?The espeak version as a tuple of integers (major, minor, patch))r   r]   r   s    r   r-   zEspeakWrapper.version   s$     == ((*}}r   c                 .    | j                   j                  S )z-The espeak library as a pathlib.Path instance)r   library_pathr   s    r   ra   zEspeakWrapper.library_path   s     ||(((r   c                    | j                   rt        j                  | j                         }|j                         r.t	        j
                  | j                   t        j                        st        | j                    d      |j                         | _	        ndt        j                  v r~t        j                  t        j                  d         }|j                         r$t	        j
                  |t        j                        st        d| d      |j                         | _	        | j                  t        | d      r| j                          | j                  S )rA   z is not a readable directoryPHONEMIZER_ESPEAK_DATA_PATHzPHONEMIZER_ESPEAK_DATA_PATH=r   )r>   rF   rG   rX   rD   rI   rJ   rK   rL   r   rE   hasattrr]   )r   r   s     r   r   zEspeakWrapper.data_path   s
   $ !!T%;%;<I$$&299T5K5KRWW+U"d&<&<%==Y#Z[['//1DO*bjj8RZZ0M%NOI$$&299Y+H"29+ >2 34 4 (//1DO ??"wtY'?((*r   c                     | j                   S )zsThe configured voice as an EspeakVoice instance

        If `set_voice` has not been called, returns None

        )r   r   s    r   r.   zEspeakWrapper.voice   s     {{r   )maxsizec           	         |rt        |      j                         }| j                  j                  |xs d      }d}g }||   r||   j                  }|j                  t        t        j                  |j                        j                  dd      t        j                  |j                        dd t        j                  |j                                     |dz  }||   r|S )z>Voices available for phonemization, as a list of `EspeakVoice`)r6   Nr   _rN      )namer6   r4   )r   	to_ctypesr   list_voicescontentsappendrD   fsdecoderj   r[   	languagesr4   )r   rj   voicesindexavailable_voicesr.   s         r   rs   zEspeakWrapper.available_voices   s     -779D))$,$7Um5M**E##K[[,44S#>U__5ab9;;u'7'78%: ; QJE Um  r   c                    d|v r7| j                  d      D ci c]  }|j                  dd |j                   }}n?i }| j                         D ]*  }|j                  |vs|j                  ||j                  <   , 	 ||   }| j
                  j                  |j                  d            dk7  rt	        d	| d      | j                         }|st	        d	| d      || _	        yc c}w # t        $ r t	        d| d      dw xY w)
a!  Setup the voice to use for phonemization

        Parameters
        ----------
        voice_code (str) : Must be a valid language code that is actually
          supported by espeak

        Raises
        ------
        RuntimeError if the required voice cannot be initialized

        r2   mbrolar3   Nzinvalid voice code ""utf8r   zfailed to load voice ")
rs   r4   r6   KeyErrorrK   r   set_voice_by_nameencode
_get_voicer   )r   
voice_coder.   	available
voice_names        r   r5   zEspeakWrapper.set_voice  s4    :
 "228<><E   $e&6&66<  > I..0>>2050@0@Ienn- 1	O":.J <<))**;*;F*CDI(A68 8 !!7
|1EFF1>  	O!5j\CD$N	Os   !C&<C+ +Dc                 z    | j                   j                         }|j                  rt        j                  |      S y)znReturns the current voice used for phonemization

        If no voice has been set up, returns None.

        N)r   get_current_voicerj   r   from_ctypes)r   r.   s     r   r{   zEspeakWrapper._get_voice.  s1     ..0::**511r   texttiec                 D   | j                   t        d      |r| j                  dk  rt        d      t        j                  t        j
                  |j                  d                  }d}| j                  dk  rd}n%|rdt        d      d	z  z  }nt        d
      d	z  dz  }g }|j                  j                  U| j                  j                  |||      }|r|j                  |j                                |j                  j                  Udj                  |      S )u  Translates a text into phonemes, must call set_voice() first.

        This method is used by the Espeak backend. Wrapper on the
        espeak_TextToPhonemes function.

        Parameters
        ----------
        text (str) : the text to phonemize

        tie (bool, optional) : When True use a '͡' character between
          consecutive characters of a single phoneme. Else separate phoneme
          with '_'. This option requires espeak>=1.49. Default to False.

        Returns
        -------
        phonemes (str) : the phonemes for the text encoded in IPA, with '_' as
          phonemes separator (excepted if ``tie`` is True) and ' ' as word
          separator.

        no voice specified)ri   0   r3   z,tie option only compatible with espeak>=1.49rw   ri         u   ͡   rh      rN   )r.   rK   r-   r   pointerc_char_prz   ordrm   valuer   text_to_phonemesrn   rW   join)r   r   r   text_ptr	text_modephonemes_moderesultphonemess           r   r   zEspeakWrapper.text_to_phonemes9  s
   * ::3444<<:->@ @ >>&//$++f2E"FG 	
 <<:%,M,s4yA~=MHMD0M%%1||44)]4Hhoo/0	 %%1
 xxr   c                    | j                   dk  rt        d      | j                  t        d      t        j                  t        j                  g| j
                  j                  _        t        j                  | j
                  j                  _	        t        j                  g| j
                  j                  _        t        j                  | j
                  j                  _	        | j                  j                  d       | j
                  j                  | j                  j                  j                         | j                  j                   j                               }| j"                  j%                  dt'        d      dz  z  |       | j"                  j)                  t        j                  |j                  d            t        j*                  t-        |      d	z         t        j.                  d	            }| j
                  j                  |       |dk7  rt        d
      | j                  j1                  d       | j                  j3                         j5                         j7                         }|S )a  Translates a text into phonemes, must call set_voice() first.

        Only compatible with espeak>=1.49. This method is used by the
        EspeakMbrola backend. Wrapper on the espeak_Synthesize function.

        Parameters
        ----------
        text (str) : the text to phonemize

        Returns
        -------
        phonemes (str) : the phonemes for the text encoded in SAMPA, with '_'
          as phonemes separator and no word separation.

        )ri   1   z not compatible with espeak<=1.48r   r      rh   r   rw   ri   zfailed to synthetize)r-   rK   r.   r   r   r$   fopenargtypesc_void_prestypefclosec_intr+   truncaterj   rz   moder   set_phoneme_tracer   
synthetizec_size_tlenc_uintseekreadrW   rY   )r   r   file_pstatus
phonemizeds        r   r   zEspeakWrapper.synthetizem  s   " <<'!ABB::344 &,__foo$F

!#)??

 &,oo%6

"$*LL

! 	"!!NN&&(NN&&(* 	&&y3s8q='@&I((OODKK/0OOCIM*MM$! 	

&!Q;566A^^((*11399;
r   r
   )F)!__name__
__module____qualname____doc__r9   r>   r   propertyr$   r+   r/   r   r7   classmethodstrr<   r?   r   r]   r   rQ   r-   ra   r   r.   	functools	lru_cachers   r5   r{   boolr   r    r   r   r   r      sY   $ O    "
5$ 
5 &# & & *c * * " "HB sC}-   ) ) ! !F   Y&  ' $(T	2 S 2 t 2  2 h2s 2r   r   )r   r   ctypes.utilr   rD   rF   r   r&   r(   typingr   r   phonemizer.backend.espeak.apir   phonemizer.backend.espeak.voicer   r   r   r   r   <module>r      s7    #    	  
    3 7@ @r   