用SAPI做一个聊天模拟器

一、目前掌握的关于SAPI的情报
1、可以通过笔记本电脑的听筒和话筒,实现语音识别,语音朗读。
2、可以识别出预先设定的中文内容。
3、可以朗读输入的中文内容。
最初的想法是为工业控制软件添加语音识别的控制,这将是慵懒的极致表现。。。。以后在实验室张嘴就能完成测试。研究途中冒出了个聊天模拟器的想法,设定好问题与答案就可以和电脑聊天了,其实答案也可以设置多个随机。。。。

二、下载与安装
参考他的,他的全
添加链接描述

这个链接下,下载 SpeechSDK51.exe、SpeechSDK51LangPach.exe和msttss22L.exe。
添加链接描述
在这里插入图片描述

依次安装 SpeechSDK51.exe SpeechSDK51LangPach.exe msttss22L.exe。
在这里插入图片描述
这里有头文件和lib文件,之后会用到。

三、整理模块
依然用vs2013MFC对话框,准备引入SAPI的必要头文件,lib文件
安装好Microsoft Speech SDK 5.1后,来到 “Microsoft Speech SDK 5.1”文件夹,“Include”文件夹下的全要,还有Lib->i386->sapi.lib文件。
在工程根目录添加一个文件夹“sapiInclude”把上边两个东西添加进来。
在这里插入图片描述
四、编写
来到vs2013IDE。创建一个类 MFC_YuYin
这是MFC_YuYin.h

#pragma once

#include "sapiInclude\sapi.h"
#include "sapiInclude\sphelper.h"
#pragma comment(lib,"sapiInclude\\sapi.lib")
#include <afxwin.h>
#define WM_RECORD  WM_USER + 100

// 引入
/*


stdafx.h中

#include "MFC_YuYin.h"


dlg.h 中

public:
MFC_YuYin myYuYin;

DWORD dwThreadID;
static DWORD WINAPI Thread_FunRead(LPVOID pthread);
atomic<BOOL> abStateruning;


protected:
afx_msg LRESULT OnRecord(WPARAM wParam, LPARAM lParam);



dlg.cpp 中


在BEGIN_MESSAGE_MAP(CXXXDlg, CDialogEx) ~END_MESSAGE_MAP()中  !!!不是CAboutDlg中  【CXXXDlg需要手动修改】

ON_MESSAGE(WM_RECORD, &CXXXDlg::OnRecord)


在 OnInitDialog 中
myYuYin.Init_YuYin(this);
abStateruning.store(TRUE, std::memory_order_release);
CreateThread(0, NULL, (LPTHREAD_START_ROUTINE)&Thread_FunRead, this, 0, &dwThreadID);



【CXXXDlg需要手动修改】

afx_msg LRESULT CXXXDlg::OnRecord(WPARAM wParam, LPARAM lParam)  
{
	USES_CONVERSION;
	CSpEvent event;
	//MessageBox(L"onrecord");
	if (myYuYin.m_pSRContext)
	{
		while (event.GetFrom(myYuYin.m_pSRContext) == S_OK){

			switch (event.eEventId)
			{
				case SPEI_RECOGNITION:
				{
					//识别出了语音输入 //m_bGotReco = TRUE;
					static const WCHAR wszUnrecognized[] = L"<Unrecognized>";

					CSpDynamicString dstrText;

					//取得识别结果
					if (FAILED(event.RecoResult()->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, &dstrText, NULL)))
					{
						dstrText = wszUnrecognized;
					}

					BSTR SRout;
					dstrText.CopyToBSTR(&SRout);

					CString Recstring;
					Recstring.Empty();
					Recstring = SRout;
					//这里开始处理语音识别的消息。
					//MessageBox(Recstring);
					SetDlgItemText(IDC_STATIC2, Recstring);

					::PostThreadMessage(dwThreadID, 2587, (WPARAM)Recstring.AllocSysString(), 0);
				}
				break;
			}
		}
	}
	return NULL;

}







DWORD WINAPI CXXXDlg::Thread_FunRead(LPVOID pthread)
{
CtrySAPIDlg* dlg = (CtrySAPIDlg*)pthread;

MSG msg;
CString strReplay;
while (dlg->abStateruning.load(std::memory_order_acquire))
{
GetMessage(&msg, NULL, 0, 0);
dlg->myYuYin.m_pSREngine->SetRecoState(SPRST_INACTIVE);
int iMessage = msg.message;
CString strJieshou = (CString)((BSTR)msg.wParam);
if (iMessage==2587)
{
if (strJieshou.Compare(L"你好")==0)
{
strReplay = L"你也好啊";
}
else if (strJieshou.Compare(L"干啥呢")==0)
{
strReplay = L"跟你唠嗑呢呗,你是不傻";
}
else if (strJieshou.Compare(L"你瞅啥")==0)
{
strReplay = L"瞅你咋弟";
}
else if (strJieshou.Compare(L"多大啊") == 0)
{
strReplay = L"18岁,零几十个月";
}
else if (strJieshou.Compare(L"你男的女的") == 0)
{
strReplay = L"看你需要";
}
else if (strJieshou.Compare(L"你喜欢小动物吗") == 0)
{
strReplay = L"喜欢,小猪小羊小牛,烤得嫩些";
}
else if (strJieshou.Compare(L"有什么爱耗") == 0)
{
strReplay = L"养鱼";
}
else if (strJieshou.Compare(L"养了多少鱼") == 0)
{
strReplay = L"我家没鱼缸啊";
}
else if (strJieshou.Compare(L"工作咋样") == 0)
{
strReplay = L"平面模特,月入上万";
}
else if (strJieshou.Compare(L"有对象吗") == 0)
{
strReplay = L"单身可撩";
}
else if (strJieshou.Compare(L"择偶标准") == 0)
{
strReplay = L"只要小哥长得好,一句在吗我就岛";
}
else if (strJieshou.Compare(L"你觉得我怎么样") == 0)
{
strReplay = L"你是个好人,但你配不上我";
}
else if (strJieshou.Compare(L"小嘴真甜") == 0)
{
strReplay = L"甜不甜,你也尝不到";
}

dlg->SetDlgItemTextW(IDC_STATIC3, strReplay);
dlg->myYuYin.MFC_Speak_ASyn(strReplay);
}

dlg->myYuYin.m_pSREngine->SetRecoState(SPRST_ACTIVE);


}



return 0;
}







*/



