blob: f5e11a6cfa7ec311c7512da50e9f723460f0a967 [file] [log] [blame]
Eric Laurent135ad072010-05-21 06:05:13 -07001/*
2 * Copyright (C) 2009 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 "Equalizer"
18#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
Eric Laurent2c8e5ca2010-07-09 12:28:50 -070019//
20#define LOG_NDEBUG 0
Mark Salyzyn60d02072016-09-29 08:48:48 -070021
Eric Laurent135ad072010-05-21 06:05:13 -070022#include <assert.h>
23#include <stdlib.h>
Eric Laurent17217ab2010-05-25 12:38:34 -070024#include <string.h>
Eric Laurent135ad072010-05-21 06:05:13 -070025#include <new>
Mark Salyzyn60d02072016-09-29 08:48:48 -070026
27#include <android/log.h>
28
Eric Laurent135ad072010-05-21 06:05:13 -070029#include "AudioEqualizer.h"
30#include "AudioBiquadFilter.h"
31#include "AudioFormatAdapter.h"
Eric Laurent6d8b6942011-06-24 07:01:31 -070032#include <audio_effects/effect_equalizer.h>
33
Eric Laurente1315cf2011-05-17 19:16:02 -070034// effect_handle_t interface implementation for equalizer effect
Eric Laurent135ad072010-05-21 06:05:13 -070035extern "C" const struct effect_interface_s gEqualizerInterface;
36
Eric Laurente44b1ef2010-07-09 13:34:17 -070037enum equalizer_state_e {
38 EQUALIZER_STATE_UNINITIALIZED,
39 EQUALIZER_STATE_INITIALIZED,
40 EQUALIZER_STATE_ACTIVE,
41};
42
Eric Laurent135ad072010-05-21 06:05:13 -070043namespace android {
44namespace {
45
46// Google Graphic Equalizer UUID: e25aa840-543b-11df-98a5-0002a5d5c51b
47const effect_descriptor_t gEqualizerDescriptor = {
48 {0x0bed4300, 0xddd6, 0x11db, 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
49 {0xe25aa840, 0x543b, 0x11df, 0x98a5, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
Eric Laurente1315cf2011-05-17 19:16:02 -070050 EFFECT_CONTROL_API_VERSION,
Eric Laurent135ad072010-05-21 06:05:13 -070051 (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST),
Eric Laurentffe9c252010-06-23 17:38:20 -070052 0, // TODO
53 1,
Eric Laurent135ad072010-05-21 06:05:13 -070054 "Graphic Equalizer",
Eric Laurente1315cf2011-05-17 19:16:02 -070055 "The Android Open Source Project",
Eric Laurent135ad072010-05-21 06:05:13 -070056};
Eric Laurent135ad072010-05-21 06:05:13 -070057
58/////////////////// BEGIN EQ PRESETS ///////////////////////////////////////////
59const int kNumBands = 5;
60const uint32_t gFreqs[kNumBands] = { 50000, 125000, 900000, 3200000, 6300000 };
61const uint32_t gBandwidths[kNumBands] = { 0, 3600, 3600, 2400, 0 };
62
63const AudioEqualizer::BandConfig gBandsClassic[kNumBands] = {
64 { 300, gFreqs[0], gBandwidths[0] },
65 { 400, gFreqs[1], gBandwidths[1] },
66 { 0, gFreqs[2], gBandwidths[2] },
67 { 200, gFreqs[3], gBandwidths[3] },
68 { -300, gFreqs[4], gBandwidths[4] }
69};
70
71const AudioEqualizer::BandConfig gBandsJazz[kNumBands] = {
72 { -600, gFreqs[0], gBandwidths[0] },
73 { 200, gFreqs[1], gBandwidths[1] },
74 { 400, gFreqs[2], gBandwidths[2] },
75 { -400, gFreqs[3], gBandwidths[3] },
76 { -600, gFreqs[4], gBandwidths[4] }
77};
78
79const AudioEqualizer::BandConfig gBandsPop[kNumBands] = {
80 { 400, gFreqs[0], gBandwidths[0] },
81 { -400, gFreqs[1], gBandwidths[1] },
82 { 300, gFreqs[2], gBandwidths[2] },
83 { -400, gFreqs[3], gBandwidths[3] },
84 { 600, gFreqs[4], gBandwidths[4] }
85};
86
87const AudioEqualizer::BandConfig gBandsRock[kNumBands] = {
88 { 700, gFreqs[0], gBandwidths[0] },
89 { 400, gFreqs[1], gBandwidths[1] },
90 { -400, gFreqs[2], gBandwidths[2] },
91 { 400, gFreqs[3], gBandwidths[3] },
92 { 200, gFreqs[4], gBandwidths[4] }
93};
94
95const AudioEqualizer::PresetConfig gEqualizerPresets[] = {
96 { "Classic", gBandsClassic },
97 { "Jazz", gBandsJazz },
98 { "Pop", gBandsPop },
99 { "Rock", gBandsRock }
100};
101
102/////////////////// END EQ PRESETS /////////////////////////////////////////////
103
104static const size_t kBufferSize = 32;
105
106typedef AudioFormatAdapter<AudioEqualizer, kBufferSize> FormatAdapter;
107
108struct EqualizerContext {
109 const struct effect_interface_s *itfe;
110 effect_config_t config;
111 FormatAdapter adapter;
112 AudioEqualizer * pEqualizer;
Eric Laurente44b1ef2010-07-09 13:34:17 -0700113 uint32_t state;
Eric Laurent135ad072010-05-21 06:05:13 -0700114};
115
Eric Laurent135ad072010-05-21 06:05:13 -0700116//--- local function prototypes
117
118int Equalizer_init(EqualizerContext *pContext);
Eric Laurent3d5188b2011-12-16 15:30:36 -0800119int Equalizer_setConfig(EqualizerContext *pContext, effect_config_t *pConfig);
Ashok Bhatb302bd52014-02-18 11:40:00 +0000120int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, uint32_t *pValueSize, void *pValue);
Eric Laurent135ad072010-05-21 06:05:13 -0700121int Equalizer_setParameter(AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue);
122
123
124//
125//--- Effect Library Interface Implementation
126//
127
Glenn Kasten5e92a782012-01-30 07:40:52 -0800128extern "C" int EffectCreate(const effect_uuid_t *uuid,
Eric Laurente1315cf2011-05-17 19:16:02 -0700129 int32_t sessionId,
130 int32_t ioId,
131 effect_handle_t *pHandle) {
Eric Laurent135ad072010-05-21 06:05:13 -0700132 int ret;
133 int i;
134
Steve Block3856b092011-10-20 11:56:00 +0100135 ALOGV("EffectLibCreateEffect start");
Eric Laurent135ad072010-05-21 06:05:13 -0700136
Eric Laurente1315cf2011-05-17 19:16:02 -0700137 if (pHandle == NULL || uuid == NULL) {
Eric Laurent135ad072010-05-21 06:05:13 -0700138 return -EINVAL;
139 }
140
141 if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) != 0) {
142 return -EINVAL;
143 }
144
145 EqualizerContext *pContext = new EqualizerContext;
146
147 pContext->itfe = &gEqualizerInterface;
148 pContext->pEqualizer = NULL;
Eric Laurente44b1ef2010-07-09 13:34:17 -0700149 pContext->state = EQUALIZER_STATE_UNINITIALIZED;
Eric Laurent135ad072010-05-21 06:05:13 -0700150
151 ret = Equalizer_init(pContext);
152 if (ret < 0) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000153 ALOGW("EffectLibCreateEffect() init failed");
Eric Laurent135ad072010-05-21 06:05:13 -0700154 delete pContext;
155 return ret;
156 }
157
Eric Laurente1315cf2011-05-17 19:16:02 -0700158 *pHandle = (effect_handle_t)pContext;
Eric Laurente44b1ef2010-07-09 13:34:17 -0700159 pContext->state = EQUALIZER_STATE_INITIALIZED;
Eric Laurent135ad072010-05-21 06:05:13 -0700160
Steve Block3856b092011-10-20 11:56:00 +0100161 ALOGV("EffectLibCreateEffect %p, size %d",
Eric Laurente1315cf2011-05-17 19:16:02 -0700162 pContext, AudioEqualizer::GetInstanceSize(kNumBands)+sizeof(EqualizerContext));
Eric Laurent135ad072010-05-21 06:05:13 -0700163
164 return 0;
165
166} /* end EffectCreate */
167
Eric Laurente1315cf2011-05-17 19:16:02 -0700168extern "C" int EffectRelease(effect_handle_t handle) {
169 EqualizerContext * pContext = (EqualizerContext *)handle;
Eric Laurent135ad072010-05-21 06:05:13 -0700170
Steve Block3856b092011-10-20 11:56:00 +0100171 ALOGV("EffectLibReleaseEffect %p", handle);
Eric Laurent135ad072010-05-21 06:05:13 -0700172 if (pContext == NULL) {
173 return -EINVAL;
174 }
175
Eric Laurente44b1ef2010-07-09 13:34:17 -0700176 pContext->state = EQUALIZER_STATE_UNINITIALIZED;
Eric Laurent135ad072010-05-21 06:05:13 -0700177 pContext->pEqualizer->free();
178 delete pContext;
179
180 return 0;
181} /* end EffectRelease */
182
Glenn Kasten5e92a782012-01-30 07:40:52 -0800183extern "C" int EffectGetDescriptor(const effect_uuid_t *uuid,
Eric Laurente1315cf2011-05-17 19:16:02 -0700184 effect_descriptor_t *pDescriptor) {
185
186 if (pDescriptor == NULL || uuid == NULL){
Steve Block3856b092011-10-20 11:56:00 +0100187 ALOGV("EffectGetDescriptor() called with NULL pointer");
Eric Laurente1315cf2011-05-17 19:16:02 -0700188 return -EINVAL;
189 }
190
191 if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0) {
Glenn Kastena189a682012-02-20 12:16:30 -0800192 *pDescriptor = gEqualizerDescriptor;
Eric Laurente1315cf2011-05-17 19:16:02 -0700193 return 0;
194 }
195
196 return -EINVAL;
197} /* end EffectGetDescriptor */
198
Eric Laurent135ad072010-05-21 06:05:13 -0700199
200//
201//--- local functions
202//
203
204#define CHECK_ARG(cond) { \
205 if (!(cond)) { \
Steve Block3856b092011-10-20 11:56:00 +0100206 ALOGV("Invalid argument: "#cond); \
Eric Laurent135ad072010-05-21 06:05:13 -0700207 return -EINVAL; \
208 } \
209}
210
211//----------------------------------------------------------------------------
Eric Laurent3d5188b2011-12-16 15:30:36 -0800212// Equalizer_setConfig()
Eric Laurent135ad072010-05-21 06:05:13 -0700213//----------------------------------------------------------------------------
214// Purpose: Set input and output audio configuration.
215//
216// Inputs:
217// pContext: effect engine context
218// pConfig: pointer to effect_config_t structure holding input and output
219// configuration parameters
220//
221// Outputs:
222//
223//----------------------------------------------------------------------------
224
Eric Laurent3d5188b2011-12-16 15:30:36 -0800225int Equalizer_setConfig(EqualizerContext *pContext, effect_config_t *pConfig)
Eric Laurent135ad072010-05-21 06:05:13 -0700226{
Eric Laurent3d5188b2011-12-16 15:30:36 -0800227 ALOGV("Equalizer_setConfig start");
Eric Laurent135ad072010-05-21 06:05:13 -0700228
229 CHECK_ARG(pContext != NULL);
230 CHECK_ARG(pConfig != NULL);
231
232 CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
233 CHECK_ARG(pConfig->inputCfg.channels == pConfig->outputCfg.channels);
234 CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
Eric Laurente1315cf2011-05-17 19:16:02 -0700235 CHECK_ARG((pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_MONO) ||
236 (pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_STEREO));
Eric Laurent135ad072010-05-21 06:05:13 -0700237 CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
238 || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
Glenn Kastenb7f08d32013-06-18 11:46:28 -0700239 CHECK_ARG(pConfig->inputCfg.format == AUDIO_FORMAT_PCM_16_BIT);
Eric Laurent135ad072010-05-21 06:05:13 -0700240
241 int channelCount;
Eric Laurente1315cf2011-05-17 19:16:02 -0700242 if (pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_MONO) {
Eric Laurent135ad072010-05-21 06:05:13 -0700243 channelCount = 1;
244 } else {
245 channelCount = 2;
246 }
247 CHECK_ARG(channelCount <= AudioBiquadFilter::MAX_CHANNELS);
248
Glenn Kastena189a682012-02-20 12:16:30 -0800249 pContext->config = *pConfig;
Eric Laurentffe9c252010-06-23 17:38:20 -0700250
Eric Laurent135ad072010-05-21 06:05:13 -0700251 pContext->pEqualizer->configure(channelCount,
252 pConfig->inputCfg.samplingRate);
253
254 pContext->adapter.configure(*pContext->pEqualizer, channelCount,
255 pConfig->inputCfg.format,
256 pConfig->outputCfg.accessMode);
257
258 return 0;
Eric Laurent3d5188b2011-12-16 15:30:36 -0800259} // end Equalizer_setConfig
260
261//----------------------------------------------------------------------------
262// Equalizer_getConfig()
263//----------------------------------------------------------------------------
264// Purpose: Get input and output audio configuration.
265//
266// Inputs:
267// pContext: effect engine context
268// pConfig: pointer to effect_config_t structure holding input and output
269// configuration parameters
270//
271// Outputs:
272//
273//----------------------------------------------------------------------------
274
275void Equalizer_getConfig(EqualizerContext *pContext, effect_config_t *pConfig)
276{
Glenn Kastena189a682012-02-20 12:16:30 -0800277 *pConfig = pContext->config;
Eric Laurent3d5188b2011-12-16 15:30:36 -0800278} // end Equalizer_getConfig
Eric Laurent135ad072010-05-21 06:05:13 -0700279
280
281//----------------------------------------------------------------------------
282// Equalizer_init()
283//----------------------------------------------------------------------------
284// Purpose: Initialize engine with default configuration and creates
285// AudioEqualizer instance.
286//
287// Inputs:
288// pContext: effect engine context
289//
290// Outputs:
291//
292//----------------------------------------------------------------------------
293
294int Equalizer_init(EqualizerContext *pContext)
295{
296 int status;
297
Steve Block3856b092011-10-20 11:56:00 +0100298 ALOGV("Equalizer_init start");
Eric Laurent135ad072010-05-21 06:05:13 -0700299
300 CHECK_ARG(pContext != NULL);
301
302 if (pContext->pEqualizer != NULL) {
303 pContext->pEqualizer->free();
304 }
305
306 pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
Eric Laurente1315cf2011-05-17 19:16:02 -0700307 pContext->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
308 pContext->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Eric Laurent135ad072010-05-21 06:05:13 -0700309 pContext->config.inputCfg.samplingRate = 44100;
310 pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
311 pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
312 pContext->config.inputCfg.bufferProvider.cookie = NULL;
313 pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
314 pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
Eric Laurente1315cf2011-05-17 19:16:02 -0700315 pContext->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
316 pContext->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Eric Laurent135ad072010-05-21 06:05:13 -0700317 pContext->config.outputCfg.samplingRate = 44100;
318 pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
319 pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
320 pContext->config.outputCfg.bufferProvider.cookie = NULL;
321 pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL;
322
323 pContext->pEqualizer = AudioEqualizer::CreateInstance(
324 NULL,
325 kNumBands,
326 AudioBiquadFilter::MAX_CHANNELS,
327 44100,
328 gEqualizerPresets,
329 ARRAY_SIZE(gEqualizerPresets));
330
331 for (int i = 0; i < kNumBands; ++i) {
332 pContext->pEqualizer->setFrequency(i, gFreqs[i]);
333 pContext->pEqualizer->setBandwidth(i, gBandwidths[i]);
334 }
335
336 pContext->pEqualizer->enable(true);
337
Eric Laurent3d5188b2011-12-16 15:30:36 -0800338 Equalizer_setConfig(pContext, &pContext->config);
Eric Laurent135ad072010-05-21 06:05:13 -0700339
340 return 0;
341} // end Equalizer_init
342
343
344//----------------------------------------------------------------------------
345// Equalizer_getParameter()
346//----------------------------------------------------------------------------
347// Purpose:
348// Get a Equalizer parameter
349//
350// Inputs:
351// pEqualizer - handle to instance data
352// pParam - pointer to parameter
353// pValue - pointer to variable to hold retrieved value
354// pValueSize - pointer to value size: maximum size as input
355//
356// Outputs:
357// *pValue updated with parameter value
358// *pValueSize updated with actual value size
359//
360//
361// Side Effects:
362//
363//----------------------------------------------------------------------------
364
Ashok Bhatb302bd52014-02-18 11:40:00 +0000365int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, uint32_t *pValueSize, void *pValue)
Eric Laurent135ad072010-05-21 06:05:13 -0700366{
367 int status = 0;
368 int32_t param = *pParam++;
369 int32_t param2;
370 char *name;
371
372 switch (param) {
373 case EQ_PARAM_NUM_BANDS:
374 case EQ_PARAM_CUR_PRESET:
375 case EQ_PARAM_GET_NUM_OF_PRESETS:
Eric Laurent3be95232010-07-30 09:12:51 -0700376 case EQ_PARAM_BAND_LEVEL:
377 case EQ_PARAM_GET_BAND:
Eric Laurent135ad072010-05-21 06:05:13 -0700378 if (*pValueSize < sizeof(int16_t)) {
379 return -EINVAL;
380 }
381 *pValueSize = sizeof(int16_t);
382 break;
383
384 case EQ_PARAM_LEVEL_RANGE:
Eric Laurent3be95232010-07-30 09:12:51 -0700385 if (*pValueSize < 2 * sizeof(int16_t)) {
386 return -EINVAL;
387 }
388 *pValueSize = 2 * sizeof(int16_t);
389 break;
390
Eric Laurent135ad072010-05-21 06:05:13 -0700391 case EQ_PARAM_BAND_FREQ_RANGE:
392 if (*pValueSize < 2 * sizeof(int32_t)) {
393 return -EINVAL;
394 }
395 *pValueSize = 2 * sizeof(int32_t);
396 break;
Eric Laurent3be95232010-07-30 09:12:51 -0700397
Eric Laurent135ad072010-05-21 06:05:13 -0700398 case EQ_PARAM_CENTER_FREQ:
399 if (*pValueSize < sizeof(int32_t)) {
400 return -EINVAL;
401 }
402 *pValueSize = sizeof(int32_t);
403 break;
404
405 case EQ_PARAM_GET_PRESET_NAME:
406 break;
407
Eric Laurent3be95232010-07-30 09:12:51 -0700408 case EQ_PARAM_PROPERTIES:
409 if (*pValueSize < (2 + kNumBands) * sizeof(uint16_t)) {
410 return -EINVAL;
411 }
412 *pValueSize = (2 + kNumBands) * sizeof(uint16_t);
413 break;
414
Eric Laurent135ad072010-05-21 06:05:13 -0700415 default:
416 return -EINVAL;
417 }
418
419 switch (param) {
420 case EQ_PARAM_NUM_BANDS:
Eric Laurent3be95232010-07-30 09:12:51 -0700421 *(uint16_t *)pValue = (uint16_t)kNumBands;
Steve Block3856b092011-10-20 11:56:00 +0100422 ALOGV("Equalizer_getParameter() EQ_PARAM_NUM_BANDS %d", *(int16_t *)pValue);
Eric Laurent135ad072010-05-21 06:05:13 -0700423 break;
424
425 case EQ_PARAM_LEVEL_RANGE:
Eric Laurent3be95232010-07-30 09:12:51 -0700426 *(int16_t *)pValue = -9600;
427 *((int16_t *)pValue + 1) = 4800;
Steve Block3856b092011-10-20 11:56:00 +0100428 ALOGV("Equalizer_getParameter() EQ_PARAM_LEVEL_RANGE min %d, max %d",
Eric Laurente1315cf2011-05-17 19:16:02 -0700429 *(int32_t *)pValue, *((int32_t *)pValue + 1));
Eric Laurent135ad072010-05-21 06:05:13 -0700430 break;
431
432 case EQ_PARAM_BAND_LEVEL:
433 param2 = *pParam;
434 if (param2 >= kNumBands) {
435 status = -EINVAL;
436 break;
437 }
Eric Laurent3be95232010-07-30 09:12:51 -0700438 *(int16_t *)pValue = (int16_t)pEqualizer->getGain(param2);
Steve Block3856b092011-10-20 11:56:00 +0100439 ALOGV("Equalizer_getParameter() EQ_PARAM_BAND_LEVEL band %d, level %d",
Eric Laurente1315cf2011-05-17 19:16:02 -0700440 param2, *(int32_t *)pValue);
Eric Laurent135ad072010-05-21 06:05:13 -0700441 break;
442
443 case EQ_PARAM_CENTER_FREQ:
444 param2 = *pParam;
445 if (param2 >= kNumBands) {
446 status = -EINVAL;
447 break;
448 }
449 *(int32_t *)pValue = pEqualizer->getFrequency(param2);
Steve Block3856b092011-10-20 11:56:00 +0100450 ALOGV("Equalizer_getParameter() EQ_PARAM_CENTER_FREQ band %d, frequency %d",
Eric Laurente1315cf2011-05-17 19:16:02 -0700451 param2, *(int32_t *)pValue);
Eric Laurent135ad072010-05-21 06:05:13 -0700452 break;
453
454 case EQ_PARAM_BAND_FREQ_RANGE:
455 param2 = *pParam;
456 if (param2 >= kNumBands) {
457 status = -EINVAL;
458 break;
459 }
460 pEqualizer->getBandRange(param2, *(uint32_t *)pValue, *((uint32_t *)pValue + 1));
Steve Block3856b092011-10-20 11:56:00 +0100461 ALOGV("Equalizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d, min %d, max %d",
Eric Laurente1315cf2011-05-17 19:16:02 -0700462 param2, *(int32_t *)pValue, *((int32_t *)pValue + 1));
Eric Laurent135ad072010-05-21 06:05:13 -0700463 break;
464
465 case EQ_PARAM_GET_BAND:
466 param2 = *pParam;
Eric Laurent3be95232010-07-30 09:12:51 -0700467 *(uint16_t *)pValue = (uint16_t)pEqualizer->getMostRelevantBand(param2);
Steve Block3856b092011-10-20 11:56:00 +0100468 ALOGV("Equalizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d",
Eric Laurente1315cf2011-05-17 19:16:02 -0700469 param2, *(int32_t *)pValue);
Eric Laurent135ad072010-05-21 06:05:13 -0700470 break;
471
472 case EQ_PARAM_CUR_PRESET:
Eric Laurent3be95232010-07-30 09:12:51 -0700473 *(uint16_t *)pValue = (uint16_t)pEqualizer->getPreset();
Steve Block3856b092011-10-20 11:56:00 +0100474 ALOGV("Equalizer_getParameter() EQ_PARAM_CUR_PRESET %d", *(int32_t *)pValue);
Eric Laurent135ad072010-05-21 06:05:13 -0700475 break;
476
477 case EQ_PARAM_GET_NUM_OF_PRESETS:
Eric Laurent3be95232010-07-30 09:12:51 -0700478 *(uint16_t *)pValue = (uint16_t)pEqualizer->getNumPresets();
Steve Block3856b092011-10-20 11:56:00 +0100479 ALOGV("Equalizer_getParameter() EQ_PARAM_GET_NUM_OF_PRESETS %d", *(int16_t *)pValue);
Eric Laurent135ad072010-05-21 06:05:13 -0700480 break;
481
482 case EQ_PARAM_GET_PRESET_NAME:
483 param2 = *pParam;
484 if (param2 >= pEqualizer->getNumPresets()) {
485 status = -EINVAL;
486 break;
487 }
488 name = (char *)pValue;
489 strncpy(name, pEqualizer->getPresetName(param2), *pValueSize - 1);
490 name[*pValueSize - 1] = 0;
491 *pValueSize = strlen(name) + 1;
Steve Block3856b092011-10-20 11:56:00 +0100492 ALOGV("Equalizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d",
Eric Laurente1315cf2011-05-17 19:16:02 -0700493 param2, gEqualizerPresets[param2].name, *pValueSize);
Eric Laurent135ad072010-05-21 06:05:13 -0700494 break;
495
Eric Laurent3be95232010-07-30 09:12:51 -0700496 case EQ_PARAM_PROPERTIES: {
497 int16_t *p = (int16_t *)pValue;
Steve Block3856b092011-10-20 11:56:00 +0100498 ALOGV("Equalizer_getParameter() EQ_PARAM_PROPERTIES");
Eric Laurent3be95232010-07-30 09:12:51 -0700499 p[0] = (int16_t)pEqualizer->getPreset();
500 p[1] = (int16_t)kNumBands;
501 for (int i = 0; i < kNumBands; i++) {
502 p[2 + i] = (int16_t)pEqualizer->getGain(i);
503 }
504 } break;
505
Eric Laurent135ad072010-05-21 06:05:13 -0700506 default:
Steve Block3856b092011-10-20 11:56:00 +0100507 ALOGV("Equalizer_getParameter() invalid param %d", param);
Eric Laurent135ad072010-05-21 06:05:13 -0700508 status = -EINVAL;
509 break;
510 }
511
512 return status;
513} // end Equalizer_getParameter
514
515
516//----------------------------------------------------------------------------
517// Equalizer_setParameter()
518//----------------------------------------------------------------------------
519// Purpose:
520// Set a Equalizer parameter
521//
522// Inputs:
523// pEqualizer - handle to instance data
524// pParam - pointer to parameter
525// pValue - pointer to value
526//
527// Outputs:
528//
529//
530// Side Effects:
531//
532//----------------------------------------------------------------------------
533
534int Equalizer_setParameter (AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue)
535{
536 int status = 0;
537 int32_t preset;
538 int32_t band;
539 int32_t level;
540 int32_t param = *pParam++;
541
542
543 switch (param) {
544 case EQ_PARAM_CUR_PRESET:
Eric Laurent3be95232010-07-30 09:12:51 -0700545 preset = (int32_t)(*(uint16_t *)pValue);
Eric Laurent135ad072010-05-21 06:05:13 -0700546
Steve Block3856b092011-10-20 11:56:00 +0100547 ALOGV("setParameter() EQ_PARAM_CUR_PRESET %d", preset);
Eric Laurent3be95232010-07-30 09:12:51 -0700548 if (preset < 0 || preset >= pEqualizer->getNumPresets()) {
Eric Laurent135ad072010-05-21 06:05:13 -0700549 status = -EINVAL;
550 break;
551 }
552 pEqualizer->setPreset(preset);
553 pEqualizer->commit(true);
554 break;
555 case EQ_PARAM_BAND_LEVEL:
556 band = *pParam;
Eric Laurent3be95232010-07-30 09:12:51 -0700557 level = (int32_t)(*(int16_t *)pValue);
Steve Block3856b092011-10-20 11:56:00 +0100558 ALOGV("setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level);
Eric Laurent135ad072010-05-21 06:05:13 -0700559 if (band >= kNumBands) {
560 status = -EINVAL;
561 break;
562 }
563 pEqualizer->setGain(band, level);
564 pEqualizer->commit(true);
565 break;
Eric Laurent3be95232010-07-30 09:12:51 -0700566 case EQ_PARAM_PROPERTIES: {
Steve Block3856b092011-10-20 11:56:00 +0100567 ALOGV("setParameter() EQ_PARAM_PROPERTIES");
Eric Laurent3be95232010-07-30 09:12:51 -0700568 int16_t *p = (int16_t *)pValue;
569 if ((int)p[0] >= pEqualizer->getNumPresets()) {
570 status = -EINVAL;
571 break;
572 }
573 if (p[0] >= 0) {
574 pEqualizer->setPreset((int)p[0]);
575 } else {
576 if ((int)p[1] != kNumBands) {
577 status = -EINVAL;
578 break;
579 }
580 for (int i = 0; i < kNumBands; i++) {
581 pEqualizer->setGain(i, (int32_t)p[2 + i]);
582 }
583 }
584 pEqualizer->commit(true);
585 } break;
Eric Laurent135ad072010-05-21 06:05:13 -0700586 default:
Steve Block3856b092011-10-20 11:56:00 +0100587 ALOGV("setParameter() invalid param %d", param);
Eric Laurent3be95232010-07-30 09:12:51 -0700588 status = -EINVAL;
Eric Laurent135ad072010-05-21 06:05:13 -0700589 break;
590 }
591
592 return status;
593} // end Equalizer_setParameter
594
595} // namespace
596} // namespace
597
598
599//
600//--- Effect Control Interface Implementation
601//
602
Eric Laurente1315cf2011-05-17 19:16:02 -0700603extern "C" int Equalizer_process(effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
Eric Laurent135ad072010-05-21 06:05:13 -0700604{
605 android::EqualizerContext * pContext = (android::EqualizerContext *) self;
606
607 if (pContext == NULL) {
608 return -EINVAL;
609 }
610 if (inBuffer == NULL || inBuffer->raw == NULL ||
611 outBuffer == NULL || outBuffer->raw == NULL ||
612 inBuffer->frameCount != outBuffer->frameCount) {
613 return -EINVAL;
614 }
615
Eric Laurente44b1ef2010-07-09 13:34:17 -0700616 if (pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
617 return -EINVAL;
618 }
619 if (pContext->state == EQUALIZER_STATE_INITIALIZED) {
620 return -ENODATA;
621 }
622
Eric Laurent135ad072010-05-21 06:05:13 -0700623 pContext->adapter.process(inBuffer->raw, outBuffer->raw, outBuffer->frameCount);
Eric Laurentffe9c252010-06-23 17:38:20 -0700624
Eric Laurent135ad072010-05-21 06:05:13 -0700625 return 0;
626} // end Equalizer_process
627
Eric Laurente1315cf2011-05-17 19:16:02 -0700628extern "C" int Equalizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
Eric Laurent25f43952010-07-28 05:40:18 -0700629 void *pCmdData, uint32_t *replySize, void *pReplyData) {
Eric Laurent135ad072010-05-21 06:05:13 -0700630
631 android::EqualizerContext * pContext = (android::EqualizerContext *) self;
632 int retsize;
633
Eric Laurente44b1ef2010-07-09 13:34:17 -0700634 if (pContext == NULL || pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
Eric Laurent135ad072010-05-21 06:05:13 -0700635 return -EINVAL;
636 }
637
638 android::AudioEqualizer * pEqualizer = pContext->pEqualizer;
639
Steve Block3856b092011-10-20 11:56:00 +0100640 ALOGV("Equalizer_command command %d cmdSize %d",cmdCode, cmdSize);
Eric Laurent135ad072010-05-21 06:05:13 -0700641
642 switch (cmdCode) {
643 case EFFECT_CMD_INIT:
644 if (pReplyData == NULL || *replySize != sizeof(int)) {
645 return -EINVAL;
646 }
647 *(int *) pReplyData = Equalizer_init(pContext);
648 break;
Eric Laurent3d5188b2011-12-16 15:30:36 -0800649 case EFFECT_CMD_SET_CONFIG:
Eric Laurent135ad072010-05-21 06:05:13 -0700650 if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
651 || pReplyData == NULL || *replySize != sizeof(int)) {
652 return -EINVAL;
653 }
Eric Laurent3d5188b2011-12-16 15:30:36 -0800654 *(int *) pReplyData = Equalizer_setConfig(pContext,
Eric Laurent135ad072010-05-21 06:05:13 -0700655 (effect_config_t *) pCmdData);
656 break;
Eric Laurent3d5188b2011-12-16 15:30:36 -0800657 case EFFECT_CMD_GET_CONFIG:
658 if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
659 return -EINVAL;
660 }
661 Equalizer_getConfig(pContext, (effect_config_t *) pCmdData);
662 break;
Eric Laurent135ad072010-05-21 06:05:13 -0700663 case EFFECT_CMD_RESET:
Eric Laurent3d5188b2011-12-16 15:30:36 -0800664 Equalizer_setConfig(pContext, &pContext->config);
Eric Laurent135ad072010-05-21 06:05:13 -0700665 break;
666 case EFFECT_CMD_GET_PARAM: {
Ashok Bhatb302bd52014-02-18 11:40:00 +0000667 if (pCmdData == NULL || cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) ||
668 pReplyData == NULL || *replySize < (sizeof(effect_param_t) + sizeof(int32_t))) {
Eric Laurent135ad072010-05-21 06:05:13 -0700669 return -EINVAL;
670 }
671 effect_param_t *p = (effect_param_t *)pCmdData;
672 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
673 p = (effect_param_t *)pReplyData;
674 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
675 p->status = android::Equalizer_getParameter(pEqualizer, (int32_t *)p->data, &p->vsize,
676 p->data + voffset);
677 *replySize = sizeof(effect_param_t) + voffset + p->vsize;
Steve Block3856b092011-10-20 11:56:00 +0100678 ALOGV("Equalizer_command EFFECT_CMD_GET_PARAM *pCmdData %d, *replySize %d, *pReplyData %08x %08x",
Eric Laurent135ad072010-05-21 06:05:13 -0700679 *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)), *replySize,
680 *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset),
681 *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset + sizeof(int32_t)));
682
683 } break;
684 case EFFECT_CMD_SET_PARAM: {
Steve Block3856b092011-10-20 11:56:00 +0100685 ALOGV("Equalizer_command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p",
Eric Laurente1315cf2011-05-17 19:16:02 -0700686 cmdSize, pCmdData, *replySize, pReplyData);
Ashok Bhatb302bd52014-02-18 11:40:00 +0000687 if (pCmdData == NULL || cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) ||
Eric Laurent135ad072010-05-21 06:05:13 -0700688 pReplyData == NULL || *replySize != sizeof(int32_t)) {
689 return -EINVAL;
690 }
691 effect_param_t *p = (effect_param_t *) pCmdData;
692 *(int *)pReplyData = android::Equalizer_setParameter(pEqualizer, (int32_t *)p->data,
693 p->data + p->psize);
694 } break;
Eric Laurentffe9c252010-06-23 17:38:20 -0700695 case EFFECT_CMD_ENABLE:
Eric Laurente44b1ef2010-07-09 13:34:17 -0700696 if (pReplyData == NULL || *replySize != sizeof(int)) {
697 return -EINVAL;
698 }
699 if (pContext->state != EQUALIZER_STATE_INITIALIZED) {
700 return -ENOSYS;
701 }
702 pContext->state = EQUALIZER_STATE_ACTIVE;
Steve Block3856b092011-10-20 11:56:00 +0100703 ALOGV("EFFECT_CMD_ENABLE() OK");
Eric Laurente44b1ef2010-07-09 13:34:17 -0700704 *(int *)pReplyData = 0;
705 break;
Eric Laurentffe9c252010-06-23 17:38:20 -0700706 case EFFECT_CMD_DISABLE:
707 if (pReplyData == NULL || *replySize != sizeof(int)) {
708 return -EINVAL;
709 }
Eric Laurente44b1ef2010-07-09 13:34:17 -0700710 if (pContext->state != EQUALIZER_STATE_ACTIVE) {
711 return -ENOSYS;
712 }
713 pContext->state = EQUALIZER_STATE_INITIALIZED;
Steve Block3856b092011-10-20 11:56:00 +0100714 ALOGV("EFFECT_CMD_DISABLE() OK");
Eric Laurentffe9c252010-06-23 17:38:20 -0700715 *(int *)pReplyData = 0;
716 break;
717 case EFFECT_CMD_SET_DEVICE:
718 case EFFECT_CMD_SET_VOLUME:
719 case EFFECT_CMD_SET_AUDIO_MODE:
720 break;
Eric Laurent135ad072010-05-21 06:05:13 -0700721 default:
Steve Block5ff1dd52012-01-05 23:22:43 +0000722 ALOGW("Equalizer_command invalid command %d",cmdCode);
Eric Laurent135ad072010-05-21 06:05:13 -0700723 return -EINVAL;
724 }
725
726 return 0;
727}
728
Eric Laurente1315cf2011-05-17 19:16:02 -0700729extern "C" int Equalizer_getDescriptor(effect_handle_t self,
730 effect_descriptor_t *pDescriptor)
731{
732 android::EqualizerContext * pContext = (android::EqualizerContext *) self;
733
734 if (pContext == NULL || pDescriptor == NULL) {
Steve Block3856b092011-10-20 11:56:00 +0100735 ALOGV("Equalizer_getDescriptor() invalid param");
Eric Laurente1315cf2011-05-17 19:16:02 -0700736 return -EINVAL;
737 }
738
Glenn Kastena189a682012-02-20 12:16:30 -0800739 *pDescriptor = android::gEqualizerDescriptor;
Eric Laurente1315cf2011-05-17 19:16:02 -0700740
741 return 0;
742}
743
744// effect_handle_t interface implementation for equalizer effect
Eric Laurent135ad072010-05-21 06:05:13 -0700745const struct effect_interface_s gEqualizerInterface = {
746 Equalizer_process,
Eric Laurente1315cf2011-05-17 19:16:02 -0700747 Equalizer_command,
Eric Laurentba7b8f82011-06-17 18:54:16 -0700748 Equalizer_getDescriptor,
749 NULL
Eric Laurent135ad072010-05-21 06:05:13 -0700750};
751
752
Eric Laurente1315cf2011-05-17 19:16:02 -0700753audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
754 tag : AUDIO_EFFECT_LIBRARY_TAG,
755 version : EFFECT_LIBRARY_API_VERSION,
756 name : "Test Equalizer Library",
757 implementor : "The Android Open Source Project",
Eric Laurente1315cf2011-05-17 19:16:02 -0700758 create_effect : android::EffectCreate,
759 release_effect : android::EffectRelease,
760 get_descriptor : android::EffectGetDescriptor,
761};