SpeakTextAsync выдает исключение «обратный вызов был выполнен для делегата с мусором» при использовании AudioConfig и PushAudioOutputStreamCallback - PullRequest
0 голосов
/ 21 июня 2019

Я создаю инструмент, использующий службу когнитивной речи MS и Naudio для синтеза текстовой речи и воспроизведения ее на указанном аудиоустройстве. Я использую PushAudioOutputStreamCallback для записи аудиоданных, которые с лазурного на волновой провайдер Naudio. Но исключение «Обратный вызов был выполнен для делегата с сборкой мусора» выбрасывается при вызове SpeakTextAsync. Как это исправить?

Этот код вызовет исключение на await speecher.SpeakTextAsync (txtSpeech.Text)

public partial class MainWindow : Window
    {
        WaveOut device;
        BufferedWaveProvider playback;
        SpeechSynthesizer speecher;
        PushNAudio push;

        public MainWindow()
        {
            InitializeComponent();

            var fmt = new WaveFormat();
            fmt = fmt.AsStandardWaveFormat();
            playback = new BufferedWaveProvider(fmt);

            var cfg = SpeechConfig.FromSubscription("xxxxx", "xxxxx");
            var asfmt = AudioStreamFormat.GetWaveFormatPCM((uint)fmt.SampleRate, (byte)fmt.BitsPerSample, (byte)fmt.Channels);
            push = new PushNAudio(playback);
            AudioConfig acfg = AudioConfig.FromStreamOutput(push, asfmt);
            speecher = new SpeechSynthesizer (cfg, acfg);

            device = new WaveOut();
            device.DeviceNumber = 1;
            device.Init(playback);
            device.Play();
        }

        public class PushNAudio : PushAudioOutputStreamCallback
        {
            private BufferedWaveProvider _provider;
            public PushNAudio(BufferedWaveProvider provider)
            {
                _provider = provider;
            }
            public override uint Write(byte[] dataBuffer)
            {
                _provider.AddSamples(dataBuffer, 0, dataBuffer.Length);
                return (uint)dataBuffer.Length;
            }
        }

        private async void DoSpeech()
        {
            if (string.IsNullOrWhiteSpace(txtSpeech.Text))
                return;

            /*Exception*/
            var result = await speecher.SpeakTextAsync(txtSpeech.Text);
            if (result.Reason == ResultReason.Canceled)
            {
                var details = SpeechSynthesisCancellationDetails.FromResult(result);
            }

        }

        private void TxtSpeech_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                DoSpeech();
                e.Handled = true;
            }
        }

Это исключение:

Был выполнен обратный вызов делегата со сборщиком мусора типа «Microsoft.CognitiveServices.Speech.csharp! Microsoft.CognitiveServices.Speech.Internal.PushAudioStreamWriteDelegate :: Invoke». Это может вызвать сбои приложения, повреждение и потерю данных. При передаче делегатов в неуправляемый код управляемое приложение должно поддерживать их работу до тех пор, пока не будет гарантировано, что они никогда не будут вызваны.

Стек:

Microsoft.CognitiveServices.Speech.csharp.dll! Microsoft.CognitiveServices.Speech.SpeechSynthesizer.SpeakTextAsync.AnonymousMethod__1 () Microsoft.CognitiveServices.Speech.csharp.dll! Microsoft.CognitiveServices.Speech.SpeechSynthesizer.DoAsyncSynthesisAction (System.Action synthImplAction) Microsoft.CognitiveServices.Speech.csharp.dll! Microsoft.CognitiveServices.Speech.SpeechSynthesizer.SpeakTextAsync.AnonymousMethod__0 () mscorlib.dll! System.Threading.Tasks.Task.InnerInvoke () mscorlib.dll! System.Threading.Tasks.Task.Execute () mscorlib.dll! System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executeContext, System.Threading.ContextCallback обратный вызов, состояние объекта, bool preserveSyncCtx) mscorlib.dll! System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executeContext, System.Threading.ContextCallback обратный вызов, состояние объекта, bool preserveSyncCtx) mscorlib.dll! System.Threading.Tasks.Task.ExecuteWithThreadLocal (ref System.Threading.Tasks.Task currentTaskSlot) mscorlib.dll! System.Threading.Tasks.Task.ExecuteEntry (bool bPreventDoubleExecution) mscorlib.dll! System.Threading.ThreadPoolWorkQueue.Dispatch ()

1 Ответ

0 голосов
/ 28 июня 2019

После нескольких попыток я обнаружил, что эти коды могут хорошо работать, когда целевое ядро ​​.net. Я думаю, что, возможно, Microsoft.CognitiveServices.Speech не были полностью протестированы в рамках .net Framework.

...