// 我的语音类
class MFC_YuYin
{
public:
	MFC_YuYin();

	~MFC_YuYin();
public:

	ISpVoice *pSpVoice; // 重要COM接口
	CLSID CLSID_SpVoice; // 似乎已经在sapi.h里定义
	IEnumSpObjectTokens *pSpEnumTokens;
	ISpObjectToken *pSpToken;


	// 【】字符转语音

	// 念字母或汉字
	void MFC_Speak_Syn(CString strWords);
	void MFC_Speak_ASyn(CString strWords);

	// 速度 -10 10
	void MFC_SetRate(long RateAdjust);
	long MFC_GetRate();

	// 语音库??
	void MFC_SetVoice(ISpObjectToken *pToken);
	ISpObjectToken* MFC_GetVoice();

	// 暂停
	void MFC_Pause();
	void MFC_Resume();

	// 设置音量,范围:0到100
	void MFC_SetVolume(int iZhi);
	int MFC_GetVolume();



public:
	// 【】语音识别
	CComPtr<ISpRecognizer> m_pSREngine;// 语音识别引擎(recognition)的接口。
	CComPtr<ISpRecoContext> m_pSRContext;// 识别引擎上下文(context)的接口。

	CComPtr<ISpAudio>m_pAudio;// 音频(Audio)的接口。(用来保存原来默认的输入流)
	ULONGLONG  ullGrammerID;
	CComPtr<ISpRecoGrammar>m_pSRGrammar;// 识别文法(grammar)的接口。

	// 连接对话框
	CDialog* dlg_SAPI;
	BOOL Init_YuYin(CDialog* dlg);


};



这是MFC_YuYin.cpp

#include "stdafx.h"
#include "MFC_YuYin.h"

MFC_YuYin::MFC_YuYin()
{
	::CoInitialize(NULL); // COM初始化

	// 【】字符转语音
	CLSIDFromProgID(_T("SAPI.SpVoice"), &CLSID_SpVoice);
	//::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // COM初始化
	pSpEnumTokens = NULL;
	if (FAILED(CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_INPROC_SERVER, IID_ISpVoice, (void**)&pSpVoice)))
	{
		return;
	}
}


MFC_YuYin::~MFC_YuYin()
{
	pSpVoice->Release();
	::CoUninitialize();
}

