summaryrefslogtreecommitdiffstats
path: root/services/audiopolicy/engineconfigurable/src/Stream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/audiopolicy/engineconfigurable/src/Stream.cpp')
-rwxr-xr-xservices/audiopolicy/engineconfigurable/src/Stream.cpp158
1 files changed, 158 insertions, 0 deletions
diff --git a/services/audiopolicy/engineconfigurable/src/Stream.cpp b/services/audiopolicy/engineconfigurable/src/Stream.cpp
new file mode 100755
index 0000000..7126c27
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/src/Stream.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "APM::AudioPolicyEngine/Stream"
+
+#include "Stream.h"
+#include <system/audio.h>
+
+using std::string;
+
+namespace android
+{
+namespace audio_policy
+{
+
+status_t Element<audio_stream_type_t>::setIdentifier(audio_stream_type_t identifier)
+{
+ if (identifier > AUDIO_STREAM_CNT) {
+ return BAD_VALUE;
+ }
+ mIdentifier = identifier;
+ ALOGD("%s: Stream %s identifier 0x%X", __FUNCTION__, getName().c_str(), identifier);
+ return NO_ERROR;
+}
+
+/**
+* Set the strategy to follow for this stream.
+* It checks if the strategy is valid.
+*
+* @param[in] strategy to be followed.
+*
+* @return NO_ERROR if the strategy is set correctly, error code otherwise.
+*/
+template <>
+status_t Element<audio_stream_type_t>::set<routing_strategy>(routing_strategy strategy)
+{
+ if (strategy >= NUM_STRATEGIES) {
+ return BAD_VALUE;
+ }
+ mApplicableStrategy = strategy;
+ ALOGD("%s: 0x%X for Stream %s", __FUNCTION__, strategy, getName().c_str());
+ return NO_ERROR;
+}
+
+template <>
+routing_strategy Element<audio_stream_type_t>::get<routing_strategy>() const
+{
+ ALOGV("%s: 0x%X for Stream %s", __FUNCTION__, mApplicableStrategy, getName().c_str());
+ return mApplicableStrategy;
+}
+
+status_t Element<audio_stream_type_t>::setVolumeProfile(Volume::device_category category,
+ const VolumeCurvePoints &points)
+{
+ ALOGD("%s: adding volume profile for %s for device category %d, points nb =%d", __FUNCTION__,
+ getName().c_str(), category, points.size());
+ mVolumeProfiles[category] = points;
+
+ for (size_t i = 0; i < points.size(); i++) {
+ ALOGV("%s: %s cat=%d curve index =%d Index=%d dBAttenuation=%f",
+ __FUNCTION__, getName().c_str(), category, i, points[i].mIndex,
+ points[i].mDBAttenuation);
+ }
+ return NO_ERROR;
+}
+
+status_t Element<audio_stream_type_t>::initVolume(int indexMin, int indexMax)
+{
+ ALOGV("initStreamVolume() stream %s, min %d, max %d", getName().c_str(), indexMin, indexMax);
+ if (indexMin < 0 || indexMin >= indexMax) {
+ ALOGW("initStreamVolume() invalid index limits for stream %s, min %d, max %d",
+ getName().c_str(), indexMin, indexMax);
+ return BAD_VALUE;
+ }
+ mIndexMin = indexMin;
+ mIndexMax = indexMax;
+
+ return NO_ERROR;
+}
+
+float Element<audio_stream_type_t>::volIndexToAmpl(Volume::device_category deviceCategory,
+ int indexInUi)
+{
+ VolumeProfileConstIterator it = mVolumeProfiles.find(deviceCategory);
+ if (it == mVolumeProfiles.end()) {
+ ALOGE("%s: device category %d not found for stream %s", __FUNCTION__, deviceCategory,
+ getName().c_str());
+ return 1.0f;
+ }
+ const VolumeCurvePoints curve = mVolumeProfiles[deviceCategory];
+ if (curve.size() != Volume::VOLCNT) {
+ ALOGE("%s: invalid profile for category %d and for stream %s", __FUNCTION__, deviceCategory,
+ getName().c_str());
+ return 1.0f;
+ }
+
+ // the volume index in the UI is relative to the min and max volume indices for this stream type
+ int nbSteps = 1 + curve[Volume::VOLMAX].mIndex -
+ curve[Volume::VOLMIN].mIndex;
+
+ if (mIndexMax - mIndexMin == 0) {
+ ALOGE("%s: Invalid volume indexes Min=Max=%d", __FUNCTION__, mIndexMin);
+ return 1.0f;
+ }
+ int volIdx = (nbSteps * (indexInUi - mIndexMin)) /
+ (mIndexMax - mIndexMin);
+
+ // find what part of the curve this index volume belongs to, or if it's out of bounds
+ int segment = 0;
+ if (volIdx < curve[Volume::VOLMIN].mIndex) { // out of bounds
+ return 0.0f;
+ } else if (volIdx < curve[Volume::VOLKNEE1].mIndex) {
+ segment = 0;
+ } else if (volIdx < curve[Volume::VOLKNEE2].mIndex) {
+ segment = 1;
+ } else if (volIdx <= curve[Volume::VOLMAX].mIndex) {
+ segment = 2;
+ } else { // out of bounds
+ return 1.0f;
+ }
+
+ // linear interpolation in the attenuation table in dB
+ float decibels = curve[segment].mDBAttenuation +
+ ((float)(volIdx - curve[segment].mIndex)) *
+ ( (curve[segment+1].mDBAttenuation -
+ curve[segment].mDBAttenuation) /
+ ((float)(curve[segment+1].mIndex -
+ curve[segment].mIndex)) );
+
+ float amplification = exp(decibels * 0.115129f); /** exp( dB * ln(10) / 20 ) */
+
+ ALOGV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f",
+ curve[segment].mIndex, volIdx,
+ curve[segment+1].mIndex,
+ curve[segment].mDBAttenuation,
+ decibels,
+ curve[segment+1].mDBAttenuation,
+ amplification);
+
+ return amplification;
+}
+
+} // namespace audio_policy
+} // namespace android
+