+
    Zj  c                     R t ^ RIHt ^ RIt^ RIHu Ht ^ RI	t	^ RI
t^ RIt^ RIHtHtHtHtHt R tR tR tR t]P.                  P0                  R 4       t]P.                  P0                  R	 4       tR
 tR tR tR tR tR t ]P.                  P0                  R 4       t!]P.                  P0                  R 4       t"R t#R t$R t%R# )u   Tests for runtime/speech/tts.py.

All offline — uses FakeTTS test double. Live Kokoro/F5 tests require
MENTORCORE_TEST_TTS=1 and installed model weights.
)annotationsN)FakeTTSVoiceConfig_float32_to_pcm16_iter_sentences_split_sentencesc                    \        R 4      p R .qV8H  q"'       g   \        P                  ! RV3RW34      RR\        P                  ! 4       9   g   \        P
                  ! V 4      '       d   \        P                  ! V 4      MRR\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR;r!R# )	zHello world.py0	sentencespy3assert %(py5)spy5N==z%(py0)s == %(py3)s	r   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation)r	   @py_assert2@py_assert1@py_format4@py_format6s        >/Users/jameslopez/projects/MentorCore/tests/speech/test_tts.pytest_split_sentences_singler      so     0I'((((((((9((((((9((((9((((((((((((    c                    \        R 4      p \        V 4      p^q!V8H  q3'       Eg   \        P                  ! RV3RW34      RR\        P
                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MRRR\        P
                  ! 4       9   g   \        P                  ! V 4      '       d   \        P                  ! V 4      MRR\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR	;p;r2V ^ ,          pR
qvV8H  q'       gy   \        P                  ! RV3RWg34      R\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR	;p;rR	# )z&Be virtuous. Avoid excess. Seek truth.r   lenpy1r	   r
   py6assert %(py8)spy8NzBe virtuous.py4assert %(py6)sr   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)sz%(py1)s == %(py4)s)
r   r!   r   r   r   r   r   r   r   r   )	r	   r   @py_assert5@py_assert4@py_format7@py_format9@py_assert0@py_assert3@py_format5s	            r   test_split_sentences_multipler1      s     !IJIy>QQ>33yy>QQ<)>)>)))))<)))<)))>))))))))r   c                     \        R 4      p R V  4       p\        V4      q"'       g   RRR\        P                  ! 4       9   g!   \        P
                  ! \        4      '       d   \        P                  ! \        4      MRR\        P                  ! V4      R\        P                  ! V4      /,          p\        \        P                  ! V4      4      hR;r\        V 4      p^qTV8H  qf'       Eg   \        P                  ! RV3RWE34      RR\        P                  ! 4       9   g!   \        P
                  ! \        4      '       d   \        P                  ! \        4      MRR	R
\        P                  ! 4       9   g   \        P
                  ! V 4      '       d   \        P                  ! V 4      MR
R\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR;p;reR# )z  First.  Second.  c              3  F   "   T F  qVP                  4       8H  x  K  	  R # 5iN)strip.0ss   & r   	<genexpr>9test_split_sentences_strips_whitespace.<locals>.<genexpr>%   s     1y!AGGI~ys   !,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}r   allpy2r&   Nr!   r"   r	   r
   r#   r$   r%   r   r(   )r   r<   r   r   r   r   r   r   r   r!   r   )	r	   r   r/   r0   r   r*   r+   r,   r-   s	            r   &test_split_sentences_strips_whitespacer>   #   s	    !67I1y113111111111131111311111111111111y>QQ>33yy>Qr   c                    R p \        V 4      p. q!V8H  q3'       g   \        P                  ! R
V3RW34      RR\        P                  ! 4       9   g!   \        P
                  ! \         4      '       d   \        P                  ! \         4      MRR\        P                  ! V 4      R\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR;p ;p;r2R	p \        V 4      p. q!V8H  q3'       g   \        P                  ! R
V3RW34      RR\        P                  ! 4       9   g!   \        P
                  ! \         4      '       d   \        P                  ! \         4      MRR\        P                  ! V 4      R\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR;p ;p;r2R# ) r   r   r=   r&   py7zassert %(py9)spy9Nz   r   )z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py7)sr   )r   r/   @py_assert6r*   @py_format8@py_format10s         r   test_split_sentences_emptyrF   )   s   %B%2%2%%%%%%%%%%%%%%%%%%B%%%%%%2%%%%%%%%!(E"(b(b((((("(((((((((((((E((("(((b((((((((r   c                 4  "   R  p . p\        V ! 4       4        Rj  xL
  pVP                  V4       K   LD\        T4      p^qCT8H  qU'       Eg   \        P                  ! RT3RY434      RR\
        P                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MRRR\
        P                  ! 4       9   g   \        P                  ! T4      '       d   \        P                  ! T4      MRR\        P                  ! T4      R\        P                  ! T4      /,          pRR	T/,          p\        \        P                  ! T4      4      hR;p;rTR
q^ ,          qT	9   q3'       gy   \        P                  ! RT3RY34      R\        P                  ! T4      R\        P                  ! T	4      /,          p
RRT
/,          p\        \        P                  ! T4      4      hR;p;r9Rq^,          qT	9   q3'       gy   \        P                  ! RT3RY34      R\        P                  ! T4      R\        P                  ! T	4      /,          p
RRT
/,          p\        \        P                  ! T4      4      hR;p;r9R# 5i)c                *   "   R F  p V 5x  K
  	  R# 5i)BeN)rI   z virtzuous. Avoidz excess. )tokens    r   tokens=test_iter_sentences_yields_complete_sentences.<locals>.tokens0   s     GEK H   Nr   r!   r"   resultsr
   r#   r$   r%   virtuousr&   r'   excessr   r(   )in)z%(py1)s in %(py4)sr   appendr!   r   r   r   r   r   r   r   r   rN   rQ   sentencer   r*   r+   r,   r-   r.   r/   r0   s              r   -test_iter_sentences_yields_complete_sentencesrY   .   sp     G)&(3 ! !hx !3 w<11<33ww<1#######:###:###########!qz!z!!!!!8!!!8!!!z!!!!!!!!s.   J757J7A.J&AJ8F Jc                   "   R  p . p\        V ! 4       4        Rj  xL
  pVP                  V4       K   LD\        T4      p^qCT8H  qU'       Eg   \        P                  ! RT3RY434      RR\
        P                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MRRR\
        P                  ! 4       9   g   \        P                  ! T4      '       d   \        P                  ! T4      MRR\        P                  ! T4      R\        P                  ! T4      /,          pRR	T/,          p\        \        P                  ! T4      4      hR;p;rTT^ ,          pR
qT	8H  q3'       gy   \        P                  ! RT3RY34      R\        P                  ! T4      R\        P                  ! T	4      /,          p
RRT
/,          p\        \        P                  ! T4      4      hR;p;r9R# 5i)c                   "   R 5x  R# 5i)No final periodNrL   rL   r   r   rN   8test_iter_sentences_yields_trailing_text.<locals>.tokens?   s     s   
Nr   r!   r"   rQ   r
   r#   r$   r%   r\   r&   r'   r   r(   r)   rU   rW   s              r   (test_iter_sentences_yields_trailing_textr^   =   s'      G)&(3 ! !hx !3 w<11<33ww<11:*********:***:************s.   H757H7A.H&AH8DHc            	     r   \        4       p V P                  pR q!V8H  q3'       g   \        P                  ! R
V3RW34      RR\        P
                  ! 4       9   g   \        P                  ! V 4      '       d   \        P                  ! V 4      MRR\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR;p;r2V P                  pRq!V8H  q3'       g   \        P                  ! R
V3RW34      RR\        P
                  ! 4       9   g   \        P                  ! V 4      '       d   \        P                  ! V 4      MRR\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR;p;r2V P                  pR	q!V8H  q3'       g   \        P                  ! R
V3RW34      RR\        P
                  ! 4       9   g   \        P                  ! V 4      '       d   \        P                  ! V 4      MRR\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR;p;r2R# )kokoror   cfgr=   r   assert %(py7)srA   Ni]        ?r   z.%(py2)s
{%(py2)s = %(py0)s.engine
} == %(py5)s)z3%(py2)s
{%(py2)s = %(py0)s.sample_rate
} == %(py5)s)z-%(py2)s
{%(py2)s = %(py0)s.speed
} == %(py5)s)r   enginer   r   r   r   r   r   r   r   sample_ratespeedra   r   r+   r/   r   rD   s         r   test_voice_config_defaultsri   M   s_   
-C::!!!!!!!:!!!!!!3!!!!3!!!:!!!!!!!!!!!??#e#e#####?######3####3###?###e########999339r   c            	        \        R R7      p V P                  pR q!V8H  q3'       g   \        P                  ! R	V3R
W34      RR\        P
                  ! 4       9   g   \        P                  ! V 4      '       d   \        P                  ! V 4      MRR\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR;p;r2R# )fakere   r   ra   r=   r   rb   rA   Nr   rd   )
r   re   r   r   r   r   r   r   r   r   rh   s         r   test_voice_config_fake_enginerm   T   s~    
V
$C:::33:r   c                    \        ^dR7      p V P                  R\        4       4      p\        V4      p^ q2V8  qD'       Eg   \        P
                  ! RV3RW#34      RR\        P                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MRRR\        P                  ! 4       9   g   \        P                  ! V4      '       d   \        P                  ! V4      MRR\        P                  ! V4      R\        P                  ! V4      /,          pR	R
V/,          p\        \        P                  ! V4      4      hR;p;rCR# )d   duration_msHello.r   r!   r"   pcmr
   r#   r$   r%   N>z/%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} > %(py6)s)r   
synthesizer   r!   r   r   r   r   r   r   r   r   )ttsrs   r   r*   r+   r,   r-   s          r   !test_fake_tts_returns_nonzero_pcmry   \   s    
c
"C
..;=
1Cs8aa<833ss8ar   c                    \        ^2R7      p V P                  R\        4       4      p\        V4      p^q2V,          p^ qTV8H  qf'       Eg3   \        P
                  ! RV3RWE34      RR\        P                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MRRR\        P                  ! 4       9   g   \        P                  ! V4      '       d   \        P                  ! V4      MRR\        P                  ! V4      R\        P                  ! V4      R	\        P                  ! V4      /,          pR
RV/,          p\        \        P                  ! V4      4      hR;p;p;p;re\        P                  ! R\        V4      ^,           R2V4      p	R V	 4       p
\        V
4      q'       g   RRR\        P                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MRR\        P                  ! V
4      R\        P                  ! V4      /,          p\        \        P                  ! V4      4      hR;rR# )z$PCM is 16-bit aligned and parseable.rp   Test.r   r!   r"   rs   r
   r   rB   zassert %(py11)spy11N<hc              3  *   "   T F	  q^ 8H  x  K  	  R# 5i    NrL   r6   s   & r   r9   2test_fake_tts_returns_valid_pcm.<locals>.<genexpr>h   s     'w!AvwrP   r;   r<   r=   r&   r   )z=(%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} %% %(py5)s) == %(py9)s)r   rw   r   r!   r   r   r   r   r   r   r   r   structunpackr<   )rx   rs   r   r+   rC   @py_assert8@py_assert7rE   @py_format12samplesr   r/   r0   s                r   test_fake_tts_returns_valid_pcmr   b   sR   
b
!C
..+-
0Cs8aa<11<33ss8a1mmaCAa0#6G'w''3''''''''''3''''3''''''''''''''r   c                     ! R R4      p \        V ! 4       4      p\        V4      p^q2V8H  qD'       Eg   \        P                  ! RV3RW#34      RR\        P
                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MRRR\        P
                  ! 4       9   g   \        P                  ! V4      '       d   \        P                  ! V4      MRR\        P                  ! V4      R\        P                  ! V4      /,          pR	R
V/,          p\        \        P                  ! V4      4      hR;p;rCR# )z/Kokoro returns torch tensors, not NumPy arrays.c                  (    ] tR t^mtR tR tR tRtR# )Atest_pcm_conversion_accepts_torch_like_tensor.<locals>.TensorLikec                	    V # r4   rL   selfs   &r   detachHtest_pcm_conversion_accepts_torch_like_tensor.<locals>.TensorLike.detachn       Kr   c                	    V # r4   rL   r   s   &r   cpuEtest_pcm_conversion_accepts_torch_like_tensor.<locals>.TensorLike.cpuq   r   r   c                	R    \         P                  ! . RO\         P                  R7      # )rc   )dtype)g      g        rc   )nparrayfloat32r   s   &r   numpyGtest_pcm_conversion_accepts_torch_like_tensor.<locals>.TensorLike.numpyt   s    88,BJJ??r   rL   N)__name__
__module____qualname____firstlineno__r   r   r   __static_attributes__rL   r   r   
TensorLiker   m   s    			@r   r   r   r!   r"   rs   r
   r#   r$   r%   Nr   r(   )
r   r!   r   r   r   r   r   r   r   r   )r   rs   r   r*   r+   r,   r-   s          r   -test_pcm_conversion_accepts_torch_like_tensorr   k   s    @ @ JL
)Cs8qq=833ss8qr   c                 |   \        ^dR7      p V P                  R\        4       4      p\        \         P                  R,          4      ^,          p\        V4      q3V8H  qD'       EgU   \        P                  ! RV3RW234      RR\        P                  ! 4       9   g!   \        P                  ! \
        4      '       d   \        P                  ! \
        4      MRRR\        P                  ! 4       9   g   \        P                  ! V4      '       d   \        P                  ! V4      MRR\        P                  ! V4      R	R
