之前在Android 4.4 音量调节流程分析(一)里已经有简单的分析音量控制的流程,今天想接着继续分析下音量大小计算的方法。对于任一播放文件而言其本身都有着固定大小的音量Volume_Max,而在AudioPolicyManagerBase.cpp文件中音量调节可以理解为在Volume_Max的基础上乘以系数κ(0≤κ≤1)。

现在对AudioPolicyManagerBase.cpp中volIndexToAmpl函数做具体分析,volIndexToAmpl的函数定义如下:

1 float AudioPolicyManagerBase::volIndexToAmpl(audio_devices_t device, const StreamDescriptor&streamDesc,2 intindexInUi)3 {4 device_category deviceCategory =getDeviceCategory(device);5 const VolumeCurvePoint *curve =streamDesc.mVolumeCurve[deviceCategory];6

7 //the volume index in the UI is relative to the min and max volume indices for this stream type

8 int nbSteps = 1 + curve[VOLMAX].mIndex -

9 curve[VOLMIN].mIndex;10 int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) /

11 (streamDesc.mIndexMax -streamDesc.mIndexMin);12

13 //find what part of the curve this index volume belongs to, or if it's out of bounds

14 int segment = 0;15 if (volIdx < curve[VOLMIN].mIndex) { //out of bounds

16 return 0.0f;17 } else if (volIdx

24 return 1.0f;25 }26

27 //linear interpolation in the attenuation table in dB

28 float decibels = curve[segment].mDBAttenuation +

29 ((float)(volIdx - curve[segment].mIndex)) *

30 ( (curve[segment+1].mDBAttenuation -

31 curve[segment].mDBAttenuation) /

32 ((float)(curve[segment+1].mIndex -

33 curve[segment].mIndex)) );34

35 float amplification = exp( decibels * 0.115129f); //exp( dB * ln(10) / 20 )

36

37 returnamplification;38 }

在该段代码内,主要是获取以下的7个变量值:

1.deviceCategory:Android系统中设备种类有如下三种,即DEVICE_CATEGORY_HEADSET,DEVICE_CATEGORY_SPEAKER & DEVICE_CATEGORY_EARPIECE。若当前使用Speaker播放音频流时,则deviceCategory即对应DEVICE_CATEGORY_SPEAKER;

2.curve:音量曲线是由Audio_Stream & device_Category两者共同决定,所有匹配类型都可以在sVolumeProfiles矩阵中获得,以Audio_Stream = AUDIO_STREAM_MUSIC & device_Category = DEVICE_CATEGORY_SPEAKER为例,则其对应的音量曲线为 sSpeakerMediaVolumeCurve;

sSpeakerMediaVolumeCurve:(以该音量曲线为例作数值计算)

1 constAudioPolicyManagerBase::VolumeCurvePoint2 AudioPolicyManagerBase::sSpeakerMediaVolumeCurve[AudioPolicyManagerBase::VOLCNT] ={3 {1, -59.1f}, {20, -48.3f}, {60, -24.4f}, {100, 0.0f}4 };

从sSpeakerMediaVolumeCurve数组可以知道是由4个点来将音量曲线分为4个部分,分别为1~20、20~60、60~100。其中每个点中参数含义为:

classVolumeCurvePoint

{public:int mIndex;//百分制下标

float mDBAttenuation;//衰减

};

3.nbSteps:为了避免计算时出现循环小数,系统中将UI界面VolumeIndex转化为0~100,以sSpeakerMediaVolumeCurve为例,curve[VOLMAX].mIndex = 100,curve[VOLMIN].mIndex = 1,所以nbSteps = 1 + 100 -1 = 100;

4.volIdx:volIdx的求解过程其实就是将UI界面的音量Index转化为百进制的过程,其中AudioStream对应的indexInUi_Max可以在AudioService.java中获得,STREAM_MUSIC对应数值为15,故streamDesc.mIndexMax = 15,streamDesc.mIndexMin = 0,则volIdx = (20/3)*indexInUi。

//AudioService.java/** @hide Maximum volume index values for audio streams*/

private static final int[] MAX_STREAM_VOLUME = new int[] {5, //STREAM_VOICE_CALL

7, //STREAM_SYSTEM

7, //STREAM_RING

15, //STREAM_MUSIC

7, //STREAM_ALARM

7, //STREAM_NOTIFICATION

15, //STREAM_BLUETOOTH_SCO

7, //STREAM_SYSTEM_ENFORCED

15, //STREAM_DTMF

15 //STREAM_TTS

};

5.segment:是用来确定UI音量界面上的VolumeIndex转化为百进制处于哪一个区间内。

6.decibels:VolumeIndex对应的音量衰减,单位为dB。其计算公式如下图所示:

若想实现speaker每音阶之间的衰减差为M(dB),其计算方法就是计算decibels_Index_N & decibels_Index_(N+1)之间的差值。为了方便计算,可以默认N & N+1属于同一segment,这样

因为curve[VOLMAX].mDBAttenuation一般为0,即不衰减状态(当然也有可能为负数,但不管怎样,curve[VOLMAX].mDBAttenuation是最容易确定的值),所以一般计算是从segment = 2开始计算,这样在60~100区间内Δdecibels的值就为:

Δdecibels = (20/3)*((0 - curve[2].mDBAttenuation)/(100 - 60)) = -(curve[2].mDBAttenuation/6)

令Δdecibels = M,则curve[2].mDBAttenuation = -6M,依次类推curve[1].mDBAttenuation = -12M,curve[0].mDBAttenuation = -15M。

