/// <summary> /// Speaks the text in the provided <see cref="SpeechString"/> using the enclosed data. /// </summary> /// <returns>Nothing.</returns> private async Task Speak(SpeechString speech) { // create a new memory stream and speech synth, to be disposed of after this method executes. using (MemoryStream stream = new MemoryStream()) using (SpeechSynthesizer synth = new SpeechSynthesizer()) { // set synthesizer properties synth.SetOutputToWaveStream(stream); synth.Rate = speech.Rate; synth.Volume = speech.Volume; // TODO: refine the speech builder and actually use the style. PromptBuilder builder = new PromptBuilder(); PromptStyle style = new PromptStyle(); builder.StartVoice(speech.Voice.VoiceInfo); builder.StartSentence(); builder.AppendText(speech.Text); builder.EndSentence(); builder.EndVoice(); // "speaks" the text directly into the memory stream synth.Speak(builder); // then block while the speech is being played. await AudioManager.Instance.Play(stream, speech.PrimaryDevice.DeviceNumber, speech.SecondaryDevice.DeviceNumber); } }
/// <summary> /// Queues a TTS task if the queue isn't full. /// </summary> /// <param name="text">Text to speak.</param> /// <param name="device1">The <see cref="SoundDevice"/> to use when speaking.</param> /// <param name="voice">The voice to use.</param> /// <param name="rate">The rate to speak this text at. Clamped to [<see cref="MIN_RATE"/>, <see cref="MAX_RATE"/>].</param> /// <param name="volume">The volume to speak this text at. Clamped to [<see cref="MIN_VOLUME"/>, <see cref="MAX_VOLUME"/>].</param> public void QueueTTS(string text, SoundDevice device1, SoundDevice device2, InstalledVoice voice, int rate = DEFAULT_RATE, int volume = DEFAULT_VOLUME) { if (!IsQueueFull()) { SpeechString data = new SpeechString(text, voice, rate, volume, device1, device2); TTSQueue.Enqueue(data); TTSHistory.Enqueue(data); } }
public SpeechSynthManager() { TTSQueue = new ObservableQueue <SpeechString>(); TTSHistory = new ObservableQueue <SpeechString>(); _queueTaskCt = new CancellationTokenSource(); var token = _queueTaskCt.Token; _queueTask = Task.Run(async() => { while (true) { // cancel if requested. if (token.IsCancellationRequested) { return; } // if the queue has entries, play the next one. if (TTSQueue.Count > 0) { // this will await until the TTS clip has finished playing. SpeechString str = TTSQueue.Peek(); await Application.Current.Dispatcher.BeginInvoke(new Action(() => this.TTSQueue.Dequeue())); await Speak(str); } } }, token); // hack method to get installed voices because there's no direct method of getting these var tmp = new SpeechSynthesizer(); Voices = tmp.GetInstalledVoices(); tmp.Dispose(); Instance = this; }