0

Hi I'm trying to parse times said by speech:

        var ret = new GrammarBuilder();

        var hours = new Choices();
        for (int c = 1; c < 24; c++)
            hours.Add(new SemanticResultValue(c.ToString(), c));

        var minutes = new Choices();
        for (int c = 1; c < 60; c = c + 1)
            minutes.Add(new SemanticResultValue(c.ToString(), c));

        var topLevelChoices = new Choices();

        //eight fourty five = 8:45
        //four twenty = 4:20
        var methodOne = new GrammarBuilder();
        methodOne.Append(new SemanticResultKey("hour", hours));
        methodOne.Append(new SemanticResultKey("minute", minutes));
        topLevelChoices.Add(methodOne);

        //quarter to five = 4:45
        //half past ten = 10:30
        var methodTwo = new GrammarBuilder();
        methodTwo.Append(new SemanticResultKey("minute", new Choices(
            new SemanticResultValue("twenty past", 20),
            new SemanticResultValue("twenty to", -20),
            new SemanticResultValue("quarter past", 15),
            new SemanticResultValue("quarter to", -15),
            new SemanticResultValue("half past", 30)
            )));
        methodTwo.Append(new SemanticResultKey("hour", hours));
        topLevelChoices.Add(methodTwo);

        //ten o'clock
        //one o'clock
        var methodThree = new GrammarBuilder();
        methodThree.Append(new SemanticResultKey("hour", hours));
        methodThree.Append("o'clock");
        topLevelChoices.Add(methodThree);

        ret.Append(topLevelChoices);

        var g = new Grammar(ret); //crash occurs here

But I'm getting an exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll (Additional information: Index was out of range. Must be non-negative and less than the size of the collection.). See the upper-stack:

mscorlib.dll!System.ThrowHelper.ThrowArgumentOutOfRangeException() + 0x4e bytes 
mscorlib.dll!System.Collections.Generic.List<System.__Canon>.this[int].set(int index, System.__Canon value) + 0x3b bytes    
System.Speech.dll!System.Speech.Internal.GrammarBuilding.BuilderElements.Optimize(System.Collections.ObjectModel.Collection<System.Speech.Internal.GrammarBuilding.RuleElement> newRules) + 0x38e bytes 
System.Speech.dll!System.Speech.Recognition.GrammarBuilder.InternalGrammarBuilder.CreateElement(System.Speech.Internal.SrgsParser.IElementFactory elementFactory, System.Speech.Internal.SrgsParser.IElement parent, System.Speech.Internal.SrgsParser.IRule rule, System.Speech.Internal.GrammarBuilding.IdentifierCollection ruleIds) + 0x83 bytes    
System.Speech.dll!System.Speech.Recognition.GrammarBuilder.CreateGrammar(System.Speech.Internal.SrgsParser.IElementFactory elementFactory) + 0x6e bytes 
System.Speech.dll!System.Speech.Recognition.GrammarBuilder.Compile(System.IO.Stream stream) + 0x7e bytes    
System.Speech.dll!System.Speech.Recognition.Grammar.LoadCfg(bool isImportedGrammar, bool stgInit) + 0x174 bytes 
System.Speech.dll!System.Speech.Recognition.Grammar.LoadAndCompileCfgData(bool isImportedGrammar, bool stgInit) + 0x32 bytes    
> SapiGrammarCrash.exe!SapiGrammarCrash.Form1.Form1_Load(object sender, System.EventArgs e) Line 71 + 0x29 bytes    C#

I have tried .NET 3.0 and 4.5 - same result. Also tried 2 machines - both x64.

Any ideas?

servermanfail
  • 2,532
  • 20
  • 21
  • I suspect that you're multiply binding the semantic result key/value pairs. Try simplifying your grammar (comment out the various subsections) until it runs, and see what that tells you. – Eric Brown Jul 12 '14 at 22:01
  • Thanks for your reply; Indeed, it runs without methodOne+methodTwo OR without methodThree. But I need all 3 :) Also tried minOccur=1 and maxOccur=1 on all. Aslo tried adding a unique suffix to the SemanticKeys for each method. Any other tips? – servermanfail Jul 13 '14 at 00:16
  • What happens if you don't reuse the 'hours' object in methodThree, and instead create a new set of SemanticResultValues? It's not the *keys* that's causing the problem, it's the *values*. [The docs](http://msdn.microsoft.com/en-us/library/system.speech.recognition.semanticresultvalue(v=vs.110).aspx) specifically say "After a SemanticResultValue has been used to set the Value, whether it is tagged with the default root key or by any particular SemanticResultKey, that value must not be modified or an exception will occur during recognition operations." – Eric Brown Jul 14 '14 at 16:25
  • That was it! I was reusing the same instance. Once I created an array of hours, the problem went away. Thank you! Please copy & paste to an answer and I'll tick it. – servermanfail Jul 15 '14 at 00:22

1 Answers1

1

I'm pretty sure you're rebinding the SemanticResultValues. The docs specifically say

After a SemanticResultValue has been used to set the Value, whether it is tagged with the default root key or by any particular SemanticResultKey, that value must not be modified or an exception will occur during recognition operations.

The workaround is to create a separate set of SemanticResultValues for your methodThree.

Eric Brown
  • 13,774
  • 7
  • 30
  • 71