Android14音频子系统-Audio HAL分析

文章目录

      • 1)概述
      • 2)HAL的打开流程
      • 3)HAL库的实现(Qualcomm)
      • 4)tinyalsa
      • 5)数据结构
      • 6)代码流程

1)概述

1、回顾HAL、tinyalsa与linux driver的关系

2、与AudioFlinger的关系

3、

1、如何判断当前平台用的是哪个库?
android\hardware\libhardware\modules\audio
android\hardware\libhardware_legacy\audio\audio_hw_hal.cpp
可尝试注入错误代码,单编 验证一下 > 但编了也不一定会用!2、hal的作用?隐藏了什么细节,还是说只是为了符合Android框架而写?
>>播放数据之前的,设置的步骤和参数就是厂家要保护的内容3、HAL如何对接tinyalsa?
把tinyalsa当做一个库接口使用即可

2)HAL的打开流程

1、由AudioFlinger负责加载
android\frameworks\av\services\audioflinger\AudioFlinger.cpp
audio_module_handle_t AudioFlinger::loadHwModule(const char *name) //name为动态库的名字2、数据结构:
/android/frameworks/av/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h 
//接口与audio_hw_hal.cpp一一对应android\frameworks\av\services\audioflinger\AudioHwDevice.h //存放device
class AudioHwDevice {
private:const audio_module_handle_t mHandle;const char * const          mModuleName;sp<DeviceHalInterface>      mHwDevice;const Flags                 mFlags;
};3、以aidl / hidl为例,传统hal实现则直接使用hw_get_module得到对应的库
AudioHwDevice* AudioFlinger::loadHwModule_l(const char *name)
mDevicesFactoryHal = DevicesFactoryHalInterface::create(); //根据版本选择aidl / hidl进程4、
android\frameworks\av\media\libaudiohal\FactoryHal.cpp
void *createPreferredImpl(bool isDevice) {
if (createHalService(std::max(*ifaceVersionIt, *siblingVersionIt), isDevice,&rawInterface)) {return rawInterface;}
}mDevicesFactoryHal->openDevice(name, &dev);
--AServiceManager_waitForService(serviceName.c_str()); 5、厂商实现的Audio aidl hal service在哪里?
android\hardware\interfaces\audio\aidl\default\main.cpp
原本传统hal库由audio policy解析audio_policy_config而来,Audio aidl hal service也要去解析audio_policy_config去dlopen库?按理来说是的

3)HAL库的实现(Qualcomm)

1、目录介绍:
Qualcomm开源的hal实现
android\hardware\qcom\audio\hal //HAL新架构
android\hardware\qcom\audio\legacy\alsa_sound //HAL旧架构
android\hardware\qcom\audio\legacy\libalsa-intf //alsa-lib2、由于Android系统的发展变化(这些混合的代码 实在让人看着难受,还费时间去对比筛选),存在多种架构
1)hal实现分为旧架构和新架构,官方实现的demo代码对应路径,厂商需要根据这个去填充自家代码实现
旧架构:android\hardware\libhardware_legacy
新架构:android\hardware\libhardware\modules\audio2)alsa-lib与tinyalsa
在Android 4.0之前是使用这alsa-lib接口,之后简化演变成现在的tinyalsa
qcom实现的alsa-lib : android\hardware\qcom\audio\legacy\libalsa-intf
tinyalsa :android\external\tinyalsa本文以HAL旧架构 + tinyalsa为例子分析hal实现3、通信模型大致如下
AudioFlinger -> aidl -> hal -> hal库(qualcomm)  -> tinyalsa -> linux driver4、常见音效:
音质:acoustics
音频后处理效果:Post Processing Effects
强化低频响应:Bass Boost
动态范围压缩:Dynamic Range Compression
虚拟环绕声:Virtualizer
均衡器:EQ5、submix
虚拟设备,实现内部音频流混合与重定向,支持屏幕录制、音频转发等高级功能
AudioUsbALSA.cpp -> 外接USB声卡6、基本代码分析
1)HAL入口函数 - 谁来调用?AudioFlinger
static int legacy_adev_open(const hw_module_t* module, const char* name,hw_device_t** device)
2)
static struct hw_module_methods_t legacy_audio_module_methods = {open: legacy_adev_open
};struct legacy_audio_module HAL_MODULE_INFO_SYM = {module: {common: {tag: HARDWARE_MODULE_TAG,module_api_version: AUDIO_MODULE_API_VERSION_0_1,hal_api_version: HARDWARE_HAL_API_VERSION,id: AUDIO_HARDWARE_MODULE_ID,name: "LEGACY Audio HW HAL",author: "The Android Open Source Project",methods: &legacy_audio_module_methods,dso : NULL,reserved : {0},},},
};3)hwif 即厂商实现的 对接hal接口
struct legacy_stream_out {struct audio_stream_out stream;AudioStreamOut *legacy_out;
};struct legacy_stream_in {struct audio_stream_in stream;AudioStreamIn *legacy_in;
};static int adev_open_output_stream()
{out->legacy_out = ladev->hwif->openOutputStreamWithFlags(devices, flags,(int *) &config->format,&raw_channel_mask,&config->sample_rate, &status);
}4)AudioHardwareALSA()构造函数中
打开库ro.hardware.alsa.default
AudioHardwareALSA()
{hw_device_t* device;err = module->methods->open(module, ALSA_HARDWARE_NAME, &device);if (err == 0) {mALSADevice = (alsa_device_t *)device;mALSADevice->init(mALSADevice, mDeviceList);}
}ssize_t AudioStreamOutALSA::write(const void *buffer, size_t bytes)
{n = pcm_write(mHandle->handle, (char *)buffer + sent, period_size);
}5)
#define HAL_MODULE_INFO_SYM HWI  //hal module info
#define HAL_MODULE_INFO_SYM_AS_STR "HMI" //#define ALSA_HARDWARE_MODULE_ID "alsa"
#define ALSA_HARDWARE_NAME      "alsa"6)alsa_handle_t
typedef List < alsa_handle_t > ALSAHandleList;struct alsa_handle_t {alsa_device_t *module;uint32_t devices;strcut pcm *handle;snd_pcm_format_t format;
}struct alsa_device_t {hw_device_t common;status_t (*init)(alsa_device_t *, ALSAHandleList &);status_t (*open)(alsa_handle_t *);...void (*setVoiceVolume)(int);
}typedef struct hw_deivce_t {struct hw_module_t* module;int (*close)(struct hw_device_t* device);
} hw_device_t;

4)tinyalsa

1、tinyalsa这套框架带来了什么?
>>操作linux driver需要open/read/write,tinyalsa根据asoc协议封装对应的操作,提供统一接口给到hal,hal只需少量参数即可操作pcm设备节点,实现功能2、测试工具tinyplay/tinycap/tinymix
源码位置:
android\external\tinyalsa\tinyplay.c
板卡位置
/system/bin/tinyplay  //播放工具
/system/bin/tinycap //录音工具
/system/bin/tinymix //控制工具(设置音量等操作),注意不是mix混音示例:tinyplay /data/M1F1-int16WE-AFsp.wav -D 1 -d 13、音频格式:
1)PCM与RAW介绍 : https://blog.csdn.net/weixin_42654603/article/details/143757958
2)tiny只支持wav格式?> 仅支持 PCM(原始数据格式)/ RAW(直接从音频源-如MIC,不经过编码和压缩的原始数据)格式
3)*.wav :Waveform audio File Format (windows系统的标准音频格式之一) - 不涉及加解密,是PCM流 储存的文件格式(在PCM流的基础上加一些控制信息)
4)常说的DOlby音效是什么格式?一般采用AC-3编码技术
5)WACE Sample Files下载 : https://blog.csdn.net/touzani/article/details/16553284、在TV上,digital output选择PCM和RAW 又分别代表什么?
PCM:会将音频数据 转换 PCM流,兼容绝大多数音频设备;
RAM:不会处理,直接输出给音频设备,音频设备要求很高;5、tinymix的使用
1)查看tinymix可控的寄存器列表
root@# tinymix
Mixer name: 'audiocodec'
Number of controls: 16
ctl type num name          value
1   INT  1  "digital volume" 0
2   INT  1  "LINEIN to output mixer gain control" 3
3   BOOL 1  "LINEOUT Switch" On
...2)设置音量
tinymix "LINEOUT volume" "2"

5)数据结构

1、module与device
在这里插入图片描述

1)qcom_audio_device与audio_hw_device的"继承"用法

这样设计的目的是什么?为什么转换来转换去?
struct qcom_audio_device {struct audio_hw_device device; //向上层提供标准接口struct AudioHardwareInterface *hwif; //向下是指向厂商实现的接口
};先来看看如何使用
static int qcom_adev_open(const hw_module_t* module, const char* name,hw_device_t** device)
{...qadev->device.init_check = adev_init_check;qadev->hwif = createAudioHardware();...*device = &qadev->device.common; //将构造好的device返回给上层调用者保存
}static int adev_init_check(const struct audio_hw_device *dev)
{const struct qcom_audio_device *qadev = to_cladev(dev); //将上层传递下来的device转换一下,相当于父子指针转换return qadev->hwif->initCheck(); //调用厂家实现的接口
}小结:向上提供的接口需要是稳定的,具体的实现则由厂商自行设计,这样是灵活的
1)父子对象可以互相转换,对于上层和hal可以用同一个指针地址,不用额外设计对应关系;
2)如果不分开audio_hw_device、AudioHardwareInterface两个结构体,则厂商的灵活性会差些,反之厂商可以根据实际情况去调整,更加灵活;

2、stream音频流

在这里插入图片描述

1)HAL库的qcom_stream_out和qcom_stream_in类设计

struct qcom_stream_out {struct audio_stream_out stream; //向上提供接口AudioStreamOut *qcom_out; //指向厂家的接口 AudioStreamOutALSA
};struct qcom_stream_in {struct audio_stream_in stream; //向上提供接口AudioStreamIn *qcom_in; //指向厂家的接口 AudioStreamInALSA
};设计目的与qcom_audio_device同理

2)qcom_stream_out与AudioStreamOutALSA的继承""用法

1、out->qcom_out = qadev->hwif->openOutputStream(devices,..);
2、AudioStreamOut * AudioHardwareALSA::openOutputStream(){
AudioStreamOutALSA *out = 0;
...
return out;
}
先把父类"继承"过来,再将其它子类独有成员一一 赋值

3)类的层级关系设计如下
handle(module的容器) -> module -> device -> stream
device //代表一个音频设备
stream //由于音频流操作颇多,抽象出单独的类,负责控制音频流,播放,暂停等

3、AlSAMixer与ALSAControl
在这里插入图片描述

1)主要作用是读写设备节点“controlC0”,设置声卡参数

6)代码流程

在这里插入图片描述

2、上层三个步骤使用声卡播放

qcom_adev_open() //hal层的open,分配资源
adev_open_output_session() // 打开声卡设备,构造stream方法
qcom_stream_out->stream.write() //写声卡数据

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

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

相关文章

前端与 Spring Boot 后端无感 Token 刷新 - 从原理到全栈实践

&#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Micro麦可乐的博客 &#x1f425;《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程&#xff0c;入门到实战 &#x1f33a;《RabbitMQ》…

【AI智能体】新手教程-通过 Chat SDK 搭建网页在线客服

通过扣子搭建的智能体可以一键发布为 Chat SDK&#xff0c;快速部署到你的自建网站中&#xff0c;作为在线智能客服面向网站的用户提供 AI 答疑服务。本文档介绍通过 Chat SDK 搭建网页版在线客服的详细操作步骤。 场景说明 网站作为企业和组织与用户互动的重要平台&#xff…

flask静态资源与模板页面、模板用户登录案例

案例代码 import flask# template_folder 模板文件夹(静态页面 html页面渲染) # static_folder 静态资源文件夹主要存放的是类似静态数据、音频、视频、图片等 app flask.Flask(__name__, static_folderstatic, template_foldertemplate)app.route(/) def index():# render_t…

【工具教程】识别PDF中文字内容,批量识别文字并保存到Excel表格中的操作步骤和方法

在日常办公和文件管理中&#xff0c;我们常常会遇到需要处理大量 PDF 文件的情况。有时&#xff0c;为了更好地管理和查找这些文件&#xff0c;需要根据 PDF 文件中特定区域的文字内容对文件进行重命名。例如&#xff0c;在企业档案管理中&#xff0c;合同文件可能需要根据合同…

重生学AI第十三集:初识神经网络之Conv2d

终于该学习神经网络的搭建了&#xff0c;开心&#xff0c;嘻嘻 学习神经网络离不开torch.nn&#xff0c;先把他印在脑子里&#xff0c;什么是torch.nn?他是Pytorch的一个模块&#xff0c;包含了大量构建神经网络需要的类和方法&#xff0c;就像前面学习的torch.utils&#xf…

学习C++、QT---07(C++的权限、C++的引用)

每日一言 你解决的每一个难题&#xff0c;都是在为未来的自己解锁新技能。 权限的讲解 这边呢我们利用银行的一个案例来讲解权限的奥秘 权限指的是public、private 、protected 就是这三种权限&#xff0c;因此有这一张表进行分清他们之间的区别和联系 但是我们在平时的话会因…

全球化短剧平台全栈技术架构白皮书:多区域部署、智能分发与沉浸式体验的完整解决方案

一、全球化基础架构深度设计 全球网络基础设施构建 采用多活数据中心部署模式&#xff0c;在北美&#xff08;弗吉尼亚&#xff09;、欧洲&#xff08;法兰克福&#xff09;、亚太&#xff08;新加坡&#xff09;建立三大核心枢纽节点 构建混合CDN网络&#xff0c;整合AWS Clo…

深入剖析 LGM—— 开启高分辨率 3D 内容创作新时代

一、引言 在当今数字化时代&#xff0c;3D 内容创作的需求如井喷般增长&#xff0c;从游戏开发中绚丽多彩的虚拟世界&#xff0c;到影视制作里震撼人心的特效场景&#xff0c;再到工业设计中精准无误的产品原型&#xff0c;3D 技术无处不在。然而&#xff0c;传统 3D 内容创作…

从用户到社区Committer:小米工程师隋亮亮的Apache Fory成长之路

Apache Fory 是一个基于JIT和零拷贝的高性能多语言序列化框架&#xff0c;实现了高效紧凑的序列化协议&#xff0c;提供极致的性能、压缩率和易用性。在多语言序列化框架技术领域取得了重大突破&#xff0c;推动序列化技术步入高性能易用新篇章&#xff01;这一切&#xff0c;都…

【Koa系列】10min快速入门Koa

简介 koa是基于node开发的一个服务端框架&#xff0c;功能同express&#xff0c;但更小巧简单。 官方仓库地址&#xff1a;https://github.com/koajs/koa 创建项目 创建文件夹nodeKoa&#xff0c;执行以下脚本 npm init -y npm i koa npm i nodemon 基础示例 创建一个服…

IDEA与通义联合:智能编程效率革命

IDEA与通义联合&#xff1a;智能编程效率革命 当最强Java IDE遇上顶尖AI助手&#xff0c;会碰撞出怎样的生产力火花&#xff1f; 思维导图解读&#xff1a;智能编程工作流 #mermaid-svg-uTAcSs1kBBmDwGfM {font-family:"trebuchet ms",verdana,arial,sans-serif;font…

