views:

179

answers:

1

Hello, this SAPI grammar catch the word name is the middle of a sentence.

<GRAMMAR LANGID="409">
    <RULE NAME="SOUNDLOG" TOPLEVEL="ACTIVE">
        <OPT>
            <DICTATION MAX="INF"/>
        </OPT>
        <L>
            <P>name</P>
        </L>
        <OPT>
            <DICTATION MAX="INF"/>
        </OPT>
    </RULE>
</GRAMMAR>

So, if I say "My name is André", the word "name" is identified. Is there a better way to do this?

+2  A: 

When you get the recognition, the SPPHRASE data associated with the recognition contains the subrules and property data and where they occur in the recognition.

So, if you had a rule or property tag for 'Name', you could find the words associated with 'Name'.

For example, given your grammar

<GRAMMAR LANGID="409"> 
    <RULE NAME="SOUNDLOG" TOPLEVEL="ACTIVE"> 
        <OPT> 
            <DICTATION MAX="INF"/> 
        </OPT> 
        <L> 
            <P>name</P> 
        </L> 
        <OPT> 
            <DICTATION MAX="INF"/> 
        </OPT> 
    </RULE> 
</GRAMMAR> 

if you change it to

<GRAMMAR LANGID="409"> 
    <RULE NAME="SOUNDLOG" TOPLEVEL="ACTIVE"> 
        <OPT> 
            <DICTATION MAX="INF"/> 
        </OPT> 
        <L PROPNAME='name'> 
            <P VAL='name'>name</P> 
        </L> 
        <OPT> 
            <DICTATION MAX="INF"/> 
        </OPT> 
    </RULE> 
</GRAMMAR> 

you could find the words that correspond to 'name' like this:

HRESULT OnRecognition(ISpRecoResult* pResult)
{
    SPPHRASE *pPhrase;
    HRESULT hr = pResult->GetPhrase(&pPhrase);
    if (SUCCEEDED(hr))
    {
         const SPPHRASEPROPERTY pProp = FindProperty(pPhrase->pProperty, L"name");
         if (pRule)
         {
             LPWSTR text(NULL);
             hr = pResult->GetText(pProp->ulFirstElement, pProp->ulCountOfElements, TRUE, &text, NULL);
             if (SUCCEEDED(hr))
             {
                 // do something with text
                 ::CoTaskMemFree(text);
             }
         }
    }
    return hr;
}
const SPPHRASEPROPERTY* FindProperty(const SPPHRASEPROPERTY* pProp, LPCWSTR what) const
{
    while (pProp!=NULL)
    {
        if (pProp->pFirstChild != NULL)
        {
            const SPPHRASEPROPERTY* pFoundProp = FindRule(pProp->pFirstChild, what);
            if (pFoundProp)
            {
                return pFoundProp;
            }
        }
        if (pProp->pszName != NULL && wcsstr(pProp->pszName, what) != NULL)
        {
            return pProp;
        }
        pProp = pProp->pNextSibling;
    }
    return NULL;
}

This code looks specifically for the text covered by the property. However, it's often better to use the val attributes to identify items without binding your code explicitly to the grammar. This allows you to tweak the grammar (or add equivalent values) without changing your code. To use the values, simply use the SPPHRASEPROPERTY.pszValue or vValue fields after fetching the property (instead of using ISpPhrase::GetText).

Eric Brown
please see my editted question :)
aF
Please see edited answer. :)
Eric Brown
Do you have in c# code?
aF
Are you using speechlib or System.Speech.Recognition? Speechlib is a thin wrapper around SAPI and the code is pretty directly translatable (you would use ISpeechPhraseInfo instead of SPPHRASE); System.Speech.Recognition is much thicker; it uses a different grammar format (SRGS) and while it's definitely possible to do the same things, the approach is slightly different and not something I'd want to put in a comment. :)
Eric Brown
@Eric+1 .. Thanks it helped
Favonius