Author Topic: Make VoiceAttack press a key when it recognises ANY speech?  (Read 1508 times)

TheGreyOne

  • Guest
Make VoiceAttack press a key when it recognises ANY speech?
« on: December 04, 2018, 09:33:34 PM »
 I use mumble, discord, teamspeak... any other number of voice-chat programs. What I'd like to do is use VoiceAttack as a *voice recognition* system for "hands-free-push-to-talk" because frankly every single 'voice activity' system in those chat programs has proven to be completely *terrible*

 I don't want to have to input a specific keyword, just have VoiceAttack immediately hold down a key (and stop after say 1/2 a second of silence) when it recognizes *any* speech whatsoever.

--

There are quite a few nice "almost" options in the forum here, but none quite do what I'm after (that I've seen.)

Is what I'm wanting currently possible?

Gary

  • Administrator
  • Hero Member
  • *****
  • Posts: 2832
Re: Make VoiceAttack press a key when it recognises ANY speech?
« Reply #1 on: December 04, 2018, 10:24:10 PM »
Hi, there.

Out of the box, there is no way to recognize just speech and invoke an event (trigger).  However, there are ways to get the audio level ({STATE_AUDIOLEVEL}) or speech active status ({STATE_SPEECHACTIVE}) at any time if you are willing to build a plugin or inline function that monitors that level and reacts accordingly (plugins and inline functions are the way VA users can extend the functionality of VA to suit specific needs).

TheGreyOne

  • Guest
Re: Make VoiceAttack press a key when it recognises ANY speech?
« Reply #2 on: December 05, 2018, 12:51:41 AM »
Hmm, thanks for that. I'll take a look at what my options are on that front. :D

TheGreyOne

  • Guest
Re: Make VoiceAttack press a key when it recognises ANY speech?
« Reply #3 on: December 05, 2018, 02:21:17 AM »
So I experimented with writing up a small inline command.

It's terribly buggy, but it does work (mostly!)

It executes an arbitrary external command (VOICE_ACTIVATED_TOGGLE), so you can have it send key presses to specific windows of your choosing etc.

