/// <summary> /// Speak back text /// </summary> /// <param name="text">Text to speak</param> /// <param name="queue">If you want to chain together speak command or cancel current</param> /// <param name="crossLocale">Locale of voice</param> /// <param name="pitch">Pitch of voice</param> /// <param name="speakRate">Speak Rate of voice (All) (0.0 - 2.0f)</param> /// <param name="volume">Volume of voice (iOS/WP) (0.0-1.0)</param> public void Speak(string text, bool queue = false, CrossLocale? crossLocale = null, float? pitch = null, float? speakRate = null, float? volume = null) { if (string.IsNullOrWhiteSpace(text)) return; if (speechSynthesizer == null) Init(); var localCode = crossLocale.HasValue && !string.IsNullOrWhiteSpace(crossLocale.Value.Language) ? crossLocale.Value.Language : AVSpeechSynthesisVoice.CurrentLanguageCode; pitch = !pitch.HasValue ? 1.0f : pitch; if (!volume.HasValue) volume = 1.0f; else if (volume > 1.0f) volume = 1.0f; else if (volume < 0.0f) volume = 0.0f; var divid = UIDevice.CurrentDevice.CheckSystemVersion(8, 0) ? 8.0f : 4.0f; if (!speakRate.HasValue) speakRate = AVSpeechUtterance.MaximumSpeechRate / divid; //normal speech, default is fast else if (speakRate.Value > AVSpeechUtterance.MaximumSpeechRate) speakRate = AVSpeechUtterance.MaximumSpeechRate; else if (speakRate.Value < AVSpeechUtterance.MinimumSpeechRate) speakRate = AVSpeechUtterance.MinimumSpeechRate; var voice = AVSpeechSynthesisVoice.FromLanguage(localCode); if(voice == null) { Console.WriteLine("Locale not found for voice: " + localCode + " is not valid using default."); voice = AVSpeechSynthesisVoice.FromLanguage(AVSpeechSynthesisVoice.CurrentLanguageCode); } if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0)) { var dummyUtterance = new AVSpeechUtterance(" "); dummyUtterance.Voice = voice; speechSynthesizer.SpeakUtterance(dummyUtterance); } var speechUtterance = new AVSpeechUtterance(text) { Rate = speakRate.Value, Voice = voice, Volume = volume.Value, PitchMultiplier = pitch.Value }; if (!queue && speechSynthesizer.Speaking) speechSynthesizer.StopSpeaking(AVSpeechBoundary.Word); speechSynthesizer.SpeakUtterance(speechUtterance); }
/// <summary> /// Speak back text /// </summary> /// <param name="text">Text to speak</param> /// <param name="queue">If you want to chain together speak command or cancel current</param> /// <param name="crossLocale">Locale of voice</param> /// <param name="pitch">Pitch of voice</param> /// <param name="speakRate">Speak Rate of voice (All) (0.0 - 2.0f)</param> /// <param name="volume">Volume of voice (iOS/WP) (0.0-1.0)</param> public void Speak(string text, bool queue = false, CrossLocale? crossLocale = null, float? pitch = null, float? speakRate = null, float? volume = null) { this.text = text; this.language = crossLocale; this.pitch = pitch == null ? 1.0f : pitch.Value; this.speakRate = speakRate == null ? 1.0f : speakRate.Value; this.queue = queue; if (textToSpeech == null || !initialized) { Init(); } else { Speak(); } }
/// <summary> /// Speak back text /// </summary> /// <param name="text">Text to speak</param> /// <param name="queue">If you want to chain together speak command or cancel current</param> /// <param name="crossLocale">Locale of voice</param> /// <param name="pitch">Pitch of voice</param> /// <param name="speakRate">Speak Rate of voice (All) (0.0 - 2.0f)</param> /// <param name="volume">Volume of voice (iOS/WP) (0.0-1.0)</param> public async void Speak(string text, bool queue = false, CrossLocale? crossLocale = null, float? pitch = null, float? speakRate = null, float? volume = null) { if (string.IsNullOrWhiteSpace(text)) return; if (speechSynthesizer == null) Init(); #if !NETFX_CORE if (!queue) speechSynthesizer.CancelAll(); #endif var localCode = string.Empty; //nothing fancy needed here if(pitch == null && speakRate == null && volume == null) { if(crossLocale.HasValue && !string.IsNullOrWhiteSpace(crossLocale.Value.Language)) { localCode = crossLocale.Value.Language; #if NETFX_CORE var voices = from voice in SpeechSynthesizer.AllVoices where (voice.Language == localCode && voice.Gender.Equals(VoiceGender.Female)) select voice; speechSynthesizer.Voice =(voices.Any() ? voices.ElementAt(0) : SpeechSynthesizer.DefaultVoice); #else var voices = from voice in InstalledVoices.All where (voice.Language == localCode && voice.Gender.Equals(VoiceGender.Female)) select voice; speechSynthesizer.SetVoice(voices.Any() ? voices.ElementAt(0) : InstalledVoices.Default); #endif } else { #if NETFX_CORE speechSynthesizer.Voice = SpeechSynthesizer.DefaultVoice; #else speechSynthesizer.SetVoice(InstalledVoices.Default); #endif } #if NETFX_CORE try { var stream = await speechSynthesizer.SynthesizeTextToStreamAsync(text); element.SetSource(stream, stream.ContentType); element.Play(); } catch(Exception ex) { Debug.WriteLine("Unable to playback stream: " + ex); } #else speechSynthesizer.SpeakTextAsync(text); #endif return; } if(crossLocale.HasValue && !string.IsNullOrWhiteSpace(crossLocale.Value.Language)) { localCode = crossLocale.Value.Language; #if NETFX_CORE var voices = from voice in SpeechSynthesizer.AllVoices where (voice.Language == localCode && voice.Gender.Equals(VoiceGender.Female)) select voice; #else var voices = from voice in InstalledVoices.All where (voice.Language == localCode && voice.Gender.Equals(VoiceGender.Female)) select voice; #endif if (!voices.Any()) { #if NETFX_CORE localCode = SpeechSynthesizer.DefaultVoice.Language; #else localCode = InstalledVoices.Default.Language; #endif } } else { #if NETFX_CORE localCode = SpeechSynthesizer.DefaultVoice.Language; #else localCode = InstalledVoices.Default.Language; #endif } if (!volume.HasValue) volume = 100.0f; else if (volume.Value > 1.0f) volume = 100.0f; else if (volume.Value < 0.0f) volume = 0.0f; else volume = volume.Value * 100.0f; var pitchProsody = "default"; //var test = "x-low", "low", "medium", "high", "x-high", or "default"; if(!pitch.HasValue) pitchProsody = "default"; else if(pitch.Value >= 1.6f) pitchProsody = "x-high"; else if(pitch.Value >= 1.1f) pitchProsody = "high"; else if(pitch.Value >= .9f) pitchProsody = "medium"; else if(pitch.Value >= .4f) pitchProsody = "low"; else pitchProsody = "x-low"; string ssmlText = "<speak version=\"1.0\" "; ssmlText += "xmlns=\"http://www.w3.org/2001/10/synthesis\" xml:lang=\"" + localCode + "\">"; ssmlText += "<prosody pitch=\""+pitchProsody+"\" volume=\""+volume.Value +"\" rate=\""+ speakRate.Value+"\" >" + text + "</prosody>"; ssmlText += "</speak>"; #if NETFX_CORE try{ var stream = await speechSynthesizer.SynthesizeSsmlToStreamAsync(ssmlText); element.SetSource(stream, stream.ContentType); element.Play(); } catch(Exception ex) { Debug.WriteLine("Unable to playback stream: " + ex); } #else speechSynthesizer.SpeakSsmlAsync(ssmlText); #endif }