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