\        P                  ! 4       9   g   \        P                  ! V4      '       d   \        P                  ! V4      MR
/,          pRRV/,          p\        \        P                  ! V4      4      hR;r4R# )z+100ms at 24kHz = 2400 samples = 4800 bytes.rp   r{   g?r   r!   r"   rs   r
   r   expected_bytesrb   rA   Nr   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py5)s)r   rw   r   intSAMPLE_RATEr!   r   r   r   r   r   r   r   r   )rx   rs   r   r   r+   r   rD   s          r   test_fake_tts_durationr   {   s    
c
"C
..+-
0C,,s23a7Ns8%~%%%%%8%%%%%%3%%%%3%%%%%%%s%%%%s%%%8%%%%%%~%%%%~%%%%%%%%r   c                   "   R  p \        ^2R7      p. pVP                  V ! 4       \        RR7      4        Rj  xL
  pVP                  V4       K   LD\	        T4      p^qTT8H  qf'       Eg   \
        P                  ! RT3RYE34      RR\        P                  ! 4       9   g!   \
        P                  ! \        4      '       d   \
        P                  ! \        4      MRRR\        P                  ! 4       9   g   \
        P                  ! T4      '       d   \
        P                  ! T4      MRR	\
        P                  ! T4      R
\
        P                  ! T4      /,          pRRT/,          p\        \
        P                  ! T4      4      hR;p;reR T 4       p	\        T	4      q'       g   RRR\        P                  ! 4       9   g!   \
        P                  ! \        4      '       d   \
        P                  ! \        4      MRR\
        P                  ! T	4      R\
        P                  ! T
4      /,          p\        \
        P                  ! T4      4      hR;rR# 5i)c                *   "   R F  p V 5x  K
  	  R# 5i)First sentence. N)r   zSecond sentence.rL   )ts    r   rN   Btest_fake_tts_stream_yields_one_chunk_per_sentence.<locals>.tokens   s     9AG :rP   rp   rk   rl   Nr   r!   r"   chunksr
   r#   r$   r%   c              3  >   "   T F  p\        V4      ^ 8  x  K  	  R# 5ir   )r!   )r7   cs   & r   r9   Etest_fake_tts_stream_yields_one_chunk_per_sentence.<locals>.<genexpr>   s     *6as1vz6s   r;   r<   r=   r&   r   r(   )r   synthesize_streamr   rV   r!   r   r   r   r   r   r   r   r   r<   )rN   rx   r   chunkr   r*   r+   r,   r-   r   r/   r0   s               r   2test_fake_tts_stream_yields_one_chunk_per_sentencer      sP     b
!CF,,VX{&7QR  eeR v;!!;33vv;!*6**3**********3****3**************s;   3IAAAIAA.IAICI&A3Ic                 *  "   R  p \        4       p. pVP                  V ! 4       \        4       4        Rj  xL
  pVP                  V4       K   LD. qBT8H  qU'       g   \        P
                  ! RT3RY$34      RR\        P                  ! 4       9   g   \        P                  ! T4      '       d   \        P                  ! T4      MRR\        P                  ! T4      /,          pRRT/,          p\        \        P                  ! T4      4      hR;rTR# 5i)	c                   "   R # 5ir4   rL   rL   r   r   rN   0test_fake_tts_stream_empty_input.<locals>.tokens   s     s   Nr   r   r
   r   r   r   r   )r   r   r   rV   r   r   r   r   r   r   r   r   )rN   rx   r   r   r   r   r   r   s           r    test_fake_tts_stream_empty_inputr      s      )CF,,VX{}E  eeE R<666Rs-   /DAAADAAD/A$Dc                    ^ RI Hp  V ! R\        RR7      4      p\        V4      p^ q2V8  qD'       Eg   \        P
                  ! RV3RW#34      RR\        P                  ! 4       9   g!   \        P                  ! \        4      '       d   \        P                  ! \        4      MRRR\        P                  ! 4       9   g   \        P                  ! V4      '       d   \        P                  ! V4      MRR	\        P                  ! V4      R
