聪明的方式来处理语音命令的代码操作的命令 [英] Smart Way to Handle Voice Commands in Code to Action a Command

查看:147
本文介绍了聪明的方式来处理语音命令的代码操作的命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

而不是使用开关/箱或IF布尔检查,可以得到很长,非常乏味的,我不知道是否可以寻求处理和处理命令一个更好的办法。



EG:

 如果(settings.getName ==命令)
{
说话(I在这);
}

如果(获取新闻频道==命令)
{
MyRSSFeed RSSNewsFeed =新MyRSSFeed();
RSSNewsFeed.GetFeed();
}



如果命令去......这是我的switch语句的一个片段

 开关(命令)
{
#地区< - 获取时间命令 - > ;

案时请:
案什么时间:
案是什么时候了它:
GetCurrentTime();
中断;

#endregion< - 获取时间命令 - >

#地区< - 获取日期命令 - >

案什么日期:
案是几号:
案请告诉我今天日期:
案是什么日子今天:
GetCurrentDate();
中断;

#endregion< - 获取日期命令 - >


#地区< - 媒体播放器命令 - >

案玩竹林七贤:

Data.MusicPlayer.Play(@\Bamboo林播放List.wpl);

中断;

案下歌:

Data.MusicPlayer.Next();

中断;

案上一首歌曲:

Data.MusicPlayer.Previous();

中断;

案停止音乐:

Data.MusicPlayer.Stop();

中断;

案暂停音乐:

Data.MusicPlayer.Pause();

中断;

案恢复音乐:

Data.MusicPlayer.Resume();

中断;


案静音音乐:

Data.MusicPlayer.Mute();

中断;

案音量:

Data.MusicPlayer.VolumeUp();

中断;

案降低音量:

Data.MusicPlayer.VolumeDown();

中断;

#endregion< - 媒体播放器命令 - >

#地区< - 语音识别控制命令 - >

案停止听:
Audio.Listen.NewCommandRecognitionEngine.RecognizeAsyncCancel();
Audio.Voice.Speak(OK);
Audio.Listen.Initialise(主);
中断;

#endregion< - 语音识别控制命令 - >

#地区< - 应用程序命令 - >

案安静:
Audio.Voice.Stop();
中断;

案下载:
Audio.Voice.Speak(打开下载窗口。);
main.dlInterface.ShowBitsJobs();
中断;

的情况下的设置:
Audio.Voice.Speak(打开设置窗口);
main.settings.Show();
中断;

案关闭:
如果(main.dlInterface.Visable ==真)
{
main.dlInterface.Hide();
Audio.Voice.Speak(关闭下载窗口。);
}
如果(main.settings.Visible ==真)
{
main.settings.Hide();
Audio.Voice.Speak(关闭设置窗口。);
}
中断;

案闪开:
如果(main.WindowState == System.Windows.Forms.FormWindowState.Normal)
{
main.WindowState = System.Windows.Forms.FormWindowState.Minimized;
Audio.Voice.Speak(我的道歉);
}
中断;

案你在哪里:
如果(main.WindowState == System.Windows.Forms.FormWindowState.Minimized)
{
main.WindowState =系统.Windows.Forms.FormWindowState.Normal;
Audio.Voice.Speak(在这里);
}
中断;


默认:
//什么都不做这里...
中断;
}



我有一个包含命令的SQL数据库。我把命令装入它,因为我所需要的。它有一个命令名称科拉姆和值科拉姆。我可以更改这些增加的变化,或根据需要删除列。



目前,一旦命令被认可,我用if语句组合和一个开关/外壳捕捉到赶上识别的命令。



我曾经想过放弃莫名其妙DLL的到一个文件夹,并在一些应用程序负载如何扫描即可。如果我添加一个命令然后以某种方式在DLL中使用值字段的行动命令。



我意识到这是一个相当复杂的情况,但我觉得一个更好的解决方案。发现使这一过程变得更加简单。



编辑:我已经看过这个早已:的 http://social.msdn.microsoft.com/Forums/en-US/4f962dc0-aec2 -4191-9fe2-e1dfeb1da5dd /语音命令API



请询问您是否需要更多的信息。



Paqogomez已经回答了这个问题。请看下文中我工作的例子:

 使用系统; 
使用System.Linq的;使用MyApp.AppCommands
;
使用的System.Reflection;
使用System.Collections.Generic;

命名空间MyApp的
{
类节目
{
静态无效的主要(字串[] args)
{
MethodInfo的myMethod的;

VAR方法=新的命令();

myMethod的= CommandFactory.GetCommandMethods(时间请);
myMethod.Invoke(方法,NULL);

myMethod的= CommandFactory.GetCommandMethods(降低音量);
myMethod.Invoke(方法,NULL);

myMethod的= CommandFactory.GetCommandMethods(增加音量);
myMethod.Invoke(方法,NULL);

到Console.ReadLine();
}
}

公共静态类的CommandFactory
{
私有静态字典<字符串,MethodInfo的> commandMethods =新词典<字符串,MethodInfo的>();

公共静态的MethodInfo GetCommandMethods(字符串命令)
{
的MethodInfo MethodInfo的;

变种myCommandMethods =新的命令();

如果(commandMethods.Count == 0)
{
VAR =方法名typeof运算(命令).GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);

变种speechAttributeMethods = methodNames.Where(Y =方式> y.GetCustomAttributes()OfType&所述; CommandAttribute方式>()任何());

的foreach(在speechAttributeMethods VAR speechAttributeMethod)
{
的foreach(在speechAttributeMethod.GetCustomAttributes var属性(真))
{
commandMethods.Add(( (CommandAttribute)属性).CommandValue,speechAttributeMethod);
}
}
MethodInfo的= commandMethods [命令]
}
,否则
{
MethodInfo的= commandMethods [命令]
}

返回MethodInfo的;
}
}
}

命名空间MyApp.AppCommands
{
公共类命令
{
[命令(时间请)]
[命令(什么时间)]
[命令(时间是个什么)]
公共无效GETTIME()
{
Console.WriteLine(DateTime.Now.ToLocalTime());
}

[命令(降低音量)]
公共无效VolumeDown()
{
Console.WriteLine(降低音量1) ;
}

[命令(增加音量)]
公共无效VolumeUp()
{
Console.WriteLine(增加音量1) ;
}
}

[System.AttributeUsage(System.AttributeTargets.Method,的AllowMultiple = TRUE)]
公共类CommandAttribute:System.Attribute
{
公共字符串CommandValue {搞定;组; }

公共CommandAttribute(字符串textValue)
{
this.CommandValue = textValue;
}
}
}



美丽的工作Paqogomez谢谢你分享! !这是快,非常优雅。



在我的情况,我需要调用的代码是:



 私有静态无效CommandRecognized(对象发件人,SpeechRecognizedEventArgs E)
{
MethodInfo的myMethod的;

VAR方法=新的命令();

myMethod的= CommandFactory.GetCommandMethods(e.Result.Text);
myMethod.Invoke(方法,NULL);
}



这是语音识别引擎的事件处理程序:

  CommandRecognitionEngine.SpeechRecognized + =新的EventHandler< SpeechRecognizedEventArgs>(CommandRecognized); 


解决方案

您正在寻找的策略模式定义的这里



这将允许您处理多个if语句变得非常容易。



一个工厂模式也可能会适合你。一个工厂可以使用反射来确定哪些命令来创建。



您也可以只是你的所有命令转储到字典中。



编辑:



由于代码示例的最后一位一厂是你所需要的。我已经把下面一起之一。



工厂只是反映在 MySpeechMethods 所有方法,寻找那些与 SpeechAttributes 并发送回的MethodInfo 来调用。如果你需要从方法的返回值,你可以设置所有的方法,以返还相同种类(如字符串)或可考虑仿制药,但我会留给你。 :)

 使用系统; 
使用System.Collections.Generic;
使用System.Linq的;
使用的System.Reflection;使用MyApp.SpeechMethods
;

命名空间MyApp的
{
类节目
{
静态无效的主要(字串[] args)
{
VAR方法=新MySpeechMethods();
MethodInfo的myMethod的;
myMethod的= SpeechFactory.GetSpeechMethod(时间请);
myMethod.Invoke(方法,NULL);
myMethod的= SpeechFactory.GetSpeechMethod(降低音量);
myMethod.Invoke(方法,NULL);
myMethod的= SpeechFactory.GetSpeechMethod(增加音量);
myMethod.Invoke(方法,NULL);
}
}

公共静态类SpeechFactory
{
私有静态字典<字符串,MethodInfo的> speechMethods =新词典<字符串,MethodInfo的>();
公共静态的MethodInfo GetSpeechMethod(字符串speechText)
{
的MethodInfo MethodInfo的;
变种mySpeechMethods =新MySpeechMethods();
如果(speechMethods.Count == 0)
{
VAR =方法名
typeof运算(MySpeechMethods).GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);
变种speechAttributeMethods = methodNames.Where(Y =方式> y.GetCustomAttributes()OfType&所述; SpeechAttribute方式>()任何());
的foreach(在speechAttributeMethods VAR speechAttributeMethod)
{
的foreach(在speechAttributeMethod.GetCustomAttributes var属性(真))
{
speechMethods.Add(((SpeechAttribute)属性).SpeechValue,speechAttributeMethod);
}
}
MethodInfo的= speechMethods [speechText]
}
,否则
{
MethodInfo的= speechMethods [speechText]
}

返回MethodInfo的;
}
}
}

命名空间MyApp.SpeechMethods
{
公共类MySpeechMethods
{
[演讲(时间请)]
[演讲(什么时间)]
[演讲(时间是个什么)]
公共无效GETTIME()
{
Console.WriteLine(DateTime.Now.ToLocalTime());
}

[演讲(降低音量)]
公共无效VolumeDown()
{
Console.WriteLine(降低音量1) ;
}

[演讲(增加音量)]
公共无效VolumeUp()
{
Console.WriteLine(增加音量1) ;
}
}

[System.AttributeUsage(System.AttributeTargets.Method,的AllowMultiple = TRUE)]
公共类SpeechAttribute:System.Attribute
{
公共字符串SpeechValue {搞定;组; }

公共SpeechAttribute(字符串textValue)
{
this.SpeechValue = textValue;
}
}
}


Rather than using Switch/Case or IF Boolean checks that can get very long and awfully tedious, I wonder if a better way can be sought for handling and processing Commands.

E.G:

if(settings.getName == Command)
{
Speak("I am here");
}

if("Get News Feed" == Command)
{
MyRSSFeed RSSNewsFeed = new MyRSSFeed();
RSSNewsFeed.GetFeed();
}

The if commands go on... Here is a snippet of my Switch Statement:

