一、音量相关概念

1. 相关术语解释

track volume : 单个App设置音量时设置的是这个,它只影响本App的音量。
stream volume :设置某一stream的音量,Android系统中支持10种stream。
stream volume alias:设置的是同一组stream的音量,比如使用某个音量调节滑动条设置的音量。比如设置媒体音,所有App的媒体音都受到影响(但是电话音,
闹钟音不受影响)。
master volume :设置它等于设置所有的stream volume和track volume。它可以写到声卡里面去,控制所有声音的音量。也可以不写到声卡里面去,而是作为一个乘数因子来影响所有的音量。

2. 华为Honor8音量设置

设置-->声音-->音量,设置界面列出了铃声、媒体、闹钟、通话,四个设置滚动条,称为四个stream type,四组。
Android系统中有10种stream,在system/core/include/system/audio.h中定义。但把这10种stream分成组,属于同一组的stream具有相同的别名(alias)。
一个音量调节滑动条具有一个alias,具有相同alias的stream都会受到这个滑动条的影响。

3. 声音播放的两种路径

(1)MixerThread
对于MixerThread(多个App共用一个声卡进行混音的的),APP对音量的设置不会影响到声卡的硬件音量,而只会影响APP的音频数据的幅值(变小或放大),
这些音频数据最终被混合后传给声卡。多个APP本身的音量设置互不影响。

(2)DirectOutputThread
对于DirectOutputThread(对于HDMI的,单个音频应用程序独占使用一个声卡的),同一时间里只有一个APP、只有一个AudioTrack使用它,
所以该AudioTrack的音量可以被DirectOutputThread直接用来设置硬件音量,这种声卡使用的不多。

若audio_policy.conf中的output的参数信息(会被解析成一个output profile)中有"flags AUDIO_OUTPUT_FLAG_DIRECT"就表示这个声卡可以
被某个App独占。这个App就会以DirectOutputThread的形式来使用这个声卡。

4. APP设置音量时互不影响, 这是AudioTrack volume

5. stream volume

stream volume可以引申出来: 各种stream的音量也可以单独设置、互不影响。比如"音乐音量"不应该影响到"来电振铃"、"闹钟"、"通话"的音量。

6. 有的手机音量控制界面有5种滑动条

有的手机音量控制界面有5种滑动条,用于设置某种类型的声音音量,但是Android系统创建AudioTrack时可以指定10种stream type,
必须分组,在Android源码中称之为"别名", 即alias。
比如在电话中, 以下5种stream的alias都是STREAM_RING,那么对应的滑动条即可控制这5种stream的音量。
STREAM_SYSTEM
STREAM_RING
STREAM_NOTIFICATION
STREAM_SYSTEM_ENFORCED
STREAM_DTMF

7. master volume

无论是AudioTrack volume、stream volume, 都是单独设置. master volume 可以设置所有的AudioTrack volume和stream volume,也可直接用来控制声卡的寄存器。

8. 混音:

app1: data1_mix = data1_in * master_volume * stream1_volume * AudioTrack1_volume

app2: data2_mix = data2_in * master_volume * stream2_volume * AudioTrack2_volume

混合在一起: data_mix = data1_mix + data2_mix 然后把混合后的数据写给硬件。

二、AudioFlinger层调节音量流程

1. AudioFlinger层调节音量流程

a. AudioFlinger对master volume, stream volume的初始化与设置
b. PlaybackThread对master volume, stream volume的初始化与设置
c. AudioTrack volume的设置
d. 这3种音量的使用

2. AudioFlinger类中有关成员:

stream_type_t mStreamTypes[AUDIO_STREAM_CNT];
//存储master volume
float mMasterVolume;
//存储是否静音
bool mMasterMute;

3. playbackThread类中:

stream_type_t mStreamTypes[AUDIO_STREAM_CNT + 1]; //为DuplicatingThread的OutputTrack多出一项
bool mMasterMute;
float mMasterVolume; //来源于AudioFlinger中的同名的变量

