Repository: MycroftAI/mycroft-core

Issue:
Mycroft is too light of a sleeper
After saying "mycroft sleep", the next time he hears "mycroft" he will wakeup (Even if you didn't say "mycroft wakeup".



Discussion:
True dat.

Options:
- Change phrase from "wake up" to "time to wake up"
- Change behavior so "hey mycroft wake up" becomes the recognizer (the old way)
- Verify with externel STT (combined with above)


Resolving patch:
diff --git a/mycroft/client/speech/listener.py b/mycroft/client/speech/listener.py
--- a/mycroft/client/speech/listener.py
+++ b/mycroft/client/speech/listener.py
@@ -199,21 +199,29 @@ def __init__(self):
 
 class RecognizerLoop(pyee.EventEmitter):
     def __init__(self, channels=int(speech_config.get('channels')),
-                 sample_rate=int(speech_config.get('sample_rate')),
+                 rate=int(speech_config.get('sample_rate')),
                  device_index=None,
                  lang=core_config.get('lang')):
         pyee.EventEmitter.__init__(self)
-        self.microphone = MutableMicrophone(sample_rate=sample_rate,
+        self.microphone = MutableMicrophone(sample_rate=rate,
                                             device_index=device_index)
 
         # FIXME - channels are not been used
         self.microphone.CHANNELS = channels
-        self.mycroft_recognizer = LocalRecognizer(sample_rate, lang)
+        self.mycroft_recognizer = self.create_mycroft_recognizer(rate, lang)
         # TODO - localization
-        self.wakeup_recognizer = LocalRecognizer(sample_rate, lang, "wake up")
+        self.wakeup_recognizer = self.create_wakeup_recognizer(rate, lang)
         self.remote_recognizer = ResponsiveRecognizer(self.mycroft_recognizer)
         self.state = RecognizerLoopState()
 
+    @staticmethod
+    def create_mycroft_recognizer(rate, lang):
+        return LocalRecognizer("hey mycroft", "1e-90", rate, lang)
+
+    @staticmethod
+    def create_wakeup_recognizer(rate, lang):
+        return LocalRecognizer("wake up", "1e-10", rate, lang)
+
     def start_async(self):
         self.state.running = True
         queue = Queue()
diff --git a/mycroft/client/speech/local_recognizer.py b/mycroft/client/speech/local_recognizer.py
--- a/mycroft/client/speech/local_recognizer.py
+++ b/mycroft/client/speech/local_recognizer.py
@@ -27,25 +27,25 @@
 
 
 class LocalRecognizer(object):
-    def __init__(self, sample_rate=16000, lang="en-us",
-                 key_phrase="hey mycroft"):
+    def __init__(self, key_phrase, threshold, sample_rate=16000, lang="en-us"):
         self.lang = lang
         self.key_phrase = key_phrase
         self.sample_rate = sample_rate
-        self.configure()
+        self.threshold = threshold
+        self.decoder = Decoder(self.create_config())
 
-    def configure(self):
+    def create_config(self):
         config = Decoder.default_config()
         config.set_string('-hmm', os.path.join(BASEDIR, 'model', self.lang,
                                                'hmm'))
         config.set_string('-dict', os.path.join(BASEDIR, 'model', self.lang,
                                                 'mycroft-en-us.dict'))
         config.set_string('-keyphrase', self.key_phrase)
-        config.set_float('-kws_threshold', float('1e-90'))
+        config.set_float('-kws_threshold', float(self.threshold))
         config.set_float('-samprate', self.sample_rate)
         config.set_int('-nfft', 2048)
         config.set_string('-logfn', '/dev/null')
-        self.decoder = Decoder(config)
+        return config
 
     def transcribe(self, byte_data, metrics=None):
         start = time.time()


Test patch:
diff --git a/test/client/audio_consumer_test.py b/test/client/audio_consumer_test.py
--- a/test/client/audio_consumer_test.py
+++ b/test/client/audio_consumer_test.py
@@ -24,6 +24,7 @@
 from speech_recognition import WavFile, AudioData
 
 from mycroft.client.speech.listener import AudioConsumer, RecognizerLoop
+from mycroft.client.speech.local_recognizer import LocalRecognizer
 from mycroft.client.speech.recognizer_wrapper import (
     RemoteRecognizerWrapperFactory
 )
@@ -59,7 +60,7 @@ def setUp(self):
             self.loop.state,
             self.queue,
             self.loop,
-            self.loop.wakeup_recognizer,
+            LocalRecognizer(self.loop.wakeup_recognizer.key_phrase, "1e-45"),
             self.loop.mycroft_recognizer,
             RemoteRecognizerWrapperFactory.wrap_recognizer(
                 self.recognizer, 'google'))
diff --git a/test/client/local_recognizer_test.py b/test/client/local_recognizer_test.py
--- a/test/client/local_recognizer_test.py
+++ b/test/client/local_recognizer_test.py
@@ -3,7 +3,7 @@
 import os
 from speech_recognition import WavFile
 
-from mycroft.client.speech.local_recognizer import LocalRecognizer
+from mycroft.client.speech.listener import RecognizerLoop
 
 __author__ = 'seanfitz'
 
@@ -12,20 +12,21 @@
 
 class LocalRecognizerTest(unittest.TestCase):
     def setUp(self):
-        self.recognizer = LocalRecognizer()
+        self.recognizer = RecognizerLoop.create_mycroft_recognizer(16000,
+                                                                   "en-us")
 
     def testRecognizerWrapper(self):
         source = WavFile(os.path.join(DATA_DIR, "hey_mycroft.wav"))
         with source as audio:
             hyp = self.recognizer.transcribe(audio.stream.read())
-            assert "mycroft" in hyp.hypstr.lower()
+            assert self.recognizer.key_phrase in hyp.hypstr.lower()
         source = WavFile(os.path.join(DATA_DIR, "mycroft.wav"))
         with source as audio:
             hyp = self.recognizer.transcribe(audio.stream.read())
-            assert "mycroft" in hyp.hypstr.lower()
+            assert self.recognizer.key_phrase in hyp.hypstr.lower()
 
     def testRecognitionInLongerUtterance(self):
         source = WavFile(os.path.join(DATA_DIR, "weather_mycroft.wav"))
         with source as audio:
             hyp = self.recognizer.transcribe(audio.stream.read())
-            assert "mycroft" in hyp.hypstr.lower()
+            assert self.recognizer.key_phrase in hyp.hypstr.lower()