From 000bb51ca507645f3aa4ccfcbbb8859e8d539629 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Sat, 12 Oct 2013 16:29:39 -0700 Subject: audio policy: fix gapless playback when effects enabled Do not allow offloading if one non offloadable effect is enabled. This prevents from creating an offloaded track and tearing it down immediately after start when audioflinger detects there is an active non offloadable effect. Not doing so breaks gapless playback because AwesomePlayer will always be able to open an offloaded track which will not be compatible with the previous PCM track and Audiosink::open() will not recycle it. Bug: 11181933. Change-Id: I6d163806849d9093b9ec701ba8e8c1ccb658e3c8 --- audio/AudioPolicyManagerBase.cpp | 45 +++++++++++++++++++++--- include/hardware_legacy/AudioPolicyManagerBase.h | 2 ++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/audio/AudioPolicyManagerBase.cpp b/audio/AudioPolicyManagerBase.cpp index c176146..dbca8ff 100644 --- a/audio/AudioPolicyManagerBase.cpp +++ b/audio/AudioPolicyManagerBase.cpp @@ -582,11 +582,22 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str flags = (AudioSystem::output_flags)(flags | AUDIO_OUTPUT_FLAG_DIRECT); } - IOProfile *profile = getProfileForDirectOutput(device, - samplingRate, - format, - channelMask, - (audio_output_flags_t)flags); + // Do not allow offloading if one non offloadable effect is enabled. This prevents from + // creating an offloaded track and tearing it down immediately after start when audioflinger + // detects there is an active non offloadable effect. + // FIXME: We should check the audio session here but we do not have it in this context. + // This may prevent offloading in rare situations where effects are left active by apps + // in the background. + IOProfile *profile = NULL; + if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) || + !isNonOffloadableEffectEnabled()) { + profile = getProfileForDirectOutput(device, + samplingRate, + format, + channelMask, + (audio_output_flags_t)flags); + } + if (profile != NULL) { AudioOutputDescriptor *outputDesc = NULL; @@ -1299,6 +1310,20 @@ status_t AudioPolicyManagerBase::setEffectEnabled(EffectDescriptor *pDesc, bool return NO_ERROR; } +bool AudioPolicyManagerBase::isNonOffloadableEffectEnabled() +{ + for (size_t i = 0; i < mEffects.size(); i++) { + const EffectDescriptor * const pDesc = mEffects.valueAt(i); + if (pDesc->mEnabled && (pDesc->mStrategy == STRATEGY_MEDIA) && + ((pDesc->mDesc.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) == 0)) { + ALOGV("isNonOffloadableEffectEnabled() non offloadable effect %s enabled on session %d", + pDesc->mDesc.name, pDesc->mSession); + return true; + } + } + return false; +} + bool AudioPolicyManagerBase::isStreamActive(int stream, uint32_t inPastMs) const { nsecs_t sysTime = systemTime(); @@ -1472,6 +1497,16 @@ bool AudioPolicyManagerBase::isOffloadSupported(const audio_offload_info_t& offl return false; } + // Do not allow offloading if one non offloadable effect is enabled. This prevents from + // creating an offloaded track and tearing it down immediately after start when audioflinger + // detects there is an active non offloadable effect. + // FIXME: We should check the audio session here but we do not have it in this context. + // This may prevent offloading in rare situations where effects are left active by apps + // in the background. + if (isNonOffloadableEffectEnabled()) { + return false; + } + // See if there is a profile to support this. // AUDIO_DEVICE_NONE IOProfile *profile = getProfileForDirectOutput(AUDIO_DEVICE_NONE /*ignore device */, diff --git a/include/hardware_legacy/AudioPolicyManagerBase.h b/include/hardware_legacy/AudioPolicyManagerBase.h index 482ea86..5fea77a 100644 --- a/include/hardware_legacy/AudioPolicyManagerBase.h +++ b/include/hardware_legacy/AudioPolicyManagerBase.h @@ -491,6 +491,8 @@ protected: audio_io_handle_t selectOutputForEffects(const SortedVector& outputs); + bool isNonOffloadableEffectEnabled(); + // // Audio policy configuration file parsing (audio_policy.conf) // -- cgit v1.1 From 18fc094c0ed41851be3d746423c6695dd28d48e1 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Thu, 14 Nov 2013 16:30:20 -0800 Subject: Define and use DRC-specific volume curves when applicable Add support for property defining whether a DRC on the speaker path is enabled and will boost soft sounds. Define new volume curves with more attenuations than existing ones to compensate for DRC-induced boost on sonification sounds to provide a more "linear" control to the user over the applied volume. Bug 11600699 Change-Id: If23dd097a8b9b5ebb61e75dd8512ff75e63ba899 --- audio/AudioPolicyManagerBase.cpp | 38 ++++++++++++++++++++++-- include/hardware_legacy/AudioPolicyManagerBase.h | 5 ++++ include/hardware_legacy/audio_policy_conf.h | 1 + 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/audio/AudioPolicyManagerBase.cpp b/audio/AudioPolicyManagerBase.cpp index dbca8ff..65e732f 100644 --- a/audio/AudioPolicyManagerBase.cpp +++ b/audio/AudioPolicyManagerBase.cpp @@ -1532,7 +1532,8 @@ AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clien mPhoneState(AudioSystem::MODE_NORMAL), mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f), mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0), - mA2dpSuspended(false), mHasA2dp(false), mHasUsb(false), mHasRemoteSubmix(false) + mA2dpSuspended(false), mHasA2dp(false), mHasUsb(false), mHasRemoteSubmix(false), + mSpeakerDrcEnabled(false) { mpClientInterface = clientInterface; @@ -1540,8 +1541,6 @@ AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clien mForceUse[i] = AudioSystem::FORCE_NONE; } - initializeVolumeCurves(); - mA2dpDeviceAddress = String8(""); mScoDeviceAddress = String8(""); mUsbCardAndDevice = String8(""); @@ -1553,6 +1552,9 @@ AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clien } } + // must be done after reading the policy + initializeVolumeCurves(); + // open all output streams needed to access attached devices for (size_t i = 0; i < mHwModules.size(); i++) { mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName); @@ -2874,6 +2876,11 @@ const AudioPolicyManagerBase::VolumeCurvePoint {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f} }; +const AudioPolicyManagerBase::VolumeCurvePoint + AudioPolicyManagerBase::sSpeakerSonificationVolumeCurveDrc[AudioPolicyManagerBase::VOLCNT] = { + {1, -35.7f}, {33, -26.1f}, {66, -13.2f}, {100, 0.0f} +}; + // AUDIO_STREAM_SYSTEM, AUDIO_STREAM_ENFORCED_AUDIBLE and AUDIO_STREAM_DTMF volume tracks // AUDIO_STREAM_RING on phones and AUDIO_STREAM_MUSIC on tablets. // AUDIO_STREAM_DTMF tracks AUDIO_STREAM_VOICE_CALL while in call (See AudioService.java). @@ -2885,6 +2892,11 @@ const AudioPolicyManagerBase::VolumeCurvePoint }; const AudioPolicyManagerBase::VolumeCurvePoint + AudioPolicyManagerBase::sDefaultSystemVolumeCurveDrc[AudioPolicyManagerBase::VOLCNT] = { + {1, -34.0f}, {33, -24.0f}, {66, -15.0f}, {100, -6.0f} +}; + +const AudioPolicyManagerBase::VolumeCurvePoint AudioPolicyManagerBase::sHeadsetSystemVolumeCurve[AudioPolicyManagerBase::VOLCNT] = { {1, -30.0f}, {33, -26.0f}, {66, -22.0f}, {100, -18.0f} }; @@ -2962,6 +2974,18 @@ void AudioPolicyManagerBase::initializeVolumeCurves() sVolumeProfiles[i][j]; } } + + // Check availability of DRC on speaker path: if available, override some of the speaker curves + if (mSpeakerDrcEnabled) { + mStreams[AUDIO_STREAM_SYSTEM].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = + sDefaultSystemVolumeCurveDrc; + mStreams[AUDIO_STREAM_RING].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = + sSpeakerSonificationVolumeCurveDrc; + mStreams[AUDIO_STREAM_ALARM].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = + sSpeakerSonificationVolumeCurveDrc; + mStreams[AUDIO_STREAM_NOTIFICATION].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] = + sSpeakerSonificationVolumeCurveDrc; + } } float AudioPolicyManagerBase::computeVolume(int stream, @@ -3688,6 +3712,11 @@ uint32_t AudioPolicyManagerBase::stringToEnum(const struct StringToEnum *table, return 0; } +bool AudioPolicyManagerBase::stringToBool(const char *value) +{ + return ((strcasecmp("true", value) == 0) || (strcmp("1", value) == 0)); +} + audio_output_flags_t AudioPolicyManagerBase::parseFlagNames(char *name) { uint32_t flag = 0; @@ -3993,6 +4022,9 @@ void AudioPolicyManagerBase::loadGlobalConfig(cnode *root) } else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) { mAvailableInputDevices = parseDeviceNames((char *)node->value) & ~AUDIO_DEVICE_BIT_IN; ALOGV("loadGlobalConfig() mAvailableInputDevices %04x", mAvailableInputDevices); + } else if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) { + mSpeakerDrcEnabled = stringToBool((char *)node->value); + ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", mSpeakerDrcEnabled); } node = node->next; } diff --git a/include/hardware_legacy/AudioPolicyManagerBase.h b/include/hardware_legacy/AudioPolicyManagerBase.h index 5fea77a..8343f2b 100644 --- a/include/hardware_legacy/AudioPolicyManagerBase.h +++ b/include/hardware_legacy/AudioPolicyManagerBase.h @@ -236,7 +236,9 @@ protected: static const VolumeCurvePoint sSpeakerMediaVolumeCurve[AudioPolicyManagerBase::VOLCNT]; // volume curve for sonification strategy on speakers static const VolumeCurvePoint sSpeakerSonificationVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + static const VolumeCurvePoint sSpeakerSonificationVolumeCurveDrc[AudioPolicyManagerBase::VOLCNT]; static const VolumeCurvePoint sDefaultSystemVolumeCurve[AudioPolicyManagerBase::VOLCNT]; + static const VolumeCurvePoint sDefaultSystemVolumeCurveDrc[AudioPolicyManagerBase::VOLCNT]; static const VolumeCurvePoint sHeadsetSystemVolumeCurve[AudioPolicyManagerBase::VOLCNT]; static const VolumeCurvePoint sDefaultVoiceVolumeCurve[AudioPolicyManagerBase::VOLCNT]; static const VolumeCurvePoint sSpeakerVoiceVolumeCurve[AudioPolicyManagerBase::VOLCNT]; @@ -499,6 +501,7 @@ protected: static uint32_t stringToEnum(const struct StringToEnum *table, size_t size, const char *name); + static bool stringToBool(const char *value); static audio_output_flags_t parseFlagNames(char *name); static audio_devices_t parseDeviceNames(char *name); void loadSamplingRates(char *name, IOProfile *profile); @@ -552,6 +555,8 @@ protected: audio_devices_t mAttachedOutputDevices; // output devices always available on the platform audio_devices_t mDefaultOutputDevice; // output device selected by default at boot time // (must be in mAttachedOutputDevices) + bool mSpeakerDrcEnabled;// true on devices that use DRC on the DEVICE_CATEGORY_SPEAKER path + // to boost soft sounds, used to adjust volume curves accordingly Vector mHwModules; diff --git a/include/hardware_legacy/audio_policy_conf.h b/include/hardware_legacy/audio_policy_conf.h index fa58c36..3ec2c94 100644 --- a/include/hardware_legacy/audio_policy_conf.h +++ b/include/hardware_legacy/audio_policy_conf.h @@ -34,6 +34,7 @@ #define ATTACHED_OUTPUT_DEVICES_TAG "attached_output_devices" #define DEFAULT_OUTPUT_DEVICE_TAG "default_output_device" #define ATTACHED_INPUT_DEVICES_TAG "attached_input_devices" +#define SPEAKER_DRC_ENABLED_TAG "speaker_drc_enabled" // hw modules descriptions #define AUDIO_HW_MODULE_TAG "audio_hw_modules" -- cgit v1.1