Home | History | Annotate | Download | only in hal
      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_init_module(struct dsp_module *module)
     42 {
     43 	module->instantiate = &empty_instantiate;
     44 	module->connect_port = &empty_connect_port;
     45 	module->get_delay = &empty_get_delay;
     46 	module->run = &empty_run;
     47 	module->deinstantiate = &empty_deinstantiate;
     48 	module->free_module = &empty_free_module;
     49 	module->get_properties = &empty_get_properties;
     50 }
     51 
     52 /*
     53  *  invert_lr module functions
     54  */
     55 static int invert_lr_instantiate(struct dsp_module *module,
     56 				 unsigned long sample_rate)
     57 {
     58 	module->data = calloc(4, sizeof(float*));
     59 	return 0;
     60 }
     61 
     62 static void invert_lr_connect_port(struct dsp_module *module,
     63 				   unsigned long port, float *data_location)
     64 {
     65 	float **ports;
     66 	ports = (float **)module->data;
     67 	ports[port] = data_location;
     68 }
     69 
     70 static void invert_lr_run(struct dsp_module *module,
     71 			  unsigned long sample_count)
     72 {
     73 	size_t i;
     74 	float **ports = (float **)module->data;
     75 
     76 	for (i = 0; i < sample_count; i++) {
     77 		ports[2][i] = -ports[0][i];
     78 		ports[3][i] = ports[1][i];
     79 	}
     80 }
     81 
     82 static void invert_lr_deinstantiate(struct dsp_module *module)
     83 {
     84 	free(module->data);
     85 }
     86 
     87 static void invert_lr_init_module(struct dsp_module *module)
     88 {
     89 	module->instantiate = &invert_lr_instantiate;
     90 	module->connect_port = &invert_lr_connect_port;
     91 	module->get_delay = &empty_get_delay;
     92 	module->run = &invert_lr_run;
     93 	module->deinstantiate = &invert_lr_deinstantiate;
     94 	module->free_module = &empty_free_module;
     95 	module->get_properties = &empty_get_properties;
     96 }
     97 
     98 /*
     99  *  mix_stereo module functions
    100  */
    101 static int mix_stereo_instantiate(struct dsp_module *module,
    102 				  unsigned long sample_rate)
    103 {
    104 	module->data = calloc(4, sizeof(float*));
    105 	return 0;
    106 }
    107 
    108 static void mix_stereo_connect_port(struct dsp_module *module,
    109 				    unsigned long port, float *data_location)
    110 {
    111 	float **ports;
    112 	ports = (float **)module->data;
    113 	ports[port] = data_location;
    114 }
    115 
    116 static void mix_stereo_run(struct dsp_module *module,
    117 			   unsigned long sample_count)
    118 {
    119 	size_t i;
    120 	float tmp;
    121 	float **ports = (float **)module->data;
    122 
    123 	for (i = 0; i < sample_count; i++) {
    124 		tmp = ports[0][i] + ports[1][i];
    125 		ports[2][i] = tmp;
    126 		ports[3][i] = tmp;
    127 	}
    128 }
    129 
    130 static void mix_stereo_deinstantiate(struct dsp_module *module)
    131 {
    132 	free(module->data);
    133 }
    134 
    135 static void mix_stereo_init_module(struct dsp_module *module)
    136 {
    137 	module->instantiate = &mix_stereo_instantiate;
    138 	module->connect_port = &mix_stereo_connect_port;
    139 	module->get_delay = &empty_get_delay;
    140 	module->run = &mix_stereo_run;
    141 	module->deinstantiate = &mix_stereo_deinstantiate;
    142 	module->free_module = &empty_free_module;
    143 	module->get_properties = &empty_get_properties;
    144 }
    145 
    146 /*
    147  *  eq module functions
    148  */
    149 struct eq_data {
    150 	int sample_rate;
    151 	struct eq *eq;  /* Initialized in the first call of eq_run() */
    152 
    153 	/* One port for input, one for output, and 4 parameters per eq */
    154 	float *ports[2 + MAX_BIQUADS_PER_EQ * 4];
    155 };
    156 
    157 static int eq_instantiate(struct dsp_module *module, unsigned long sample_rate)
    158 {
    159 	struct eq_data *data;
    160 
    161 	module->data = calloc(1, sizeof(struct eq_data));
    162 	data = (struct eq_data *) module->data;
    163 	data->sample_rate = (int) sample_rate;
    164 	return 0;
    165 }
    166 
    167 static void eq_connect_port(struct dsp_module *module,
    168 			    unsigned long port, float *data_location)
    169 {
    170 	struct eq_data *data = (struct eq_data *) module->data;
    171 	data->ports[port] = data_location;
    172 }
    173 
    174 static void eq_run(struct dsp_module *module, unsigned long sample_count)
    175 {
    176 	struct eq_data *data = (struct eq_data *) module->data;
    177 	if (!data->eq) {
    178 		float nyquist = data->sample_rate / 2;
    179 		int i;
    180 
    181 		data->eq = eq_new();
    182 		for (i = 2; i < 2 + MAX_BIQUADS_PER_EQ * 4; i += 4) {
    183 			if (!data->ports[i])
    184 				break;
    185 			int type = (int) *data->ports[i];
    186 			float freq = *data->ports[i+1];
    187 			float Q = *data->ports[i+2];
    188 			float gain = *data->ports[i+3];
    189 			eq_append_biquad(data->eq, type, freq / nyquist, Q,
    190 					 gain);
    191 		}
    192 	}
    193 	if (data->ports[0] != data->ports[1])
    194 		memcpy(data->ports[1], data->ports[0],
    195 		       sizeof(float) * sample_count);
    196 	eq_process(data->eq, data->ports[1], (int) sample_count);
    197 }
    198 
    199 static void eq_deinstantiate(struct dsp_module *module)
    200 {
    201 	struct eq_data *data = (struct eq_data *) module->data;
    202 	if (data->eq)
    203 		eq_free(data->eq);
    204 	free(data);
    205 }
    206 
    207 static void eq_init_module(struct dsp_module *module)
    208 {
    209 	module->instantiate = &eq_instantiate;
    210 	module->connect_port = &eq_connect_port;
    211 	module->get_delay = &empty_get_delay;
    212 	module->run = &eq_run;
    213 	module->deinstantiate = &eq_deinstantiate;
    214 	module->free_module = &empty_free_module;
    215 	module->get_properties = &empty_get_properties;
    216 }
    217 
    218 /*
    219  *  eq2 module functions
    220  */
    221 struct eq2_data {
    222 	int sample_rate;
    223 	struct eq2 *eq2;  /* Initialized in the first call of eq2_run() */
    224 
    225 	/* Two ports for input, two for output, and 8 parameters per eq pair */
    226 	float *ports[4 + MAX_BIQUADS_PER_EQ2 * 8];
    227 };
    228 
    229 static int eq2_instantiate(struct dsp_module *module, unsigned long sample_rate)
    230 {
    231 	struct eq2_data *data;
    232 
    233 	module->data = calloc(1, sizeof(struct eq2_data));
    234 	data = (struct eq2_data *) module->data;
    235 	data->sample_rate = (int) sample_rate;
    236 	return 0;
    237 }
    238 
    239 static void eq2_connect_port(struct dsp_module *module,
    240 			     unsigned long port, float *data_location)
    241 {
    242 	struct eq2_data *data = (struct eq2_data *) module->data;
    243 	data->ports[port] = data_location;
    244 }
    245 
    246 static void eq2_run(struct dsp_module *module, unsigned long sample_count)
    247 {
    248 	struct eq2_data *data = (struct eq2_data *) module->data;
    249 	if (!data->eq2) {
    250 		float nyquist = data->sample_rate / 2;
    251 		int i, channel;
    252 
    253 		data->eq2 = eq2_new();
    254 		for (i = 4; i < 4 + MAX_BIQUADS_PER_EQ2 * 8; i += 8) {
    255 			if (!data->ports[i])
    256 				break;
    257 			for (channel = 0; channel < 2; channel++) {
    258 				int k = i + channel * 4;
    259 				int type = (int) *data->ports[k];
    260 				float freq = *data->ports[k+1];
    261 				float Q = *data->ports[k+2];
    262 				float gain = *data->ports[k+3];
    263 				eq2_append_biquad(data->eq2, channel, type,
    264 						  freq / nyquist, Q, gain);
    265 			}
    266 		}
    267 	}
    268 
    269 
    270 	if (data->ports[0] != data->ports[2])
    271 		memcpy(data->ports[2], data->ports[0],
    272 		       sizeof(float) * sample_count);
    273 	if (data->ports[3] != data->ports[1])
    274 		memcpy(data->ports[3], data->ports[1],
    275 		       sizeof(float) * sample_count);
    276 
    277 	eq2_process(data->eq2, data->ports[2], data->ports[3],
    278 		    (int) sample_count);
    279 }
    280 
    281 static void eq2_deinstantiate(struct dsp_module *module)
    282 {
    283 	struct eq2_data *data = (struct eq2_data *) module->data;
    284 	if (data->eq2)
    285 		eq2_free(data->eq2);
    286 	free(data);
    287 }
    288 
    289 static void eq2_init_module(struct dsp_module *module)
    290 {
    291 	module->instantiate = &eq2_instantiate;
    292 	module->connect_port = &eq2_connect_port;
    293 	module->get_delay = &empty_get_delay;
    294 	module->run = &eq2_run;
    295 	module->deinstantiate = &eq2_deinstantiate;
    296 	module->free_module = &empty_free_module;
    297 	module->get_properties = &empty_get_properties;
    298 }
    299 
    300 /*
    301  *  drc module functions
    302  */
    303 struct drc_data {
    304 	int sample_rate;
    305 	struct drc *drc;  /* Initialized in the first call of drc_run() */
    306 
    307 	/* Two ports for input, two for output, one for disable_emphasis,
    308 	 * and 8 parameters each band */
    309 	float *ports[4 + 1 + 8 * 3];
    310 };
    311 
    312 static int drc_instantiate(struct dsp_module *module, unsigned long sample_rate)
    313 {
    314 	struct drc_data *data;
    315 
    316 	module->data = calloc(1, sizeof(struct drc_data));
    317 	data = (struct drc_data *) module->data;
    318 	data->sample_rate = (int) sample_rate;
    319 	return 0;
    320 }
    321 
    322 static void drc_connect_port(struct dsp_module *module,
    323 			    unsigned long port, float *data_location)
    324 {
    325 	struct drc_data *data = (struct drc_data *) module->data;
    326 	data->ports[port] = data_location;
    327 }
    328 
    329 static int drc_get_delay(struct dsp_module *module)
    330 {
    331 	struct drc_data *data = (struct drc_data *) module->data;
    332 	return DRC_DEFAULT_PRE_DELAY * data->sample_rate;
    333 }
    334 
    335 static void drc_run(struct dsp_module *module, unsigned long sample_count)
    336 {
    337 	struct drc_data *data = (struct drc_data *) module->data;
    338 	if (!data->drc) {
    339 		int i;
    340 		float nyquist = data->sample_rate / 2;
    341 		struct drc *drc = drc_new(data->sample_rate);
    342 
    343 		data->drc = drc;
    344 		drc->emphasis_disabled = (int) *data->ports[4];
    345 		for (i = 0; i < 3; i++) {
    346 			int k = 5 + i * 8;
    347 			float f = *data->ports[k];
    348 			float enable = *data->ports[k+1];
    349 			float threshold = *data->ports[k+2];
    350 			float knee = *data->ports[k+3];
    351 			float ratio = *data->ports[k+4];
    352 			float attack = *data->ports[k+5];
    353 			float release = *data->ports[k+6];
    354 			float boost = *data->ports[k+7];
    355 			drc_set_param(drc, i, PARAM_CROSSOVER_LOWER_FREQ,
    356 				      f / nyquist);
    357 			drc_set_param(drc, i, PARAM_ENABLED, enable);
    358 			drc_set_param(drc, i, PARAM_THRESHOLD, threshold);
    359 			drc_set_param(drc, i, PARAM_KNEE, knee);
    360 			drc_set_param(drc, i, PARAM_RATIO, ratio);
    361 			drc_set_param(drc, i, PARAM_ATTACK, attack);
    362 			drc_set_param(drc, i, PARAM_RELEASE, release);
    363 			drc_set_param(drc, i, PARAM_POST_GAIN, boost);
    364 		}
    365 		drc_init(drc);
    366 	}
    367 	if (data->ports[0] != data->ports[2])
    368 		memcpy(data->ports[2], data->ports[0],
    369 		       sizeof(float) * sample_count);
    370 	if (data->ports[1] != data->ports[3])
    371 		memcpy(data->ports[3], data->ports[1],
    372 		       sizeof(float) * sample_count);
    373 
    374 	drc_process(data->drc, &data->ports[2], (int) sample_count);
    375 }
    376 
    377 static void drc_deinstantiate(struct dsp_module *module)
    378 {
    379 	struct drc_data *data = (struct drc_data *) module->data;
    380 	if (data->drc)
    381 		drc_free(data->drc);
    382 	free(data);
    383 }
    384 
    385 static void drc_init_module(struct dsp_module *module)
    386 {
    387 	module->instantiate = &drc_instantiate;
    388 	module->connect_port = &drc_connect_port;
    389 	module->get_delay = &drc_get_delay;
    390 	module->run = &drc_run;
    391 	module->deinstantiate = &drc_deinstantiate;
    392 	module->free_module = &empty_free_module;
    393 	module->get_properties = &empty_get_properties;
    394 }
    395 
    396 /*
    397  *  builtin module dispatcher
    398  */
    399 struct dsp_module *cras_dsp_module_load_builtin(struct plugin *plugin)
    400 {
    401 	struct dsp_module *module;
    402 	if (strcmp(plugin->library, "builtin") != 0)
    403 		return NULL;
    404 
    405 	module = calloc(1, sizeof(struct dsp_module));
    406 
    407 	if (strcmp(plugin->label, "mix_stereo") == 0) {
    408 		mix_stereo_init_module(module);
    409 	} else if (strcmp(plugin->label, "invert_lr") == 0) {
    410 		invert_lr_init_module(module);
    411 	} else if (strcmp(plugin->label, "eq") == 0) {
    412 		eq_init_module(module);
    413 	} else if (strcmp(plugin->label, "eq2") == 0) {
    414 		eq2_init_module(module);
    415 	} else if (strcmp(plugin->label, "drc") == 0) {
    416 		drc_init_module(module);
    417 	} else {
    418 		empty_init_module(module);
    419 	}
    420 
    421 	return module;
    422 }
    423