AudioTrack.write()。 Android文档说明
在流媒体模式下,写入通常会阻塞,直到所有数据都已排入队列进行播放,并且将返回完整的传输计数。
但是,在我的代码中,write()方法似乎要等到播放整个缓冲区,直到从扬声器开始。因此,例如,之后调用stop()方法或填充更多数据是不可能的。
录音带由以下内容初始化:
int mBufferSize = AudioTrack.getMinBufferSize(44100,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_8BIT);
AudioTrack mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100,
AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT,
mBufferSize, AudioTrack.MODE_STREAM);
int duration = 44100*5;
short[] mBuffer = new short[duration];
on onCreate:
for (int i = 0; i < wavelength; i++) {
waveform[i] = Math.sin(((double) i)/wavelength * 2 * Math.PI - Math.PI);
}
mAudioTrack.play();
点击一下按钮,这叫做:
private void playSound(double frequency, int duration) {
int idx = 0;
for (int i = 0; i < duration-1; i++) {
idx = idx + (int) Math.ceil(frequency);
if (idx > wavelength-1)
idx = idx % wavelength;
mBuffer[i] = (short) (waveform[idx] * Short.MAX_VALUE);
}
long startTime = System.currentTimeMillis();
ret = mAudioTrack.write(mBuffer, 0, mBuffer.length);
long runtime = System.currentTimeMillis() - startTime;
debugText.setText(Long.toString(runtime));
}
时间戳显示write()调用只花了5秒钟,这是音频片段的长度,我不相信传输时间会完全相同。我想生成更多要播放的数据(可能是另一个频率),而之前的数据仍然在播放。我知道有些开发人员使用多个线程(我没有线程经验,所以我不知道怎么做),但是文档表明它也可能这样......
答案 0 :(得分:1)
对AudioTrack.write(...)
的调用将阻塞,直到所有提供的数据都被复制到AudioTrack的流式缓冲区中。 AudioTrack缓冲区的大小(上面mBufferSize
)设置为AudioTrack.getMinBufferSize(...)
,因此显然很小,肯定只有一秒钟的音频。
您想要入队的5秒音频数据显然不适合这么小的缓冲区。所以AudioTrack.write(...)
必须重复填充该缓冲区,因为它正在被播放耗尽。在它返回之前,它必须将音频数据的最后部分排入队列。在它可以做到这一点之前,它必须至少等待除了最后mBufferSize
个音频数据之外的所有内容。
如果您按不同金额增加mBufferSize
,您应该开始看到AudioTrack.write
来电阻止的时间更短。