Home | History | Annotate | Download | only in server
      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  */
     16 static int empty_instantiate(struct dsp_module *module,
     17 			     unsigned long sample_rate)
     18 {
     19 	return 0;
     20 }
     21 
     22 static void empty_connect_port(struct dsp_module *module, unsigned long port,
     23 			       float *data_location) {}
     24 
     25 static int empty_get_delay(struct dsp_module *module)
     26 {
     27 	return 0;
     28 }
     29 
     30 static void empty_run(struct dsp_module *module, unsigned long sample_count) {}
     31 
     32 static void empty_deinstantiate(struct dsp_module *module) {}
     33 
     34 static void empty_free_module(struct dsp_module *module)
     35 {
     36 	free(module);
     37 }
     38 
     39 static int empty_get_properties(struct dsp_module *module) { return 0; }
     40 
     41 static void empty_dump(struct dsp_module *module, struct dumper *d)
     42 {
     43 	dumpf(d, "built-in module\n");
     44 }
     45 
     46 static 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  */
     61 static 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 
     68 static 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 
     76 static 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 
     92 static void swap_lr_deinstantiate(struct dsp_module *module)
     93 {
     94 	free(module->data);
     95 }
     96 
     97 static 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  */
    111 static 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 
    118 static 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 
    126 static 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 
    138 static void invert_lr_deinstantiate(struct dsp_module *module)
    139 {
    140 	free(module->data);
    141 }
    142 
    143 static 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  */
    157 static 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 
    164 static 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 
    172 static 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 
    186 static void mix_stereo_deinstantiate(struct dsp_module *module)
    187 {
    188 	free(module->data);
    189 }
    190 
    191 static 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  */
    206 struct 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 
    214 static 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 
    224 static 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 
    231 static 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 
    256 static 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 
    264 static 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  */
    279 struct 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 
    287 static 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 
    297 static 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 
    304 static 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 
    339 static 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 
    347 static 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  */
    362 struct 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 
    371 static 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 
    381 static 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 
    388 static 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 
    394 static 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 
    436 static 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 
    444 static 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  */
    459 struct 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