⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jyy1dlg.cpp

📁 语音识别与合成实例
💻 CPP
字号:
// jyy1Dlg.cpp : implementation file
//

#include "stdafx.h"
#include "jyy1.h"
#include "jyy1Dlg.h"
#include "common.h"
#include "grammar1.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//全局变量定义
ISpVoice* pVoice;
CComPtr<ISpVoice> pSynthVoice;
CComPtr<ISpRecognizer> pRecognizer;
CComPtr<ISpRecoContext> pRecoContext;
CComPtr<ISpRecoGrammar> pRecoGrammar;
CComPtr<ISpObjectToken> pObjectToken;
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

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

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CJyy1Dlg dialog

CJyy1Dlg::CJyy1Dlg(CWnd* pParent /*=NULL*/)
	: CDialog(CJyy1Dlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CJyy1Dlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CJyy1Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CJyy1Dlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CJyy1Dlg, CDialog)
	//{{AFX_MSG_MAP(CJyy1Dlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_CLOSE()
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_RECOEVENT,OnRecoEvent)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CJyy1Dlg message handlers

BOOL CJyy1Dlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

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

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	BOOL IsInitSpeech=InitSpeech();
	if (FALSE==IsInitSpeech)
	{
		AfxMessageBox("Fail to InitSpeech!");
	}
	if (!InitSynth())
	{
		AfxMessageBox("Fail to InitSynth!");
		return FALSE;
	}
	//返回回调函数的消息
	HRESULT hr=pRecoContext->SetNotifyWindowMessage(this->m_hWnd,WM_RECOEVENT,0,0);
	//设置识别状态
	hr=pRecognizer->SetRecoState(SPRST_ACTIVE);
	return TRUE;  // return TRUE  unless you set the focus to a control
}

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

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CJyy1Dlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		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;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CJyy1Dlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

BOOL CJyy1Dlg::InitSpeech()
{
	//初始化SAPI
	HRESULT hr=CoCreateInstance(CLSID_SpVoice,NULL,CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
	/*if(SUCCEEDED(hr))
	{
		pVoice->Speak(L"Hello!",SPF_ASYNC,NULL);
	}*/
	if (FAILED(hr))
	{
		return FALSE;
	}
	//创建识别引擎
	hr=pRecognizer.CoCreateInstance(CLSID_SpSharedRecognizer);
	if (FAILED(hr))
	{
		return FALSE;
	}
	//创建识别上下文
	hr=pRecognizer->CreateRecoContext(&pRecoContext);
	if (FAILED(hr))
	{
		return FALSE;
	}
	//创建语法规则
	hr=pRecoContext->CreateGrammar(GRAMMARID1,&pRecoGrammar);
	if (FAILED(hr))
	{
		return FALSE;
	}
	//加载语法规则.xml方式
    hr=pRecoGrammar->LoadCmdFromResource(NULL,
		MAKEINTRESOURCEW(IDR_SRGRAMMAR1),
		L"SRGRAMMAR",
		MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),SPLO_DYNAMIC);
    if (FAILED(hr))
    {
		return FALSE;
    }
	//激活语法规则状态
	pRecoGrammar->SetRuleState(NULL,NULL,SPRS_ACTIVE);
	//返回回调函数的消息
	hr=pRecoContext->SetNotifyWindowMessage(m_hWnd,WM_RECOEVENT,0,0);
	if (FAILED(hr))
    {
		return FALSE;
    }
	//设置程序需要处理的识别消息
    hr=pRecoContext->SetInterest(SPFEI(SPEI_RECOGNITION),SPFEI(SPEI_RECOGNITION));
	if (FAILED(hr))
    {
		return FALSE;
    }
	return TRUE;
}

BOOL CJyy1Dlg::InitSynth()
{
	HRESULT hr=S_OK;
	//系统中查找合适的合成引擎
	hr=SpFindBestToken(SPCAT_VOICES,L"Language=409",NULL,&pObjectToken);
	if (FAILED(hr))
	{
		return FALSE;
	}
	//创建实例
	hr=CoCreateInstance(CLSID_SpVoice,NULL,CLSCTX_ALL,IID_ISpVoice,(void**)&pSynthVoice);
	if (FAILED(hr))
	{
		return FALSE;
	}
	//设置某一声音
    pSynthVoice->SetVoice(pObjectToken); 
	//改变语音速度
	pSynthVoice->SetRate(-1);
	return TRUE;
}

void CJyy1Dlg::OnRecoEvent()
{
	CSpEvent event;
	while (S_OK==event.GetFrom(pRecoContext))
	{
		switch(event.eEventId)
		{
		case SPEI_RECOGNITION:
			ExecuteCommand(event.RecoResult());
			break;
		case SPEI_FALSE_RECOGNITION:
			AfxMessageBox("Sorry,I don't know!");
			break;
		}
	}
}

void CJyy1Dlg::ExecuteCommand(ISpRecoResult *pPhrase)
{
	HRESULT hr=pRecognizer->SetRecoState(SPRST_INACTIVE);
	SPPHRASE *pElements;
	if (SUCCEEDED(pPhrase->GetPhrase(&pElements)))
	{
		switch ( pElements->Rule.ulId )
        {
		case VID_Meet:
			pVoice->Speak(L"Hi!",SPF_ASYNC,NULL);
            AfxMessageBox("您好!");
            break;
        }
		hr=pRecognizer->SetRecoState(SPRST_ACTIVE);
        //释放所分配了的内存
        ::CoTaskMemFree(pElements);
	}
}

void CJyy1Dlg::CleanupSAPI()
{
	if (pObjectToken)
	{
		pObjectToken.Release();
	}
    if (pRecoGrammar)
    {
		pRecoGrammar.Release();
    }
	if (pRecoContext)
	{
		pRecoContext->SetNotifySink(NULL);
		pRecoContext.Release();
	}
	if (pRecognizer)
	{
		pRecognizer.Release();
	}
	if (pSynthVoice)
	{
		pSynthVoice.Release();
	}
	if (pVoice)
	{
		pVoice->Release();
	}
}

void CJyy1Dlg::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
	CleanupSAPI();
	CDialog::OnClose();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -