Android进阶

oboe实现音频播放

2020-03-30  本文已影响0人  性感小猪

什么是oboe?


oboe是谷歌推出用于在Android上实现高性能音频应用的c++库,支持API16以上Android版本。在API27以上使用AAudio实现,27以下使用OpenSL ES实现,以提供最好的音频能力。适用于低延迟、高互动的场景,比如耳返功能、高互动游戏等。

如何使用oboe?


官方指导文档在这里,可以通过两种方式使用oboe,这里是把源码拉下来编译到项目。

1. 下载oboe库->https://github.com/google/oboe

2. 修改项目CMakeLists.txt

添加oboe源文件路径

# Set the path to the Oboe directory.
set (OBOE_DIR ***PATH TO OBOE***)

# Add the Oboe library as a subdirectory in your project.
# add_subdirectory tells CMake to look in this directory to
# compile oboe source files using oboe's CMake file.
# ./oboe specifies where the compiled binaries will be stored
add_subdirectory (${OBOE_DIR} ./oboe)

# Specify the path to the Oboe header files.
# This allows targets compiled with this CMake (application code)
# to see public Oboe headers, in order to access its API.
include_directories (${OBOE_DIR}/include)

添加oboe到target_link_libraries命令
target_link_libraries(native-lib oboe)

3. 使用oboe进行录音或者播放

成功添加oboe到项目中编译通过后,很容易就能使用oboe的api实现播放或者录音,编译遇到问题的话,可以从下载的oboe源码demo中参考CMakeLists.txt。


第一步:导入oboe头文件

#include <oboe/Oboe.h>

第二步:创建builder并设置参数
oboe::AudioStreamBuilder builder;
builder.setPerformanceMode(oboe::PerformanceMode::LowLatency)
  ->setSharingMode(oboe::SharingMode::Exclusive)
  ->setCallback(myCallback)
  ->setFormat(oboe::AudioFormat::Float);

由于每个方法返回的是builder本身,所以可以链式调用,具体的参数意义可以查询官方文档,这里指定direction为Output意味着用于播放音频。

第三步:设置回调接口

上面代码中setCallback方法设置的是AudioStreamCallback对象。在音频流请求数据时,会回调onAudioReady方法

class MyCallback : public oboe::AudioStreamCallback {
public:
    oboe::DataCallbackResult
    onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) {
        
        // We requested AudioFormat::Float so we assume we got it.
        // For production code always check what format
        // the stream has and cast to the appropriate type.
        auto *outputData = static_cast<float *>(audioData);
    
        // Generate random numbers (white noise) centered around zero.
        const float amplitude = 0.2f;
        for (int i = 0; i < numFrames; ++i){
            outputData[i] = ((float)drand48() - 0.5f) * 2 * amplitude;
        }
    
        return oboe::DataCallbackResult::Continue;
    }
};

其中,如果是播放音频,需要在audioData指向的缓冲区填充数据,如果是录音,audioData则是录音到的数据。方法返回的值决定流的操作是继续还是停止。

第四步:播放音频

在设置完各种参数以及回调之后,可以通过调用builder的openStream()方法创建音频流,然后就可以执行播放操作了
注意:获取到创建的音频流时,应该先判断一下音频流的格式是否符合需求

oboe::AudioFormat format = stream->getFormat();
LOGI("AudioStream format is %s", oboe::convertToText(format));
音频流状态切换

一般我们在开始播放的地方调用requestStart(),然后在onAudioReady()回调中处理数据,在结束播放是调用requestStop()即可,要注意的是,request*()方法是异步,音频流状态并不会立刻改变。

第五步:关闭音频流

在不再播放或录音时,请务必关闭音频流,直接调用close()方法即可。
另外,如果音频流对象作用域结束,也会自动关闭

{
    ManagedStream mStream;
    AudioStreamBuilder().build(mStream);
    mStream->requestStart();
} // Out of this scope the mStream has been automatically closed 

以上就能实现简单播放音频功能了,需要更深入了解oboe的使用和其他API,例如线程安全问题、阻塞与非阻塞数据处理,建议详细阅读官方文档。

上一篇 下一篇

猜你喜欢

热点阅读