Author Topic: Command name (semi)constants  (Read 1812 times)

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1484
  • RTFM
Command name (semi)constants
« on: September 27, 2017, 11:43:40 pm »
Requests have been made in the past for a system that allows truly dynamic command names, however this is not possible with the way the speech recognition engine works.

What I propose is admittedly not ideal, but I believe it to be possible considering the technical limitations.
I also believe the utility to be worth the effort of implementation(Speaking as someone that wouldn't be doing the actual implementing, of course ::)):

Allow tokens in command names, however, only rebuild the phrase list when a specific action(E.G. "update dynamic commands") is explicitly called.


Disregarding the issues for a moment, this feature would allow command phrases to be changed semi-on-the-fly at the cost of losing speech recognition while the profile reloads.

E.G.
A command has the "When I say" value "[Curly;Larry;Moe;Johnny 5;Newton;Newton Crosby;Stephanie;Stephani Speck;Ben;Ben Jabituya;Ben Jahveri;Fred;Fred Ritter;Sandy;Sandy Banatoni] follow me;follow me [Curly;Larry;Moe;Johnny 5;Newton;Newton Crosby;Stephanie;Stephani Speck;Ben;Ben Jabituya;Ben Jahveri;Fred;Fred Ritter;Sandy;Sandy Banatoni]"

Not only would every variation on this command add many derived commands, it's also difficult to edit the phrases because there's so much unchanging text in the way(imagine replacing "follow me" in five different commands).

This proposed feature would allow the "When I say" value to instead be "{TXT:Character} follow me;follow me {TXT:Character}"

The command that runs when the profile loads would set up the variable:
Code: [Select]
Set Text [Character] to '[Curly;Larry;Moe;Johnny 5;Newton;Newton Crosby;Stephanie;Stephani Speck;Ben;Ben Jabituya;Ben Jahveri;Fred;Fred Ritter;Sandy;Sandy Banatoni]'
Or, as a more likely scenario in which you'll only address one character at a time:
Code: [Select]
Set Text [Character] to [Saved Value]


For my setup, this would work quite well, as with the current optimizations all my profiles load in under 100ms, though I realize the phrase variations I use are minimal.


Coming back to the issues with this system, there is the obvious question of what happens when a token returns either "Not Set", or a result that would cause a duplicate command phrase.

The option I can see causing the fewest issues(and communicating clearly to the user that there's something amiss, rather than having random commands not work for example) is to abort the phrase generation when this occurs, and displaying a warning in the log.
When this state is reached, either the speech engine could fall back to the previous phrase list(provided it's not flushed or edited by the generation process), or be disabled until a valid phrase list can be generated(as when starting VoiceAttack, variables wouldn't be initialized yet, so this is likely to occur).

The only UI modification I suggest(aside from the one to implement the "update dynamic commands" action) is a checkbox in the profile settings to "wait for the dynamic commands update action before starting the speech engine", or a dropdown "execute this command to initialize dynamic commands before starting the speech engine"(or both, made mutually exclusive).


The second, potentially deal-breaking issue, is the overhead added by token processing while generating commands.
If this feature were to significantly increase the time this process takes, even for users that don't utilize it, I understand it's a non-starter.

Exergist

  • Sr. Member
  • ****
  • Posts: 325
  • Can you dig it?
Re: Command name (semi)constants
« Reply #1 on: September 28, 2017, 10:30:11 am »
Seconded for seeing if this would be feasible!

TheThingIs

  • Global Moderator
  • Full Member
  • *****
  • Posts: 232
    • HCS Voicepacks
Re: Command name (semi)constants
« Reply #2 on: September 30, 2017, 05:20:28 am »
thirded!!!!! we need this :)
The Singularity profile - One profile to rule them all and at HCS we bound them ;)

You see, TheThingIs, eventually you'll be allright.

Gary

  • Administrator
  • Hero Member
  • *****
  • Posts: 1625
