Android AudioTrack.write()在播放整个缓冲区后返回

Android AudioTrack.write()在播放整个缓冲区后返回,android,audio,audiotrack,Android,Audio,Audiotrack,AudioTrack.write()。Android文档中说 在流模式下,写入操作通常会阻塞,直到所有数据排队等待播放,并返回完整的传输计数 然而,在我的代码中,write()方法似乎要等到整个缓冲区播放完毕,直到扬声器发出声音。因此,例如,事后调用stop()方法或填充更多数据是不可能的 音频曲目由以下内容初始化: int mBufferSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_MONO,

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();
for(int i=0;i
单击按钮时,这称为:

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));
}
private void playSound(双频,整数持续时间){
int-idx=0;
对于(int i=0;i波长-1)
idx=idx%波长;
mBuffer[i]=(短)(波形[idx]*短。最大_值);
}
long startTime=System.currentTimeMillis();
ret=mAudioTrack.write(mBuffer,0,mBuffer.length);
long runtime=System.currentTimeMillis()-startTime;
setText(Long.toString(运行时));
}

时间戳显示write()调用正好需要5秒,这是音频片段的长度,我不相信传输时间会完全相同。我希望生成更多的数据来播放(可能使用另一个频率),而之前的数据仍在播放。我知道一些开发人员使用多线程(我没有线程方面的经验,所以我不知道如何做),但文档表明也可以这样做…

调用
AudioTrack.write(…)
块,直到所有提供的数据都复制到AudioTrack的流缓冲区。AudioTrack缓冲区的大小(
mBufferSize
以上)设置为
AudioTrack.getMinBufferSize(…)
,因此显然很小,肯定只足以容纳一秒钟的音频

您想要排队的5秒音频数据显然无法放入如此小的缓冲区。因此,
AudioTrack.write(…)
必须重复填充该缓冲区,因为它正在被播放耗尽。在返回之前,它必须将音频数据的最后一部分排队。在它能够做到这一点之前,它必须至少等到音频数据的最后一个
mBufferSize
播放完毕


如果您将
mBufferSize
增加不同的数量,您应该开始看到
音频曲目。写入
呼叫阻塞的时间更短。

mBufferSize的值是多少?调试器说是1764。我不知道这个缓冲区的大小到底是什么。我试着把它放大,但它崩溃了。1764字节只够20ms的单声道、16位、44.1kHz音频。理解这个缓冲区是理解问题的关键。不知道坠机的事,也许那是另一个问题?(PS我假设getMinBufferSize调用中的AudioFormat.ENCODING_PCM_8BIT是一个输入错误)谢谢您的回答。你是对的。我在原始消息中添加了导致崩溃的原因。顺便问一下,你说的打字错误是什么意思?它似乎起作用了。