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];

在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秒钟,这就是音频剪辑的长度,而且我不相信传输时间会完全相同。我想生成更多要播放的数据(也许以其他频率播放),同时仍在播放先前的数据。我知道有些开发人员使用多个线程(而且我没有线程处理经验,所以我不知道该怎么做),但是文档表明也可以通过这种方式...

最佳答案

调用AudioTrack.write(...)会阻止,直到将所有提供的数据复制到AudioTrack的流缓冲区中为止。 AudioTrack缓冲区的大小(上面的mBufferSize)设置为AudioTrack.getMinBufferSize(...),因此显然很小,可以肯定只需要一秒钟的音频。

您想要排队的5秒钟音频数据显然无法容纳如此小的缓冲区。因此,AudioTrack.write(...)必须重复填充该缓冲区,因为缓冲区正在被播放耗尽。在返回之前,它必须使音频数据的最后一部分入队。并且在它可以执行之前,它必须至少等待,直到播放了除音频数据的最后mBufferSize以外的所有内容。

如果您增加mBufferSize的数量,您应该开始看到AudioTrack.write call 阻塞的时间减少了。

关于android - 播放整个缓冲区后,Android AudioTrack.write()返回,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39741926/

10-13 00:47