【Android 高性能音频】Oboe 开发流程 ( 包含头 Oboe 头文件 | 创建音频流 | 设置音频流 | 音频流回调类 AudioStreamCallback )

简介: 【Android 高性能音频】Oboe 开发流程 ( 包含头 Oboe 头文件 | 创建音频流 | 设置音频流 | 音频流回调类 AudioStreamCallback )

文章目录

一、包含头 Oboe 头文件

二、音频流构建器 AudioStreamBuilder

三、音频流回调 AudioStreamCallback



Oboe GitHub 主页 : GitHub/Oboe


① 简单使用 : Getting Started


② Oboe 全指南 : Full Guide To Oboe


③ Oboe API 参考 : API reference


④ Android 音频框架发展 : Android audio history



在 【Android 高性能音频】Oboe 开发流程 ( 导入 Oboe 库 | 使用预构建的二进制库和头文件 | 编译 Oboe 源码 ) 博客中介绍了 如何导入 Oboe 函数库到项目中 , 本博客中在导入 Oboe 函数库的基础上 , 进行 Oboe 播放器功能开发 ;






一、包含头 Oboe 头文件


#include <oboe/Oboe.h>





二、音频流构建器 AudioStreamBuilder


创建 AudioStreamBuilder 对象 :


// 音频流构建器
oboe::AudioStreamBuilder builder = oboe::AudioStreamBuilder();



通过 AudioStreamBuilder 配置 Oboe 音频流 : 配置 音频流方向 , 性能优先级 , 共享模式 , 音频采样格式 , 声道数 ;


// 设置音频流方向
builder.setDirection(oboe::Direction::Output);
// 设置性能优先级
builder.setPerformanceMode(oboe::PerformanceMode::LowLatency);
// 设置共享模式 , 独占
builder.setSharingMode(oboe::SharingMode::Exclusive);
// 设置音频采样格式
builder.setFormat(oboe::AudioFormat::Float);
// 设置声道数 , 单声道/立体声
builder.setChannelCount(oboe::ChannelCount::Mono);




三、音频流回调 AudioStreamCallback


定义 音频流回调类 AudioStreamCallback , 当 音频流需要新的 PCM 音频数据时 , 会自动回调 AudioStreamCallback 类 中的 onAudioReady 方法 ;



下面是文档中给出的代码示例 : 这是 Google 文档中给出的示例 , 仅做参考 ;


class MyCallback : public oboe::AudioStreamCallback {
public:
    oboe::DataCallbackResult
    onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) {
        // 请求音频格式 AudioFormat::Float , 假设已经得到了相应数据.
        // 对于生产者 ( 生产音频 ) 代码 , 
        // 检查音频流中的音频数据格式 , 与自己生产的音频数据格式是否一致
        // 如果不一致需要转转数据类型
        // 这里将数据类型转为生产的数据类型 
        auto *outputData = static_cast<float *>(audioData);
        // 生成随机数 (白噪音) 以 0 为中心值 .
        const float amplitude = 0.2f;
        for (int i = 0; i < numFrames; ++i){
            outputData[i] = ((float)drand48() - 0.5f) * 2 * amplitude;
        }
        return oboe::DataCallbackResult::Continue;
    }
};



AudioStreamCallback 类简介 : 该类定义在 oboe 命名空间下 ,


① 数据格式 : 对于输出流 , 该方法应该渲染和写出指定帧数的数据到音频数据缓冲区中 , 这些数据的格式与当前流的格式相同 , 如果不一致需要转转数据类型 ;


② 输出流 : 对于输出流 , 该方法应该 渲染和写出指定帧数的数据到音频数据缓冲区中 , 这些数据的格式与当前流的格式相同 ;


③ 输入流 : 对于输入流 , 该方法应该 从音频数据缓冲区中读取和处理相应帧数的数据 ;


④ 数据传递 : 音频数据通过缓冲区传递 , 不需要额外在音频流中调用 read() 或 write() 方法 ;


⑤ 该方法中不能进行如下操作 :


分配内存操作 , 如 malloc() 或者 new 操作

文件操作 , 如打开 , 读取 , 写出 , 关闭 等文件操作

网络相关操作

