blob: 56cd247623dda7ca774223482a07d9a9be05ebbd [file] [log] [blame]
rago9f011fe2018-02-05 09:29:56 -08001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "EffectDP"
18//#define LOG_NDEBUG 0
19
20#include <assert.h>
21#include <math.h>
22#include <stdlib.h>
23#include <string.h>
24#include <time.h>
25#include <new>
26
27#include <log/log.h>
28
29#include <audio_effects/effect_dynamicsprocessing.h>
30#include <dsp/DPBase.h>
31
32//#define VERY_VERY_VERBOSE_LOGGING
33#ifdef VERY_VERY_VERBOSE_LOGGING
34#define ALOGVV ALOGV
35#else
36#define ALOGVV(a...) do { } while (false)
37#endif
38
39// union to hold command values
40using value_t = union {
41 int32_t i;
42 float f;
43};
44
45// effect_handle_t interface implementation for DP effect
46extern const struct effect_interface_s gDPInterface;
47
48// AOSP Dynamics Processing UUID: e0e6539b-1781-7261-676f-6d7573696340
49const effect_descriptor_t gDPDescriptor = {
50 {0x7261676f, 0x6d75, 0x7369, 0x6364, {0x28, 0xe2, 0xfd, 0x3a, 0xc3, 0x9e}}, // type
51 {0xe0e6539b, 0x1781, 0x7261, 0x676f, {0x6d, 0x75, 0x73, 0x69, 0x63, 0x40}}, // uuid
52 EFFECT_CONTROL_API_VERSION,
53 (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST),
54 0, // TODO
55 1,
56 "Dynamics Processing",
57 "The Android Open Source Project",
58};
59
60enum dp_state_e {
61 DYNAMICS_PROCESSING_STATE_UNINITIALIZED,
62 DYNAMICS_PROCESSING_STATE_INITIALIZED,
63 DYNAMICS_PROCESSING_STATE_ACTIVE,
64};
65
66struct DynamicsProcessingContext {
67 const struct effect_interface_s *mItfe;
68 effect_config_t mConfig;
69 uint8_t mState;
70
71 dp_fx::DPBase * mPDynamics; //the effect (or current effect)
72 int32_t mCurrentVariant;
73 float mPreferredFrameDuration;
74};
75
76// The value offset of an effect parameter is computed by rounding up
77// the parameter size to the next 32 bit alignment.
78static inline uint32_t computeParamVOffset(const effect_param_t *p) {
79 return ((p->psize + sizeof(int32_t) - 1) / sizeof(int32_t)) *
80 sizeof(int32_t);
81}
82
83//--- local function prototypes
84int DP_setParameter(DynamicsProcessingContext *pContext,
85 uint32_t paramSize,
86 void *pParam,
87 uint32_t valueSize,
88 void *pValue);
89int DP_getParameter(DynamicsProcessingContext *pContext,
90 uint32_t paramSize,
91 void *pParam,
92 uint32_t *pValueSize,
93 void *pValue);
94int DP_getParameterCmdSize(uint32_t paramSize,
95 void *pParam);
96void DP_expectedParamValueSizes(uint32_t paramSize,
97 void *pParam,
98 bool isSet,
99 uint32_t *pCmdSize,
100 uint32_t *pValueSize);
101//
102//--- Local functions (not directly used by effect interface)
103//
104
105void DP_reset(DynamicsProcessingContext *pContext)
106{
107 ALOGV("> DP_reset(%p)", pContext);
108 if (pContext->mPDynamics != NULL) {
109 pContext->mPDynamics->reset();
110 } else {
111 ALOGE("DP_reset(%p): null DynamicsProcessing", pContext);
112 }
113}
114
115//----------------------------------------------------------------------------
116// DP_setConfig()
117//----------------------------------------------------------------------------
118// Purpose: Set input and output audio configuration.
119//
120// Inputs:
121// pContext: effect engine context
122// pConfig: pointer to effect_config_t structure holding input and output
123// configuration parameters
124//
125// Outputs:
126//
127//----------------------------------------------------------------------------
128
129int DP_setConfig(DynamicsProcessingContext *pContext, effect_config_t *pConfig)
130{
131 ALOGV("DP_setConfig(%p)", pContext);
132
133 if (pConfig->inputCfg.samplingRate != pConfig->outputCfg.samplingRate) return -EINVAL;
134 if (pConfig->inputCfg.channels != pConfig->outputCfg.channels) return -EINVAL;
135 if (pConfig->inputCfg.format != pConfig->outputCfg.format) return -EINVAL;
136 if (pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_WRITE &&
137 pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_ACCUMULATE) return -EINVAL;
138 if (pConfig->inputCfg.format != AUDIO_FORMAT_PCM_FLOAT) return -EINVAL;
139
140 pContext->mConfig = *pConfig;
141
142 DP_reset(pContext);
143
144 return 0;
145}
146
147//----------------------------------------------------------------------------
148// DP_getConfig()
149//----------------------------------------------------------------------------
150// Purpose: Get input and output audio configuration.
151//
152// Inputs:
153// pContext: effect engine context
154// pConfig: pointer to effect_config_t structure holding input and output
155// configuration parameters
156//
157// Outputs:
158//
159//----------------------------------------------------------------------------
160
161void DP_getConfig(DynamicsProcessingContext *pContext, effect_config_t *pConfig)
162{
163 *pConfig = pContext->mConfig;
164}
165
166//----------------------------------------------------------------------------
167// DP_init()
168//----------------------------------------------------------------------------
169// Purpose: Initialize engine with default configuration.
170//
171// Inputs:
172// pContext: effect engine context
173//
174// Outputs:
175//
176//----------------------------------------------------------------------------
177
178int DP_init(DynamicsProcessingContext *pContext)
179{
180 ALOGV("DP_init(%p)", pContext);
181
182 pContext->mItfe = &gDPInterface;
183 pContext->mPDynamics = NULL;
184 pContext->mState = DYNAMICS_PROCESSING_STATE_UNINITIALIZED;
185
186 pContext->mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
187 pContext->mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
188 pContext->mConfig.inputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
189 pContext->mConfig.inputCfg.samplingRate = 44100;
190 pContext->mConfig.inputCfg.bufferProvider.getBuffer = NULL;
191 pContext->mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
192 pContext->mConfig.inputCfg.bufferProvider.cookie = NULL;
193 pContext->mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
194 pContext->mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
195 pContext->mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
196 pContext->mConfig.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
197 pContext->mConfig.outputCfg.samplingRate = 44100;
198 pContext->mConfig.outputCfg.bufferProvider.getBuffer = NULL;
199 pContext->mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
200 pContext->mConfig.outputCfg.bufferProvider.cookie = NULL;
201 pContext->mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
202
203 pContext->mCurrentVariant = -1; //none
204 pContext->mPreferredFrameDuration = 0; //none
205
206 DP_setConfig(pContext, &pContext->mConfig);
207 pContext->mState = DYNAMICS_PROCESSING_STATE_INITIALIZED;
208 return 0;
209}
210
211void DP_changeVariant(DynamicsProcessingContext *pContext, int newVariant) {
212 if (pContext->mPDynamics != NULL) {
213 delete pContext->mPDynamics;
214 pContext->mPDynamics = NULL;
215 }
216 switch(newVariant) {
217 //TODO: actually instantiate one of the variants. For now all instantiate the base;
218 default:
219 pContext->mCurrentVariant = newVariant;
220 pContext->mPDynamics = new dp_fx::DPBase();
221 break;
222 }
223}
224
225//
226//--- Effect Library Interface Implementation
227//
228
229int DPLib_Release(effect_handle_t handle) {
230 DynamicsProcessingContext * pContext = (DynamicsProcessingContext *)handle;
231
232 ALOGV("DPLib_Release %p", handle);
233 if (pContext == NULL) {
234 return -EINVAL;
235 }
236 delete pContext->mPDynamics;
237 delete pContext;
238
239 return 0;
240}
241
242int DPLib_Create(const effect_uuid_t *uuid,
243 int32_t sessionId __unused,
244 int32_t ioId __unused,
245 effect_handle_t *pHandle) {
246 ALOGV("DPLib_Create()");
247
248 if (pHandle == NULL || uuid == NULL) {
249 return -EINVAL;
250 }
251
252 if (memcmp(uuid, &gDPDescriptor.uuid, sizeof(*uuid)) != 0) {
253 return -EINVAL;
254 }
255
256 DynamicsProcessingContext *pContext = new DynamicsProcessingContext;
257 *pHandle = (effect_handle_t)pContext;
258 int ret = DP_init(pContext);
259 if (ret < 0) {
260 ALOGW("DPLib_Create() init failed");
261 DPLib_Release(*pHandle);
262 return ret;
263 }
264
265 ALOGV("DPLib_Create context is %p", pContext);
266 return 0;
267}
268
269int DPLib_GetDescriptor(const effect_uuid_t *uuid,
270 effect_descriptor_t *pDescriptor) {
271
272 if (pDescriptor == NULL || uuid == NULL){
273 ALOGE("DPLib_GetDescriptor() called with NULL pointer");
274 return -EINVAL;
275 }
276
277 if (memcmp(uuid, &gDPDescriptor.uuid, sizeof(*uuid)) == 0) {
278 *pDescriptor = gDPDescriptor;
279 return 0;
280 }
281
282 return -EINVAL;
283} /* end DPLib_GetDescriptor */
284
285//
286//--- Effect Control Interface Implementation
287//
288int DP_process(effect_handle_t self, audio_buffer_t *inBuffer,
289 audio_buffer_t *outBuffer) {
290 DynamicsProcessingContext * pContext = (DynamicsProcessingContext *)self;
291
292 if (pContext == NULL) {
293 ALOGE("DP_process() called with NULL context");
294 return -EINVAL;
295 }
296
297 if (inBuffer == NULL || inBuffer->raw == NULL ||
298 outBuffer == NULL || outBuffer->raw == NULL ||
299 inBuffer->frameCount != outBuffer->frameCount ||
300 inBuffer->frameCount == 0) {
301 ALOGE("inBuffer or outBuffer are NULL or have problems with frame count");
302 return -EINVAL;
303 }
304 if (pContext->mState != DYNAMICS_PROCESSING_STATE_ACTIVE) {
305 ALOGE("mState is not DYNAMICS_PROCESSING_STATE_ACTIVE. Current mState %d",
306 pContext->mState);
307 return -ENODATA;
308 }
309 //if dynamics exist...
310 if (pContext->mPDynamics != NULL) {
311 int32_t channelCount = (int32_t)audio_channel_count_from_out_mask(
312 pContext->mConfig.inputCfg.channels);
313 pContext->mPDynamics->processSamples(inBuffer->f32, inBuffer->f32,
314 inBuffer->frameCount * channelCount);
315 if (inBuffer->raw != outBuffer->raw) {
316 if (pContext->mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
317 for (size_t i = 0; i < outBuffer->frameCount * channelCount; i++) {
318 outBuffer->f32[i] += inBuffer->f32[i];
319 }
320 } else {
321 memcpy(outBuffer->raw, inBuffer->raw,
322 outBuffer->frameCount * channelCount * sizeof(float));
323 }
324 }
325 } else {
326 //do nothing. no effect created yet. warning.
327 ALOGW("Warning: no DynamicsProcessing engine available");
328 return -EINVAL;
329 }
330 return 0;
331}
332
333int DP_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
334 void *pCmdData, uint32_t *replySize, void *pReplyData) {
335
336 DynamicsProcessingContext * pContext = (DynamicsProcessingContext *)self;
337
338 if (pContext == NULL || pContext->mState == DYNAMICS_PROCESSING_STATE_UNINITIALIZED) {
339 ALOGE("DP_command() called with NULL context or uninitialized state.");
340 return -EINVAL;
341 }
342
343 ALOGV("DP_command command %d cmdSize %d",cmdCode, cmdSize);
344 switch (cmdCode) {
345 case EFFECT_CMD_INIT:
346 if (pReplyData == NULL || *replySize != sizeof(int)) {
347 ALOGE("EFFECT_CMD_INIT wrong replyData or repySize");
348 return -EINVAL;
349 }
350 *(int *) pReplyData = DP_init(pContext);
351 break;
352 case EFFECT_CMD_SET_CONFIG:
353 if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
354 || pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
355 ALOGE("EFFECT_CMD_SET_CONFIG error with pCmdData, cmdSize, pReplyData or replySize");
356 return -EINVAL;
357 }
358 *(int *) pReplyData = DP_setConfig(pContext,
359 (effect_config_t *) pCmdData);
360 break;
361 case EFFECT_CMD_GET_CONFIG:
362 if (pReplyData == NULL ||
363 *replySize != sizeof(effect_config_t)) {
364 ALOGE("EFFECT_CMD_GET_CONFIG wrong replyData or repySize");
365 return -EINVAL;
366 }
367 DP_getConfig(pContext, (effect_config_t *)pReplyData);
368 break;
369 case EFFECT_CMD_RESET:
370 DP_reset(pContext);
371 break;
372 case EFFECT_CMD_ENABLE:
373 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
374 ALOGE("EFFECT_CMD_ENABLE wrong replyData or repySize");
375 return -EINVAL;
376 }
377 if (pContext->mState != DYNAMICS_PROCESSING_STATE_INITIALIZED) {
378 ALOGE("EFFECT_CMD_ENABLE state not initialized");
379 *(int *)pReplyData = -ENOSYS;
380 } else {
381 pContext->mState = DYNAMICS_PROCESSING_STATE_ACTIVE;
382 ALOGV("EFFECT_CMD_ENABLE() OK");
383 *(int *)pReplyData = 0;
384 }
385 break;
386 case EFFECT_CMD_DISABLE:
387 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
388 ALOGE("EFFECT_CMD_DISABLE wrong replyData or repySize");
389 return -EINVAL;
390 }
391 if (pContext->mState != DYNAMICS_PROCESSING_STATE_ACTIVE) {
392 ALOGE("EFFECT_CMD_DISABLE state not active");
393 *(int *)pReplyData = -ENOSYS;
394 } else {
395 pContext->mState = DYNAMICS_PROCESSING_STATE_INITIALIZED;
396 ALOGV("EFFECT_CMD_DISABLE() OK");
397 *(int *)pReplyData = 0;
398 }
399 break;
400 case EFFECT_CMD_GET_PARAM: {
401 if (pCmdData == NULL || pReplyData == NULL || replySize == NULL) {
402 ALOGE("null pCmdData or pReplyData or replySize");
403 return -EINVAL;
404 }
405 effect_param_t *pEffectParam = (effect_param_t *) pCmdData;
406 uint32_t expectedCmdSize = DP_getParameterCmdSize(pEffectParam->psize,
407 pEffectParam->data);
408 if (cmdSize != expectedCmdSize || *replySize < expectedCmdSize) {
409 ALOGE("error cmdSize: %d, expetedCmdSize: %d, replySize: %d",
410 cmdSize, expectedCmdSize, *replySize);
411 return -EINVAL;
412 }
413
414 ALOGVV("DP_command expectedCmdSize: %d", expectedCmdSize);
415 memcpy(pReplyData, pCmdData, expectedCmdSize);
416 effect_param_t *p = (effect_param_t *)pReplyData;
417
418 uint32_t voffset = computeParamVOffset(p);
419
420 p->status = DP_getParameter(pContext,
421 p->psize,
422 p->data,
423 &p->vsize,
424 p->data + voffset);
425 *replySize = sizeof(effect_param_t) + voffset + p->vsize;
426
427 ALOGVV("DP_command replysize %u, status %d" , *replySize, p->status);
428 break;
429 }
430 case EFFECT_CMD_SET_PARAM: {
431 if (pCmdData == NULL ||
432 cmdSize < (sizeof(effect_param_t) + sizeof(int32_t) + sizeof(int32_t)) ||
433 pReplyData == NULL || replySize == NULL || *replySize != sizeof(int32_t)) {
434 ALOGE("\tLVM_ERROR : DynamicsProcessing cmdCode Case: "
435 "EFFECT_CMD_SET_PARAM: ERROR");
436 return -EINVAL;
437 }
438
439 effect_param_t * const p = (effect_param_t *) pCmdData;
440 const uint32_t voffset = computeParamVOffset(p);
441
442 *(int *)pReplyData = DP_setParameter(pContext,
443 p->psize,
444 (void *)p->data,
445 p->vsize,
446 p->data + voffset);
447 break;
448 }
449 case EFFECT_CMD_SET_DEVICE:
450 case EFFECT_CMD_SET_VOLUME:
451 case EFFECT_CMD_SET_AUDIO_MODE:
452 break;
453
454 default:
455 ALOGW("DP_command invalid command %d",cmdCode);
456 return -EINVAL;
457 }
458
459 return 0;
460}
461
462//register expected cmd size
463int DP_getParameterCmdSize(uint32_t paramSize,
464 void *pParam) {
465 if (paramSize < sizeof(int32_t)) {
466 return 0;
467 }
468 int32_t param = *(int32_t*)pParam;
469 switch(param) {
470 case DP_PARAM_GET_CHANNEL_COUNT: //paramcmd
471 case DP_PARAM_ENGINE_ARCHITECTURE:
472 //effect + param
473 return (int)(sizeof(effect_param_t) + sizeof(uint32_t));
474 case DP_PARAM_INPUT_GAIN: //paramcmd + param
475 case DP_PARAM_LIMITER:
476 case DP_PARAM_PRE_EQ:
477 case DP_PARAM_POST_EQ:
478 case DP_PARAM_MBC:
479 //effect + param
480 return (int)(sizeof(effect_param_t) + 2 * sizeof(uint32_t));
481 case DP_PARAM_PRE_EQ_BAND:
482 case DP_PARAM_POST_EQ_BAND:
483 case DP_PARAM_MBC_BAND:
484 return (int)(sizeof(effect_param_t) + 3 * sizeof(uint32_t));
485 }
486 return 0;
487}
488
489//helper function
490bool DP_checkSizesInt(uint32_t paramSize, uint32_t valueSize, uint32_t expectedParams,
491 uint32_t expectedValues) {
492 if (paramSize < expectedParams * sizeof(int32_t)) {
493 ALOGE("Invalid paramSize: %u expected %u", paramSize,
494 (uint32_t) (expectedParams * sizeof(int32_t)));
495 return false;
496 }
497 if (valueSize < expectedValues * sizeof(int32_t)) {
498 ALOGE("Invalid valueSize %u expected %u", valueSize,
499 (uint32_t)(expectedValues * sizeof(int32_t)));
500 return false;
501 }
502 return true;
503}
504
505static dp_fx::DPChannel* DP_getChannel(DynamicsProcessingContext *pContext,
506 int32_t channel) {
507 if (pContext->mPDynamics == NULL) {
508 return NULL;
509 }
510 dp_fx::DPChannel *pChannel = pContext->mPDynamics->getChannel(channel);
511 ALOGE_IF(pChannel == NULL, "DPChannel NULL. invalid channel %d", channel);
512 return pChannel;
513}
514
515static dp_fx::DPEq* DP_getEq(DynamicsProcessingContext *pContext, int32_t channel,
516 int32_t eqType) {
517 dp_fx::DPChannel * pChannel = DP_getChannel(pContext, channel);
518 if (pChannel == NULL) {
519 return NULL;
520 }
521 dp_fx::DPEq *pEq = eqType == DP_PARAM_PRE_EQ ? pChannel->getPreEq() : pChannel->getPostEq();
522 ALOGE_IF(pEq == NULL,"DPEq NULL invalid eq");
523 return pEq;
524}
525
526static dp_fx::DPEqBand* DP_getEqBand(DynamicsProcessingContext *pContext, int32_t channel,
527 int32_t eqType, int32_t band) {
528 dp_fx::DPEq *pEq = DP_getEq(pContext, channel, eqType);
529 if (pEq == NULL) {
530 return NULL;
531 }
532 dp_fx::DPEqBand *pEqBand = pEq->getBand(band);
533 ALOGE_IF(pEqBand == NULL, "DPEqBand NULL. invalid band %d", band);
534 return pEqBand;
535}
536
537static dp_fx::DPMbc* DP_getMbc(DynamicsProcessingContext *pContext, int32_t channel) {
538 dp_fx::DPChannel * pChannel = DP_getChannel(pContext, channel);
539 if (pChannel == NULL) {
540 return NULL;
541 }
542 dp_fx::DPMbc *pMbc = pChannel->getMbc();
543 ALOGE_IF(pMbc == NULL, "DPMbc NULL invalid MBC");
544 return pMbc;
545}
546
547static dp_fx::DPMbcBand* DP_getMbcBand(DynamicsProcessingContext *pContext, int32_t channel,
548 int32_t band) {
549 dp_fx::DPMbc *pMbc = DP_getMbc(pContext, channel);
550 if (pMbc == NULL) {
551 return NULL;
552 }
553 dp_fx::DPMbcBand *pMbcBand = pMbc->getBand(band);
554 ALOGE_IF(pMbcBand == NULL, "pMbcBand NULL. invalid band %d", band);
555 return pMbcBand;
556}
557
558int DP_getParameter(DynamicsProcessingContext *pContext,
559 uint32_t paramSize,
560 void *pParam,
561 uint32_t *pValueSize,
562 void *pValue) {
563 int status = 0;
564 int32_t *params = (int32_t *)pParam;
565 static_assert(sizeof(float) == sizeof(int32_t) && sizeof(float) == sizeof(value_t) &&
566 alignof(float) == alignof(int32_t) && alignof(float) == alignof(value_t),
567 "Size/alignment mismatch for float/int32_t/value_t");
568 value_t *values = reinterpret_cast<value_t*>(pValue);
569
570 ALOGVV("%s start", __func__);
571#ifdef VERY_VERY_VERBOSE_LOGGING
572 for (size_t i = 0; i < paramSize/sizeof(int32_t); i++) {
573 ALOGVV("Param[%zu] %d", i, params[i]);
574 }
575#endif
576 if (paramSize < sizeof(int32_t)) {
577 ALOGE("%s invalid paramSize: %u", __func__, paramSize);
578 return -EINVAL;
579 }
580 const int32_t command = params[0];
581 switch (command) {
582 case DP_PARAM_GET_CHANNEL_COUNT: {
583 if (!DP_checkSizesInt(paramSize,*pValueSize, 1 /*params*/, 1 /*values*/)) {
584 ALOGE("%s DP_PARAM_GET_CHANNEL_COUNT (cmd %d) invalid sizes.", __func__, command);
585 status = -EINVAL;
586 break;
587 }
588 *pValueSize = sizeof(uint32_t);
589 *(uint32_t *)pValue = (uint32_t)audio_channel_count_from_out_mask(
590 pContext->mConfig.inputCfg.channels);
591 ALOGVV("%s DP_PARAM_GET_CHANNEL_COUNT channels %d", __func__, *(int32_t *)pValue);
592 break;
593 }
594 case DP_PARAM_ENGINE_ARCHITECTURE: {
595 ALOGVV("engine architecture paramsize: %d valuesize %d",paramSize, *pValueSize);
596 if (!DP_checkSizesInt(paramSize, *pValueSize, 1 /*params*/, 9 /*values*/)) {
597 ALOGE("%s DP_PARAM_ENGINE_ARCHITECTURE (cmd %d) invalid sizes.", __func__, command);
598 status = -EINVAL;
599 break;
600 }
601// Number[] params = { PARAM_ENGINE_ARCHITECTURE };
602// Number[] values = { 0 /*0 variant */,
603// 0.0f /* 1 preferredFrameDuration */,
604// 0 /*2 preEqInUse */,
605// 0 /*3 preEqBandCount */,
606// 0 /*4 mbcInUse */,
607// 0 /*5 mbcBandCount*/,
608// 0 /*6 postEqInUse */,
609// 0 /*7 postEqBandCount */,
610// 0 /*8 limiterInUse */};
611 if (pContext->mPDynamics == NULL) {
612 ALOGE("%s DP_PARAM_ENGINE_ARCHITECTURE error mPDynamics is NULL", __func__);
613 status = -EINVAL;
614 break;
615 }
616 values[0].i = pContext->mCurrentVariant;
617 values[1].f = pContext->mPreferredFrameDuration;
618 values[2].i = pContext->mPDynamics->isPreEQInUse();
619 values[3].i = pContext->mPDynamics->getPreEqBandCount();
620 values[4].i = pContext->mPDynamics->isMbcInUse();
621 values[5].i = pContext->mPDynamics->getMbcBandCount();
622 values[6].i = pContext->mPDynamics->isPostEqInUse();
623 values[7].i = pContext->mPDynamics->getPostEqBandCount();
624 values[8].i = pContext->mPDynamics->isLimiterInUse();
625
626 *pValueSize = sizeof(value_t) * 9;
627
628 ALOGVV(" variant %d, preferredFrameDuration: %f, preEqInuse %d, bands %d, mbcinuse %d,"
629 "mbcbands %d, posteqInUse %d, bands %d, limiterinuse %d",
630 values[0].i, values[1].f, values[2].i, values[3].i, values[4].i, values[5].i,
631 values[6].i, values[7].i, values[8].i);
632 break;
633 }
634 case DP_PARAM_INPUT_GAIN: {
635 ALOGVV("engine get PARAM_INPUT_GAIN paramsize: %d valuesize %d",paramSize, *pValueSize);
636 if (!DP_checkSizesInt(paramSize, *pValueSize, 2 /*params*/, 1 /*values*/)) {
637 ALOGE("%s get PARAM_INPUT_GAIN invalid sizes.", __func__);
638 status = -EINVAL;
639 break;
640 }
641
642 const int32_t channel = params[1];
643 dp_fx::DPChannel * pChannel = DP_getChannel(pContext, channel);
644 if (pChannel == NULL) {
645 ALOGE("%s get PARAM_INPUT_GAIN invalid channel %d", __func__, channel);
646 status = -EINVAL;
647 break;
648 }
649 values[0].f = pChannel->getInputGain();
650 *pValueSize = sizeof(value_t) * 1;
651
652 ALOGVV(" channel: %d, input gain %f\n", channel, values[0].f);
653 break;
654 }
655 case DP_PARAM_PRE_EQ:
656 case DP_PARAM_POST_EQ: {
657 ALOGVV("engine get PARAM_*_EQ paramsize: %d valuesize %d",paramSize, *pValueSize);
658 if (!DP_checkSizesInt(paramSize, *pValueSize, 2 /*params*/, 3 /*values*/)) {
659 ALOGE("%s get PARAM_*_EQ (cmd %d) invalid sizes.", __func__, command);
660 status = -EINVAL;
661 break;
662 }
663// Number[] params = {paramSet == PARAM_PRE_EQ ? PARAM_PRE_EQ : PARAM_POST_EQ,
664// channelIndex};
665// Number[] values = {0 /*0 in use */,
666// 0 /*1 enabled*/,
667// 0 /*2 band count */};
668 const int32_t channel = params[1];
669
670 dp_fx::DPEq *pEq = DP_getEq(pContext, channel, command);
671 if (pEq == NULL) {
672 ALOGE("%s get PARAM_*_EQ invalid eq", __func__);
673 status = -EINVAL;
674 break;
675 }
676 values[0].i = pEq->isInUse();
677 values[1].i = pEq->isEnabled();
678 values[2].i = pEq->getBandCount();
679 *pValueSize = sizeof(value_t) * 3;
680
681 ALOGVV(" %s channel: %d, inUse::%d, enabled:%d, bandCount:%d\n",
682 (command == DP_PARAM_PRE_EQ ? "preEq" : "postEq"), channel,
683 values[0].i, values[1].i, values[2].i);
684 break;
685 }
686 case DP_PARAM_PRE_EQ_BAND:
687 case DP_PARAM_POST_EQ_BAND: {
688 ALOGVV("engine get PARAM_*_EQ_BAND paramsize: %d valuesize %d",paramSize, *pValueSize);
689 if (!DP_checkSizesInt(paramSize, *pValueSize, 3 /*params*/, 3 /*values*/)) {
690 ALOGE("%s get PARAM_*_EQ_BAND (cmd %d) invalid sizes.", __func__, command);
691 status = -EINVAL;
692 break;
693 }
694// Number[] params = {paramSet,
695// channelIndex,
696// bandIndex};
697// Number[] values = {(eqBand.isEnabled() ? 1 : 0),
698// eqBand.getCutoffFrequency(),
699// eqBand.getGain()};
700 const int32_t channel = params[1];
701 const int32_t band = params[2];
702
703 dp_fx::DPEqBand *pEqBand = DP_getEqBand(pContext, channel, command, band);
704 if (pEqBand == NULL) {
705 ALOGE("%s get PARAM_*_EQ_BAND invalid channel %d or band %d", __func__, channel, band);
706 status = -EINVAL;
707 break;
708 }
709
710 values[0].i = pEqBand->isEnabled();
711 values[1].f = pEqBand->getCutoffFrequency();
712 values[2].f = pEqBand->getGain();
713 *pValueSize = sizeof(value_t) * 3;
714
715 ALOGVV("%s channel: %d, band::%d, enabled:%d, cutoffFrequency:%f, gain%f\n",
716 (command == DP_PARAM_PRE_EQ_BAND ? "preEqBand" : "postEqBand"), channel, band,
717 values[0].i, values[1].f, values[2].f);
718 break;
719 }
720 case DP_PARAM_MBC: {
721 ALOGVV("engine get PDP_PARAM_MBC paramsize: %d valuesize %d",paramSize, *pValueSize);
722 if (!DP_checkSizesInt(paramSize, *pValueSize, 2 /*params*/, 3 /*values*/)) {
723 ALOGE("%s get PDP_PARAM_MBC (cmd %d) invalid sizes.", __func__, command);
724 status = -EINVAL;
725 break;
726 }
727
728// Number[] params = {PARAM_MBC,
729// channelIndex};
730// Number[] values = {0 /*0 in use */,
731// 0 /*1 enabled*/,
732// 0 /*2 band count */};
733
734 const int32_t channel = params[1];
735
736 dp_fx::DPMbc *pMbc = DP_getMbc(pContext, channel);
737 if (pMbc == NULL) {
738 ALOGE("%s get PDP_PARAM_MBC invalid MBC", __func__);
739 status = -EINVAL;
740 break;
741 }
742
743 values[0].i = pMbc->isInUse();
744 values[1].i = pMbc->isEnabled();
745 values[2].i = pMbc->getBandCount();
746 *pValueSize = sizeof(value_t) * 3;
747
748 ALOGVV("DP_PARAM_MBC channel: %d, inUse::%d, enabled:%d, bandCount:%d\n", channel,
749 values[0].i, values[1].i, values[2].i);
750 break;
751 }
752 case DP_PARAM_MBC_BAND: {
753 ALOGVV("engine get DP_PARAM_MBC_BAND paramsize: %d valuesize %d",paramSize, *pValueSize);
754 if (!DP_checkSizesInt(paramSize, *pValueSize, 3 /*params*/, 11 /*values*/)) {
755 ALOGE("%s get DP_PARAM_MBC_BAND (cmd %d) invalid sizes.", __func__, command);
756 status = -EINVAL;
757 break;
758 }
759// Number[] params = {PARAM_MBC_BAND,
760// channelIndex,
761// bandIndex};
762// Number[] values = {0 /*0 enabled */,
763// 0.0f /*1 cutoffFrequency */,
764// 0.0f /*2 AttackTime */,
765// 0.0f /*3 ReleaseTime */,
766// 0.0f /*4 Ratio */,
767// 0.0f /*5 Threshold */,
768// 0.0f /*6 KneeWidth */,
769// 0.0f /*7 NoiseGateThreshold */,
770// 0.0f /*8 ExpanderRatio */,
771// 0.0f /*9 PreGain */,
772// 0.0f /*10 PostGain*/};
773
774 const int32_t channel = params[1];
775 const int32_t band = params[2];
776
777 dp_fx::DPMbcBand *pMbcBand = DP_getMbcBand(pContext, channel, band);
778 if (pMbcBand == NULL) {
779 ALOGE("%s get PARAM_MBC_BAND invalid channel %d or band %d", __func__, channel, band);
780 status = -EINVAL;
781 break;
782 }
783
784 values[0].i = pMbcBand->isEnabled();
785 values[1].f = pMbcBand->getCutoffFrequency();
786 values[2].f = pMbcBand->getAttackTime();
787 values[3].f = pMbcBand->getReleaseTime();
788 values[4].f = pMbcBand->getRatio();
789 values[5].f = pMbcBand->getThreshold();
790 values[6].f = pMbcBand->getKneeWidth();
791 values[7].f = pMbcBand->getNoiseGateThreshold();
792 values[8].f = pMbcBand->getExpanderRatio();
793 values[9].f = pMbcBand->getPreGain();
794 values[10].f = pMbcBand->getPostGain();
795
796 *pValueSize = sizeof(value_t) * 11;
797 ALOGVV(" mbcBand channel: %d, band::%d, enabled:%d, cutoffFrequency:%f, attackTime:%f,"
798 "releaseTime:%f, ratio:%f, threshold:%f, kneeWidth:%f, noiseGateThreshold:%f,"
799 "expanderRatio:%f, preGain:%f, postGain:%f\n", channel, band, values[0].i,
800 values[1].f, values[2].f, values[3].f, values[4].f, values[5].f, values[6].f,
801 values[7].f, values[8].f, values[9].f, values[10].f);
802 break;
803 }
804 case DP_PARAM_LIMITER: {
805 ALOGVV("engine get DP_PARAM_LIMITER paramsize: %d valuesize %d",paramSize, *pValueSize);
806 if (!DP_checkSizesInt(paramSize, *pValueSize, 2 /*params*/, 8 /*values*/)) {
807 ALOGE("%s DP_PARAM_LIMITER (cmd %d) invalid sizes.", __func__, command);
808 status = -EINVAL;
809 break;
810 }
811
812 int32_t channel = params[1];
813// Number[] values = {0 /*0 in use (int)*/,
814// 0 /*1 enabled (int)*/,
815// 0 /*2 link group (int)*/,
816// 0.0f /*3 attack time (float)*/,
817// 0.0f /*4 release time (float)*/,
818// 0.0f /*5 ratio (float)*/,
819// 0.0f /*6 threshold (float)*/,
820// 0.0f /*7 post gain(float)*/};
821 dp_fx::DPChannel * pChannel = DP_getChannel(pContext, channel);
822 if (pChannel == NULL) {
823 ALOGE("%s DP_PARAM_LIMITER invalid channel %d", __func__, channel);
824 status = -EINVAL;
825 break;
826 }
827 dp_fx::DPLimiter *pLimiter = pChannel->getLimiter();
828 if (pLimiter == NULL) {
829 ALOGE("%s DP_PARAM_LIMITER null LIMITER", __func__);
830 status = -EINVAL;
831 break;
832 }
833 values[0].i = pLimiter->isInUse();
834 values[1].i = pLimiter->isEnabled();
835 values[2].i = pLimiter->getLinkGroup();
836 values[3].f = pLimiter->getAttackTime();
837 values[4].f = pLimiter->getReleaseTime();
838 values[5].f = pLimiter->getRatio();
839 values[6].f = pLimiter->getThreshold();
840 values[7].f = pLimiter->getPostGain();
841
842 *pValueSize = sizeof(value_t) * 8;
843
844 ALOGVV(" Limiter channel: %d, inUse::%d, enabled:%d, linkgroup:%d attackTime:%f,"
845 "releaseTime:%f, ratio:%f, threshold:%f, postGain:%f\n",
846 channel, values[0].i/*inUse*/, values[1].i/*enabled*/, values[2].i/*linkGroup*/,
847 values[3].f/*attackTime*/, values[4].f/*releaseTime*/,
848 values[5].f/*ratio*/, values[6].f/*threshold*/,
849 values[7].f/*postGain*/);
850 break;
851 }
852 default:
853 ALOGE("%s invalid param %d", __func__, params[0]);
854 status = -EINVAL;
855 break;
856 }
857
858 ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
859 return status;
860} /* end DP_getParameter */
861
862int DP_setParameter(DynamicsProcessingContext *pContext,
863 uint32_t paramSize,
864 void *pParam,
865 uint32_t valueSize,
866 void *pValue) {
867 int status = 0;
868 int32_t *params = (int32_t *)pParam;
869 static_assert(sizeof(float) == sizeof(int32_t) && sizeof(float) == sizeof(value_t) &&
870 alignof(float) == alignof(int32_t) && alignof(float) == alignof(value_t),
871 "Size/alignment mismatch for float/int32_t/value_t");
872 value_t *values = reinterpret_cast<value_t*>(pValue);
873
874 ALOGVV("%s start", __func__);
875 if (paramSize < sizeof(int32_t)) {
876 ALOGE("%s invalid paramSize: %u", __func__, paramSize);
877 return -EINVAL;
878 }
879 const int32_t command = params[0];
880 switch (command) {
881 case DP_PARAM_ENGINE_ARCHITECTURE: {
882 ALOGVV("engine architecture paramsize: %d valuesize %d",paramSize, valueSize);
883 if (!DP_checkSizesInt(paramSize, valueSize, 1 /*params*/, 9 /*values*/)) {
884 ALOGE("%s DP_PARAM_ENGINE_ARCHITECTURE (cmd %d) invalid sizes.", __func__, command);
885 status = -EINVAL;
886 break;
887 }
888// Number[] params = { PARAM_ENGINE_ARCHITECTURE };
889// Number[] values = { variant /* variant */,
890// preferredFrameDuration,
891// (preEqInUse ? 1 : 0),
892// preEqBandCount,
893// (mbcInUse ? 1 : 0),
894// mbcBandCount,
895// (postEqInUse ? 1 : 0),
896// postEqBandCount,
897// (limiterInUse ? 1 : 0)};
898 const int32_t variant = values[0].i;
899 const float preferredFrameDuration = values[1].f;
900 const int32_t preEqInUse = values[2].i;
901 const int32_t preEqBandCount = values[3].i;
902 const int32_t mbcInUse = values[4].i;
903 const int32_t mbcBandCount = values[5].i;
904 const int32_t postEqInUse = values[6].i;
905 const int32_t postEqBandCount = values[7].i;
906 const int32_t limiterInUse = values[8].i;
907 ALOGVV("variant %d, preEqInuse %d, bands %d, mbcinuse %d, mbcbands %d, posteqInUse %d,"
908 "bands %d, limiterinuse %d", variant, preEqInUse, preEqBandCount, mbcInUse,
909 mbcBandCount, postEqInUse, postEqBandCount, limiterInUse);
910
911 //set variant (instantiate effect)
912 //initArchitecture for effect
913 DP_changeVariant(pContext, variant);
914 if (pContext->mPDynamics == NULL) {
915 ALOGE("%s DP_PARAM_ENGINE_ARCHITECTURE error setting variant %d", __func__, variant);
916 status = -EINVAL;
917 break;
918 }
919 pContext->mPreferredFrameDuration = preferredFrameDuration;
920 pContext->mPDynamics->init((uint32_t)audio_channel_count_from_out_mask(
921 pContext->mConfig.inputCfg.channels),
922 preEqInUse != 0, (uint32_t)preEqBandCount,
923 mbcInUse != 0, (uint32_t)mbcBandCount,
924 postEqInUse != 0, (uint32_t)postEqBandCount,
925 limiterInUse != 0);
926 break;
927 }
928 case DP_PARAM_INPUT_GAIN: {
929 ALOGVV("engine DP_PARAM_INPUT_GAIN paramsize: %d valuesize %d",paramSize, valueSize);
930 if (!DP_checkSizesInt(paramSize, valueSize, 2 /*params*/, 1 /*values*/)) {
931 ALOGE("%s DP_PARAM_INPUT_GAIN invalid sizes.", __func__);
932 status = -EINVAL;
933 break;
934 }
935
936 const int32_t channel = params[1];
937 dp_fx::DPChannel * pChannel = DP_getChannel(pContext, channel);
938 if (pChannel == NULL) {
939 ALOGE("%s DP_PARAM_INPUT_GAIN invalid channel %d", __func__, channel);
940 status = -EINVAL;
941 break;
942 }
943 const float gain = values[0].f;
944 ALOGVV("%s DP_PARAM_INPUT_GAIN channel %d, level %f", __func__, channel, gain);
945 pChannel->setInputGain(gain);
946 break;
947 }
948 case DP_PARAM_PRE_EQ:
949 case DP_PARAM_POST_EQ: {
950 ALOGVV("engine DP_PARAM_*_EQ paramsize: %d valuesize %d",paramSize, valueSize);
951 if (!DP_checkSizesInt(paramSize, valueSize, 2 /*params*/, 3 /*values*/)) {
952 ALOGE("%s DP_PARAM_*_EQ (cmd %d) invalid sizes.", __func__, command);
953 status = -EINVAL;
954 break;
955 }
956// Number[] params = {paramSet,
957// channelIndex};
958// Number[] values = { (eq.isInUse() ? 1 : 0),
959// (eq.isEnabled() ? 1 : 0),
960// bandCount};
961 const int32_t channel = params[1];
962
963 const int32_t enabled = values[1].i;
964 const int32_t bandCount = values[2].i;
965 ALOGVV(" %s channel: %d, inUse::%d, enabled:%d, bandCount:%d\n",
966 (command == DP_PARAM_PRE_EQ ? "preEq" : "postEq"), channel, values[0].i,
967 values[2].i, bandCount);
968
969 dp_fx::DPEq *pEq = DP_getEq(pContext, channel, command);
970 if (pEq == NULL) {
971 ALOGE("%s set PARAM_*_EQ invalid channel %d or command %d", __func__, channel,
972 command);
973 status = -EINVAL;
974 break;
975 }
976
977 pEq->setEnabled(enabled != 0);
978 //fail if bandcountis different? maybe.
979 if ((int32_t)pEq->getBandCount() != bandCount) {
980 ALOGW("%s warning, trying to set different bandcount from %d to %d", __func__,
981 pEq->getBandCount(), bandCount);
982 }
983 break;
984 }
985 case DP_PARAM_PRE_EQ_BAND:
986 case DP_PARAM_POST_EQ_BAND: {
987 ALOGVV("engine set PARAM_*_EQ_BAND paramsize: %d valuesize %d",paramSize, valueSize);
988 if (!DP_checkSizesInt(paramSize, valueSize, 3 /*params*/, 3 /*values*/)) {
989 ALOGE("%s PARAM_*_EQ_BAND (cmd %d) invalid sizes.", __func__, command);
990 status = -EINVAL;
991 break;
992 }
993// Number[] values = { channelIndex,
994// bandIndex,
995// (eqBand.isEnabled() ? 1 : 0),
996// eqBand.getCutoffFrequency(),
997// eqBand.getGain()};
998
999// Number[] params = {paramSet,
1000// channelIndex,
1001// bandIndex};
1002// Number[] values = {(eqBand.isEnabled() ? 1 : 0),
1003// eqBand.getCutoffFrequency(),
1004// eqBand.getGain()};
1005
1006 const int32_t channel = params[1];
1007 const int32_t band = params[2];
1008
1009 const int32_t enabled = values[0].i;
1010 const float cutoffFrequency = values[1].f;
1011 const float gain = values[2].f;
1012
1013
1014 ALOGVV(" %s channel: %d, band::%d, enabled:%d, cutoffFrequency:%f, gain%f\n",
1015 (command == DP_PARAM_PRE_EQ_BAND ? "preEqBand" : "postEqBand"), channel, band,
1016 enabled, cutoffFrequency, gain);
1017
1018 dp_fx::DPEq *pEq = DP_getEq(pContext, channel, command);
1019 if (pEq == NULL) {
1020 ALOGE("%s set PARAM_*_EQ_BAND invalid channel %d or command %d", __func__, channel,
1021 command);
1022 status = -EINVAL;
1023 break;
1024 }
1025
1026 dp_fx::DPEqBand eqBand;
1027 eqBand.init(enabled != 0, cutoffFrequency, gain);
1028 pEq->setBand(band, eqBand);
1029 break;
1030 }
1031 case DP_PARAM_MBC: {
1032 ALOGVV("engine DP_PARAM_MBC paramsize: %d valuesize %d",paramSize, valueSize);
1033 if (!DP_checkSizesInt(paramSize, valueSize, 2 /*params*/, 3 /*values*/)) {
1034 ALOGE("%s DP_PARAM_MBC (cmd %d) invalid sizes.", __func__, command);
1035 status = -EINVAL;
1036 break;
1037 }
1038// Number[] params = { PARAM_MBC,
1039// channelIndex};
1040// Number[] values = {(mbc.isInUse() ? 1 : 0),
1041// (mbc.isEnabled() ? 1 : 0),
1042// bandCount};
1043 const int32_t channel = params[1];
1044
1045 const int32_t enabled = values[1].i;
1046 const int32_t bandCount = values[2].i;
1047 ALOGVV("MBC channel: %d, inUse::%d, enabled:%d, bandCount:%d\n", channel, values[0].i,
1048 enabled, bandCount);
1049
1050 dp_fx::DPMbc *pMbc = DP_getMbc(pContext, channel);
1051 if (pMbc == NULL) {
1052 ALOGE("%s set DP_PARAM_MBC invalid channel %d ", __func__, channel);
1053 status = -EINVAL;
1054 break;
1055 }
1056
1057 pMbc->setEnabled(enabled != 0);
1058 //fail if bandcountis different? maybe.
1059 if ((int32_t)pMbc->getBandCount() != bandCount) {
1060 ALOGW("%s warning, trying to set different bandcount from %d to %d", __func__,
1061 pMbc->getBandCount(), bandCount);
1062 }
1063 break;
1064 }
1065 case DP_PARAM_MBC_BAND: {
1066 ALOGVV("engine set DP_PARAM_MBC_BAND paramsize: %d valuesize %d ",paramSize, valueSize);
1067 if (!DP_checkSizesInt(paramSize, valueSize, 3 /*params*/, 11 /*values*/)) {
1068 ALOGE("%s DP_PARAM_MBC_BAND: (cmd %d) invalid sizes.", __func__, command);
1069 status = -EINVAL;
1070 break;
1071 }
1072// Number[] params = { PARAM_MBC_BAND,
1073// channelIndex,
1074// bandIndex};
1075// Number[] values = {(mbcBand.isEnabled() ? 1 : 0),
1076// mbcBand.getCutoffFrequency(),
1077// mbcBand.getAttackTime(),
1078// mbcBand.getReleaseTime(),
1079// mbcBand.getRatio(),
1080// mbcBand.getThreshold(),
1081// mbcBand.getKneeWidth(),
1082// mbcBand.getNoiseGateThreshold(),
1083// mbcBand.getExpanderRatio(),
1084// mbcBand.getPreGain(),
1085// mbcBand.getPostGain()};
1086
1087 const int32_t channel = params[1];
1088 const int32_t band = params[2];
1089
1090 const int32_t enabled = values[0].i;
1091 const float cutoffFrequency = values[1].f;
1092 const float attackTime = values[2].f;
1093 const float releaseTime = values[3].f;
1094 const float ratio = values[4].f;
1095 const float threshold = values[5].f;
1096 const float kneeWidth = values[6].f;
1097 const float noiseGateThreshold = values[7].f;
1098 const float expanderRatio = values[8].f;
1099 const float preGain = values[9].f;
1100 const float postGain = values[10].f;
1101
1102 ALOGVV(" mbcBand channel: %d, band::%d, enabled:%d, cutoffFrequency:%f, attackTime:%f,"
1103 "releaseTime:%f, ratio:%f, threshold:%f, kneeWidth:%f, noiseGateThreshold:%f,"
1104 "expanderRatio:%f, preGain:%f, postGain:%f\n",
1105 channel, band, enabled, cutoffFrequency, attackTime, releaseTime, ratio,
1106 threshold, kneeWidth, noiseGateThreshold, expanderRatio, preGain, postGain);
1107
1108 dp_fx::DPMbc *pMbc = DP_getMbc(pContext, channel);
1109 if (pMbc == NULL) {
1110 ALOGE("%s set DP_PARAM_MBC_BAND invalid channel %d", __func__, channel);
1111 status = -EINVAL;
1112 break;
1113 }
1114
1115 dp_fx::DPMbcBand mbcBand;
1116 mbcBand.init(enabled != 0, cutoffFrequency, attackTime, releaseTime, ratio, threshold,
1117 kneeWidth, noiseGateThreshold, expanderRatio, preGain, postGain);
1118 pMbc->setBand(band, mbcBand);
1119 break;
1120 }
1121 case DP_PARAM_LIMITER: {
1122 ALOGVV("engine DP_PARAM_LIMITER paramsize: %d valuesize %d",paramSize, valueSize);
1123 if (!DP_checkSizesInt(paramSize, valueSize, 2 /*params*/, 8 /*values*/)) {
1124 ALOGE("%s DP_PARAM_LIMITER (cmd %d) invalid sizes.", __func__, command);
1125 status = -EINVAL;
1126 break;
1127 }
1128// Number[] params = { PARAM_LIMITER,
1129// channelIndex};
1130// Number[] values = {(limiter.isInUse() ? 1 : 0),
1131// (limiter.isEnabled() ? 1 : 0),
1132// limiter.getLinkGroup(),
1133// limiter.getAttackTime(),
1134// limiter.getReleaseTime(),
1135// limiter.getRatio(),
1136// limiter.getThreshold(),
1137// limiter.getPostGain()};
1138
1139 const int32_t channel = params[1];
1140
1141 const int32_t inUse = values[0].i;
1142 const int32_t enabled = values[1].i;
1143 const int32_t linkGroup = values[2].i;
1144 const float attackTime = values[3].f;
1145 const float releaseTime = values[4].f;
1146 const float ratio = values[5].f;
1147 const float threshold = values[6].f;
1148 const float postGain = values[7].f;
1149
1150 ALOGVV(" Limiter channel: %d, inUse::%d, enabled:%d, linkgroup:%d attackTime:%f,"
1151 "releaseTime:%f, ratio:%f, threshold:%f, postGain:%f\n", channel, inUse,
1152 enabled, linkGroup, attackTime, releaseTime, ratio, threshold, postGain);
1153
1154 dp_fx::DPChannel * pChannel = DP_getChannel(pContext, channel);
1155 if (pChannel == NULL) {
1156 ALOGE("%s DP_PARAM_LIMITER invalid channel %d", __func__, channel);
1157 status = -EINVAL;
1158 break;
1159 }
1160 dp_fx::DPLimiter limiter;
1161 limiter.init(inUse != 0, enabled != 0, linkGroup, attackTime, releaseTime, ratio,
1162 threshold, postGain);
1163 pChannel->setLimiter(limiter);
1164 break;
1165 }
1166 default:
1167 ALOGE("%s invalid param %d", __func__, params[0]);
1168 status = -EINVAL;
1169 break;
1170 }
1171
1172 ALOGVV("%s end param: %d, status: %d", __func__, params[0], status);
1173 return status;
1174} /* end DP_setParameter */
1175
1176/* Effect Control Interface Implementation: get_descriptor */
1177int DP_getDescriptor(effect_handle_t self,
1178 effect_descriptor_t *pDescriptor)
1179{
1180 DynamicsProcessingContext * pContext = (DynamicsProcessingContext *) self;
1181
1182 if (pContext == NULL || pDescriptor == NULL) {
1183 ALOGE("DP_getDescriptor() invalid param");
1184 return -EINVAL;
1185 }
1186
1187 *pDescriptor = gDPDescriptor;
1188
1189 return 0;
1190} /* end DP_getDescriptor */
1191
1192
1193// effect_handle_t interface implementation for Dynamics Processing effect
1194const struct effect_interface_s gDPInterface = {
1195 DP_process,
1196 DP_command,
1197 DP_getDescriptor,
1198 NULL,
1199};
1200
1201extern "C" {
1202// This is the only symbol that needs to be exported
1203__attribute__ ((visibility ("default")))
1204audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
1205 .tag = AUDIO_EFFECT_LIBRARY_TAG,
1206 .version = EFFECT_LIBRARY_API_VERSION,
1207 .name = "Dynamics Processing Library",
1208 .implementor = "The Android Open Source Project",
1209 .create_effect = DPLib_Create,
1210 .release_effect = DPLib_Release,
1211 .get_descriptor = DPLib_GetDescriptor,
1212};
1213
1214}; // extern "C"
1215