mirror of
https://github.com/Gigaslav/HL2Overcharged.git
synced 2026-01-07 14:10:02 +03:00
388 lines
15 KiB
C#
388 lines
15 KiB
C#
//=============================================================================
|
|
//
|
|
// Copyright (c) Microsoft Corporation All Rights Reserved.
|
|
//
|
|
//=============================================================================
|
|
|
|
namespace SAPI51Samples
|
|
{
|
|
using System;
|
|
using System.Collections;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Data;
|
|
using System.Windows.Forms;
|
|
using System.Diagnostics;
|
|
using SpeechLib;
|
|
|
|
/// <summary>
|
|
/// SpeechListBox is a speech enabled listbox control. It inherits
|
|
/// from the standard System.Windows.Forms.ListBox, and thus exposes
|
|
/// all the standard properties, methods and events. A few new methods
|
|
/// are added to provide speech specific functionalities.
|
|
/// </summary>
|
|
public class SpeechListBox : System.Windows.Forms.ListBox
|
|
{
|
|
private const int grammarId = 10;
|
|
private bool speechEnabled = false;
|
|
private bool speechInitialized = false;
|
|
private String PreCommandString = "Select";
|
|
private SpeechLib.SpSharedRecoContext objRecoContext;
|
|
private SpeechLib.ISpeechRecoGrammar grammar;
|
|
private SpeechLib.ISpeechGrammarRule ruleTopLevel;
|
|
private SpeechLib.ISpeechGrammarRule ruleListItems;
|
|
|
|
/// <summary>
|
|
/// AddItem is used to add a newitem to the list item collection.
|
|
/// It will automatically update the grammar. It's equivalent to
|
|
/// calling ListBox.Items.Add() followed by BuildGrammar().
|
|
/// </summary>
|
|
/// <param name="newItem">
|
|
/// The new item to be added to the list.
|
|
/// </param>
|
|
/// <returns>
|
|
/// The index of the newly added item.
|
|
/// </returns>
|
|
public int AddItem(object newItem)
|
|
{
|
|
// Since we can't add the same word to the same transition in
|
|
// the grammar, we don't allow same string to be added
|
|
// multiple times. So do nothing if Item is already in the list.
|
|
// Some level of error message may be helpful. The sample chooses
|
|
// to silently ignore to keep code simple.
|
|
|
|
// The leading and trailing spaces are not needed, trim it before
|
|
// inserting. SAPI will return error in AddWordTransition if two
|
|
// phrases differ only in spaces. A program needs to handle this
|
|
// error if random phrase is added to a rule.
|
|
// Note: In this sample, we only trim leading and trailing spaces.
|
|
// Internal spaces will need to be handled as well.
|
|
|
|
string strItem;
|
|
int index = -1;
|
|
|
|
strItem = newItem.ToString().Trim();
|
|
|
|
// only add it if trimmed phrase is not empty
|
|
if( strItem.Length > 0 )
|
|
{
|
|
index = this.FindString(strItem);
|
|
|
|
if( index < 0 )
|
|
{
|
|
// if it doesn't exist yet, add it to the list
|
|
index = this.Items.Add(strItem);
|
|
|
|
// if speech is enabled, we need to update grammar with the change
|
|
if( speechEnabled ) RebuildGrammar();
|
|
}
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
/// <summary>
|
|
/// RemoveItem will remove the item with the given index and then
|
|
/// call BuildGrammar() to update grammar. It's equivalent to
|
|
/// calling ListBox.Items.RemoveAt() followed by BuildGrammar().
|
|
/// </summary>
|
|
/// <param name="index">
|
|
/// Index of the item to be removed from the list.
|
|
/// </param>
|
|
public void RemoveItem(int index)
|
|
{
|
|
this.Items.RemoveAt(index);
|
|
if( speechEnabled ) RebuildGrammar();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Property SpeechEnabled is read/write-able. When it's set to
|
|
/// true, speech recognition will be started. When it's set to
|
|
/// false, speech recognition will be stopped.
|
|
/// </summary>
|
|
public bool SpeechEnabled
|
|
{
|
|
get
|
|
{
|
|
return speechEnabled;
|
|
}
|
|
set
|
|
{
|
|
if( speechEnabled != value )
|
|
{
|
|
speechEnabled = value ;
|
|
if(this.DesignMode) return;
|
|
|
|
if (speechEnabled)
|
|
{
|
|
EnableSpeech();
|
|
}
|
|
else
|
|
{
|
|
DisableSpeech();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// RecoContext_Hypothesis is the event handler function for
|
|
/// SpSharedRecoContext object's Hypothesis event.
|
|
/// </summary>
|
|
/// <param name="StreamNumber"></param>
|
|
/// <param name="StreamPosition"></param>
|
|
/// <param name="Result"></param>
|
|
/// <remarks>
|
|
/// See EnableSpeech() for how to hook up this function with the
|
|
/// event.
|
|
/// </remarks>
|
|
public void RecoContext_Hypothesis(int StreamNumber,
|
|
object StreamPosition,
|
|
ISpeechRecoResult Result)
|
|
{
|
|
Debug.WriteLine("Hypothesis: " +
|
|
Result.PhraseInfo.GetText(0, -1, true) + ", " +
|
|
StreamNumber + ", " + StreamPosition);
|
|
}
|
|
|
|
/// <summary>
|
|
/// RecoContext_Hypothesis is the event handler function for
|
|
/// SpSharedRecoContext object's Recognition event.
|
|
/// </summary>
|
|
/// <param name="StreamNumber"></param>
|
|
/// <param name="StreamPosition"></param>
|
|
/// <param name="RecognitionType"></param>
|
|
/// <param name="Result"></param>
|
|
/// <remarks>
|
|
/// See EnableSpeech() for how to hook up this function with the
|
|
/// event.
|
|
/// </remarks>
|
|
public void RecoContext_Recognition(int StreamNumber,
|
|
object StreamPosition,
|
|
SpeechRecognitionType RecognitionType,
|
|
ISpeechRecoResult Result)
|
|
{
|
|
Debug.WriteLine("Recognition: " +
|
|
Result.PhraseInfo.GetText(0, -1, true) + ", " +
|
|
StreamNumber + ", " + StreamPosition);
|
|
|
|
int index;
|
|
ISpeechPhraseProperty oItem;
|
|
|
|
// oItem will be the property of the second part in the recognized
|
|
// phase. For example, if the top level rule matchs
|
|
// "select Seattle". Then the ListItemsRule matches "Seattle" part.
|
|
// The following code will get the property of the "Seattle"
|
|
// phrase, which is set when the word "Seattle" is added to the
|
|
// ruleListItems in RebuildGrammar.
|
|
oItem = Result.PhraseInfo.Properties.Item(0).Children.Item(0);
|
|
index = oItem.Id;
|
|
|
|
if ((System.Decimal)Result.PhraseInfo.GrammarId == grammarId)
|
|
{
|
|
// Check to see if the item at the same position in the list
|
|
// still has the same text.
|
|
// This is to prevent the rare case that the user keeps
|
|
// talking while the list is being added or removed. By the
|
|
// time this event is fired and handled, the list box may have
|
|
// already changed.
|
|
if( oItem.Name.CompareTo(this.Items[index].ToString())==0 )
|
|
{
|
|
this.SelectedIndex = index;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// This function will create the main SpSharedRecoContext object
|
|
/// and other required objects like Grammar and rules.
|
|
/// In this sample, we are building grammar dynamically since
|
|
/// listbox content can change from time to time.
|
|
/// If your grammar is static, you can write your grammar file
|
|
/// and ask SAPI to load it during run time. This can reduce the
|
|
/// complexity of your code.
|
|
/// </summary>
|
|
private void InitializeSpeech()
|
|
{
|
|
Debug.WriteLine("Initializing SAPI objects...");
|
|
|
|
try
|
|
{
|
|
// First of all, let's create the main reco context object.
|
|
// In this sample, we are using shared reco context. Inproc reco
|
|
// context is also available. Please see the document to decide
|
|
// which is best for your application.
|
|
objRecoContext = new SpeechLib.SpSharedRecoContext();
|
|
|
|
// Then, let's set up the event handler. We only care about
|
|
// Hypothesis and Recognition events in this sample.
|
|
objRecoContext.Hypothesis += new
|
|
_ISpeechRecoContextEvents_HypothesisEventHandler(
|
|
RecoContext_Hypothesis);
|
|
|
|
objRecoContext.Recognition += new
|
|
_ISpeechRecoContextEvents_RecognitionEventHandler(
|
|
RecoContext_Recognition);
|
|
|
|
// Now let's build the grammar.
|
|
// The top level rule consists of two parts: "select <items>".
|
|
// So we first add a word transition for the "select" part, then
|
|
// a rule transition for the "<items>" part, which is dynamically
|
|
// built as items are added or removed from the listbox.
|
|
grammar = objRecoContext.CreateGrammar(grammarId);
|
|
ruleTopLevel = grammar.Rules.Add("TopLevelRule",
|
|
SpeechRuleAttributes.SRATopLevel | SpeechRuleAttributes.SRADynamic, 1);
|
|
ruleListItems = grammar.Rules.Add("ListItemsRule",
|
|
SpeechRuleAttributes.SRADynamic, 2);
|
|
|
|
SpeechLib.ISpeechGrammarRuleState stateAfterSelect;
|
|
stateAfterSelect = ruleTopLevel.AddState();
|
|
|
|
object PropValue = "";
|
|
ruleTopLevel.InitialState.AddWordTransition(stateAfterSelect,
|
|
PreCommandString, " ", SpeechGrammarWordType.SGLexical,
|
|
"", 0, ref PropValue, 1.0F );
|
|
|
|
PropValue = "";
|
|
stateAfterSelect.AddRuleTransition(null, ruleListItems, "",
|
|
1, ref PropValue, 0F);
|
|
|
|
// Now add existing list items to the ruleListItems
|
|
RebuildGrammar();
|
|
|
|
// Now we can activate the top level rule. In this sample, only
|
|
// the top level rule needs to activated. The ListItemsRule is
|
|
// referenced by the top level rule.
|
|
grammar.CmdSetRuleState("TopLevelRule", SpeechRuleState.SGDSActive);
|
|
speechInitialized = true;
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
System.Windows.Forms.MessageBox.Show(
|
|
"Exception caught when initializing SAPI."
|
|
+ " This application may not run correctly.\r\n\r\n"
|
|
+ e.ToString(),
|
|
"Error");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// EnableSpeech will initialize all speech objects on first time,
|
|
/// then rebuild grammar and start speech recognition.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// true if speech is enabled and grammar updated.
|
|
/// false otherwise, which happens if we are in design mode.
|
|
/// </returns>
|
|
/// <remarks>
|
|
/// This is a private function.
|
|
/// </remarks>
|
|
private bool EnableSpeech()
|
|
{
|
|
Debug.Assert(speechEnabled, "speechEnabled must be true in EnableSpeech");
|
|
|
|
if (this.DesignMode) return false;
|
|
|
|
if (speechInitialized == false)
|
|
{
|
|
InitializeSpeech();
|
|
}
|
|
else
|
|
{
|
|
RebuildGrammar();
|
|
}
|
|
|
|
objRecoContext.State = SpeechRecoContextState.SRCS_Enabled;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// RebuildGrammar() will update grammar object with current list
|
|
/// items. It is called automatically by AddItem and RemoveItem.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// true if grammar is updated.
|
|
/// false if grammar is not updated, which can happen if speech is
|
|
/// not enabled or if it's in design mode.
|
|
/// </returns>
|
|
/// <remarks>
|
|
/// RebuildGrammar should be called every time after the list item
|
|
/// has changed. AddItem and RemoveItem methods are provided as a
|
|
/// way to update list item and the grammar object automatically.
|
|
/// Don't forget to call RebuildGrammar if the list is changed
|
|
/// through ListBox.Items collection. Otherwise speech engine will
|
|
/// continue to recognize old list items.
|
|
/// </remarks>
|
|
public bool RebuildGrammar()
|
|
{
|
|
if( !speechEnabled || this.DesignMode )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// In this funtion, we are only rebuilding the ruleListItems, as
|
|
// this is the only part that's really changing dynamically in
|
|
// this sample. However, you still have to call
|
|
// Grammar.Rules.Commit to commit the grammar.
|
|
int i, count;
|
|
String word;
|
|
object propValue = "";
|
|
|
|
try
|
|
{
|
|
ruleListItems.Clear();
|
|
count = this.Items.Count;
|
|
|
|
for(i=0; i<count; i++)
|
|
{
|
|
word = this.Items[i].ToString();
|
|
|
|
// Note: if the same word is added more than once to the same
|
|
// rule state, SAPI will return error. In this sample, we
|
|
// don't allow identical items in the list box so no need for
|
|
// the checking, otherwise special checking for identical words
|
|
// would have to be done here.
|
|
ruleListItems.InitialState.AddWordTransition(null, word,
|
|
" ", SpeechGrammarWordType.SGLexical, word, i, ref propValue, 1F);
|
|
}
|
|
|
|
grammar.Rules.Commit();
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
System.Windows.Forms.MessageBox.Show(
|
|
"Exception caught when rebuilding dynamic listbox rule.\r\n\r\n"
|
|
+ e.ToString(),
|
|
"Error");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// This is a private function that stops speech recognition.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private bool DisableSpeech()
|
|
{
|
|
if (this.DesignMode) return false;
|
|
|
|
Debug.Assert(speechInitialized,
|
|
"speech must be initialized in DisableSpeech");
|
|
|
|
if( speechInitialized )
|
|
{
|
|
// Putting the recognition context to disabled state will
|
|
// stop speech recognition. Changing the state to enabled
|
|
// will start recognition again.
|
|
objRecoContext.State = SpeechRecoContextState.SRCS_Disabled;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
}
|
|
}
|
|
|