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