2014-10-30 166 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控制率。

回到三角形例如,这将是这样的:

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