AudioTrack有时不会在点击按钮时播放样本

时间:2016-02-22 06:16:40

标签: android audiotrack

我的Android操作系统是Android M. Nexus 6。 我将AndroidSpeakerWriter实现为

public class AndroidSpeakerWriter {

    private final static String TAG= "AndroidSpeakerWriter";

    private AudioTrack audioTrack;

    short[] buffer;

    public AndroidSpeakerWriter() {
        buffer = new short[1024];
    }


    public void init(int sampleRateInHZ){
        int minBufferSize = AudioTrack.getMinBufferSize(sampleRateInHZ,
            AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
        audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRateInHZ,
            AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize,
            AudioTrack.MODE_STREAM); // 0-static 1-stream
    }   

    public void fillBuffer(short[] samples) {
        if (buffer.length<samples.length) {
            buffer = new short[samples.length];
        }
        System.arraycopy(samples, 0, buffer, 0, samples.length);
    }

    public void writeSamples(short[] samples) {
        fillBuffer(samples);
        audioTrack.write(buffer, 0, samples.length);
    }

    public void stop() {
        audioTrack.stop();
    }

    public void play() {
        audioTrack.play();
     }
}

然后我点击按钮时发送样本

public void play(final short[] signal) {
    if (signal == null){
        Log.d(TAG, "play: a null signal");
        return;
    }
    Thread t = new Thread(new Runnable() {
        @Override
        public void run() {
            android.os.Process
                    .setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
            androidSpeakerWriter.play();
            androidSpeakerWriter.writeSamples(signal);
            androidSpeakerWriter.stop();
        }
    });
    t.start();
}

问题是每次单击按钮时设备都不会发出蜂鸣声。 有时候它有效,有时则不然。 当我在旧的nexus galaxy手机安卓4.3上运行时没有这样的问题。有人遇到过类似的问题吗?提前感谢您的帮助。

有一点是,目前我的嘟嘟声非常短(256个样本),甚至不接近minBufferSize

静态模式的bufferSizeInBytes构造函数中的AudioTrack应该是您根据模糊document想要播放的音频样本长度。 那么即使对于静态模式,它仍然对缓冲区有最小的大小约束吗?为什么nexus galaxy可以在静态模式下播放256个样本音频而nexus 6不能播放。

我使用AudioManager来获取本机缓冲区大小/采样率 nexus galaxy:144/44100 nexus 6:192/48000

我找到了那些相关的:

1 个答案:

答案 0 :(得分:0)

我认为这是由线程之间的不正确同步引起的。您的androidSpeakerWriter实例分别在不同的线程调用play()writeSamples()stop()中不断运行。单击按钮将触发创建具有相同androidSpeakerWriter实例的新线程。

因此,当线程A正在执行androidSpeakerWriter.play()时,线程B可能正在执行androidSpeakerWriter.writeSamples(),这可能会覆盖正在播放的当前音频数据。

尝试

synchronized(androidSpeakerWriter) {
        androidSpeakerWriter.play();
        androidSpeakerWriter.writeSamples(signal);
        androidSpeakerWriter.stop();
}
如果您必须播放不适合内存的长音频数据,则使用

MODE_STREAM。如果您需要播放短音频文件,如哔声,则可以在创建AudioTrack时使用MODE_STATIC。然后更改播放代码,如下所示:

synchronized(androidSpeakerWriter) {
        androidSpeakerWriter.writeSamples(signal);
        androidSpeakerWriter.play();
}