【Android Audio】Audio: set MP3 volume

先来看两张图,第一张是audio系统的框架图,第二张是Binder机制的框架图

audio layer

                    Binder layer


当点击改变MP3音量的时候,会产生如下log:

10-11 08:09:44.610: D/MusicPlayerActivity(2276): onKeyDown(25) start from clicking
10-11 08:09:44.610: D/CorePlayerService(1726): isAVPlayerMode(): false
10-11 08:09:44.610: V/AudioPolicyManagerBase(87): getNewDevice() selected device 0
10-11 08:09:44.610: D/AudioManager(2276): isAudioPathEarjack() : false current path :SPK
10-11 08:09:44.620: I/AudioService(342): isMediaSilentMode false
10-11 08:09:44.620: E/AudioPolicyService(87): _________index-->13 current index is 13
// send  broadcast  MSG_VOLUME_CHANGED
10-11 08:09:44.620: D/VolumePanel(342): change volume by MSG_VOLUME_CHANGED
10-11 08:09:44.620: D/InputReader(342): IInput event: device=0 type=0x0001 code=0x0114 value=0x00000000
10-11 08:09:44.620: D/VolumePanel(342): onVolumeChanged(streamType: 3, flags: 0)
10-11 08:09:44.620: D/VolumePanel(342): Call setChangeSeekbarColor(false)
10-11 08:09:44.620: E/AudioPolicyManagerBase(87): stream type [13], return media stratege
10-11 08:09:44.630: V/AudioPolicyManagerBase(87): getNewDevice() selected device 0
10-11 08:09:44.630: E/AudioFlinger(87): ------->setParameters--> music_volume=0.3548133671;music_volume_index=13
10-11 08:09:44.630: V/AudioFlinger(87): setParameters(): io 1, keyvalue music_volume=0.3548133671;music_volume_index=13, tid 284, calling pid 87End


根据以上log可以有如下的流程图:


对以上两张流程图作一个解释:

AudioFlinger:
1.AudioFlinger继承libmedia中的接口,提供实现库libaudioflinger.so,audio framework是libmedia.so的一个部分,这些Audio接口对上层提供接口,
由下层audio native部分去实现,也就是说,上层调用的只是libmedia.so的部分接口,但是实际上调用的内容是libaudioflinger.so
2.AudioFlinger作为audio系统的中间件,在整个系统中起到服务的作用, AudioFlinger以下统称为Audio Hal层(AudioPolice、AudioHardware等等)
3.AudioFlinger为libmedia.so提供audio部分的接口的实现。主要提供createTrack()创建音频的输出设备IAudioTrack,openRecord()创建音频的输入设备IAudioRecord,
还有一个重要的功能就是get/set接口,用于控制(音量,路由等)。
4.上层AudioService可以实现的功能就不会再通过AudioManage调用AudioSystem让下层实现
AudioService-->AudioManage-->AudioSystem
AP-->APS-->APMB
AudioSystem.java-->AudioSystem.cpp-->IAudioFlinger.cpp-->AudioFlinger.cpp-->AudioHardwareInterface.cpp


AudioPolicyService:
1.AudioPolicyService的很大一部分管理工作都是在AudioPolicyManager中完成的。包括音量管理,音频策略(strategy)管理,输入输出设备管理。
2.AudioPolicyService有一个内部线程类AudioCommandThread,顾名思义,所有的命令(音量控制,输入、输出的切换等)最终都会在该线程中排队执行.


AudioCommandThread:
AudioCommandThread是AudioPolicyService中的一个线程,主要用于处理音频设置相关的命令。包括:
START_TONE
STOP_TONE
SET_VOLUME
SET_PARAMETERS
SET_VOICE_VOLUME
每种命令的参数有相应的包装:
class ToneData
class VolumeData
class ParametersData
class VoiceVolumeData


Audio Volume 综述:
1.AudioPolicyManager提供了一下几个与音量相关的函数:
initStreamVolume(AudioSystem::stream_type stream, int indexMin, int indexMax)
setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
getStreamVolumeIndex(AudioSystem::stream_type stream)
2.AudioService.java中定义了每一种音频流的最大音量级别,
其中,电话铃声可以有7个级别的音量,而音乐则可以有15个音量级别,java的代码通过jni,最后调用AudioPolicyService的initStreamVolume(),把这个数组的内容传入AudioPolicyManager中,
这样AudioPolicyManager也就记住了每一个音频流的音量级别。应用程序可以调用setStreamVolumeIndex设置各个音频流的音量级别,setStreamVolumeIndex会把这个整数的音量级别转化为适合人耳的对数级别,
然后通过AudioPolicyService的AudioCommandThread,最终会将设置应用到AudioFlinger的相应的Track中。
例如:
AudioPolicyService::AudioPolicyService()
    : BnAudioPolicyService() , mpAudioPolicyDev(NULL) , mpAudioPolicy(NULL)
{
   ……
    // start tone playback thread,Tone音播放线程(系统,按键音)
    mTonePlaybackThread = new AudioCommandThread(String8(""));
    // start audio commands thread,控制命令线程(音量,路由)
    mAudioCommandThread = new AudioCommandThread(String8("ApmCommand"));
   ……
}
START_TONE/STOP_TONE:播放电话系统中常用的特殊音调,例如:TONE_DTMF_0,TONE_SUP_BUSY等等。
SET_VOLUME:最终会调用AudioFlinger进行音量设置
SET_VOICE_VOLUME:最终会调用AudioFlinger进行电话音量设置
SET_PARAMETERS:通过一个KeyValuePairs形式的字符串进行参数设置,KeyValuePairs的格式可以这样:
"sampling_rate=44100"
"channels=2"
"sampling_rate=44100;channels=2" // 组合形式
这些KeyValuePairs可以通过AudioPolicyService的成员函数setParameters()传入。
从工作的角度看,AudioFlinger在初始化之后,首先获得放音设备,然后为混音器(Mixer)建立线程,接着建立放音设备线程,在线程中获得放音设备。
设备选择的原因:
   在创建audiotrack时,传入的音频类型是music,当插上耳机时,这种类型的声音只会从耳机中出来,但如果音频流类型是ring,则会从耳机和扬声器中同时出来;
音量级别的原因:
   不同的音频流类型的音量级的个数不同,例如music有15个级别可以选择,而有些只有7个级别的音量。
/* output devices */
    AUDIO_DEVICE_OUT_EARPIECE                  = 0x1, // 听筒
    AUDIO_DEVICE_OUT_SPEAKER                   = 0x2, // 扬声器
    AUDIO_DEVICE_OUT_WIRED_HEADSET             = 0x4, // 耳机
    AUDIO_DEVICE_OUT_WIRED_HEADPHONE           = 0x8, // 另一种耳机
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO             = 0x10, // 蓝牙,通话语音
    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP            = 0x80, // 蓝牙,立体声

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

audiotrack和audiorecord是两个相反的过程,简单的理解如下:

audio播放(out_write)
java层拿到手机里已经存在的MP3等压缩格式的文件,把路径传入FW层,FW层选择合适的rounting,samplerate等,并由AudioFlinger把MP3数据转化为PCM写入共享内存,hardware层拿到PCM数据并播放;
audio录音 (in_read)
hardware从外部read PCM数据并放入内存,FW层拿到PCM数据并转化为MP3数据存放到手机中并把路径传给java层;




你可能感兴趣的:(【Android Audio】Audio: set MP3 volume)