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

Я делаю инструмент, который использует службу когнитивной речи 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) 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 ExecutionContext, обратный вызов System.Threading.ContextCallback, состояние объекта, bool saveSyncCtx) mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext mscorlib.dll!System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task cur rentTaskSlot) mscorlib.dll!System.Threading.Tasks.Task.ExecuteEntry(bool bPreventDoubleExecution) mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch()


person John Guo    schedule 21.06.2019    source источник
comment
Дикое предположение, но пробовали ли вы присвоить txtSpeech.Text переменной, прежде чем использовать ее в операторе if и передать эту переменную в тест if и асинхронный вызов?   -  person Joshua Drake    schedule 25.06.2019
comment
Пробовал, то же исключение   -  person John Guo    schedule 26.06.2019


Ответы (1)


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

person John Guo    schedule 28.06.2019