
    Zj                    Z   d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
ZddlZddlmZmZmZmZmZ d Zd Zd Zd Zej        j        d	             Zej        j        d
             Zd Zd Zd Zd Zd Zd Z ej        j        d             Z!ej        j        d             Z"d Z#d Z$d Z%dS )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                 p   t          d          } dg}| |k    }|st          j        d|fd| |f          dt          j                    v st          j        |           rt          j        |           ndt          j        |          dz  }dd|iz  }t          t          j        |                    d x}}d S )NzHello world.==z%(py0)s == %(py3)s	sentencespy0py3assert %(py5)spy5	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!      s     00I'((9(((((((((((9(((((((((((((9(((((9((((((((((((((((((((((((((((((((((    c                 N   t          d          } t          |           }d}||k    }|st          j        d|fd||f          dt	          j                    v st          j        t                    rt          j        t                    nddt	          j                    v st          j        |           rt          j        |           ndt          j        |          t          j        |          dz  }dd	|iz  }t          t          j	        |                    d x}x}}| d
         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j	        |                    d x}x}}d S )Nz&Be virtuous. Avoid excess. Seek truth.   r
   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenr   r   py1r   py6assert %(py8)spy8r   zBe virtuous.z%(py1)s == %(py4)sr(   py4assert %(py6)sr)   )
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_multipler7      s    !IJJIy>>Q>Q>Q33yy>QQ<)>)<>))))))))))<>)))))<))))>)))))))))))))))))))))))))))))r"   c                    t          d          } d | D             }t          |          }|sddt          j                    v st	          j        t                    rt	          j        t                    ndt	          j        |          t	          j        |          dz  }t          t	          j        |                    d x}}t          |           }d}||k    }|st	          j
        d|fd||f          d	t          j                    v st	          j        t                    rt	          j        t                    nd	d
t          j                    v st	          j        |           rt	          j        |           nd
t	          j        |          t	          j        |          dz  }dd|iz  }t          t	          j        |                    d x}x}}d S )Nz  First.  Second.  c              3  F   K   | ]}||                                 k    V  d S N)strip.0ss     r    	<genexpr>z9test_split_sentences_strips_whitespace.<locals>.<genexpr>%   s.      11!qAGGII~111111r"   ,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}allr   py2r.      r
   r%   r&   r   r'   r*   r+   )r   rA   r   r   r   r   r   r   r   r&   r   )	r   r   r5   r6   r   r0   r1   r2   r3   s	            r    &test_split_sentences_strips_whitespacerE   #   s    !677I11y11113111111111111111131111131111111111111111111111111111111y>>Q>Q>Q33yy>Qr"   c                    d} t          |           }g }||k    }|st          j        d|fd||f          dt          j                    v st          j        t                     rt          j        t                     ndt          j        |           t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x} x}x}}d} t          |           }g }||k    }|st          j        d|fd||f          dt          j                    v st          j        t                     rt          j        t                     ndt          j        |           t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x} x}x}}d S )	N r
   )z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py7)sr   )r   rC   r.   py7zassert %(py9)spy9z   r   )r   r5   @py_assert6r0   @py_format8@py_format10s         r    test_split_sentences_emptyrM   )   s   %B%2%2%%%%%%%%%%2%%%%%%%%%%%%%%%%%%%%%%%B%%%%%%%%2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!(E""(b("b(((((((((("b(((((((((((((((((((((((E(((("((((b(((((((((((((((((((((((((((((((r"   c                   K   d } g }t           |                       2 3 d {V }|                    |           6 t          |          }d}||k    }|st          j        d|fd||f          dt          j                    v st          j        t                    rt          j        t                    nddt          j                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          dz  }dd	|iz  }t          t          j
        |                    d x}x}}d
}|d         }	||	v }|slt          j        d|fd||	f          t          j        |          t          j        |	          dz  }
dd|
iz  }t          t          j
        |                    d x}x}}	d}|d         }	||	v }|slt          j        d|fd||	f          t          j        |          t          j        |	          dz  }
dd|
iz  }t          t          j
        |                    d x}x}}	d S )Nc                   K   dD ]} | W V  d S )N)Bez virtzuous. Avoidz excess. )tokens    r    tokensz=test_iter_sentences_yields_complete_sentences.<locals>.tokens0   s,      G 	 	EKKKKK	 	r"   rD   r
   r%   r&   resultsr'   r*   r+   virtuousr   )in)z%(py1)s in %(py4)sr-   r/   r)   excess   r   appendr&   r   r   r   r   r   r   r   r   rU   rV   sentencer   r0   r1   r2   r3   r4   r5   r6   s              r    -test_iter_sentences_yields_complete_sentencesr_   .   s        G)&&((33 ! ! ! ! ! ! !hx     4 w<<1<1<133ww<1##:##########:#####:###############################!wqz!8z!!!!!!!!!!8z!!!!!8!!!!z!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   <c                   K   d } g }t           |                       2 3 d {V }|                    |           6 t          |          }d}||k    }|st          j        d|fd||f          dt          j                    v st          j        t                    rt          j        t                    nddt          j                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          dz  }dd	|iz  }t          t          j
        |                    d x}x}}|d
         }d}	||	k    }|slt          j        d|fd||	f          t          j        |          t          j        |	          dz  }
