I recreated a minimal example from GitHub's SpeechRecognitionAndSynthesis from the Scenario_SRGSConstraint.xaml.cs scenario using the grammar I created in an xml file called grammar.
What I would like to solve would be the sequence of words with which to start the action. I recreated the model so that I could choose two colors: red and green for a rectangle background.
Now what I have to say (I will use words in Italian by necessity) to start the action after pressing the button I must pronounce the color first, between red and green and then background to start the action.
I would like to be able to pronounce the background first (then sfondo) and then the color (then rosso o verde), I tried in various ways to modify the grammar.xml several times without success.
I wanted to ask at this point what changes I have to make to start the action by saying the sentence for example: red background or green background ... so as to pronounce the word background (then sfondo) first and then red or green (then rosso o verde) word.
Finally I would like to ask if I need to change only the grammar.xml or even the Code Behind.
MainPage.xaml.cs:
private SpeechRecognizer speechRecognizer;
private IAsyncOperation<SpeechRecognitionResult> recognitionOperation;
private ResourceContext speechContext;
private ResourceMap speechResourceMap;
private Dictionary<string, Color> colorLookup = new Dictionary<string, Color>
{
{ "COLOR_RED", Colors.Red }, {"COLOR_GREEN", Colors.Green}
};
public MainPage()
{
InitializeComponent();
}
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
bool permissionGained = await AudioCapturePermissions.RequestMicrophonePermission();
if (permissionGained)
{
Language speechLanguage = SpeechRecognizer.SystemSpeechLanguage;
string langTag = speechLanguage.LanguageTag;
speechContext = ResourceContext.GetForCurrentView();
speechContext.Languages = new string[] { langTag };
speechResourceMap = ResourceManager.Current.MainResourceMap.GetSubtree("LocalizationSpeechResources");
await InitializeRecognizer();
}
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
if (speechRecognizer != null)
{
if (speechRecognizer.State != SpeechRecognizerState.Idle)
{
if (recognitionOperation != null)
{
recognitionOperation.Cancel();
recognitionOperation = null;
}
}
speechRecognizer.StateChanged -= SpeechRecognizer_StateChanged;
this.speechRecognizer.Dispose();
this.speechRecognizer = null;
}
}
private async Task InitializeRecognizer()
{
if (speechRecognizer != null)
{
speechRecognizer.StateChanged -= SpeechRecognizer_StateChanged;
this.speechRecognizer.Dispose();
this.speechRecognizer = null;
}
try
{
string languageTag = SpeechRecognizer.SystemSpeechLanguage.LanguageTag;
StorageFile grammarFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///grammar.xml"));
speechRecognizer = new SpeechRecognizer(SpeechRecognizer.SystemSpeechLanguage);
speechRecognizer.StateChanged += SpeechRecognizer_StateChanged;
SpeechRecognitionGrammarFileConstraint grammarConstraint = new SpeechRecognitionGrammarFileConstraint(grammarFile);
speechRecognizer.Constraints.Add(grammarConstraint);
SpeechRecognitionCompilationResult compilationResult = await speechRecognizer.CompileConstraintsAsync();
}
catch (Exception ex) { string message = ex.Message; }
}
private async void SpeechRecognizer_StateChanged(SpeechRecognizer sender, SpeechRecognizerStateChangedEventArgs args)
{
}
private async void RecognizeWithoutUI_Click(object sender, RoutedEventArgs e)
{
try
{
recognitionOperation = speechRecognizer.RecognizeAsync();
SpeechRecognitionResult speechRecognitionResult = await recognitionOperation;
if (speechRecognitionResult.Status == SpeechRecognitionResultStatus.Success)
{
HandleRecognitionResult(speechRecognitionResult);
}
}
catch (TaskCanceledException exception)
{
System.Diagnostics.Debug.WriteLine("TaskCanceledException caught while recognition in progress (can be ignored):");
System.Diagnostics.Debug.WriteLine(exception.ToString());
}
}
/// <summary>
/// Uses the result from the speech recognizer to change the colors of the shapes.
/// </summary>
/// <param name="recoResult">The result from the recognition event</param>
private void HandleRecognitionResult(SpeechRecognitionResult recoResult)
{
// Check the confidence level of the recognition result.
if (recoResult.Confidence == SpeechRecognitionConfidence.High ||
recoResult.Confidence == SpeechRecognitionConfidence.Medium)
{
if (recoResult.SemanticInterpretation.Properties.ContainsKey("KEY_BACKGROUND") && recoResult.SemanticInterpretation.Properties["KEY_BACKGROUND"][0].ToString() != "...")
{
string backgroundColor = recoResult.SemanticInterpretation.Properties["KEY_BACKGROUND"][0].ToString();
colorRectangle.Fill = new SolidColorBrush(getColor(backgroundColor));
}
}
}
/// <summary>
/// Creates a color object from the passed in string.
/// </summary>
/// <param name="colorString">The name of the color</param>
private Color getColor(string colorString)
{
Color newColor = Colors.Transparent;
if (colorLookup.ContainsKey(colorString))
{
newColor = colorLookup[colorString];
}
return newColor;
}
grammar.xml:
<?xml version="1.0" encoding="utf-8" ?>
<grammar xml:lang="it-IT" root="colorChooser"
tag-format="semantics/1.0" version="1.0"
xmlns="http://www.w3.org/2001/06/grammar">
<rule id="background_Color">
<item>
<item>
<ruleref uri="#color"/>
</item>
sfondo
</item>
</rule>
<rule id="colorChooser">
<one-of>
<item>
<item>
<ruleref uri="#background_Color"/>
<tag> out.KEY_BACKGROUND=rules.latest(); </tag>
</item>
</item>
</one-of>
</rule>
<rule id="color">
<one-of>
<item>
rosso <tag> out="COLOR_RED"; </tag>
</item>
<item>
verde <tag> out="COLOR_GREEN"; </tag>
</item>
</one-of>
</rule>
</grammar>
Thanks in advance for the help.
--Update--
With this setting it is wrong ... I also tried to set playCommands with items that have exit tags but it does not run correctly (I update my post to highlight my test with your suggestion) The problem is that " out.KEY_BACKGROUND = rules.latest (); " must be inserted somewhere to start the action because in the code behind it is executed through this key: KEY_BACKGROUND.
Codice grammar.xml provato da me con il tuo suggerimento:
<?xml version="1.0" encoding="utf-8" ?>
<grammar xml:lang="it-IT" root="playCommands"
tag-format="semantics/1.0" version="1.0"
xmlns="http://www.w3.org/2001/06/grammar">
<rule id="background_Color">
<item>
sfondo
</item>
</rule>
<rule id="playCommands">
<item>
<ruleref uri="#background_Color" />
</item>
<item>
<ruleref uri="#color" />
<tag> out.KEY_BACKGROUND=rules.latest(); </tag>
</item>
</rule>
<rule id="color">
<one-of>
<item>
rosso <tag> out="COLOR_RED"; </tag>
</item>
<item>
verde <tag> out="COLOR_GREEN"; </tag>
</item>
</one-of>
</rule>
</grammar>
--Update1--
I tried your code and I think that the grammar.xml logic is correct, but in the code behind it gives me an error here:
recognitionOperation = speechRecognizer.RecognizeAsync();
In the method RecognizeWithoutUI_Click
And the error is this:
The text associated with this error code could not be found.
Here is the complete project: Test Grammar UWP
If you want to the elements must be listed in the order that the user will speak the command, you can create a top-level rule element that references both the background and color rules to create a flexible collection of commands, And set the command to be the root, like below:
grammar.xml:
<grammar xml:lang="it-IT" root="playCommands"
tag-format="semantics/1.0" version="1.0"
xmlns="http://www.w3.org/2001/06/grammar">
<rule id="background_Color">
<item>
sfondo
</item>
</rule>
<rule id="playCommands">
<ruleref uri="#background_Color" />
<ruleref uri="#color" />
</rule>
<rule id="color">
<one-of>
<item>
rosso <tag> out="COLOR_RED"; </tag>
</item>
<item>
verde <tag> out="COLOR_GREEN"; </tag>
</item>
</one-of>
</rule>
</grammar>
Update:
If you want to use "out.KEY_BACKGROUND = rules.latest();" You just need to change the position of the sfondo and <ruleref uri="#color"/>. In this case, it will execute the backgroundColor first and then the color.
<?xml version="1.0" encoding="utf-8" ?>
<grammar xml:lang="it-IT" root="colorChooser"
tag-format="semantics/1.0" version="1.0"
xmlns="http://www.w3.org/2001/06/grammar">
<rule id="background_Color">
<item>
sfondo
<item>
<ruleref uri="#color"/>
</item>
</item>
</rule>
<rule id="colorChooser">
<item>
<ruleref uri="#background_Color"/>
<tag> out.KEY_BACKGROUND=rules.latest(); </tag>
</item>
</rule>
<rule id="color">
<one-of>
<item>
rosso <tag> out="COLOR_RED"; </tag>
</item>
<item>
verde <tag> out="COLOR_GREEN"; </tag>
</item>
</one-of>
</rule>
</grammar>
Related
so I'm making an project and i been having a problem with a XML replacing some elements after getting from them a texts
i tried a lot of options remove add then new
and XML is like this:
<?xml version="1.0" encoding="utf-8"?>
<UserAccountData>
<user>
<username>Admin</username>
<password>Partyguest12</password>
<ID1>1<stats level="50" HP="1000" exp="250000" /></ID1>
</user>
<user>
<username>2</username>
<password>2</password>
<ID2>2<stats Level="1" HP="20" exp="0" /></ID2>
</user>
<user>
<username>3</username>
<password>3</password>
<ID3>3<stats Level="1" HP="20" exp="0" /></ID3>
</user>
<user>
<username>4</username>
<password>4</password>
<ID4>4<stats Level="1" HP="20" exp="0" /></ID4>
</user>
<user>
<username>5</username>
<password>5</password>
<ID5>5<stats Level="1" HP="20" exp="0" /></ID5>
</user>
</UserAccountData>
public partial class Game : MetroFramework.Forms.MetroForm
{
private void Save_data_Progress_Click(object sender, EventArgs e)
{
int IDcheck = 0;
XmlDocument User_Data_Exp_Use = new XmlDocument();
User_Data_Exp_Use.Load("UserData.xml");
foreach (XmlNode ID_Finder in User_Data_Exp_Use.SelectNodes("UserAccountData/user"))
{
IDcheck++;
if ((Account.Text == ID_Finder.SelectSingleNode("username").InnerText) && (Log_In_Data.PassKey == ID_Finder.SelectSingleNode("password").InnerText))
{
break;
}
}
XmlNode User_Path = User_Data_Exp_Use.SelectSingleNode("UserAccountData/user/ID" + IDcheck);
XmlElement Stats_Set = User_Data_Exp_Use.CreateElement("stats");
Stats_Set.SetAttribute("Level", Lv.Text);
Stats_Set.SetAttribute("HP", Hit_Points.Text);
Stats_Set.SetAttribute("exp",XP.Text);
User_Path.AppendChild(Stats_Set);
User_Data_Exp_Use.Save("UserData.xml");
}
}
it got me nothing or one of the XML error after run, saying its NULL
Trying to open this test file, which exists in a folder under my solution:
C:\dev\trunk\Development\WebSvc\WCFProj\Xml\po.xml
My c# method is :
public XmlDocument generateXmlResponse()
{
string appDir = AppContext.BaseDirectory;
XmlDocument xml = new XmlDocument();
xml.LoadXml(#"Xml\ResponseTempl.xml");
return xml;
}
and the exception message is :
"Data at the root level is invalid. Line 1, position 1."
Now when I step thru the code, I can use the relative path :
appDir + #"Xml\po.xml"
which correctly resolves to:
C:\dev\trunk\Development\WebSvc\WCFProj\Xml\po.xml
and I just took the sample PurchaseOrder.xml from the ms website https://msdn.microsoft.com/en-us/library/bb343181(v=vs.110).aspx :
<PurchaseOrder PurchaseOrderNumber="99503" OrderDate="1999-10-20">
<Address Type="Shipping">
<Name>Ellen Adams</Name>
<Street>123 Maple Street</Street>
<City>Mill Valley</City>
<State>CA</State>
<Zip>10999</Zip>
<Country>USA</Country>
</Address>
<Address Type="Billing">
<Name>Tai Yee</Name>
<Street>8 Oak Avenue</Street>
<City>Old Town</City>
<State>PA</State>
<Zip>95819</Zip>
<Country>USA</Country>
</Address>
<DeliveryNotes>Please leave packages in shed by driveway.</DeliveryNotes>
<Items>
<Item PartNumber="872-AA">
<ProductName>Lawnmower</ProductName>
<Quantity>1</Quantity>
<USPrice>148.95</USPrice>
<Comment>Confirm this is electric</Comment>
</Item>
<Item PartNumber="926-AA">
<ProductName>Baby Monitor</ProductName>
<Quantity>2</Quantity>
<USPrice>39.98</USPrice>
<ShipDate>1999-05-21</ShipDate>
</Item>
</Items>
</PurchaseOrder>
The issue here is that the following line:
xml.LoadXml(#"Xml\ResponseTempl.xml");
Is trying to load the string as XML and giving you the error as it is invalid XML. LoadXml should be used like so:
xml.LoadXml("<item><name>wrench</name></item>");
Since you are trying to read from a file you need to use:
https://msdn.microsoft.com/en-us/library/875kz807(v=vs.110).aspx
This will look like the following:
xml.Load(#"Xml\ResponseTempl.xml");
in the last days i tried to change a value of a single attribute of this application File
The Xml-File:
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd"
manifestVersion="1.0" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1"
xmlns="urn:schemas-microsoft-com:asm.v2"
xmlns:asmv2="urn:schemas-microsoft-com:asm.v2"
xmlns:xrml="urn:mpeg:mpeg21:2003:01-REL-R-NS"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"
xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"
xmlns:co.v1="urn:schemas-microsoft-com:clickonce.v1"
xmlns:co.v2="urn:schemas-microsoft-com:clickonce.v2">
<assemblyIdentity name="lolz" version="1.1.1.1" publicKeyToken="12345" language="neutral" processorArchitecture="x86" xmlns="urn:schemas-microsoft-com:asm.v1" />
<description asmv2:publisher="Example" asmv2:product="Productexample2" asmv2:supportUrl="Example" xmlns="urn:schemas-microsoft-com:asm.v1" />
<deployment install="true" mapFileExtensions="true" minimumRequiredVersion="1.1.1.1" trustURLParameters="true">
<subscription>
<update>
<beforeApplicationStartup />
</update>
</subscription>
<deploymentProvider codebase="http://Test" />
</deployment>
</asmv1:assembly>
Here i try to change the value of
<description asmv2:product = "Productexample">
into
<description asmv2:product = "Productexample2">
,and the value of
<deploymentProvider codebase="http://Test" />
into
<deploymentProvider codebase="http://Test2" />
Currently i tried :
private void changeAttribute (string xmlPath)
{
string newValue = "Productexample2";
XmlDocument xmlDoc= new XmlDocument();
xmlDoc.Load(xmlPath);
XmlNode node = xmlDoc.SelectSingleNode("asmv1:assembly/description/asmv2:product");
node.Attributes[0].Value = newValue;
xmlDoc.Save(xmlPath);
}
But it throws the Exception 'An unhandled exception of type 'System.Xml.XPath.XPathException' occurred in System.Xml.dll' so i think asmv1:assembly/description/asmv2:product is wrong ...
any suggestions of code?
as always you can correct me in any way :)
You have to use a namespace manager to make the prefixes work and you need the # character to indicate it is an attribute you are referencing.
So this should work:
XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable);
manager.AddNamespace("asmv1", "urn:schemas-microsoft-com:asm.v1");
manager.AddNamespace("asmv2", "urn:schemas-microsoft-com:asm.v2");
XmlNode node = xmlDoc.SelectSingleNode("/asmv1:assembly/asmv1:description/#asmv2:product", manager);
Also, your first line in the XML root is incomplete. It should be:
<asmv1:assembly xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd"
manifestVersion="1.0"
xmlns:asmv1="urn:schemas-microsoft-com:asm.v1"
xmlns="urn:schemas-microsoft-com:asm.v2"
xmlns:asmv2="urn:schemas-microsoft-com:asm.v2"
xmlns:xrml="urn:mpeg:mpeg21:2003:01-REL-R-NS"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"
xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"
xmlns:co.v1="urn:schemas-microsoft-com:clickonce.v1"
xmlns:co.v2="urn:schemas-microsoft-com:clickonce.v2"
>
The following program is a simple speech recognition console application in C# using the Microsoft managed speech API that just recognizes the words 'yes' and 'no'. When I create the Srgs rule 'MyRule' inline using the Srgs methods everything works Ok. However if I put the rule in an external XML file and create an SrgsRuleRef to reference it I always get the error: "A rule reference to an imported grammar cannot be resolved." I have tried changing various parameters such as the language, media type and semantic tag format but nothing seems to make any difference.
using System;
using System.Speech.Recognition;
using System.Speech.Recognition.SrgsGrammar;
namespace SpeechRecognitionConsole
{
class Program
{
static void Main(string[] args)
{
try
{
System.Globalization.CultureInfo culture =
new System.Globalization.CultureInfo("en-US");
SrgsRule RootRule = new SrgsRule("RootRule");
RootRule.Add(new SrgsRuleRef(
new Uri("c:\\projects.net\\speechrecognitionconsole\\MyGrammar.xml"), "MyRule"));
RootRule.Scope = SrgsRuleScope.Public;
SrgsDocument MyDocument = new SrgsDocument(RootRule);
MyDocument.Culture = culture;
Grammar g = new Grammar(MyDocument);
g.Name = ("MyGrammar");
SpeechRecognitionEngine recognizer = new SpeechRecognitionEngine(culture);
recognizer.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>
(recognizer_SpeechRecognized);
recognizer.LoadGrammar(g);
recognizer.SetInputToDefaultAudioDevice();
recognizer.RecognizeAsync(RecognizeMode.Multiple);
Console.WriteLine("Starting asynchronous recognition...");
Console.Read();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
static void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
Console.WriteLine(e.Result.Text);
}
}
}
The grammar file "c:\projects.net\speechrecognitionconsole\MyGrammar.xml" contains:
<?xml version="1.0" encoding="utf-8"?>
<grammar xml:lang="en-US" tag-format="semantics/1.0" version="1.0" xmlns="http://www.w3.org/2001/06/grammar">
<rule id="MyRule" scope="public">
<one-of>
<item>yes</item>
<item>no</item>
</one-of>
</rule>
</grammar>
To get this working today using Visual Studio 2013 I had to add root="MyRule" not sure if the same fix would have helped when question was asked in 2012.
<?xml version="1.0" encoding="utf-8"?>
<grammar xml:lang="en-US" tag-format="semantics/1.0"
version="1.0" xmlns="http://www.w3.org/2001/06/grammar" root="MyRule">
<rule id="MyRule" scope="public">
<one-of>
<item>yes</item>
<item>no</item>
</one-of>
</rule>
</grammar>
My XML file as below. It mixed schema and normal elements.
<?xml version="1.0" encoding="utf-8"?>
<!-- R1 -->
<ax:root xmlns:ax="http://amecn/software/realtime/ax">
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="EquipmentConstants">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="unbounded" ref="EquipmentConstant" />
</xsd:sequence>
</xsd:complexType>
<xsd:unique name="id">
<xsd:selector xpath=".//EquipmentConstant" />
<xsd:field xpath="#id" />
</xsd:unique>
</xsd:element>
......
......
</xsd:schema>
<EquipmentConstants xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<EquipmentConstant id="0">
<Name>SerialNumber</Name>
<Group>SYSTEM</Group>
<Data>
<Value min="0" max="10000000" scale_factor="0" unit="U_NO_UNITS" permission="NolimitedAndNoChangeable" type="xsd_string" enum="" flag="0">0</Value>
</Data>
<Description>Serial Number</Description>
</EquipmentConstant>
.....
.....
</EquipmentConstants>
</ax:root>
My C# code as below. I want to loop the elements start from (by pass all the content of schema)
<EquipmentConstants xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
XPathDocument doc = new XPathDocument("test.xml");
XPathNavigator navigator = doc.CreateNavigator();
navigator.MoveToRoot(); // <?xml version="1.0" encoding="utf-8"?>
//navigator.MoveToFirstChild(); // <!-- R1 -->
// 1st, I tried to use MoveToChield(), But I failed to move there.
navigator.MoveToChild("EquipmentConstants");
// Then, I also tried to use SelectSingleNode(). But I failed too.
navigator.SelectSingleNode("ax/EquipmentConstants");
while (navigator.MoveToNext())
{
// do something.
}
Could you please give me some suggestion. Thank you.
XPathNavigator navigator = doc.CreateNavigator();
if (navigator == null)
{
return;
}
foreach (XPathNavigator nav in
navigator.Select("/" + "EquipmentConstants" + "/" + "EquipmentConstant"))
{
}
My solution as below.
XPathDocument doc = new XPathDocument("test.xml");
XPathNavigator navigator = doc.CreateNavigator();
navigator.MoveToRoot(); // <?xml version="1.0" encoding="utf-8"?>
navigator.MoveToFirstChild(); // <!-- R1 -->
navigator.MoveToNext(); // <ax:root xmlns:ax="http://amecn/software/realtime/ax">
navigator.MoveToChild("EquipmentConstants", ""); // <EquipmentConstants xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
navigator.MoveToFirstChild(); // <EquipmentConstant id="0">
do
{
// Loop body;
} while (navigator.MoveToNext());