There's a couple of "todo"s that I couldn't work out how to solve immediately (I'm probably not finding the 'right' documentation sadly.)

If anyone wants to use it (edit: as a base for a fixed "proper" version, or better; point out my failures so I can fix them :D ), feel free.

Code: [Select]
using System;
using System.Threading;
using System.Diagnostics;

public class VAInline
{
public void main()
{
bool buttonPressed = false;

try // avoid any weird exceptions causing problems.
{
// todo: get this time from VA?
float timeToKeepRecording = 0.3f; // time in seconds after our last recognised speech, that we keep the 'push to talk' key pressed.

Stopwatch sw = new Stopwatch();

bool exit = false;

VA.WriteToLog("Beginning Voice Toggle","green");

while(!exit)
{
if(exit || VA.Stopped) // if we or VA wants us to stop, abandon our task.
break;

if(VA.ParseTokens("{STATE_SPEECHACTIVE}") == "1") // we currently hear speech:
{
if(buttonPressed == true)
{
// restart our timer.
sw.Stop();
sw.Reset();
sw.Start();
}
else
{
// todo: just directly press down button combo?
// press down our button
if(VA.CommandExists("VOICE_ACTIVATED_TOGGLE"))
{
VA.ExecuteCommand("VOICE_ACTIVATED_TOGGLE");
VA.WriteToLog("Voice Toggle Enabled","green");
}
buttonPressed = true;
sw.Start();
}
}
else // we currently do NOT hear speech:
{
// if we are current holding down our button, and we've not heard new speech in a while
if(buttonPressed == true && sw.Elapsed.Seconds > timeToKeepRecording)
{
// then stop our button press, and stop our timer.
if(VA.CommandExists("VOICE_ACTIVATED_TOGGLE"))
{
VA.ExecuteCommand("VOICE_ACTIVATED_TOGGLE");
VA.WriteToLog("Voice Toggle Disabled","green");
}
buttonPressed = false;
sw.Stop();
}
}

// don't do anything for a little while... no need to waste cpu cycles.
Thread.Sleep(10);
}
}
catch
{
VA.WriteToLog("Voice Toggle Failed","red");

// release our button
if(buttonPressed == true && VA.CommandExists("VOICE_ACTIVATED_TOGGLE"))
VA.ExecuteCommand("VOICE_ACTIVATED_TOGGLE");
}

VA.WriteToLog("Voice Toggle Exitin","purple");
}
}

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4782
  • RTFM
Re: Make VoiceAttack press a key when it recognises ANY speech?
« Reply #4 on: December 05, 2018, 05:35:09 AM »
I made some modifications; Ended up with this:

VOICE_ACTIVATED_TOGGLE [true;false]
Code: [Select]
Begin Text Compare : [{CMDACTION}] Equals 'Plugin'
    Do nothing (ignore command)
    Begin Text Compare : [{CMD}] Ends With 'on'
        Press down Left Alt key
    Else
        Release Left Alt key
    End Condition
Else
    Set integer [~PTTHoldTime] value to 300
    Inline C# Function: Voice Toggle
End Condition


Where "Voice Toggle" contains:
Code: [Select]
using System;
using System.Threading;
using System.Diagnostics;

public class VAInline
{
bool buttonPressed = false;

public void main()
{
//Check if the required command exists, otherwise exit
if(!VA.CommandExists("VOICE_ACTIVATED_TOGGLE true") || !VA.CommandExists("VOICE_ACTIVATED_TOGGLE false"))
{
VA.WriteToLog("Voice Toggle Error: Command 'VOICE_ACTIVATED_TOGGLE [true;false]' does not exist, startup aborted","red");
return;
}

try // avoid any weird exceptions causing problems.
{
float timeToKeepRecording = VA.GetInt("~PTTHoldTime") ?? 300; // time in seconds after our last recognised speech, that we keep the 'push to talk' key pressed. Default is 300ms if not set in the VoiceAttack command.

Stopwatch sw = new Stopwatch();
bool speechDetected = false;

VA.WriteToLog("Beginning Voice Toggle","green");

while(true)
{
if(VA.Stopped) // if VA wants us to stop, abandon our task.
{
break;
}

if(VA.ParseTokens("{STATE_SPEECHACTIVE}") == "1") // we currently hear speech:
{
speechDetected = true;

if (!buttonPressed)
{
pushToTalk(true);
}
}
else // we currently do NOT hear speech:
{
if (speechDetected && !sw.IsRunning)
{
sw.Start();
speechDetected = false;
}
else if (buttonPressed && sw.ElapsedMilliseconds > timeToKeepRecording)
{
pushToTalk(false);
sw.Reset();
}
}

// don't do anything for a little while... no need to waste cpu cycles.
Thread.Sleep(10);
}
}
catch(Exception e)
{
VA.WriteToLog("Voice Toggle Exception: " + e,"red");
}
finally
{
pushToTalk(false);
VA.WriteToLog("Voice Toggle Exiting","purple");
}
}

void pushToTalk(bool targetState)
{
VA.ExecuteCommand("VOICE_ACTIVATED_TOGGLE " + targetState);
VA.WriteToLog("Voice Toggle " + (targetState ? "Enabled" : "Disabled"),"green");
buttonPressed = targetState;
}
}


I noticed you're using a toggle command, which means that state the push-to-talk key ends up in cannot be guaranteed, so this instead explicitly sets that state.

TheGreyOne

  • Guest
Re: Make VoiceAttack press a key when it recognises ANY speech?
« Reply #5 on: December 05, 2018, 06:17:46 AM »
Ah, perfect! I wasn't sure how to build the explicit command for holding/releasing the key, which definitely was causing me bugs on my end.

Thank you very much for the improvements. I'll definitely play around with it a little when I've got some more free time.