Распознавание с нестандартного микрофона

от автора

Некоторые сталкиваются с тем что необходимо распознать речь перевести её в текст и обработать. Проблема описывалась много раз как впрочем и пути её решения так что Google в помощь, но вот я столкнулся на собственном опыте с проблемой которая потребовала нетривиального решения, а именно как заставить распознавать речь с микрофона которые не установлен «по умолчанию». Если вы тоже столкнулись с подобной проблемой то эта статья именно для вас.

Итак что мы имеем — есть два различных движка для распознавания речи в Microsoft Windows (стандартный и Microsoft Speech SDK 11) причём сразу скажу что русский язык поддерживает пока только один из них, а именно Microsoft Speech SDK 11 с установленным русским языком. Если внимательно прочитать документацию по обоим движкам, то видно что в качестве устройства можно выбрать только DefaultInputDevice, но копнув глубже, а именно открыв сборку декомпилятором Telerik JustDecompile я убедился что все классы являются лишь обёрткой над СОМ объектами, а как раз в этих СОМ объектах нужная функция есть. Естественно что как и все программисты я ленивый и работать с СОМ не хотел, поэтому совмести два решения. Итак первое что нам необходима это найти Token нужного нам микрофона для этого существует следующая функция:

private SpeechLib.SpObjectToken FindMicByName(string name)         {             if (isot != null)             {                 for (int i = 0; i < isot.Count; i++)                 {                     sot = isot.Item(i);                     string desc = sot.GetDescription(1033);                     string id = sot.Id;                     if (desc.Contains(name) != false)                     {                         break;                     }                 }                 return sot;             }             else                 return null;         } 

После того как мы получим Token необходимо вызвать приватные методы у класса «движка» распознавания для этого используется следующая функция:

public void SetMicByName(string name, ref System.Speech.Recognition.SpeechRecognitionEngine sre)         {             if (isot != null)             {                 sre.SetInputToDefaultAudioDevice();                 sot = FindMicByName(name);                 if (sot != null)                 {                     FieldInfo fi = sre.GetType().GetField("_sapiRecognizer", BindingFlags.Instance | BindingFlags.NonPublic);                     object _sapiRecognizer = fi.GetValue(sre);                     MethodInfo mi = _sapiRecognizer.GetType().GetMethod("SetInput", BindingFlags.Instance | BindingFlags.NonPublic);                     object[] parms = new object[] { sot, true };                     mi.Invoke(_sapiRecognizer, parms);                 }             }         }

В конце я приведу полный текст вспомогательного класса, который используется в моей разработке, Вы можете использовать его полностью или частично или просто вставить необходимые фрагмента кода себе. Всё это проверенно на Windows 7,8,8.1 ,NET 4.0, 4.5, но думаю что и с другими версиями будет работать также.

using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text;   namespace RMI.SmartHouse.Service {     /// <summary>     /// Позволяет осуществить выбор микрофонов.     /// </summary>     public class MicSelector : IDisposable     {         #region Приватные поля         SpeechLib.SpInProcRecoContext siprc;         SpeechLib.ISpeechObjectTokens isot;         SpeechLib.SpObjectToken sot;         #endregion                  #region Конструкторы                  /// <summary>         /// Конструктор по умолчанию.         /// </summary>         public MicSelector()          {             siprc = new SpeechLib.SpInProcRecoContext();             isot = siprc.Recognizer.GetAudioInputs(null, null);             sot = null;         }                  #endregion                  #region Публичные свойства                  /// <summary>         /// Список доступных устройств.         /// </summary>         public SpeechLib.ISpeechObjectTokens Isot         {             get             {                 return this.isot;             }             private set             {                 this.isot = value;             }         }                  #endregion                  #region Публичные методы                  /// <summary>         /// Устанавливает выбранный микрофон.         /// </summary>         /// <param name="name">Имя микрофона.         /// <param name="sre">Движок для распознавания.         public void SetMicByName(string name, ref System.Speech.Recognition.SpeechRecognitionEngine sre)         {             if (isot != null)             {                 sre.SetInputToDefaultAudioDevice();                 sot = FindMicByName(name);                 if (sot != null)                 {                     FieldInfo fi = sre.GetType().GetField("_sapiRecognizer", BindingFlags.Instance | BindingFlags.NonPublic);                     object _sapiRecognizer = fi.GetValue(sre);                     MethodInfo mi = _sapiRecognizer.GetType().GetMethod("SetInput", BindingFlags.Instance | BindingFlags.NonPublic);                     object[] parms = new object[] { sot, true };                     mi.Invoke(_sapiRecognizer, parms);                 }             }         }                  /// <summary>         /// Устанавливает выбранный микрофон.         /// </summary>         /// <param name="name">Имя микрофона.         /// <param name="sre">Движок для распознавания.                 public void SetMicByName(string name, ref Microsoft.Speech.Recognition.SpeechRecognitionEngine sre)         {             if (isot != null)             {                 sre.SetInputToDefaultAudioDevice();                 sot = FindMicByName(name);                 if (sot != null)                 {                      FieldInfo fi = sre.GetType().GetField("_sapiRecognizer", BindingFlags.Instance | BindingFlags.NonPublic);                     object _sapiRecognizer = fi.GetValue(sre);                     MethodInfo mi = _sapiRecognizer.GetType().GetMethod("SetInput", BindingFlags.Instance | BindingFlags.NonPublic);                     object[] parms = new object[] { sot, true };                     mi.Invoke(_sapiRecognizer, parms);                 }             }         }                  /// <summary>         /// Обновляет список доступных устройств.         /// </summary>         /// <returns>Список доступных устройств.</returns>         public SpeechLib.ISpeechObjectTokens UpdateDeviceList()         {             if (siprc != null)             {                 isot = siprc.Recognizer.GetAudioInputs(null, null);                 return isot;             }             else             {                 return null;             }         }                  /// <summary>         /// Освобождение ресурсов.         /// </summary>         public void Dispose()         {             if (sot != null)             {                 sot = null;             }             if (isot != null)             {                 isot = null;             }             if (siprc != null)             {                 siprc = null;             }             GC.Collect();         }                  #endregion                  #region Приватные функции         /// <summary>         /// Поиск микрофона по имени.         /// </summary>         /// <param name="name">Имя для поиска.         /// <returns>Токен микрофона.</returns>         private SpeechLib.SpObjectToken FindMicByName(string name)         {             if (isot != null)             {                 for (int i = 0; i < isot.Count; i++)                 {                     sot = isot.Item(i);                     string desc = sot.GetDescription(1033);                     string id = sot.Id;                     if (desc.Contains(name) != false)                     {                         break;                     }                 }                 return sot;             }             else                 return null;         }           #endregion     } }

ссылка на оригинал статьи http://habrahabr.ru/post/214635/