OpenHarmony南向之Audio

音频架构

Audio驱动框架基于HDF驱动框架实现,包含内核态(KHDF),和用户态(UHDF), 对北向提供音频HDI接口

音频框架图

驱动架构主要由以下几部分组成。

  • HDI adapter:实现Audio HAL层驱动(HDI接口适配),给Audio服务(frameworks)提供所需的音频硬件驱动能力接口。包含 Audio Manager、Audio Adapter、Audio Control、Audio Capture、Audio Render等接口对象。
  • Audio Interface Lib:向下配合内核中的Audio Driver Model使用,实现音频硬件的控制、录音数据的读取、播放数据的写入,向上和上层的Audio HDI Adapter层进行对接。
  • ADM(Audio Driver Model):音频驱动框架模型,向上服务于多媒体音频子系统,向下统一接口适配各自的驱动代码。

主要代码目录

  • drivers/hdf_core/framework/model/audiodevice/board/xxx/yyy/audio_drivers等: ADM相关驱动,KHDF部分
  • drivers/peripheral/audio: audio HAL 实现,UHDF部分
  • foundation/multimedia/audio_framework: audio framework 实现

调用流程

Audio Service

目录:foundation/multimedia/audio_framework/services/

client:
通过 Remote()->SendRequest,和服务端进行通信(IPC),binder
server:
server端向上通过IPC与client交互,向下与HAL交互

使用PulseAudio进行音频流管理
foundation/multimedia/audio_framework/services/audio_service/client/src/audio_service_client.cpp

HAL

HAL简单架构

  • alsa adapter(drivers/peripheral/audio/supportlibs/alsa_adapter):
    基于alsa lib(alsa用户态接口库),对alsa接口的封装,向下驱动基于alsa
  • adm adapter(drivers/peripheral/audio/supportlibs/adm_adapter):
    基于amate(ADM用户态接口库),对ADM接口的封装,向下驱动基于alsa
  • supportlib
    屏蔽声卡访问控制的差异,在用户态实现一套符合 hdi-adapter 规范的访问控制
  • hdi-passthrough
    将声卡(片内声卡、usb 声卡、HDMI 声卡等)抽象成 adapter,每个 adapter 都包含 supportlibs 抽象的 audioRender 和 audiocapture,最后通过 audiomanager 管理 adapters。进一步将音频 HDI 接口规范化封装
  • hdi-binder
    HDF音频驱动框架最上层的封装,基于C/S的IPC机制

所以,由此可以得到音频驱动适配的几种主流方案:

  1. 通过”adm adapter”对接自研ADM内核驱动,是目前社区主流方案
  2. 通过”alsa lib”对接ASLA,是针对已支持ASLA产品的友好适配方案
  3. 通过自己实现Vendor HAL来对接音频HDI接口,主要针对厂商有自己成熟的音频中间件的情况

目录结构

从下面代码目录结构可以很容易和上面的架构图一一对应

zdd@zdd-PC:~/WorkSpace/OHOS/oh-v3.2.2/drivers/peripheral/audio$ tree -L 2
.
├── audio.gni
├── BUILD.gn
├── bundle.json
├── config
├── hal
│   ├── hdi_binder
│   │   ├── proxy
│   │   └── server
│   ├── hdi_passthrough
│   └── pathselect
├── hdi_service
│   ├── binder
│   ├── BUILD.gn
│   ├── passthrough
│   ├── pathselect
│   └── supportlibs
├── interfaces
│   ├── 2.0
│   └── include
├── supportlibs
│   ├── adm_adapter
│   ├── alsa_adapter
│   ├── BUILD.gn
│   └── interfaces
└── test├── BUILD.gn├── fuzztest├── resource├── sample├── systemtest└── unittest

HAL流程

ADM流程

ADM流程基本上都是基于驱动消息机制(dispatch)实现:drivers/peripheral/audio/supportlibs/adm_adapter/src/audio_interface_lib_common.c

