120f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie/*
220f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie * Copyright (C) 2015 The Android Open Source Project
320f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie *
420f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie * Licensed under the Apache License, Version 2.0 (the "License");
520f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie * you may not use this file except in compliance with the License.
620f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie * You may obtain a copy of the License at
720f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie *
820f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie *      http://www.apache.org/licenses/LICENSE-2.0
920f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie *
1020f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie * Unless required by applicable law or agreed to in writing, software
1120f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie * distributed under the License is distributed on an "AS IS" BASIS,
1220f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie * See the License for the specific language governing permissions and
1420f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie * limitations under the License.
1520f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie */
1620f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
1720f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie#define LOG_TAG "APM::AudioPolicyEngine/Stream"
1820f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
1920f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie#include "Stream.h"
2020f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie#include <system/audio.h>
2120f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
2220f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffieusing std::string;
2320f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
2420f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffienamespace android
2520f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie{
2620f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffienamespace audio_policy
2720f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie{
2820f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
2920f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffiestatus_t Element<audio_stream_type_t>::setIdentifier(audio_stream_type_t identifier)
3020f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie{
3120f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    if (identifier > AUDIO_STREAM_CNT) {
3220f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie        return BAD_VALUE;
3320f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    }
3420f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    mIdentifier = identifier;
3520f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    ALOGD("%s: Stream %s identifier 0x%X", __FUNCTION__, getName().c_str(), identifier);
3620f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    return NO_ERROR;
3720f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie}
3820f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
3920f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie/**
4020f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie* Set the strategy to follow for this stream.
4120f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie* It checks if the strategy is valid.
4220f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie*
4320f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie* @param[in] strategy to be followed.
4420f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie*
4520f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie* @return NO_ERROR if the strategy is set correctly, error code otherwise.
4620f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie*/
4720f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffietemplate <>
4820f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffiestatus_t Element<audio_stream_type_t>::set<routing_strategy>(routing_strategy strategy)
4920f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie{
5020f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    if (strategy >= NUM_STRATEGIES) {
5120f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie        return BAD_VALUE;
5220f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    }
5320f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    mApplicableStrategy = strategy;
5420f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    ALOGD("%s: 0x%X for Stream %s", __FUNCTION__, strategy, getName().c_str());
5520f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    return NO_ERROR;
5620f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie}
5720f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
5820f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffietemplate <>
5920f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffierouting_strategy Element<audio_stream_type_t>::get<routing_strategy>() const
6020f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie{
6120f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    ALOGV("%s: 0x%X for Stream %s", __FUNCTION__, mApplicableStrategy, getName().c_str());
6220f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    return mApplicableStrategy;
6320f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie}
6420f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
6520f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffiestatus_t Element<audio_stream_type_t>::setVolumeProfile(Volume::device_category category,
6620f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie                                                        const VolumeCurvePoints &points)
6720f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie{
6820f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    ALOGD("%s: adding volume profile for %s for device category %d, points nb =%d", __FUNCTION__,
6920f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie          getName().c_str(), category, points.size());
7020f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    mVolumeProfiles[category] = points;
7120f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
7220f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    for (size_t i = 0; i < points.size(); i++) {
7320f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie        ALOGV("%s: %s cat=%d curve index =%d Index=%d dBAttenuation=%f",
7420f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie              __FUNCTION__, getName().c_str(), category, i, points[i].mIndex,
7520f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie             points[i].mDBAttenuation);
7620f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    }
7720f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    return NO_ERROR;
7820f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie}
7920f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
8020f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffiestatus_t Element<audio_stream_type_t>::initVolume(int indexMin, int indexMax)
8120f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie{
8220f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    ALOGV("initStreamVolume() stream %s, min %d, max %d", getName().c_str(), indexMin, indexMax);
8320f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    if (indexMin < 0 || indexMin >= indexMax) {
8420f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie        ALOGW("initStreamVolume() invalid index limits for stream %s, min %d, max %d",
8520f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie              getName().c_str(), indexMin, indexMax);
8620f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie        return BAD_VALUE;
8720f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    }
8820f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    mIndexMin = indexMin;
8920f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    mIndexMax = indexMax;
9020f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
9120f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    return NO_ERROR;
9220f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie}
9320f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
9420f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffiefloat Element<audio_stream_type_t>::volIndexToDb(Volume::device_category deviceCategory,
9520f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie                                                   int indexInUi)
9620f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie{
9720f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    VolumeProfileConstIterator it = mVolumeProfiles.find(deviceCategory);
9820f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    if (it == mVolumeProfiles.end()) {
9920f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie        ALOGE("%s: device category %d not found for stream %s", __FUNCTION__, deviceCategory,
10020f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie              getName().c_str());
10120f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie        return 1.0f;
10220f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    }
10320f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    const VolumeCurvePoints curve = mVolumeProfiles[deviceCategory];
10420f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    if (curve.size() != Volume::VOLCNT) {
10520f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie        ALOGE("%s: invalid profile for category %d and for stream %s", __FUNCTION__, deviceCategory,
10620f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie              getName().c_str());
10720f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie        return 1.0f;
10820f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    }
10920f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
11020f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    // the volume index in the UI is relative to the min and max volume indices for this stream type
11120f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    int nbSteps = 1 + curve[Volume::VOLMAX].mIndex -
11220f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie            curve[Volume::VOLMIN].mIndex;
11320f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
11420f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    if (mIndexMax - mIndexMin == 0) {
11520f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie        ALOGE("%s: Invalid volume indexes Min=Max=%d", __FUNCTION__, mIndexMin);
11620f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie        return 1.0f;
11720f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    }
11820f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    int volIdx = (nbSteps * (indexInUi - mIndexMin)) /
11920f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie            (mIndexMax - mIndexMin);
12020f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
12120f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    // find what part of the curve this index volume belongs to, or if it's out of bounds
12220f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    int segment = 0;
12320f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    if (volIdx < curve[Volume::VOLMIN].mIndex) {         // out of bounds
12420f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie        return 0.0f;
12520f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    } else if (volIdx < curve[Volume::VOLKNEE1].mIndex) {
12620f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie        segment = 0;
12720f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    } else if (volIdx < curve[Volume::VOLKNEE2].mIndex) {
12820f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie        segment = 1;
12920f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    } else if (volIdx <= curve[Volume::VOLMAX].mIndex) {
13020f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie        segment = 2;
13120f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    } else {                                                               // out of bounds
13220f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie        return 1.0f;
13320f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    }
13420f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
13520f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    // linear interpolation in the attenuation table in dB
13620f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    float decibels = curve[segment].mDBAttenuation +
13720f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie            ((float)(volIdx - curve[segment].mIndex)) *
13820f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie                ( (curve[segment+1].mDBAttenuation -
13920f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie                        curve[segment].mDBAttenuation) /
14020f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie                    ((float)(curve[segment+1].mIndex -
14120f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie                            curve[segment].mIndex)) );
14220f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
14320f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    ALOGV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f]",
14420f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie            curve[segment].mIndex, volIdx,
14520f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie            curve[segment+1].mIndex,
14620f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie            curve[segment].mDBAttenuation,
14720f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie            decibels,
14820f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie            curve[segment+1].mDBAttenuation);
14920f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
15020f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie    return decibels;
15120f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie}
15220f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
15320f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie} // namespace audio_policy
15420f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie} // namespace android
15520f06f996337c9bf79d0b112083f6427a122ebabFrançois Gaffie
156