C# 将NAudio与语音合成器结合使用

C# 将NAudio与语音合成器结合使用,c#,text-to-speech,naudio,C#,Text To Speech,Naudio,我想将NAudio与SpeechSynthesizer结合使用,但如果不先将.wav文件写入磁盘,我就无法工作 我不明白为什么,我尝试了原始wav数据和带有标题的wav,请参见以下示例 我有以下例子: 示例1-这可以工作,但会保存一个.wav文件 using (var synth = new SpeechSynthesizer()) { synth.SetOutputToWaveFile(@".\Test.wav"); synth.Speak("This is sampl

我想将NAudio与SpeechSynthesizer结合使用,但如果不先将.wav文件写入磁盘,我就无法工作

我不明白为什么,我尝试了原始wav数据和带有标题的wav,请参见以下示例

我有以下例子:

示例1-这可以工作,但会保存一个.wav文件

  using (var synth = new SpeechSynthesizer())
  {
    synth.SetOutputToWaveFile(@".\Test.wav");
    synth.Speak("This is sample text-to-speech output.");
    synth.SetOutputToNull();

    var reader = new WaveFileReader(@".\Test.wav");
    var waveOut = new WaveOut();
    waveOut.Init(reader);
    waveOut.Play();
  }
  using (var synth = new SpeechSynthesizer())
  using (var stream = new MemoryStream())
  {
    synth.SetOutputToWaveStream(stream);
    synth.Speak("This is sample text-to-speech output.");

    using (var fileStream = File.Create(@".\Test.wav"))
    {
      stream.Seek(0, SeekOrigin.Begin);
      stream.CopyTo(fileStream);
    }

    var reader = new WaveFileReader(@".\Test.wav");
    var waveOut = new WaveOut();
    waveOut.Init(reader);
    waveOut.Play();
  }
示例2-这也可以,但仍然使用文件

  using (var synth = new SpeechSynthesizer())
  {
    synth.SetOutputToWaveFile(@".\Test.wav");
    synth.Speak("This is sample text-to-speech output.");
    synth.SetOutputToNull();

    var reader = new WaveFileReader(@".\Test.wav");
    var waveOut = new WaveOut();
    waveOut.Init(reader);
    waveOut.Play();
  }
  using (var synth = new SpeechSynthesizer())
  using (var stream = new MemoryStream())
  {
    synth.SetOutputToWaveStream(stream);
    synth.Speak("This is sample text-to-speech output.");

    using (var fileStream = File.Create(@".\Test.wav"))
    {
      stream.Seek(0, SeekOrigin.Begin);
      stream.CopyTo(fileStream);
    }

    var reader = new WaveFileReader(@".\Test.wav");
    var waveOut = new WaveOut();
    waveOut.Init(reader);
    waveOut.Play();
  }
示例3-这不起作用,它只播放一小部分秒并停止

我之所以使用SetOutputToWaveStream来保留RIFF头,是为了避免设置wave格式

    using (var synth = new SpeechSynthesizer())
    using (var stream = new MemoryStream())
    {
      synth.SetOutputToWaveStream(stream);
      synth.Speak("This is sample text-to-speech output.");

      stream.Seek(0, SeekOrigin.Begin);
      var reader = new WaveFileReader(stream);
      var waveOut = new WaveOut();
      waveOut.Init(reader);
      waveOut.Play();
    }
示例4-与示例4相同的结果

这使用了原始数据,而且有点笨重

  using (var synth = new SpeechSynthesizer())
  using (var stream = new MemoryStream())
  {
    synth.SetOutputToAudioStream(stream, new SpeechAudioFormatInfo(44100, AudioBitsPerSample.Sixteen, AudioChannel.Mono));
    synth.Speak("This is sample text-to-speech output.");

    stream.Seek(0, SeekOrigin.Begin);
    IWaveProvider provider = new RawSourceWaveStream(stream, new WaveFormat(44100, 16, 1));
    var waveOut = new WaveOut();
    waveOut.Init(provider);
    waveOut.Play();
  }

我也尝试过使用WasapiOut,但情况更糟。

示例3就差不多了。在重新定位到开始位置之前,对内存流调用
Flush
。另外,
Play
仅开始播放,因此您需要等待播放完成,或者使用块将
WaveOut
实例移动到
之外。否则,它会在播放到很远的地方之前将垃圾收集起来。

如果有帮助的话(对于解决方案3),这段代码适合我


谢谢你,我在这上面瞎了眼,这是因为垃圾收集。我认为内存流上的Flush()是多余的,因为它已经直接写入RAM了??。是的,也许刷新是没有必要的,它只是我自己实现中的东西,所以我想我无论如何都要提到它。我还必须将SpeechSynthesizer放在它自己的线程中,否则我仍然会有问题,只能获得一部分输出。有关更多信息,请参见此。不需要其他线程,只需等待播放完成。你过早地处置了球员。