下面看看几种基本的ADM流程:

ADM启动流程

  1. 系统启动时Audio模块的Platform、Codec、Dsp、Dai各个驱动首先被加载,各驱动从各自私有配置文件中获取配置信息,并将获取的配置信息保存到各驱动的Data数据结构中。
  2. 各驱动模块调用ADM注册接口将自己添加到各驱动模块的链表中。
  3. ADM模块读取hdf_audio_driver_0和hdf_audio_driver_1配置信息,加载各模块的具体设备。
  4. ADM模块调用各模块的初始化函数对各模块设备进行初始化。
  5. 将初始化成功的音频设备添加到cardManager链表。
HCS

以rk3568平台,结合上面的启动流程看看audio相关的hcs文件

  • device_info.hcs:
...
audio :: host {hostName = "audio_host";priority = 110;device_dai0 :: device {device0 :: deviceNode {policy = 1;priority = 50;preload = 0;permission = 0666;moduleName = "DAI_RK3568";serviceName = "dai_service";deviceMatchAttr = "hdf_dai_driver";}}device_codec_0 :: device {device0 :: deviceNode {policy = 1;priority = 50;preload = 0;permission = 0666;moduleName = "CODEC_RK809";serviceName = "codec_service_0";deviceMatchAttr = "hdf_codec_driver_0";}}device_codec_1 :: device {device0 :: deviceNode {policy = 1;priority = 50;preload = 0;permission = 0666;moduleName = "CODEC_RK817";serviceName = "codec_service_1";deviceMatchAttr = "hdf_codec_driver_1";}}device_dsp :: device {device0 :: deviceNode {policy = 1;priority = 50;preload = 0;permission = 0666;moduleName = "DSP_RK3568";serviceName = "dsp_service_0";deviceMatchAttr = "hdf_dsp_driver";}}device_dma :: device {device0 :: deviceNode {policy = 1;priority = 50;preload = 0;permission = 0666;moduleName = "DMA_RK3568";serviceName = "dma_service_0";deviceMatchAttr = "hdf_dma_driver";}}device_audio :: device {device0 :: deviceNode {policy = 2;priority = 60;preload = 0;permission = 0666;moduleName = "HDF_AUDIO";deviceMatchAttr = "hdf_audio_driver_0";serviceName = "hdf_audio_codec_primary_dev0";}device1 :: deviceNode {policy = 2;priority = 60;preload = 0;permission = 0666;moduleName = "HDF_AUDIO";deviceMatchAttr = "hdf_audio_driver_1";serviceName = "hdf_audio_codec_primary_dev11";}}device_stream :: device {device0 :: deviceNode {policy = 2;priority = 80;preload = 0;permission = 0666;moduleName = "HDF_AUDIO_STREAM";serviceName = "hdf_audio_render";}device1 :: deviceNode {policy = 2;priority = 80;preload = 0;permission = 0666;moduleName = "HDF_AUDIO_STREAM";serviceName = "hdf_audio_capture";}}device_control :: device {device0 :: deviceNode {policy = 2;priority = 80;preload = 0;permission = 0666;moduleName = "HDF_AUDIO_CONTROL";serviceName = "hdf_audio_control";}}device_analog_headset :: device {device0 :: deviceNode {policy = 1;priority = 90;preload = 0;permission = 0666;moduleName = "AUDIO_ANALOG_HEADSET";serviceName = "analog_headset_service";deviceMatchAttr = "analog_headset_attr";}}}
...
  • audio_config.hcs

hcs

root {platform {template card_controller {match_attr = "";serviceName = "";codecName = "";platformName = "";cpuDaiName = "";codecDaiName = "";dspName = "";dspDaiName = "";}controller_0x120c1000 :: card_controller {match_attr = "hdf_audio_driver_0";serviceName = "hdf_audio_codec_primary_dev0";codecName = "codec_service_0";platformName = "dma_service_0";cpuDaiName = "dai_service";codecDaiName = "codec_dai";dspName = "dsp_service_0";dspDaiName = "dsp_dai";}controller_0x120c1001 :: card_controller {match_attr = "hdf_audio_driver_1";serviceName = "hdf_audio_codec_primary_dev11";codecName = "codec_service_1";platformName = "dma_service_0";cpuDaiName = "dai_service";codecDaiName = "rk817_dai";dspName = "dsp_service_0";dspDaiName = "dsp_dai";}}
}
  • codec_config.hcs