使用互斥操作 或 同步操作 , 即不能在该方法中阻塞等待

休眠 sleep

Oboe 音频流的 oboeStream->stop(), pause(), flush() or close() 操作

Oboe 音频流的 oboeStream->read() 操作

Oboe 音频流的 boeStream->write() 操作

总的来说 , 该方法可能要在 1 秒钟内调用几百上千次 , 不能做任何耗时操作 ;


⑥ 在该回调函数中可以进行的操作:


oboeStream->get*()

oboe::convertToText()

oboeStream->setBufferSizeInFrames()

#ifndef OBOE_STREAM_CALLBACK_H

#define OBOE_STREAM_CALLBACK_H


#include "oboe/Definitions.h"


namespace oboe {


class AudioStream;


/**
 * AudioStreamCallback 定义了如下回调接口:
 *
 * 1) 通过 'onAudioReady' 方法 , 将数据放入/取出音频流
 * 2) 当音频流出现错误 , 回调 `onError*` 方法用于示警
 *
 */
class AudioStreamCallback {
public:
    virtual ~AudioStreamCallback() = default;
    /**
     * 缓冲区已经准备好进行相应处理.
     *
     * 对于输出流 , 该方法应该渲染和写出指定帧数的数据到音频数据缓冲区中 , 
     * 这些数据的格式与当前流的格式相同
     * 
     * 对于输入流 , 该方法应该从音频数据缓冲区中读取和处理相应帧数的数据 .
     * 
     * 音频数据通过缓冲区传递 . 
     * 不需要额外在音频流中调用 read() 或 write() 方法 .
     *
     * 除非调用 AudioStreamBuilder::setFramesPerCallback() 方法 , 
     * 读写的帧数可以改变 .
     * 
     * 该回调函数应该被看做实时的 .
     * 在该函数中不应该执行任何耗时操作 , 否则会导致音频电流等故障 ; 
     * 
     * 该方法中不能进行如下操作 : 
     * 1. 分配内存操作 , 如 malloc() 或者 new 操作 
     * 2. 文件操作 , 如打开 , 读取 , 写出 , 关闭 等文件操作 
     * 3. 网络相关操作
     * 4. 使用互斥操作 或 同步操作 , 即不能在该方法中阻塞等待
     * 5. 休眠 sleep 
     * 6. Oboe 音频流的 oboeStream->stop(), pause(), flush() or close() 操作 
     * 7. Oboe 音频流的 oboeStream->read() 操作 
     * 8. Oboe 音频流的 boeStream->write() 操作 
     * 总的来说 , 该方法可能要在 1 秒钟内调用几百上千次 , 不能做任何耗时操作 ; 
     *
     * 在该回调函数中可以进行的操作:
     * 1. oboeStream->get*()
     * 2. oboe::convertToText()
     * 3. oboeStream->setBufferSizeInFrames()
     * 
     * 如果你需要移动数据 , 如 MIDI 指令 , 传入/传输到该回调类方法中 , 推荐使用非阻塞技术 , 如 atomic FIFO .
     *
     * @param oboeStream Oboe 音频流指针 
     * @param audioData 输入/输出 音频数据缓冲区
     * @param numFrames 要处理的帧数 
     * @return DataCallbackResult::Continue or DataCallbackResult::Stop
     */
    virtual DataCallbackResult onAudioReady(
            AudioStream *oboeStream,
            void *audioData,
            int32_t numFrames) = 0;
};
} // namespace oboe
#endif //OBOE_STREAM_CALLBACK_H



