asr_offline_sample.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <errno.h>
  5. #include <unistd.h>
  6. #include "../../include/qisr.h"
  7. #include "../../include/msp_cmn.h"
  8. #include "../../include/msp_errors.h"
  9. #define SAMPLE_RATE_16K (16000)
  10. #define SAMPLE_RATE_8K (8000)
  11. #define MAX_GRAMMARID_LEN (32)
  12. #define MAX_PARAMS_LEN (1024)
  13. const char * ASR_RES_PATH = "fo|res/asr/common.jet"; //离线语法识别资源路径
  14. const char * GRM_BUILD_PATH = "res/asr/GrmBuilld"; //构建离线语法识别网络生成数据保存路径
  15. const char * GRM_FILE = "call.bnf"; //构建离线识别语法网络所用的语法文件
  16. const char * LEX_NAME = "contact"; //更新离线识别语法的contact槽(语法文件为此示例中使用的call.bnf)
  17. typedef struct _UserData {
  18. int build_fini; //标识语法构建是否完成
  19. int update_fini; //标识更新词典是否完成
  20. int errcode; //记录语法构建或更新词典回调错误码
  21. char grammar_id[MAX_GRAMMARID_LEN]; //保存语法构建返回的语法ID
  22. }UserData;
  23. const char *get_audio_file(void); //选择进行离线语法识别的语音文件
  24. int build_grammar(UserData *udata); //构建离线识别语法网络
  25. int update_lexicon(UserData *udata); //更新离线识别语法词典
  26. int run_asr(UserData *udata); //进行离线语法识别
  27. const char* get_audio_file(void)
  28. {
  29. char key = 0;
  30. while(key != 27) //按Esc则退出
  31. {
  32. printf("请选择音频文件:\n");
  33. printf("1.打电话给丁伟\n");
  34. printf("2.打电话给黄辣椒\n");
  35. key = getchar();
  36. getchar();
  37. switch(key)
  38. {
  39. case '1':
  40. printf("\n1.打电话给丁伟\n");
  41. return "wav/ddhgdw.pcm";
  42. case '2':
  43. printf("\n2.打电话给黄辣椒\n");
  44. return "wav/ddhghlj.pcm";
  45. default:
  46. continue;
  47. }
  48. }
  49. exit(0);
  50. return NULL;
  51. }
  52. int build_grm_cb(int ecode, const char *info, void *udata)
  53. {
  54. UserData *grm_data = (UserData *)udata;
  55. if (NULL != grm_data) {
  56. grm_data->build_fini = 1;
  57. grm_data->errcode = ecode;
  58. }
  59. if (MSP_SUCCESS == ecode && NULL != info) {
  60. printf("构建语法成功! 语法ID:%s\n", info);
  61. if (NULL != grm_data)
  62. snprintf(grm_data->grammar_id, MAX_GRAMMARID_LEN - 1, info);
  63. }
  64. else
  65. printf("构建语法失败!%d\n", ecode);
  66. return 0;
  67. }
  68. int build_grammar(UserData *udata)
  69. {
  70. FILE *grm_file = NULL;
  71. char *grm_content = NULL;
  72. unsigned int grm_cnt_len = 0;
  73. char grm_build_params[MAX_PARAMS_LEN] = {NULL};
  74. int ret = 0;
  75. grm_file = fopen(GRM_FILE, "rb");
  76. if(NULL == grm_file) {
  77. printf("打开\"%s\"文件失败![%s]\n", GRM_FILE, strerror(errno));
  78. return -1;
  79. }
  80. fseek(grm_file, 0, SEEK_END);
  81. grm_cnt_len = ftell(grm_file);
  82. fseek(grm_file, 0, SEEK_SET);
  83. grm_content = (char *)malloc(grm_cnt_len + 1);
  84. if (NULL == grm_content)
  85. {
  86. printf("内存分配失败!\n");
  87. fclose(grm_file);
  88. grm_file = NULL;
  89. return -1;
  90. }
  91. fread((void*)grm_content, 1, grm_cnt_len, grm_file);
  92. grm_content[grm_cnt_len] = '\0';
  93. fclose(grm_file);
  94. grm_file = NULL;
  95. snprintf(grm_build_params, MAX_PARAMS_LEN - 1,
  96. "engine_type = local, \
  97. asr_res_path = %s, sample_rate = %d, \
  98. grm_build_path = %s, ",
  99. ASR_RES_PATH,
  100. SAMPLE_RATE_16K,
  101. GRM_BUILD_PATH
  102. );
  103. ret = QISRBuildGrammar("bnf", grm_content, grm_cnt_len, grm_build_params, build_grm_cb, udata);
  104. free(grm_content);
  105. grm_content = NULL;
  106. return ret;
  107. }
  108. int update_lex_cb(int ecode, const char *info, void *udata)
  109. {
  110. UserData *lex_data = (UserData *)udata;
  111. if (NULL != lex_data) {
  112. lex_data->update_fini = 1;
  113. lex_data->errcode = ecode;
  114. }
  115. if (MSP_SUCCESS == ecode)
  116. printf("更新词典成功!\n");
  117. else
  118. printf("更新词典失败!%d\n", ecode);
  119. return 0;
  120. }
  121. int update_lexicon(UserData *udata)
  122. {
  123. const char *lex_content = "丁伟\n黄辣椒";
  124. unsigned int lex_cnt_len = strlen(lex_content);
  125. char update_lex_params[MAX_PARAMS_LEN] = {NULL};
  126. snprintf(update_lex_params, MAX_PARAMS_LEN - 1,
  127. "engine_type = local, text_encoding = UTF-8, \
  128. asr_res_path = %s, sample_rate = %d, \
  129. grm_build_path = %s, grammar_list = %s, ",
  130. ASR_RES_PATH,
  131. SAMPLE_RATE_16K,
  132. GRM_BUILD_PATH,
  133. udata->grammar_id);
  134. return QISRUpdateLexicon(LEX_NAME, lex_content, lex_cnt_len, update_lex_params, update_lex_cb, udata);
  135. }
  136. int run_asr(UserData *udata)
  137. {
  138. char asr_params[MAX_PARAMS_LEN] = {NULL};
  139. const char *rec_rslt = NULL;
  140. const char *session_id = NULL;
  141. const char *asr_audiof = NULL;
  142. FILE *f_pcm = NULL;
  143. char *pcm_data = NULL;
  144. long pcm_count = 0;
  145. long pcm_size = 0;
  146. int last_audio = 0;
  147. int aud_stat = MSP_AUDIO_SAMPLE_CONTINUE;
  148. int ep_status = MSP_EP_LOOKING_FOR_SPEECH;
  149. int rec_status = MSP_REC_STATUS_INCOMPLETE;
  150. int rss_status = MSP_REC_STATUS_INCOMPLETE;
  151. int errcode = -1;
  152. asr_audiof = get_audio_file();
  153. f_pcm = fopen(asr_audiof, "rb");
  154. if (NULL == f_pcm) {
  155. printf("打开\"%s\"失败![%s]\n", f_pcm, strerror(errno));
  156. goto run_error;
  157. }
  158. fseek(f_pcm, 0, SEEK_END);
  159. pcm_size = ftell(f_pcm);
  160. fseek(f_pcm, 0, SEEK_SET);
  161. pcm_data = (char *)malloc(pcm_size);
  162. if (NULL == pcm_data)
  163. goto run_error;
  164. fread((void *)pcm_data, pcm_size, 1, f_pcm);
  165. fclose(f_pcm);
  166. f_pcm = NULL;
  167. //离线语法识别参数设置
  168. snprintf(asr_params, MAX_PARAMS_LEN - 1,
  169. "engine_type = local, \
  170. asr_res_path = %s, sample_rate = %d, \
  171. grm_build_path = %s, local_grammar = %s, \
  172. result_type = xml, result_encoding = UTF-8, ",
  173. ASR_RES_PATH,
  174. SAMPLE_RATE_16K,
  175. GRM_BUILD_PATH,
  176. udata->grammar_id
  177. );
  178. session_id = QISRSessionBegin(NULL, asr_params, &errcode);
  179. if (NULL == session_id)
  180. goto run_error;
  181. printf("开始识别...\n");
  182. while (1) {
  183. unsigned int len = 6400;
  184. if (pcm_size < 12800) {
  185. len = pcm_size;
  186. last_audio = 1;
  187. }
  188. aud_stat = MSP_AUDIO_SAMPLE_CONTINUE;
  189. if (0 == pcm_count)
  190. aud_stat = MSP_AUDIO_SAMPLE_FIRST;
  191. if (len <= 0)
  192. break;
  193. printf(">");
  194. fflush(stdout);
  195. errcode = QISRAudioWrite(session_id, (const void *)&pcm_data[pcm_count], len, aud_stat, &ep_status, &rec_status);
  196. if (MSP_SUCCESS != errcode)
  197. goto run_error;
  198. pcm_count += (long)len;
  199. pcm_size -= (long)len;
  200. //检测到音频结束
  201. if (MSP_EP_AFTER_SPEECH == ep_status)
  202. break;
  203. usleep(150 * 1000); //模拟人说话时间间隙
  204. }
  205. //主动点击音频结束
  206. QISRAudioWrite(session_id, (const void *)NULL, 0, MSP_AUDIO_SAMPLE_LAST, &ep_status, &rec_status);
  207. free(pcm_data);
  208. pcm_data = NULL;
  209. //获取识别结果
  210. while (MSP_REC_STATUS_COMPLETE != rss_status && MSP_SUCCESS == errcode) {
  211. rec_rslt = QISRGetResult(session_id, &rss_status, 0, &errcode);
  212. usleep(150 * 1000);
  213. }
  214. printf("\n识别结束:\n");
  215. printf("=============================================================\n");
  216. if (NULL != rec_rslt)
  217. printf("%s\n", rec_rslt);
  218. else
  219. printf("没有识别结果!\n");
  220. printf("=============================================================\n");
  221. goto run_exit;
  222. run_error:
  223. if (NULL != pcm_data) {
  224. free(pcm_data);
  225. pcm_data = NULL;
  226. }
  227. if (NULL != f_pcm) {
  228. fclose(f_pcm);
  229. f_pcm = NULL;
  230. }
  231. run_exit:
  232. QISRSessionEnd(session_id, NULL);
  233. return errcode;
  234. }
  235. int main(int argc, char* argv[])
  236. {
  237. const char *login_config = "appid = 5d5b9efd"; //登录参数
  238. UserData asr_data;
  239. int ret = 0 ;
  240. char c;
  241. ret = MSPLogin(NULL, NULL, login_config); //第一个参数为用户名,第二个参数为密码,传NULL即可,第三个参数是登录参数
  242. if (MSP_SUCCESS != ret) {
  243. printf("登录失败:%d\n", ret);
  244. goto exit;
  245. }
  246. memset(&asr_data, 0, sizeof(UserData));
  247. printf("构建离线识别语法网络...\n");
  248. ret = build_grammar(&asr_data); //第一次使用某语法进行识别,需要先构建语法网络,获取语法ID,之后使用此语法进行识别,无需再次构建
  249. if (MSP_SUCCESS != ret) {
  250. printf("构建语法调用失败!\n");
  251. goto exit;
  252. }
  253. while (1 != asr_data.build_fini)
  254. usleep(300 * 1000);
  255. if (MSP_SUCCESS != asr_data.errcode)
  256. goto exit;
  257. printf("离线识别语法网络构建完成,开始识别...\n");
  258. ret = run_asr(&asr_data);
  259. if (MSP_SUCCESS != ret) {
  260. printf("离线语法识别出错: %d \n", ret);
  261. goto exit;
  262. }
  263. printf("更新离线语法词典...\n");
  264. ret = update_lexicon(&asr_data); //当语法词典槽中的词条需要更新时,调用QISRUpdateLexicon接口完成更新
  265. if (MSP_SUCCESS != ret) {
  266. printf("更新词典调用失败!\n");
  267. goto exit;
  268. }
  269. while (1 != asr_data.update_fini)
  270. usleep(300 * 1000);
  271. if (MSP_SUCCESS != asr_data.errcode)
  272. goto exit;
  273. printf("更新离线语法词典完成,开始识别...\n");
  274. ret = run_asr(&asr_data);
  275. if (MSP_SUCCESS != ret) {
  276. printf("离线语法识别出错: %d \n", ret);
  277. goto exit;
  278. }
  279. exit:
  280. MSPLogout();
  281. printf("请按任意键退出...\n");
  282. getchar();
  283. return 0;
  284. }