7.amplification:放大/缩小倍数。将求得的decibels带入公式就可以直接求到,没有什么特别要说的。

总结:该篇文章以sSpeakerMediaVolumeCurve为例,描述了音量衰减值的计算过程。其它音量曲线调节可以按照该方法同样实现。

android 音量调节流程分析,Android 4.4 音量调节流程分析(二)相关推荐

  1. 【Android多媒体(重采样与混频)】从playback流程分析AudioResampler,AudioMixer

    文章大致内容介绍 本文主要讲述播放音乐流程,AudioResampler是如何生效的 播放流程 AudioMixer分析 从MixerThread分析 播放流程 在Android中间,如果使用硬解码O ...

  2. android 休眠唤醒驱动流程分析,Android 电源管理——gotosleep和userActivity关注

    一.Android power management应用层分析 Android提供了android.os.PowerManager类,该类用于控制设备的电源状态的切换. 该类对外有三个接口函数: 1. ...

  3. 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | RawDexFile.cpp 分析 | dvmRawDexFileOpen函数读取 DEX 文件 )

    文章目录 前言 一.RawDexFile.cpp 中 dvmRawDexFileOpen() 方法分析 前言 上一篇博客 [Android 逆向]整体加固脱壳 ( DexClassLoader 加载 ...

  4. 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | 查找 DexFile 对应的C代码 | dalvik_system_DexFile.cpp 分析 )

    文章目录 前言 一.查找 DexFile 对应的 C++ 代码 1.根据 Native 文件命名惯例查找 C++ 代码 2.根据方法名查找 二.dalvik_system_DexFile.cpp 源码 ...

  5. 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexFile loadDexFile 函数 | 构造函数 | openDexFile 函数 )

    文章目录 前言 一.DexFile.loadDexFile 函数分析 二.DexFile 构造函数分析 三.DexFile.openDexFile 函数分析 前言 上一篇博客 [Android 逆向] ...

  6. 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexPathList 中根据 File 加载 DexFile | loadDexFile 分析 )

    文章目录 前言 一.根据 File 加载 DexFile 二.DexPathList.loadDexFile 函数分析 前言 上一篇博客 [Android 逆向]整体加固脱壳 ( DexClassLo ...

  7. 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexPathList 构造函数分析 | makeDexElements 函数分析 )

    文章目录 前言 一.DexPathList 构造函数分析 二.DexPathList.makeDexElements 函数分析 三.Element 类分析 前言 上一篇博客 [Android 逆向]整 ...

  8. 【Android 逆向】逆向修改游戏应用 ( APK 解析工具 | 解包 -> 分析 -> 重打包 -> 签名 流程 )

    文章目录 一.APK 解析工具 二.解包 -> 分析 -> 重打包 -> 签名 流程 一.APK 解析工具 使用 [Android 逆向]使用 Python 编写 APK 批处理分析 ...

  9. android源码settings中显示所有正在运行进程流程分析

    下面我要分享一下这几天看源码中获得正在运行进程的简单流程: 也就是图中所看到的 首先我们看到的是settings下的application(应用程序)下的manageApplication(管理应用程 ...

  10. Android 系统(78)---《android framework常用api源码分析》之 app应用安装流程

    <android framework常用api源码分析>之 app应用安装流程 <android framework常用api源码分析>android生态在中国已经发展非常庞大 ...

最新文章

  1. 【计算机网络】计算机网络 OSI 参考模型 ( 计算机网络分层结构 | OSI 七层参考模型 | 应用层 | 表示层 | 会话层 | 传输层 | 网络层 | 数据链路层 | 物理层 )
  2. MySQL8小时连接超时断开问题
  3. referer htttp headers 统计信息 防盗链
  4. python用format保留三位小数_关于Python 保留小数使用format、%、round()、Decimal函数及format和%只能保留到六位问题...
  5. Mac 录制视频,并转为GIF格式
  6. LeetCode - 3Sum Closest
  7. C# RichTextBox 做简单的HTML代码编辑器 ---------左侧显示行号
  8. oracle数据modeling分类,由浅入深 NoSQL的五种主流数据模型
  9. 在Pandas DataFrame中重塑数据
  10. Spring Boot 2.x :通过 spring-boot-starter-hbase 集成 HBase
  11. 19 Tips For Everyday Git Use
  12. 陶哲轩实分析 习题 12.5.4,12.5.5
  13. 页面中引入js的几种方法
  14. (六)洞悉linux下的Netfilteriptables:如何理解连接跟踪机制?(2)
  15. android实现资源嗅探器手机版,OPPO Reno尝鲜Android Q教程来了
  16. 监视及系统响应的补充FMEA (FMEA-MSR)
  17. jpg图片怎么压缩大小?简单快捷的方法教给你
  18. 稳压二极管_百度百科
  19. 【论文精读】UV-SLAM: Unconstrained Line-based SLAM Using Vanishing Points for Structural Mapping
  20. “天罡”霸气侧漏,华为5G长驱直入

热门文章

  1. 【Beta阶段】第三次Scrum Meeting!
  2. 分层架构中各层之间关系如何界定,期待大家来讨论
  3. 對比加班時間和考勤時間,得出實際加班時長函数
  4. 年轻人的第一个自定义Springboot starter
  5. sftp本地上传和远程下载
  6. 云数据库MySQL5.7单机基础版上线
  7. 安装Centos7时提示 /dev/root does not exits
  8. 【Android】13.3 使用SQLite.NET-PCL访问SQLite数据库
  9. flex学习笔记 数据验证
  10. 关于C#操作mysql数据库乱码