2009-06-01 25 views

回答

3

以我的經驗.wav file formatWikipedia 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

只是爲了詳細說明Jon已經說過的 - 你所做的只是創建一個8位(即字節[1024])或16位緩衝區並填充它(即對於方波它是[255 255 255 255 0 0 0 0 255 255 255 255 0 0 0 0])。

1

查看this question的示例代碼,瞭解如何在C#中生成正弦波。將其擴展到正方形或鋸齒波將非常簡單。通過混合簡單的波形,可以生成更復雜的波形。

您還可以使用NAudioWaveFileWriter類,如果您需要將生成的數據寫入到一個WAV文件。

0

有基於吉爾Khouzam的博客文章Playing back Wave files in Silverlight和皮特·布朗的Creating Sound using MediaStreamSource in Silverlight 3 Beta一個查爾斯Petzold的文章Simple Electronic Music Sequencer for Silverlight。 Mike Hodnick有一篇基於Petzold文章Digital Audio Synthesis on Windows Phone 7的有用博客文章。

在主窗口麥克的XAML引入了一個媒體元素

<MediaElement x:Name="media"/> 

,然後使用SetSource方法來設置媒體元素源到波他構建

this.media.SetSource(new TonesSource()); 
this.media.Play(); 

麥克的ToneSource子類他的BaseSource又是MediaStreamSource的小類,並且覆蓋了其幾種方法:OpenMediaAsync,GetSampleAsync,SeekAsync,CloseMedia,GetDiagnosticAsyncSwitchMediaStreamAsync。關於他們更多的在the MSDN documentation; Mike的代碼本身並不長,但涉及位移和寫入內存流,值得在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) 
    }; 
} 
更簡單