admin管理员组文章数量:1562652
上一篇的地址手把手的操作——用java调用科大讯飞的离线语音识别dll实现离线识别(JNA实现)(一)
上一篇讲到了最难的地方,参数的转换,这里单独写出来
**
三、参数的转换(难点)
**
注:本文是以讯飞提供的C语言例子作为模板改写,语音来源于文件
1、先分析提供的例子
本人使用的是VS2010
下载链接链接:https://pan.baidu/s/1CZX3k6nhsbLkuzB3mocyww 提取码:6r5g
2.45G大小,需要安装一段时间,因为用JNA只用看,这个版本够了
【为了给我一样对C/C++不了解的初阶,大神轻喷】
运行之后
【文件】–【打开】–【项目/解决方案】–自己找文件位置–【asr_offline_sample.vcxproj】
同样的方法打开头文件
【文件】–【打开】–【文件】–自己找文件位置–【头文件.h结尾的】
主要看例子asr_sample.c
在java中主要就是将这个文件进行改写,所以要先看懂
我自己看了很久,讲下结构吧:
上面几个是各项功能的函数,最下面是主函数main,跟java的结构很像吧
几大主要功能
【登录】
【建立语法】
【建立词典】
【语音识别】
【退出】
看上去很简单啊,接下来就是一个一个在java中实现
我先建立了一个lib接口,里面放调用的东西
(先把动态库加载进来)
public interface VoiceLib extends Library{
VoiceLib instance = (VoiceLib)Native.loadLibrary("msc_x64", VoiceLib.class);
}
#1登录
这个功能在(一)中已经有例子了,这里重写一遍就好
public interface VoiceLib extends Library{
VoiceLib instance = (VoiceLib)Native.loadLibrary("msc_x64", VoiceLib.class);
int MSPLogin(String usr, String pwd, String params);
}
新建主类xMsc
改写登录功能
public static void main(String[] args) {
String login_config = "appid=5ba4***"; //登录参数
UserData asr_data=null ;
int ret = 0;
ret = VoiceLib.instance.MSPLogin(null, null, login_config);
//第一个参数为用户名,第二个参数为密码,传null即可,第三个参数是登录参数
if (MSP_SUCCESS!= ret) {
System.out.println("登录失败!");
exit();
}
}
上面先改写下几个常量:
public class xMsc {
public static final int SAMPLE_RATE_16K = 16000;
public static final int SAMPLE_RATE_8K = 8000;
public static final int MAX_GRAMMARID_LEN = 32;
public static final int MAX_PARAMS_LEN = 1024;
public static final int MSP_SUCCESS = 0;
public static final int MSP_FAILED = 1;
private static int MSP_AUDIO_SAMPLE_FIRS = 1;
private static int MSP_AUDIO_SAMPLE_CONTINUE = 2;
private static int MSP_EP_LOOKING_FOR_SPEECH = 0;
private static int MSP_REC_STATUS_INCOMPLETE = 2;
private static int MSP_EP_AFTER_SPEECH = 3;
private static int MSP_AUDIO_SAMPLE_LAST = 4;
private static int MSP_REC_STATUS_COMPLETE = 5;
private static File f_pcm = null;
private static byte[] pcm_data =null;
private static int errcode = -1;
private static String session_id = "";
private static IntByReference ep_status = new IntByReference(MSP_EP_LOOKING_FOR_SPEECH);
private static IntByReference rec_status = new IntByReference(MSP_REC_STATUS_INCOMPLETE);
private static IntByReference rss_status1 = new IntByReference(MSP_AUDIO_SAMPLE_FIRS);
private static IntByReference err = new IntByReference(errcode);
public static final String ASR_RES_PATH = "fo|common.jet"; // 离线语法识别资源路径
public static final String GRM_BUILD_PATH = "./msc/GrmBuilld_x64"; // 构建离线语法识别网络生成数据保存路径
public static final String GRM_FILE = "./source/szx.bnf"; // 构建离线识别语法网络所用的语法文件
public static final String LEX_NAME = "contact"; // 更新离线识别语法的contact槽(语法文件为此示例中使用的call.bnf)
里面的路径必须要跟我一样,尤其是 ASR_RES_PATH ,前面必须加"fo|"
有几个文件要拷贝过来啊,语法文件之类,我建立了一个source文件夹,都放里面了
现在的结构
【先一口气把main里面的全部改写完吧!】
public static void main(String[] args) {
String login_config = "appid=5ba4*****"; //登录参数,要改成自己的
asr_data = new UserData();
int ret = 0;
ret = VoiceLib.instance.MSPLogin(null, null, login_config); // 第一个参数为用户名,第二个参数为密码,传null即可,第三个参数是登录参数
if (MSP_SUCCESS != ret) {
System.out.println("登录失败!");
exit();
}
System.out.println("登录成功!");
System.out.println("构建离线识别语法网络...\n");
ret = build_grammar(asr_data); // 第一次使用某语法进行识别,需要先构建语法网络,获取语法ID,之后使用此语法进行识别,无需再次构建
if (MSP_SUCCESS != ret) {
System.out.println("构建语法调用失败!\n");
exit();
}
while (MSP_FAILED != asr_data.build_fini) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (MSP_SUCCESS != asr_data.errcode) {
exit();
}
System.out.println("离线识别语法网络构建完成,开始识别...\n");
ret = run_asr(asr_data);
if (MSP_SUCCESS != ret) {
System.out.println("离线语法识别出错: \n");
exit();
}
}
【注】词典我删掉了,和构建语法一样,需要的自己写喽
¥¥¥¥¥退出功能先封装一下¥¥¥¥¥¥
public static void exit(){
VoiceLib.instance.MSPLogout();
System.out.println("请按任意键退出...\n");
}
【再来一口气】把要用的函数全部封装到VoiceLib中,等下直接调用
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.szxinfo.recognizer.CallbackUtil.GrammarCallBack;
public interface VoiceLib extends Library{
String filePath = "mscx64";
VoiceLib instance = (VoiceLib)Native.loadLibrary(filePath, VoiceLib.class);
int MSPLogin(String usr, String pwd, String params);
int QISRBuildGrammar (String cs2, String grm_content, int grm_cnt_len, String grm_build_params, GrammarCallBack grammarCallBack, Pointer pointer);
String QISRSessionBegin(String grammarList, String asr_params, IntByReference errcode);
int QISRAudioWrite(String session_id, byte[] every, int waveLen, int audioStatus, IntByReference ep_status1, IntByReference rec_status1);
String QISRGetResult(String session_id, IntByReference rss_status1, int waitTime, IntByReference err);
int QISRSessionEnd(String sessionID, String hints);
// int GrammarCallBack(int ecode, String info, UserData udata);
int MSPLogout();
}
【这里的参数我都已经改好啦,等下到具体功能再解释】
然后写语法的
//重要分割线*********************************//
在讯飞提供的例子中,有一个回调函数和一个构建语法函数,都要改写,怎么办呢?
回调函数我封装到一个Util中(后面的词典回调一起了)
package com.xinzhi;
import com.sun.jna.Callback;
import com.sun.jna.Pointer;
public class CallbackUtil {
//语法回调函数的接口
public static interface GrammarCallBack extends Callback{
int build_grm_cb(int ecode, String info, Pointer udata);
}
//语法回调函数的实现
public static class GrammarCallBack_Realize implements GrammarCallBack{
@Override
public int build_grm_cb(int ecode, String info,Pointer udata) {
UserData g_udata=Util.fromPointer(udata
版权声明:本文标题:手把手的操作——用java调用科大讯飞的离线语音识别dll实现离线识别(JNA实现)(二) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/xitong/1727480641a1116786.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论