美文网首页Android进阶
oboe实现音频播放

oboe实现音频播放

作者: 性感小猪 | 来源:发表于2020-03-30 00:05 被阅读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,例如线程安全问题、阻塞与非阻塞数据处理,建议详细阅读官方文档。

    相关文章

      网友评论

        本文标题:oboe实现音频播放

        本文链接:https://www.haomeiwen.com/subject/fidduhtx.html