使用OpenSL播放生成声音

时间:2014-01-17 11:35:40

标签: android android-ndk opensl

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

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

现在我已经阅读了很多关于此的教程和博客文章,最后使用带有Android Simple Buffer Queue的OpenSL Engine进行了自己的实现。

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

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

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

1 个答案:

答案 0 :(得分:3)

关于延迟:为设备选择正确的采样率和缓冲区大小非常重要。您可以使用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