void MFC_YuYin::MFC_Speak_Syn(CString strWords)
{
	pSpVoice->Speak(strWords, SPF_DEFAULT, NULL);
}
void MFC_YuYin::MFC_Speak_ASyn(CString strWords)
{
	pSpVoice->Speak(strWords, SPF_ASYNC, NULL);
}


// 速度 -10 10
void MFC_YuYin::MFC_SetRate(long RateAdjust)
{
	pSpVoice->SetRate(RateAdjust);
}
long MFC_YuYin::MFC_GetRate()
{
	long rate = 0;
	pSpVoice->GetRate(&rate);
	return rate;
}

// 语音库
void MFC_YuYin::MFC_SetVoice(ISpObjectToken *pToken)
{

	//pSpVoice->SetVoice();
}
ISpObjectToken* MFC_YuYin::MFC_GetVoice()
{
	ISpObjectToken* p = NULL;
	return p;
}
// 暂停
void MFC_YuYin::MFC_Pause()
{
	pSpVoice->Pause();
}
void MFC_YuYin::MFC_Resume()
{
	pSpVoice->Resume();
}

// 设置音量,范围:0到100
void MFC_YuYin::MFC_SetVolume(int iZhi)
{
	pSpVoice->SetVolume(iZhi);
}
int MFC_YuYin::MFC_GetVolume()
{
	USHORT  iZhi = 0;
	pSpVoice->GetVolume(&iZhi);
	return iZhi;
}


BOOL MFC_YuYin::Init_YuYin(CDialog* dlg)
{
	dlg_SAPI = dlg;
	// 【】语音识别
	HRESULT hr;
	hr = m_pSREngine.CoCreateInstance(CLSID_SpInprocRecognizer);
	if (FAILED(hr)){
		dlg_SAPI->MessageBox(L"m_pSREngine.CoCreateInstance");
		return FALSE;
	}

	hr = m_pSREngine->CreateRecoContext(&m_pSRContext);//建立上下文
	if (FAILED(hr)){
		dlg_SAPI->MessageBox(L" m_pSREngine->CreateRecoContext ");
		return FALSE;
	}

	//这里是设置事件
	HWND hwnd = dlg_SAPI->GetSafeHwnd();
	hr = m_pSRContext->SetNotifyWindowMessage(hwnd, WM_RECORD, 0, 0);
	if (FAILED(hr)){
		dlg_SAPI->MessageBox(L"SetNotifyWindowMessage");
		return FALSE;
	}

	hr = m_pSRContext->SetInterest(SPFEI(SPEI_RECOGNITION), SPFEI(SPEI_RECOGNITION));

	IEnumSpObjectTokens* m_pIEnumSpObjectTokens = NULL;

	SpEnumTokens(SPCAT_VOICES, NULL, NULL, &m_pIEnumSpObjectTokens);

	//这里是设置默认的音频输入
	hr = SpCreateDefaultObjectFromCategoryId(SPCAT_AUDIOIN, &m_pAudio);
	m_pSREngine->SetInput(m_pAudio, true);

	//这里是加载默认的语法规则
	ullGrammerID = 1000;
	hr = m_pSRContext->CreateGrammar(ullGrammerID, &m_pSRGrammar);
	if (FAILED(hr)){
		dlg_SAPI->MessageBox(L"CreateGrammar");
		return FALSE;
	}

	//WCHAR wszXMLFile[20] = L"";
	//MultiByteToWideChar(CP_ACP, 0, (LPCSTR)"sapiInclude\\main.xml", -1, wszXMLFile, 256);  //这里修改XML的目录
	hr = m_pSRGrammar->LoadCmdFromFile(L"sapiInclude\\main.xml", SPLO_DYNAMIC);
	if (FAILED(hr)){
		dlg_SAPI->MessageBox(L"LoadCmdFromFile");
		return FALSE;
	}

	//开启语音识别
	m_pSRGrammar->SetRuleState(NULL, NULL, SPRS_ACTIVE);
	hr = m_pSREngine->SetRecoState(SPRST_ACTIVE);
	if (FAILED(hr)){
		dlg_SAPI->MessageBox(L"SetRecoState");
		return FALSE;
	}

	return TRUE;
}





在stdafx.h里头添加


#include <atomic>
#include "MFC_YuYin.h"
using namespace std;

