一、目前掌握的关于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 10void MFC_SetRate(long RateAdjust);long MFC_GetRate();// 语音库??void MFC_SetVoice(ISpObjectToken *pToken);ISpObjectToken* MFC_GetVoice();// 暂停void MFC_Pause();void MFC_Resume();// 设置音量,范围:0到100void 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);一下,重新开启语音识别。


这是视频演示:

聊天模拟器

用SAPI做一个聊天模拟器相关推荐

  1. 来做一个聊天机器人吧[1]

    来做一个聊天机器人吧[1] 前言 准备 GUI开发 聊天模块1.0版本 语音合成1.0版本 版本1.0 前言 课程设计自己选了这个课题,因为之前就对NLP(Natural Language Proce ...

  2. 关于“做一个聊天+信息分享客户端”的设想(SNS?)

    最近有个点子:做一个聊天+信息分享客户端,聊天工具类似QQ.MSN,信息分享一个方面的功能类似博客.微博. 聊天与信息分享分别可以积累评价信息,聊天与信息分享在内容与积累的信誉方面无缝共享.聊天/信息 ...

  3. python制作聊天机器人原理_用 Python 来做一个聊天机器人吧!(一)

    在我的一个回答里,我提到了用 Python 搭建聊天机器人.从今天开始,我就带着大家从0开始搭建一个聊天机器人. (顺便说一句,我喜欢把链接像上面这样加在文字里,如果找不到文中所说的资源,可以看看周围 ...

  4. 如何用Excel做一个战斗模拟器(一)升级经验表

    如何用Excel做一个战斗模拟器(二)属性表 如何用Excel做一个战斗模拟器(三)战斗过程模拟 目录索引 引言 确定战斗公式与怪物强度 确定人物升级经验 确定人物升级时间 确定升级所需经验 引言 作 ...

  5. 如何用Excel做一个战斗模拟器(三)战斗过程模拟

    如何用Excel做一个战斗模拟器(一)升级经验表 如何用Excel做一个战斗模拟器(二)属性表 目录索引 定义战斗子过程 定位战斗双方基础属性 利用基础属性与战斗公式进行计算 战斗过程的运算与输出 判 ...

  6. 如何用Excel做一个战斗模拟器(四)装备的掉落与展示

    如何用Excel做一个战斗模拟器(一)升级经验表 如何用Excel做一个战斗模拟器(二)属性表 如何用Excel做一个战斗模拟器(三)战斗过程模拟 目录索引 定义掉落表与装备表 怪物本身掉落装备 定义 ...

  7. pygelet做一个飞行模拟器完整代码

    pyglet是一个跨平台的Python库,可以用来制作2D和3D图形和游戏.如果你想用pyglet做一个飞行模拟器,你可以这样做: 导入pyglet库 创建一个窗口 加载飞机模型和背景图片 在每一帧中 ...

  8. 如何用Excel做一个战斗模拟器(二)属性表

    如何用Excel做一个战斗模拟器(一)升级经验表 如何用Excel做一个战斗模拟器(三)战斗过程模拟 目录索引 属性表 属性表 首先确定人物的生命.攻击.防御.暴击值与闪避值属性.用公式将其设定为与等 ...

  9. 树莓派做一个聊天机器人

    首先来安装所需要的第三方库: pip3 install baidu-aip 为了播放音频,还需要安装播放器: sudo apt-get install omxplayersudo apt-get -y ...

最新文章

  1. Spring Cloud Config 配置中心
  2. 集合的势也称集合的基数(cardinal number)
  3. 需要“jquery”ScriptResourceMapping。请添加一个名为 jquery (区分大小写)的 ScriptResourceMapping。
  4. ibatis查询CHAR类型的字段
  5. git 分支推送项目
  6. response对象的使用
  7. 单片机四位数加减计算机程序,51单片机简易计算器程序 实现数字的加减乘除运算...
  8. 2014 java面试题_2014 java面试题 (答案)
  9. kotlin list转map
  10. 儿童机器人编程入门优先学习什么?
  11. 20170216.双目摄像机标定参数说明
  12. python爬取58同城的兼职信息
  13. 聊下git merge --squash
  14. 用最虔诚的心攻克英语!
  15. 微信应用签名生成工具
  16. 微信支付服务商点金计划
  17. 电磁波是如何产生的以及分类
  18. auth2 并发登录出现 nested exception is org.redisson.client.WriteRedisConnectionException
  19. 肖 清华计算机系 北大生命科学,7个清华北大,11+复旦交大,后续还有一大波浙大……他们都是同班同学!...
  20. 此错误(HTTP 500 内部服务器错误)意味着您正在访问的网站出现了服务器问题,此问题阻止了该网页的显示

热门文章

  1. 美团外卖用户差评情况分析
  2. 集合collection
  3. 全年精彩内容大盘点 | 虎年贺岁特辑
  4. 彩虹代刷网免授权+精美WAP端源码
  5. iOS 14 Beta 5 来了,修复游戏闪退问题了,还有着几个变化!
  6. 怎么判断一篇微信公众号文章阅读量是不是刷上来的?
  7. 一个清华保送生妈妈对竞赛的感受,自主招生家长都要看看!
  8. ug电子产品计算机建模,UG10网格曲面咖啡壶
  9. rstudio查询命令_R语言和RStudio的一些用法,常用命令等
  10. 6.9对一个工作簿中的所有工作表分别求和并将求和结果写入固定单元格