之前有个项目需求是要在客户内网实现一个连续大词汇语音识别功能,由于客户的内网是独立的,不能访问互联网,所以我只能到开源社区去找找碰碰运气了。后来在网上找到了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[];
GetCurrentDirectory(,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==)
{
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,,str,-,NULL,,NULL,NULL);
result=(char *)malloc((textlen+)*sizeof(char));
memset(result,,sizeof(char)*(textlen+));
WideCharToMultiByte(CP_ACP,,str,-,result,textlen,NULL,NULL);
return result;
} wchar_t * UTF8ToNunicode(const char* str)
{
int textlen;
wchar_t * result;
textlen=MultiByteToWideChar(CP_UTF8,,str,-,NULL,);
result=(wchar_t *)malloc((textlen+)*sizeof(wchar_t));
memset(result,,(textlen+)*sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8,,str,-,(LPWSTR)result,textlen);
return result;
} char* UTF8ToANSI(const char* str)
{
return UnicodeToANSI(UTF8ToNunicode(str));
} char strResult[];//保存语音识别返回结果
/*语言识别方法一
*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[];
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 < )
{
strcpy(strResult,"解码失败!");
return strResult;
}
while (!feof(fh)) {
size_t nsamp;
nsamp = fread(buf, , , fh);
rv = ps_process_raw(ps, buf, nsamp, FALSE, FALSE);
}
rv = ps_end_utt(ps);
if (rv < )
{
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 = ,
/// <summary>
/// 英文
/// </summary>
Zh =
}
}

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

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

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

    最近做项目,需要做一个从mysql数据库中随机取几条数据出来. 总所周知,order by rand 会死人的..因为本人对大数据量方面的只是了解的很少,无解,去找百度老师..搜索结果千篇一律.特发到 ...

  2. MySQL大数据量快速分页实现(转载)

    在mysql中如果是小数据量分页我们直接使用limit x,y即可,但是如果千万数据使用这样你无法正常使用分页功能了,那么大数据量要如何构造sql查询分页呢?     般刚开始学SQL语句的时候,会这 ...

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

    数据库设计方面: 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将 ...

  4. sql大数据量查询的优化技巧

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

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

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

  6. Mysql千万级大数据量查询优化

    来源于:https://blog.csdn.net/A350204530/article/details/79040277 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 ord ...

  7. 大数据量下的SQL Server数据库自身优化

    原文: http://www.d1net.com/bigdata/news/284983.html 1.1:增加次数据文件 从SQL SERVER 2005开始,数据库不默认生成NDF数据文件,一般情 ...

  8. DB开发之大数据量高并发的数据库优化

    一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之前,完备的数据库模型的设计是必须的. ...

  9. 大数据量高并发的数据库优化详解(MSSQL)

    转载自:http://www.jb51.net/article/71041.htm 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能. ...

随机推荐

  1. 跳跃【BFS】

    From 牛客网:https://ac.nowcoder.com/acm/problem/25160

  2. rtp传输h264

    ---恢复内容开始--- 基本概念的理解 H.264的主要目标:1.高的视频压缩比2.良好的网络亲和性 解决方案:VCL video coding layer 视频编码层NAL network abs ...

  3. 曼孚科技:AI领域3种典型的深度学习算法

    ​深度学习(Deep Learning)是机器学习(Machine Learning)领域中一个新的研究方向,引领了第三次人工智能的浪潮. 本文整理了深度学习领域3种典型的算法,希望可以帮助大家更好地 ...

  4. UVa 12050 - Palindrome Numbers (回文数)

    A palindrome is a word, number, or phrase that reads the same forwards as backwards. For example, th ...

  5. 微信小程序open-data userAvatarUrl圆角显示

    从年初开始,打开小程序,工具栏都会弹出这个提醒: 也就是,默认不弹出授权询问框,默认获取不到用户信息(头像.昵称等)! 如果你需要用到这个接口,可以尝试以下方法: 1.用 button 组件,将属性名 ...

  6. 阿里云部署JeecgBoot

    阿里云部署JeecgBoot 首先贴出官网教程:http://jeecg-boot.mydoc.io/?t=345682 自己在部署的时候遇到了各种各样的问题,其实一步一步的按照官网给出的步骤来是没问 ...

  7. [CF1304C] Air Conditioner

    维护一区间 \([l,r]\) 人按照时间升序 考虑 \((l_i, h_i, t_i)\),当前的所有区间与这个区间取交 推到 \(t_{i+1}\) 时,所有区间的端点向两边扩张即可 注意把空掉的 ...

  8. [TJOI2007] 路标设置 - 二分答案,贪心

    考虑到答案满足可二分性,段内可以贪心,所以暴力二分即可 注意-1 详见代码(我这题都能写WA) #include <bits/stdc++.h> using namespace std; ...

  9. window.resizeTo

    概述 动态调整窗口的大小. 语法 window.resizeTo(aWidth, aHeight) 参数 aWidth 是一个整数,表示新的 outerWidth(单位:像素)(包括滚动条.窗口边框等 ...

  10. 菜鸟教程 Missing parentheses in call to 'print'

    个人博客 地址:http://www.wenhaofan.com/article/20180618180327 >>> print "hello" SyntaxE ...