赞
踩
/*****************************************************************************************************/
声明:本文内容是基于Android 8.1的源码分析
https://blog.csdn.net/xuechwtx原创,转载请注明出处,谢谢!
/*****************************************************************************************************/- IVolumeCurvesCollection *mVolumeCurves;
- mVolumeCurves = new VolumeCurvesCollection()
从AudioPolicymanager中可以看到,在操作音量的函数中,大都会调用mVolumeCurves的一些方法。比如在函数getStreamVolumeIndex中就调用了 mVolumeCurves->getVolumeIndex()的方法。所以我们可以猜测, mVolumeCurves可能保存着音量的信息, 并且有一些操作音量的方法. 在头文件中,mVolumeCurves被声明为IVolumeCurvesCollection类型。
IVolumeCurvesCollection,这个类的定义在文件<IVolumeCurvesCollection.h>。在IVolumeCurvesCollection类中的public方法都被声明为虚函数,这些方法都是对AudioPolicy的接口,这些接口的实现应该都是在VolumeCurvesCollection类中。
- class VolumeCurvesCollection :
- public KeyedVector<audio_stream_type_t, VolumeCurvesForStream>,
- public IVolumeCurvesCollection
VolumeCurvesCollection首先继承于IVolumeCurvesCollection,并且实现了父类中的虚函数。另外VolumeCurvesCollection继承于一个容器KeyedVector<audio_stream_type_t, VolumeCurvesForStream>,容器的下标是流类型,容器的元素是VolumeCurvesForStream类型的对象。从VolumeCurvesCollection构造函数可以看出,构造时会每一种流类型创建一个VolumeCurvesForStream。所以我们可以猜测VolumeCurvesForStream中保存着每个流的音量信息。这样做可以对不同的流使用各自的策略。
- class VolumeCurvesForStream : public KeyedVector<device_category, sp<VolumeCurve> >
- {
- private:
- KeyedVector<device_category, sp<VolumeCurve> > mOriginVolumeCurves;
- KeyedVector<audio_devices_t, int> mIndexCur; /**< current volume index per device. */
- int mIndexMin; /**< min volume index. */
- int mIndexMax; /**< max volume index. */
- bool mCanBeMuted; /**< true is the stream can be muted. */
- };
mIndexMin,mIndexMax这两个属性代表着该流可以调节音量的最大值和最小值,这里的音量值就是我们实际调节音量键的时候所调节的音量值。最大值,最小值保存在AudioService.java中的MAX_STREAM_VOLUME,MIN_STREAM_VOLUME数组内。在AudioService构造的时候会调用AudioSystem的接口initStreamVolume传入每个流的最大值和最小值。
- private static 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
- 15 // STREAM_ACCESSIBILITY
- };
-
- private static int[] MIN_STREAM_VOLUME = new int[] {
- 1, // STREAM_VOICE_CALL
- 0, // STREAM_SYSTEM
- 0, // STREAM_RING
- 0, // STREAM_MUSIC
- 0, // STREAM_ALARM
- 0, // STREAM_NOTIFICATION
- 0, // STREAM_BLUETOOTH_SCO
- 0, // STREAM_SYSTEM_ENFORCED
- 0, // STREAM_DTMF
- 0, // STREAM_TTS
- 0 // STREAM_ACCESSIBILITY
- };
mCanBeMuted
表示该流是否可以被Mute,现在代码环境下,都是ture。- class VolumeCurve : public RefBase
- {
- private:
- SortedVector<CurvePoint> mCurvePoints;
- device_category mDeviceCategory;
- audio_stream_type_t mStreamType;
- };
- struct CurvePoint
- {
- uint32_t mIndex;
- int mAttenuationInMb;
- };
VolumeCurve里面保存一个CurvePoint(曲线点)的容器,曲线点的横坐标是Index,纵坐标是mAttenuationInMb(单位是mdB).接下来看一下其中一条音量曲线. 我们可以看到该曲线包含四个点, index是从0~100,Attenuation的大小是-58dB~0dB。具体的音量值, Index和Attenuation之间的转换关系我们稍后会具体分析.
- <reference name="DEFAULT_DEVICE_CATEGORY_SPEAKER_VOLUME_CURVE">
- <!-- Default is Speaker Media Volume Curve -->
- <point>1,-5800</point>
- <point>20,-4000</point>
- <point>60,-1700</point>
- <point>100,0</point>
- </reference>
接下来总结一下VolumeCurvesCollection的结构:
首先我们看一下音量配置文件的结构。首先default_volume_tables.xml文件中保存着一些默认的音量配置,这些配置可以被audio_policy_volumes.xml中具体的音量配置引用,例如, AUDIO_STREAM_MUSIC流DEVICE_CATEGORY_SPEAKER类的设备使用的音量曲线的配置是DEFAULT_DEVICE_CATEGORY_SPEAKER_VOLUME_CURVE。
- <!-- In the filse default_volume_tables.xml -->
- <reference name="DEFAULT_DEVICE_CATEGORY_SPEAKER_VOLUME_CURVE">
- <!-- Default is Speaker Media Volume Curve -->
- <point>1,-5800</point>
- <point>20,-4000</point>
- <point>60,-1700</point>
- <point>100,0</point>
- </reference>
-
- <!-- In the filse audio_policy_volumes.xml -->
- <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER"
- ref="DEFAULT_DEVICE_CATEGORY_SPEAKER_VOLUME_CURVE"/>
音量相关的配置文件包括audio_policy_volumes.xml和default_volume_tables.xml,默认在frameworks/av/services/audiopolicy/config/目录下, 配置文件的位置在不同平台不同。通常跟AudioPolicy的配置文件audio_policy_configuration.xml在同一个目录下。我们可以看到audio_policy_configuration.xml中引用了音量的配置文件。所以音频配置文件在AudioPolicyManager的构造函数中,跟audio_policy_configuration.xml一起解析。
- AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
- // 1. 创建一个VolumeCurvesCollection对象
- mVolumeCurves = new VolumeCurvesCollection();
-
- // 2. 把mVolumeCurves对象传入AudioPolicyConfig的构造函数
- AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
- mDefaultOutputDevice, speakerDrcEnabled,
- static_cast<VolumeCurvesCollection *>(mVolumeCurves));
- // 保存传入的mVolumeCurves对象
- config.mVolumeCurves = mVolumeCurves;
-
- // 3. 尝试解析Audiolicy的配置文件 audio_policy_configuration.xml
- deserializeAudioPolicyXmlConfig(config);
- // 依次尝试查找下面目录下的audio_policy_configuration.xml配置文件,
- // {"/odm/etc", "/vendor/etc/audio", "/vendor/etc", "/system/etc"};
- // audioPolicyXmlConfigFile = “audio_policy_configuration.xml”
- PolicySerializer serializer;
- serializer.deserialize(audioPolicyXmlConfigFile, config)
- // 4. 初始化 mVolumeCurves,在当前代码中initializeVolumeCurves没有做什么操作
- mVolumeCurves->initializeVolumeCurves(speakerDrcEnabled);
AudioPolicyManager通过PolicySerializer::deserialize来解析Audio Policy 的配置文件其中包括audio_policy_configuration.xml
- status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig &config)
- // 解析文件xml文件,找到跟节点xmlNodePtr cur
- xml文件,DocPtr doc = xmlParseFile(configFile);
- xmlNodePtr cur = xmlDocGetRootElement(doc);
-
- // 调用 deserializeCollection 函数解析Volume类型的节点
- // 设置AudioPolicyConfig中的属性mVolumeCurves = volumes;
- VolumeTraits::Collection volumes;
- deserializeCollection<VolumeTraits>(doc, cur, volumes, &config);
- config.setVolumes(volumes);
deserializeCollection函数最终会调用VolumeTraits::deserialize函数解析每一个音量曲线。VolumeTraits::deserialize函数根据 “stream” “deviceCategory” “point”解析每条曲线配置。
- <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA"
- ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
- <volume stream="AUDIO_STREAM_SYSTEM" deviceCategory="DEVICE_CATEGORY_HEADSET">
- <point>1,-3000</point>
- <point>33,-2600</point>
- <point>66,-2200</point>
- <point>100,-1800</point>
- </volume>
- status_t VolumeTraits::deserialize(_xmlDoc *doc, const _xmlNode *root, PtrElement &element,
- PtrSerializingCtx /*serializingContext*/)
- {
- // 解析 “stream” Tag
- string streamTypeLiteral = getXmlAttribute(root, Attributes::stream);
- audio_stream_type_t streamType;
- StreamTypeConverter::fromString(streamTypeLiteral, streamType);
- // 解析 “deviceCategory” Tag
- string deviceCategoryLiteral = getXmlAttribute(root, Attributes::deviceCategory);
- device_category deviceCategory;
- DeviceCategoryConverter::fromString(deviceCategoryLiteral, deviceCategory);
- // 解析 “ref” Tag
- string referenceName = getXmlAttribute(root, Attributes::reference);
- const _xmlNode *ref = NULL;
- if (!referenceName.empty()) {
- getReference<VolumeTraits>(root->parent, ref, referenceName);
- }
-
- element = new Element(deviceCategory, streamType);
-
- const xmlNode *child = referenceName.empty() ? root->xmlChildrenNode : ref->xmlChildrenNode;
- while (child != NULL) {
- if (!xmlStrcmp(child->name, (const xmlChar *)volumePointTag)) {
- xmlChar *pointDefinition = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);;
- // 解析 “point”
- Vector<int32_t> point;
- collectionFromString<DefaultTraits<int32_t> >((const char*)pointDefinition, point, ",");
- // 添加解析出来的 Point
- element->add(CurvePoint(point[0], point[1]));
- xmlFree(pointDefinition);
- }
- child = child->next;
- }
- }
- void clearCurrentVolumeIndex(audio_stream_type_t stream)
- editCurvesFor(stream).clearCurrentVolumeIndex();
- // 清空当前音量的容器 KeyedVector<audio_devices_t, int> mIndexCur
- mIndexCur.clear();
addCurrentVolumeIndex,更新某个流某个设备的音量 AudioPolicyManager在函数setStreamVolumeIndex时会调用该接口
- void addCurrentVolumeIndex(audio_stream_type_t stream, audio_devices_t device, int index)
- // VolumeCurvesForStream::addCurrentVolumeIndex
- editCurvesFor(stream).addCurrentVolumeIndex(device, index);
- // 向当前音量的容器添加一项,替换当前保存的音量值
- mIndexCur.add(device, index);
canBeMuted,判断该流是否可以静音
当前代码没有setcanBeMuted的接口。 mCanBeMuted默认为ture, 该接口返回ture
- bool canBeMuted(audio_stream_type_t stream)
- return getCurvesFor(stream).canBeMuted()
- // 返回 流的音量信息中的 mCanBeMuted
- // VolumeCurvesForStream.mCanBeMuted
- VolumeCurvesForStream::canBeMuted()
- return mCanBeMuted;
getVolumeIndexMin,获取该流的最小音量
没有set的接口, Min和Max只有被接口initializeVolumeCurves设置
- int getVolumeIndexMin(audio_stream_type_t stream)
- return getCurvesFor(stream).getVolumeIndexMin()
- // 返回 流的音量信息中的 mIndexMin
- // VolumeCurvesForStream.mIndexMin
- VolumeCurvesForStream::getVolumeIndexMin()
- return mIndexMin
getVolumeIndexMax,获取该流的最大音量
- int getVolumeIndexMax(audio_stream_type_t stream)
- return getCurvesFor(stream).getVolumeIndexMax()
- // 返回 流的音量信息中的 mIndexMax
- // VolumeCurvesForStream.mIndexMax
- VolumeCurvesForStream::getVolumeIndexMax()
- return mIndexMax
initStreamVolume,初始化特定流的VolumeCurvesForStream
这里只是设置 VolumeCurvesForStream 的最大音量和最小音量
这也是唯一可以设置最大最小值的接口
- virtual status_t initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax)
- editValueAt(stream).setVolumeIndexMin(indexMin);
- // VolumeCurvesForStream.mIndexMin = indexMin;
- editValueAt(stream).setVolumeIndexMax(indexMax);
- // VolumeCurvesForStream.mIndexMax = indexMax;
getVolumeIndex,获取该特定流特定设备的音量
返回VolumeCurvesForStream.mIndexCur.valueFor(device)
- int getVolumeIndex(audio_stream_type_t stream, audio_devices_t device)
- return getCurvesFor(stream).getVolumeIndex(device)
- VolumeCurvesForStream::getVolumeIndex()
- // 从多个设备选择中提取一个的设备
- // getCurvesFor(stream).mIndexCur.valueFor(device)
- device = Volume::getDeviceForVolume(device)
- return mIndexCur.valueFor(device)
hasVolumeIndexForDevice,有没有为特定的流特定的设备设置音量值
- virtual bool hasVolumeIndexForDevice(audio_stream_type_t stream,
- audio_devices_t device) const
- // VolumeCurvesForStream::hasVolumeIndexForDevice(device)
- return getCurvesFor(stream).hasVolumeIndexForDevice(device);
- // mIndexCur.indexOfKey(device) < 0 表示mIndexCur没有该项
- device = Volume::getDeviceForVolume(device);
- return mIndexCur.indexOfKey(device) >= 0;
initializeVolumeCurves,解析配置文件的时候已经被初始化,不需要再初始化
void initializeVolumeCurves(bool /*isSpeakerDrcEnabled*/) {}
switchVolumeCurve, 用src流的mOriginVolumeCurves音量曲线替换dst的音量曲线
这样dst会暂时使用跟src流相同的音量曲线,dst的mOriginVolumeCurves音量曲线不变
virtual void switchVolumeCurve(audio_stream_type_t src流的, audio_stream_type_t dst)
restoreOriginVolumeCurve,从mOriginVolumeCurves音量曲线恢复该流的音量曲线
与switchVolumeCurve配合使用,用来回复switchVolumeCurve的修改
- virtual void restoreOriginVolumeCurve(audio_stream_type_t stream)
- {
- switchVolumeCurve(stream, stream);
- }
上层设置到AudioPolicy的音量是用户设置的音量值, 而底层把音量值转换成分贝值才能处理该音量。音量曲线的作用就是做这种转换。具体的转换流程在函数volIndexToDb内完成的。
1. 找到特定的音量曲线
传入的参数是:特定的流,特定的设备类型,需要计算的音量值。
因为音量的计算依赖于特定的音量曲线,需要根据stream,category找到该音量曲线,调用音量曲线的函数VolumeCurve::volIndexToDb
- virtual float volIndexToDb(audio_stream_type_t stream, device_category cat, int indexInUi) const
- return getCurvesFor(stream).volIndexToDb(cat, indexInUi);
-
- float volIndexToDb(device_category deviceCat, int indexInUi) const
- return getCurvesFor(deviceCat)->volIndexToDb(indexInUi, mIndexMin, mIndexMax);
2. 计算音量值对应的横坐标- // 传入特定流的音量最大值,最小值
- float VolumeCurve::volIndexToDb(int indexInUi, int volIndexMin, int volIndexMax) const
- {
- // 确定曲线的点的个数
- size_t nbCurvePoints = mCurvePoints.size();
- // 曲线两个端点横坐标的的差值,一般情况下是100
- int nbSteps = 1 + mCurvePoints[nbCurvePoints - 1].mIndex - mCurvePoints[0].mIndex;
- // 计算出横坐标
- if (indexInUi >= volIndexMin)
- volIdx = (nbSteps * (indexInUi - volIndexMin)) / (volIndexMax - volIndexMin);
3. 计算横坐标对应的分贝值(纵坐标)p[n-1].y + (x-p[n-1].x) * ( (p[n].y - p[n-1].y) / (p[n].x - p[n-1].x) )
- // 计算出横坐标在哪一条线段,即上面公式中的n
- size_t indexInUiPosition = mCurvePoints.orderOf(CurvePoint(volIdx, 0));
- // 如果横坐标大于最大值,使用最大的音量
- if (indexInUiPosition >= nbCurvePoints) {
- return mCurvePoints[nbCurvePoints - 1].mAttenuationInMb / 100.0f;
- }
- // 如果横坐标小于最小值,使用最小的音量
- if (indexInUiPosition == 0) {
- if (indexInUiPosition != mCurvePoints[0].mIndex) {
- return VOLUME_MIN_DB; // out of bounds
- }
- return mCurvePoints[0].mAttenuationInMb / 100.0f;
- }
- // 根据线性关系算出音量(衰减)
- // 因为配置文件中存入的值不是以dB为单位,所以计算过程中需要做“/100”的操作
- float decibels = (mCurvePoints[indexInUiPosition - 1].mAttenuationInMb / 100.0f) +
- ((float)(volIdx - mCurvePoints[indexInUiPosition - 1].mIndex)) *
- ( ((mCurvePoints[indexInUiPosition].mAttenuationInMb / 100.0f) -
- (mCurvePoints[indexInUiPosition - 1].mAttenuationInMb / 100.0f)) /
- ((float)(mCurvePoints[indexInUiPosition].mIndex -
- mCurvePoints[indexInUiPosition - 1].mIndex)) );
setStreamVolumeIndex,设置特定流特定设备的音量
其中参数device是AudioServer.java通过AudioSystem,AudioPlicy的接口 getStrategyForStream获得, 即Stream->Strategy->Device的方式, 这也是AudioPolicy获得设备的标准方式。
(4) 如果请求的设备是默认设备,需要curStreamDevice没有音量配置
- status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
- int index, audio_devices_t device)
- // 1. 判断传入的参数
- // 音量不可大于流的最大音量,小于最小音量值
- if ((index < mVolumeCurves->getVolumeIndexMin(stream)) ||
- (index > mVolumeCurves->getVolumeIndexMax(stream)))
- return BAD_VALUE;
-
- // 设备需要是输出设备
- if (!audio_is_output_device(device))
- return BAD_VALUE;
-
- // 如果传入的流不能被Mute, 强制使用该流的最高音量
- // canBeMuted,现在代码中,没有设置canBeMuted的接口,默认被设置为true
- if (!mVolumeCurves->canBeMuted的接口,默认被设置为true(stream)) index = mVolumeCurves->getVolumeIndexMax(stream);
-
- // 2. 更新与传入的流,设备的音量值
- for (int curStream = 0; curStream < AUDIO_STREAM_FOR_POLICY_CNT; curStream++) {
- // return (stream1 == stream2)
- if (!streamsMatchForvolume(stream, (audio_stream_type_t)curStream)) {
- continue;
- }
- // 更新特定流,特定设备的音量值
- mVolumeCurves->addCurrentVolumeIndex((audio_stream_type_t)curStream, device, index);
- }
-
- // 3. 遍历已经打开的所有的output,对所有的符合条件的output和流设置音量
- status_t status = NO_ERROR;
- for (size_t i = 0; i < mOutputs.size(); i++) {
- // 获得该output的配置信息
- sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
- // curDevice 是根据当前output使用的设备得出的
- // 其中主要对双设备做了处理,一般双设备只选取了speaker
- audio_devices_t curDevice = Volume::getDeviceForVolume(desc->device());
- for (int curStream = 0; curStream < AUDIO_STREAM_FOR_POLICY_CNT; curStream++) {
- // (1) 请求的流必须在当前output中Active(可以理解为正在播放)
- // 遍历所有的流,仅对跟请求的流符合的流(当前的代码下可以认为自有请求的流)
- if (!streamsMatchForvolume(stream, (audio_stream_type_t)curStream)) {
- continue;
- }
- // 判断流是不是Active
- if (!(desc->isStreamActive((audio_stream_type_t)curStream) ||
- (isInCall() && (curStream == AUDIO_STREAM_VOICE_CALL)))) {
- continue;
- }
- // (2) 判断请求的设备是否跟当前获得的设备匹配
- // 获得请求的流在当前场景下应该使用的设备
- routing_strategy curStrategy = getStrategy((audio_stream_type_t)curStream);
- audio_devices_t curStreamDevice = Volume::getDeviceForVolume(getDeviceForStrategy(
- curStrategy, false /*fromCache*/));
- // 请求的设备跟curStreamDevice是否有相同的设备, 是否是默认设备
- // 如果两个条件都不符合,不会调整当前流的音量
- if ((device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) &&
- ((curStreamDevice & device) == 0)) {
- continue;
- }
-
- bool applyVolume;
- // (3) OutPut的当前设备是否与请求的设备或者请求的设备的子设备相同
- if (device != AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
- curStreamDevice |= device;
- applyVolume = (curDevice & curStreamDevice) != 0;
- } else {
- // (4) 如果请求的设备是默认设备,需要curStreamDevice没有音量配置
- applyVolume = !mVolumeCurves->hasVolumeIndexForDevice(
- stream, curStreamDevice);
- }
-
- if (applyVolume) {
- // 调用checkAndSetVolume应用该音量值
- status_t volStatus =
- checkAndSetVolume((audio_stream_type_t)curStream, index, desc, curDevice,
- (stream == AUDIO_STREAM_SYSTEM) ? TOUCH_SOUND_FIXED_DELAY_MS : 0);
Audiopoicy真正通知Audofinger调节音量的接口是checkAndSetVolume。需要传入的参数主要包括stream,outputDesc,index,force。对于AudioFlinger来说每一个output对应一个播放线程。因为每个output所用输出设备会不同,所以对于不同output需要有不同的音量, 每一个output内可以同时支持多种流播放,每个output中不同的流需要与不同的音量值. 而一个output在当前只能使用同一个输出设备, 所以AudioFlinger只需要关心每个output中每个流的音量. 在每个output都有mCurVolume[stream]保存着该流音量的分贝值。
接下来分析哪些因素会引起调节音量。首先是音量值的改变即主动调节音量setStreamVolumeIndex,其次就是设置静音setStreamMute。上面都是属于主动因素,接下来看一下被动因素,这里面主要就是输出设备的改变,可以导致输出设备改变的调用包括startOutput, stopOutput, setPhoneState, setDeviceConnectionState, setForceUse. 这些函数涉及到比较复杂的output和设备的管理。需呀逐个分析。这里暂时只分析checkAndSetVolume函数。
- status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,
- int index,
- const sp<AudioOutputDescriptor>& outputDesc,
- audio_devices_t device,
- int delayMs,
- bool force)
- {
- // 1. 如果请求的流已经被Mute, 则不能调节该流的音量
- if (outputDesc->mMuteCount[stream] != 0) {
- return NO_ERROR;
- }
- // 2. 如果设置Forceuse SCO,不能设置AUDIO_STREAM_VOICE_CALL的音量、
- // 如果没有设置Forceuse SCO,不能设置AUDIO_STREAM_BLUETOOTH_SCO的音量
- // AUDIO_STREAM_BLUETOOTH_SCO可以看作是是特殊的VOICE流,用于SCO通话
- audio_policy_forced_cfg_t forceUseForComm =
- mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION);
- if ((stream == AUDIO_STREAM_VOICE_CALL && forceUseForComm == AUDIO_POLICY_FORCE_BT_SCO) ||
- (stream == AUDIO_STREAM_BLUETOOTH_SCO && forceUseForComm != AUDIO_POLICY_FORCE_BT_SCO)) {
- return INVALID_OPERATION;
- }
- // 3. 如果传入的设备是空,使用output当前使用的音量
- // 有待分析 ???
- if (device == AUDIO_DEVICE_NONE) {
- device = outputDesc->device();
- }
-
- // 4. 获得需要调节音量的分贝值
- // 这里主要是调用volIndexToDb完成,另外还会这里还会针对一些特殊情况,调整获得音量
- // 代码中有很详尽的注释,不再具体分析
- float volumeDb = computeVolume(stream, index, device);
-
- // 5. 把音量传到AudioFlinger
- // AudioFlinger是音量调节的执行者,AudioPolicy是决策者
- outputDesc->setVolume(volumeDb, stream, device, delayMs, force);
-
- // 6. 计算并设置Voice的音量
- // 对于Voice的数据不会经过AP侧,音量的调节一般需要在底层完成(Modem?)
- if (stream == AUDIO_STREAM_VOICE_CALL ||
- stream == AUDIO_STREAM_BLUETOOTH_SCO) {
- float voiceVolume;
- if (stream == AUDIO_STREAM_VOICE_CALL) {
- // 计算出Voice流的音量
- voiceVolume = (float)index/(float)mVolumeCurves->getVolumeIndexMax(stream);
- } else {
- // 对于AUDIO_STREAM_BLUETOOTH_SCO流,蓝牙侧会调节音量,所以这里会使用最大音量值
- voiceVolume = 1.0;
- }
-
- if (voiceVolume != mLastVoiceVolume) {
- // 直接调用AudioFinger的setVoiceVolume接口
- mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
- mLastVoiceVolume = voiceVolume;
SwAudioOutputDescriptor::setVolume把计算出来的音量float volume传到AudioFlinger
- bool SwAudioOutputDescriptor::setVolume(float volume,
- audio_stream_type_t stream,
- audio_devices_t device,
- uint32_t delayMs,
- bool force)
- // 判断是否需要改变音量
- // 这里需要改变音量的条件是当前Outut的请求的流的音量已经改变
- // 或者force == true
- // 这里的mCurVolume只是区别流的音量,没有区别设备的音量,所以在切换设备的过程中,也会应用音量
- // 这里的原因大概是,一个output中所有的Track可能有不同的流类型,但是设备是相同的
- bool changed = AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force)
- return (volume != mCurVolume[stream] || force)
- if (changed) {
- // 把计算出的音量的衰减传入到AudioFnger
- // 分贝值转换为衰减,分贝值一般小于0, 所以这里计算出来的增益(理解为相对的电压值或压强值)是小于1的
- float volume = Volume::DbToAmpl(mCurVolume[stream]);
- // ???
- if (stream == AUDIO_STREAM_BLUETOOTH_SCO) {
- mClientInterface->setStreamVolume(
- AUDIO_STREAM_VOICE_CALL, volume, mIoHandle, delayMs);
- }
- // 把音量传递给AudioFinger
- mClientInterface->setStreamVolume(stream, volume, mIoHandle, delayMs);
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。