Question Speech Recognition question

manbearpig001

Member
Joined
Jun 15, 2012
Messages
8
Programming Experience
5-10
Hey,
I have been trying to create a set of grammar rules for a speech recognition program with an array, but cannot seem to accomplish this task. Here is the general idea:

Code:
Dim commandlist As New Recognition.SrgsGrammar.SrgsOneOf(websites(0), websites(1), websites(2))
        commandRule.Add(commandlist)
        gram.Rules.Add(commandRule)
        gram.Root = commandRule
        recog.LoadGrammar(New Recognition.Grammar(gram))
I have a string array - websites() - and for each string in this array, I want to add it to the commandlist. Unfortunately, the only way I know of doing this is by writing it one by one, as seen above. I tried doing this:

Code:
Dim commandlist As New Recognition.SrgsGrammar.SrgsOneOf
        dim i as integer = 0
        do until i = websites.items.count
        commandlist.items.add(websites(i))
        i +=1
        loop
        commandRule.Add(commandlist)
        gram.Rules.Add(commandRule)
        gram.Root = commandRule
        recog.LoadGrammar(New Recognition.Grammar(gram))
But this did not work, because I cannot convert strings into srgsoneof... Anyone have any idea how this could be done?
 

Dunfiddlin

Well-known member
Joined
Jun 15, 2012
Messages
253
Programming Experience
5-10
New SrgsOneOf handles arrays so is it not as simple as .... ?


Dim commandlist As New Recognition.SrgsGrammar.SrgsOneOf(websites)
 

manbearpig001

Member
Joined
Jun 15, 2012
Messages
8
Programming Experience
5-10
New SrgsOneOf handles arrays so is it not as simple as .... ?


Dim commandlist As New Recognition.SrgsGrammar.SrgsOneOf(websites)
I do not think it is as simple as that. I tried to implement this and no speech recognized handlers fired off.

Any other suggestions?
 

Dunfiddlin

Well-known member
Joined
Jun 15, 2012
Messages
253
Programming Experience
5-10
Yes, declare commandlist as a separate instance and then use it from there.

Dim commandlist as New SrgsOneOf(websites)
 

manbearpig001

Member
Joined
Jun 15, 2012
Messages
8
Programming Experience
5-10
Yes, declare commandlist as a separate instance and then use it from there.

Dim commandlist as New SrgsOneOf(websites)
I fail to see the difference in what you just posted and what you posted before. Just the import clause? Because that does not alter anything.
 

Dunfiddlin

Well-known member
Joined
Jun 15, 2012
Messages
253
Programming Experience
5-10
You don't wanna give it a try first, just in case it might work? I think you'll find that there is a considerable difference in fact!
 

manbearpig001

Member
Joined
Jun 15, 2012
Messages
8
Programming Experience
5-10
Tried it. Threw an error, so I imported System.Speech.Recognition.SrgsGrammar, and it did not do anything. Perhaps I misunderstood the code you presented?
 

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,377
Location
Norway
Programming Experience
10+

Dunfiddlin

Well-known member
Joined
Jun 15, 2012
Messages
253
Programming Experience
5-10
There is one rather important difference at least. One works, the other doesn't! The syntax is sacrosanct here. Please refer to my answer to the original poster in about 5 minutes!
 

Dunfiddlin

Well-known member
Joined
Jun 15, 2012
Messages
253
Programming Experience
5-10
A little perhaps. If you use the long form it is an instance assignment but the short form acts essentially as a conversion function - cf. New String(chr_array).

The exception is thrown if you declare the websites array without bounds. It isn't coming from the commandlist declaration itself. The following works only if the array is declared with the exact number of items it contains (3 in this case enumerated 0 to 2)



Imports System.Speech.Recognition.SrgsGrammar


Public Class Form1


Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim websites(2) As String
websites(0) = "First"
websites(1) = "Second"
websites(2) = "Third"




Dim commandlist As New SrgsOneOf(websites)


End Sub
End Class
 

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,377
Location
Norway
Programming Experience
10+
If you use the long form it is an instance assignment but the short form acts essentially as a conversion function
That is not true, the difference in those two statements is that one is qualifying the namespace, the other is not (implying the namespace must be imported). Code-wise they are equal.
 

Dunfiddlin

Well-known member
Joined
Jun 15, 2012
Messages
253
Programming Experience
5-10
If you want to insist on form over function then that's your prerogative. I should point however that I did very carefully say "acts as" rather than "is" which is how you seem to have interpreted it. As far as I'm concerned nothing is equal 'code-wise' that does not do exactly the same thing in the same place in the same conditions. You cannot substitute one for the other here. That's the bottom line. I'm sure in most cases on this forum people prefer what works to what may seem more 'correct' to VB 'grammarians'.
 

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,377
Location
Norway
Programming Experience
10+
I should point however that I did very carefully say "acts as" rather than "is" which is how you seem to have interpreted it.
You said they were different, which they are not.
As far as I'm concerned nothing is equal 'code-wise' that does not do exactly the same thing in the same place in the same conditions. You cannot substitute one for the other here.
That is exactly the point, those two pieces of code are for all practical purposes completely identical. There is no substitution because they are the same. Both is invoking the same SrgsOneOf constructor with same argument.
You can't use any type in VB without qualifying it by namespace, there are three ways to do this, (a) directly qualifying it when declaring the variable, (a) by using the Imports statement in a code file, or (c) by importing the namespace globally in project settings. Commonly used namespaces are imported by default for the different project types. If one use a namespace a lot in a code file is it natural to use the Imports statement to avoid code getting too "wordy".
Here you can start learning about namespaces: Namespaces in Visual Basic
 

manbearpig001

