summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2010-06-23 17:38:20 -0700
committerEric Laurent <elaurent@google.com>2010-06-25 11:59:35 -0700
commitffe9c25ce85e1af55d58ec025adc6367d70db7e8 (patch)
tree664f0a33a690b4d020417a9ecc81b32f696d0f0e /media
parent2439a8d6d99864ba0c2d94f428e6c9ee258cdd45 (diff)
downloadframeworks_av-ffe9c25ce85e1af55d58ec025adc6367d70db7e8.zip
frameworks_av-ffe9c25ce85e1af55d58ec025adc6367d70db7e8.tar.gz
frameworks_av-ffe9c25ce85e1af55d58ec025adc6367d70db7e8.tar.bz2
Various fixes and improvements in audio effects implementation
Effect API: - Use different definitions for audio device, channels, formats... in AudioSystem and EffectApi: Removed media/AudioCommon.h file created for initial version of EffectApi - Indicate audio session and output ID to effect library when calling EffectCreate(). Session ID can be useful to optimize the implementation of effect chains in the same audio session. Output ID can be used for effects implemented in audio hardware. - Renamed EffectQueryNext() function to EffectQueryEffect() and changed operating mode: now an index is passed for the queried effect instead of implicitly querying the next one. - Added CPU load and memory usage indication in effects descriptor - Added flags and commands to indicate changes in audio mode (ring tone, in call...) to effect engine - Added flag to indicate hardware accelerated effect implementation. - Renamed EffectFactoryApi.h to EffectsFactoryApi.h for consistency with EffectsFactory.c/h Effect libraries: - Reflected changes in Effect API - Several fixes in reverb implementation - Added build option TEST_EFFECT_LIBRARIES in makefile to prepare integration of actual effect library. - Replaced pointer by integer identifier for library handle returned by effects factory Audio effect framework: - Added support for audio session -1 in preparation of output stage effects configuration. - Reflected changes in Effect API - Removed volume ramp up/down when effect is inserted/removed: this has to be taken care of by effect engines. - Added some overflow verification on indexes used for deferred parameter updates via shared memory - Added hardcoded CPU and memory limit check when creating a new effect instance Change-Id: I43fee5182ee201384ea3479af6d0acb95092901d
Diffstat (limited to 'media')
-rw-r--r--media/libeffects/Android.mk12
-rw-r--r--media/libeffects/AudioCoefInterpolator.cpp2
-rw-r--r--media/libeffects/AudioCommon.h2
-rw-r--r--media/libeffects/AudioFormatAdapter.h6
-rw-r--r--media/libeffects/AudioShelvingFilter.cpp4
-rw-r--r--media/libeffects/EffectEqualizer.cpp37
-rw-r--r--media/libeffects/EffectReverb.c93
-rw-r--r--media/libeffects/EffectReverb.h4
-rw-r--r--media/libeffects/EffectsFactory.c100
-rw-r--r--media/libeffects/EffectsFactory.h3
-rw-r--r--media/libmedia/AudioEffect.cpp4
-rw-r--r--media/libmedia/IAudioFlinger.cpp11
12 files changed, 195 insertions, 83 deletions
diff --git a/media/libeffects/Android.mk b/media/libeffects/Android.mk
index ff21454..b5f1d42 100644
--- a/media/libeffects/Android.mk
+++ b/media/libeffects/Android.mk
@@ -1,5 +1,8 @@
LOCAL_PATH:= $(call my-dir)
+#
+TEST_EFFECT_LIBRARIES := true
+
# Effect factory library
include $(CLEAR_VARS)
@@ -25,7 +28,8 @@ LOCAL_C_INCLUDES := \
include $(BUILD_SHARED_LIBRARY)
-# Default Reverb library
+ifeq ($(TEST_EFFECT_LIBRARIES),true)
+# Test Reverb library
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
@@ -54,7 +58,7 @@ LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
-# Default Equalizer library
+# Test Equalizer library
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
@@ -87,4 +91,6 @@ LOCAL_C_INCLUDES := \
LOCAL_PRELINK_MODULE := false
-include $(BUILD_SHARED_LIBRARY) \ No newline at end of file
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/media/libeffects/AudioCoefInterpolator.cpp b/media/libeffects/AudioCoefInterpolator.cpp
index 05898c9..039ab9f 100644
--- a/media/libeffects/AudioCoefInterpolator.cpp
+++ b/media/libeffects/AudioCoefInterpolator.cpp
@@ -46,7 +46,7 @@ void AudioCoefInterpolator::getCoef(const int intCoord[], uint32_t fracCoord[],
while (dim-- > 0) {
if (UNLIKELY(intCoord[dim] < 0)) {
fracCoord[dim] = 0;
- } else if (UNLIKELY(intCoord[dim] >= mInDims[dim] - 1)) {
+ } else if (UNLIKELY(intCoord[dim] >= (int)mInDims[dim] - 1)) {
fracCoord[dim] = 0;
index += mInDimOffsets[dim] * (mInDims[dim] - 1);
} else {
diff --git a/media/libeffects/AudioCommon.h b/media/libeffects/AudioCommon.h
index 12d2193..444f93a 100644
--- a/media/libeffects/AudioCommon.h
+++ b/media/libeffects/AudioCommon.h
@@ -1,4 +1,4 @@
-/* //device/include/server/AudioFlinger/AudioCommon.h
+/*
**
** Copyright 2009, The Android Open Source Project
**
diff --git a/media/libeffects/AudioFormatAdapter.h b/media/libeffects/AudioFormatAdapter.h
index 8aa5e65..d93ebe9 100644
--- a/media/libeffects/AudioFormatAdapter.h
+++ b/media/libeffects/AudioFormatAdapter.h
@@ -75,7 +75,7 @@ public:
while (numSamples > 0) {
uint32_t numSamplesIter = min(numSamples, mMaxSamplesPerCall);
uint32_t nSamplesChannels = numSamplesIter * mNumChannels;
- if (mPcmFormat == PCM_FORMAT_S7_24) {
+ if (mPcmFormat == SAMPLE_FORMAT_PCM_S7_24) {
if (mBehavior == EFFECT_BUFFER_ACCESS_WRITE) {
mpProcessor->process(
reinterpret_cast<const audio_sample_t *> (pIn),
@@ -125,7 +125,7 @@ private:
// sample.
// numSamples The number of single-channel samples to process.
void ConvertInput(const void *& pIn, uint32_t numSamples) {
- if (mPcmFormat == PCM_FORMAT_S15) {
+ if (mPcmFormat == SAMPLE_FORMAT_PCM_S15) {
const int16_t * pIn16 = reinterpret_cast<const int16_t *>(pIn);
audio_sample_t * pOut = mBuffer;
while (numSamples-- > 0) {
@@ -143,7 +143,7 @@ private:
// When function exist will point to the next output sample.
// numSamples The number of single-channel samples to process.
void ConvertOutput(void *& pOut, uint32_t numSamples) {
- if (mPcmFormat == PCM_FORMAT_S15) {
+ if (mPcmFormat == SAMPLE_FORMAT_PCM_S15) {
const audio_sample_t * pIn = mBuffer;
int16_t * pOut16 = reinterpret_cast<int16_t *>(pOut);
if (mBehavior == EFFECT_BUFFER_ACCESS_WRITE) {
diff --git a/media/libeffects/AudioShelvingFilter.cpp b/media/libeffects/AudioShelvingFilter.cpp
index d8abbd2..b8650ba 100644
--- a/media/libeffects/AudioShelvingFilter.cpp
+++ b/media/libeffects/AudioShelvingFilter.cpp
@@ -50,8 +50,8 @@ AudioCoefInterpolator AudioShelvingFilter::mLoCoefInterp(2, kLoInDims, 5, (const
AudioShelvingFilter::AudioShelvingFilter(ShelfType type, int nChannels,
int sampleRate)
- : mBiquad(nChannels, sampleRate)
- , mType(type) {
+ : mType(type),
+ mBiquad(nChannels, sampleRate) {
configure(nChannels, sampleRate);
}
diff --git a/media/libeffects/EffectEqualizer.cpp b/media/libeffects/EffectEqualizer.cpp
index e39e595..d19c6b9 100644
--- a/media/libeffects/EffectEqualizer.cpp
+++ b/media/libeffects/EffectEqualizer.cpp
@@ -39,10 +39,11 @@ const effect_descriptor_t gEqualizerDescriptor = {
{0xe25aa840, 0x543b, 0x11df, 0x98a5, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
EFFECT_API_VERSION,
(EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST),
+ 0, // TODO
+ 1,
"Graphic Equalizer",
"Google Inc.",
};
-static int gEffectIndex;
/////////////////// BEGIN EQ PRESETS ///////////////////////////////////////////
const int kNumBands = 5;
@@ -101,7 +102,6 @@ struct EqualizerContext {
AudioEqualizer * pEqualizer;
};
-
//--- local function prototypes
int Equalizer_init(EqualizerContext *pContext);
@@ -116,22 +116,23 @@ int Equalizer_setParameter(AudioEqualizer * pEqualizer, int32_t *pParam, void *p
extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects) {
*pNumEffects = 1;
- gEffectIndex = 0;
return 0;
} /* end EffectQueryNumberEffects */
-extern "C" int EffectQueryNext(effect_descriptor_t *pDescriptor) {
+extern "C" int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) {
if (pDescriptor == NULL) {
return -EINVAL;
}
- if (gEffectIndex++ > 0) {
- return -ENOENT;
+ if (index > 0) {
+ return -EINVAL;
}
memcpy(pDescriptor, &gEqualizerDescriptor, sizeof(effect_descriptor_t));
return 0;
} /* end EffectQueryNext */
extern "C" int EffectCreate(effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
effect_interface_t *pInterface) {
int ret;
int i;
@@ -160,7 +161,7 @@ extern "C" int EffectCreate(effect_uuid_t *uuid,
*pInterface = (effect_interface_t)pContext;
- LOGV("EffectLibCreateEffect %p", pContext);
+ LOGV("EffectLibCreateEffect %p, size %d", pContext, AudioEqualizer::GetInstanceSize(kNumBands)+sizeof(EqualizerContext));
return 0;
@@ -219,8 +220,8 @@ int Equalizer_configure(EqualizerContext *pContext, effect_config_t *pConfig)
CHECK_ARG((pConfig->inputCfg.channels == CHANNEL_MONO) || (pConfig->inputCfg.channels == CHANNEL_STEREO));
CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
|| pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
- CHECK_ARG(pConfig->inputCfg.format == PCM_FORMAT_S7_24
- || pConfig->inputCfg.format == PCM_FORMAT_S15);
+ CHECK_ARG(pConfig->inputCfg.format == SAMPLE_FORMAT_PCM_S7_24
+ || pConfig->inputCfg.format == SAMPLE_FORMAT_PCM_S15);
int channelCount;
if (pConfig->inputCfg.channels == CHANNEL_MONO) {
@@ -230,6 +231,8 @@ int Equalizer_configure(EqualizerContext *pContext, effect_config_t *pConfig)
}
CHECK_ARG(channelCount <= AudioBiquadFilter::MAX_CHANNELS);
+ memcpy(&pContext->config, pConfig, sizeof(effect_config_t));
+
pContext->pEqualizer->configure(channelCount,
pConfig->inputCfg.samplingRate);
@@ -268,7 +271,7 @@ int Equalizer_init(EqualizerContext *pContext)
pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
pContext->config.inputCfg.channels = CHANNEL_STEREO;
- pContext->config.inputCfg.format = PCM_FORMAT_S15;
+ pContext->config.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
pContext->config.inputCfg.samplingRate = 44100;
pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
@@ -276,7 +279,7 @@ int Equalizer_init(EqualizerContext *pContext)
pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
pContext->config.outputCfg.channels = CHANNEL_STEREO;
- pContext->config.outputCfg.format = PCM_FORMAT_S15;
+ pContext->config.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
pContext->config.outputCfg.samplingRate = 44100;
pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
@@ -526,6 +529,7 @@ extern "C" int Equalizer_process(effect_interface_t self, audio_buffer_t *inBuff
}
pContext->adapter.process(inBuffer->raw, outBuffer->raw, outBuffer->frameCount);
+
return 0;
} // end Equalizer_process
@@ -589,6 +593,17 @@ extern "C" int Equalizer_command(effect_interface_t self, int cmdCode, int cmdSi
*(int *)pReplyData = android::Equalizer_setParameter(pEqualizer, (int32_t *)p->data,
p->data + p->psize);
} break;
+ case EFFECT_CMD_ENABLE:
+ case EFFECT_CMD_DISABLE:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ *(int *)pReplyData = 0;
+ break;
+ case EFFECT_CMD_SET_DEVICE:
+ case EFFECT_CMD_SET_VOLUME:
+ case EFFECT_CMD_SET_AUDIO_MODE:
+ break;
default:
LOGW("Equalizer_command invalid command %d",cmdCode);
return -EINVAL;
diff --git a/media/libeffects/EffectReverb.c b/media/libeffects/EffectReverb.c
index 202f50b..ada252c 100644
--- a/media/libeffects/EffectReverb.c
+++ b/media/libeffects/EffectReverb.c
@@ -24,8 +24,6 @@
#include "EffectReverb.h"
#include "EffectsMath.h"
-static int gEffectIndex;
-
// effect_interface_t interface implementation for reverb effect
const struct effect_interface_s gReverbInterface = {
Reverb_Process,
@@ -37,7 +35,10 @@ static const effect_descriptor_t gAuxEnvReverbDescriptor = {
{0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}},
{0x1f0ae2e0, 0x4ef7, 0x11df, 0xbc09, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
EFFECT_API_VERSION,
- EFFECT_FLAG_TYPE_AUXILIARY,
+ // flags other than EFFECT_FLAG_TYPE_AUXILIARY set for test purpose
+ EFFECT_FLAG_TYPE_AUXILIARY | EFFECT_FLAG_DEVICE_IND | EFFECT_FLAG_AUDIO_MODE_IND,
+ 0, // TODO
+ 33,
"Aux Environmental Reverb",
"Google Inc."
};
@@ -48,6 +49,8 @@ static const effect_descriptor_t gInsertEnvReverbDescriptor = {
{0xaa476040, 0x6342, 0x11df, 0x91a4, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
EFFECT_API_VERSION,
EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+ 0, // TODO
+ 33,
"Insert Environmental reverb",
"Google Inc."
};
@@ -58,6 +61,8 @@ static const effect_descriptor_t gAuxPresetReverbDescriptor = {
{0x63909320, 0x53a6, 0x11df, 0xbdbd, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
EFFECT_API_VERSION,
EFFECT_FLAG_TYPE_AUXILIARY,
+ 0, // TODO
+ 33,
"Aux Preset Reverb",
"Google Inc."
};
@@ -68,6 +73,8 @@ static const effect_descriptor_t gInsertPresetReverbDescriptor = {
{0xd93dc6a0, 0x6342, 0x11df, 0xb128, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
EFFECT_API_VERSION,
EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+ 0, // TODO
+ 33,
"Insert Preset Reverb",
"Google Inc."
};
@@ -77,8 +84,7 @@ static const effect_descriptor_t * const gDescriptors[] = {
&gAuxEnvReverbDescriptor,
&gInsertEnvReverbDescriptor,
&gAuxPresetReverbDescriptor,
- &gInsertPresetReverbDescriptor,
- NULL
+ &gInsertPresetReverbDescriptor
};
/*----------------------------------------------------------------------------
@@ -88,25 +94,25 @@ static const effect_descriptor_t * const gDescriptors[] = {
/*--- Effect Library Interface Implementation ---*/
int EffectQueryNumberEffects(uint32_t *pNumEffects) {
- *pNumEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *)
- - 1;
- gEffectIndex = 0;
+ *pNumEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
return 0;
}
-int EffectQueryNext(effect_descriptor_t *pDescriptor) {
+int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) {
if (pDescriptor == NULL) {
return -EINVAL;
}
- if (gDescriptors[gEffectIndex] == NULL) {
- return -ENOENT;
+ if (index >= sizeof(gDescriptors) / sizeof(const effect_descriptor_t *)) {
+ return -EINVAL;
}
- memcpy(pDescriptor, gDescriptors[gEffectIndex++],
+ memcpy(pDescriptor, gDescriptors[index],
sizeof(effect_descriptor_t));
return 0;
}
int EffectCreate(effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
effect_interface_t *pInterface) {
int ret;
int i;
@@ -152,7 +158,7 @@ int EffectCreate(effect_uuid_t *uuid,
*pInterface = (effect_interface_t) module;
- LOGV("EffectLibCreateEffect %p", module);
+ LOGV("EffectLibCreateEffect %p ,size %d", module, sizeof(reverb_module_t));
return 0;
}
@@ -191,8 +197,23 @@ static int Reverb_Process(effect_interface_t self, audio_buffer_t *inBuffer, aud
//if bypassed or the preset forces the signal to be completely dry
if (pReverb->m_bBypass) {
- if (inBuffer->raw != outBuffer->raw && !pReverb->m_Aux) {
- memcpy(outBuffer->raw, inBuffer->raw, outBuffer->frameCount * NUM_OUTPUT_CHANNELS * sizeof(int16_t));
+ if (inBuffer->raw != outBuffer->raw) {
+ int16_t smp;
+ pSrc = inBuffer->s16;
+ pDst = outBuffer->s16;
+ size_t count = inBuffer->frameCount;
+ if (pRvbModule->config.inputCfg.channels == pRvbModule->config.outputCfg.channels) {
+ count *= 2;
+ while (count--) {
+ *pDst++ = *pSrc++;
+ }
+ } else {
+ while (count--) {
+ smp = *pSrc++;
+ *pDst++ = smp;
+ *pDst++ = smp;
+ }
+ }
}
return 0;
}
@@ -226,10 +247,11 @@ static int Reverb_Process(effect_interface_t self, audio_buffer_t *inBuffer, aud
numSamples -= processedSamples;
if (pReverb->m_Aux) {
- pDst += processedSamples;
+ pSrc += processedSamples;
} else {
pSrc += processedSamples * NUM_OUTPUT_CHANNELS;
}
+ pDst += processedSamples * NUM_OUTPUT_CHANNELS;
}
return 0;
@@ -292,6 +314,35 @@ static int Reverb_Command(effect_interface_t self, int cmdCode, int cmdSize,
*(int *)pReplyData = Reverb_setParameter(pReverb, *(int32_t *)cmd->data,
cmd->vsize, cmd->data + sizeof(int32_t));
break;
+ case EFFECT_CMD_ENABLE:
+ case EFFECT_CMD_DISABLE:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ *(int *)pReplyData = 0;
+ break;
+ case EFFECT_CMD_SET_DEVICE:
+ if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
+ return -EINVAL;
+ }
+ LOGV("Reverb_Command EFFECT_CMD_SET_DEVICE: 0x%08x", *(uint32_t *)pCmdData);
+ break;
+ case EFFECT_CMD_SET_VOLUME: {
+ // audio output is always stereo => 2 channel volumes
+ if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t) * 2) {
+ return -EINVAL;
+ }
+ float left = (float)(*(uint32_t *)pCmdData) / (1 << 24);
+ float right = (float)(*((uint32_t *)pCmdData + 1)) / (1 << 24);
+ LOGV("Reverb_Command EFFECT_CMD_SET_VOLUME: left %f, right %f ", left, right);
+ break;
+ }
+ case EFFECT_CMD_SET_AUDIO_MODE:
+ if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
+ return -EINVAL;
+ }
+ LOGV("Reverb_Command EFFECT_CMD_SET_AUDIO_MODE: %d", *(uint32_t *)pCmdData);
+ break;
default:
LOGW("Reverb_Command invalid command %d",cmdCode);
return -EINVAL;
@@ -339,7 +390,7 @@ int Reverb_Init(reverb_module_t *pRvbModule, int aux, int preset) {
} else {
pRvbModule->config.inputCfg.channels = CHANNEL_STEREO;
}
- pRvbModule->config.inputCfg.format = PCM_FORMAT_S15;
+ pRvbModule->config.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
pRvbModule->config.inputCfg.bufferProvider.getBuffer = NULL;
pRvbModule->config.inputCfg.bufferProvider.releaseBuffer = NULL;
pRvbModule->config.inputCfg.bufferProvider.cookie = NULL;
@@ -347,7 +398,7 @@ int Reverb_Init(reverb_module_t *pRvbModule, int aux, int preset) {
pRvbModule->config.inputCfg.mask = EFFECT_CONFIG_ALL;
pRvbModule->config.outputCfg.samplingRate = 44100;
pRvbModule->config.outputCfg.channels = CHANNEL_STEREO;
- pRvbModule->config.outputCfg.format = PCM_FORMAT_S15;
+ pRvbModule->config.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
pRvbModule->config.outputCfg.bufferProvider.getBuffer = NULL;
pRvbModule->config.outputCfg.bufferProvider.releaseBuffer = NULL;
pRvbModule->config.outputCfg.bufferProvider.cookie = NULL;
@@ -391,8 +442,8 @@ int Reverb_Configure(reverb_module_t *pRvbModule, effect_config_t *pConfig,
if (pConfig->inputCfg.samplingRate
!= pConfig->outputCfg.samplingRate
|| pConfig->outputCfg.channels != OUTPUT_CHANNELS
- || pConfig->inputCfg.format != PCM_FORMAT_S15
- || pConfig->outputCfg.format != PCM_FORMAT_S15) {
+ || pConfig->inputCfg.format != SAMPLE_FORMAT_PCM_S15
+ || pConfig->outputCfg.format != SAMPLE_FORMAT_PCM_S15) {
LOGV("Reverb_Configure invalid config");
return -EINVAL;
}
@@ -1033,6 +1084,7 @@ int Reverb_setParameter(reverb_object_t *pReverb, int32_t param, size_t size,
// Convert milliseconds to => m_nRvbLpfFwd (function of m_nRvbLpfFbk)
// convert ms to samples
value32 = (value32 * pReverb->m_nSamplingRate) / 1000;
+
// calculate valid decay time range as a function of current reverb delay and
// max feed back gain. Min value <=> -40dB in one pass, Max value <=> feedback gain = -1 dB
// Calculate attenuation for each round in late reverb given a total attenuation of -6000 millibels.
@@ -1834,7 +1886,6 @@ static int ReverbUpdateRoom(reverb_object_t *pReverb, bool fullUpdate) {
//gsReverbObject.m_nXfadeInterval = pPreset->m_nXfadeInterval;
pReverb->m_nXfadeCounter = pReverb->m_nXfadeInterval + 1; // force update on first iteration
-
pReverb->m_nCurrentRoom = pReverb->m_nNextRoom;
return 0;
diff --git a/media/libeffects/EffectReverb.h b/media/libeffects/EffectReverb.h
index 578e09e..f5aadfa 100644
--- a/media/libeffects/EffectReverb.h
+++ b/media/libeffects/EffectReverb.h
@@ -293,8 +293,8 @@ typedef struct reverb_module_s {
*------------------------------------
*/
int EffectQueryNumberEffects(uint32_t *pNumEffects);
-int EffectQueryNext(effect_descriptor_t *pDescriptor);
-int EffectCreate(effect_uuid_t *effectUID, effect_interface_t *pInterface);
+int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor);
+int EffectCreate(effect_uuid_t *effectUID, int32_t sessionId, int32_t ioId, effect_interface_t *pInterface);
int EffectRelease(effect_interface_t interface);
static int Reverb_Process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer);
diff --git a/media/libeffects/EffectsFactory.c b/media/libeffects/EffectsFactory.c
index 6800765..edd6184 100644
--- a/media/libeffects/EffectsFactory.c
+++ b/media/libeffects/EffectsFactory.c
@@ -26,11 +26,16 @@
static list_elem_t *gEffectList; // list of effect_entry_t: all currently created effects
static list_elem_t *gLibraryList; // list of lib_entry_t: all currently loaded libraries
static pthread_mutex_t gLibLock = PTHREAD_MUTEX_INITIALIZER; // controls access to gLibraryList
+static uint32_t gNumEffects; // total number number of effects
static list_elem_t *gCurLib; // current library in enumeration process
static list_elem_t *gCurEffect; // current effect in enumeration process
+static uint32_t gCurEffectIdx; // current effect index in enumeration process
static const char * const gEffectLibPath = "/system/lib/soundfx"; // path to built-in effect libraries
static int gInitDone; // true is global initialization has been preformed
+static int gNextLibId; // used by loadLibrary() to allocate unique library handles
+static int gCanQueryEffect; // indicates that call to EffectQueryEffect() is valid, i.e. that the list of effects
+ // was not modified since last call to EffectQueryNumberEffects()
/////////////////////////////////////////////////
// Local functions prototypes
@@ -39,7 +44,8 @@ static int gInitDone; // true is global initialization has been preformed
static int init();
static int loadLibrary(const char *libPath, int *handle);
static int unloadLibrary(int handle);
-static uint32_t numEffectModules();
+static void resetEffectEnumeration();
+static uint32_t updateNumEffects();
static int findEffect(effect_uuid_t *uuid, lib_entry_t **lib, effect_descriptor_t **desc);
static void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len);
@@ -107,38 +113,53 @@ int EffectQueryNumberEffects(uint32_t *pNumEffects)
}
pthread_mutex_lock(&gLibLock);
- *pNumEffects = numEffectModules();
+ *pNumEffects = gNumEffects;
+ gCanQueryEffect = 1;
pthread_mutex_unlock(&gLibLock);
LOGV("EffectQueryNumberEffects(): %d", *pNumEffects);
return ret;
}
-int EffectQueryNext(effect_descriptor_t *pDescriptor)
+int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor)
{
int ret = init();
if (ret < 0) {
return ret;
}
- if (pDescriptor == NULL) {
+ if (pDescriptor == NULL ||
+ index >= gNumEffects) {
return -EINVAL;
}
+ if (gCanQueryEffect == 0) {
+ return -ENOSYS;
+ }
pthread_mutex_lock(&gLibLock);
ret = -ENOENT;
+ if (index < gCurEffectIdx) {
+ resetEffectEnumeration();
+ }
while (gCurLib) {
if (gCurEffect) {
- memcpy(pDescriptor, gCurEffect->object, sizeof(effect_descriptor_t));
- gCurEffect = gCurEffect->next;
- ret = 0;
- break;
+ if (index == gCurEffectIdx) {
+ memcpy(pDescriptor, gCurEffect->object, sizeof(effect_descriptor_t));
+ ret = 0;
+ break;
+ } else {
+ gCurEffect = gCurEffect->next;
+ gCurEffectIdx++;
+ }
} else {
gCurLib = gCurLib->next;
gCurEffect = ((lib_entry_t *)gCurLib->object)->effects;
}
}
+
+#if (LOG_NDEBUG == 0)
char str[256];
dumpEffectDescriptor(pDescriptor, str, 256);
- LOGV("EffectQueryNext() desc:%s", str);
+ LOGV("EffectQueryEffect() desc:%s", str);
+#endif
pthread_mutex_unlock(&gLibLock);
return ret;
}
@@ -164,7 +185,7 @@ int EffectGetDescriptor(effect_uuid_t *uuid, effect_descriptor_t *pDescriptor)
return ret;
}
-int EffectCreate(effect_uuid_t *uuid, effect_interface_t *pInterface)
+int EffectCreate(effect_uuid_t *uuid, int32_t sessionId, int32_t ioId, effect_interface_t *pInterface)
{
list_elem_t *e = gLibraryList;
lib_entry_t *l = NULL;
@@ -198,9 +219,9 @@ int EffectCreate(effect_uuid_t *uuid, effect_interface_t *pInterface)
}
// create effect in library
- ret = l->createFx(uuid, &itfe);
- if (ret < 0) {
- LOGW("EffectCreate() library %s: could not create fx %s", l->path, d->name);
+ ret = l->createFx(uuid, sessionId, ioId, &itfe);
+ if (ret != 0) {
+ LOGW("EffectCreate() library %s: could not create fx %s, error %d", l->path, d->name, ret);
goto exit;
}
@@ -282,7 +303,10 @@ int EffectLoadLibrary(const char *libPath, int *handle)
if (libPath == NULL) {
return -EINVAL;
}
- return loadLibrary(libPath, handle);
+
+ ret = loadLibrary(libPath, handle);
+ updateNumEffects();
+ return ret;
}
int EffectUnloadLibrary(int handle)
@@ -292,7 +316,9 @@ int EffectUnloadLibrary(int handle)
return ret;
}
- return unloadLibrary(handle);
+ ret = unloadLibrary(handle);
+ updateNumEffects();
+ return ret;
}
int EffectIsNullUuid(effect_uuid_t *uuid)
@@ -339,7 +365,7 @@ int init() {
}
}
closedir(dir);
-
+ updateNumEffects();
gInitDone = 1;
LOGV("init() done");
return 0;
@@ -350,7 +376,7 @@ int loadLibrary(const char *libPath, int *handle)
{
void *hdl;
effect_QueryNumberEffects_t queryNumFx;
- effect_QueryNextEffect_t queryFx;
+ effect_QueryEffect_t queryFx;
effect_CreateEffect_t createFx;
effect_ReleaseEffect_t releaseFx;
uint32_t numFx;
@@ -378,9 +404,9 @@ int loadLibrary(const char *libPath, int *handle)
ret = -ENODEV;
goto error;
}
- queryFx = (effect_QueryNextEffect_t)dlsym(hdl, "EffectQueryNext");
+ queryFx = (effect_QueryEffect_t)dlsym(hdl, "EffectQueryEffect");
if (queryFx == NULL) {
- LOGW("could not get EffectQueryNext from lib %s", libPath);
+ LOGW("could not get EffectQueryEffect from lib %s", libPath);
ret = -ENODEV;
goto error;
}
@@ -409,7 +435,7 @@ int loadLibrary(const char *libPath, int *handle)
ret = -ENOMEM;
goto error;
}
- ret = queryFx(d);
+ ret = queryFx(fx, d);
if (ret == 0) {
#if (LOG_NDEBUG==0)
char s[256];
@@ -434,8 +460,12 @@ int loadLibrary(const char *libPath, int *handle)
LOGW("Error querying effect # %d on lib %s", fx, libPath);
}
}
+
+ pthread_mutex_lock(&gLibLock);
+
// add entry for library in gLibraryList
l = malloc(sizeof(lib_entry_t));
+ l->id = ++gNextLibId;
l->handle = hdl;
strncpy(l->path, libPath, PATH_MAX);
l->createFx = createFx;
@@ -444,14 +474,13 @@ int loadLibrary(const char *libPath, int *handle)
pthread_mutex_init(&l->lock, NULL);
e = malloc(sizeof(list_elem_t));
- pthread_mutex_lock(&gLibLock);
e->next = gLibraryList;
e->object = l;
gLibraryList = e;
pthread_mutex_unlock(&gLibLock);
LOGV("loadLibrary() linked library %p", l);
- *handle = (int)hdl;
+ *handle = l->id;
return 0;
@@ -480,7 +509,7 @@ int unloadLibrary(int handle)
el2 = NULL;
while (el1) {
l = (lib_entry_t *)el1->object;
- if (handle == (int)l->handle) {
+ if (handle == l->id) {
if (el2) {
el2->next = el1->next;
} else {
@@ -508,6 +537,7 @@ int unloadLibrary(int handle)
// disable all effects from this library
pthread_mutex_lock(&l->lock);
+
el1 = gEffectList;
while (el1) {
fx = (effect_entry_t *)el1->object;
@@ -523,17 +553,23 @@ int unloadLibrary(int handle)
return 0;
}
+void resetEffectEnumeration()
+{
+ gCurLib = gLibraryList;
+ gCurEffect = NULL;
+ if (gCurLib) {
+ gCurEffect = ((lib_entry_t *)gCurLib->object)->effects;
+ }
+ gCurEffectIdx = 0;
+}
-
-uint32_t numEffectModules() {
- list_elem_t *e = gLibraryList;
+uint32_t updateNumEffects() {
+ list_elem_t *e;
uint32_t cnt = 0;
- // Reset pointers for EffectQueryNext()
- gCurLib = e;
- if (e) {
- gCurEffect = ((lib_entry_t *)e->object)->effects;
- }
+ resetEffectEnumeration();
+
+ e = gLibraryList;
while (e) {
lib_entry_t *l = (lib_entry_t *)e->object;
list_elem_t *efx = l->effects;
@@ -543,6 +579,8 @@ uint32_t numEffectModules() {
}
e = e->next;
}
+ gNumEffects = cnt;
+ gCanQueryEffect = 0;
return cnt;
}
diff --git a/media/libeffects/EffectsFactory.h b/media/libeffects/EffectsFactory.h
index 17ad3f0..8f543ca 100644
--- a/media/libeffects/EffectsFactory.h
+++ b/media/libeffects/EffectsFactory.h
@@ -20,7 +20,7 @@
#include <cutils/log.h>
#include <pthread.h>
#include <dirent.h>
-#include <media/EffectFactoryApi.h>
+#include <media/EffectsFactoryApi.h>
#if __cplusplus
@@ -35,6 +35,7 @@ typedef struct list_elem_s {
typedef struct lib_entry_s {
char path[PATH_MAX];
void *handle;
+ int id;
effect_CreateEffect_t createFx;
effect_ReleaseEffect_t releaseFx;
list_elem_t *effects; //list of effect_descriptor_t
diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp
index 8648211..4afa2dc 100644
--- a/media/libmedia/AudioEffect.cpp
+++ b/media/libmedia/AudioEffect.cpp
@@ -394,11 +394,11 @@ status_t AudioEffect::queryNumberEffects(uint32_t *numEffects)
return af->queryNumberEffects(numEffects);
}
-status_t AudioEffect::queryNextEffect(effect_descriptor_t *descriptor)
+status_t AudioEffect::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
{
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
- return af->queryNextEffect(descriptor);
+ return af->queryEffect(index, descriptor);
}
status_t AudioEffect::getEffectDescriptor(effect_uuid_t *uuid, effect_descriptor_t *descriptor)
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index f2a8db3..7d6a5d3 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -67,7 +67,7 @@ enum {
LOAD_EFFECT_LIBRARY,
UNLOAD_EFFECT_LIBRARY,
QUERY_NUM_EFFECTS,
- QUERY_NEXT_EFFECT,
+ QUERY_EFFECT,
GET_EFFECT_DESCRIPTOR,
CREATE_EFFECT
};
@@ -586,14 +586,15 @@ public:
return NO_ERROR;
}
- virtual status_t queryNextEffect(effect_descriptor_t *pDescriptor)
+ virtual status_t queryEffect(uint32_t index, effect_descriptor_t *pDescriptor)
{
if (pDescriptor == NULL) {
return BAD_VALUE;
}
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- status_t status = remote()->transact(QUERY_NEXT_EFFECT, data, &reply);
+ data.writeInt32(index);
+ status_t status = remote()->transact(QUERY_EFFECT, data, &reply);
if (status != NO_ERROR) {
return status;
}
@@ -980,10 +981,10 @@ status_t BnAudioFlinger::onTransact(
}
return NO_ERROR;
}
- case QUERY_NEXT_EFFECT: {
+ case QUERY_EFFECT: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
effect_descriptor_t desc;
- status_t status = queryNextEffect(&desc);
+ status_t status = queryEffect(data.readInt32(), &desc);
reply->writeInt32(status);
if (status == NO_ERROR) {
reply->write(&desc, sizeof(effect_descriptor_t));