2014-10-30 167 views
1

我想用javax.sound.sampled.SourceDataLine生成純正弦波。 對於一個恆定頻率,它工作正常,但頻率改變時總會有一種卡嗒聲。 我在做什麼錯,我該怎麼做才能避免這種情況?java SourceDataLine正弦波點擊

  line.start(); 
      final byte[] toneBuffer = new byte[SAMPLE_CHUNK]; 

      while(run) { 
       createSineWaveBuffer(frequency, toneBuffer); 
       line.write(toneBuffer, 0, toneBuffer.length); 
      } 

      line.drain(); 
      line.close(); 

其中

private double alpha = 0.0; 
private static final double step_alpha = (2.0*Math.PI)/SAMPLE_RATE; 

private void createSineWaveBuffer(final double freq, final byte[] buffer) { 
    for(int i = 0; i < buffer.length; ++i) { 
     buffer[i] = (byte)(Math.sin(freq*alpha)*127.0); 
     alpha += step_alpha; 

     if(alpha >= 2.0*Math.PI) { 
      alpha = 0.0; 
     } 
    } 
} 

回答

1

您遇到的點擊,因爲當freq變化,整個正弦波移動。作爲一個具有更易於戰平三角波的例子:

1 Hz 
    /\ /\ /
/\/\/
/ \/ \/ 

.5 Hz_ 
    /\ 
/ \ /
/  \_/ 

如果您在任意時間,這些之間切換:

/\ |\ 
/\ | \ /
/ \| \_/ 

有間斷,你聽到的點擊。

這基本上是因爲你導致從sin(freq * alpha)突然跳躍到sin(.5 * freq *(alpha + step_alpha))。不僅輸入的導數sin()不連續地變化(這就是你需要改變頻率),這個值也是不連續地變化的。

解決方法是隻改變sin()的輸入導數。您可以通過保持增量基於頻率計數器做到這一點:

private void createSineWaveBuffer(final double freq, final byte[] buffer) { 

    for(int i = 0; i < buffer.length; ++i) { 
     buffer[i] = (byte)(Math.sin(alpha)*127.0); 
     alpha += freq*step_alpha; 

     if(alpha >= 2.0*Math.PI) { 
      alpha -= 2.0*Math.PI; 
     } 
    } 

    return t; 
} 

在這裏,我已經改變了你的alpha增加在當前freq控制率。

回到三角形例如,這將是這樣的:

  _ 
    /\ /\ 
/\ / \ 
/ \/   \