我一直在钻研 Android AudioTrack 以对抗我更好的兴趣。我正在尝试在两个 AudioTrack 的播放之间无缝过渡,即一个应该暂停,另一个应该开始,两者之间应该没有间隙。
这没问题,但我注意到当在 AudioTrack 上调用 .pause() 方法时,它会在停止播放声音时“爆裂”或“噼啪”。这并不奇怪,因为以这种方式突然停止播放声音(尤其是在高点时)势必会产生这些类型的伪影。
但是,如果我可以在调用 pause 时淡出 AudioTrack 的播放,这将不是问题。然而,这说起来容易做起来难,因为 Android AudioTracks 似乎无法就地修改。我也不能使用 .setVolume() 因为我的目标是 API 17 作为我的最低要求,所以 Android 4.0 用户仍然可以使用我的应用程序。
有没有办法做到这一点?我的直接想法是创建一个新的 pause(AudioTrack at) 方法,该方法将修改 AudioTrack 缓冲区并使其快速淡出,然后在它淡出后调用 pause。如果暂停发生晚了几帧,这对我来说并不是什么大不了的事,如果这意味着爆音将消失。不幸的是,我没有看到一个简单的方法来做到这一点。
这是我到目前为止所拥有的:
if(event.getAction() == MotionEvent.ACTION_DOWN) {
audioTracks[noteToPlay].release();
audioTracks[noteToPlay] = new AudioTrack(AudioManager.STREAM_MUSIC,
sr, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, BUFFSIZE,
AudioTrack.MODE_STATIC);
writeSample(noteToPlay);
audioTracks[noteToPlay].play();
}
else if (event.getAction() == MotionEvent.ACTION_UP) {
short[] release = makeReleaseSample(noteToPlay);
AudioTrack releaseTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
sr, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, BUFFSIZE,
AudioTrack.MODE_STATIC);
releaseTrack.write(release, 0, release.length);
audioTracks[noteToPlay].pause();
releaseTrack.play();
}
如您所见,在 ACTION_UP 处理程序中,我暂停了audioTracks[noteToPlay]轨道,然后立即播放发布轨道。暂停时会出现爆音,因为 audioTracks[noteToPlay] 包含正弦波,并且暂停不会在低点暂停,因此会产生伪影。
需要注意的是,audioTrack 的最后一帧和 release 的第一帧包含相同的帧,所以我知道这不是从第一个 audioTrack 中的点跳转到第二个中的点的情况——我相当确定是由于第一个 audioTrack 的突然中断。
有任何想法吗?