2

我正在构建一个可以产生声音的应用程序(现在它主要是实验性的)并在 Android 手机上播放它。

现在我正在尝试播放简单的正弦波声音(440 Hz),并首先尝试使用 Audiotrack 但遇到一些缓冲区欠载。所以我决定看看 OpenSL。

现在我已经阅读了很多关于此的教程和博客文章,最后我自己实现了,使用带有 Android 简单缓冲区队列的 OpenSL 引擎。

现在在缓冲区回调中,我生成了一个新的缓冲区数据并将其添加到队列中,但是延迟比音轨差得多(我可以听到每个缓冲区之间的间隙)。

我的问题是,在 OpenSL 中生成声音的最佳实践/架构是什么?我应该在另一个线程中填充缓冲区(然后需要一些与缓冲区回调同步的过程)吗?

我还没有找到关于生成声音的 OpenSL ES 教程(大多数是关于播放音频文件或将音频输入重定向到音频输出)。

4

1 回答 1

4

关于延迟:为您的设备选择正确的采样率和缓冲区大小非常重要。您可以使用 Android SDK 的 AudioManager(仅从 API 级别 17 可用)查询设备的推荐值,并将这些值传递给 NDK 应用程序PROPERTY_OUTPUT_SAMPLE_RATEPROPERTY_OUTPUT_FRAMES_PER_BUFFER

// getting the samplerate and buffer size
if ( android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 )
{
    AudioManager am = ( AudioManager ) aContext.getSystemService( Context.AUDIO_SERVICE );
    int sampleRate = Integer.parseInt( am.getProperty( AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE ));
    int bufferSize = Integer.parseInt( am.getProperty( AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER ));
}

正确获取采样率的重要性在于,如果它不同于设备首选的采样率(一些使用 48 kHz,另一些使用 44.1 kHz),则音频在硬件输出之前路由通过系统重采样器,从而增加整体潜伏。此外,获得正确缓冲区大小的重要性是防止在几次缓冲区回调后样本/帧丢失,这可能会导致您描述的问题在回调之间发生间隙/故障。您可以使用倍数(2 的幂)来减少/增加缓冲区大小,以试验更稳定的引擎(更大的缓冲区大小)和更快的响应(更低的缓冲区大小)。

在创建了一些简单的 Android 应用程序之后,我写了一篇小文章,稍微详细地解释了上述建议以及如何构建音乐相关应用程序的基本序列引擎,但是页面只是一个基本架构大纲,根据您的需要可能完全没用 > OpenSL 中的 Android 音频引擎

于 2014-01-27T09:28:09.367 回答