鸿蒙媒体开发系列09——OpenSL ES音频录制

如果你也对鸿蒙开发感兴趣,加入“Harmony自习室”吧!扫描下方名片,关注公众号,公众号更新更快,同时也有更多学习资料和技术讨论群。

1、概述

OpenSL ES全称为Open Sound Library for Embedded Systems,是一个嵌入式、跨平台、免费的音频处理库。为嵌入式移动多媒体设备上的应用开发场景提供标准化、高性能、低延迟的API。

HarmonyOS的Native API基于Khronos Group开发的OpenSL ES 1.0.1 API 规范实现,可以在HarmonyOS上使用相关API。

OpenSL ES中提供了以下的接口,可以实现音频录制的基础功能(HarmonyOS当前仅实现了部分OpenSL ES接口)。

调用未实现接口后会返回SL_RESULT_FEATURE_UNSUPPORTED,当前没有相关扩展可以使用。

下面列举了HarmonyOS上已实现的OpenSL ES的接口,具体说明请参考OpenSL ES规范(url👉🏻 https://www.khronos.org/opensles/ ):

  • HarmonyOS上支持的Engine接口:

    • SLresult (*CreateAudioPlayer) (SLEngineItf self, SLObjectItf * pPlayer, SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces, const SLInterfaceID * pInterfaceIds, const SLboolean * pInterfaceRequired)

    • SLresult (*CreateAudioRecorder) (SLEngineItf self, SLObjectItf * pRecorder, SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces, const SLInterfaceID * pInterfaceIds, const SLboolean * pInterfaceRequired)

    • SLresult (*CreateOutputMix) (SLEngineItf self, SLObjectItf * pMix, SLuint32 numInterfaces, const SLInterfaceID * pInterfaceIds, const SLboolean * pInterfaceRequired)

  • HarmonyOS上支持的Object接口:

    • SLresult (*Realize) (SLObjectItf self, SLboolean async)

    • SLresult (*GetState) (SLObjectItf self, SLuint32 * pState)

    • SLresult (*GetInterface) (SLObjectItf self, const SLInterfaceID iid, void * pInterface)

    • void (*Destroy) (SLObjectItf self)

  • HarmonyOS上支持的Recorder接口:

    • SLresult (*SetRecordState) (SLRecordItf self, SLuint32 state)

    • SLresult (*GetRecordState) (SLRecordItf self,SLuint32 *pState)

  • HarmonyOS上支持的BufferQueue接口:

    以下接口需引入<OpenSLES_OpenHarmony.h>使用。

接口

说明

SLresult (*Enqueue) (SLOHBufferQueueItf self, const void *buffer, SLuint32 size)

根据情况将buffer加到相应队列中。

如果是播放操作,则将带有音频数据的buffer插入到filledBufferQ_队列中;如果是录音操作,则将录音使用后的空闲buffer插入到freeBufferQ_队列中。

self:表示调用该函数的BufferQueue接口对象。

buffer:播放时表示带有音频数据的buffer,录音时表示已存储完录音数据后的空闲buffer。

size:表示buffer的大小。

SLresult (*Clear) (SLOHBufferQueueItf self)

释放BufferQueue接口对象。

self:表示调用该函数的BufferQueue接口对象将被释放。

SLresult (*GetState) (SLOHBufferQueueItf self, SLOHBufferQueueState *state)

获取BufferQueue接口对象状态。

self:表示调用该函数的BufferQueue接口对象。

state:BufferQueue的当前状态。

SLresult (*RegisterCallback) (SLOHBufferQueueItf self, SlOHBufferQueueCallback callback, void* pContext)

注册回调函数。

self:表示调用该函数的BufferQueue接口对象。

callback:播放/录音时注册的回调函数。

pContext:播放时传入待播放音频文件,录音时传入将要录制的音频文件。

SLresult (*GetBuffer) (SLOHBufferQueueItf self, SLuint8** buffer, SLuint32* size)

根据情况获取相应的buffer。

如果是播放操作,则从freeBufferQ_队列中获取空闲buffer;如果是录音操作,则从filledBufferQ_队列中获取携带录音数据的buffer。

self:表示调用该函数的BufferQueue接口对象。

buffer:播放时表示空闲的buffer,录音时表示携带录音数据的buffer。

size:表示buffer的大小。

2、开发流程示例

示例来自于官方介绍。

1、添加头文件

#include "SLES/OpenSLES.h"#include "SLES/OpenSLES_OpenHarmony.h"#include "SLES/OpenSLES_Platform.h"

2、使用slCreateEngine接口创建引擎对象和实例化引擎对象engine。

SLObjectItf engineObject = nullptr;slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);(*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);

3、获取接口SL_IID_ENGINE的引擎接口engineEngine实例。​​​​​​​

SLEngineItf engineItf = nullptr;(*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineItf);

4、配置录音器信息(配置输入源audiosource、输出源audiosink),创建录音对象pcmCapturerObject。​​​​​​​

