1 /* 2 * Copyright (C) 2014 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 "offload_effect_equalizer" 18 //#define LOG_NDEBUG 0 19 20 #include <cutils/list.h> 21 #include <cutils/log.h> 22 #include <tinyalsa/asoundlib.h> 23 #include <sound/audio_effects.h> 24 #include <audio_effects/effect_equalizer.h> 25 26 #include "effect_api.h" 27 #include "equalizer.h" 28 29 /* Offload equalizer UUID: a0dac280-401c-11e3-9379-0002a5d5c51b */ 30 const effect_descriptor_t equalizer_descriptor = { 31 {0x0bed4300, 0xddd6, 0x11db, 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type 32 {0xa0dac280, 0x401c, 0x11e3, 0x9379, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid 33 EFFECT_CONTROL_API_VERSION, 34 (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_HW_ACC_TUNNEL | EFFECT_FLAG_VOLUME_CTRL), 35 0, /* TODO */ 36 1, 37 "MSM offload equalizer", 38 "The Android Open Source Project", 39 }; 40 41 static const char *equalizer_preset_names[] = { 42 "Normal", 43 "Classical", 44 "Dance", 45 "Flat", 46 "Folk", 47 "Heavy Metal", 48 "Hip Hop", 49 "Jazz", 50 "Pop", 51 "Rock" 52 }; 53 54 static const uint32_t equalizer_band_freq_range[NUM_EQ_BANDS][2] = { 55 {30000, 120000}, 56 {120001, 460000}, 57 {460001, 1800000}, 58 {1800001, 7000000}, 59 {7000001, 20000000}}; 60 61 static const int16_t equalizer_band_presets_level[] = { 62 3, 0, 0, 0, 3, /* Normal Preset */ 63 5, 3, -2, 4, 4, /* Classical Preset */ 64 6, 0, 2, 4, 1, /* Dance Preset */ 65 0, 0, 0, 0, 0, /* Flat Preset */ 66 3, 0, 0, 2, -1, /* Folk Preset */ 67 4, 1, 9, 3, 0, /* Heavy Metal Preset */ 68 5, 3, 0, 1, 3, /* Hip Hop Preset */ 69 4, 2, -2, 2, 5, /* Jazz Preset */ 70 -1, 2, 5, 1, -2, /* Pop Preset */ 71 5, 3, -1, 3, 5}; /* Rock Preset */ 72 73 const uint16_t equalizer_band_presets_freq[NUM_EQ_BANDS] = { 74 60, /* Frequencies in Hz */ 75 230, 76 910, 77 3600, 78 14000 79 }; 80 81 /* 82 * Equalizer operations 83 */ 84 85 int equalizer_get_band_level(equalizer_context_t *context, int32_t band) 86 { 87 ALOGV("%s: band: %d level: %d", __func__, band, 88 context->band_levels[band] * 100); 89 return context->band_levels[band] * 100; 90 } 91 92 int equalizer_set_band_level(equalizer_context_t *context, int32_t band, 93 int32_t level) 94 { 95 ALOGV("%s: band: %d, level: %d", __func__, band, level); 96 if (level > 0) { 97 level = (int)((level+50)/100); 98 } else { 99 level = (int)((level-50)/100); 100 } 101 context->band_levels[band] = level; 102 context->preset = PRESET_CUSTOM; 103 104 offload_eq_set_preset(&(context->offload_eq), PRESET_CUSTOM); 105 offload_eq_set_bands_level(&(context->offload_eq), 106 NUM_EQ_BANDS, 107 equalizer_band_presets_freq, 108 context->band_levels); 109 if (context->ctl) 110 offload_eq_send_params(context->ctl, &context->offload_eq, 111 OFFLOAD_SEND_EQ_ENABLE_FLAG | 112 OFFLOAD_SEND_EQ_BANDS_LEVEL); 113 return 0; 114 } 115 116 int equalizer_get_center_frequency(equalizer_context_t *context __unused, int32_t band) 117 { 118 ALOGV("%s: band: %d", __func__, band); 119 return (equalizer_band_freq_range[band][0] + 120 equalizer_band_freq_range[band][1]) / 2; 121 } 122 123 int equalizer_get_band_freq_range(equalizer_context_t *context __unused, int32_t band, 124 uint32_t *low, uint32_t *high) 125 { 126 ALOGV("%s: band: %d", __func__, band); 127 *low = equalizer_band_freq_range[band][0]; 128 *high = equalizer_band_freq_range[band][1]; 129 return 0; 130 } 131 132 int equalizer_get_band(equalizer_context_t *context __unused, uint32_t freq) 133 { 134 int i; 135 136 ALOGV("%s: freq: %d", __func__, freq); 137 for (i = 0; i < NUM_EQ_BANDS; i++) { 138 if (freq <= equalizer_band_freq_range[i][1]) { 139 return i; 140 } 141 } 142 return NUM_EQ_BANDS - 1; 143 } 144 145 int equalizer_get_preset(equalizer_context_t *context) 146 { 147 ALOGV("%s: preset: %d", __func__, context->preset); 148 return context->preset; 149 } 150 151 int equalizer_set_preset(equalizer_context_t *context, int preset) 152 { 153 int i; 154 155 ALOGV("%s: preset: %d", __func__, preset); 156 context->preset = preset; 157 for (i=0; i<NUM_EQ_BANDS; i++) 158 context->band_levels[i] = 159 equalizer_band_presets_level[i + preset * NUM_EQ_BANDS]; 160 161 offload_eq_set_preset(&(context->offload_eq), preset); 162 offload_eq_set_bands_level(&(context->offload_eq), 163 NUM_EQ_BANDS, 164 equalizer_band_presets_freq, 165 context->band_levels); 166 if(context->ctl) 167 offload_eq_send_params(context->ctl, &context->offload_eq, 168 OFFLOAD_SEND_EQ_ENABLE_FLAG | 169 OFFLOAD_SEND_EQ_PRESET); 170 return 0; 171 } 172 173 const char * equalizer_get_preset_name(equalizer_context_t *context __unused, 174 int32_t preset) 175 { 176 ALOGV("%s: preset: %s", __func__, equalizer_preset_names[preset]); 177 if (preset == PRESET_CUSTOM) { 178 return "Custom"; 179 } else { 180 return equalizer_preset_names[preset]; 181 } 182 } 183 184 int equalizer_get_num_presets(equalizer_context_t *context __unused) 185 { 186 ALOGV("%s: presets_num: %zu", __func__, 187 sizeof(equalizer_preset_names)/sizeof(char *)); 188 return sizeof(equalizer_preset_names)/sizeof(char *); 189 } 190 191 int equalizer_get_parameter(effect_context_t *context, effect_param_t *p, 192 uint32_t *size) 193 { 194 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 195 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); 196 int32_t *param_tmp = (int32_t *)p->data; 197 int32_t param = *param_tmp++; 198 int32_t param2; 199 char *name; 200 void *value = p->data + voffset; 201 int i; 202 203 ALOGV("%s", __func__); 204 205 p->status = 0; 206 207 switch (param) { 208 case EQ_PARAM_NUM_BANDS: 209 case EQ_PARAM_CUR_PRESET: 210 case EQ_PARAM_GET_NUM_OF_PRESETS: 211 case EQ_PARAM_BAND_LEVEL: 212 case EQ_PARAM_GET_BAND: 213 if (p->vsize < sizeof(int16_t)) 214 p->status = -EINVAL; 215 p->vsize = sizeof(int16_t); 216 break; 217 218 case EQ_PARAM_LEVEL_RANGE: 219 if (p->vsize < 2 * sizeof(int16_t)) 220 p->status = -EINVAL; 221 p->vsize = 2 * sizeof(int16_t); 222 break; 223 case EQ_PARAM_BAND_FREQ_RANGE: 224 if (p->vsize < 2 * sizeof(int32_t)) 225 p->status = -EINVAL; 226 p->vsize = 2 * sizeof(int32_t); 227 break; 228 229 case EQ_PARAM_CENTER_FREQ: 230 if (p->vsize < sizeof(int32_t)) 231 p->status = -EINVAL; 232 p->vsize = sizeof(int32_t); 233 break; 234 235 case EQ_PARAM_GET_PRESET_NAME: 236 break; 237 238 case EQ_PARAM_PROPERTIES: 239 if (p->vsize < (2 + NUM_EQ_BANDS) * sizeof(uint16_t)) 240 p->status = -EINVAL; 241 p->vsize = (2 + NUM_EQ_BANDS) * sizeof(uint16_t); 242 break; 243 244 default: 245 p->status = -EINVAL; 246 } 247 248 *size = sizeof(effect_param_t) + voffset + p->vsize; 249 250 if (p->status != 0) 251 return 0; 252 253 switch (param) { 254 case EQ_PARAM_NUM_BANDS: 255 ALOGV("%s: EQ_PARAM_NUM_BANDS", __func__); 256 *(uint16_t *)value = (uint16_t)NUM_EQ_BANDS; 257 break; 258 259 case EQ_PARAM_LEVEL_RANGE: 260 ALOGV("%s: EQ_PARAM_LEVEL_RANGE", __func__); 261 *(int16_t *)value = -1500; 262 *((int16_t *)value + 1) = 1500; 263 break; 264 265 case EQ_PARAM_BAND_LEVEL: 266 ALOGV("%s: EQ_PARAM_BAND_LEVEL", __func__); 267 param2 = *param_tmp; 268 if (param2 < 0 || param2 >= NUM_EQ_BANDS) { 269 p->status = -EINVAL; 270 if (param2 < 0) { 271 android_errorWriteLog(0x534e4554, "32438598"); 272 ALOGW("\tERROR EQ_PARAM_BAND_LEVEL band %d", param2); 273 } 274 break; 275 } 276 *(int16_t *)value = (int16_t)equalizer_get_band_level(eq_ctxt, param2); 277 break; 278 279 case EQ_PARAM_CENTER_FREQ: 280 ALOGV("%s: EQ_PARAM_CENTER_FREQ", __func__); 281 param2 = *param_tmp; 282 if (param2 < 0 || param2 >= NUM_EQ_BANDS) { 283 p->status = -EINVAL; 284 if (param2 < 0) { 285 android_errorWriteLog(0x534e4554, "32436341"); 286 ALOGW("\tERROR EQ_PARAM_CENTER_FREQ band %d", param2); 287 } 288 break; 289 } 290 *(int32_t *)value = equalizer_get_center_frequency(eq_ctxt, param2); 291 break; 292 293 case EQ_PARAM_BAND_FREQ_RANGE: 294 ALOGV("%s: EQ_PARAM_BAND_FREQ_RANGE", __func__); 295 param2 = *param_tmp; 296 if (param2 < 0 || param2 >= NUM_EQ_BANDS) { 297 p->status = -EINVAL; 298 if (param2 < 0) { 299 android_errorWriteLog(0x534e4554, "32247948"); 300 ALOGW("\tERROR EQ_PARAM_BAND_FREQ_RANGE band %d", param2); 301 } 302 break; 303 } 304 equalizer_get_band_freq_range(eq_ctxt, param2, (uint32_t *)value, 305 ((uint32_t *)value + 1)); 306 break; 307 308 case EQ_PARAM_GET_BAND: 309 ALOGV("%s: EQ_PARAM_GET_BAND", __func__); 310 param2 = *param_tmp; 311 *(uint16_t *)value = (uint16_t)equalizer_get_band(eq_ctxt, param2); 312 break; 313 314 case EQ_PARAM_CUR_PRESET: 315 ALOGV("%s: EQ_PARAM_CUR_PRESET", __func__); 316 *(uint16_t *)value = (uint16_t)equalizer_get_preset(eq_ctxt); 317 break; 318 319 case EQ_PARAM_GET_NUM_OF_PRESETS: 320 ALOGV("%s: EQ_PARAM_GET_NUM_OF_PRESETS", __func__); 321 *(uint16_t *)value = (uint16_t)equalizer_get_num_presets(eq_ctxt); 322 break; 323 324 case EQ_PARAM_GET_PRESET_NAME: 325 ALOGV("%s: EQ_PARAM_GET_PRESET_NAME", __func__); 326 param2 = *param_tmp; 327 ALOGV("param2: %d", param2); 328 if ((param2 < 0 && param2 != PRESET_CUSTOM) || 329 param2 >= equalizer_get_num_presets(eq_ctxt)) { 330 p->status = -EINVAL; 331 if (param2 < 0) { 332 android_errorWriteLog(0x534e4554, "32588016"); 333 ALOGW("\tERROR EQ_PARAM_GET_PRESET_NAME preset %d", param2); 334 } 335 break; 336 } 337 338 if (p->vsize < 1) { 339 p->status = -EINVAL; 340 android_errorWriteLog(0x534e4554, "37536407"); 341 break; 342 } 343 344 name = (char *)value; 345 strlcpy(name, equalizer_get_preset_name(eq_ctxt, param2), p->vsize - 1); 346 name[p->vsize - 1] = 0; 347 p->vsize = strlen(name) + 1; 348 break; 349 350 case EQ_PARAM_PROPERTIES: { 351 ALOGV("%s: EQ_PARAM_PROPERTIES", __func__); 352 int16_t *prop = (int16_t *)value; 353 prop[0] = (int16_t)equalizer_get_preset(eq_ctxt); 354 prop[1] = (int16_t)NUM_EQ_BANDS; 355 for (i = 0; i < NUM_EQ_BANDS; i++) { 356 prop[2 + i] = (int16_t)equalizer_get_band_level(eq_ctxt, i); 357 } 358 } break; 359 360 default: 361 p->status = -EINVAL; 362 break; 363 } 364 365 return 0; 366 } 367 368 int equalizer_set_parameter(effect_context_t *context, effect_param_t *p, 369 uint32_t size __unused) 370 { 371 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 372 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); 373 void *value = p->data + voffset; 374 uint32_t vsize = p->vsize; 375 int32_t *param_tmp = (int32_t *)p->data; 376 int32_t param = *param_tmp++; 377 int32_t preset; 378 int32_t band; 379 int32_t level; 380 int i; 381 382 ALOGV("%s", __func__); 383 384 p->status = 0; 385 386 switch (param) { 387 case EQ_PARAM_CUR_PRESET: 388 ALOGV("EQ_PARAM_CUR_PRESET"); 389 if (vsize < sizeof(int16_t)) { 390 p->status = -EINVAL; 391 break; 392 } 393 preset = (int32_t)(*(uint16_t *)value); 394 395 if ((preset >= equalizer_get_num_presets(eq_ctxt)) || (preset < 0)) { 396 p->status = -EINVAL; 397 break; 398 } 399 equalizer_set_preset(eq_ctxt, preset); 400 break; 401 case EQ_PARAM_BAND_LEVEL: 402 ALOGV("EQ_PARAM_BAND_LEVEL"); 403 if (vsize < sizeof(int16_t)) { 404 p->status = -EINVAL; 405 break; 406 } 407 band = *param_tmp; 408 level = (int32_t)(*(int16_t *)value); 409 if (band < 0 || band >= NUM_EQ_BANDS) { 410 p->status = -EINVAL; 411 if (band < 0) { 412 android_errorWriteLog(0x534e4554, "32585400"); 413 ALOGW("\tERROR EQ_PARAM_BAND_LEVEL band %d", band); 414 } 415 break; 416 } 417 equalizer_set_band_level(eq_ctxt, band, level); 418 break; 419 case EQ_PARAM_PROPERTIES: { 420 ALOGV("EQ_PARAM_PROPERTIES"); 421 if (vsize < sizeof(int16_t)) { 422 p->status = -EINVAL; 423 break; 424 } 425 int16_t *prop = (int16_t *)value; 426 if ((int)prop[0] >= equalizer_get_num_presets(eq_ctxt)) { 427 p->status = -EINVAL; 428 break; 429 } 430 if (prop[0] >= 0) { 431 equalizer_set_preset(eq_ctxt, (int)prop[0]); 432 } else { 433 if (vsize < (2 + NUM_EQ_BANDS) * sizeof(int16_t)) { 434 android_errorWriteLog(0x534e4554, "37563371"); 435 ALOGE("\tERROR EQ_PARAM_PROPERTIES valueSize %u < %u", 436 vsize, (unsigned int)((2 + NUM_EQ_BANDS) * sizeof(int16_t))); 437 p->status = -EINVAL; 438 break; 439 } 440 if ((int)prop[1] != NUM_EQ_BANDS) { 441 p->status = -EINVAL; 442 break; 443 } 444 for (i = 0; i < NUM_EQ_BANDS; i++) { 445 equalizer_set_band_level(eq_ctxt, i, (int)prop[2 + i]); 446 } 447 } 448 } break; 449 default: 450 p->status = -EINVAL; 451 break; 452 } 453 454 return 0; 455 } 456 457 int equalizer_set_device(effect_context_t *context, uint32_t device) 458 { 459 ALOGV("%s: device: %d", __func__, device); 460 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 461 eq_ctxt->device = device; 462 offload_eq_set_device(&(eq_ctxt->offload_eq), device); 463 return 0; 464 } 465 466 int equalizer_reset(effect_context_t *context) 467 { 468 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 469 470 return 0; 471 } 472 473 int equalizer_init(effect_context_t *context) 474 { 475 ALOGV("%s", __func__); 476 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 477 478 context->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ; 479 context->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; 480 context->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 481 context->config.inputCfg.samplingRate = 44100; 482 context->config.inputCfg.bufferProvider.getBuffer = NULL; 483 context->config.inputCfg.bufferProvider.releaseBuffer = NULL; 484 context->config.inputCfg.bufferProvider.cookie = NULL; 485 context->config.inputCfg.mask = EFFECT_CONFIG_ALL; 486 context->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE; 487 context->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; 488 context->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 489 context->config.outputCfg.samplingRate = 44100; 490 context->config.outputCfg.bufferProvider.getBuffer = NULL; 491 context->config.outputCfg.bufferProvider.releaseBuffer = NULL; 492 context->config.outputCfg.bufferProvider.cookie = NULL; 493 context->config.outputCfg.mask = EFFECT_CONFIG_ALL; 494 495 set_config(context, &context->config); 496 497 memset(&(eq_ctxt->offload_eq), 0, sizeof(struct eq_params)); 498 offload_eq_set_preset(&(eq_ctxt->offload_eq), INVALID_PRESET); 499 500 return 0; 501 } 502 503 int equalizer_enable(effect_context_t *context) 504 { 505 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 506 507 ALOGV("%s", __func__); 508 509 if (!offload_eq_get_enable_flag(&(eq_ctxt->offload_eq))) { 510 offload_eq_set_enable_flag(&(eq_ctxt->offload_eq), true); 511 if (eq_ctxt->ctl) 512 offload_eq_send_params(eq_ctxt->ctl, &eq_ctxt->offload_eq, 513 OFFLOAD_SEND_EQ_ENABLE_FLAG | 514 OFFLOAD_SEND_EQ_BANDS_LEVEL); 515 } 516 return 0; 517 } 518 519 int equalizer_disable(effect_context_t *context) 520 { 521 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 522 523 ALOGV("%s", __func__); 524 if (offload_eq_get_enable_flag(&(eq_ctxt->offload_eq))) { 525 offload_eq_set_enable_flag(&(eq_ctxt->offload_eq), false); 526 if (eq_ctxt->ctl) 527 offload_eq_send_params(eq_ctxt->ctl, &eq_ctxt->offload_eq, 528 OFFLOAD_SEND_EQ_ENABLE_FLAG); 529 } 530 return 0; 531 } 532 533 int equalizer_start(effect_context_t *context, output_context_t *output) 534 { 535 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 536 537 ALOGV("%s: %p", __func__, output->ctl); 538 eq_ctxt->ctl = output->ctl; 539 if (offload_eq_get_enable_flag(&(eq_ctxt->offload_eq))) 540 if (eq_ctxt->ctl) 541 offload_eq_send_params(eq_ctxt->ctl, &eq_ctxt->offload_eq, 542 OFFLOAD_SEND_EQ_ENABLE_FLAG | 543 OFFLOAD_SEND_EQ_BANDS_LEVEL); 544 return 0; 545 } 546 547 int equalizer_stop(effect_context_t *context, output_context_t *output __unused) 548 { 549 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 550 551 ALOGV("%s", __func__); 552 eq_ctxt->ctl = NULL; 553 return 0; 554 } 555