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), 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: %d", __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 >= NUM_EQ_BANDS) { 269 p->status = -EINVAL; 270 break; 271 } 272 *(int16_t *)value = (int16_t)equalizer_get_band_level(eq_ctxt, param2); 273 break; 274 275 case EQ_PARAM_CENTER_FREQ: 276 ALOGV("%s: EQ_PARAM_CENTER_FREQ", __func__); 277 param2 = *param_tmp; 278 if (param2 >= NUM_EQ_BANDS) { 279 p->status = -EINVAL; 280 break; 281 } 282 *(int32_t *)value = equalizer_get_center_frequency(eq_ctxt, param2); 283 break; 284 285 case EQ_PARAM_BAND_FREQ_RANGE: 286 ALOGV("%s: EQ_PARAM_BAND_FREQ_RANGE", __func__); 287 param2 = *param_tmp; 288 if (param2 >= NUM_EQ_BANDS) { 289 p->status = -EINVAL; 290 break; 291 } 292 equalizer_get_band_freq_range(eq_ctxt, param2, (uint32_t *)value, 293 ((uint32_t *)value + 1)); 294 break; 295 296 case EQ_PARAM_GET_BAND: 297 ALOGV("%s: EQ_PARAM_GET_BAND", __func__); 298 param2 = *param_tmp; 299 *(uint16_t *)value = (uint16_t)equalizer_get_band(eq_ctxt, param2); 300 break; 301 302 case EQ_PARAM_CUR_PRESET: 303 ALOGV("%s: EQ_PARAM_CUR_PRESET", __func__); 304 *(uint16_t *)value = (uint16_t)equalizer_get_preset(eq_ctxt); 305 break; 306 307 case EQ_PARAM_GET_NUM_OF_PRESETS: 308 ALOGV("%s: EQ_PARAM_GET_NUM_OF_PRESETS", __func__); 309 *(uint16_t *)value = (uint16_t)equalizer_get_num_presets(eq_ctxt); 310 break; 311 312 case EQ_PARAM_GET_PRESET_NAME: 313 ALOGV("%s: EQ_PARAM_GET_PRESET_NAME", __func__); 314 param2 = *param_tmp; 315 ALOGV("param2: %d", param2); 316 if (param2 >= equalizer_get_num_presets(eq_ctxt)) { 317 p->status = -EINVAL; 318 break; 319 } 320 name = (char *)value; 321 strlcpy(name, equalizer_get_preset_name(eq_ctxt, param2), p->vsize - 1); 322 name[p->vsize - 1] = 0; 323 p->vsize = strlen(name) + 1; 324 break; 325 326 case EQ_PARAM_PROPERTIES: { 327 ALOGV("%s: EQ_PARAM_PROPERTIES", __func__); 328 int16_t *prop = (int16_t *)value; 329 prop[0] = (int16_t)equalizer_get_preset(eq_ctxt); 330 prop[1] = (int16_t)NUM_EQ_BANDS; 331 for (i = 0; i < NUM_EQ_BANDS; i++) { 332 prop[2 + i] = (int16_t)equalizer_get_band_level(eq_ctxt, i); 333 } 334 } break; 335 336 default: 337 p->status = -EINVAL; 338 break; 339 } 340 341 return 0; 342 } 343 344 int equalizer_set_parameter(effect_context_t *context, effect_param_t *p, 345 uint32_t size __unused) 346 { 347 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 348 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); 349 void *value = p->data + voffset; 350 int32_t *param_tmp = (int32_t *)p->data; 351 int32_t param = *param_tmp++; 352 int32_t preset; 353 int32_t band; 354 int32_t level; 355 int i; 356 357 ALOGV("%s", __func__); 358 359 p->status = 0; 360 361 switch (param) { 362 case EQ_PARAM_CUR_PRESET: 363 ALOGV("EQ_PARAM_CUR_PRESET"); 364 preset = (int32_t)(*(uint16_t *)value); 365 366 if ((preset >= equalizer_get_num_presets(eq_ctxt)) || (preset < 0)) { 367 p->status = -EINVAL; 368 break; 369 } 370 equalizer_set_preset(eq_ctxt, preset); 371 break; 372 case EQ_PARAM_BAND_LEVEL: 373 ALOGV("EQ_PARAM_BAND_LEVEL"); 374 band = *param_tmp; 375 level = (int32_t)(*(int16_t *)value); 376 if (band >= NUM_EQ_BANDS) { 377 p->status = -EINVAL; 378 break; 379 } 380 equalizer_set_band_level(eq_ctxt, band, level); 381 break; 382 case EQ_PARAM_PROPERTIES: { 383 ALOGV("EQ_PARAM_PROPERTIES"); 384 int16_t *prop = (int16_t *)value; 385 if ((int)prop[0] >= equalizer_get_num_presets(eq_ctxt)) { 386 p->status = -EINVAL; 387 break; 388 } 389 if (prop[0] >= 0) { 390 equalizer_set_preset(eq_ctxt, (int)prop[0]); 391 } else { 392 if ((int)prop[1] != NUM_EQ_BANDS) { 393 p->status = -EINVAL; 394 break; 395 } 396 for (i = 0; i < NUM_EQ_BANDS; i++) { 397 equalizer_set_band_level(eq_ctxt, i, (int)prop[2 + i]); 398 } 399 } 400 } break; 401 default: 402 p->status = -EINVAL; 403 break; 404 } 405 406 return 0; 407 } 408 409 int equalizer_set_device(effect_context_t *context, uint32_t device) 410 { 411 ALOGV("%s: device: %d", __func__, device); 412 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 413 eq_ctxt->device = device; 414 offload_eq_set_device(&(eq_ctxt->offload_eq), device); 415 return 0; 416 } 417 418 int equalizer_reset(effect_context_t *context) 419 { 420 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 421 422 return 0; 423 } 424 425 int equalizer_init(effect_context_t *context) 426 { 427 ALOGV("%s", __func__); 428 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 429 430 context->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ; 431 context->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; 432 context->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 433 context->config.inputCfg.samplingRate = 44100; 434 context->config.inputCfg.bufferProvider.getBuffer = NULL; 435 context->config.inputCfg.bufferProvider.releaseBuffer = NULL; 436 context->config.inputCfg.bufferProvider.cookie = NULL; 437 context->config.inputCfg.mask = EFFECT_CONFIG_ALL; 438 context->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE; 439 context->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; 440 context->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 441 context->config.outputCfg.samplingRate = 44100; 442 context->config.outputCfg.bufferProvider.getBuffer = NULL; 443 context->config.outputCfg.bufferProvider.releaseBuffer = NULL; 444 context->config.outputCfg.bufferProvider.cookie = NULL; 445 context->config.outputCfg.mask = EFFECT_CONFIG_ALL; 446 447 set_config(context, &context->config); 448 449 memset(&(eq_ctxt->offload_eq), 0, sizeof(struct eq_params)); 450 offload_eq_set_preset(&(eq_ctxt->offload_eq), INVALID_PRESET); 451 452 return 0; 453 } 454 455 int equalizer_enable(effect_context_t *context) 456 { 457 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 458 459 ALOGV("%s", __func__); 460 461 if (!offload_eq_get_enable_flag(&(eq_ctxt->offload_eq))) { 462 offload_eq_set_enable_flag(&(eq_ctxt->offload_eq), true); 463 if (eq_ctxt->ctl) 464 offload_eq_send_params(eq_ctxt->ctl, &eq_ctxt->offload_eq, 465 OFFLOAD_SEND_EQ_ENABLE_FLAG | 466 OFFLOAD_SEND_EQ_BANDS_LEVEL); 467 } 468 return 0; 469 } 470 471 int equalizer_disable(effect_context_t *context) 472 { 473 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 474 475 ALOGV("%s", __func__); 476 if (offload_eq_get_enable_flag(&(eq_ctxt->offload_eq))) { 477 offload_eq_set_enable_flag(&(eq_ctxt->offload_eq), false); 478 if (eq_ctxt->ctl) 479 offload_eq_send_params(eq_ctxt->ctl, &eq_ctxt->offload_eq, 480 OFFLOAD_SEND_EQ_ENABLE_FLAG); 481 } 482 return 0; 483 } 484 485 int equalizer_start(effect_context_t *context, output_context_t *output) 486 { 487 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 488 489 ALOGV("%s: %p", __func__, output->ctl); 490 eq_ctxt->ctl = output->ctl; 491 if (offload_eq_get_enable_flag(&(eq_ctxt->offload_eq))) 492 if (eq_ctxt->ctl) 493 offload_eq_send_params(eq_ctxt->ctl, &eq_ctxt->offload_eq, 494 OFFLOAD_SEND_EQ_ENABLE_FLAG | 495 OFFLOAD_SEND_EQ_BANDS_LEVEL); 496 return 0; 497 } 498 499 int equalizer_stop(effect_context_t *context, output_context_t *output __unused) 500 { 501 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context; 502 503 ALOGV("%s", __func__); 504 eq_ctxt->ctl = NULL; 505 return 0; 506 } 507