代码改变世界

【转】SAPI中的IspeechRecoContext(接口)

2013-11-22 08:59  于为源  阅读(1636)  评论(0编辑  收藏  举报

IspeechRecoContext自动化接口定义一个识别上下文。

什么是一个识别上下文?

一个识别上下文就是应用程序和SAPI共同作用来实现语音识别的最主要方法。它就是用来允许应用程序来开始、停止识别,接收识别结果、其他事件的一个对象。它也能控制哪些单词或者短语可以被提供给用户来发音。一个应用程序可能有很多的识别上下文在同一时间同时开放,每一个控制应用程序的不同部分。一个特殊的识别上下文控制可被使用的单词的集合,并且被关联给应用程序的特殊部分。在一般情况下,这样的单词的集合就是限制哪些语音识别尝试被限定,并且被轮询去符合单词。不被保留在集合或者上下文中的单词,将不会被用于语音识别的尝试。通过设置识别上下文,应用程序限制或扩展单词的范围,这些单词是满足应用程序特殊方向使用的需要。这种语音识别的精细度通过删除当时不需要的单词,来提高语音识别的质量。相应地,这种精细度也允许应用程序来增加必要的单词。

例如:一个应用程序可能只有一个识别上下文,所有的单词都在词典中,所有的单词在所有的时候都可用。如果这个应用程序只是单纯的听写,唯一上下文模式也可以被很好地使用,用户可以在任意时间说任何单词给应用程序,并且可能被成功使用。然而,如果应用程序有一个退出的新要求的时候,当用户说“Close”,唯一上下文模式将会关闭。假设在听写期间,单词“Close”被说出时,应用程序突然停止运行并且关闭,用户将会很失望。

很明显,这里的单词“Close”有两种用法(上下文),第一种是语音的一部分(如"please close the door," "that was too close for comfort," "we'll close in on the criminal"),第二种上下文是一种专有的命令。这里必须有一种方法去区别两者的不同。一个识别上下文允许应用程序去做这样的区分。

应用程序可以有多于一个的识别上下文。实际上,它可以有尽可能多的有意义的上下文。例如,一个识别上下文可以被关联给菜单栏,另一个可以关联给听写屏幕,还有另一个关联给对话框,甚至只是Yes/No/Cancel这样的临时对话框。程序员需要去决定识别上下文的范围,一个应用程序的菜单系统可能有多个识别上下文,可能每一个菜单项对应一个上下文。这种精细度授予应用程序鲁棒地集中资源。例如,一个小菜单可能只有12与之相关的项目,不仅如此,它还有12个非常特殊的单词。因此,不必要去使用整个听写集合(大约有65000到1000000个词汇),实际上只有12个单词被用到。一个多于需要的词汇库不仅占有更多的进程时间,而且导致更多的搭错的单词。同样的原因,在上面“Close”例子中,一个听写模式将不能把“Close”与其他单词区分。两个识别上下文可以用来去区分这种不同。

如何使用识别上下文?

产生一个识别上下文,需要使用两个步骤处理法。一个识别上下文必须先被声明,然后才能产生。

识别上下文的类型:

识别上下文有两种类型:共享的或者独占的(Inproc)。一个共享的上下文允许资源可以被其他的识别上下文或者应用程序使用。在一台机器上使用共享上下文的所有应用程序共同使用一个音频输入、语音识别(SR)引擎、语法。当用户发音时,SR引擎将会识别,SAPI根据哪个语法的结果最符合要求,决定发送哪个上下文给识别结果。在一般情况下,大多数应用程序使用共享上下文。

独占上下文限制可用的资源给一个上下文或者应用程序,这就是一个SR引擎或者麦克风被一个独占识别上下文使用。将不会被其他的应用程序使用。在使用独占上下文状况下,要求最高的性能标准、响应时间或者严格的识别质量。独占上下文对于其他硬件平台的嵌入系统是非常重要的,同样也被使用在无麦克风识别(如从文件中识别)。然而,独占上下文也应该被谨慎地使用,原因就是它排除其他应用程序使用语音识别资源。

默认值:

识别上下文按照计算机系统的默认状态产生自己的默认值。这些默认值可以在控制面板中的语音属性中进行设置。尽管应用程序可能因为特殊的原因而重写这些默认值,但是应用程序不应该直接设置或者修改这些默认值。

这些默认值包括:

Recognizer:确定语音识别(SR)引擎;

EventInterests:确定语音识别(SR)引擎产生哪个事件;

RetainedAudio:为语音坚持实际的音频;

RetainedAudioFormat:确定要保留的音频格式;

Voice:对文本进行发音;

语法:

唯一被明确产生的资源是语法使用CreateGrammar。语法定义了一系列的单词为识别上下文。语法也可以是两种类型:听写式和命令控制式(C&C)。听写式语法通常不限制单词列表,目的是包括语言中尽可能多的单词。听写式模式允许用户说任一单词或者短语,并且被用在传统的侦测,来听写一封信或报纸。例如,下面的代码片段声明了一个听写语法。

Set myGrammar = RC.CreateGrammar

myGrammar.DictationSetState SGDSActive

一个命令控制语法是一个有限的单词列表(限制发音人在一个小集合中)。在这种方式下,用户可以说一个命令,通常是一个单一的单词,有更多的机会来被失败。小集合单词不接受不在特殊列表中的单词,一个语法对能响应语音菜单很有用的。菜单语法可以很小,拥有精确的单词或短语命令,如"New," "Exit," or "Open."等等,下面一段代码片段声明了一个命令和控制语法。

Set myGrammar = RC.CreateGrammar

myGrammar.CmdLoadFromFile "sol.xml", SLODynamic

myGrammar.CmdSetRuleIdState 101, SGDSActive

由于单词列表的内容是有限的,一个显式的列表将会被使用。在这个例子里,命令文件sol.xml被使用。另外,上面的代码中激活了一条规则,这个规则有一个Id值为101。

状态:

尽管个体语法规则可能随着条件的改变而处于激活或者非激活状态。在识别上下文中所有的语法规则都随着State属性的改变,而变成激活或者非激活状态。例如,一个窗体不在当前的焦点是,语法可能被关闭。当这个窗体重新得到焦点是,语法将会恢复。另外,识别上下文可以被暂时停止,并且可以被重新启动。使用Pause方法可以暂时停止识别,以便和语法保持同步。在暂停之后,可以使用Resume方法来恢复识别过程。在暂停的时候,引擎将会继续接受声音输入和语言加工。提供一个暂停对于系统并不过分,在默认的情况下,一次暂停的时间不应该超过30秒。

ISpeechRecoContext对象总是关联一个单一的语音识别引擎(也被称为识别器)。然而,一个单一的识别器可能有很多的识别上下文。

事件

作为一个与识别上下文相关的结果,语音识别(SR)引擎返回信息给使用事件机理的应用程序。一个事件是用户或者应用程序感兴趣的特殊发生。事件的例子包括通知应用程序一个成功的识别或者指出音频流达到的指定位置。不管怎样,应用程序与加工进程或者忽略进程是无关的。

另外,事件可能被过滤,允许引擎去返回一些或者所有事件。或者避免对于应用程序无关的事件在第一位产生。过滤是使用EventInterests控制的。

ISpeechRecoContext自动化接口包括以下元素:

属性有:

AllowVoiceFormatMathingOnNextSet属性:确定识别上下文是否可以改变输出声音的音频格式去适应输入音频流的音频格式。

AllowVoiceFormatMathingOnNextSet只有在一个声音通过识别上下文产生时才会被使用。如果这个属性被设置为True,声音的输出格式将会被设置成和关联与语音识别(SR)引擎的音频输入格式一样的格式。这种转化只有在下一次设置SpVoice.Voice时才会发生。如果这个音频对象已经被绑定给一个有特殊格式的音频流,即使在被设置为True的情况下,声音格式将不会随着语音识别(SR)引擎的输入格式而进行改变。如果是False,这种改变将不会进行。

使用相同的声音格式给输入、输出资源对于不支持全双工音频(例如:输入格式必须适应输出格式)的声卡是有用的。如果输入格式低于输出格式质量,输出格式质量将会降低到输入的质量的水平。

AllowVoiceFormatMathingOnNextSet在默认情况下被设置为True。

AudioInputInterferenceStatus属性:返回关于识别上下文的音频输入的干扰的信息。这个信息通常被IspeechRecoContext的Interference时间返回。

CmdMaxAlternates属性:指定为命令和控制语法生成的替换的最大数量。

在默认状态下,最大的替换数量为0,所以一个应用程序必须在试图接收或者依靠为命令和控制的替换前调用这个方法。不是所有的不是所有的语音识别(SR)引擎都支持命令和控制语法或者专有语法的替换。如果特殊的引擎不支持替换,这个方法将会表示已经成功替换,但是替换的数量将返回0值。

EventInterests属性:指定被SpeechRecoContext对象接收的事件的类型。

一个感兴趣事件就是给每一个识别上下文加上过滤机制。通过设置EventInterests,识别上下文允许或者拒绝语音识别(SR)引擎事件到达应用程序。所有、无一、被选择类型的事件都可以被过滤。在默认状态下,语音识别(SR)引擎除了SREAudioLevel事件外,允许所有的事件。

注意:

为EventInterests设置事件常量的定义位于SpeechRecoEvents列表中,每一个事件类型通过它本身的值来表现。传递给EventInterests的值就是应用程序要求的每一个事件的总和。例如:SRESoundStart+SRERecognition将会作为一个值被传递,可供选择的两种事件将会被像一个单一的值18一样被传递。SRESoundStart(值为2)加上SRERecognition(值为16)。相反地,如果应用程序取回当前的事件设置,值为1064,它表示有三个事件是激活状态,SREPhraseStart(值为8),SREHypothesis(值为32),SREInterference(值为1024)加起来就是1064.

Recognizer属性:表示和识别上下文关联的识别器。

注意:

尽管在通常情况下,定义一个对象需要准确的类名。ISpeechRecognizer通常以SpSharedRecognizer或者SpInprocRecognizer来实现。由于在使用前不知道哪种类型将会被使用,所以定义这个对象为Object是安全的。

RequestedUIType属性:指出从引擎要求的最后的用户界面(UI)的UI类型(UIType)。

在语音识别(SR)引擎发送一个RequestUI事件之后,UIType持续直到下个RequestUI事件。使用这种方式,应用程序可以检查最后要求的UI类型。如果没有UI被要求,UIType字符串将为空。

RetainedAudio属性:得到或者设置识别上下文的音频保留状态。

在默认状态下,一个识别上下文不保留音频,最初将被设置为SRAONone。如果企图访问一个不存在的音频会导致一个SPERR_NO_AUDIO_DATA的错误,对ISpeechRecoResult.Audio和ISpeechRecoResult.SpeekAudiao的调用就会导致这个错误。这个错误在设置一个SpAudioFormat实例时也会发生。

如果为了保留音频,需要把这个属性设置为SRAORetainAudio

RetainedAudioFormat属性:得到或者被识别上下文保留的音频的格式。

在默认状态下,被保留的音频格式将会和输入的音频格式一样。输入的音频格式通过调用Recognizer.GetFormat(使用SFTInput作为参数)来进行回收。音频格式可以通过传递Nothing作为参数来设置或者重设(在上一次改变以后)为引擎正在使用的相同的格式。

注意:

识别上下文的RetainedAudio需要不被设置为SRAORetainAudio才能使RetainedAudioFormat才能被成功调用。RetainedAudioFormat表示音频应该被保留的格式,而不管这个音频当前是否被保留。

State属性:得到或者设置识别上下文的活动状态。

被关联给识别上下文的整个语法可以是禁用的或可用的。否则,语法的个别规则状态是不受影响的。这些条件允许应用程序在高级别控制语法的状态。例如,一个窗体失去当前的焦点,如果识别不需要,与这个窗体关联的识别上下文就会被禁用。同样的,当窗体得到焦点,所有相关的识别上下文就可以变成可用的。

Voice属性:指定与识别上下文相关联的SpVoice对象。

注意:

ISpeechRecoContext.Voice可以被临时改变,并且限制上下文。改变Voice可以使用控制面板中的语音选项。

VoicePurgeEvent属性:得到或者设置RecoContext事件。这个事件可以停止RecoContext声音,并且清除声音队列。

应用程序可以为了一个声音输入而使用一个RecoContext对象的声音属性来提示用户。当用户开始发音时,设置VoicePurgeEvent给SRESoundStart事件将会引起RecoContext的声音停止发音。

方法有:

Bookmark方法:在当前识别流中设置一个书签。

一个书签在音频流位置和对应用程序有重要意义的事件之间建立联系。语音识别(SR)引擎在发音到识别之间有一个潜伏期,这个潜伏状态可能被这些事件所引起:一个长的发音周期(引擎必须在加工之前得到所有的短语),或者引擎必须完成已经在排队的等候事件。然而,在潜伏时期,用户或者应用程序可以继续操作(如鼠标移动或者发音)。因此,一个应用程序的条件在识别复原和识别初始化时将会有所不同。书签允许应用程序标记或者记录应用程序的特殊识别企图。

Bookmark是一个对于引擎查询音频位置的方便替换。当引擎产生一个书签时,将会有一个Bookmark事件被返回。

SpeechRecoContext.Bookmark(

Options As SpeechBookmarkOptions,

StreamPos As Variant,

BookmarkId As Variant

)

注意:

例如:一个想显示识别进展的应用程序,可以在每一个书签被收到的同时,使用ISpeechRecoContext.Bookmark并且更新UI。

CreateGrammar方法:在ISpeechRecoGrammar的基础上产生一个对象。

在语音识别发生之前,一个语音识别(SR)引擎要求两件事:语法产生和语法激活。一个识别器可能有多于一个与之关联的语法,尽管他们被限制为两种类型:听写式语法、与上下文无关式语法(CFG)。CFG被用做命令和控制。识别器可能有多于一个的同一类型的活动类型的语法在同一时间开放。在这种情况下,识别将在完全符合的语法下进行。如果有多于一个的语法符合,那个最早开放的语法将会被识别接受。

一个语法在使用之前必须是激活的,调用ISpeechRecoGrammar.DictationSetState去激活或者释放一个听写语法。ISpeechRecoGrammar.CmdSetRulesStates被用来激活或者释放一个命令和控制规则(其同样控制相关联的语法)。通过控制语法的状态,不同的语法被用在不同的时间。

下面的代码用来说明如何产生和激活一个听写式语法:

Public WithEvents RC As SpSharedRecoContext

Public myGrammar As ISpeechRecoGrammar

 

Set RC = New SpSharedRecoContext

Set myGrammar = RC.CreateGrammar(0)

myGrammar.DictationLoad

myGrammar.DictationSetState SGDSActive

 

下面的代码则用来说明如何产生和激活一个CFG语法:

Public WithEvents RC As SpSharedRecoContext

Public myGrammar As ISpeechRecoGrammar

 

Set RC = New SpSharedRecoContext

Set myGrammar = RC.CreateGrammar

 

myGrammar.CmdLoadFromFile "sol.xml", SLODynamic

myGrammar.CmdSetRuleIdState 0, SGDSActive

Pause方法:暂停引擎对象,以便和语音识别(SR)引擎同步。Pause停止SR引擎在同步点,以便改变语法和规则状态。任何一个Recogition事件、Bookmark事件或者明确调用Pause都会产生一个同步点。在同步语法和规则状态后,如果调用Resume,引擎将会继续识别。

在应用程序已经改变状态或语法后,它应该调用ISpeechRecoContext.Resume。每一个Resume调用对应于一个Pause调用。SAPI将会自动把缓冲音频数据提供给SR引擎。确保没有实时数据丢失,用户的体验过程不被打断。一旦调用Resume,SAPI将会重启SR引擎。

在暂停过程中,SAPI收集和保存音频,放入一个音频缓冲中。SAPI音频缓冲有一个静态限制,以防止SAPI应用程序或SR引擎消耗大量的系统资源。如果SR引擎暂停时间过长,并且音频缓冲被填充,这时候缓冲就会溢出(SPER_AUDIO_BUFFER_OVERFLOW),这将会导致打断正在使用SAPI的其他应用程序。缓冲被设置为每秒平均量的30倍或者被设置为30秒。因此,在缓冲溢出的点之间的被收集的音频数据(或者当音频流重新开始时)都将会被彻底丢弃。使用Pause只能是在很短的时间,并且一旦语法和规则状态改变,应立即调用Resume。

注意:

当SR引擎在运行时,语法和规则状态的改变都会被要求。然而,这种改变可能不会发生直到引擎停止或同步时。由于一个Recognition事件是一个普通的同步点。在很多情况下,没有必要去调用Pause。但是如果语法或者状态改变需要立即实现,调用Pause,做出改变,然后调用Resume。

SAPI5的SR引擎同步每过60秒自动关闭,用来避免响亮或者持续背景噪声造成的干扰。

Resume方法:从暂停状态中释放SR引擎,重启识别进程。

SetAdaptationData方法:传递一串适应数据给SR引擎。

一个应用程序通过训练SR引擎接受新单词或者词组来提高对口述的不常用单词或者词组的识别准确率。

一个应用程序通过使用SetAdptationData方法可以产生或者获得典型文本,并且发送结果给引擎。

注意:

应用程序使用适应数据应该把数据分成小块(1KB或者更小),并且单独地提交这些块。首先,使用ISpeechRecoContex.EventInterests方法可以指定适应事件中感兴趣的内容。Adapation事件中的兴趣默认是打开状态。然后,使用SetAdaptation方法发送一个小数据块到SR引擎,并且等待ISpeechRecoContext.Adaptation事件,这个事件指出适应数据已经被加工。发送所有连续的数据块都使用这种方法。最后,使用EventInterests方法来关闭Adaptation事件。由于这个事件仅在显式调用SetAdaptationData之后被返回,所以这个事件的兴趣不需要移除,除非有大量的词组被添加或者加工的时间不可接受。Adaptation事件表示引擎已经加工适应性字符串,并且准备去接受另一个SetAdaptation调用。