1d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie/* 2d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie * Copyright (C) 2015 The Android Open Source Project 3d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie * 4d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie * Licensed under the Apache License, Version 2.0 (the "License"); 5d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie * you may not use this file except in compliance with the License. 6d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie * You may obtain a copy of the License at 7d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie * 8d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie * http://www.apache.org/licenses/LICENSE-2.0 9d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie * 10d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie * Unless required by applicable law or agreed to in writing, software 11d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie * distributed under the License is distributed on an "AS IS" BASIS, 12d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie * See the License for the specific language governing permissions and 14d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie * limitations under the License. 15d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie */ 16d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie 17d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie#define LOG_TAG "APM::VolumeCurve" 18d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie//#define LOG_NDEBUG 0 19d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie 20d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie#include "VolumeCurve.h" 21d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie#include "TypeConverter.h" 22d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie 23d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffienamespace android { 24d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie 25d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffiefloat VolumeCurve::volIndexToDb(int indexInUi, int volIndexMin, int volIndexMax) const 26d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie{ 27d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie ALOG_ASSERT(!mCurvePoints.isEmpty(), "Invalid volume curve"); 28d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie 29d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie size_t nbCurvePoints = mCurvePoints.size(); 30d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie // the volume index in the UI is relative to the min and max volume indices for this stream 31d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie int nbSteps = 1 + mCurvePoints[nbCurvePoints - 1].mIndex - mCurvePoints[0].mIndex; 32d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie int volIdx = (nbSteps * (indexInUi - volIndexMin)) / (volIndexMax - volIndexMin); 33d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie 34d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie // Where would this volume index been inserted in the curve point 35d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie size_t indexInUiPosition = mCurvePoints.orderOf(CurvePoint(volIdx, 0)); 36d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie if (indexInUiPosition >= nbCurvePoints) { 37d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie return 0.0f; // out of bounds 38d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie } 39d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie if (indexInUiPosition == 0) { 40d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie if (indexInUiPosition != mCurvePoints[0].mIndex) { 41d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie return VOLUME_MIN_DB; // out of bounds 42d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie } 43d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie return mCurvePoints[0].mAttenuationInMb / 100.0f; 44d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie } 45d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie // linear interpolation in the attenuation table in dB 46d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie float decibels = (mCurvePoints[indexInUiPosition - 1].mAttenuationInMb / 100.0f) + 47d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie ((float)(volIdx - mCurvePoints[indexInUiPosition - 1].mIndex)) * 48d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie ( ((mCurvePoints[indexInUiPosition].mAttenuationInMb / 100.0f) - 49d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie (mCurvePoints[indexInUiPosition - 1].mAttenuationInMb / 100.0f)) / 50d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie ((float)(mCurvePoints[indexInUiPosition].mIndex - 51d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie mCurvePoints[indexInUiPosition - 1].mIndex)) ); 52d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie 53d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie ALOGV("VOLUME mDeviceCategory %d, mStreamType %d vol index=[%d %d %d], dB=[%.1f %.1f %.1f]", 54d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie mDeviceCategory, mStreamType, 55d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie mCurvePoints[indexInUiPosition - 1].mIndex, volIdx, 56d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie mCurvePoints[indexInUiPosition].mIndex, 57d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie ((float)mCurvePoints[indexInUiPosition - 1].mAttenuationInMb / 100.0f), decibels, 58d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie ((float)mCurvePoints[indexInUiPosition].mAttenuationInMb / 100.0f)); 59d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie 60d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie return decibels; 61d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie} 62d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie 63d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffievoid VolumeCurve::dump(int fd) const 64d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie{ 65d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie const size_t SIZE = 256; 66d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie char buffer[SIZE]; 67d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie String8 result; 68d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie snprintf(buffer, SIZE, " {"); 69d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie result.append(buffer); 70d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie for (size_t i = 0; i < mCurvePoints.size(); i++) { 71d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie snprintf(buffer, SIZE, "(%3d, %5d)", 72d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie mCurvePoints[i].mIndex, mCurvePoints[i].mAttenuationInMb); 73d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie result.append(buffer); 74d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie result.append(i == (mCurvePoints.size() - 1) ? " }\n" : ", "); 75d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie } 76d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie write(fd, result.string(), result.size()); 77d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie} 78d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie 79d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffievoid VolumeCurvesForStream::dump(int fd, int spaces = 0, bool curvePoints) const 80d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie{ 81d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie const size_t SIZE = 256; 82d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie char buffer[SIZE]; 83d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie String8 result; 84d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie 85d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie if (!curvePoints) { 86d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie snprintf(buffer, SIZE, "%s %02d %02d ", 87d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax); 88d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie result.append(buffer); 89d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie for (size_t i = 0; i < mIndexCur.size(); i++) { 90d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie snprintf(buffer, SIZE, "%04x : %02d, ", mIndexCur.keyAt(i), mIndexCur.valueAt(i)); 91d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie result.append(buffer); 92d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie } 93d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie result.append("\n"); 94d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie write(fd, result.string(), result.size()); 95d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie return; 96d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie } 97d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie 98d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie for (size_t i = 0; i < size(); i++) { 99d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie std::string deviceCatLiteral; 100d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie DeviceCategoryConverter::toString(keyAt(i), deviceCatLiteral); 101d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie snprintf(buffer, SIZE, "%*s %s :", 102d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie spaces, "", deviceCatLiteral.c_str()); 103d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie write(fd, buffer, strlen(buffer)); 104d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie valueAt(i)->dump(fd); 105d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie } 106d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie result.append("\n"); 107d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie write(fd, result.string(), result.size()); 108d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie} 109d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie 110d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffiestatus_t VolumeCurvesCollection::dump(int fd) const 111d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie{ 112d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie const size_t SIZE = 256; 113d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie char buffer[SIZE]; 114d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie 115d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie snprintf(buffer, SIZE, "\nStreams dump:\n"); 116d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie write(fd, buffer, strlen(buffer)); 117d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie snprintf(buffer, SIZE, 118d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie " Stream Can be muted Index Min Index Max Index Cur [device : index]...\n"); 119d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie write(fd, buffer, strlen(buffer)); 120d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie for (size_t i = 0; i < size(); i++) { 121d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie snprintf(buffer, SIZE, " %02zu ", i); 122d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie write(fd, buffer, strlen(buffer)); 123d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie valueAt(i).dump(fd); 124d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie } 125d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie snprintf(buffer, SIZE, "\nVolume Curves for Use Cases (aka Stream types) dump:\n"); 126d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie write(fd, buffer, strlen(buffer)); 127d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie for (size_t i = 0; i < size(); i++) { 128d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie std::string streamTypeLiteral; 129d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie StreamTypeConverter::toString(keyAt(i), streamTypeLiteral); 130d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie snprintf(buffer, SIZE, 131d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie " %s (%02zu): Curve points for device category (index, attenuation in millibel)\n", 132d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie streamTypeLiteral.c_str(), i); 133d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie write(fd, buffer, strlen(buffer)); 134d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie valueAt(i).dump(fd, 2, true); 135d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie } 136d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie 137d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie return NO_ERROR; 138d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie} 139d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie 140d1ab2bd4f1ea166a7e9e81cfd7f3e5dd47135d4dFrançois Gaffie}; // namespace android 141