c++ - SAPI 识别超过 2 个属性

标签 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
            }
        }
    }
}

最佳答案

好的,抱歉让您久等了。我编写了一个简单的程序,可以帮助您弄清楚您要做什么。

这是我的语法文件:

<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->GetPhrase(&phrase) 区域。除了规则的名称,您还可以获得它的 ID。

关于c++ - SAPI 识别超过 2 个属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34358823/

相关文章:

c++ - 将 boost::signal 作为 boost::function 传递

c++ - Boost.Spirit X3 另类算子

c++ - 如何实现 `my_class_instance(a, b) = value`操作

javascript - Javascript 中的 Microsoft Sapi - 改变声音

c# - 检测所有已安装的 SAPI 语音

c++ - 无法打开包含文件 : 'atlbase.h' : No such file or directory

c++ - 使用赋值是危险的,因为之前的值无效

c++ - Unordered_Set的迭代器抛出奇怪的错误

c# - 如何为 tts 创建自定义 sapi 语音

windows - 如何更改用于 SAPI.SPVoice 的语音