此时编译会报错 crt_secure_no_warnings等一类的错误,说是添加在预处理里,比较累,不如把那几个特定的函数改一改。
sphelper.h有很多错误。参考这个链接改
添加链接描述

 Ln 769 const ulLenVendorPreferred = wcslen(pszVendorPreferred);

             const unsigned long ulLenVendorPreferred = wcslen(pszVendorPreferred);

Ln 1418 static CoMemCopyWFEX(const WAVEFORMATEX * pSrc, WAVEFORMATEX ** ppCoMemWFEX)

              static HRESULT CoMemCopyWFEX(const WAVEFORMATEX * pSrc, WAVEFORMATEX ** ppCoMemWFEX)

Ln 2372 for (const WCHAR * psz = (const WCHAR *)lParam; *psz; psz++) {}

             const WCHAR * psz; for (psz = (const WCHAR *)lParam; *psz; psz++) {}

Ln 2559 SPPHONEID* pphoneId = dsPhoneId;

              SPPHONEID* pphoneId = (SPPHONEID*)((WCHAR *)dsPhoneId);

Ln 2633 pphoneId += wcslen(pphoneId) + 1;

              pphoneId += wcslen((const wchar_t *)pphoneId) + 1; 

由于我们没有用引用外库的方式引入inlcude而是在根目录下添加了头文件和lib所以要把一些<>改成“”

sphelper.h里
Ln 25 #include “sapiddk.h”
Ln 29 #include “SPError.h”
Ln 33 #include “SPDebug.h”

还有一些函数
Ln 741 SPDBG_FUNC(“SpEnumTokens”); ->
SPDBG_FUNC(PCHAR(“SpEnumTokens”));
Ln 769 const ulLenVendorPreferred = wcslen(pszVendorPreferred); ->
const unsigned long ulLenVendorPreferred = wcslen(pszVendorPreferred);
Ln 778~780 wcscpy(pszOptAttribsVendorPref, pszOptAttribs);
wcscat(pszOptAttribsVendorPref, L";");
wcscat(pszOptAttribsVendorPref, pszVendorPreferred); ->
wcscpy_s(pszOptAttribsVendorPref, wcslen(pszOptAttribs), pszOptAttribs);
wcscat_s(pszOptAttribsVendorPref, wcslen(pszOptAttribsVendorPref), L";");
wcscat_s(pszOptAttribsVendorPref, wcslen(pszOptAttribsVendorPref), pszVendorPreferred);
Ln 784 wcscpy(pszOptAttribsVendorPref, pszVendorPreferred); ->
wcscpy_s(pszOptAttribsVendorPref, wcslen(pszOptAttribsVendorPref), pszVendorPreferred);
Ln 920~921 wcscpy(szLangCondition, L"Language=");
wcscat(szLangCondition, szLang); ->
wcscpy_s(szLangCondition, wcslen(szLangCondition), L"Language=");
wcscat_s(szLangCondition, wcslen(szLangCondition), szLang);
Ln 1002 if(!GetVersionEx(&Osv)) ->
if (0) // 这个实在不会改了。。。。。暂时改成这样
Ln 1237 memset( pwfex, 0, NumBytes ); ->
::memset( pwfex, 0, NumBytes );
Ln 1262 memset( pwfex, 0, sizeof(WAVEFORMATEX) ); ->
::memset( pwfex, 0, sizeof(WAVEFORMATEX) );
Ln 1342 memset( pwfex, 0, NumBytes ); ->
::memset( pwfex, 0, NumBytes );
Ln 1373 memset( pwfex, 0, NumBytes ); ->
::memset( pwfex, 0, NumBytes );
Ln 1418 static CoMemCopyWFEX(const WAVEFORMATEX * pSrc, WAVEFORMATEX ** ppCoMemWFEX) ->
static HRESULT CoMemCopyWFEX(const WAVEFORMATEX * pSrc, WAVEFORMATEX ** ppCoMemWFEX)
Ln 1726 memset(&m_guidFormatId, 0, sizeof(m_guidFormatId)); ->
::memset(&m_guidFormatId, 0, sizeof(m_guidFormatId));
Ln 1734 memset(&m_guidFormatId, 0, sizeof(m_guidFormatId)); ->
::memset(&m_guidFormatId, 0, sizeof(m_guidFormatId));
Ln 1746 memset(pFormatId, 0, sizeof(pFormatId)); ->
::memset(pFormatId, 0, sizeof(pFormatId));
Ln 1921 memset(pe, 0, sizeof(pe)); ->
::memset(pe, 0, sizeof(pe));
Ln 2097 wcscpy((WCHAR
)pDestEvent->lParam, (WCHAR
)lParam); ->
wcscpy_s((WCHAR
)pDestEvent->lParam, wcslen((WCHAR
)pDestEvent->lParam), (WCHAR*)lParam);
Ln 2127 加::
Ln 2129 加::
Ln 2372 for (const WCHAR * psz = (const WCHAR *)lParam; psz; psz++) {} ->
for (const WCHAR * psz = (const WCHAR )lParam; psz; psz++) {}
Ln 2559 SPPHONEID
pphoneId = dsPhoneId; ->
SPPHONEID
pphoneId = (SPPHONEID
)((WCHAR *)dsPhoneId);
Ln 2593 wcscpy( pText, ppWords[i] ); ->
wcscpy_s(pText, wcslen(pText), ppWords[i]);
Ln 2633 pphoneId += wcslen(pphoneId) + 1; ->
pphoneId += wcslen((const wchar_t *)pphoneId) + 1;

