代码:
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();
答案 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。