Merge "oem add: dds_client-rk3308-32-dual-sdk-v0.5.2 rk3308_2mic_release-0.52-online"

This commit is contained in:
yuyongzhen
2018-12-21 11:56:44 +08:00
committed by Gerrit Code Review
222 changed files with 5649 additions and 0 deletions

View File

@ -0,0 +1,11 @@
## 基本信息:
平台: rk3308-32
录音: 2chs_1ref
内核版本: duilite_v0.1.98(wtkv1.9.27.5, fesplv1.1.0.5, ttsv2.02, NRv1.0.1)
dds版本: v0.2.17
AEC资源: AEC_ch3-2-ch2_1ref_common_20180806_v0.9.4.bin 03b08816196b5456bbc701e10c8580f4
BF资源: UDA_asr_chan2-2-mic2_30mm_v1.1.0.6_20180828.bin 774867db1240d863fbe959313ce0f572
WK资源: wakeup_aifar_comm_20180104.bin 0507e6588c7fc6d8ca4feeb12e6cec68
VAD资源: vad_aihome_v0.6.bin 0227b2b1b39a66212f0e8140e77f7069
config: ./demo/config_rk3308-32_fespl2_meiling.json

View File

@ -0,0 +1 @@
cd /oem/demo/ && ./demo_main &

View 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

View File

@ -0,0 +1,115 @@
/*================================================================
* * 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.5.2"
#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
#define DDS_CLIENT_USER_EXTERNAL_WAKEUP 1002
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);
int dds_client_trigger_intent(struct dds_client *ds, char *skill, char *task,
char *intent, char *slots);
/*
* 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);
/*
* 声纹相关
*/
char *dds_client_vprint_get_detail(struct dds_client *ds);
int dds_client_vprint_regist(struct dds_client *ds, char *name);
int dds_client_vprint_unregist(struct dds_client *ds, char *name);
/*
* 能量接口
*/
int dds_client_energy_estimate(struct dds_client* ds, int second);
/*
* 设备端接口
*/
int dds_client_upload_location(struct dds_client* ds, char *city);
#ifdef __cplusplus
}
#endif
#endif //DDS_CLIENT_H

View File

