语音编程之Speech SDK概述(3)

来源:互联网 发布:突厥 唐太宗 知乎 编辑:程序博客网 时间:2024/05/29 15:22
5.管理COM对象的生命期

当对象被创建时,系统将分配必需的内存资源。当一个对象不再需要时,应该删除它。系统将收回它所占有的内存,以用于其他目的。对于C++对象,应直接使用new delete 操作符来控制对象的生命期。COM不允许直接创建或删除对象。其原因是同一对象可能被多个应用程序所使用。如果其中的一个应用程序要删除该对象,其他的应用程序就可能失败。实际上,COM采用引用计数系统来控制对象的生命期。

对象的引用计数就是其中的接口被请求的次数。接口每被请求一次,其引用计数都将增加。当不再需要接口时,应用程序将释放该接口,并减少其引用计数。只要引用计数大于0,对象将保留在内存中。当引用计数变为0时,对象将释放自己。我们不必关心对象的引用计数,只需要正确地获取和释放对象的接口,对象将具有适当的生命期。

合理地处理引用计数对COM编程来说是非常重要的。处理不当将导致内存泄漏。COM编程人员最常见的错误是不释放接口。当出现这样的错误时,引用计数将永远不能变为0,对象将不确定地保留在内存中。

只要获得一个新的接口指针,引用计数就必须调用IUnknown::AddRef 来增加。但是,应用程序通常不需要调用该方法。如果通过调用一个对象创建方法或IUnknown::QueryInterface来获得接口指针,对象将自动地增加引用计数。如果用其他的方法来创建接口指针,比如拷贝已有的指针,就必须明确地调用IUnknown::AddRef。否则,当释放原来的接口指针时,你得到的对象可能被破坏,即使你还需要使用该指针的拷贝。

不论明确地或对象自动地增加了引用计数,都必须释放接口指针。当不再需要接口指针时,调用IUnknown::Release来减少引用计数。一种常用的方法是,将所有的接口指针初始化为NULL,并在释放接口后将它们重新设为NULL。这样可以在清除代码中测试所有的接口指针。那些不为NULL的接口指针就是仍然活动的,需要在退出应用程序之前释放它们。

6.用C来操作COM对象

虽然C++是最常用的COM编程语言,有些时候也需要使用C语言来访问COM对象。这样做更加直截了当,但也要用到更加复杂的语法。

所有的方法都需要一个额外的参数,放在参数表的最前面。这个参数必须设为接口指针。而且,必须明确地引用对象的vtable

每个COM对象都有一个包含指向对象所暴露的方法的指针的列表。接口指针指向vtable 的相应位置,该位置包含了指向你要调用的特定方法的指针。使用C++时,不必关心vtable,因为它在C++中是不可见的。当然,如果需要使用C来调用COM方法,就必须包括一个明确引用vtable的间接的额外层。

有些组件在它们的头文件中定义了一些宏,它们能很好地解决如何正确地调用COM

7.用ATL来处理COM接口

如果使用活动模板库(Active Template LibraryATL)来处理Microsoft Speech,为了兼容ATL,必须首先重新声明接口。这将允许你合理地使用CComQIPtr类来获取指向接口的指针。

如果没有为ATL重新声明接口,则会得到下面的错误信息:

C:/Program Files/Microsoft Visual Studio/VC98/ATL/INCLUDE/atlbase.h(566) :

  error C2787: 'ISpVoice' : no GUID has been associated with this object

11.1.2  SAPI接口

SAPI提供应用程序和语音引擎之间的高层接口,它实现并隐藏了控制和管理不同语音引擎的实时操作的底层技术细节。SAPI的结构如图11-1所示。

最基本的语音引擎包括Text-To-SpeechTTS)和语音识别器。 TTS 通过合成声音来朗读文本字符串和文本文件。语音识别器将人类的语音转换成可阅读的字符串和文件。

1Text-To-Speech API

应用程序通过ISpVoice 组件对象接口(Component Object Model Interface)来控制Text-To-Speech (TTS)。一旦应用程序创建了IspVoice对象,调用接口IspVoice的方法ISpVoice::Speak,就能产生朗读指定的文字的声音。IspVoice接口还提供了其他一系列的方法来改变声音和其合成特征,比如控制语速的ISpVoice::SetRate,控制输出音量的ISpVoice::SetVolume和改变当前语音的ISpVoice::SetVoice

在输入用于朗读的文字中还可插入一系列的特殊SAPI控制符,用来控制输出声音的实时合成特性,如语音、语调、重音、语速和音量等。合成标志文件sapi.xsd用来说明声音的合成特性。sapi.xsd是一种标准XML格式文件,它与特定的引擎或当前正在使用的语音无关,是一种简单而功能强大的定制TTS语音的方法。

IspVoice::Speak方法既能同步地(在语音播放完之后才返回)也能异步地(语音开始播放就返回,语音播放在后台处理)操作语音。 指定SPF_ASYNC 作为播放方式时,语音异步播放。这时可调用ISpVoice::GetStatus方法来获取实时状态信息,如播放状态、当前播放的文字位置等。同时,既可以打断当前的播放而立即播放新的文字(需指定SPF_PURGEBEFORESPEAK参数),也可以在播放完当前文字之后再自动播放新的文字。

除了IspVoice接口以外, SAPI还提供了许多有用的COM接口来实现高级的TTS应用程序。

1)事件(Events

SAPI通过使用标准的回调机制(窗口消息、回调函数或Win32事件)来与应用程序传送事件。对于TTS,事件主要用来同步语音输出。应用程序能同步处理语音输出和实时动作,比如词语分界、音位或嘴形动画分界及应用程序定制的分界等。应用程序可通过调用IspNotifySourceIspNotifySinkIspNotifyTranslatorIspEventSinkIspEventSourceISpNotifyCallbackcan 来初始化和处理这些实时事件。

2)词典(Lexicons

通过调用IspContainerLexiconIspLexiconIspPhoneConverter接口提供的方法,应用程序能为语音合成引擎设置定制的词汇发音。

3)资源(Resources

下面的COM接口用于处理SAPI语音数据(比如声音文件和发音词典):

IspDataKeyIspRegDataKeyIspObjectTokenInitIspObjectTokenCategoryIspObjectTokenIenumSpObjectTokensIspObjectWithTokenIspResourceManagerIspTask

4)声音(Audio

SAPI还提供了定制声音输出到特定目标(如电话和客户硬件)的接口,包括IspAudioISpMMSysAudioIspStreamIspStreamFormatIspStreamFormatConverter