Using Events in Code (SAPI 5.4)
Using Events in Code
Associated With Recognition Contexts
Once the event handler is created, using that particular event is simple. No additional code is needed to initiate the event. That is, if the application receives a Recognition event from SAPI, the Recognition code is invoked automatically and immediately. For example, if the recognition event code were as follows for, notice two issues.
Private Sub RC_Recognition(ByVal StreamNumber As Long, ByVal StreamPosition As Variant, ByVal RecognitionType As SpeechLib.SpeechRecognitionType, ByVal Result As SpeechLib.ISpeechRecoResult) Form1.Label1.Caption = Result.PhraseInfo.GetText End Sub
First, a hypothetical Label1 text box on Form1 of the application would be updated with the text from the successful recognition. Second, notice each event is associated with a particular recognition context. In this case recognition context is presumed to be named RC. A possible declaration could be
Public WithEvents RC As SpSharedRecoContext
Associating each event with a recognition context simplifies handling the event. Since each application can have more than one recognition context, a particular recognition context can be active or inactive at any moment, and recognition contexts are generally used to isolate specific application areas (such as one recognition context for the menus, another for general dictation, and possible others for dialog boxes), when an event is received, the scope of the event is automatically defined. For example, in the RC_Recognition listed above, the event simply displays the results to a text box. The application does not have to test if the event related to menus, which would probably require a different set of actions.
Applications, however, can have additional processing within the event. For example, assuming there is one recognition context for all the menus, the following recognition event does have to test for which menu is intended. It uses a context free (CFG) grammar and all the rule names are defined inside that file.
Private Sub MenuBar_Recognition(ByVal StreamNumber As Long, ByVal StreamPosition As Variant, ByVal RecognitionType As SpeechLib.SpeechRecognitionType, ByVal Result As SpeechLib.ISpeechRecoResult) Set RecoResult = Result Dim rp As ISpeechPhraseInfo Set rp = RecoResult.PhraseInfo If rp.Rule.Name = "filemenu" Then Form2.Command1_Click If rp.Rule.Name = "editmenu" Then Form2.EditMenu_Click If rp.Rule.Name = "aboutapplication" Then frmAbout.Show vbModal End Sub
Both speech recognition and text-to-speech have a wide variety of events. By default, SAPI using automation has all events active except for SREAudioLevel for speech recognition and SVEAudioLevel for text-to-speech. That means all the other kinds of events will be returned by SAPI to the application. Remember, the application does not have to support any particular events; it could simply omit an event handler for it. Nevertheless, the application still receives the event and it takes a minimal amount of time to process it through the queue. For simple applications, this processing time is negligible and has little or no effect. For other applications this additional time could represent an undesirable lag. For instance, if the application were animating a face by using visemes to change the mouth position of the on screen character, speed and timing is important. For speech recognition, a game application could rely on speed as well to process a voice command. While some amount of lag time is inherent to all speech systems (speech processing is not instantaneous), removing unwanted events is one way to minimize the demands on the application.
Controlling the flow of events is done by setting event interests. Event interests is a filtering mechanism by which specific events may be sent back to the application or repressed by the engine to begin with. All, none, or selective events may be chosen to be received. Both groups of events have a similar call for setting interests: speech recognition has ISpeechRecoContext.EventInterests and text-to-speech uses SpVoice.EventInterests. Both methods sets event interest but for the appropriate set of interests.
Event interests work the same way for either technology. The SetInterests specifies only the events to be sent by the engines. Therefore the following call allows a single event to be sent, that of the successful recognition. The sample also assumes a valid RecoContext.
RecoContext.EventInterests = SRERecognition
Additional interests may be set by adding the values together. So that the next sample now allows two events be sent, a recognition and a sound start.
RecoContext.EventInterests = SRERecognition + SRESoundStart
If addition is used, the new value completely replaces the previous set of interests. For example, if the last two samples were executed in the reverse order than presented, the recognition context would only use one event afterward: the recognition. It is not recommended to use subtraction to modify interests. Instead, use logical operators.
Logical operators may also be applied to event interests. For example, an application may need to add one specific event for the moment. Instead of having to refine the entire set of interests, a potentially laborious task if many interests are currently set, use the logical And operator. For example, the following code tests if the current set of interests excludes SRERecognition (by using the logical And) and it not, adds it (by using the logical Or).
If (RC.EventInterests And SREAudioLevel) <> SREAudioLevel Then RC.EventInterests = RC.EventInterests Or SREAudioLevel End If
Setting interests is more simple than retrieving them. Symbolic equivalent may be to set interests. That means to add recognition events the Symbolic equivalent SRERecognition. However, in retrieving the current set of interests, a numeric value is returned instead. For example, by default voice event interests are set to 33,287. The value is the sum of all the individual events. An event interest of SVEWordBoundary, SVEVoiceChange , and SVEViseme would have a value of 296.