884 lines
24 KiB
C
884 lines
24 KiB
C
#include "analog.h"
|
|
#include "audioflinger.h"
|
|
#include "hal_aud.h"
|
|
#include "hal_cmu.h"
|
|
#include "hal_sleep.h"
|
|
#include "hal_timer.h"
|
|
#include "hal_trace.h"
|
|
//#include "app_audio.h"
|
|
#include "app_utils.h"
|
|
#include "audio_dump.h"
|
|
#include "speech_ssat.h"
|
|
#include "voice_detector.h"
|
|
#include <string.h>
|
|
|
|
#include "pmu.h"
|
|
#ifdef __CYBERON
|
|
#include "CSpotterSDKApi.h"
|
|
#endif
|
|
|
|
#ifdef I2C_VAD
|
|
#include "vad_sensor.h"
|
|
#endif
|
|
|
|
/* This macro is used to show trace info for debugging */
|
|
#define VD_DEBUG
|
|
|
|
#ifdef VD_DEBUG
|
|
#define VD_LOG TRACE
|
|
#else
|
|
#define VD_LOG(...) \
|
|
do { \
|
|
} while (0)
|
|
#endif
|
|
|
|
#ifdef VD_TEST
|
|
#define VD_TRACE TRACE
|
|
#else
|
|
#define VD_TRACE(...) \
|
|
do { \
|
|
} while (0)
|
|
#endif
|
|
|
|
#define CMD_QUEUE_DATA_SIZE 15
|
|
|
|
struct command_queue {
|
|
int idx;
|
|
int out;
|
|
int data[CMD_QUEUE_DATA_SIZE];
|
|
};
|
|
|
|
struct voice_detector_dev {
|
|
uint8_t init;
|
|
uint8_t dfl;
|
|
uint8_t run;
|
|
enum voice_detector_state state;
|
|
uint32_t wakeup_cnt;
|
|
uint32_t arguments[VOICE_DET_CB_QTY];
|
|
voice_detector_cb_t callback[VOICE_DET_CB_QTY];
|
|
struct command_queue cmd_queue;
|
|
struct AUD_VAD_CONFIG_T conf;
|
|
struct AF_STREAM_CONFIG_T cap_conf;
|
|
struct AF_STREAM_CONFIG_T ply_conf;
|
|
struct CODEC_VAD_BUF_INFO_T vad_buf_info;
|
|
uint32_t sys_clk;
|
|
};
|
|
|
|
static struct voice_detector_dev voice_det_devs[VOICE_DETECTOR_QTY];
|
|
uint32_t vad_buf_len = 0;
|
|
|
|
short vad_buf[VAD_BUFFER_LEN] = {0};
|
|
|
|
#ifdef __CYBERON
|
|
static uint32_t POSSIBLY_UNUSED cyb_buf[20 * 1024];
|
|
static uint32_t POSSIBLY_UNUSED cyb_buf_used = 0;
|
|
|
|
extern unsigned char __g_cybase_start[];
|
|
extern unsigned char __g_cygroup_start[];
|
|
#define BASE_MODEL_DATA (__g_cybase_start)
|
|
#define COMMAND_MODEL_DATA (__g_cygroup_start)
|
|
HANDLE h_CSpotter = NULL;
|
|
#endif
|
|
|
|
static void voice_detector_vad_callback(int found);
|
|
static void voice_detector_exec_callback(struct voice_detector_dev *pdev,
|
|
enum voice_detector_cb_id id);
|
|
|
|
#define to_voice_dev(id) (&voice_det_devs[(id)])
|
|
|
|
static int cmd_queue_enqueue(struct command_queue *q, int c) {
|
|
if (q->idx >= CMD_QUEUE_DATA_SIZE) {
|
|
VD_LOG(2, "%s, overflow cmd=%d", __func__, c);
|
|
return -2;
|
|
}
|
|
if (q->idx < 0) {
|
|
q->idx = 0;
|
|
}
|
|
q->data[q->idx++] = c;
|
|
// VD_LOG(2, "%s, cmd=%d", __func__, c);
|
|
return 0;
|
|
}
|
|
|
|
static int cmd_queue_dequeue(struct command_queue *q) {
|
|
int cmd;
|
|
|
|
if (q->idx < 0) {
|
|
// VD_LOG(1, "%s, empty", __func__);
|
|
return -2;
|
|
}
|
|
if (q->out < 0) {
|
|
q->out = 0;
|
|
}
|
|
cmd = q->data[q->out++];
|
|
if (q->out >= q->idx) {
|
|
q->out = -1;
|
|
q->idx = -1;
|
|
}
|
|
// VD_LOG(2, "%s, cmd=%d", __func__, cmd);
|
|
return cmd;
|
|
}
|
|
|
|
static int cmd_queue_is_empty(struct command_queue *q) {
|
|
return (q->idx < 0) ? 1 : 0;
|
|
}
|
|
|
|
static void voice_detector_init_cmd_queue(struct command_queue *q) {
|
|
if (q) {
|
|
q->idx = -1;
|
|
q->out = -1;
|
|
}
|
|
}
|
|
|
|
static void voice_detector_init_vad(struct AUD_VAD_CONFIG_T *c, int id,
|
|
enum AUD_VAD_TYPE_T vad_type) {
|
|
if (c) {
|
|
c->type = vad_type;
|
|
#ifdef VAD_USE_8K_SAMPLE_RATE
|
|
c->sample_rate = AUD_SAMPRATE_8000;
|
|
#else
|
|
c->sample_rate = AUD_SAMPRATE_16000;
|
|
#endif
|
|
c->bits = AUD_BITS_16;
|
|
c->handler = voice_detector_vad_callback;
|
|
c->udc = VAD_DEFAULT_UDC;
|
|
c->upre = VAD_DEFAULT_UPRE;
|
|
#ifdef I2C_VAD
|
|
c->frame_len = VAD_DEFAULT_SENSOR_FRAME_LEN;
|
|
#else
|
|
c->frame_len = VAD_DEFAULT_MIC_FRAME_LEN;
|
|
#endif
|
|
c->mvad = VAD_DEFAULT_MVAD;
|
|
c->dig_mode = VAD_DEFAULT_DIG_MODE;
|
|
c->pre_gain = VAD_DEFAULT_PRE_GAIN;
|
|
c->sth = VAD_DEFAULT_STH;
|
|
c->dc_bypass = VAD_DEFAULT_DC_BYPASS;
|
|
c->frame_th[0] = VAD_DEFAULT_FRAME_TH0;
|
|
c->frame_th[1] = VAD_DEFAULT_FRAME_TH0;
|
|
c->frame_th[2] = VAD_DEFAULT_FRAME_TH0;
|
|
c->range[0] = VAD_DEFAULT_RANGE0;
|
|
c->range[1] = VAD_DEFAULT_RANGE1;
|
|
c->range[2] = VAD_DEFAULT_RANGE2;
|
|
c->range[3] = VAD_DEFAULT_RANGE3;
|
|
c->psd_th[0] = VAD_DEFAULT_PSD_TH0;
|
|
c->psd_th[1] = VAD_DEFAULT_PSD_TH1;
|
|
}
|
|
}
|
|
|
|
int voice_detector_open(enum voice_detector_id id,
|
|
enum AUD_VAD_TYPE_T vad_type) {
|
|
struct voice_detector_dev *pdev;
|
|
|
|
if (id >= VOICE_DETECTOR_QTY) {
|
|
VD_LOG(1, "%s, invalid id=%d", __func__, id);
|
|
return -1;
|
|
}
|
|
|
|
pdev = to_voice_dev(id);
|
|
if (pdev->init) {
|
|
VD_LOG(1, "%s, dev already open", __func__);
|
|
return -2;
|
|
}
|
|
if (pdev->run) {
|
|
VD_LOG(1, "%s, dev not stoped", __func__);
|
|
return -3;
|
|
}
|
|
|
|
memset(pdev, 0x0, sizeof(struct voice_detector_dev));
|
|
memset(&pdev->cap_conf, 0x0, sizeof(struct AF_STREAM_CONFIG_T));
|
|
memset(&pdev->ply_conf, 0x0, sizeof(struct AF_STREAM_CONFIG_T));
|
|
voice_detector_init_cmd_queue(&pdev->cmd_queue);
|
|
voice_detector_init_vad(&pdev->conf, id, vad_type);
|
|
pdev->state = VOICE_DET_STATE_IDLE;
|
|
pdev->run = 0;
|
|
pdev->dfl = 1;
|
|
pdev->init = 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void voice_detector_close(enum voice_detector_id id) {
|
|
struct voice_detector_dev *pdev;
|
|
|
|
if (id >= VOICE_DETECTOR_QTY) {
|
|
VD_LOG(2, "%s, invalid id=%d", __func__, id);
|
|
return;
|
|
}
|
|
|
|
pdev = to_voice_dev(id);
|
|
if (pdev->init) {
|
|
if (pdev->run) {
|
|
cmd_queue_enqueue(&pdev->cmd_queue, VOICE_DET_CMD_EXIT);
|
|
}
|
|
pdev->init = 0;
|
|
}
|
|
}
|
|
|
|
int voice_detector_setup_vad(enum voice_detector_id id,
|
|
struct AUD_VAD_CONFIG_T *conf) {
|
|
struct voice_detector_dev *pdev;
|
|
|
|
if (id >= VOICE_DETECTOR_QTY) {
|
|
VD_LOG(2, "%s, invalid id=%d", __func__, id);
|
|
return -1;
|
|
}
|
|
|
|
pdev = to_voice_dev(id);
|
|
if (!pdev->init) {
|
|
VD_LOG(1, "%s, dev not open", __func__);
|
|
return -2;
|
|
}
|
|
|
|
if (conf) {
|
|
memcpy(&pdev->conf, conf, sizeof(*conf));
|
|
pdev->conf.handler = voice_detector_vad_callback;
|
|
pdev->dfl = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int voice_detector_setup_stream(enum voice_detector_id id,
|
|
enum AUD_STREAM_T stream_id,
|
|
struct AF_STREAM_CONFIG_T *stream) {
|
|
struct voice_detector_dev *pdev;
|
|
|
|
if (id >= VOICE_DETECTOR_QTY) {
|
|
VD_LOG(2, "%s, invalid id=%d", __func__, id);
|
|
return -1;
|
|
}
|
|
|
|
pdev = to_voice_dev(id);
|
|
if (!pdev->init) {
|
|
VD_LOG(1, "%s, dev not open", __func__);
|
|
return -2;
|
|
}
|
|
|
|
if (stream_id == AUD_STREAM_CAPTURE)
|
|
memcpy(&pdev->cap_conf, stream, sizeof(struct AF_STREAM_CONFIG_T));
|
|
else
|
|
memcpy(&pdev->ply_conf, stream, sizeof(struct AF_STREAM_CONFIG_T));
|
|
|
|
return 0;
|
|
}
|
|
|
|
int voice_detector_setup_callback(enum voice_detector_id id,
|
|
enum voice_detector_cb_id func_id,
|
|
voice_detector_cb_t func, void *param) {
|
|
struct voice_detector_dev *pdev;
|
|
|
|
if (id >= VOICE_DETECTOR_QTY) {
|
|
VD_LOG(2, "%s, invalid id=%d", __func__, id);
|
|
return -1;
|
|
}
|
|
|
|
pdev = to_voice_dev(id);
|
|
if (!pdev->init) {
|
|
VD_LOG(1, "%s, dev not open", __func__);
|
|
return -2;
|
|
}
|
|
|
|
if (func_id >= VOICE_DET_CB_QTY) {
|
|
VD_LOG(2, "%s, invalid func_id=%d", __func__, func_id);
|
|
return -3;
|
|
}
|
|
pdev->arguments[func_id] = (uint32_t)param;
|
|
pdev->callback[func_id] = func;
|
|
return 0;
|
|
}
|
|
|
|
int voice_detector_send_cmd(enum voice_detector_id id,
|
|
enum voice_detector_cmd cmd) {
|
|
int r;
|
|
struct voice_detector_dev *pdev;
|
|
|
|
if (id >= VOICE_DETECTOR_QTY) {
|
|
VD_LOG(2, "%s, invalid id=%d", __func__, id);
|
|
return -1;
|
|
}
|
|
pdev = to_voice_dev(id);
|
|
|
|
r = cmd_queue_enqueue(&pdev->cmd_queue, (int)cmd);
|
|
return r;
|
|
}
|
|
|
|
int voice_detector_send_cmd_array(enum voice_detector_id id, int *cmd_array,
|
|
int num) {
|
|
int r, i;
|
|
struct voice_detector_dev *pdev;
|
|
|
|
if (id >= VOICE_DETECTOR_QTY) {
|
|
VD_LOG(2, "%s, invalid id=%d", __func__, id);
|
|
return -1;
|
|
}
|
|
pdev = to_voice_dev(id);
|
|
|
|
for (i = 0; i < num; i++) {
|
|
r = cmd_queue_enqueue(&pdev->cmd_queue, cmd_array[i]);
|
|
if (r)
|
|
return r;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
enum voice_detector_state
|
|
voice_detector_query_status(enum voice_detector_id id) {
|
|
struct voice_detector_dev *pdev;
|
|
|
|
if (id >= VOICE_DETECTOR_QTY) {
|
|
return VOICE_DET_STATE_IDLE;
|
|
}
|
|
pdev = to_voice_dev(id);
|
|
|
|
VD_LOG(2, "%s, state=%d", __func__, pdev->state);
|
|
return pdev->state;
|
|
}
|
|
|
|
static void voice_detector_vad_callback(int found) {
|
|
struct voice_detector_dev *pdev;
|
|
enum voice_detector_id id = VOICE_DETECTOR_ID_0;
|
|
|
|
pdev = to_voice_dev(id);
|
|
|
|
pdev->wakeup_cnt++;
|
|
|
|
VD_LOG(3, "%s, voice detector[%d], wakeup_cnt=%d", __func__, id,
|
|
pdev->wakeup_cnt);
|
|
|
|
if (pdev->wakeup_cnt == 1) {
|
|
/*
|
|
* VOICE_DET_CB_APP should be called only once
|
|
* after CPU is waked up from sleeping.
|
|
* The VAD already can gernerates interrupts at this monment or later.
|
|
*/
|
|
voice_detector_exec_callback(pdev, found ? VOICE_DET_FIND_APP
|
|
: VOICE_DET_NOT_FIND_APP);
|
|
}
|
|
}
|
|
|
|
static int voice_detector_vad_open(struct voice_detector_dev *pdev) {
|
|
struct AUD_VAD_CONFIG_T *c = &pdev->conf;
|
|
|
|
if (pdev->dfl) {
|
|
VD_LOG(1, "%s, use dfl vad", __func__);
|
|
}
|
|
af_vad_open(c);
|
|
#ifdef I2C_VAD
|
|
vad_sensor_open();
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static int voice_detector_vad_start(struct voice_detector_dev *pdev) {
|
|
/* wakeup_cnt is cleared while VAD starts */
|
|
pdev->wakeup_cnt = 0;
|
|
af_vad_start();
|
|
#ifdef I2C_VAD
|
|
vad_sensor_engine_start();
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static int voice_detector_vad_stop(struct voice_detector_dev *pdev) {
|
|
af_vad_stop();
|
|
|
|
#ifdef I2C_VAD
|
|
vad_sensor_engine_stop();
|
|
#else
|
|
/* get vad buf info after stopping it */
|
|
af_vad_get_data_info(&(pdev->vad_buf_info));
|
|
TRACE(4,
|
|
"vad_buf base_addr:0x%x, buf_size:0x%x, data_count:%d, addr_count:%d",
|
|
pdev->vad_buf_info.base_addr, pdev->vad_buf_info.buf_size,
|
|
pdev->vad_buf_info.data_count, pdev->vad_buf_info.addr_count);
|
|
#if defined(CHIP_BEST2300)
|
|
vad_buf_len = pdev->vad_buf_info.data_count / 2;
|
|
#else
|
|
vad_buf_len = pdev->vad_buf_info.data_count;
|
|
#endif
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
void voice_detector_get_vad_data_info(
|
|
enum voice_detector_id id, struct CODEC_VAD_BUF_INFO_T *vad_buf_info) {
|
|
|
|
struct voice_detector_dev *pdev;
|
|
|
|
pdev = to_voice_dev(id);
|
|
|
|
vad_buf_info->base_addr = pdev->vad_buf_info.base_addr;
|
|
vad_buf_info->buf_size = pdev->vad_buf_info.buf_size;
|
|
vad_buf_info->data_count = pdev->vad_buf_info.data_count;
|
|
vad_buf_info->addr_count = pdev->vad_buf_info.addr_count;
|
|
}
|
|
|
|
static int voice_detector_vad_close(struct voice_detector_dev *pdev) {
|
|
#ifdef I2C_VAD
|
|
vad_sensor_close();
|
|
#endif
|
|
af_vad_close();
|
|
return 0;
|
|
}
|
|
|
|
static int voice_detector_aud_cap_open(struct voice_detector_dev *pdev) {
|
|
struct AF_STREAM_CONFIG_T *conf = &pdev->cap_conf;
|
|
|
|
if ((!conf->handler) || (!conf->data_ptr)) {
|
|
VD_LOG(1, "%s, capture stream is null", __func__);
|
|
return -1;
|
|
}
|
|
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE, conf);
|
|
return 0;
|
|
}
|
|
|
|
static int voice_detector_aud_cap_start(struct voice_detector_dev *pdev) {
|
|
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
|
return 0;
|
|
}
|
|
|
|
static int voice_detector_aud_cap_stop(struct voice_detector_dev *pdev) {
|
|
af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
|
return 0;
|
|
}
|
|
|
|
static int voice_detector_aud_cap_close(struct voice_detector_dev *pdev) {
|
|
af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
|
return 0;
|
|
}
|
|
|
|
static int voice_detector_sys_clk(struct voice_detector_dev *pdev) {
|
|
#ifdef VD_TEST
|
|
app_sysfreq_req(APP_SYSFREQ_USER_APP_0,
|
|
(enum APP_SYSFREQ_FREQ_T)(pdev->sys_clk));
|
|
#else
|
|
app_sysfreq_req(APP_SYSFREQ_USER_AI_VOICE,
|
|
(enum APP_SYSFREQ_FREQ_T)(pdev->sys_clk));
|
|
#endif
|
|
// VD_TRACE(2,"%s, cpu freq=%d", __func__,
|
|
// hal_sys_timer_calc_cpu_freq(5,0));
|
|
return 0;
|
|
}
|
|
|
|
static int voice_detector_exit(struct voice_detector_dev *pdev) {
|
|
// TODO: exit process
|
|
return 0;
|
|
}
|
|
|
|
static int voice_detector_idle(struct voice_detector_dev *pdev) {
|
|
// TODO: idle process
|
|
return 0;
|
|
}
|
|
|
|
struct cmd_vector {
|
|
const char *name;
|
|
int cmd;
|
|
int (*func)(struct voice_detector_dev *pdev);
|
|
};
|
|
|
|
static struct cmd_vector cmd_vectors[] = {
|
|
{"idle", VOICE_DET_CMD_IDLE, voice_detector_idle},
|
|
{"exit", VOICE_DET_CMD_EXIT, voice_detector_exit},
|
|
{"vad open", VOICE_DET_CMD_VAD_OPEN, voice_detector_vad_open},
|
|
{"vad start", VOICE_DET_CMD_VAD_START, voice_detector_vad_start},
|
|
{"vad stop", VOICE_DET_CMD_VAD_STOP, voice_detector_vad_stop},
|
|
{"vad close", VOICE_DET_CMD_VAD_CLOSE, voice_detector_vad_close},
|
|
{"cap start", VOICE_DET_CMD_AUD_CAP_START, voice_detector_aud_cap_start},
|
|
{"cap stop", VOICE_DET_CMD_AUD_CAP_STOP, voice_detector_aud_cap_stop},
|
|
{"cap open", VOICE_DET_CMD_AUD_CAP_OPEN, voice_detector_aud_cap_open},
|
|
{"cap close", VOICE_DET_CMD_AUD_CAP_CLOSE, voice_detector_aud_cap_close},
|
|
{"clk32k", VOICE_DET_CMD_SYS_CLK_32K, voice_detector_sys_clk},
|
|
{"clk26m", VOICE_DET_CMD_SYS_CLK_26M, voice_detector_sys_clk},
|
|
{"clk52m", VOICE_DET_CMD_SYS_CLK_52M, voice_detector_sys_clk},
|
|
{"clk104m", VOICE_DET_CMD_SYS_CLK_104M, voice_detector_sys_clk},
|
|
};
|
|
|
|
static int voice_detector_process_cmd(struct voice_detector_dev *pdev,
|
|
int cmd) {
|
|
int err;
|
|
|
|
VD_LOG(3, "%s, cmd[%d]: %s", __func__, cmd, cmd_vectors[(int)cmd].name);
|
|
|
|
switch (cmd) {
|
|
case VOICE_DET_CMD_SYS_CLK_32K:
|
|
pdev->sys_clk = APP_SYSFREQ_32K;
|
|
break;
|
|
case VOICE_DET_CMD_SYS_CLK_26M:
|
|
pdev->sys_clk = APP_SYSFREQ_26M;
|
|
break;
|
|
case VOICE_DET_CMD_SYS_CLK_52M:
|
|
pdev->sys_clk = APP_SYSFREQ_52M;
|
|
break;
|
|
case VOICE_DET_CMD_SYS_CLK_104M:
|
|
pdev->sys_clk = APP_SYSFREQ_104M;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
err = cmd_vectors[(int)cmd].func(pdev);
|
|
return err;
|
|
}
|
|
|
|
static void voice_detector_set_status(struct voice_detector_dev *pdev,
|
|
enum voice_detector_state s) {
|
|
if ((s == VOICE_DET_STATE_SYS_CLK_104M) ||
|
|
(s == VOICE_DET_STATE_SYS_CLK_52M) ||
|
|
(s == VOICE_DET_STATE_SYS_CLK_26M) ||
|
|
(s == VOICE_DET_STATE_SYS_CLK_32K)) {
|
|
return;
|
|
}
|
|
pdev->state = s;
|
|
VD_LOG(2, "%s, state=%d", __func__, pdev->state);
|
|
}
|
|
|
|
static void voice_detector_exec_callback(struct voice_detector_dev *pdev,
|
|
enum voice_detector_cb_id id) {
|
|
voice_detector_cb_t func;
|
|
|
|
func = pdev->callback[id];
|
|
if (func) {
|
|
void *argv = (void *)(pdev->arguments[id]);
|
|
|
|
func(pdev->state, argv);
|
|
}
|
|
}
|
|
|
|
int voice_detector_enhance_perform(enum voice_detector_id id) {
|
|
struct voice_detector_dev *pdev = to_voice_dev(id);
|
|
|
|
pdev->sys_clk = APP_SYSFREQ_26M;
|
|
|
|
return app_sysfreq_req(APP_SYSFREQ_USER_AI_VOICE,
|
|
(enum APP_SYSFREQ_FREQ_T)(pdev->sys_clk));
|
|
}
|
|
|
|
int voice_detector_run(enum voice_detector_id id, int continous) {
|
|
int exit = 0;
|
|
int exit_code = 0;
|
|
struct voice_detector_dev *pdev;
|
|
|
|
if (id >= VOICE_DETECTOR_QTY) {
|
|
return -1;
|
|
}
|
|
|
|
pdev = to_voice_dev(id);
|
|
if (!pdev->init)
|
|
return -2;
|
|
|
|
voice_detector_exec_callback(pdev, VOICE_DET_CB_PREVIOUS);
|
|
pdev->run = 1;
|
|
while (1) {
|
|
int err = 0;
|
|
int cmd = cmd_queue_dequeue(&pdev->cmd_queue);
|
|
|
|
if (cmd < 0) {
|
|
// cmd is invalid, invoke waitting callback
|
|
voice_detector_exec_callback(pdev, VOICE_DET_CB_RUN_WAIT);
|
|
} else {
|
|
// cmd is okay, process it
|
|
err = voice_detector_process_cmd(pdev, cmd);
|
|
if (!err) {
|
|
voice_detector_set_status(pdev, (enum voice_detector_state)cmd);
|
|
voice_detector_exec_callback(pdev, VOICE_DET_CB_RUN_DONE);
|
|
} else {
|
|
voice_detector_exec_callback(pdev, VOICE_DET_CB_ERROR);
|
|
VD_LOG(3, "%s, process cmd %d error, %d", __func__, cmd, err);
|
|
}
|
|
}
|
|
switch (continous) {
|
|
case VOICE_DET_MODE_ONESHOT:
|
|
// not continous, run only once
|
|
exit_code = err;
|
|
exit = 1;
|
|
break;
|
|
case VOICE_DET_MODE_EXEC_CMD:
|
|
// continous run,exit until cmd queue is empty
|
|
if (cmd_queue_is_empty(&pdev->cmd_queue)) {
|
|
exit = 1;
|
|
exit_code = err;
|
|
// invoke waitting callback
|
|
voice_detector_exec_callback(pdev, VOICE_DET_CB_RUN_WAIT);
|
|
}
|
|
break;
|
|
case VOICE_DET_MODE_LOOP:
|
|
// continous run forever, exit until receive VOICE_DET_CMD_EXIT
|
|
if (cmd == VOICE_DET_CMD_EXIT) {
|
|
exit = 1;
|
|
exit_code = err;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (exit) {
|
|
break;
|
|
}
|
|
}
|
|
pdev->run = 0;
|
|
voice_detector_exec_callback(pdev, VOICE_DET_CB_POST);
|
|
|
|
return exit_code;
|
|
}
|
|
|
|
#ifdef VD_TEST
|
|
|
|
#include "app_voice_detector.h"
|
|
|
|
#define AUDIO_CAP_BUFF_SIZE (160 * 2 * 2 * 2)
|
|
|
|
static uint32_t buff_capture[AUDIO_CAP_BUFF_SIZE / 4];
|
|
static uint32_t voice_det_evt = 0;
|
|
static uint8_t vad_data_buf[8 * 1024];
|
|
|
|
static void voice_detector_send_evt(uint32_t evt) { voice_det_evt = evt; }
|
|
|
|
static void print_vad_raw_data(uint8_t *buf, uint32_t len) {
|
|
VD_TRACE(3, "%s, buf=%x, len=%d", __func__, (uint32_t)buf, len);
|
|
// TODO: print data
|
|
}
|
|
|
|
static int State_M_1 = 0;
|
|
void dc_filter_f(short *in, int len, float left_gain, float right_gain) {
|
|
int tmp1;
|
|
for (int i = 0; i < len; i += 1) {
|
|
State_M_1 = (15 * State_M_1 + in[i]) >> 4;
|
|
tmp1 = in[i];
|
|
tmp1 -= State_M_1;
|
|
in[i] = speech_ssat_int16(tmp1);
|
|
}
|
|
}
|
|
|
|
static uint32_t mic_data_come(uint8_t *buf, uint32_t len) {
|
|
static int come_cnt = 0;
|
|
short *p16data = (short *)buf;
|
|
uint32_t sample_len = len / 2;
|
|
int retcode = 0;
|
|
|
|
dc_filter_f(p16data, sample_len, 0.0, 0.0);
|
|
|
|
audio_dump_clear_up();
|
|
audio_dump_add_channel_data(0, p16data, sample_len);
|
|
// audio_dump_add_channel_data(1, temp_buf, sample_len);
|
|
audio_dump_run();
|
|
|
|
#ifdef __CYBERON
|
|
retcode = CSpotter_AddSample(h_CSpotter, p16data, sample_len);
|
|
|
|
if (retcode == CSPOTTER_SUCCESS) {
|
|
int id, score;
|
|
|
|
id = CSpotter_GetResult(h_CSpotter);
|
|
TRACE(1, "##### CSpotterGetResult return ID : %d\n", id);
|
|
|
|
score = CSpotter_GetResultScore(h_CSpotter);
|
|
TRACE(1, "CSpotter_GetResultScore return Score: %d", score);
|
|
|
|
CSpotter_Reset(h_CSpotter);
|
|
}
|
|
#endif
|
|
|
|
if (come_cnt % 100 == 0) {
|
|
TRACE(1, "retcode: %d", retcode);
|
|
}
|
|
come_cnt++;
|
|
// if ((come_cnt % 200) == 0) {
|
|
// VD_TRACE(3,"%s, buf=%x, len=%d", __func__, (uint32_t)buf, len);
|
|
// }
|
|
if ((come_cnt % 300) == 0) {
|
|
come_cnt = 0;
|
|
voice_detector_send_evt(VOICE_DET_EVT_VAD_START);
|
|
VD_TRACE(1, "%s, close audio stream ...", __func__);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef __CYBERON
|
|
static int CSpotter_Init_bes() {
|
|
#define TIMES (1000)
|
|
int err;
|
|
int state_size, mem_size;
|
|
uint8_t *state_buffer, *mem_pool;
|
|
uint8_t *p_combuf = (uint8_t *)cyb_buf;
|
|
|
|
TRACE(1, "%s", __func__);
|
|
|
|
state_size = CSpotter_GetStateSize((BYTE *)COMMAND_MODEL_DATA);
|
|
TRACE(2, "%s, state_size=%d", __func__, state_size);
|
|
|
|
state_buffer = p_combuf + cyb_buf_used;
|
|
cyb_buf_used += state_size;
|
|
if (!state_buffer) {
|
|
TRACE(0, "alloc state buff failed");
|
|
err = -1;
|
|
goto fail;
|
|
}
|
|
|
|
mem_size = CSpotter_GetMemoryUsage_Sep((BYTE *)BASE_MODEL_DATA,
|
|
(BYTE *)COMMAND_MODEL_DATA, TIMES);
|
|
TRACE(1, "mem_size=%d", mem_size);
|
|
|
|
mem_pool = p_combuf + cyb_buf_used;
|
|
cyb_buf_used += mem_size;
|
|
if (!mem_pool) {
|
|
TRACE(0, "alloc mem pool failed");
|
|
err = -2;
|
|
goto fail;
|
|
}
|
|
|
|
h_CSpotter = CSpotter_Init_Sep((BYTE *)BASE_MODEL_DATA,
|
|
(BYTE *)COMMAND_MODEL_DATA, TIMES, mem_pool,
|
|
mem_size, state_buffer, state_size, &err);
|
|
if (!h_CSpotter) {
|
|
TRACE(1, "CSpotter Init fail! err : %d\n", err);
|
|
err = -3;
|
|
goto fail;
|
|
}
|
|
|
|
return 0;
|
|
|
|
fail:
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
static void cmd_wait_handler(int state, void *param) {
|
|
voice_detector_send_evt(VOICE_DET_EVT_IDLE);
|
|
|
|
VD_TRACE(2, "%s, state=%d", __func__, state);
|
|
// hal_sys_timer_delay(MS_TO_TICKS(100));
|
|
// while(1);
|
|
|
|
// hal_sleep_enter_sleep();
|
|
}
|
|
|
|
static void cmd_done_handler(int state, void *param) {
|
|
VD_TRACE(2, "%s, state=%d", __func__, state);
|
|
}
|
|
|
|
static void cpu_det_find_wakeup_handler(int state, void *param) {
|
|
static uint32_t cpu_wakeup_cnt = 0;
|
|
|
|
cpu_wakeup_cnt++;
|
|
VD_TRACE(3, "%s, state=%d, cnt=%d", __func__, state, cpu_wakeup_cnt);
|
|
// VD_TRACE(2,"%s, calc sys freq=%d", __func__,
|
|
// hal_sys_timer_calc_cpu_freq(5,0));
|
|
|
|
voice_detector_send_evt(VOICE_DET_EVT_AUD_CAP_START);
|
|
}
|
|
|
|
static void cpu_det_notfind_wakeup_handler(int state, void *param) {
|
|
|
|
VD_TRACE(2, "%s, state=%d", __func__, state);
|
|
// VD_TRACE(2,"%s, calc sys freq=%d", __func__,
|
|
// hal_sys_timer_calc_cpu_freq(5,0));
|
|
|
|
voice_detector_send_evt(VOICE_DET_EVT_VAD_START);
|
|
}
|
|
|
|
void voice_detector_test(void) {
|
|
enum voice_detector_id id = VOICE_DETECTOR_ID_0;
|
|
int r, run;
|
|
struct AF_STREAM_CONFIG_T stream_cfg;
|
|
enum HAL_SLEEP_STATUS_T sleep;
|
|
uint32_t len;
|
|
|
|
VD_TRACE(1, "%s, start", __func__);
|
|
|
|
af_open();
|
|
|
|
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
|
|
|
stream_cfg.sample_rate = AUD_SAMPRATE_16000;
|
|
stream_cfg.bits = AUD_BITS_16;
|
|
stream_cfg.vol = 16;
|
|
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
|
stream_cfg.io_path = AUD_INPUT_PATH_VADMIC;
|
|
stream_cfg.channel_num = AUD_CHANNEL_NUM_1;
|
|
stream_cfg.handler = mic_data_come;
|
|
stream_cfg.data_ptr = (uint8_t *)buff_capture;
|
|
stream_cfg.data_size = AUDIO_CAP_BUFF_SIZE;
|
|
|
|
audio_dump_init(AUDIO_CAP_BUFF_SIZE / 2 / 2, sizeof(short), 1);
|
|
|
|
#ifdef __CYBERON
|
|
CSpotter_Init_bes();
|
|
#endif
|
|
|
|
r = voice_detector_open(id);
|
|
if (r) {
|
|
VD_TRACE(2, "%s, error %d", __func__, r);
|
|
return;
|
|
}
|
|
|
|
voice_detector_setup_stream(id, AUD_STREAM_CAPTURE, &stream_cfg);
|
|
voice_detector_setup_callback(id, VOICE_DET_CB_RUN_WAIT, cmd_wait_handler,
|
|
NULL);
|
|
voice_detector_setup_callback(id, VOICE_DET_CB_RUN_DONE, cmd_done_handler,
|
|
NULL);
|
|
voice_detector_setup_callback(id, VOICE_DET_FIND_APP,
|
|
cpu_det_find_wakeup_handler, NULL);
|
|
voice_detector_setup_callback(id, VOICE_DET_NOT_FIND_APP,
|
|
cpu_det_notfind_wakeup_handler, NULL);
|
|
|
|
VD_TRACE(2, "%s, calc sys freq=%d", __func__,
|
|
hal_sys_timer_calc_cpu_freq(5, 0));
|
|
|
|
voice_detector_send_cmd(id, VOICE_DET_CMD_AUD_CAP_OPEN);
|
|
voice_detector_send_cmd(id, VOICE_DET_CMD_AUD_CAP_CLOSE);
|
|
voice_detector_send_evt(VOICE_DET_EVT_VAD_START);
|
|
run = 0;
|
|
|
|
while (1) {
|
|
if (voice_det_evt != VOICE_DET_EVT_IDLE) {
|
|
switch (voice_det_evt) {
|
|
case VOICE_DET_EVT_VAD_START:
|
|
if (voice_detector_query_status(id) == VOICE_DET_STATE_VAD_CLOSE) {
|
|
voice_detector_send_cmd(id, VOICE_DET_CMD_AUD_CAP_STOP);
|
|
voice_detector_send_cmd(id, VOICE_DET_CMD_AUD_CAP_CLOSE);
|
|
}
|
|
// TODO: save current system clock
|
|
voice_detector_send_cmd(id, VOICE_DET_CMD_VAD_OPEN);
|
|
voice_detector_send_cmd(id, VOICE_DET_CMD_VAD_START);
|
|
voice_detector_send_cmd(id, VOICE_DET_CMD_SYS_CLK_32K);
|
|
run = 1;
|
|
break;
|
|
case VOICE_DET_EVT_AUD_CAP_START:
|
|
voice_detector_send_cmd(id, VOICE_DET_CMD_SYS_CLK_26M);
|
|
voice_detector_send_cmd(id, VOICE_DET_CMD_AUD_CAP_OPEN);
|
|
voice_detector_send_cmd(id, VOICE_DET_CMD_AUD_CAP_START);
|
|
voice_detector_send_cmd(id, VOICE_DET_CMD_VAD_STOP);
|
|
voice_detector_send_cmd(id, VOICE_DET_CMD_VAD_CLOSE);
|
|
// voice_detector_send_cmd(id, VOICE_DET_CMD_AUD_CAP_OPEN);
|
|
// voice_detector_send_cmd(id, VOICE_DET_CMD_AUD_CAP_START);
|
|
run = 1;
|
|
break;
|
|
default:
|
|
run = 0;
|
|
break;
|
|
}
|
|
voice_det_evt = VOICE_DET_EVT_IDLE;
|
|
}
|
|
if (run) {
|
|
run = 0;
|
|
voice_detector_run(id, VOICE_DET_MODE_EXEC_CMD);
|
|
}
|
|
|
|
#ifndef RTOS
|
|
extern void af_thread(void const *argument);
|
|
af_thread(NULL);
|
|
#endif
|
|
|
|
// while(1);
|
|
sleep = hal_sleep_enter_sleep();
|
|
if (sleep == HAL_SLEEP_STATUS_DEEP) {
|
|
VD_TRACE(0, "wake up from deep sleep");
|
|
}
|
|
|
|
len = voice_detector_recv_vad_data(VOICE_DETECTOR_ID_0, vad_data_buf,
|
|
sizeof(vad_data_buf));
|
|
if (len) {
|
|
print_vad_raw_data(vad_data_buf, len);
|
|
}
|
|
}
|
|
}
|
|
#endif
|