我正在尝试获取 .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;
}
}
低通滤波器尚未应用,但问题仍然存在,以防有人提供一个好的答案和/或更好的方法:)