3

我正在尝试获取 .NET SpeechSynthesizer 的波形输出,以使声音听起来像机器人。

经过一番研究,我发现环形调制可能是获得我想要的效果的好选择。我已经看到公式基本上是Result(t) = Voice(t) * SineWave(t).

虽然,我不知道如何从 Wave Stream 应用这种效果,但是否有任何库:

  • 生成正弦波并将其处理成 Wave Stream
  • 将两个 Stream 相乘以获得结果

如果没有,你知道还有其他选择吗?也许我可以将 Voice Wave Stream 中的每个样本乘以正弦波中的每个样本?

我正在使用 C# /.net 框架。

谢谢 !

编辑:好的,经过几个小时的失败尝试,我终于想出了似乎是好的结果。唯一的问题是输出上有很多噼啪声,我发现的唯一解决方法是应用低通滤波器。

这是我到目前为止所得到的(快速、肮脏和未注释的代码,但应该是不言自明的):

class Mixer
{
    public static Stream RingModulation(Stream voiceStream, TimeSpan duration, SpeechAudioFormatInfo format)
    {
        var sineWave = SineOscillator.GenerateWave(duration, 80, 1, format);
        var numSamples = Convert.ToInt32(duration.TotalSeconds * format.SamplesPerSecond);
        var dataStream = new MemoryStream();

        sineWave.Position = 0;
        voiceStream.Position = 0;

        var buf1 = new byte[2];
        var buf2 = new byte[2];
        for (var i = 0; i < numSamples; i++)
        {
            voiceStream.Read(buf1, 0, 2);
            sineWave.Read(buf2, 0, 2);

            var data = BitConverter.GetBytes(Convert.ToInt16(BitConverter.ToInt16(buf1, 0) * BitConverter.ToInt16(buf2, 0)));
            dataStream.Write(data, 0, data.Length);
        }

        return dataStream;
    }
}

class SineOscillator
{
    public static Stream GenerateWave(TimeSpan duration, double frequency, int amplitude, SpeechAudioFormatInfo format)
    {
        var numSamples = Convert.ToInt32(duration.TotalSeconds * format.SamplesPerSecond);
        var dataStream = new MemoryStream();
        var angle = (Math.PI * 2 * frequency) / (format.SamplesPerSecond * format.ChannelCount);

        for (var i = 0; i < numSamples; i++)
        {
            var data = BitConverter.GetBytes(Convert.ToInt16(amplitude * Math.Sin(angle*i)));
            // Generate a sine wave in both channels.
            dataStream.Write(data, 0, data.Length);
        }

        return dataStream;
    }
} 

低通滤波器尚未应用,但问题仍然存在,以防有人提供一个好的答案和/或更好的方法:)

4

1 回答 1

0

I worked in audio processing for some time. Another way to have some "robot effect" was to repeat the same frequency for a few milliseconds instead of having a well smoothed curve.

Take the frequency values for an interval
Average the values
Write the average to your output buffer for the whole interval

There are different "robot effects" that do not sound the same, this will not sound like Optimus Prime but will unmistakably seem to be computer generated

于 2013-05-20T00:01:23.197 回答