typedef struct { struct timeval major_time; struct timeval minor_time; } wakeup_info_t; static int wakeup_callback(void *userdata, int type, char *data, int len) { wakeup_info_t *info = (wakeup_info_t *)userdata; OS_LOG_I(wakeup, "WAKEUP:%s", data); cJSON *js = cJSON_Parse(data); if (js) { dui_msg_t m; memset(&m, 0, sizeof(m)); m.wakeup.index = -1; cJSON *major_js = cJSON_GetObjectItem(js, "major"); cJSON *word_js = cJSON_GetObjectItem(js, "wakeupWord"); m.wakeup.major = (major_js->valueint != 0) ? true : false; if (m.wakeup.major) { m.type = WAKEUP_INFO_WAKEUP; m.wakeup.last_major_time = info->major_time; gettimeofday(&m.wakeup.cur_major_time, NULL); info->major_time = m.wakeup.cur_major_time; } else { m.type = WAKEUP_INFO_WAKEUP_MINOR; m.wakeup.last_minor_time = info->minor_time; gettimeofday(&m.wakeup.cur_minor_time, NULL); info->minor_time = m.wakeup.cur_minor_time; } int i; for (i = 0; i < g_cfg.wakeup.word_count; i++) { if (is_same_word(word_js->valuestring, g_cfg.wakeup.word[i])) { m.wakeup.index = i; break; } } cJSON_Delete(js); if (m.wakeup.index != -1) { os_queue_send(process_queue, &m); os_queue_send(user_listen_queue, &m); } } return 0; } static int beamforming_callback(void *userdata, int type, char *data, int len) { if (type == DUILITE_MSG_TYPE_JSON) { } else { #ifdef SAVE_AUDIO fwrite(data, 1, len, output_fd); #endif os_stream_write(vad_stream, data, len); } return 0; } static int doa_callback(void *userdata, int type, char *data, int len) { dui_msg_t m; memset(&m, 0, sizeof(m)); m.type = WAKEUP_INFO_DOA; OS_LOG_I(wakeup, "DOA: %s", data); cJSON *js = cJSON_Parse(data); if (js) { cJSON *doa_js = cJSON_GetObjectItem(js, "doa"); m.wakeup.doa = doa_js->valueint; cJSON_Delete(js); os_queue_send(user_listen_queue, &m); } return 0; } static void wakeup_run(void *args) { int ret; dui_msg_t m; wakeup_info_t info; memset(&info, 0, sizeof(info)); //50ms int read_buf_size = g_cfg.recorder.channels * g_cfg.recorder.bits / 8 * g_cfg.recorder.samplerate / 20; char *read_buf = (char *)os_malloc(read_buf_size); assert(read_buf != NULL); OS_LOG_I(wakeup, "%s", g_cfg.wakeup.cfg); struct duilite_fespa *fespa_engine = duilite_fespa_new(g_cfg.wakeup.cfg); assert(fespa_engine != NULL); duilite_fespa_register(fespa_engine, DUILITE_CALLBACK_FESPA_WAKEUP, wakeup_callback, &info); duilite_fespa_register(fespa_engine, DUILITE_CALLBACK_FESPA_DOA, doa_callback, NULL); duilite_fespa_register(fespa_engine, DUILITE_CALLBACK_FESPA_BEAMFORMING, beamforming_callback, NULL); //置位线程READY标志 os_event_group_set_bits(task_ready_ev, WAKEUP_READY_BIT); OS_LOG_I(wakeup, "READY"); while (1) { ret = os_queue_receive(wakeup_queue, &m); if (ret == -1) break; OS_LOG_I(wakeup, "%s", dui_msg_table[m.type]); if (m.type == WAKEUP_CMD_START) { OS_LOG_I(wakeup, "START"); //注意:duilite_fespa_start内部会清空已有数据,避免数据乱序 duilite_fespa_start(fespa_engine, g_cfg.wakeup.param); int read_bytes; while (1) { read_bytes = os_stream_read(wakeup_stream, read_buf, read_buf_size); if (read_bytes == -1) break; //录音缓冲被终止 #ifdef SAVE_AUDIO fwrite(read_buf, 1, read_bytes, input_fd); #endif duilite_fespa_feed(fespa_engine, read_buf, read_bytes); } } else if (m.type == WAKEUP_CMD_STOP) { os_queue_send(user_listen_queue, &m); OS_LOG_I(wakeup, "STOP"); } } os_free(read_buf); duilite_fespa_delete(fespa_engine); OS_LOG_I(wakeup, "EXIT"); }