2012-03-06 76 views
0

我想寫一個迷你合成器程序。本質上,每發射一個定時器200mS。當它被觸發時,循環產生200ms的PCM樣本(例如鋸齒波,正弦波等),與採樣率和掃描週期有關的採樣數。例如每200mS,4000個樣本準備好在波陣列中播放。我的問題是,我該如何播放這個數組,PlaySound方法應該做什麼?每200mS調用PlaySound應連續播放後續樣本。我玩過DirectSound和NAudio都無濟於事。在C中實時播放合成聲音#

const int SAMPLE_RATE = 20000; 
    const double SCAN_PERIOD = .2; // S 
    Timer _ScanTimer = new Timer(); 


    double[] wave = new double[(int)((double)SAMPLE_RATE * SCAN_PERIOD)]; 



_ScanTimer.Tick += new EventHandler(_ScanTimer_Tick); 




    private void _ScanTimer_Tick(object sender, EventArgs e) { 
     int numSamplesPerTick = (int)((double)SAMPLE_RATE * SCAN_PERIOD); 
     double secondsPerTick = (double)2/SAMPLE_RATE; 

     for (int i = 0; i < numSamplesPerTick; i++) { 
      wave[i] = GetSynthOutput(); 
      _CurrentTime += secondsPerTick; 
      if (_CurrentTime > double.MaxValue - 1) 
       _CurrentTime = 0; 

     } 



     PlaySound(wave); 
    } 

我意識到,定時器可能不完全激發每200ms,而4000個樣本可能含有輕微過少或過多的樣本的實際時間。我並不擔心這一點,因爲我可以根據隨後的定時器啓動之間的實際時間調整樣本數。

+0

你有沒有試過System.Media.SoundPlayer?你的樣本是否在流中?什麼是確切的聲音格式? – weismat 2012-03-06 12:30:25

+0

目前他們在雙打陣列中,每個樣本一個元素,但可以放入沒有問題的memorrystream中。同時查看SoundPlayer。乾杯。 – user1240122 2012-03-06 13:46:31

回答

1

大多數音頻合成程序不是在定時器上創建聲音,而是使用兩個緩衝區 - 一個正在填充而另一個正在播放。 NAudio允許您通過在ISampleProvider或IWaveProvider派生類中實現Read函數來完成此操作。只要聲卡需要更多音頻播放,就會調用此方法。如果你想,你可以設置你的緩衝區大小爲200ms。