接下来编画个界面
在这里插入图片描述
第一个静态文本控件 ID是 IDC_STATIC2 第二个是 IDC_STATIC3

对话框头文件


// trySAPIDlg.h : 头文件
//

#pragma once


// CtrySAPIDlg 对话框
class CtrySAPIDlg : public CDialogEx
{
// 构造
public:
	CtrySAPIDlg(CWnd* pParent = NULL);	// 标准构造函数

// 对话框数据
	enum { IDD = IDD_TRYSAPI_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()


	afx_msg LRESULT OnRecord(WPARAM wParam, LPARAM lParam);
public:
	MFC_YuYin myYuYin;

	DWORD dwThreadID;
	static DWORD WINAPI Thread_FunRead(LPVOID pthread);
	atomic<BOOL> abStateruning;
};

对话框.cpp文件


// trySAPIDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "trySAPI.h"
#include "trySAPIDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CtrySAPIDlg 对话框



CtrySAPIDlg::CtrySAPIDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CtrySAPIDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CtrySAPIDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CtrySAPIDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_MESSAGE(WM_RECORD, &CtrySAPIDlg::OnRecord)
END_MESSAGE_MAP()


// CtrySAPIDlg 消息处理程序

BOOL CtrySAPIDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO:  在此添加额外的初始化代码
	myYuYin.Init_YuYin(this);
	abStateruning.store(TRUE, std::memory_order_release);
	CreateThread(0, NULL, (LPTHREAD_START_ROUTINE)&Thread_FunRead, this, 0, &dwThreadID);



	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CtrySAPIDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CtrySAPIDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CtrySAPIDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

afx_msg LRESULT CtrySAPIDlg::OnRecord(WPARAM wParam, LPARAM lParam)
{
	USES_CONVERSION;
	CSpEvent event;
	//MessageBox(L"onrecord");
	if (myYuYin.m_pSRContext)
	{
		while (event.GetFrom(myYuYin.m_pSRContext) == S_OK){

			switch (event.eEventId)
			{
				case SPEI_RECOGNITION:
				{
					//识别出了语音输入 //m_bGotReco = TRUE;
					static const WCHAR wszUnrecognized[] = L"<Unrecognized>";

					CSpDynamicString dstrText;

					//取得识别结果
					if (FAILED(event.RecoResult()->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, &dstrText, NULL)))
					{
						dstrText = wszUnrecognized;
					}

					BSTR SRout;
					dstrText.CopyToBSTR(&SRout);

					CString Recstring;
					Recstring.Empty();
					Recstring = SRout;
					//这里开始处理语音识别的消息。
					//MessageBox(Recstring);
					SetDlgItemText(IDC_STATIC2, Recstring);

					::PostThreadMessage(dwThreadID, 2587, (WPARAM)Recstring.AllocSysString(), 0);

				}
				break;
			}
		}
	}
	return NULL;

}


