summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2011-10-18 14:03:28 -0700
committerEric Laurent <elaurent@google.com>2011-10-18 18:29:26 -0700
commite43c5c4ca4477a6b384711552c3e990609039d93 (patch)
tree7fbfac1c95edb2a67066bad28173c9c056da350c /audio
parent3a9b39837b4c13a6221d5d60ec0b7452ec4edf8a (diff)
downloadhardware_libhardware_legacy-e43c5c4ca4477a6b384711552c3e990609039d93.zip
hardware_libhardware_legacy-e43c5c4ca4477a6b384711552c3e990609039d93.tar.gz
hardware_libhardware_legacy-e43c5c4ca4477a6b384711552c3e990609039d93.tar.bz2
Fix issue 5440852: Youtube volume is too small ...
When no DRC is applied by the platform when playing over the device speaker, faint audio signals are not boosted and barely audible until the media volume is raised to about one fourth of the range. Compensate this by applying a different volume curve for music stream when the speaker is selected. Change-Id: I03f316fb28150eda50b05dfa12310701e2674648
Diffstat (limited to 'audio')
-rw-r--r--audio/AudioPolicyManagerBase.cpp137
1 files changed, 111 insertions, 26 deletions
diff --git a/audio/AudioPolicyManagerBase.cpp b/audio/AudioPolicyManagerBase.cpp
index 35d72e2..191ba9d 100644
--- a/audio/AudioPolicyManagerBase.cpp
+++ b/audio/AudioPolicyManagerBase.cpp
@@ -1868,61 +1868,146 @@ audio_io_handle_t AudioPolicyManagerBase::getActiveInput()
return 0;
}
+
+AudioPolicyManagerBase::device_category AudioPolicyManagerBase::getDeviceCategory(uint32_t device)
+{
+ if (device == 0) {
+ // this happens when forcing a route update and no track is active on an output.
+ // In this case the returned category is not important.
+ return DEVICE_CATEGORY_SPEAKER;
+ }
+
+ if (AudioSystem::popCount(device) > 1) {
+ // Multiple device selection is either:
+ // - speaker + one other device: give priority to speaker in this case.
+ // - one A2DP device + another device: happens with duplicated output. In this case
+ // retain the device on the A2DP output as the other must not correspond to an active
+ // selection if not the speaker.
+ if (device & AUDIO_DEVICE_OUT_SPEAKER)
+ return DEVICE_CATEGORY_SPEAKER;
+
+ device &= AUDIO_DEVICE_OUT_ALL_A2DP;
+ }
+
+ LOGW_IF(AudioSystem::popCount(device) != 1,
+ "getDeviceCategory() invalid device combination: %08x",
+ device);
+
+ switch(device) {
+ case AUDIO_DEVICE_OUT_EARPIECE:
+ return DEVICE_CATEGORY_EARPIECE;
+ case AUDIO_DEVICE_OUT_WIRED_HEADSET:
+ case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
+ return DEVICE_CATEGORY_HEADSET;
+ case AUDIO_DEVICE_OUT_SPEAKER:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
+ default:
+ return DEVICE_CATEGORY_SPEAKER;
+ }
+}
+
float AudioPolicyManagerBase::volIndexToAmpl(uint32_t device, const StreamDescriptor& streamDesc,
- int indexInUi) {
+ int indexInUi)
+{
+ device_category deviceCategory = getDeviceCategory(device);
+ const VolumeCurvePoint *curve = streamDesc.mVolumeCurve[deviceCategory];
+
// the volume index in the UI is relative to the min and max volume indices for this stream type
- int nbSteps = 1 + streamDesc.mVolumeCurve[VOLMAX].mIndex -
- streamDesc.mVolumeCurve[VOLMIN].mIndex;
+ int nbSteps = 1 + curve[VOLMAX].mIndex -
+ curve[VOLMIN].mIndex;
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.mVolumeCurve[VOLMIN].mIndex) { // out of bounds
+ if (volIdx < curve[VOLMIN].mIndex) { // out of bounds
return 0.0f;
- } else if (volIdx < streamDesc.mVolumeCurve[VOLKNEE1].mIndex) {
+ } else if (volIdx < curve[VOLKNEE1].mIndex) {
segment = 0;
- } else if (volIdx < streamDesc.mVolumeCurve[VOLKNEE2].mIndex) {
+ } else if (volIdx < curve[VOLKNEE2].mIndex) {
segment = 1;
- } else if (volIdx <= streamDesc.mVolumeCurve[VOLMAX].mIndex) {
+ } else if (volIdx <= curve[VOLMAX].mIndex) {
segment = 2;
} else { // out of bounds
return 1.0f;
}
// linear interpolation in the attenuation table in dB
- float decibels = streamDesc.mVolumeCurve[segment].mDBAttenuation +
- ((float)(volIdx - streamDesc.mVolumeCurve[segment].mIndex)) *
- ( (streamDesc.mVolumeCurve[segment+1].mDBAttenuation -
- streamDesc.mVolumeCurve[segment].mDBAttenuation) /
- ((float)(streamDesc.mVolumeCurve[segment+1].mIndex -
- streamDesc.mVolumeCurve[segment].mIndex)) );
+ 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 )
LOGV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f",
- streamDesc.mVolumeCurve[segment].mIndex, volIdx,
- streamDesc.mVolumeCurve[segment+1].mIndex,
- streamDesc.mVolumeCurve[segment].mDBAttenuation,
+ curve[segment].mIndex, volIdx,
+ curve[segment+1].mIndex,
+ curve[segment].mDBAttenuation,
decibels,
- streamDesc.mVolumeCurve[segment+1].mDBAttenuation,
+ curve[segment+1].mDBAttenuation,
amplification);
return amplification;
}
const AudioPolicyManagerBase::VolumeCurvePoint
- AudioPolicyManagerBase::sVolumeProfiles[AudioPolicyManagerBase::NUM_STRATEGIES]
- [AudioPolicyManagerBase::VOLCNT] = {
- { {1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f}}, // STRATEGY_MEDIA
- { {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f}}, // STRATEGY_PHONE
- { {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f}}, // STRATEGY_SONIFICATION
- { {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f}} // STRATEGY_DTMF
+ AudioPolicyManagerBase::sDefaultVolumeCurve[AudioPolicyManagerBase::VOLCNT] = {
+ {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f}
+};
+
+const AudioPolicyManagerBase::VolumeCurvePoint
+ AudioPolicyManagerBase::sDefaultMediaVolumeCurve[AudioPolicyManagerBase::VOLCNT] = {
+ {1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f}
};
-void AudioPolicyManagerBase::initializeVolumeCurves() {
- for (int i=0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
- for (int j=0; j < VOLCNT; j++) {
+const AudioPolicyManagerBase::VolumeCurvePoint
+ AudioPolicyManagerBase::sSpeakerMediaVolumeCurve[AudioPolicyManagerBase::VOLCNT] = {
+ {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f}
+};
+
+const AudioPolicyManagerBase::VolumeCurvePoint
+ AudioPolicyManagerBase::sSpeakerSonificationVolumeCurve[AudioPolicyManagerBase::VOLCNT] = {
+ {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f}
+};
+
+
+const AudioPolicyManagerBase::VolumeCurvePoint
+ *AudioPolicyManagerBase::sVolumeProfiles[AudioPolicyManagerBase::NUM_STRATEGIES]
+ [AudioPolicyManagerBase::DEVICE_CATEGORY_CNT] = {
+ { // STRATEGY_MEDIA
+ sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ sDefaultMediaVolumeCurve // DEVICE_CATEGORY_EARPIECE
+ },
+ { // STRATEGY_PHONE
+ sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ sDefaultVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ sDefaultVolumeCurve // DEVICE_CATEGORY_EARPIECE
+ },
+ { // STRATEGY_SONIFICATION
+ sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ sDefaultVolumeCurve // DEVICE_CATEGORY_EARPIECE
+ },
+ { // STRATEGY_DTMF
+ sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ sDefaultVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ sDefaultVolumeCurve // DEVICE_CATEGORY_EARPIECE
+ }
+};
+
+void AudioPolicyManagerBase::initializeVolumeCurves()
+{
+ for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
+ for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
mStreams[i].mVolumeCurve[j] =
sVolumeProfiles[getStrategy((AudioSystem::stream_type)i)][j];
}