SLDataLocator_IODevice io_device = {    SL_DATALOCATOR_IODEVICE,    SL_IODEVICE_AUDIOINPUT,    SL_DEFAULTDEVICEID_AUDIOINPUT,    NULL};SLDataSource audioSource = {    &io_device,    NULL};SLDataLocator_BufferQueue buffer_queue = {    SL_DATALOCATOR_BUFFERQUEUE,    3};// 具体参数需要根据音频文件格式进行适配SLDataFormat_PCM format_pcm = {    SL_DATAFORMAT_PCM,           // 输入的音频格式    1,                                              // 单声道    SL_SAMPLINGRATE_44_1,        // 采样率: 44100HZ    SL_PCMSAMPLEFORMAT_FIXED_16, // 音频采样格式,小尾数,带符号的16位整数    0,    0,    0};SLDataSink audioSink = {    &buffer_queue,    &format_pcm};SLObjectItf pcmCapturerObject = nullptr;(*engineItf)->CreateAudioRecorder(engineItf, &pcmCapturerObject,    &audioSource, &audioSink, 0, nullptr, nullptr);(*pcmCapturerObject)->Realize(pcmCapturerObject, SL_BOOLEAN_FALSE);

5、获取录音接口SL_IID_RECORD的recordItf接口实例。​​​​​​​

SLRecordItf  recordItf;(*pcmCapturerObject)->GetInterface(pcmCapturerObject, SL_IID_RECORD, &recordItf);

6、获取接口 SL_IID_OH_BUFFERQUEUE 的 bufferQueueItf 实例​​​​​​​

SLOHBufferQueueItf bufferQueueItf;(*pcmCapturerObject)->GetInterface(pcmCapturerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);

7、注册BufferQueueCallback回调。​​​​​​​

