如果你有口齿不清,请不要试着说出我的头衔。
但是,是的,最简单的方法是为更复杂的锯齿和其他波浪生成简单或奖励。
答案 0 :(得分:3)
根据我的经验,.wav file format(Wikipedia entry列出了提供文件格式的其他文档;使用您认为最好的文件格式)是最简单的广泛使用的文档格式。编写未压缩的PCM非常容易。
对于像正弦波和锯齿一样的东西,我将任务分为采样和文件制作。所以你可能有一个界面,如:
public interface IWave
{
double Sample(double time);
}
其中Sample
将被赋予大于0的时间(但可能大于1)并且应该返回介于-1和1之间的值。(您可以使用委托代替。)然后写一个文件生成器根据采样持续时间(例如“100000波”)和采样频率(例如50000 Hz)创建wav文件。
然后,这只是适当实施IWave
的情况 - 例如对于简单的正弦波返回sin(time / (2 * pi))
的版本,或对于锯齿返回(time % 1.0) * 2 - 1
的版本。为了奖励娱乐,您可以编写合成功能来加速或减慢波形,放大波形,组合其他波浪等。文件生成器当然不需要知道任何。它只需要采用单 IWave
并对其进行适当的采样,将[-1,1]范围适当地缩放到[0,255]。
答案 1 :(得分:1)
只是详细说明Jon已经说过 - 你要做的就是创建一个8位(即字节[1024])或16位缓冲区并将其填满(即对于方波,它是[255 255 255 255 0] 0 0 0 255 255 255 255 0 0 0 0])。
答案 2 :(得分:1)
有关如何在C#中生成正弦波的示例代码,请查看this question。将其扩展到方波或锯齿波将非常容易。您可以通过将简单波形混合在一起来生成更复杂的波形。
如果需要,您还可以使用NAudio WaveFileWriter
类将生成的数据写入WAV文件。
答案 3 :(得分:0)
有一篇Charles Petzold的文章Simple Electronic Music Sequencer for Silverlight基于Gilles Khouzam的博客文章Playing back Wave files in Silverlight和Pete Brown的Creating Sound using MediaStreamSource in Silverlight 3 Beta。 Mike Hodnick有一篇有用的博客文章,其中包含基于Petzold文章Digital Audio Synthesis on Windows Phone 7的示例代码。
在主窗口的XAML中,Mike介绍了一个媒体元素
<MediaElement x:Name="media"/>
然后使用SetSource
方法将媒体元素源设置为他正在构建的wave
this.media.SetSource(new TonesSource());
this.media.Play();
迈克ToneSource
将他的BaseSource
子类化,后者依次为MediaStreamSource
子类并覆盖其中的几个方法:OpenMediaAsync
,GetSampleAsync
,SeekAsync
, CloseMedia
,GetDiagnosticAsync
和SwitchMediaStreamAsync
。 the MSDN documentation中有更多关于它们的内容;迈克的代码本身并不长,但涉及到位移和写入内存流,值得在the source provided in Mike's blog post中查看。
ToneSource
班级提供立体声样本
protected override StereoSample GetSample()
{
short left = 0;
short right = 0;
foreach (var oscillator in this.leftOscillators)
left += oscillator.GetNextSample();
foreach (var oscillator in this.rightOscillators)
right += oscillator.GetNextSample();
return new StereoSample() { Left = left, Right = right };
}
使用他的Oscillator
类
public short GetNextSample()
{
ushort wholePhaseAngle = (ushort)(phaseAngle >> 16);
short amplitude = 0;
amplitude = (short)(short.MaxValue * Math.Sin(2 * Math.PI * wholePhaseAngle / ushort.MaxValue));
amplitude = (short)((amplitude * multiplier) >> 16);
phaseAngle += phaseAngleIncrement;
return amplitude;
}
迈克提供的NoiseSource
甚至比ToneSource
protected override StereoSample GetSample()
{
return new StereoSample()
{
Left = (short)random.Next(short.MinValue, short.MaxValue),
Right = (short)random.Next(short.MinValue, short.MaxValue)
};
}