如何在静态模式下使用 AudioTrack

问题描述

我想在 Android 上播放浮点数组。我想先走(我认为是)简单的方法,所以我想我会使用 AudioTrack。我选择使用静态模式是因为音频流不是连续的。在文档中它说:

在静态缓冲模式下,将数据复制到偏移量0开始的缓冲中,写入模式被忽略。请注意,此数据的实际播放可能会在此函数返回后发生。

所以最初我的实现看起来像:

// constructor ..
audioTrack = new AudioTrack(new AudioAttributes.Builder()
                            .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
                            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build(),new AudioFormat.Builder()
                            .setEncoding(AudioFormat.ENCODING_PCM_FLOAT)
                            .setSampleRate(sample_rate)
                            .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO).build(),sample_rate * 2 * 10,AudioTrack.MODE_STATIC,AudioManager.AUdio_SESSION_ID_GENERATE);
[...]
public ... () { // function
    audioTrack.write(sound,sound.length,AudioTrack.WRITE_NON_BLOCKING);
    audioTrack.play()

这导致了一个声音只能播放一次的第一个问题。我found 我需要在stop() 之后调用reloadStaticData()play()。但这会导致根本没有播放第一个声音。以及任何以下声音播放错误(意味着声音错误)。

我尝试将 stop()reloadStaticData() 放在 write() 之后和 play() 之前,然后播放第一个声音但接下来的声音是错误的(它们是一个剪辑关闭版本的第一个声音而不是不同的声音)。

根据这些经验,在我看来 write() 实际上并未写入缓冲区的开头。一般来说,我完全不清楚如何使用 AudioTrackstop() 似乎停止播放。但是我必须在 play() 之后调用它来重置播放头位置。

解决方法

原来我的手机扬声器无法播放声音......这是我的解决方案

public void play_sound(float[] sound) {
        if (audioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) {
            audioTrack.stop();
            audioTrack.reloadStaticData();
        }

        float[] buffer = new float[buffer_size_in_bytes / 4];
        for (int i = 0; i < sound.length; i++) {
            buffer[i] = sound[i];
        }
        // Last arg is ignored.
        audioTrack.write(buffer,buffer.length,AudioTrack.WRITE_BLOCKING);
        audioTrack.play();
    }

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...