Member
Joined
Jun 15, 2012
Messages
8
Programming Experience
5-10
SrgsOneOf is used for alternate words to match a single rule, is that what you're trying to do?
SrgsOneOf is used for alternate words to match a single set of rules, but not one single rule. The set of rules are then uploaded to a grammar set which then ties into Windows7 Speech Recognition Software. In the past, I had to type in something like this:

Dim commandlist As New Recognition.SrgsGrammar.SrgsOneOf(websites(0), websites(1), websites(2))
commandRule.Add(commandlist)
gram.Rules.Add(commandRule)
gram.Root = commandRule
recog.LoadGrammar(New Recognition.Grammar(gram))

The issue with this for my case is that the number of items in my database, websites() is dynamic, and it is incorrect of me to change the code every time I want to add a freaking website to the array. So I need to find a way to upload every string from the array websites() to SrgsOneOf, so that I can then upload them into my grammar rules. Seems simple, but it has proven to cause some trouble thus far.

In response to the debate above, you are correct in saying that there is no actual difference in the two methods, but rather that it offers a method to which one can clean up the code by eliminating the words System.blahblahblah before each reference. That is why I was confused at first, because at first glance there is no difference. I tried it for the hell of it and I was correct in believing that there was no difference (at least of relevance to my case) because it did not solve the problem.
 

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,377
Location
Norway
Programming Experience
10+
So I need to find a way to upload every string from the array websites() to SrgsOneOf
As correctly pointed out by Dunfiddlin in post 2 the SrgsOneOf class has a constructor that takes a String array as parameter, so if that is what you are trying to do the you just have to pass that array to the constructor.
 

manbearpig001

Member
Joined
Jun 15, 2012
Messages
8
Programming Experience
5-10
As correctly pointed out by Dunfiddlin in post 2 the SrgsOneOf class has a constructor that takes a String array as parameter, so if that is what you are trying to do the you just have to pass that array to the constructor.
Interestingly enough, I tried this a while back and no cases were recognized by Windows Speech Recognition with the array. Here is what I have now, and it does not work:

Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim gram As New Recognition.SrgsGrammar.SrgsDocument
Dim commandRule As New Recognition.SrgsGrammar.SrgsRule("commands")
Dim sr As StreamReader = System.IO.File.OpenText("C:\Users\andrewbourhis\Documents\Speech Recog Library\websites.txt")
Dim sdata As String
sdata = sr.ReadToEnd
websites = Split(sdata, ControlChars.NewLine)
Dim webst As Integer = 0
Do Until webst = websites.Count
Websitesbox.Items.Add(websites(webst))
webst += 1
Loop
sr.Close()
Dim commandlist As New SrgsOneOf(websites)
commandRule.Add(commandlist)
gram.Rules.Add(commandRule)
gram.Root = commandRule
recog.LoadGrammar(New Recognition.Grammar(gram))
SerialPort1.WriteBufferSize = 4
SerialPort1.Open()
Timer1.Enabled = True
recog.Enabled = True
End Sub

Dim muted As Boolean = False
Private Sub reco_SpeechRecognized(ByVal sender As Object, ByVal e As System.Speech.Recognition.RecognitionEventArgs) Handles recog.SpeechRecognized
Dim buff() As Byte = {0, 0, 0, 0}
Dim stacy As New Synthesis.SpeechSynthesizer
Dim webst As Integer = 0
Do Until webst = websites.Count 'sift through each website in the text file and go to it if it has been said
If websites(webst) = e.Result.Text Then
Process.Start("www." & e.Result.Text & ".com")
End If
webst += 1
Loop
Select Case e.Result.Text


Case "mute"
If muted = True Then Exit Sub
muted = True
SendMessageW(Me.Handle, WM_APPCOMMAND, _
Me.Handle, New IntPtr(APPCOMMAND_VOLUME_MUTE))
Case "unmute"
If muted = True Then
SendMessageW(Me.Handle, WM_APPCOMMAND, _
Me.Handle, New IntPtr(APPCOMMAND_VOLUME_MUTE))
muted = False
End If
Case "play my music", "play my music please", "play some music"
System.Diagnostics.Process.Start("www.pandora.com")
Case ("solder on")
Dim i As Integer = 5
Dim i1 As Integer = 5
Do Until i = 9
buff = {1, 0, i, i1}
SerialPort1.Write(buff, 0, 5)
System.Threading.Thread.Sleep(50)
If i1 = 5 Then
i += 1
i1 = 0
Else
i1 = 5
End If
Loop


Case Else
stacy.Speak("Sorry, I don't understand")


End Select
End Sub


<DllImport("user32.dll")> _
Public Shared Function SendMessageW(ByVal hWnd As IntPtr, _
ByVal Msg As Integer, ByVal wParam As IntPtr, _
ByVal lParam As IntPtr) As IntPtr
End Function


EDIT: keep in mind some of the commands will not work with the website array as of now, because of the if statement. I only intend on making the websites work right now, so disregard the case select statement.
 

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,377
Location
Norway
Programming Experience
10+
manbearpig001 said:
websites = Split(sdata, ControlChars.NewLine)
This was the first that I noticed, because of this documentation:
help said:
Delimiter
Optional. Any single character used to identify substring limits.
but it was later changed to this:
new help said:
Delimiter

Optional. Any string of characters used to identify substring limit
Much simpler though, use the File.ReadAllLines method to get the array. As it is your speech recog code currently can be expressed like this:
Dim websites = IO.File.ReadAllLines("....websites.txt")
recog.LoadGrammar(New Grammar(New SrgsDocument(New SrgsRule("commands", New SrgsOneOf(websites)))))

I have of course tested this, and the rule is recognised using any of the alternate words from that file.

Use the posting editor and put the code in code box when you post code, as it is now it is too much a strain to bother reading it thoroughly.
 
Top Bottom