android 语音识别 语音手电(一)
2015-11-14 16:29
489 查看
一,语音识别库 cmu-pocketsphinx
当然要用现成的语音识别库了,自己的水平离开发语音识别库还远的很呢。网上搜索找到卡内基梅龙大学的开源语音项目,好象是李开复创办的项目。有JAVA实现,有C语言实现,pocketsphinx是专为嵌入式开发的轻便型C语言实现版本。而且已经有Android版本,所以语音识别库就选它了。
要做语音识别需要几样东西:
1. 程序代码。
2. 声学模型文件。应该是声音与音素的对应关系。为一个文件夹。
3. 词典文件。音素与字词的对应关系。是一个文件 。
4. 语言模型。词与句子的对应关系。一个文件 。我只是想用来做简单命令词的识别,应该没用,不过好象不加载语言模型文件不能运行。
程序用官网上的pocketsphine_continuous.exe,声学模型文件与用官网的中文声学模型,词典和语言模型先用网上搜的某博客下载的一个很小词汇量的,在命令行指定声学模型字典和语言模型后可以运行了,但识别出来的是乱码,说不同的话显示不同的乱码,相同的话显示相同的乱码,猜想可能是编码不对,把字典和语言模型文件都改成GB2312的,就可以正确识别与显示了.
自己的词典和语言模型用在线生成方法生成,但是中文的词典不能生成,要手工从官网的某个中文词典中复制音素,还要注意词典和语言模型文件 的编码,在windows 下都用GB2312可以显示中文,估计Andriod下要转成UTF8。在windows下测试成功,识别率感觉还不错。
现在只是依葫芦画漂,还没有深入学习。比如上面的文件中,对于小词汇量,文件都很小,但声学模型比较大,不知道有什么方法减小没有,也不知道自己训练声学模型会不会小点,再说训练好象比较麻烦,自己不定能精力有能力训练声学模型。再有就是以上数据是以文件形式加载的,Android APK中打包文件在NDK中使用好象也不是太方便,将来不知道能不能直接人内存加载,这样就少方便些了。
语音识别模块开发,先在PC环境把语音模块的代码完成,调试好,再到NDK环境下编译,在NDK用要用的模块文件中除了pocketsphinx库关相的别的东西都不使用,减少依赖。本模块直接用pocketsphinx的语音识别程序pocketsphine_continuous.exe的源码continuous.c修改,这个程序在命令行指定声学模型、字典和语言模型后就可以进行语音识别。
我们把涉及到语音识别的代码提取出来到一个单独文件speech.c中,做成三个函数,
一个初始化函数speech_init(const char * model_path);
一个反初始化函数speech_uninit();
一个不停提供音频数据的函数speech_feed(short * data,int len);
语音识别就在speech_feed这个函数中完成,将来这个函数再去回调JAVA,把识别出来的语音反回到JAVA代码。基本就是代码复制,没什么技术含量。音频读取代码还在原来的文件中。这样就实现了和原来pocketsphine_continuous.exe功能一样的程序。整个程序开发在VS Express 2013 for Desktop中完成,用自己改写的代码测试,可以正确识别,和原来的官网程序一模一样.
然后到NDK是编译speech.c基本上没什么问题,很容易就成功了。
基本代码如下:
当然要用现成的语音识别库了,自己的水平离开发语音识别库还远的很呢。网上搜索找到卡内基梅龙大学的开源语音项目,好象是李开复创办的项目。有JAVA实现,有C语言实现,pocketsphinx是专为嵌入式开发的轻便型C语言实现版本。而且已经有Android版本,所以语音识别库就选它了。
要做语音识别需要几样东西:
1. 程序代码。
2. 声学模型文件。应该是声音与音素的对应关系。为一个文件夹。
3. 词典文件。音素与字词的对应关系。是一个文件 。
4. 语言模型。词与句子的对应关系。一个文件 。我只是想用来做简单命令词的识别,应该没用,不过好象不加载语言模型文件不能运行。
程序用官网上的pocketsphine_continuous.exe,声学模型文件与用官网的中文声学模型,词典和语言模型先用网上搜的某博客下载的一个很小词汇量的,在命令行指定声学模型字典和语言模型后可以运行了,但识别出来的是乱码,说不同的话显示不同的乱码,相同的话显示相同的乱码,猜想可能是编码不对,把字典和语言模型文件都改成GB2312的,就可以正确识别与显示了.
自己的词典和语言模型用在线生成方法生成,但是中文的词典不能生成,要手工从官网的某个中文词典中复制音素,还要注意词典和语言模型文件 的编码,在windows 下都用GB2312可以显示中文,估计Andriod下要转成UTF8。在windows下测试成功,识别率感觉还不错。
现在只是依葫芦画漂,还没有深入学习。比如上面的文件中,对于小词汇量,文件都很小,但声学模型比较大,不知道有什么方法减小没有,也不知道自己训练声学模型会不会小点,再说训练好象比较麻烦,自己不定能精力有能力训练声学模型。再有就是以上数据是以文件形式加载的,Android APK中打包文件在NDK中使用好象也不是太方便,将来不知道能不能直接人内存加载,这样就少方便些了。
语音识别模块开发,先在PC环境把语音模块的代码完成,调试好,再到NDK环境下编译,在NDK用要用的模块文件中除了pocketsphinx库关相的别的东西都不使用,减少依赖。本模块直接用pocketsphinx的语音识别程序pocketsphine_continuous.exe的源码continuous.c修改,这个程序在命令行指定声学模型、字典和语言模型后就可以进行语音识别。
我们把涉及到语音识别的代码提取出来到一个单独文件speech.c中,做成三个函数,
一个初始化函数speech_init(const char * model_path);
一个反初始化函数speech_uninit();
一个不停提供音频数据的函数speech_feed(short * data,int len);
语音识别就在speech_feed这个函数中完成,将来这个函数再去回调JAVA,把识别出来的语音反回到JAVA代码。基本就是代码复制,没什么技术含量。音频读取代码还在原来的文件中。这样就实现了和原来pocketsphine_continuous.exe功能一样的程序。整个程序开发在VS Express 2013 for Desktop中完成,用自己改写的代码测试,可以正确识别,和原来的官网程序一模一样.
然后到NDK是编译speech.c基本上没什么问题,很容易就成功了。
基本代码如下:
static ps_decoder_t *ps; static cmd_ln_t *config; static inited = 0; int speech_init(const char * data_path) { char hmm[256] = ""; char lm[256] = ""; char dict[256] = ""; strcat(hmm, data_path); strcat(hmm, "/tdt_sc_8k"); strcat(lm, data_path); strcat(lm, "/light.lm"); strcat(dict, data_path); strcat(dict, "/light.dic"); config = cmd_ln_init(NULL, ps_args(), TRUE,"-hmm", hmm,"-lm",lm,"-dict", dict,NULL); LOGI("speech_init hmm--->%s", (const char *)hmm); LOGI("speech_init lm--->%s", (const char *)lm); LOGI("speech_init dict--->%s", (const char *)dict); ps_default_search_args(config); ps = ps_init(config); if (ps == NULL) { cmd_ln_free_r(config); return -1; } if (ps_start_utt(ps) < 0) { printf("Failed to start utterance\n"); return -1; } inited = 1; return 0; } int speech_uninit() { if (ps!=NULL) ps_free(ps); cmd_ln_free_r(config); return 0; } int speech_feed(const short * buf, int len) { static char utt_started = FALSE; char in_speech = 0; char const *hyp; if (inited != 1) return -1; ps_process_raw(ps, buf, len, FALSE, FALSE); in_speech = ps_get_in_speech(ps); if (in_speech && !utt_started) { utt_started = TRUE; //printf("Listening...\n"); } if (!in_speech && utt_started) { /* speech -> silence transition, time to start new utterance */ ps_end_utt(ps); hyp = ps_get_hyp(ps, NULL); if (hyp != NULL) { //LOGI("speech:%s", (const char *)hyp); CallBack_Java(hyp); //printf("%s\n", hyp); } ps_start_utt(ps); utt_started = FALSE; //printf("READY....\n"); } return 0; }
相关文章推荐
- Android基础入门教程——10.11 传感器专题(2)——方向传感器
- Android UsageStatsService源码
- IDEA引入第三方开源库的几点注意事项
- Android代码强制区分规范
- Android view的工作原理(Android开发艺术探索随笔)
- Android Studio 导入jar ,so 及 开源库
- 关于Android中ImageView中tint属性的一点点整理
- android:descendantFocusability用法简析
- Android-自定义多TAB悬浮控件实现蘑菇街首页效果
- Android性能分析工具-TraceView
- 推荐大家一个不错android模拟器工具Genymotion
- android studio 添加快捷按钮.
- Android学习:TextUtils类介绍
- 关于android中数据持久化存储的方法的知识整理
- 一个android的各种控件库
- Android实现TextView字符串波浪式跳动
- 安卓学习笔记一 —— Activity的一些使用技巧
- Android的Message机制(简单小结)
- 环境配置正确的前提下,Run as 不出现Android Application的问题
- android 数据存储二使用文件存储数据