/VoiceRecognition/CommandRecognizerMode.cs

https://github.com/kring/Voodoo-Voice · C# · 274 lines · 228 code · 36 blank · 10 comment · 31 complexity · 231e740b1c2922504f3d314a75560a04 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using SpeechLib;
  5. namespace FuzzLab.VoiceRecognition
  6. {
  7. public class CommandRecognizerMode
  8. {
  9. public delegate void ActiveStateChangedHandler();
  10. public event ActiveStateChangedHandler ActiveStateChanged;
  11. public delegate void CommandRecognitionHandler(CommandHandler handler);
  12. public event CommandRecognitionHandler CommandExecuting;
  13. public event CommandRecognitionHandler CommandExecuted;
  14. public delegate void CommandNotRecognizedHandler();
  15. public event CommandNotRecognizedHandler CommandNotRecognized;
  16. public CommandRecognizerMode(string name, ISpeechRecoGrammar grammar, int firstRuleId, int lastRuleId)
  17. {
  18. m_name = name;
  19. m_grammar = grammar;
  20. m_firstRuleId = firstRuleId;
  21. m_nextRuleId = firstRuleId;
  22. m_lastRuleId = lastRuleId;
  23. }
  24. public string Name
  25. {
  26. get { return m_name; }
  27. }
  28. public int FirstRuleId
  29. {
  30. get { return m_firstRuleId; }
  31. }
  32. public int LastRuleId
  33. {
  34. get { return m_lastRuleId; }
  35. }
  36. public bool IsActive
  37. {
  38. get { return m_isActive; }
  39. set
  40. {
  41. // Set activation of all rules in this mode
  42. SpeechRuleState newState = value ? SpeechRuleState.SGDSActive : SpeechRuleState.SGDSInactive;
  43. foreach (int id in m_handlers.Keys)
  44. {
  45. m_grammar.CmdSetRuleIdState(id, newState);
  46. }
  47. if (m_isActive != value)
  48. {
  49. m_isActive = value;
  50. RaiseActiveStateChanged();
  51. }
  52. }
  53. }
  54. public delegate void CommandHandler(Dictionary<string, string> arguments);
  55. public void AddCommand(string commandPhrase, CommandRecognizerMode.CommandHandler handler)
  56. {
  57. if (m_nextRuleId > m_lastRuleId)
  58. {
  59. throw new Exception("Maximum number of rules exceeded for Command Recognizer Mode '" + Name + "'.");
  60. }
  61. List<CommandPart> parts = GetParts(commandPhrase);
  62. int ruleId = m_nextRuleId;
  63. ++m_nextRuleId;
  64. m_handlers[ruleId] = handler;
  65. // Create a new rule in the grammar
  66. ISpeechGrammarRule rule = m_grammar.Rules.Add("",
  67. SpeechRuleAttributes.SRATopLevel,
  68. ruleId);
  69. // Add a state for each part of the phrase and connect them together with
  70. // appropriate transitions
  71. ISpeechGrammarRuleState from = rule.InitialState;
  72. for (int i = 0; i < parts.Count; ++i)
  73. {
  74. CommandPart part = parts[i];
  75. ISpeechGrammarRuleState state = null;
  76. if (i != parts.Count - 1)
  77. {
  78. state = rule.AddState();
  79. }
  80. object propertyValue = 0;
  81. if (part.isWordFromList)
  82. {
  83. // Add a transition through a list rule
  84. ISpeechGrammarRule listRule = m_grammar.Rules.FindRule(part.phrase);
  85. if (listRule == null)
  86. {
  87. listRule = m_grammar.Rules.Add(part.phrase, 0, 0);
  88. propertyValue = "placeholder";
  89. listRule.InitialState.AddWordTransition(null, "placeholder", " ", SpeechGrammarWordType.SGLexical, part.phrase, 0, ref propertyValue, 1);
  90. propertyValue = 0;
  91. }
  92. from.AddRuleTransition(state, listRule, "", 0, ref propertyValue, 1);
  93. }
  94. else
  95. {
  96. // Add a simple rule transition
  97. from.AddWordTransition(state, part.phrase, " ", SpeechGrammarWordType.SGLexical, "", 0, ref propertyValue, 1);
  98. }
  99. from = state;
  100. }
  101. }
  102. internal void OnCommandRecognized(ISpeechRecoResult result)
  103. {
  104. int id = result.PhraseInfo.Rule.Id;
  105. if (m_handlers.ContainsKey(id))
  106. {
  107. CommandHandler handler = m_handlers[id];
  108. if (handler != null)
  109. {
  110. // Pull any parameters from properties
  111. Dictionary<string, string> parameters = new Dictionary<string, string>();
  112. foreach (ISpeechPhraseProperty property in result.PhraseInfo.Properties)
  113. {
  114. if (property.Children != null)
  115. {
  116. foreach (ISpeechPhraseProperty childProperty in property.Children)
  117. {
  118. if (childProperty.Name.Length > 0 &&
  119. childProperty.Value != null)
  120. {
  121. parameters[childProperty.Name] = childProperty.Value.ToString();
  122. }
  123. }
  124. }
  125. }
  126. RaiseCommandExecuting(handler);
  127. handler(parameters);
  128. RaiseCommandExecuted(handler);
  129. }
  130. }
  131. else
  132. {
  133. throw new ArgumentOutOfRangeException("Command Recognizer Mode does not contain the recognized command.");
  134. }
  135. }
  136. internal void OnCommandNotRecognized(ISpeechRecoResult result)
  137. {
  138. RaiseCommandNotRecognized();
  139. }
  140. protected void RaiseActiveStateChanged()
  141. {
  142. ActiveStateChangedHandler temp = ActiveStateChanged;
  143. if (temp != null)
  144. {
  145. temp();
  146. }
  147. }
  148. protected void RaiseCommandExecuting(CommandHandler handler)
  149. {
  150. CommandRecognitionHandler temp = CommandExecuting;
  151. if (temp != null)
  152. {
  153. temp(handler);
  154. }
  155. }
  156. protected void RaiseCommandExecuted(CommandHandler handler)
  157. {
  158. CommandRecognitionHandler temp = CommandExecuted;
  159. if (temp != null)
  160. {
  161. temp(handler);
  162. }
  163. }
  164. protected void RaiseCommandNotRecognized()
  165. {
  166. CommandNotRecognizedHandler temp = CommandNotRecognized;
  167. if (temp != null)
  168. {
  169. temp();
  170. }
  171. }
  172. private struct CommandPart
  173. {
  174. public bool isWordFromList;
  175. public string phrase;
  176. }
  177. private List<CommandPart> GetParts(string phrase)
  178. {
  179. List<CommandPart> parts = new List<CommandPart>();
  180. int nextListPart = phrase.IndexOf('[');
  181. while (nextListPart >= 0)
  182. {
  183. if (nextListPart > 0)
  184. {
  185. // Add the phrase up to the beginning of the list part
  186. CommandPart phrasePart;
  187. phrasePart.isWordFromList = false;
  188. phrasePart.phrase = phrase.Substring(0, nextListPart).Trim();
  189. parts.Add(phrasePart);
  190. // Trim off the phrase part, leaving the list part starting with '['
  191. phrase = phrase.Substring(nextListPart);
  192. }
  193. if (phrase.Length == 1)
  194. {
  195. // Phrase ends with a '[', which makes no sense, so we're done
  196. phrase = "";
  197. }
  198. else
  199. {
  200. int endOfListPart = phrase.IndexOf(']');
  201. if (endOfListPart < 0)
  202. {
  203. endOfListPart = phrase.Length;
  204. }
  205. CommandPart listPart;
  206. listPart.isWordFromList = true;
  207. listPart.phrase = phrase.Substring(1, endOfListPart - 1);
  208. parts.Add(listPart);
  209. if (endOfListPart >= phrase.Length - 1)
  210. {
  211. phrase = "";
  212. nextListPart = -1;
  213. }
  214. else
  215. {
  216. phrase = phrase.Substring(endOfListPart + 1);
  217. nextListPart = phrase.IndexOf('[');
  218. }
  219. }
  220. }
  221. if (phrase.Length > 0)
  222. {
  223. CommandPart part;
  224. part.isWordFromList = false;
  225. part.phrase = phrase;
  226. parts.Add(part);
  227. }
  228. return parts;
  229. }
  230. private string m_name;
  231. private bool m_isActive;
  232. private ISpeechRecoGrammar m_grammar;
  233. private int m_firstRuleId;
  234. private int m_nextRuleId;
  235. private int m_lastRuleId;
  236. private Dictionary<int, CommandHandler> m_handlers = new Dictionary<int, CommandHandler>();
  237. }
  238. }