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层;




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值