跟直接朗读文本相似,我们仍旧使用SpVoice的Speak()函数朗读文本,只是我们通过指定SpVoice的AudioOutputStream属性,将语音输出到一个音频文件,这样就完成了文本文件到音频文件的转换。
完成转换工作者线程的创建后,我们就可以利用它来完成具体的转换工作。在窗体的保存按钮的单击响应函数中,我们创建相应的工作者线程来进行文本的转换。
private void btnSavetoWAV_Click(object sender, EventArgs e)
{
string strWAVFile = "";
try
{
// 使用保存文件对话框,选择保存的文件
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "All files (*.*)|*.*|wav files (*.wav)|*.wav";
sfd.Title = "Save to a wave file";
sfd.FilterIndex = 2;
sfd.RestoreDirectory = true;
if (sfd.ShowDialog() == DialogResult.OK)
{
// 获取用户输入的文件名
strWAVFile = sfd.FileName;
// 从Text Box控件获取要转换的文本
ArrayList arrText = new ArrayList();
foreach (String sLine in this.textPreview.Lines)
arrText.Add(sLine);
// 显示进度条
progressForm = new Form2();
progressForm.Show();
// 创建工作者线程,并向工作者线程传递要转换的文本
WorkerThread myThreadFun = new WorkerThread(
this.cmbVoices.SelectedIndex, arrText, strWAVFile);
// 注册线程事件
myThreadFun.threadStartEvent += new EventHandler(method_threadStartEvent);
myThreadFun.threadEvent += new EventHandler(method_threadEvent);
myThreadFun.threadEndEvent += new EventHandler(method_threadEndEvent);
// 创建线程,执行工作者线程
Thread thread = new Thread(new ThreadStart(myThreadFun.runMethod));
// 启动线程
thread.Start();
}
}
catch
{
}
}
{
string strWAVFile = "";
try
{
// 使用保存文件对话框,选择保存的文件
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "All files (*.*)|*.*|wav files (*.wav)|*.wav";
sfd.Title = "Save to a wave file";
sfd.FilterIndex = 2;
sfd.RestoreDirectory = true;
if (sfd.ShowDialog() == DialogResult.OK)
{
// 获取用户输入的文件名
strWAVFile = sfd.FileName;
// 从Text Box控件获取要转换的文本
ArrayList arrText = new ArrayList();
foreach (String sLine in this.textPreview.Lines)
arrText.Add(sLine);
// 显示进度条
progressForm = new Form2();
progressForm.Show();
// 创建工作者线程,并向工作者线程传递要转换的文本
WorkerThread myThreadFun = new WorkerThread(
this.cmbVoices.SelectedIndex, arrText, strWAVFile);
// 注册线程事件
myThreadFun.threadStartEvent += new EventHandler(method_threadStartEvent);
myThreadFun.threadEvent += new EventHandler(method_threadEvent);
myThreadFun.threadEndEvent += new EventHandler(method_threadEndEvent);
// 创建线程,执行工作者线程
Thread thread = new Thread(new ThreadStart(myThreadFun.runMethod));
// 启动线程
thread.Start();
}
}
catch
{
}
}
除了创建线程进行文本的转换之外,为了让我们的软件更加易用,更加人性化,我们还需要响应线程事件,移动进度条的位置以反映转换的进度,免得用户以为软件在比较长的转换过程中死掉了。
// 线程开始的时候调用的委托
private delegate void maxValueDelegate(int maxValue);
// 线程执行中调用的委托
private delegate void nowValueDelegate(int nowValue);
// 线程结束的时候调用的委托
private delegate void hideProgressDelegate(int n);
/// 线程完成事件,隐藏进度条窗口
/// 但是我们不能直接操作进度条,需要一个委托来替我们完成
void method_threadEndEvent(object sender, EventArgs e)
{
hideProgressDelegate hide = new hideProgressDelegate(hideProgress);
this.Invoke(hide, 0);
}
/// 线程执行中的事件,设置进度条当前进度
/// 这里的sender,是WorkerThread 函数中传过来的当前值
void method_threadEvent(object sender, EventArgs e)
{
int nowValue = Convert.ToInt32(sender);
nowValueDelegate now = new nowValueDelegate(setNow);
this.Invoke(now, nowValue);
}
/// 线程开始事件,设置进度条最大值
/// 但是我不能直接操作进度条,需要一个委托来替我完成
/// 这里的sender,是WorkerThread 函数中传过来的最大值
void method_threadStartEvent(object sender, EventArgs e)
{
int maxValue = Convert.ToInt32(sender);
maxValueDelegate max = new maxValueDelegate(setMax);
this.Invoke(max, maxValue);
}
/// 被委托调用的函数,专门操作进度条
private void setMax(int maxValue)
{
progressForm.progressBar1.Maximum = maxValue;
}
private void setNow(int nowValue)
{
progressForm.progressBar1.Value = nowValue;
}
private void hideProgress(int n)
{
progressForm.Hide();
}
private delegate void maxValueDelegate(int maxValue);
// 线程执行中调用的委托
private delegate void nowValueDelegate(int nowValue);
// 线程结束的时候调用的委托
private delegate void hideProgressDelegate(int n);
/// 线程完成事件,隐藏进度条窗口
/// 但是我们不能直接操作进度条,需要一个委托来替我们完成
void method_threadEndEvent(object sender, EventArgs e)
{
hideProgressDelegate hide = new hideProgressDelegate(hideProgress);
this.Invoke(hide, 0);
}
/// 线程执行中的事件,设置进度条当前进度
/// 这里的sender,是WorkerThread 函数中传过来的当前值
void method_threadEvent(object sender, EventArgs e)
{
int nowValue = Convert.ToInt32(sender);
nowValueDelegate now = new nowValueDelegate(setNow);
this.Invoke(now, nowValue);
}
/// 线程开始事件,设置进度条最大值
/// 但是我不能直接操作进度条,需要一个委托来替我完成
/// 这里的sender,是WorkerThread 函数中传过来的最大值
void method_threadStartEvent(object sender, EventArgs e)
{
int maxValue = Convert.ToInt32(sender);
maxValueDelegate max = new maxValueDelegate(setMax);
this.Invoke(max, maxValue);
}
/// 被委托调用的函数,专门操作进度条
private void setMax(int maxValue)
{
progressForm.progressBar1.Maximum = maxValue;
}
private void setNow(int nowValue)
{
progressForm.progressBar1.Value = nowValue;
}
private void hideProgress(int n)
{
progressForm.Hide();
}