4. AudioTrack类中(App端)

float mVolume[2]; //两项,分别表示App设置的左右声道的音量

5. stream volume和audioTreack中的volume只是软件上的处理,masterVolue中保存的值若HAL提供了相应的写函数就会写给硬件。

6. DuplicatingThread可以用于在两个声卡上播放出同样的声音。

7. 加载HAL时设置为初始化值

AudioFlinger::loadHwModule(const char *name) //AudioFlinger.cpploadHwModule_l(name);//调用HAL的open函数,得到一个audio_hw_device_taudio_hw_device_t *dev;load_audio_interface(name, &dev);//if_name来自audio_policy.conf,是"primary",AUDIO_HARDWARE_MODULE_ID是"audio"//最后组合成的名字就是: audio.primary.tiny4412.sohw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);audio_hw_device_open(mod, dev);//若HAL提供了get_master_volume就获取硬件的值赋给mMasterVolumemMasterVolume = dev->get_master_volume(dev, &mv)//若HAL提供了get_master_mute就获取硬件的值赋给mMasterMutemMasterMute = dev->get_master_mute(dev, &mm)//若存在对应的函数则调用设置dev->set_master_volume(dev, mMasterVolume)dev->set_master_mute(dev, mMasterMute)audio_hw_device_t里面有masterVolume的存取函数:
typedef struct audio_hw_device audio_hw_device_t;
int (*set_master_mute)(struct audio_hw_device *dev, bool mute);
int (*get_master_mute)(struct audio_hw_device *dev, bool *mute);AudioFlinger中还提供了函数设置MasterVolume和MasterMute
AudioFlinger::setMasterVolume(float value)
AudioFlinger::setMasterMute(bool muted)AudioFlinger中的setStreamVolume
AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value, audio_io_handle_t output)mStreamTypes[stream].volume = value;AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value) //Threads.cppmStreamTypes[stream].volume = value;broadcast_l();PlaybackThread中的初始值都是来自AudioFlinger
AudioFlinger::PlaybackThread::PlaybackThread()mMasterVolume = audioFlinger->masterVolume_l();mMasterMute = audioFlinger->masterMute_l();//对于数组的每一项都执行mStreamTypes[stream].volume = mAudioFlinger->streamVolume_l(stream);mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);AudioTrack中的
AudioTrack::setVolume(float left, float right) //AudioTrack.cppmVolume[AUDIO_INTERLEAVE_LEFT] = left;mVolume[AUDIO_INTERLEAVE_RIGHT] = right;//mProxy->setVolumeLR(gain_minifloat_pack(gain_from_float(left), gain_from_float(right)));//mProxy = new AudioTrackClientProxy(cblk, buffers, frameCount, mFrameSizeAF);//仅仅是把这个数据记录在mVolumeLR域中而已。Cblk就是共享内存的头部。mCblk->mVolumeLR = volumeLR; //AudioTrackShared.h

8. App中的AudioTrack与SurfaceFlinger中的mTracks

App中的AudioTrack与SurfaceFlinger中的mTracks中的对应项通过共享内存进行通信,这个mProxy就是共享内存的代理类。

9. App去设置音量

App去设置音量只需要执行AudioTrack::setVolume就可以了。它会把设置的值放在自己的私有成员里面,也会放到共享内存的头部。

10. 低16bit是左声道数据,高16bit是右声道数据

11. AudioMixer中的音量如何保存

AudioMixer中的音量如何保存:音量有整数表示方式也有float表示方式,float表示方式是未来的发展趋势

三、音量键和Setting界面调节音量流程

1. 通过seekBar设置音量

对于seekBar控件,当滑动滑动条的时候,onProgressRefresh(AbsSeekBar.java)就会被调用,通过seekBar设置音量的两种方法:
① 重写onProgressRefresh
② 添加Listener

2. seekBar是通过packages目录下的 notification_settings.xml 文件画出来的,packages/apps/Settings/res/xml/notification_settings.xml

