Speech SDK 5.1(SAPI 5.1)語音開發——————c++(詞語匹配)

 

 

微軟語音識別分兩種模式:聽寫識別模式和命令識別模式。

1.聽寫識別模式使用的是skd中提供的字典,特點是含有的詞彙量大。這種方式適合沒有預定的聽寫內容的應用。同時因爲詞彙量大直接導致識別的精度降低,識別速度較慢。

2.命令識別模式使用開發人員自己定義的字典庫進行識別,使用xml格式文件。這種自定義的識別方式有缺點也有優點,缺點是語法庫的詞彙量小,只有在xml文件中寫入的詞語能夠被識別出並不會輸出其他多餘的內容。而其優點是可以進行精確地數據匹配,識別出開發者希望程序識別出的內容。

一、安裝Speech SDK 5.1(SAPI 5.1)

首先開發得需要Microsoft Speech SDK的支持,以下是下載地址
http://download.csdn.net/detail/michaelliang12/9510691

二、配置環境(vs2013)

設置: 
1,屬性–配置屬性–C/C++–常規–附加包含目錄:C:\Program Files\Microsoft SDKs\Speech\v11.0\Include(具體路徑與與你安裝時的路徑有關) 
2,屬性–配置屬性–鏈接器–輸入–附加依賴項:sapi.lib;

三、源文件

注:在我做的程序中是將語音識別的內容編寫爲.h文件,在主程序中進行函數調用取得識別出的文字,對識別出的地名進行處理。

c++的碼段:

#pragma once
#include <windows.h>
#include <sapi.h>
#include <iostream>
#include <string.h>
#include <atlbase.h>
#include "sphelper.h"
#include"string"
#include <atlbase.h>
using namespace std;
inline HRESULT BlockForResult(ISpRecoContext * pRecoCtxt, ISpRecoResult ** ppResult) //識別
{
	HRESULT hr = S_OK;
	CSpEvent event;
	while (SUCCEEDED(hr) &&
		SUCCEEDED(hr = event.GetFrom(pRecoCtxt)) &&
		hr == S_FALSE)
	{
		hr = pRecoCtxt->WaitForNotifyEvent(INFINITE);
	}

	*ppResult = event.RecoResult();
	if (*ppResult)
	{
		(*ppResult)->AddRef();
	}
	return hr;
}
string Speech_1()
{
	HRESULT hr = E_FAIL;
	string str;
	CSpDynamicString dstrText;//取得識別結果 
	
	if (SUCCEEDED(hr = ::CoInitialize(NULL))) //進行COM初始化
	{
		{
			CComPtr<ISpRecoContext> r_cpRecoCtxt;// 識別引擎上下文(context)的接口。
			CComPtr<ISpRecoGrammar> r_cpRecoGrammar;// 識別文法(grammar)的接口。
			CComPtr<ISpVoice> r_cpVoice;//語音發聲(Voice)的接口
			CComPtr<ISpRecoResult> cpResult;//接收語音識別(SR)引擎識別的結果
			if (FAILED(hr = r_cpRecoCtxt.CoCreateInstance(CLSID_SpSharedRecoContext)))
			{
				printf("r_cpRecoCtxt.CoCreateInstance() fail. hr = %x", hr);
			}
			if (FAILED(hr = r_cpRecoCtxt->GetVoice(&r_cpVoice)))
			{
				printf("r_cpRecoCtxt->GetVoice() fail. hr = %x", hr);
			}
			if (r_cpRecoCtxt && r_cpVoice)
			{
				if (FAILED(hr = r_cpRecoCtxt->SetNotifyWin32Event()))
				{
					printf("r_cpRecoCtxt->SetNotifyWin32Event() fail. hr = %x", hr);
				}
				if (FAILED(hr = r_cpRecoCtxt->SetInterest(SPFEI(SPEI_RECOGNITION), SPFEI(SPEI_RECOGNITION))))
				{
					printf("r_cpRecoCtxt->SetInterest() fail. hr = %x", hr);
				}
				if (FAILED(hr = r_cpRecoCtxt->SetAudioOptions(SPAO_RETAIN_AUDIO, NULL, NULL)))
				{
					printf("r_cpRecoCtxt->SetAudioOptions() fail. hr = %x", hr);
				}
				if (FAILED(hr = r_cpRecoCtxt->CreateGrammar(7, &r_cpRecoGrammar)))//創建語法規則 
				{
					printf("r_cpRecoCtxt->CreateGrammar() fail. hr = %x", hr);
				}
				if (FAILED(hr = r_cpRecoGrammar->SetGrammarState(SPGS_DISABLED)))
				{
					printf("r_cpRecoGrammar->SetGrammarState() fail. hr = %x", hr);
				}
				if (FAILED(hr = r_cpRecoGrammar->LoadCmdFromFile(L"conf.xml", SPLO_DYNAMIC)))//加載語法規則 
				{
					printf("r_cpRecoGrammar->LoadCmdFromFile() fail. hr = %x", hr);
			    }
				USES_CONVERSION;/* USES_CONVERSION是用來轉換類型的*/
				CComPtr<ISpRecoResult> cpResult;//接收語音識別(SR)引擎識別的結果
				while (SUCCEEDED(hr = BlockForResult(r_cpRecoCtxt, &cpResult)))
				{
					if (SUCCEEDED(cpResult->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE,
						TRUE, &dstrText, NULL)))
					{
						printf("%s", W2A(dstrText));//輸出識別內容
						cpResult.Release();//釋放結果
						str = W2A(dstrText);//取得識別內容
						if (!str.empty())
							break;
					}
					r_cpRecoGrammar->SetRuleState(NULL, NULL, SPRS_ACTIVE);
				}
			}
		}
		::CoUninitialize();//釋放結果
	}
	return str;
}

conf.xml代碼:

GRAMMAR LANGID="804"> 
    <DEFINE> 
       <ID NAME="CMD" VAL="10"/> 
    </DEFINE> 
    <RULE NAME="COMMAND" ID="CMD" TOPLEVEL="ACTIVE"> 
      <L> 
<p>圖書館</P> 
<p>東門</p> 
<p>西門</p> 
<p>操場</p> 
<p>藝術館</p> 
<p>體育館</p> 
<p>教學樓</p> 
<p>辦公樓</p> 
      </L> 
    </RULE> 
</GRAMMAR> 

 以上的代碼僅能實現詞語匹配的功能。

在製作這個程序的過程中參考了網上的大部分資料,才能在那麼短的時間裏做出想要的功能。

參考網站

1.https://blog.csdn.net/qikaibinglan/article/details/4205325
2.https://blog.csdn.net/artemisrj/article/details/8723095

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章