2012-04-27 55 views
2

我想在java中製作一個可以實時操作的基本音調發生器(只需要開始練習)。你如何創建一個音調發生器,其音調可以在「實時」或在Java中實時操作?

我想從簡單開始,然後添加更復雜的音色生成和效果,最終得到某種基本合成器。

我發現a helpful post on this site在applet Beeper.java中提供了一些示例代碼。

它生成一個音並將其保存到剪輯。然後在需要時將該剪輯播放回路上。相關音代位:

/** Generates a tone, and assigns it to the Clip. */ 
public void generateTone() 
    throws LineUnavailableException { 
    if (clip!=null) { 
     clip.stop(); 
     clip.close(); 
    } else { 
     clip = AudioSystem.getClip(); 
    } 
    boolean addHarmonic = harmonic.isSelected(); 

    int intSR = ((Integer)sampleRate.getSelectedItem()).intValue(); 
    int intFPW = framesPerWavelength.getValue(); 

    float sampleRate = (float)intSR; 

    // oddly, the sound does not loop well for less than 
    // around 5 or so, wavelengths 
    int wavelengths = 20; 
    byte[] buf = new byte[2*intFPW*wavelengths]; 
    AudioFormat af = new AudioFormat(
     sampleRate, 
     8, // sample size in bits 
     2, // channels 
     true, // signed 
     false // bigendian 
     ); 

    int maxVol = 127; 
    for(int i=0; i<intFPW*wavelengths; i++){ 
     double angle = ((float)(i*2)/((float)intFPW))*(Math.PI); 
     buf[i*2]=getByteValue(angle); 
     if(addHarmonic) { 
      buf[(i*2)+1]=getByteValue(2*angle); 
     } else { 
      buf[(i*2)+1] = buf[i*2]; 
     } 
    } 

    try { 
     byte[] b = buf; 
     AudioInputStream ais = new AudioInputStream(
      new ByteArrayInputStream(b), 
      af, 
      buf.length/2); 

     clip.open(ais); 
    } catch(Exception e) { 
     e.printStackTrace(); 
    } 
} 

循環位:

/** Loops the current Clip until a commence false is passed. */ 
public void loopSound(boolean commence) { 
    if (commence) { 
     clip.setFramePosition(0); 
     clip.loop(Clip.LOOP_CONTINUOUSLY); 
    } else { 
     clip.stop(); 
    } 
} 

我試圖纏鬥,這樣我會在後臺創建另一個剪輯,並迅速改變一個爲其他時候我想改變音高但是當一個剪輯開始並且另一個停止時,當然會有明顯的點擊。

所以我猜我需要一些聰明的緩衝來做到這一點,匹配一個波與另一個無縫結束?

或者這是不可能與預生成的剪輯?如果是的話,我應該怎麼做呢?

作爲一個相關的因素,軟件合成器是如何工作的?他們是否連續產生所有聲音和效果,或者是否預先生成「剪輯」並像Beeper.java一樣循環播放?

謝謝!

回答

1

聽起來好像你想用Java中的階段累加器實現numerically controlled oscillator (NCO)

基本上,您需要計算出您想要的頻率的增量相位,然後繼續向累加器添加模2π。累加器的值用作sin()的值以生成樣本值。

如果要更改頻率,請更新增量相位。這確保了樣本的連續性(波浪中沒有突然的中斷)。我懷疑這是什麼導致你的點擊。如果你想要更好的改變,那麼你需要逐漸改變一堆樣本的增量相位。

+0

謝謝,我想我明白你在說什麼,但它真的都超出了我的頭。這是我應該使用剪輯做的事情,還是應該不斷產生音調並立即回放? – kiman 2012-04-28 17:23:15

+0

我認爲如果你不想有不連續性,剪輯可能會非常棘手。任意頻率不會有恰好對應於一個波週期的「好」數樣本。 – mpdonadio 2012-04-28 17:32:03

+0

是啊,我認爲是這樣......你不能指向我一些基本的Java代碼使用標準的API可以說明「現場」生成和正弦波的播放可以嗎?! :) – kiman 2012-04-29 02:39:36

相關問題