summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2010-06-25 14:22:39 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2010-06-25 14:22:39 -0700
commita93b488457b8d7dd17a1d80c82a9accafcdd8bad (patch)
tree8e258fd14ef2938d71a12b795409800f847d051c /media
parentfd6440c0aca0659ce2c5220ecded707dfd4db1bc (diff)
parent0070c924a2050b6683d6d170602201cc5f83a1a6 (diff)
downloadframeworks_av-a93b488457b8d7dd17a1d80c82a9accafcdd8bad.zip
frameworks_av-a93b488457b8d7dd17a1d80c82a9accafcdd8bad.tar.gz
frameworks_av-a93b488457b8d7dd17a1d80c82a9accafcdd8bad.tar.bz2
am cdf1357b: am 8e103da1: Merge "Various fixes and improvements in audio effects implementation" into gingerbread
Merge commit 'cdf1357b6e0152280dcd611b5f096db4887d8126' * commit 'cdf1357b6e0152280dcd611b5f096db4887d8126': Various fixes and improvements in audio effects implementation
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));