Re: Command name (semi)constants
« Reply #3 on: September 30, 2017, 01:59:57 pm »
I'm just a little bit hesitant to do this, and I'll explain.  The speech engine 'stuff' and the command 'stuff' is all processed in one big go.  That's for optimization reasons, and there's a lot of very specific conditions that are being looked at to try to make a profile load as fast as possible (and there's still more to do, actually).  Any variable initialization is done by user-created commands.  This is, of course, after the profile loads up.  It's one of those cases where yeah, it would be great to have that, but I'm not quite sure just how right it could be across the board (like, does it work completely with number ranges, does it work completely with composite (prefix/suffix) commands, does it work with the, 'override' commands, etc., etc.).  What's going on right now is that the guts are mostly out for doing language-y things and I've got the brakes on making new stuff until I get that wrapped up, so I am shying away from getting into the constant back and forth where it's not working everywhere or there are functionality issues brought about by it.  That said, it's almost ZERO code for me to add token support to the, 'when I say' values.  What I will do is make this an, 'unofficial' feature for now, and if it sticks, great, but if it totally blows up, it can be put back into order really fast.  I would like to add a new action (or maybe just tack it on to the, 'Windows Function' action) that resets the speech engine.  That can be done AFTER profile load (yes, that means the profile would need to load TWICE, but this is overhead that would be at the cost of the folks that are using it (thinking very few) and not EVERYBODY else that is not using it (since profile loads would have to be changed to have multiple parts running in sequence... I think you get the idea).  So, what you could do for now is simulate the aforementioned new action by just creating an empty profile and switch to it... then switch back.  It's just for a test and there's no guarantee that any of this will stick ;)

Wow...that's a lot of words.  I'm hungry & it's time for lunch o_O



Edit:  There's a build out in the, 'unofficial' bin for you to try if you'd like:  http://www.voiceattack.com/unofficial
« Last Edit: September 30, 2017, 02:06:26 pm by Gary »

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1484
  • RTFM
Re: Command name (semi)constants
« Reply #4 on: October 02, 2017, 06:15:38 pm »
In doing some testing, I'm rather pleased with the functionality. No doubt there are still things to be discovered, but overall the results are encouraging:

One feature this system provides(at least partially) has also been requested before: Disabling commands from recognition.
By using a fully variable command name(E.G. "{TXT:CommandName}") or even an unpronounceable prefix(E.G. "{TXT:DisablePrefix} My command name", where "DisablePrefix"="dddddddddddddddd"), the voice recognition portion can be "disabled".
Obviously this isn't a full solution as is doesn't disable keyboard, mouse, or controller shortcuts, but to me it's a neat side effect at least.

Commands with the exact same parsed name(as opposed to the base name, I.E. what is entered into the "When I Say" textbox) are "handled" as duplicate commands always have been(when imported through a modified .vap): The first match is executed.
E.G. if you have "{TXT:test1}" and "{TXT:test2}" as command names, and set both variables to "test", speaking "test" will execute the first command that matches(In my testing the order is alphabetical, though there are no guarantees, and frankly duplicates should be avoided by the profile creator).

Number ranges are processed after tokens are, and seem to work fine. As, unlike the existing dynamic command sections, tokens do not add spaces, even things like "Number {TXT:NumberRange}{TXT:NumberRange2}" where "NumberRange"="[1." and "NumberRange2"=".10]" work as expected.

"Override listening if my spoken command begins with" doesn't seem to accept tokens as input, but then it never did.
However, it overrides listening just fine for commands named using tokens, like it would for any other command.


One specific restriction that did pop up during testing:
Using double quote characters in dynamic command names is prohibited, which does not allow use of literal input for tokens(E.G. '{TXTCONCAT:"test":"test"}' cannot be stored).
I assume this is because the speech recognition engine doesn't accept/has trouble with double quotes. This would require additional processing either to determine whether all double quotes are encapsulated in valid tokens(as '{"}' for example would still render as a double quote), or to sanitize the strings after token processing.


I set up a utility profile to embed in other profiles which would automatically reload the profile in use when called(to emulate the proposed "update dynamic commands"/"reset speech engine" action):

Reload phrase list
Code: [Select]
Set Text [ProfileInUse] to '{PROFILE}'
Switch to profile, 'Reload phrase list' (by name)
This command would be executed from the profile in use to initiate the reload

Switch back
Code: [Select]
Begin Condition : ([ProfileInUse] Has Been Set AND [ProfileInUse] Does Not Equal 'Reload phrase list')
    Switch to profile, '{TXT:ProfileInUse}' (by name)
Else
    Write '[Red] Reload Error: Profile invalid' to log
End Condition
This command would automatically execute when the utility profile loads. Minor sanity check is included to avoid an infinite loop if the profile is told to switch to itself.


As an aside, having an action to reload the speech recognition engine would come in handy even without the above functionality, as with my microphone, which picks up quite a bit of environmental noise, speech recognition gets less reliable the longer VoiceAttack runs.
Currently I use a batch file to restart VoiceAttack automatically after it closes when requested, but having an action built in would make that unnecessary.

Exergist

  • Sr. Member
  • ****
  • Posts: 325
  • Can you dig it?
Re: Command name (semi)constants
« Reply #5 on: October 03, 2017, 07:49:14 am »
Your research and testing is much appreciated Pfeil!

Maybe this needs to be discussed in a separate thread, but I'm rather interested in one of Pfeil's last comments:
Quote
...as with my microphone, which picks up quite a bit of environmental noise, speech recognition gets less reliable the longer VoiceAttack runs.

@Gary do you have any thoughts about why/how this would happen?

Gary

  • Administrator
  • Hero Member
  • *****
  • Posts: 1625
Re: Command name (semi)constants
« Reply #6 on: October 03, 2017, 11:54:17 am »
If the speech engine is listening all the time, it tends to try to, 'adapt' to your environment.  What it's actually doing is something only Microsoft can explain.  You can always try enabling the option, 'Disable adaptive recognition' and see if that helps if you are having problems like this.

blueknight

  • Newbie
  • *
  • Posts: 13
Re: Command name (semi)constants
« Reply #7 on: October 17, 2017, 11:37:44 am »
Is this going to be in the production version?

Exergist

  • Sr. Member
  • ****
  • Posts: 325
  • Can you dig it?
Re: Command name (semi)constants
« Reply #8 on: December 01, 2017, 09:05:24 am »
Would it be possible to add a VoiceAttack action to restart VoiceAttack? This would reset the speech engine and avoid the need for a separate blank profile for performing the engine reset. I added this

Quote
Currently I use a batch file to restart VoiceAttack automatically after it closes when requested

@Pfeil would you mind sharing your "restart VoiceAttack" batch file code?
« Last Edit: December 01, 2017, 09:36:46 am by Exergist »

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1484
  • RTFM
Re: Command name (semi)constants
« Reply #9 on: December 01, 2017, 02:38:36 pm »
@Pfeil would you mind sharing your "restart VoiceAttack" batch file code?

RestartVA.bat
Code: [Select]
:wait
tasklist|find /i "VoiceAttack"
IF "%ERRORLEVEL%"=="1" (
start "" "C:\Program Files\VoiceAttackBeta\VoiceAttack.exe"
GOTO exit
)
GOTO wait
:exit

Restart VoiceAttack
Code: [Select]
Run application '{VA_APPS}\RestartVA.bat' (hidden)
Close window 'VoiceAttack'

The batch file checks whether VoiceAttack is currently running, loops until it's not, and finally starts VoiceAttack again.
The loop is infinite and without added delay, but I've not experienced any issues with it running that way.

If VoiceAttack is running as admin, the batch file also runs as admin, and VoiceAttack will in turn start and run as admin(as a process started by another process runs with the rights of that process, unless explicitly otherwise specified).

Malic

  • Newbie
  • *
  • Posts: 20
Re: Command name (semi)constants
« Reply #10 on: December 03, 2017, 04:52:03 am »
Is this in the live version?

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1484
  • RTFM
Re: Command name (semi)constants
« Reply #11 on: December 03, 2017, 04:57:27 am »
Yes, this is included in VoiceAttack v1.6.8 and up. It's not publicized as there may be undiscovered issues with this feature.