Code

root {platform {template codec_controller {match_attr = "";serviceName = "";codecDaiName = "";}controller_0x120c1030 :: codec_controller {match_attr = "hdf_codec_driver_0";serviceName = "codec_service_0";codecDaiName = "codec_dai";regConfig {/* reg, value */initSeqConfig = [0x13,    0xf4,...];controlsConfig = [/*array index, iface, mixer/mux, enable,*/0,  2,  0,  1,...];/* reg, rreg, shift, rshift, min, max, mask, invert, value */ctrlParamsSeqConfig = [0x31,    0x32,    0,    0,    0x00,    0xFF,   0xFF,   1,    0x00, // DACL/R Playback Volume...];/* reg, rreg, shift, rshift, min, max, mask, invert, value */daiParamsSeqConfig = [0x45,    0x45,    0,     0,    0x0,   0xFF,    0xFF,   0,     0x0C, // PLL_PREDIV_BIT...];ctrlSapmParamsSeqConfig = [0x27,    0x27,    5,     5,    0x00,    0x1,    0x1,    1,    0x00,     //LPGA MIC  -- connect MIC1...];/*sapmreg is 0xFFFF: component has no sapm register bitsapmType, compNameIndex, reg, mask, shift, invert, kcontrolNews, kcontrolsNum*/sapmComponent = [10,      0,       0x18,       0x1,     7,     1,     0,     0,  //ADCL...];/*array index, iface, mixer/mux, enable*/sapmConfig = [0,     2,    0,    1,...];}}controller_0x120c1031 :: codec_controller {match_attr = "hdf_codec_driver_1";serviceName = "codec_service_1";codecDaiName = "rk817_dai";}}
}

ADM播放流程

  1. 播放音频时,Interface Lib层通过播放流服务下发Render Open指令,Audio Stream Dispatch服务收到指令后分别调用各模块的函数接口对指令进行下发。
  2. Interface Lib层通过控制服务下发通路选择指令,Control Dispatch控制服务收到指令后调用Dai模块接口设置通路。
  3. Interface Lib层通过播放流服务下发硬件参数,Audio Stream Dispatch服务收到参数后分别调用各模块参数设置接口,对硬件参数进行设置。
  4. Interface Lib层通过播放流服务下发播放启动指令,Audio Stream Dispatch服务收到指令后分别调用各模块启动接口,对各模块进行启动设置。
  5. Interface Lib层通过播放流服务下发音频数据,Audio Stream Dispatch服务收到数据后调用Platform AudioPcmWrite接口将音频数据传给Dma。
  6. Interface Lib层通过播放流服务下发播放停止指令,Audio Stream Dispatch服务收到指令后分别调用各模块停止接口,对各模块进行停止设置。
  7. Interface Lib层通过播放流服务下发Render Close指令,Audio Stream Dispatch服务收到指令后调用Platform AudioRenderClose对已申请资源进行释放。

ADM控制流程

  1. 设置音量,首先Interface Lib层通过控制服务下发获取音量范围指令,Control Dispatch控制服务收到指令后进行解析,并调用Codec模块Get函数,获取可设置音量的范围。
  2. Interface Lib层通过控制服务下发设置音量指令,Control Dispatch控制服务收到指令后进行解析,并调用Codec模块Set函数设置音量。

分布式音频组件

分布式音频是指多个设备之间音频外设跨设备协同使用的能力,如将设备A的音频通过设备B的Speaker进行播音,或者设备A使用设备B的Mic进行录音。
分布式音频不直接向应用提供接口,应用可以通过音频框架的接口来调用分布式音频能力,使用方式与本地音频一致。

概念说明

主控端(source) :分布式音频控制端设备,向被控端设备发送指令,实现在被控端设备上音频播放和录制的功能;

被控端(sink) :分布式音频被控制端设备,接收来自主控端设备的指令,使本地音频外设为主控端设备所用,用来播音或录音。


为了能让大家更好的学习鸿蒙 (Harmony OS) 开发技术,这边特意整理了《鸿蒙 (Harmony OS)开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙 (Harmony OS)开发学习手册》

入门必看:https://qr21.cn/FV7h05

  1. 应用开发导读(ArkTS)
  2. 应用开发导读(Java)

HarmonyOS 概念:https://qr21.cn/FV7h05

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. 构建第一个JS应用
  4. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring 是如何解决循环依赖问题的方案

文章目录 Spring 是如何解决循环依赖问题的? Spring 是如何解决循环依赖问题的? 我们都知道,如果在代码中,将两个或多个 Bean 互相之间持有对方的引用就会发生循环依赖。循环的依赖将会导致注入死循环。这是 Spring 发生循环依赖…

数据库开发之图形化工具以及表操作的详细解析

2.3 图形化工具 2.3.1 介绍 前面我们讲解了DDL中关于数据库操作的SQL语句,在我们编写这些SQL时,都是在命令行当中完成的。大家在练习的时候应该也感受到了,在命令行当中来敲这些SQL语句很不方便,主要的原因有以下 3 点&#xff…

Android Studio 进行NDK开发,实现JNI,以及编写C++与Java交互(Java调用本地函数)并编译出本地so动态库

1.首先认识一下NDK。 (1)什么是NDK? NDK全称是Native Development Kit,NDK提供了一系列的工具,帮助开发者快速开发C/C的动态库,并能自动将so和java应用一起打包成apk。NDK集成了交叉编译器(交叉…

Android 13 动态启用或禁用IPV6

介绍 客户想要通过APK来控制IPV6的启用和禁用,这里我们通过广播的方式来让客户控制IPV6。 效果展示 adb shell ifconfig 这里我们用debug软件,将下面节点置为1 如图ipv6已被禁用了 echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6 修改 接下来…

算法学习系列(十五):最小堆、堆排序

目录 引言一、最小堆概念二、堆排序模板(最小堆)三、模拟堆 引言 这个堆排序的话,考的还挺多的,主要是构建最小堆,并且在很多情况下某些东西还用得着它来优化,比如说迪杰斯特拉算法可以用最小堆优化&#…

Spring Boot学习随笔- Jasypt加密数据库用户名和密码以及解密

学习视频:【编程不良人】2021年SpringBoot最新最全教程 第十九章、Jasypt加密 Jasypt全称是Java Simplified Encryption,是一个开源项目。 Jasypt与Spring Boot集成,以便在应用程序的属性文件中加密敏感信息,然后在应用程序运行…

Openslide安装

文章目录 安装open-slide python下载openslide二进制文件解压到Anaconda的library目录下配置环境变量在py文件中添加以下语句即可 官网链接 安装open-slide python 表面上这样就可以导入了但事实上会遇到 Couldn’t locate OpendSlide DLL的问题,openslide必须独立安…

VSCODE : SSH远程配置+免密登录

SSH基础配置 填入地址,回车 ssh userhost-or-ip 然后选择默认的配置,回车,得到以下结果: 点击链接 选择远程的系统 输入密码 免密登录 生成SSH密钥: 首先,确保你已经在本地生成了SSH密钥。你可以使…

nodejs+vue+微信小程序+python+PHP的艺术展览馆艺术品管理系统-计算机毕业设计推荐

选择轻量级的关系型MySQL数据库存储数据。接着进行系统的需求分析、功能设计、数据库设计,最后进行编码实现。具体如下: 1)网站首页:艺术品浏览展示,艺术品作者线下。供会员浏览查看。 2)注册登录&#xff…

OpenCV-Python(21):OPenCV查找及绘制轮廓

1.认识轮廓 1.1 目标 理解什么是轮廓学习掌握找轮廓、绘制轮廓等学习使用cv2.findContours()、cv2.drawContours()函数的用法 1.2 什么是轮廓 在OpenCV中,轮廓是图像中连续的边界线的曲线,具有相同的颜色或者灰度,用于表示物体的形状。轮廓…

vue中使用echarts实现省市地图绘制,根据数据显示省市天气图标及温度信息

一、实现效果 使用echarts实现省市地图绘制根据数据显示省下市的天气图标根据数据显示省下市的温度信息 二、实现方法 1、安装echarts插件 npm install echarts --save2、获取省市json数据 https://datav.aliyun.com/portal/school/atlas/area_selector 通过 阿里旗下的高…

简述Redis备份策略以及对应的实现机制

引言 Redis作为高性能的内存数据库,数据的安全性至关重要。一旦数据丢失,可能会对业务造成重大影响。因此,备份Redis数据是每个Redis使用者都必须考虑的问题。本文将介绍Redis的备份策略以及对应的实现机制。 一、备份策略 1.1 定期备份 …

easycython和cython将py编译为pyd对比

前提了解 为了实验的准确性,在全过程使用的python环境版本都为同一版本 easycython和cython编译为pyd文件的不同在于,easycython编译的原始文件后缀为pyx,cython编译的原始文件为py 1.cython 1.1原始文件 def ZWHCythonTest():print(&qu…

怎么用Facebook找客户?Facebook开发客户攻略分享

跨境人最了解的电商平台之一就是Facebook了,说到Facebook,它拥有超过20亿的活跃用户,所以你可以在这个平台上面找到更多的潜在客户。今天的文章就主要分享用Facebook开发客户的方法,全是干货,建议收藏! 一、…

2024 年政府和技术预测

新的一年即将来临,这意味着专家、技术专家和专栏作家应该尝试预测 2024 年政府和技术即将出现的一些最大趋势。今年可能使这些预测变得更加困难的是事实上,许多技术正在以惊人的速度向前发展。在某些情况下,过去需要多年才能慢慢发生的变化现…

LLM之RAG实战(九)| 高级RAG 03:多文档RAG体系结构

在RAG(检索和生成)这样的框架内管理和处理多个文档有很大的挑战。关键不仅在于提取相关内容,还在于选择包含用户查询所寻求的信息的适当文档。基于用户查询对齐的多粒度特性,需要动态选择文档,本文将介绍结构化层次检索…

腾讯云轻量服务器和云服务器区别对比(超详细)

腾讯云轻量服务器和云服务器CVM该怎么选?不差钱选云服务器CVM,追求性价比选择轻量应用服务器,轻量真优惠呀,活动 https://curl.qcloud.com/oRMoSucP 轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年,540元三…

设计模式-多例模式

设计模式专栏 模式介绍多例模式和单例模式的区别应用场景Spring中多例模式的优缺点代码示例Java实现多例模式Python实现多例模式 多例模式在spring中的应用 模式介绍 多例模式是一种创建型设计模式,属于对象创建类型。多例模式的特点是允许一个类有多个实例&#x…

西北大学844计算机类考研-25级初试高分总攻略

西北大学844计算机类考研-25级初试高分攻略 个人介绍 ​ 本人是西北大学22级软件工程研究生,考研专业课129分,过去一年里在各大辅导机构任职,辅导考研学生专业课844,辅导总时长达400小时,辅导学生超过20余人&#xf…

Android集成OpenSSL实现加解密-集成

导入so 将编译生成的 OpenSSL 动态库文件(.so 文件)复制到你的 Android 项目的 libs 目录中 导入头文件 将编译生成的include文件夹导入到项目中 build.gradle添加配置 defaultConfig {……testInstrumentationRunner "androidx.test.runner…