Где находится номер потока в информации о событии для System.Speech.Synthesis? - PullRequest
6 голосов
/ 02 апреля 2019

Можно разрешить SpeechSynthesizer произносить текст асинхронно, например, так:

Private WithEvents _Synth As New SpeechSynthesizer

Private Sub TextBox1_KeyUp(sender As Object, e As KeyEventArgs) Handles TextBox1.KeyUp
    If e.KeyCode = Keys.Enter Then
        _Synth.SpeakAsync(New Prompt(Me.TextBox1.Text))
    End If
End Sub

События, которые генерирует SpeechSynthesizer, позволяют нам определить, что компьютерный голос только говорит.

Например, вы можете визуализировать речевой вывод, выбрав следующие символы:

Private Sub _Synth_SpeakProgress(sender As Object, e As SpeakProgressEventArgs) Handles _Synth.SpeakProgress

    Me.TextBox1.SelectionStart = e.CharacterPosition
    Me.TextBox1.SelectionLength = e.CharacterCount

End Sub

Однако, когда SpeakAsync вызывается повторно (например, когда мы говорим SpeechSyntesizer говоритьтот же текст, в то время как он в настоящее время просто говорит), речевые запросы ставятся в очередь, и SpeechSynthesizer воспроизводит их один за другим.

Однако я не смог выяснить, какой запрос синтезатор в настоящее времяГоворящий.SpeakProgressEventArgs не раскрывать это :

Используя SAPI5, события предоставили StreamNumber:

Parameters
StreamNumber
    The stream number which generated the event. When a voice enqueues more than one stream by speaking asynchronously, the stream number is necessary to associate an event with the appropriate stream.

Используя этот StreamNumber, вы всегда можете сказать, что SpeechSynthesizer просто воспроизводит / говорит.

Реализация System.Speech.Synthesis является современной версией реализации SAPI5.

ОднакоЯ просто не нахожу индикатор StreamNumber или подобную информацию.

System.Speech.Synthesis предоставляет информацию обо всем, что только что происходит, поэтому весьма маловероятно, что он не предоставит информацию о том, какой иззапросы это просто обработка.

Как это можно получить?

Ответы [ 2 ]

1 голос
/ 12 апреля 2019

Чтобы уточнить мой комментарий об использовании класса подсказок для хранения любого необходимого идентифицирующего состояния, рассмотрите следующее, где Prompt содержит ссылку на источник TextBox.

Imports System.Speech.Synthesis
Public Class MyPrompt : Inherits Prompt
    Private tbRef As WeakReference(Of TextBox)

    Public Sub New(textBox As TextBox)
        MyBase.New(textBox.Text)
        ' only hold a weak reference to the TextBox
        ' to avoid any disposal issues
        tbRef = New WeakReference(Of TextBox)(textBox)
    End Sub

    Public ReadOnly Property SourceTextBox As TextBox
        Get
            Dim ret As TextBox = Nothing
            tbRef.TryGetTarget(ret)
            Return ret
        End Get
    End Property
End Class

Теперь ваш исходный код можно записать в виде:

Imports System.Speech.Synthesis

Public Class Form1
    Private WithEvents _Synth As New SpeechSynthesizer

    Private Sub TextBox1_KeyUp(sender As Object, e As KeyEventArgs) Handles TextBox1.KeyUp
        If e.KeyCode = Keys.Enter Then
            ' use a custom prompt to store the TextBox
            _Synth.SpeakAsync(New MyPrompt(Me.TextBox1))
        End If
    End Sub

    Private Sub _Synth_SpeakProgress(sender As Object, e As SpeakProgressEventArgs) Handles _Synth.SpeakProgress
        Dim mp As MyPrompt = TryCast(e.Prompt, MyPrompt)
        If mp IsNot Nothing Then
            Dim tb As TextBox = mp.SourceTextBox
            If tb IsNot Nothing Then
                ' set the selection in the source TextBox
                tb.SelectionStart = e.CharacterPosition
                tb.SelectionLength = e.CharacterCount
            End If
        End If
    End Sub

End Class

Редактировать:

ОП хочет использовать это с SpeakSsmlAsync методом .Само по себе это невозможно, поскольку этот метод создает базу Prompt с помощью конструктора Prompt (String, SynthesisTextFormat) и возвращает созданный Prompt после вызова SpeechSynthesizer.SpeakAsync(created_prompt).

ниже.является производным классом Prompt, который принимает либо строку ssml, либо экземпляр PromptBuilder вместе с целочисленным идентификатором.Новая версия MyPrompt для использования ssml и целочисленного идентификатора.

Imports System.Speech.Synthesis

Public Class MyPromptV2 : Inherits Prompt
    Public Sub New(ssml As String, identifier As Int32)
        MyBase.New(ssml, SynthesisTextFormat.Ssml)
        Me.Identifier = identifier
    End Sub

    Public Sub New(builder As PromptBuilder, identifier As Int32)
        MyBase.New(builder)
        Me.Identifier = identifier
    End Sub

    Public ReadOnly Property Identifier As Int32
End Class

...

Imports System.Speech.Synthesis

Public Class Form1
    Private WithEvents _Synth As New SpeechSynthesizer

    Private Sub TextBox1_KeyUp(sender As Object, e As KeyEventArgs) Handles TextBox1.KeyUp
        If e.KeyCode = Keys.Enter Then
            ' build some ssml from the text
            Dim pb As New PromptBuilder
            pb.AppendText(TextBox1.Text)
            ' use ssml and and integer
            _Synth.SpeakAsync(New MyPrompt(pb.ToXml, 10))
            ' or 
            '_Synth.SpeakAsync(New MyPrompt(pb, 10))
        End If
    End Sub

    Private Sub _Synth_SpeakProgress(sender As Object, e As SpeakProgressEventArgs) Handles _Synth.SpeakProgress
        Dim mp As MyPromptV2 = TryCast(e.Prompt, MyPromptV2)
        If mp IsNot Nothing Then
            Select Case mp.Identifier
                Case 10
                    TextBox1.SelectionStart = e.CharacterPosition
                    TextBox1.SelectionLength = e.CharacterCount
            End Select
        End If
    End Sub
End Class
0 голосов
/ 11 апреля 2019

Есть еще один способ узнать, какое предложение в настоящее время обрабатывается. Вы можете назначить номера выбора вашим предложениям, а затем распознать речь, получив индекс этого предложения; которые вы можете в дальнейшем обрабатывать условия. Используйте SpeechRecognizedEventArgs аргумент метода SpeechRecognized для получения индекса предложения.

void sre_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
  string txt = e.Result.Text;
  int sentenceIndex = txt.IndexOf("My Sentence");

  if (sentenceIndex >= 0)
  {
    Console.WriteLine("Currently Speaking Sentence: My Sentence, with index number: " 
                 + sentenceIndex);
  }

  //.... some code here
}

Следуйте полному примеру здесь .


Редактировать 1:

Объект class-scope SpeechSynthesizer дает приложению возможность говорить. Объект SpeechRecognitionEngine позволяет приложению прослушивать и распознавать произнесенные слова или фразы.

...