目录
相关文章
|
7月前
|
存储 缓存 Android开发
安卓Jetpack Compose+Kotlin, 使用ExoPlayer播放多个【远程url】音频,搭配Okhttp库进行下载和缓存,播放完随机播放下一首
这是一个Kotlin项目,使用Jetpack Compose和ExoPlayer框架开发Android应用,功能是播放远程URL音频列表。应用会检查本地缓存,如果文件存在且大小与远程文件一致则使用缓存,否则下载文件并播放。播放完成后或遇到异常,会随机播放下一首音频,并在播放前随机设置播放速度(0.9到1.2倍速)。代码包括ViewModel,负责音频管理和播放逻辑,以及UI层,包含播放和停止按钮。
|
7月前
|
存储 数据库 Android开发
安卓Jetpack Compose+Kotlin,支持从本地添加音频文件到播放列表,支持删除,使用ExoPlayer播放音乐
为了在UI界面添加用于添加和删除本地音乐文件的按钮,以及相关的播放功能,你需要实现以下几个步骤: 1. **集成用户选择本地音乐**:允许用户从设备中选择音乐文件。 2. **创建UI按钮**:在界面中创建添加和删除按钮。 3. **数据库功能**:使用Room数据库来存储音频文件信息。 4. **更新ViewModel**:处理添加、删除和播放音频文件的逻辑。 5. **UI实现**:在UI层支持添加、删除音乐以及播放功能。
|
3月前
|
Java 程序员 开发工具
Android|修复阿里云播放器下载不回调的问题
虽然 GC 带来了很多便利,但在实际编码时,我们也需要注意对象的生命周期管理,该存活的存活,该释放的释放,避免因为 GC 导致的问题。
47 2
|
5月前
|
算法 数据处理 开发工具
Android平台RTSP|RTMP播放器如何回调YUV或RGB数据
在开发Android平台上的RTSP或RTMP播放器时,开发者不仅追求低延迟播放,还希望获取解码后的视频数据(如YUV或RGB格式),以便进行视觉算法分析。使用大牛直播SDK中的SmartPlayer,可在确保播放流畅的同时,通过设置外部渲染器(`SmartPlayerSetExternalRender`)来高效地回调原始视频数据。例如,对于RGBA数据,需实现`NTExternalRender`接口,并重写相关方法以处理数据和尺寸变化。同样地,对于I420(YUV)数据,也需要相应地实现接口以满足需求。这种方式使得开发者能在不影响常规播放功能的情况下,进行定制化的视频处理任务。
|
5月前
|
开发工具 Android开发
Android项目架构设计问题之SDK内部减少每次回调时的冗余判断逻辑如何解决
Android项目架构设计问题之SDK内部减少每次回调时的冗余判断逻辑如何解决
47 0
|
5月前
|
开发工具 Android开发
Android项目架构设计问题之外部客户方便地设置回调如何解决
Android项目架构设计问题之外部客户方便地设置回调如何解决
35 0
|
5月前
|
Java API 开发工具
Android项目架构设计问题之为SDK添加新的回调支持如何解决
Android项目架构设计问题之为SDK添加新的回调支持如何解决
34 0
|
7月前
|
缓存 Android开发 Kotlin
【安卓app开发】kotlin Jetpack Compose框架 | 先用OKhttp下载远程音频文件再使用ExoPlayer播放
使用 Kotlin 的 Jetpack Compose 开发安卓应用时,可以结合 OkHttp 下载远程音频文件和 ExoPlayer 进行播放。在 `build.gradle` 添加相关依赖后,示例代码展示了如何下载音频并用 ExoPlayer 播放。代码包括添加依赖、下载文件、播放文件及简单的 Compose UI。注意,示例未包含完整错误处理和资源释放,实际应用需补充这些内容。
|
7月前
|
Android开发 Kotlin
安卓Jetpack Compose+Kotlin, 使用ExoPlayer播放多个【本地】音频,播放完随机播放下一首,遇到播放错误,也自动播放下一首
使用Kotlin和Jetpack Compose开发的安卓应用中,实现了两个EvoPlayer同时播放res/raw目录下的音频。一个音轨播放人声(顺序播放),另一个播放背景音乐(随机播放)。每个音轨都有独立的播放和停止控制,且在播放结束或遇到错误时会自动切换到下一首。MediaPlayer置于ViewModel中,UI界面包含播放和停止按钮,控制两个音轨。每次切换音频前,还会随机调整播放速度在0.9到1.2之间。代码示例展示了如何创建ViewModel和UI以实现这一功能。
|
Android开发
android 回调函数一:基本概念
1、概念 客户程序C调用服务程序S中的某个函数A,然后S又在某个时候反过来调用C中的某个函数B,对于C来说,这个B便叫做回调函数。 一般说来,C不会自己调用B,C提供B的目的就是让S来调用它,而且是C不得不提供。
1026 0