Welcome to GotSpeech.NET Sign in | Join | Help

Marshall Harrison - "the gotspeech guy"

Site news, Speech Server insight and assorted ramblings
Dynamic Grammars

I’ve been messing around with dynamic grammars and put some code together to show how it’s done. This was for a real world problem I was facing but the code is just a proof of concept that I used to get everything working.

I used the code shown below to create a DTMF grammar that takes from 1 to 4 digits. The resulting SML looks like this -

<SML text="1 2 3 4" utteranceConfidence="1.000" confidence="1.000">
        <slot confidence="1.000">1234</slot>
        4
</SML>

There is more than one way to create the grammars but this is what I came up with. Part of the goal was to utilize most of the grammar building methods available to me. The code to write the grammar out to a file was a big help in debugging the grammar. The first thing I did was use the Grammar Editor to create a grammar that did what I wanted. I then compared this to the generated grammar to make sure i understood what was happening with the different methods and classes.

        private Microsoft.SpeechServer.Recognition.Grammar buildDTMFGrammar()
        {
            string ValidDigits = "0123456789";
            // Create the root rule and set its scope
            SrgsRule rootRule = new SrgsRule("Rule1");
            rootRule.Scope = SrgsRuleScope.Public;

            // Create the oneof
            SrgsOneOf oneOf = new SrgsOneOf();

            // Create the slot name to use
            string slotName = "slot";

            // Create the items (need and inner and an outer to get
            // all the tags to work properly
            SrgsItem itemInner;
            SrgsItem itemOuter = new SrgsItem();

            // Create the first tag. We have to do it in two parts because the "{}"
            // part of the tag creates havoc with string.foramt()
            SrgsSemanticInterpretationTag sr3 = new SrgsSemanticInterpretationTag();
            string tagPartA = string.Format("$.{0} = $.{1} ? $.{2} : ", slotName, slotName, slotName);
            string tagPartB = string.Format("; $.{0}._value = \"\"", slotName);
            sr3.Script = tagPartA + "{}" + tagPartB;
            // Add the tag at the root level
            rootRule.Add(sr3);

            itemOuter.SetRepeat(1, 4);
            rootRule.Add(itemOuter);

            foreach (char t in ValidDigits)
            {
                itemInner = new SrgsItem(t.ToString());
                oneOf.Add(itemInner);
                SrgsSemanticInterpretationTag sr2 = new SrgsSemanticInterpretationTag();
                sr2.Script = "$._value = \"" + t.ToString() + "\"";
                itemInner.Add(sr2);
            }

            itemOuter.Add(oneOf);

            SrgsSemanticInterpretationTag sr4 = new SrgsSemanticInterpretationTag();
            sr4.Script = string.Format("$.{0}._value = $.{1}._value + $._value", slotName, slotName);
            itemOuter.Add(sr4);

            // Create the SRGS Document for A DTMF gramamr and add the root rule
            SrgsDocument srgsDocument = new SrgsDocument();
            srgsDocument.Mode = SrgsGrammarMode.Dtmf;


            srgsDocument.Rules.Add(rootRule);
            srgsDocument.Root = rootRule;
            string filePath = @"e:\mylogs\test.grxml";

            XmlTextWriter writer = new XmlTextWriter(filePath, System.Text.Encoding.UTF8);
            srgsDocument.WriteSrgs(writer);
            writer.Flush();
            writer.Close();
            Microsoft.SpeechServer.Recognition.Grammar dynamicGrammar = new Microsoft.SpeechServer.Recognition.Grammar(srgsDocument);

            return dynamicGrammar;
        }

 

After creating the grammar and assigning it to my questionAnswerActivity I was faced with the problem of how to get the recognition results. Since the grammar “slots” are created at runtime I can’t just use the standard method of referencing the key value – I don’t know the key name at coding time. The first thing I did was to search the forums on GotSpeech.Net but I didn’t find an answer there though I did get some ideas. Then I asked a few developer friends but it seemed no one had done anything quite like this. I was on my own on this one.

Well I thought of several approaches but none seem to practical. Most wouldn’t even compile for some reason or another or gave error messages about no public GetEnumerator. Well after spending some time in the debugger looking at the RecognitionResult object this is what I came up with. (note: I realize this will overwrite the values each time through the foreach loop but this was just to test that I can get to the proper values. In a real world app you would need to save them off).

            string password;
            string key;

            foreach (System.Collections.Generic.KeyValuePair <string, SemanticValue> si in this.questionAnswerActivity1.RecognitionResult.Semantics)
            {
                key = si.Key;
                password = si.Value.Value.ToString();
            }

I hope this helps someone and saves them some time.

Posted: Tuesday, January 05, 2010 9:26 PM by marshallharrison

Comments

No Comments

Anonymous comments are disabled