Java 方波频率不';我不能平稳地改变

Java 方波频率不';我不能平稳地改变,java,audio,javasound,Java,Audio,Javasound,我写了一个小型方波发生器。每当我试图平稳地改变频率时,声音中总会清晰地听到“脚步声”。我很确定有一个非常明显的解决方案,但我没有看到:( 代码: double rate=44100; 字节[]缓冲区; 音频格式;音频格式; 缓冲区=新字节[1]; audioFormat=新的audioFormat((浮动)速率,8,1,真,假); SourceDataLine SourceDataLine=AudioSystem.getSourceDataLine(audioFormat); sourceDat

我写了一个小型方波发生器。每当我试图平稳地改变频率时,声音中总会清晰地听到“脚步声”。我很确定有一个非常明显的解决方案,但我没有看到:(

代码:

double rate=44100;
字节[]缓冲区;
音频格式;音频格式;
缓冲区=新字节[1];
audioFormat=新的audioFormat((浮动)速率,8,1,真,假);
SourceDataLine SourceDataLine=AudioSystem.getSourceDataLine(audioFormat);
sourceDataLine.open(音频格式);
sourceDataLine.start();
int i=0;
布尔开=假;
而(!t.isInterrupted())
{
i++;
如果(i<速率/频率)
{
i++;
}否则
{
i=0;
on=!on;
}
如果(打开)
缓冲区[0]=(字节)(卷/2);
其他的
缓冲区[0]=(字节)(-volume/2);
写入(缓冲区,0,1);
}
sourceDataLine.drain();
sourceDataLine.stop();
sourceDataLine.close();

这可能是因为您仅使用8位样本大小。这仅提供256个声级,不足以进行平滑更改。使用16位样本可获得64k声级。

这可能是因为您仅使用8位样本大小。这仅提供256个声级,不足以进行平滑更改。Use 16位采样以获得64k电平。

如果您只是像这样更改频率

frequency=440.0;
你也在暗中改变信号的相位。 思考:函数sin(440x)在x=10时的值与sin(442x)不同。 这种差异是以爆裂声的形式出现的。为了防止这种情况发生,您必须通过oldFrequency/newFrequency因子来调整信号的相位(在您的例子中是“i”变量,我将其更改为下面的“相位”)。 您还需要稍微更改代码,以使其正常工作:

double phase=0;
public void setFrequency(double newFrequency){
  phase*=frequency/newFrequency;
  freqency=newFrequency;
}
public void run(){
  //...
  while(!t.isInterrupted()){
    phase++;
    if (phase > rate / frequency)  //flipped inequality sign!
    {
      phase %= rate / frequency;
      on = !on;
    }
    //...
  }
}

PS:您可能还应该增加缓冲区的大小。缓冲区也用于通过预先计算信号来保持信号平滑。如果您只是像这样更改频率,那么一个好的缓冲区大小应该是200。

frequency=440.0;
你也在暗中改变信号的相位。 思考:函数sin(440x)在x=10时的值与sin(442x)不同。 这种差异是以爆裂声的形式出现的。为了防止这种情况发生,您必须通过oldFrequency/newFrequency因子来调整信号的相位(在您的例子中是“i”变量,我将其更改为下面的“相位”)。 您还需要稍微更改代码,以使其正常工作:

double phase=0;
public void setFrequency(double newFrequency){
  phase*=frequency/newFrequency;
  freqency=newFrequency;
}
public void run(){
  //...
  while(!t.isInterrupted()){
    phase++;
    if (phase > rate / frequency)  //flipped inequality sign!
    {
      phase %= rate / frequency;
      on = !on;
    }
    //...
  }
}

PS:您可能还应该增加缓冲区大小。缓冲区也用于通过提前计算信号来保持信号平滑。一个好的缓冲区大小应该是200。

Swing代码与此问题无关。请删除它。Swing代码与此问题无关。请删除它。OP是gener使用矩形函数的方波。不需要增加样本大小,因为hi和lo之间的变化是即时的,例如|⎺⎺|__|⎺⎺|__|OP产生一个矩形函数的方波。不需要增加样本量,因为hi和lo之间的变化是即时的,例如|⎺⎺|__|⎺⎺|__|