方波频率不会平滑变化

时间:2016-02-09 01:33:45

标签: java audio javasound

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

代码:

double rate = 44100;
byte[] buffer;
AudioFormat audioFormat;

buffer = new byte[1];
audioFormat = new AudioFormat((float) rate, 8, 1, true, false);

SourceDataLine sourceDataLine = AudioSystem.getSourceDataLine(audioFormat);
sourceDataLine.open(audioFormat);
sourceDataLine.start();

int i = 0;
boolean on = false;
while (!t.isInterrupted())
{
    i++;
    if (i < rate / frequency)
    {
        i++;
    } else
    {
        i = 0;
        on = !on;
    }
    if (on)
        buffer[0] = (byte) (volume / 2);
    else
        buffer[0] = (byte) (-volume / 2);
    sourceDataLine.write(buffer, 0, 1);
}
sourceDataLine.drain();
sourceDataLine.stop();
sourceDataLine.close();

2 个答案:

答案 0 :(得分:1)

这可能是因为您只使用8位样本大小。这只会给你256个声级,这不足以提供平滑的变化。使用16位样本获得64k级别。

答案 1 :(得分:0)

如果您只是改变频率

frequency=440.0;

你也隐含地改变了信号的相位。 想一想:函数sin(440x)在x = 10和sin(442x)处有不同的值。 听到这种差异是一种砰砰声。为了防止这种情况,您必须通过因子oldFrequency / newFrequency调整信号的相位(在您的情况下为'i'变量,我将其更改为'phase')。 您还需要稍微更改代码才能使其正常工作:

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。