
    11i0                         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
  SSKJr  SSKJrJrJrJrJrJr  SSKJr  SSKJr  SSKJr  SS	KJrJr   " S
 S\5      rg)#Festival backend for the phonemizer    N)Logger)Path)OptionalDictListIOUnionPattern)BaseBackend)lispy)	Separator)get_package_resourceversion_as_tuplec                   4  ^  \ rS rSrSrSr   S&S\S\\\\	4      S\
S\\   4U 4S jjjr\S	 5       r\S
\4S j5       r\S\4S j5       r\S 5       r\S 5       r\S\\\4   4S j5       rS\\   S\S\S\
S\\   4
S jr\S\S\4S j5       r\S\4S j5       r\S\\   4S j5       rS\4S jr\S\S\S\4S j5       r \S\\   S\S\
S\4S j5       r!\S \\\      S\S\
S\4S! j5       r"\S\S\
S\4S" j5       r#\S#\S\S\
S\\   4S$ j5       r$S%r%U =r&$ )'FestivalBackend#   r   Nlanguagepunctuation_markspreserve_punctuationloggerc                 >  > [         TU ]  UUUUS9  U R                  R                  SU R	                  5       5        [        S5      n[        US5       nUR                  5       U l        S S S 5        U R                  R                  SU5        g ! , (       d  f       N+= f)N)r   r   r   zfestival executable is %szfestival/phonemize.scmrz	loaded %s)	super__init__r   debug
executabler   openread_script)selfr   r   r   r   script_filefscript	__class__s          ^/home/james-whalen/.local/lib/python3.13/site-packages/phonemizer/backend/festival/festival.pyr   FestivalBackend.__init__*   s     	/!5	 	 	 	5t7HI ++CD+s#w"<<>DL $+{3 $#s   B
Bc                      g)Nfestival r)       r%   nameFestivalBackend.name<   s    r*   r   c                 
   Uc  SU l         g[        R                  " U5      nUR                  5       (       a*  [        R
                  " U[        R                  5      (       d  [        U S35      eUR                  5       U l         g)ap  Sets the festival backend to use `executable`

If this is not set, the backend uses the default festival executable
from the system installation.

Parameters
----------
executable (str) : the path to the festival executable to use as
    backend. Set `executable` to None to restore the default.

Raises
------
RuntimeError if `executable` is not an executable file.

N is not an executable file)	_FESTIVAL_EXECUTABLEpathlibr   is_fileosaccessX_OKRuntimeErrorresolveclsr   s     r%   set_executableFestivalBackend.set_executable@   sq    " '+C$\\*-
""$$:rww)G)G,89; ; $.#5#5#7 r*   returnc                    U R                   (       a  U R                   $ S[        R                  ;   a  [        R                  " [        R                  S   5      nUR                  5       (       a(  [        R                  " U[        R                  S9(       d  [        SU S35      eUR                  5       $ [        R                  " S5      nU(       d  [        S5      e[	        U5      R                  5       $ )a  Returns the absolute path to the festival executable used as backend

The following precedence rule applies for executable lookup:

1. As specified by FestivalBackend.set_executable()
2. Or as specified by the environment variable
   PHONEMIZER_FESTIVAL_EXECUTABLE
3. Or the default 'festival' binary found on the system with ``shutil.which('festival')``


Raises
------
RuntimeError
    if the festival executable cannot be found or if the
    environment variable PHONEMIZER_FESTIVAL_EXECUTABLE is set to a
    non-executable file

PHONEMIZER_FESTIVAL_EXECUTABLE)modezPHONEMIZER_FESTIVAL_EXECUTABLE=r.   r(   z"failed to find festival executable)r/   r2   environr0   r   r1   r3   r4   r5   r6   shutilwhichr7   s     r%   r   FestivalBackend.executable\   s    ( ##++++rzz9 bjj*J'L MJ &&((		*277;"5j\ B0 12 2 %%''\\*-
46 6J''))r*   c                 F     U R                  5         g! [         a     gf = f)z=True if the festival executable is available, False otherwiseFT)r   r5   )r8   s    r%   is_availableFestivalBackend.is_available   s*    	NN   		s    
  c                 ,   U R                  5       n[        R                  " US/5      R                  S5      R	                  5       nSn [
        R                  " X25      R                  S5      n[        U5      $ ! [         a    [        SU 35      Sef = f)zFestival version as a tupe of integers (major, minor, patch)

Raises
------
RuntimeError if FestivalBackend.is_available() is False or if the
    version cannot be extracted for some reason.

z	--versionlatin1z.* ([0-9\.]+[0-9]):   z%cannot extract festival version from N)r   
subprocesscheck_outputdecodestriprematchgroupAttributeErrorr5   r   )r8   r(   long_versionfestival_version_reversions        r%   rS   FestivalBackend.version   s     >># "..{#%%+VH%5eeg 	 5	Nhh2AGGJG
  ((	  	N7zBDIMN	Ns   	%A9 9Bc                  
    SS0$ )zuA dictionnary of language codes -> name supported by festival

Actually only en-us (American English) is supported.

zen-usz
english-usr)   r)   r*   r%   supported_languages#FestivalBackend.supported_languages   s     &&r*   textoffset	separatorrL   c                     U R                  U5      n[        U5      S:X  a  / $ U R                  U5      nU R                  XU5      nU$ )a|  Return a phonemized version of `text` with festival

