C# Microsoft SpeechSynthesizer在输出到文件和流时发出爆裂声

C# Microsoft SpeechSynthesizer在输出到文件和流时发出爆裂声,c#,powershell,audio,text-to-speech,C#,Powershell,Audio,Text To Speech,我正在写一个东西,它使用SpeechSynthesizer根据请求生成波形文件,但我遇到了噼啪作响的问题。奇怪的是,直接输出到声卡就可以了 这个简短的powershell脚本演示了这个问题,尽管我正在用C编写程序 Add-Type -AssemblyName System.Speech $speech = New-Object System.Speech.Synthesis.SpeechSynthesizer $speech.Speak('Guybrush Threepwood, mighty

我正在写一个东西,它使用SpeechSynthesizer根据请求生成波形文件,但我遇到了噼啪作响的问题。奇怪的是,直接输出到声卡就可以了

这个简短的powershell脚本演示了这个问题,尽管我正在用C编写程序

Add-Type -AssemblyName System.Speech
$speech = New-Object System.Speech.Synthesis.SpeechSynthesizer
$speech.Speak('Guybrush Threepwood, mighty pirate!')
$speech.SetOutputToWaveFile("${PSScriptRoot}\foo.wav")
$speech.Speak('Guybrush Threepwood, mighty pirate!')
这应该做的是,输出到扬声器,然后在脚本旁边保存与foo.wav相同的声音

它所做的是输出到扬声器,然后保存一个噼啪作响的,旧的唱机声音版本作为波形文件。我在三台不同的机器上进行了测试,虽然他们默认选择了不同的声音——所有微软提供的默认声音——但它们听起来都像是wave文件中从楼梯上掉下来的垃圾

为什么?

编辑:我正在Windows10Pro上进行测试,最新的更新在任务栏上添加了“讨厌的人”按钮

编辑2:

编辑3:


编辑4:

我很难相信这是一个时髦的问题。 在磁盘的序列化上进行编码不是很时髦。它是正在使用的API/类

'msdn.microsoft.com/en-us/library/system.speech.synthesis.speechsynthezerv=vs.110.aspx'

根据MSDN,没有控制编码、比特率等的选项

.wav从来都不是总部的东西。所以,我想知道你是否可以通过转换器将.wav转换成.mp3或mp4,这样可以解决你的质量问题。但这也意味着在用户系统上安装转换器


其次,自Win8以来,默认播放器甚至不能正确或根本不能播放.wav。当然,您仍然可以将.wav的默认播放设置为Windows Media Player或通过VLC调用该文件,但它仍然是.wav文件。然而,这也意味着,您必须在每个目标系统上设置媒体播放器分配。

这是SpeechSynthesizer API的一个问题,正如上面的示例所示,它只提供了质量差、声音刺耳的音频。解决方案是像TextSoundough那样,直接使用SpeechLib COM对象

这是通过向Microsoft Speech Object Library 5.4添加COM引用来实现的。下面是我最后得到的一段代码,它生成的音频剪辑质量与TextOutloude相同:

public new static byte[] GetSound(Order o)
{
    const SpeechVoiceSpeakFlags speechFlags = SpeechVoiceSpeakFlags.SVSFlagsAsync;
    var synth = new SpVoice();
    var wave = new SpMemoryStream();
    var voices = synth.GetVoices();
    try
    {
        // synth setup
        synth.Volume = Math.Max(1, Math.Min(100, o.Volume ?? 100));
        synth.Rate = Math.Max(-10, Math.Min(10, o.Rate ?? 0));
        foreach (SpObjectToken voice in voices)
        {
            if (voice.GetAttribute("Name") == o.Voice.Name)
            {
                synth.Voice = voice;
            }
        }
        wave.Format.Type = SpeechAudioFormatType.SAFT22kHz16BitMono;
        synth.AudioOutputStream = wave;
        synth.Speak(o.Text, speechFlags);
        synth.WaitUntilDone(Timeout.Infinite);

        var waveFormat = new WaveFormat(22050, 16, 1);
        using (var ms = new MemoryStream((byte[])wave.GetData()))
        using (var reader = new RawSourceWaveStream(ms, waveFormat))
        using (var outStream = new MemoryStream())
        using (var writer = new WaveFileWriter(outStream, waveFormat))
        {
            reader.CopyTo(writer);
            return o.Mp3 ? ConvertToMp3(outStream) : outStream.GetBuffer();
        }
    }
    finally
    {
        Marshal.ReleaseComObject(voices);
        Marshal.ReleaseComObject(wave);
        Marshal.ReleaseComObject(synth);
    }
}
这是将波形文件转换为mp3的代码。它用的是nuget的NAudio,Lame

internal static byte[] ConvertToMp3(Stream wave)
{
    wave.Position = 0;
    using (var mp3 = new MemoryStream())
    using (var reader = new WaveFileReader(wave))
    using (var writer = new LameMP3FileWriter(mp3, reader.WaveFormat, 128))
    {
        reader.CopyTo(writer);
        mp3.Position = 0;
        return mp3.ToArray();
    }
}

无法复制。无论我是把结果保存在文件中还是马上播放演讲,听起来都一样。麻烦你把你的wav文件上传到什么地方好吗?我使用的那个网站非常简单,不需要注册。如果只是我的声卡或wav文件播放设置,您的wav文件应该与我的相同。或者,你听到crackle在播放我的wav吗?我想我在Thank分享了我的foo.wav文件!不过,那似乎和我的一样有裂纹。人们甚至可以在图表上看到他们,ItAudi.Io使得,在单词“海盗”的中间有两条垂直线,还有几个其他地方,尽管没有那么明显。我确信,当脚本直接输出到演讲者时,我没有听到这些。我现在甚至在第四台机器上试过,这是我最近得到的一台小型笔记本电脑——结果也是一样。我在我的问题中添加了另一个声音文件,这次是一个女声。同样,裂纹也是垂直线,所以它不应该是回放设备。这确实是一个API问题,就像在C中一样。但是,关于wave文件的质量,您是错的,并且API在您使用时确实有设置质量的选项。关于质量,wave通常用于速度较慢的计算机,由于处理能力的限制,无法将CD音频直接编码为mp3。虽然mp3会降低音质,但它并没有降低音质。我弄乱了SetOutputOutput流,在我尝试的任何尝试中,它都没有产生任何影响。因此,我先前的答复是。但你似乎比我花更多的时间在一起,所以,我不得不相信你的话。然而,我对.mp3/mp4格式在现场使用或序列化时没有任何问题。它不能做很多事情,因为每个声音本身通常是有限的。例如,来自的声音通常是22kHz,或者更准确地说是22050Hz,这意味着如果你以44.1kHz的频率采样,你所做的就是在一个文件中获得两个样本,每个样本的大小是文件的两倍。不过,如果您讨厌耳朵,您可以运行较少的示例。您是如何添加对Microsoft语音对象库的引用的?我需要在/reference中为csc指定什么?在我的Visual Studio.Net not core中,我右键单击了References=>Add reference=>COM=>Microsoft Speech Object Library version 5.4