Browse Source

完善snowboy_wakeup代码

corvin 5 years ago
parent
commit
ede6cf1375
48 changed files with 933 additions and 1074 deletions
  1. 28 0
      catkin_ws/src/snowboy_wakeup/.gitignore
  2. 3 0
      catkin_ws/src/snowboy_wakeup/.gitmodules
  3. 17 0
      catkin_ws/src/snowboy_wakeup/.travis.yml
  4. 31 71
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/README.md
  5. 2 7
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/README_ZH_CN.md
  6. 0 10
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/binding.gyp
  7. 0 22
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/examples/C++/Makefile
  8. 1 3
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/examples/C++/demo.cc
  9. 0 4
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/examples/C++/demo2.cc
  10. 0 20
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/examples/C/Makefile
  11. 0 2
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/examples/C/demo.c
  12. 3 27
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/examples/Python/snowboydecoder.py
  13. 3 27
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/examples/Python3/snowboydecoder.py
  14. 1 7
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/include/snowboy-detect.h
  15. BIN
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/lib/aarch64-ubuntu1604/libsnowboy-detect.a
  16. BIN
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/lib/android/armv7a/libsnowboy-detect.a
  17. BIN
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/lib/android/armv8-aarch64/libsnowboy-detect.a
  18. BIN
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/lib/ios/libsnowboy-detect.a
  19. BIN
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/lib/osx/libsnowboy-detect.a
  20. BIN
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/lib/rpi/libsnowboy-detect.a
  21. 2 1
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/package.json
  22. BIN
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/ding.wav
  23. BIN
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/dong.wav
  24. BIN
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/models/computer.umdl
  25. BIN
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/models/hey_extreme.umdl
  26. BIN
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/models/jarvis.umdl
  27. BIN
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/models/neoya.umdl
  28. BIN
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/models/subex.umdl
  29. BIN
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/models/view_glass.umdl
  30. BIN
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/snowboy.wav
  31. 0 30
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/scripts/install_swig.sh
  32. 0 73
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/swig/Python/Makefile
  33. 0 77
      catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/swig/Python3/Makefile
  34. 78 175
      catkin_ws/src/snowboy_wakeup/CMakeLists.txt
  35. 419 0
      catkin_ws/src/snowboy_wakeup/cmake_modules/FindBLAS.cmake
  36. 0 226
      catkin_ws/src/snowboy_wakeup/include/snowboy-detect.h
  37. 53 0
      catkin_ws/src/snowboy_wakeup/include/snowboy_wakeup/hotword_detector.h
  38. 24 0
      catkin_ws/src/snowboy_wakeup/launch/snowboy_wakeup.launch
  39. 7 55
      catkin_ws/src/snowboy_wakeup/package.xml
  40. BIN
      catkin_ws/src/snowboy_wakeup/resources/corvin.pmdl
  41. BIN
      catkin_ws/src/snowboy_wakeup/resources/ding.wav
  42. BIN
      catkin_ws/src/snowboy_wakeup/resources/dong.wav
  43. BIN
      catkin_ws/src/snowboy_wakeup/resources/libsnowboy-detect.a
  44. BIN
      catkin_ws/src/snowboy_wakeup/resources/models/snowboy.umdl
  45. BIN
      catkin_ws/src/snowboy_wakeup/resources/wakeup_alert.mp3
  46. 63 0
      catkin_ws/src/snowboy_wakeup/src/hotword_detector.cpp
  47. 198 0
      catkin_ws/src/snowboy_wakeup/src/hotword_detector_node.cpp
  48. 0 237
      catkin_ws/src/snowboy_wakeup/src/snowboy_wakeup.cpp

+ 28 - 0
catkin_ws/src/snowboy_wakeup/.gitignore

@@ -0,0 +1,28 @@
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app

+ 3 - 0
catkin_ws/src/snowboy_wakeup/.gitmodules

@@ -0,0 +1,3 @@
+[submodule "3rdparty/snowboy"]
+	path = 3rdparty/snowboy
+	url = https://github.com/Kitt-AI/snowboy.git

+ 17 - 0
catkin_ws/src/snowboy_wakeup/.travis.yml

@@ -0,0 +1,17 @@
+sudo: true
+
+language: cpp
+
+services:
+  - docker
+
+before_install:
+  - wget https://raw.githubusercontent.com/tue-robotics/tue-env/master/ci/install-package.sh
+  - wget https://raw.githubusercontent.com/tue-robotics/tue-env/master/ci/build-package.sh
+  - export PACKAGE=${TRAVIS_REPO_SLUG#*/}
+
+install:
+  - bash install-package.sh --package=$PACKAGE --branch=$TRAVIS_BRANCH --commit=$TRAVIS_COMMIT --pullrequest=$TRAVIS_PULL_REQUEST
+
+script: 
+  - bash build-package.sh --package=$PACKAGE

+ 31 - 71
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/README.md

@@ -14,83 +14,60 @@ Version: 1.3.0 (2/19/2018)
 
 ## Alexa support
 
-Snowboy now brings hands-free experience to the [Alexa AVS sample app](https://github.com/alexa/avs-device-sdk/wiki/Raspberry-Pi-Quick-Start-Guide-with-Script) on Raspberry Pi! See more info below regarding the performance and how you can use other hotword models. The following instructions currently support AVS sdk Version 1.12.1.
+Snowboy now brings hands-free experience to the [Alexa AVS sample app](https://github.com/alexa/alexa-avs-sample-app) on Raspberry Pi! See more info below regarding the performance and how you can use other hotword models.
 
 **Performance**
 
 The performance of hotword detection usually depends on the actual environment, e.g., is it used with a quality microphone, is it used on the street, in a kitchen, or is there any background noise, etc. So we feel it is best for the users to evaluate it in their real environment. For the evaluation purpose, we have prepared an Android app which can be installed and run out of box: [SnowboyAlexaDemo.apk](https://github.com/Kitt-AI/snowboy/raw/master/resources/alexa/SnowboyAlexaDemo.apk) (please uninstall any previous versions first if you have installed this app before). 
 
-**Kittai KWD Engine**
-
-* Set up [Alexa AVS sample app](https://github.com/alexa/avs-device-sdk/wiki/Raspberry-Pi-Quick-Start-Guide-with-Script) following the official AVS instructions
-
-* Apply patch to replace the Sensory KWD engine with Kittai engine
-```
-# Copy the patch file to the root directory of Alexa AVS sample app. Please replace $ALEXA_AVS_SAMPLE_APP_PATH with the actual path where you
-# cloned the Alexa AVS sample app repository, and replace $SNOWBOY_ROOT_PATH with the actual path where you clone the Snowboy repository
-cd $ALEXA_AVS_SAMPLE_APP_PATH
-cp $SNOWBOY_PATH/resource/alexa/alexa-avs-sample-app/avs-kittai.patch ./
-
-# Apply the patch, this will modify the scripts setup.sh and pi.sh
-patch < avs-kittai.patch
-```
-
-* Re-compile the avs-device-sdk and sample app
-```
-sudo bash setup.sh config.json
-```
-
-* Run the sample app
-```
-sudo bash startsample.sh
-```
-
-Here is a [demo video](https://www.youtube.com/watch?v=wiLEr6TeE58) for how to use Snowboy hotword engine in Alexa Voice Service.
-
 **Personal model**
 
 * Create your personal hotword model through our [website](https://snowboy.kitt.ai) or [hotword API](https://snowboy.kitt.ai/api/v1/train/)
 
+* Replace the hotword model in [Alexa AVS sample app](https://github.com/alexa/alexa-avs-sample-app) (after installation) with your personal model
 
-* Put your personal model in [snowboy/resources](https://github.com/Kitt-AI/snowboy/tree/master/resources)
 ```
-# Please put YOUR_PERSONAL_MODEL.pmdl in $ALEXA_AVS_SAMPLE_APP_PATH/third-party/snowboy/resources,
-# and $ALEXA_AVS_SAMPLE_APP_PATH with the actual path where you put the Alexa AVS sample app repository.
-
-cp YOUR_PERSONAL_MODEL.pmdl $ALEXA_AVS_SAMPLE_APP_PATH/third-party/snowboy/resources/
-
+# Please replace YOUR_PERSONAL_MODEL.pmdl with the personal model you just
+# created, and $ALEXA_AVS_SAMPLE_APP_PATH with the actual path where you
+# cloned the Alexa AVS sample app repository.
+cp YOUR_PERSONAL_MODEL.pmdl $ALEXA_AVS_SAMPLE_APP_PATH/samples/wakeWordAgent/ext/resources/alexa.umdl
 ```
 
-* Replace the model name 'alexa.umdl' with your personal model name, update `KITT_AI_SENSITIVITY`, set `KITT_AI_APPLY_FRONT_END_PROCESSING` to `false` in the [Alexa AVS sample app code](https://github.com/alexa/avs-device-sdk/blob/master/KWD/KWDProvider/src/KeywordDetectorProvider.cpp) and re-compile
+* Set `APPLY_FRONTEND` to `false` and update `SENSITIVITY` in the [Alexa AVS sample app code](https://github.com/alexa/alexa-avs-sample-app/blob/master/samples/wakeWordAgent/src/KittAiSnowboyWakeWordEngine.cpp) and re-compile
+
 ```
-# Modify $ALEXA_AVS_SAMPLE_APP_PATH/avs-device-sdk/blob/master/KWD/KWDProvider/src/KeywordDetectorProvider.cpp:
-#     Replace the model name 'alexa.umdl' with your personal model name 'YOUR_PERSONAL_MODEL.pmdl' at line 52
-#     Update `KITT_AI_SENSITIVITY` at line 26
-#     Set `KITT_AI_APPLY_FRONT_END_PROCESSING` to `false` at line 32
-sudo bash setup.sh config.json
+# Please replace $ALEXA_AVS_SAMPLE_APP_PATH with the actual path where you
+# cloned the Alexa AVS sample app repository.
+cd $ALEXA_AVS_SAMPLE_APP_PATH/samples/wakeWordAgent/src/
+
+# Modify KittAiSnowboyWakeWordEngine.cpp and update SENSITIVITY at line 28.
+# Modify KittAiSnowboyWakeWordEngine.cpp and set APPLY_FRONTEND to false at
+# line 30.
+make
 ```
 
 * Run the wake word agent with engine set to `kitt_ai`!
 
-Here is a [demo video](https://www.youtube.com/watch?v=9Bj8kdfwG7I) for how to use a personal model in Alexa Voice Service.
-
 **Universal model**
 
-* Put your personal model in [snowboy/resources](https://github.com/Kitt-AI/snowboy/tree/master/resources)
+* Replace the hotword model in [Alexa AVS sample app](https://github.com/alexa/alexa-avs-sample-app) (after installation) with your universal model
+
+```
+# Please replace YOUR_UNIVERSAL_MODEL.umdl with the personal model you just
+# created, and $ALEXA_AVS_SAMPLE_APP_PATH with the actual path where you
+# cloned the Alexa AVS sample app repository.
+cp YOUR_UNIVERSAL_MODEL.umdl $ALEXA_AVS_SAMPLE_APP_PATH/samples/wakeWordAgent/ext/resources/alexa.umdl
 ```
-# Please put YOUR_UNIVERSAL_MODEL.umdl in $ALEXA_AVS_SAMPLE_APP_PATH/third-party/snowboy/resources,
-# and $ALEXA_AVS_SAMPLE_APP_PATH with the actual path where you put the Alexa AVS sample app repository.
 
-cp YOUR_UNIVERSAL_MODEL.umdl $ALEXA_AVS_SAMPLE_APP_PATH/third-party/snowboy/resources/
+* Update `SENSITIVITY` in the [Alexa AVS sample app code](https://github.com/alexa/alexa-avs-sample-app/blob/master/samples/wakeWordAgent/src/KittAiSnowboyWakeWordEngine.cpp) and re-compile
 
 ```
+# Please replace $ALEXA_AVS_SAMPLE_APP_PATH with the actual path where you
+# cloned the Alexa AVS sample app repository.
+cd $ALEXA_AVS_SAMPLE_APP_PATH/samples/wakeWordAgent/src/
 
-* Replace the model name 'alexa.umdl' with your universal model name, update `KITT_AI_SENSITIVITY` in the [Alexa AVS sample app code](https://github.com/alexa/avs-device-sdk/blob/master/KWD/KWDProvider/src/KeywordDetectorProvider.cpp) and re-compile
-```
-# Modify $ALEXA_AVS_SAMPLE_APP_PATH/avs-device-sdk/blob/master/KWD/KWDProvider/src/KeywordDetectorProvider.cpp:
-#     Replace the model name 'alexa.umdl' with your universal model name 'YOUR_UNIVERSAL_MODEL.umdl' at line 52
-#     Update `KITT_AI_SENSITIVITY` at line 26
-sudo bash setup.sh config.json
+# Modify KittAiSnowboyWakeWordEngine.cpp and update SENSITIVITY at line 28.
+make
 ```
 
 * Run the wake word agent with engine set to `kitt_ai`!
@@ -190,11 +167,6 @@ Here is the list of the models, and the parameters that you have to use for them
 * **resources/models/snowboy.umdl**: Universal model for the hotword "Snowboy". Set SetSensitivity to 0.5 and ApplyFrontend to false.
 * **resources/models/jarvis.umdl**: Universal model for the hotword "Jarvis" (https://snowboy.kitt.ai/hotword/29). It has two different models for the hotword Jarvis, so you have to use two sensitivites. Set sensitivities to "0.8,0.80" and ApplyFrontend to true.
 * **resources/models/smart_mirror.umdl**: Universal model for the hotword "Smart Mirror" (https://snowboy.kitt.ai/hotword/47). Set sensitivity to Sensitivity to 0.5, and ApplyFrontend to false.
-* **resources/models/subex.umdl**: Universal model for the hotword "Subex" (https://snowboy.kitt.ai/hotword/22014). Set sensitivity to Sensitivity to 0.5, and ApplyFrontend to true.
-* **resources/models/neoya.umdl**: Universal model for the hotword "Neo ya" (https://snowboy.kitt.ai/hotword/22171). It has two different models for the hotword "Neo ya", so you have to use two sensitivites. Set sensitivities to "0.7,0.7", and ApplyFrontend to true.
-* **resources/models/hey_extreme.umdl**: Universal model for the hotword "Hey Extreme" (https://snowboy.kitt.ai/hotword/15428). Set sensitivity to Sensitivity to 0.6, and ApplyFrontend to true.
-* **resources/models/computer.umdl**: Universal model for the hotword "Computer" (https://snowboy.kitt.ai/hotword/46). Set sensitivity to Sensitivity to 0.6, and ApplyFrontend to true.
-* **resources/models/view_glass.umdl**: Universal model for the hotword "View Glass" (https://snowboy.kitt.ai/hotword/7868). Set Sensitivity to 0.7, and ApplyFrontend to true.
 
 ## Precompiled node module
 
@@ -244,23 +216,11 @@ Make sure that you can record audio with your microphone:
 
 ### Ubuntu/Raspberry Pi/Pine64/Nvidia Jetson TX1/Nvidia Jetson TX2
 
-First `apt-get` install `sox`, `portaudio` and its Python binding `pyaudio`:
+First `apt-get` install `swig`, `sox`, `portaudio` and its Python binding `pyaudio`:
 
-    sudo apt-get install python-pyaudio python3-pyaudio sox
+    sudo apt-get install swig3.0 python-pyaudio python3-pyaudio sox
     pip install pyaudio
     
-Compile a supported swig version (3.0.10 or above)
-
-    wget http://downloads.sourceforge.net/swig/swig-3.0.10.tar.gz
-    sudo apt-get install libpcre3 libpcre3-dev
-    ./configure --prefix=/usr                  \
-            --without-clisp                    \
-            --without-maximum-compile-warnings &&
-    make
-    make install &&
-    install -v -m755 -d /usr/share/doc/swig-3.0.10 &&
-    cp -v -R Doc/* /usr/share/doc/swig-3.0.10
-    
 Then install the `atlas` matrix computing library:
 
     sudo apt-get install libatlas-base-dev

+ 2 - 7
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/README_ZH_CN.md

@@ -156,13 +156,8 @@ Snowboy底层库由C++写成,通过swig被封装成能在多种操作系统和
 
 * **resources/alexa/alexa-avs-sample-app/alexa.umdl**:这个是为[Alexa AVS sample app](https://github.com/alexa/alexa-avs-sample-app)优化过的唤醒词为“Alexa”的通用模型,将`SetSensitivity`设置为`0.6`,并将`ApplyFrontend`设置为true。当`ApplyFrontend`设置为`true`时,这是迄今为止我们公开发布的最好的“Alexa”的模型。
 * **resources/models/snowboy.umdl**:唤醒词为“snowboy”的通用模型。将`SetSensitivity`设置为`0.5`,`ApplyFrontend`设置为`false`。
-* **resources/models/jarvis.umdl**: 唤醒词为“Jarvis” (https://snowboy.kitt.ai/hotword/29) 的通用模型,其中包含了对应于“Jarvis”的两个唤醒词模型,所以需要设置两个`sensitivity`。将`SetSensitivity`设置为`0.8,0.8`,`ApplyFrontend`设置为`true`。
-* **resources/models/smart_mirror.umdl**: 唤醒词为“Smart Mirror” (https://snowboy.kitt.ai/hotword/47) 的通用模型。将`SetSensitivity`设置为`0.5`,`ApplyFrontend`设置为`false`。
-* **resources/models/subex.umdl**: 唤醒词为“Subex”(https://snowboy.kitt.ai/hotword/22014) 的通用模型。将`SetSensitivity`设置为`0.5`,`ApplyFrontend`设置为`true`。
-* **resources/models/neoya.umdl**: 唤醒词为“Neo ya”(https://snowboy.kitt.ai/hotword/22171) 的通用模型。其中包含了对应于“Neo ya”的两个>唤醒词模型,所以需要设置两个`sensitivity`。将`SetSensitivity`设置为`0.7,0.7`,`ApplyFrontend`设置为`true`。
-* **resources/models/hey_extreme.umdl**: 唤醒词为“Hey Extreme” (https://snowboy.kitt.ai/hotword/15428)的通用模型。将`SetSensitivity`设置为`0.6`,`ApplyFrontend`设置为`true`。
-* **resources/models/computer.umdl**: 唤醒词为“Computer” (https://snowboy.kitt.ai/hotword/46) 的通用模型。将`SetSensitivity`设置为`0.6`,`ApplyFrontend`设置为`true`。
-* **resources/models/view_glass.umdl**: 唤醒词为“View Glass” (https://snowboy.kitt.ai/hotword/7868) 的通用模型。将`SetSensitivity`设置为`0.7`,`ApplyFrontend`设置为`true`。
+* **resources/models/jarvis.umdl**: 唤醒词为“Jarvis” (https://snowboy.kitt.ai/hotword/29)的通用模型,其中包含了对应于“Jarvis”的两个唤醒词模型,所以需要设置两个`sensitivity`。将`SetSensitivity`设置为`0.8,0.8`,`ApplyFrontend`设置为`true`。
+* **resources/models/smart_mirror.umdl**: 唤醒词为“Smart Mirror” (https://snowboy.kitt.ai/hotword/47)的通用模型。将`SetSensitivity`设置为`0.5`,`ApplyFrontend`设置为`false`。
 
 ## 预编译node模块
 

+ 0 - 10
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/binding.gyp

@@ -31,16 +31,6 @@
                         '<(module_root_dir)/lib/rpi/libsnowboy-detect.a',
                     ]
                 }
-            }],
-            ['OS=="linux" and target_arch=="arm64"', {
-                'link_settings': {
-                    'ldflags': [
-                        '-Wl,--no-as-needed',
-                    ],
-                    'libraries': [
-                        '<(module_root_dir)/lib/aarch64-ubuntu1604/libsnowboy-detect.a',
-                    ]
-                }
             }]
         ],
         'cflags': [

+ 0 - 22
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/examples/C++/Makefile

@@ -1,22 +0,0 @@
-include demo.mk
-
-BINFILES = demo demo2
-
-all: $(BINFILES)
-
-%.a:
-	$(MAKE) -C ${@D} ${@F}
-
-$(BINFILES): $(PORTAUDIOLIBS) $(SNOWBOYDETECTLIBFILE)
-
-$(PORTAUDIOLIBS):
-	@-./install_portaudio.sh
-
-clean:
-	-rm -f *.o *.a $(BINFILES)
-
-depend:
-	-$(CXX) -M $(CXXFLAGS) *.cc > .depend.mk
-
-# Putting "-" so no error messages.
--include .depend.mk

+ 1 - 3
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/examples/C++/demo.cc

@@ -11,7 +11,7 @@
 #include <string>
 #include <vector>
 
-#include "../../include/snowboy-detect.h"
+#include "include/snowboy-detect.h"
 
 int PortAudioCallback(const void* input,
                       void* output,
@@ -207,13 +207,11 @@ int main(int argc, char* argv[]) {
   std::string model_filename = "resources/models/snowboy.umdl";
   std::string sensitivity_str = "0.5";
   float audio_gain = 1;
-  bool apply_frontend = false;
 
   // Initializes Snowboy detector.
   snowboy::SnowboyDetect detector(resource_filename, model_filename);
   detector.SetSensitivity(sensitivity_str);
   detector.SetAudioGain(audio_gain);
-  detector.ApplyFrontend(apply_frontend);
 
   // Initializes PortAudio. You may use other tools to capture the audio.
   PortAudioWrapper pa_wrapper(detector.SampleRate(),

+ 0 - 4
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/examples/C++/demo2.cc

@@ -5,8 +5,6 @@
 #define resource_filename "resources/common.res"
 #define model_filename "resources/models/snowboy.umdl"
 #define sensitivity_str "0.5"
-#define audio_gain 1.0
-#define apply_frontend false
 
 struct wavHeader { //44 byte HEADER only
   char  RIFF[4];
@@ -138,8 +136,6 @@ int main(int argc, char * argv[]) {
   // Initializes Snowboy detector.
   snowboy::SnowboyDetect detector(resource_filename, model_filename);
   detector.SetSensitivity(sensitivity_str);
-  detector.SetAudioGain(audio_gain);
-  detector.ApplyFrontend(apply_frontend);
 
   int result = detector.RunDetection(&data_buffer[0], fsize/sizeof(short));
   std::cout << ">>>>> Result: " << result << " <<<<<" << std::endl;

+ 0 - 20
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/examples/C/Makefile

@@ -1,20 +0,0 @@
-include demo.mk
-
-BINFILE = demo
-
-OBJFILES = demo.o snowboy-detect-c-wrapper.o
-
-all: $(BINFILE)
-
-%.a:
-	$(MAKE) -C ${@D} ${@F}
-
-# We have to use the C++ compiler to link.
-$(BINFILE): $(PORTAUDIOLIBS) $(SNOWBOYDETECTLIBFILE) $(OBJFILES)
-	$(CXX) $(OBJFILES) $(SNOWBOYDETECTLIBFILE) $(PORTAUDIOLIBS) $(LDLIBS) -o $(BINFILE)
-
-$(PORTAUDIOLIBS):
-	@-./install_portaudio.sh
-
-clean:
-	-rm -f *.o *.a $(BINFILE) $(OBJFILES)

+ 0 - 2
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/examples/C/demo.c

@@ -190,14 +190,12 @@ int main(int argc, char* argv[]) {
   const char model_filename[] = "resources/models/snowboy.umdl";
   const char sensitivity_str[] = "0.5";
   float audio_gain = 1;
-  bool apply_frontend = false;
 
   // Initializes Snowboy detector.
   SnowboyDetect* detector = SnowboyDetectConstructor(resource_filename,
                                                      model_filename);
   SnowboyDetectSetSensitivity(detector, sensitivity_str);
   SnowboyDetectSetAudioGain(detector, audio_gain);
-  SnowboyDetectApplyFrontend(detector, apply_frontend);
 
   // Initializes PortAudio. You may use other tools to capture the audio.
   StartAudioCapturing(SnowboyDetectSampleRate(detector),

+ 3 - 27
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/examples/Python/snowboydecoder.py

@@ -7,8 +7,6 @@ import time
 import wave
 import os
 import logging
-from ctypes import *
-from contextlib import contextmanager
 
 logging.basicConfig()
 logger = logging.getLogger("snowboy")
@@ -19,23 +17,6 @@ RESOURCE_FILE = os.path.join(TOP_DIR, "resources/common.res")
 DETECT_DING = os.path.join(TOP_DIR, "resources/ding.wav")
 DETECT_DONG = os.path.join(TOP_DIR, "resources/dong.wav")
 
-def py_error_handler(filename, line, function, err, fmt):
-    pass
-
-ERROR_HANDLER_FUNC = CFUNCTYPE(None, c_char_p, c_int, c_char_p, c_int, c_char_p)
-
-c_error_handler = ERROR_HANDLER_FUNC(py_error_handler)
-
-@contextmanager
-def no_alsa_error():
-    try:
-        asound = cdll.LoadLibrary('libasound.so')
-        asound.snd_lib_error_set_handler(c_error_handler)
-        yield
-        asound.snd_lib_error_set_handler(None)
-    except:
-        yield
-        pass
 
 class RingBuffer(object):
     """Ring buffer to hold audio from PortAudio"""
@@ -62,8 +43,7 @@ def play_audio_file(fname=DETECT_DING):
     """
     ding_wav = wave.open(fname, 'rb')
     ding_data = ding_wav.readframes(ding_wav.getnframes())
-    with no_alsa_error():
-        audio = pyaudio.PyAudio()
+    audio = pyaudio.PyAudio()
     stream_out = audio.open(
         format=audio.get_format_from_width(ding_wav.getsampwidth()),
         channels=ding_wav.getnchannels(),
@@ -88,13 +68,11 @@ class HotwordDetector(object):
                               decoder. If an empty list is provided, then the
                               default sensitivity in the model will be used.
     :param audio_gain: multiply input volume by this factor.
-    :param apply_frontend: applies the frontend processing algorithm if True.
     """
     def __init__(self, decoder_model,
                  resource=RESOURCE_FILE,
                  sensitivity=[],
-                 audio_gain=1,
-                 apply_frontend=False):
+                 audio_gain=1):
 
         def audio_callback(in_data, frame_count, time_info, status):
             self.ring_buffer.extend(in_data)
@@ -112,7 +90,6 @@ class HotwordDetector(object):
         self.detector = snowboydetect.SnowboyDetect(
             resource_filename=resource.encode(), model_str=model_str.encode())
         self.detector.SetAudioGain(audio_gain)
-        self.detector.ApplyFrontend(apply_frontend)
         self.num_hotwords = self.detector.NumHotwords()
 
         if len(decoder_model) > 1 and len(sensitivity) == 1:
@@ -127,8 +104,7 @@ class HotwordDetector(object):
 
         self.ring_buffer = RingBuffer(
             self.detector.NumChannels() * self.detector.SampleRate() * 5)
-        with no_alsa_error():
-            self.audio = pyaudio.PyAudio()
+        self.audio = pyaudio.PyAudio()
         self.stream_in = self.audio.open(
             input=True, output=False,
             format=self.audio.get_format_from_width(

+ 3 - 27
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/examples/Python3/snowboydecoder.py

@@ -7,8 +7,6 @@ import time
 import wave
 import os
 import logging
-from ctypes import *
-from contextlib import contextmanager
 
 logging.basicConfig()
 logger = logging.getLogger("snowboy")
@@ -19,23 +17,6 @@ RESOURCE_FILE = os.path.join(TOP_DIR, "resources/common.res")
 DETECT_DING = os.path.join(TOP_DIR, "resources/ding.wav")
 DETECT_DONG = os.path.join(TOP_DIR, "resources/dong.wav")
 
-def py_error_handler(filename, line, function, err, fmt):
-    pass
-
-ERROR_HANDLER_FUNC = CFUNCTYPE(None, c_char_p, c_int, c_char_p, c_int, c_char_p)
-
-c_error_handler = ERROR_HANDLER_FUNC(py_error_handler)
-
-@contextmanager
-def no_alsa_error():
-    try:
-        asound = cdll.LoadLibrary('libasound.so')
-        asound.snd_lib_error_set_handler(c_error_handler)
-        yield
-        asound.snd_lib_error_set_handler(None)
-    except:
-        yield
-        pass
 
 class RingBuffer(object):
     """Ring buffer to hold audio from PortAudio"""
@@ -63,8 +44,7 @@ def play_audio_file(fname=DETECT_DING):
     """
     ding_wav = wave.open(fname, 'rb')
     ding_data = ding_wav.readframes(ding_wav.getnframes())
-    with no_alsa_error():
-        audio = pyaudio.PyAudio()
+    audio = pyaudio.PyAudio()
     stream_out = audio.open(
         format=audio.get_format_from_width(ding_wav.getsampwidth()),
         channels=ding_wav.getnchannels(),
@@ -89,14 +69,12 @@ class HotwordDetector(object):
                               decoder. If an empty list is provided, then the
                               default sensitivity in the model will be used.
     :param audio_gain: multiply input volume by this factor.
-    :param apply_frontend: applies the frontend processing algorithm if True.
     """
 
     def __init__(self, decoder_model,
                  resource=RESOURCE_FILE,
                  sensitivity=[],
-                 audio_gain=1,
-                 apply_frontend=False):
+                 audio_gain=1):
 
         tm = type(decoder_model)
         ts = type(sensitivity)
@@ -109,7 +87,6 @@ class HotwordDetector(object):
         self.detector = snowboydetect.SnowboyDetect(
             resource_filename=resource.encode(), model_str=model_str.encode())
         self.detector.SetAudioGain(audio_gain)
-        self.detector.ApplyFrontend(apply_frontend)
         self.num_hotwords = self.detector.NumHotwords()
 
         if len(decoder_model) > 1 and len(sensitivity) == 1:
@@ -164,8 +141,7 @@ class HotwordDetector(object):
             play_data = chr(0) * len(in_data)
             return play_data, pyaudio.paContinue
 
-        with no_alsa_error():
-            self.audio = pyaudio.PyAudio()
+        self.audio = pyaudio.PyAudio()
         self.stream_in = self.audio.open(
             input=True, output=False,
             format=self.audio.get_format_from_width(

+ 1 - 7
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/include/snowboy-detect.h

@@ -124,13 +124,7 @@ class SnowboyDetect {
   int NumHotwords() const;
 
   // If <apply_frontend> is true, then apply frontend audio processing;
-  // otherwise turns the audio processing off. Frontend audio processing
-  // includes algorithms such as automatic gain control (AGC), noise suppression
-  // (NS) and so on. Generally adding frontend audio processing helps the
-  // performance, but if the model is not trained with frontend audio
-  // processing, it may decrease the performance. The general rule of thumb is:
-  //   1. For personal models, set it to false.
-  //   2. For universal models, follow the instruction of each published model
+  // otherwise turns the audio processing off.
   void ApplyFrontend(const bool apply_frontend);
 
   // Returns the required sampling rate, number of channels and bits per sample

BIN
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/lib/aarch64-ubuntu1604/libsnowboy-detect.a


BIN
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/lib/android/armv7a/libsnowboy-detect.a


BIN
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/lib/android/armv8-aarch64/libsnowboy-detect.a


BIN
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/lib/ios/libsnowboy-detect.a


BIN
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/lib/osx/libsnowboy-detect.a


BIN
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/lib/rpi/libsnowboy-detect.a


+ 2 - 1
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/package.json

@@ -1,6 +1,6 @@
 {
   "name": "snowboy",
-  "version": "1.3.1",
+  "version": "1.3.0",
   "description": "Snowboy is a customizable hotword detection engine",
   "main": "lib/node/index.js",
   "typings": "lib/node/index.d.ts",
@@ -12,6 +12,7 @@
     "host": "https://snowboy-release-node.s3-us-west-2.amazonaws.com"
   },
   "scripts": {
+    "preinstall": "npm install node-pre-gyp",
     "install": "node-pre-gyp install --fallback-to-build",
     "test": "node index.js",
     "prepublish": "tsc --listFiles"

BIN
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/ding.wav


BIN
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/dong.wav


BIN
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/models/computer.umdl


BIN
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/models/hey_extreme.umdl


BIN
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/models/jarvis.umdl


BIN
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/models/neoya.umdl


BIN
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/models/subex.umdl


BIN
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/models/view_glass.umdl


BIN
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/resources/snowboy.wav


+ 0 - 30
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/scripts/install_swig.sh

@@ -1,30 +0,0 @@
-#!/bin/bash
-
-# SWIG is a tool to compile c++ code into Python.
-
-echo "Installing SWIG"
-
-if [ ! -e swig-3.0.10.tar.gz ]; then
-  cp exteral_tools/swig-3.0.10.tar.gz ./ || \
-  wget -T 10 -t 3 \
-    http://prdownloads.sourceforge.net/swig/swig-3.0.10.tar.gz || exit 1;
-fi
-
-tar -xovzf swig-3.0.10.tar.gz || exit 1
-ln -s swig-3.0.10 swig
-
-cd swig
-
-# We first have to install PCRE.
-if [ ! -e pcre-8.37.tar.gz ]; then
-  cp ../exteral_tools/pcre-8.37.tar.gz ./ || \
-  wget -T 10 -t 3 \
-    https://sourceforge.net/projects/pcre/files/pcre/8.37/pcre-8.37.tar.gz || exit 1;
-fi
-Tools/pcre-build.sh
-
-./configure --prefix=`pwd` --with-pic
-make
-make install
-
-cd ..

+ 0 - 73
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/swig/Python/Makefile

@@ -1,73 +0,0 @@
-# Example Makefile that converts snowboy c++ library (snowboy-detect.a) to
-# python library (_snowboydetect.so, snowboydetect.py), using swig.
-
-# Please use swig-3.0.10 or up.
-SWIG := swig
-
-SWIG_VERSION := $(shell expr `$(SWIG) -version | grep -i Version | \
-	sed "s/^.* //g" | sed -e "s/\.\([0-9][0-9]\)/\1/g" -e "s/\.\([0-9]\)/0\1/g" \
-	-e "s/^[0-9]\{3,4\}$$/&00/"` \>= 30010)
-
-ifeq ($(SWIG_VERSION), 0)
-checkversion:
-	$(info You need at least Swig 3.0.10 to run)
-	$(info Your current version is $(shell $(SWIG) -version | grep -i Version))
-	@exit -1
-endif
-
-SNOWBOYDETECTSWIGITF = snowboy-detect-swig.i
-SNOWBOYDETECTSWIGOBJ = snowboy-detect-swig.o
-SNOWBOYDETECTSWIGCC = snowboy-detect-swig.cc
-SNOWBOYDETECTSWIGLIBFILE = _snowboydetect.so
-
-TOPDIR := ../../
-CXXFLAGS := -I$(TOPDIR) -O3 -fPIC -D_GLIBCXX_USE_CXX11_ABI=0
-LDFLAGS :=
-
-ifeq ($(shell uname), Darwin)
-  CXX := clang++
-  PYINC := $(shell python-config --includes)
-  PYLIBS := $(shell python-config --ldflags)
-  SWIGFLAGS := -bundle -flat_namespace -undefined suppress
-  LDLIBS := -lm -ldl -framework Accelerate
-  SNOWBOYDETECTLIBFILE = $(TOPDIR)/lib/osx/libsnowboy-detect.a
-else
-  CXX := g++
-  PYINC := $(shell python-config --cflags)
-  PYLIBS := $(shell python-config --ldflags)
-  SWIGFLAGS := -shared
-  CXXFLAGS += -std=c++0x
-  # Make sure you have Atlas installed. You can statically link Atlas if you
-  # would like to be able to move the library to a machine without Atlas.
-  ifneq ("$(ldconfig -p | grep lapack_atlas)","")
-    LDLIBS := -lm -ldl -lf77blas -lcblas -llapack_atlas -latlas
-  else
-    LDLIBS := -lm -ldl -lf77blas -lcblas -llapack -latlas
-  endif
-  SNOWBOYDETECTLIBFILE = $(TOPDIR)/lib/ubuntu64/libsnowboy-detect.a
-  ifneq (,$(findstring arm,$(shell uname -m)))
-    SNOWBOYDETECTLIBFILE = $(TOPDIR)/lib/rpi/libsnowboy-detect.a
-    ifeq ($(findstring fc,$(shell uname -r)), fc)
-      SNOWBOYDETECTLIBFILE = $(TOPDIR)/lib/fedora25-armv7/libsnowboy-detect.a
-      LDLIBS := -L/usr/lib/atlas -lm -ldl -lsatlas
-    endif
-  endif
-endif
-
-all: $(SNOWBOYSWIGLIBFILE) $(SNOWBOYDETECTSWIGLIBFILE)
-
-%.a:
-	$(MAKE) -C ${@D} ${@F}
-
-$(SNOWBOYDETECTSWIGCC): $(SNOWBOYDETECTSWIGITF)
-	$(SWIG) -I$(TOPDIR) -c++ -python -o $(SNOWBOYDETECTSWIGCC) $(SNOWBOYDETECTSWIGITF)
-
-$(SNOWBOYDETECTSWIGOBJ): $(SNOWBOYDETECTSWIGCC)
-	$(CXX) $(PYINC) $(CXXFLAGS) -c $(SNOWBOYDETECTSWIGCC)
-
-$(SNOWBOYDETECTSWIGLIBFILE): $(SNOWBOYDETECTSWIGOBJ) $(SNOWBOYDETECTLIBFILE)
-	$(CXX) $(CXXFLAGS) $(LDFLAGS) $(SWIGFLAGS) $(SNOWBOYDETECTSWIGOBJ) \
-	$(SNOWBOYDETECTLIBFILE) $(PYLIBS) $(LDLIBS) -o $(SNOWBOYDETECTSWIGLIBFILE)
-
-clean:
-	-rm -f *.o *.a *.so snowboydetect.py *.pyc $(SNOWBOYDETECTSWIGCC)

+ 0 - 77
catkin_ws/src/snowboy_wakeup/3rdparty/snowboy/swig/Python3/Makefile

@@ -1,77 +0,0 @@
-# Example Makefile that converts snowboy c++ library (snowboy-detect.a) to
-# python3 library (_snowboydetect.so, snowboydetect.py), using swig.
-
-# Please use swig-3.0.10 or up.
-SWIG := swig
-
-SWIG_VERSION := $(shell expr `$(SWIG) -version | grep -i Version | \
-	sed "s/^.* //g" | sed -e "s/\.\([0-9][0-9]\)/\1/g" -e "s/\.\([0-9]\)/0\1/g" \
-	-e "s/^[0-9]\{3,4\}$$/&00/"` \>= 30010)
-
-ifeq ($(SWIG_VERSION), 0)
-checkversion:
-	$(info You need at least Swig 3.0.10 to run)
-	$(info Your current version is $(shell $(SWIG) -version | grep -i Version))
-	@exit -1
-endif
-
-
-SNOWBOYDETECTSWIGITF = snowboy-detect-swig.i
-SNOWBOYDETECTSWIGOBJ = snowboy-detect-swig.o
-SNOWBOYDETECTSWIGCC = snowboy-detect-swig.cc
-SNOWBOYDETECTSWIGLIBFILE = _snowboydetect.so
-
-TOPDIR := ../../
-CXXFLAGS := -I$(TOPDIR) -O3 -fPIC -D_GLIBCXX_USE_CXX11_ABI=0
-LDFLAGS :=
-
-ifeq ($(shell uname), Darwin)
-  CXX := clang++
-  PYINC := $(shell python3-config --includes)
-  # If you use Anaconda, the command `python3-config` will not return full path.
-  # In this case, please manually specify the full path like the following:
-  # PYLIBS := -L/Users/YOURNAME/anaconda3/lib/python3.6/config-3.6m-darwin -lpython3.6m -ldl -framework CoreFoundation
-  PYLIBS := $(shell python3-config --ldflags)
-  SWIGFLAGS := -bundle -flat_namespace -undefined suppress
-  LDLIBS := -lm -ldl -framework Accelerate
-  SNOWBOYDETECTLIBFILE = $(TOPDIR)/lib/osx/libsnowboy-detect.a
-else
-  CXX := g++
-  PYINC := $(shell python3-config --cflags)
-  PYLIBS := $(shell python3-config --ldflags)
-  SWIGFLAGS := -shared
-  CXXFLAGS += -std=c++0x
-  # Make sure you have Atlas installed. You can statically link Atlas if you
-  # would like to be able to move the library to a machine without Atlas.
-  ifneq ("$(ldconfig -p | grep lapack_atlas)","")
-    LDLIBS := -lm -ldl -lf77blas -lcblas -llapack_atlas -latlas
-  else
-    LDLIBS := -lm -ldl -lf77blas -lcblas -llapack -latlas
-  endif
-  SNOWBOYDETECTLIBFILE = $(TOPDIR)/lib/ubuntu64/libsnowboy-detect.a
-  ifneq (,$(findstring arm,$(shell uname -m)))
-    SNOWBOYDETECTLIBFILE = $(TOPDIR)/lib/rpi/libsnowboy-detect.a
-    ifeq ($(findstring fc,$(shell uname -r)), fc)
-      SNOWBOYDETECTLIBFILE = $(TOPDIR)/lib/fedora25-armv7/libsnowboy-detect.a
-      LDLIBS := -L/usr/lib/atlas -lm -ldl -lsatlas
-    endif
-  endif
-endif
-
-all: $(SNOWBOYSWIGLIBFILE) $(SNOWBOYDETECTSWIGLIBFILE)
-
-%.a:
-	$(MAKE) -C ${@D} ${@F}
-
-$(SNOWBOYDETECTSWIGCC): $(SNOWBOYDETECTSWIGITF)
-	$(SWIG) -I$(TOPDIR) -c++ -python -o $(SNOWBOYDETECTSWIGCC) $(SNOWBOYDETECTSWIGITF)
-
-$(SNOWBOYDETECTSWIGOBJ): $(SNOWBOYDETECTSWIGCC)
-	$(CXX) $(PYINC) $(CXXFLAGS) -c $(SNOWBOYDETECTSWIGCC)
-
-$(SNOWBOYDETECTSWIGLIBFILE): $(SNOWBOYDETECTSWIGOBJ) $(SNOWBOYDETECTLIBFILE)
-	$(CXX) $(CXXFLAGS) $(LDFLAGS) $(SWIGFLAGS) $(SNOWBOYDETECTSWIGOBJ) \
-	$(SNOWBOYDETECTLIBFILE) $(PYLIBS) $(LDLIBS) -o $(SNOWBOYDETECTSWIGLIBFILE)
-
-clean:
-	-rm -f *.o *.a *.so snowboydetect.py *.pyc $(SNOWBOYDETECTSWIGCC)

+ 78 - 175
catkin_ws/src/snowboy_wakeup/CMakeLists.txt

@@ -1,206 +1,109 @@
 cmake_minimum_required(VERSION 2.8.3)
 project(snowboy_wakeup)
 
-## Compile as C++11, supported in ROS Kinetic and newer
-add_compile_options(-std=c++11)
-
-## Find catkin macros and libraries
-## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
-## is used, also find other catkin packages
 find_package(catkin REQUIRED COMPONENTS
-  roscpp
-  std_msgs
+    roscpp
+    audio_common_msgs
+    dynamic_reconfigure
 )
 
-## System dependencies are found with CMake's conventions
-# find_package(Boost REQUIRED COMPONENTS system)
-
-
-## Uncomment this if the package has a setup.py. This macro ensures
-## modules and global scripts declared therein get installed
-## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
-# catkin_python_setup()
-
-################################################
-## Declare ROS messages, services and actions ##
-################################################
-
-## To declare and build messages, services or actions from within this
-## package, follow these steps:
-## * Let MSG_DEP_SET be the set of packages whose message types you use in
-##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
-## * In the file package.xml:
-##   * add a build_depend tag for "message_generation"
-##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
-##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
-##     but can be declared for certainty nonetheless:
-##     * add a exec_depend tag for "message_runtime"
-## * In this file (CMakeLists.txt):
-##   * add "message_generation" and every package in MSG_DEP_SET to
-##     find_package(catkin REQUIRED COMPONENTS ...)
-##   * add "message_runtime" and every package in MSG_DEP_SET to
-##     catkin_package(CATKIN_DEPENDS ...)
-##   * uncomment the add_*_files sections below as needed
-##     and list every .msg/.srv/.action file to be processed
-##   * uncomment the generate_messages entry below
-##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
-
-## Generate messages in the 'msg' folder
+set(CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS}")
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules)
+
+find_package(BLAS)
+
+# ------------------------------------------------------------------------------------------------
+#                                     ROS MESSAGES AND SERVICES
+# ------------------------------------------------------------------------------------------------
+
+# Generate messages
 # add_message_files(
-#   FILES
-#   Message1.msg
-#   Message2.msg
+#    FILES
+#    message1.msg
+#    ...
 # )
 
-## Generate services in the 'srv' folder
+# Generate services
 # add_service_files(
-#   FILES
-#   Service1.srv
-#   Service2.srv
+#    FILES
+#    service1.srv
+#    ...
 # )
 
-## Generate actions in the 'action' folder
-# add_action_files(
-#   FILES
-#   Action1.action
-#   Action2.action
-# )
-
-## Generate added messages and services with any dependencies listed here
+# Generate added messages and services with any dependencies listed here
 # generate_messages(
-#   DEPENDENCIES
-#   std_msgs
+#    DEPENDENCIES
+#    geometry_msgs
+#    ...
 # )
 
-################################################
-## Declare ROS dynamic reconfigure parameters ##
-################################################
-
-## To declare and build dynamic reconfigure parameters within this
-## package, follow these steps:
-## * In the file package.xml:
-##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
-## * In this file (CMakeLists.txt):
-##   * add "dynamic_reconfigure" to
-##     find_package(catkin REQUIRED COMPONENTS ...)
-##   * uncomment the "generate_dynamic_reconfigure_options" section below
-##     and list every .cfg file to be processed
-
-## Generate dynamic reconfigure parameters in the 'cfg' folder
-# generate_dynamic_reconfigure_options(
-#   cfg/DynReconf1.cfg
-#   cfg/DynReconf2.cfg
-# )
+#add dynamic reconfigure api
+#find_package(catkin REQUIRED dynamic_reconfigure)
+generate_dynamic_reconfigure_options(
+    cfg/SnowboyReconfigure.cfg
+)
+
+# ------------------------------------------------------------------------------------------------
+#                                          CATKIN EXPORT
+# ------------------------------------------------------------------------------------------------
 
-###################################
-## catkin specific configuration ##
-###################################
-## The catkin_package macro generates cmake config files for your package
-## Declare things to be passed to dependent projects
-## INCLUDE_DIRS: uncomment this if your package contains header files
-## LIBRARIES: libraries you create in this project that dependent projects also need
-## CATKIN_DEPENDS: catkin_packages dependent projects also need
-## DEPENDS: system dependencies of this project that dependent projects also need
 catkin_package(
-  INCLUDE_DIRS include
-#  LIBRARIES snowboy_wakeup
-#  CATKIN_DEPENDS roscpp std_msgs
+#  INCLUDE_DIRS include
+#  LIBRARIES hotword_detector
+#  CATKIN_DEPENDS roscpp audio_common_msgs
 #  DEPENDS system_lib
 )
 
-###########
-## Build ##
-###########
+# ------------------------------------------------------------------------------------------------
+#                                              BUILD
+# ------------------------------------------------------------------------------------------------
 
-## Specify additional locations of header files
-## Your package locations should be listed before other locations
 include_directories(
- include
-  ${catkin_INCLUDE_DIRS}
+    include
+    3rdparty
+    ${catkin_INCLUDE_DIRS}
 )
 
-## Declare a C++ library
-# add_library(${PROJECT_NAME}
-#   src/${PROJECT_NAME}/snowboy_wakeup.cpp
-# )
+file(GLOB_RECURSE HEADER_FILES include/*.h)
+file(GLOB_RECURSE 3RD_PARTY_FILES 3rdparty/*.h)
 
-## Add cmake target dependencies of the library
-## as an example, code may need to be generated before libraries
-## either from message generation or dynamic reconfigure
-# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
-
-## Declare a C++ executable
-## With catkin_make all packages are built within a single CMake context
-## The recommended prefix ensures that target names across packages don't collide
- add_executable(${PROJECT_NAME}_node src/snowboy_wakeup.cpp)
-
-## Rename C++ executable without prefix
-## The above recommended prefix causes long target names, the following renames the
-## target back to the shorter version for ease of user use
-## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
-# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
-
-## Add cmake target dependencies of the executable
-## same as for the library above
-# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
-
-## Specify libraries to link a library or executable target against
-target_link_libraries(${PROJECT_NAME}_node
-  ${CMAKE_CURRENT_SOURCE_DIR}/resources/libsnowboy-detect.a
-  ${catkin_LIBRARIES}
+add_library(hotword_detector
+    src/hotword_detector.cpp
+    ${HEADER_FILES}
+    ${3RD_PARTY_FILES}
 )
 
-#############
-## Install ##
-#############
-
-# all install targets should use catkin DESTINATION variables
-# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
-
-## Mark executable scripts (Python etc.) for installation
-## in contrast to setup.py, you can choose the destination
-# install(PROGRAMS
-#   scripts/my_python_script
-#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
-# )
-
-## Mark executables for installation
-## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
-# install(TARGETS ${PROJECT_NAME}_node
-#   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
-# )
-
-## Mark libraries for installation
-## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
-# install(TARGETS ${PROJECT_NAME}
-#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
-#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
-#   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
-# )
-
-## Mark cpp header files for installation
-# install(DIRECTORY include/${PROJECT_NAME}/
-#   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
-#   FILES_MATCHING PATTERN "*.h"
-#   PATTERN ".svn" EXCLUDE
-# )
+target_link_libraries(hotword_detector
+    ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/snowboy/lib/ubuntu64/libsnowboy-detect.a
+    ${catkin_LIBRARIES}
+    ${BLAS_LIBRARIES}
+)
 
-## Mark other files for installation (e.g. launch and bag files, etc.)
-# install(FILES
-#   # myfile1
-#   # myfile2
-#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
-# )
+add_executable(hotword_detector_node
+    src/hotword_detector_node.cpp
+)
+target_link_libraries(hotword_detector_node
+    hotword_detector
+    ${catkin_LIBRARIES}
+)
+add_dependencies(hotword_detector_node ${PROJECT_NAME}_gencfg)
+
+install(
+  TARGETS
+  hotword_detector
+  hotword_detector_node
+  ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
+  LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
+  RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
+)
 
-#############
-## Testing ##
-#############
+install(
+  DIRECTORY launch/
+  DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
+)
 
-## Add gtest based cpp test target and link libraries
-# catkin_add_gtest(${PROJECT_NAME}-test test/test_snowboy_wakeup.cpp)
-# if(TARGET ${PROJECT_NAME}-test)
-#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
-# endif()
+install(
+  DIRECTORY resources/
+  DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/resources
+)
 
-## Add folders to be run by python nosetests
-# catkin_add_nosetests(test)

+ 419 - 0
catkin_ws/src/snowboy_wakeup/cmake_modules/FindBLAS.cmake

@@ -0,0 +1,419 @@
+# Find BLAS library
+#
+# This module finds an installed library that implements the BLAS
+# linear-algebra interface (see http://www.netlib.org/blas/).
+# The list of libraries searched for is mainly taken
+# from the autoconf macro file, acx_blas.m4 (distributed at
+# http://ac-archive.sourceforge.net/ac-archive/acx_blas.html).
+#
+# This module sets the following variables:
+#  BLAS_FOUND - set to true if a library implementing the BLAS interface
+#    is found
+#  BLAS_INCLUDE_DIR - Directories containing the BLAS header files
+#  BLAS_DEFINITIONS - Compilation options to use BLAS
+#  BLAS_LINKER_FLAGS - Linker flags to use BLAS (excluding -l
+#    and -L).
+#  BLAS_LIBRARIES_DIR - Directories containing the BLAS libraries.
+#     May be null if BLAS_LIBRARIES contains libraries name using full path.
+#  BLAS_LIBRARIES - List of libraries to link against BLAS interface.
+#     May be null if the compiler supports auto-link (e.g. VC++).
+#  BLAS_USE_FILE - The name of the cmake module to include to compile
+#     applications or libraries using BLAS.
+#
+# This module was modified by CGAL team:
+# - find libraries for a C++ compiler, instead of Fortran
+# - added BLAS_INCLUDE_DIR, BLAS_DEFINITIONS and BLAS_LIBRARIES_DIR
+# - removed BLAS95_LIBRARIES
+
+include(CheckFunctionExists)
+
+
+# This macro checks for the existence of the combination of fortran libraries
+# given by _list.  If the combination is found, this macro checks (using the
+# check_function_exists macro) whether can link against that library
+# combination using the name of a routine given by _name using the linker
+# flags given by _flags.  If the combination of libraries is found and passes
+# the link test, LIBRARIES is set to the list of complete library paths that
+# have been found and DEFINITIONS to the required definitions.
+# Otherwise, LIBRARIES is set to FALSE.
+# N.B. _prefix is the prefix applied to the names of all cached variables that
+# are generated internally and marked advanced by this macro.
+macro(check_fortran_libraries DEFINITIONS LIBRARIES _prefix _name _flags _list _path)
+  #message("DEBUG: check_fortran_libraries(${_list} in ${_path})")
+
+  # Check for the existence of the libraries given by _list
+  set(_libraries_found TRUE)
+  set(_libraries_work FALSE)
+  set(${DEFINITIONS} "")
+  set(${LIBRARIES} "")
+  set(_combined_name)
+  foreach(_library ${_list})
+    set(_combined_name ${_combined_name}_${_library})
+
+    if(_libraries_found)
+      # search first in ${_path}
+      find_library(${_prefix}_${_library}_LIBRARY
+                  NAMES ${_library}
+                  PATHS ${_path} NO_DEFAULT_PATH
+                  )
+      # if not found, search in environment variables and system
+      if ( WIN32 )
+        find_library(${_prefix}_${_library}_LIBRARY
+                    NAMES ${_library}
+                    PATHS ENV LIB
+                    )
+      elseif ( APPLE )
+        find_library(${_prefix}_${_library}_LIBRARY
+                    NAMES ${_library}
+                    PATHS /usr/local/lib /usr/lib /usr/local/lib64 /usr/lib64 ENV DYLD_LIBRARY_PATH
+                    )
+      else ()
+        find_library(${_prefix}_${_library}_LIBRARY
+                    NAMES ${_library}
+                    PATHS /usr/local/lib /usr/lib /usr/local/lib64 /usr/lib64 ENV LD_LIBRARY_PATH
+                    )
+      endif()
+      mark_as_advanced(${_prefix}_${_library}_LIBRARY)
+      set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY})
+      set(_libraries_found ${${_prefix}_${_library}_LIBRARY})
+    endif(_libraries_found)
+  endforeach(_library ${_list})
+  if(_libraries_found)
+    set(_libraries_found ${${LIBRARIES}})
+  endif()
+
+  # Test this combination of libraries with the Fortran/f2c interface.
+  # We test the Fortran interface first as it is well standardized.
+  if(_libraries_found AND NOT _libraries_work)
+    set(${DEFINITIONS}  "-D${_prefix}_USE_F2C")
+    set(${LIBRARIES}    ${_libraries_found})
+    # Some C++ linkers require the f2c library to link with Fortran libraries.
+    # I do not know which ones, thus I just add the f2c library if it is available.
+    find_package( F2C QUIET )
+    if ( F2C_FOUND )
+      set(${DEFINITIONS}  ${${DEFINITIONS}} ${F2C_DEFINITIONS})
+      set(${LIBRARIES}    ${${LIBRARIES}} ${F2C_LIBRARIES})
+    endif()
+    set(CMAKE_REQUIRED_DEFINITIONS  ${${DEFINITIONS}})
+    set(CMAKE_REQUIRED_LIBRARIES    ${_flags} ${${LIBRARIES}})
+    #message("DEBUG: CMAKE_REQUIRED_DEFINITIONS = ${CMAKE_REQUIRED_DEFINITIONS}")
+    #message("DEBUG: CMAKE_REQUIRED_LIBRARIES = ${CMAKE_REQUIRED_LIBRARIES}")
+    # Check if function exists with f2c calling convention (ie a trailing underscore)
+    check_function_exists(${_name}_ ${_prefix}_${_name}_${_combined_name}_f2c_WORKS)
+    set(CMAKE_REQUIRED_DEFINITIONS} "")
+    set(CMAKE_REQUIRED_LIBRARIES    "")
+    mark_as_advanced(${_prefix}_${_name}_${_combined_name}_f2c_WORKS)
+    set(_libraries_work ${${_prefix}_${_name}_${_combined_name}_f2c_WORKS})
+  endif(_libraries_found AND NOT _libraries_work)
+
+  # If not found, test this combination of libraries with a C interface.
+  # A few implementations (ie ACML) provide a C interface. Unfortunately, there is no standard.
+  if(_libraries_found AND NOT _libraries_work)
+    set(${DEFINITIONS} "")
+    set(${LIBRARIES}   ${_libraries_found})
+    set(CMAKE_REQUIRED_DEFINITIONS "")
+    set(CMAKE_REQUIRED_LIBRARIES   ${_flags} ${${LIBRARIES}})
+    #message("DEBUG: CMAKE_REQUIRED_LIBRARIES = ${CMAKE_REQUIRED_LIBRARIES}")
+    check_function_exists(${_name} ${_prefix}_${_name}${_combined_name}_WORKS)
+    set(CMAKE_REQUIRED_LIBRARIES "")
+    mark_as_advanced(${_prefix}_${_name}${_combined_name}_WORKS)
+    set(_libraries_work ${${_prefix}_${_name}${_combined_name}_WORKS})
+  endif(_libraries_found AND NOT _libraries_work)
+
+  # on failure
+  if(NOT _libraries_work)
+    set(${DEFINITIONS} "")
+    set(${LIBRARIES}   FALSE)
+  endif()
+  #message("DEBUG: ${DEFINITIONS} = ${${DEFINITIONS}}")
+  #message("DEBUG: ${LIBRARIES} = ${${LIBRARIES}}")
+endmacro(check_fortran_libraries)
+
+
+#
+# main
+#
+
+# Is it already configured?
+if (BLAS_LIBRARIES_DIR OR BLAS_LIBRARIES)
+
+  set(BLAS_FOUND TRUE)
+
+else()
+
+  # reset variables
+  set( BLAS_INCLUDE_DIR "" )
+  set( BLAS_DEFINITIONS "" )
+  set( BLAS_LINKER_FLAGS "" )
+  set( BLAS_LIBRARIES "" )
+  set( BLAS_LIBRARIES_DIR "" )
+
+    #
+    # If Unix, search for BLAS function in possible libraries
+    #
+
+    # BLAS in ATLAS library? (http://math-atlas.sourceforge.net/)
+    if(NOT BLAS_LIBRARIES)
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "cblas;f77blas;atlas"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+    endif()
+
+    # BLAS in PhiPACK libraries? (requires generic BLAS lib, too)
+    if(NOT BLAS_LIBRARIES)
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "sgemm;dgemm;blas"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+    endif()
+
+    # BLAS in Alpha CXML library?
+    if(NOT BLAS_LIBRARIES)
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "cxml"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+    endif()
+
+    # BLAS in Alpha DXML library? (now called CXML, see above)
+    if(NOT BLAS_LIBRARIES)
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "dxml"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+    endif()
+
+    # BLAS in Sun Performance library?
+    if(NOT BLAS_LIBRARIES)
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      "-xlic_lib=sunperf"
+      "sunperf;sunmath"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+      if(BLAS_LIBRARIES)
+        # Extra linker flag
+        set(BLAS_LINKER_FLAGS "-xlic_lib=sunperf")
+      endif()
+    endif()
+
+    # BLAS in SCSL library?  (SGI/Cray Scientific Library)
+    if(NOT BLAS_LIBRARIES)
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "scsl"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+    endif()
+
+    # BLAS in SGIMATH library?
+    if(NOT BLAS_LIBRARIES)
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "complib.sgimath"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+    endif()
+
+    # BLAS in IBM ESSL library? (requires generic BLAS lib, too)
+    if(NOT BLAS_LIBRARIES)
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "essl;blas"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+    endif()
+
+    #BLAS in intel mkl 10 library? (em64t 64bit)
+    if(NOT BLAS_LIBRARIES)
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "mkl_intel_lp64;mkl_intel_thread;mkl_core;guide;pthread"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+    endif()
+
+    ### windows version of intel mkl 10?
+    if(NOT BLAS_LIBRARIES)
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      SGEMM
+      ""
+      "mkl_c_dll;mkl_intel_thread_dll;mkl_core_dll;libguide40"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+    endif()
+
+    #older versions of intel mkl libs
+
+    # BLAS in intel mkl library? (shared)
+    if(NOT BLAS_LIBRARIES)
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "mkl;guide;pthread"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+    endif()
+
+    #BLAS in intel mkl library? (static, 32bit)
+    if(NOT BLAS_LIBRARIES)
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "mkl_ia32;guide;pthread"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+    endif()
+
+    #BLAS in intel mkl library? (static, em64t 64bit)
+    if(NOT BLAS_LIBRARIES)
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "mkl_em64t;guide;pthread"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+    endif()
+
+    #BLAS in acml library?
+    if(NOT BLAS_LIBRARIES)
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "acml"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+    endif()
+
+    # Apple BLAS library?
+    if(NOT BLAS_LIBRARIES)
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "Accelerate"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+    endif()
+
+    if ( NOT BLAS_LIBRARIES )
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "vecLib"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+    endif ( NOT BLAS_LIBRARIES )
+
+    # Generic BLAS library?
+    # This configuration *must* be the last try as this library is notably slow.
+    if ( NOT BLAS_LIBRARIES )
+      check_fortran_libraries(
+      BLAS_DEFINITIONS
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "blas"
+      "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR"
+      )
+    endif()
+
+  if(BLAS_LIBRARIES_DIR OR BLAS_LIBRARIES)
+    set(BLAS_FOUND TRUE)
+  else()
+    set(BLAS_FOUND FALSE)
+  endif()
+
+  if(NOT BLAS_FIND_QUIETLY)
+    if(BLAS_FOUND)
+      message(STATUS "A library with BLAS API found.")
+    else(BLAS_FOUND)
+      if(BLAS_FIND_REQUIRED)
+        message(FATAL_ERROR "A required library with BLAS API not found. Please specify library location.")
+      else()
+        message(STATUS "A library with BLAS API not found. Please specify library location.")
+      endif()
+    endif(BLAS_FOUND)
+  endif(NOT BLAS_FIND_QUIETLY)
+
+  # Add variables to cache
+  set( BLAS_INCLUDE_DIR   "${BLAS_INCLUDE_DIR}"
+                          CACHE PATH "Directories containing the BLAS header files" FORCE )
+  set( BLAS_DEFINITIONS   "${BLAS_DEFINITIONS}"
+                          CACHE STRING "Compilation options to use BLAS" FORCE )
+  set( BLAS_LINKER_FLAGS  "${BLAS_LINKER_FLAGS}"
+                          CACHE STRING "Linker flags to use BLAS" FORCE )
+  set( BLAS_LIBRARIES     "${BLAS_LIBRARIES}"
+                          CACHE FILEPATH "BLAS libraries name" FORCE )
+  set( BLAS_LIBRARIES_DIR "${BLAS_LIBRARIES_DIR}"
+                          CACHE PATH "Directories containing the BLAS libraries" FORCE )
+
+  #message("DEBUG: BLAS_INCLUDE_DIR = ${BLAS_INCLUDE_DIR}")
+  #message("DEBUG: BLAS_DEFINITIONS = ${BLAS_DEFINITIONS}")
+  #message("DEBUG: BLAS_LINKER_FLAGS = ${BLAS_LINKER_FLAGS}")
+  #message("DEBUG: BLAS_LIBRARIES = ${BLAS_LIBRARIES}")
+  #message("DEBUG: BLAS_LIBRARIES_DIR = ${BLAS_LIBRARIES_DIR}")
+  #message("DEBUG: BLAS_FOUND = ${BLAS_FOUND}")
+
+endif(BLAS_LIBRARIES_DIR OR BLAS_LIBRARIES)

+ 0 - 226
catkin_ws/src/snowboy_wakeup/include/snowboy-detect.h

@@ -1,226 +0,0 @@
-// include/snowboy-detect.h
-
-// Copyright 2016  KITT.AI (author: Guoguo Chen)
-
-#ifndef SNOWBOY_INCLUDE_SNOWBOY_DETECT_H_
-#define SNOWBOY_INCLUDE_SNOWBOY_DETECT_H_
-
-#include <memory>
-#include <string>
-
-namespace snowboy {
-
-// Forward declaration.
-struct WaveHeader;
-class PipelineDetect;
-class PipelineVad;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// SnowboyDetect class interface.
-//
-////////////////////////////////////////////////////////////////////////////////
-class SnowboyDetect {
- public:
-  // Constructor that takes a resource file, and a list of hotword models which
-  // are separated by comma. In the case that more than one hotword exist in the
-  // provided models, RunDetection() will return the index of the hotword, if
-  // the corresponding hotword is triggered.
-  //
-  // CAVEAT: a personal model only contain one hotword, but an universal model
-  //         may contain multiple hotwords. It is your responsibility to figure
-  //         out the index of the hotword. For example, if your model string is
-  //         "foo.pmdl,bar.umdl", where foo.pmdl contains hotword x, bar.umdl
-  //         has two hotwords y and z, the indices of different hotwords are as
-  //         follows:
-  //         x 1
-  //         y 2
-  //         z 3
-  //
-  // @param [in]  resource_filename   Filename of resource file.
-  // @param [in]  model_str           A string of multiple hotword models,
-  //                                  separated by comma.
-  SnowboyDetect(const std::string& resource_filename,
-                const std::string& model_str);
-
-  // Resets the detection. This class handles voice activity detection (VAD)
-  // internally. But if you have an external VAD, you should call Reset()
-  // whenever you see segment end from your VAD.
-  bool Reset();
-
-  // Runs hotword detection. Supported audio format is WAVE (with linear PCM,
-  // 8-bits unsigned integer, 16-bits signed integer or 32-bits signed integer).
-  // See SampleRate(), NumChannels() and BitsPerSample() for the required
-  // sampling rate, number of channels and bits per sample values. You are
-  // supposed to provide a small chunk of data (e.g., 0.1 second) each time you
-  // call RunDetection(). Larger chunk usually leads to longer delay, but less
-  // CPU usage.
-  //
-  // Definition of return values:
-  // -2: Silence.
-  // -1: Error.
-  //  0: No event.
-  //  1: Hotword 1 triggered.
-  //  2: Hotword 2 triggered.
-  //  ...
-  //
-  // @param [in]  data               Small chunk of data to be detected. See
-  //                                 above for the supported data format.
-  // @param [in]  is_end             Set it to true if it is the end of a
-  //                                 utterance or file.
-  int RunDetection(const std::string& data, bool is_end = false);
-
-  // Various versions of RunDetection() that take different format of audio. If
-  // NumChannels() > 1, e.g., NumChannels() == 2, then the array is as follows:
-  //
-  //   d1c1, d1c2, d2c1, d2c2, d3c1, d3c2, ..., dNc1, dNc2
-  //
-  // where d1c1 means data point 1 of channel 1.
-  //
-  // @param [in]  data               Small chunk of data to be detected. See
-  //                                 above for the supported data format.
-  // @param [in]  array_length       Length of the data array.
-  // @param [in]  is_end             Set it to true if it is the end of a
-  //                                 utterance or file.
-  int RunDetection(const float* const data,
-                   const int array_length, bool is_end = false);
-  int RunDetection(const int16_t* const data,
-                   const int array_length, bool is_end = false);
-  int RunDetection(const int32_t* const data,
-                   const int array_length, bool is_end = false);
-
-  // Sets the sensitivity string for the loaded hotwords. A <sensitivity_str> is
-  // a list of floating numbers between 0 and 1, and separated by comma. For
-  // example, if there are 3 loaded hotwords, your string should looks something
-  // like this:
-  //   0.4,0.5,0.8
-  // Make sure you properly align the sensitivity value to the corresponding
-  // hotword.
-  void SetSensitivity(const std::string& sensitivity_str);
-
-  // Similar to the sensitivity setting above. When set higher than the above
-  // sensitivity, the algorithm automatically chooses between the normal
-  // sensitivity set above and the higher sensitivity set here, to maximize the
-  // performance. By default, it is not set, which means the algorithm will
-  // stick with the sensitivity set above.
-  void SetHighSensitivity(const std::string& high_sensitivity_str);
-
-  // Returns the sensitivity string for the current hotwords.
-  std::string GetSensitivity() const;
-
-  // Applied a fixed gain to the input audio. In case you have a very weak
-  // microphone, you can use this function to boost input audio level.
-  void SetAudioGain(const float audio_gain);
-
-  // Writes the models to the model filenames specified in <model_str> in the
-  // constructor. This overwrites the original model with the latest parameter
-  // setting. You are supposed to call this function if you have updated the
-  // hotword sensitivities through SetSensitivity(), and you would like to store
-  // those values in the model as the default value.
-  void UpdateModel() const;
-
-  // Returns the number of the loaded hotwords. This helps you to figure the
-  // index of the hotwords.
-  int NumHotwords() const;
-
-  // If <apply_frontend> is true, then apply frontend audio processing;
-  // otherwise turns the audio processing off. Frontend audio processing
-  // includes algorithms such as automatic gain control (AGC), noise suppression
-  // (NS) and so on. Generally adding frontend audio processing helps the
-  // performance, but if the model is not trained with frontend audio
-  // processing, it may decrease the performance. The general rule of thumb is:
-  //   1. For personal models, set it to false.
-  //   2. For universal models, follow the instruction of each published model
-  void ApplyFrontend(const bool apply_frontend);
-
-  // Returns the required sampling rate, number of channels and bits per sample
-  // values for the audio data. You should use this information to set up your
-  // audio capturing interface.
-  int SampleRate() const;
-  int NumChannels() const;
-  int BitsPerSample() const;
-
-  ~SnowboyDetect();
-
- private:
-  std::unique_ptr<WaveHeader> wave_header_;
-  std::unique_ptr<PipelineDetect> detect_pipeline_;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// SnowboyVad class interface.
-//
-////////////////////////////////////////////////////////////////////////////////
-class SnowboyVad {
- public:
-  // Constructor that takes a resource file. It shares the same resource file
-  // with SnowboyDetect.
-  SnowboyVad(const std::string& resource_filename);
-
-  // Resets the VAD.
-  bool Reset();
-
-  // Runs the VAD algorithm. Supported audio format is WAVE (with linear PCM,
-  // 8-bits unsigned integer, 16-bits signed integer or 32-bits signed integer).
-  // See SampleRate(), NumChannels() and BitsPerSample() for the required
-  // sampling rate, number of channels and bits per sample values. You are
-  // supposed to provide a small chunk of data (e.g., 0.1 second) each time you
-  // call RunDetection(). Larger chunk usually leads to longer delay, but less
-  // CPU usage.
-  //
-  // Definition of return values:
-  // -2: Silence.
-  // -1: Error.
-  //  0: Non-silence.
-  //
-  // @param [in]  data               Small chunk of data to be detected. See
-  //                                 above for the supported data format.
-  // @param [in]  is_end             Set it to true if it is the end of a
-  //                                 utterance or file.
-  int RunVad(const std::string& data, bool is_end = false);
-
-  // Various versions of RunVad() that take different format of audio. If
-  // NumChannels() > 1, e.g., NumChannels() == 2, then the array is as follows:
-  //
-  //   d1c1, d1c2, d2c1, d2c2, d3c1, d3c2, ..., dNc1, dNc2
-  //
-  // where d1c1 means data point 1 of channel 1.
-  //
-  // @param [in]  data               Small chunk of data to be detected. See
-  //                                 above for the supported data format.
-  // @param [in]  array_length       Length of the data array.
-  // @param [in]  is_end             Set it to true if it is the end of a
-  //                                 utterance or file.
-  int RunVad(const float* const data,
-             const int array_length, bool is_end = false);
-  int RunVad(const int16_t* const data,
-             const int array_length, bool is_end = false);
-  int RunVad(const int32_t* const data,
-             const int array_length, bool is_end = false);
-
-  // Applied a fixed gain to the input audio. In case you have a very weak
-  // microphone, you can use this function to boost input audio level.
-  void SetAudioGain(const float audio_gain);
-
-  // If <apply_frontend> is true, then apply frontend audio processing;
-  // otherwise turns the audio processing off.
-  void ApplyFrontend(const bool apply_frontend);
-
-  // Returns the required sampling rate, number of channels and bits per sample
-  // values for the audio data. You should use this information to set up your
-  // audio capturing interface.
-  int SampleRate() const;
-  int NumChannels() const;
-  int BitsPerSample() const;
-
-  ~SnowboyVad();
-
- private:
-  std::unique_ptr<WaveHeader> wave_header_;
-  std::unique_ptr<PipelineVad> vad_pipeline_;
-};
-
-}  // namespace snowboy
-
-#endif  // SNOWBOY_INCLUDE_SNOWBOY_DETECT_H_

+ 53 - 0
catkin_ws/src/snowboy_wakeup/include/snowboy_wakeup/hotword_detector.h

@@ -0,0 +1,53 @@
+#ifndef SNOWBOY_ROS_HOTWORD_DETECTOR_H_
+#define SNOWBOY_ROS_HOTWORD_DETECTOR_H_
+
+#include <snowboy/include/snowboy-detect.h>
+
+namespace snowboy_wakeup
+{
+
+//!
+//! \brief The HotwordDetector class wraps Snowboy detect so we can use C++ 11
+//!
+class HotwordDetector
+{
+
+public:
+
+  HotwordDetector();
+  ~HotwordDetector();
+
+  //!
+  //! \brief initialize Initializes the Snowbody
+  //! \param [in]  resource_filename   Filename of resource file.
+  //! \param [in]  model_str           A string of multiple hotword models,
+  //!
+  void initialize(const char* resource_filename, const char* model_filename);
+
+  //!
+  //! \brief configure Configure the detector on runtime
+  //! \param sensitivity Hotword sensitivity
+  //! \param audio_gain Fixed gain to the input audio.
+  //! \return True if success, False otherwise
+  //!
+  bool configure(double sensitivity, double audio_gain);
+
+  //!
+  //! \brief runDetection Runs hotword detection of Snowboy, see Snowboy API for more docs
+  //! \param data Small chunk of data to be detected
+  //! \param array_length Length of the data array.
+  //! \return -3 not initialized, -2 Silence, -1 Error, 0 No event, 1 Hotword triggered
+  //!
+  int runDetection(const int16_t* const data, const int array_length);
+
+private:
+
+  //!
+  //! \brief detector_ Instance of Snowboy detect
+  //!
+  snowboy::SnowboyDetect* detector_;
+};
+
+}  // namespace snowboy_wakeup
+
+#endif  // SNOWBOY_ROS_HOTWORD_DETECTOR_H_

+ 24 - 0
catkin_ws/src/snowboy_wakeup/launch/snowboy_wakeup.launch

@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<launch>
+    <arg name="ASR_Topic" default="/voice_system/asr_topic" />
+    <arg name="publish_wave" default="false" />
+
+    <node name="audio_capture" pkg="audio_capture" type="audio_capture" output="screen" required="true">
+        <param name="format" value="wave" />
+        <param name="channels" value="1" />
+        <param name="depth" value="16" />
+        <param name="sample_rate" value="16000" />
+
+        <remap from="audio" to="microphone" />
+    </node>
+
+    <node pkg="snowboy_wakeup" type="hotword_detector_node" name="snowboy" required="true">
+        <param name="resource_filename" value="$(find snowboy_wakeup)/resources/common.res" />
+        <param name="model_filename" value="$(find snowboy_wakeup)/resources/corvin.pmdl" />
+        <param name="sensitivity_str" value="0.5" type="str" />
+        <param name="audio_gain" value="1.0" />
+        <param name="publish_wave" value="$(arg publish_wave)" />
+        <param name="asr_topic" value="$(arg ASR_Topic)" />
+    </node>
+
+</launch>

+ 7 - 55
catkin_ws/src/snowboy_wakeup/package.xml

@@ -1,65 +1,17 @@
 <?xml version="1.0"?>
-<package format="2">
+<package>
   <name>snowboy_wakeup</name>
   <version>0.0.0</version>
-  <description>The snowboy_wakeup package</description>
+  <description>snowboy make hotword detector</description>
 
-  <!-- One maintainer tag required, multiple allowed, one person per tag -->
-  <!-- Example:  -->
-  <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
-  <maintainer email="corvin@todo.todo">corvin</maintainer>
+  <maintainer email="corvin_zhang@corvin.cn">corvin</maintainer>
 
+  <license>MIT</license>
 
-  <!-- One license tag required, multiple allowed, one license per tag -->
-  <!-- Commonly used license strings: -->
-  <!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
-  <license>TODO</license>
-
-
-  <!-- Url tags are optional, but multiple are allowed, one per tag -->
-  <!-- Optional attribute type can be: website, bugtracker, or repository -->
-  <!-- Example: -->
-  <!-- <url type="website">http://wiki.ros.org/snowboy_wakeup</url> -->
-
-
-  <!-- Author tags are optional, multiple are allowed, one per tag -->
-  <!-- Authors do not have to be maintainers, but could be -->
-  <!-- Example: -->
-  <!-- <author email="jane.doe@example.com">Jane Doe</author> -->
-
-
-  <!-- The *depend tags are used to specify dependencies -->
-  <!-- Dependencies can be catkin packages or system dependencies -->
-  <!-- Examples: -->
-  <!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
-  <!--   <depend>roscpp</depend> -->
-  <!--   Note that this is equivalent to the following: -->
-  <!--   <build_depend>roscpp</build_depend> -->
-  <!--   <exec_depend>roscpp</exec_depend> -->
-  <!-- Use build_depend for packages you need at compile time: -->
-  <!--   <build_depend>message_generation</build_depend> -->
-  <!-- Use build_export_depend for packages you need in order to build against this package: -->
-  <!--   <build_export_depend>message_generation</build_export_depend> -->
-  <!-- Use buildtool_depend for build tool packages: -->
-  <!--   <buildtool_depend>catkin</buildtool_depend> -->
-  <!-- Use exec_depend for packages you need at runtime: -->
-  <!--   <exec_depend>message_runtime</exec_depend> -->
-  <!-- Use test_depend for packages you need only for testing: -->
-  <!--   <test_depend>gtest</test_depend> -->
-  <!-- Use doc_depend for packages you need only for building documentation: -->
-  <!--   <doc_depend>doxygen</doc_depend> -->
   <buildtool_depend>catkin</buildtool_depend>
-  <build_depend>roscpp</build_depend>
-  <build_depend>std_msgs</build_depend>
-  <build_export_depend>roscpp</build_export_depend>
-  <build_export_depend>std_msgs</build_export_depend>
-  <exec_depend>roscpp</exec_depend>
-  <exec_depend>std_msgs</exec_depend>
-
 
-  <!-- The export tag contains other, unspecified, tags -->
-  <export>
-    <!-- Other tools can request additional information be placed here -->
+  <build_depend>libblas-dev</build_depend>
+  <build_depend>audio_common_msgs</build_depend>
+  <run_depend>audio_common_msgs</run_depend>
 
-  </export>
 </package>

BIN
catkin_ws/src/snowboy_wakeup/resources/corvin.pmdl


BIN
catkin_ws/src/snowboy_wakeup/resources/ding.wav


BIN
catkin_ws/src/snowboy_wakeup/resources/dong.wav


BIN
catkin_ws/src/snowboy_wakeup/resources/libsnowboy-detect.a


BIN
catkin_ws/src/snowboy_wakeup/resources/models/snowboy.umdl


BIN
catkin_ws/src/snowboy_wakeup/resources/wakeup_alert.mp3


+ 63 - 0
catkin_ws/src/snowboy_wakeup/src/hotword_detector.cpp

@@ -0,0 +1,63 @@
+#define _GLIBCXX_USE_CXX11_ABI 0
+
+#include "snowboy_wakeup/hotword_detector.h"
+
+#include <sstream>
+
+namespace snowboy_wakeup
+{
+
+HotwordDetector::HotwordDetector() : detector_(0)
+{
+}
+
+void HotwordDetector::initialize(const char* resource_filename, const char* model_filename)
+{
+  // Delete detector if we already had one
+  if (detector_)
+  {
+    delete detector_;
+  }
+
+  // We need to use cpp98 therefore we cannot pass std::strings
+  std::string resource_filename_cpp98(resource_filename);
+  std::string model_filename_cpp98(model_filename);
+
+  detector_ = new snowboy::SnowboyDetect(resource_filename_cpp98, model_filename_cpp98);
+}
+
+bool HotwordDetector::configure(double sensitivity, double audio_gain)
+{
+  // Return false if detector not initialized
+  if (!detector_)
+  {
+    return false;
+  }
+
+  std::stringstream sensitivity_ss; sensitivity_ss << sensitivity;
+
+  detector_->SetAudioGain(audio_gain);
+  detector_->SetSensitivity(sensitivity_ss.str());
+
+  return true;
+}
+
+HotwordDetector::~HotwordDetector()
+{
+  if (detector_)
+  {
+    delete detector_;
+  }
+}
+
+int HotwordDetector::runDetection(const int16_t* const data, const int array_length)
+{
+  if (!detector_)
+  {
+    return -3;
+  }
+  return detector_->RunDetection(data, array_length);
+}
+
+}
+

+ 198 - 0
catkin_ws/src/snowboy_wakeup/src/hotword_detector_node.cpp

@@ -0,0 +1,198 @@
+#include "snowboy_wakeup/hotword_detector.h"
+
+#include <ros/node_handle.h>
+#include <ros/debug.h>
+#include <audio_common_msgs/AudioData.h>
+#include <std_msgs/Int32.h>
+
+#include <dynamic_reconfigure/server.h>
+#include <snowboy_wakeup/SnowboyReconfigureConfig.h>
+
+#include <boost/filesystem.hpp>
+
+
+#define  ASR_START_FLAG  1  //detect hotword then start ASR
+
+namespace snowboy_wakeup
+{
+
+//!
+//! \brief The HotwordDetectorNode class Wraps the C++ 11 Snowboy detector in a ROS node
+//!
+class HotwordDetectorNode
+{
+public:
+  HotwordDetectorNode():
+    nh_(""),
+    nh_p_("~")
+  {
+  }
+
+  bool initialize()
+  {
+    std::string resource_filename;
+    if (!nh_p_.getParam("resource_filename", resource_filename))
+    {
+      ROS_ERROR("Mandatory parameter 'resource_filename' not present on the parameter server");
+      return false;
+    }
+
+    if ( !boost::filesystem::exists( resource_filename ) )
+    {
+      ROS_ERROR("Resource '%s' does not exist", resource_filename.c_str());
+      return false;
+    }
+
+    std::string resource_extension = boost::filesystem::extension(resource_filename);
+    if ( resource_extension != ".res" )
+    {
+      ROS_ERROR("'%s' not a valid Snowboy resource extension ('.res').", resource_filename.c_str());
+      return false;
+    }
+
+    std::string model_filename;
+    if (!nh_p_.getParam("model_filename", model_filename))
+    {
+      ROS_ERROR("Mandatory parameter 'model_filename' not present on the parameter server");
+      return false;
+    }
+
+    std::string asr_topic;
+    if (!nh_p_.getParam("asr_topic", asr_topic))
+    {
+      ROS_ERROR("Mandatory parameter 'asr_topic' not present on the parameter server");
+      return false;
+    }
+
+    if ( !boost::filesystem::exists( model_filename ) )
+    {
+      ROS_ERROR("Model '%s' does not exist", model_filename.c_str());
+      return false;
+    }
+
+    std::string model_extension = boost::filesystem::extension(model_filename);
+    if ( model_extension  != ".pmdl" && model_extension != ".umdl" )
+    {
+      ROS_ERROR("Model '%s', not a valid Snowboy model extension ('.pmdl', '.umdl').", resource_filename.c_str());
+      return false;
+    }
+
+    audio_sub_ = nh_.subscribe("microphone", 1000, &HotwordDetectorNode::audioCallback, this);
+    hotword_pub_ = nh_.advertise<std_msgs::Int32>(asr_topic, 10);
+
+    detector_.initialize(resource_filename.c_str(), model_filename.c_str());
+
+    dynamic_reconfigure_server_.setCallback(boost::bind(&HotwordDetectorNode::reconfigureCallback, this, _1, _2));
+
+    return true;
+  }
+
+private:
+
+  //!
+  //! \brief nh_ Global nodehandle for topics
+  //!
+  ros::NodeHandle nh_;
+
+  //!
+  //! \brief nh_p_ Local nodehandle for parameters
+  //!
+  ros::NodeHandle nh_p_;
+
+  //!
+  //! \brief audio_sub_ Subscriber to incoming audio feed
+  //!
+  ros::Subscriber audio_sub_;
+
+  //!
+  //! \brief hotword_pub_ hotword publisher
+  //!
+  ros::Publisher hotword_pub_;
+
+  //!
+  //! \brief dynamic_reconfigure_server_ In order to online tune the sensitivity and audio gain
+  //!
+  dynamic_reconfigure::Server<SnowboyReconfigureConfig> dynamic_reconfigure_server_;
+
+  //!
+  //! \brief detector_ C++ 11 Wrapped Snowboy detect
+  //!
+  HotwordDetector detector_;
+
+  //!
+  //! \brief reconfigureCallback Reconfigure update for sensitiviy and audio level
+  //! \param cfg The updated config
+  //!
+  void reconfigureCallback(SnowboyReconfigureConfig cfg, uint32_t /*level*/)
+  {
+    detector_.configure(cfg.sensitivity, cfg.audio_gain);
+    ROS_INFO("SnowboyROS (Re)Configured");
+  }
+
+  //!
+  //! \brief audioCallback Audio stream callback
+  //! \param msg The audo data
+  //!
+  void audioCallback(const audio_common_msgs::AudioDataConstPtr& msg)
+  {
+    if (msg->data.size() != 0)
+    {
+      /* Sound signal is encoded with bit depth 16 and cut up in a byte array. RunDetection wants it as an array of
+       * int16_t. Therefore, we bit shift the second (MSB) byte of a sample by 8 and cast it to an int16_t and add the
+       * first (LSB) byte of the sample to the result (also after typecast).
+       */
+
+      if ( msg->data.size() % 2 )
+      {
+        ROS_ERROR("Not an even number of bytes in this message!");
+      }
+
+      int16_t sample_array[msg->data.size()/2];
+      for ( size_t i = 0; i < msg->data.size(); i+=2 )
+      {
+        sample_array[i/2] = ((int16_t) (msg->data[i+1]) << 8) + (int16_t) (msg->data[i]);
+      }
+
+      int result = detector_.runDetection( &sample_array[0], msg->data.size()/2);
+      if (result > 0)
+      {
+        ROS_DEBUG("Hotword detected!");
+
+        system("play ~/Music/wakeup_alert.mp3");
+        std_msgs::Int32 hotword_msg;
+        hotword_msg.data = ASR_START_FLAG;
+        hotword_pub_.publish(hotword_msg);
+      }
+      else if (result == -3)
+      {
+        ROS_ERROR("Hotword detector not initialized");
+      }
+      else if (result == -1)
+      {
+        ROS_ERROR("Snowboy error");
+      }
+    }
+  }
+};
+
+}
+
+int main(int argc, char** argv)
+{
+  ros::init(argc, argv, "snowboy_wakeup_node");
+
+  snowboy_wakeup::HotwordDetectorNode ros_hotword_detector_node;
+
+  if (ros_hotword_detector_node.initialize())
+  {
+    ros::spin();
+  }
+  else
+  {
+    ROS_ERROR("Failed to initialize snowboy_node");
+    return 1;
+  }
+
+  return 0;
+}
+

+ 0 - 237
catkin_ws/src/snowboy_wakeup/src/snowboy_wakeup.cpp

@@ -1,237 +0,0 @@
-// example/C++/demo.cc
-
-// Copyright 2016  KITT.AI (author: Guoguo Chen)
-
-#include <cassert>
-#include <csignal>
-#include <iostream>
-#include <pa_ringbuffer.h>
-#include <pa_util.h>
-#include <portaudio.h>
-#include <string>
-#include <vector>
-#include <ros/ros.h>
-#include <std_msgs/Int32.h>
-#include "snowboy-detect.h"
-
-int PortAudioCallback(const void* input,
-                      void* output,
-                      unsigned long frame_count,
-                      const PaStreamCallbackTimeInfo* time_info,
-                      PaStreamCallbackFlags status_flags,
-                      void* user_data);
-
-class PortAudioWrapper {
- public:
-  // Constructor.
-  PortAudioWrapper(int sample_rate, int num_channels, int bits_per_sample) {
-    num_lost_samples_ = 0;
-    min_read_samples_ = sample_rate * 0.1;
-    Init(sample_rate, num_channels, bits_per_sample);
-  }
-
-  // Reads data from ring buffer.
-  template<typename T>
-  void Read(std::vector<T>* data) {
-    assert(data != NULL);
-
-    // Checks ring buffer overflow.
-    if (num_lost_samples_ > 0) {
-      std::cerr << "Lost " << num_lost_samples_ << " samples due to ring"
-          << " buffer overflow." << std::endl;
-      num_lost_samples_ = 0;
-    }
-
-    ring_buffer_size_t num_available_samples = 0;
-    while (true) {
-      num_available_samples =
-          PaUtil_GetRingBufferReadAvailable(&pa_ringbuffer_);
-      if (num_available_samples >= min_read_samples_) {
-        break;
-      }
-      Pa_Sleep(5);
-    }
-
-    // Reads data.
-    num_available_samples = PaUtil_GetRingBufferReadAvailable(&pa_ringbuffer_);
-    data->resize(num_available_samples);
-    ring_buffer_size_t num_read_samples = PaUtil_ReadRingBuffer(
-        &pa_ringbuffer_, data->data(), num_available_samples);
-    if (num_read_samples != num_available_samples) {
-      std::cerr << num_available_samples << " samples were available,  but "
-          << "only " << num_read_samples << " samples were read." << std::endl;
-    }
-  }
-
-  int Callback(const void* input, void* output,
-               unsigned long frame_count,
-               const PaStreamCallbackTimeInfo* time_info,
-               PaStreamCallbackFlags status_flags) {
-    // Input audio.
-    ring_buffer_size_t num_written_samples =
-        PaUtil_WriteRingBuffer(&pa_ringbuffer_, input, frame_count);
-    num_lost_samples_ += frame_count - num_written_samples;
-    return paContinue;
-  }
-
-  ~PortAudioWrapper() {
-    Pa_StopStream(pa_stream_);
-    Pa_CloseStream(pa_stream_);
-    Pa_Terminate();
-    PaUtil_FreeMemory(ringbuffer_);
-  }
-
- private:
-  // Initialization.
-  bool Init(int sample_rate, int num_channels, int bits_per_sample) {
-    // Allocates ring buffer memory.
-    int ringbuffer_size = 16384;
-    ringbuffer_ = static_cast<char*>(
-        PaUtil_AllocateMemory(bits_per_sample / 8 * ringbuffer_size));
-    if (ringbuffer_ == NULL) {
-      std::cerr << "Fail to allocate memory for ring buffer." << std::endl;
-      return false;
-    }
-
-    // Initializes PortAudio ring buffer.
-    ring_buffer_size_t rb_init_ans =
-        PaUtil_InitializeRingBuffer(&pa_ringbuffer_, bits_per_sample / 8,
-                                    ringbuffer_size, ringbuffer_);
-    if (rb_init_ans == -1) {
-      std::cerr << "Ring buffer size is not power of 2." << std::endl;
-      return false;
-    }
-
-    // Initializes PortAudio.
-    PaError pa_init_ans = Pa_Initialize();
-    if (pa_init_ans != paNoError) {
-      std::cerr << "Fail to initialize PortAudio, error message is \""
-          << Pa_GetErrorText(pa_init_ans) << "\"" << std::endl;
-      return false;
-    }
-
-    PaError pa_open_ans;
-    if (bits_per_sample == 8) {
-      pa_open_ans = Pa_OpenDefaultStream(
-          &pa_stream_, num_channels, 0, paUInt8, sample_rate,
-          paFramesPerBufferUnspecified, PortAudioCallback, this);
-    } else if (bits_per_sample == 16) {
-      pa_open_ans = Pa_OpenDefaultStream(
-          &pa_stream_, num_channels, 0, paInt16, sample_rate,
-          paFramesPerBufferUnspecified, PortAudioCallback, this);
-    } else if (bits_per_sample == 32) {
-      pa_open_ans = Pa_OpenDefaultStream(
-          &pa_stream_, num_channels, 0, paInt32, sample_rate,
-          paFramesPerBufferUnspecified, PortAudioCallback, this);
-    } else {
-      std::cerr << "Unsupported BitsPerSample: " << bits_per_sample
-          << std::endl;
-      return false;
-    }
-    if (pa_open_ans != paNoError) {
-      std::cerr << "Fail to open PortAudio stream, error message is \""
-          << Pa_GetErrorText(pa_open_ans) << "\"" << std::endl;
-      return false;
-    }
-
-    PaError pa_stream_start_ans = Pa_StartStream(pa_stream_);
-    if (pa_stream_start_ans != paNoError) {
-      std::cerr << "Fail to start PortAudio stream, error message is \""
-          << Pa_GetErrorText(pa_stream_start_ans) << "\"" << std::endl;
-      return false;
-    }
-    return true;
-  }
-
- private:
-  // Pointer to the ring buffer memory.
-  char* ringbuffer_;
-
-  // Ring buffer wrapper used in PortAudio.
-  PaUtilRingBuffer pa_ringbuffer_;
-
-  // Pointer to PortAudio stream.
-  PaStream* pa_stream_;
-
-  // Number of lost samples at each Read() due to ring buffer overflow.
-  int num_lost_samples_;
-
-  // Wait for this number of samples in each Read() call.
-  int min_read_samples_;
-};
-
-int PortAudioCallback(const void* input,
-                      void* output,
-                      unsigned long frame_count,
-                      const PaStreamCallbackTimeInfo* time_info,
-                      PaStreamCallbackFlags status_flags,
-                      void* user_data) {
-  PortAudioWrapper* pa_wrapper = reinterpret_cast<PortAudioWrapper*>(user_data);
-  pa_wrapper->Callback(input, output, frame_count, time_info, status_flags);
-  return paContinue;
-}
-
-void SignalHandler(int signal){
-  std::cerr << "Caught signal " << signal << ", terminating..." << std::endl;
-  exit(0);
-}
-
-int main(int argc, char* argv[]) 
-{
-    ros::init(argc, argv, "snowboy_wakeup_node");
-    ros::NodeHandle node_handle;
-    ros::Publisher pub_wakeup = node_handle.advertise<std_msgs::Int32>("/ros_voice_system/wakeup_topic", 1);
-  
-    // Configures signal handling.
-   struct sigaction sig_int_handler;
-   sig_int_handler.sa_handler = SignalHandler;
-   sigemptyset(&sig_int_handler.sa_mask);
-   sig_int_handler.sa_flags = 0;
-   sigaction(SIGINT, &sig_int_handler, NULL);
-
-  // Parameter section.
-  // If you have multiple hotword models (e.g., 2), you should set
-  // <model_filename> and <sensitivity_str> as follows:
-  //   model_filename =
-  //     "resources/models/snowboy.umdl,resources/models/smart_mirror.umdl";
-  //   sensitivity_str = "0.5,0.5";
-  std::string resource_filename = "resources/common.res";
-  std::string model_filename = "resources/models/snowboy.umdl";
-  std::string sensitivity_str = "0.5";
-  float audio_gain = 1;
-  bool apply_frontend = false;
-
-  // Initializes Snowboy detector.
-  snowboy::SnowboyDetect detector(resource_filename, model_filename);
-  detector.SetSensitivity(sensitivity_str);
-  detector.SetAudioGain(audio_gain);
-  detector.ApplyFrontend(apply_frontend);
-
-  // Initializes PortAudio. You may use other tools to capture the audio.
-  PortAudioWrapper pa_wrapper(detector.SampleRate(),
-                              detector.NumChannels(), detector.BitsPerSample());
-
-  // Runs the detection.
-  // Note: I hard-coded <int16_t> as data type because detector.BitsPerSample()
-  //       returns 16.
-  std::cout << "Listening... Press Ctrl+C to exit" << std::endl;
-  std::vector<int16_t> data;
-    std_msgs::Int32 msg;
-    while (ros::ok()) 
-    {
-        pa_wrapper.Read(&data);
-        if (data.size() != 0) 
-        {
-            int result = detector.RunDetection(data.data(), data.size());
-            if (result > 0) 
-            {
-                std::cout << "Hotword " << result << " detected!" << std::endl;
-                msg.data = 1;
-                pub_wakeup.publish(msg);
-            }
-        }
-    ros::spinOnce();
-  }
-
-  return 0;
-}