android - 使用 OpenSL 播放生成声音

标签 android android-ndk opensl

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

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

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

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

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

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

最佳答案

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

// 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 应用程序来执行此操作后,我写了一篇小文章,更详细地解释了上述建议,以及如何构建音乐相关应用程序的基本排序引擎,但是该页面只是基本的架构轮廓,根据您的需求,可能完全没用 > Android audio engine in OpenSL

关于android - 使用 OpenSL 播放生成声音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21184979/

相关文章:

android - 是否可以使用Android SDK或NDK重启手机?

android - 在 Android NDK 中为 AccountPicker 接收 onActivityResult

android - Android 上的 OpenSL 播放速度高于应有的速度

android - 使用 OpenSL 在 Android 中进行语音通话

java - 使用 userID 获取 Facebook 的大头像

android - 测试谷歌地图

java - 如何创建通用方法来容纳任意数量的 POJO

android - 在 Android 上使用 Address Sanitizer 构建,但使用 CMake

android - OpenSL ES 改变音高

android - RecyclerView View 中的 EditText 在键盘打开时分离