简体   繁体   中英

Waiting for text-to-speech

I am trying to play with the Task in order to understand how it works, so in my toy project, I just wanted to start a text to speech, and print the time. This is my effort:

await Task.Factory.StartNew(
    ()    => System.Diagnostics.Debug.Print("START PLAYING {0}", 
                 System.DateTime.Now.ToString("HH:mm:ss"))).ContinueWith(

    (arg) => DependencyService.Get<ITextToSpeech>().Speak(s)).ContinueWith(

    (arg) => System.Diagnostics.Debug.Print("STOP  PLAYING {0}", 
                 System.DateTime.Now.ToString("HH:mm:ss"))
);

The code is inside an async void Play_Clicked(object sender, System.EventArgs e) event handler, but as I see, it won't await the TTS to finish and print the time right away:

START PLAYING 11:22:44
START IMPLEMENTATION 11:22:44
STOP  IMPLEMENTATION 11:22:45
STOP  PLAYING 11:22:45

The implementation for the dependency is just a copy/paste from the Xamarin's tutorial on TTS:

using Xamarin.Forms;
using AVFoundation;

[assembly: Dependency(typeof(Testers.iOS.TextToSpeechImplementation))]
namespace Testers.iOS
{
    public class TextToSpeechImplementation : ITextToSpeech
    {
        public TextToSpeechImplementation() { }

        public void Speak(string text)
        {
            System.Diagnostics.Debug.Print("START IMPLEMENTATION {0}", System.DateTime.Now.ToString("HH:mm:ss"));

            var speechSynthesizer = new AVSpeechSynthesizer();
            var speechUtterance = new AVSpeechUtterance(text)
            {
                Rate = AVSpeechUtterance.MaximumSpeechRate / 2.8f,
                Voice = AVSpeechSynthesisVoice.FromLanguage(App.current_lang),
                PreUtteranceDelay = 0.5f,
                PostUtteranceDelay = 0.0f,
                Volume = 0.5f,
                PitchMultiplier = 1.0f
            };

            speechSynthesizer.SpeakUtterance(speechUtterance);
            System.Diagnostics.Debug.Print("STOP  IMPLEMENTATION {0}", System.DateTime.Now.ToString("HH:mm:ss"));
        }
    }
}

with its interface defined as

using System;

namespace Testers
{
    public interface ITextToSpeech
    {
        void Speak(string text);
    }
}

I still am grasping this whole async / await concept, so I am obviously missing something important here.

Any help would be appreciated!

You use a TaskCompletionSource along with the DidFinishSpeechUtterance handler to determine when the speech output is finished.

Note: The DidFinishSpeechUtterance handler is auto-assigning a AVSpeechSynthesizerDelegate , so you can skip the Xamarin handler wrappers and directly create/use your own delegate (that is needed for some use-cases)

Example Usage:

await speechSynthesizer.SpeakUtteranceAsync(speechUtterance, cancelToken);

Example Extension:

public static class AClassyClass
{
    public static async Task SpeakUtteranceAsync(this AVSpeechSynthesizer synthesizer, AVSpeechUtterance speechUtterance, CancellationToken cancelToken)
    {
        var tcsUtterance = new TaskCompletionSource<bool>();
        try
        {
            synthesizer.DidFinishSpeechUtterance += OnFinishedSpeechUtterance;
            synthesizer.SpeakUtterance(speechUtterance);
            using (cancelToken.Register(TryCancel))
            {
                await tcsUtterance.Task;
            }
        }
        finally
        {
            synthesizer.DidFinishSpeechUtterance -= OnFinishedSpeechUtterance;
        }

        void TryCancel()
        {
            synthesizer?.StopSpeaking(AVSpeechBoundary.Word);
            tcsUtterance?.TrySetResult(true);
        }

        void OnFinishedSpeechUtterance(object sender, AVSpeechSynthesizerUteranceEventArgs args)
        {
            if (speechUtterance == args.Utterance)
                tcsUtterance?.TrySetResult(true);
        }
    }
}

Note: Xamarin.Essentials includes this flow using TaskCompletionSource and provides a TextToSpeech.SpeakAsync providing the same feature

Re: https://docs.microsoft.com/en-us/xamarin/essentials/text-to-speech

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM