Android音频架构
音频基础知识
声音有哪些重要属性呢?
响度(Loudness)
响度就是人类可以感知到的各种声音的大小,也就是音量。响度与声波的振幅有直接关系。
音调(Pitch)
音调与声音的频率有关系,当声音的频率越大时,人耳所感知到的音调就越高,否则就越低。
音色(Quality)
同一种乐器,使用不同的材质来制作,所表现出来的音色效果是不一样的,这是由物体本身的结构特性所决定的。
如何将各种媒体源数字化呢?
音频采样
将声波波形信号通过ADC转换成计算机支持的二进制的过程叫做音频采样(Audio Sampling)。采样(Sampling)的核心是把连续的模拟信号转换成离散的数字信号。
样本(Sample)
这是我们进行采样的初始资料,比如一段连续的声音波形。
采样器(Sampler)
采样器是将样本转换成终态信号的关键。它可以是一个子系统,也可以指一个操作过程,甚至是一个算法,取决于不同的信号处理场景。理想的采样器要求尽可能不产生信号失真。
量化(Quantization)
采样后的值还需要通过量化,也就是将连续值近似为某个范围内有限多个离散值的处理过程。因为原始数据是模拟的连续信号,而数字信号则是离散的,它的表达范围是有限的,所以量化是必不可少的一个步骤。
编码(Coding)
计算机的世界里,所有数值都是用二进制表示的,因而我们还需要把量化值进行二进制编码。这一步通常与量化同时进行。
奈奎斯特采样理论
“当对被采样的模拟信号进行还原时,其最高频率只有采样频率的一半”。
换句话说,如果我们要完整重构原始的模拟信号,则采样频率就必须是它的两倍以上。比如人的声音范围是2~ 20kHZ,那么选择的采样频率就应该在40kHZ左右,数值太小则声音将产生失真现象,而数值太大也无法明显提升人耳所能感知的音质。
录制过程
音频采集设备(比如Microphone)捕获声音信息。
模拟信号通过模数转换器(ADC)处理成计算机能接受的二进制数据。
根据需求进行必要的渲染处理,比如音效调整、过滤等等。
处理后的音频数据理论上已经可以存储到计算机设备中了,比如硬盘、USB设备等等。不过由于这时的音频数据体积相对庞大,不利于保存和传输,通常还会对其进行压缩处理。比如我们常见的mp3音乐,实际上就是对原始数据采用相应的压缩算法后得到的。压缩过程根据采样率、位深等因素的不同,最终得到的音频文件可能会有一定程度的失真,另外,音视频的编解码既可以由纯软件完成,也同样可以借助于专门的硬件芯片来完成。
回放过程
从存储设备中取出相关文件,并根据录制过程采用的编码方式进行相应的解码。
音频系统为这一播放实例选定最终匹配的音频回放设备。
解码后的数据经过音频系统设计的路径传输。
音频数据信号通过数模转换器(DAC)变换成模拟信号。
模拟信号经过回放设备,还原出原始声音。
Audio框架
APP
厂商根据特定需求自己写的一个音乐播放器软件等等。
Framework
Android也提供了另两个相似功能的类,即AudioTrack和AudioRecorder,MediaPlayerService内部的实现就是通过它们来完成的,只不过MediaPlayer/MediaRecorder提供了更强大的控制功能,相比前者也更易于使用。除此以外,Android系统还为我们控制音频系统提供了AudioManager、AudioService及AudioSystem类。这些都是framework为便利上层应用开发所设计的。
Libraries
framework只是向应用程序提供访问Android库的桥梁,具体功能实现放在库中完成。比如上面的AudioTrack、AudioRecorder、MediaPlayer和MediaRecorder等等在库中都能找到相对应的类。
1、frameworks/av/media/libmedia【libmedia.so】
2、frameworks/av/services/audioflinger【libaudioflinger.so】
3、frameworks/av/media/libmediaplayerservice【libmediaplayerservice.so】
4. HAL
从设计上来看,硬件抽象层是AudioFlinger直接访问的对象。这说明了两个问题,一方面AudioFlinger并不直接调用底层的驱动程序;另一方面,AudioFlinger上层模块只需要与它进行交互就可以实现音频相关的功能了。因而我们可以认为AudioFlinger是Android音频系统中真正的“隔离板”,无论下面如何变化,上层的实现都可以保持兼容。
音频方面的硬件抽象层主要分为两部分,即AudioFlinger和AudioPolicyService。实际上后者并不是一个真实的设备,只是采用虚拟设备的方式来让厂商可以方便地定制出自己的策略。抽象层的任务是将AudioFlinger/AudioPolicyService真正地与硬件设备关联起来,但又必须提供灵活的结构来应对变化——特别是对于Android这个更新相当频繁的系统。比如以前Android系统中的Audio系统依赖于ALSA-lib,但后期就变为了tinyalsa,这样的转变不应该对上层造成破坏。因而Audio HAL提供了统一的接口来定义它与AudioFlinger/AudioPolicyService之间的通信方式,这就是audio_hw_device、audio_stream_in及audio_stream_out等等存在的目的,这些Struct数据类型内部大多只是函数指针的定义,是一些“壳”。当AudioFlinger/AudioPolicyService初始化时,它们会去寻找系统中最匹配的实现(这些实现驻留在以audio.primary.*,audio.a2dp.*为名的各种库中)来填充这些“壳”。根据产品的不同,音频设备存在很大差异,在Android的音频架构中,这些问题都是由HAL层的audio.primary等等库来解决的,而不需要大规模地修改上层实现。换句话说,厂商在定制时的重点就是如何提供这部分库的高效实现了。
AudioRcorder和AudioTrack是Audio系统对外提供API类,AudioRcorder主要用于完成音频数据的采集,而AudioTrack则是负责音频数据的输出。AudioFlinger管理着系统中的输入输出音频流,并承担着音频数据的混合,通过读写Audio硬件实现音频数据的输入输出功能;AudioPolicyService是Audio系统的策略控制中心,掌管系统中声音设备的选择和切换、音量控制等。
Audio 系统代码:
(1)Audio 的Java 部分
frameworks/base/media/java/android/media
与Audio 相关的Java包是android.media,主要包含AudioManager和Audio 系统的几个类。
(2)Audio 的JNI 部分
frameworks/base/core/jni
生成库libandroid_runtime.so,Audio 的JNI是其中的一个部分。
(3)Audio 的框架部分
frameworks/base/include/media/
frameworks/base/media/libmedia/
这部分内容被编译成库libmedia.so,实现Audio系统的核心框架,同时提供了IAudioFlinger 类接口。在这个类中,可以获得IAudioTrack 和IAudioRecorder 两个接口,分别用于声音的播放和录制。AudioTrack 和AudioRecorder 分别调用IAudioTrack 和IAudioRecorder 来实现。IAudioFlinger.h、IAudioTrack.h 和IAudioRecorder.h 这三个接口通过下层来实现。AudioSystem.h、AudioTrack.h 和AudioRecorder.h 是对上层提供的接口,它们既供本地程序调用,也可以通过JNI 向Java 层提供接口。从功能上看,AudioSystem 负责的是Audio 系统的综合管理功能,而AudioTrack 和AudioRecorder 分别负责音频数据的输出和输入,即播放和录制。另外一个接口是IAudioFlingerClient,它作为向IAudioFlinger中注册的监听器,相当于使用回调函数获取IAudioFlinger运行时信息。
(4)Audio Flinger
frameworks/base/libs/audioflinger
这部分内容被编译成库libaudioflinger.so,它是Audio系统的本地服务部分。
(5)Audio 的硬件抽象层接口
hardware/libhardware_legacy/include/hardware/
1、Audio使用JNI和Java对上层提供接口,JNI部分通过调用libmedia库提供的接口来实现。
2、 Audio 本地框架类是libmedia.so的一个部分,这些Audio框架类对上层提供接口,由下层的本地代码去实现。
3、AudioFlinger继承libmeida中的接口,提供实现库libaudiofilnger.so。这部分内容没有自己的对外头文件,上层调用的只是libmedia本部分的接口,但实际调用的内容是libaudioflinger.so。
4、Audio的硬件抽象层提供到硬件的接口,供AudioFlinger调用。Audio的硬件抽象层实际上是各个平台开发过程中需要主要关注和独立完成的部分。
在Android的Audio系统中,无论上层还是下层,都使用一个管理类和输出输入两个类来表示整个Audio系统,输出输入两个类负责数据通道。在各个层次之间具有对应关系:
在libhardware_legacy中定义的音频相关的硬件抽象层数据结构legacy_audio_device、legacy_stream_out、legacy_stream_in如下:
音频设备描述符:
struct legacy_audio_device {
struct audio_hw_device device;
struct AudioHardwareInterface *hwif;
};
音频输出描述符:
struct legacy_stream_out {
struct audio_stream_out stream;
AudioStreamOut *legacy_out;
};
音频输入描述符:
struct legacy_stream_in {
struct audio_stream_in stream;
AudioStreamIn *legacy_in;
};
通过上表比较可以看出,audio_hw_device和AudioHardwareInterface、audio_stream_out和AudioStreamOut、audio_stream_in和AudioStreamIn定义的接口基本一致,这是为了兼容Android先前版本。
AudioHardwareInterface.cpp负责实现基础类和管理,而AudioHardwareGeneric.cpp、AudioHardwareStub.cpp、AudioDumpInterface.cpp和A2dpAudioInterface.cpp各自代表一种Auido硬件抽象层的实现。
AudioHardwareGeneric.cpp:实现基于特定驱动的通用Audio硬件抽象层,这是一个真正能够使用的Audio硬件抽象层,但是它需要Android的一种特殊的声音驱动程序的支持。
AudioHardwareStub.cpp:实现Audio硬件抽象层的一个桩,这个实现不操作实际的硬件和文件,它所进行的是空操作。
AudioDumpInterface.cpp:实现输出到文件的Audio硬件抽象层,支持Audio的输出功能,不支持输入功能。
A2dpAudioInterface.cpp:实现蓝牙音频的Audio硬件抽象层。
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/yangwen123/article/details/39502689
相关文章:

Android音频架构
音频基础知识 声音有哪些重要属性呢? 响度(Loudness) 响度就是人类可以感知到的各种声音的大小,也就是音量。响度与声波的振幅有直接关系。 音调(Pitch) 音调与声音的频率有关系,当声音的频率越大时,人耳所感知到的音调就越高&a…...

AI 智享直播:开启直播新篇,引领未来互动新趋势!
在数字化浪潮席卷全球的今天,AI技术正以不可阻挡之势渗透进我们生活的方方面面,从智能家居到自动驾驶,从医疗健康到金融服务,无一不彰显着其强大的影响力和无限的潜力。而在这一波科技革新的洪流中,直播行业也迎来了前…...

【AIGC】国内AI工具复现GPTs效果详解
博客主页: [小ᶻZ࿆] 本文专栏: AIGC | GPTs应用实例 文章目录 💯前言💯本文所要复现的GPTs介绍💯GPTs指令作为提示词在ChatGPT实现类似效果💯国内AI工具复现GPTs效果可能出现的问题解决方法解决后的效果 …...

Charles抓https包-配置系统证书(雷电)
1、导出证书 2、下载 主页上传资源中有安装包,免费的 openssl 安装教程自己搜 openssl x509 -subject_hash_old -in charles.pem 3、修改证书名、后缀改成点0 雷电打开root和磁盘写入 4、导入雷电证书根目录 证书拖进去,基本就完成了ÿ…...