Docker 数据持久化完全指南:Volume、Bind Mount 与匿名卷

Docker 数据持久化完全指南&#xff1a;Volume、Bind Mount 与匿名卷 引言 在 Docker 中&#xff0c;容器的文件系统默认是临时的&#xff0c;容器删除后数据也会丢失。为了实现数据持久化&#xff0c;Docker 提供了多种存储方式&#xff0c;主要包括&#xff1a; docker vo…

OSS跨区域复制灾备方案:华东1到华南1的数据同步与故障切换演练

1. 引言 对象存储服务&#xff08;OSS&#xff09;已成为现代数据架构的核心组件。随着业务全球化&#xff0c;跨区域数据灾备从“可选”变为“必选”。本文以阿里云OSS为实验环境&#xff0c;实战演练华东1&#xff08;杭州&#xff09;到华南1&#xff08;深圳&#xff09;的…

前端登录状态管理:主流方案对比与安全实践指南

根据目前业内前端登录状态管理的主流设计方案&#xff0c;及其演进趋势进行汇总&#xff0c;生成主要包括如下内容的报告&#xff1a; 登录状态保持的基础原理&#xff1a;从HTTP无状态问题出发解析技术需求&#xff0c;使用表格对比核心挑战。主流技术方案对比&#xff1a;详…

动手用 Web 实现一个 2048 游戏

文章目录 为什么选择 2048&#xff1f;关键技术点与算法详解HTML 结构&#xff1a;搭建游戏界面CSS 样式&#xff1a;美化游戏界面JavaScript 核心逻辑&#xff1a;驱动游戏运行1&#xff09;数据结构&#xff1a;二维数组表示游戏网格2&#xff09;核心算法&#xff1a;添加随…

frp v0.62.1内网穿透搭建和使用

官网&#xff1a;https://gofrp.org/zh-cn/ Github&#xff1a;https://github.com/fatedier/frp 开源项目 frp frp 是一种快速反向代理&#xff0c;允许您将位于 NAT 或防火墙后面的本地服务器公开给 Internet。目前支持 TCP 和 UDP&#xff0c;以及 HTTP 和 HTTPS 协议&…

如何使用 USB 数据线将文件从 PC 传输到 iPhone

虽然用 USB 数据线将文件从 PC 传输到安卓设备非常容易&#xff0c;但对于 iPhone 用户来说&#xff0c;情况就不同了。不过&#xff0c;幸运的是&#xff0c;我们找到了三种可靠的方法&#xff0c;可以使用 USB 数据线将文件从 PC 传输到 iPhone&#xff0c;让您轻松完成这项任…

【C++高阶三】AVL树深度剖析

【C高阶三】AVL树深度剖析 1.什么是AVL树2.AVL树的实现2.1节点类和基本结构2.2插入2.3旋转处理2.3.1左单旋2.3.2右单旋2.3.3左右双旋2.3.4右左双旋 1.什么是AVL树 AVL树也叫二叉搜索平衡树 因为二叉搜索树如果插入顺序是有序的&#xff0c;那么这棵树的查找效率将会是O(N)&…

LangChain 文本分割器深度解析:从原理到落地应用(上)

食用指南 LangChain 作为大语言模型应用开发框架&#xff0c;文本分割器是其核心组件之一&#xff0c;本文以此作为切入点&#xff0c;详细介绍文本分割的作用、策略、以及常见的文本切割器应用。考虑到篇幅过长&#xff0c;故拆分为上、中、下三篇&#xff0c;后续会在中篇介…

【Java高频面试问题】高并发篇

【Java高频面试问题】高并发篇 Kafka原理核心组件高吞吐核心机制高可用设计 Kafka 如何保证消息不丢失如何解决Kafka重复消费一、生产者端&#xff1a;根源防重二、消费者端&#xff1a;精准控制三、业务层&#xff1a;幂等性设计&#xff08;核心方案&#xff09; 如何解决Kaf…