
    rHJj0                         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
 ddlmZ ddlmZmZmZmZmZmZ ddlmZ ddlmZ ddlmZ dd	lmZmZ  G d
 de      Zy)#Festival backend for the phonemizer    N)Logger)Path)OptionalDictListIOUnionPattern)BaseBackend)lispy)	Separator)get_package_resourceversion_as_tuplec                       e Zd ZdZdZ	 	 	 d$dedeeeef      de	dee
   f fdZed        Zed	efd
       Zedefd       Zed        Zed        Zedeeef   fd       Zdee   dedede	dee   f
dZededefd       Zedefd       Zedee   fd       ZdefdZedededefd       Zedee   dede	defd       Z edeee      dede	defd        Z!edede	defd!       Z"ed"edede	dee   fd#       Z# xZ$S )%FestivalBackendr   Nlanguagepunctuation_markspreserve_punctuationloggerc                 :   t         |   ||||       | j                  j                  d| j	                                t        d      }t        |d      5 }|j                         | _        d d d        | j                  j                  d|       y # 1 sw Y   &xY w)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          n/Users/ahmed/devFolder/claude-voice/.venv/lib/python3.12/site-packages/phonemizer/backend/festival/festival.pyr   zFestivalBackend.__init__*   s     	/!5	 	 	 	5t7HI ++CD+s#w"<<>DL $+{3 $#s   BBc                       y)Nfestival r'       r$   namezFestivalBackend.name<   s    r(   r   c                     |d| _         yt        j                  |      }|j                         r$t	        j
                  |t        j                        st        | d      |j                         | _         y)a  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_executablezFestivalBackend.set_executable@   sk    " '+C$\\*-
""$:rww)G,89; ; $.#5#5#7 r(   returnc                    | j                   r| j                   S dt        j                  v rzt        j                  t        j                  d         }|j                         r%t        j                  |t        j                        st        d| d      |j                         S t        j                  d      }|st        d      t	        |      j                         S )av  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,   r/   environr-   r   r.   r0   r1   r2   r3   shutilwhichr4   s     r$   r   zFestivalBackend.executable\   s    ( ##++++rzz9 bjj*J'L MJ &&(		*277;"5j\ B0 12 2 %%''\\*-
46 6J''))r(   c                 D    	 | j                          y# t        $ r Y yw xY w)z=True if the festival executable is available, False otherwiseFT)r   r2   )r5   s    r$   is_availablezFestivalBackend.is_available   s*    	NN   		s    	c                 (   | j                         }t        j                  |dg      j                  d      j	                         }d}	 t        j                  ||      j                  d      }t        |      S # t        $ r t        d|       dw xY w)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AttributeErrorr2   r   )r5   r&   long_versionfestival_version_reversions        r$   rM   zFestivalBackend.version   s     >># "..{#%%+VH%5eeg 	 5	Nhh2LAGGJG
  ((	  	N7zBDIMN	Ns   %A8 8Bc                  
    ddiS )zA 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_languagesz#FestivalBackend.supported_languages   s     &&r(   textoffset	separatorrF   c                     | j                  |      }t        |      dk(  rg S | j                  |      }| j                  |||      }|S )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    rP   rQ   rR   rF   s        r$   _phonemize_auxzFestivalBackend._phonemize_aux   sK    " %t9>I}}T"  y%8r(   linec                     d| z   dz   S )z4Return the string `line` surrounded by double quotes"r'   rY   s    r$   _double_quotedzFestivalBackend._double_quoted   s     TzCr(   c                     t        |       t        d      k(  rd} | j                  dd      j                  dd      j                  dd      j                         S )z+Remove 'forbidden' characters from the line' r[   ())setreplacerF   r\   s    r$   _cleanedzFestivalBackend._cleaned   sO    
 t9C D ||C$,,S"5==c2FLLNNr(   c                 N      fd|D        }dj                   fd|D              S )a  Returns 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   L   K   | ]  }|d k7  s	j                  |        ywr`   N)re   .0rY   r5   s     r$   	<genexpr>z.FestivalBackend._preprocess.<locals>.<genexpr>   s$      ?+/442:CLL4   
$$
c              3   L   K   | ]  }|d k7  s	j                  |        ywrh   )r]   ri   s     r$   rk   z.FestivalBackend._preprocess.<locals>.<genexpr>   s'      M1=Ct$rl   )join)r5   rP   cleaned_texts   `  r$   rT   zFestivalBackend._preprocess   s6    ?+/? yy M1=M M 	Mr(   c                    t        j                  dd      5 }	 |j                  |       |j                          |j                  }t
        j                  dk(  r|j                  dd      }t        j                  dd      5 }	 |j                  | j                  j                  |             |j                          | j                          d|j                   }| j                  r| j                  j                  d|       t        j                  d      5 }| j                  ||      cd	d	d	       t        j                   |j                         cd	d	d	       t        j                   |j                         cd	d	d	       S # 1 sw Y   nxY w	 t        j                   |j                         n$# t        j                   |j                         w xY w	 d	d	d	       n# 1 sw Y   nxY wt        j                   |j                         n$# t        j                   |j                         w xY w	 d	d	d	       y	# 1 sw Y   y	xY w)
a  Return 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platformrd   r   formatr   r   r   TemporaryFile_run_festivalr/   remove)r    rP   datar)   scmcmdfstderrs          r$   rV   z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#5c7#C :9 		#((+# ED& 		$))$= =<2 :99 		#((+		#((++# EDD& 		$))$		$))$$= =<<s~   H<A)HG"BF4F-	F46G"	HH<FF4 G"4!GG"	H"G+	'H. H<!H//H<<Ir   r   c           
      Z   	 t        j                  t        j                  | d      |      }t	        j
                  dd|j                  d            S # t         j                  $ rC}|j                  d       t        d|  d	|j                   d
|j                                dd}~ww xY w)zRuns the festival command for phonemization

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

        F)posix)stderrz + rA   r   z	Command "z" returned exit status z, output is:
N)rC   rD   shlexsplitrG   subrE   CalledProcessErrorseekr2   
returncoder   )r   r   outputerrs       r$   r}   z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                 t    |j                   }d | dd D        }|j                  d |D              }|r|S ||z   S )z3Parse a syllable from festival to phonemized outputc              3   L   K   | ]  }|d    d    j                  dd        yw)r   r[   r`   N)rd   )rj   phones     r$   rk   z4FestivalBackend._postprocess_syll.<locals>.<genexpr>/  s&     BuQx{""3+s   "$rB   Nc              3   ,   K   | ]  }|d k7  s	|  ywrh   r'   )rj   os     r$   rk   z4FestivalBackend._postprocess_syll.<locals>.<genexpr>0  s     1#Qbq#s   
)r   ro   )r   rR   rF   sepouts        r$   _postprocess_syllz!FestivalBackend._postprocess_syll+  sB     ooBabBhh1#11s*s*r(   wordc                 p     j                   }|j                   fd|dd D              }r|S ||z   S )z/Parse a word from festival to phonemized outputc              3   D   K   | ]  }j                  |        y w)N)r   )rj   r   r5   rR   rF   s     r$   rk   z4FestivalBackend._postprocess_word.<locals>.<genexpr>7  s(      "  !!$	59 s    rB   N)syllablero   )r5   r   rR   rF   r   r   s   ` ``  r$   _postprocess_wordz!FestivalBackend._postprocess_word3  sD       hh "QR" " s*s*r(   c                     |j                   }g }t        j                  |      D ],  }| j                  |||      }|dk7  s|j	                  |       . |j                  |      }|r|S ||z   S )z/Parse a line from festival to phonemized outputr`   )r   r   parser   appendro   )r5   rY   rR   rF   r   r   r   s          r$   _postprocess_linez!FestivalBackend._postprocess_line<  sl     nnKK%D((y%@Drz

4  & hhsms*s*r(   treec                 t    |j                  d      D cg c]  }|dvr| j                  |||       c}S c c}w )z8Conversion from festival syllable tree to desired formatrm   )r`   z(nil nil nil))r   r   )r5   r   rR   rF   rY   s        r$   rW   zFestivalBackend._postprocessI  sJ     !JJt,6,D44 %%dIu=,6 	6 6s   5)NFN)%__name__
__module____qualname____doc__r,   strr   r
   r   boolr   r   staticmethodr)   classmethodr6   r   r   r?   rM   r   rO   r   intr   rX   r]   re   rT   rV   r	   r}   r   r   r   rW   __classcell__)r#   s   @r$   r   r   #   s   -   EI.3,04 4$,U3<-@$A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   r/   r-   rG   r   r<   rC   ry   ru   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(   