1/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. 4 */ 5 6#include <stdlib.h> 7#include "cras_dsp_module.h" 8#include "drc.h" 9#include "dsp_util.h" 10#include "eq.h" 11#include "eq2.h" 12 13/* 14 * empty module functions (for source and sink) 15 */ 16static int empty_instantiate(struct dsp_module *module, 17 unsigned long sample_rate) 18{ 19 return 0; 20} 21 22static void empty_connect_port(struct dsp_module *module, unsigned long port, 23 float *data_location) {} 24 25static int empty_get_delay(struct dsp_module *module) 26{ 27 return 0; 28} 29 30static void empty_run(struct dsp_module *module, unsigned long sample_count) {} 31 32static void empty_deinstantiate(struct dsp_module *module) {} 33 34static void empty_free_module(struct dsp_module *module) 35{ 36 free(module); 37} 38 39static int empty_get_properties(struct dsp_module *module) { return 0; } 40 41static void empty_dump(struct dsp_module *module, struct dumper *d) 42{ 43 dumpf(d, "built-in module\n"); 44} 45 46static void empty_init_module(struct dsp_module *module) 47{ 48 module->instantiate = &empty_instantiate; 49 module->connect_port = &empty_connect_port; 50 module->get_delay = &empty_get_delay; 51 module->run = &empty_run; 52 module->deinstantiate = &empty_deinstantiate; 53 module->free_module = &empty_free_module; 54 module->get_properties = &empty_get_properties; 55 module->dump = &empty_dump; 56} 57 58/* 59 * swap_lr module functions 60 */ 61static int swap_lr_instantiate(struct dsp_module *module, 62 unsigned long sample_rate) 63{ 64 module->data = calloc(4, sizeof(float*)); 65 return 0; 66} 67 68static void swap_lr_connect_port(struct dsp_module *module, 69 unsigned long port, float *data_location) 70{ 71 float **ports; 72 ports = (float **)module->data; 73 ports[port] = data_location; 74} 75 76static void swap_lr_run(struct dsp_module *module, 77 unsigned long sample_count) 78{ 79 size_t i; 80 float **ports = (float **)module->data; 81 82 /* This module runs dsp in-place, so ports[0] == ports[2], 83 * ports[1] == ports[3]. Here we swap data on two channels. 84 */ 85 for (i = 0; i < sample_count; i++) { 86 float temp = ports[0][i]; 87 ports[2][i] = ports[1][i]; 88 ports[3][i] = temp; 89 } 90} 91 92static void swap_lr_deinstantiate(struct dsp_module *module) 93{ 94 free(module->data); 95} 96 97static void swap_lr_init_module(struct dsp_module *module) 98{ 99 module->instantiate = &swap_lr_instantiate; 100 module->connect_port = &swap_lr_connect_port; 101 module->get_delay = &empty_get_delay; 102 module->run = &swap_lr_run; 103 module->deinstantiate = &swap_lr_deinstantiate; 104 module->free_module = &empty_free_module; 105 module->get_properties = &empty_get_properties; 106} 107 108/* 109 * invert_lr module functions 110 */ 111static int invert_lr_instantiate(struct dsp_module *module, 112 unsigned long sample_rate) 113{ 114 module->data = calloc(4, sizeof(float*)); 115 return 0; 116} 117 118static void invert_lr_connect_port(struct dsp_module *module, 119 unsigned long port, float *data_location) 120{ 121 float **ports; 122 ports = (float **)module->data; 123 ports[port] = data_location; 124} 125 126static void invert_lr_run(struct dsp_module *module, 127 unsigned long sample_count) 128{ 129 size_t i; 130 float **ports = (float **)module->data; 131 132 for (i = 0; i < sample_count; i++) { 133 ports[2][i] = -ports[0][i]; 134 ports[3][i] = ports[1][i]; 135 } 136} 137 138static void invert_lr_deinstantiate(struct dsp_module *module) 139{ 140 free(module->data); 141} 142 143static void invert_lr_init_module(struct dsp_module *module) 144{ 145 module->instantiate = &invert_lr_instantiate; 146 module->connect_port = &invert_lr_connect_port; 147 module->get_delay = &empty_get_delay; 148 module->run = &invert_lr_run; 149 module->deinstantiate = &invert_lr_deinstantiate; 150 module->free_module = &empty_free_module; 151 module->get_properties = &empty_get_properties; 152} 153 154/* 155 * mix_stereo module functions 156 */ 157static int mix_stereo_instantiate(struct dsp_module *module, 158 unsigned long sample_rate) 159{ 160 module->data = calloc(4, sizeof(float*)); 161 return 0; 162} 163 164static void mix_stereo_connect_port(struct dsp_module *module, 165 unsigned long port, float *data_location) 166{ 167 float **ports; 168 ports = (float **)module->data; 169 ports[port] = data_location; 170} 171 172static void mix_stereo_run(struct dsp_module *module, 173 unsigned long sample_count) 174{ 175 size_t i; 176 float tmp; 177 float **ports = (float **)module->data; 178 179 for (i = 0; i < sample_count; i++) { 180 tmp = ports[0][i] + ports[1][i]; 181 ports[2][i] = tmp; 182 ports[3][i] = tmp; 183 } 184} 185 186static void mix_stereo_deinstantiate(struct dsp_module *module) 187{ 188 free(module->data); 189} 190 191static void mix_stereo_init_module(struct dsp_module *module) 192{ 193 module->instantiate = &mix_stereo_instantiate; 194 module->connect_port = &mix_stereo_connect_port; 195 module->get_delay = &empty_get_delay; 196 module->run = &mix_stereo_run; 197 module->deinstantiate = &mix_stereo_deinstantiate; 198 module->free_module = &empty_free_module; 199 module->get_properties = &empty_get_properties; 200 module->dump = &empty_dump; 201} 202 203/* 204 * eq module functions 205 */ 206struct eq_data { 207 int sample_rate; 208 struct eq *eq; /* Initialized in the first call of eq_run() */ 209 210 /* One port for input, one for output, and 4 parameters per eq */ 211 float *ports[2 + MAX_BIQUADS_PER_EQ * 4]; 212}; 213 214static int eq_instantiate(struct dsp_module *module, unsigned long sample_rate) 215{ 216 struct eq_data *data; 217 218 module->data = calloc(1, sizeof(struct eq_data)); 219 data = (struct eq_data *) module->data; 220 data->sample_rate = (int) sample_rate; 221 return 0; 222} 223 224static void eq_connect_port(struct dsp_module *module, 225 unsigned long port, float *data_location) 226{ 227 struct eq_data *data = (struct eq_data *) module->data; 228 data->ports[port] = data_location; 229} 230 231static void eq_run(struct dsp_module *module, unsigned long sample_count) 232{ 233 struct eq_data *data = (struct eq_data *) module->data; 234 if (!data->eq) { 235 float nyquist = data->sample_rate / 2; 236 int i; 237 238 data->eq = eq_new(); 239 for (i = 2; i < 2 + MAX_BIQUADS_PER_EQ * 4; i += 4) { 240 if (!data->ports[i]) 241 break; 242 int type = (int) *data->ports[i]; 243 float freq = *data->ports[i+1]; 244 float Q = *data->ports[i+2]; 245 float gain = *data->ports[i+3]; 246 eq_append_biquad(data->eq, type, freq / nyquist, Q, 247 gain); 248 } 249 } 250 if (data->ports[0] != data->ports[1]) 251 memcpy(data->ports[1], data->ports[0], 252 sizeof(float) * sample_count); 253 eq_process(data->eq, data->ports[1], (int) sample_count); 254} 255 256static void eq_deinstantiate(struct dsp_module *module) 257{ 258 struct eq_data *data = (struct eq_data *) module->data; 259 if (data->eq) 260 eq_free(data->eq); 261 free(data); 262} 263 264static void eq_init_module(struct dsp_module *module) 265{ 266 module->instantiate = &eq_instantiate; 267 module->connect_port = &eq_connect_port; 268 module->get_delay = &empty_get_delay; 269 module->run = &eq_run; 270 module->deinstantiate = &eq_deinstantiate; 271 module->free_module = &empty_free_module; 272 module->get_properties = &empty_get_properties; 273 module->dump = &empty_dump; 274} 275 276/* 277 * eq2 module functions 278 */ 279struct eq2_data { 280 int sample_rate; 281 struct eq2 *eq2; /* Initialized in the first call of eq2_run() */ 282 283 /* Two ports for input, two for output, and 8 parameters per eq pair */ 284 float *ports[4 + MAX_BIQUADS_PER_EQ2 * 8]; 285}; 286 287static int eq2_instantiate(struct dsp_module *module, unsigned long sample_rate) 288{ 289 struct eq2_data *data; 290 291 module->data = calloc(1, sizeof(struct eq2_data)); 292 data = (struct eq2_data *) module->data; 293 data->sample_rate = (int) sample_rate; 294 return 0; 295} 296 297static void eq2_connect_port(struct dsp_module *module, 298 unsigned long port, float *data_location) 299{ 300 struct eq2_data *data = (struct eq2_data *) module->data; 301 data->ports[port] = data_location; 302} 303 304static void eq2_run(struct dsp_module *module, unsigned long sample_count) 305{ 306 struct eq2_data *data = (struct eq2_data *) module->data; 307 if (!data->eq2) { 308 float nyquist = data->sample_rate / 2; 309 int i, channel; 310 311 data->eq2 = eq2_new(); 312 for (i = 4; i < 4 + MAX_BIQUADS_PER_EQ2 * 8; i += 8) { 313 if (!data->ports[i]) 314 break; 315 for (channel = 0; channel < 2; channel++) { 316 int k = i + channel * 4; 317 int type = (int) *data->ports[k]; 318 float freq = *data->ports[k+1]; 319 float Q = *data->ports[k+2]; 320 float gain = *data->ports[k+3]; 321 eq2_append_biquad(data->eq2, channel, type, 322 freq / nyquist, Q, gain); 323 } 324 } 325 } 326 327 328 if (data->ports[0] != data->ports[2]) 329 memcpy(data->ports[2], data->ports[0], 330 sizeof(float) * sample_count); 331 if (data->ports[3] != data->ports[1]) 332 memcpy(data->ports[3], data->ports[1], 333 sizeof(float) * sample_count); 334 335 eq2_process(data->eq2, data->ports[2], data->ports[3], 336 (int) sample_count); 337} 338 339static void eq2_deinstantiate(struct dsp_module *module) 340{ 341 struct eq2_data *data = (struct eq2_data *) module->data; 342 if (data->eq2) 343 eq2_free(data->eq2); 344 free(data); 345} 346 347static void eq2_init_module(struct dsp_module *module) 348{ 349 module->instantiate = &eq2_instantiate; 350 module->connect_port = &eq2_connect_port; 351 module->get_delay = &empty_get_delay; 352 module->run = &eq2_run; 353 module->deinstantiate = &eq2_deinstantiate; 354 module->free_module = &empty_free_module; 355 module->get_properties = &empty_get_properties; 356 module->dump = &empty_dump; 357} 358 359/* 360 * drc module functions 361 */ 362struct drc_data { 363 int sample_rate; 364 struct drc *drc; /* Initialized in the first call of drc_run() */ 365 366 /* Two ports for input, two for output, one for disable_emphasis, 367 * and 8 parameters each band */ 368 float *ports[4 + 1 + 8 * 3]; 369}; 370 371static int drc_instantiate(struct dsp_module *module, unsigned long sample_rate) 372{ 373 struct drc_data *data; 374 375 module->data = calloc(1, sizeof(struct drc_data)); 376 data = (struct drc_data *) module->data; 377 data->sample_rate = (int) sample_rate; 378 return 0; 379} 380 381static void drc_connect_port(struct dsp_module *module, 382 unsigned long port, float *data_location) 383{ 384 struct drc_data *data = (struct drc_data *) module->data; 385 data->ports[port] = data_location; 386} 387 388static int drc_get_delay(struct dsp_module *module) 389{ 390 struct drc_data *data = (struct drc_data *) module->data; 391 return DRC_DEFAULT_PRE_DELAY * data->sample_rate; 392} 393 394static void drc_run(struct dsp_module *module, unsigned long sample_count) 395{ 396 struct drc_data *data = (struct drc_data *) module->data; 397 if (!data->drc) { 398 int i; 399 float nyquist = data->sample_rate / 2; 400 struct drc *drc = drc_new(data->sample_rate); 401 402 data->drc = drc; 403 drc->emphasis_disabled = (int) *data->ports[4]; 404 for (i = 0; i < 3; i++) { 405 int k = 5 + i * 8; 406 float f = *data->ports[k]; 407 float enable = *data->ports[k+1]; 408 float threshold = *data->ports[k+2]; 409 float knee = *data->ports[k+3]; 410 float ratio = *data->ports[k+4]; 411 float attack = *data->ports[k+5]; 412 float release = *data->ports[k+6]; 413 float boost = *data->ports[k+7]; 414 drc_set_param(drc, i, PARAM_CROSSOVER_LOWER_FREQ, 415 f / nyquist); 416 drc_set_param(drc, i, PARAM_ENABLED, enable); 417 drc_set_param(drc, i, PARAM_THRESHOLD, threshold); 418 drc_set_param(drc, i, PARAM_KNEE, knee); 419 drc_set_param(drc, i, PARAM_RATIO, ratio); 420 drc_set_param(drc, i, PARAM_ATTACK, attack); 421 drc_set_param(drc, i, PARAM_RELEASE, release); 422 drc_set_param(drc, i, PARAM_POST_GAIN, boost); 423 } 424 drc_init(drc); 425 } 426 if (data->ports[0] != data->ports[2]) 427 memcpy(data->ports[2], data->ports[0], 428 sizeof(float) * sample_count); 429 if (data->ports[1] != data->ports[3]) 430 memcpy(data->ports[3], data->ports[1], 431 sizeof(float) * sample_count); 432 433 drc_process(data->drc, &data->ports[2], (int) sample_count); 434} 435 436static void drc_deinstantiate(struct dsp_module *module) 437{ 438 struct drc_data *data = (struct drc_data *) module->data; 439 if (data->drc) 440 drc_free(data->drc); 441 free(data); 442} 443 444static void drc_init_module(struct dsp_module *module) 445{ 446 module->instantiate = &drc_instantiate; 447 module->connect_port = &drc_connect_port; 448 module->get_delay = &drc_get_delay; 449 module->run = &drc_run; 450 module->deinstantiate = &drc_deinstantiate; 451 module->free_module = &empty_free_module; 452 module->get_properties = &empty_get_properties; 453 module->dump = &empty_dump; 454} 455 456/* 457 * builtin module dispatcher 458 */ 459struct dsp_module *cras_dsp_module_load_builtin(struct plugin *plugin) 460{ 461 struct dsp_module *module; 462 if (strcmp(plugin->library, "builtin") != 0) 463 return NULL; 464 465 module = calloc(1, sizeof(struct dsp_module)); 466 467 if (strcmp(plugin->label, "mix_stereo") == 0) { 468 mix_stereo_init_module(module); 469 } else if (strcmp(plugin->label, "invert_lr") == 0) { 470 invert_lr_init_module(module); 471 } else if (strcmp(plugin->label, "eq") == 0) { 472 eq_init_module(module); 473 } else if (strcmp(plugin->label, "eq2") == 0) { 474 eq2_init_module(module); 475 } else if (strcmp(plugin->label, "drc") == 0) { 476 drc_init_module(module); 477 } else if (strcmp(plugin->label, "swap_lr") == 0) { 478 swap_lr_init_module(module); 479 } else { 480 empty_init_module(module); 481 } 482 483 return module; 484} 485