EffectLoudnessEnhancer.cpp revision 9803acb6b2c1b9c01444e0c8c0124adbe9a7157a
16cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi/* 26cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * Copyright (C) 2013 The Android Open Source Project 36cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * 46cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License"); 56cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * you may not use this file except in compliance with the License. 66cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * You may obtain a copy of the License at 76cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * 86cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * http://www.apache.org/licenses/LICENSE-2.0 96cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * 106cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software 116cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS, 126cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * See the License for the specific language governing permissions and 146cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * limitations under the License. 156cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi */ 166cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 176cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#define LOG_TAG "EffectLE" 186cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//#define LOG_NDEBUG 0 196cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include <cutils/log.h> 206cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include <assert.h> 216cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include <stdlib.h> 226cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include <string.h> 236cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include <new> 246cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include <time.h> 256cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include <math.h> 266cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include <audio_effects/effect_loudnessenhancer.h> 276cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include "dsp/core/dynamic_range_compression.h" 286cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 296cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviextern "C" { 306cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 316cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// effect_handle_t interface implementation for LE effect 326cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviextern const struct effect_interface_s gLEInterface; 336cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 346cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// AOSP Loudness Enhancer UUID: fa415329-2034-4bea-b5dc-5b381c8d1e2c 356cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviconst effect_descriptor_t gLEDescriptor = { 366cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi {0xfe3199be, 0xaed0, 0x413f, 0x87bb, {0x11, 0x26, 0x0e, 0xb6, 0x3c, 0xf1}}, // type 376cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi {0xfa415329, 0x2034, 0x4bea, 0xb5dc, {0x5b, 0x38, 0x1c, 0x8d, 0x1e, 0x2c}}, // uuid 386cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi EFFECT_CONTROL_API_VERSION, 396cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST), 406cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 0, // TODO 416cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1, 426cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi "Loudness Enhancer", 436cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi "The Android Open Source Project", 446cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}; 456cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 466cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivienum le_state_e { 476cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LOUDNESS_ENHANCER_STATE_UNINITIALIZED, 486cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LOUDNESS_ENHANCER_STATE_INITIALIZED, 496cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LOUDNESS_ENHANCER_STATE_ACTIVE, 506cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}; 516cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 526cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivistruct LoudnessEnhancerContext { 536cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi const struct effect_interface_s *mItfe; 546cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi effect_config_t mConfig; 556cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi uint8_t mState; 566cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi int32_t mTargetGainmB;// target gain in mB 576cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi // in this implementation, there is no coupling between the compression on the left and right 586cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi // channels 59cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi le_fx::AdaptiveDynamicRangeCompression* mCompressor; 606cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}; 616cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 626cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// 636cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//--- Local functions (not directly used by effect interface) 646cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// 656cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 666cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivivoid LE_reset(LoudnessEnhancerContext *pContext) 676cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi{ 686cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGV(" > LE_reset(%p)", pContext); 696cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 70cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi if (pContext->mCompressor != NULL) { 716cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi float targetAmp = pow(10, pContext->mTargetGainmB/2000.0f); // mB to linear amplification 726cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGV("LE_reset(): Target gain=%dmB <=> factor=%.2fX", pContext->mTargetGainmB, targetAmp); 73cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi pContext->mCompressor->Initialize(targetAmp, pContext->mConfig.inputCfg.samplingRate); 746cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } else { 756cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGE("LE_reset(%p): null compressors, can't apply target gain", pContext); 766cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 776cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} 786cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 796cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivistatic inline int16_t clamp16(int32_t sample) 806cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi{ 816cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if ((sample>>15) ^ (sample>>31)) 826cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi sample = 0x7FFF ^ (sample>>31); 836cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return sample; 846cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} 856cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 866cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//---------------------------------------------------------------------------- 876cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// LE_setConfig() 886cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//---------------------------------------------------------------------------- 896cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// Purpose: Set input and output audio configuration. 906cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// 916cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// Inputs: 926cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// pContext: effect engine context 936cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// pConfig: pointer to effect_config_t structure holding input and output 946cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// configuration parameters 956cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// 966cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// Outputs: 976cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// 986cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//---------------------------------------------------------------------------- 996cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1006cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviint LE_setConfig(LoudnessEnhancerContext *pContext, effect_config_t *pConfig) 1016cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi{ 1026cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGV("LE_setConfig(%p)", pContext); 1036cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1046cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pConfig->inputCfg.samplingRate != pConfig->outputCfg.samplingRate) return -EINVAL; 1056cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pConfig->inputCfg.channels != pConfig->outputCfg.channels) return -EINVAL; 1066cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pConfig->inputCfg.format != pConfig->outputCfg.format) return -EINVAL; 1076cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pConfig->inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) return -EINVAL; 1086cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_WRITE && 1096cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_ACCUMULATE) return -EINVAL; 1106cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pConfig->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL; 1116cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1126cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig = *pConfig; 1136cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1146cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LE_reset(pContext); 1156cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1166cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return 0; 1176cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} 1186cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1196cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1206cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//---------------------------------------------------------------------------- 1216cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// LE_getConfig() 1226cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//---------------------------------------------------------------------------- 1236cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// Purpose: Get input and output audio configuration. 1246cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// 1256cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// Inputs: 1266cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// pContext: effect engine context 1276cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// pConfig: pointer to effect_config_t structure holding input and output 1286cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// configuration parameters 1296cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// 1306cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// Outputs: 1316cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// 1326cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//---------------------------------------------------------------------------- 1336cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1346cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivivoid LE_getConfig(LoudnessEnhancerContext *pContext, effect_config_t *pConfig) 1356cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi{ 1366cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *pConfig = pContext->mConfig; 1376cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} 1386cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1396cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1406cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//---------------------------------------------------------------------------- 1416cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// LE_init() 1426cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//---------------------------------------------------------------------------- 1436cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// Purpose: Initialize engine with default configuration. 1446cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// 1456cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// Inputs: 1466cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// pContext: effect engine context 1476cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// 1486cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// Outputs: 1496cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// 1506cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//---------------------------------------------------------------------------- 1516cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1526cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviint LE_init(LoudnessEnhancerContext *pContext) 1536cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi{ 1546cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGV("LE_init(%p)", pContext); 1556cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1566cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ; 1576cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; 1586cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 1596cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig.inputCfg.samplingRate = 44100; 1606cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig.inputCfg.bufferProvider.getBuffer = NULL; 1616cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig.inputCfg.bufferProvider.releaseBuffer = NULL; 1626cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig.inputCfg.bufferProvider.cookie = NULL; 1636cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig.inputCfg.mask = EFFECT_CONFIG_ALL; 1646cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE; 1656cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; 1666cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 1676cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig.outputCfg.samplingRate = 44100; 1686cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig.outputCfg.bufferProvider.getBuffer = NULL; 1696cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig.outputCfg.bufferProvider.releaseBuffer = NULL; 1706cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig.outputCfg.bufferProvider.cookie = NULL; 1716cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mConfig.outputCfg.mask = EFFECT_CONFIG_ALL; 1726cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1736cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mTargetGainmB = LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB; 1746cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi float targetAmp = pow(10, pContext->mTargetGainmB/2000.0f); // mB to linear amplification 1756cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGV("LE_init(): Target gain=%dmB <=> factor=%.2fX", pContext->mTargetGainmB, targetAmp); 1766cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 177cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi if (pContext->mCompressor == NULL) { 178cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi pContext->mCompressor = new le_fx::AdaptiveDynamicRangeCompression(); 179cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi pContext->mCompressor->Initialize(targetAmp, pContext->mConfig.inputCfg.samplingRate); 1806cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 1816cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1826cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LE_setConfig(pContext, &pContext->mConfig); 1836cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1846cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return 0; 1856cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} 1866cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1876cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// 1886cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//--- Effect Library Interface Implementation 1896cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// 1906cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1916cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviint LELib_Create(const effect_uuid_t *uuid, 1926cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi int32_t sessionId, 1936cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi int32_t ioId, 1946cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi effect_handle_t *pHandle) { 1956cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGV("LELib_Create()"); 1966cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi int ret; 1976cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi int i; 1986cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1996cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pHandle == NULL || uuid == NULL) { 2006cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 2016cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 2026cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2036cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (memcmp(uuid, &gLEDescriptor.uuid, sizeof(effect_uuid_t)) != 0) { 2046cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 2056cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 2066cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2076cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LoudnessEnhancerContext *pContext = new LoudnessEnhancerContext; 2086cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2096cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mItfe = &gLEInterface; 2106cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mState = LOUDNESS_ENHANCER_STATE_UNINITIALIZED; 2116cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 212cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi pContext->mCompressor = NULL; 2136cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ret = LE_init(pContext); 2146cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (ret < 0) { 2156cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGW("LELib_Create() init failed"); 2166cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi delete pContext; 2176cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return ret; 2186cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 2196cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2206cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *pHandle = (effect_handle_t)pContext; 2216cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2226cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mState = LOUDNESS_ENHANCER_STATE_INITIALIZED; 2236cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2246cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGV(" LELib_Create context is %p", pContext); 2256cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2266cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return 0; 2276cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2286cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} 2296cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2306cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviint LELib_Release(effect_handle_t handle) { 2316cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LoudnessEnhancerContext * pContext = (LoudnessEnhancerContext *)handle; 2326cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2336cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGV("LELib_Release %p", handle); 2346cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pContext == NULL) { 2356cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 2366cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 2376cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mState = LOUDNESS_ENHANCER_STATE_UNINITIALIZED; 238cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi if (pContext->mCompressor != NULL) { 239cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi delete pContext->mCompressor; 240cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi pContext->mCompressor = NULL; 2416cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 2426cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi delete pContext; 2436cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2446cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return 0; 2456cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} 2466cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2476cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviint LELib_GetDescriptor(const effect_uuid_t *uuid, 2486cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi effect_descriptor_t *pDescriptor) { 2496cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2506cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pDescriptor == NULL || uuid == NULL){ 2516cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGV("LELib_GetDescriptor() called with NULL pointer"); 2526cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 2536cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 2546cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2556cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (memcmp(uuid, &gLEDescriptor.uuid, sizeof(effect_uuid_t)) == 0) { 2566cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *pDescriptor = gLEDescriptor; 2576cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return 0; 2586cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 2596cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2606cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 2616cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} /* end LELib_GetDescriptor */ 2626cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2636cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// 2646cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//--- Effect Control Interface Implementation 2656cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// 2666cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviint LE_process( 2676cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) 2686cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi{ 2696cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LoudnessEnhancerContext * pContext = (LoudnessEnhancerContext *)self; 2706cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2716cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pContext == NULL) { 2726cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 2736cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 2746cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2756cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (inBuffer == NULL || inBuffer->raw == NULL || 2766cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi outBuffer == NULL || outBuffer->raw == NULL || 2776cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi inBuffer->frameCount != outBuffer->frameCount || 2786cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi inBuffer->frameCount == 0) { 2796cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 2806cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 2816cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2826cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi //ALOGV("LE about to process %d samples", inBuffer->frameCount); 2836cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi uint16_t inIdx; 2846cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi float inputAmp = pow(10, pContext->mTargetGainmB/2000.0f); 285cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi float leftSample, rightSample; 2866cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi for (inIdx = 0 ; inIdx < inBuffer->frameCount ; inIdx++) { 287cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi // makeup gain is applied on the input of the compressor 288cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi leftSample = inputAmp * (float)inBuffer->s16[2*inIdx]; 289cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi rightSample = inputAmp * (float)inBuffer->s16[2*inIdx +1]; 290cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi pContext->mCompressor->Compress(&leftSample, &rightSample); 291cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi inBuffer->s16[2*inIdx] = (int16_t) leftSample; 292cd0c4683947231a7d3dc7811bedb75c5a965103cJean-Michel Trivi inBuffer->s16[2*inIdx +1] = (int16_t) rightSample; 2936cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 2946cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 2956cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (inBuffer->raw != outBuffer->raw) { 2966cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pContext->mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) { 2976cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi for (size_t i = 0; i < outBuffer->frameCount*2; i++) { 2986cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi outBuffer->s16[i] = clamp16(outBuffer->s16[i] + inBuffer->s16[i]); 2996cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 3006cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } else { 3016cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi memcpy(outBuffer->raw, inBuffer->raw, outBuffer->frameCount * 2 * sizeof(int16_t)); 3026cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 3036cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 3046cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pContext->mState != LOUDNESS_ENHANCER_STATE_ACTIVE) { 3056cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -ENODATA; 3066cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 3076cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return 0; 3086cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} 3096cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 3106cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviint LE_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, 3116cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi void *pCmdData, uint32_t *replySize, void *pReplyData) { 3126cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 3136cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LoudnessEnhancerContext * pContext = (LoudnessEnhancerContext *)self; 3146cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi int retsize; 3156cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 3166cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pContext == NULL || pContext->mState == LOUDNESS_ENHANCER_STATE_UNINITIALIZED) { 3176cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 3186cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 3196cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 3206cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// ALOGV("LE_command command %d cmdSize %d",cmdCode, cmdSize); 3216cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi switch (cmdCode) { 3226cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi case EFFECT_CMD_INIT: 3236cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pReplyData == NULL || *replySize != sizeof(int)) { 3246cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 3256cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 3266cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *(int *) pReplyData = LE_init(pContext); 3276cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi break; 3286cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi case EFFECT_CMD_SET_CONFIG: 3296cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) 3306cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi || pReplyData == NULL || *replySize != sizeof(int)) { 3316cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 3326cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 3336cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *(int *) pReplyData = LE_setConfig(pContext, 3346cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi (effect_config_t *) pCmdData); 3356cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi break; 3366cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi case EFFECT_CMD_GET_CONFIG: 3376cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pReplyData == NULL || 3386cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *replySize != sizeof(effect_config_t)) { 3396cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 3406cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 3416cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LE_getConfig(pContext, (effect_config_t *)pReplyData); 3426cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi break; 3436cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi case EFFECT_CMD_RESET: 3446cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LE_reset(pContext); 3456cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi break; 3466cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi case EFFECT_CMD_ENABLE: 3476cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pReplyData == NULL || *replySize != sizeof(int)) { 3486cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 3496cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 3506cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pContext->mState != LOUDNESS_ENHANCER_STATE_INITIALIZED) { 3516cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -ENOSYS; 3526cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 3536cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mState = LOUDNESS_ENHANCER_STATE_ACTIVE; 3546cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGV("EFFECT_CMD_ENABLE() OK"); 3556cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *(int *)pReplyData = 0; 3566cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi break; 3576cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi case EFFECT_CMD_DISABLE: 3586cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pReplyData == NULL || *replySize != sizeof(int)) { 3596cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 3606cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 3616cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pContext->mState != LOUDNESS_ENHANCER_STATE_ACTIVE) { 3626cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -ENOSYS; 3636cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 3646cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mState = LOUDNESS_ENHANCER_STATE_INITIALIZED; 3656cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGV("EFFECT_CMD_DISABLE() OK"); 3666cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *(int *)pReplyData = 0; 3676cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi break; 3686cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi case EFFECT_CMD_GET_PARAM: { 3696cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pCmdData == NULL || 3706cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi cmdSize != (int)(sizeof(effect_param_t) + sizeof(uint32_t)) || 3716cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pReplyData == NULL || 3726cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *replySize < (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint32_t))) { 3736cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 3746cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 3756cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(uint32_t)); 3766cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi effect_param_t *p = (effect_param_t *)pReplyData; 3776cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi p->status = 0; 3786cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *replySize = sizeof(effect_param_t) + sizeof(uint32_t); 3796cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (p->psize != sizeof(uint32_t)) { 3806cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi p->status = -EINVAL; 3816cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi break; 3826cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 3836cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi switch (*(uint32_t *)p->data) { 3846cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi case LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB: 3856cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGV("get target gain(mB) = %d", pContext->mTargetGainmB); 3866cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *((int32_t *)p->data + 1) = pContext->mTargetGainmB; 3876cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi p->vsize = sizeof(int32_t); 3886cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *replySize += sizeof(int32_t); 3896cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi break; 3906cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi default: 3916cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi p->status = -EINVAL; 3926cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 3936cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } break; 3946cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi case EFFECT_CMD_SET_PARAM: { 3956cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pCmdData == NULL || 3966cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi cmdSize != (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint32_t)) || 3976cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pReplyData == NULL || *replySize != sizeof(int32_t)) { 3986cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 3996cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 4006cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *(int32_t *)pReplyData = 0; 4016cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi effect_param_t *p = (effect_param_t *)pCmdData; 4026cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (p->psize != sizeof(uint32_t) || p->vsize != sizeof(uint32_t)) { 4036cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *(int32_t *)pReplyData = -EINVAL; 4046cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi break; 4056cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 4066cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi switch (*(uint32_t *)p->data) { 4076cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi case LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB: 4086cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi pContext->mTargetGainmB = *((int32_t *)p->data + 1); 4096cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGV("set target gain(mB) = %d", pContext->mTargetGainmB); 4106cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LE_reset(pContext); // apply parameter update 4116cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi break; 4126cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi default: 4136cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *(int32_t *)pReplyData = -EINVAL; 4146cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 4156cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } break; 4166cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi case EFFECT_CMD_SET_DEVICE: 4176cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi case EFFECT_CMD_SET_VOLUME: 4186cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi case EFFECT_CMD_SET_AUDIO_MODE: 4196cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi break; 4206cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 4216cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi default: 4226cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGW("LE_command invalid command %d",cmdCode); 4236cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 4246cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 4256cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 4266cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return 0; 4276cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} 4286cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 4296cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi/* Effect Control Interface Implementation: get_descriptor */ 4306cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviint LE_getDescriptor(effect_handle_t self, 4316cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi effect_descriptor_t *pDescriptor) 4326cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi{ 4336cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LoudnessEnhancerContext * pContext = (LoudnessEnhancerContext *) self; 4346cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 4356cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (pContext == NULL || pDescriptor == NULL) { 4366cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGV("LE_getDescriptor() invalid param"); 4376cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return -EINVAL; 4386cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 4396cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 4406cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *pDescriptor = gLEDescriptor; 4416cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 4426cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return 0; 4436cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} /* end LE_getDescriptor */ 4446cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 4456cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// effect_handle_t interface implementation for DRC effect 4466cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviconst struct effect_interface_s gLEInterface = { 4476cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LE_process, 4486cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LE_command, 4496cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LE_getDescriptor, 4506cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi NULL, 4516cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}; 4526cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 4536cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi// This is the only symbol that needs to be exported 4546cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi__attribute__ ((visibility ("default"))) 4556cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Triviaudio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { 4569803acb6b2c1b9c01444e0c8c0124adbe9a7157asynergy dev .tag = AUDIO_EFFECT_LIBRARY_TAG, 4579803acb6b2c1b9c01444e0c8c0124adbe9a7157asynergy dev .version = EFFECT_LIBRARY_API_VERSION, 4589803acb6b2c1b9c01444e0c8c0124adbe9a7157asynergy dev .name = "Loudness Enhancer Library", 4599803acb6b2c1b9c01444e0c8c0124adbe9a7157asynergy dev .implementor = "The Android Open Source Project", 4609803acb6b2c1b9c01444e0c8c0124adbe9a7157asynergy dev .create_effect = LELib_Create, 4619803acb6b2c1b9c01444e0c8c0124adbe9a7157asynergy dev .release_effect = LELib_Release, 4629803acb6b2c1b9c01444e0c8c0124adbe9a7157asynergy dev .get_descriptor = LELib_GetDescriptor, 4636cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}; 4646cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 4656cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}; // extern "C" 4666cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 467