我正在制作一个工具,它使用MS认知语音服务和Naudio来合成文本语音并在指定的音频设备上播放。我使用PushAudioOutputStreamCallback将音频数据从天蓝色写入Naudio的wave提供程序。但是,调用SpeakTextAsync时会引发异常“对垃圾收集的委托进行了回调” 。如何解决?
此代码将在 等待演讲者时抛出异常。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回调,对象状态,布尔类型saveSyncCtx) mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContextexecutionContext,System.Threading.ContextCallback回调,对象状态,bool keepSyncCtx) mscorlib.dll!System.Threading.Tasks.Task.ExecuteWithThreadLocal(参考System.Threading.Tasks.Task currentTaskSlot) mscorlib.dll!System.Threading.Tasks.Task.ExecuteEntry(bool bPreventDoubleExecution) mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch()
答案 0 :(得分:0)
经过多次尝试,我发现这些代码在目标.net核心时可以正常工作。我认为Microsoft.CognitiveServices.Speech可能尚未在.net框架下经过全面测试。