我正试图在Android中播放一些循环声音,而且我对我来说非常好。但是,所有美好的事物必须结束,我希望包含我的音频循环。但是,如果我在这个循环之后调用AudioTrack.release()
,就像我应该的那样,音频流的结尾会被切断 - 我知道我应该听到额外的数据,但是没有。
我通过在发布之前放入一个Thread.sleep(2000)来验证这一点 - 声音在那里正确播放。我的代码看起来像这样:
// Initialize Audiotrack
int minBufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, 2 * minBufferSize, AudioTrack.MODE_STREAM);
mAudioTrack.play();
// Play looping sound
while (stuff) {
mAudioTrack.write(stuff);
}
// Play one last bit of sound before returning
mAudioTrack.write(lastSound);
// Block until the AudioTrack has played everything we've given it
Thread.sleep(2000);
// Get rid of the Audiotrack
mAudioTrack.release();
我想我可以将Thread.sleep(2000)留在那里并称之为一天,但这对我来说听起来很混乱和不负责任。我希望在最合适的时间内使用while()
循环块,或者使用AudioTrack.setPlaybackPositionUpdateListener()
并将release()
放在那里。
如果我走第一条路线,我需要一些东西可以挂起,而AudioTrack.getPlayState()
似乎总是报道该曲目正在播放。所以我被困在那里。
如果我走第二条路线,我需要一种方法来获取最后写入的AudioTrack缓冲区中的位置,所以我可以告诉AudioTrack我正在等待它播放的位置。但是,我对如何获取这些信息没有任何想法。
我想我并不关心我这样做的方式,所以对于以某种方式解决问题的任何帮助都会非常感激。
答案 0 :(得分:1)
问题与AudioTrack中的缓冲区大小有关。
想象一下,minBufferSize
是8k。这意味着当缓冲区已满时,AudioTrack将播放声音。
mAudioTrack.write(stuff);
如果stuff
仅为4K,则AudioTrack将等到下一次调用write
,直到有足够的数据播放。
结论:您需要跟踪已写入的数据量,并在播放结束时向AudioTrack提供一些虚拟字节以完成minBufferSize
。为了让事情变得更容易,你可以提供整整minBufferSize
个静音字节。
顺便说一下,要输入虚拟或静音,只需用零填充数据。