TSS(Text To Speech),语音朗读文本的技术,在Windows*下,微软给我们提供了一套API接口(Speech API)。金山词霸的朗读功能就是用的这个接口。
WindowsXP自带的是Speech API 5.1版本,默认只支持英文,如果要支持中文需要安装语音库。
Vista版本开始,系统自带的Speech API就换成了5.3版本,比较奇怪的是这个API并没有做到向下兼容,5.3版本在Vista以下的版本是不可用的。
有一些非官方的Windows优化版本去掉了语音功能,需要对系统进行修复。
TTS修复工具及一些其他的语音库下载
http://www.dacidian.net/tts/
下面我说一下如何实现,使用.NET 4.0新增的dynamic类型,可以很方便的使用COM类库。
Type type = Type.GetTypeFromProgID("SAPI.SpVoice");
dynamic spVoice = Activator.CreateInstance(type);
spVoice.Speak("Text To Speech 语音朗读文本技术");
当然,直接使用dynamic还是很不方便的,可以对SAPI.SpVoice进行封装
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Diagnostics;
using System.Runtime.InteropServices; namespace COM
{
[Guid("ED5DCE10-F40B-4655-9E7B-903779C77AF2")]
public partial class SpVoice : Object
{
public enum Flags
{
SVSFDefault = ,
SVSFlagsAsync = ,
SVSFPurgeBeforeSpeak = ,
SVSFIsFilename = ,
SVSFIsXML = ,
SVSFIsNotXML = ,
SVSFPersistXML = ,
SVSFNLPSpeakPunc = ,
SVSFParseSapi = ,
SVSFParseSsml = ,
SVSFParseAutodetect = ,
SVSFNLPMask = ,
SVSFParseMask = ,
SVSFVoiceMask = ,
SVSFUnusedFlags = -
} public enum Priority
{
SVPNormal = ,
SVPAlert = ,
SVPOver =
}
}
public partial class SpVoice : Object
{
private Type _ComType = null;
private object _ComObject = null; public SpVoice()
{
this.Init();
} public bool Init()
{
this._ComType = Type.GetTypeFromProgID("SAPI.SpVoice", true); // CLSID {269316D8-57BD-11D2-9EEE-00C04F797396}
if (this._ComType == null) {
throw new Exception("COM调用失败");
}
this._ComObject = Activator.CreateInstance(this._ComType, true);
return this._ComObject != null;
} public int Release()
{
return Marshal.ReleaseComObject(this._ComObject);
} public int Rate
{
get {
return (int)this._ComType.InvokeMember("Rate", BindingFlags.GetProperty, null, this._ComObject, null);
}
set {
this._ComType.InvokeMember("Rate", BindingFlags.SetProperty, null, this._ComObject, new object[] { value });
}
} public void Pause()
{
this._ComType.InvokeMember("Pause", BindingFlags.InvokeMethod, null, this._ComObject, null);
} public void Resume()
{
this._ComType.InvokeMember("Resume", BindingFlags.InvokeMethod, null, this._ComObject, null);
} public int Volume
{
get
{
return (int)this._ComType.InvokeMember("Volume", BindingFlags.GetProperty, null, this._ComObject, null);
}
set
{
this._ComType.InvokeMember("Volume", BindingFlags.SetProperty, null, this._ComObject, new object[] { value });
}
} public int Skip(int Type, int NumItems)
{
return (int)this._ComType.InvokeMember("Skip", BindingFlags.InvokeMethod, null, this._ComObject, new object[] { Type, NumItems });
} public bool IsUISupported(string TypeOfUI, object ExtraData)
{
return (bool)this._ComType.InvokeMember("IsUISupported", BindingFlags.InvokeMethod, null, this._ComObject, new object[] { TypeOfUI, ExtraData });
} public bool WaitUntilDone(int msTimeout) {
return (bool)this._ComType.InvokeMember("WaitUntilDone", BindingFlags.InvokeMethod, null, this._ComObject, new object[] { msTimeout });
} public void DisplayUI(int hWndParent, string Title, string TypeOfUI, object ExtraData)
{
this._ComType.InvokeMember("DisplayUI", BindingFlags.InvokeMethod, null, this._ComObject, new object[] { hWndParent, Title, TypeOfUI, ExtraData });
} public void Speak(string Text, Flags Flags)
{
this._ComType.InvokeMember("Speak", BindingFlags.InvokeMethod, null, this._ComObject, new object[] { Text, Flags });
} public Priority Property
{
get {
return (Priority)this._ComType.InvokeMember("Priority", BindingFlags.GetProperty, null, this._ComObject, null);
}
set {
this._ComType.InvokeMember("Priority", BindingFlags.SetProperty, null, this._ComType, new object[] { value });
}
} public List<string> GetVoices()
{
List<string> _ret = null;
object Item = null, _Voices = this._ComType.InvokeMember("GetVoices", BindingFlags.InvokeMethod, null, this._ComObject, null);
int Count = (int)_Voices.GetType().InvokeMember("Count", BindingFlags.GetProperty, null, _Voices, null);
if (Count != ) {
_ret = new List<string>();
}
for (int i = ; i < Count; i++) {
Item = _Voices.GetType().InvokeMember("Item", BindingFlags.InvokeMethod, null, _Voices, new object[]{ i });
if (Item != null) {
_ret.Add(Item.GetType().InvokeMember("GetDescription", BindingFlags.InvokeMethod, null, Item, null).ToString());
}
}
return _ret;
} public bool SetVoices(string Name)
{
bool _ret = false;
object Item = null, _Voices = this._ComType.InvokeMember("GetVoices", BindingFlags.InvokeMethod, null, this._ComObject, null);
int Count = (int)_Voices.GetType().InvokeMember("Count", BindingFlags.GetProperty, null, _Voices, null);
for (int i = ; i < Count; i++) {
Item = _Voices.GetType().InvokeMember("Item", BindingFlags.InvokeMethod, null, _Voices, new object[] { i });
if (Item != null) {
var _str = Item.GetType().InvokeMember("GetDescription", BindingFlags.InvokeMethod, null, Item, null).ToString();
if (_str == Name) {
this._ComType.InvokeMember("Voice", BindingFlags.SetProperty, null, this._ComObject, new object[] { Item });
}
}
}
return _ret;
}
}
}
转载于http://blog.csdn.net/windowsvipcuvs/article/details/30751707
这样使用起来就比较方便
var spVoices = new SpVoice()
{
Rate = -,
Volume =
};
spVoices.SetVoices(spVoices.GetVoices()[]);
spVoices.Speak(speak, SpVoice.Flags.SVSFlagsAsync);