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 197cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn#include <log/log.h> 20da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#include <assert.h> 217cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn#include <inttypes.h> 22da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#include <stdlib.h> 23da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#include <string.h> 24da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent#include <new> 25183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent#include <time.h> 2609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi#include <math.h> 276d8b694d999e9be7d5dcc336535832a80fb6f61fEric Laurent#include <audio_effects/effect_visualizer.h> 28da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 29da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 30e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurentextern "C" { 31e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 32e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent// effect_handle_t interface implementation for visualizer effect 33e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurentextern const struct effect_interface_s gVisualizerInterface; 34da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 35da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// Google Visualizer UUID: d069d9e0-8329-11df-9168-0002a5d5c51b 36da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentconst effect_descriptor_t gVisualizerDescriptor = { 37da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent {0xe46b26a0, 0xdddd, 0x11db, 0x8afd, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type 38da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent {0xd069d9e0, 0x8329, 0x11df, 0x9168, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid 39e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent EFFECT_CONTROL_API_VERSION, 40da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST), 41da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 0, // TODO 42da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 1, 43da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent "Visualizer", 44e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent "The Android Open Source Project", 45da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}; 46da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 47da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentenum visualizer_state_e { 48da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent VISUALIZER_STATE_UNINITIALIZED, 49da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent VISUALIZER_STATE_INITIALIZED, 50da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent VISUALIZER_STATE_ACTIVE, 51da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}; 52da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 53183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent// maximum time since last capture buffer update before resetting capture buffer. This means 543df40a093d8d3d211f693e0e3ef4076750cabfeaEric Laurent// that the framework has stopped playing audio and we must start returning silence 55183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent#define MAX_STALL_TIME_MS 1000 563df40a093d8d3d211f693e0e3ef4076750cabfeaEric Laurent 57f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen#define CAPTURE_BUF_SIZE 65536 // "64k should be enough for everyone" 58f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen 5909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi#define DISCARD_MEASUREMENTS_TIME_MS 2000 // discard measurements older than this number of ms 6009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi 6109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi// maximum number of buffers for which we keep track of the measurements 626fbc9ef121b081f888163190bb13cbac31599900Jean-Michel Trivi#define MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS 25 // note: buffer index is stored in uint8_t 6309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi 6409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi 6509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivistruct BufferStats { 6609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi bool mIsValid; 6709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi uint16_t mPeakU16; // the positive peak of the absolute value of the samples in a buffer 6809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi float mRmsSquared; // the average square of the samples in a buffer 6909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi}; 7009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi 71da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstruct VisualizerContext { 72da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent const struct effect_interface_s *mItfe; 73da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent effect_config_t mConfig; 74da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent uint32_t mCaptureIdx; 75da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent uint32_t mCaptureSize; 763476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi uint32_t mScalingMode; 773df40a093d8d3d211f693e0e3ef4076750cabfeaEric Laurent uint8_t mState; 785baf2af52cd186633b7173196c1e4a4cd3435f22Eric Laurent uint32_t mLastCaptureIdx; 79f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen uint32_t mLatency; 80183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent struct timespec mBufferUpdateTime; 81f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen uint8_t mCaptureBuf[CAPTURE_BUF_SIZE]; 8209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi // for measurements 8309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi uint8_t mChannelCount; // to avoid recomputing it every time a buffer is processed 8409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi uint32_t mMeasurementMode; 8509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi uint8_t mMeasurementWindowSizeInBuffers; 8609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi uint8_t mMeasurementBufferIdx; 8709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi BufferStats mPastMeasurements[MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS]; 88da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}; 89da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 90da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 91da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//--- Local functions 92da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 9309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Triviuint32_t Visualizer_getDeltaTimeMsFromUpdatedTime(VisualizerContext* pContext) { 9409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi uint32_t deltaMs = 0; 9509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi if (pContext->mBufferUpdateTime.tv_sec != 0) { 9609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi struct timespec ts; 9709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { 9809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi time_t secs = ts.tv_sec - pContext->mBufferUpdateTime.tv_sec; 9909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi long nsec = ts.tv_nsec - pContext->mBufferUpdateTime.tv_nsec; 10009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi if (nsec < 0) { 10109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi --secs; 10209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi nsec += 1000000000; 10309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } 10409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi deltaMs = secs * 1000 + nsec / 1000000; 10509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } 10609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } 10709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi return deltaMs; 10809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi} 10909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi 110da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 111da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentvoid Visualizer_reset(VisualizerContext *pContext) 112da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{ 113da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mCaptureIdx = 0; 114f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pContext->mLastCaptureIdx = 0; 115183dc7772d7eba127aab63829c7ca0359d817593Eric Laurent pContext->mBufferUpdateTime.tv_sec = 0; 116f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pContext->mLatency = 0; 117f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen memset(pContext->mCaptureBuf, 0x80, CAPTURE_BUF_SIZE); 118da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} 119da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 120da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//---------------------------------------------------------------------------- 1213d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// Visualizer_setConfig() 122da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//---------------------------------------------------------------------------- 123da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// Purpose: Set input and output audio configuration. 124da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 125da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// Inputs: 126da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// pContext: effect engine context 127da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// pConfig: pointer to effect_config_t structure holding input and output 128da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// configuration parameters 129da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 130da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// Outputs: 131da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 132da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//---------------------------------------------------------------------------- 133da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 1343d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurentint Visualizer_setConfig(VisualizerContext *pContext, effect_config_t *pConfig) 135da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{ 1363d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent ALOGV("Visualizer_setConfig start"); 137da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 138da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pConfig->inputCfg.samplingRate != pConfig->outputCfg.samplingRate) return -EINVAL; 139da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pConfig->inputCfg.channels != pConfig->outputCfg.channels) return -EINVAL; 140da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pConfig->inputCfg.format != pConfig->outputCfg.format) return -EINVAL; 141e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent if (pConfig->inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) return -EINVAL; 142da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_WRITE && 143da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_ACCUMULATE) return -EINVAL; 144e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent if (pConfig->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL; 145da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 146a189a6883ee55cf62da1d7bf5bf5a8ab501938a4Glenn Kasten pContext->mConfig = *pConfig; 147da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 148da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent Visualizer_reset(pContext); 149da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 150da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return 0; 151da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} 152da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 153da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 154da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//---------------------------------------------------------------------------- 1553d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// Visualizer_getConfig() 1563d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent//---------------------------------------------------------------------------- 1573d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// Purpose: Get input and output audio configuration. 1583d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// 1593d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// Inputs: 1603d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// pContext: effect engine context 1613d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// pConfig: pointer to effect_config_t structure holding input and output 1623d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// configuration parameters 1633d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// 1643d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// Outputs: 1653d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent// 1663d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent//---------------------------------------------------------------------------- 1673d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent 1683d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurentvoid Visualizer_getConfig(VisualizerContext *pContext, effect_config_t *pConfig) 1693d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent{ 170a189a6883ee55cf62da1d7bf5bf5a8ab501938a4Glenn Kasten *pConfig = pContext->mConfig; 1713d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent} 1723d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent 1733d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent 1743d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent//---------------------------------------------------------------------------- 175da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// Visualizer_init() 176da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//---------------------------------------------------------------------------- 177da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// Purpose: Initialize engine with default configuration. 178da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 179da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// Inputs: 180da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// pContext: effect engine context 181da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 182da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// Outputs: 183da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 184da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//---------------------------------------------------------------------------- 185da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 186da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentint Visualizer_init(VisualizerContext *pContext) 187da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{ 188da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ; 189e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent pContext->mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; 190e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent pContext->mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 191da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.inputCfg.samplingRate = 44100; 192da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.inputCfg.bufferProvider.getBuffer = NULL; 193da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.inputCfg.bufferProvider.releaseBuffer = NULL; 194da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.inputCfg.bufferProvider.cookie = NULL; 195da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.inputCfg.mask = EFFECT_CONFIG_ALL; 196da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE; 197e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent pContext->mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; 198e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent pContext->mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 199da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.outputCfg.samplingRate = 44100; 200da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.outputCfg.bufferProvider.getBuffer = NULL; 201da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.outputCfg.bufferProvider.releaseBuffer = NULL; 202da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.outputCfg.bufferProvider.cookie = NULL; 203da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mConfig.outputCfg.mask = EFFECT_CONFIG_ALL; 204da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 20509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi // visualization initialization 206da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mCaptureSize = VISUALIZER_CAPTURE_SIZE_MAX; 2073476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi pContext->mScalingMode = VISUALIZER_SCALING_MODE_NORMALIZED; 208da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 20909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi // measurement initialization 210e541269be94f3a1072932d51537905b120ef4733Andy Hung pContext->mChannelCount = 211e541269be94f3a1072932d51537905b120ef4733Andy Hung audio_channel_count_from_out_mask(pContext->mConfig.inputCfg.channels); 21209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pContext->mMeasurementMode = MEASUREMENT_MODE_NONE; 21309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pContext->mMeasurementWindowSizeInBuffers = MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS; 21409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pContext->mMeasurementBufferIdx = 0; 2156fbc9ef121b081f888163190bb13cbac31599900Jean-Michel Trivi for (uint32_t i=0 ; i<pContext->mMeasurementWindowSizeInBuffers ; i++) { 21609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pContext->mPastMeasurements[i].mIsValid = false; 21709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pContext->mPastMeasurements[i].mPeakU16 = 0; 21809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pContext->mPastMeasurements[i].mRmsSquared = 0; 21909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } 22009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi 2213d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent Visualizer_setConfig(pContext, &pContext->mConfig); 222da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 223da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return 0; 224da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} 225da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 226da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 227da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//--- Effect Library Interface Implementation 228da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 229da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 2305e92a7861196ddae14638d4b7a63fc4892b7ef59Glenn Kastenint VisualizerLib_Create(const effect_uuid_t *uuid, 2317cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn int32_t /*sessionId*/, 2327cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn int32_t /*ioId*/, 233e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent effect_handle_t *pHandle) { 234da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent int ret; 235da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent int i; 236da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 237e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent if (pHandle == NULL || uuid == NULL) { 238da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 239da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 240da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 241da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (memcmp(uuid, &gVisualizerDescriptor.uuid, sizeof(effect_uuid_t)) != 0) { 242da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 243da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 244da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 245da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent VisualizerContext *pContext = new VisualizerContext; 246da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 247da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mItfe = &gVisualizerInterface; 248da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mState = VISUALIZER_STATE_UNINITIALIZED; 249da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 250da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent ret = Visualizer_init(pContext); 251da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (ret < 0) { 2525ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("VisualizerLib_Create() init failed"); 253da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent delete pContext; 254da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return ret; 255da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 256da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 257e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent *pHandle = (effect_handle_t)pContext; 258da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 259da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mState = VISUALIZER_STATE_INITIALIZED; 260da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 2613856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("VisualizerLib_Create %p", pContext); 262da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 263da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return 0; 264da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 265da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} 266da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 267e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurentint VisualizerLib_Release(effect_handle_t handle) { 268e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent VisualizerContext * pContext = (VisualizerContext *)handle; 269da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 2703856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("VisualizerLib_Release %p", handle); 271da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pContext == NULL) { 272da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 273da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 274da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mState = VISUALIZER_STATE_UNINITIALIZED; 275da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent delete pContext; 276da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 277da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return 0; 278da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} 279da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 2805e92a7861196ddae14638d4b7a63fc4892b7ef59Glenn Kastenint VisualizerLib_GetDescriptor(const effect_uuid_t *uuid, 281e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent effect_descriptor_t *pDescriptor) { 282e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 283e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent if (pDescriptor == NULL || uuid == NULL){ 2843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("VisualizerLib_GetDescriptor() called with NULL pointer"); 285e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent return -EINVAL; 286e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent } 287e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 288e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent if (memcmp(uuid, &gVisualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0) { 289a189a6883ee55cf62da1d7bf5bf5a8ab501938a4Glenn Kasten *pDescriptor = gVisualizerDescriptor; 290e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent return 0; 291e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent } 292e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 293e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent return -EINVAL; 294e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent} /* end VisualizerLib_GetDescriptor */ 295e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 296da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 297da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent//--- Effect Control Interface Implementation 298da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent// 299da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 300da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentstatic inline int16_t clamp16(int32_t sample) 301da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{ 302da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if ((sample>>15) ^ (sample>>31)) 303da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent sample = 0x7FFF ^ (sample>>31); 304da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return sample; 305da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} 306da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 307e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurentint Visualizer_process( 308e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent effect_handle_t self,audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) 309da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent{ 310e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent VisualizerContext * pContext = (VisualizerContext *)self; 311da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 312da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pContext == NULL) { 313da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 314da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 315da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 316da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (inBuffer == NULL || inBuffer->raw == NULL || 317da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent outBuffer == NULL || outBuffer->raw == NULL || 318da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent inBuffer->frameCount != outBuffer->frameCount || 319da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent inBuffer->frameCount == 0) { 320da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 321da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 322da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 32309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi // perform measurements if needed 32409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi if (pContext->mMeasurementMode & MEASUREMENT_MODE_PEAK_RMS) { 32509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi // find the peak and RMS squared for the new buffer 32609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi uint32_t inIdx; 32709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi int16_t maxSample = 0; 32809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi float rmsSqAcc = 0; 32909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi for (inIdx = 0 ; inIdx < inBuffer->frameCount * pContext->mChannelCount ; inIdx++) { 33009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi if (inBuffer->s16[inIdx] > maxSample) { 33109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi maxSample = inBuffer->s16[inIdx]; 33209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } else if (-inBuffer->s16[inIdx] > maxSample) { 33309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi maxSample = -inBuffer->s16[inIdx]; 33409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } 33509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi rmsSqAcc += (inBuffer->s16[inIdx] * inBuffer->s16[inIdx]); 33609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } 33709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi // store the measurement 33809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pContext->mPastMeasurements[pContext->mMeasurementBufferIdx].mPeakU16 = (uint16_t)maxSample; 33909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pContext->mPastMeasurements[pContext->mMeasurementBufferIdx].mRmsSquared = 34009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi rmsSqAcc / (inBuffer->frameCount * pContext->mChannelCount); 34109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pContext->mPastMeasurements[pContext->mMeasurementBufferIdx].mIsValid = true; 34209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi if (++pContext->mMeasurementBufferIdx >= pContext->mMeasurementWindowSizeInBuffers) { 34309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pContext->mMeasurementBufferIdx = 0; 34409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } 34509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } 34609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi 347da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent // all code below assumes stereo 16 bit PCM output and input 3483476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi int32_t shift; 3493476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi 3503476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi if (pContext->mScalingMode == VISUALIZER_SCALING_MODE_NORMALIZED) { 3513476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi // derive capture scaling factor from peak value in current buffer 3523476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi // this gives more interesting captures for display. 3533476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi shift = 32; 3543476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi int len = inBuffer->frameCount * 2; 3553476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi for (int i = 0; i < len; i++) { 3563476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi int32_t smp = inBuffer->s16[i]; 3573476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi if (smp < 0) smp = -smp - 1; // take care to keep the max negative in range 3583476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi int32_t clz = __builtin_clz(smp); 3593476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi if (shift > clz) shift = clz; 3603476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi } 3613476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi // A maximum amplitude signal will have 17 leading zeros, which we want to 3623476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi // translate to a shift of 8 (for converting 16 bit to 8 bit) 3633476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi shift = 25 - shift; 3643476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi // Never scale by less than 8 to avoid returning unaltered PCM signal. 3653476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi if (shift < 3) { 3663476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi shift = 3; 3673476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi } 3683476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi // add one to combine the division by 2 needed after summing left and right channels below 3693476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi shift++; 3703476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi } else { 3713476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi assert(pContext->mScalingMode == VISUALIZER_SCALING_MODE_AS_PLAYED); 3723476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi shift = 9; 3730e75f0f0147baeb6277c3dcc4403cf0201155a99Eric Laurent } 3740e75f0f0147baeb6277c3dcc4403cf0201155a99Eric Laurent 375da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent uint32_t captIdx; 376da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent uint32_t inIdx; 377f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen uint8_t *buf = pContext->mCaptureBuf; 378da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent for (inIdx = 0, captIdx = pContext->mCaptureIdx; 379f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen inIdx < inBuffer->frameCount; 380da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent inIdx++, captIdx++) { 381f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen if (captIdx >= CAPTURE_BUF_SIZE) { 382f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen // wrap around 383f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen captIdx = 0; 384f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen } 385da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent int32_t smp = inBuffer->s16[2 * inIdx] + inBuffer->s16[2 * inIdx + 1]; 38664c3bdea8cba454d4404baded584ea0f0611b3eeMarco Nelissen smp = smp >> shift; 387da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent buf[captIdx] = ((uint8_t)smp)^0x80; 388da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 389da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 390f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen // XXX the following two should really be atomic, though it probably doesn't 391f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen // matter much for visualization purposes 392f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pContext->mCaptureIdx = captIdx; 393f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen // update last buffer update time stamp 394f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen if (clock_gettime(CLOCK_MONOTONIC, &pContext->mBufferUpdateTime) < 0) { 395f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pContext->mBufferUpdateTime.tv_sec = 0; 396da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 397da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 398da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (inBuffer->raw != outBuffer->raw) { 399da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pContext->mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) { 400da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent for (size_t i = 0; i < outBuffer->frameCount*2; i++) { 401da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent outBuffer->s16[i] = clamp16(outBuffer->s16[i] + inBuffer->s16[i]); 402da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 403da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } else { 404da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent memcpy(outBuffer->raw, inBuffer->raw, outBuffer->frameCount * 2 * sizeof(int16_t)); 405da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 406da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 407f997cabca292d70d078ae828e21c28e6df62995fEric Laurent if (pContext->mState != VISUALIZER_STATE_ACTIVE) { 408f997cabca292d70d078ae828e21c28e6df62995fEric Laurent return -ENODATA; 409f997cabca292d70d078ae828e21c28e6df62995fEric Laurent } 410da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return 0; 411da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} // end Visualizer_process 412da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 413e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurentint Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, 41425f4395b932fa9859a6e91ba77c5d20d009da64aEric Laurent void *pCmdData, uint32_t *replySize, void *pReplyData) { 415da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 416e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent VisualizerContext * pContext = (VisualizerContext *)self; 417da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent int retsize; 418da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 419da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pContext == NULL || pContext->mState == VISUALIZER_STATE_UNINITIALIZED) { 420da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 421da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 422da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 4237cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn// ALOGV("Visualizer_command command %" PRIu32 " cmdSize %" PRIu32, cmdCode, cmdSize); 424da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 425da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent switch (cmdCode) { 426da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_INIT: 427da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pReplyData == NULL || *replySize != sizeof(int)) { 428da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 429da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 430da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *(int *) pReplyData = Visualizer_init(pContext); 431da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent break; 4323d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent case EFFECT_CMD_SET_CONFIG: 433da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) 434da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent || pReplyData == NULL || *replySize != sizeof(int)) { 435da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 436da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 4373d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent *(int *) pReplyData = Visualizer_setConfig(pContext, 438da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent (effect_config_t *) pCmdData); 439da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent break; 4403d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent case EFFECT_CMD_GET_CONFIG: 4413d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent if (pReplyData == NULL || 4423d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent *replySize != sizeof(effect_config_t)) { 4433d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent return -EINVAL; 4443d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent } 4453d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent Visualizer_getConfig(pContext, (effect_config_t *)pReplyData); 4463d5188bd6abe55898f10a0edf3c05aff8aa2ef67Eric Laurent break; 447da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_RESET: 448da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent Visualizer_reset(pContext); 449da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent break; 450da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_ENABLE: 451da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pReplyData == NULL || *replySize != sizeof(int)) { 452da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 453da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 454da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pContext->mState != VISUALIZER_STATE_INITIALIZED) { 455da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -ENOSYS; 456da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 457da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mState = VISUALIZER_STATE_ACTIVE; 4583856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("EFFECT_CMD_ENABLE() OK"); 459da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *(int *)pReplyData = 0; 460da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent break; 461da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_DISABLE: 462da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pReplyData == NULL || *replySize != sizeof(int)) { 463da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 464da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 465da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pContext->mState != VISUALIZER_STATE_ACTIVE) { 466da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -ENOSYS; 467da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 468da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pContext->mState = VISUALIZER_STATE_INITIALIZED; 4693856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("EFFECT_CMD_DISABLE() OK"); 470da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *(int *)pReplyData = 0; 471da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent break; 472da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_GET_PARAM: { 473da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pCmdData == NULL || 474da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent cmdSize != (int)(sizeof(effect_param_t) + sizeof(uint32_t)) || 475da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pReplyData == NULL || 476da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *replySize < (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint32_t))) { 477da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 478da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 479da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(uint32_t)); 480da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent effect_param_t *p = (effect_param_t *)pReplyData; 481da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent p->status = 0; 482da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *replySize = sizeof(effect_param_t) + sizeof(uint32_t); 4833476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi if (p->psize != sizeof(uint32_t)) { 484da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent p->status = -EINVAL; 485da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent break; 486da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 4873476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi switch (*(uint32_t *)p->data) { 4883476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi case VISUALIZER_PARAM_CAPTURE_SIZE: 4897cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn ALOGV("get mCaptureSize = %" PRIu32, pContext->mCaptureSize); 4903476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi *((uint32_t *)p->data + 1) = pContext->mCaptureSize; 4913476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi p->vsize = sizeof(uint32_t); 4923476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi *replySize += sizeof(uint32_t); 4933476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi break; 4943476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi case VISUALIZER_PARAM_SCALING_MODE: 4957cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn ALOGV("get mScalingMode = %" PRIu32, pContext->mScalingMode); 4963476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi *((uint32_t *)p->data + 1) = pContext->mScalingMode; 4973476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi p->vsize = sizeof(uint32_t); 4983476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi *replySize += sizeof(uint32_t); 4993476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi break; 50009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi case VISUALIZER_PARAM_MEASUREMENT_MODE: 5017cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn ALOGV("get mMeasurementMode = %" PRIu32, pContext->mMeasurementMode); 50209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi *((uint32_t *)p->data + 1) = pContext->mMeasurementMode; 50309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi p->vsize = sizeof(uint32_t); 50409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi *replySize += sizeof(uint32_t); 50509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi break; 5063476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi default: 5073476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi p->status = -EINVAL; 5083476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi } 509da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } break; 510da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_SET_PARAM: { 511da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pCmdData == NULL || 512da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent cmdSize != (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint32_t)) || 513da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent pReplyData == NULL || *replySize != sizeof(int32_t)) { 514da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 515da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 516da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *(int32_t *)pReplyData = 0; 517da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent effect_param_t *p = (effect_param_t *)pCmdData; 5183476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi if (p->psize != sizeof(uint32_t) || p->vsize != sizeof(uint32_t)) { 5193476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi *(int32_t *)pReplyData = -EINVAL; 5203476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi break; 5213476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi } 5223476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi switch (*(uint32_t *)p->data) { 5233476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi case VISUALIZER_PARAM_CAPTURE_SIZE: 5243476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi pContext->mCaptureSize = *((uint32_t *)p->data + 1); 5257cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn ALOGV("set mCaptureSize = %" PRIu32, pContext->mCaptureSize); 5263476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi break; 5273476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi case VISUALIZER_PARAM_SCALING_MODE: 5283476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi pContext->mScalingMode = *((uint32_t *)p->data + 1); 5297cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn ALOGV("set mScalingMode = %" PRIu32, pContext->mScalingMode); 5303476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi break; 531f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen case VISUALIZER_PARAM_LATENCY: 532f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pContext->mLatency = *((uint32_t *)p->data + 1); 5337cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn ALOGV("set mLatency = %" PRIu32, pContext->mLatency); 534f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen break; 53509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi case VISUALIZER_PARAM_MEASUREMENT_MODE: 53609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pContext->mMeasurementMode = *((uint32_t *)p->data + 1); 5377cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn ALOGV("set mMeasurementMode = %" PRIu32, pContext->mMeasurementMode); 53809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi break; 5393476de62fb10e76412452ef4c6bd71936c9f7db1Jean-Michel Trivi default: 540da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent *(int32_t *)pReplyData = -EINVAL; 541da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 542da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } break; 543da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_SET_DEVICE: 544da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_SET_VOLUME: 545da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent case EFFECT_CMD_SET_AUDIO_MODE: 546da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent break; 547da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 548da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 549abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica case VISUALIZER_CMD_CAPTURE: { 5507cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn uint32_t captureSize = pContext->mCaptureSize; 551abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica if (pReplyData == NULL || *replySize != captureSize) { 5527cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn ALOGV("VISUALIZER_CMD_CAPTURE() error *replySize %" PRIu32 " captureSize %" PRIu32, 553abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica *replySize, captureSize); 554da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 555da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 556da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent if (pContext->mState == VISUALIZER_STATE_ACTIVE) { 55709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi const uint32_t deltaMs = Visualizer_getDeltaTimeMsFromUpdatedTime(pContext); 558f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen 559f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen // if audio framework has stopped playing audio although the effect is still 560f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen // active we must clear the capture buffer to return silence 561f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen if ((pContext->mLastCaptureIdx == pContext->mCaptureIdx) && 562abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica (pContext->mBufferUpdateTime.tv_sec != 0) && 563abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica (deltaMs > MAX_STALL_TIME_MS)) { 564f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen ALOGV("capture going to idle"); 565f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pContext->mBufferUpdateTime.tv_sec = 0; 566abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica memset(pReplyData, 0x80, captureSize); 567abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica } else { 568abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica int32_t latencyMs = pContext->mLatency; 569abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica latencyMs -= deltaMs; 570abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica if (latencyMs < 0) { 571abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica latencyMs = 0; 572f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen } 573abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica const uint32_t deltaSmpl = 574abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica pContext->mConfig.inputCfg.samplingRate * latencyMs / 1000; 575abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica int32_t capturePoint = pContext->mCaptureIdx - captureSize - deltaSmpl; 576abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica 577abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica if (capturePoint < 0) { 5787cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn uint32_t size = -capturePoint; 579abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica if (size > captureSize) { 580abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica size = captureSize; 581abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica } 582abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica memcpy(pReplyData, 583abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica pContext->mCaptureBuf + CAPTURE_BUF_SIZE + capturePoint, 584abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica size); 585abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica pReplyData = (char *)pReplyData + size; 586abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica captureSize -= size; 587abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica capturePoint = 0; 588abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica } 589abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica memcpy(pReplyData, 590abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica pContext->mCaptureBuf + capturePoint, 591abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica captureSize); 592f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen } 593abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica 594f06c2ed50e1db871ae9eb2bd15a196064f8c278cMarco Nelissen pContext->mLastCaptureIdx = pContext->mCaptureIdx; 595da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } else { 596abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica memset(pReplyData, 0x80, captureSize); 597da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 5983df40a093d8d3d211f693e0e3ef4076750cabfeaEric Laurent 599abb7b17613fff41433cda94207eb535c9fed8fbaRyszard Grzesica } break; 600da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 60109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi case VISUALIZER_CMD_MEASURE: { 60209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi uint16_t peakU16 = 0; 60309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi float sumRmsSquared = 0.0f; 60409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi uint8_t nbValidMeasurements = 0; 60509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi // reset measurements if last measurement was too long ago (which implies stored 60609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi // measurements aren't relevant anymore and shouldn't bias the new one) 60709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi const int32_t delayMs = Visualizer_getDeltaTimeMsFromUpdatedTime(pContext); 60809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi if (delayMs > DISCARD_MEASUREMENTS_TIME_MS) { 6097cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn ALOGV("Discarding measurements, last measurement is %" PRId32 "ms old", delayMs); 6106fbc9ef121b081f888163190bb13cbac31599900Jean-Michel Trivi for (uint32_t i=0 ; i<pContext->mMeasurementWindowSizeInBuffers ; i++) { 61109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pContext->mPastMeasurements[i].mIsValid = false; 61209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pContext->mPastMeasurements[i].mPeakU16 = 0; 61309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pContext->mPastMeasurements[i].mRmsSquared = 0; 61409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } 61509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pContext->mMeasurementBufferIdx = 0; 61609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } else { 61709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi // only use actual measurements, otherwise the first RMS measure happening before 61809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi // MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS have been played will always be artificially 61909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi // low 6206fbc9ef121b081f888163190bb13cbac31599900Jean-Michel Trivi for (uint32_t i=0 ; i < pContext->mMeasurementWindowSizeInBuffers ; i++) { 62109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi if (pContext->mPastMeasurements[i].mIsValid) { 62209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi if (pContext->mPastMeasurements[i].mPeakU16 > peakU16) { 62309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi peakU16 = pContext->mPastMeasurements[i].mPeakU16; 62409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } 6256fbc9ef121b081f888163190bb13cbac31599900Jean-Michel Trivi sumRmsSquared += pContext->mPastMeasurements[i].mRmsSquared; 62609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi nbValidMeasurements++; 62709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } 62809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } 62909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } 63009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi float rms = nbValidMeasurements == 0 ? 0.0f : sqrtf(sumRmsSquared / nbValidMeasurements); 63109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi int32_t* pIntReplyData = (int32_t*)pReplyData; 63209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi // convert from I16 sample values to mB and write results 63309647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi if (rms < 0.000016f) { 63409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pIntReplyData[MEASUREMENT_IDX_RMS] = -9600; //-96dB 63509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } else { 63609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pIntReplyData[MEASUREMENT_IDX_RMS] = (int32_t) (2000 * log10(rms / 32767.0f)); 63709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } 63809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi if (peakU16 == 0) { 63909647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pIntReplyData[MEASUREMENT_IDX_PEAK] = -9600; //-96dB 64009647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } else { 64109647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi pIntReplyData[MEASUREMENT_IDX_PEAK] = (int32_t) (2000 * log10(peakU16 / 32767.0f)); 64209647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } 6437cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn ALOGV("VISUALIZER_CMD_MEASURE peak=%" PRIu16 " (%" PRId32 "mB), rms=%.1f (%" PRId32 "mB)", 64409647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi peakU16, pIntReplyData[MEASUREMENT_IDX_PEAK], 64509647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi rms, pIntReplyData[MEASUREMENT_IDX_RMS]); 64609647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi } 64709647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi break; 64809647d29eaf429ce88c9c9709ff63dee62f2147aJean-Michel Trivi 649da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent default: 6507cb0e733210c2ce7dd2a7c9d32f6d83c4dab9656Mark Salyzyn ALOGW("Visualizer_command invalid command %" PRIu32, cmdCode); 651da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return -EINVAL; 652da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent } 653da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 654da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent return 0; 655da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent} 656da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 657e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent/* Effect Control Interface Implementation: get_descriptor */ 658e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurentint Visualizer_getDescriptor(effect_handle_t self, 659e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent effect_descriptor_t *pDescriptor) 660e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent{ 661e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent VisualizerContext * pContext = (VisualizerContext *) self; 662e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 663e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent if (pContext == NULL || pDescriptor == NULL) { 6643856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Visualizer_getDescriptor() invalid param"); 665e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent return -EINVAL; 666e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent } 667e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 668a189a6883ee55cf62da1d7bf5bf5a8ab501938a4Glenn Kasten *pDescriptor = gVisualizerDescriptor; 669e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 670e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent return 0; 671e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent} /* end Visualizer_getDescriptor */ 672e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 673e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent// effect_handle_t interface implementation for visualizer effect 674da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurentconst struct effect_interface_s gVisualizerInterface = { 675da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent Visualizer_process, 676e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent Visualizer_command, 677ba7b8f881a9b6b21803752326d2932a3bd42d7cfEric Laurent Visualizer_getDescriptor, 678ba7b8f881a9b6b21803752326d2932a3bd42d7cfEric Laurent NULL, 679da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent}; 680da7581b7b61b84f15e8d671c86fd117c322b009eEric Laurent 6817f16b197c76fbae9399242f055a7ee16dcd0fd6dMarco Nelissen// This is the only symbol that needs to be exported 6827f16b197c76fbae9399242f055a7ee16dcd0fd6dMarco Nelissen__attribute__ ((visibility ("default"))) 683e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurentaudio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { 684c9d8ea7f8f9a1ca8ecd266695e3cac423790b2f9synergydev .tag = AUDIO_EFFECT_LIBRARY_TAG, 685c9d8ea7f8f9a1ca8ecd266695e3cac423790b2f9synergydev .version = EFFECT_LIBRARY_API_VERSION, 686c9d8ea7f8f9a1ca8ecd266695e3cac423790b2f9synergydev .name = "Visualizer Library", 687c9d8ea7f8f9a1ca8ecd266695e3cac423790b2f9synergydev .implementor = "The Android Open Source Project", 688c9d8ea7f8f9a1ca8ecd266695e3cac423790b2f9synergydev .create_effect = VisualizerLib_Create, 689c9d8ea7f8f9a1ca8ecd266695e3cac423790b2f9synergydev .release_effect = VisualizerLib_Release, 690c9d8ea7f8f9a1ca8ecd266695e3cac423790b2f9synergydev .get_descriptor = VisualizerLib_GetDescriptor, 691e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent}; 692e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent 693e1315cf0b63b4c14a77046519e6b01f6f60d74b0Eric Laurent}; // extern "C" 694