Vb.net Microsoft语音。合成异步语音不是异步的

Vb.net Microsoft语音。合成异步语音不是异步的,vb.net,text-to-speech,speech-synthesis,Vb.net,Text To Speech,Speech Synthesis,晚上好。我尝试使用一个简单的延迟来实现混响效果,但是代码不会继续执行,尽管使用了SpeakAsync方法 我在任何地方都找不到关于这个问题的文档,所以我非常感谢任何人提供的提示。谢谢你抽出时间! 我正在Visual Studio 2017中使用System.Speech 4.0.0版。 我的目标是运行时4.5.2 Imports System.Speech.Synthesis Imports System.Threading Imports System.Threading.Tasks Mod

晚上好。我尝试使用一个简单的延迟来实现混响效果,但是代码不会继续执行,尽管使用了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

结束模块

深入到
System.Speech.dll
中,它似乎将speak操作排队。因此,即使演讲以异步方式开始,一次也只能播放一个

这是我进入反编译程序集之前所做的工作,我认为这是必须进行的:

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

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

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

混响效应是一种回声效应,其中快波在短延迟内合并在一起。因此,要产生混响效果,可以产生两个或多个相同的声音,每个声音之间都有延迟。

Reverb()
方法将调用两次
OutSpeech()
,设置一个精确的延迟(100ms似乎可以得到结果)。

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

顺便说一句,在您的问题中,您引用的是
MicrosoftSpeech
,但您的代码使用的是
System.Speech
。这是两个不同的程序集,您应该对此更加具体。您不能使用
块将
SpeechSynthesizer
放在
中,因为它在声音播放之前就被处理掉了。@Crowcoder您错过了
等待任务。运行(Sub(),而(…)
我说的是“您也可以…SpeechHolder.Dispose()不再需要了”编辑。也许我误解了,但如果我误解了,那么OP也可能。@Crowcoder你的意思是我应该更明确地描述为什么不再需要了?我没有尝试你的代码,我只是在谈论我的代码。我现在明白了你的意思,你是如何在
时使用合成器的状态的。
。如果你不仔细阅读(像我一样)然后,您可以使用
示例误解您所说的
的意思。
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