static void BufferQueueCallback(SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size){    // 可从pContext获取注册时传入的使用者信息    SLuint8 *buffer = nullptr;    SLuint32 pSize = 0;    (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, &pSize);    if (buffer != nullptr) {        // 可从buffer内读取录音数据进行后续处理         (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, size);    }}void *pContext; // 可传入自定义的上下文信息,会在Callback内收到(*bufferQueueItf)->RegisterCallback(bufferQueueItf, BufferQueueCallback, pContext);

8、开始录音

(*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_RECORDING);

9、结束音频录制​​​​​​​

(*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_STOPPED);(*pcmCapturerObject)->Destroy(pcmCapturerObject);

这里的OpenSL ES涉及到native API,后续针对Native API可以单独做讨论学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/147155.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【我的 PWN 学习手札】tcache extend

目录 前言 一、利用手法 二、流程演示 &#xff08;1&#xff09;三块物理相邻的堆块 &#xff08;2&#xff09;溢出修改 size &#xff08;3&#xff09;释放该 chunk &#xff08;4&#xff09;重新申请该 chunk &#xff08;5&#xff09;释放第三块 chunk&#x…

vcs/verdi常用命令(持续更新)

1. 操作rtl 1.1 加载rtl命令 verdi -dbdir simv.daidir的目录 1.2 显示某时刻rtl的值 首先鼠标左键在波形上选中某个特定时刻&#xff0c;然后鼠标选中rtl代码文件&#xff0c;按x就会显示&#xff0c;再按x就会退出显示。 1.3 查找字符串 按/ 1.4 vcs将rtl的信号加载到…

DNS是什么?怎么设置

NS是什么意思?有什么用呢?专业的说DNS就是域名系统 (Domain Name System)的简称&#xff0c;也就是IT人士常说的域名解析系统。主要是让用户在互联网上通过域名找到域名对应的IP地址&#xff0c;因为IP地址都是一串数字(例如&#xff1a;192.168.0.1)不方便记忆&#xff0c;便…

与 CESS Network 共探去中心化创新:重塑数据基础设施,驱动未来变革

随着互联网的快速发展和数据量的爆炸式增长&#xff0c;如何有效管理、存储和保护数据成为了一个日益重要的课题。传统的中心化平台&#xff0c;如 YouTube&#xff0c;虽然为用户提供了便捷的服务&#xff0c;但数据的所有权和控制权往往掌握在平台手中&#xff0c;用户的内容…

口腔检测系统源码分享

口腔检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

Memory Controller Unit (MCU)内存控制器介绍

文章目录 Memory Controller Unit (MCU)内存控制器介绍1. MCU基本概念和功能地址映射读写操作缓存控制内存刷新1.1 地址映射1.2 读写操作1.3 缓存控制1.4 内存刷新 2. MCU的工作原理接收CPU的请求地址转换执行操作管理缓存 3. MCU的类型SDRAM控制器DDR控制器Flash控制器 4. MCU…

嵌入式 开发技巧和经验分享

文章目录 前言嵌入式 开发技巧和经验分享目录1.1嵌入式 系统的 定义1.2 嵌入式 操作系统的介绍1.3 嵌入式 开发环境1.4 编译工具链和优化1.5 嵌入式系统软件开发1.6 嵌入式SDK开发2.1选择移植的系统-FreeRtos2.2FreeRtos 移植步骤2.3 系统移植之中断处理2.4系统移植之内存管理2…

与姜妍同款冰箱,容声516WILL养鲜冰箱领“鲜”上市

9月20日&#xff0c;容声冰箱在“养鲜新净界”——2024年容声新品上市发布会上推出了WILL系列的最新力作——516WILL养鲜冰箱。 据「TMT星球」了解&#xff0c;此次新品搭载了升级版的WILL自然养鲜技术&#xff0c;并以60CM整机平嵌一体&#xff0c;完美融入现代家居美学&…

Mapper代理开发

目的 解决原生方式中的硬编码简化后期执行SQL 步骤 1&#xff0c; 整体目录结构 2&#xff0c; UserMapper.xml 设置SQL映射文件的namespace属性为Mapper接口全限定名 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapperPUBLIC &quo…

P9235 [蓝桥杯 2023 省 A] 网络稳定性

*原题链接* 最小瓶颈生成树题&#xff0c;和货车运输完全一样。 先简化题意&#xff0c; 次询问&#xff0c;每次给出 &#xff0c;问 到 的所有路径集合中&#xff0c;最小边权的最大值。 对于这种题可以用kruskal生成树来做&#xff0c;也可以用倍增来写&#xff0c;但不…

程序员工作中经常使用的C/C++开源库

Bundle 项目地址&#xff1a;GitHub - r-lyeh-archived/bundle: :package: Bundle, an embeddable compression library: DEFLATE, LZMA, LZIP, BZIP2, ZPAQ, LZ4, ZSTD, BROTLI, BSC, CSC, BCM, MCM, ZMOLLY, ZLING, TANGELO, SHRINKER, CRUSH, LZJB and SHOCO streams in a …

Datawhale X 南瓜书 task02学习笔记

算法原理引入 样本点通常应该在模型的2侧&#xff0c;原因&#xff1a;在实际中&#xff0c;因为某种不可控的因素&#xff0c;测出来的样本点肯定是有误差的。如果样本数据点都在模型上&#xff0c;则说明在建立模型时&#xff0c;把误差也考虑进去了&#xff0c;这就是我们说…

9月21日 电子产品世界上海站沙龙

9月21日 电子产品世界上海站沙龙 有幸参加了 9月21日 14: 00 在上海 九江路 700号 上海南新雅皇冠假日酒店 4楼 举行的 TI MSPM0 MCU开发经验交流 会 本次邀请资深开发者&#xff0c;现场跟大家进行TI MSPM0 MCU开发经验交流&#xff0c;并详细展示基于TI MSPM0 MCU开发的实用…

动态规划day39|198. 打家劫舍、213. 打家劫舍 II(环形怎么处理?)、337. 打家劫舍 III(二叉树与动态规划的完美结合!)

动态规划day39|198. 打家劫舍、213. 打家劫舍 II&#xff08;环形怎么处理&#xff1f;&#xff09;、337. 打家劫舍 III&#xff08;二叉树与动态规划的完美结合&#xff01;&#xff09; 198. 打家劫舍213. 打家劫舍 II337. 打家劫舍 III 198. 打家劫舍 你是一个专业的小偷&…

盘点3款.NetCore(C#)开源免费商城系统

CoreShop商城 介绍 核心商城系统&#xff08;CoreShop&#xff09; 是基于 Asp.Net 8.0、Uni-App开发、支持可视化布局的小程序商城系统&#xff1b;前后端分离&#xff0c;支持跨平台运行&#xff1b;拥有分销、代理、团购秒杀、接龙、拼团、直播、优惠券、自定义表单等众多营…

为什么用迭代器调用不了对象中的函数

没加const可以 加了const就不行 我懂了 加了const v的值就不能修改&#xff0c;我的那些函数都可以修改值 应该是 好像不对 有大佬会吗

直通滤波-PassThrough Filter-原理-代码实现

前言 对坐标轴上的上下限进行约束&#xff0c;选取其中符合范围的点云区域使用场景&#xff1a;去除噪声点&#xff0c;关注特定区域&#xff0c;减小计算量 工作流程 假设我们要在 d d d 轴&#xff08; d ∈ { x , y , z } d \in \{x, y, z\} d∈{x,y,z} &#xff09;上…

yolov5足球运动分析-速度分析-足球跟踪

足球分析项目 引言 在现代体育分析领域&#xff0c;利用先进的计算机视觉技术和机器学习模型对比赛视频进行深入解析已成为一种趋势。本项目旨在通过YOLO&#xff08;You Only Look Once&#xff09;这一顶级的人工智能目标检测模型来识别并跟踪足球比赛中的球员、裁判以及足球…

软件开发详解:通过源码搭建高效的食堂采购与供应链管理平台

通过源码构建定制化的系统&#xff0c;能够让企业根据自身需求灵活调整功能&#xff0c;打造符合其业务流程的高效管理平台。接下来&#xff0c;小编将详细介绍如何通过源码搭建一套高效的食堂采购与供应链管理平台&#xff0c;并分析其在技术架构、功能实现及优化策略方面的关…