Добрый вечер. Я пытаюсь создать эффект реверберации, используя простую задержку, но код не продолжает выполняться, несмотря на использование метода SpeakAsync.

Я мог найти очень мало документации по этой проблеме где угодно, поэтому буду очень признателен за любые советы, которые вы можете дать. Спасибо за уделенное время! Я использую System.Speech версии 4.0.0 в Visual Studio 2017. Я нацелен на среду выполнения 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

Конечный модуль

1
Fedaykin 31 Дек 2017 в 06:28

2 ответа

Лучший ответ

Последовательный вызов 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() становится асинхронным, поэтому вызовы будут перекрываться при создании нового синтезатора.
Созданы две задачи. Один для установки задержки, а другой для (а) ожидания, пока синтезатор "говорит", проверяя 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
1
Jimi 12 Янв 2018 в 02:36

Если заглянуть в 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 для одновременного воспроизведения звуков или смещения во время сна.

0
Crowcoder 31 Дек 2017 в 14:37