最後說訊飛的語音引擎部分,這部分的實現邏輯能夠參考官方給的demo,一步一步來就行。linux
#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
根據代碼的結構作一下小小的改動。session
#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/ app
我是在linux系統下實現的,也提供其餘系統的SDK,根據本身需求選擇下載類型。dom
在此再次感謝科大訊飛。spa