一、目前掌握的关于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);一下,重新开启语音识别。
这是视频演示:
聊天模拟器