我正在尝试编写一个 Android 应用程序,该应用程序将用作节拍器等。这需要能够定期以准确的时间播放各种声音,但现在我正在努力让一个工作。超过 2-3ms 的错误很容易被训练有素的听众检测到。这是我的播放线程:
protected void onCreate(Bundle savedInstanceState) {
// stuff
int minBufferSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
}
public void startThread(View view){
mThread = new Thread (new Runnable() {
public void run(){
Log.d(TAG, "Starting met at tempo: " + mTempo + " Interval: " + (60000 / mTempo) );
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
InputStream in = getResources().openRawResource(R.raw.chirp);
byte [] output = getBytesFromStream(in);
Log.d(TAG, "Output length: " + output.length);
mAudioTrack.play();
while (mRunning) {
mAudioTrack.write(output, 0, output.length);
try {
Thread.sleep(60000 / mTempo);
} catch (InterruptedException e) {
}
}
mAudioTrack.release();
}
});
mThread.start();
}
R.raw.chirp 是 Audacity 中生成的正弦波。1000hz 以 44100hz 采样 100ms,所以应该是 4410 个样本左右。在 Nexus 4 上进行测试,速度设置为 200bpm(即,啁啾声应该每 300 毫秒播放一次),声音似乎不错,但为了更好地衡量,我通过线路输入将输出记录到 Audacity。我注意到两个奇怪的地方:
1) 唧唧声似乎在 298-299 毫秒之间的某个时间段播放。这在很大程度上是一致的,但是 1-2 毫秒将速度更改为 201bpm,这足以让它与参考节拍器不同步。
2)第二个奇点不是始终可重复的,但是在看似随机数量的啁啾声之后,会有一个啁啾声延迟整整 20 毫秒。
第二个问题我可以想象得到解释;也许是线程/优先级问题?然而,第一个问题让我感到困惑。我想如果有什么叫声应该迟到,而不是早。我相信这些问题是相关的,而且我也开始认为我没有正确理解正在发生的事情并且正在做一些非常基本的错误(这是我第一次使用任何类型的音频代码。)
任何帮助将非常感激。