当前位置:文档之家› 实验二 语音交互设计TTS-基于图形用户界面

实验二 语音交互设计TTS-基于图形用户界面

COM:即组件对象模型,Component Object Model。

1、在COM构架下,人们可以开发出各种各样的功能专一的组件,组件实际上是一些小的二进制可执行程序,它们可以给应用程序、操作系统以及其他组件提供服务,然后将它们按照需要组合起来,构成复杂的应用系统(如dll)。

优点:可用新组件替换原有组件,系统升级和定制更加简便;可在多个应用系统中重复利用同一个组件;可以方便的将应用系统扩展到网络环境下;COM与语言、平台无关,程序员可充分发挥自己的才智与专长编写组件模块等。

2、使用和处理COM对象。

COM独立于语言,COM为自己提供对象管理例程。

COM中创建对象,实际是调用COM库中的API函数CoCreatInstance().调用该函数时,在注册表中查找COM服务器位置,将服务器加载到内存,并创建所请求的实例。

3、一般使用COM对象的步骤是:●初始化COM库(Initialize);●创建一个COM对象,获得相应接口;●如果对象创建成功,则调用COM对象的某个方法;●释放接口;●收回COM库(Uninitialize)二、TTS—基于图形界面基于图形用户界面创建一个TTS应用程序,通过对菜单命令的选择执行文本-语音的转换。

一、建立项目1、创建一个实现典型“Hello world”应用的windows 32平台应用程序项目。

二、设置sapi路径:与SAPI相关的文件路径必须在项目中声明。

(sapi.h和sapi.lib)1、选择“Tools”→“Options”→“Directories”选项卡;2、选择“Include Files”下拉式选单,增加“sapi.h”的文件路径;3、选择“Library Files”下拉式选单,增加“sapi.lib”的文件路径;三、创建“Speak”菜单命令1、修改自动生成的菜单项。

打开“资源管理器”→“File”菜单→增加“Speak”命令项→资源ID设置为“IDM_SPEAK”。

四、实现speak功能第1步:初始化COM第2步:创建语音对象设置声音第3步:调用speak函数第4步:设置感兴趣的事件第5步:确定事件类型第6步:响应事件1、初始化COMif( FAILED( CoInitialize(NULL) ) ){return FALSE;}2、创建语音对象设置声音一旦com运行后,下一步就是要创建语音对象。

这里需要用到CoCreatInstance().为简洁和方便起见,这个例子使用了特别的处理方式。

首先,它使用initinstance ()来初始化声音。

这是最简单的初始化过程。

第二,这个语音对象是全局性的。

第三,语音对象建立之后,对象本省和用到的内存立即被释放。

最后,如果初始化失败,应用程序应该有更强有力的检查错误机,更广泛的报告和更详细的资料。

程序清单2:ISpVoice *pVoice; //SAPI voice(初始化模块)……BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){。

// Instead of using IDC_TEST, use the identifier of menu resource of the current application.SetMenu(hWnd, LoadMenu(hInstance, MAKEINTRESOURCE(IDC_TEST))); ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);//Initialize SAPIHRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL,IID_ISpVoice, (void **)&pVoice);if( SUCCEEDED( hr ) ) {pVoice->SetInterest( SPFEI(SPEI_WORD_BOUNDARY),SPFEI(SPEI_WORD_B OUNDARY) );pVoice->SetNotifyWindowMessage( hWnd, WM_USER, 0, 0 );}elsereturn FALSE;3、调用Speak函数实现“讲话”的功能要让计算机讲话只需一句简单的调用命令,要讲话的内容用一个参数传给语音对象,常是从一个对话框或一个文件获取字符串的。

另外,字符串也可以从一个流中获取,但就要使用另外一个调用ispvoice::speakstream 。

Speak函数的调用代码是放在windows的消息处理函数wndproc ()相应的消息处理中的。

从文件菜单选择Speak命令,计算机将开始讲:"我很高兴发言。

"程序代码3:// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)。

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){。

WCHAR tempString[30];。

switch (wmId){。

case IDM_SPEAK:wcscpy( theString, L"I am glad to speak." );pVoice->Speak( theString, SPF_ASYNC, NULL);pVoice->Speak(L"I am glad to speak", SPF_ASYNC, NULL);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}4、设置事件像其它大部分windows应用程序一样,在COM组件中有很多交互动作,这些交互信息将以信息形式出现。

sapi是也一样。

信息是在TTS或SR引擎中产生的,某个特定的事件也是在那里开始和结束的.很多时候, sapi或sapi的引擎产生的事件是对应用程序有用的。

举例来说,当一个识别过程开始的时候,应用程序会得到相应的通知或消息,最终的用户也可以得到相应的通知。

(1)首先,需要接收一个来自sapi的或sapi的引擎的消息。

这个消息是程序自定义的.但是,所有的活动sapi都使用相同的消息通知应用程序;(2)得到通知后,应用程序要检查一个事件结构,这个事件结构是由SAPI完成的.利用这个结构来确定具体是发生了什么事件(见第五步骤).(3)设定感兴趣的事件。

程序可以用setinterest 来设置感兴趣的事件。

默认情况下,TTS不向程序发出任何事件通知。

也就是说,如果程序忽略了setinterest的调用,TTS应用程序是得不到任何事件通知的。

(4)设定消息。

不论以何种事件,应用程序都应该将一个消息与sapi联系起来。

程序通过调用setnotifywindowmessage来完成这个任务,本例使用WM_USER消息。

程序清单4://Initialize SAPIHRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);if( SUCCEEDED( hr ) ){pVoice->SetInterest( SPFEI(SPEI_WORD_BOUNDARY),SPFEI(SPEI_WORD_BOUN DARY) );pVoice->SetNotifyWindowMessage( hWnd, WM_USER, 0, 0 );}elsereturn FALSE;5、确定事件。

使用事件来工作需要2个步骤。

(1)首先是使用一个简单和标准的做法设置和使用Windows消息。

消息是被发送到程序的消息环中的。

在这个例子里,wndproc()接收wm_user讯息。

一旦讯息是捕获,其余事情由sapi函数来完成。

(2)第二个步骤是确定哪些消息发生了。

Sapi使用spevent和getevents方法来确定具体的事件和消息。

通过这两个函数可以获取指定的事件信息和事件类型。

在SPEVENT 的成员eeventid恰恰是setinterest所设定的值。

该spevent结构必须在首次使用时被初始化。

而且重新使用之前也要被清除。

可以使用spclearevent来完成清除工作。

程序清单5:switch (message){case WM_COMMAND:wmId = LOWORD(wParam);wmEvent = HIWORD(wParam);。

case WM_USER: //处理speak命令的窗口SPEVENT eventItem;memset( &eventItem, 0,sizeof(SPEVENT));while( pVoice->GetEvents(1, &eventItem, NULL ) == S_OK ){switch(eventItem.eEventId ){case SPEI_WORD_BOUNDARY :SPVOICESTATUS eventStatus;pVoice->GetStatus( &eventStatus, NULL );ULONG start, end;start = eventStatus.ulInputWordPos;end = eventStatus.ulInputWordLen;wcsncpy( tempString, theString + start , end );tempString[ end ] = '/0';//MessageBoxW( hWnd, tempString, L"GUIApp",MB_OK|MB_ICONWARNING );MessageBoxW( hWnd, tempString, L"SayApp",MB_OK|MB_ICONWARNING );break;default:break;}SpClearEvent( &eventItem );}break;。

case WM_DESTROY: //释放语音对象if (pVoice){pVoice->Release();pVoice = NULL;}PostQuitMessage(0);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}6、响应事件。

相关主题