API二次开发接口

介绍

API二次开发接口,通过内存中的语音流直接识别,适用于在自己的软交换系统嵌入空号识别,或者语音板卡等类型的呼叫中心嵌入空号识别模块。

头文件

/*
* Copyright (C) 2017, <cdevelop@qq.com>
*
* da2.h -- da2.0 二次开发接口
*
*/


#ifndef DA2_H_
#define DA2_H_

#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 //DA2_H_

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;
}