switch (Command)
        {
            #region <-- Get Time Command -->

            case "Time Please":
            case "Whats the Time":
            case "What Time is it":
                GetCurrentTime();
                break;

            #endregion <-- Get Time Command -->

            #region <-- Get Date Command -->

            case "Whats the Date":
            case "What Date is it":
            case "Whats the Date Today":
            case "What is the Date Today":
                GetCurrentDate();
                break;

            #endregion <-- Get Date Command -->


            #region <-- Media Player Commands -->

            case "Play Bamboo Forest":

                Data.MusicPlayer.Play(@"\Bamboo Forest Play List.wpl");

                break;

            case "Next Song":

                Data.MusicPlayer.Next();

                break;

            case "Previous Song":

                Data.MusicPlayer.Previous();

                break;

            case "Stop Music":

                Data.MusicPlayer.Stop();

                break;

            case "Pause Music":

                Data.MusicPlayer.Pause();

                break;

            case "Resume Music":

                Data.MusicPlayer.Resume();

                break;


            case "Mute Music":

                Data.MusicPlayer.Mute();

                break;

            case "Volume Up":

                Data.MusicPlayer.VolumeUp();

                break;

            case "Volume Down":

                Data.MusicPlayer.VolumeDown();

                break;

            #endregion <-- Media Player Commands -->

            #region <-- Voice Recognition Control Commands -->

            case "Stop Listening":
                Audio.Listen.NewCommandRecognitionEngine.RecognizeAsyncCancel();
                Audio.Voice.Speak("Ok");
                Audio.Listen.Initialise(main);
                break;

            #endregion <-- Voice Recognition Control Commands -->

            #region <-- Application Commands -->

            case "Quiet":
                Audio.Voice.Stop();
                break;

            case "Download":
                Audio.Voice.Speak("Opening Download Window.");
                main.dlInterface.ShowBitsJobs();
                break;

            case "Settings":
                Audio.Voice.Speak("Opening Settings Window.");
                main.settings.Show();
                break;

            case "Close":
                if (main.dlInterface.Visable == true)
                {
                    main.dlInterface.Hide();
                    Audio.Voice.Speak("Closing Download Window.");
                }
                if (main.settings.Visible == true)
                {
                    main.settings.Hide();
                    Audio.Voice.Speak("Closing Settings Window.");
                }
                break;

            case "Out of the way":
                if (main.WindowState == System.Windows.Forms.FormWindowState.Normal)
                {
                    main.WindowState = System.Windows.Forms.FormWindowState.Minimized;
                    Audio.Voice.Speak("My apologies");
                }
                break;

            case "Where Are You":
                if (main.WindowState == System.Windows.Forms.FormWindowState.Minimized)
                {
                    main.WindowState = System.Windows.Forms.FormWindowState.Normal;
                    Audio.Voice.Speak("Here");
                }
                break;


            default:
                // Do Nothing here...
                break;
        }

I have a SQL Database that contains Commands. I Load Commands into it as I need. It has a Command Name Colum and a Value Colum. I can change these to add change or delete columns as needed.

Currently, once a command is recognised, I use a combination of IF Statements and a Switch/Case Catch to catch the recognised Command.

I have thought about somehow dropping dll's into a folder and some how scanning then on app load. If I add a Command then somehow use the Value Field to action the command in the dll.

I realise this is a rather complex situation but I feel a much better solution can be found to make this process much more simple.

EDIT: I have looked at this already: http://social.msdn.microsoft.com/Forums/en-US/4f962dc0-aec2-4191-9fe2-e1dfeb1da5dd/voice-command-api

Please ask if you need any more information.

[EDIT] Paqogomez has answered this question. See my working example below:

using System;
using System.Linq;
using MyApp.AppCommands;
using System.Reflection;
using System.Collections.Generic;

namespace MyApp
{
class Program
{
static void Main(string[] args)
{
MethodInfo myMethod;

var methods = new Commands();

myMethod = CommandFactory.GetCommandMethods("Time Please");
myMethod.Invoke(methods, null);

myMethod = CommandFactory.GetCommandMethods("Volume Down");
myMethod.Invoke(methods, null);

myMethod = CommandFactory.GetCommandMethods("Volume Up");
myMethod.Invoke(methods, null);

Console.ReadLine();
}
}

public static class CommandFactory
{
private static Dictionary<string, MethodInfo> commandMethods = new Dictionary<string, MethodInfo>();

public static MethodInfo GetCommandMethods(string Command)
{
MethodInfo methodInfo;

var myCommandMethods = new Commands();

if (commandMethods.Count == 0)
{
var methodNames = typeof(Commands).GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);

var speechAttributeMethods = methodNames.Where(y => y.GetCustomAttributes().OfType<CommandAttribute>().Any());

foreach (var speechAttributeMethod in speechAttributeMethods)
{
foreach (var attribute in speechAttributeMethod.GetCustomAttributes(true))
{
commandMethods.Add(((CommandAttribute)attribute).CommandValue, speechAttributeMethod);
}
}
methodInfo = commandMethods[Command];
}
else
{
methodInfo = commandMethods[Command];
}

return methodInfo;
}
}
}

namespace MyApp.AppCommands
{
public class Commands
{
[Command("Time Please")]
[Command("Whats the Time")]
[Command("What Time is it")]
public void GetTime()
{
Console.WriteLine(DateTime.Now.ToLocalTime());
}

[Command("Volume Down")]
public void VolumeDown()
{
Console.WriteLine("Volume Down 1");
}

[Command("Volume Up")]
public void VolumeUp()
{
Console.WriteLine("Volume Up 1");
}
}

[System.AttributeUsage(System.AttributeTargets.Method, AllowMultiple = true)]
public class CommandAttribute : System.Attribute
{
public string CommandValue { get; set; }

public CommandAttribute(string textValue)
{
this.CommandValue = textValue;
}
}
}

Beautiful Work Paqogomez and thank you for Sharing! This is fast and very elegant!.

In my case, all I need to call the code is:

private static void CommandRecognized(object sender, SpeechRecognizedEventArgs e)
{
MethodInfo myMethod;

var methods = new Commands();

myMethod = CommandFactory.GetCommandMethods(e.Result.Text);
myMethod.Invoke(methods, null);
}

which is the Event Handler of the Speech Recognition Engine:

CommandRecognitionEngine.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(CommandRecognized);

解决方案

You are looking for the Strategy pattern as defined here.

This will allow you to handle multiple if statements very easily.

A factory pattern might also suit you. A factory could use reflection to determine which command to create.

You could also just dump all your commands into a dictionary.

EDIT:

Given the last bit of code example a factory is what you need. I've put one together below.

The factory simply reflects on all the methods in MySpeechMethods, looks for ones with SpeechAttributes and sends back the MethodInfo to invoke. If you need return values from your methods you can either set all the methods to return the same type (like string) or look into generics, but I'll leave that to you. :)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using MyApp.SpeechMethods;

namespace MyApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var methods = new MySpeechMethods();
            MethodInfo myMethod;
            myMethod = SpeechFactory.GetSpeechMethod("Time Please");
            myMethod.Invoke(methods, null);
            myMethod = SpeechFactory.GetSpeechMethod("Volume Down");
            myMethod.Invoke(methods, null);
            myMethod = SpeechFactory.GetSpeechMethod("Volume Up");
            myMethod.Invoke(methods, null);
        }
    }

    public static class SpeechFactory
    {
        private static Dictionary<string, MethodInfo> speechMethods = new Dictionary<string, MethodInfo>();
        public static MethodInfo GetSpeechMethod(string speechText)
        {
            MethodInfo methodInfo;
            var mySpeechMethods = new MySpeechMethods();
            if (speechMethods.Count == 0)
            {
                var methodNames =
                    typeof (MySpeechMethods).GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);
                var speechAttributeMethods = methodNames.Where(y => y.GetCustomAttributes().OfType<SpeechAttribute>().Any());
                foreach (var speechAttributeMethod in speechAttributeMethods)
                {
                    foreach (var attribute in speechAttributeMethod.GetCustomAttributes(true))
                    {
                        speechMethods.Add(((SpeechAttribute)attribute).SpeechValue, speechAttributeMethod);
                    }
                }
                methodInfo = speechMethods[speechText];
            }
            else
            {
                methodInfo = speechMethods[speechText];
            }

            return methodInfo;
        }
    }
}

namespace MyApp.SpeechMethods
{
    public class MySpeechMethods
    {
        [Speech("Time Please")]
        [Speech("Whats the Time")]
        [Speech("What Time is it")]
        public void GetTime()
        {
            Console.WriteLine(DateTime.Now.ToLocalTime());
        }

        [Speech("Volume Down")]
        public void VolumeDown()
        {
            Console.WriteLine("Volume Down 1");
        }

        [Speech("Volume Up")]
        public void VolumeUp()
        {
            Console.WriteLine("Volume Up 1");
        }
    }

    [System.AttributeUsage(System.AttributeTargets.Method, AllowMultiple = true)]
    public class SpeechAttribute : System.Attribute
    {
        public string SpeechValue { get; set; }

        public SpeechAttribute(string textValue)
        {
            this.SpeechValue = textValue;
        }
    }
}

这篇关于聪明的方式来处理语音命令的代码操作的命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