Hasan A Yousef Hasan A Yousef - 2 months ago 20
C# Question

async wait in Speech recognizer

I'm trying duplicating this example with the following changes:


  1. Using Console app instead of Windows: This looks to be fine as the computer is speaking to me

  2. Using
    Sync
    functionality: and here looks I've a mistake.



UPDATE
Once the program is executed, it speaks to me, and waited for key to be pressed, after that it waited a little to 'listening' but the
sre_SpeechRecognized
is not executed.

Below is my code, thanks:

using System;
using System.Threading.Tasks;
using System.Speech.Synthesis;
using System.Speech.Recognition;

class Startup {
// Create a simple handler for the SpeechRecognized event
static void sre_SpeechRecognized (object sender, SpeechRecognizedEventArgs e)
{
string speech = e.Result.Text;

//handle custom commands
switch (speech)
{
case "red":
Console.WriteLine("Hello");
break;
case "green":
System.Diagnostics.Process.Start("Notepad");
break;
case "blue":
Console.WriteLine("You said blue");
break;
case "Close":
Console.WriteLine("Speech recognized: {0}", e.Result.Text);
break;
}
Console.WriteLine("Speech recognized: {0}", e.Result.Text);
}

public async Task<object> Invoke(dynamic i) {
// Initialize a new instance of the SpeechSynthesizer.
SpeechSynthesizer synth = new SpeechSynthesizer();

// Configure the audio output.
synth.SetOutputToDefaultAudioDevice();

// Speak a string.
synth.Speak("This example demonstrates a basic use of Speech Synthesizer");

Console.WriteLine();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();

// Create a new SpeechRecognitionEngine instance.
SpeechRecognizer recognizer = new SpeechRecognizer();

// Create a simple grammar that recognizes "red", "green", or "blue".
Choices colors = new Choices();
colors.Add(new string[] { "red", "green", "blue" });

// Create a GrammarBuilder object and append the Choices object.
GrammarBuilder gb = new GrammarBuilder();
gb.Append(colors);

// Create the Grammar instance and load it into the speech recognition engine.
Grammar g = new Grammar(gb);
recognizer.LoadGrammar(g);

// Register a handler for the SpeechRecognized event.
recognizer.SpeechRecognized +=
new EventHandler<SpeechRecognizedEventArgs> (Startup.sre_SpeechRecognized);
Console.WriteLine("Exiting now..");
return null;
}
}

Answer

Modify the Invoke method as follows (this is typical case of Async caller (Node Js here) waiting for a Synchronous event to complete)

Important Details (please note basis of this modification is that otherwise Speech engine is working as expected)

  1. Made Invoke method Sync, instead of Async, as there was no Async call in the original code
  2. Replaced the return value as Task to fetch the event return value
  3. Made the event Inline for ease of using objects
  4. Added Recognize sync method in the end
  5. Will return when the Task completes post event firing and will contain result inside Task<string>, which can fetch result using TaskObject.Result property

     public object Invoke(dynamic i) {
      var tcs = new TaskCompletionSource<string>();
      // Initialize a new instance of the SpeechSynthesizer.
        SpeechSynthesizer synth = new SpeechSynthesizer();
    
        // Configure the audio output. 
        synth.SetOutputToDefaultAudioDevice();
    
        // Speak a string.
        synth.Speak("This example demonstrates a basic use of Speech Synthesizer");
    
        Console.WriteLine();
        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
    
        // Create a new SpeechRecognitionEngine instance.
    
        SpeechRecognitionEngine recognizer = new SpeechRecognitionEngine();
    
        recognizer.SetInputToDefaultAudioDevice();
    
        // Create a simple grammar that recognizes "red", "green", or "blue".
        Choices colors = new Choices();
        colors.Add(new string[] { "red", "green", "blue" });
    
        // Create a GrammarBuilder object and append the Choices object.
        GrammarBuilder gb = new GrammarBuilder();
        gb.Append(colors);
    
        // Create the Grammar instance and load it into the speech recognition engine.
        Grammar g = new Grammar(gb);
        recognizer.LoadGrammar(g);
    
        // Register a handler for the SpeechRecognized event.
        recognizer.SpeechRecognized += (sender,e) => {
    
           string speech = e.Result.Text;
    
            //handle custom commands
            switch (speech)
            {
                case "red":
                 tcs.SetResult("Hello Red");
                break;
                case "green":
                 tcs.SetResult("Hello Green");
                break;
                case "blue":
                 tcs.SetResult("Hello Blue");
                 break;
                case "Close":
                 tcs.SetResult("Hello Close");
                break;
               default:
                 tcs.SetResult("Hello Not Sure");
              break;
    }
    
     };
    
      recognizer.Recognize();
    
       return tcs.Task.Result;
    }
    

Async specific changes

  1. public async Task<object> Invoke(dynamic i) (Make method async and return type Task, requirements of an async method)
  2. Call await recognizer.RecognizeAsync(); (Call await on Async call)
  3. return tcs.Task (return type needs to be Task)
Comments