dd|
iz  }t          t          j
        |                    d x}x}}	d S )Nc                   K   dW V  d S )NNo final periodrS   rS   r"   r    rU   z8test_iter_sentences_yields_trailing_text.<locals>.tokens?   s      r"   rZ   r
   r%   r&   rV   r'   r*   r+   r   rc   r,   r-   r/   r)   r[   r]   s              r    (test_iter_sentences_yields_trailing_textrd   =   s8           G)&&((33 ! ! ! ! ! ! !hx     4 w<<1<1<133ww<11:***:***********:******:**********************************r`   c                    t                      } | j        }d}||k    }|st          j        d|fd||f          dt	          j                    v st          j        |           rt          j        |           ndt          j        |          t          j        |          dz  }dd|iz  }t          t          j	        |                    d x}x}}| j
        }d}||k    }|st          j        d|fd	||f          dt	          j                    v st          j        |           rt          j        |           ndt          j        |          t          j        |          dz  }dd|iz  }t          t          j	        |                    d x}x}}| j        }d
}||k    }|st          j        d|fd||f          dt	          j                    v st          j        |           rt          j        |           ndt          j        |          t          j        |          dz  }dd|iz  }t          t          j	        |                    d x}x}}d S )Nkokoror
   z.%(py2)s
{%(py2)s = %(py0)s.engine
} == %(py5)scfgr   rC   r   assert %(py7)srH   i]  )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rh   r   r1   r5   r   rK   s         r    test_voice_config_defaultsrp   M   s   
--C:!!:!!!!!!!!!!:!!!!!!!!!!!!3!!!!!3!!!!!!:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!?#e#?e##########?e############3#####3######?####e###########################999339r"   c                    t          d          } | j        }d}||k    }|st          j        d|fd||f          dt	          j                    v st          j        |           rt          j        |           ndt          j        |          t          j        |          dz  }dd|iz  }t          t          j	        |                    d x}x}}d S )	Nfakerl   r
   rg   rh   ri   rj   rH   )
