SAPI识别超过2个属性

时间:2015-12-18 15:22:39

标签: c++ sapi

我在谷歌搜索有关SAPI识别短语的一些信息时发现了这一点。此示例显示规则中是否只有一个属性。那么如果该规则中有2个或更多属性呢?如何为此编写代码?我仍然对SAPI感到困惑,并试图理解它。欢迎任何帮助,谢谢!

The alternate method is add a property to your list tag/items [you appear to
 be familiar with properties], iterate through the property tree to find the
property, and then retrieve the associated item from the property. Note if
this is the only property in your recognized rule, then it is fairly easy to
retrieve the property [no need to navigate the property tree].
For example, you could change your rule to be the following:

<RULE ID="VID_Vcs">
<L PROPNAME="NAME_LIST">
   <P VAL="1">Mike </P>
   <P VAL="2">Davor </P>
   <P VAL="3">Kurt </P>
   <P VAL="4">Steve </P>
</L>
</RULE>


Use the following code to retrieve the list item value/phrase text
SPPHRASE* pPhrase = NULL;
hr = cpRecoResult->GetPhrase(&pPhrase);
// Check hr

// Let's assume that you only have one property in your rule, so there is only one property in the property tree.
// ASSERT: NULL == pPhrase->pProperties->pNextSibling && NULL == pPhrase->pProperties->pFirstChild
// ASSERT: NULL != pPhrase->pProperties->pszName && 0 == wcscmp(pPhrase->pProperties->pszName, L"NAME_LIST")

// retrieve the list item index [e.g. 1-4], see VAL XML tags in aforementioned grammar
long lRecognizedListItemIndex = pPhrase->pProperties->vValue.lVal;

// retrieve the phrase text
hr = cpRecoResult->GetText(pPhrase->pProperties->ulFirstElement, pPhrase->pProperties->ulCOuntOfElements, FALSE, &pwszListItem, NULL);
// Check hr

// pwszListItem now contains the recognized list item


