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的设计规范。

发布了134 篇原创文章 · 获赞 170 · 访问量 39万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览