Skip to content

Commit

Permalink
Merge pull request #532 from alexylem/beta
Browse files Browse the repository at this point in the history
Beta
  • Loading branch information
alexylem authored Apr 9, 2017
2 parents 6a195e7 + 9d19a4d commit 61e6e72
Show file tree
Hide file tree
Showing 10 changed files with 418 additions and 67 deletions.
1 change: 1 addition & 0 deletions jarvis-config-default.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ recorder="sox"
send_usage_stats=true
separator=""
show_commands=true
snowboy_checkticks=true
snowboy_sensitivity="0.4"
tmp_folder="/tmp"
trigger=""
Expand Down
7 changes: 5 additions & 2 deletions jarvis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ show_help () { cat <<EOF
EOF
}

headline="NEW: Try snowboy recorder in Settings > Audio > Recorder"
headline="NEW: Improve snowboy reaction with Settings > Voice Reco > Snowboy settings > Check ticks"

# Move to Jarvis directory
export jv_dir="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
Expand Down Expand Up @@ -130,6 +130,7 @@ configure () {
'send_usage_stats'
'separator'
'show_commands'
'snowboy_checkticks'
'snowboy_sensitivity'
'snowboy_token'
'tmp_folder'
Expand Down Expand Up @@ -185,7 +186,8 @@ configure () {
"en_GB (English)"
"es_ES (Español)"
"fr_FR (Français)"
"it_IT (Italiano)")
"it_IT (Italiano)"
"pt_PT (Português)")
language="$(dialog_select "Language" options[@] "$language")"
language="${language% *}" # "fr_FR (Français)" => "fr_FR"
;;
Expand Down Expand Up @@ -274,6 +276,7 @@ configure () {
send_usage_stats) eval "$1=\"$(dialog_yesno "Send anynomous usage statistics to help improving Jarvis" "${!1}")\"";;
separator) eval "$1=\"$(dialog_input "Separator for multiple commands at once\nex: 'then' or empty to disable" "${!1}")\"";;
show_commands) eval "$1=\"$(dialog_yesno "Show commands on startup and possible answers" "${!1}")\"";;
snowboy_checkticks) eval "$1=\"$(dialog_yesno "Check ticks?\nReduce false positives but slower to react" "${!1}")\"";;
snowboy_sensitivity) eval "$1=\"$(dialog_input "Snowboy sensitivity from 0 (strict) to 1 (permissive)\nRecommended value: 0.4" "${!1}")\"";;
snowboy_token) eval "$1=\"$(dialog_input "Snowboy token\nGet one at: https://snowboy.kitt.ai (in profile settings)" "${!1}" true)\"";;
tmp_folder) eval "$1=\"$(dialog_input "Cache folder" "${!1}")\"";;
Expand Down
135 changes: 76 additions & 59 deletions stt_engines/snowboy/main.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import maindecoder
import sys
import signal
# import librairies
import maindecoder_sox as maindecoder # snowboy decoder
import sys # exit
import signal # catch SIGINT
import argparse # program arguments
#import time # perf measurement

# Demo code for listening two hotwords at the same time

# hide alsa errors
from ctypes import *
ERROR_HANDLER_FUNC = CFUNCTYPE(None, c_char_p, c_int, c_char_p, c_int, c_char_p)
def py_error_handler(filename, line, function, err, fmt):
pass
c_error_handler = ERROR_HANDLER_FUNC(py_error_handler)
try:
asound = cdll.LoadLibrary('libasound.so.2')
asound.snd_lib_error_set_handler(c_error_handler)
except Exception as e:
pass
# hide alsa errors # not anymore needed with sox?
# from ctypes import *
# ERROR_HANDLER_FUNC = CFUNCTYPE(None, c_char_p, c_int, c_char_p, c_int, c_char_p)
# def py_error_handler(filename, line, function, err, fmt):
# pass
# c_error_handler = ERROR_HANDLER_FUNC(py_error_handler)
# try:
# asound = cdll.LoadLibrary('libasound.so.2')
# asound.snd_lib_error_set_handler(c_error_handler)
# except Exception as e:
# pass

interrupted = False


def signal_handler(signal, frame):
global interrupted
interrupted = True
Expand All @@ -28,48 +28,65 @@ def interrupt_callback():
return interrupted

def detected_callback(modelid):
#global detector #makes it slower to react
#detector.terminate() #makes it slower to react
global detector
detector.terminate() #makes it 0.1 sec slower to react
#print "time_finished", time.time()
sys.exit(modelid+10) # main.sh substracts 10

if len(sys.argv) < 3:
print("Error: need to specify the sensitivity and at least one model")
print("Usage: python main.py 0.5 resources/model1.pmdl resources/model2.pmdl [...]")
sys.exit(-1)

