将NAudio与SpeechSynthesizer结合使用

本文关键字:结合 SpeechSynthesizer NAudio | 更新日期: 2023-09-27 18:00:39

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

我不明白为什么,我尝试了RAW波形数据和带标题的波形,请参阅以下示例。。。

示例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();
  }

示例2-这也可以,但仍然使用文件

  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标头,以避免设置波形格式。

    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-与示例3结果相同

这使用了原始数据,而且有点庞大。

  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,但情况更糟。

将NAudio与SpeechSynthesizer结合使用

您只需了解示例3。在重新定位到起点之前,调用内存流上的Flush。此外,Play只开始播放,因此您需要等待播放完成,或者将WaveOut实例移动到using块之外。否则,它只会在播放之前被收集垃圾。

如果可以的话(对于解决方案3),这段代码对我很有用。

        IWaveProvider provider = null;
        var stream = new MemoryStream();
        using (var synth = new SpeechSynthesizer())
        {
            synth.SetOutputToAudioStream(stream,
                new SpeechAudioFormatInfo(44100, AudioBitsPerSample.Sixteen, AudioChannel.Mono));
            synth.Speak("This is sample text-to-speech output.");
            stream.Seek(0, SeekOrigin.Begin);
            provider = new RawSourceWaveStream(stream, new WaveFormat(44100, 16, 1));
        }
        var waveOut = new WaveOut();
        waveOut.Init(provider);
        waveOut.Play();