1
votes

The following program is a simple speech recognition console application in C# using the Microsoft managed speech API that just recognizes the words 'yes' and 'no'. When I create the Srgs rule 'MyRule' inline using the Srgs methods everything works Ok. However if I put the rule in an external XML file and create an SrgsRuleRef to reference it I always get the error: "A rule reference to an imported grammar cannot be resolved." I have tried changing various parameters such as the language, media type and semantic tag format but nothing seems to make any difference.

using System;
using System.Speech.Recognition;
using System.Speech.Recognition.SrgsGrammar;

namespace SpeechRecognitionConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                System.Globalization.CultureInfo culture = 
                    new System.Globalization.CultureInfo("en-US");
                SrgsRule RootRule = new SrgsRule("RootRule");
                RootRule.Add(new SrgsRuleRef(
                    new Uri("c:\\projects.net\\speechrecognitionconsole\\MyGrammar.xml"), "MyRule"));
                RootRule.Scope = SrgsRuleScope.Public;
                SrgsDocument MyDocument = new SrgsDocument(RootRule);
                MyDocument.Culture = culture;
                Grammar g = new Grammar(MyDocument);
                g.Name = ("MyGrammar");
                SpeechRecognitionEngine recognizer = new SpeechRecognitionEngine(culture);
                recognizer.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>
                                               (recognizer_SpeechRecognized);
                recognizer.LoadGrammar(g);
                recognizer.SetInputToDefaultAudioDevice();
                recognizer.RecognizeAsync(RecognizeMode.Multiple);
                Console.WriteLine("Starting asynchronous recognition...");
                Console.Read();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        static void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            Console.WriteLine(e.Result.Text);
        }
    }
}

The grammar file "c:\projects.net\speechrecognitionconsole\MyGrammar.xml" contains:

<?xml version="1.0" encoding="utf-8"?>
<grammar xml:lang="en-US" tag-format="semantics/1.0" version="1.0" xmlns="http://www.w3.org/2001/06/grammar">
  <rule id="MyRule" scope="public">
    <one-of>
      <item>yes</item>
      <item>no</item>
    </one-of>
  </rule>
</grammar>
1
Don't you have to prefix the URI with "file://" for accessing the local file system? - Kevin Junghans
The file path is converted by the Uri constructor into 'file:///c:/projects.net/speechrecognitionconsole/MyGrammar.xml' which I believe is the correct form for a local file. - Graham Shaw
I tested the code with an http uri too and it gave me the same error at LoadGrammar. I thought I saw something odd in the debugger where the SrgsRuleRef with the file url had #MyRule appended as an http url would, but I got the same results with http. - Michael Levy
The other thought I had was that the root rule in the document should match the rule specified by the srgsruleref, this is what is shown in the sample at msdn.microsoft.com/en-us/library/ms554282.aspx, but that didn't work out for me either. So, I'm stumped. - Michael Levy
I also tested it with an http Uri and it did not work. I am pretty sure the external rule does not have to be the root rule because this would make it of very limited use although it does have to be public, which it is. I eventually gave up on external rule references and just loaded all the rules in the file and then added my own rules programmatically, which worked Ok. - Graham Shaw

1 Answers

0
votes

To get this working today using Visual Studio 2013 I had to add root="MyRule" not sure if the same fix would have helped when question was asked in 2012.

<?xml version="1.0" encoding="utf-8"?>
<grammar xml:lang="en-US" tag-format="semantics/1.0"
 version="1.0" xmlns="http://www.w3.org/2001/06/grammar" root="MyRule">
  <rule id="MyRule" scope="public">
    <one-of>
      <item>yes</item>
      <item>no</item>
    </one-of>
  </rule>
</grammar>