17 #if defined(_WIN32) || defined(_WIN64)
27 #define DR_WAV_IMPLEMENTATION
31 #include "pv_porcupine.h"
33 static void *
open_dl(
const char *dl_path) {
35 #if defined(_WIN32) || defined(_WIN64)
37 return LoadLibrary(dl_path);
41 return dlopen(dl_path, RTLD_NOW);
49 #if defined(_WIN32) || defined(_WIN64)
51 return GetProcAddress((HMODULE) handle, symbol);
55 return dlsym(handle, symbol);
63 #if defined(_WIN32) || defined(_WIN64)
65 FreeLibrary((HMODULE) handle);
77 #if defined(_WIN32) || defined(_WIN64)
79 fprintf(stderr,
"%s with code '%lu'.\n", message, GetLastError());
83 fprintf(stderr,
"%s with '%s'.\n", message, dlerror());
90 {
"library_path", required_argument,
NULL,
'l'},
91 {
"model_path", required_argument,
NULL,
'm'},
92 {
"keyword_path", required_argument,
NULL,
'k'},
93 {
"sensitivity", required_argument,
NULL,
't'},
94 {
"access_key", required_argument,
NULL,
'a'},
95 {
"wav_path", required_argument,
NULL,
'w'}
99 fprintf(stderr,
"Usage : %s -l LIBRARY_PATH -m MODEL_PATH -k KEYWORD_PATH -t SENSITIVITY -a ACCESS_KEY -w WAV_PATH\n", program_name);
103 const char *library_path =
NULL;
104 const char *model_path =
NULL;
105 const char *keyword_path =
NULL;
106 float sensitivity = 0.5;
107 const char *access_key =
NULL;
108 const char *wav_path =
NULL;
114 library_path = optarg;
120 keyword_path = optarg;
123 sensitivity = strtof(optarg,
NULL);
136 if (!library_path || !model_path || !keyword_path || !access_key) {
141 void *porcupine_library =
open_dl(library_path);
142 if (!porcupine_library) {
143 fprintf(stderr,
"failed to open library\n");
147 const char *(*pv_status_to_string_func)(
pv_status_t) =
load_symbol(porcupine_library,
"pv_status_to_string");
148 if (!pv_status_to_string_func) {
153 int32_t (*pv_sample_rate_func)() =
load_symbol(porcupine_library,
"pv_sample_rate");
154 if (!pv_sample_rate_func) {
159 pv_status_t (*pv_porcupine_init_func)(
const char *,
const char *, int32_t,
const char *
const *,
const float *,
pv_porcupine_t **)
160 =
load_symbol(porcupine_library,
"pv_porcupine_init");
161 if (!pv_porcupine_init_func) {
167 if (!pv_porcupine_delete_func) {
173 load_symbol(porcupine_library,
"pv_porcupine_process");
174 if (!pv_porcupine_process_func) {
179 int32_t (*pv_porcupine_frame_length_func)() =
load_symbol(porcupine_library,
"pv_porcupine_frame_length");
180 if (!pv_porcupine_frame_length_func) {
181 print_dl_error(
"failed to load 'pv_porcupine_frame_length' with '%s'.\n");
185 const char *(*pv_porcupine_version_func)() =
load_symbol(porcupine_library,
"pv_porcupine_version");
186 if (!pv_porcupine_version_func) {
194 fprintf(stderr,
"failed to open wav file at '%s'.", wav_path);
198 if (
f.sampleRate != (uint32_t) pv_sample_rate_func()) {
199 fprintf(stderr,
"audio sample rate should be %d\n.", pv_sample_rate_func());
203 if (
f.bitsPerSample != 16) {
204 fprintf(stderr,
"audio format should be 16-bit\n.");
208 if (
f.channels != 1) {
209 fprintf(stderr,
"audio should be single-channel.\n");
213 int16_t *pcm = calloc(pv_porcupine_frame_length_func(),
sizeof(int16_t));
215 fprintf(stderr,
"failed to allocate memory for audio frame.\n");
220 pv_status_t status = pv_porcupine_init_func(access_key, model_path, 1, &keyword_path, &sensitivity, &porcupine);
222 fprintf(stderr,
"'pv_porcupine_init' failed with '%s'\n", pv_status_to_string_func(status));
226 fprintf(stdout,
"V%s\n\n", pv_porcupine_version_func());
228 double total_cpu_time_usec = 0;
229 double total_processed_time_usec = 0;
230 int32_t frame_index = 0;
233 struct timeval before;
234 gettimeofday(&before,
NULL);
236 int32_t keyword_index = -1;
237 status = pv_porcupine_process_func(porcupine, pcm, &keyword_index);
239 fprintf(stderr,
"'pv_porcupine_process' failed with '%s'\n", pv_status_to_string_func(status));
243 struct timeval after;
244 gettimeofday(&after,
NULL);
246 if (keyword_index != -1) {
247 fprintf(stdout,
"detected at %.1f seconds\n", (
double) frame_index * pv_porcupine_frame_length_func() / pv_sample_rate_func());
250 total_cpu_time_usec +=
251 (double) (after.tv_sec - before.tv_sec) * 1e6 + (double) (after.tv_usec - before.tv_usec);
252 total_processed_time_usec += (pv_porcupine_frame_length_func() * 1e6) / pv_sample_rate_func();
256 const double real_time_factor = total_cpu_time_usec / total_processed_time_usec;
257 fprintf(stdout,
"real time factor : %.3f\n", real_time_factor);
261 pv_porcupine_delete_func(porcupine);