blob: e39e59542766c814b3294190b752ae68ed9c7942 [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])
19//#define LOG_NDEBUG 0
20#include <cutils/log.h>
21#include <assert.h>
22#include <stdlib.h>
Eric Laurent17217ab2010-05-25 12:38:34 -070023#include <string.h>
Eric Laurent135ad072010-05-21 06:05:13 -070024#include <new>
25#include "AudioEqualizer.h"
26#include "AudioBiquadFilter.h"
27#include "AudioFormatAdapter.h"
28#include <media/EffectEqualizerApi.h>
29
30// effect_interface_t interface implementation for equalizer effect
31extern "C" const struct effect_interface_s gEqualizerInterface;
32
33namespace android {
34namespace {
35
36// Google Graphic Equalizer UUID: e25aa840-543b-11df-98a5-0002a5d5c51b
37const effect_descriptor_t gEqualizerDescriptor = {
38 {0x0bed4300, 0xddd6, 0x11db, 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
39 {0xe25aa840, 0x543b, 0x11df, 0x98a5, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
40 EFFECT_API_VERSION,
41 (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST),
42 "Graphic Equalizer",
43 "Google Inc.",
44};
45static int gEffectIndex;
46
47/////////////////// BEGIN EQ PRESETS ///////////////////////////////////////////
48const int kNumBands = 5;
49const uint32_t gFreqs[kNumBands] = { 50000, 125000, 900000, 3200000, 6300000 };
50const uint32_t gBandwidths[kNumBands] = { 0, 3600, 3600, 2400, 0 };
51
52const AudioEqualizer::BandConfig gBandsClassic[kNumBands] = {
53 { 300, gFreqs[0], gBandwidths[0] },
54 { 400, gFreqs[1], gBandwidths[1] },
55 { 0, gFreqs[2], gBandwidths[2] },
56 { 200, gFreqs[3], gBandwidths[3] },
57 { -300, gFreqs[4], gBandwidths[4] }
58};
59
60const AudioEqualizer::BandConfig gBandsJazz[kNumBands] = {
61 { -600, gFreqs[0], gBandwidths[0] },
62 { 200, gFreqs[1], gBandwidths[1] },
63 { 400, gFreqs[2], gBandwidths[2] },
64 { -400, gFreqs[3], gBandwidths[3] },
65 { -600, gFreqs[4], gBandwidths[4] }
66};
67
68const AudioEqualizer::BandConfig gBandsPop[kNumBands] = {
69 { 400, gFreqs[0], gBandwidths[0] },
70 { -400, gFreqs[1], gBandwidths[1] },
71 { 300, gFreqs[2], gBandwidths[2] },
72 { -400, gFreqs[3], gBandwidths[3] },
73 { 600, gFreqs[4], gBandwidths[4] }
74};
75
76const AudioEqualizer::BandConfig gBandsRock[kNumBands] = {
77 { 700, gFreqs[0], gBandwidths[0] },
78 { 400, gFreqs[1], gBandwidths[1] },
79 { -400, gFreqs[2], gBandwidths[2] },
80 { 400, gFreqs[3], gBandwidths[3] },
81 { 200, gFreqs[4], gBandwidths[4] }
82};
83
84const AudioEqualizer::PresetConfig gEqualizerPresets[] = {
85 { "Classic", gBandsClassic },
86 { "Jazz", gBandsJazz },
87 { "Pop", gBandsPop },
88 { "Rock", gBandsRock }
89};
90
91/////////////////// END EQ PRESETS /////////////////////////////////////////////
92
93static const size_t kBufferSize = 32;
94
95typedef AudioFormatAdapter<AudioEqualizer, kBufferSize> FormatAdapter;
96
97struct EqualizerContext {
98 const struct effect_interface_s *itfe;
99 effect_config_t config;
100 FormatAdapter adapter;
101 AudioEqualizer * pEqualizer;
102};
103
104
105//--- local function prototypes
106
107int Equalizer_init(EqualizerContext *pContext);
108int Equalizer_configure(EqualizerContext *pContext, effect_config_t *pConfig);
109int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue);
110int Equalizer_setParameter(AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue);
111
112
113//
114//--- Effect Library Interface Implementation
115//
116
Eric Laurentbe916aa2010-06-01 23:49:17 -0700117extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects) {
Eric Laurent135ad072010-05-21 06:05:13 -0700118 *pNumEffects = 1;
119 gEffectIndex = 0;
120 return 0;
121} /* end EffectQueryNumberEffects */
122
123extern "C" int EffectQueryNext(effect_descriptor_t *pDescriptor) {
124 if (pDescriptor == NULL) {
125 return -EINVAL;
126 }
127 if (gEffectIndex++ > 0) {
128 return -ENOENT;
129 }
130 memcpy(pDescriptor, &gEqualizerDescriptor, sizeof(effect_descriptor_t));
131 return 0;
132} /* end EffectQueryNext */
133
134extern "C" int EffectCreate(effect_uuid_t *uuid,
135 effect_interface_t *pInterface) {
136 int ret;
137 int i;
138
139 LOGV("EffectLibCreateEffect start");
140
141 if (pInterface == NULL || uuid == NULL) {
142 return -EINVAL;
143 }
144
145 if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) != 0) {
146 return -EINVAL;
147 }
148
149 EqualizerContext *pContext = new EqualizerContext;
150
151 pContext->itfe = &gEqualizerInterface;
152 pContext->pEqualizer = NULL;
153
154 ret = Equalizer_init(pContext);
155 if (ret < 0) {
156 LOGW("EffectLibCreateEffect() init failed");
157 delete pContext;
158 return ret;
159 }
160
161 *pInterface = (effect_interface_t)pContext;
162
163 LOGV("EffectLibCreateEffect %p", pContext);
164
165 return 0;
166
167} /* end EffectCreate */
168
169extern "C" int EffectRelease(effect_interface_t interface) {
170 EqualizerContext * pContext = (EqualizerContext *)interface;
171
172 LOGV("EffectLibReleaseEffect %p", interface);
173 if (pContext == NULL) {
174 return -EINVAL;
175 }
176
177 pContext->pEqualizer->free();
178 delete pContext;
179
180 return 0;
181} /* end EffectRelease */
182
183
184//
185//--- local functions
186//
187
188#define CHECK_ARG(cond) { \
189 if (!(cond)) { \
190 LOGV("Invalid argument: "#cond); \
191 return -EINVAL; \
192 } \
193}
194
195//----------------------------------------------------------------------------
196// Equalizer_configure()
197//----------------------------------------------------------------------------
198// Purpose: Set input and output audio configuration.
199//
200// Inputs:
201// pContext: effect engine context
202// pConfig: pointer to effect_config_t structure holding input and output
203// configuration parameters
204//
205// Outputs:
206//
207//----------------------------------------------------------------------------
208
209int Equalizer_configure(EqualizerContext *pContext, effect_config_t *pConfig)
210{
211 LOGV("Equalizer_configure start");
212
213 CHECK_ARG(pContext != NULL);
214 CHECK_ARG(pConfig != NULL);
215
216 CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
217 CHECK_ARG(pConfig->inputCfg.channels == pConfig->outputCfg.channels);
218 CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
219 CHECK_ARG((pConfig->inputCfg.channels == CHANNEL_MONO) || (pConfig->inputCfg.channels == CHANNEL_STEREO));
220 CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
221 || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
222 CHECK_ARG(pConfig->inputCfg.format == PCM_FORMAT_S7_24
223 || pConfig->inputCfg.format == PCM_FORMAT_S15);
224
225 int channelCount;
226 if (pConfig->inputCfg.channels == CHANNEL_MONO) {
227 channelCount = 1;
228 } else {
229 channelCount = 2;
230 }
231 CHECK_ARG(channelCount <= AudioBiquadFilter::MAX_CHANNELS);
232
233 pContext->pEqualizer->configure(channelCount,
234 pConfig->inputCfg.samplingRate);
235
236 pContext->adapter.configure(*pContext->pEqualizer, channelCount,
237 pConfig->inputCfg.format,
238 pConfig->outputCfg.accessMode);
239
240 return 0;
241} // end Equalizer_configure
242
243
244//----------------------------------------------------------------------------
245// Equalizer_init()
246//----------------------------------------------------------------------------
247// Purpose: Initialize engine with default configuration and creates
248// AudioEqualizer instance.
249//
250// Inputs:
251// pContext: effect engine context
252//
253// Outputs:
254//
255//----------------------------------------------------------------------------
256
257int Equalizer_init(EqualizerContext *pContext)
258{
259 int status;
260
261 LOGV("Equalizer_init start");
262
263 CHECK_ARG(pContext != NULL);
264
265 if (pContext->pEqualizer != NULL) {
266 pContext->pEqualizer->free();
267 }
268
269 pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
270 pContext->config.inputCfg.channels = CHANNEL_STEREO;
271 pContext->config.inputCfg.format = PCM_FORMAT_S15;
272 pContext->config.inputCfg.samplingRate = 44100;
273 pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
274 pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
275 pContext->config.inputCfg.bufferProvider.cookie = NULL;
276 pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
277 pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
278 pContext->config.outputCfg.channels = CHANNEL_STEREO;
279 pContext->config.outputCfg.format = PCM_FORMAT_S15;
280 pContext->config.outputCfg.samplingRate = 44100;
281 pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
282 pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
283 pContext->config.outputCfg.bufferProvider.cookie = NULL;
284 pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL;
285
286 pContext->pEqualizer = AudioEqualizer::CreateInstance(
287 NULL,
288 kNumBands,
289 AudioBiquadFilter::MAX_CHANNELS,
290 44100,
291 gEqualizerPresets,
292 ARRAY_SIZE(gEqualizerPresets));
293
294 for (int i = 0; i < kNumBands; ++i) {
295 pContext->pEqualizer->setFrequency(i, gFreqs[i]);
296 pContext->pEqualizer->setBandwidth(i, gBandwidths[i]);
297 }
298
299 pContext->pEqualizer->enable(true);
300
301 Equalizer_configure(pContext, &pContext->config);
302
303 return 0;
304} // end Equalizer_init
305
306
307//----------------------------------------------------------------------------
308// Equalizer_getParameter()
309//----------------------------------------------------------------------------
310// Purpose:
311// Get a Equalizer parameter
312//
313// Inputs:
314// pEqualizer - handle to instance data
315// pParam - pointer to parameter
316// pValue - pointer to variable to hold retrieved value
317// pValueSize - pointer to value size: maximum size as input
318//
319// Outputs:
320// *pValue updated with parameter value
321// *pValueSize updated with actual value size
322//
323//
324// Side Effects:
325//
326//----------------------------------------------------------------------------
327
328int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue)
329{
330 int status = 0;
331 int32_t param = *pParam++;
332 int32_t param2;
333 char *name;
334
335 switch (param) {
336 case EQ_PARAM_NUM_BANDS:
337 case EQ_PARAM_CUR_PRESET:
338 case EQ_PARAM_GET_NUM_OF_PRESETS:
339 if (*pValueSize < sizeof(int16_t)) {
340 return -EINVAL;
341 }
342 *pValueSize = sizeof(int16_t);
343 break;
344
345 case EQ_PARAM_LEVEL_RANGE:
346 case EQ_PARAM_BAND_FREQ_RANGE:
347 if (*pValueSize < 2 * sizeof(int32_t)) {
348 return -EINVAL;
349 }
350 *pValueSize = 2 * sizeof(int32_t);
351 break;
352 case EQ_PARAM_BAND_LEVEL:
353 case EQ_PARAM_GET_BAND:
354 case EQ_PARAM_CENTER_FREQ:
355 if (*pValueSize < sizeof(int32_t)) {
356 return -EINVAL;
357 }
358 *pValueSize = sizeof(int32_t);
359 break;
360
361 case EQ_PARAM_GET_PRESET_NAME:
362 break;
363
364 default:
365 return -EINVAL;
366 }
367
368 switch (param) {
369 case EQ_PARAM_NUM_BANDS:
370 *(int16_t *)pValue = kNumBands;
371 LOGV("Equalizer_getParameter() EQ_PARAM_NUM_BANDS %d", *(int16_t *)pValue);
372 break;
373
374 case EQ_PARAM_LEVEL_RANGE:
375 *(int32_t *)pValue = -9600;
376 *((int32_t *)pValue + 1) = 4800;
377 LOGV("Equalizer_getParameter() EQ_PARAM_LEVEL_RANGE min %d, max %d", *(int32_t *)pValue, *((int32_t *)pValue + 1));
378 break;
379
380 case EQ_PARAM_BAND_LEVEL:
381 param2 = *pParam;
382 if (param2 >= kNumBands) {
383 status = -EINVAL;
384 break;
385 }
386 *(int32_t *)pValue = pEqualizer->getGain(param2);
387 LOGV("Equalizer_getParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", param2, *(int32_t *)pValue);
388 break;
389
390 case EQ_PARAM_CENTER_FREQ:
391 param2 = *pParam;
392 if (param2 >= kNumBands) {
393 status = -EINVAL;
394 break;
395 }
396 *(int32_t *)pValue = pEqualizer->getFrequency(param2);
397 LOGV("Equalizer_getParameter() EQ_PARAM_CENTER_FREQ band %d, frequency %d", param2, *(int32_t *)pValue);
398 break;
399
400 case EQ_PARAM_BAND_FREQ_RANGE:
401 param2 = *pParam;
402 if (param2 >= kNumBands) {
403 status = -EINVAL;
404 break;
405 }
406 pEqualizer->getBandRange(param2, *(uint32_t *)pValue, *((uint32_t *)pValue + 1));
407 LOGV("Equalizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d, min %d, max %d", param2, *(int32_t *)pValue, *((int32_t *)pValue + 1));
408 break;
409
410 case EQ_PARAM_GET_BAND:
411 param2 = *pParam;
412 *(int32_t *)pValue = pEqualizer->getMostRelevantBand(param2);
413 LOGV("Equalizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d", param2, *(int32_t *)pValue);
414 break;
415
416 case EQ_PARAM_CUR_PRESET:
417 *(int16_t *)pValue = pEqualizer->getPreset();
418 LOGV("Equalizer_getParameter() EQ_PARAM_CUR_PRESET %d", *(int32_t *)pValue);
419 break;
420
421 case EQ_PARAM_GET_NUM_OF_PRESETS:
422 *(int16_t *)pValue = pEqualizer->getNumPresets();
423 LOGV("Equalizer_getParameter() EQ_PARAM_GET_NUM_OF_PRESETS %d", *(int16_t *)pValue);
424 break;
425
426 case EQ_PARAM_GET_PRESET_NAME:
427 param2 = *pParam;
428 if (param2 >= pEqualizer->getNumPresets()) {
429 status = -EINVAL;
430 break;
431 }
432 name = (char *)pValue;
433 strncpy(name, pEqualizer->getPresetName(param2), *pValueSize - 1);
434 name[*pValueSize - 1] = 0;
435 *pValueSize = strlen(name) + 1;
436 LOGV("Equalizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d", param2, gEqualizerPresets[param2].name, *pValueSize);
437 break;
438
439 default:
440 LOGV("Equalizer_getParameter() invalid param %d", param);
441 status = -EINVAL;
442 break;
443 }
444
445 return status;
446} // end Equalizer_getParameter
447
448
449//----------------------------------------------------------------------------
450// Equalizer_setParameter()
451//----------------------------------------------------------------------------
452// Purpose:
453// Set a Equalizer parameter
454//
455// Inputs:
456// pEqualizer - handle to instance data
457// pParam - pointer to parameter
458// pValue - pointer to value
459//
460// Outputs:
461//
462//
463// Side Effects:
464//
465//----------------------------------------------------------------------------
466
467int Equalizer_setParameter (AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue)
468{
469 int status = 0;
470 int32_t preset;
471 int32_t band;
472 int32_t level;
473 int32_t param = *pParam++;
474
475
476 switch (param) {
477 case EQ_PARAM_CUR_PRESET:
478 preset = *(int16_t *)pValue;
479
480 LOGV("setParameter() EQ_PARAM_CUR_PRESET %d", preset);
481 if (preset >= pEqualizer->getNumPresets()) {
482 status = -EINVAL;
483 break;
484 }
485 pEqualizer->setPreset(preset);
486 pEqualizer->commit(true);
487 break;
488 case EQ_PARAM_BAND_LEVEL:
489 band = *pParam;
490 level = *(int32_t *)pValue;
491 LOGV("setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level);
492 if (band >= kNumBands) {
493 status = -EINVAL;
494 break;
495 }
496 pEqualizer->setGain(band, level);
497 pEqualizer->commit(true);
498 break;
499 default:
500 LOGV("setParameter() invalid param %d", param);
501 break;
502 }
503
504 return status;
505} // end Equalizer_setParameter
506
507} // namespace
508} // namespace
509
510
511//
512//--- Effect Control Interface Implementation
513//
514
515extern "C" int Equalizer_process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
516{
517 android::EqualizerContext * pContext = (android::EqualizerContext *) self;
518
519 if (pContext == NULL) {
520 return -EINVAL;
521 }
522 if (inBuffer == NULL || inBuffer->raw == NULL ||
523 outBuffer == NULL || outBuffer->raw == NULL ||
524 inBuffer->frameCount != outBuffer->frameCount) {
525 return -EINVAL;
526 }
527
528 pContext->adapter.process(inBuffer->raw, outBuffer->raw, outBuffer->frameCount);
529 return 0;
530} // end Equalizer_process
531
532extern "C" int Equalizer_command(effect_interface_t self, int cmdCode, int cmdSize,
533 void *pCmdData, int *replySize, void *pReplyData) {
534
535 android::EqualizerContext * pContext = (android::EqualizerContext *) self;
536 int retsize;
537
538 if (pContext == NULL) {
539 return -EINVAL;
540 }
541
542 android::AudioEqualizer * pEqualizer = pContext->pEqualizer;
543
544 LOGV("Equalizer_command command %d cmdSize %d",cmdCode, cmdSize);
545
546 switch (cmdCode) {
547 case EFFECT_CMD_INIT:
548 if (pReplyData == NULL || *replySize != sizeof(int)) {
549 return -EINVAL;
550 }
551 *(int *) pReplyData = Equalizer_init(pContext);
552 break;
553 case EFFECT_CMD_CONFIGURE:
554 if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
555 || pReplyData == NULL || *replySize != sizeof(int)) {
556 return -EINVAL;
557 }
558 *(int *) pReplyData = Equalizer_configure(pContext,
559 (effect_config_t *) pCmdData);
560 break;
561 case EFFECT_CMD_RESET:
562 Equalizer_configure(pContext, &pContext->config);
563 break;
564 case EFFECT_CMD_GET_PARAM: {
565 if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
566 pReplyData == NULL || *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))) {
567 return -EINVAL;
568 }
569 effect_param_t *p = (effect_param_t *)pCmdData;
570 memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
571 p = (effect_param_t *)pReplyData;
572 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
573 p->status = android::Equalizer_getParameter(pEqualizer, (int32_t *)p->data, &p->vsize,
574 p->data + voffset);
575 *replySize = sizeof(effect_param_t) + voffset + p->vsize;
576 LOGV("Equalizer_command EFFECT_CMD_GET_PARAM *pCmdData %d, *replySize %d, *pReplyData %08x %08x",
577 *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)), *replySize,
578 *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset),
579 *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset + sizeof(int32_t)));
580
581 } break;
582 case EFFECT_CMD_SET_PARAM: {
583 LOGV("Equalizer_command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p", cmdSize, pCmdData, *replySize, pReplyData);
584 if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
585 pReplyData == NULL || *replySize != sizeof(int32_t)) {
586 return -EINVAL;
587 }
588 effect_param_t *p = (effect_param_t *) pCmdData;
589 *(int *)pReplyData = android::Equalizer_setParameter(pEqualizer, (int32_t *)p->data,
590 p->data + p->psize);
591 } break;
592 default:
593 LOGW("Equalizer_command invalid command %d",cmdCode);
594 return -EINVAL;
595 }
596
597 return 0;
598}
599
600// effect_interface_t interface implementation for equalizer effect
601const struct effect_interface_s gEqualizerInterface = {
602 Equalizer_process,
603 Equalizer_command
604};
605
606