16 #include <alsa/asoundlib.h>
20 #include <wiringPiSPI.h>
22 #include "pv_porcupine.h"
24 static const uint8_t
OFF_RGB[3] = {0, 0, 0};
25 static const uint8_t
BLUE_RGB[3] = {0, 0, 255};
28 static const uint8_t
PINK_RGB[3] = {255, 51, 153};
30 static const uint8_t
RED_RGB[3] = {255, 0, 0};
31 static const uint8_t
WHITE_RGB[3] = {255, 255, 255};
37 for(int32_t i = 0; i < 4; i++) {
39 wiringPiSPIDataRW(0, &zero, 1);
42 static const uint32_t BRIGHTNESS = 1;
43 for(int32_t i = 0; i < 12; i++) {
45 led_frame[0] = 0b11100000 | (0b00011111 & BRIGHTNESS);
46 led_frame[1] = rgb[2];
47 led_frame[2] = rgb[1];
48 led_frame[3] = rgb[0];
49 wiringPiSPIDataRW(0, led_frame, 4);
52 for(int32_t i = 0; i < 4; i++) {
54 wiringPiSPIDataRW(0, &zero, 1);
67 "usage : %s access_key library_path model_path sensitivity input_audio_device alexa_keyword_path "
68 "computer_keyword_path hey_google_keyword_path hey_siri_keyword_path jarvis_keyword_path "
69 "picovoice_keyword_path porcupine_keyword_path bumblebee_keyword_path terminator_keyword_path\n",
argv[0]);
75 const char *access_key =
argv[1];
76 const char *library_path =
argv[2];
77 const char *model_path =
argv[3];
78 const float sensitivity = (float) atof(
argv[4]);
79 const char *input_audio_device =
argv[5];
80 const char **keyword_paths = (
const char **) &
argv[6];
81 const int32_t num_keywords = 9;
83 void *porcupine_library = dlopen(library_path, RTLD_NOW);
84 if (!porcupine_library) {
85 fprintf(stderr,
"failed to open library.\n");
91 const char *(*pv_status_to_string_func)(
pv_status_t) = dlsym(porcupine_library,
"pv_status_to_string");
93 fprintf(stderr,
"failed to load 'pv_status_to_string' with '%s'.\n",
error);
97 int32_t (*pv_sample_rate_func)() = dlsym(porcupine_library,
"pv_sample_rate");
99 fprintf(stderr,
"failed to load 'pv_sample_rate' with '%s'.\n",
error);
103 pv_status_t (*pv_porcupine_init_func)(
const char *,
const char *, int32_t,
const char *
const *,
const float *,
pv_porcupine_t **) =
104 dlsym(porcupine_library,
"pv_porcupine_init");
106 fprintf(stderr,
"failed to load 'pv_porcupine_init' with '%s'.\n",
error);
110 void (*pv_porcupine_delete_func)(
pv_porcupine_t *) = dlsym(porcupine_library,
"pv_porcupine_delete");
112 fprintf(stderr,
"failed to load 'pv_porcupine_delete' with '%s'.\n",
error);
117 dlsym(porcupine_library,
"pv_porcupine_process");
119 fprintf(stderr,
"failed to load 'pv_porcupine_process' with '%s'.\n",
error);
123 int32_t (*pv_porcupine_frame_length_func)() = dlsym(porcupine_library,
"pv_porcupine_frame_length");
125 fprintf(stderr,
"failed to load 'pv_porcupine_frame_length' with '%s'.\n",
error);
130 float sensitivities[num_keywords];
131 for (int32_t i = 0; i < num_keywords; i++) {
132 sensitivities[i] = sensitivity;
134 pv_status_t status = pv_porcupine_init_func(access_key, model_path, num_keywords, keyword_paths, sensitivities, &porcupine);
136 fprintf(stderr,
"'pv_porcupine_init' failed with '%s'\n", pv_status_to_string_func(status));
140 snd_pcm_t *alsa_handle =
NULL;
141 int error_code = snd_pcm_open(&alsa_handle, input_audio_device, SND_PCM_STREAM_CAPTURE, 0);
142 if (error_code != 0) {
143 fprintf(stderr,
"'snd_pcm_open' failed with '%s'\n", snd_strerror(error_code));
147 snd_pcm_hw_params_t *hardware_params =
NULL;
148 error_code = snd_pcm_hw_params_malloc(&hardware_params);
149 if (error_code != 0) {
150 fprintf(stderr,
"'snd_pcm_hw_params_malloc' failed with '%s'\n", snd_strerror(error_code));
154 error_code = snd_pcm_hw_params_any(alsa_handle, hardware_params);
155 if (error_code != 0) {
156 fprintf(stderr,
"'snd_pcm_hw_params_any' failed with '%s'\n", snd_strerror(error_code));
160 error_code = snd_pcm_hw_params_set_access(alsa_handle, hardware_params, SND_PCM_ACCESS_RW_INTERLEAVED);
161 if (error_code != 0) {
162 fprintf(stderr,
"'snd_pcm_hw_params_set_access' failed with '%s'\n", snd_strerror(error_code));
166 error_code = snd_pcm_hw_params_set_format(alsa_handle, hardware_params, SND_PCM_FORMAT_S16_LE);
167 if (error_code != 0) {
168 fprintf(stderr,
"'snd_pcm_hw_params_set_format' failed with '%s'\n", snd_strerror(error_code));
172 error_code = snd_pcm_hw_params_set_rate(alsa_handle, hardware_params, pv_sample_rate_func(), 0);
173 if (error_code != 0) {
174 fprintf(stderr,
"'snd_pcm_hw_params_set_rate' failed with '%s'\n", snd_strerror(error_code));
178 error_code = snd_pcm_hw_params_set_channels(alsa_handle, hardware_params, 1);
179 if (error_code != 0) {
180 fprintf(stderr,
"'snd_pcm_hw_params_set_channels' failed with '%s'\n", snd_strerror(error_code));
184 error_code = snd_pcm_hw_params(alsa_handle, hardware_params);
185 if (error_code != 0) {
186 fprintf(stderr,
"'snd_pcm_hw_params' failed with '%s'\n", snd_strerror(error_code));
190 snd_pcm_hw_params_free(hardware_params);
192 error_code = snd_pcm_prepare(alsa_handle);
193 if (error_code != 0) {
194 fprintf(stderr,
"'snd_pcm_prepare' failed with '%s'\n", snd_strerror(error_code));
198 const int32_t frame_length = pv_porcupine_frame_length_func();
200 int16_t *pcm = malloc(frame_length *
sizeof(int16_t));
202 fprintf(stderr,
"failed to allocate memory for audio buffer\n");
207 if(wiringPiSPISetup(0, 6000000) < 0) {
208 fprintf(stderr,
"failed to setup SPI interface\n");
213 digitalWrite(21, HIGH);
215 fprintf(stdout,
"[Listening]\n");
218 const int count = snd_pcm_readi(alsa_handle, pcm, frame_length);
220 fprintf(stderr,
"'snd_pcm_readi' failed with '%s'\n", snd_strerror(
count));
222 }
else if (
count != frame_length) {
223 fprintf(stderr,
"read %d frames instead of %d\n",
count, frame_length);
227 int32_t keyword_index = -1;
228 status = pv_porcupine_process_func(porcupine, pcm, &keyword_index);
230 fprintf(stderr,
"'pv_porcupine_process' failed with '%s'\n", pv_status_to_string_func(status));
233 if (keyword_index != -1) {
246 fprintf(stdout,
"detected '%s'\n",
KEYWORDS[keyword_index]);
248 static const char *COLORS[] = {
260 switch (keyword_index) {
293 snd_pcm_close(alsa_handle);
294 pv_porcupine_delete_func(porcupine);
295 dlclose(porcupine_library);