//compared to the phrase tag of the dictionary (XML)
if(SUCCEEDED (hResult)) {
    if ((pPhrase->pProperties != nullptr) &&         (pPhrase->pProperties->pFirstChild != nullptr)){
        const SPPHRASEPROPERTY* pRule = pPhrase->pProperties->pFirstChild ;
        if (pRule->SREngineConfidence->confidence Threshold) {
            if ( wcscmp ( L"word one", pRule->pszValue) == 0 ) {
                //do stuff here
            }
            else if ( wcscmp ( L"word two", pRule->pszValue) == 0 ) {
                //do stuff here
            }
            else if ( wcscmp ( L"word three", pRule->pszValue) == 0 ) {
                //do stuff here
            }
            else if ( wcscmp ( L"word four", pRule->pszValue ) == 0) {
                //do stuff
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

好吧,对不起等待。我制作了一个简单的程序,可以帮助你弄清楚你想要做什么。

所以这是我的语法文件:

<GRAMMAR LANGID="409">
    <DEFINE>
        <ID NAME="LIKE_VAL" VAL="1"/>
        <ID NAME="SUBJECT_VAL" VAL="2"/>
        <ID NAME="COMBINED_VAL" VAL="3"/>
        <ID NAME="EXIT_VAL" VAL="4"/>
    </DEFINE>
    <RULE NAME="LIKE_VAL" TOPLEVEL="ACTIVE">
        <L>
            <P>I <O>really</O> like</P>
            <P>I <O>really</O> do not like</P>
        </L>
    </RULE>
    <RULE NAME="SUBJECT_VAL" TOPLEVEL="ACTIVE">
        <P>ponies.</P>
    </RULE>
    <RULE NAME="COMBINED_VAL" TOPLEVEL="ACTIVE">
        <RULEREF NAME="LIKE_VAL"/>
        <RULEREF NAME="SUBJECT_VAL"/>
    </RULE>
    <RULE NAME="EXIT_VAL" TOPLEVEL="ACTIVE">
        <L>
            <P>Exit</P>
            <P>Quit</P>
            <P>Terminate</P>
            <P>Deluminate</P>
        </L>
    </RULE>
</GRAMMAR>

这是一个使用它的完整程序:

#include "sphelper.h"
#include <Windows.h>
#include <string>

int main(int argc, char* argv[])
{
    CComPtr<ISpRecognizer> cpReco;
    CComPtr<ISpRecoContext> cpRecoCtx;
    CComPtr<ISpRecoGrammar>  cpRecoGram;

    ULONGLONG ullEvents = SPFEI(SPEI_RECOGNITION)|
       SPFEI(SPEI_FALSE_RECOGNITION);

    ISpObjectToken* pInputToken;
    ISpRecoResult* cpRecoRslt;
    HRESULT hr = S_OK;

    hr = ::CoInitialize(NULL);
    hr = cpReco.CoCreateInstance(CLSID_SpInprocRecognizer);
    hr = cpReco->CreateRecoContext(&cpRecoCtx);
    hr = cpRecoCtx->CreateGrammar(0, &cpRecoGram);
    hr = cpRecoCtx->SetNotifyWin32Event();

    hr = cpRecoCtx->SetInterest(ullEvents, ullEvents);
    hr = SpGetDefaultTokenFromCategoryId(SPCAT_AUDIOIN, &pInputToken);
    hr = cpReco->SetInput(pInputToken, FALSE);
    hr = cpRecoGram->LoadCmdFromFile(L"Your_Test_File.cfg",SPLO_STATIC);
    hr = cpReco->SetRecoState(SPRST_ACTIVE);
    hr = cpRecoCtx->SetContextState(SPCS_ENABLED);
    hr = cpRecoGram->SetGrammarState(SPGS_ENABLED);
    hr = cpRecoGram->SetRuleState(NULL, NULL, SPRS_ACTIVE);
    std::wstring strExit = L"Exit";
    std::wstring strExitRuleName = L"EXIT_VAL";
    CSpEvent spEvent;
    bool isListening = true;
    do{
        hr = cpRecoCtx->WaitForNotifyEvent(INFINITE);
        if(spEvent.GetFrom(cpRecoCtx) == S_OK)
        {
            switch(spEvent.eEventId){
                case SPEI_RECOGNITION:{

                    WCHAR* strReco = 0;
                    cpRecoRslt = spEvent.RecoResult();
                    cpRecoRslt->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, &strReco, NULL);
                    printf("%ls\n",strReco);

                    SPPHRASE *phrase = NULL;
                    cpRecoRslt->GetPhrase(&phrase);
                    if(phrase){
                        std::wstring ruleName = phrase->Rule.pszName;
                        if(strExitRuleName.compare(strExit)==0){
                            isListening = false;
                        }
                    }
                    break;
                }
                case SPEI_FALSE_RECOGNITION:{
                    printf("False Recognition\n");
                    break;
                }
            }
        }
    }while(isListening);

    cpRecoGram.Release();
    cpRecoCtx.Release();
    cpReco.Release();

    ::CoUninitialize();
    printf("Press any key to continue...");
    getchar();

    return 0;
}

您必须更改加载语法调用的加载位置。根据我的理解,您尝试做的是在无上下文语法文件中创建语法并尝试以编程方式执行此操作。通常,您可以从语法文件开始,并在需要时进行修改。

但是,如果你真的需要以编程方式添加新语法,例如当有人输入新语法时,那么你就有机会SPLO_STATIC到SPLO_DYNAMIC并开始实现你在后半部分看到的代码。你看到的MSDN帖子。

我完全遗漏了任何错误检查。如果您需要访问您正在查看的规则的其他属性,请使用pPhrase-&gt; GetPhrase(&amp; phrase)区域。除了规则的名称,您还可以获得它的ID。