blob: 52fbf79e0d3cd888c9d0b0c538c7a2bb6ba70ee4 [file] [log] [blame]
Eric Laurent5fe37c62010-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 Laurent2c87e9c2010-07-09 12:28:50 -070019//
20#define LOG_NDEBUG 0
Eric Laurent5fe37c62010-05-21 06:05:13 -070021#include <cutils/log.h>
22#include <assert.h>
23#include <stdlib.h>
Eric Laurenta9d635d2010-05-25 12:38:34 -070024#include <string.h>
Eric Laurent5fe37c62010-05-21 06:05:13 -070025#include <new>
26#include "AudioEqualizer.h"
27#include "AudioBiquadFilter.h"
28#include "AudioFormatAdapter.h"
Eric Laurent5cc05262011-06-24 07:01:31 -070029#include <audio_effects/effect_equalizer.h>
30
Eric Laurent5fe37c62010-05-21 06:05:13 -070031
Eric Laurent0fb66c22011-05-17 19:16:02 -070032// effect_handle_t interface implementation for equalizer effect
Eric Laurent5fe37c62010-05-21 06:05:13 -070033extern "C" const struct effect_interface_s gEqualizerInterface;
34
Eric Laurent7d850f22010-07-09 13:34:17 -070035enum equalizer_state_e {
36 EQUALIZER_STATE_UNINITIALIZED,
37 EQUALIZER_STATE_INITIALIZED,
38 EQUALIZER_STATE_ACTIVE,
39};
40
Eric Laurent5fe37c62010-05-21 06:05:13 -070041namespace android {
42namespace {
43
44// Google Graphic Equalizer UUID: e25aa840-543b-11df-98a5-0002a5d5c51b
45const effect_descriptor_t gEqualizerDescriptor = {
46 {0x0bed4300, 0xddd6, 0x11db, 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
47 {0xe25aa840, 0x543b, 0x11df, 0x98a5, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
Eric Laurent0fb66c22011-05-17 19:16:02 -070048 EFFECT_CONTROL_API_VERSION,
Eric Laurent5fe37c62010-05-21 06:05:13 -070049 (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST),
Eric Laurent53334cd2010-06-23 17:38:20 -070050 0, // TODO
51 1,
Eric Laurent5fe37c62010-05-21 06:05:13 -070052 "Graphic Equalizer",
Eric Laurent0fb66c22011-05-17 19:16:02 -070053 "The Android Open Source Project",
Eric Laurent5fe37c62010-05-21 06:05:13 -070054};
Eric Laurent5fe37c62010-05-21 06:05:13 -070055
56/////////////////// BEGIN EQ PRESETS ///////////////////////////////////////////
57const int kNumBands = 5;
58const uint32_t gFreqs[kNumBands] = { 50000, 125000, 900000, 3200000, 6300000 };
59const uint32_t gBandwidths[kNumBands] = { 0, 3600, 3600, 2400, 0 };
60
61const AudioEqualizer::BandConfig gBandsClassic[kNumBands] = {
62 { 300, gFreqs[0], gBandwidths[0] },
63 { 400, gFreqs[1], gBandwidths[1] },
64 { 0, gFreqs[2], gBandwidths[2] },
65 { 200, gFreqs[3], gBandwidths[3] },
66 { -300, gFreqs[4], gBandwidths[4] }
67};
68
69const AudioEqualizer::BandConfig gBandsJazz[kNumBands] = {
70 { -600, gFreqs[0], gBandwidths[0] },
71 { 200, gFreqs[1], gBandwidths[1] },
72 { 400, gFreqs[2], gBandwidths[2] },
73 { -400, gFreqs[3], gBandwidths[3] },
74 { -600, gFreqs[4], gBandwidths[4] }
75};
76
77const AudioEqualizer::BandConfig gBandsPop[kNumBands] = {
78 { 400, gFreqs[0], gBandwidths[0] },
79 { -400, gFreqs[1], gBandwidths[1] },
80 { 300, gFreqs[2], gBandwidths[2] },
81 { -400, gFreqs[3], gBandwidths[3] },
82 { 600, gFreqs[4], gBandwidths[4] }
83};
84
85const AudioEqualizer::BandConfig gBandsRock[kNumBands] = {
86 { 700, gFreqs[0], gBandwidths[0] },
87 { 400, gFreqs[1], gBandwidths[1] },
88 { -400, gFreqs[2], gBandwidths[2] },
89 { 400, gFreqs[3], gBandwidths[3] },
90 { 200, gFreqs[4], gBandwidths[4] }
91};
92
93const AudioEqualizer::PresetConfig gEqualizerPresets[] = {
94 { "Classic", gBandsClassic },
95 { "Jazz", gBandsJazz },
96 { "Pop", gBandsPop },
97 { "Rock", gBandsRock }
98};
99
100/////////////////// END EQ PRESETS /////////////////////////////////////////////
101
102static const size_t kBufferSize = 32;
103
104typedef AudioFormatAdapter<AudioEqualizer, kBufferSize> FormatAdapter;
105
106struct EqualizerContext {
107 const struct effect_interface_s *itfe;
108 effect_config_t config;
109 FormatAdapter adapter;
110 AudioEqualizer * pEqualizer;
Eric Laurent7d850f22010-07-09 13:34:17 -0700111 uint32_t state;
Eric Laurent5fe37c62010-05-21 06:05:13 -0700112};
113
Eric Laurent5fe37c62010-05-21 06:05:13 -0700114//--- local function prototypes
115
116int Equalizer_init(EqualizerContext *pContext);
Eric Laurent4abf8822011-12-16 15:30:36 -0800117int Equalizer_setConfig(EqualizerContext *pContext, effect_config_t *pConfig);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700118int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue);
119int Equalizer_setParameter(AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue);
120
121
122//
123//--- Effect Library Interface Implementation
124//
125
Eric Laurent65b65452010-06-01 23:49:17 -0700126extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects) {
Eric Laurent5fe37c62010-05-21 06:05:13 -0700127 *pNumEffects = 1;
Eric Laurent5fe37c62010-05-21 06:05:13 -0700128 return 0;
129} /* end EffectQueryNumberEffects */
130
Eric Laurent0fb66c22011-05-17 19:16:02 -0700131extern "C" int EffectQueryEffect(uint32_t index,
132 effect_descriptor_t *pDescriptor) {
Eric Laurent5fe37c62010-05-21 06:05:13 -0700133 if (pDescriptor == NULL) {
134 return -EINVAL;
135 }
Eric Laurent53334cd2010-06-23 17:38:20 -0700136 if (index > 0) {
137 return -EINVAL;
Eric Laurent5fe37c62010-05-21 06:05:13 -0700138 }
139 memcpy(pDescriptor, &gEqualizerDescriptor, sizeof(effect_descriptor_t));
140 return 0;
141} /* end EffectQueryNext */
142
143extern "C" int EffectCreate(effect_uuid_t *uuid,
Eric Laurent0fb66c22011-05-17 19:16:02 -0700144 int32_t sessionId,
145 int32_t ioId,
146 effect_handle_t *pHandle) {
Eric Laurent5fe37c62010-05-21 06:05:13 -0700147 int ret;
148 int i;
149
Steve Block71f2cf12011-10-20 11:56:00 +0100150 ALOGV("EffectLibCreateEffect start");
Eric Laurent5fe37c62010-05-21 06:05:13 -0700151
Eric Laurent0fb66c22011-05-17 19:16:02 -0700152 if (pHandle == NULL || uuid == NULL) {
Eric Laurent5fe37c62010-05-21 06:05:13 -0700153 return -EINVAL;
154 }
155
156 if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) != 0) {
157 return -EINVAL;
158 }
159
160 EqualizerContext *pContext = new EqualizerContext;
161
162 pContext->itfe = &gEqualizerInterface;
163 pContext->pEqualizer = NULL;
Eric Laurent7d850f22010-07-09 13:34:17 -0700164 pContext->state = EQUALIZER_STATE_UNINITIALIZED;
Eric Laurent5fe37c62010-05-21 06:05:13 -0700165
166 ret = Equalizer_init(pContext);
167 if (ret < 0) {
168 LOGW("EffectLibCreateEffect() init failed");
169 delete pContext;
170 return ret;
171 }
172
Eric Laurent0fb66c22011-05-17 19:16:02 -0700173 *pHandle = (effect_handle_t)pContext;
Eric Laurent7d850f22010-07-09 13:34:17 -0700174 pContext->state = EQUALIZER_STATE_INITIALIZED;
Eric Laurent5fe37c62010-05-21 06:05:13 -0700175
Steve Block71f2cf12011-10-20 11:56:00 +0100176 ALOGV("EffectLibCreateEffect %p, size %d",
Eric Laurent0fb66c22011-05-17 19:16:02 -0700177 pContext, AudioEqualizer::GetInstanceSize(kNumBands)+sizeof(EqualizerContext));
Eric Laurent5fe37c62010-05-21 06:05:13 -0700178
179 return 0;
180
181} /* end EffectCreate */
182
Eric Laurent0fb66c22011-05-17 19:16:02 -0700183extern "C" int EffectRelease(effect_handle_t handle) {
184 EqualizerContext * pContext = (EqualizerContext *)handle;
Eric Laurent5fe37c62010-05-21 06:05:13 -0700185
Steve Block71f2cf12011-10-20 11:56:00 +0100186 ALOGV("EffectLibReleaseEffect %p", handle);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700187 if (pContext == NULL) {
188 return -EINVAL;
189 }
190
Eric Laurent7d850f22010-07-09 13:34:17 -0700191 pContext->state = EQUALIZER_STATE_UNINITIALIZED;
Eric Laurent5fe37c62010-05-21 06:05:13 -0700192 pContext->pEqualizer->free();
193 delete pContext;
194
195 return 0;
196} /* end EffectRelease */
197
Eric Laurent0fb66c22011-05-17 19:16:02 -0700198extern "C" int EffectGetDescriptor(effect_uuid_t *uuid,
199 effect_descriptor_t *pDescriptor) {
200
201 if (pDescriptor == NULL || uuid == NULL){
Steve Block71f2cf12011-10-20 11:56:00 +0100202 ALOGV("EffectGetDescriptor() called with NULL pointer");
Eric Laurent0fb66c22011-05-17 19:16:02 -0700203 return -EINVAL;
204 }
205
206 if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0) {
207 memcpy(pDescriptor, &gEqualizerDescriptor, sizeof(effect_descriptor_t));
208 return 0;
209 }
210
211 return -EINVAL;
212} /* end EffectGetDescriptor */
213
Eric Laurent5fe37c62010-05-21 06:05:13 -0700214
215//
216//--- local functions
217//
218
219#define CHECK_ARG(cond) { \
220 if (!(cond)) { \
Steve Block71f2cf12011-10-20 11:56:00 +0100221 ALOGV("Invalid argument: "#cond); \
Eric Laurent5fe37c62010-05-21 06:05:13 -0700222 return -EINVAL; \
223 } \
224}
225
226//----------------------------------------------------------------------------
Eric Laurent4abf8822011-12-16 15:30:36 -0800227// Equalizer_setConfig()
Eric Laurent5fe37c62010-05-21 06:05:13 -0700228//----------------------------------------------------------------------------
229// Purpose: Set input and output audio configuration.
230//
231// Inputs:
232// pContext: effect engine context
233// pConfig: pointer to effect_config_t structure holding input and output
234// configuration parameters
235//
236// Outputs:
237//
238//----------------------------------------------------------------------------
239
Eric Laurent4abf8822011-12-16 15:30:36 -0800240int Equalizer_setConfig(EqualizerContext *pContext, effect_config_t *pConfig)
Eric Laurent5fe37c62010-05-21 06:05:13 -0700241{
Eric Laurent4abf8822011-12-16 15:30:36 -0800242 ALOGV("Equalizer_setConfig start");
Eric Laurent5fe37c62010-05-21 06:05:13 -0700243
244 CHECK_ARG(pContext != NULL);
245 CHECK_ARG(pConfig != NULL);
246
247 CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
248 CHECK_ARG(pConfig->inputCfg.channels == pConfig->outputCfg.channels);
249 CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
Eric Laurent0fb66c22011-05-17 19:16:02 -0700250 CHECK_ARG((pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_MONO) ||
251 (pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_STEREO));
Eric Laurent5fe37c62010-05-21 06:05:13 -0700252 CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
253 || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
Eric Laurent0fb66c22011-05-17 19:16:02 -0700254 CHECK_ARG(pConfig->inputCfg.format == AUDIO_FORMAT_PCM_8_24_BIT
255 || pConfig->inputCfg.format == AUDIO_FORMAT_PCM_16_BIT);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700256
257 int channelCount;
Eric Laurent0fb66c22011-05-17 19:16:02 -0700258 if (pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_MONO) {
Eric Laurent5fe37c62010-05-21 06:05:13 -0700259 channelCount = 1;
260 } else {
261 channelCount = 2;
262 }
263 CHECK_ARG(channelCount <= AudioBiquadFilter::MAX_CHANNELS);
264
Eric Laurent53334cd2010-06-23 17:38:20 -0700265 memcpy(&pContext->config, pConfig, sizeof(effect_config_t));
266
Eric Laurent5fe37c62010-05-21 06:05:13 -0700267 pContext->pEqualizer->configure(channelCount,
268 pConfig->inputCfg.samplingRate);
269
270 pContext->adapter.configure(*pContext->pEqualizer, channelCount,
271 pConfig->inputCfg.format,
272 pConfig->outputCfg.accessMode);
273
274 return 0;
Eric Laurent4abf8822011-12-16 15:30:36 -0800275} // end Equalizer_setConfig
276
277//----------------------------------------------------------------------------
278// Equalizer_getConfig()
279//----------------------------------------------------------------------------
280// Purpose: Get input and output audio configuration.
281//
282// Inputs:
283// pContext: effect engine context
284// pConfig: pointer to effect_config_t structure holding input and output
285// configuration parameters
286//
287// Outputs:
288//
289//----------------------------------------------------------------------------
290
291void Equalizer_getConfig(EqualizerContext *pContext, effect_config_t *pConfig)
292{
293 memcpy(pConfig, &pContext->config, sizeof(effect_config_t));
294} // end Equalizer_getConfig
Eric Laurent5fe37c62010-05-21 06:05:13 -0700295
296
297//----------------------------------------------------------------------------
298// Equalizer_init()
299//----------------------------------------------------------------------------
300// Purpose: Initialize engine with default configuration and creates
301// AudioEqualizer instance.
302//
303// Inputs:
304// pContext: effect engine context
305//
306// Outputs:
307//
308//----------------------------------------------------------------------------
309
310int Equalizer_init(EqualizerContext *pContext)
311{
312 int status;
313
Steve Block71f2cf12011-10-20 11:56:00 +0100314 ALOGV("Equalizer_init start");
Eric Laurent5fe37c62010-05-21 06:05:13 -0700315
316 CHECK_ARG(pContext != NULL);
317
318 if (pContext->pEqualizer != NULL) {
319 pContext->pEqualizer->free();
320 }
321
322 pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
Eric Laurent0fb66c22011-05-17 19:16:02 -0700323 pContext->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
324 pContext->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Eric Laurent5fe37c62010-05-21 06:05:13 -0700325 pContext->config.inputCfg.samplingRate = 44100;
326 pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
327 pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
328 pContext->config.inputCfg.bufferProvider.cookie = NULL;
329 pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
330 pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
Eric Laurent0fb66c22011-05-17 19:16:02 -0700331 pContext->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
332 pContext->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
Eric Laurent5fe37c62010-05-21 06:05:13 -0700333 pContext->config.outputCfg.samplingRate = 44100;
334 pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
335 pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
336 pContext->config.outputCfg.bufferProvider.cookie = NULL;
337 pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL;
338
339 pContext->pEqualizer = AudioEqualizer::CreateInstance(
340 NULL,
341 kNumBands,
342 AudioBiquadFilter::MAX_CHANNELS,
343 44100,
344 gEqualizerPresets,
345 ARRAY_SIZE(gEqualizerPresets));
346
347 for (int i = 0; i < kNumBands; ++i) {
348 pContext->pEqualizer->setFrequency(i, gFreqs[i]);
349 pContext->pEqualizer->setBandwidth(i, gBandwidths[i]);
350 }
351
352 pContext->pEqualizer->enable(true);
353
Eric Laurent4abf8822011-12-16 15:30:36 -0800354 Equalizer_setConfig(pContext, &pContext->config);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700355
356 return 0;
357} // end Equalizer_init
358
359
360//----------------------------------------------------------------------------
361// Equalizer_getParameter()
362//----------------------------------------------------------------------------
363// Purpose:
364// Get a Equalizer parameter
365//
366// Inputs:
367// pEqualizer - handle to instance data
368// pParam - pointer to parameter
369// pValue - pointer to variable to hold retrieved value
370// pValueSize - pointer to value size: maximum size as input
371//
372// Outputs:
373// *pValue updated with parameter value
374// *pValueSize updated with actual value size
375//
376//
377// Side Effects:
378//
379//----------------------------------------------------------------------------
380
381int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue)
382{
383 int status = 0;
384 int32_t param = *pParam++;
385 int32_t param2;
386 char *name;
387
388 switch (param) {
389 case EQ_PARAM_NUM_BANDS:
390 case EQ_PARAM_CUR_PRESET:
391 case EQ_PARAM_GET_NUM_OF_PRESETS:
Eric Laurent92e847e2010-07-30 09:12:51 -0700392 case EQ_PARAM_BAND_LEVEL:
393 case EQ_PARAM_GET_BAND:
Eric Laurent5fe37c62010-05-21 06:05:13 -0700394 if (*pValueSize < sizeof(int16_t)) {
395 return -EINVAL;
396 }
397 *pValueSize = sizeof(int16_t);
398 break;
399
400 case EQ_PARAM_LEVEL_RANGE:
Eric Laurent92e847e2010-07-30 09:12:51 -0700401 if (*pValueSize < 2 * sizeof(int16_t)) {
402 return -EINVAL;
403 }
404 *pValueSize = 2 * sizeof(int16_t);
405 break;
406
Eric Laurent5fe37c62010-05-21 06:05:13 -0700407 case EQ_PARAM_BAND_FREQ_RANGE:
408 if (*pValueSize < 2 * sizeof(int32_t)) {
409 return -EINVAL;
410 }
411 *pValueSize = 2 * sizeof(int32_t);
412 break;
Eric Laurent92e847e2010-07-30 09:12:51 -0700413
Eric Laurent5fe37c62010-05-21 06:05:13 -0700414 case EQ_PARAM_CENTER_FREQ:
415 if (*pValueSize < sizeof(int32_t)) {
416 return -EINVAL;
417 }
418 *pValueSize = sizeof(int32_t);
419 break;
420
421 case EQ_PARAM_GET_PRESET_NAME:
422 break;
423
Eric Laurent92e847e2010-07-30 09:12:51 -0700424 case EQ_PARAM_PROPERTIES:
425 if (*pValueSize < (2 + kNumBands) * sizeof(uint16_t)) {
426 return -EINVAL;
427 }
428 *pValueSize = (2 + kNumBands) * sizeof(uint16_t);
429 break;
430
Eric Laurent5fe37c62010-05-21 06:05:13 -0700431 default:
432 return -EINVAL;
433 }
434
435 switch (param) {
436 case EQ_PARAM_NUM_BANDS:
Eric Laurent92e847e2010-07-30 09:12:51 -0700437 *(uint16_t *)pValue = (uint16_t)kNumBands;
Steve Block71f2cf12011-10-20 11:56:00 +0100438 ALOGV("Equalizer_getParameter() EQ_PARAM_NUM_BANDS %d", *(int16_t *)pValue);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700439 break;
440
441 case EQ_PARAM_LEVEL_RANGE:
Eric Laurent92e847e2010-07-30 09:12:51 -0700442 *(int16_t *)pValue = -9600;
443 *((int16_t *)pValue + 1) = 4800;
Steve Block71f2cf12011-10-20 11:56:00 +0100444 ALOGV("Equalizer_getParameter() EQ_PARAM_LEVEL_RANGE min %d, max %d",
Eric Laurent0fb66c22011-05-17 19:16:02 -0700445 *(int32_t *)pValue, *((int32_t *)pValue + 1));
Eric Laurent5fe37c62010-05-21 06:05:13 -0700446 break;
447
448 case EQ_PARAM_BAND_LEVEL:
449 param2 = *pParam;
450 if (param2 >= kNumBands) {
451 status = -EINVAL;
452 break;
453 }
Eric Laurent92e847e2010-07-30 09:12:51 -0700454 *(int16_t *)pValue = (int16_t)pEqualizer->getGain(param2);
Steve Block71f2cf12011-10-20 11:56:00 +0100455 ALOGV("Equalizer_getParameter() EQ_PARAM_BAND_LEVEL band %d, level %d",
Eric Laurent0fb66c22011-05-17 19:16:02 -0700456 param2, *(int32_t *)pValue);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700457 break;
458
459 case EQ_PARAM_CENTER_FREQ:
460 param2 = *pParam;
461 if (param2 >= kNumBands) {
462 status = -EINVAL;
463 break;
464 }
465 *(int32_t *)pValue = pEqualizer->getFrequency(param2);
Steve Block71f2cf12011-10-20 11:56:00 +0100466 ALOGV("Equalizer_getParameter() EQ_PARAM_CENTER_FREQ band %d, frequency %d",
Eric Laurent0fb66c22011-05-17 19:16:02 -0700467 param2, *(int32_t *)pValue);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700468 break;
469
470 case EQ_PARAM_BAND_FREQ_RANGE:
471 param2 = *pParam;
472 if (param2 >= kNumBands) {
473 status = -EINVAL;
474 break;
475 }
476 pEqualizer->getBandRange(param2, *(uint32_t *)pValue, *((uint32_t *)pValue + 1));
Steve Block71f2cf12011-10-20 11:56:00 +0100477 ALOGV("Equalizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d, min %d, max %d",
Eric Laurent0fb66c22011-05-17 19:16:02 -0700478 param2, *(int32_t *)pValue, *((int32_t *)pValue + 1));
Eric Laurent5fe37c62010-05-21 06:05:13 -0700479 break;
480
481 case EQ_PARAM_GET_BAND:
482 param2 = *pParam;
Eric Laurent92e847e2010-07-30 09:12:51 -0700483 *(uint16_t *)pValue = (uint16_t)pEqualizer->getMostRelevantBand(param2);
Steve Block71f2cf12011-10-20 11:56:00 +0100484 ALOGV("Equalizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d",
Eric Laurent0fb66c22011-05-17 19:16:02 -0700485 param2, *(int32_t *)pValue);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700486 break;
487
488 case EQ_PARAM_CUR_PRESET:
Eric Laurent92e847e2010-07-30 09:12:51 -0700489 *(uint16_t *)pValue = (uint16_t)pEqualizer->getPreset();
Steve Block71f2cf12011-10-20 11:56:00 +0100490 ALOGV("Equalizer_getParameter() EQ_PARAM_CUR_PRESET %d", *(int32_t *)pValue);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700491 break;
492
493 case EQ_PARAM_GET_NUM_OF_PRESETS:
Eric Laurent92e847e2010-07-30 09:12:51 -0700494 *(uint16_t *)pValue = (uint16_t)pEqualizer->getNumPresets();
Steve Block71f2cf12011-10-20 11:56:00 +0100495 ALOGV("Equalizer_getParameter() EQ_PARAM_GET_NUM_OF_PRESETS %d", *(int16_t *)pValue);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700496 break;
497
498 case EQ_PARAM_GET_PRESET_NAME:
499 param2 = *pParam;
500 if (param2 >= pEqualizer->getNumPresets()) {
501 status = -EINVAL;
502 break;
503 }
504 name = (char *)pValue;
505 strncpy(name, pEqualizer->getPresetName(param2), *pValueSize - 1);
506 name[*pValueSize - 1] = 0;
507 *pValueSize = strlen(name) + 1;
Steve Block71f2cf12011-10-20 11:56:00 +0100508 ALOGV("Equalizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d",
Eric Laurent0fb66c22011-05-17 19:16:02 -0700509 param2, gEqualizerPresets[param2].name, *pValueSize);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700510 break;
511
Eric Laurent92e847e2010-07-30 09:12:51 -0700512 case EQ_PARAM_PROPERTIES: {
513 int16_t *p = (int16_t *)pValue;
Steve Block71f2cf12011-10-20 11:56:00 +0100514 ALOGV("Equalizer_getParameter() EQ_PARAM_PROPERTIES");
Eric Laurent92e847e2010-07-30 09:12:51 -0700515 p[0] = (int16_t)pEqualizer->getPreset();
516 p[1] = (int16_t)kNumBands;
517 for (int i = 0; i < kNumBands; i++) {
518 p[2 + i] = (int16_t)pEqualizer->getGain(i);
519 }
520 } break;
521
Eric Laurent5fe37c62010-05-21 06:05:13 -0700522 default:
Steve Block71f2cf12011-10-20 11:56:00 +0100523 ALOGV("Equalizer_getParameter() invalid param %d", param);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700524 status = -EINVAL;
525 break;
526 }
527
528 return status;
529} // end Equalizer_getParameter
530
531
532//----------------------------------------------------------------------------
533// Equalizer_setParameter()
534//----------------------------------------------------------------------------
535// Purpose:
536// Set a Equalizer parameter
537//
538// Inputs:
539// pEqualizer - handle to instance data
540// pParam - pointer to parameter
541// pValue - pointer to value
542//
543// Outputs:
544//
545//
546// Side Effects:
547//
548//----------------------------------------------------------------------------
549
550int Equalizer_setParameter (AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue)
551{
552 int status = 0;
553 int32_t preset;
554 int32_t band;
555 int32_t level;
556 int32_t param = *pParam++;
557
558
559 switch (param) {
560 case EQ_PARAM_CUR_PRESET:
Eric Laurent92e847e2010-07-30 09:12:51 -0700561 preset = (int32_t)(*(uint16_t *)pValue);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700562
Steve Block71f2cf12011-10-20 11:56:00 +0100563 ALOGV("setParameter() EQ_PARAM_CUR_PRESET %d", preset);
Eric Laurent92e847e2010-07-30 09:12:51 -0700564 if (preset < 0 || preset >= pEqualizer->getNumPresets()) {
Eric Laurent5fe37c62010-05-21 06:05:13 -0700565 status = -EINVAL;
566 break;
567 }
568 pEqualizer->setPreset(preset);
569 pEqualizer->commit(true);
570 break;
571 case EQ_PARAM_BAND_LEVEL:
572 band = *pParam;
Eric Laurent92e847e2010-07-30 09:12:51 -0700573 level = (int32_t)(*(int16_t *)pValue);
Steve Block71f2cf12011-10-20 11:56:00 +0100574 ALOGV("setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700575 if (band >= kNumBands) {
576 status = -EINVAL;
577 break;
578 }
579 pEqualizer->setGain(band, level);
580 pEqualizer->commit(true);
581 break;
Eric Laurent92e847e2010-07-30 09:12:51 -0700582 case EQ_PARAM_PROPERTIES: {
Steve Block71f2cf12011-10-20 11:56:00 +0100583 ALOGV("setParameter() EQ_PARAM_PROPERTIES");
Eric Laurent92e847e2010-07-30 09:12:51 -0700584 int16_t *p = (int16_t *)pValue;
585 if ((int)p[0] >= pEqualizer->getNumPresets()) {
586 status = -EINVAL;
587 break;
588 }
589 if (p[0] >= 0) {
590 pEqualizer->setPreset((int)p[0]);
591 } else {
592 if ((int)p[1] != kNumBands) {
593 status = -EINVAL;
594 break;
595 }
596 for (int i = 0; i < kNumBands; i++) {
597 pEqualizer->setGain(i, (int32_t)p[2 + i]);
598 }
599 }
600 pEqualizer->commit(true);
601 } break;
Eric Laurent5fe37c62010-05-21 06:05:13 -0700602 default:
Steve Block71f2cf12011-10-20 11:56:00 +0100603 ALOGV("setParameter() invalid param %d", param);
Eric Laurent92e847e2010-07-30 09:12:51 -0700604 status = -EINVAL;
Eric Laurent5fe37c62010-05-21 06:05:13 -0700605 break;
606 }
607
608 return status;
609} // end Equalizer_setParameter
610
611} // namespace
612} // namespace
613
614
615//
616//--- Effect Control Interface Implementation
617//
618
Eric Laurent0fb66c22011-05-17 19:16:02 -0700619extern "C" int Equalizer_process(effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
Eric Laurent5fe37c62010-05-21 06:05:13 -0700620{
621 android::EqualizerContext * pContext = (android::EqualizerContext *) self;
622
623 if (pContext == NULL) {
624 return -EINVAL;
625 }
626 if (inBuffer == NULL || inBuffer->raw == NULL ||
627 outBuffer == NULL || outBuffer->raw == NULL ||
628 inBuffer->frameCount != outBuffer->frameCount) {
629 return -EINVAL;
630 }
631
Eric Laurent7d850f22010-07-09 13:34:17 -0700632 if (pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
633 return -EINVAL;
634 }
635 if (pContext->state == EQUALIZER_STATE_INITIALIZED) {
636 return -ENODATA;
637 }
638
Eric Laurent5fe37c62010-05-21 06:05:13 -0700639 pContext->adapter.process(inBuffer->raw, outBuffer->raw, outBuffer->frameCount);
Eric Laurent53334cd2010-06-23 17:38:20 -0700640
Eric Laurent5fe37c62010-05-21 06:05:13 -0700641 return 0;
642} // end Equalizer_process
643
Eric Laurent0fb66c22011-05-17 19:16:02 -0700644extern "C" int Equalizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
Eric Laurenta4c72ac2010-07-28 05:40:18 -0700645 void *pCmdData, uint32_t *replySize, void *pReplyData) {
Eric Laurent5fe37c62010-05-21 06:05:13 -0700646
647 android::EqualizerContext * pContext = (android::EqualizerContext *) self;
648 int retsize;
649
Eric Laurent7d850f22010-07-09 13:34:17 -0700650 if (pContext == NULL || pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
Eric Laurent5fe37c62010-05-21 06:05:13 -0700651 return -EINVAL;
652 }
653
654 android::AudioEqualizer * pEqualizer = pContext->pEqualizer;
655
Steve Block71f2cf12011-10-20 11:56:00 +0100656 ALOGV("Equalizer_command command %d cmdSize %d",cmdCode, cmdSize);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700657
658 switch (cmdCode) {
659 case EFFECT_CMD_INIT:
660 if (pReplyData == NULL || *replySize != sizeof(int)) {
661 return -EINVAL;
662 }
663 *(int *) pReplyData = Equalizer_init(pContext);
664 break;
Eric Laurent4abf8822011-12-16 15:30:36 -0800665 case EFFECT_CMD_SET_CONFIG:
Eric Laurent5fe37c62010-05-21 06:05:13 -0700666 if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
667 || pReplyData == NULL || *replySize != sizeof(int)) {
668 return -EINVAL;
669 }
Eric Laurent4abf8822011-12-16 15:30:36 -0800670 *(int *) pReplyData = Equalizer_setConfig(pContext,
Eric Laurent5fe37c62010-05-21 06:05:13 -0700671 (effect_config_t *) pCmdData);
672 break;
Eric Laurent4abf8822011-12-16 15:30:36 -0800673 case EFFECT_CMD_GET_CONFIG:
674 if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
675 return -EINVAL;
676 }
677 Equalizer_getConfig(pContext, (effect_config_t *) pCmdData);
678 break;
Eric Laurent5fe37c62010-05-21 06:05:13 -0700679 case EFFECT_CMD_RESET:
Eric Laurent4abf8822011-12-16 15:30:36 -0800680 Equalizer_setConfig(pContext, &pContext->config);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700681 break;
682 case EFFECT_CMD_GET_PARAM: {
683 if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
684 pReplyData == NULL || *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))) {
685 return -EINVAL;
686 }
687 effect_param_t *p = (effect_param_t *)pCmdData;
688 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
689 p = (effect_param_t *)pReplyData;
690 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
691 p->status = android::Equalizer_getParameter(pEqualizer, (int32_t *)p->data, &p->vsize,
692 p->data + voffset);
693 *replySize = sizeof(effect_param_t) + voffset + p->vsize;
Steve Block71f2cf12011-10-20 11:56:00 +0100694 ALOGV("Equalizer_command EFFECT_CMD_GET_PARAM *pCmdData %d, *replySize %d, *pReplyData %08x %08x",
Eric Laurent5fe37c62010-05-21 06:05:13 -0700695 *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)), *replySize,
696 *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset),
697 *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset + sizeof(int32_t)));
698
699 } break;
700 case EFFECT_CMD_SET_PARAM: {
Steve Block71f2cf12011-10-20 11:56:00 +0100701 ALOGV("Equalizer_command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p",
Eric Laurent0fb66c22011-05-17 19:16:02 -0700702 cmdSize, pCmdData, *replySize, pReplyData);
Eric Laurent5fe37c62010-05-21 06:05:13 -0700703 if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
704 pReplyData == NULL || *replySize != sizeof(int32_t)) {
705 return -EINVAL;
706 }
707 effect_param_t *p = (effect_param_t *) pCmdData;
708 *(int *)pReplyData = android::Equalizer_setParameter(pEqualizer, (int32_t *)p->data,
709 p->data + p->psize);
710 } break;
Eric Laurent53334cd2010-06-23 17:38:20 -0700711 case EFFECT_CMD_ENABLE:
Eric Laurent7d850f22010-07-09 13:34:17 -0700712 if (pReplyData == NULL || *replySize != sizeof(int)) {
713 return -EINVAL;
714 }
715 if (pContext->state != EQUALIZER_STATE_INITIALIZED) {
716 return -ENOSYS;
717 }
718 pContext->state = EQUALIZER_STATE_ACTIVE;
Steve Block71f2cf12011-10-20 11:56:00 +0100719 ALOGV("EFFECT_CMD_ENABLE() OK");
Eric Laurent7d850f22010-07-09 13:34:17 -0700720 *(int *)pReplyData = 0;
721 break;
Eric Laurent53334cd2010-06-23 17:38:20 -0700722 case EFFECT_CMD_DISABLE:
723 if (pReplyData == NULL || *replySize != sizeof(int)) {
724 return -EINVAL;
725 }
Eric Laurent7d850f22010-07-09 13:34:17 -0700726 if (pContext->state != EQUALIZER_STATE_ACTIVE) {
727 return -ENOSYS;
728 }
729 pContext->state = EQUALIZER_STATE_INITIALIZED;
Steve Block71f2cf12011-10-20 11:56:00 +0100730 ALOGV("EFFECT_CMD_DISABLE() OK");
Eric Laurent53334cd2010-06-23 17:38:20 -0700731 *(int *)pReplyData = 0;
732 break;
733 case EFFECT_CMD_SET_DEVICE:
734 case EFFECT_CMD_SET_VOLUME:
735 case EFFECT_CMD_SET_AUDIO_MODE:
736 break;
Eric Laurent5fe37c62010-05-21 06:05:13 -0700737 default:
738 LOGW("Equalizer_command invalid command %d",cmdCode);
739 return -EINVAL;
740 }
741
742 return 0;
743}
744
Eric Laurent0fb66c22011-05-17 19:16:02 -0700745extern "C" int Equalizer_getDescriptor(effect_handle_t self,
746 effect_descriptor_t *pDescriptor)
747{
748 android::EqualizerContext * pContext = (android::EqualizerContext *) self;
749
750 if (pContext == NULL || pDescriptor == NULL) {
Steve Block71f2cf12011-10-20 11:56:00 +0100751 ALOGV("Equalizer_getDescriptor() invalid param");
Eric Laurent0fb66c22011-05-17 19:16:02 -0700752 return -EINVAL;
753 }
754
755 memcpy(pDescriptor, &android::gEqualizerDescriptor, sizeof(effect_descriptor_t));
756
757 return 0;
758}
759
760// effect_handle_t interface implementation for equalizer effect
Eric Laurent5fe37c62010-05-21 06:05:13 -0700761const struct effect_interface_s gEqualizerInterface = {
762 Equalizer_process,
Eric Laurent0fb66c22011-05-17 19:16:02 -0700763 Equalizer_command,
Eric Laurent325b8e82011-06-17 18:54:16 -0700764 Equalizer_getDescriptor,
765 NULL
Eric Laurent5fe37c62010-05-21 06:05:13 -0700766};
767
768
Eric Laurent0fb66c22011-05-17 19:16:02 -0700769audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
770 tag : AUDIO_EFFECT_LIBRARY_TAG,
771 version : EFFECT_LIBRARY_API_VERSION,
772 name : "Test Equalizer Library",
773 implementor : "The Android Open Source Project",
774 query_num_effects : android::EffectQueryNumberEffects,
775 query_effect : android::EffectQueryEffect,
776 create_effect : android::EffectCreate,
777 release_effect : android::EffectRelease,
778 get_descriptor : android::EffectGetDescriptor,
779};