<!-- Media volume -->
<com.android.settings.notification.VolumeSeekBarPreferenceandroid:key="media_volume"android:icon="@drawable/ic_audio_vol_24dp"android:title="@string/media_volume_option_title" /><!-- Alarm volume -->
<com.android.settings.notification.VolumeSeekBarPreferenceandroid:key="alarm_volume"android:icon="@drawable/ic_audio_alarm_24dp"android:title="@string/alarm_volume_option_title" /><!-- Ring volume -->
<com.android.settings.notification.VolumeSeekBarPreferenceandroid:key="ring_volume"android:icon="@drawable/ring_notif"android:title="@string/ring_volume_option_title" /><!-- Notification volume -->
<com.android.settings.notification.VolumeSeekBarPreferenceandroid:key="notification_volume"android:icon="@drawable/ring_notif"android:title="@string/notification_volume_option_title" />

3. 音量键和Setting界面调节音量流程

a. 音量键处理流程
音量键: 如果APP没有重写它的处理函数,音量键的处理将交给 PhoneFallbackEventHandler 来处理,它会调用AudioService.adjustSuggestedStreamVolume调整"推荐的流"的音量a.1 如何获得"推荐的流": stream = getActiveStreamType(...)a.2 音量设置的"alias"如何起作用: set volume for stream; // 设置"推荐的流"的音量if (mStreamVolumeAlias[other stream] == stream)set volume for other stream;  // 设置同属一个alias的其他流的音量对于不同的设备(电话、TV、平板), mStreamVolumeAlias指向不同的数组a.3 怎么设置流的音量:设置audioflinger中的数组:   mStreamTypes[stream].volume = value;设置PlaybackThread中的数组: mStreamTypes[stream].volume = value;b. 音量滑动条处理流程b.1 通过下面文件定义音量滑动条:
packages/apps/Settings/res/xml/notification_settings.xml该文件定义了多个VolumeSeekBarPreference,每个VolumeSeekBarPreference要跟一个SeekBar绑定b.2 在VolumeSeekBarPreference的绑定函数onBindView中,设置了对应的SeekBar的SeekBarChangeListener (一个SeekBarVolumizer对象)b.3 当SeekBar被滑动时, 它的onProgressRefresh被调用,该函数会调用 mOnSeekBarChangeListener.onProgressChangedb.4 mOnSeekBarChangeListener.onProgressChanged去设置音量b.5 每一个SeekBar对应一个stream,滑动SeekBar时会设置该stream的音量,也会去设置同属一个alias(同一分组)的其他stream的音量c. 两者最终都会调用AudioService.java的代码发出MSG:sendMsg(mAudioHandler,MSG_SET_DEVICE_VOLUME,SENDMSG_QUEUE,device,0,streamState,0);

参考:
Android官方setting文档:https://developer.android.google.cn/guide/topics/ui/settings

android5.0设置模块音量调节流程:https://blog.csdn.net/fireness/article/details/46738643

Android音量调节的实现(RingtoneManager和RingerVolumePreference):https://blog.csdn.net/liranke/article/details/6683000

android设置中拖动音量条调节音量流程(android5.1):https://blog.csdn.net/qq_28534581/article/details/77337599

Android 音量控制流程分析:https://blog.csdn.net/kehyuanyu/article/details/49153223

转载于:Android音频(9)——音量调节 - Hello-World3 - 博客园

