Unity利用Sapi进行windows语音开发
软件中的语音技术主要包含两种:语音识别speech recognition和语音合成speech synthesis。一般地,开发者会因为技术实力和资金实力等各方面的问题无力完成专业的语音引擎,因此通常选择现有的较为专业的语音引擎来完成相关的开发,比如国内非常出名的科大讯飞,百度语音等等。当然国外的还有Google语音,微软有SAPI等等。
在VR开发过程中,由于运行在Windows环境下,那么自然而然,我们首选SAPI来进行语音开发。一是和Windows原生,二是离线不需要网络,三是不需要任何插件。另外就是SAPI发音,尤其是英文发音,还是相对来说质量不错的。(Win7以上自带)
使用SAPI,需要使用到的是System.Speech.dll文件。由于Unity需要将Dll文件放在Asset目录下,而这样的结果会发现sapi failed to initialize。原因怀疑为需要特定的上下文环境才能运行dll的api,以至于拷贝到Asset目录导致上下文环境缺失而无法运行。
但是如果做过这方面开发的知道,在C#的其他应用里面引用System.Speech.dll是完全没有问题的。那么是不是我们可以开发一个专门的第三方程序,然后unity进行调用呢?按照这个思路,我们开发了一个控制台程序Speech.exe,主要功能是根据输入文本进行语音合成。
代码较为简单
/*简单的SAPI语音合成控制台程序*/
using System.Speech.Synthesis;
using SpeechTest.Properties; namespace SpeechTest
{
class Program
{
static void Main(string[] args)
{
var speaker = new SpeechSynthesizer();
speaker.Speak(“test”);
}
}
}
OK,运行就可以听到机器发音Test了。
我们修改一下,改为从参数中读取,这样的话,我们可以在unity中利用Process运行Speech.exe,并传给Speech参数。
/*从参数读取需要发音的文本*/
using System.Speech.Synthesis;
using SpeechTest.Properties; namespace SpeechTest
{
class Program
{
static void Main(string[] args)
{
var speaker = new SpeechSynthesizer();
var res = args.Length == ? "请说" : args[];
speaker.Speak(res);
}
}
}
我们先使用CMD命令行,cd到Speech.exe所在的目录,然后输入Speech.exe test,如我们预想的那般,机器发音test。测试通过。
为了能够更改发音的配置,增加一些代码,从Setting中读取相关的配置数据,代码更改如下:
/*能够配置的控制台程序*/
using System.Speech.Synthesis;
using SpeechTest.Properties; namespace SpeechTest
{
class Program
{
static void Main(string[] args)
{
var speaker = new SpeechSynthesizer();
speaker.Volume = Settings.Default.SpeakVolume;
speaker.Rate = Settings.Default.SpeakRate;
var voice = Settings.Default.SpeakVoice;
if (!string.IsNullOrEmpty(voice))
speaker.SelectVoice(voice);
var res = args.Length == ? "请说" : args[];
speaker.Speak(res);
}
}
}
接下来我们在Unity中使用Process来开启这个Speech.exe,代码如下:
/*Unity中开启Speech.exe进程*/
using System.Diagnostics; public class Speecher: MonoBehaviour
{
public static void Speak(string str)
{
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "speech.exe",
Arguments = "\"" + str + "\"",
}
};
proc.Start();
} /***测试代码,可删除Start***/
protected void Start()
{
Speak("test");
}
/***测试代码,可删除End***/
}
将脚本挂在任何一个GO(GameObject)上,运行,黑框出现,同时听到发音,测试完成。
接下来我们隐藏这个黑框。代码修改如下:
/*Unity开启无框的Speech.exe进程*/
using System.Diagnostics; public class Speecher: MonoBehaviour
{
public static void Speak(string str)
{
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "speech.exe",
Arguments = "\"" + str + "\"",
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
}
};
proc.Start();
}
/***测试代码,可删除Start***/
protected void Start()
{
Speak("test");
}
/***测试代码,可删除End***/
}
其实到了这一步,主要的功能都完成了。但是细心的会发现,这样不断创建进程然后关闭进程的方式会不会太笨了。可不可以让Speech这个进程一直开启着,收到unity的信息时就发音呢?这就涉及到进程间通信了。
Windows的进程是相互独立的,各自有各自的分配空间。但是并不意味这不能相互通信。方法有很多,比如读写文件,发送消息(hook),Socket等等。其中Socket实现起来相对简单,尤其是我们已经拥有Socket封装库的情况下,只要少量代码就行了。
于是在Speech改成一个Socket服务器,代码如下:
/*Speech 服务端*/
using System;
using System.Linq;
using System.Speech.Synthesis;
using System.Text;
using Speech.Properties; namespace Speech
{
class Program
{
static void Main(string[] args)
{
var server = new NetServer();
server.StartServer(); while (true)
{
var res = Console.ReadLine();
if (res == "exit")
break;
}
}
} public class NetServer : SocketExtra.INetComponent
{
private readonly Speecher m_speecher; private readonly SocketExtra m_socket; public NetServer()
{
m_speecher = new Speecher();
m_socket = new SocketExtra(this);
} public void StartServer()
{
m_socket.Bind("127.0.0.1", Settings.Default.Port);
} public bool NetSendMsg(byte[] sendbuffer)
{
return true;
} public bool NetReciveMsg(byte[] recivebuffer)
{
var str = Encoding.Default.GetString(recivebuffer);
Console.WriteLine(str);
m_speecher.Speak(str);
return true;
} public bool Connected { get { return m_socket.Connected; } }
} public class Speecher
{
private readonly SpeechSynthesizer m_speaker; public Speecher()
{
m_speaker = new SpeechSynthesizer();
var installs = m_speaker.GetInstalledVoices(); m_speaker.Volume = Settings.Default.SpeakVolume;
m_speaker.Rate = Settings.Default.SpeakRate;
var voice = Settings.Default.SpeakVoice; var selected = false;
if (!string.IsNullOrEmpty(voice))
{
if (installs.Any(install => install.VoiceInfo.Name == voice))
{
m_speaker.SelectVoice(voice);
selected = true;
}
}
if (!selected)
{
foreach (var install in installs.Where(install => install.VoiceInfo.Culture.Name == "en-US"))
{
m_speaker.SelectVoice(install.VoiceInfo.Name);
break;
}
}
} public void Speak(string msg)
{
m_speaker.Speak(msg);
}
}
}
同时修改Unity代码,增加Socket相关代码:
/*Unity客户端代码*/
using System.Collections;
using System.Diagnostics;
using System.Text;
using UnityEngine; public class Speecher : MonoBehaviour, SocketExtra.INetComponent
{
private SocketExtra m_socket;
private Process m_process; protected void Awake()
{
Ins = this;
m_process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "speech.exe",
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
},
};
m_process.Start();
} /***测试代码,可删除Start***/
protected IEnumerator Start()
{
yield return StartCoroutine(Connect());
Speak("test");
}
/***测试代码,可删除End***/ public IEnumerator Connect()
{
m_socket = new SocketExtra(this);
m_socket.Connect("127.0.0.1", );
while (!m_socket.Connected)
{
yield return ;
}
} protected void OnDestroy()
{
if (m_process != null && !m_process.HasExited)
m_process.Kill();
m_process = null;
} public static Speecher Ins; public static void Speak(string str)
{
#if UNITY_EDITOR||UNITY_STANDALONE_WIN
Ins.Speech(str);
#endif
} public void Speech(string str)
{
if (m_socket.Connected)
{
var bytes = Encoding.Default.GetBytes(str);
m_socket.SendMsg(bytes);
}
} public bool NetReciveMsg(byte[] recivebuffer)
{
return true;
} public bool NetSendMsg(byte[] sendbuffer)
{
return true;
}
}
OK,大功告成。工程见Github
https://github.com/CodeGize/UnitySapi/
转载请注明出处www.codegize.com
Unity利用Sapi进行windows语音开发的更多相关文章
- Kinect for Windows SDK开发学习相关资源
Kinect for Windows SDK(K4W)将Kinect的体感操作带到了平常的应用学习中,提供了一种不同于传统的鼠标,键盘及触摸的无接触的交互方式,在某种程度上实现了自然交互界面的理想,即 ...
- Spark:利用Eclipse构建Spark集成开发环境
前一篇文章“Apache Spark学习:将Spark部署到Hadoop 2.2.0上”介绍了如何使用Maven编译生成可直接运行在Hadoop 2.2.0上的Spark jar包,而本文则在此基础上 ...
- Kinect for Windows SDK开发入门(15):进阶指引 下
Kinect for Windows SDK开发入门(十五):进阶指引 下 上一篇文章介绍了Kinect for Windows SDK进阶开发需要了解的一些内容,包括影像处理Coding4Fun K ...
- Windows Phone开发人员必看资料
win phone开发必看资料,下载地址收藏啦!收藏后可有选择性的下载,希望大家喜欢! 完整附件下载:http://down.51cto.com/data/414417 附件预览: Windows E ...
- Windows Phone开发(46):与Socket有个约会
原文:Windows Phone开发(46):与Socket有个约会 不知道大家有没有"谈Socket色变"的经历?就像我一位朋友所说的,Socket这家伙啊,不得已而用之.哈,S ...
- Windows Phone开发(43):推送通知第一集——Toast推送
原文:Windows Phone开发(43):推送通知第一集--Toast推送 好像有好几天没更新了,抱歉抱歉,最近"光荣"地失业,先是忙于寻找新去处,唉,暂时没有下文.而后又有一 ...
- Windows Phone开发(15):资源
原文:Windows Phone开发(15):资源 活字印刷术是我国"四大发明"之一,毕昇在发明活字印刷术之后,他很快发现一个问题,随着要印刷资料的不断增加,要用到的汉字数目越来越 ...
- windows phone开发-Webbrowser使用技巧
原文:windows phone开发-Webbrowser使用技巧 5月份开发了脸萌WP版,其中需要使用web技术来绘制图像,于是就使用了原生webbrowser控件.在使用webbrowser co ...
- 利用cygwin创建windows下的crontab定时任务
要求 必备知识 熟悉基本编程环境搭建. 运行环境 windows 7(64位); Cygwin-1.7.35 下载地址 环境下载 什么是Cygwin Cygwin是一个在windows平台上运行的类U ...
随机推荐
- ios 学习动画的套路 (一)
你也肯定喜欢炫酷的动画! 在APP中,动画就是一个点睛之笔!可以给用户增加一些独特的体验感,估计也有许多的和我一样的,看着那些觉得不错的动画,也就只能流口水的孩子,毕竟~不知道从哪里下手去写!会连续的 ...
- CSS3中选择器
::selection选择器 <style type="text/css"> .selectColor::selection{color:#fff;background ...
- Apache 的安装
1.获取源码包 cd /usr/local/src/ ls wget http://mirrors.cnnic.cn/apache/httpd/httpd-2.4.25.tar.gz 2.解压.编译. ...
- ConOS安装mysql5.7 及简单配置
安装 保证你的用户有权限 安装 没有 切换 root su root (su的意思:swich user) # rpm -ivh http://dev.mysql.com/get/mysql57- ...
- laravel项目中手机浏览器在线阅读pdf文件-->PDFJS插件
第一步:下载链接:http://mozilla.github.io/pdf.js/getting_started/#download 第二步:将下载的文件放在项目中. 第三步:在项目中想要预览的地方给 ...
- 《C++ Primer》读书笔记—第一章 开始
声明: 文中内容收集整理自<C++ Primer 中文版 (第5版)>,版权归原书所有. 学习一门程序设计语言最好的方法就是练习编程. 1.一个函数的定义包含四个部分:返回类型(retur ...
- loadrunner测试结果分析
LR性能测试结果样例分析 测试结果分析 LoadRunner性能测试结果分析是个复杂的过程,通常可以从结果摘要.并发数.平均事务响应时间.每秒点击数.业务成功率.系统资源.网页细分图.Web服务器资源 ...
- 磁盘工作原理与IO性能分析
最近,在研究如何优化产品设备的磁盘IO性能,需要深入研究磁盘及文件系统原理和工作机制,下面简要总结下关于磁盘方面的东西,下篇文章再分享文件系统的. 机械磁盘结构: 无论哪种机械硬盘,都主要由盘片.磁头 ...
- UI培训就业会很难吗
众所周知UI是研究人机交互的学科,他是从互联网发展而来的,单从目前它的应用领域来看,主要应用于软件.互联网.移动智能设备.游戏和虚拟现实影音方面.这些都是新兴的热门方向和活跃领域.目前人才缺口和社会需 ...
- MySQL调优三步曲(慢查询、explain profile)
在做性能测试中经常会遇到一些sql的问题,其实做性能测试这几年遇到问题最多还是数据库这块,要么就是IO高要么就是cpu高,所以对数据的优化在性能测试过程中占据着很重要的地方,下面我就介绍一些msyql ...