如果你有口齿不清,请不要试着说我的头衔。
但是,是的,什么是最简单的方法来产生简单的,或更复杂的锯齿波和其他波的奖金。
根据我的经验, .wav文件格式 ( 维基百科条目列出了提供文件格式的其他文件;使用最适合您的文件格式)是最为广泛使用的文件格式。 编写未压缩的PCM非常容易。
对于正弦波和锯齿波这样的事情,我会把这个任务分成抽样和文件制作。 所以你可能有一个接口,如:
public interface IWave { double Sample(double time); }
其中Sample
将被赋予大于0的时间(但可能大于1),并且应该返回-1和1之间的值(您可以使用委托来代替)。然后编写一个文件生成器来创建基于wav的文件样本持续时间(例如“100000波”)和采样频率(例如50000Hz)。
那么这只是适当地实施IWave
一个例子 – 例如对于一个简单的正弦波返回sin(time / (2 * pi))
的一个版本,或者对于一个锯齿波来说(time % 1.0) * 2 - 1
。 对于奖励娱乐,你可以写作文功能来加速或减速波,放大,结合其他波等。文件生成器当然不需要知道任何 。 它只需要采取一个单一的 IWave
并采样适当的次数,适当地将[-1,1]范围缩放到[0,255]。
只是要详细说明Jon已经说过的 – 你所做的只是创建一个8位(即字节[1024])或16位缓冲区并填充它(即对于方波它是[255 255 255 255 0 0 0 0 255 255 255 255 0 0 0 0])。
看看这个问题的示例代码如何在C#中生成正弦波。 将其扩展到正方形或锯齿波将非常简单。 您可以通过混合简单的波形来生成更复杂的波形。
如果需要,您也可以使用NAudio WaveFileWriter
类将生成的数据写入WAV文件。
有一个查尔斯Petzold文章简单的电子音乐序列器Silverlight基于Gilles Khouzam的博客条目在Silverlight中播放Wave文件和在Silverlight 3 Beta中使用MediaStreamSource创建声音 。 Mike Hodnick 在Windows Phone 7上基于Petzold文章“ 数字音频合成 ”( Digital Audio Synthesis)提供了一个有用的博文,文章中提供了示例代码。
在主窗口的XAML中,Mike介绍了一个媒体元素
<MediaElement x:Name="media"/>
然后使用SetSource
方法将媒体元素源设置为他正在构建的wave
this.media.SetSource(new TonesSource()); this.media.Play();
Mike的ToneSource
了他的BaseSource
,它ToneSource
了MediaStreamSource
子类并覆盖了几个方法: OpenMediaAsync
, GetSampleAsync
, SeekAsync
, CloseMedia
, GetDiagnosticAsync
和SwitchMediaStreamAsync
。 在MSDN文档中有更多关于它们的内容 。 Mike的代码本身并不长,但涉及位移和写入内存流,值得关注Mike的博客文章中提供的源代码 。
Mike的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; }
Mike所提供的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) }; }