接上文
現在,硬件上的准備工作做完了.
下一步,先打開Modem的電源,用SecureCRT連接串口,敲入些AT命令,看看Modem能否執行.
這里簡單說一下AT命令:
AT命令有兩種解釋一種是調制解調器命令語言,簡單來說就是一些固定格式的字符串,我們通過串口向Modem發送AT命令的字符串,Modem就會按照
命令去執行不同的操作.AT命令的百度百科請看這里,具體的命令格式和使用方法請自行百度.
我們先來試試撥號
向串口發送命令 : atdt10086;\r
不出意外的話Modem就會摘機,並發出撥號音,然后就會聽到10086的語音了.
然后是按鍵交互
比如我要按 1鍵 然后按 #號鍵則
按鍵命令 : atd,1,#;\r
逗號的作用是延時,讓多個按鍵之間有些間隔,防止對方識別不清
然后是掛機
掛機的命令是 : ath;\r
發送這個命令,Modem就執行掛機動作了.
這些基本動作都可以完成之后,下面就進入第二個問題了:
用什么技術來實現語音識別1xx86那邊所說的語音?
這里我經過一段時間的技術調查,最終決定使用微軟Windows 7 自帶的語音識別引擎
這個引擎有兩種識別模式,第一種是自由識別,這種方式每當引擎識別出任意一段文字之后便會觸發識別事件SpeechRecognized
另一種方式是關鍵詞識別,這種方式只有引擎識別出的文字符合關鍵詞,才會觸發識別事件SpeechRecognized
我們采用關鍵詞模式進行識別,根據1xx86語音播報的不同關鍵詞,來按不同的按鍵,完成功能.
這個功能在控制面板里可以看到 控制面板 -> 輕松訪問 -> 語音識別
.Net 有對應的類庫可以調用,命名空間如下:
using System.Speech.Recognition; using System.Speech.Synthesis;
引擎使用方法:
首先,創建語音識別引擎,設置音頻輸入設備
CultureInfo myCIintl = new CultureInfo("zh-CN"); foreach (RecognizerInfo config in SpeechRecognitionEngine.InstalledRecognizers())//獲取所有語音引擎 { if (config.Culture.Equals(myCIintl) && config.Id == "MS-2052-80-DESK") { Recognizer = new SpeechRecognitionEngine(config); Recognizer.SetInputToDefaultAudioDevice();//選擇默認的音頻輸入設備 break; }//選擇中文的識別引擎 } if (Recognizer != null) { InitializeSpeechRecognitionEngine(fg);//初始化語音識別引擎 } else { MessageBox.Show("創建語音識別失敗"); }
然后進行初始化,加載關鍵詞
/// <summary> /// 初始化,加載關鍵詞組 /// </summary> /// <param name="fg">關鍵詞組</param> private void InitializeSpeechRecognitionEngine(string[] fg) { Grammar customGrammar = CreateCustomGrammar(fg); //根據關鍵字數組建立語法 Recognizer.UnloadAllGrammars(); Recognizer.LoadGrammar(customGrammar); //加載語法 }
然后開始識別
/// <summary> /// 開始識別 /// </summary> public void BeginRec() { TurnSpeechRecognitionOn(); }
上述簡單介紹了識別引擎的使用過程,我將此過程封裝為一個類,方便主程序調用
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Speech; using System.Speech.Recognition; using System.Globalization; using System.Windows.Forms; using System.Speech.Synthesis; using System.Diagnostics; namespace Sp10086 { public class SRecognition { /// <summary> /// 語音識別引擎 /// </summary> public SpeechRecognitionEngine Recognizer { get; set; } //重載構造函數 public SRecognition() : this(new string[]{" "}) { } public SRecognition(string[] fg) //創建關鍵詞語列表 { CultureInfo myCIintl = new CultureInfo("zh-CN"); foreach (RecognizerInfo config in SpeechRecognitionEngine.InstalledRecognizers())//獲取所有語音引擎 { if (config.Culture.Equals(myCIintl) && config.Id == "MS-2052-80-DESK") { Recognizer = new SpeechRecognitionEngine(config); Recognizer.SetInputToDefaultAudioDevice();//選擇默認的音頻輸入設備 break; }//選擇中文的識別引擎 } if (Recognizer != null) { InitializeSpeechRecognitionEngine(fg);//初始化語音識別引擎 } else { MessageBox.Show("創建語音識別失敗"); } } /// <summary> /// 初始化,加載關鍵詞組 /// </summary> /// <param name="fg">關鍵詞組</param> private void InitializeSpeechRecognitionEngine(string[] fg) { Grammar customGrammar = CreateCustomGrammar(fg); //根據關鍵字數組建立語法 Recognizer.UnloadAllGrammars(); Recognizer.LoadGrammar(customGrammar); //加載語法 } /// <summary> /// 開始識別 /// </summary> public void BeginRec() { TurnSpeechRecognitionOn(); } /// <summary> /// 停止語音識別引擎 /// </summary> public void StopRec() { TurnSpeechRecognitionOff(); } /// <summary> /// 加載關鍵詞組 /// </summary> /// <param name="fg">關鍵詞組</param> public void ChangeKeywords(string[] fg) { InitializeSpeechRecognitionEngine(fg); System.Threading.Thread.Sleep(100); foreach(Grammar g in this.Recognizer.Grammars) { Debug.WriteLine("正在聽:" + g.Name); } } /// <summary> /// 加載關鍵詞組 /// </summary> /// <param name="fg">關鍵詞組</param> public void ChangeKeywords(string prefix, string[] fg) { GrammarBuilder grammarBuilder = new GrammarBuilder(prefix); string words = string.Empty; foreach (string s in fg) { words += "(" + prefix + s + ")"; } grammarBuilder.Append(new Choices(fg)); //根據關鍵字數組建立語法 Recognizer.UnloadAllGrammars(); Recognizer.LoadGrammar(new Grammar(grammarBuilder) { Name = words }); System.Threading.Thread.Sleep(100); foreach (Grammar g in this.Recognizer.Grammars) { Debug.WriteLine("正在聽:" + g.Name); } } /// <summary> /// 創造自定義語法 /// </summary> /// <param name="fg">關鍵詞組</param> /// <returns></returns> public virtual Grammar CreateCustomGrammar(string[] fg) { GrammarBuilder grammarBuilder = new GrammarBuilder(); grammarBuilder.Append(new Choices(fg)); string words = string.Empty; foreach (string s in fg) { words += "("+s+")"; } return new Grammar(grammarBuilder) { Name = words }; } /// <summary> /// 啟動語音識別函數 /// </summary> private void TurnSpeechRecognitionOn() { if (Recognizer != null) { Recognizer.RecognizeAsync(RecognizeMode.Multiple); //識別模式為連續識別 } else { MessageBox.Show("創建語音識別失敗"); } } /// <summary> /// 關閉語音識別函數 /// </summary> private void TurnSpeechRecognitionOff() { if (Recognizer != null) { Recognizer.RecognizeAsyncCancel(); } else { MessageBox.Show("創建語音識別失敗"); } } } }
主程序調用方法如下:
SRecognition sr = new SRecognition(); sr.Recognizer.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(recognizer_SpeechRecognized); sr.BeginRec();
識別出關鍵詞之后的處理函數:
/// <summary> /// 識別出關鍵字后的處理函數 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e) { //識別出的關鍵詞 string text = e.Result.Text; switch (text) { case "歡迎使用中國移動": //根據關鍵詞不同,按不同的按鍵 serialPort1.Write("atd,,1,#;\r"); //然后改變引擎所關注的關鍵詞,進行下一步的識別 sr.ChangeKeywords(new string[] { "查詢余額" }); break; case "查詢余額": serialPort1.Write("atd,2,#;\r"); sr.ChangeKeywords(new string[] { "xxx" }); break; //以下過程涉及業務邏輯,故省略 case "xxx": break; case "yyy": break; default: break; } }
過程如下:
撥通電話
引擎開始識別 關鍵詞 "歡迎使用中國移動"
"歡迎使用中國移動"識別出后,進行按鍵 1鍵 #號鍵 引擎換關鍵詞 "查詢服務"
"查詢服務" 識別出后,進行按鍵 2鍵 #號鍵
如此一直循環下去,都是按照1xx86的充值順序進行,一直進行到輸入充值卡密碼,進行按鍵,將充值卡密碼上送 引擎換關鍵詞 "充值成功"和"充值失敗"
根據識別出的關鍵詞 是"充值成功"還是"充值失敗",進行記錄,錄入數據庫.
最后掛機,完成.