This function is a wrapper on festival, a text to speech
program, allowing simple phonemization of some English
text. The US phoneset we use is the default one in festival,
as described at http://www.festvox.org/bsv/c4711.html

Any opening and closing parenthesis in `text` are removed, as
they interfer with the Scheme expression syntax. Moreover
double quotes are replaced by simple quotes because double
quotes denotes utterances boundaries in festival.

Parsing a ill-formed Scheme expression during post-processing
(typically with unbalanced parenthesis) raises an IndexError.

r   )_preprocesslen_process_postprocess)r!   rX   rY   rZ   rL   s        r%   _phonemize_auxFestivalBackend._phonemize_aux   sI    " %t9>I}}T"  %8r*   linec                     SU -   S-   $ )z4Return the string `line` surrounded by double quotes"r)   rb   s    r%   _double_quotedFestivalBackend._double_quoted   s     TzCr*   c                     [        U 5      [        S5      :X  a  Sn U R                  SS5      R                  SS5      R                  SS5      R                  5       $ )z+Remove 'forbidden' characters from the line' rd   ())setreplacerL   re   s    r%   _cleanedFestivalBackend._cleaned   sO    
 t9C D ||C$,,S"5==c2FLLNNr*   c                 R   ^  U 4S jU 5       nSR                  U 4S jU 5       5      $ )zReturns the contents of `text` formatted for festival input

This function adds double quotes to begining and end of each
line in text, if not already presents. The returned result is
a multiline string. Empty lines in inputs are ignored.

c              3   T   >#    U  H  oS :w  d  M
  TR                  U5      v   M     g7frj   N)ro   .0rb   r8   s     r%   	<genexpr>.FestivalBackend._preprocess.<locals>.<genexpr>   s'      ?+/42:CLL4   	((