@ -0,0 +1,23 @@
LOCAL_MODULE := demo_main
LOCAL_SRC_FILES += main.c
LOCAL_SRC_FILES += music.c
LOCAL_SRC_DIRS += json
LOCAL_CFLAGS := -rdynamic -g -O0 -Wall -DMG_ENABLE_THREADS -Wno-unused-variable -fPIC
LOCAL_CFLAGS += -I.. -Ijson/
LOCAL_LDFLAGS += -Wl,-rpath,../
LOCAL_LDFLAGS += -L../ -ldds_client
LOCAL_LDFLAGS += -Wl,-rpath,../libs/
LOCAL_LDFLAGS += -L../libs/ -ldds
LOCAL_LDFLAGS += -L../libs/ -laudio_play
LOCAL_LDFLAGS += -lpthread
LOCAL_LDFLAGS += -L../libs/ -lduilite_fespl
LOCAL_LDFLAGS += -L../libs/ -lauth
LOCAL_LDFLAGS += -lasound
LOCAL_CXXFLAGS := LOCAL_CFLAGS -rdynamic
include $(BUILD_EXECUTABLE)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,75 @@
{
"sdk": {
"configPath":"./config.json"
},
"auth": {
"productId": "278572662",
"deviceProfile":"xYKXuuou17VptMur5lwru2/naA1fyB8nyRdtcUPCCRR+Ei0qMIzh9oTdm5qJlpyarJqcjZqL3cXdnM/Oy56bzsrMzM3My8+bnMbJnJvJx8icns7Jxpqazcvd092ek5OQiN3FztPdj42Qm4qci7ab3cXdzcjHysjNycnN3dPdm5qJlpyasZ6Smt3F3Z2czp2eyZvPzM/MmsuZzMaemprOypzInMqam8ibnsyd3dPdjJyQj5rdxaTdnpOT3aKC1"
},
"front": {
"aecBinPath": "../res/fesp/AEC_ch3-2-ch2_1ref_common_20180806_v0.9.4.bin",
"wakeupBinPath": "../res/wakeup/wakeup_aifar_comm_20180104.bin",
"beamformingBinPath": "../res/fesp/UDA_asr_chan2-2-mic2_30mm_v1.1.0.6_20180828.bin",
"env":"words=ni hao xiao le;thresh=0.34;dcheck=0;major=1;",
"rollBack": 1700,
"resNRBinPath":"../res/vprint/NR_v1.0.1_20180816.bin",
"wakeupBinPath2":"../res/wakeup/wakeup_aifar_comm_qike_v10.bin",
"env2":"words=da kai kong tiao,guan bi kong tiao,da kai sheng yin,zeng da yin liang,jian xiao yin liang,guan bi sheng yin,qie huan nan sheng,qie huan nv sheng,sheng wen cai ji,qing chu cai ji xin xi,zhi leng mo shi,zhi re mo shi,nuan feng mo shi,song feng mo shi,pi ei mu wei mo shi,kong qi qing xin,chu shi mo shi,kong wen chu shi,jie neng mo shi,guan bi jie neng,dian jia re,guan bi dian jia re,feng sui sheng dong,guan bi feng sui sheng dong,feng ni sheng dong,guan bi feng ni sheng dong,ge xing mo shi,guan bi ge xing mo shi,ting zhi bai dong,zuo you bai dong,shang xia bai dong,zui xiao feng,zhong deng feng,zui da feng,zeng da feng su,jian xiao feng su,zi dong feng,shang shu shi feng,xia shu shi feng,quan shu shi feng,sheng gao wen du,jiang di wen du,shi liu du,shi qi du,shi ba du,shi jiu du,er shi du,er shi yi du,er shi er du,er shi san du,er shi si du,er shi wu du,er shi liu du,er shi qi du,er shi ba du,er shi jiu du,san shi du,san shi yi du,san shi er du,kai ji,guan ji,shu shi mo shi,yi shei ou,guan bi yi shei ou,feng da dian,feng xiao dian,tai re le,tai leng le;thresh=0.25,0.28,0.29,0.13,0.20,0.29,0.17,0.13,0.16,0.06,0.28,0.24,0.30,0.38,0.06,0.25,0.45,0.19,0.30,0.28,0.30,0.14,0.23,0.20,0.23,0.22,0.28,0.14,0.14,0.16,0.12,0.26,0.26,0.32,0.20,0.20,0.36,0.22,0.14,0.25,0.18,0.12,0.40,0.40,0.40,0.40,0.55,0.36,0.30,0.30,0.38,0.24,0.32,0.36,0.36,0.26,0.42,0.28,0.22,0.40,0.40,0.38,0.22,0.14,0.30,0.30,0.30,0.28;dcheck=0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0;"
},
"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,
"zhilingf": {
"resBinPath": "../res/tts/cntts/zhilingf_common_param_ce_local.v2.008.bin",
"dictPath": "../res/tts/cntts/aitts_sent_dict_v3.26.db"
}
},
"vprint": {
"resBinPath":"../res/vprint/vprint_aihome_qikekongtiao_20180916.bin",
"modelFile":"../res/vprint/model.bin",
"resWkBinPath":"../res/vprint/wakeup_aihome_qi_ke_kong_tiao_20180816.bin",
"resNRBinPath":"../res/vprint/NR_v1.0.1_20180816.bin",
"env":"words=qi ke kong tiao;thresh=0.13;dcheck=1;"
},
"oneShot": {
"enable": false
},
"wakeup": {
"majorword": [{
"greetingFile":"path:../res/tts/help.mp3",
"greeting": "我在,有什么可以帮你",
"pinyin": "qi ke kong tiao",
"name": "启客空调",
"threshold": 0.13
}]
},
"abnormal": {
"netErrorHint":"path:../res/tts/net.mp3",
"ttsErrorHint":"path:../res/tts/tts_error.mp3"
},
"debug": {
"recAudioDumpFile":"",
"bfAudioDumpFile":""
}
}

Binary file not shown.

View 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.
}

View 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

View File

