0

这个 SAPI 语法抓住了单词名称是句子的中间部分。

<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>

所以,如果我说“我的名字是安德烈”,那么“名字”这个词就被识别出来了。有一个更好的方法吗?

4

1 回答 1

2

当您获得识别时,与识别关联的 SPPHRASE 数据包含子规则和属性数据以及它们在识别中出现的位置。

因此,如果您有“姓名”的规则或属性标签,您可以找到与“姓名”相关联的词。

例如,给定您的语法

<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> 

如果你把它改成

<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> 

您可以像这样找到与“名称”相对应的单词:

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;
}

此代码专门查找该属性所涵盖的文本。但是,通常最好使用 val 属性来识别项目,而无需将代码显式绑定到语法。这允许您在不更改代码的情况下调整语法(或添加等效值)。要使用这些值,只需在获取属性后使用 SPPHRASEPROPERTY.pszValue 或 vValue 字段(而不是使用 ISpPhrase::GetText)。

于 2010-02-05T21:21:43.237 回答