Fix volume problems with insert revert
- Use a constant input level to the reverb engine and implement volume control in the
insert reverb. This avoids the volume spikes when an effect that was inserted after
the reverb is disabled or removed.
- Fix clicks (one silent buffer) at the end of the reverb disable period.
- Modified volume management in audioflinger so that the volume ramp is also done by
the insert effect if present when the track is paused (avoids clicks).
- Increased room level for all presets.
Also fixed problems with output stage session (-1):
- effect bundle wrapper was not designed to support session -1
- the permission check in audioflinger for using session -1 failed due to a wrong usage of
getCallingPid()
Change-Id: Id1ff51327263364bf71d3f2668fa5cde4311d84f
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index e86ed99..90756d0 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -65,6 +65,7 @@
int LvmInitFlag = LVM_FALSE;
int LvmSessionsActive = 0;
SessionContext GlobalSessionMemory[LVM_MAX_SESSIONS];
+
int SessionIndex[LVM_MAX_SESSIONS];
// NXP SW BassBoost UUID
@@ -199,11 +200,6 @@
return -EINVAL;
}
- if(sessionId < 0){
- LOGV("\tLVM_ERROR : EffectCreate sessionId is less than 0");
- return -EINVAL;
- }
-
if(LvmInitFlag == LVM_FALSE){
LvmInitFlag = LVM_TRUE;
LOGV("\tEffectCreate - Initializing all global memory");
@@ -214,7 +210,7 @@
// Find next available sessionNo
for(i=0; i<LVM_MAX_SESSIONS; i++){
- if((SessionIndex[i] == -1)||(SessionIndex[i] == sessionId)){
+ if((SessionIndex[i] == LVM_UNUSED_SESSION)||(SessionIndex[i] == sessionId)){
sessionNo = i;
SessionIndex[i] = sessionId;
LOGV("\tEffectCreate: Allocating SessionNo %d for SessionId %d\n", sessionNo,sessionId);
@@ -398,7 +394,7 @@
// Clear the SessionIndex
for(int i=0; i<LVM_MAX_SESSIONS; i++){
if(SessionIndex[i] == pContext->pBundledContext->SessionId){
- SessionIndex[i] = -1;
+ SessionIndex[i] = LVM_UNUSED_SESSION;
LOGV("\tEffectRelease: Clearing SessionIndex SessionNo %d for SessionId %d\n",
i, pContext->pBundledContext->SessionId);
break;
@@ -432,7 +428,7 @@
GlobalSessionMemory[i].bVirtualizerInstantiated = LVM_FALSE;
GlobalSessionMemory[i].pBundledContext = LVM_NULL;
- SessionIndex[i] = -1;
+ SessionIndex[i] = LVM_UNUSED_SESSION;
}
return;
}
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
index 35e1114..91963af 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -21,6 +21,7 @@
#include <media/EffectBassBoostApi.h>
#include <media/EffectVirtualizerApi.h>
#include <LVM.h>
+#include <limits.h>
#if __cplusplus
extern "C" {
@@ -30,6 +31,7 @@
#define MAX_NUM_BANDS 5
#define MAX_CALL_SIZE 256
#define LVM_MAX_SESSIONS 32
+#define LVM_UNUSED_SESSION INT_MAX
#define BASS_BOOST_CUP_LOAD_ARM9E 150 // Expressed in 0.1 MIPS
#define VIRTUALIZER_CUP_LOAD_ARM9E 120 // Expressed in 0.1 MIPS
#define EQUALIZER_CUP_LOAD_ARM9E 220 // Expressed in 0.1 MIPS
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 60f4288..26c5aca 100755
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -59,17 +59,17 @@
// REVERB_PRESET_NONE: values are unused
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
// REVERB_PRESET_SMALLROOM
- {-1000, -600, 1100, 830, -400, 5, 500, 10, 1000, 1000},
+ {-400, -600, 1100, 830, -400, 5, 500, 10, 1000, 1000},
// REVERB_PRESET_MEDIUMROOM
- {-1000, -600, 1300, 830, -1000, 20, -200, 20, 1000, 1000},
+ {-400, -600, 1300, 830, -1000, 20, -200, 20, 1000, 1000},
// REVERB_PRESET_LARGEROOM
- {-1000, -600, 1500, 830, -1600, 5, -1000, 40, 1000, 1000},
+ {-400, -600, 1500, 830, -1600, 5, -1000, 40, 1000, 1000},
// REVERB_PRESET_MEDIUMHALL
- {-1000, -600, 1800, 700, -1300, 15, -800, 30, 1000, 1000},
+ {-400, -600, 1800, 700, -1300, 15, -800, 30, 1000, 1000},
// REVERB_PRESET_LARGEHALL
- {-1000, -600, 1800, 700, -2000, 30, -1400, 60, 1000, 1000},
+ {-400, -600, 1800, 700, -2000, 30, -1400, 60, 1000, 1000},
// REVERB_PRESET_PLATE
- {-1000, -200, 1300, 900, 0, 2, 0, 10, 1000, 750},
+ {-400, -200, 1300, 900, 0, 2, 0, 10, 1000, 750},
};
@@ -90,7 +90,7 @@
{0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}},
{0xc7a511a0, 0xa3bb, 0x11df, 0x860e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
EFFECT_API_VERSION,
- EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+ EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST | EFFECT_FLAG_VOLUME_CTRL,
LVREV_CUP_LOAD_ARM9E,
LVREV_MEM_USAGE,
"Insert Environmental Reverb",
@@ -114,7 +114,7 @@
{0x47382d60, 0xddd8, 0x11db, 0xbf3a, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
{0x172cdf00, 0xa3bc, 0x11df, 0xa72f, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
EFFECT_API_VERSION,
- EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+ EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST | EFFECT_FLAG_VOLUME_CTRL,
LVREV_CUP_LOAD_ARM9E,
LVREV_MEM_USAGE,
"Insert Preset Reverb",
@@ -153,10 +153,25 @@
uint16_t curPreset;
uint16_t nextPreset;
int SamplesToExitCount;
+ LVM_INT16 leftVolume;
+ LVM_INT16 rightVolume;
+ LVM_INT16 prevLeftVolume;
+ LVM_INT16 prevRightVolume;
+ int volumeMode;
+};
+
+enum {
+ REVERB_VOLUME_OFF,
+ REVERB_VOLUME_FLAT,
+ REVERB_VOLUME_RAMP,
};
#define REVERB_DEFAULT_PRESET REVERB_PRESET_MEDIUMROOM
+
+#define REVERB_SEND_LEVEL (0x0C00) // 0.75 in 4.12 format
+#define REVERB_UNIT_VOLUME (0x1000) // 1.0 in 4.12 format
+
//--- local function prototypes
int Reverb_init (ReverbContext *pContext);
void Reverb_free (ReverbContext *pContext);
@@ -426,9 +441,20 @@
if (pContext->preset && pContext->nextPreset != pContext->curPreset) {
Reverb_LoadPreset(pContext);
}
+
+
+
// Convert to Input 32 bits
- for(int i=0; i<frameCount*samplesPerFrame; i++){
- pContext->InFrames32[i] = (LVM_INT32)pIn[i]<<8;
+ if (pContext->auxiliary) {
+ for(int i=0; i<frameCount*samplesPerFrame; i++){
+ pContext->InFrames32[i] = (LVM_INT32)pIn[i]<<8;
+ }
+ } else {
+ // insert reverb input is always stereo
+ for (int i = 0; i < frameCount; i++) {
+ pContext->InFrames32[2*i] = (pIn[2*i] * REVERB_SEND_LEVEL) >> 4; // <<8 + >>12
+ pContext->InFrames32[2*i+1] = (pIn[2*i+1] * REVERB_SEND_LEVEL) >> 4; // <<8 + >>12
+ }
}
if (pContext->preset && pContext->curPreset == REVERB_PRESET_NONE) {
@@ -458,6 +484,42 @@
for (int i=0; i < frameCount*2; i++) { //always stereo here
OutFrames16[i] = clamp16((pContext->OutFrames32[i]>>8) + (LVM_INT32)pIn[i]);
}
+
+ // apply volume with ramp if needed
+ if ((pContext->leftVolume != pContext->prevLeftVolume ||
+ pContext->rightVolume != pContext->prevRightVolume) &&
+ pContext->volumeMode == REVERB_VOLUME_RAMP) {
+ LVM_INT32 vl = (LVM_INT32)pContext->prevLeftVolume << 16;
+ LVM_INT32 incl = (((LVM_INT32)pContext->leftVolume << 16) - vl) / frameCount;
+ LVM_INT32 vr = (LVM_INT32)pContext->prevRightVolume << 16;
+ LVM_INT32 incr = (((LVM_INT32)pContext->rightVolume << 16) - vr) / frameCount;
+
+ for (int i = 0; i < frameCount; i++) {
+ OutFrames16[2*i] =
+ clamp16((LVM_INT32)((vl >> 16) * OutFrames16[2*i]) >> 12);
+ OutFrames16[2*i+1] =
+ clamp16((LVM_INT32)((vr >> 16) * OutFrames16[2*i+1]) >> 12);
+
+ vl += incl;
+ vr += incr;
+ }
+
+ pContext->prevLeftVolume = pContext->leftVolume;
+ pContext->prevRightVolume = pContext->rightVolume;
+ } else if (pContext->volumeMode != REVERB_VOLUME_OFF) {
+ if (pContext->leftVolume != REVERB_UNIT_VOLUME ||
+ pContext->rightVolume != REVERB_UNIT_VOLUME) {
+ for (int i = 0; i < frameCount; i++) {
+ OutFrames16[2*i] =
+ clamp16((LVM_INT32)(pContext->leftVolume * OutFrames16[2*i]) >> 12);
+ OutFrames16[2*i+1] =
+ clamp16((LVM_INT32)(pContext->rightVolume * OutFrames16[2*i+1]) >> 12);
+ }
+ }
+ pContext->prevLeftVolume = pContext->leftVolume;
+ pContext->prevRightVolume = pContext->rightVolume;
+ pContext->volumeMode = REVERB_VOLUME_RAMP;
+ }
}
#ifdef LVM_PCM
@@ -658,6 +720,12 @@
pContext->config.outputCfg.bufferProvider.cookie = NULL;
pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL;
+ pContext->leftVolume = REVERB_UNIT_VOLUME;
+ pContext->rightVolume = REVERB_UNIT_VOLUME;
+ pContext->prevLeftVolume = REVERB_UNIT_VOLUME;
+ pContext->prevRightVolume = REVERB_UNIT_VOLUME;
+ pContext->volumeMode = REVERB_VOLUME_FLAT;
+
LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
LVREV_ControlParams_st params; /* Control Parameters */
LVREV_InstanceParams_st InstParams; /* Instance parameters */
@@ -1781,15 +1849,6 @@
LOGV("\tLVM_ERROR : Reverb_process() ERROR NULL INPUT POINTER OR FRAME COUNT IS WRONG");
return -EINVAL;
}
- if (pContext->bEnabled == LVM_FALSE){
- if( pContext->SamplesToExitCount > 0){
- pContext->SamplesToExitCount -= outBuffer->frameCount;
- LOGV("\tReverb_process() Effect is being stopped %d", pContext->SamplesToExitCount);
- }else{
- LOGV("\tReverb_process() Effect is being stopped");
- return -ENODATA;
- }
- }
//LOGV("\tReverb_process() Calling process with %d frames", outBuffer->frameCount);
/* Process all the available frames, block processing is handled internalLY by the LVM bundle */
status = process( (LVM_INT16 *)inBuffer->raw,
@@ -1797,6 +1856,14 @@
outBuffer->frameCount,
pContext);
+ if (pContext->bEnabled == LVM_FALSE) {
+ if (pContext->SamplesToExitCount > 0) {
+ pContext->SamplesToExitCount -= outBuffer->frameCount;
+ } else {
+ status = -ENODATA;
+ }
+ }
+
return status;
} /* end Reverb_process */
@@ -1943,6 +2010,8 @@
LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "EFFECT_CMD_ENABLE")
pContext->SamplesToExitCount =
(ActiveParams.T60 * pContext->config.inputCfg.samplingRate)/1000;
+ // force no volume ramp for first buffer processed after enabling the effect
+ pContext->volumeMode = android::REVERB_VOLUME_FLAT;
//LOGV("\tEFFECT_CMD_ENABLE SamplesToExitCount = %d", pContext->SamplesToExitCount);
break;
case EFFECT_CMD_DISABLE:
@@ -1963,8 +2032,34 @@
pContext->bEnabled = LVM_FALSE;
break;
- case EFFECT_CMD_SET_DEVICE:
case EFFECT_CMD_SET_VOLUME:
+ if (pCmdData == NULL ||
+ cmdSize != 2 * sizeof(uint32_t)) {
+ LOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_SET_VOLUME: ERROR");
+ return -EINVAL;
+ }
+
+
+ if (pReplyData != NULL) { // we have volume control
+ pContext->leftVolume = (LVM_INT16)((*(uint32_t *)pCmdData + (1 << 11)) >> 12);
+ pContext->rightVolume = (LVM_INT16)((*((uint32_t *)pCmdData + 1) + (1 << 11)) >> 12);
+ *(uint32_t *)pReplyData = (1 << 24);
+ *((uint32_t *)pReplyData + 1) = (1 << 24);
+ if (pContext->volumeMode == android::REVERB_VOLUME_OFF) {
+ // force no volume ramp for first buffer processed after getting volume control
+ pContext->volumeMode = android::REVERB_VOLUME_FLAT;
+ }
+ } else { // we don't have volume control
+ pContext->leftVolume = REVERB_UNIT_VOLUME;
+ pContext->rightVolume = REVERB_UNIT_VOLUME;
+ pContext->volumeMode = android::REVERB_VOLUME_OFF;
+ }
+ LOGV("EFFECT_CMD_SET_VOLUME left %d, right %d mode %d",
+ pContext->leftVolume, pContext->rightVolume, pContext->volumeMode);
+ break;
+
+ case EFFECT_CMD_SET_DEVICE:
case EFFECT_CMD_SET_AUDIO_MODE:
//LOGV("\tReverb_command cmdCode Case: "
// "EFFECT_CMD_SET_DEVICE/EFFECT_CMD_SET_VOLUME/EFFECT_CMD_SET_AUDIO_MODE start");
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 3770b55..886c25b 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1752,14 +1752,15 @@
}
// compute volume for this track
- int16_t left, right, aux;
+ uint32_t vl, vr, va;
if (track->isMuted() || track->isPausing() ||
mStreamTypes[track->type()].mute) {
- left = right = aux = 0;
+ vl = vr = va = 0;
if (track->isPausing()) {
track->setPaused();
}
} else {
+
// read original volumes with volume control
float typeVolume = mStreamTypes[track->type()].volume;
#ifdef LVMX
@@ -1774,35 +1775,36 @@
}
#endif
float v = masterVolume * typeVolume;
- uint32_t vl = (uint32_t)(v * cblk->volume[0]) << 12;
- uint32_t vr = (uint32_t)(v * cblk->volume[1]) << 12;
+ vl = (uint32_t)(v * cblk->volume[0]) << 12;
+ vr = (uint32_t)(v * cblk->volume[1]) << 12;
- // Delegate volume control to effect in track effect chain if needed
- if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
- // Do not ramp volume is volume is controlled by effect
- param = AudioMixer::VOLUME;
- track->mHasVolumeController = true;
- } else {
- // force no volume ramp when volume controller was just disabled or removed
- // from effect chain to avoid volume spike
- if (track->mHasVolumeController) {
- param = AudioMixer::VOLUME;
- }
- track->mHasVolumeController = false;
- }
-
- // Convert volumes from 8.24 to 4.12 format
- uint32_t v_clamped = (vl + (1 << 11)) >> 12;
- if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
- left = int16_t(v_clamped);
- v_clamped = (vr + (1 << 11)) >> 12;
- if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
- right = int16_t(v_clamped);
-
- v_clamped = (uint32_t)(v * cblk->sendLevel);
- if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
- aux = int16_t(v_clamped);
+ va = (uint32_t)(v * cblk->sendLevel);
}
+ // Delegate volume control to effect in track effect chain if needed
+ if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
+ // Do not ramp volume if volume is controlled by effect
+ param = AudioMixer::VOLUME;
+ track->mHasVolumeController = true;
+ } else {
+ // force no volume ramp when volume controller was just disabled or removed
+ // from effect chain to avoid volume spike
+ if (track->mHasVolumeController) {
+ param = AudioMixer::VOLUME;
+ }
+ track->mHasVolumeController = false;
+ }
+
+ // Convert volumes from 8.24 to 4.12 format
+ int16_t left, right, aux;
+ uint32_t v_clamped = (vl + (1 << 11)) >> 12;
+ if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
+ left = int16_t(v_clamped);
+ v_clamped = (vr + (1 << 11)) >> 12;
+ if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
+ right = int16_t(v_clamped);
+
+ if (va > MAX_GAIN_INT) va = MAX_GAIN_INT;
+ aux = int16_t(va);
#ifdef LVMX
if ( tracksConnectedChanged || stateChanged )
@@ -2283,7 +2285,7 @@
// only one effect chain can be present on DirectOutputThread, so if
// there is one, the track is connected to it
if (!effectChains.isEmpty()) {
- // Do not ramp volume is volume is controlled by effect
+ // Do not ramp volume if volume is controlled by effect
if(effectChains[0]->setVolume_l(&vl, &vr)) {
rampVolume = false;
}
@@ -4728,7 +4730,7 @@
// Session AudioSystem::SESSION_OUTPUT_STAGE is reserved for output stage effects
// that can only be created by audio policy manager (running in same process)
if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE &&
- getpid() != IPCThreadState::self()->getCallingPid()) {
+ getpid() != pid) {
lStatus = INVALID_OPERATION;
goto Exit;
}