aisppech-2mic-32bit: commit for 32bit
Change-Id: I029af5d2015800cc62971c65b2986b6a9e4d3344 Signed-off-by: Nyx Zheng <zyh@rock-chips.com>
This commit is contained in:
56
rk3308/aispeech-2mic-32bit/RkLunch.sh
Executable file
56
rk3308/aispeech-2mic-32bit/RkLunch.sh
Executable file
@ -0,0 +1,56 @@
|
||||
arecord -D vad -c 8 -r 16000 -f S16_LE -d 1 -t raw /tmp/test.pcm
|
||||
rm /tmp/test.pcm
|
||||
echo 0x60 0x40ff0050 > /sys/kernel/debug/vad/reg
|
||||
echo 0x5c 0x000e2080 > /sys/kernel/debug/vad/reg
|
||||
|
||||
ln -s /oem/aispeech_softap_lite /data/aispeech_softap_lite
|
||||
ln -s /oem/wifi_monitor.sh /data/
|
||||
ln -s /oem/dds_client /data/dds_client
|
||||
ln -s /oem/dds_service.sh /data/
|
||||
|
||||
export AISPEECH_WIFI_CFG="/data/wpa_supplicant.conf"
|
||||
|
||||
#aispeech dui app information file
|
||||
export AISPEECH_DUIKIT_APP="/data/aispeech_softap_lite/device/app.json"
|
||||
|
||||
#aispeech dui device file
|
||||
export AISPEECH_DUIKIT_DEVICE="/data/aispeech_softap_lite/device/device.json"
|
||||
|
||||
#aispeech dui softap web server address
|
||||
export AISPEECH_SOFTAP_SERVER_PORT="8000"
|
||||
|
||||
#aispeech dui softap configuration folder
|
||||
export AISPEECH_SOFTAP_DIR="/data/cfg"
|
||||
|
||||
export AISPEECH_DO_CONNECT_MP3="/data/aispeech_softap_lite/audio/do_connect.mp3"
|
||||
|
||||
export AISPEECH_WIFI_OK_MP3="/data/aispeech_softap_lite/audio/wifi_ok.mp3"
|
||||
|
||||
export AISPEECH_NEED_CONNECT_MP3="/data/aispeech_softap_lite/audio/need_connect.mp3"
|
||||
|
||||
export AISPEECH_CONNECT_OK_MP3="/data/aispeech_softap_lite/audio/connect_ok.mp3"
|
||||
|
||||
export AISPEECH_START_CONNECT_MP3="/data/aispeech_softap_lite/audio/start_connect.mp3"
|
||||
|
||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/userdata:/userdata/bin:/data/bin:/data/bin/rk_pcba_test:/data/aispeech_softap_lite/bin
|
||||
|
||||
#if [ -f ${AISPEECH_WIFI_CFG} ]; then
|
||||
#aispeech_player ${AISPEECH_WIFI_OK_MP3}
|
||||
# aispeech_led -m on 6
|
||||
# wpa_supplicant -B -i wlan0 -c ${AISPEECH_WIFI_CFG} &
|
||||
# dhcpcd &
|
||||
# aispeech_player ${AISPEECH_DO_CONNECT_MP3}
|
||||
#else
|
||||
# aispeech_player ${AISPEECH_NEED_CONNECT_MP3} &
|
||||
# aispeech_led -m breath 1 -s 500
|
||||
# ifconfig wlan0 down
|
||||
# aispeech_softap_server -s aiengine -p 12345678 start &
|
||||
#fi
|
||||
#aispeech_startup &
|
||||
|
||||
#/data/wifi_monitor.sh &
|
||||
|
||||
wpa_supplicant -B -i wlan0 -c /data/wpa_supplicant.conf
|
||||
|
||||
cd /oem/dds_client/demo/
|
||||
./demo_main &
|
||||
39
rk3308/aispeech-2mic-32bit/dds_client/audio_player.h
Executable file
39
rk3308/aispeech-2mic-32bit/dds_client/audio_player.h
Executable file
@ -0,0 +1,39 @@
|
||||
#ifndef __AUDIO_PLAYER_H__
|
||||
#define __AUDIO_PLAYER_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define AUDIO_PLAYER_EXPORT __attribute ((visibility("default")))
|
||||
|
||||
#define AUDIO_PLAYER_EV_BEGIN 0x01
|
||||
#define AUDIO_PLAYER_EV_START 0x02
|
||||
#define AUDIO_PLAYER_EV_END 0x03
|
||||
#define AUDIO_PLAYER_EV_ERROR 0x04
|
||||
#define AUDIO_PLAYER_EV_PAUSED 0x05
|
||||
#define AUDIO_PLAYER_EV_PLAYING 0x06
|
||||
#define AUDIO_PLAYER_EV_STOPPED 0x07
|
||||
|
||||
typedef int (*audio_player_callback)(void *userdata, int ev);
|
||||
typedef struct audio_player audio_player_t;
|
||||
|
||||
AUDIO_PLAYER_EXPORT audio_player_t *audio_player_new(audio_player_callback ccb, void *userdata);
|
||||
AUDIO_PLAYER_EXPORT int audio_player_delete(audio_player_t *aplayer);
|
||||
AUDIO_PLAYER_EXPORT int audio_player_play(audio_player_t *aplayer, char *path);
|
||||
AUDIO_PLAYER_EXPORT int audio_player_pause(audio_player_t *aplayer);
|
||||
AUDIO_PLAYER_EXPORT int audio_player_resume(audio_player_t *aplayer);
|
||||
AUDIO_PLAYER_EXPORT int audio_player_stop(audio_player_t *aplayer);
|
||||
|
||||
AUDIO_PLAYER_EXPORT int audio_player_get_volume(char *dev, int *l_vol, int *r_vol);
|
||||
AUDIO_PLAYER_EXPORT int audio_player_set_volume(char *dev, int l_vol, int r_vol);
|
||||
|
||||
AUDIO_PLAYER_EXPORT int audio_player_set_channel_volume(audio_player_t *aplayer, float multiplier);
|
||||
|
||||
AUDIO_PLAYER_EXPORT int audio_player_set_device(audio_player_t *aplayer, char *device);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
92
rk3308/aispeech-2mic-32bit/dds_client/dds_client.h
Executable file
92
rk3308/aispeech-2mic-32bit/dds_client/dds_client.h
Executable file
@ -0,0 +1,92 @@
|
||||
/*================================================================
|
||||
* * Copyright (C) 2018 AISpeech Ltd. All rights reserved.
|
||||
* *
|
||||
* * 文件名称:dds_client.h
|
||||
* * 创建日期:2018年04月06日
|
||||
* * 描 述:
|
||||
* *
|
||||
* ================================================================*/
|
||||
|
||||
|
||||
#ifndef _DDS_CLIENT_H
|
||||
#define _DDS_CLIENT_H
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define DDS_CLIENT_VERSION "DDS_CLIENT 0.1.10"
|
||||
|
||||
#define DDS_CLIENT_TTS_ZHILING "zhilingf" // 甜美女神
|
||||
#define DDS_CLIENT_TTS_GDG "gdgm" // 沉稳纲叔
|
||||
#define DDS_CLIENT_TTS_GEYOU "geyou" // 淡定葛爷
|
||||
#define DDS_CLIENT_TTS_HYANIF "hyanif" // 邻家女声
|
||||
#define DDS_CLIENT_TTS_XIJUNM "xijunm" // 标准男声
|
||||
#define DDS_CLIENT_TTS_QIANRAN "qianranf" // 可爱童声
|
||||
#define DDS_CLIENT_TTS_LUCYF "lucyf" // 标准女声
|
||||
|
||||
#define DDS_CLIENT_USER_EV_BASE 1000
|
||||
#define DDS_CLIENT_USER_DEVICE_MODE 1001
|
||||
|
||||
struct dds_client;
|
||||
|
||||
typedef void (*ddsLintener)(const char *topic, const char *topic_data, void *user);
|
||||
|
||||
struct dds_client *dds_client_init (const char *config_json);
|
||||
|
||||
int dds_client_start(struct dds_client *, ddsLintener cb, void *user);
|
||||
|
||||
void dds_client_release(struct dds_client *);
|
||||
|
||||
// 发送事件给 sdk
|
||||
int dds_client_publish(struct dds_client *ds, int ev, const char *data);
|
||||
|
||||
/*
|
||||
* 对 nativeAPI 命令做出查询回应的接口,其中 native_api_data_json 的格式如下:
|
||||
* duiWidget 字段表示 dui 控件的类型,当前仅支持 "text"。
|
||||
* extra 字段用于返回用户的数据。
|
||||
* {
|
||||
* "duiWidget":"text",
|
||||
* "extra": {
|
||||
* "xx": "11"
|
||||
* }
|
||||
* }
|
||||
* 出错时返回值为 -1。
|
||||
*/
|
||||
int dds_client_resp_nativeapi(struct dds_client *ds, const char *native_api,
|
||||
const char *native_api_data_json);
|
||||
/*
|
||||
* 录音机接口
|
||||
*/
|
||||
int dds_client_feed_audio(struct dds_client *ds, char *data, int len);
|
||||
|
||||
/*
|
||||
* 对话的接口
|
||||
*/
|
||||
int dds_client_stop_dialog(struct dds_client *ds);
|
||||
|
||||
/*
|
||||
* tts 的相关接口
|
||||
*/
|
||||
int dds_client_speak(struct dds_client *ds, const char *text);
|
||||
char *dds_client_get_speaker(struct dds_client *ds);
|
||||
float dds_client_get_speed(struct dds_client *ds);
|
||||
int dds_client_get_volume(struct dds_client *ds);
|
||||
|
||||
int dds_client_set_speaker(struct dds_client *ds, char *speaker);
|
||||
int dds_client_set_speed(struct dds_client *ds, float speed);
|
||||
int dds_client_set_volume(struct dds_client *ds, int vol);
|
||||
|
||||
/*
|
||||
* 唤醒的相关设置
|
||||
*/
|
||||
int dds_client_disable_wakeup(struct dds_client *ds);
|
||||
int dds_client_enable_wakeup(struct dds_client *ds);
|
||||
int dds_client_update_customword(struct dds_client *ds, const char *word);
|
||||
char* dds_client_get_wakeupwords(struct dds_client *ds);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif //DDS_CLIENT_H
|
||||
|
||||
26
rk3308/aispeech-2mic-32bit/dds_client/demo/aimakefile
Executable file
26
rk3308/aispeech-2mic-32bit/dds_client/demo/aimakefile
Executable file
@ -0,0 +1,26 @@
|
||||
LOCAL_MODULE := demo_main
|
||||
LOCAL_SRC_FILES += main.c
|
||||
LOCAL_SRC_FILES += music.c
|
||||
LOCAL_SRC_DIRS += json
|
||||
#LOCAL_SRC_DIRS += button
|
||||
LOCAL_SRC_DIRS += busserver/mongoose
|
||||
LOCAL_SRC_DIRS += busserver/src/busserver.c
|
||||
|
||||
LOCAL_CFLAGS := -rdynamic -g -O0 -Wall -DMG_ENABLE_THREADS -Wno-unused-variable -fPIC
|
||||
LOCAL_CFLAGS += -I.. -Ijson/ -Ibutton/ -Ibusserver/mongoose -Ibusserver/src
|
||||
|
||||
LOCAL_LDFLAGS += -Wl,-rpath,../
|
||||
LOCAL_LDFLAGS += -L../ -ldds_client
|
||||
|
||||
LOCAL_LDFLAGS += -Wl,-rpath,../libs/
|
||||
LOCAL_LDFLAGS += -L../libs/ -lduilite_fespl
|
||||
LOCAL_LDFLAGS += -L../libs/ -lauth
|
||||
LOCAL_LDFLAGS += -L../libs/ -ldds
|
||||
LOCAL_LDFLAGS += -L../libs/ -laudio_play
|
||||
LOCAL_LDFLAGS += -lpthread
|
||||
LOCAL_LDFLAGS += -lasound
|
||||
|
||||
|
||||
LOCAL_CXXFLAGS := LOCAL_CFLAGS -rdynamic
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/aispeech_led
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/aispeech_led
Executable file
Binary file not shown.
12
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/aimakefile
Executable file
12
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/aimakefile
Executable file
@ -0,0 +1,12 @@
|
||||
LOCAL_MODULE := test
|
||||
LOCAL_SRC_DIRS += mongoose
|
||||
LOCAL_SRC_DIRS += src
|
||||
|
||||
LOCAL_CFLAGS := -rdynamic -g -O0 -Wall -DMG_ENABLE_THREADS -Wno-unused-variable -fPIC
|
||||
LOCAL_CFLAGS += -Imongoose
|
||||
|
||||
LOCAL_LDFLAGS += -lpthread
|
||||
|
||||
LOCAL_CXXFLAGS := LOCAL_CFLAGS -rdynamic
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
16
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/mongoose/LICENSE
Executable file
16
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/mongoose/LICENSE
Executable file
@ -0,0 +1,16 @@
|
||||
Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
|
||||
Copyright (c) 2013-2016 Cesanta Software Limited
|
||||
All rights reserved
|
||||
|
||||
This software is dual-licensed: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
published by the Free Software Foundation. For the terms of this
|
||||
license, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You are free to use this software under the terms of the GNU General
|
||||
Public License, but WITHOUT ANY WARRANTY; without even the implied
|
||||
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
Alternatively, you can license this software under a commercial
|
||||
license, as set out in <https://www.cesanta.com/license>.
|
||||
12332
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/mongoose/mongoose.c
Executable file
12332
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/mongoose/mongoose.c
Executable file
File diff suppressed because it is too large
Load Diff
4340
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/mongoose/mongoose.h
Executable file
4340
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/mongoose/mongoose.h
Executable file
File diff suppressed because it is too large
Load Diff
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/mongoose/mongoose.o
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/mongoose/mongoose.o
Executable file
Binary file not shown.
188
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/src/busserver.c
Executable file
188
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/src/busserver.c
Executable file
@ -0,0 +1,188 @@
|
||||
/*================================================================
|
||||
* Copyright (C) 2018 FREEDOM Ltd. All rights reserved.
|
||||
*
|
||||
* 文件名称:busserver.c
|
||||
* 创 建 者:chenjie.gu
|
||||
* 创建日期:2018年05月23日
|
||||
* 描 述:
|
||||
*
|
||||
================================================================*/
|
||||
|
||||
|
||||
#include "busserver.h"
|
||||
#include "mongoose.h"
|
||||
|
||||
#define BUSCLIENT_KEEPALIVE 1
|
||||
#define BUSCLIENT_RPC_REQUEST 2
|
||||
#define BUSCLIENT_RPC_RESPONSE 3
|
||||
#define BUSCLIENT_SEND_TOPIC 4
|
||||
#define BUSCLIENT_RECV_TOPIC 5
|
||||
|
||||
struct mg_connection *conn = NULL;
|
||||
event_cb user_cb = NULL;
|
||||
void *user = NULL;
|
||||
|
||||
struct message {
|
||||
struct multipart bm;
|
||||
};
|
||||
|
||||
static int find_in_str(const char *p)
|
||||
{
|
||||
char *pos = strstr(p, "\r\n");
|
||||
if (pos == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return pos - p;
|
||||
}
|
||||
|
||||
static int busclient_parse_multipart_msg(struct mg_connection *nc, struct message *msg, int *type)
|
||||
{
|
||||
const char *pp = nc->recv_mbuf.buf;
|
||||
const char *p = pp;
|
||||
int len = nc->recv_mbuf.len;
|
||||
int handle_len = 0, reserve_len = len, part_len = 0, _len = 0, n = 0;
|
||||
|
||||
for (int i = 0; i < BUSCLIENT_MAX_MULTIPART_OPT; ++i) {
|
||||
_len = find_in_str(p);
|
||||
part_len = atoi(p);
|
||||
if( reserve_len >= _len+2+part_len+2 && strncmp(p+_len,"\r\n",2)==0 && strncmp(p+_len+2+part_len, "\r\n", 2) == 0) {
|
||||
msg->bm.part[n].len = part_len;
|
||||
msg->bm.part[n].data = p + _len + 2;
|
||||
n++;
|
||||
msg->bm.n = n;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
handle_len = handle_len + _len + 2 + part_len + 2;
|
||||
reserve_len = len - handle_len;
|
||||
p = pp + handle_len;
|
||||
|
||||
if (reserve_len >=2 && strncmp(p, "\r\n", 2) == 0) {
|
||||
if (strncmp(msg->bm.part[0].data, "keepalive", strlen("keepalive")) == 0) {
|
||||
*type = BUSCLIENT_KEEPALIVE;
|
||||
}
|
||||
if (strncmp(msg->bm.part[0].data, "request", strlen("request")) == 0) {
|
||||
*type = BUSCLIENT_RPC_REQUEST;
|
||||
}
|
||||
if (strncmp(msg->bm.part[0].data, "response", strlen("response")) == 0) {
|
||||
*type = BUSCLIENT_RPC_RESPONSE;
|
||||
}
|
||||
if (strncmp(msg->bm.part[0].data, "publish", strlen("publish")) == 0) {
|
||||
*type = BUSCLIENT_RECV_TOPIC;
|
||||
}
|
||||
return handle_len + 2;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void busclient_mg_send(struct mg_connection *nc, const char *data, int len)
|
||||
{
|
||||
char tmp[10] = { 0 };
|
||||
int _len = 0;
|
||||
|
||||
_len = sprintf(tmp, "%d", len);
|
||||
mg_send(nc, tmp, _len);
|
||||
mg_send(nc, "\r\n", 2);
|
||||
mg_send(nc, data, len);
|
||||
mg_send(nc, "\r\n", 2);
|
||||
}
|
||||
|
||||
static void busclient_multipart_send(struct mg_connection *nc, struct multipart *bm) {
|
||||
for (int i = 0; i < bm->n; i++) {
|
||||
busclient_mg_send(nc, bm->part[i].data, bm->part[i].len);
|
||||
}
|
||||
mg_send(nc, "\r\n", 2);
|
||||
}
|
||||
|
||||
|
||||
static void handle_multipart_msg(struct mg_connection *nc, struct message *msg) {
|
||||
if (!strncmp(msg->bm.part[0].data, "request", msg->bm.part[0].len)) {
|
||||
if (!strncmp(msg->bm.part[1].data, "/bus/join", msg->bm.part[1].len)) {
|
||||
struct multipart m = {1, {
|
||||
{strlen("response"), "response"}
|
||||
}};
|
||||
|
||||
busclient_multipart_send(nc, &m);
|
||||
}
|
||||
else if (!strncmp(msg->bm.part[1].data, "/bus/subscribe", msg->bm.part[1].len)) {
|
||||
struct multipart m = {1, {
|
||||
{strlen("response"), "response"}
|
||||
}};
|
||||
|
||||
busclient_multipart_send(nc, &m);
|
||||
}
|
||||
}
|
||||
|
||||
else if (!strncmp(msg->bm.part[0].data, "publish", msg->bm.part[0].len)) {
|
||||
if (!strncmp(msg->bm.part[1].data, "ui.control.topics", msg->bm.part[1].len)) {
|
||||
if (user_cb) {
|
||||
user_cb("ui.control.topics", msg->bm.part[2].data, msg->bm.part[2].len, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ev_handler(struct mg_connection *nc, int ev, void *p) {
|
||||
struct mbuf *io = &nc->recv_mbuf;
|
||||
(void) p;
|
||||
|
||||
switch (ev) {
|
||||
case MG_EV_RECV:
|
||||
conn = nc;
|
||||
// receive multipart
|
||||
int len = 0, type = 0;
|
||||
struct message msg;
|
||||
while (1) {
|
||||
len = busclient_parse_multipart_msg(nc, &msg, &type);
|
||||
if (len == -1 || type == 0) break;
|
||||
handle_multipart_msg(nc, &msg);
|
||||
mbuf_remove(&nc->recv_mbuf, len);
|
||||
}
|
||||
break;
|
||||
|
||||
case MG_EV_TIMER:
|
||||
{
|
||||
struct multipart *m = (struct multipart *)p;
|
||||
busclient_multipart_send(nc, m);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void busserver_run(const char *addr, event_cb cb, void *u) {
|
||||
//
|
||||
struct mg_mgr mgr;
|
||||
mg_mgr_init(&mgr, NULL);
|
||||
mg_bind(&mgr, addr, ev_handler);
|
||||
|
||||
user_cb = cb;
|
||||
user = u;
|
||||
|
||||
for (;;) {
|
||||
mg_mgr_poll(&mgr, 100);
|
||||
}
|
||||
|
||||
mg_mgr_free(&mgr);
|
||||
}
|
||||
|
||||
int busserver_send_msg(const char *topic, const char *data) {
|
||||
|
||||
if (!topic) return -1;
|
||||
|
||||
struct multipart m = {3, {
|
||||
{strlen("publish"), "publish"},
|
||||
{strlen(topic), topic},
|
||||
{strlen(data), data}
|
||||
}};
|
||||
|
||||
if (conn)
|
||||
ev_handler(conn, MG_EV_TIMER, &m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
31
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/src/busserver.h
Executable file
31
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/src/busserver.h
Executable file
@ -0,0 +1,31 @@
|
||||
#ifndef BUSSERVER_H_
|
||||
#define BUSSERVER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct bc_str {
|
||||
int len;
|
||||
const char *data;
|
||||
};
|
||||
|
||||
#define BUSCLIENT_MAX_MULTIPART_OPT 20
|
||||
|
||||
struct multipart {
|
||||
int n;
|
||||
// int capacity;
|
||||
struct bc_str part[BUSCLIENT_MAX_MULTIPART_OPT];
|
||||
};
|
||||
|
||||
typedef void (*event_cb)(const char *topic, const char *topic_data, int data_len, void *user);
|
||||
|
||||
void busserver_run(const char *addr, event_cb, void *user);
|
||||
|
||||
int busserver_send_msg(const char *topic, const char *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/src/busserver.o
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/src/busserver.o
Executable file
Binary file not shown.
43
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/src/main.c
Executable file
43
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/src/main.c
Executable file
@ -0,0 +1,43 @@
|
||||
/*================================================================
|
||||
* Copyright (C) 2018 FREEDOM Ltd. All rights reserved.
|
||||
*
|
||||
* 文件名称:main.c
|
||||
* 创 建 者:chenjie.gu
|
||||
* 创建日期:2018年05月23日
|
||||
* 描 述:
|
||||
*
|
||||
================================================================*/
|
||||
|
||||
#include "busserver.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/select.h>
|
||||
#include <pthread.h>
|
||||
|
||||
void cb(const char *topic, const char *topic_data, void *user) {
|
||||
|
||||
printf("%s: %s\n", topic, topic_data);
|
||||
|
||||
}
|
||||
|
||||
void *busserver_routine(void *user) {
|
||||
busserver_run("127.0.0.1:50001", cb, NULL);
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
int main () {
|
||||
//
|
||||
//
|
||||
|
||||
int ret = 0;
|
||||
pthread_t tid;
|
||||
ret = pthread_create(&tid, NULL, busserver_routine, NULL);
|
||||
|
||||
struct timeval tv = {10, 0};
|
||||
select(0, 0, 0, 0, &tv);
|
||||
|
||||
busserver_send_msg("bus.event", "yyyyyyyyyyy");
|
||||
|
||||
select(0, 0, 0, 0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/src/main.o
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/src/main.o
Executable file
Binary file not shown.
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/test
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/busserver/test
Executable file
Binary file not shown.
55
rk3308/aispeech-2mic-32bit/dds_client/demo/button/button.h
Executable file
55
rk3308/aispeech-2mic-32bit/dds_client/demo/button/button.h
Executable file
@ -0,0 +1,55 @@
|
||||
#ifndef BUTTON_H
|
||||
#define BUTTON_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum {
|
||||
//短按触发
|
||||
BUTTON_EVENT_VOLUME_ADD = 0,
|
||||
//短按触发
|
||||
BUTTON_EVENT_VOLUME_SUB,
|
||||
//长按每隔1.5秒触发一次
|
||||
BUTTON_EVENT_PREV,
|
||||
//长按每隔1.5秒触发一次
|
||||
BUTTON_EVENT_NEXT,
|
||||
//短按触发
|
||||
BUTTON_EVENT_PLAY_PAUSE,
|
||||
//长按1.5秒后触发
|
||||
BUTTON_EVENT_PLAY_PAUSE_LONG,
|
||||
//短按触发
|
||||
BUTTON_EVENT_MUTE_UNMUTE,
|
||||
//长按1.5秒触发
|
||||
BUTTON_EVENT_MUTE_UNMUTE_LONG,
|
||||
//长按3秒触发
|
||||
BUTTON_EVENT_MODE_WIFI,
|
||||
//短按触发
|
||||
BUTTON_EVENT_MODE_NORMAL,
|
||||
BUTTON_EVENT_MAX
|
||||
}button_event_t;
|
||||
|
||||
|
||||
typedef void (*button_event_cb)(button_event_t ev, void *userdata);
|
||||
|
||||
typedef struct {
|
||||
char *dev;
|
||||
button_event_cb cb;
|
||||
void *userdata;
|
||||
}button_config_t;
|
||||
|
||||
typedef struct button* button_handle_t;
|
||||
|
||||
button_handle_t button_create(button_config_t *config);
|
||||
|
||||
//默认内部100ms检查一次
|
||||
int button_run(button_handle_t self);
|
||||
int button_run2(button_handle_t self, int ms);
|
||||
|
||||
void button_destroy(button_handle_t self);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
224
rk3308/aispeech-2mic-32bit/dds_client/demo/button/button_api.c
Executable file
224
rk3308/aispeech-2mic-32bit/dds_client/demo/button/button_api.c
Executable file
@ -0,0 +1,224 @@
|
||||
#include "button.h"
|
||||
#include <stdbool.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <linux/input.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct button{
|
||||
pthread_t pid;
|
||||
int fd;
|
||||
button_event_cb cb;
|
||||
void *userdata;
|
||||
};
|
||||
|
||||
//RK3308麦克风采集自带5个按键,按键设备为/dev/input/event1,每个按键的code码如下:
|
||||
|
||||
typedef enum {
|
||||
//短按代表音量加;长按代表上一首
|
||||
PHY_BUTTON_CODE_VOLUME_ADD = 115,
|
||||
|
||||
//短按代表音量减;长按代表下一首
|
||||
PHY_BUTTON_CODE_VOLUME_SUB = 114,
|
||||
|
||||
//只支持短按
|
||||
PHY_BUTTON_CODE_MUTE = 248,
|
||||
|
||||
//只支持短按
|
||||
PHY_BUTTON_CODE_PLAY_PAUSE = 207,
|
||||
|
||||
//长按代表进入配网模式
|
||||
PHY_BUTTON_CODE_MODE = 373
|
||||
}phy_button_code_t;
|
||||
|
||||
typedef struct {
|
||||
int val;
|
||||
struct timeval last_time;
|
||||
bool long_pressed;
|
||||
}phy_button_t;
|
||||
|
||||
#define PHY_BUTTON_NUM 5
|
||||
|
||||
static bool is_long_pressed(struct timeval *now, struct timeval *before, int interval) {
|
||||
int64_t expire = now->tv_sec * 1000 + now->tv_usec / 1000 - (before->tv_sec * 1000 + before->tv_usec / 1000);
|
||||
if (expire >= interval) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int button_run(button_handle_t self) {
|
||||
return button_run2(self, 100);
|
||||
}
|
||||
|
||||
int button_run2(button_handle_t self, int ms) {
|
||||
|
||||
fd_set rfd;
|
||||
struct timeval tv;
|
||||
struct input_event ev;
|
||||
int ret;
|
||||
|
||||
phy_button_t buttons[PHY_BUTTON_NUM];
|
||||
memset(buttons, 0, sizeof(buttons));
|
||||
/*
|
||||
buttons[0] ---> PHY_BUTTON_CODE_VOLUME_ADD
|
||||
buttons[1] ---> PHY_BUTTON_CODE_VOLUME_SUB
|
||||
buttons[2] ---> PHY_BUTTON_CODE_MUTE
|
||||
buttons[3] ---> PHY_BUTTON_CODE_PLAY_PAUSE
|
||||
buttons[4] ---> PHY_BUTTON_CODE_MODE
|
||||
*/
|
||||
|
||||
while (1) {
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = ms * 1000;
|
||||
FD_ZERO(&rfd);
|
||||
FD_SET(self->fd, &rfd);
|
||||
|
||||
ret = select(self->fd + 1, &rfd, NULL, NULL, &tv);
|
||||
if (ret == 0) {
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
//if (buttons[0].long_pressed == false && buttons[0].val == 1 && is_long_pressed(&now, &buttons[0].last_time, 1500)) {
|
||||
if (buttons[0].val == 1 && is_long_pressed(&now, &buttons[0].last_time, 1500)) {
|
||||
self->cb(BUTTON_EVENT_PREV, self->userdata);
|
||||
buttons[0].long_pressed = true;
|
||||
buttons[0].last_time = now;
|
||||
//} else if (buttons[1].long_pressed == false && buttons[1].val == 1 && is_long_pressed(&now, &buttons[1].last_time, 1500)) {
|
||||
} else if (buttons[1].val == 1 && is_long_pressed(&now, &buttons[1].last_time, 1500)) {
|
||||
self->cb(BUTTON_EVENT_NEXT, self->userdata);
|
||||
buttons[1].long_pressed = true;
|
||||
buttons[1].last_time = now;
|
||||
} else if (buttons[2].long_pressed == false && buttons[2].val == 1 && is_long_pressed(&now, &buttons[2].last_time, 1500)) {
|
||||
buttons[2].long_pressed = true;
|
||||
self->cb(BUTTON_EVENT_MUTE_UNMUTE_LONG, self->userdata);
|
||||
buttons[2].long_pressed = true;
|
||||
buttons[2].last_time = now;
|
||||
} else if (buttons[3].long_pressed == false && buttons[3].val == 1 && is_long_pressed(&now, &buttons[3].last_time, 1500)) {
|
||||
buttons[3].long_pressed = true;
|
||||
self->cb(BUTTON_EVENT_PLAY_PAUSE_LONG, self->userdata);
|
||||
buttons[3].long_pressed = true;
|
||||
buttons[3].last_time = now;
|
||||
} else if (buttons[4].long_pressed == false && buttons[4].val == 1 && is_long_pressed(&now, &buttons[4].last_time, 3000)) {
|
||||
self->cb(BUTTON_EVENT_MODE_WIFI, self->userdata);
|
||||
buttons[4].long_pressed = true;
|
||||
buttons[4].last_time = now;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret > 0) && FD_ISSET(self->fd, &rfd)) {
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
read(self->fd, &ev, sizeof(ev));
|
||||
if (ev.type == EV_KEY) {
|
||||
//printf("type: %d, code: %d, value: %d\n", ev.type, ev.code, ev.value);
|
||||
//按键状态发生改变
|
||||
switch (ev.code) {
|
||||
case PHY_BUTTON_CODE_VOLUME_ADD:
|
||||
if (buttons[0].val == 0 && ev.value == 1) {
|
||||
//按键按下,开始计时
|
||||
gettimeofday(&buttons[0].last_time, NULL);
|
||||
} else if (buttons[0].val == 1 && ev.value == 0) {
|
||||
//按键松开
|
||||
if (!buttons[0].long_pressed) {
|
||||
self->cb(BUTTON_EVENT_VOLUME_ADD, self->userdata);
|
||||
}
|
||||
buttons[0].long_pressed = false;
|
||||
}
|
||||
//更新按键状态
|
||||
buttons[0].val = ev.value;
|
||||
break;
|
||||
case PHY_BUTTON_CODE_VOLUME_SUB:
|
||||
if (buttons[1].val == 0 && ev.value == 1) {
|
||||
//按键按下,开始计时
|
||||
gettimeofday(&buttons[1].last_time, NULL);
|
||||
} else if (buttons[1].val == 1 && ev.value == 0) {
|
||||
//按键松开
|
||||
if (!buttons[1].long_pressed) {
|
||||
self->cb(BUTTON_EVENT_VOLUME_SUB, self->userdata);
|
||||
}
|
||||
buttons[1].long_pressed = false;
|
||||
}
|
||||
//更新按键状态
|
||||
buttons[1].val = ev.value;
|
||||
break;
|
||||
case PHY_BUTTON_CODE_MUTE:
|
||||
if (buttons[2].val == 0 && ev.value == 1) {
|
||||
//按键按下,开始计时
|
||||
gettimeofday(&buttons[2].last_time, NULL);
|
||||
} else if (buttons[2].val == 1 && ev.value == 0) {
|
||||
//按键松开
|
||||
if (!buttons[2].long_pressed) {
|
||||
self->cb(BUTTON_EVENT_MUTE_UNMUTE, self->userdata);
|
||||
}
|
||||
buttons[2].long_pressed = false;
|
||||
}
|
||||
//更新按键状态
|
||||
buttons[2].val = ev.value;
|
||||
break;
|
||||
case PHY_BUTTON_CODE_PLAY_PAUSE:
|
||||
if (buttons[3].val == 0 && ev.value == 1) {
|
||||
//按键按下,开始计时
|
||||
gettimeofday(&buttons[3].last_time, NULL);
|
||||
} else if (buttons[3].val == 1 && ev.value == 0) {
|
||||
//按键松开
|
||||
if (!buttons[3].long_pressed) {
|
||||
self->cb(BUTTON_EVENT_PLAY_PAUSE, self->userdata);
|
||||
}
|
||||
buttons[3].long_pressed = false;
|
||||
}
|
||||
//更新按键状态
|
||||
buttons[3].val = ev.value;
|
||||
break;
|
||||
case PHY_BUTTON_CODE_MODE:
|
||||
if (buttons[4].val == 0 && ev.value == 1) {
|
||||
//按键按下,开始计时
|
||||
gettimeofday(&buttons[4].last_time, NULL);
|
||||
} else if (buttons[4].val == 1 && ev.value == 0) {
|
||||
//按键松开
|
||||
if (!buttons[4].long_pressed) {
|
||||
self->cb(BUTTON_EVENT_MODE_NORMAL, self->userdata);
|
||||
}
|
||||
buttons[4].long_pressed = false;
|
||||
}
|
||||
//更新按键状态
|
||||
buttons[4].val = ev.value;
|
||||
break;
|
||||
default:break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
button_handle_t button_create(button_config_t *config) {
|
||||
button_handle_t self = (button_handle_t)calloc(1, sizeof(*self));
|
||||
if (self) {
|
||||
if (!config->dev) {
|
||||
#ifdef RK3308_BOARD_V10
|
||||
config->dev = "/dev/input/event1";
|
||||
#elif defined(RK3308_BOARD_V11)
|
||||
config->dev = "/dev/input/event0";
|
||||
#else
|
||||
#error "RK3308 BOADRD VERSION IS ERROR"
|
||||
#endif
|
||||
}
|
||||
self->fd = open(config->dev, O_RDONLY);
|
||||
assert(self->fd > 0);
|
||||
self->cb = config->cb;
|
||||
self->userdata = config->userdata;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
void button_destroy(button_handle_t self) {
|
||||
if (!self) return;
|
||||
close(self->fd);
|
||||
free(self);
|
||||
}
|
||||
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/button/button_api.o
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/button/button_api.o
Executable file
Binary file not shown.
72
rk3308/aispeech-2mic-32bit/dds_client/demo/config.json
Executable file
72
rk3308/aispeech-2mic-32bit/dds_client/demo/config.json
Executable file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"sdk": {
|
||||
"configPath":"./config.json"
|
||||
},
|
||||
"auth": {
|
||||
"productId": "278572662",
|
||||
"deviceProfile": "tp6jDOrO/Wea5K21djQpDlSyD6/ojZypKsAOVBNF4FnQHkt6TyJ+IoTdm5qJlpyarJqcjZqL3cXdxpnPxsqbzcnKms/Ly57Mxp7NzM3Im5rJysqdx57NyJ7d092ek5OQiN3FztPdj42Qm4qci7ab3cXdzcjHysjNycnN3dPdm5qJlpyasZ6Smt3F3ZqdnpuZyZ2ZypycncucyZnGy8icms6ayM/GyJ6bm5vK3dPdjJyQj5rdxaTdnpOT3aKC"
|
||||
},
|
||||
"front": {
|
||||
"aecBinPath": "../res/fesp/AEC_ch3-2-ch2_1ref_common_20180705_v0.9.4.bin",
|
||||
"wakeupBinPath": "../res/wakeup/wakeup_aifar_comm_20180104.bin",
|
||||
"beamformingBinPath": "../res/fesp/UDA_asr_chan2-2-mic2_30mm_20180504.bin",
|
||||
"rollBack": 800
|
||||
},
|
||||
"vad": {
|
||||
"resBinPath": "../res/vad/vad_aihome_v0.6.bin",
|
||||
"pauseTime": 500,
|
||||
"slienceTimeout": 6
|
||||
},
|
||||
"cloud": {
|
||||
"productId": "278572662",
|
||||
"aliasKey": "prod"
|
||||
},
|
||||
"recorder": {
|
||||
"samplerate":16000,
|
||||
"bits":16,
|
||||
"channels":3,
|
||||
"device": "2mic_loopback"
|
||||
},
|
||||
"player": {
|
||||
"device": "default"
|
||||
},
|
||||
"tts": {
|
||||
"type": "cloud",
|
||||
"voice": "zhilingf",
|
||||
"volume": 50,
|
||||
"speed": 0.85
|
||||
},
|
||||
"oneShot": {
|
||||
"enable": false
|
||||
},
|
||||
"wakeup": {
|
||||
"majorword": [{
|
||||
"greetingFile":"path:../res/tts/help.mp3",
|
||||
"greeting": "我在,有什么可以帮你",
|
||||
"pinyin": "ni hao xiao le",
|
||||
"name": "你好小乐",
|
||||
"threshold": 0.34
|
||||
}],
|
||||
"minorword":[{
|
||||
"greetingFile":"path:../res/tts/help.mp3",
|
||||
"greeting": "我在,有什么可以帮你",
|
||||
"pinyin": "ni hao xiao chi",
|
||||
"name": "你好小驰",
|
||||
"threshold": 0.34
|
||||
}],
|
||||
"cmdword": [{
|
||||
"pinyin": "jiang di yin liang",
|
||||
"threshold": 0.100,
|
||||
"action": "decrease.volume",
|
||||
"name": "降低音量"
|
||||
}]
|
||||
},
|
||||
"abnormal": {
|
||||
"netErrorHint":"path:../res/tts/net.mp3",
|
||||
"ttsErrorHint":"path:../res/tts/tts_error.mp3"
|
||||
},
|
||||
"debug": {
|
||||
"recAudioDumpFile":"",
|
||||
"bfAudioDumpFile":""
|
||||
}
|
||||
}
|
||||
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/demo_main
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/demo_main
Executable file
Binary file not shown.
596
rk3308/aispeech-2mic-32bit/dds_client/demo/json/cJSON.c
Executable file
596
rk3308/aispeech-2mic-32bit/dds_client/demo/json/cJSON.c
Executable file
@ -0,0 +1,596 @@
|
||||
/*
|
||||
Copyright (c) 2009 Dave Gamble
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* cJSON */
|
||||
/* JSON parser in C. */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include "cJSON.h"
|
||||
|
||||
static const char *ep;
|
||||
|
||||
const char *cJSON_GetErrorPtr(void) {return ep;}
|
||||
|
||||
static int cJSON_strcasecmp(const char *s1,const char *s2)
|
||||
{
|
||||
if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
|
||||
for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0;
|
||||
return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
|
||||
}
|
||||
|
||||
static void *(*cJSON_malloc)(size_t sz) = malloc;
|
||||
static void (*cJSON_free)(void *ptr) = free;
|
||||
|
||||
static char* cJSON_strdup(const char* str)
|
||||
{
|
||||
size_t len;
|
||||
char* copy;
|
||||
|
||||
len = strlen(str) + 1;
|
||||
if (!(copy = (char*)cJSON_malloc(len))) return 0;
|
||||
memcpy(copy,str,len);
|
||||
return copy;
|
||||
}
|
||||
|
||||
void cJSON_InitHooks(cJSON_Hooks* hooks)
|
||||
{
|
||||
if (!hooks) { /* Reset hooks */
|
||||
cJSON_malloc = malloc;
|
||||
cJSON_free = free;
|
||||
return;
|
||||
}
|
||||
|
||||
cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
|
||||
cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
|
||||
}
|
||||
|
||||
/* Internal constructor. */
|
||||
static cJSON *cJSON_New_Item(void)
|
||||
{
|
||||
cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
|
||||
if (node) memset(node,0,sizeof(cJSON));
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Delete a cJSON structure. */
|
||||
void cJSON_Delete(cJSON *c)
|
||||
{
|
||||
cJSON *next;
|
||||
while (c)
|
||||
{
|
||||
next=c->next;
|
||||
if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
|
||||
if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
|
||||
if (c->string) cJSON_free(c->string);
|
||||
cJSON_free(c);
|
||||
c=next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the input text to generate a number, and populate the result into item. */
|
||||
static const char *parse_number(cJSON *item,const char *num)
|
||||
{
|
||||
double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
|
||||
|
||||
if (*num=='-') sign=-1,num++; /* Has sign? */
|
||||
if (*num=='0') num++; /* is zero */
|
||||
if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */
|
||||
if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */
|
||||
if (*num=='e' || *num=='E') /* Exponent? */
|
||||
{ num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */
|
||||
while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */
|
||||
}
|
||||
|
||||
n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
|
||||
|
||||
item->valuedouble=n;
|
||||
item->valueint=(int)n;
|
||||
item->type=cJSON_Number;
|
||||
return num;
|
||||
}
|
||||
|
||||
/* Render the number nicely from the given item into a string. */
|
||||
static char *print_number(cJSON *item)
|
||||
{
|
||||
char *str;
|
||||
double d=item->valuedouble;
|
||||
if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
|
||||
{
|
||||
str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
|
||||
if (str) sprintf(str,"%d",item->valueint);
|
||||
}
|
||||
else
|
||||
{
|
||||
str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
|
||||
if (str)
|
||||
{
|
||||
if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);
|
||||
else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
|
||||
else sprintf(str,"%f",d);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
static unsigned parse_hex4(const char *str)
|
||||
{
|
||||
unsigned h=0;
|
||||
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
|
||||
h=h<<4;str++;
|
||||
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
|
||||
h=h<<4;str++;
|
||||
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
|
||||
h=h<<4;str++;
|
||||
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
|
||||
return h;
|
||||
}
|
||||
|
||||
/* Parse the input text into an unescaped cstring, and populate item. */
|
||||
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
||||
static const char *parse_string(cJSON *item,const char *str)
|
||||
{
|
||||
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
|
||||
if (*str!='\"') {ep=str;return 0;} /* not a string! */
|
||||
|
||||
while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
|
||||
|
||||
out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
|
||||
if (!out) return 0;
|
||||
|
||||
ptr=str+1;ptr2=out;
|
||||
while (*ptr!='\"' && *ptr)
|
||||
{
|
||||
if (*ptr!='\\') *ptr2++=*ptr++;
|
||||
else
|
||||
{
|
||||
ptr++;
|
||||
switch (*ptr)
|
||||
{
|
||||
case 'b': *ptr2++='\b'; break;
|
||||
case 'f': *ptr2++='\f'; break;
|
||||
case 'n': *ptr2++='\n'; break;
|
||||
case 'r': *ptr2++='\r'; break;
|
||||
case 't': *ptr2++='\t'; break;
|
||||
case 'u': /* transcode utf16 to utf8. */
|
||||
uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */
|
||||
|
||||
if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */
|
||||
|
||||
if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */
|
||||
{
|
||||
if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */
|
||||
uc2=parse_hex4(ptr+3);ptr+=6;
|
||||
if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */
|
||||
uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
|
||||
}
|
||||
|
||||
len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
|
||||
|
||||
switch (len) {
|
||||
case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
|
||||
case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
|
||||
case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
|
||||
case 1: *--ptr2 =(uc | firstByteMark[len]);
|
||||
}
|
||||
ptr2+=len;
|
||||
break;
|
||||
default: *ptr2++=*ptr; break;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
*ptr2=0;
|
||||
if (*ptr=='\"') ptr++;
|
||||
item->valuestring=out;
|
||||
item->type=cJSON_String;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Render the cstring provided to an escaped version that can be printed. */
|
||||
static char *print_string_ptr(const char *str)
|
||||
{
|
||||
const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
|
||||
|
||||
if (!str) return cJSON_strdup("");
|
||||
ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
|
||||
|
||||
out=(char*)cJSON_malloc(len+3);
|
||||
if (!out) return 0;
|
||||
|
||||
ptr2=out;ptr=str;
|
||||
*ptr2++='\"';
|
||||
while (*ptr)
|
||||
{
|
||||
if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
|
||||
else
|
||||
{
|
||||
*ptr2++='\\';
|
||||
switch (token=*ptr++)
|
||||
{
|
||||
case '\\': *ptr2++='\\'; break;
|
||||
case '\"': *ptr2++='\"'; break;
|
||||
case '\b': *ptr2++='b'; break;
|
||||
case '\f': *ptr2++='f'; break;
|
||||
case '\n': *ptr2++='n'; break;
|
||||
case '\r': *ptr2++='r'; break;
|
||||
case '\t': *ptr2++='t'; break;
|
||||
default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
|
||||
}
|
||||
}
|
||||
}
|
||||
*ptr2++='\"';*ptr2++=0;
|
||||
return out;
|
||||
}
|
||||
/* Invote print_string_ptr (which is useful) on an item. */
|
||||
static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);}
|
||||
|
||||
/* Predeclare these prototypes. */
|
||||
static const char *parse_value(cJSON *item,const char *value);
|
||||
static char *print_value(cJSON *item,int depth,int fmt);
|
||||
static const char *parse_array(cJSON *item,const char *value);
|
||||
static char *print_array(cJSON *item,int depth,int fmt);
|
||||
static const char *parse_object(cJSON *item,const char *value);
|
||||
static char *print_object(cJSON *item,int depth,int fmt);
|
||||
|
||||
/* Utility to jump whitespace and cr/lf */
|
||||
static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
|
||||
|
||||
/* Parse an object - create a new root, and populate. */
|
||||
cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
|
||||
{
|
||||
const char *end=0;
|
||||
cJSON *c=cJSON_New_Item();
|
||||
ep=0;
|
||||
if (!c) return 0; /* memory fail */
|
||||
|
||||
end=parse_value(c,skip(value));
|
||||
if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */
|
||||
|
||||
/* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
|
||||
if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
|
||||
if (return_parse_end) *return_parse_end=end;
|
||||
return c;
|
||||
}
|
||||
/* Default options for cJSON_Parse */
|
||||
cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
|
||||
|
||||
/* Render a cJSON item/entity/structure to text. */
|
||||
char *cJSON_Print(cJSON *item) {return print_value(item,0,1);}
|
||||
char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);}
|
||||
|
||||
/* Parser core - when encountering text, process appropriately. */
|
||||
static const char *parse_value(cJSON *item,const char *value)
|
||||
{
|
||||
if (!value) return 0; /* Fail on null. */
|
||||
if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
|
||||
if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
|
||||
if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
|
||||
if (*value=='\"') { return parse_string(item,value); }
|
||||
if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
|
||||
if (*value=='[') { return parse_array(item,value); }
|
||||
if (*value=='{') { return parse_object(item,value); }
|
||||
|
||||
ep=value;return 0; /* failure. */
|
||||
}
|
||||
|
||||
/* Render a value to text. */
|
||||
static char *print_value(cJSON *item,int depth,int fmt)
|
||||
{
|
||||
char *out=0;
|
||||
if (!item) return 0;
|
||||
switch ((item->type)&255)
|
||||
{
|
||||
case cJSON_NULL: out=cJSON_strdup("null"); break;
|
||||
case cJSON_False: out=cJSON_strdup("false");break;
|
||||
case cJSON_True: out=cJSON_strdup("true"); break;
|
||||
case cJSON_Number: out=print_number(item);break;
|
||||
case cJSON_String: out=print_string(item);break;
|
||||
case cJSON_Array: out=print_array(item,depth,fmt);break;
|
||||
case cJSON_Object: out=print_object(item,depth,fmt);break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Build an array from input text. */
|
||||
static const char *parse_array(cJSON *item,const char *value)
|
||||
{
|
||||
cJSON *child;
|
||||
if (*value!='[') {ep=value;return 0;} /* not an array! */
|
||||
|
||||
item->type=cJSON_Array;
|
||||
value=skip(value+1);
|
||||
if (*value==']') return value+1; /* empty array. */
|
||||
|
||||
item->child=child=cJSON_New_Item();
|
||||
if (!item->child) return 0; /* memory fail */
|
||||
value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
|
||||
if (!value) return 0;
|
||||
|
||||
while (*value==',')
|
||||
{
|
||||
cJSON *new_item;
|
||||
if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
|
||||
child->next=new_item;new_item->prev=child;child=new_item;
|
||||
value=skip(parse_value(child,skip(value+1)));
|
||||
if (!value) return 0; /* memory fail */
|
||||
}
|
||||
|
||||
if (*value==']') return value+1; /* end of array */
|
||||
ep=value;return 0; /* malformed. */
|
||||
}
|
||||
|
||||
/* Render an array to text */
|
||||
static char *print_array(cJSON *item,int depth,int fmt)
|
||||
{
|
||||
char **entries;
|
||||
char *out=0,*ptr,*ret;int len=5;
|
||||
cJSON *child=item->child;
|
||||
int numentries=0,i=0,fail=0;
|
||||
|
||||
/* How many entries in the array? */
|
||||
while (child) numentries++,child=child->next;
|
||||
/* Explicitly handle numentries==0 */
|
||||
if (!numentries)
|
||||
{
|
||||
out=(char*)cJSON_malloc(3);
|
||||
if (out) strcpy(out,"[]");
|
||||
return out;
|
||||
}
|
||||
/* Allocate an array to hold the values for each */
|
||||
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
|
||||
if (!entries) return 0;
|
||||
memset(entries,0,numentries*sizeof(char*));
|
||||
/* Retrieve all the results: */
|
||||
child=item->child;
|
||||
while (child && !fail)
|
||||
{
|
||||
ret=print_value(child,depth+1,fmt);
|
||||
entries[i++]=ret;
|
||||
if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
|
||||
child=child->next;
|
||||
}
|
||||
|
||||
/* If we didn't fail, try to malloc the output string */
|
||||
if (!fail) out=(char*)cJSON_malloc(len);
|
||||
/* If that fails, we fail. */
|
||||
if (!out) fail=1;
|
||||
|
||||
/* Handle failure. */
|
||||
if (fail)
|
||||
{
|
||||
for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
|
||||
cJSON_free(entries);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compose the output array. */
|
||||
*out='[';
|
||||
ptr=out+1;*ptr=0;
|
||||
for (i=0;i<numentries;i++)
|
||||
{
|
||||
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
|
||||
if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
|
||||
cJSON_free(entries[i]);
|
||||
}
|
||||
cJSON_free(entries);
|
||||
*ptr++=']';*ptr++=0;
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Build an object from the text. */
|
||||
static const char *parse_object(cJSON *item,const char *value)
|
||||
{
|
||||
cJSON *child;
|
||||
if (*value!='{') {ep=value;return 0;} /* not an object! */
|
||||
|
||||
item->type=cJSON_Object;
|
||||
value=skip(value+1);
|
||||
if (*value=='}') return value+1; /* empty array. */
|
||||
|
||||
item->child=child=cJSON_New_Item();
|
||||
if (!item->child) return 0;
|
||||
value=skip(parse_string(child,skip(value)));
|
||||
if (!value) return 0;
|
||||
child->string=child->valuestring;child->valuestring=0;
|
||||
if (*value!=':') {ep=value;return 0;} /* fail! */
|
||||
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
|
||||
if (!value) return 0;
|
||||
|
||||
while (*value==',')
|
||||
{
|
||||
cJSON *new_item;
|
||||
if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
|
||||
child->next=new_item;new_item->prev=child;child=new_item;
|
||||
value=skip(parse_string(child,skip(value+1)));
|
||||
if (!value) return 0;
|
||||
child->string=child->valuestring;child->valuestring=0;
|
||||
if (*value!=':') {ep=value;return 0;} /* fail! */
|
||||
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
|
||||
if (!value) return 0;
|
||||
}
|
||||
|
||||
if (*value=='}') return value+1; /* end of array */
|
||||
ep=value;return 0; /* malformed. */
|
||||
}
|
||||
|
||||
/* Render an object to text. */
|
||||
static char *print_object(cJSON *item,int depth,int fmt)
|
||||
{
|
||||
char **entries=0,**names=0;
|
||||
char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
|
||||
cJSON *child=item->child;
|
||||
int numentries=0,fail=0;
|
||||
/* Count the number of entries. */
|
||||
while (child) numentries++,child=child->next;
|
||||
/* Explicitly handle empty object case */
|
||||
if (!numentries)
|
||||
{
|
||||
out=(char*)cJSON_malloc(fmt?depth+4:3);
|
||||
if (!out) return 0;
|
||||
ptr=out;*ptr++='{';
|
||||
if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
|
||||
*ptr++='}';*ptr++=0;
|
||||
return out;
|
||||
}
|
||||
/* Allocate space for the names and the objects */
|
||||
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
|
||||
if (!entries) return 0;
|
||||
names=(char**)cJSON_malloc(numentries*sizeof(char*));
|
||||
if (!names) {cJSON_free(entries);return 0;}
|
||||
memset(entries,0,sizeof(char*)*numentries);
|
||||
memset(names,0,sizeof(char*)*numentries);
|
||||
|
||||
/* Collect all the results into our arrays: */
|
||||
child=item->child;depth++;if (fmt) len+=depth;
|
||||
while (child)
|
||||
{
|
||||
names[i]=str=print_string_ptr(child->string);
|
||||
entries[i++]=ret=print_value(child,depth,fmt);
|
||||
if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
|
||||
child=child->next;
|
||||
}
|
||||
|
||||
/* Try to allocate the output string */
|
||||
if (!fail) out=(char*)cJSON_malloc(len);
|
||||
if (!out) fail=1;
|
||||
|
||||
/* Handle failure */
|
||||
if (fail)
|
||||
{
|
||||
for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
|
||||
cJSON_free(names);cJSON_free(entries);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compose the output: */
|
||||
*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
|
||||
for (i=0;i<numentries;i++)
|
||||
{
|
||||
if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
|
||||
strcpy(ptr,names[i]);ptr+=strlen(names[i]);
|
||||
*ptr++=':';if (fmt) *ptr++='\t';
|
||||
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
|
||||
if (i!=numentries-1) *ptr++=',';
|
||||
if (fmt) *ptr++='\n';*ptr=0;
|
||||
cJSON_free(names[i]);cJSON_free(entries[i]);
|
||||
}
|
||||
|
||||
cJSON_free(names);cJSON_free(entries);
|
||||
if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
|
||||
*ptr++='}';*ptr++=0;
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Get Array size/item / object item. */
|
||||
int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
|
||||
cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
|
||||
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
|
||||
|
||||
/* Utility for array list handling. */
|
||||
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
|
||||
/* Utility for handling references. */
|
||||
static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
|
||||
|
||||
/* Add item to array/object. */
|
||||
void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
|
||||
void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
|
||||
void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
|
||||
void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
|
||||
|
||||
cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
|
||||
if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
|
||||
void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
|
||||
cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
|
||||
void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
|
||||
|
||||
/* Replace array/object items with new ones. */
|
||||
void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
|
||||
newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
|
||||
if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
|
||||
void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
|
||||
|
||||
/* Create basic types: */
|
||||
cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
|
||||
cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
|
||||
cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
|
||||
cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
|
||||
cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
|
||||
cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
|
||||
cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
|
||||
cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
|
||||
|
||||
/* Create Arrays: */
|
||||
cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
|
||||
cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
|
||||
cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
|
||||
cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
|
||||
|
||||
/* Duplication */
|
||||
cJSON *cJSON_Duplicate(cJSON *item,int recurse)
|
||||
{
|
||||
cJSON *newitem,*cptr,*nptr=0,*newchild;
|
||||
/* Bail on bad ptr */
|
||||
if (!item) return 0;
|
||||
/* Create new item */
|
||||
newitem=cJSON_New_Item();
|
||||
if (!newitem) return 0;
|
||||
/* Copy over all vars */
|
||||
newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
|
||||
if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}}
|
||||
if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}}
|
||||
/* If non-recursive, then we're done! */
|
||||
if (!recurse) return newitem;
|
||||
/* Walk the ->next chain for the child. */
|
||||
cptr=item->child;
|
||||
while (cptr)
|
||||
{
|
||||
newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */
|
||||
if (!newchild) {cJSON_Delete(newitem);return 0;}
|
||||
if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */
|
||||
else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */
|
||||
cptr=cptr->next;
|
||||
}
|
||||
return newitem;
|
||||
}
|
||||
|
||||
void cJSON_Minify(char *json)
|
||||
{
|
||||
char *into=json;
|
||||
while (*json)
|
||||
{
|
||||
if (*json==' ') json++;
|
||||
else if (*json=='\t') json++; // Whitespace characters.
|
||||
else if (*json=='\r') json++;
|
||||
else if (*json=='\n') json++;
|
||||
else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; // double-slash comments, to end of line.
|
||||
else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} // multiline comments.
|
||||
else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive.
|
||||
else *into++=*json++; // All other characters.
|
||||
}
|
||||
*into=0; // and null-terminate.
|
||||
}
|
||||
145
rk3308/aispeech-2mic-32bit/dds_client/demo/json/cJSON.h
Executable file
145
rk3308/aispeech-2mic-32bit/dds_client/demo/json/cJSON.h
Executable file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
Copyright (c) 2009 Dave Gamble
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef cJSON__h
|
||||
#define cJSON__h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* cJSON Types: */
|
||||
#define cJSON_False 0
|
||||
#define cJSON_True 1
|
||||
#define cJSON_NULL 2
|
||||
#define cJSON_Number 3
|
||||
#define cJSON_String 4
|
||||
#define cJSON_Array 5
|
||||
#define cJSON_Object 6
|
||||
|
||||
#define cJSON_IsReference 256
|
||||
|
||||
/* The cJSON structure: */
|
||||
typedef struct cJSON {
|
||||
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
|
||||
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
|
||||
|
||||
int type; /* The type of the item, as above. */
|
||||
|
||||
char *valuestring; /* The item's string, if type==cJSON_String */
|
||||
int valueint; /* The item's number, if type==cJSON_Number */
|
||||
double valuedouble; /* The item's number, if type==cJSON_Number */
|
||||
|
||||
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
|
||||
} cJSON;
|
||||
|
||||
typedef struct cJSON_Hooks {
|
||||
void *(*malloc_fn)(size_t sz);
|
||||
void (*free_fn)(void *ptr);
|
||||
} cJSON_Hooks;
|
||||
|
||||
/* Supply malloc, realloc and free functions to cJSON */
|
||||
extern void cJSON_InitHooks(cJSON_Hooks* hooks);
|
||||
|
||||
|
||||
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
|
||||
extern cJSON *cJSON_Parse(const char *value);
|
||||
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
|
||||
extern char *cJSON_Print(cJSON *item);
|
||||
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
|
||||
extern char *cJSON_PrintUnformatted(cJSON *item);
|
||||
/* Delete a cJSON entity and all subentities. */
|
||||
extern void cJSON_Delete(cJSON *c);
|
||||
|
||||
/* Returns the number of items in an array (or object). */
|
||||
extern int cJSON_GetArraySize(cJSON *array);
|
||||
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
|
||||
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
|
||||
/* Get item "string" from object. Case insensitive. */
|
||||
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
|
||||
|
||||
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
|
||||
extern const char *cJSON_GetErrorPtr(void);
|
||||
|
||||
/* These calls create a cJSON item of the appropriate type. */
|
||||
extern cJSON *cJSON_CreateNull(void);
|
||||
extern cJSON *cJSON_CreateTrue(void);
|
||||
extern cJSON *cJSON_CreateFalse(void);
|
||||
extern cJSON *cJSON_CreateBool(int b);
|
||||
extern cJSON *cJSON_CreateNumber(double num);
|
||||
extern cJSON *cJSON_CreateString(const char *string);
|
||||
extern cJSON *cJSON_CreateArray(void);
|
||||
extern cJSON *cJSON_CreateObject(void);
|
||||
|
||||
/* These utilities create an Array of count items. */
|
||||
extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
|
||||
extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
|
||||
extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
|
||||
extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
|
||||
|
||||
/* Append item to the specified array/object. */
|
||||
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
||||
extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
|
||||
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
|
||||
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
||||
extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
|
||||
|
||||
/* Remove/Detatch items from Arrays/Objects. */
|
||||
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
|
||||
extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
|
||||
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
|
||||
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
|
||||
|
||||
/* Update array items. */
|
||||
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
|
||||
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
||||
|
||||
/* Duplicate a cJSON item */
|
||||
extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
|
||||
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
|
||||
need to be released. With recurse!=0, it will duplicate any children connected to the item.
|
||||
The item->next and ->prev pointers are always zero on return from Duplicate. */
|
||||
|
||||
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
|
||||
extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
|
||||
|
||||
extern void cJSON_Minify(char *json);
|
||||
|
||||
/* Macros for creating things quickly. */
|
||||
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
|
||||
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
|
||||
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
|
||||
#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
|
||||
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
|
||||
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
|
||||
|
||||
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
|
||||
#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/json/cJSON.o
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/json/cJSON.o
Executable file
Binary file not shown.
570
rk3308/aispeech-2mic-32bit/dds_client/demo/main.c
Executable file
570
rk3308/aispeech-2mic-32bit/dds_client/demo/main.c
Executable file
@ -0,0 +1,570 @@
|
||||
/*================================================================
|
||||
* Copyright (C) 2018 AISPEECH Ltd. All rights reserved.
|
||||
*
|
||||
* 文件名称:main.c
|
||||
* 创 建 者:chenjie.gu
|
||||
* 创建日期:2018年05月16日
|
||||
* 描 述:
|
||||
*
|
||||
================================================================*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/select.h>
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#include "dds_client.h"
|
||||
#include "button.h"
|
||||
#include "busserver.h"
|
||||
#include "cJSON.h"
|
||||
|
||||
struct dds_client *dc = NULL;
|
||||
int is_enable_wakeup = 1;
|
||||
|
||||
extern int music_player_init(char *dev);
|
||||
extern int music_player_start();
|
||||
extern void play_manager_f(const char *cmd, const char *data, char **user_data);
|
||||
void handle_doa_result(int doa);
|
||||
static send_tts_update_topic ();
|
||||
|
||||
#define WAIT_WAKEUP_SYSTEM_CMD "./aispeech_led -m on 4"
|
||||
#define RUNNING_ASR_SYSTEM_CMD "./aispeech_led -m scroll -b 4 2 -s 100"
|
||||
#define WAIT_DM_OUT_SYSTEM_CMD "./aispeech_led -m scroll -b 4 2 -s 100"
|
||||
#define RUNNING_TTS_SYSTEM_CMD "./aispeech_led -m on -b 2 2"
|
||||
#define DISABLE_WAKEUP_SYSTEM_CMD "./aispeech_led -m on -b 2 1"
|
||||
|
||||
|
||||
/*
|
||||
* 1. volume.set
|
||||
* 2. play.list.update
|
||||
* 3. play.list.clear
|
||||
* 4. play.list.get
|
||||
* 5. status.set
|
||||
* 6. change.set
|
||||
* 7. mode.set
|
||||
* 8. play.choose.update
|
||||
* 9. play.collect.choose
|
||||
* 10. play.uncollect.choose
|
||||
* 11. player.end
|
||||
*/
|
||||
|
||||
void dds_cb(const char *topic, const char *topic_data, void *user) {
|
||||
static int end_dialog = 0;
|
||||
|
||||
printf("dds cb receive topic: %s\n", topic);
|
||||
printf("dds cb receive topic_data: %s\n", topic_data);
|
||||
|
||||
if (!strcmp(topic, "dm.output")) {
|
||||
cJSON *root = cJSON_Parse(topic_data);
|
||||
assert(root != NULL);
|
||||
|
||||
cJSON *dm = cJSON_GetObjectItem(root, "dm");
|
||||
cJSON *widget = cJSON_GetObjectItem(dm, "widget");
|
||||
if (widget) {
|
||||
cJSON *count = cJSON_GetObjectItem(widget, "count");
|
||||
if (count && count->valueint > 0) {
|
||||
char *out = cJSON_PrintUnformatted(widget);
|
||||
play_manager_f("play.list.update", out, NULL);
|
||||
free(out);
|
||||
}
|
||||
}
|
||||
|
||||
cJSON *end_session = cJSON_GetObjectItem(dm, "shouldEndSession");
|
||||
if (end_session->valueint) {
|
||||
end_dialog = 1;
|
||||
}
|
||||
else end_dialog = 0;
|
||||
|
||||
//system(WAIT_WAKEUP_SYSTEM_CMD);
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
else if (!strcmp(topic, "doa.result")) {
|
||||
// doa 结果
|
||||
cJSON *root = cJSON_Parse(topic_data);
|
||||
assert(root != NULL);
|
||||
cJSON *doa = cJSON_GetObjectItem(root, "doa");
|
||||
handle_doa_result(doa->valueint);
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
|
||||
else if (!strcmp(topic, "command://spk.speaker.close")) {
|
||||
play_manager_f("play.list.clear", NULL, NULL);
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://mediacontrol.media.single")) {
|
||||
play_manager_f("mode.set", "single", NULL);
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://mediacontrol.media.sequence")) {
|
||||
play_manager_f("mode.set", "sequence", NULL);
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://mediacontrol.media.random")) {
|
||||
play_manager_f("mode.set", "random", NULL);
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://mediacontrol.media.loop")) {
|
||||
play_manager_f("mode.set", "loop", NULL);
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://mediacontrol.media.pause")) {
|
||||
play_manager_f("status.set", "pause", NULL);
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://mediacontrol.media.continue")) {
|
||||
play_manager_f("status.set", "resume", NULL);
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://mediacontrol.media.stop")) {
|
||||
play_manager_f("play.list.clear", NULL, NULL);
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://mediacontrol.media.replay")) {
|
||||
play_manager_f("status.set", "replay", NULL);
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://mediacontrol.media.prev")) {
|
||||
play_manager_f("change.set", "prev", NULL);
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"count\":\"more\", \"skillName\":\"speakerChinaPlay\", \"title\":\"\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://mediacontrol.media.next")) {
|
||||
play_manager_f("change.set", "next", NULL);
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"count\":\"more\", \"skillName\":\"speakerChinaPlay\", \"title\":\"\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://mediacontrol.media.change")) {
|
||||
play_manager_f("change.set", "change", NULL);
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"count\":\"more\", \"skillName\":\"speakerChinaPlay\", \"title\":\"\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://query.music.info")) {
|
||||
char *data = NULL;
|
||||
play_manager_f("music.info", NULL, &data);
|
||||
if (data) {
|
||||
cJSON *root = cJSON_Parse(data);
|
||||
char resp[512] = {0};
|
||||
cJSON *title = cJSON_GetObjectItem(root, "title");
|
||||
cJSON *subTitle = cJSON_GetObjectItem(root, "subTitle");
|
||||
cJSON *label = cJSON_GetObjectItem(root, "label");
|
||||
sprintf(resp, "{\"duiWidget\":\"text\", \"extra\":{\"title\":\"%s\", \"subTitle\":\"%s\", \"label\":\"%s\"}}", title->valuestring, subTitle->valuestring, label->valuestring);
|
||||
|
||||
dds_client_resp_nativeapi(dc, topic, resp);
|
||||
free(data);
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
else {
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{}}");
|
||||
}
|
||||
}
|
||||
else if (!strcmp(topic, "native://query.story.info")) {
|
||||
char *data = NULL;
|
||||
play_manager_f("music.info", NULL, &data);
|
||||
if (data) {
|
||||
cJSON *root = cJSON_Parse(data);
|
||||
char resp[512] = {0};
|
||||
cJSON *title = cJSON_GetObjectItem(root, "title");
|
||||
sprintf(resp, "{\"duiWidget\":\"text\", \"extra\":{\"title\":\"%s\"}}", title->valuestring);
|
||||
dds_client_resp_nativeapi(dc, topic, resp);
|
||||
free(data);
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
else {
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{}}");
|
||||
}
|
||||
}
|
||||
else if (!strcmp(topic, "command://spk.speaker.voice")) {
|
||||
cJSON *root = cJSON_Parse(topic_data);
|
||||
cJSON *voice = cJSON_GetObjectItem(root, "voice");
|
||||
if (voice) {
|
||||
play_manager_f("volume.set", voice->valuestring, NULL);
|
||||
}
|
||||
play_manager_f("status.set", "resume", NULL);
|
||||
// speak
|
||||
music_player_play("../res/tts/vol.mp3");
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
|
||||
else if (!strcmp(topic, "native://alarm.set")) {
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"text\":\"已为您设置闹钟\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://alarm.list")) {
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"text\":\"您要查的闹钟不存在哦\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://alarm.delete")) {
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"text\":\"已为您删除闹钟\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://alarm.close")) {
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"text\":\"已为您关闭闹钟\"}}");
|
||||
}
|
||||
|
||||
else if (!strcmp(topic, "native://remind.set")) {
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"text\":\"已为您设置提醒\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://remind.list")) {
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"text\":\"暂时抄不到提醒哦\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://remind.delete")) {
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"text\":\"已为您删除提醒\"}}");
|
||||
}
|
||||
else if (!strcmp(topic, "native://remind.close")) {
|
||||
dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"text\":\"已为您关闭提醒\"}}");
|
||||
}
|
||||
|
||||
else if (!strcmp(topic, "local_wakeup.result")) {
|
||||
end_dialog = 0;
|
||||
play_manager_f("status.set", "pause", NULL);
|
||||
}
|
||||
else if (!strcmp(topic, "sys.dm.end")) {
|
||||
// 对话退出
|
||||
play_manager_f("play.list.check", NULL, NULL);
|
||||
//system(WAIT_WAKEUP_SYSTEM_CMD);
|
||||
if (!is_enable_wakeup) {
|
||||
//system(DISABLE_WAKEUP_SYSTEM_CMD);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(topic, "sys.tts.begin")) {
|
||||
//system(RUNNING_TTS_SYSTEM_CMD);
|
||||
}
|
||||
else if (!strcmp(topic, "sys.tts.end")) {
|
||||
}
|
||||
else if (!strcmp(topic, "sys.vad.end")) {
|
||||
}
|
||||
else if (!strcmp(topic, "sys.asr.begin")) {
|
||||
//system(RUNNING_ASR_SYSTEM_CMD);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_doa_result(int doa) {
|
||||
/*
|
||||
printf("handle_doa_result doa is %d\n", doa);
|
||||
#ifdef DUAL_MIC
|
||||
system("./aispeech_led -m on 1");
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef RK3308_BOARD_V11
|
||||
static char *doa_led_table[12] = {
|
||||
"./aispeech_led -m single -i 2 0",
|
||||
"./aispeech_led -m single -i 3 0",
|
||||
"./aispeech_led -m single -i 4 0",
|
||||
"./aispeech_led -m single -i 5 0",
|
||||
"./aispeech_led -m single -i 6 0",
|
||||
"./aispeech_led -m single -i 7 0",
|
||||
"./aispeech_led -m single -i 8 0",
|
||||
"./aispeech_led -m single -i 9 0",
|
||||
"./aispeech_led -m single -i 10 0",
|
||||
"./aispeech_led -m single -i 11 0",
|
||||
"./aispeech_led -m single -i 0 0",
|
||||
"./aispeech_led -m single -i 1 0"
|
||||
};
|
||||
|
||||
#elif defined(RK3308_BOARD_V10)
|
||||
static char *doa_led_table[12] = {
|
||||
"./aispeech_led -m single -i 7 0",
|
||||
"./aispeech_led -m single -i 8 0",
|
||||
"./aispeech_led -m single -i 9 0",
|
||||
"./aispeech_led -m single -i 10 0",
|
||||
"./aispeech_led -m single -i 11 0",
|
||||
"./aispeech_led -m single -i 0 0",
|
||||
"./aispeech_led -m single -i 1 0",
|
||||
"./aispeech_led -m single -i 2 0",
|
||||
"./aispeech_led -m single -i 3 0",
|
||||
"./aispeech_led -m single -i 4 0",
|
||||
"./aispeech_led -m single -i 5 0",
|
||||
"./aispeech_led -m single -i 6 0"
|
||||
};
|
||||
#endif
|
||||
|
||||
if (doa >= 0) {
|
||||
if (doa >=345 || doa < 15) {
|
||||
system(doa_led_table[0]);
|
||||
} else if (doa >= 15 && doa < 45) {
|
||||
system(doa_led_table[1]);
|
||||
} else if (doa >= 45 && doa < 75) {
|
||||
system(doa_led_table[2]);
|
||||
} else if (doa >= 75 && doa < 105) {
|
||||
system(doa_led_table[3]);
|
||||
} else if (doa >= 105 && doa < 135) {
|
||||
system(doa_led_table[4]);
|
||||
} else if (doa >= 135 && doa < 165) {
|
||||
system(doa_led_table[5]);
|
||||
} else if (doa >= 165 && doa < 195) {
|
||||
system(doa_led_table[6]);
|
||||
} else if (doa >= 195 && doa < 225) {
|
||||
system(doa_led_table[7]);
|
||||
} else if (doa >= 225 && doa < 255) {
|
||||
system(doa_led_table[8]);
|
||||
} else if (doa >= 255 && doa < 285) {
|
||||
system(doa_led_table[9]);
|
||||
} else if (doa >= 285 && doa < 315) {
|
||||
system(doa_led_table[10]);
|
||||
} else if (doa >= 315 && doa < 345) {
|
||||
system(doa_led_table[11]);
|
||||
}
|
||||
}
|
||||
else printf("=== doa result is wrong\n");
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void button_cb(button_event_t ev, void *userdata) {
|
||||
const char *info[] = {
|
||||
"BUTTON_EVENT_VOLUME_ADD",
|
||||
"BUTTON_EVENT_VOLUME_SUB",
|
||||
"BUTTON_EVENT_PREV",
|
||||
"BUTTON_EVENT_NEXT",
|
||||
"BUTTON_EVENT_PLAY_PAUSE",
|
||||
"BUTTON_EVENT_PLAY_PAUSE_LONG",
|
||||
"BUTTON_EVENT_MUTE_UNMUTE",
|
||||
"BUTTON_EVENT_MUTE_UNMUTE_LONG",
|
||||
"BUTTON_EVENT_MODE_WIFI",
|
||||
"BUTTON_EVENT_MODE_NORMAL"
|
||||
};
|
||||
|
||||
printf("%s\n", info[ev]);
|
||||
|
||||
if (ev == BUTTON_EVENT_VOLUME_ADD) {
|
||||
//短按触发
|
||||
play_manager_f("volume.set", "+", NULL);
|
||||
}
|
||||
else if (ev == BUTTON_EVENT_VOLUME_SUB) {
|
||||
//短按触发
|
||||
play_manager_f("volume.set", "-", NULL);
|
||||
}
|
||||
else if (ev == BUTTON_EVENT_PREV) {
|
||||
//长按每隔1.5秒触发一次
|
||||
play_manager_f("change.set", "prev", NULL);
|
||||
play_manager_f("play.list.check", NULL, NULL);
|
||||
}
|
||||
else if (ev == BUTTON_EVENT_NEXT) {
|
||||
//长按每隔1.5秒触发一次
|
||||
play_manager_f("change.set", "next", NULL);
|
||||
play_manager_f("play.list.check", NULL, NULL);
|
||||
}
|
||||
else if (ev == BUTTON_EVENT_PLAY_PAUSE) {
|
||||
//短按触发
|
||||
play_manager_f("status.set", "step", NULL);
|
||||
}
|
||||
else if (ev == BUTTON_EVENT_MUTE_UNMUTE) {
|
||||
// mute
|
||||
if (is_enable_wakeup) {
|
||||
is_enable_wakeup = 0;
|
||||
dds_client_stop_dialog(dc);
|
||||
dds_client_disable_wakeup(dc);
|
||||
//system(DISABLE_WAKEUP_SYSTEM_CMD);
|
||||
}
|
||||
else {
|
||||
is_enable_wakeup = 1;
|
||||
dds_client_enable_wakeup(dc);
|
||||
//system(WAIT_WAKEUP_SYSTEM_CMD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mqtt_cb(const char *topic, const char *topic_data, int data_len, void *user) {
|
||||
printf("mqtt_cb receive: %s: %.*s\n", topic, data_len, topic_data);
|
||||
|
||||
cJSON *root = cJSON_Parse(topic_data);
|
||||
assert(root != NULL);
|
||||
cJSON *volume, *music, *tts;
|
||||
volume = cJSON_GetObjectItem(root, "volume");
|
||||
music = cJSON_GetObjectItem(root, "music");
|
||||
tts = cJSON_GetObjectItem(root, "tts");
|
||||
if (volume) {
|
||||
// 音量设置
|
||||
play_manager_f("volume.set", volume->valuestring, NULL);
|
||||
}
|
||||
if (music) {
|
||||
// 音乐设置
|
||||
cJSON *data;
|
||||
cJSON *change, *status, *mode, *currentIndex;
|
||||
data = cJSON_Parse(music->valuestring);
|
||||
assert(data != NULL);
|
||||
change = cJSON_GetObjectItem(data, "change");
|
||||
if (change) {
|
||||
static char change_cmd[3][10] = {
|
||||
{"nothing"},
|
||||
{"prev"},
|
||||
{"next"}
|
||||
};
|
||||
play_manager_f("change.set", change_cmd[change->valueint], NULL);
|
||||
play_manager_f("play.list.check", NULL, NULL);
|
||||
}
|
||||
status = cJSON_GetObjectItem(data, "status");
|
||||
if (status) {
|
||||
static char status_cmd[3][10] = {
|
||||
{"nothing"},
|
||||
{"resume"},
|
||||
{"pause"}
|
||||
};
|
||||
play_manager_f("status.set", status_cmd[status->valueint], NULL);
|
||||
}
|
||||
mode = cJSON_GetObjectItem(data, "mode");
|
||||
if (mode) {
|
||||
static char mode_cmd[5][10] = {
|
||||
{"nothing"},
|
||||
{"sequence"},
|
||||
{"random"},
|
||||
{"single"},
|
||||
{"loop"}
|
||||
};
|
||||
play_manager_f("mode.set", mode_cmd[mode->valueint], NULL);
|
||||
}
|
||||
|
||||
currentIndex = cJSON_GetObjectItem(data, "currentIndex");
|
||||
if (currentIndex) {
|
||||
char index[8];
|
||||
sprintf(index, "%d", currentIndex->valueint);
|
||||
play_manager_f("play.choose.update", index, NULL);
|
||||
}
|
||||
|
||||
cJSON_Delete(data);
|
||||
}
|
||||
if (tts) {
|
||||
cJSON *data;
|
||||
cJSON *current;
|
||||
data = cJSON_Parse(data->valuestring);
|
||||
assert(data != NULL);
|
||||
current = cJSON_GetObjectItem(data, "current");
|
||||
if (current) {
|
||||
cJSON *voice = cJSON_GetObjectItem(current, "voiceId");
|
||||
dds_client_set_speaker(dc, voice->valuestring);
|
||||
dds_client_speak(dc, "该轮到我上场了");
|
||||
send_tts_update_topic();
|
||||
}
|
||||
cJSON_Delete(data);
|
||||
}
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
|
||||
static send_tts_update_topic () {
|
||||
static char *tts_label[8] = {"甜美女生",
|
||||
"沉稳纲叔",
|
||||
"淡定葛爷",
|
||||
"邻家女声",
|
||||
"标准男声",
|
||||
"可爱童声",
|
||||
"标准女声",
|
||||
NULL};
|
||||
|
||||
static char *tts_voiceId[8] = {"zhilingf", "gdgm", "geyou", "hyanif", "xijunm",
|
||||
"qianranf", "lucyf", NULL};
|
||||
|
||||
cJSON *root, *root2, *array, *temp, *current;
|
||||
root = cJSON_CreateObject();
|
||||
root2 = cJSON_CreateObject();
|
||||
|
||||
array = cJSON_CreateArray();
|
||||
for (int i = 0; tts_voiceId[i]; i++) {
|
||||
temp = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(temp, "voiceId", tts_voiceId[i]);
|
||||
cJSON_AddStringToObject(temp, "label", tts_label[i]);
|
||||
cJSON_AddItemToArray(array, temp);
|
||||
}
|
||||
cJSON_AddItemToObject(root, "list", array);
|
||||
|
||||
current = cJSON_CreateObject();
|
||||
char *speaker = dds_client_get_speaker(dc);
|
||||
int volume = dds_client_get_volume(dc);
|
||||
float speed = dds_client_get_speed(dc);
|
||||
|
||||
cJSON_AddStringToObject(current, "voiceId", speaker);
|
||||
cJSON_AddNumberToObject(current, "volume", volume);
|
||||
cJSON_AddNumberToObject(current, "speed", speed);
|
||||
|
||||
cJSON_AddItemToObject(root, "current", current);
|
||||
|
||||
char *tts = cJSON_PrintUnformatted(root);
|
||||
cJSON_Delete(root);
|
||||
|
||||
cJSON_AddStringToObject(root2, "tts", tts);
|
||||
char *out = cJSON_PrintUnformatted(root2);
|
||||
|
||||
printf("send_tts_update_topic is %s\n", out);
|
||||
busserver_send_msg("ui.control.topics.response", out);
|
||||
|
||||
free(tts);
|
||||
free(out);
|
||||
}
|
||||
|
||||
/*
|
||||
void *button_routine(void *user) {
|
||||
button_config_t config = {
|
||||
.dev = "/dev/input/event0", // v11: event0 | v10: event1
|
||||
.cb = button_cb
|
||||
};
|
||||
button_handle_t button = button_create(&config);
|
||||
while (1) {
|
||||
button_run(button);
|
||||
}
|
||||
button_destroy(button);
|
||||
return (void *)0;
|
||||
}
|
||||
*/
|
||||
|
||||
void *busserver_routine(void *user) {
|
||||
busserver_run("0.0.0.0:50001", mqtt_cb, NULL);
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
int main () {
|
||||
int ret;
|
||||
char config[1024 * 5];
|
||||
FILE *fp = NULL;
|
||||
fp = fopen("./config.json", "r");
|
||||
if (fp) {
|
||||
fread(config, 1, 1024 * 5, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
else return -1;
|
||||
|
||||
// 1. init music player
|
||||
cJSON *root = cJSON_Parse(config);
|
||||
cJSON *player = cJSON_GetObjectItem(root, "player");
|
||||
if (player) {
|
||||
player = cJSON_GetObjectItem(player, "device");
|
||||
if (player) music_player_init(player->valuestring);
|
||||
else music_player_init("default");
|
||||
}
|
||||
else music_player_init("default");
|
||||
|
||||
// 2. start the music player
|
||||
music_player_start();
|
||||
|
||||
// 3. run the busserver
|
||||
pthread_t tid;
|
||||
ret = pthread_create(&tid, NULL, busserver_routine, NULL);
|
||||
assert(ret != -1);
|
||||
|
||||
// 3. run the dds client
|
||||
dc = dds_client_init(config);
|
||||
assert(dc != NULL);
|
||||
|
||||
ret = dds_client_start(dc, dds_cb, NULL);
|
||||
assert(ret != -1);
|
||||
|
||||
// 4. button thread
|
||||
pthread_t tid2;
|
||||
//pthread_create(&tid2, NULL, button_routine, NULL);
|
||||
|
||||
// 5. system init
|
||||
system("amixer cset name='Master Playback Volume' 70");
|
||||
system("chmod +x aispeech_led");
|
||||
|
||||
system("tinymix set 28 3");
|
||||
system("tinymix set 36 18");
|
||||
system("tinymix set 29 3");
|
||||
system("tinymix set 37 18");
|
||||
|
||||
system("tinymix set 26 3");
|
||||
system("tinymix set 35 18");
|
||||
|
||||
send_tts_update_topic();
|
||||
|
||||
select(0, 0, 0, 0, 0);
|
||||
|
||||
dds_client_release(dc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/main.o
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/main.o
Executable file
Binary file not shown.
372
rk3308/aispeech-2mic-32bit/dds_client/demo/music.c
Executable file
372
rk3308/aispeech-2mic-32bit/dds_client/demo/music.c
Executable file
@ -0,0 +1,372 @@
|
||||
/*================================================================
|
||||
* Copyright (C) 2018 AISPEECH Ltd. All rights reserved.
|
||||
*
|
||||
* 文件名称:music.c
|
||||
* 创 建 者:chenjie.gu
|
||||
* 创建日期:2018年05月24日
|
||||
* 描 述:
|
||||
*
|
||||
================================================================*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "audio_player.h"
|
||||
#include <time.h>
|
||||
#include "cJSON.h"
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
audio_player_t *aplayer = NULL;
|
||||
float vol_multiplier = 0.5;
|
||||
int vol_system = 70;
|
||||
int player_is_end = 0;
|
||||
pthread_mutex_t music_mutex;
|
||||
|
||||
int play_judge_f(int index, int count, int mode);
|
||||
|
||||
void play_manager_f(const char *cmd, const char *data, char **user_data);
|
||||
|
||||
static int play_callback(void *userdata, int ev) {
|
||||
if (ev == AUDIO_PLAYER_EV_END) {
|
||||
player_is_end = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *player_routine(void *user) {
|
||||
while (1) {
|
||||
if (player_is_end) {
|
||||
player_is_end = 0;
|
||||
play_manager_f("player.end", NULL, NULL);
|
||||
}
|
||||
usleep(100 * 1000);
|
||||
}
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
int music_player_init(char *dev) {
|
||||
aplayer = audio_player_new(play_callback, NULL);
|
||||
audio_player_set_device(aplayer, dev);
|
||||
audio_player_set_channel_volume(aplayer, vol_multiplier);
|
||||
pthread_mutex_init(&music_mutex, NULL);
|
||||
system("amixer cset name='Master Playback Volume' 70");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int music_player_play(char *path) {
|
||||
audio_player_play(aplayer, path);
|
||||
}
|
||||
|
||||
int music_player_start() {
|
||||
int ret;
|
||||
pthread_t tid;
|
||||
pthread_create(&tid, NULL, player_routine, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void send_vol_update_topic (int vol) {
|
||||
printf("send_vol_update_topic vol is %d\n", vol);
|
||||
char out[128] = {0};
|
||||
sprintf(out, "{\"volume\":\"%d\"}", vol);
|
||||
printf("send_vol_update_topic is %s\n", out);
|
||||
busserver_send_msg("ui.control.topics.response", out);
|
||||
}
|
||||
|
||||
static void send_music_update_topic(int change, int status, int mode, int index, cJSON *list) {
|
||||
printf("send_music_update_topic %d %d %d %d %p\n", change, status, mode, index, list);
|
||||
char *out;
|
||||
cJSON *root, *root2;
|
||||
char *music;
|
||||
|
||||
root = cJSON_CreateObject();
|
||||
root2 = cJSON_CreateObject();
|
||||
cJSON_AddNumberToObject(root, "change", change);
|
||||
cJSON_AddNumberToObject(root, "status", status);
|
||||
cJSON_AddNumberToObject(root, "mode", mode);
|
||||
cJSON_AddNumberToObject(root, "currentIndex", index);
|
||||
if (list) {
|
||||
cJSON *tmp = cJSON_GetObjectItem(list, "content");
|
||||
cJSON_AddItemReferenceToObject(root, "list", tmp);
|
||||
}
|
||||
|
||||
music = cJSON_PrintUnformatted(root);
|
||||
cJSON_Delete(root);
|
||||
|
||||
cJSON_AddStringToObject(root2, "music", music);
|
||||
out = cJSON_PrintUnformatted(root2);
|
||||
cJSON_Delete(root2);
|
||||
|
||||
printf("send_music_update_topic is %s\n", out);
|
||||
busserver_send_msg("ui.control.topics.response", out);
|
||||
free(music);
|
||||
free(out);
|
||||
}
|
||||
|
||||
void play_manager_f(const char *cmd, const char *data, char **user_data) {
|
||||
|
||||
/*
|
||||
* 1. volume.set
|
||||
* 2. play.list.update
|
||||
* 3. play.list.clear
|
||||
* 4. play.list.get
|
||||
* 5. status.set
|
||||
* 6. change.set
|
||||
* 7. mode.set
|
||||
* 8. play.choose.update
|
||||
* 9. play.collect.choose
|
||||
* 10. play.uncollect.choose
|
||||
* 11. player.end
|
||||
* 12. music.info
|
||||
*/
|
||||
|
||||
enum PLAY_MODE {
|
||||
sequence, random, single, loop
|
||||
};
|
||||
|
||||
enum PLAY_STATUS {
|
||||
idle, playing, pause
|
||||
};
|
||||
|
||||
static enum PLAY_MODE mode = sequence;
|
||||
static enum PLAY_STATUS status = idle;
|
||||
static int count = 0;
|
||||
static int index = 0;
|
||||
static int old_index = 0;
|
||||
static cJSON *root = NULL;
|
||||
|
||||
printf("play_manager_f cmd: %s\tdata: %s\n", cmd, data);
|
||||
|
||||
pthread_mutex_lock(&music_mutex);
|
||||
|
||||
if (!strcmp(cmd, "volume.set")) {
|
||||
// 设置音量
|
||||
if (!strcmp(data, "+")) {
|
||||
vol_system += 10;
|
||||
if (vol_system > 100) vol_system = 100;
|
||||
}
|
||||
|
||||
else if (!strcmp(data, "-")) {
|
||||
vol_system -= 10;
|
||||
if (vol_system < 0) vol_system = 0;
|
||||
}
|
||||
else {
|
||||
vol_system = atoi(data);
|
||||
}
|
||||
|
||||
char cmd[64] = {0};
|
||||
sprintf(cmd, "amixer cset name='Master Playback Volume' %d", vol_system);
|
||||
system(cmd);
|
||||
printf("set vol to %d\n", vol_system);
|
||||
send_vol_update_topic(vol_system);
|
||||
}
|
||||
|
||||
else if (!strcmp(cmd, "play.list.clear")) {
|
||||
// 清空播放列表
|
||||
printf("clear the play list info\n");
|
||||
audio_player_stop(aplayer);
|
||||
cJSON_Delete(root);
|
||||
root = NULL;
|
||||
index = 0;
|
||||
old_index = 0;
|
||||
count = 0;
|
||||
status = idle;
|
||||
send_music_update_topic(0, status, mode, index, NULL);
|
||||
}
|
||||
|
||||
else if (!strcmp(cmd, "play.list.get")) {
|
||||
}
|
||||
else if (!strcmp(cmd, "music.info")) {
|
||||
if (root) {
|
||||
cJSON *temp, *music;
|
||||
music = cJSON_GetObjectItem(root, "content");
|
||||
temp = cJSON_GetArrayItem(music, index);
|
||||
*user_data = cJSON_Print(temp);
|
||||
}
|
||||
else *user_data = NULL;
|
||||
}
|
||||
else if (!strcmp(cmd, "play.list.check")) {
|
||||
// 开始真正播放
|
||||
cJSON *temp, *music;
|
||||
if (root) {
|
||||
if (status == idle) {
|
||||
temp = cJSON_GetObjectItem(root, "count");
|
||||
count = temp->valueint;
|
||||
if (count > 0) {
|
||||
status = playing;
|
||||
music = cJSON_GetObjectItem(root, "content");
|
||||
temp = cJSON_GetArrayItem(music, index);
|
||||
temp = cJSON_GetObjectItem(temp, "linkUrl");
|
||||
printf("ready to play url is %s\n", temp->valuestring);
|
||||
audio_player_play(aplayer, temp->valuestring);
|
||||
}
|
||||
}
|
||||
else if (status == pause) {
|
||||
status = playing;
|
||||
audio_player_resume(aplayer);
|
||||
}
|
||||
send_music_update_topic(0, status, mode, index, root);
|
||||
}
|
||||
else send_music_update_topic(0, status, mode, index, NULL);
|
||||
}
|
||||
else if (!strcmp(cmd, "play.list.update")) {
|
||||
// 更新播放列表
|
||||
// TODO: update
|
||||
printf("update the play list info\n");
|
||||
audio_player_stop(aplayer);
|
||||
if (root) cJSON_Delete(root);
|
||||
root = NULL;
|
||||
index = 0;
|
||||
old_index = 0;
|
||||
count = 0;
|
||||
status = idle;
|
||||
root = cJSON_Parse(data);
|
||||
}
|
||||
else if (!strcmp(cmd, "status.set")) {
|
||||
// 设置播放状态
|
||||
printf("status.set data is %s status is %d\n", data, status);
|
||||
if (!strcmp(data, "pause") && status == playing) {
|
||||
status = pause;
|
||||
audio_player_pause(aplayer);
|
||||
}
|
||||
else if (!strcmp(data, "resume") && status == pause) {
|
||||
status = playing;
|
||||
audio_player_resume(aplayer);
|
||||
}
|
||||
else if (!strcmp(data, "replay") && status == pause) {
|
||||
status = playing;
|
||||
}
|
||||
else if (!strcmp(data, "step")) {
|
||||
if (status == playing) {
|
||||
status = pause;
|
||||
audio_player_pause(aplayer);
|
||||
}
|
||||
else if (status == pause) {
|
||||
status = playing;
|
||||
audio_player_resume(aplayer);
|
||||
}
|
||||
}
|
||||
send_music_update_topic(0, status, mode, index, root);
|
||||
}
|
||||
else if (!strcmp(cmd, "mode.set")) {
|
||||
// 播放模式
|
||||
if (!strcmp(data, "sequence")) mode = sequence;
|
||||
else if (!strcmp(data, "random")) mode = random;
|
||||
else if (!strcmp(data, "single")) mode = single;
|
||||
else if (!strcmp(data, "loop")) mode = loop;
|
||||
send_music_update_topic(0, status, mode, index, root);
|
||||
}
|
||||
else if (!strcmp(cmd, "change.set")) {
|
||||
// 歌曲切换
|
||||
// TODO: update
|
||||
if (!strcmp(data, "prev")) {
|
||||
// 上一首
|
||||
index = old_index;
|
||||
}
|
||||
else if (!strcmp(data, "next")) {
|
||||
// 下一首
|
||||
old_index = index;
|
||||
index = play_judge_f(index, count, mode);
|
||||
}
|
||||
else if (!strcmp(data, "change")) {
|
||||
// 换一首
|
||||
old_index = index;
|
||||
index = play_judge_f(index, count, mode);
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
// 播放结束
|
||||
cJSON_Delete(root);
|
||||
audio_player_stop(aplayer);
|
||||
root = NULL;
|
||||
index = 0;
|
||||
old_index = 0;
|
||||
count = 0;
|
||||
status = idle;
|
||||
}
|
||||
else {
|
||||
// 待播放指定的音频
|
||||
status = idle;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(cmd, "play.choose.update")) {
|
||||
// 播放特定歌曲
|
||||
old_index = index;
|
||||
index = atoi(data);
|
||||
cJSON *temp, *music;
|
||||
music = cJSON_GetObjectItem(root, "content");
|
||||
temp = cJSON_GetArrayItem(music, index);
|
||||
temp = cJSON_GetObjectItem(temp, "linkUrl");
|
||||
printf("ready to play url is %s\n", temp->valuestring);
|
||||
audio_player_stop(aplayer);
|
||||
audio_player_play(aplayer, temp->valuestring);
|
||||
send_music_update_topic(0, status, mode, index, root);
|
||||
}
|
||||
else if (!strcmp(cmd, "play.collect.choose")) {
|
||||
// 收藏歌曲
|
||||
}
|
||||
|
||||
else if (!strcmp(cmd, "play.uncollect.choose")) {
|
||||
// 取消收藏
|
||||
}
|
||||
|
||||
else if (!strcmp(cmd, "player.end") && root) {
|
||||
// 播放器播放结束
|
||||
// TODO: update
|
||||
old_index = index;
|
||||
index = play_judge_f(index, count, mode);
|
||||
printf("play_judge_f index is %d\n", index);
|
||||
if (index == -1) {
|
||||
// 播放结束
|
||||
audio_player_stop(aplayer);
|
||||
cJSON_Delete(root);
|
||||
root = NULL;
|
||||
index = 0;
|
||||
old_index = 0;
|
||||
count = 0;
|
||||
status = idle;
|
||||
send_music_update_topic(0, status, mode, index, NULL);
|
||||
}
|
||||
else {
|
||||
// 播放指定的音频
|
||||
cJSON *temp, *music;
|
||||
music = cJSON_GetObjectItem(root, "content");
|
||||
temp = cJSON_GetArrayItem(music, index);
|
||||
temp = cJSON_GetObjectItem(temp, "linkUrl");
|
||||
printf("ready to play url is %s\n", temp->valuestring);
|
||||
audio_player_stop(aplayer);
|
||||
audio_player_play(aplayer, temp->valuestring);
|
||||
send_music_update_topic(0, status, mode, index, root);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&music_mutex);
|
||||
}
|
||||
|
||||
int play_judge_f(int index, int count, int mode) {
|
||||
// sequence, random, single, loop
|
||||
if (mode == 0) {
|
||||
// 顺序播放
|
||||
if (index + 1 == count) return -1;
|
||||
else return index + 1;
|
||||
}
|
||||
else if (mode == 1) {
|
||||
// 随机播放
|
||||
srand(time(0));
|
||||
return rand() % count;
|
||||
}
|
||||
else if (mode == 2) {
|
||||
// 单曲循环
|
||||
return index;
|
||||
}
|
||||
else if (mode == 3) {
|
||||
// 循环播放
|
||||
return (index + 1) % count;
|
||||
}
|
||||
|
||||
else return -1;
|
||||
}
|
||||
|
||||
|
||||
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/music.o
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/music.o
Executable file
Binary file not shown.
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/璇存硶绀轰緥.pdf
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/demo/璇存硶绀轰緥.pdf
Executable file
Binary file not shown.
809
rk3308/aispeech-2mic-32bit/dds_client/doc/sdk甯姪鏂囨。.md
Executable file
809
rk3308/aispeech-2mic-32bit/dds_client/doc/sdk甯姪鏂囨。.md
Executable file
@ -0,0 +1,809 @@
|
||||
## linux-sdk 使用说明
|
||||
|
||||
### 接口说明
|
||||
|
||||
**sdk语音相关的接口**
|
||||
|
||||
```
|
||||
sdk 初始化函数,主要包括sdk参数初始化和授权两个过程,这个函数是阻塞的,
|
||||
授权的超时时间为 15 秒。
|
||||
|
||||
struct dds_client *dds_client_init (const char *config_json);
|
||||
|
||||
参数说明:
|
||||
|
||||
@ config_json: 配置选项,json 格式的字符串;
|
||||
|
||||
返回值:
|
||||
|
||||
错误情况下返回NULL, 否则返回 struct dds_client 实例指针;
|
||||
```
|
||||
```
|
||||
运行 sdk 函数,调用此函数之后就可以语音交互了。
|
||||
|
||||
int dds_client_start(struct dds_client *ds, ddsLintener cb,
|
||||
void *user);
|
||||
|
||||
参数说明:
|
||||
|
||||
@ ds: 由 dds_client_init 返回的 struct dds_client 实例指针;
|
||||
@ cb: 监听 sdk 事件的回调函数;
|
||||
@ user: 用户参数;
|
||||
|
||||
返回值:
|
||||
|
||||
出错返回 -1
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
释放 sdk 实例的函数:
|
||||
|
||||
void dds_client_release(struct dds_client *ds);
|
||||
|
||||
参数说明:
|
||||
|
||||
@ ds: 由 dds_client_init 返回的 struct dds_client 实例指针;
|
||||
|
||||
```
|
||||
|
||||
**下面的接口必须在 `dds_client_init ` 和 `dds_client_start` 正确返回之后才能正确执行。**
|
||||
|
||||
```
|
||||
向 sdk 内部发送消息:
|
||||
|
||||
int dds_client_publish(struct dds_client *ds, int ev,
|
||||
const char *data);
|
||||
|
||||
参数说明:
|
||||
@ ds: 由 dds_client_init 返回的 struct dds_client 实例指针;
|
||||
@ ev: 发送的消息事件;
|
||||
@ data: 此消息附带的数据, json 格式;
|
||||
|
||||
|
||||
返回值:
|
||||
|
||||
只有当 sdk 完成初始化并且授权成功之后才能正确返回,否则返回 -1
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
返回 nativeAPI 查询结果的接口
|
||||
|
||||
int dds_client_resp_nativeapi(struct dds_client *ds,
|
||||
const char *native_api, const char *native_api_data_json);
|
||||
|
||||
参数说明:
|
||||
|
||||
ds: sdk 实例指针;
|
||||
|
||||
native_api: 这个 nativeAPI topic 名;
|
||||
|
||||
native_api_data_json: 查询数据结果,json string,格式如下,
|
||||
"duiWidget" 字段必须包含, 且目前取值为 "text"。 用户自定义的数据必须放在
|
||||
extra 字段中。
|
||||
|
||||
{
|
||||
"duiWidget": "text",
|
||||
"extra": {
|
||||
"xx": "11"
|
||||
}
|
||||
}
|
||||
|
||||
返回值: 如果 sdk 没有初始化完成或者授权成功则返回-1
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
内部合成的接口:
|
||||
|
||||
int dds_client_speak(struct dds_client *ds, const char *text);
|
||||
|
||||
参数说明:
|
||||
|
||||
ds: sdk 实例指针
|
||||
|
||||
text: 需要合成的文本
|
||||
|
||||
返回值: 如果 sdk 没有初始化完成或者授权成功则返回-1
|
||||
```
|
||||
|
||||
```
|
||||
外部 feed 音频接口:
|
||||
|
||||
int dds_client_feed_audio(struct dds_client *ds, char *data, int len);
|
||||
|
||||
参数说明:
|
||||
|
||||
ds: sdk 实例指针
|
||||
|
||||
data: 录音机数据
|
||||
|
||||
len: 数据长度
|
||||
|
||||
返回值: 出错返回 -1 ,此接口只有在 recorder 配置为外部方式才会生效。
|
||||
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
停止当前对话,包括停止合成,取消识别等。
|
||||
|
||||
int dds_client_stop_dialog(struct dds_client *ds);
|
||||
|
||||
参数说明:
|
||||
|
||||
ds: sdk 实例指针
|
||||
|
||||
text: 需要合成的文本
|
||||
|
||||
返回值: 如果 sdk 没有初始化完成或者授权成功则返回-1
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
关闭唤醒,如果在语音对话过程中调用此接口,会在这条对话自然结束之后才会禁止唤醒。
|
||||
|
||||
int dds_client_disable_wakeup(struct dds_client *ds);
|
||||
|
||||
参数说明:
|
||||
|
||||
ds: sdk 实例指针
|
||||
|
||||
返回值: 如果 sdk 没有初始化完成或者授权成功则返回-1
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
打开唤醒
|
||||
|
||||
int dds_client_enable_wakeup(struct dds_client *ds);
|
||||
|
||||
参数说明:
|
||||
|
||||
ds: sdk 实例指针
|
||||
|
||||
返回值: 如果 sdk 没有初始化完成或者授权成功则返回-1
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
设置用户唤醒词
|
||||
|
||||
int dds_client_update_customword(struct dds_client *ds,
|
||||
const char *word);
|
||||
|
||||
参数说明:
|
||||
ds: sdk 实例指针
|
||||
word: 唤醒词配置,格式是 json string,说明如下:
|
||||
|
||||
{
|
||||
"greetingFile":"path:../res/tts/help.mp3", 可选
|
||||
"greeting": "我在,有什么可以帮你", 可选
|
||||
"pinyin": "ni hao xiao chi", 必选
|
||||
"name": "你好小驰", 必选
|
||||
"threshold": 0.127 必选
|
||||
}
|
||||
|
||||
此函数成功返回后,唤醒词的相关配置会更新到 config.json 文件。
|
||||
对于客户端异常断电可能导致 config.json 文件破坏的话, 需要开发者自己来避免,
|
||||
比如采用备份文件的机制。
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
获取当前的唤醒词
|
||||
|
||||
char* dds_client_get_wakeupwords(struct dds_client *ds);
|
||||
|
||||
参数说明:
|
||||
ds: sdk 实例指针
|
||||
|
||||
此函数返回字符串指针, 开发者需要主动释放内存。 返回字符串为json格式,如下:
|
||||
|
||||
{
|
||||
"majorword": [{
|
||||
"greetingFile": "path:../res/tts/help.mp3",
|
||||
"greeting": "我在,有什么可以帮你",
|
||||
"pinyin": "ni hao xiao le",
|
||||
"name": "你好小乐",
|
||||
"threshold": 0.144000
|
||||
}],
|
||||
"minorword": [{
|
||||
"greetingFile": "path:../res/tts/help.mp3",
|
||||
"greeting": "我在,有什么可以帮你",
|
||||
"pinyin": "ni hao xiao chi",
|
||||
"name": "你好小驰",
|
||||
"threshold": 0.127000
|
||||
}],
|
||||
"cmdword": [{
|
||||
"pinyin": "jiang di yin liang",
|
||||
"threshold": 0.100000,
|
||||
"action": "decrease.volume",
|
||||
"name": "降低音量"
|
||||
}],
|
||||
"customword": [{
|
||||
"pinyin": "ni hao tiam mao",
|
||||
"name": "你好天猫",
|
||||
"threshold": 0.200000
|
||||
}]
|
||||
}
|
||||
|
||||
majorword 为主唤醒词,minorword 为副唤醒词, cmdword 为命令词,
|
||||
customword 为用户定义唤醒词。 其实就是 config.json 文件里面的配置。
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
// 获取当前的 tts 发音人,出错返回 NULL
|
||||
char *dds_client_get_speaker(struct dds_client *ds);
|
||||
|
||||
// 获取当前的 tts 播报速度,为 float 型, 在 0 ~ 1 之间,越大表示速度越慢。
|
||||
float dds_clent_get_speed(struct dds_client *ds);
|
||||
|
||||
// 获取当前的 tts 的播报音量大小, 为 int 型, 在 0 ~ 100 之间。
|
||||
int dds_client_get_volume(struct dds_client *ds);
|
||||
|
||||
// 设置当前的 tts 的播报音色人,出错返回 -1
|
||||
int dds_client_set_speaker(struct dds_client *ds, char *speaker);
|
||||
|
||||
// 设置当前的 tts 的播报速度大小,出错返回 -1
|
||||
int dds_client_set_speed(struct dds_client *ds, float speed);
|
||||
|
||||
// 设置当前的 tts 的播报音量大小,出错返回 -1
|
||||
int dds_client_set_volume(struct dds_client *ds, int vol);
|
||||
|
||||
```
|
||||
|
||||
**sdk回调消息接口**
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>回调函数</th>
|
||||
<th>消息</th>
|
||||
<th>含义</th>
|
||||
<th>参数</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> ddsLintener </td>
|
||||
<td> local_wakeup.result </td>
|
||||
<td> 唤醒事件 </td>
|
||||
<td> json string,形如
|
||||
{"type":"major","greeting":"好的",
|
||||
"word":"你好小驰"} </td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td> ddsLintener </td>
|
||||
<td> doa.result </td>
|
||||
<td> doa事件 </td>
|
||||
<td> json string, 形如 {"dao": 100} </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> ddsLintener </td>
|
||||
<td> sys.vad.begin </td>
|
||||
<td> vad开始的事件 </td>
|
||||
<td> 无 </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> ddsLintener </td>
|
||||
<td> sys.vad.end </td>
|
||||
<td> vad结束的事件 </td>
|
||||
<td> 无 </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> ddsLintener </td>
|
||||
<td> sys.tts.begin </td>
|
||||
<td> 合成音开始的事件 </td>
|
||||
<td> 无 </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> ddsLintener </td>
|
||||
<td> sys.tts.end </td>
|
||||
<td> 合成音结束的事件,播放结束 </td>
|
||||
<td> 无 </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> ddsLintener </td>
|
||||
<td> sys.asr.begin </td>
|
||||
<td> sdk内部开始做识别 </td>
|
||||
<td> 无 </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> ddsLintener </td>
|
||||
<td> asr.speech.text </td>
|
||||
<td> 实时的语音识别结果反馈 </td>
|
||||
<td> json string </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> ddsLintener </td>
|
||||
<td> asr.speech.result </td>
|
||||
<td> 最终的语音识别结果反馈 </td>
|
||||
<td> json string </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> ddsLintener </td>
|
||||
<td> dm.output </td>
|
||||
<td> 对话的输出结果 </td>
|
||||
<td> json string </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> ddsLintener </td>
|
||||
<td> sys.dm.end </td>
|
||||
<td> 表示结束对话 </td>
|
||||
<td> 无 </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> ddsLintener </td>
|
||||
<td> device.mode.return </td>
|
||||
<td> 表示设置设备状态的回复消息 </td>
|
||||
<td> json string "{"result":"success"}"</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> ddsLintener </td>
|
||||
<td> sys.client.error </td>
|
||||
<td> 表示客户端出现异常情况 </td>
|
||||
<td> json string "{"error":"ttsError"}" 目前 error 字段的取值一共有: ttsError, ddsNetworkError, vadSlienceTimeout</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> ddsLintener </td>
|
||||
<td> command://xx </td>
|
||||
<td> 在dui平台上配置的 command 指令 </td>
|
||||
<td> json string </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> ddsLintener </td>
|
||||
<td> native://xx </td>
|
||||
<td> 在dui平台上配置的 native 指令 </td>
|
||||
<td> json string </td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
### 配置选项
|
||||
|
||||
```
|
||||
|
||||
{
|
||||
"sdk": {
|
||||
"configPath":"./config.json"
|
||||
},
|
||||
"auth": {
|
||||
"productId": "278569448",
|
||||
"deviceProfile": ""
|
||||
},
|
||||
"front": {
|
||||
"aecBinPath": "",
|
||||
"wakeupBinPath": "",
|
||||
"beamformingBinPath": "",
|
||||
"rollBack": 0
|
||||
},
|
||||
"vad": {
|
||||
"resBinPath": "",
|
||||
"pauseTime": 500,
|
||||
"slienceTimeout": 5
|
||||
},
|
||||
"cloud": {
|
||||
"productId": "278569448",
|
||||
"aliasKey": "prod"
|
||||
},
|
||||
"recorder": {
|
||||
"mode": "internal"
|
||||
"samplerate":16000,
|
||||
"bits":16,
|
||||
"channels":1,
|
||||
"device": "default"
|
||||
},
|
||||
"player": {
|
||||
"device": "default"
|
||||
},
|
||||
"tts": {
|
||||
"type": "cloud",
|
||||
"voice": "zhilingf",
|
||||
"volume": 50,
|
||||
"speed": 0.85
|
||||
},
|
||||
"oneShot": {
|
||||
"enable": false
|
||||
},
|
||||
"wakeup": {
|
||||
"majorword": [{
|
||||
"greetingFile":"path:./res/tts/help.mp3",
|
||||
"greeting": "我在,有什么可以帮你",
|
||||
"pinyin": "ni hao xiao le",
|
||||
"name": "你好小乐",
|
||||
"threshold": 0.144
|
||||
}],
|
||||
"minorword": [{
|
||||
"greetingFile":"path:./res/tts/help.mp3",
|
||||
"greeting": "我在,有什么可以帮你",
|
||||
"pinyin": "ni hao xiao chi",
|
||||
"name": "你好小驰",
|
||||
"threshold": 0.127
|
||||
}],
|
||||
"minorword": [{
|
||||
"greetingFile":"path:./res/tts/help.mp3",
|
||||
"greeting": "我在,有什么可以帮你",
|
||||
"pinyin": "ni hao xiao bu",
|
||||
"name": "你好小步",
|
||||
"threshold": 0.127
|
||||
}],
|
||||
"cmdword": [{
|
||||
"pinyin": "jiang di yin liang",
|
||||
"threshold": 0.100,
|
||||
"action": "decrease.volume",
|
||||
"name": "降低音量"
|
||||
}]
|
||||
},
|
||||
"abnormal": {
|
||||
"netErrorHint":"path:../res/tts/net.mp3",
|
||||
"ttsErrorHint":"path:../res/tts/tts_error.mp3"
|
||||
},
|
||||
"debug": {
|
||||
"recAudioDumpFile":"",
|
||||
"bfAudioDumpFile":""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>参数</th>
|
||||
<th>类型</th>
|
||||
<th>含义</th>
|
||||
<th>是否必须</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> sdk </td>
|
||||
<td> json 对象 </td>
|
||||
<td> 客户端的一些配置 </td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> sdk.configPath </td>
|
||||
<td> string </td>
|
||||
<td> 配置文件路径 </td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> auth </td>
|
||||
<td> json 对象 </td>
|
||||
<td> 授权信息 </td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> auth.productId </td>
|
||||
<td>string</td>
|
||||
<td> dui 上创建产品ID </td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> auth.deviceProfile </td>
|
||||
<td>string</td>
|
||||
<td>授权信息</td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> front </td>
|
||||
<td>json 对象 </td>
|
||||
<td> 前端信号处理的相关配置 </td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> front.aecBinPath </td>
|
||||
<td> string</td>
|
||||
<td>aec 算法资源路径</td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> front.wakeupBinPath </td>
|
||||
<td>string</td>
|
||||
<td>唤醒算法资源路径</td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> front.beamformingBinPath </td>
|
||||
<td>string</td>
|
||||
<td>beamforming 算法资源路径</td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> vad </td>
|
||||
<td> json 对象 </td>
|
||||
<td>vad 算法模块配置 </td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> vad.resBinPath </td>
|
||||
<td>string</td>
|
||||
<td>vad算法资源路径 </td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> vad.pauseTime </td>
|
||||
<td>int</td>
|
||||
<td>vad截止检测时长,单位为 ms,默认为 500ms </td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> vad.slienceTimeout </td>
|
||||
<td>int</td>
|
||||
<td> vad 的静音检测超时时长,单位为s,默认为 6s </td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> cloud </td>
|
||||
<td>json 对象 </td>
|
||||
<td>云端产品的相关配置 </td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>cloud.productId </td>
|
||||
<td>string</td>
|
||||
<td>dui平台上创建的产品ID</td>
|
||||
<td>必选 </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> cloud.aliasKey </td>
|
||||
<td>string</td>
|
||||
<td> dui平台上创建的产品ID 发布支持, 取值为 "prod | test"</td>
|
||||
<td>可选,默认为 prod 分支</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>recorder </td>
|
||||
<td>json 对象 </td>
|
||||
<td>录音机的相关配置 </td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> recorder.mode </td>
|
||||
<td> string </td>
|
||||
<td> 录音方式,取值为 "internal | external" 分列表示内部录音和外部录音。 </td>
|
||||
<td> 可选 </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> recorder.samplerate </td>
|
||||
<td> int </td>
|
||||
<td> 录音采样率 </td>
|
||||
<td> 必选 </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> recorder.bits </td>
|
||||
<td>int</td>
|
||||
<td>录音采样位数</td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> recorder.channels </td>
|
||||
<td>int</td>
|
||||
<td>录音采用通道数</td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> recorder.device </td>
|
||||
<td> string </td>
|
||||
<td>内部录音机的设备名,默认当前系统的 default 音频设备 </td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> player</td>
|
||||
<td> json 对象 </td>
|
||||
<td>内部播放器的设置 </td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> player.device </td>
|
||||
<td> string </td>
|
||||
<td>内部播放器的设备名,默认为 default </td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> tts </td>
|
||||
<td>json 对象</td>
|
||||
<td>合成音的相关配置</td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td> tts.type </td>
|
||||
<td>string </td>
|
||||
<td>合成音的类型,当前仅支持 "cloud" </td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> tts.voice </td>
|
||||
<td>string </td>
|
||||
<td>合成音的音色 </td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> tts.volume </td>
|
||||
<td> int </td>
|
||||
<td>合成音的音量 </td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> tts.speed </td>
|
||||
<td> int </td>
|
||||
<td>合成音的速度 </td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> oneShot </td>
|
||||
<td> json 对象 </td>
|
||||
<td> oneshot 模块配置 </td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> oneShot.enable </td>
|
||||
<td> bool </td>
|
||||
<td> 是否启用oneshot,当前仅支持 false </td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> wakeup </td>
|
||||
<td> json 对象 </td>
|
||||
<td> 唤醒词的相关配置</td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> wakeup.majorword </td>
|
||||
<td> json 数组 </td>
|
||||
<td> 主唤醒词的相关配置</td>
|
||||
<td>必选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> wakeup.minorword </td>
|
||||
<td> json 数组 </td>
|
||||
<td> 副唤醒词的相关配置</td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> wakeup.customword </td>
|
||||
<td> json 数组 </td>
|
||||
<td> 用户定义唤醒词的相关配置</td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td> wakeup.cmdword </td>
|
||||
<td> json 数组 </td>
|
||||
<td> 快捷唤醒词配置 </td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> abnormal </td>
|
||||
<td> json 对象 </td>
|
||||
<td> sdk异常情况下对话配置 </td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> abnormal.netErrorHint </td>
|
||||
<td> string </td>
|
||||
<td> 网络错误下的提示音,需要配置成本地文件,网络不好的情况下云端合成也用不了。 </td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> abnormal.ttsErrorHint </td>
|
||||
<td> string </td>
|
||||
<td> 云端tts合成播放错误情况下的的提示音,需要配置成本地文件。 </td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> debug</td>
|
||||
<td> json 对象 </td>
|
||||
<td> 保存音频的配置选项 </td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> debug.recAudioDumpFile</td>
|
||||
<td> string </td>
|
||||
<td> 原始录音保存文件路径 </td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> debug.bfAudioDumpFile</td>
|
||||
<td> string </td>
|
||||
<td> beamforming算法输出的音频文件路径 </td>
|
||||
<td>可选</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
**唤醒词说明**
|
||||
|
||||
```
|
||||
{
|
||||
"greetingFile":"path:./res/tts/help.mp3",
|
||||
"greeting": "我在,有什么可以帮你",
|
||||
"pinyin": "ni hao xiao chi",
|
||||
"name": "你好小驰",
|
||||
"threshold": 0.127
|
||||
}
|
||||
|
||||
|
||||
greetingFile: 唤醒之后播放的提示音,支持本地录音文件,传入文件路径。
|
||||
greeting: 唤醒之后的提示文本, sdk内部合成。
|
||||
pinyin: 唤醒词拼音。
|
||||
name: 唤醒词的中文。
|
||||
threshold: 唤醒词阈值。
|
||||
|
||||
唤醒提示音播放优先级: 如果配置了 greetingFile 则播放 greetingFile ,
|
||||
否则播放 greeting 。
|
||||
|
||||
```
|
||||
|
||||
|
||||
**命令唤醒词说明**
|
||||
|
||||
```
|
||||
{
|
||||
"pinyin": "jiang di yin liang",
|
||||
"threshold": 0.100,
|
||||
"action": "decrease.volume",
|
||||
"name": "降低音量"
|
||||
}
|
||||
|
||||
pinyin: 唤醒词拼音。
|
||||
name: 唤醒词的中文。
|
||||
threshold: 唤醒词阈值。
|
||||
action: 该命令唤醒词对应的动作,比如这个例子中,sdk回调函数会抛出
|
||||
command://decrease.volume 消息。
|
||||
```
|
||||
BIN
rk3308/aispeech-2mic-32bit/dds_client/doc/sdk甯姪鏂囨。.pdf
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/doc/sdk甯姪鏂囨。.pdf
Executable file
Binary file not shown.
BIN
rk3308/aispeech-2mic-32bit/dds_client/libs/libaudio_play.so
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/libs/libaudio_play.so
Executable file
Binary file not shown.
BIN
rk3308/aispeech-2mic-32bit/dds_client/libs/libauth.so
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/libs/libauth.so
Executable file
Binary file not shown.
BIN
rk3308/aispeech-2mic-32bit/dds_client/libs/libdds.so
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/libs/libdds.so
Executable file
Binary file not shown.
BIN
rk3308/aispeech-2mic-32bit/dds_client/libs/libdds_client.so
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/libs/libdds_client.so
Executable file
Binary file not shown.
BIN
rk3308/aispeech-2mic-32bit/dds_client/libs/libduilite_fespl.so
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/libs/libduilite_fespl.so
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
rk3308/aispeech-2mic-32bit/dds_client/res/tts/help.mp3
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/res/tts/help.mp3
Executable file
Binary file not shown.
BIN
rk3308/aispeech-2mic-32bit/dds_client/res/tts/net.mp3
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/res/tts/net.mp3
Executable file
Binary file not shown.
BIN
rk3308/aispeech-2mic-32bit/dds_client/res/tts/tts_error.mp3
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/res/tts/tts_error.mp3
Executable file
Binary file not shown.
BIN
rk3308/aispeech-2mic-32bit/dds_client/res/tts/vol.mp3
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/res/tts/vol.mp3
Executable file
Binary file not shown.
BIN
rk3308/aispeech-2mic-32bit/dds_client/res/vad/vad_aihome_v0.6.bin
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/res/vad/vad_aihome_v0.6.bin
Executable file
Binary file not shown.
BIN
rk3308/aispeech-2mic-32bit/dds_client/res/wakeup/wakeup_aifar_comm_20180104.bin
Executable file
BIN
rk3308/aispeech-2mic-32bit/dds_client/res/wakeup/wakeup_aifar_comm_20180104.bin
Executable file
Binary file not shown.
23
rk3308/aispeech-2mic-32bit/dds_service.sh
Executable file
23
rk3308/aispeech-2mic-32bit/dds_service.sh
Executable file
@ -0,0 +1,23 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
#
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo "Starting $0..."
|
||||
cd /oem/dds_client/demo && ./demo_main &
|
||||
;;
|
||||
stop)
|
||||
echo "Stop $0..."
|
||||
killall demo_main
|
||||
;;
|
||||
restart|reload)
|
||||
killall demo_main
|
||||
cd /oem/dds_client/demo && ./demo_main &
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart}"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit $?
|
||||
Reference in New Issue
Block a user