您的位置:首页 > 移动开发 > Android开发

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基本上没什么问题,很容易就成功了。

基本代码如下:

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: