pocketsphinx实现连续大词汇量语音识别

之前有个项目需求是要在客户内网实现一个连续大词汇语音识别功能,由于客户的内网是独立的,不能访问互联网,所以我只能到开源社区去找找碰碰运气了。后来在网上找到了cmusphinx(地址:http://cmusphinx.sourceforge.net/),项目是c#语言的,pocketsphinx这个语音识别引擎是cpp写的,Sphinx4这是java的版本,为了很好的集成到项目中去,我选择了pocketsphinx,因为它在移动端和PC端都能运行。本人C++语言很差,东拼西凑总算把调用识别引擎的方法写好了,编译成Dll以后,在C#里面用DllImport来调用。从github上下载项目源码后,写一个下面的类,代码如下:

#include <pocketsphinx.h>
#include <fstream>
#include <iostream>
#include <string>
#include <Windows.h>
#define EXPORT_DLL extern "C" __declspec(dllexport)//向c#开放此文件的cpp方法
using  namespace std; 

//#define MODELDIR "model"

//获取运行环境路径
EXPORT_DLL string GetProgramDir()
{
    char buf[1024];
    GetCurrentDirectory(1024,buf);
    string path(buf);
    return path;
} 

//保存识别结果
static void write_results(char *rec_result)
{
    ofstream fResult("D:/run_path.txt",ios::app);
    fResult<<rec_result;
    fResult.close();
}

//获取配置文件(1:英文识别,2:中文识别)
static cmd_ln_t* get_config(char *modelDir,int language_type)
{
    string configPath(modelDir);
    if(modelDir==NULL)
    {
        string configPath=GetProgramDir();
    }
    //write_results((char*)configPath.c_str());
    cmd_ln_t *config;
    string hmm,lm,dict;
    if(language_type==1)
    {
        hmm=configPath+"/model/en-us/en-us";
        lm=configPath+"/model/en-us/en-us.lm.dmp";
        dict=configPath+"/model/en-us/cmudict-en-us.dict";
        config = cmd_ln_init(NULL, ps_args(), TRUE,
            "-hmm", hmm.c_str(),
            "-lm", lm.c_str(),
            "-dict",dict.c_str(),
            NULL);
    }else
    {
        hmm=configPath+"/model/zh/zh";
        lm=configPath+"/model/zh/zh_broadcastnews_64000_utf8.dmp";
        dict=configPath+"/model/zh/zh_broadcastnews_utf8.dic";
        config = cmd_ln_init(NULL, ps_args(), TRUE,
            "-hmm", hmm.c_str(),
            "-lm", lm.c_str(),
            "-dict", dict.c_str(),
            NULL);
    }
    /*if (config == NULL)
    return config;*/
    return config;
}

//字符编码转换
char * UnicodeToANSI(const wchar_t* str)
{
    char* result;
    int textlen;
    textlen=WideCharToMultiByte(CP_ACP,0,str,-1,NULL,0,NULL,NULL);
    result=(char *)malloc((textlen+1)*sizeof(char));
    memset(result,0,sizeof(char)*(textlen+1));
    WideCharToMultiByte(CP_ACP,0,str,-1,result,textlen,NULL,NULL);
    return result;
}

wchar_t * UTF8ToNunicode(const char* str)
{
    int textlen;
    wchar_t * result;
    textlen=MultiByteToWideChar(CP_UTF8,0,str,-1,NULL,0);
    result=(wchar_t *)malloc((textlen+1)*sizeof(wchar_t));
    memset(result,0,(textlen+1)*sizeof(wchar_t));
    MultiByteToWideChar(CP_UTF8,0,str,-1,(LPWSTR)result,textlen);
    return result;
}

char* UTF8ToANSI(const char* str)
{
    return UnicodeToANSI(UTF8ToNunicode(str));
}

char strResult[1024];//保存语音识别返回结果
/*语言识别方法一
*languageType:(1:英文识别,2:中文识别,)
*file_name: (wav音频文件路径)
*/
EXPORT_DLL char* wavfile_speech_rec(int languageType,char *modelDir,char *file_name)
{
    ps_decoder_t *ps;
    int rv;
    int16 buf[512];
    int32 score;
    FILE *fh;
    char const *hyp, *uttid;
    cmd_ln_t *config=get_config(modelDir,languageType);
    if(config==NULL)
    {
        strcpy(strResult,"语音模型配置文件读取失败!");
        return strResult;
    }
    ps=ps_init(config);
    if (ps == NULL)
    {
        strcpy(strResult,"解码器初始化失败!");
        return strResult;
    }
    fh = fopen(file_name, "rb");
    if (fh == NULL)
    {
        strcpy(strResult,"不是有效的wav文件!");
        return strResult;
    }
    rv = ps_start_utt(ps);
    if (rv < 0)
    {
        strcpy(strResult,"解码失败!");
        return strResult;
    }
    while (!feof(fh)) {
        size_t nsamp;
        nsamp = fread(buf, 2, 512, fh);
        rv = ps_process_raw(ps, buf, nsamp, FALSE, FALSE);
    }
    rv = ps_end_utt(ps);
    if (rv < 0)
    {
        strcpy(strResult,"解码失败!");
        return strResult;
    }
    hyp = ps_get_hyp(ps, &score);
    if (hyp == NULL)
    {
        strcpy(strResult,"");
        return strResult;
    }else
    {
        strcpy(strResult,hyp);
    }
    fclose(fh);
    fh=NULL;
    ps_free(ps);
    cmd_ln_free_r(config);
    return UTF8ToANSI(strResult);
}

c#中调用的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace SpeechRec
{
    /// <summary>
    /// 语音识别工具类
    /// </summary>
    public class SpeechRecTool
    {
        public SpeechRecTool()
        {

        }
        [DllImport("pocketsphinx_speech_rec.dll", EntryPoint = "GetProgramDir", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr GetProgramDir();
        /// <summary>
        /// wav文件识别
        /// </summary> CharSet = CharSet.Ansi, EntryPoint = "wavfile_speech_rec")
        /// <returns></returns>
        [DllImport("pocketsphinx_speech_rec.dll", EntryPoint = "wavfile_speech_rec", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        private static extern IntPtr wavfile_speech_rec(int lang, string modelPath, string fileName);
        /// <summary>
        /// wav文件识别
        /// </summary>
        /// <param name="language"></param>
        /// <param name="fileName"></param>
        public string WavFileSpeechRec(LanguageType language, string fileName)
        {
            string strResult = "";
            if (System.IO.File.Exists(fileName))
            {
                WavTools wTool = new WavTools();
                if (!new WavTools().IsStandardWavFile(fileName))
                {
                    fileName = wTool.FormateWavFile(fileName);
                }
                IntPtr intPtrResult = wavfile_speech_rec((int)language, @"E:\SoftWare\语音识别\狮身人面像\pocketsphinx\bin\Release\Win32", fileName);
                strResult = Marshal.PtrToStringAnsi(intPtrResult);
                System.IO.File.WriteAllText("D:\\aa.txt", strResult, System.Text.Encoding.GetEncoding("GB2312"));
                Console.WriteLine("执行结果:" + strResult);
            }
            else
            {
                Console.WriteLine("不是有效的音频文件");
            }
            return strResult;
        }
    }
    /// <summary>
    /// 语言类型
    /// </summary>
    public enum LanguageType
    {
        /// <summary>
        /// 中文
        /// </summary>
        En = 1,
        /// <summary>
        /// 英文
        /// </summary>
        Zh = 2
    }
}

注意事项:音频要是wav,而且格式要和它demo里面的一致,我用了Naudio开源组件来实现wav音频格式的转换,如果音频比特率和采样率和它demo里面的不一样的话,会导致识别率降低

时间: 2024-11-08 22:10:17

pocketsphinx实现连续大词汇量语音识别的相关文章

MySQL随机获取数据的方法,支持大数据量

最近做项目,需要做一个从mysql数据库中随机取几条数据出来. 总所周知,order by rand 会死人的..因为本人对大数据量方面的只是了解的很少,无解,去找百度老师..搜索结果千篇一律.特发到这里来,供大家学习. 在mysql中带了随机取数据的函数,在mysql中我们会有rand()函数,很多朋友都会直接使用,如果几百条数据肯定没事,如果几万或百万时你会发现,直接使用是错误的.下面我来介绍随机取数据一些优化方法. SELECT * FROM table_name ORDER BY ran

大数据量高并发的数据库优化

一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之前,完备的数据库模型的设计是必须的. 在一个系统分析.设计阶段,因为数据量较小,负荷较低.我们往往只注意到功能的实现,而很难注意到性能的薄弱之处,等到系统投入实际运行一段时间后,才发现系统的性能在降低,这时再来考虑提高系统性能则要花费更多的人力物力,而整个系统也不可避免的形成了一个打补丁工程. 所以在考虑整个系统的流程的时候,我们必须

大数据量下的SQL Server数据库自身优化 (转载)

1.1:增加次数据文件 从SQL SERVER 2005开始,数据库不默认生成NDF数据文件,一般情况下有一个主数据文件(MDF)就够了,但是有些大型的数据库,由于信息很多,而且查询频繁,所以为了提高查询速度,可以把一些表或者一些表中的部分记录分开存储在不同的数据文件里 由于CPU和内存的速度远大于硬盘的读写速度,所以可以把不同的数据文件放在不同的物理硬盘里,这样执行查询的时候,就可以让多个硬盘同时进行查询,以充分利用CPU和内存的性能,提高查询速度. 在这里详细介绍一下其写入的原理,数据文件(

[转]浅析大数据量高并发的数据库优化

链接:http://www.uml.org.cn/sjjm/201308264.asp 高并发数据库可以同时处理海量信息,应用范围很广.今天我们将讨论的是大数据量高并发的数据库优化,希望对大家有所帮助. 一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之前,完备的数据库模型的设计是必须的. 在一个系统分析.设计阶段,因为数据量较小,负荷较低.我们往往只注意到功能的实现,而很难注意到性

大数据量查询优化——数据库设计、SQL语句、JAVA编码

数据库设计方面: 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描.             如: select id from t where num is null              可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from t where num=0 3

大数据量高并发访问的数据库优化方法

一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之前,完备的数据库模型的设计是必须的. 在一个系统分析.设计阶段,因为数据量较小,负荷较低.我们往往只注意到功能的实现,而很难注意到性能的薄弱之处,等到系统投入实际运行一段时间后,才发现系统的性能在降低,这时再来考虑提高系统性能则要花费更多的人力物力,而整个系统也不可避免的形成了一个打补丁工程. 所以在考虑整个系统的流程的时候,我们必须

(转)大数据量高并发的数据库优化与sql优化

大数据量高并发的数据库优化 一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之前,完备的数据库模型的设计是必须的. 在一个系统分析.设计阶段,因为数据量较小,负荷较低.我们往往只注意到功能的实现,而很难注意到性能的薄弱之处,等到系统投入实际运行一段时间后,才发现系统的性能在降低,这时再来考虑提高系统性能则要花费更多的人力物力,而整个系统也不可避免的形成了一个打补丁工程. 所以在考虑整

数据库性能优化一:数据库自身优化(大数据量)

数据库优化包含以下三部分,数据库自身的优化,数据库表优化,程序操作优化.此文为第一部分 数据库性能优化一:数据库自身优化 优化①:增加次数据文件,设置文件自动增长(粗略数据分区) 1.1:增加次数据文件 从SQL SERVER 2005开始,数据库不默认生成NDF数据文件,一般情况下有一个主数据文件(MDF)就够了,但是有些大型的数据库,由于信息很多,而且查询频繁,所以为了提高查询速度,可以把一些表或者一些表中的部分记录分开存储在不同的数据文件里由于CPU和内存的速度远大于硬盘的读写速度,所以可

提高MYSQL大数据量查询的速度

1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:select id from t where num=0 3.应尽量避免在 where 子句中使用!=或<>操作符,否则引擎将放弃使用