热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android耳返实践OpenSLESAAudioOboe

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

耳返概述:

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

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


推荐阅读
author-avatar
认识你不笑嘻嘻
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有