r   rl   r   r   r   r   r   r   r   r   ro   s         r    test_voice_config_fake_enginert   T   s    
V
$
$
$C:::33:r"   c                    t          d          } |                     dt                                }t          |          }d}||k    }|st	          j        d|fd||f          dt          j                    v st	          j        t                    rt	          j	        t                    nddt          j                    v st	          j        |          rt	          j	        |          ndt	          j	        |          t	          j	        |          d	z  }d
d|iz  }t          t	          j        |                    d x}x}}d S )Nd   duration_msHello.r   >z/%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} > %(py6)sr&   pcmr'   r*   r+   )r   
synthesizer   r&   r   r   r   r   r   r   r   r   )ttsr}   r   r0   r1   r2   r3   s          r    !test_fake_tts_returns_nonzero_pcmr   \   sI   
c
"
"
"C
..;==
1
1Cs88a8a<8a33ss8ar"   c                    t          d          } |                     dt                                }t          |          }d}||z  }d}||k    }|st	          j        d|fd||f          dt          j                    v st	          j        t                    rt	          j	        t                    ndd	t          j                    v st	          j        |          rt	          j	        |          nd	t	          j	        |          t	          j	        |          t	          j	        |          d
z  }dd|iz  }t          t	          j        |                    dx}x}x}x}}t          j        dt          |          dz   d|          }	d |	D             }
t          |
          }|sddt          j                    v st	          j        t                    rt	          j	        t                    ndt	          j	        |
          t	          j	        |          dz  }t          t	          j        |                    dx}
}dS )z$PCM is 16-bit aligned and parseable.2   rw   Test.rD   r   r
   )z=(%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} %% %(py5)s) == %(py9)sr&   r}   )r   r(   r   r   rI   zassert %(py11)spy11N<hc              3  "   K   | ]
}|d k    V  dS r   NrS   r<   s     r    r?   z2test_fake_tts_returns_valid_pcm.<locals>.<genexpr>h   s&      ''!qAv''''''r"   r@   rA   rB   )r   r~   r   r&   r   r   r   r   r   r   r   r   structunpackrA   )r   r}   r   r1   rJ   @py_assert8@py_assert7rL   @py_format12samplesr   r5   r6   s                r    test_fake_tts_returns_valid_pcmr   b   sO   
b
!
!
!C
..+--
0
0Cs88a8a<1<1<133ss8a1m0CA000#66G''w''''3''''''''''''''''3'''''3'''''''''''''''''''''''''''''''''r"   c                 p    G d d          } t           |                       }t          |          }d}||k    }|st          j        d|fd||f          dt	          j                    v st          j        t                    rt          j        t                    nddt	          j                    v st          j        |          rt          j        |          ndt          j        |          t          j        |          dz  }d	d
|iz  }t          t          j	        |                    dx}x}}dS )z/Kokoro returns torch tensors, not NumPy arrays.c                       e Zd Zd Zd Zd ZdS )Atest_pcm_conversion_accepts_torch_like_tensor.<locals>.TensorLikec                    | S r:   rS   selfs    r    detachzHtest_pcm_conversion_accepts_torch_like_tensor.<locals>.TensorLike.detachn       Kr"   c                    | S r:   rS   r   s    r    cpuzEtest_pcm_conversion_accepts_torch_like_tensor.<locals>.TensorLike.cpuq   r   r"   c                F    t          j        g dt           j                  S )N)g      g        rk   )dtype)nparrayfloat32r   s    r    numpyzGtest_pcm_conversion_accepts_torch_like_tensor.<locals>.TensorLike.numpyt   s     8,,,BJ????r"   N)__name__
__module____qualname__r   r   r   rS   r"   r    
TensorLiker   m   sF        	 	 		 	 		@ 	@ 	@ 	@ 	@r"   r      r
   r%   r&   r}   r'   r*   r+   N)
r   r&   r   r   r   r   r   r   r   r   )r   r}   r   r0   r1   r2   r3   s          r    -test_pcm_conversion_accepts_torch_like_tensorr   k   sg   @ @ @ @ @ @ @ @ JJLL
)
)Cs88q8q=8q33ss8qr"   c                    t          d          } |                     dt                                }t          t           j        dz            dz  }t          |          }||k    }|st          j        d|fd||f          dt          j	                    v st          j
        t
                    rt          j        t
                    ndd	t          j	                    v st          j
        |          rt          j        |          nd	t          j        |          d
t          j	                    v st          j
        |          rt          j        |          nd
dz  }dd|iz  }t          t          j        |                    dx}}dS )z+100ms at 24kHz = 2400 samples = 4800 bytes.rv   rw   r   g?rD   r
   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py5)sr&   r}   expected_bytes)r   r(   r   r   rj   rH   N)r   r~   r   intSAMPLE_RATEr&   r   r   r   r   r   r   r   r   )r   r}   r   r   r1   r   rK   s          r    test_fake_tts_durationr   {   s   
c
"
"
"C
..+--
0
0C,s233a7Ns88%8~%%%%%%%%%%8~%%%%%%%%%%%%3%%%%%3%%%%%%%%%%%%%s%%%%%s%%%%%%8%%%%%%%%%%%~%%%%%~%%%%%%%%%%%%%%%%%%%%%%%%%%%%%r"   c                 V  K   d } t          d          }g }|                     |             t          d                    2 3 d {V }|                    |           6 t	          |          }d}||k    }|st          j        d|fd||f          d	t          j                    v st          j	        t                    rt          j
        t                    nd	d
t          j                    v st          j	        |          rt          j
        |          nd
t          j
        |          t          j
        |          dz  }dd|iz  }t          t          j        |                    d x}x}}d |D             }	t          |	          }
