Android 耳返实践 OpenSL ES AAudio Oboe

耳返概述:

耳返主要实现监听的功能,在低延时的情况下可以给主播一个比较真实音频的反馈,在演唱会等专业场景里比较常用。
技术实现上来说就是要时时的把录制进的音频数据立刻播放出去,当然这个过程要低延迟。

AudioRecord,AudioTrack

在Android系统上做耳返,实现一个高性能的音频录制音频播放是一件很痛苦的事;因为我们并不能直接使用系统的AudioRecord,AudioTrack。这两个函数有很大的延迟,尤其是AudioTrack,不同的系统延迟范围在40ms到200ms之间。对于耳返来说有延迟感是不能忍受的。

那么不使用系统API实现,要怎么实现呢?

答案:直接和手机品牌厂商合作,拿到定制接口 hhh。
哈哈 ,如果你的公司有实力直接和各品牌厂商合作请忽略下面的内容。

OpenSL ES 和 AAudio

OpenSL ES:
OpenSL ES 是 Khronos Group 开发的 OpenSL ES™ API 规范的实现,专用于 Android。
NDK 软件包中OpenSL ES™ API 规范 Android 特定实现。利用这个库,不论是编写合成器、卡拉 OK、游戏还是其他实时应用,都可以使用 C 或 C++ 实现高性能、短延迟时间音频。
OpenSL ES Android demo: https://github.com/googlesamples/android-ndk/tree/master/audio-echo

AAudio:
AAudio 是作为 OpenSL ES 库的轻量级原生 Android 替代项而开发。 与 OpenSL ES 相比,AAudio API 不仅较小,而且容易使用。
AAudio 是在 Android O 版本中引入的全新 Android C API。 此 API 是专为需要低延迟的高性能音频应用而设计。 应用通过读取并将数据写入流来与 AAudio 进行通信。
AAudio Android demo: https://github.com/googlesamples/android-audio-high-performance/tree/master/aaudio

使用android系统底层的OpenSL ES或者AAudio都可以实现一个高性能的音频程序,尤其是AAudio更是简单易用,性能上,功能上都更佳,但是AAudio 是在 Android O 版本中才引入的全新 Android C API,在以前的系统版本中只能使用OpenSL ES。
那么我们需要做的是在新版本系统中使用AAudio,在不支持AAudio的系统版本中使用OpenSL ES,两套API同时使用。不要怕困难,因为这是一个即面向未来,又兼顾现在,历史的good idea。不要害怕这有多么困难,Google已经帮我们实现了——Oboe

Oboe:https://github.com/google/oboe

在这里插入图片描述
Oboe是一个C ++库,可以轻松地在Android上构建高性能音频应用程序。内部有OpenSL ES和AAudio两大音频引擎,一行代码随意切换使用,我们可以用JNI在android应用上使用它们。

下面提供一下Oboe使用实例:

录制器

 setupCommonStreamParameters(
    oboe::AudioStreamBuilder *builder) {
    
    builder->setAudioApi(mAudioApi)
        ->setSharingMode(oboe::SharingMode::Exclusive)
        ->setPerformanceMode(oboe::PerformanceMode::LowLatency);
    return builder;

 setupRecordingStreamParameters(
    oboe::AudioStreamBuilder *builder ,bool isCallBack) {
    
   builder->setCallback(this)
        ->setDirection(oboe::Direction::Input)
    return setupCommonStreamParameters(builder);


 oboe::AudioStream *mRecordingStream = nullptr;
 oboe::AudioStreamBuilder builder;

 setupRecordingStreamParameters(&builder);
  oboe::Result result = builder.openStream(&mRecordingStream);
    if (result == oboe::Result::OK && mRecordingStream) {
    oboe::Result result = mRecordingStream->requestStart();  //开始录制。
    }


播放器:

 setupCommonStreamParameters(
    oboe::AudioStreamBuilder *builder) {
    
    builder->setAudioApi(mAudioApi)
        ->setSharingMode(oboe::SharingMode::Exclusive)
        ->setPerformanceMode(oboe::PerformanceMode::LowLatency);
    return builder;

 setupPlayStreamParameters(
    oboe::AudioStreamBuilder *builder ,bool isCallBack) {
    
   builder->setCallback(this)
        ->setDirection(oboe::Direction::output)
    return setupCommonStreamParameters(builder);


 oboe::AudioStream *mPlayStream = nullptr;
 oboe::AudioStreamBuilder builder;

 setupPlayStreamParameters(&builder);
  oboe::Result result = builder.openStream(&mPlayStream);
    if (result == oboe::Result::OK && mPlayStream) {
    oboe::Result result = mPlayStream->requestStart();  //开始播放。
    }

oboe::DataCallbackResult LiveEffectEngine::onAudioReady(
    oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) {
    
    render(audioData,numFrames); //audioData放入数据即可播放。
    
     return oboe::DataCallbackResult::Continue;
   }

我们的项目在使用Oboe做录制和播放引擎后明显的优化了耳返延迟问题。之前120Ms的回路延迟设备,优化后延时在25Ms左右,对于用户来说已经感受不到了延迟回声感。
很遗憾在测试了很多设备后仍发现在vivo的部分手机上耳返优化并没有那么明显,还有延迟感;应该是这款设备在系统内部的音频模块上并没有遵循Google的设计规范。

Table of Contents PART 1: USER MANUAL ......................................................................................... 1 1 OVERVIEW ..................................................................................................... 2 2 FEATURES AND PROFILES .............................................................................. 9 3 DESIGN OVERVIEW ...................................................................................... 14 FUNCTIONAL OVERVIEW .............................................................................. 30 PART 2: API REFERENCE ..................................................................................... 60 5 BASE TYPES AND UNITS ............................................................................... 61 6 FUNCTIONS .................................................................................................. 64 7 OBJECT DEFINITIONS .................................................................................. 67 8 INTERFACE DEFINITIONS ............................................................................ 93 9 MACROS AND TYPEDEFS............................................................................. 439 PART 3: APPENDICES ........................................................................................ 501 APPENDIX A: REFERENCES ............................................................................... 502 APPENDIX B: SAMPLE CODE.............................................................................. 504 APPENDIX C: USE CASE SAMPLE CODE .............................................................. 555 APPENDIX D: OBJECT-INTERFACE MAPPING..................................................... 585
Android中的V4L2(Video for Linux 2)是一个用于处理视频输入和输出的子系统。(monitoring)是指在录制音频时,允许用户同时通过机或扬声器实时听到录制的声音。 在Android中实现功能,首先需要通过V4L2子系统来捕获音频输入。具体来说,可以使用ALSA(Advanced Linux Sound Architecture)来配置和控制音频设备,并通过V4L2的API来进行音频数据的读取。 首先,我们需要打开和配置音频设备,例如通过alsa-lib库来打开mic输入设备。然后,我们可以使用V4L2的API来获取音频数据。可以通过提供一个回调函数或直接轮询来读取音频帧。 当获取到音频数据后,我们可以将其传递给播放音频的设备,例如机或扬声器。在Android中,可以使用AudioTrack类来实现音频的输出。可以使用AudioManager类来管理音频设备和音量。 在将音频数据传递给扬声器或机之前,可能还需要进行一些处理,例如音频混音,增益控制,降噪等。这可以通过使用Android提供的音频处理库来完成。 总结起来,通过V4L2子系统和Android的音频框架,我们可以实现Android功能。首先,使用alsa-lib库打开和配置音频设备,然后通过V4L2的API获取音频数据,并使用AudioTrack类将音频数据输出到扬声器或机。在此过程中,可能需要一些音频处理操作,可以使用Android提供的音频处理库来完成。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值