@ -0,0 +1,455 @@
/*================================================================
* 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 "cJSON.h"
struct dds_client *dc = NULL;
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);
/*
* 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
*/
static char cmd_word_hint_map[69][64] = {
{"command://qi ke kong tiao"},
{"command://da kai kong tiao"},
{"command://guan bi kong tiao"},
{"command://da kai sheng yin"},
{"command://zeng da yin liang"},
{"command://jian xiao yin liang"},
{"command://guan bi sheng yin"},
{"command://qie huan nan sheng"},
{"command://qie huan nv sheng"},
{"command://sheng wen cai ji"},
{"command://qing chu cai ji xin xi"},
{"command://zhi leng mo shi"},
{"command://zhi re mo shi"},
{"command://nuan feng mo shi"},
{"command://song feng mo shi"},
{"command://pi ei mu wei mo shi"},
{"command://kong qi qing xin"},
{"command://chu shi mo shi"},
{"command://kong wen chu shi"},
{"command://jie neng mo shi"},
{"command://guan bi jie neng"},
{"command://dian jia re"},
{"command://guan bi dian jia re"},
{"command://feng sui sheng dong"},
{"command://guan bi feng sui sheng dong"},
{"command://feng ni sheng dong"},
{"command://guan bi feng ni sheng dong"},
{"command://ge xing mo shi"},
{"command://guan bi ge xing mo shi"},
{"command://ting zhi bai dong"},
{"command://zuo you bai dong"},
{"command://shang xia bai dong"},
{"command://zui xiao feng"},
{"command://zhong deng feng"},
{"command://zui da feng"},
{"command://zeng da feng su"},
{"command://jian xiao feng su"},
{"command://zi dong feng"},
{"command://shang shu shi feng"},
{"command://xia shu shi feng"},
{"command://quan shu shi feng"},
{"command://sheng gao wen du"},
{"command://jiang di wen du"},
{"command://shi liu du"},
{"command://shi qi du"},
{"command://shi ba du"},
{"command://shi jiu du"},
{"command://er shi du"},
{"command://er shi yi du"},
{"command://er shi er du"},
{"command://er shi san du"},
{"command://er shi si du"},
{"command://er shi wu du"},
{"command://er shi liu du"},
{"command://er shi qi du"},
{"command://er shi ba du"},
{"command://er shi jiu du"},
{"command://san shi du"},
{"command://san shi yi du"},
{"command://san shi er du"},
{"command://kai ji"},
{"command://guan ji"},
{"command://shu shi mo shi"},
{"command://yi shei ou"},
{"command://guan bi yi shei ou"},
{"command://feng da dian"},
{"command://feng xiao dian"},
{"command://tai re le"},
{"command://tai leng le"}
};
void dds_cb(const char *topic, const char *topic_data, void *user) {
static int end_dialog = 0;
static int num = 0;
printf("dds cb receive topic: %s\n", topic);
printf("dds cb receive topic_data: %s\n", topic_data);
if (!strncmp(topic, "command", 7)) {
for (int i = 0; i < 69; i++) {
if (!strcmp(topic, cmd_word_hint_map[i])) {
// do the speak
char wav_name[16] = {0};
sprintf(wav_name, "./audio/%d.wav", i + 1);
char play_cmd[32] = {0};
sprintf(play_cmd, "aplay %s", wav_name);
system(play_cmd);
break;
}
}
}
if (!strcmp(topic, "command://sheng wen cai ji")) {
// 注册声纹
char name[64] = {0};
sprintf(name, "{\"name\":\"%s%d\"}", "test", ++num);
dds_client_vprint_regist(dc, name);
}
else if (!strcmp(topic, "command://qing chu cai ji xin xi")) {
// 删除声纹
//dds_client_vprint_unregist(dc, "test1");
}
else if (!strcmp(topic, "vprint.regist.result")) {
// 收到了声纹注册的消息
cJSON *root = cJSON_Parse(topic_data);
cJSON *operation = cJSON_GetObjectItem(root, "operation");
if (!strcmp(operation->valuestring, "start")) {
printf("====================== 开始注册声纹\n");
dds_client_speak(dc, "请说唤醒词,开始注册声纹");
}
if (!strcmp(operation->valuestring, "nameRepeat")) {
printf("====================== 注册姓名重复\n");
dds_client_speak(dc, "注册姓名重复");
}
else if (!strcmp(operation->valuestring, "vNumLimit")) {
printf("============= 注册数量已满\n");
dds_client_speak(dc, "注册数量已满");
}
else if (!strcmp(operation->valuestring, "unavailable")) {
printf("============= 信噪比不符合要求\n");
dds_client_speak(dc, "信噪比不符合要求");
}
else if (!strcmp(operation->valuestring, "continue")) {
printf("============= 请继续注册声纹\n");
dds_client_speak(dc, "请继续注册声纹");
}
else if (!strcmp(operation->valuestring, "success")) {
printf("============ 声纹注册成功\n");
dds_client_speak(dc, "声纹注册成功");
}
cJSON_Delete(root);
}
else if (!strcmp(topic, "vprint.unregist.result")) {
// 收到了声纹删除的消息
cJSON *root = cJSON_Parse(topic_data);
cJSON *operation = cJSON_GetObjectItem(root, "operation");
if (!strcmp(operation->valuestring, "success")) {
printf("==================== 声纹删除成功");
//dds_client_speak(dc, "声纹删除成功");
}
else if (!strcmp(operation->valuestring, "noSpeaker")) {
printf("==================== 该用户尚未注册");
//dds_client_speak(dc, "该用户尚未注册");
}
cJSON_Delete(root);
}
else if (!strcmp(topic, "vprint.test.result")) {
// 收到了声纹计算的结果,有以下三种情况:
/*
* 1. {"register":"nothing"} // 目前还没有声纹模型
*
*
* // 收到了匹配的声纹计算结果
* 2. {"score":23.286682,"word":"qi ke kong tiao","register":"test0","time":179.679932,"speech":0.880000,"RTF":0.204188}
*
*
* // 收到了不匹配的声纹计算结果
*
* 3. {"score":23.286682,"word":"qi ke kong tiao","register":"others","time":179.679932,"speech":0.880000,"RTF":0.204188}
*
*/
printf("vprint test receive result is %s\n", topic_data);
cJSON *root = cJSON_Parse(topic_data);
cJSON *reg = cJSON_GetObjectItem(root, "register");
if (!strcmp("nothing", reg->valuestring)) {
play_manager_f("status.set", "pause", NULL);
char *hint = "{\"nlg\":\"path:../res/tts/help.mp3\"}";
dds_client_publish(dc, DDS_CLIENT_USER_EXTERNAL_WAKEUP, hint);
}
else {
play_manager_f("status.set", "pause", NULL);
char hint[256] = {0};
snprintf(hint, 256, "{\"nlg\":\"path:../res/tts/help.mp3\"}", reg->valuestring);
dds_client_publish(dc, DDS_CLIENT_USER_EXTERNAL_WAKEUP, hint);
}
cJSON_Delete(root);
}
else 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;
cJSON_Delete(root);
}
else if (!strcmp(topic, "doa.result")) {
// doa 结果
}
else if (!strcmp(topic, "command://sys.tts.setspeaker")) {
static char speakers[6][20] = {
{"zhilingf"},
{"gdgm"},
{"geyou"},
{"hyanif"},
{"xijunm"},
{"qianranf"}
};
srand(time(0));
int choose = rand() % 6;
dds_client_set_speaker(dc, speakers[choose]);
//dds_client_speak(dc, "已经为您切换");
}
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);
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);
}
else if (!strcmp(topic, "sys.tts.begin")) {
}
else if (!strcmp(topic, "sys.tts.end")) {
}
else if (!strcmp(topic, "sys.vad.end")) {
}
else if (!strcmp(topic, "sys.asr.begin")) {
}
}
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 dds client
dc = dds_client_init(config);
assert(dc != NULL);
ret = dds_client_start(dc, dds_cb, NULL);
assert(ret != -1);
select(0, 0, 0, 0, 0);
dds_client_release(dc);
return 0;
}

Binary file not shown.

View File

@ -0,0 +1,348 @@
/*================================================================
* 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.8;
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);
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;
}
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, pause, playing
};
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_multiplier += 0.05;
if (vol_multiplier > 1.0) vol_multiplier = 0.99;
audio_player_set_channel_volume(aplayer, vol_multiplier);
printf("set vol_multiplier to %f\n", vol_multiplier);
printf("set vol to %d\n", (int)(vol_multiplier * 100.0));
}
else if (!strcmp(data, "-")) {
vol_multiplier -= 0.05;
if (vol_multiplier < 0.01) vol_multiplier = 0.01;
audio_player_set_channel_volume(aplayer, vol_multiplier);
printf("set vol_multiplier to %f\n", vol_multiplier);
printf("set vol to %d\n", (int)(vol_multiplier * 100.0));
}
else {
int vol = atoi(data);
vol_multiplier = vol / 100.0;
audio_player_set_channel_volume(aplayer, vol_multiplier);
printf("set vol_multiplier to %f\n", vol_multiplier);
printf("set vol to %d\n", (int)(vol_multiplier * 100.0));
}
}
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;
}
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);
}
}
}
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 = idle;
}
else if (!strcmp(data, "step")) {
if (status == playing) {
status = pause;
audio_player_pause(aplayer);
}
else if (status == pause) {
status = playing;
audio_player_resume(aplayer);
}
}
}
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;
}
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")) {
// 播放特定歌曲
// TODO: update
int find = 0;
int i = 0;
cJSON *temp = cJSON_Parse(data);
temp = cJSON_GetObjectItem(temp, "linkUrl");
cJSON *music = cJSON_GetObjectItem(root, "content");
cJSON *xx;
for (i = 0; i < count; i++) {
xx = cJSON_GetArrayItem(music, i);
xx = cJSON_GetObjectItem(xx, "linkUrl");
if (!strcmp(xx->valuestring, temp->valuestring)) {
find = 1;
break;
}
}
if (find) {
old_index = index;
index = i;
printf("ready to play url is %s\n", temp->valuestring);
audio_player_stop(aplayer);
audio_player_play(aplayer, temp->valuestring);
}
else {
// 播放歌曲不在播放列表里面
printf("wwwwwwwwwwwwwwwwwwwwwwwwwww\n");
}
}
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;
}
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);
}
}
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;
}

Binary file not shown.

View File

@ -0,0 +1,875 @@
## 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);
```
```
声纹的相关接口
// 获取当前的声纹详细信息
char *dds_client_vprint_get_detail(struct dds_client *ds);
返回的是一个 json 格式字符串,格式为:
{
"vNum": 2,
"detail": [
{
"name":"test1"
},
{
"name":"test2"
}
]
}
// 开始进入声纹注册的接口
int dds_client_vprint_regist(struct dds_client *ds, char *name);
name 参数表示声纹注册人的姓名标识。
出错返回-1通常是格式错误。而声纹注册过程中的详细错误将会通过回调抛出。
// 删除注册人信息
int dds_client_vprint_unregist(struct dds_client *ds, char *name);
出错返回-1通常是格式错误。而声纹删除过程中的详细错误将会通过回调抛出。
```
```
能量接口
int dds_client_energy_estimate(struct dds_client* ds, int second);
second 参数表示接下来所要计算的音频时间长度,单位为秒。计算结果通过回调给出。
出错返回 -1
```
```
客户端信息上传的相关接口
int dds_client_upload_city(struct dds_client *dc, char *city);
city 为当前设备所在的城市名,比如苏州,上海等
出错返回 -1
```
**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>
<tr>
<td> ddsLintener </td>
<td> vprint.regist.result </td>
<td> 声纹注册的消息回调 </td>
<td> json string 形如, {"operation":"start"} 表示声纹注册接口调用成成功,开始注册声纹。 {"operation":"nameRepeat"} 表示注册人姓名重复, {"operation":"vNumLimit"} 表示超出声纹注册上限, {"operation":"unavailable"} 表示所注册音频信噪比不够, {"operation":"continue"} 表示可以继续注册声纹,{"operation":"success"}表示声纹注册成功</td>
</tr>
<tr>
<td> ddsLintener </td>
<td> vprint.unregist.result </td>
<td> 声纹删除的消息回调 </td>
<td> json string 形如 {"operation":"success"} 表示删除成功, {"operation":"noSpeaker"} 表示没有所有删除的注册人信息</td>
</tr>
<tr>
<td> ddsLintener </td>
<td> vprint.test.result </td>
<td> 声纹计算的消息回调 </td>
<td> json string 形如: {"register":"nothing"} 表示当前还没有声纹模型, {"score":23.286682,"word":"qi ke kong tiao","register":"test0","time":179.679932,"speech":0.880000,"RTF":0.204188} 表示收到了正常的计算结果,其中的 register 字段表示所计算的声纹标识。 如果 register 为 others表示没有匹配到具体的声纹</td>
</tr>
<tr>
<td> ddsLintener </td>
<td> energy.estimate.result </td>
<td> 能量计算的消息回调 </td>
<td> json string 形如, {"value":40} </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",
"zhilingf": {
"resBinPath":"",
"dictPath":""
},
"voice": "zhilingf",
"volume": 50,
"speed": 0.85
},
"oneShot": {
"enable": false
},
"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" | "local" 分别表示云端合成和本地合成</td>
<td>必选</td>
</tr>
<tr>
<td> tts.voice </td>
<td>string </td>
<td>合成音的音色,如果为本地合成, 仅支持 "zhilingf" </td>
<td>必选</td>
</tr>
<tr>
<td> tts.zhilingf </td>
<td> json 对象 </td>
<td>当 tts.type 为 "local"时,会根据 tts.voice 选择对应音色的合成资源路径。</td>
<td>可选</td>
</tr>
<tr>
<td> tts.zhilingf.resBinPath </td>
<td> string </td>
<td>本地合成 zhilingf 的资源路径</td>
<td>可选</td>
</tr>
<tr>
<td> tts.zhilingf.dictPath </td>
<td> string </td>
<td>本地合成 zhilingf 的词典路径</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> 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 消息。
```
**用户事件说明**
用户可以通过dds_client_publish(struct dds_client *ds, int ev, const char *data); 接口给sdk发送事件。
`DDS_CLIENT_USER_EXTERNAL_WAKEUP` 表示外部唤醒事件用户可以在收到声纹计算结果之后通过这个事件让sdk继续交互。
这个事件传入的数据格式为:
{
"nlg":"xxxx"
}
可以通过nlg字段传入所有播报的内容播放完成之后就可以做识别了。 如果传入NULL表示立刻开始识别。

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More