|
sddt          j                    v st          j	        t                    rt          j
        t                    ndt          j
        |	          t          j
        |
          dz  }t          t          j        |                    d x}	}
d S )Nc                   K   dD ]} | W V  d S )N)zFirst sentence. zSecond sentence.rS   )ts    r    rU   zBtest_fake_tts_stream_yields_one_chunk_per_sentence.<locals>.tokens   s,      9 	 	AGGGGG	 	r"   r   rw   rr   rs   rD   r
   r%   r&   chunksr'   r*   r+   c              3  <   K   | ]}t          |          d k    V  dS r   )r&   )r=   cs     r    r?   zEtest_fake_tts_stream_yields_one_chunk_per_sentence.<locals>.<genexpr>   s,      **as1vvz******r"   r@   rA   rB   )r   synthesize_streamr   r\   r&   r   r   r   r   r   r   r   r   rA   )rU   r   r   chunkr   r0   r1   r2   r3   r   r5   r6   s               r    2test_fake_tts_stream_yields_one_chunk_per_sentencer      si        b
!
!
!CF,,VVXX{&7Q7Q7QRR       ee S v;;!;!;!33vv;!**6****3****************3*****3*********************************s   A!c                 
  K   d } t                      }g }|                     |             t                                2 3 d {V }|                    |           6 g }||k    }|st	          j        d|fd||f          dt          j                    v st	          j        |          rt	          j	        |          ndt	          j	        |          dz  }dd|iz  }t          t	          j        |                    d x}}d S )Nc                
   K   d S r:   rS   rS   r"   r    rU   z0test_fake_tts_stream_empty_input.<locals>.tokens   s      r"   r
   r   r   r   r   r   )r   r   r   r\   r   r   r   r   r   r   r   r   )rU   r   r   r   r   r   r   r   s           r     test_fake_tts_stream_empty_inputr      sK        ))CF,,VVXX{}}EE       ee F 6R<6R66Rs    Ac                 h   ddl m}   | dt          d                    }t          |          }d}||k    }|st	          j        d|fd||f          dt          j                    v st	          j        t                    rt	          j	        t                    ndd	t          j                    v st	          j        |          rt	          j	        |          nd	t	          j	        |          t	          j	        |          d
z  }dd|iz  }t          t	          j        |                    d x}x}}d S )Nr   r~   ry   rr   rs   rz   r|   r&   r}   r'   r*   r+   )runtime.speech.ttsr~   r   r&   r   r   r   r   r   r   r   r   )r~   r}   r   r0   r1   r2   r3   s          r    test_synthesize_fake_enginer      sP   ------
*X{&999
:
:Cs88a8a<8a33ss8ar"   c                     ddl m}  t          j        t          d          5   | dt          d                     d d d            d S # 1 swxY w Y   d S )Nr   r   zUnknown TTS enginematchry   unknownrs   r   r~   pytestraises
ValueErrorr   r   s    r    %test_synthesize_unknown_engine_raisesr      s    ------	z)=	>	>	> < <
8[	:::;;;< < < < < < < < < < < < < < < < < <   A

AAc                     ddl m}  t          j        t          d          5   | dt          d                     d d d            d S # 1 swxY w Y   d S )Nr   r   reference_audior   ry   f5rs   r   r   s    r    1test_synthesize_f5_without_reference_audio_raisesr      s    ------	z):	;	;	; 7 7
8[5556667 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7r   )&__doc__
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   r   r   r   r   r   r   r   r   r   r   r!   r7   rE   rM   markasyncior_   rd   rp   rt   r   r   r   r   r   r   r   r   r   rS   r"   r    <module>r      s    # " " " " "                                ) ) )
* * *  ) ) )
 " " " 	+ 	+ 	+         ( ( (   & & & + + + 
 
 
   < < <7 7 7 7 7r"   