Android音频 —— 音量调节相关推荐

  1. Android音频——音量调节

    一.音量相关概念 1. 相关术语解释 track volume : 单个App设置音量时设置的是这个,它只影响本App的音量. stream volume :设置某一stream的音量,Android ...

  2. Android视频编辑器(五)音频编解码、从视频中分离音频、音频混音、音频音量调节等

    前言 这篇博客,主要讲解的是android端的音频处理,在开发Android视频编辑器的时候,有一个非常重要的点就是音频的相关处理.比如如何从视频中分离音频(保存为mp3文件),然后分离出来的音频如何 ...

  3. android 音量 广播,Android平台音量调节(一)音量键调节音量

    Android平台音量调节 本文基于Android 8.0讲述Android平台原生音量控制功能. 流的定义 Android中,音量都是分开控制,各种流定义各种流的音量.在Android8.0中,定义 ...

  4. android 自定义音量调节,Android——自定义音量调节控件

    今天我们要实现一个上图中音量调节的效果.主要有两种实现方式自定义RatingBar和自定义View. 自定义RatingBar volume_rating.xml main.xml android:i ...

  5. Android系统音量调节策略学习总结

    二.外设类型 USB音箱底座 蓝牙音箱 3.5mm线控耳机 三.相关术语 track volume: 单个App设置音量时设置的是这个,它只影响本App的音量. stream volume: 设置某一 ...

  6. android 声卡 音量控制,android audio 音量调节

    这次的分析是从setting设置开始,进入声音设置,然后进入音量设置! 先上传上来,后期进行整理吧 调用流程: -------------------------------------------- ...

  7. html音频音量调节

    在调节音量的时候,我们大多数情况下会使用input type=range的拖动条来控制: <p>volume<input id="volume" type=&qu ...

  8. android 耳机 音量调节 id,Android音频相关(一)插入耳机后调节音量(安全音量)...

    一.安全音量提醒框的开启 二.修改安全音量提醒框显示 三.重启后还会显示安全音量提醒框 四.一些关于安全音量的初始值 一.安全音量提醒框的开启 安卓系统是有耳机音量保护机制的,对于一些出口欧盟的手机来 ...

  9. android 耳机 音量调节 id,Android链接耳机音量到主音量

    据我所知,这是飞利浦Android TV用户的常见问题(例如 this篇中的第22页,或 that讨论). 一般来说,您的任务的模板是跟踪插入/拔出事件和"系统/音乐"音频流(或媒 ...

最新文章

  1. mac下用Dosbox搭建dos下的汇编环境
  2. ASP.NET MVC 4 中的JSON数据交互总结
  3. 《塞洛特傳說》道具系统
  4. 关于C语言中单双引号的问题
  5. linux shell 查看 cpu核数
  6. MIPS SDE简介
  7. 一款图像相关软件PhoXo
  8. 一天搞定HTML----标签类型与类型转换05
  9. JS 异常: Uncaught RangeError: Maximum call stack size exceeded
  10. python 解析xml 文件: SAX方式
  11. js中时间戳与日期格式的相互转换
  12. rpm安装与yum安装的区别与特点
  13. MySQL基础——DDL语言学习\数据库的建立\MySQL数据类型\MySQL常见约束\表的增删改
  14. 事务回退机制 android,【Android基础】——Fragment-使用方法
  15. linux命令-eq是什么意思,linux查看系统信息命令
  16. 计算机辅助设计利用计算机的,计算机基础知识:计算机辅助设计
  17. 指标公式c语言源码下载,通达信超级厉害指标公式源码附图-通达信公式-公式指标网...
  18. 软件工程:第三章:可行性分析与需求分析
  19. Leetcode第904题
  20. 第一章-问题求解策略-LA4234-Binary Clock

热门文章

  1. 魔法少女小Scarlet
  2. Linux内核完全注释 阅读笔记:2.4、控制器和控制卡
  3. 揭秘英雄联盟的数据服务器
  4. super.getClass()与this.getClass()的问题
  5. flutter bloc 实例
  6. 如何让精灵在不同的帧率下运动速度不变--Frame Rate Independent Movement
  7. html div 高度100,深入理解CSS的height:100%和height:inherit之间的使用区别
  8. JQuery Marquee插件(无缝滚动效果)- marquee.js
  9. HTML5期末大作业:电影网站设计——指环王:护戒使者(13页) HTML+CSS+JavaScript
  10. 感恩美文:生命中总有一些人值得感恩