summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorJean-Michel Trivi <jmtrivi@google.com>2011-01-24 15:28:26 -0800
committerJean-Michel Trivi <jmtrivi@google.com>2011-01-25 10:04:31 -0800
commit61dca6702ce50d937fc764c55bb0842b40dcd0e4 (patch)
treeafed90c2745038d5eb95f0d75c2f98a5d3fa4717 /services
parent7aa9f73b06525781245b8c2970f09f48050a276d (diff)
downloadframeworks_av-61dca6702ce50d937fc764c55bb0842b40dcd0e4.zip
frameworks_av-61dca6702ce50d937fc764c55bb0842b40dcd0e4.tar.gz
frameworks_av-61dca6702ce50d937fc764c55bb0842b40dcd0e4.tar.bz2
Bug 3376700 Add support in APM for stream-specific volume curves
The stream volume was handled the same way for all different stream, the only potential difference between each of them being the number of steps available to the user to change the volume. This was mapped to 99 steps of 0.5dB amplitude, offering a maximum attenuation of -49.5dB. This change consists in defining for each stream a curve with two knees (3 segments) for conversion from volume index to attenuation. This curve is defined in the AudioPolicyManager in initializeVolumeCurves(), and can therefore be overridden by the platform. Note that this change doesn't modify the volume curves: this CL enables the curves to be changed by overriding this default behavior. Change-Id: I575b66799c52df2906db248943b15120b8a79ea2
Diffstat (limited to 'services')
-rw-r--r--services/audioflinger/AudioPolicyManagerBase.cpp62
1 files changed, 60 insertions, 2 deletions
diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp
index e4086c4..18abc0b 100644
--- a/services/audioflinger/AudioPolicyManagerBase.cpp
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <hardware_legacy/AudioPolicyManagerBase.h>
#include <media/mediarecorder.h>
+#include <math.h>
namespace android {
@@ -1019,6 +1020,8 @@ AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clien
mForceUse[i] = AudioSystem::FORCE_NONE;
}
+ initializeVolumeCurves();
+
// devices available by default are speaker, ear piece and microphone
mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE |
AudioSystem::DEVICE_OUT_SPEAKER;
@@ -1810,6 +1813,62 @@ audio_io_handle_t AudioPolicyManagerBase::getActiveInput()
return 0;
}
+float AudioPolicyManagerBase::volIndexToAmpl(uint32_t device, const StreamDescriptor& streamDesc,
+ int indexInUi) {
+ // the volume index in the UI is relative to the min and max volume indices for this stream type
+ int nbSteps = 1 + streamDesc.mVolIndex[StreamDescriptor::VOLMAX] -
+ streamDesc.mVolIndex[StreamDescriptor::VOLMIN];
+ int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) /
+ (streamDesc.mIndexMax - streamDesc.mIndexMin);
+
+ // find what part of the curve this index volume belongs to, or if it's out of bounds
+ int segment = 0;
+ if (volIdx < streamDesc.mVolIndex[StreamDescriptor::VOLMIN]) { // out of bounds
+ return 0.0f;
+ } else if (volIdx < streamDesc.mVolIndex[StreamDescriptor::VOLKNEE1]) {
+ segment = 0;
+ } else if (volIdx < streamDesc.mVolIndex[StreamDescriptor::VOLKNEE2]) {
+ segment = 1;
+ } else if (volIdx <= streamDesc.mVolIndex[StreamDescriptor::VOLMAX]) {
+ segment = 2;
+ } else { // out of bounds
+ return 1.0f;
+ }
+
+ // linear interpolation in the attenuation table in dB
+ float decibels = streamDesc.mVolDbAtt[segment] +
+ ((float)(volIdx - streamDesc.mVolIndex[segment])) *
+ ( (streamDesc.mVolDbAtt[segment+1] - streamDesc.mVolDbAtt[segment]) /
+ ((float)(streamDesc.mVolIndex[segment+1] - streamDesc.mVolIndex[segment])) );
+
+ float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 )
+
+ LOGV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f",
+ streamDesc.mVolIndex[segment], volIdx, streamDesc.mVolIndex[segment+1],
+ streamDesc.mVolDbAtt[segment], decibels, streamDesc.mVolDbAtt[segment+1],
+ amplification);
+
+ return amplification;
+}
+
+void AudioPolicyManagerBase::initializeVolumeCurves() {
+ // initialize the volume curves to a (-49.5 - 0 dB) attenuation in 0.5dB steps
+ for (int i=0 ; i< AudioSystem::NUM_STREAM_TYPES ; i++) {
+ mStreams[i].mVolIndex[StreamDescriptor::VOLMIN] = 1;
+ mStreams[i].mVolDbAtt[StreamDescriptor::VOLMIN] = -49.5f;
+ mStreams[i].mVolIndex[StreamDescriptor::VOLKNEE1] = 33;
+ mStreams[i].mVolDbAtt[StreamDescriptor::VOLKNEE1] = -33.5f;
+ mStreams[i].mVolIndex[StreamDescriptor::VOLKNEE2] = 66;
+ mStreams[i].mVolDbAtt[StreamDescriptor::VOLKNEE2] = -17.0f;
+ // here we use 100 steps to avoid rounding errors
+ // when computing the volume in volIndexToAmpl()
+ mStreams[i].mVolIndex[StreamDescriptor::VOLMAX] = 100;
+ mStreams[i].mVolDbAtt[StreamDescriptor::VOLMAX] = 0.0f;
+ }
+
+ // TODO add modifications for music to have finer steps below knee1 and above knee2
+}
+
float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_handle_t output, uint32_t device)
{
float volume = 1.0;
@@ -1820,8 +1879,7 @@ float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_hand
device = outputDesc->device();
}
- int volInt = (100 * (index - streamDesc.mIndexMin)) / (streamDesc.mIndexMax - streamDesc.mIndexMin);
- volume = AudioSystem::linearToLog(volInt);
+ volume = volIndexToAmpl(device, streamDesc, index);
// if a headset is connected, apply the following rules to ring tones and notifications
// to avoid sound level bursts in user's ears: