涉及技術
動態調用Com對象(全反射、沒有引用com ocx)
取得系統存在的各種語言引擎
使用引擎進行朗讀
使用引擎進行保存聲音
程序圖列:
主要功能描述
實列變量等,構造函授等
取得所有的 識別對象模塊集合,放入下拉框
代碼
object _spVoiceCls =
null; //保存朗讀用的 SAPI.SpVoice
const
int SpFlags =
1; //SpeechVoiceSpeakFlags.SVSFlagsAsyn
object _oISpeechObjectTokens =
null; //保存 SAPI.ISpeechObjectTokens 就是系統有的語音引擎集合
int TokensCount =
0; // 語音引擎集合 數
DictionaryEntry[] _deTokens=null; //榜定下拉框用的
public MainForm()
{
InitializeComponent();
this.HandleDestroyed +=
new EventHandler(Form1_HandleDestroyed);
}
private
void Form1_Load(object sender, EventArgs e)
{
InitSAPI();
}
系統事件:程序加載
取得所有的 識別對象模塊集合,放入下拉框
代碼
void InitSAPI()
{
//創建語音對象朗讀用
_spVoiceCls = CreateComObject("SAPI.SpVoice");
if (_spVoiceCls == null)
{
MessageBox.Show("您的系統沒有,微軟語音組件");
Application.Exit();
}
else
{//取得所有的 識別對象模塊集合
_oISpeechObjectTokens = CallComMethod("GetVoices", _spVoiceCls); //取得SAPI.ISpeechObjectTokens
//識別對象集合 Count;
object r = GetComPropery("Count", _oISpeechObjectTokens);
if (r is int)
{
TokensCount = (int)r;
if (TokensCount > 0)
{
//取得全部語音識別對象模塊,及名稱,以被以後使用
_deTokens = new DictionaryEntry[TokensCount];
for (int i = 0; i < TokensCount; i++)
{
//從集合中取出單個 識別對象模塊
object oSpObjectToken = CallComMethod("Item", _oISpeechObjectTokens, i); //返回 SAPI.SpObjectToken
//取名稱
string Description = CallComMethod("GetDescription", oSpObjectToken) as string;
//放到 DictionaryEntry 對象中,key 是 識別對象模塊,value 是名稱
_deTokens= new DictionaryEntry(oSpObjectToken, Description);
}
//邦定到 下拉框
cboxTokens.DisplayMember = "Value";
cboxTokens.ValueMember = "Key";
cboxTokens.DataSource = _deTokens;
cboxTokens.SelectedIndex = 0;
}
}
}
}
用戶事件:朗讀
朗讀輸入的文本信息
代碼
private void btnSynthesis_Click(object sender, EventArgs e)
{
string msg = rTxtMsg.Text.Trim();
if (msg.Length != 0)
{
if (_spVoiceCls != null)
{
//設置語言引擎
SetComProperty("Voice", _spVoiceCls, cboxTokens.SelectedValue);
//調用Speak 函數,msg 是要播放的文本,1 是異步播放,因為是異步的 com 對象不立刻釋放
CallComMethod("Speak", _spVoiceCls, msg, SpFlags);
}
}
}
用戶事件:保存聲音
將輸入的文本信息生成音頻文件保存到文件
代碼
private void Save()
{
string msg = rTxtMsg.Text.Trim();
if (msg.Length != 0)
{
using (SaveFileDialog sfd = new SaveFileDialog())
{
sfd.Filter = "wav 文件 (*.wav)|*.wav";
sfd.RestoreDirectory = true;
if (sfd.ShowDialog() == DialogResult.OK)
{
/*
Enum SpeechStreamFileMode;
SSFMOpenForRead = 0;
SSFMOpenReadWrite = 1;
SSFMCreate = 2;
SSFMCreateForWrite = 3;
*/
int SpFileMode = 3;// SpeechStreamFileMode.SSFMCreateForWrite
object oSpFileStream = CreateComObject("SAPI.SpFileStream"); //創建 SAPI.SpFileStream
object oSpVoice = CreateComObject("SAPI.SpVoice"); //創建 SAPI.SpVoice
try
{
CallComMethod("Open", oSpFileStream, sfd.FileName, SpFileMode, false); //打開流
SetComProperty("Voice", oSpVoice, cboxTokens.SelectedValue); //設置 Voice 屬性,讓誰朗讀
SetComProperty("AudioOutputStream", oSpVoice, oSpFileStream); //設置流
CallComMethod("Speak", oSpVoice, msg, SpFlags); //調用 Speak
CallComMethod("WaitUntilDone", oSpVoice, Timeout.Infinite); //等
CallComMethod("Close", oSpFileStream); //關閉流
MessageBox.Show("保存成功");
}
finally
{
Marshal.ReleaseComObject(oSpVoice);
Marshal.ReleaseComObject(oSpFileStream);
}
}
}
}
}
private void btnSave_Click(object sender, EventArgs e)
{
try
{
btnSave.Enabled = false;
Save();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
btnSave.Enabled = true;
}
}
調用com組件,功能函數
自己寫的壹些幫助函數可以方便調用反射,要不太郁悶(如果是VB 就不用如此費盡了)
#region 調用com組件,功能通用函數
/// <summary>
/// 設置屬性
/// </summary>
/// <param name="name"></param>
/// <param name="o"></param>
/// <param name="vlaue"></param>
private static void SetComProperty(string name, object o, object vlaue)
{
Type t = o.GetType();
t.InvokeMember(name, BindingFlags.Instance | BindingFlags.SetProperty, null, o, new
object[] { vlaue });
}
/// <summary>
/// 取得屬性
/// </summary>
/// <param name="name"></param>
/// <param name="o"></param>
/// <returns></returns>
private static object GetComPropery(string name, object o)
{
Type t = o.GetType();
return t.InvokeMember(name, BindingFlags.Instance | BindingFlags.GetProperty, null, o, null);
}
/// <summary>
/// 調用方法函授
/// </summary>
/// <param name="name"></param>
/// <param name="o"></param>
/// <param name="parms"></param>
/// <returns></returns>
private static object CallComMethod(string name, object o, params object[] parms)
{
Type t = o.GetType();
return t.InvokeMember(name, BindingFlags.Instance | BindingFlags.InvokeMethod, null, o, parms);
}
/// <summary>
/// 創建 com 對象
/// </summary>
/// <param name="FromProgID"></param>
/// <returns></returns>
private static object CreateComObject(string FromProgID)
{
Type comType = Type.GetTypeFromProgID(FromProgID);
object rVar = null;
if (comType != null)
rVar = System.Activator.CreateInstance(comType);
return rVar;
}
#endregion
釋放com對象
很簡單的就壹行即可
代碼
void Form1_HandleDestroyed(object sender, EventArgs e)
{
//釋放com對象
Marshal.ReleaseComObject(_spVoiceCls);
}