DWORD WINAPI CtrySAPIDlg::Thread_FunRead(LPVOID pthread)
{
	CtrySAPIDlg* dlg = (CtrySAPIDlg*)pthread;

	MSG msg;
	CString strReplay;
	while (dlg->abStateruning.load(std::memory_order_acquire))
	{
		GetMessage(&msg, NULL, 0, 0);
		dlg->myYuYin.m_pSREngine->SetRecoState(SPRST_INACTIVE);
		int iMessage = msg.message;
		CString strJieshou = (CString)((BSTR)msg.wParam);
		if (iMessage==2587)
		{
			if (strJieshou.Compare(L"你好")==0)
			{
				strReplay = L"你也好啊";
			}
			else if (strJieshou.Compare(L"干啥呢")==0)
			{
				strReplay = L"跟你唠嗑呢呗,你是不傻";
			}
			else if (strJieshou.Compare(L"你瞅啥")==0)
			{
				strReplay = L"瞅你咋弟";
			}
			else if (strJieshou.Compare(L"多大啊") == 0)
			{
				strReplay = L"18岁,零几十个月";
			}
			else if (strJieshou.Compare(L"你男的女的") == 0)
			{
				strReplay = L"看你需要";
			}
			else if (strJieshou.Compare(L"你喜欢小动物吗") == 0)
			{
				strReplay = L"喜欢,小猪小羊小牛,烤得嫩些";
			}
			else if (strJieshou.Compare(L"有什么爱耗") == 0)
			{
				strReplay = L"养鱼";
			}
			else if (strJieshou.Compare(L"养了多少鱼") == 0)
			{
				strReplay = L"我家没鱼缸啊";
			}
			else if (strJieshou.Compare(L"工作咋样") == 0)
			{
				strReplay = L"平面模特,月入上万";
			}
			else if (strJieshou.Compare(L"有对象吗") == 0)
			{
				strReplay = L"单身可撩";
			}
			else if (strJieshou.Compare(L"择偶标准") == 0)
			{
				strReplay = L"只要小哥长得好,一句在吗我就岛";
			}
			else if (strJieshou.Compare(L"你觉得我怎么样") == 0)
			{
				strReplay = L"你是个好人,但你配不上我";
			}
			else if (strJieshou.Compare(L"小嘴真甜") == 0)
			{
				strReplay = L"甜不甜,你也尝不到";
			}
			
			dlg->SetDlgItemTextW(IDC_STATIC3, strReplay);
			dlg->myYuYin.MFC_Speak_ASyn(strReplay);
		}

		dlg->myYuYin.m_pSREngine->SetRecoState(SPRST_ACTIVE);


	}



	return 0;
}


五、运行效果

预先设置了几个问题与答案。
注意这样一个问题:在语音朗读时候,应该关闭语音识别,否则会监听她自己说的话。
dlg->myYuYin.m_pSREngine->SetRecoState(SPRST_INACTIVE); 这一句即使为了关闭语音识别,
自己读完了她再 dlg->myYuYin.m_pSREngine->SetRecoState(SPRST_ACTIVE);一下,重新开启语音识别。

在这里插入图片描述
这是视频演示:

聊天模拟器

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
sapi.spvoice是Windows操作系统中的一个语音合成技术,它可以通过人工智能算法将文本转化为声音,并通过电脑的音频输出设备播放出来。 sapi.spvoice的使用非常简单。首先,我们需要通过COM接口获取sapi.SpVoice对象。然后,我们可以调用该对象的相关方法和属性来实现我们想要的功能。 通过sapi.spvoice,我们可以将文本合成为语音。可以使用Speak方法来实现这一功能,例如: ```python import win32com.client # 获取sapi.SpVoice对象 voice = win32com.client.Dispatch("SAPI.SpVoice") # 将文本合成为语音并播放 text = "你好,欢迎使用sapi.spvoice技术" voice.Speak(text) ``` 此外,sapi.spvoice还支持一些其他的功能。我们可以通过设置voice对象的属性来实现特定的效果,例如设置语速和音量: ```python # 设置语速和音量 voice.Rate = 1 # 语速,范围从-10到10,默认为0 voice.Volume = 100 # 音量,范围从0到100,默认为100 # 合成为语音并播放 text = "你好,欢迎使用sapi.spvoice技术" voice.Speak(text) ``` 除了上述的基本功能之外,sapi.spvoice还支持其他一些高级的功能,例如选择不同的音频输出设备、选择不同的语音合成引擎等等。具体的使用方法可以参考相关的文档或者教程。 总的来说,sapi.spvoice是Windows平台上实现文本合成语音的技术之一,通过简单的调用相关的方法和属性,我们可以实现将文本转化为声音并播放的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胸毛男

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值