
    11ia;                         S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKrSSK	J
r
Jr  SSKJr  SSKJr   " S S5      rg)zWrapper on espeak-ng library    N)TupleDict)	EspeakAPI)EspeakVoicec                   X   \ rS rSrSrSrSrS r\S 5       r	\S 5       r
S rS\4S	 jr\S
\4S j5       r\S\4S j5       r\S 5       rS r\S\\\\4   4S j5       r\S 5       r\S 5       r\S 5       r\R6                  " SS9SS j5       rS rS rSS\S\S\4S jjr S\4S jr!Sr"g) EspeakWrapper   a  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                     S U l         S U l        S U l        [        U R	                  5       U R
                  5      U l        S U l        S U l        g N)	_version
_data_path_voicer   library	data_path_espeak_libc_
_tempfile_selfs    [/home/james-whalen/.local/lib/python3.13/site-packages/phonemizer/backend/espeak/wrapper.py__init__EspeakWrapper.__init__5   sC     *. !@     c                    U R                   co  [        R                  S:X  a  [        R                  R
                  O;[        R                  R                  [        R                  R                  S5      5      U l         U R                   $ )Nwin32c)
r   sysplatformctypeswindllmsvcrtcdllLoadLibraryutilfind_libraryr   s    r   _libcEspeakWrapper._libcC   sX    ;;(+(?$$''(@(@(EF K {{r   c                     U R                   cO  [        R                  " 5       U l         [        R                  " U R                   U R                   R
                  5        U R                   $ r   )r   tempfileNamedTemporaryFileweakreffinalizecloser   s    r   	_tempfileEspeakWrapper._tempfileK   sF    ??" '99;DOT__doo.C.CDr   c                 J    U R                   U R                  U R                  S.$ )z/For pickling, when phonemizing on multiple jobs)versionr   voice)r   r   r   r   s    r   __getstate__EspeakWrapper.__getstate__T   s#     }}[[" 	"r   statec                 T   U R                  5         US   U l        US   U l        US   U l        U R                  (       ai  SU R                  R                  ;   a)  U R                  U R                  R                  SS 5        gU R                  U R                  R                  5        gg)z1For unpickling, when phonemizing on multiple jobsr1   r   r2   mb   N)r   r   r   r   
identifier	set_voicelanguage)r   r5   s     r   __setstate__EspeakWrapper.__setstate__[   s    i(,Gn;;t{{---t{{55ab9:t{{334	 r   r   c                     Xl         g)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_libraryEspeakWrapper.set_libraryg   s
     &r   r   c                     Xl         g)a.  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)rA   r   s     r   set_data_pathEspeakWrapper.set_data_pathv   s
     !*r   c                     U R                   (       a  U R                   $ S[        R                  ;   a  [        R                  " [        R                  S   5      nUR                  5       (       a*  [        R                  " U[        R                  5      (       d  [        SU S35      eUR                  5       $ [        R                  R                  S5      =(       d    [        R                  R                  S5      nU(       d  [        S5      eU$ )  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)r?   osenvironpathlibPathis_fileaccessR_OKRuntimeErrorresolver   r$   r%   r@   s     r   r   EspeakWrapper.library   s    $ &&&&"**4ll2::.I#JKGOO%%"))GRWW*E*E"0	 :- ./ / ??$$ ((5 3((2 	 /1 1r   c                    U R                   R                  5       u  p[        R                  " UR	                  5       5      U l        U R
                  R                  5       (       d  [        S5      eUR	                  5       R                  5       R                  S5      S   R                  SS5      n[        S UR                  S5       5       5      U l        g)	z9Initializes version and dapa path from the espeak libraryz(failed to retrieve espeak data directory r   z-dev c              3   8   #    U  H  n[        U5      v   M     g 7fr   )int).0vs     r   	<genexpr>8EspeakWrapper._fetch_version_and_path.<locals>.<genexpr>   s     A.@c!ff.@s   .N)r   inforN   rO   decoder   is_dirrS   stripsplitreplacetupler   )r   r1   r   s      r   _fetch_version_and_path%EspeakWrapper._fetch_version_and_path   s    !\\..0 ",,y'7'7'9:%%''IJJ .."((*005a8@@LAgmmC.@AAr   returnc                 T    U R                   c  U R                  5         U R                   $ )z?The espeak version as a tuple of integers (major, minor, patch))r   rg   r   s    r   r1   EspeakWrapper.version   s$     == ((*}}r   c                 .    U R                   R                  $ )z-The espeak library as a pathlib.Path instance)r   library_pathr   s    r   rm   EspeakWrapper.library_path   s     ||(((r   c                    U R                   (       a  [        R                  " U R                   5      nUR                  5       (       a4  [        R
                  " U R                   [        R                  5      (       d  [        U R                    S35      eUR                  5       U l	        OS[        R                  ;   a  [        R                  " [        R                  S   5      nUR                  5       (       a*  [        R
                  " U[        R                  5      (       d  [        SU S35      eUR                  5       U l	        U R                  c!  [        U S5      (       a  U R                  5         U R                  $ )rI   z is not a readable directoryPHONEMIZER_ESPEAK_DATA_PATHzPHONEMIZER_ESPEAK_DATA_PATH=r   )rE   rN   rO   rb   rL   rQ   rR   rS   rT   r   rM   hasattrrg   )r   r   s     r   r   EspeakWrapper.data_path   s   $ !!T%;%;<I$$&&299T5K5KRWW+U+U"d&<&<%==Y#Z[['//1DO*bjj8RZZ0M%NOI$$&&299Y+H+H"29+ >2 34 4 (//1DO ??"wtY'?'?((*r   c                     U R                   $ )zcThe configured voice as an EspeakVoice instance

If `set_voice` has not been called, returns None

)r   r   s    r   r2   EspeakWrapper.voice   s     {{r   )maxsizec           	         U(       a  [        US9R                  5       nU R                  R                  U=(       d    S5      nSn/ nX#   (       a  X#   R                  nUR                  [        [        R                  " UR                  5      R                  SS5      [        R                  " UR                  5      SS [        R                  " UR                  5      S95        US-  nX#   (       a  M  U$ )z>Voices available for phonemization, as a list of `EspeakVoice`)r;   Nr   _rW      )namer;   r9   )r   	to_ctypesr   list_voicescontentsappendrL   fsdecodery   re   	languagesr9   )r   ry   voicesindexavailable_voicesr2   s         r   r   EspeakWrapper.available_voices   s     -779D))$,$7mM**E##K[[,44S#>U__5ab9;;u'7'78%: ; QJE mm  r   c                 ,   SU;   a:  U R                  S5       Vs0 s H  nUR                  SS UR                  _M     nnOC0 nU R                  5        H-  nUR                  U;  d  M  UR                  X2R                  '   M/      X1   nU R
                  R                  UR                  S5      5      S:w  a  [	        S	U S35      eU R                  5       nU(       d  [	        S	U S35      eX l	        gs  snf ! [         a    [	        SU S35      Sef = f)
zSetup 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

r7   mbrolar8   Nzinvalid voice code ""utf8r   zfailed to load voice ")
r   r9   r;   KeyErrorrS   r   set_voice_by_nameencode
_get_voicer   )r   
voice_coder2   	available
voice_names        r   r:   EspeakWrapper.set_voice  s0    :
 "228<><E   $e&6&66<  >I I..0>>2050@0@Inn- 1	O".J <<))**;*;F*CDI(A68 8 !!7
|1EFF1>  	O!5j\CD$N	Os   $C3C8 8Dc                     U R                   R                  5       nUR                  (       a  [        R                  " U5      $ g)z^Returns the current voice used for phonemization

If no voice has been set up, returns None.

N)r   get_current_voicery   r   from_ctypes)r   r2   s     r   r   EspeakWrapper._get_voice.  s1     ..0::**511r   texttiec                 p   U R                   c  [        S5      eU(       a  U R                  S::  a  [        S5      e[        R                  " [        R
                  " UR                  S5      5      5      nSnU R                  S::  a  SnO*U(       a  S[        S5      S	-  -  nO[        S
5      S	-  S-  n/ nUR                  R                  b[  U R                  R                  X4U5      nU(       a  UR                  UR                  5       5        UR                  R                  b  M[  SR                  U5      $ )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)rx   0   r8   z,tie option only compatible with espeak>=1.49r   rx         u   ͡   rw      rW   )r2   rS   r1   r   pointerc_char_pr   ordr|   valuer   text_to_phonemesr}   ra   join)r   r   r   text_ptr	text_modephonemes_moderesultphonemess           r   r   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                    U R                   S:  a  [        S5      eU R                  c  [        S5      e[        R                  [        R                  /U R
                  R                  l        [        R                  U R
                  R                  l	        [        R                  /U R
                  R                  l        [        R                  U R
                  R                  l	        U R                  R                  S5        U R
                  R                  U R                  R                  R                  5       U R                  R                   R                  5       5      nU R"                  R%                  S['        S5      S-  -  U5        U R"                  R)                  [        R                  " UR                  S5      5      [        R*                  " [-        U5      S	-   5      [        R.                  " S	5      5      nU R
                  R                  U5        US:w  a  [        S
5      eU R                  R1                  S5        U R                  R3                  5       R5                  5       R7                  5       nU$ )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.

)rx   1   z not compatible with espeak<=1.48r   r      rw   r   r   rx   zfailed to synthetize)r1   rS   r2   r   r   r&   fopenargtypesc_void_prestypefclosec_intr.   truncatery   r   moder   set_phoneme_tracer   
synthetizec_size_tlenc_uintseekreadra   rc   )r   r   file_pstatus
phonemizeds        r   r   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   r   r   r   r   r   r   )F)#__name__
__module____qualname____firstlineno____doc__r?   rE   r   propertyr&   r.   r3   r   r<   classmethodstrrB   rF   r   rg   r   rZ   r1   rm   r   r2   	functools	lru_cacher   r:   r   boolr   r   __static_attributes__ r   r   r   r      sW   $ O    "
5$ 
5 &# & & *c * * " "HB sC}-   ) ) ! !F   &  ' $(T	2 S 2 t 2  2 h2s 2r   r   )r   r   ctypes.utilr   rL   rN   r   r)   r+   typingr   r   phonemizer.backend.espeak.apir   phonemizer.backend.espeak.voicer   r   r   r   r   <module>r      s7    #    	  
    3 7@ @r   