当前位置: 首页 > news >正文

AudioFramework面试题

蓝牙、usb、耳机设备连接后声音如何从该设备输出

首先会用通知AudioManager.java,告诉现在要设置usb了,然后会通过jni调到APM中到函数SetDeviceConnectionState中.
SetDeviceConnectionState中会分别调用checkOutputsForDevicecheckForDeviceAndOutputChanges

1**checkOutputsForDevice**作用是:

当新音频设备连接时,检查系统是否支持该设备,并确保有合适的输出流可以路由到该设备。如果没有现成的输出流可用,它会尝试打开新的输出流来支持该设备。
这样就打开了一个支持该设备的输出流了。那么接下来还需要把AudioTrack与AudioFlinger关联的共享内存配置到新打开的输出流中。

2**checkForDeviceAndOutputChanges->checkOutputForAllStrategies**作用是:

对所有的strategy分组声音,判断是否需要迁移到新的output, 如果需要则迁移对应Track到新的output,并且会调用invalidateStream将相关的Audiotrack设置成invalid,这样当再次使用AudioTrack.write时候,发现状态是invalid,会重新创建新的audiotrack绑定到新的output中。
这里涉及2个判断
判断是否需要迁移:
对于该strategy, 得到它的oldDevice, 进而得到它的outputs (srcOutputs);
对于该strategy, 得到它的newDevice, 进而得到它的outputs (dstOutputs);
如果这2个srcOutputs、dstOutputs不相同, 表示需要迁移

setOutputDevice 这需要操作HAL层

AudioTrack如何写数据到hal层

这一个过程涉及到三个进程间的数据传输,使用的数据拷贝技术是共享内存。
三个进程分别是app、audioserver、android.hardware.audio.
对于app与audioserver的通信主要设计两个模块一个是app端的AudioTrack,一个是audioserver端的AudioFlinger.
AudioTrack 在构建过程中会创建一个共享内存与AudioFlinger相关联。这样对于AudioTrack来说写数据就是使用通过obtainBuffer从共享内存中获取一块buffer,然后拷贝数据到buffer中然后在释放掉这个buffer
AudioFlinger会在playbackThread中持续的从activity的AudioTRck中获取buffer,然后读取buffer中的数据做处理,在释放掉这个buffer。 是一个生产者与消费者模型,
AudioServer与android.hardware.audio类似

AudioFlinger与AudioPolicyManager各自的功能:

简单的来说APM是策略的执行者,AF是策略的管理者。
APM 负责设备连接断开事件、管理设备路由策略、音量策略
AF负责所有音频流的混音与路由执行、管理playbackThread、recordThread等县城、直接与hal层交互、打开关闭音频设备、分配共享内存等

AudioTrack的播放流程

对于用户来说,使用AudioTrack的方式是创建一个AudioTrack对象,然后调用start方法,然后调用write方法写入数据的过程,
接下来说一下AudioTrack的构建过程。

AudioTrack的构建

  • 首先会根据AuidoFormat、sampleRate、channelCount来获取一个最小buffersize。
  • 然后会创建一个AudioTrack对象,传参包括audio三件套、buffersize、stream_type 还有一个Mode,这个Mode有两种模式,一种是MODE_STREAM,一种是MODE_STATIC。在AudioTrack中首先会调用getOutputForAttr获取到output,然后在AudioFlinger中创建共享内存并且会会在output对应到playbackThread中创建一个track。
  • 这样AudioTrack.write数据,playbackThread中可以通过创建到track 读取到写入的数据,这样就完成了数据传输。
  • 然后把所有从绑定到playbackTrread的track的数据mix在一起写入hal层。

音量设置流程

AudioManager.java 存在两个设置音量的API setStreamVolumeadjustStreamVolume
分为两种情况:硬件支持音量增益、硬件不支持音量增益

硬件不支持音量增益

在APM中会将设置下来的音量index通过解析出来的音量曲线,映射成增益,然后计算成振幅。设置到AudioFlinger中。在AudioFlinger中会把获取到的pcm数据与振幅值做运算从而实现音量的调整。

硬件支持音量增益

如果硬件支持音量增益,那么会直接调用到hal层中的setAudioPortConfig直接设置音量值。

eswin平台

会监听音量设置的广播,当接收到广播之后调用我们AudioOutput的私有接口,来完成音量的增益,我们的方案也是分为软件与硬件。 这么实现的目的是对DTV、HDMI的数据进行软件增益。

AudioFlinger、APM启动流程

AudioFlinger启动流程

  • AudioFlinger会创建EffectFactory与DeviceFactory的对象。 对于Device而言是分为devicelocal和devicehidl。在创建DeviceFactory对象中会根据字符串android.hardware.audio与IDevicesFactory来查找对应的服务,如果查找到了就dlopen一个libaudiohalxx.so.并且使用函数dlsym创建一个函数createIDeviceFactory这样我们就获取了一个hal层服务了。 到此AudioFlinger的启动流程就结束了

APM启动

  • 解析audio_policy_configuration.xml文件, 然后根据解析出来的数据配置策略与音量曲线等。
  • 调用函数onNewAudioModulesAvailable ,该函数主要做了两件事
    1.lodaHwModel 直接调用到audio_hw.c的adev_open函数
    2.openOutPut 创建输出流线程,并且打开输出通道 也就是调用audio_hw.c中openOutputStream,音频可以通过该输出通道输送个某个设备

相关文章:

  • 【动态规划】线性dp
  • Windows事件日志清除
  • spring mvc异步请求 sse 大文件下载 断点续传下载Range
  • 【Kafka基础】topics命令行操作大全:进阶命令解析(2)
  • OpenSceneGraph (OSG) 开发入门
  • LeetCode 热题 100 堆
  • 快速通过简单代码了解装饰模式
  • 在Unity中,如果物体上的脚本丢失,可以通过编写一个自定义编辑器脚本来查找并删除这些丢失的组件
  • DeepSeek 教我 C++ (7) :常见的一些未定义UB
  • 基于论文的大模型应用:基于SmartETL的arXiv论文数据接入与预处理(一)
  • 嵌入式硬件篇---TOF陀螺仪SPI液晶屏
  • Xorg内存管理机制深度解析
  • P1025 [NOIP 2001 提高组] 数的划分(DFS)
  • 【Linux】:HTTP协议
  • Spring RestTemplate修仙指南:从HTTP萌新到请求大能的终极奥义
  • 【VS Code】为什么vscode已经关闭,http://localhost:5173/还可以打开或项目还在运行,端口被占用
  • 软件工程面试题(三十二)
  • 如何计算卷积的复杂度、卷积层的参数量
  • 基于springboot+vue的漫画天堂网
  • frp内网穿透零基础详细教程
  • 视频网站模板下载/成都企业seo
  • wordpress 首页动画/无锡seo网站管理
  • 网站qq号获取/网络推广seo教程
  • 做直播网站用什么网上空间好/河南网站排名优化
  • 做英文版网站/百度推广费用多少
  • 五屏网站建设哪家有/做seo有什么好处