# capture SIGINT signal, e.g., Ctrl+C
signal.signal(signal.SIGINT, signal_handler)

models = sys.argv[2:]
nbmodel = len(models)
callbacks = []
for i in range(1,nbmodel+1):
callbacks.append(lambda i=i: detected_callback(i))
if __name__ == "__main__":
# capture SIGINT signal, e.g., Ctrl+C
signal.signal(signal.SIGINT, signal_handler)

# arg parser
parser = argparse.ArgumentParser()
parser.add_argument('-m','--models', nargs='+', help='<Required> list of models', required=True)
parser.add_argument('-s','--sensitivity', help='sensitivity', default='0.4')
parser.add_argument('-g','--gain', help='audio gain', type=int, default=0)
parser.add_argument('-t', '--ticks', help='check ticks', action='store_true')
args = parser.parse_args()

# retrieve arguments
#models = sys.argv[2:]
models=args.models
nbmodel = len(models)
sensitivity = args.sensitivity

# if len(sys.argv) < 3:
# print("Error: need to specify the sensitivity and at least one model")
# print("Usage: python main.py 0.5 resources/model1.pmdl resources/model2.pmdl [...]")
# sys.exit(-1)

# build array of callbacks by model
callbacks = []
for i in range(1,nbmodel+1):
callbacks.append(lambda i=i: detected_callback(i))

# build array of sensitivities by model
sensitivities = [sensitivity]*nbmodel

# build array of ticks
if args.ticks:
# a tick is the sleep time of snowboy
# [ min silence ticks before detection,
# max voice ticks before detection, - "jarvis" itself
# max voice ticks after detection - "ss" of "Jarvisss"
# min silence ticks after detection ] - -1 for immediate reaction
ticks = [ 2, 20, 5, -1 ] #TODO get from jarvis as user settings
else:
ticks = [ -1, -1, -1, -1 ]

# initiatlize decoder
detector = maindecoder.JarvisHotwordDetector(
models,
sensitivity=sensitivities,
audio_gain=args.gain,
trigger_ticks=ticks)

sensitivity = sys.argv[1]
sensitivities = [sensitivity]*nbmodel
# Trigger ticks:
# a tick is the sleep time of snowboy - argument of start()
# [0] ticks_silence_before_detect:
# min silence ticks before detection
# [1] param ticks_voice_before_detect:
# max voice ticks before detection
# [2] ticks_voice_after_detect:
# max voice ticks after detection
# [3] ticks_silence_after_detect:
# min silence ticks after detection
trigger_ticks = [ 2, 20, 5, -1 ]

detector = maindecoder.JarvisHotwordDetector(
models,
sensitivity=sensitivities,
trigger_ticks=trigger_ticks)

# main loop
# make sure you have the same numbers of callbacks and models
detector.start(detected_callback=callbacks,
interrupt_check=interrupt_callback,
sleep_time=0.03)

detector.terminate()
sys.exit(-1)
# run decoder
detector.start(detected_callback=callbacks,
interrupt_check=interrupt_callback,
sleep_time=0.03)

# should not reach here, issue occured
detector.terminate()
sys.exit(-1)
7 changes: 6 additions & 1 deletion stt_engines/snowboy/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,12 @@ _snowboy_STT () {
fi;

printf $_gray
eval $timeout python stt_engines/snowboy/main.py $snowboy_sensitivity $smodels $quiet #TODO on mac: WARNING: 140: This application, or a library it uses, is using the deprecated Carbon Component Manager for hosting Audio Units. Support for this will be removed in a future release. Also, this makes the host incompatible with version 3 audio units. Please transition to the API's in AudioComponent.h.
eval $timeout python stt_engines/snowboy/main.py \
--models $smodels \
--sensitivity $snowboy_sensitivity \
--gain $gain \
$( $snowboy_checkticks && echo "--tick" ) \
$quiet #TODO on mac: WARNING: 140: This application, or a library it uses, is using the deprecated Carbon Component Manager for hosting Audio Units. Support for this will be removed in a future release. Also, this makes the host incompatible with version 3 audio units. Please transition to the API's in AudioComponent.h.
local retcode=$?
printf $_reset
[ $retcode -eq 124 ] && return 124 # timeout
Expand Down
3 changes: 1 addition & 2 deletions stt_engines/snowboy/maindecoder.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python

import snowboydecoder
import snowboydetect
import pyaudio
Expand Down Expand Up @@ -205,7 +204,7 @@ def start(self, detected_callback=snowboydecoder.play_audio_file,
if tticks[0] != -1 or tticks[1] != -1 or w_ticks_onsilence != False:
w_ticks = True
callback = None

while True:
if interrupt_check():
logger.debug("detect voice break")
Expand Down
Loading

0 comments on commit 61e6e72

Please sign in to comment.