介绍
API二次开发接口,通过内存中的语音流直接识别,适用于在自己的软交换系统嵌入空号识别,或者语音板卡等类型的呼叫中心嵌入空号识别模块。
头文件
/*
* Copyright (C) 2017, <cdevelop@qq.com>
*
* da2.h -- da2.0 二次开发接口
*
*/
#ifndef DA2H
#define DA2H
#include<stdio.h>
#ifndef _WIN32
#define DA2_API
#else
#ifdef DA2_EXPORTS
#define DA2_API __declspec(dllexport)
#else
#define DA2_API __declspec(dllimport)
#endif
#endif
#ifdef __cplusplus
extern “C” {
#endif
//返回 0:成功 ,-1:失败
DA2_API int Da2_Init(const char configurefilename,const char logfilename);
DA2_API void Da2_Term();
DA2_API void Da2_AllocHandler();
DA2_API void Da2_FreeHandler(void handler);
DA2_API void Da2_ResetHandler(void *handler);
//设置hhandler关联的用户数据,Da2_ResetHandler后需要重新设置。请在Da2_AllocHandler或者Da2_ResetHandler之后立刻设置。
//用户数据用于标记后台详单
//userdata 40字节以内字符
DA2_API void Da2_SetUserData(void *handler,const char *userdata);
DA2_API void Da2_SetKey(void *handler, const char *key);
//wavelen 是样本的采样数,也就是 byte/2
//返回值 0:还没有检测结果,1:已经有检测结果。 -1:错误
DA2_API int Da2_Detect(void *handler, const short *wavedata, int wavelen);
//数据已经提交完毕。reset之前不能在调用Da2_Detect。
DA2_API void Da2_Finish(void handler);
DA2_API void Da2_Status(int ready, int limit, int peak, int inuse, int incache);
//返回值 0:所有请求都已经返回。 1:还有请求没有返回。 -1:错误
DA2_API int Da2_WaitResult(void *handler,int waitms);
typedef enum {
DA_ACCURACY_NONE,
DA_ACCURACY_LOOSE,
DA_ACCURACY_INACCURACY,
DA_ACCURACY_ACCURACY
} DA_ACCURACY_T;
typedef struct {
int point;
struct {
char* uniqueid;
char* name;
char* alias;
char* brief;
char* detail;
char* language;
char* source;
char* number;
int category;
int recognize;
double discrepancy;
int accuracy;
} sample;
} DA_TONE_INFO_T;
typedef enum {
DA_TONE_NONE = 0,
DA_TONE_BUSYTONE = 0x01,
DA_TONE_RINGBACKTONE = 0x02,
DA_TONE_COOLRINGBACKTONE = 0x04,
DA_TONE_PROMPTTONE = 0x08,
DA_TONE_SAMPLE = 0x10
} DA_TONE_FLAG_T;
//取出检测结果
DA2_API DA_TONE_FLAG_T Da2_TakeResult(void handler, DA_TONE_INFO_T toneinfo);
DA2_API const char* Da2_PrintToneFlag(DA_TONE_FLAG_T flag);
DA2_API const char* Da2_PrintToneInfo(const DA_TONE_INFO_T *toneinfo, char *outbuf, int len);
//Da2_TakeResult获取的DA_TONE_INFO_T,需要调用这个函数来释放一次。
DA2_API void Da2_FreeToneInfo(DA_TONE_INFO_T *toneinfo);
//打开wave文件,并且跳过文件头,请使用fclose关闭文件。
//formatTag 编码方式
//channels 声道数目
//samplespersec 采样频率
//blockalign 数据块对齐单位(每个采样需要的字节数)
DA2_API FILE* Da2_OpenWaveFile(const char *filename,int *formattag,int *channels,int *samplespersec, int *blockalign);
DA2_API short* Da2_AlawtoPcm(char *alaw,short *pcm,int len);
DA2_API short* Da2_UlawtoPcm(char *ulaw, short *pcm, int len);
#ifdef __cplusplus
}
#endif
#endif //DA2H
demo
#include "da2.h"
#include "stdio.h"
#include <stdarg.h>
#include "malloc.h"
#include <time.h>
#include <string.h>
#ifdef MULTITHREADING
#include <thread>
#endif
#ifdef _WIN32
#include <windows.h>
#define cross_sleep(ms) Sleep(ms)
#define strcasecmp _stricmp
#else
#include <unistd.h>
#include <sys/types.h>
#include <time.h>
#define cross_sleep(msec) usleep(msec*1000)
#endif
//文件格式 wave 8000hz 16位
void test(const char filename)
{
FILE file = NULL;
int formattag = 1;
int filename_len = (int)strlen(filename);
if (filename_len < 4) {
return;
}
else if (!strcasecmp(filename + filename_len - 4, “.pcm”)) {
file = fopen(filename, “rb”);
}
else if (!strcasecmp(filename + filename_len - 4, “.wav”)) {
int channels, samplespersec, blockalign;
file = Da2_OpenWaveFile(filename, &formattag, &channels, &samplespersec, &blockalign);
if (file) {
if ((formattag != 1 && formattag != 6 && formattag != 7) || channels != 1 || samplespersec != 8000) {
fclose(file);
file = NULL;
}
}
}
if (file) {
void *da2_handler = Da2_AllocHandler();
if (!da2_handler) {
return;
}
Da2_SetUserData(da2_handler, filename);
char tracefilename[256];
snprintf(tracefilename,sizeof(tracefilename), "%s.raw", filename);
FILE *tracefile = fopen(tracefilename, "wb");
for (;;) {
short buf[160];
int l = 0;
if (formattag == 1) {
l = (int)fread(buf, sizeof(short), sizeof(buf) / sizeof(short), file);
}
else {
char data[160];
l = (int)fread(data, 1, sizeof(data) , file);
if (formattag == 6) {
Da2_AlawtoPcm(data, buf, l);
}
else if (formattag == 7) {
Da2_UlawtoPcm(data, buf, l);
}
else {
fclose(file);
break;
}
}
if (l > 0) {
if(tracefile)
fwrite(buf,l,2,tracefile);
Da2_Detect(da2_handler, buf, l);
#ifdef MULTITHREADING
cross_sleep(20);
#endif
}
else {
fclose(file);
break;
}
}
Da2_Finish(da2_handler);
time_t finish_time = time(0);
Da2_WaitResult(da2_handler, 10000);
for (;;) {
DA_TONE_INFO_T info;
DA_TONE_FLAG_T flag = Da2_TakeResult(da2_handler, &info);
if (flag == DA_TONE_NONE) {
printf("filename:%s detect finish\n",filename);
break;
}
else {
printf("filename:%s %d\n", filename,(int)(time(0)- finish_time));
printf(“tone:%s\npoint:%d\n”, Da2_PrintToneFlag(flag), info.point);
if (flag == DA_TONE_SAMPLE) {
printf(“uniqueid:%s\n”, info.sample.uniqueid ? info.sample.uniqueid : “”);
printf(“name:%s\n”, info.sample.name ? info.sample.name : “”);
printf(“alias:%s\n”, info.sample.alias ? info.sample.alias : “”);
printf(“brief:%s\n”, info.sample.brief ? info.sample.brief : “”);
printf(“detail:%s\n”, info.sample.detail ? info.sample.detail : “”);
printf(“language:%s\n”, info.sample.language ? info.sample.language : “”);
printf(“source:%s\n”, info.sample.source ? info.sample.source : “”);
printf(“number:%s\n”, info.sample.number ? info.sample.number : “”);
printf(“category:%d\n”, info.sample.category);
printf(“accuracy:%d\n”, info.sample.accuracy);
printf(“feature:%d\n”, info.sample.feature);
printf(“discrepancy:%f\n”, info.sample.discrepancy);
printf(“==========================\n”);
}
Da2_FreeToneInfo(&info);
}
}
Da2_FreeHandler(da2_handler);
if (tracefile)
fclose(tracefile);
}
}
int main()
{
Da2_Init(“da2.json”,”da2.log”);
//等待和daserver链接;
cross_sleep(3000);
#ifdef MULTITHREADING
std::thread t[100];
int c = 50;
for (int i = 0; i < c; ++i) {
t[i] = std::thread(test,"test.pcm");
cross_sleep(100);
}
for (int i = 0; i < c; ++i) {
t[i].join();
}
#else
test("test.pcm");
test("test.wav");
test("alaw.wav");
test("ulaw.wav");
#endif
Da2_Term();
printf("Press the return key to exit!");
getchar();
return 0;
}