EffectEqualizer.cpp revision be916aa1267e2e6b1c148f51d11bcbbc79cb864c
1/* 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 <string.h> 24#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 117extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects) { 118 *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 607