77using Windows . Foundation ;
88using Windows . Media . SpeechSynthesis ;
99using Windows . Storage . Streams ;
10+ using System . Linq ;
1011using System . Threading . Tasks ;
1112#endif
1213
1314namespace HoloToolkit . Unity
1415{
16+ /// <summary>
17+ /// The well-know voices that can be used by <see cref="TextToSpeechManager"/>.
18+ /// </summary>
19+ public enum TextToSpeechVoice
20+ {
21+ /// <summary>
22+ /// The default system voice.
23+ /// </summary>
24+ Default ,
25+
26+ /// <summary>
27+ /// Microsoft David Mobile
28+ /// </summary>
29+ David ,
30+
31+ /// <summary>
32+ /// Microsoft Mark Mobile
33+ /// </summary>
34+ Mark ,
35+
36+ /// <summary>
37+ /// Microsoft Zira Mobile
38+ /// </summary>
39+ Zira ,
40+ }
41+
1542 /// <summary>
1643 /// Enables text to speech using the Windows 10 <see cref="SpeechSynthesizer"/> class.
1744 /// </summary>
@@ -27,11 +54,17 @@ public class TextToSpeechManager : MonoBehaviour
2754 {
2855 // Inspector Variables
2956 [ Tooltip ( "The audio source where speech will be played." ) ]
30- public AudioSource audioSource ;
57+ [ SerializeField ]
58+ private AudioSource audioSource ;
59+
60+ [ Tooltip ( "The voice that will be used to generate speech." ) ]
61+ [ SerializeField ]
62+ private TextToSpeechVoice voice ;
3163
3264 // Member Variables
3365 #if WINDOWS_UWP
3466 private SpeechSynthesizer synthesizer ;
67+ private VoiceInformation voiceInfo ;
3568 #endif
3669
3770 // Static Helper Methods
@@ -205,6 +238,30 @@ private void PlaySpeech(string text, Func<IAsyncOperation<SpeechSynthesisStream>
205238 // This is good since it frees up Unity to keep running anyway.
206239 Task . Run ( async ( ) =>
207240 {
241+ // Change voice?
242+ if ( voice != TextToSpeechVoice . Default )
243+ {
244+ // Get name
245+ var voiceName = Enum . GetName ( typeof ( TextToSpeechVoice ) , voice ) ;
246+
247+ // See if it's never been found or is changing
248+ if ( ( voiceInfo == null ) || ( ! voiceInfo . DisplayName . Contains ( voiceName ) ) )
249+ {
250+ // Search for voice info
251+ voiceInfo = SpeechSynthesizer . AllVoices . Where ( v => v . DisplayName . Contains ( voiceName ) ) . FirstOrDefault ( ) ;
252+
253+ // If found, select
254+ if ( voiceInfo != null )
255+ {
256+ synthesizer . Voice = voiceInfo ;
257+ }
258+ else
259+ {
260+ Debug . LogErrorFormat ( "TTS voice {0} could not be found." , voiceName ) ;
261+ }
262+ }
263+ }
264+
208265 // Speak and get stream
209266 var speechStream = await speakFunc ( ) ;
210267
@@ -324,5 +381,15 @@ public void SpeakText(string text)
324381 LogSpeech ( text ) ;
325382 #endif
326383 }
384+
385+ /// <summary>
386+ /// Gets or sets the audio source where speech will be played.
387+ /// </summary>
388+ public AudioSource AudioSource { get { return audioSource ; } set { audioSource = value ; } }
389+
390+ /// <summary>
391+ /// Gets or sets the voice that will be used to generate speech.
392+ /// </summary>
393+ public TextToSpeechVoice Voice { get { return voice ; } set { voice = value ; } }
327394 }
328395}
0 commit comments