1da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent/* 2da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * Copyright (C) 2010 The Android Open Source Project 3da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * 4da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * Licensed under the Apache License, Version 2.0 (the "License"); 5da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * you may not use this file except in compliance with the License. 6da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * You may obtain a copy of the License at 7da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * 8da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * http://www.apache.org/licenses/LICENSE-2.0 9da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * 10da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * Unless required by applicable law or agreed to in writing, software 11da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * distributed under the License is distributed on an "AS IS" BASIS, 12da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * See the License for the specific language governing permissions and 14da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent * limitations under the License. 15da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent */ 16da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 173476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi#define LOG_TAG "EffectVisualizer" 18da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//#define LOG_NDEBUG 0 19da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#include <cutils/log.h> 20da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#include <assert.h> 21da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#include <stdlib.h> 22da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#include <string.h> 23da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#include <new> 24183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent#include <time.h> 256d8b694d999e9be7d5dcc336535832a80fb6f61fEric Laurent#include <audio_effects/effect_visualizer.h> 26da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 27da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 28e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurentextern "C" { 29e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 30e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent// effect_handle_t interface implementation for visualizer effect 31e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurentextern const struct effect_interface_s gVisualizerInterface; 32da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 33da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// Google Visualizer UUID: d069d9e0-8329-11df-9168-0002a5d5c51b 34da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentconst effect_descriptor_t gVisualizerDescriptor = { 35da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent {0xe46b26a0, 0xdddd, 0x11db, 0x8afd, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type 36da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent {0xd069d9e0, 0x8329, 0x11df, 0x9168, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid 37e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent EFFECT_CONTROL_API_VERSION, 38da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST), 39da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 0, // TODO 40da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 1, 41da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent "Visualizer", 42e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent "The Android Open Source Project", 43da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}; 44da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 45da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentenum visualizer_state_e { 46da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent VISUALIZER_STATE_UNINITIALIZED, 47da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent VISUALIZER_STATE_INITIALIZED, 48da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent VISUALIZER_STATE_ACTIVE, 49da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}; 50da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 51183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent// maximum time since last capture buffer update before resetting capture buffer. This means 523df40a093d8d3d211f693e0e3ef4076750cabfeaEric Laurent// that the framework has stopped playing audio and we must start returning silence 53183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent#define MAX_STALL_TIME_MS 1000 543df40a093d8d3d211f693e0e3ef4076750cabfeaEric Laurent 55f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen#define CAPTURE_BUF_SIZE 65536 // "64k should be enough for everyone" 56f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen 57da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstruct VisualizerContext { 58da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent const struct effect_interface_s *mItfe; 59da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent effect_config_t mConfig; 60da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent uint32_t mCaptureIdx; 61da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent uint32_t mCaptureSize; 623476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi uint32_t mScalingMode; 633df40a093d8d3d211f693e0e3ef4076750cabfeaEric Laurent uint8_t mState; 64f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen uint8_t mLastCaptureIdx; 65f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen uint32_t mLatency; 66183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent struct timespec mBufferUpdateTime; 67f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen uint8_t mCaptureBuf[CAPTURE_BUF_SIZE]; 68da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}; 69da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 70da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 71da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//--- Local functions 72da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 73da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 74da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentvoid Visualizer_reset(VisualizerContext *pContext) 75da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{ 76da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mCaptureIdx = 0; 77f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pContext->mLastCaptureIdx = 0; 78183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent pContext->mBufferUpdateTime.tv_sec = 0; 79f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pContext->mLatency = 0; 80f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen memset(pContext->mCaptureBuf, 0x80, CAPTURE_BUF_SIZE); 81da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} 82da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 83da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//---------------------------------------------------------------------------- 843d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// Visualizer_setConfig() 85da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//---------------------------------------------------------------------------- 86da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// Purpose: Set input and output audio configuration. 87da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 88da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// Inputs: 89da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// pContext: effect engine context 90da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// pConfig: pointer to effect_config_t structure holding input and output 91da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// configuration parameters 92da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 93da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// Outputs: 94da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 95da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//---------------------------------------------------------------------------- 96da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 973d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurentint Visualizer_setConfig(VisualizerContext *pContext, effect_config_t *pConfig) 98da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{ 993d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent ALOGV("Visualizer_setConfig start"); 100da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 101da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pConfig->inputCfg.samplingRate != pConfig->outputCfg.samplingRate) return -EINVAL; 102da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pConfig->inputCfg.channels != pConfig->outputCfg.channels) return -EINVAL; 103da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pConfig->inputCfg.format != pConfig->outputCfg.format) return -EINVAL; 104e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent if (pConfig->inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) return -EINVAL; 105da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_WRITE && 106da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_ACCUMULATE) return -EINVAL; 107e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent if (pConfig->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL; 108da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 109da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent memcpy(&pContext->mConfig, pConfig, sizeof(effect_config_t)); 110da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 111da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent Visualizer_reset(pContext); 112da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 113da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return 0; 114da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} 115da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 116da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 117da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//---------------------------------------------------------------------------- 1183d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// Visualizer_getConfig() 1193d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent//---------------------------------------------------------------------------- 1203d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// Purpose: Get input and output audio configuration. 1213d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// 1223d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// Inputs: 1233d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// pContext: effect engine context 1243d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// pConfig: pointer to effect_config_t structure holding input and output 1253d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// configuration parameters 1263d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// 1273d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// Outputs: 1283d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// 1293d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent//---------------------------------------------------------------------------- 1303d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent 1313d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurentvoid Visualizer_getConfig(VisualizerContext *pContext, effect_config_t *pConfig) 1323d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent{ 1333d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent memcpy(pConfig, &pContext->mConfig, sizeof(effect_config_t)); 1343d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent} 1353d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent 1363d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent 1373d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent//---------------------------------------------------------------------------- 138da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// Visualizer_init() 139da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//---------------------------------------------------------------------------- 140da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// Purpose: Initialize engine with default configuration. 141da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 142da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// Inputs: 143da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// pContext: effect engine context 144da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 145da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// Outputs: 146da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 147da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//---------------------------------------------------------------------------- 148da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 149da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentint Visualizer_init(VisualizerContext *pContext) 150da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{ 151da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ; 152e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent pContext->mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; 153e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent pContext->mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 154da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.inputCfg.samplingRate = 44100; 155da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.inputCfg.bufferProvider.getBuffer = NULL; 156da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.inputCfg.bufferProvider.releaseBuffer = NULL; 157da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.inputCfg.bufferProvider.cookie = NULL; 158da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.inputCfg.mask = EFFECT_CONFIG_ALL; 159da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE; 160e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent pContext->mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; 161e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent pContext->mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 162da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.outputCfg.samplingRate = 44100; 163da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.outputCfg.bufferProvider.getBuffer = NULL; 164da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.outputCfg.bufferProvider.releaseBuffer = NULL; 165da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.outputCfg.bufferProvider.cookie = NULL; 166da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.outputCfg.mask = EFFECT_CONFIG_ALL; 167da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 168da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mCaptureSize = VISUALIZER_CAPTURE_SIZE_MAX; 1693476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi pContext->mScalingMode = VISUALIZER_SCALING_MODE_NORMALIZED; 170da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 1713d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent Visualizer_setConfig(pContext, &pContext->mConfig); 172da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 173da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return 0; 174da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} 175da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 176da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 177da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//--- Effect Library Interface Implementation 178da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 179da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 180e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurentint VisualizerLib_QueryNumberEffects(uint32_t *pNumEffects) { 181da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *pNumEffects = 1; 182da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return 0; 183da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} 184da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 185e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurentint VisualizerLib_QueryEffect(uint32_t index, 186e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent effect_descriptor_t *pDescriptor) { 187da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pDescriptor == NULL) { 188da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 189da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 190da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (index > 0) { 191da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 192da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 193da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent memcpy(pDescriptor, &gVisualizerDescriptor, sizeof(effect_descriptor_t)); 194da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return 0; 195da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} 196da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 1975e92a7861196ddae14638d4b7a63fc4892b7ef59Glenn Kastenint VisualizerLib_Create(const effect_uuid_t *uuid, 198e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent int32_t sessionId, 199e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent int32_t ioId, 200e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent effect_handle_t *pHandle) { 201da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent int ret; 202da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent int i; 203da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 204e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent if (pHandle == NULL || uuid == NULL) { 205da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 206da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 207da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 208da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (memcmp(uuid, &gVisualizerDescriptor.uuid, sizeof(effect_uuid_t)) != 0) { 209da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 210da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 211da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 212da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent VisualizerContext *pContext = new VisualizerContext; 213da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 214da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mItfe = &gVisualizerInterface; 215da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mState = VISUALIZER_STATE_UNINITIALIZED; 216da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 217da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent ret = Visualizer_init(pContext); 218da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (ret < 0) { 2195ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("VisualizerLib_Create() init failed"); 220da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent delete pContext; 221da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return ret; 222da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 223da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 224e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent *pHandle = (effect_handle_t)pContext; 225da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 226da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mState = VISUALIZER_STATE_INITIALIZED; 227da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 2283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("VisualizerLib_Create %p", pContext); 229da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 230da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return 0; 231da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 232da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} 233da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 234e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurentint VisualizerLib_Release(effect_handle_t handle) { 235e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent VisualizerContext * pContext = (VisualizerContext *)handle; 236da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 2373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("VisualizerLib_Release %p", handle); 238da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pContext == NULL) { 239da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 240da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 241da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mState = VISUALIZER_STATE_UNINITIALIZED; 242da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent delete pContext; 243da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 244da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return 0; 245da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} 246da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 2475e92a7861196ddae14638d4b7a63fc4892b7ef59Glenn Kastenint VisualizerLib_GetDescriptor(const effect_uuid_t *uuid, 248e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent effect_descriptor_t *pDescriptor) { 249e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 250e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent if (pDescriptor == NULL || uuid == NULL){ 2513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("VisualizerLib_GetDescriptor() called with NULL pointer"); 252e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent return -EINVAL; 253e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent } 254e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 255e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent if (memcmp(uuid, &gVisualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0) { 256e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent memcpy(pDescriptor, &gVisualizerDescriptor, sizeof(effect_descriptor_t)); 257e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent return 0; 258e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent } 259e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 260e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent return -EINVAL; 261e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent} /* end VisualizerLib_GetDescriptor */ 262e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 263da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 264da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//--- Effect Control Interface Implementation 265da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 266da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 267da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatic inline int16_t clamp16(int32_t sample) 268da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{ 269da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if ((sample>>15) ^ (sample>>31)) 270da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent sample = 0x7FFF ^ (sample>>31); 271da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return sample; 272da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} 273da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 274e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurentint Visualizer_process( 275e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent effect_handle_t self,audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) 276da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{ 277e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent VisualizerContext * pContext = (VisualizerContext *)self; 278da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 279da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pContext == NULL) { 280da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 281da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 282da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 283da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (inBuffer == NULL || inBuffer->raw == NULL || 284da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent outBuffer == NULL || outBuffer->raw == NULL || 285da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent inBuffer->frameCount != outBuffer->frameCount || 286da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent inBuffer->frameCount == 0) { 287da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 288da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 289da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 290da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent // all code below assumes stereo 16 bit PCM output and input 2913476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi int32_t shift; 2923476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi 2933476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi if (pContext->mScalingMode == VISUALIZER_SCALING_MODE_NORMALIZED) { 2943476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi // derive capture scaling factor from peak value in current buffer 2953476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi // this gives more interesting captures for display. 2963476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi shift = 32; 2973476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi int len = inBuffer->frameCount * 2; 2983476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi for (int i = 0; i < len; i++) { 2993476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi int32_t smp = inBuffer->s16[i]; 3003476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi if (smp < 0) smp = -smp - 1; // take care to keep the max negative in range 3013476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi int32_t clz = __builtin_clz(smp); 3023476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi if (shift > clz) shift = clz; 3033476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi } 3043476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi // A maximum amplitude signal will have 17 leading zeros, which we want to 3053476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi // translate to a shift of 8 (for converting 16 bit to 8 bit) 3063476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi shift = 25 - shift; 3073476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi // Never scale by less than 8 to avoid returning unaltered PCM signal. 3083476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi if (shift < 3) { 3093476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi shift = 3; 3103476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi } 3113476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi // add one to combine the division by 2 needed after summing left and right channels below 3123476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi shift++; 3133476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi } else { 3143476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi assert(pContext->mScalingMode == VISUALIZER_SCALING_MODE_AS_PLAYED); 3153476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi shift = 9; 3160e75f0f0147baeb6277c3dcc4403cf0201155a99Eric Laurent } 3170e75f0f0147baeb6277c3dcc4403cf0201155a99Eric Laurent 318da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent uint32_t captIdx; 319da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent uint32_t inIdx; 320f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen uint8_t *buf = pContext->mCaptureBuf; 321da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent for (inIdx = 0, captIdx = pContext->mCaptureIdx; 322f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen inIdx < inBuffer->frameCount; 323da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent inIdx++, captIdx++) { 324f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen if (captIdx >= CAPTURE_BUF_SIZE) { 325f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen // wrap around 326f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen captIdx = 0; 327f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen } 328da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent int32_t smp = inBuffer->s16[2 * inIdx] + inBuffer->s16[2 * inIdx + 1]; 32964c3bdea8cba454d4404baded584ea0f0611b3eeMarco Nelissen smp = smp >> shift; 330da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent buf[captIdx] = ((uint8_t)smp)^0x80; 331da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 332da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 333f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen // XXX the following two should really be atomic, though it probably doesn't 334f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen // matter much for visualization purposes 335f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pContext->mCaptureIdx = captIdx; 336f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen // update last buffer update time stamp 337f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen if (clock_gettime(CLOCK_MONOTONIC, &pContext->mBufferUpdateTime) < 0) { 338f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pContext->mBufferUpdateTime.tv_sec = 0; 339da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 340da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 341da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (inBuffer->raw != outBuffer->raw) { 342da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pContext->mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) { 343da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent for (size_t i = 0; i < outBuffer->frameCount*2; i++) { 344da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent outBuffer->s16[i] = clamp16(outBuffer->s16[i] + inBuffer->s16[i]); 345da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 346da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } else { 347da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent memcpy(outBuffer->raw, inBuffer->raw, outBuffer->frameCount * 2 * sizeof(int16_t)); 348da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 349da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 350f997cabca292d70d078ae828e21c28e6df62995fEric Laurent if (pContext->mState != VISUALIZER_STATE_ACTIVE) { 351f997cabca292d70d078ae828e21c28e6df62995fEric Laurent return -ENODATA; 352f997cabca292d70d078ae828e21c28e6df62995fEric Laurent } 353da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return 0; 354da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} // end Visualizer_process 355da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 356e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurentint Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, 35725f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent void *pCmdData, uint32_t *replySize, void *pReplyData) { 358da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 359e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent VisualizerContext * pContext = (VisualizerContext *)self; 360da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent int retsize; 361da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 362da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pContext == NULL || pContext->mState == VISUALIZER_STATE_UNINITIALIZED) { 363da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 364da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 365da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 3663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block// ALOGV("Visualizer_command command %d cmdSize %d",cmdCode, cmdSize); 367da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 368da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent switch (cmdCode) { 369da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_INIT: 370da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pReplyData == NULL || *replySize != sizeof(int)) { 371da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 372da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 373da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *(int *) pReplyData = Visualizer_init(pContext); 374da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent break; 3753d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent case EFFECT_CMD_SET_CONFIG: 376da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) 377da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent || pReplyData == NULL || *replySize != sizeof(int)) { 378da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 379da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 3803d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent *(int *) pReplyData = Visualizer_setConfig(pContext, 381da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent (effect_config_t *) pCmdData); 382da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent break; 3833d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent case EFFECT_CMD_GET_CONFIG: 3843d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent if (pReplyData == NULL || 3853d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent *replySize != sizeof(effect_config_t)) { 3863d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent return -EINVAL; 3873d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent } 3883d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent Visualizer_getConfig(pContext, (effect_config_t *)pReplyData); 3893d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent break; 390da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_RESET: 391da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent Visualizer_reset(pContext); 392da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent break; 393da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_ENABLE: 394da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pReplyData == NULL || *replySize != sizeof(int)) { 395da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 396da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 397da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pContext->mState != VISUALIZER_STATE_INITIALIZED) { 398da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -ENOSYS; 399da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 400da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mState = VISUALIZER_STATE_ACTIVE; 4013856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("EFFECT_CMD_ENABLE() OK"); 402da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *(int *)pReplyData = 0; 403da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent break; 404da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_DISABLE: 405da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pReplyData == NULL || *replySize != sizeof(int)) { 406da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 407da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 408da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pContext->mState != VISUALIZER_STATE_ACTIVE) { 409da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -ENOSYS; 410da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 411da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mState = VISUALIZER_STATE_INITIALIZED; 4123856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("EFFECT_CMD_DISABLE() OK"); 413da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *(int *)pReplyData = 0; 414da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent break; 415da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_GET_PARAM: { 416da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pCmdData == NULL || 417da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent cmdSize != (int)(sizeof(effect_param_t) + sizeof(uint32_t)) || 418da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pReplyData == NULL || 419da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *replySize < (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint32_t))) { 420da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 421da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 422da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(uint32_t)); 423da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent effect_param_t *p = (effect_param_t *)pReplyData; 424da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent p->status = 0; 425da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *replySize = sizeof(effect_param_t) + sizeof(uint32_t); 4263476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi if (p->psize != sizeof(uint32_t)) { 427da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent p->status = -EINVAL; 428da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent break; 429da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 4303476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi switch (*(uint32_t *)p->data) { 4313476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi case VISUALIZER_PARAM_CAPTURE_SIZE: 4323476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi ALOGV("get mCaptureSize = %d", pContext->mCaptureSize); 4333476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi *((uint32_t *)p->data + 1) = pContext->mCaptureSize; 4343476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi p->vsize = sizeof(uint32_t); 4353476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi *replySize += sizeof(uint32_t); 4363476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi break; 4373476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi case VISUALIZER_PARAM_SCALING_MODE: 4383476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi ALOGV("get mScalingMode = %d", pContext->mScalingMode); 4393476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi *((uint32_t *)p->data + 1) = pContext->mScalingMode; 4403476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi p->vsize = sizeof(uint32_t); 4413476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi *replySize += sizeof(uint32_t); 4423476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi break; 4433476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi default: 4443476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi p->status = -EINVAL; 4453476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi } 446da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } break; 447da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_SET_PARAM: { 448da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pCmdData == NULL || 449da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent cmdSize != (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint32_t)) || 450da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pReplyData == NULL || *replySize != sizeof(int32_t)) { 451da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 452da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 453da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *(int32_t *)pReplyData = 0; 454da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent effect_param_t *p = (effect_param_t *)pCmdData; 4553476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi if (p->psize != sizeof(uint32_t) || p->vsize != sizeof(uint32_t)) { 4563476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi *(int32_t *)pReplyData = -EINVAL; 4573476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi break; 4583476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi } 4593476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi switch (*(uint32_t *)p->data) { 4603476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi case VISUALIZER_PARAM_CAPTURE_SIZE: 4613476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi pContext->mCaptureSize = *((uint32_t *)p->data + 1); 4623476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi ALOGV("set mCaptureSize = %d", pContext->mCaptureSize); 4633476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi break; 4643476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi case VISUALIZER_PARAM_SCALING_MODE: 4653476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi pContext->mScalingMode = *((uint32_t *)p->data + 1); 4663476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi ALOGV("set mScalingMode = %d", pContext->mScalingMode); 4673476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi break; 468f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen case VISUALIZER_PARAM_LATENCY: 469f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pContext->mLatency = *((uint32_t *)p->data + 1); 470f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen ALOGV("set mLatency = %d", pContext->mLatency); 471f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen break; 4723476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi default: 473da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *(int32_t *)pReplyData = -EINVAL; 474da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 475da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } break; 476da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_SET_DEVICE: 477da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_SET_VOLUME: 478da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_SET_AUDIO_MODE: 479da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent break; 480da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 481da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 4826d8b694d999e9be7d5dcc336535832a80fb6f61fEric Laurent case VISUALIZER_CMD_CAPTURE: 4830e75f0f0147baeb6277c3dcc4403cf0201155a99Eric Laurent if (pReplyData == NULL || *replySize != pContext->mCaptureSize) { 4843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("VISUALIZER_CMD_CAPTURE() error *replySize %d pContext->mCaptureSize %d", 485da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *replySize, pContext->mCaptureSize); 486da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 487da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 488da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pContext->mState == VISUALIZER_STATE_ACTIVE) { 489f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen int32_t latencyMs = pContext->mLatency; 490f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen uint32_t deltaMs = 0; 491f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen if (pContext->mBufferUpdateTime.tv_sec != 0) { 492183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent struct timespec ts; 493183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { 494183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent time_t secs = ts.tv_sec - pContext->mBufferUpdateTime.tv_sec; 495183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent long nsec = ts.tv_nsec - pContext->mBufferUpdateTime.tv_nsec; 496183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent if (nsec < 0) { 497183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent --secs; 498183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent nsec += 1000000000; 499183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent } 500f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen deltaMs = secs * 1000 + nsec / 1000000; 501f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen latencyMs -= deltaMs; 502f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen if (latencyMs < 0) { 503f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen latencyMs = 0; 5043df40a093d8d3d211f693e0e3ef4076750cabfeaEric Laurent } 5053df40a093d8d3d211f693e0e3ef4076750cabfeaEric Laurent } 5063df40a093d8d3d211f693e0e3ef4076750cabfeaEric Laurent } 507f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen uint32_t deltaSmpl = pContext->mConfig.inputCfg.samplingRate * latencyMs / 1000; 508f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen 509f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen int32_t capturePoint = pContext->mCaptureIdx - pContext->mCaptureSize - deltaSmpl; 510f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen int32_t captureSize = pContext->mCaptureSize; 511f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen if (capturePoint < 0) { 512f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen int32_t size = -capturePoint; 513f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen if (size > captureSize) { 514f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen size = captureSize; 515f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen } 516f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen memcpy(pReplyData, 517f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pContext->mCaptureBuf + CAPTURE_BUF_SIZE + capturePoint, 518f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen size); 519f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pReplyData += size; 520f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen captureSize -= size; 521f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen capturePoint = 0; 522f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen } 523f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen memcpy(pReplyData, 524f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pContext->mCaptureBuf + capturePoint, 525f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen captureSize); 526f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen 527f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen 528f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen // if audio framework has stopped playing audio although the effect is still 529f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen // active we must clear the capture buffer to return silence 530f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen if ((pContext->mLastCaptureIdx == pContext->mCaptureIdx) && 531f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen (pContext->mBufferUpdateTime.tv_sec != 0)) { 532f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen if (deltaMs > MAX_STALL_TIME_MS) { 533f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen ALOGV("capture going to idle"); 534f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pContext->mBufferUpdateTime.tv_sec = 0; 535f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen memset(pReplyData, 0x80, pContext->mCaptureSize); 536f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen } 537f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen } 538f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pContext->mLastCaptureIdx = pContext->mCaptureIdx; 539da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } else { 540da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent memset(pReplyData, 0x80, pContext->mCaptureSize); 541da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 5423df40a093d8d3d211f693e0e3ef4076750cabfeaEric Laurent 543da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent break; 544da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 545da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent default: 5465ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("Visualizer_command invalid command %d",cmdCode); 547da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 548da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 549da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 550da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return 0; 551da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} 552da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 553e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent/* Effect Control Interface Implementation: get_descriptor */ 554e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurentint Visualizer_getDescriptor(effect_handle_t self, 555e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent effect_descriptor_t *pDescriptor) 556e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent{ 557e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent VisualizerContext * pContext = (VisualizerContext *) self; 558e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 559e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent if (pContext == NULL || pDescriptor == NULL) { 5603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Visualizer_getDescriptor() invalid param"); 561e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent return -EINVAL; 562e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent } 563e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 564e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent memcpy(pDescriptor, &gVisualizerDescriptor, sizeof(effect_descriptor_t)); 565e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 566e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent return 0; 567e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent} /* end Visualizer_getDescriptor */ 568e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 569e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent// effect_handle_t interface implementation for visualizer effect 570da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentconst struct effect_interface_s gVisualizerInterface = { 571da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent Visualizer_process, 572e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent Visualizer_command, 573ba7b8f881a9b6b21803752326d2932a3bd42d7cfEric Laurent Visualizer_getDescriptor, 574ba7b8f881a9b6b21803752326d2932a3bd42d7cfEric Laurent NULL, 575da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}; 576da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 577da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 578e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurentaudio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { 579e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent tag : AUDIO_EFFECT_LIBRARY_TAG, 580e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent version : EFFECT_LIBRARY_API_VERSION, 581e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent name : "Visualizer Library", 582e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent implementor : "The Android Open Source Project", 583e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent query_num_effects : VisualizerLib_QueryNumberEffects, 584e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent query_effect : VisualizerLib_QueryEffect, 585e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent create_effect : VisualizerLib_Create, 586e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent release_effect : VisualizerLib_Release, 587e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent get_descriptor : VisualizerLib_GetDescriptor, 588e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent}; 589e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 590e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent}; // extern "C" 591