智能语音计算器(四)

最后说讯飞的语音引擎部分,这部分的实现逻辑可以参考官方给的demo,一步一步来就行。

#ifndef CALCULATORASR_H
#define CALCULATORASR_H

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include "qisr.h"
#include "msp_cmn.h"
#include "msp_errors.h"

#define    BUFFER_SIZE    4096
#define FRAME_LEN    640 
#define HINTS_SIZE  100
#define RET_SIZE 100

class CalculatorASR
{
    public:
        CalculatorASR();
        ~CalculatorASR();
        void myLogin();
        void run_iat(const char* audio_file, const char* session_begin_params);
        void myLogOut();
        char* getResult();
    private:
        char result[RET_SIZE];
};

#endif

根据代码的结构做一下小小的改动。

#include "CalculatorASR.h"

CalculatorASR::CalculatorASR()
{
    
}

CalculatorASR::~CalculatorASR()
{

}

void CalculatorASR::run_iat(const char* audio_file, const char* session_begin_params)
{
    const char*        session_id                    =    NULL;
    char            rec_result[BUFFER_SIZE]        =    {NULL};    
    char            hints[HINTS_SIZE]            =    {NULL}; //hints为结束本次会话的原因描述,由用户自定义
    unsigned int    total_len                    =    0; 
    int                aud_stat                    =    MSP_AUDIO_SAMPLE_CONTINUE ;        //音频状态
    int                ep_stat                        =    MSP_EP_LOOKING_FOR_SPEECH;        //端点检测
    int                rec_stat                    =    MSP_REC_STATUS_SUCCESS ;            //识别状态
    int                errcode                        =    MSP_SUCCESS ;

    FILE*            f_pcm                        =    NULL;
    char*            p_pcm                        =    NULL;
    long            pcm_count                    =    0;
    long            pcm_size                    =    0;
    long            read_size                    =    0;

    
    if (NULL == audio_file)
        goto iat_exit;

    f_pcm = fopen(audio_file, "rb");
    if (NULL == f_pcm) 
    {
        printf("\nopen [%s] failed! \n", audio_file);
        goto iat_exit;
    }
    
    fseek(f_pcm, 0, SEEK_END);
    pcm_size = ftell(f_pcm); //获取音频文件大小 
    fseek(f_pcm, 0, SEEK_SET);        

    p_pcm = (char *)malloc(pcm_size);
    if (NULL == p_pcm)
    {
        printf("\nout of memory! \n");
        goto iat_exit;
    }

    read_size = fread((void *)p_pcm, 1, pcm_size, f_pcm); //读取音频文件内容
    if (read_size != pcm_size)
    {
        printf("\nread [%s] error!\n", audio_file);
        goto iat_exit;
    }
    
    //printf("\n开始语音听写 ...\n");
    session_id = QISRSessionBegin(NULL, session_begin_params, &errcode); //听写不需要语法,第一个参数为NULL
    if (MSP_SUCCESS != errcode)
    {
        printf("\nQISRSessionBegin failed! error code:%d\n", errcode);
        goto iat_exit;
    }
    
    while (1) 
    {
        unsigned int len = 10 * FRAME_LEN; // 每次写入200ms音频(16k,16bit):1帧音频20ms,10帧=200ms。16k采样率的16位音频,一帧的大小为640Byte
        int ret = 0;

        if (pcm_size < 2 * len) 
            len = pcm_size;
        if (len <= 0)
            break;

        aud_stat = MSP_AUDIO_SAMPLE_CONTINUE;
        if (0 == pcm_count)
            aud_stat = MSP_AUDIO_SAMPLE_FIRST;

        ret = QISRAudioWrite(session_id, (const void *)&p_pcm[pcm_count], len, aud_stat, &ep_stat, &rec_stat);
        if (MSP_SUCCESS != ret)
        {
            printf("\nQISRAudioWrite failed! error code:%d\n", ret);
            goto iat_exit;
        }
            
        pcm_count += (long)len;
        pcm_size  -= (long)len;
        
        if (MSP_REC_STATUS_SUCCESS == rec_stat) //已经有部分听写结果
        {
            const char *rslt = QISRGetResult(session_id, &rec_stat, 0, &errcode);
            if (MSP_SUCCESS != errcode)
            {
                printf("\nQISRGetResult failed! error code: %d\n", errcode);
                goto iat_exit;
            }
            if (NULL != rslt)
            {
                unsigned int rslt_len = strlen(rslt);
                total_len += rslt_len;
                if (total_len >= BUFFER_SIZE)
                {
                    printf("\nno enough buffer for rec_result !\n");
                    goto iat_exit;
                }
                strncat(rec_result, rslt, rslt_len);
            }
        }

        if (MSP_EP_AFTER_SPEECH == ep_stat)
            break;
        //usleep(200*1000); //模拟人说话时间间隙。200ms对应10帧的音频
    }
    errcode = QISRAudioWrite(session_id, NULL, 0, MSP_AUDIO_SAMPLE_LAST, &ep_stat, &rec_stat);
    if (MSP_SUCCESS != errcode)
    {
        printf("\nQISRAudioWrite failed! error code:%d \n", errcode);
        goto iat_exit;    
    }

    while (MSP_REC_STATUS_COMPLETE != rec_stat) 
    {
        const char *rslt = QISRGetResult(session_id, &rec_stat, 0, &errcode);
        if (MSP_SUCCESS != errcode)
        {
            printf("\nQISRGetResult failed, error code: %d\n", errcode);
            goto iat_exit;
        }
        if (NULL != rslt)
        {
            unsigned int rslt_len = strlen(rslt);
            total_len += rslt_len;
            if (total_len >= BUFFER_SIZE)
            {
                printf("\nno enough buffer for rec_result !\n");
                goto iat_exit;
            }
            strncat(rec_result, rslt, rslt_len);
        }
        usleep(150*1000); //防止频繁占用CPU
    }
    memset(result,0,sizeof(result));
    strcpy(result,rec_result);

iat_exit:
    if (NULL != f_pcm)
    {
        fclose(f_pcm);
        f_pcm = NULL;
    }
    if (NULL != p_pcm)
    {    free(p_pcm);
        p_pcm = NULL;
    }

    QISRSessionEnd(session_id, hints);
}

void CalculatorASR::myLogin()
{
    int            ret                        =    MSP_SUCCESS;
    const char* login_params            =    "appid = 5bc94820, work_dir = ."; // 登录参数,appid与msc库绑定,请勿随意改动

    const char* session_begin_params    =    "sub = iat, domain = iat, language = zh_cn, accent = mandarin, sample_rate = 16000, result_type = plain, result_encoding = utf8";

    /* 用户登录 */
    ret = MSPLogin(NULL, NULL, login_params); //第一个参数是用户名,第二个参数是密码,均传NULL即可,第三个参数是登录参数    
    if (MSP_SUCCESS != ret)
    {
        printf("MSPLogin failed , Error code %d.\n",ret);
        //goto exit; //登录失败,退出登录
    }
}
 
void CalculatorASR::myLogOut()
{
    MSPLogout();
}

char *CalculatorASR::getResult()
{
    return result;
}

讯飞的下载地址:https://doc.xfyun.cn/msc_linux/  

我是在linux系统下实现的,也提供其他系统的SDK,根据自己需求选择下载类型。

在此再次感谢科大讯飞。

猜你喜欢

转载自www.cnblogs.com/wzqstudy/p/10076875.html