2008-10-06 49 views
10

我正在編寫一個軟件合成器,需要以44.1 kHz採樣率實時生成帶限,別名自由波形。鋸齒波形現在可以實現,因爲我可以通過將兩個鋸齒混合在一起產生一個脈衝波,一個反相併移相。帶限波形生成

到目前爲止,我已經嘗試以下方法:

  1. 在預先計算在啓動不同的bandlimit頻率一個週期完全限帶波形採樣,然後回放兩個最接近的人混在一起。工作好吧我猜,但不覺得很優雅。需要大量的樣品或者他們之間的「差距」會被聽到。插值和混合也是CPU密集型的。

  2. 積分一串直流補償sinc脈衝獲得一個鋸齒波。聽起來很不錯,只是如果你沒有完全正確地獲得DC補償(我發現這非常棘手),則波會從零漂移。增加一點泄漏到積分器可以減少DC問題,但是你會失去低頻。

所以,我的問題是:通常的做法是什麼?任何建議的解決方案都必須在CPU方面高效,因爲它必須實時完成,對於許多聲音一次。

+0

我意識到這是一年前問過的,但對於其他任何人磕磕絆絆,我會推薦搜索友好和高度勝任的[DSP和插件開發](http://www.kvraudio.com/論壇/ viewforum.php?f = 33)論壇在[KVR](http://www.kvraudio.com/) – 2009-10-03 07:15:43

回答

4

有很多方法來處理帶限波形生成。像往常一樣,您將最終按照質量交易計算成本。

我建議你看看這個網站瀏覽:

http://www.musicdsp.org/

退房存檔!它充滿了很好的材料。我只是搜索關鍵字「bandlimited」。彈出的材料應該至少保持一週。

順便說一句 - 不知道這是你在找什麼,但幾年前我做了別名減少(例如不是真正的頻帶有限)波形生成。我只是計算了最後一個樣本位置和當前樣本位置之間的積分。對於傳統的合成器波形,如果以奇點分割積分間隔(例如鋸齒得到他的復位),則可以很容易地進行。 CPU負載很低,質量可以滿足我的需求。

我有相同的漂移問題,但在積分上應用具有非常低的截止頻率的高通消除了這種效應。無論如何,真正的模擬合成器不會進入亞赫茲區域,所以你不會錯過太多。

+0

「phase + =(sampleRate /(float TableSize)/頻率;」不編譯。 「(sampleRate /(float TableSize))/ frequency;」? – user877329 2014-07-06 17:17:15

2

這是我想出的,受到尼爾斯想法的啓發。在這裏粘貼它以防其他人使用。我簡單地用最後一個採樣的相位變化作爲內核大小(或截止值)來分析濾波鋸齒波。它工作得很好,在最高音符處有一些可聽見的別名,但對於正常使用來說聽起來很棒。

爲了減少更多的混疊,內核大小可以增加一點,使得2 * phaseChange例如聽起來不錯,儘管你失去了一些最高頻率。

另外,這裏是我在瀏覽類似主題的SP時發現的另一個很好的DSP資源:The Synthesis ToolKit in C++ (STK)。這是一個擁有很多有用的DSP工具的類庫。它甚至可以使用帶限波形發生器。他們使用的方法是整合sinc,就像我在第一篇文章中所描述的那樣(儘管我猜他們做得更好,然後我......)。

float getSaw(float phaseChange) 
{ 
    static float phase = 0.0f; 
    phase = fmod(phase + phaseChange, 1.0f); 
    return getBoxFilteredSaw(phase, phaseChange); 
} 

float getPulse(float phaseChange, float pulseWidth) 
{ 
    static float phase = 0.0f; 
    phase = fmod(phase + phaseChange, 1.0f); 
    return getBoxFilteredSaw(phase, phaseChange) - getBoxFilteredSaw(fmod(phase + pulseWidth, 1.0f), phaseChange); 
} 

float getBoxFilteredSaw(float phase, float kernelSize) 
{ 
    float a, b; 

    // Check if kernel is longer that one cycle 
    if (kernelSize >= 1.0f) { 
     return 0.0f; 
    } 

    // Remap phase and kernelSize from [0.0, 1.0] to [-1.0, 1.0] 
    kernelSize *= 2.0f; 
    phase = phase * 2.0f - 1.0f; 

    if (phase + kernelSize > 1.0f) 
    { 
     // Kernel wraps around edge of [-1.0, 1.0] 
     a = phase; 
     b = phase + kernelSize - 2.0f; 
    } 
    else 
    { 
     // Kernel fits nicely in [-1.0, 1.0] 
     a = phase; 
     b = phase + kernelSize; 
    } 

    // Integrate and divide with kernelSize 
    return (b * b - a * a)/(2.0f * kernelSize); 
} 
6

生成帶限波形的一種快速方法是使用帶限步驟(BLEPs)。您生成帶限步驟本身:

enter image description here

,並存儲在波表,然後更換了帶限一步每一個過渡,創建波形看起來像這樣的:

enter image description here

請參閱步驟Band-Limited Sound Synthesis。由於該BLEP是非因果性的(意味着它延伸到未來),爲了生成實時波形,最好使用最小相位頻帶限制步驟,稱爲MinBLEP,它具有相同的頻譜,但只延伸到了過去:

MinBLEPs採取進一步的想法和 採取一個窗口正弦,執行 最小相位重建,然後 整合的結果,並將其存儲在一個 表。現在製作一個振盪器,您只需在波形中的每個 不連續處插入一個MinBLEP。因此,對於 方波,您插入一個MinBLEP ,其中波形反轉,鋸齒 您插入一個MinBLEP,其中 值反轉,但您正常生成 斜坡。

1

來自blit的DC偏移 - 可以通過簡單的高通濾波器來降低! - 就像一個真正的模擬電路一樣,他們使用直流阻塞蓋帽!