【问题标题】:Microsoft Speech.Synthesis Async speech not AsynchronousMicrosoft Speech.Synthesis 异步语音不是异步的
【发布时间】:2017-12-31 03:28:59
【问题描述】:

晚上好。我正在尝试使用简单的延迟来制作混响效果,但尽管使用了 SpeakAsync 方法,但代码不会继续执行。

我在任何地方都找不到有关此问题的文档,因此我非常感谢您提供的任何提示。感谢您的时间! 我在 Visual Studio 2017 中使用 System.Speech 版本 4.0.0。 我的目标是运行时 4.5.2

Imports System.Speech.Synthesis
Imports System.Threading
Imports System.Threading.Tasks

Module Module1

Sub main()
    Dim SpeechString As String = "This is a test phrase, there are many 
like it, but this one is mine."
    Call OutSpeech(1, 100, SpeechString)

End Sub


Sub OutSpeech(SpeechRate As Integer, SpeechVolume As Integer, SpeechText As String)
    Dim SpeechHolder As New SpeechSynthesizer

    SpeechHolder.Rate = SpeechRate
    SpeechHolder.Volume = SpeechVolume
    SpeechHolder.SpeakAsync(SpeechText)
    Thread.Sleep(100)
    SpeechHolder.SpeakAsync(SpeechText)
    Console.ReadLine()
End Sub

结束模块

【问题讨论】:

  • 顺便说一句,在您的问题中您引用了Microsoft Speech,但您的代码使用了System.Speech。这是两个不同的程序集,您应该对此更加具体。

标签: vb.net text-to-speech speech-synthesis


【解决方案1】:

按顺序调用 SpeechHolder.SpeakAsync(SpeechText) 只会将输出排队,并且语音不会重叠。

混响效果是一种回声效果,其中快速波在很短的延迟内合并在一起。因此,要获得类似混响的效果,请生成两个或多个相同的声音,每个声音之间都有延迟。

Reverb() 方法将调用两次OutSpeech(),设置适当的延迟(100 毫秒似乎适合得到结果)。

Sub Reverb()
  Dim Delay As Integer = 100
  Dim SpeechString As String = "This is a test phrase, there are many like it, but this one is mine."
  OutSpeech(1, 100, Delay, SpeechString)
  OutSpeech(1, 100, Delay, SpeechString)

End Sub

OutSpeech() 方法变为异步方法,因此在创建新合成器时调用会重叠。
创建了两个任务。一个用于设置延迟,一个用于 (a) 在合成器“说话”时等待,测试 SpeechHolder.State

Async Sub OutSpeech(SpeechRate As Integer, SpeechVolume As Integer, Delay As Integer, SpeechText As String)
    Using SpeechHolder As SpeechSynthesizer = New SpeechSynthesizer
        SpeechHolder.Rate = SpeechRate
        SpeechHolder.Volume = SpeechVolume

        Await Task.Run(Async Function() As Task(Of Boolean)
                       SpeechHolder.SpeakAsync(SpeechText)
                       Await Task.Delay(Delay)
                       Await Task.Run(Sub()
                                          While SpeechHolder.State = SynthesizerState.Speaking
                                          End While
                                      End Sub)
                       Return True
                   End Function)
    End Using
End Sub

【讨论】:

  • 您不能将SpeechSynthesizer 放在using 块中,因为它在声音有机会播放之前就被释放了。
  • @Crowcoder 你错过了Await Task.Run(Sub() While (...)
  • 我说的是“你可能还...... SpeechHolder.Dispose() 不再需要”编辑。也许我误解了,但如果我误解了,那么 OP 也可能。
  • @Crowcoder 你的意思是我应该更明确地描述为什么不再需要?
  • 我没有尝试你的代码,我说的是我的。我现在明白你的意思了,你是如何在while 中使用合成器的状态的。如果您不仔细阅读(像我一样),那么您可能会误解 Using 示例的含义。
【解决方案2】:

深入了解System.Speech.dll,它似乎在排队发言操作。因此,即使语音会异步开始,它也只会一次播放一个。

这是我进入反编译程序集之前我认为这是必须发生的事情:

private void AddSpeakParameters(VoiceSynthesis.Parameters param)
{
    lock (this._pendingSpeakQueue)
    {
        this._pendingSpeakQueue.Enqueue(param);
        if (this._pendingSpeakQueue.Count == 1)
        {
            this._evtPendingSpeak.Set();
        }
    }
}

您可以使用多个SpeechSynthesizer 实例同时播放声音或通过睡眠来抵消。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-05
    • 2019-11-16
    • 2015-05-16
    • 1970-01-01
    • 2018-02-11
    • 2019-11-30
    • 1970-01-01
    • 2012-08-20
    相关资源
    最近更新 更多