在卷积神经网络中真正占用内存的是什么
在卷积神经网络(CNN)中,占用内存的主要部分包括以下几个方面: 1. 模型参数(Weights and Biases) CNN 中的权重和偏置(即模型的参数)通常是占用内存的最大部分。具体来说࿱…...

2024 ECCV | DualDn: 通过可微ISP进行双域去噪
文章标题:《DualDn: Dual-domain Denoising via Differentiable ISP》 论文链接: DualDn 代码链接: https://openimaginglab.github.io/DualDn/ 本文收录于2024ECCV,是上海AI Lab、浙江大学、香港中文大学(薛天帆等…...

Elasticsearch 和 Kibana 8.16:Kibana 获得上下文和 BBQ 速度并节省开支!
作者:来自 Elastic Platform Product Team Elastic Search AI 平台(Elasticsearch、Kibana 和机器学习)的 8.16 版本包含大量新功能,可提高性能、优化工作流程和简化数据管理。 使用更好的二进制量化 (Better Binary Quantizatio…...

Linux 抓包工具 --- tcpdump
序言 在传输层 Tcp 的学习中,我们了解了 三次握手和四次挥手 的概念,但是看了这么多篇文章,我们也只是停留在 纸上谈兵。 欲知事情如何,我们其实可以尝试去看一下具体的网络包的信息。在这篇文章中将向大家介绍,在 L…...

Vector Optimization – Stride
文章目录 Vector优化 – stride跳跃Vector优化 – stride跳跃 This distance between memory locations that separates the elements to be gathered into a single register is called the stride. A stride of one unit is called a unit-stride. This is equivalent to se…...

git config是做什么的?
git config是做什么的? git config作用配置级别三种配置级别的介绍及使用,配置文件说明 使用说明git confi查看参数 默认/不使用这个参数 情况下 Git 使用哪个配置等级? 一些常见的行为查看配置信息设置配置信息删除配置信息 一些常用的配置信…...

计算机网络(7) 数据链路层
数据链路层的内容不学不知道,一学真的是吓一跳哦,内容真的挺多的,但是大家不要害怕,总会学完的。 还有由于数据链路层的内容太多,一篇肯定是讲不完的所以我决定把它分为好几个部分进行学习与讲解。大家可以关注以后文…...

2024年秋国开电大《建筑结构试验》形考任务1-4
形考作业一 1.下列选项中,( )项不属于科学研究性试验。 答案:检验结构的质量,说明工程的可靠性 2.下列各项,( )项不属于工程鉴定性试验。 答案:验证结构计算理论的假定 3.按试验目的进行分类,可将结构试验分成( )。 答案:工程鉴定性试验和科学研究性试验…...

【MySQL】explain之type类型
explain的type共有以下几种类型,system、const、eq_ref、ref、range、index、all。 system:当表中只有一条记录并且该表使用的存储引擎的统计数据是精确的,比如MyISAM、Memory,那么对该表的访问方法就是system。 constÿ…...

Llama架构及代码详解
Llama的框架图如图: 源码中含有大量分布式训练相关的代码,读起来比较晦涩难懂,所以我们对llama自顶向下进行了解析及复现,我们对其划分成三层,分别是顶层、中层、和底层,如下: Llama的整体组成…...

Android onConfigurationChanged 基础配置
onConfigurationChanged 代替重建 0. **定义与基本用途**1. **具体使用场景 - 屏幕方向改变**2. **具体使用场景 - 键盘可用性改变**3. **具体使用场景 - 语言设置变更**4. **具体使用场景 - 屏幕密度变化**5. **具体使用场景 - 字体大小改变**6. **具体使用场景 - 屏幕尺寸变化…...

3. Sharding-Jdbc核⼼流 程+多种分⽚策略
1. Sharding-Jdbc 分库分表执⾏核⼼流程 Sharding-JDBC执行流程 1. SQL解析 -> SQL优化 -> SQL路由 -> SQL改写 -> SQL执⾏-> 结果归并 ->返回结果简写为:解析->路由->改写->执⾏->结果归并1.1 SQL解析 1. SQL解析过程分为词法解析…...

为什么财富的蓝图如此重要
我们生活在一个二元对立的世界里:上与下、明与暗、冷与热内与外、快与慢、左与右。这些还只是千百种对立之中的几个例子而已。 有了一个极端,表示一定同时有相对的另一端存在。有了右边不可能没有左边。 所以,在钱这件事上,有外…...

【云计算解决方案面试整理】1-2云计算基础概念及云计算技术原理
准备面云计算解决方案的岗位,整理了一些,也请大佬们指点。 文档分为 云计算基础概念、云计算技术原理、主流云计算平台(以天翼云为例)、云计算架构(弹性设计、高可用设计、高性能设计)、安全防护几个方面。 一、云计算基础概念 1.请简要解释一下什么是云计算? 简单说呢…...

循环语句 while()... 与 for()...(day11)
一、while()与do...while()... 循环语句: 通过循环语句可以反复执行一段代码多次 1、while循环: - 语法: while(①条件表达式){ ②语句... } - while语句在执行时, 先对条件表达式进行求值判断, 如果值为true&#…...

Mysql篇-三大日志
概述 undo log(回滚日志):是 Innodb 存储引擎层生成的日志,实现了事务中的原子性,主要用于事务回滚和 MVCC。 redo log(重做日志):是 Innodb 存储引擎层生成的日志,实现…...

MySQL的SQL书写顺序和执行顺序
老是忘记执行顺序,记录一下: 1. SQL语句的书写顺序 书写顺序通常是我们编写SQL查询时的顺序,主要包括以下关键字: SELECT:选择要查询的字段。FROM:指定数据来源表。JOIN(可选)&am…...

摄像机视频分析软件下载LiteAIServer视频智能分析软件抖动检测的技术实现
在现代社会中,视频监控系统扮演着至关重要的角色,其可靠性和有效性在很大程度上取决于视频质量。然而,由于多种因素,如摄像机安装不当、外部环境振动或视频信号传输的不稳定,视频画面常常出现抖动问题,这不…...

spring gateway 动态路由
##yml配置 spring:application:name: public-gateway # cloud: # gateway: # routes: # - id: mybatis-plus-test # 路由的唯一标识 # uri: http://192.168.3.188:9898 # 目标服务的地址 # predicates: # - Path/test/** # 匹配…...

除了 Postman,还有什么好用的 API 管理工具吗?
Postman在团队协作上的支持相对有限,且免费版本的功能较为基础,高级功能需要付费解锁。 为了寻找更加符合团队需求的解决方案,许多开发者开始探索其他API管理工具,其中Apifox便是备受推崇的选择之一。下面通过一个表格来简单了解…...

JAVA:探索 EasyExcel 的技术指南
1、简述 在 Java 开发中,Excel 文件的读写操作是一项常见的需求。阿里巴巴开源的 EasyExcel 提供了一种高效、简洁的解决方案,特别是在处理大规模数据时表现尤为突出。本文将详细介绍 EasyExcel 的优缺点、应用场景,并通过实例展示其基本用法…...

【数字图像处理+MATLAB】对图片进行伽马校正(Gamma Correction):使用幂律变换公式进行伽马变换
引言 伽马校正(Gamma Correction)是一种用于图像处理的技术,主要用于调整图像的亮度或对比度。其基本原理是对图像的每一个像素应用一个非线性变换,以更好地适应人眼的视觉感知。在数字图像处理中,伽马校正通常用于调…...

算法——螺旋矩阵II(leetcode59)
给你一个正整数 n ,生成一个包含 1 到 n^2所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 对于螺旋矩阵来讲难点主要在于行或列放置元素时的边界条件,我们遵循一个循环不变量原则在放置行或列元素时遵循左闭右开来放置元…...

以往运维岗本人面试真题分享
以下是本人面试运维岗的一些面试经历,在此做个记录分享 目录 TCP/IP三次握手 IPtables IPtables四表五链都是什么? nat端口如何做? 开放本机的80端口该如何做? 如何在单用户模式下引导Centos? nginx轮询模式都有…...

macOS解决U盘装完系统容量变小的问题
发现原来256GB容量的U盘在mac电脑上只显示34GB,想起来之前用该U盘装过系统,最终搜到了以下解决方案,在此记录: (1) 查看盘符列表,找到需要格式化的U盘,假设为disk4 diskutil list(2) 卸载分区disk4 disk…...

ORA-00257: archiver error
ORA-00257: archiver error 归档满问题: 报错: SQL> conn admin/admin ERROR: ORA-00257: archiver error. Connect internal only, until freed. Warning: You are no longer connected to ORACLE. 检查空间: SQL> select name, tot…...