summaryrefslogtreecommitdiff
path: root/media/libeffects/visualizer
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2010-07-09 12:28:50 -0700
committerEric Laurent <elaurent@google.com>2010-07-17 06:33:00 -0700
commit2c8e5cab3faa6d360e222b7a6c40a80083d021ac (patch)
treefd19b8baa829edb78116b089d1122ea4ef0921e1 /media/libeffects/visualizer
parentada2ac8e09b6d3f2b3c3155a852ba0fffae1b592 (diff)
First submission of audio effect library from NXP software.
This CL contains the first open sourceable version of the audio effect library from NXP software. The effects implemented are: - Bass boost - Virtualizer (stereo widening) - Equalizer - Spectrum analyzer Source file for the effect engines are located under libeffects/lvm/lib The wrapper implementing the interface with the audio effect framework in under libeffects/lvm/wrapper The code of other effect libraries has also been reorganized fo clarity: - the effect factory is now under libeffects/factory - the test equalizer and reverb effects are under libeffect/testlibs - the visualizer is under libeffects/virtualizer Change-Id: I8d91e2181f81b89f8fc0c1e1e6bf552c5809b2eb
Diffstat (limited to 'media/libeffects/visualizer')
-rw-r--r--media/libeffects/visualizer/Android.mk30
-rw-r--r--media/libeffects/visualizer/EffectVisualizer.cpp401
2 files changed, 431 insertions, 0 deletions
diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk
new file mode 100644
index 00000000..82cd9255
--- /dev/null
+++ b/media/libeffects/visualizer/Android.mk
@@ -0,0 +1,30 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Visualizer library
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ EffectVisualizer.cpp
+
+LOCAL_CFLAGS+= -O2
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+LOCAL_MODULE:= libvisualizer
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldlS
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, graphics corecg)
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY) \ No newline at end of file
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
new file mode 100644
index 00000000..bcda06e8
--- /dev/null
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Visualizer"
+//#define LOG_NDEBUG 0
+#include <cutils/log.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <new>
+#include <media/EffectVisualizerApi.h>
+
+namespace android {
+
+// effect_interface_t interface implementation for visualizer effect
+extern "C" const struct effect_interface_s gVisualizerInterface;
+
+// Google Visualizer UUID: d069d9e0-8329-11df-9168-0002a5d5c51b
+const effect_descriptor_t gVisualizerDescriptor = {
+ {0xe46b26a0, 0xdddd, 0x11db, 0x8afd, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
+ {0xd069d9e0, 0x8329, 0x11df, 0x9168, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
+ EFFECT_API_VERSION,
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST),
+ 0, // TODO
+ 1,
+ "Visualizer",
+ "Google Inc.",
+};
+
+enum visualizer_state_e {
+ VISUALIZER_STATE_UNINITIALIZED,
+ VISUALIZER_STATE_INITIALIZED,
+ VISUALIZER_STATE_ACTIVE,
+};
+
+struct VisualizerContext {
+ const struct effect_interface_s *mItfe;
+ effect_config_t mConfig;
+ uint32_t mState;
+ uint32_t mCaptureIdx;
+ uint32_t mCaptureSize;
+ uint32_t mCurrentBuf;
+ uint8_t mCaptureBuf[2][VISUALIZER_CAPTURE_SIZE_MAX];
+};
+
+
+//
+//--- Local functions
+//
+
+void Visualizer_reset(VisualizerContext *pContext)
+{
+ pContext->mCaptureIdx = 0;
+ pContext->mCurrentBuf = 0;
+ memset(pContext->mCaptureBuf[0], 0, VISUALIZER_CAPTURE_SIZE_MAX);
+ memset(pContext->mCaptureBuf[1], 0, VISUALIZER_CAPTURE_SIZE_MAX);
+}
+
+//----------------------------------------------------------------------------
+// Visualizer_configure()
+//----------------------------------------------------------------------------
+// Purpose: Set input and output audio configuration.
+//
+// Inputs:
+// pContext: effect engine context
+// pConfig: pointer to effect_config_t structure holding input and output
+// configuration parameters
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Visualizer_configure(VisualizerContext *pContext, effect_config_t *pConfig)
+{
+ LOGV("Visualizer_configure start");
+
+ if (pConfig->inputCfg.samplingRate != pConfig->outputCfg.samplingRate) return -EINVAL;
+ if (pConfig->inputCfg.channels != pConfig->outputCfg.channels) return -EINVAL;
+ if (pConfig->inputCfg.format != pConfig->outputCfg.format) return -EINVAL;
+ if (pConfig->inputCfg.channels != CHANNEL_STEREO) return -EINVAL;
+ if (pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_WRITE &&
+ pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_ACCUMULATE) return -EINVAL;
+ if (pConfig->inputCfg.format != SAMPLE_FORMAT_PCM_S15) return -EINVAL;
+
+ memcpy(&pContext->mConfig, pConfig, sizeof(effect_config_t));
+
+ Visualizer_reset(pContext);
+
+ return 0;
+}
+
+
+//----------------------------------------------------------------------------
+// Visualizer_init()
+//----------------------------------------------------------------------------
+// Purpose: Initialize engine with default configuration.
+//
+// Inputs:
+// pContext: effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Visualizer_init(VisualizerContext *pContext)
+{
+ pContext->mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+ pContext->mConfig.inputCfg.channels = CHANNEL_STEREO;
+ pContext->mConfig.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
+ pContext->mConfig.inputCfg.samplingRate = 44100;
+ pContext->mConfig.inputCfg.bufferProvider.getBuffer = NULL;
+ pContext->mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
+ pContext->mConfig.inputCfg.bufferProvider.cookie = NULL;
+ pContext->mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
+ pContext->mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+ pContext->mConfig.outputCfg.channels = CHANNEL_STEREO;
+ pContext->mConfig.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
+ pContext->mConfig.outputCfg.samplingRate = 44100;
+ pContext->mConfig.outputCfg.bufferProvider.getBuffer = NULL;
+ pContext->mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
+ pContext->mConfig.outputCfg.bufferProvider.cookie = NULL;
+ pContext->mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
+
+ pContext->mCaptureSize = VISUALIZER_CAPTURE_SIZE_MAX;
+
+ Visualizer_configure(pContext, &pContext->mConfig);
+
+ return 0;
+}
+
+//
+//--- Effect Library Interface Implementation
+//
+
+extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects) {
+ *pNumEffects = 1;
+ return 0;
+}
+
+extern "C" int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) {
+ if (pDescriptor == NULL) {
+ return -EINVAL;
+ }
+ if (index > 0) {
+ return -EINVAL;
+ }
+ memcpy(pDescriptor, &gVisualizerDescriptor, sizeof(effect_descriptor_t));
+ return 0;
+}
+
+extern "C" int EffectCreate(effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_interface_t *pInterface) {
+ int ret;
+ int i;
+
+ if (pInterface == NULL || uuid == NULL) {
+ return -EINVAL;
+ }
+
+ if (memcmp(uuid, &gVisualizerDescriptor.uuid, sizeof(effect_uuid_t)) != 0) {
+ return -EINVAL;
+ }
+
+ VisualizerContext *pContext = new VisualizerContext;
+
+ pContext->mItfe = &gVisualizerInterface;
+ pContext->mState = VISUALIZER_STATE_UNINITIALIZED;
+
+ ret = Visualizer_init(pContext);
+ if (ret < 0) {
+ LOGW("EffectCreate() init failed");
+ delete pContext;
+ return ret;
+ }
+
+ *pInterface = (effect_interface_t)pContext;
+
+ pContext->mState = VISUALIZER_STATE_INITIALIZED;
+
+ LOGV("EffectCreate %p", pContext);
+
+ return 0;
+
+}
+
+extern "C" int EffectRelease(effect_interface_t interface) {
+ VisualizerContext * pContext = (VisualizerContext *)interface;
+
+ LOGV("EffectRelease %p", interface);
+ if (pContext == NULL) {
+ return -EINVAL;
+ }
+ pContext->mState = VISUALIZER_STATE_UNINITIALIZED;
+ delete pContext;
+
+ return 0;
+}
+
+//
+//--- Effect Control Interface Implementation
+//
+
+static inline int16_t clamp16(int32_t sample)
+{
+ if ((sample>>15) ^ (sample>>31))
+ sample = 0x7FFF ^ (sample>>31);
+ return sample;
+}
+
+extern "C" int Visualizer_process(
+ effect_interface_t self,audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
+{
+ android::VisualizerContext * pContext = (android::VisualizerContext *)self;
+
+ if (pContext == NULL) {
+ return -EINVAL;
+ }
+ if (pContext->mState != VISUALIZER_STATE_ACTIVE) {
+ return -ENODATA;
+ }
+
+ if (inBuffer == NULL || inBuffer->raw == NULL ||
+ outBuffer == NULL || outBuffer->raw == NULL ||
+ inBuffer->frameCount != outBuffer->frameCount ||
+ inBuffer->frameCount == 0) {
+ return -EINVAL;
+ }
+
+ // all code below assumes stereo 16 bit PCM output and input
+ uint32_t captIdx;
+ uint32_t inIdx;
+ uint8_t *buf = pContext->mCaptureBuf[pContext->mCurrentBuf];
+ for (inIdx = 0, captIdx = pContext->mCaptureIdx;
+ inIdx < inBuffer->frameCount && captIdx < pContext->mCaptureSize;
+ inIdx++, captIdx++) {
+ int32_t smp = inBuffer->s16[2 * inIdx] + inBuffer->s16[2 * inIdx + 1];
+ smp = (smp + (1 << 8)) >> 9;
+ buf[captIdx] = ((uint8_t)smp)^0x80;
+ }
+ pContext->mCaptureIdx = captIdx;
+
+ // go to next buffer when buffer full
+ if (pContext->mCaptureIdx == pContext->mCaptureSize) {
+ pContext->mCurrentBuf ^= 1;
+ pContext->mCaptureIdx = 0;
+ }
+
+ if (inBuffer->raw != outBuffer->raw) {
+ if (pContext->mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+ for (size_t i = 0; i < outBuffer->frameCount*2; i++) {
+ outBuffer->s16[i] = clamp16(outBuffer->s16[i] + inBuffer->s16[i]);
+ }
+ } else {
+ memcpy(outBuffer->raw, inBuffer->raw, outBuffer->frameCount * 2 * sizeof(int16_t));
+ }
+ }
+ return 0;
+} // end Visualizer_process
+
+extern "C" int Visualizer_command(effect_interface_t self, int cmdCode, int cmdSize,
+ void *pCmdData, int *replySize, void *pReplyData) {
+
+ android::VisualizerContext * pContext = (android::VisualizerContext *)self;
+ int retsize;
+
+ if (pContext == NULL || pContext->mState == VISUALIZER_STATE_UNINITIALIZED) {
+ return -EINVAL;
+ }
+
+// LOGV("Visualizer_command command %d cmdSize %d",cmdCode, cmdSize);
+
+ switch (cmdCode) {
+ case EFFECT_CMD_INIT:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ *(int *) pReplyData = Visualizer_init(pContext);
+ break;
+ case EFFECT_CMD_CONFIGURE:
+ if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
+ || pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ *(int *) pReplyData = Visualizer_configure(pContext,
+ (effect_config_t *) pCmdData);
+ break;
+ case EFFECT_CMD_RESET:
+ Visualizer_reset(pContext);
+ break;
+ case EFFECT_CMD_ENABLE:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ if (pContext->mState != VISUALIZER_STATE_INITIALIZED) {
+ return -ENOSYS;
+ }
+ pContext->mState = VISUALIZER_STATE_ACTIVE;
+ LOGV("EFFECT_CMD_ENABLE() OK");
+ *(int *)pReplyData = 0;
+ break;
+ case EFFECT_CMD_DISABLE:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ if (pContext->mState != VISUALIZER_STATE_ACTIVE) {
+ return -ENOSYS;
+ }
+ pContext->mState = VISUALIZER_STATE_INITIALIZED;
+ LOGV("EFFECT_CMD_DISABLE() OK");
+ *(int *)pReplyData = 0;
+ break;
+ case EFFECT_CMD_GET_PARAM: {
+ if (pCmdData == NULL ||
+ cmdSize != (int)(sizeof(effect_param_t) + sizeof(uint32_t)) ||
+ pReplyData == NULL ||
+ *replySize < (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint32_t))) {
+ return -EINVAL;
+ }
+ memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(uint32_t));
+ effect_param_t *p = (effect_param_t *)pReplyData;
+ p->status = 0;
+ *replySize = sizeof(effect_param_t) + sizeof(uint32_t);
+ if (p->psize != sizeof(uint32_t) ||
+ *(uint32_t *)p->data != VISU_PARAM_CAPTURE_SIZE) {
+ p->status = -EINVAL;
+ break;
+ }
+ LOGV("get mCaptureSize = %d", pContext->mCaptureSize);
+ *((uint32_t *)p->data + 1) = pContext->mCaptureSize;
+ p->vsize = sizeof(uint32_t);
+ *replySize += sizeof(uint32_t);
+ } break;
+ case EFFECT_CMD_SET_PARAM: {
+ if (pCmdData == NULL ||
+ cmdSize != (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint32_t)) ||
+ pReplyData == NULL || *replySize != sizeof(int32_t)) {
+ return -EINVAL;
+ }
+ *(int32_t *)pReplyData = 0;
+ effect_param_t *p = (effect_param_t *)pCmdData;
+ if (p->psize != sizeof(uint32_t) ||
+ p->vsize != sizeof(uint32_t) ||
+ *(uint32_t *)p->data != VISU_PARAM_CAPTURE_SIZE) {
+ *(int32_t *)pReplyData = -EINVAL;
+ break;;
+ }
+ pContext->mCaptureSize = *((uint32_t *)p->data + 1);
+ LOGV("set mCaptureSize = %d", pContext->mCaptureSize);
+ } break;
+ case EFFECT_CMD_SET_DEVICE:
+ case EFFECT_CMD_SET_VOLUME:
+ case EFFECT_CMD_SET_AUDIO_MODE:
+ break;
+
+
+ case VISU_CMD_CAPTURE:
+ if (pReplyData == NULL || *replySize != (int)pContext->mCaptureSize) {
+ LOGV("VISU_CMD_CAPTURE() error *replySize %d pContext->mCaptureSize %d",
+ *replySize, pContext->mCaptureSize);
+ return -EINVAL;
+ }
+ if (pContext->mState == VISUALIZER_STATE_ACTIVE) {
+ memcpy(pReplyData,
+ pContext->mCaptureBuf[pContext->mCurrentBuf ^ 1],
+ pContext->mCaptureSize);
+ } else {
+ memset(pReplyData, 0x80, pContext->mCaptureSize);
+ }
+ break;
+
+ default:
+ LOGW("Visualizer_command invalid command %d",cmdCode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+// effect_interface_t interface implementation for visualizer effect
+const struct effect_interface_s gVisualizerInterface = {
+ Visualizer_process,
+ Visualizer_command
+};
+
+} // namespace
+