TTS开发步骤基于图形界面.docx
- 文档编号:4687234
- 上传时间:2022-12-07
- 格式:DOCX
- 页数:17
- 大小:22.66KB
TTS开发步骤基于图形界面.docx
《TTS开发步骤基于图形界面.docx》由会员分享,可在线阅读,更多相关《TTS开发步骤基于图形界面.docx(17页珍藏版)》请在冰豆网上搜索。
TTS开发步骤基于图形界面
事件驱动的文本语音转换(TTS)实例
介绍一个基本的文字转语音的例子,应用程序使用图形界面(非控制台应用程序)
建立项目
首先,创建一个新的windows32平台应用程序项目,在向导中,选择一个典型的“Helloworld!
”应用。
由此产生的项目代码比命令行版本的长,且大多数新的复杂代码与sapi关系不大,但是是实现图形界面所必须的代码。
设置sapi的路径
与SAPI相关的文件路径必须在项目中声明。
以下是设置“sapi.h”路径的步骤:
1,在菜单上,选择工具“Tools”,然后单击选项“Options”。
2,单击“Directories”选项卡。
3,选择“IncludeFiles”下拉式选单
4,单击最后一行闲置在路径清单,并输入“sapi.h”的文件路径:
“C:
/ProgramFiles/MicrosoftSpeechSDK5.1/Include”
5,选择“LibraryFiles”下拉式选单,并输入“sapi.lib”的文件路径:
“C:
/ProgramFiles/MicrosoftSpeechSDK5.1/Lib/i386”。
最后单击确定。
创建“Speak”菜单命令
为了使应用程序响应我们发出“Speak”命令,并且发出声音,需要对自动生成的菜单项做一些修改。
读者可以通过VC6.0的资源管理器,在“File”菜单下面,增加一个“Speak”命令项,并且将该命令项的资源ID设置为“IDM_SPEAK”。
后文再讲述如何处理这个命令事件的代码。
现在先来编译和运行这个应用程序,确保以上的设置准确无误。
程序除了在屏幕上面显示“Helloworld”之外,其它什么事情也没做,但是它确实可以运行起来了。
使用这个实例
第1步:
初始化com
第2步:
设置声音
第3步:
讲!
第4步:
设置感兴趣的事件
第5步:
确定事件类型
第6步:
响应事件
第1步:
初始化com
用一个winmain中的程序段说明。
唯一的限制是在使用任何sapi的特定代码前com必须是初始化完成了,并且在运行sapi过程中,COM一直都是活动的。
既然sapi是用initinstance来实例化的,COM的初始化就应该在initinstance之前被初始化,并在消息环之后被撤销。
程序清单1:
粗体字代表着这个例子的新代码
if(FAILED(CoInitialize(NULL)))
{
returnFALSE;
}
//Performapplicationinitialization:
if(!
InitInstance(hInstance,nCmdShow))
{
returnFALSE;
}
hAccelTable=LoadAccelerators(hInstance,(LPCTSTR)IDC_GUIAPP);
//Mainmessageloop:
while(GetMessage(&msg,NULL,0,0))
{
if(!
TranslateAccelerator(msg.hwnd,hAccelTable,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
CoUninitialize();
第2步:
设置声音
一旦com运行后,下一步就是要创建语音对象。
这里需要用到cocreateinstance()。
正如上一篇中的命令例子中说,sapi使用很多智能的默认配置。
所以只要进行很少的初始化,你即时可以使用语音对象。
这些默认配置放在在语音属性,控制面板,一个可选的声音模式(如果你的系统有一个以上的),和语言(英文,日文等)。
有些则默认是显而易见的,其他的就没这么明显(如讲话速率,基音周期等)。
不过,你可以以编程的方式或通过控制面板来改变所有的默认配置。
为求简洁和方便起见,这个例子使用了特别的处理方式。
首先,它使用initinstance()来初始化的声音。
这是最简单的初始化过程。
在其他一些应用中,特别是使用语音识别(SR)实例中,程序可能有专门的初始化模块,这样可以使SAPI相关的代码与普通的程序代码独立开来。
第二,这个语音对象是全局性的。
根据你的应用程序的设计和要求,你可能不需要一个全局的语音对象。
第三,对下面的代码来说,语音对象建立之后,对象本省和用到的内存立即被释放。
显然,如果这个对象有其它用途的话,它是不能被释放的。
这过渡性的代码,只是为了做一个简单的说明。
最后,如果初始化失败,应用程序应该有更强有力的检查错误机制,更广泛的报告和更详细的资料。
程序清单2:
ISpVoice*pVoice; //SAPIvoice
BOOLInitInstance(HINSTANCEhInstance,intnCmdShow)
{
HWNDhWnd;
hInst=hInstance;//Storeinstancehandleinourglobalvariable
hWnd=CreateWindow(szWindowClass,szTitle,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
if(!
hWnd)
{
returnFALSE;
}
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
//InitializeSAPI
HRESULThr=CoCreateInstance(CLSID_SpVoice,NULL,CLSCTX_ALL,IID_ISpVoice,(void**)&pVoice);
if(SUCCEEDED(hr))
{
pVoice->Release();
pVoice=NULL;
}
else
returnFALSE;
returnTRUE;
}
第3步:
讲!
要讲话的内容用一个参数传给语音对象。
这些内容可以根据程序的具体应用来改变。
如前所述,常是从一个对话框或一个文件获取字符串的。
另外,字符串也可以从一个流中获取,但就要使用另外一个调用ispvoice:
:
speakstream。
这个例子使用一个简单的,代码化的句子。
Speak函数可以使用类似于下面的文本
Speak(L”Iamgladtospeak.”,spf_async,NULL);
这个调用代码是放在windows的消息处理函数wndproc()相应的消息处理中的。
选择从文件菜单,选择Speak命令,计算机将开始讲:
"我很高兴发言。
"
程序代码3:
ISpVoice*pVoice; //SAPIvoice
BOOLInitInstance(HINSTANCEhInstance,intnCmdShow)
{
HWNDhWnd;
hInst=hInstance;//Storeinstancehandleinourglobalvariable
hWnd=CreateWindow(szWindowClass,szTitle,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
if(!
hWnd)
{
returnFALSE;
}
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
//InitializeSAPI
HRESULThr=CoCreateInstance(CLSID_SpVoice,NULL,CLSCTX_ALL,IID_ISpVoice,(void**)&pVoice);
if(SUCCEEDED(hr))
{
pVoice->Release();
pVoice=NULL;
}
else
returnFALSE;
returnTRUE;
}
第4步:
设置事件
在COM组件中有很多交互动作,这些交互信息将以信息形式出现。
sapi是也一样。
信息是在TTS或SR引擎中产生的,某个特定的事件也是在那里开始和结束的.很多时候,sapi或sapi的引擎产生的事件是对应用程序有用的。
举例来说,当一个识别过程开始的时候,应用程序会得到相应的通知或消息,最终的用户也可以得到相应的通知。
同样,应用或许会有兴趣知道什么时候完成了所有的处理,处理完成后,也许要通知用户,甚至关闭引擎或应用本身时。
应用程序处理这些消息时要进行两个步骤的操作。
首先,它需要接收一个来自sapi的或sapi的引擎的消息。
这个消息是程序自定义的.但是,所有的活动sapi都使用相同的消息通知应用程序。
要确定确切的正在发生的活动,更多的资料是由sapi的提供的。
一个完整的清单,请参见speventenum。
第二个步骤。
得到通知后,应用程序要检查一个事件结构,这个事件结构是由SAPI完成的.利用这个结构来确定具体是发生了什么事件(见第五步骤).
设定感兴趣的事件:
程序可以用setinterest来设置感兴趣的事件。
默认情况下,TTS不向程序发出任何事件通知,而语音识别只发出(spei_recognition)消息。
也就是说,如果程序忽略了setinterest的调用,TTS应用程序是得不到任何事件通知的,而SR程序只能得到识别完成的通知和消息。
在任何时候都可以改变感兴趣的事件。
设定消息
不论以何种事件,应用程序都应该将一个消息与sapi联系起来。
程序通过调用setnotifywindowmessage来完成这个任务。
有三类消息可以使用,但至少少用其中一种。
第四类是为多线程应用的,在这里没有用到。
这四种消息可以参见ispnotifysource节的介绍。
实际使用的消息名字和值由程序决定,本例子使用了WM_USER消息。
程序清单4:
//InitializeSAPI
HRESULThr=CoCreateInstance(CLSID_SpVoice,NULL,CLSCTX_ALL,IID_ISpVoice,(void**)&pVoice);
if(SUCCEEDED(hr))
{
pVoice->SetInterest(SPFEI(SPEI_WORD_BOUNDARY),SPFEI(SPEI_WORD_BOUNDARY));
pVoice->SetNotifyWindowMessage(hWnd,WM_USER,0,0);
}
else
returnFALSE;
第5步:
确定事件
如前所述,使用事件来工作需要2个步骤。
首先是使用一个简单和标准的做法社设置和使用Windows消息。
消息是被发送到程序的消息环中的。
在这个例子里,wndproc()接收wm_user讯息。
一旦讯息是捕获,其余事情靠sapi函数来完成。
第二个步骤是,以确定哪些消息发生了。
Sapi使用spevent和getevents方法来确定具体的事件和消息。
通过这两个函数,你可以获取指定的事件信息和事件类型。
在SPEVENT的成员eeventid恰恰是setinterest所设定的值。
该spevent结构必须在首次使用时被初始化。
而且重新使用之前也要被清除。
可以使用spclearevent来完成清除工作。
有可能事件和消息发生的速度比应用处理速度要快。
这是一个常见的情况。
getevents可以一次性取出一个以上事件。
这程序对这些这些事件进行批处理,一般专业应用程序是需要这样做的。
另一种方式来处理这种情况,是用一个while循环。
一个一个的检索出每一事件。
请看下例。
程序清单5:
caseWM_USER:
SPEVENTeventItem;
memset(&eventItem,0,sizeof(SPEVENT));
while(pVoice->GetEvents(1,&eventItem,NULL)==S_OK)
{
switch(eventItem.eEventId)
{
caseSPEI_WORD_BOUNDARY:
break;
default:
break;
}
SpClearEvent(eventItem);
第6步:
响应事件
一旦事件和消息是确定后,编程变得更加标准了。
在这个例子中,应用程序使用spei_word_boundary消息来取定每一个单词。
可以用getstatus函数和spvoicestatus结构。
来获取更详细的信息。
一个独立的单词,可以用事件发生时的第一个字母和最后一个字母的位置来确定。
在这个例子中,使用MessageBoxW来显示所讲的单词。
在说话过程中,屏幕是实时更新的,并显示实际发言的文字。
这个特点是由spf_async标志控制的。
如果在Speak函数中使用NULL参数,而不是SPF_ASYNC参数,那样就要等整句话说完之后,才显示消息框。
pVoice->Speak(theString,SPF_ASYNC,NULL);
程序代码6:
caseSPEI_WORD_BOUNDARY:
SPVOICESTATUSeventStatus;
pVoice->GetStatus(&eventStatus,NULL);
ULONGstart,end;
start=eventStatus.ulInputWordPos;
end=eventStatus.ulInputWordLen;
wcsncpy(tempString,theString+start,end);
tempString[end]='/0';
MessageBoxW(hWnd,tempString,L"GUIApp",MB_OK|MB_ICONWARNING);
break;
总结:
最后,总结一下这个例子的主要知识点:
1,初始化COM:
CoInitialize和CoUninitialize
2,建立语音对象实例:
CoCreateInstance
3,讲话:
Speck
4,设置感兴趣的事件:
SetInterest
设定SAPI返回的消息:
setnotifywindowmessage
5,消息来时,确定事件类型:
GetEvents
清除事件结构:
SpClearEvent
6,相应事件时,用GetStatus确定当前SAPI的状态
最后完整的实例代码:
//GUIApp.cpp:
Definestheentrypointfortheapplication.
#include"stdafx.h"
#include #include"string.h" #include"resource.h" #include"sphelper.h" #defineMAX_LOADSTRING100 //GlobalVariables: HINSTANCEhInst; //currentinstance TCHARszTitle[MAX_LOADSTRING]=_T("SpeakHelloworldApp"); //Thetitlebartext TCHARszWindowClass[MAX_LOADSTRING]=_T("SpeakWinClass"); //Thetitlebartext //ForSAPI WCHARtheString[30]; ISpVoice*pVoice; //SAPIvoice //Forwarddeclarationsoffunctionsincludedinthiscodemodule: ATOM MyRegisterClass(HINSTANCEhInstance); BOOL InitInstance(HINSTANCE,int); LRESULTCALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); LRESULTCALLBACK About(HWND,UINT,WPARAM,LPARAM); intAPIENTRYWinMain(HINSTANCEhInstance, HINSTANCEhPrevInstance, LPSTR lpCmdLine, int nCmdShow) { //TODO: Placecodehere. MSGmsg; // HACCELhAccelTable; //Initializeglobalstrings //LoadString(hInstance,IDS_APP_TITLE,szTitle,MAX_LOADSTRING); //LoadString(hInstance,IDC_GUIAPP,szWindowClass,MAX_LOADSTRING); MyRegisterClass(hInstance); if(FAILED(CoInitialize(NULL))) { returnFALSE; } //Performapplicationinitialization: if(! InitInstance(hInstance,nCmdShow)) { returnFALSE; } //hAccelTable=LoadAccelerators(hInstance,(LPCTSTR)IDC_GUIAPP); //Mainmessageloop: while(GetMessage(&msg,NULL,0,0)) { //if(! TranslateAccelerator(msg.hwnd,hAccelTable,&msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } CoUninitialize(); returnmsg.wParam; } // FUNCTION: MyRegisterClass() // PURPOSE: Registersthewindowclass. // COMMENTS: // Thisfunctionanditsusageisonlynecessaryifyouwantthiscode // tobecompatiblewithWin32systemspriortothe'RegisterClassEx' // functionthatwasaddedtoWindows95.Itisimportanttocallthisfunction // sothattheapplicationwillget'wellformed'smalliconsassociated // withit. // ATOMMyRegisterClass(HINSTANCEhInstance) { WNDCLASSEXwcex; wcex.cbSize=sizeof(WNDCLASSEX); wcex.style =CS_HREDRAW|CS_VREDRAW; wcex.lpfnWndProc =(WNDPROC)WndProc; wcex.cbClsExtra =0; wcex.cbWndExtra =0; wcex.hInstance =hInstance; wcex.hIcon =NULL;//LoadIcon(hInstance,(LPCTSTR)IDI_GUIAPP); wcex.hCursor =NULL;//LoadCursor(NULL,IDC_ARROW); wcex.hbrBackground =(HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName =NULL;//MAKEINTRESOURCE(IDC_TEST);//(LPCSTR)IDC_GUIAPP; wcex.lpszClassName =szWindowClass; wcex.hIconSm =NULL;//LoadIcon(wcex.hInstance,(LPCTSTR)IDI_SMALL); returnRegisterClassEx
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- TTS 开发 步骤 基于 图形界面