\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR;p;rCR# )r   rw   rr   rk   rl   r   r!   r"   rs   r
   r#   r$   r%   Nrt   rv   )runtime.speech.ttsrw   r   r!   r   r   r   r   r   r   r   r   )rw   rs   r   r*   r+   r,   r-   s          r   test_synthesize_fake_enginer      s    -
X{&9
:Cs8aa<833ss8ar   c            	         ^ RI Hp  \        P                  ! \        RR7      ;_uu_ 4        V ! R\        RR7      4       RRR4       R#   + '       g   i     R# ; i)r   r   zUnknown TTS enginematchrr   unknownrl   Nr   rw   pytestraises
ValueErrorr   r   s    r   %test_synthesize_unknown_engine_raisesr      s5    -	z)=	>	>8[	:; 
?	>	>	>   A		A	c            	         ^ RI Hp  \        P                  ! \        RR7      ;_uu_ 4        V ! R\        RR7      4       RRR4       R#   + '       g   i     R# ; i)r   r   reference_audior   rr   f5rl   Nr   r   s    r   1test_synthesize_f5_without_reference_audio_raisesr      s5    -	z):	;	;8[56 
<	;	;	;r   )&__doc__
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   r   r   r   r   r   r   r   r   r   r   r   r1   r>   rF   markasynciorY   r^   ri   rm   ry   r   r   r   r   r   r   r   r   rL   r   r   <module>r      s    #      )
*)
 " " 	+ 	+ ( & + + 
 
 <7r   