c              3   T   >#    U  H  oS :w  d  M
  TR                  U5      v   M     g7frs   )rf   rt   s     r%   rv   rw      s*      M1=$Ct$$rx   )join)r8   rX   cleaned_texts   `  r%   r\   FestivalBackend._preprocess   s6    ?+/? yy M1=M M 	Mr*   c                    [         R                  " SSS9 n UR                  U5        UR                  5         UR                  n[
        R                  S:X  a  UR                  SS5      n[         R                  " SSS9 n UR                  U R                  R                  U5      5        UR                  5         U R                  5        SUR                   3nU R                  (       a  U R                  R                  SU5        [         R                  " S5       nU R                  XV5      sS	S	S	5        [        R                   " UR                  5        sS	S	S	5        [        R                   " UR                  5        sS	S	S	5        $ ! , (       d  f       O= f [        R                   " UR                  5        O%! [        R                   " UR                  5        f = f S	S	S	5        O! , (       d  f       O= f[        R                   " UR                  5        O%! [        R                   " UR                  5        f = f S	S	S	5        g	! , (       d  f       g	= f)
zReturn the raw phonemization of `text`

This function delegates to festival the text analysis and
syllabic structure extraction.

Return a string containing the "SylStructure" relation tree of
the text, as a scheme expression.

zw+F)deletewin32\z\\z -b z
running %sN)tempfileNamedTemporaryFilewritecloser+   sysplatformrn   r    formatr   r   r   TemporaryFile_run_festivalr2   remove)r!   rX   datar+   scmcmdfstderrs          r%   r^   FestivalBackend._process   s    ((e<%

4 

 yy<<7*<<f5D00eD,		$,,"5"5d";<		!%!2 34zB;; KK--lC@ &33D9W#'#5#5c#C :9 		#((+# ED& 		$))$= =<2 :99 		#((+		#((++# EDD& 		$))$		$))$$= =<<s~   IA(H G-BF>F/	F>8 G-	H! I
FF>!G->"G  G-$	H-
G;	7H>!I"II
Ir   r   c           
      V    [         R                  " [        R                  " U SS9US9n[        R
                  " SSUR                  S5      5      $ ! [         R                   aC  nUR                  S5        [        SU  S	UR                   S
UR                  5        35      SeSnAff = f)zRuns the festival command for phonemization

Returns the raw phonemized output (need to be postprocesses). Raises a
RuntimeError if festival fails.

F)posix)stderrz + rG   r   z	Command "z" returned exit status z, output is:
N)rI   rJ   shlexsplitrM   subrK   CalledProcessErrorseekr5   
returncoder   )r   r   outputerrs       r%   r   FestivalBackend._run_festival  s    	;,,Cu-g?F 66$V]]8%<==,, 	;LLOC5 77G H&||~.016:;	;s   AA B(%>B##B(syllc                 |    UR                   nS U SS  5       nUR                  S U 5       5      nU(       a  U$ XC-   $ )z3Parse a syllable from festival to phonemized outputc              3   P   #    U  H  oS    S    R                  SS5      v   M     g7f)r   rd   rj   N)rn   )ru   phones     r%   rv   4FestivalBackend._postprocess_syll.<locals>.<genexpr>/  s&     BQx{""3++s   $&rH   Nc              3   4   #    U  H  oS :w  d  M
  Uv   M     g7frs   r)   )ru   os     r%   rv   r   0  s     1#Qbqq#s   		)r   r{   )r   rZ   rL   sepouts        r%   _postprocess_syll!FestivalBackend._postprocess_syll+  s@     ooBabBhh1#11s**r*   wordc                 z   ^ ^^ TR                   nUR                  U UU4S jUSS  5       5      nT(       a  U$ XT-   $ )z/Parse a word from festival to phonemized outputc              3   J   >#    U  H  nTR                  UTT5      v   M     g 7f)N)r   )ru   r   r8   rZ   rL   s     r%   rv   4FestivalBackend._postprocess_word.<locals>.<genexpr>7  s*      "  !!$	599 s    #rH   N)syllabler{   )r8   r   rZ   rL   r   r   s   ` ``  r%   _postprocess_word!FestivalBackend._postprocess_word3  sB       hh "QR" " s**r*   c                     UR                   n/ n[        R                  " U5       H.  nU R                  XbU5      nUS:w  d  M  UR	                  U5        M0     UR                  U5      nU(       a  U$ XT-   $ )z/Parse a line from festival to phonemized outputrj   )r   r   parser   appendr{   )r8   rb   rZ   rL   r   r   r   s          r%   _postprocess_line!FestivalBackend._postprocess_line<  sh     nnKK%D((%@Drz

4  & hhsms**r*   treec                     UR                  S5       Vs/ s H  nUS;  d  M  U R                  XBU5      PM     sn$ s  snf )z8Conversion from festival syllable tree to desired formatry   )rj   z(nil nil nil))r   r   )r8   r   rZ   rL   rb   s        r%   r_   FestivalBackend._postprocessI  sJ     !JJt,6,D44 >%%du=,6 	6 6s   
;;)r    )NFN)'__name__
__module____qualname____firstlineno____doc__r/   strr   r
   r   boolr   r   staticmethodr+   classmethodr9   r   r   rD   rS   r   rV   r   intr   r`   rf   ro   r\   r^   r	   r   r   r   r   r_   __static_attributes____classcell__)r$   s   @r%   r   r   #   s   -   EI.3,04 4$,U3<-@$A4'+4 "&)4 4$   8 8 86 &*4 &* &*P   ) )6 'c3h ' '49 c i X\ aefiaj 0  S  S     	Os 	O 	O MtCy M M(%S (%T ;3 ; ; ; ;( +S	 +i + +QT + + +T$s)_ + +SW +\_ + + 
+S 
+D 
+S 
+ 
+ 6 6	 6$ 64PS9 6 6r*   r   )r   r2   r0   rM   r   r@   rI   r   r   loggingr   r   typingr   r   r   r	   r
   r   phonemizer.backend.baser   phonemizer.backend.festivalr   phonemizer.separatorr   phonemizer.utilsr   r   r   r)   r*   r%   <module>r      sH    * 	  	    
    ; ; / - * Ck6k k6r*   