2011-08-10 96 views
3

到目前爲止,我已經實現了在這個blog post上找到的算法,並取得了有限的成功。NAudio算法播放頻率可以實時平滑變化的正弦波

我的程序的概念是初始化正弦波,然後根據鼠標在屏幕上的位置改變頻率 - 向上移動鼠標並且正弦波變得更高,反之亦然(本質上是一種使用民族類型的樂器鼠標)。

到目前爲止,我所實現的問題是,當正弦波的頻率更新時,會出現可聽見的咔嗒聲,而不是提供平滑的頻率掃描,這聽起來像有離散頻率水平。 我一直在NAudio論壇上和這裏搜索高低,但似乎並沒有其他人試圖使用NAudio來做這種事情,或者對於任何其他聲音模塊 - 所有類似的程序使用類似於Kinect使用虛擬MIDI佈線和現有軟件模塊的設備執行類似的操作,但是我希望在不依賴外部軟件包的情況下實現相同的概念。

我已經在NAudio的論壇here上發佈了我的代碼相關部分,正如您所看到的,我通過MarkHeath的建議來嘗試找到解決方案。

+0

您可以發佈一個例子的音頻? – Shannon

回答

9

您需要避免輸出波形中的不連續點(這些是您聽到的點擊)。最簡單的方法是使用基於LUT的波形發生器 - 這適用於任何週期性波形(即不只是純正弦波)。通常情況下,您使用一個固定點相位累加器,該累加器通過對應於當前輸出頻率的增量值對每個新樣本遞增。不管你喜歡什麼,你都可以安全地修改增量,波形仍然是連續的。

僞代碼(一個輸出採樣):

const int LUT_SIZE; 
const int LUT[LUT_SIZE]; // waveform lookup table (typically 2^N, N >= 8) 
Fixed index; // current index into LUT (integer + fraction) 
Fixed delta; // delta controls output frequency 

output_value = LUT[(int)index]; 
    // NB: for higher quality use the fractional part of index to interpolate 
    //  between LUT[(int)index] and LUT[(int)index + 1], rather than just 
    //  truncating the index and using LUT[(int)index] only. Depends on both 
    //  LUT_SIZE and required output quality. 
index = (index + delta) % LUT_SIZE; 


注:計算 delta給定輸出頻率 f和採樣率 Fs

delta = FloatToFixed(LUT_SIZE * f/Fs); 
+0

謝謝保羅,我會試試看!你知道任何網站/教程,我可以看看如何實施它? –

+0

某些實現細節將特定於您的操作系統和音頻API,但如果Google針對「波形查找表綜合」或類似應用,則應該獲得大量點擊。 –

+0

最後一行的索引不應該是'output_index'嗎? –