cerberspace 发表于 2012-12-19 23:10:28

Android音量控制曲线

<div id="cnblogs_post_body">  摘要:本文介绍了android音量的控制曲线的计算方法。
  由于人耳对声音的听感具指数曲线型,也就是对小音量时比较敏感,随着声音的加大其听感随之变的不敏感,其变化近似指数函数曲线的形式。为了使听感变的近似直线的变化,人们在实践中就采用了音量变化近似对数式曲线型的电位器来实现这个目的。对比法产生音量控制曲线与最终扬声器输出的声压有关,当然您也可以根据扬声器的输出功率来进行比对,但功率终究不如电压来的方便。音量调节框的UI滑动条的刻度是线性的,这样就给我们生成音量控制曲线打下了很好的对比基础。下面我们就来通过一个音量调节的场景来分析Android是如何控制音量的。
  首先,我们按音量调节键使得media音量逐级增加到最大。STREAM_MUSIC流的音量分为15级,通过AudioManger的handleKeyDown函数调用adjustSuggestedStreamVolume设置,一路找下去,发现在AudioService中adjustSuggestedStreamVolume然后调用adjustStreamVolume,通过消息MSG_SET_SYSTEM_VOLUME调用setSystemVolume,转到AudioSystem中的setStreamVolumeIndex,再通过jni层调用本地层的AudioSystem调用AudioPolicymanagerService,最后到AudiopolicyManagerBase的setStreamVolumeIndex,接下来的由checkAndSetVolume调用computeVolume,马上就要到真相大白的时候了。volIndexToAmpl函数时真正计算音量的地方,我们一起来分析这个函数
 
<div class="cnblogs_code"> 1 float AudioPolicyManagerBase::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc, 2         int indexInUi) 3 { 4   device_category deviceCategory = getDeviceCategory(device); 5   const VolumeCurvePoint *curve = streamDesc.mVolumeCurve; 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.mIndex - 9             curve.mIndex;//计算预置的曲线区间的范围,这里是(1-100)10   ALOGI("VOLUME vol indexInUi=%d, nbSteps=%d, mIndexMin=%d, mIndexMax=%d",indexInUi,nbSteps,streamDesc.mIndexMin,streamDesc.mIndexMax);11   int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) /12             (streamDesc.mIndexMax - streamDesc.mIndexMin);//(由传进来的UIIndex计算百分比的index,比如现在是第一级 100*(1-0)/(15-0)=6)13 14   // find what part of the curve this index volume belongs to, or if it's out of bounds15   int segment = 0;16   if (volIdx < curve.mIndex) {         // out of bounds17         return 0.0f;18   } else if (volIdx < curve.mIndex) {19         segment = 0;20   } else if (volIdx < curve.mIndex) {21         segment = 1;22   } else if (volIdx <= curve.mIndex) {23         segment = 2;24   } else {                                                               // out of bounds25         return 1.0f;26     }27 //第一极6是在区间VOLKNEE1之间,其区间表是在AudioPolicyManager初始化的时候就已经加载,因此它对应的segment为028   // linear interpolation in the attenuation table in dB29   float decibels = curve.mDBAttenuation +30             ((float)(volIdx - curve.mIndex)) *31               ( (curve1].mDBAttenuation -32                         curve.mDBAttenuation) /33                     ((float)(curve1].mIndex -34                             curve.mIndex)) );35 //计算衰减分贝数 curve.db + 该区间每一级index对应的db*index数36   float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 )37//由指数公式计算出音量amplification db = 20log(V/Vmax)linearToLog Vmax是一个参考值38   ALOGI("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f",39             curve.mIndex, volIdx,40             curve1].mIndex,41             curve.mDBAttenuation,42             decibels,43             curve1].mDBAttenuation,44             amplification);45 46   return amplification;47 }
页: [1]
查看完整版本: Android音量控制曲线