关于Thread.sleep()不可靠的答案是正确的:你不能指望它完全返回你指定的时间.事实上,我很惊讶你的节拍器可以使用,特别是当你的系统负载不足时.阅读Thread.sleep()的文档以获取更多详细信息.关于MIDI的Max Beikirch的答案是一个很好的建议:MIDI处理时机非常好.
但你问如何用音频做到这一点.诀窍是打开音频流并在节拍器点击之间填充静音,并将节拍器点击插入所需的位置.当您这样做时,您的声卡以恒定速率播放样本(无论它们是否包含咔嗒声或静音).这里的关键是保持音频流打开,永不关闭它.那么,时钟是音频硬件,而不是你的系统时钟 – 一个微妙但重要的区别.
因此,假设您正在以44100 Hz生成16位单声道样本.这是一个以所需速率创建咔嗒声的功能.请记住,这种咔嗒声对扬声器(和你的耳朵)来说是不好的,所以如果你真的使用它,请以低音量播放. (此外,此代码未经测试 – 只是为了演示这个概念)
int interval = 44100; // 1 beat per second, by default
int count = 0;
void setBPM( float bpm ) {
interval = ( bpm / 60 ) * 44100 ;
}
void generateMetronomeSamples( short[] s ) {
for( int i=0; i
s = 0;
++count;
if( count == 0 ) {
s = Short.MAX_VALUE;
}
if( count == interval ) {
count = 0;
}
}
}
使用setBPM设置速度后,可以重复调用generateMetronomeSamples()函数生成的样本,并使用JavaSound将输出流式传输到扬声器. (请参阅JSResources.org以获得一个很好的教程)
一旦你有了这个工作,你就可以用从WAV或AIFF或短音或其他任何东西获得的声音来代替刺耳的咔嗒声.