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 "dcblock.h"
11 #include "eq.h"
12 #include "eq2.h"
13
14 /*
15 * empty module functions (for source and sink)
16 */
empty_instantiate(struct dsp_module * module,unsigned long sample_rate)17 static int empty_instantiate(struct dsp_module *module,
18 unsigned long sample_rate)
19 {
20 return 0;
21 }
22
empty_connect_port(struct dsp_module * module,unsigned long port,float * data_location)23 static void empty_connect_port(struct dsp_module *module, unsigned long port,
24 float *data_location) {}
25
empty_get_delay(struct dsp_module * module)26 static int empty_get_delay(struct dsp_module *module)
27 {
28 return 0;
29 }
30
empty_run(struct dsp_module * module,unsigned long sample_count)31 static void empty_run(struct dsp_module *module, unsigned long sample_count) {}
32
empty_deinstantiate(struct dsp_module * module)33 static void empty_deinstantiate(struct dsp_module *module) {}
34
empty_free_module(struct dsp_module * module)35 static void empty_free_module(struct dsp_module *module)
36 {
37 free(module);
38 }
39
empty_get_properties(struct dsp_module * module)40 static int empty_get_properties(struct dsp_module *module) { return 0; }
41
empty_dump(struct dsp_module * module,struct dumper * d)42 static void empty_dump(struct dsp_module *module, struct dumper *d)
43 {
44 dumpf(d, "built-in module\n");
45 }
46
empty_init_module(struct dsp_module * module)47 static void empty_init_module(struct dsp_module *module)
48 {
49 module->instantiate = &empty_instantiate;
50 module->connect_port = &empty_connect_port;
51 module->get_delay = &empty_get_delay;
52 module->run = &empty_run;
53 module->deinstantiate = &empty_deinstantiate;
54 module->free_module = &empty_free_module;
55 module->get_properties = &empty_get_properties;
56 module->dump = &empty_dump;
57 }
58
59 /*
60 * swap_lr module functions
61 */
swap_lr_instantiate(struct dsp_module * module,unsigned long sample_rate)62 static int swap_lr_instantiate(struct dsp_module *module,
63 unsigned long sample_rate)
64 {
65 module->data = calloc(4, sizeof(float*));
66 return 0;
67 }
68
swap_lr_connect_port(struct dsp_module * module,unsigned long port,float * data_location)69 static void swap_lr_connect_port(struct dsp_module *module,
70 unsigned long port, float *data_location)
71 {
72 float **ports;
73 ports = (float **)module->data;
74 ports[port] = data_location;
75 }
76
swap_lr_run(struct dsp_module * module,unsigned long sample_count)77 static void swap_lr_run(struct dsp_module *module,
78 unsigned long sample_count)
79 {
80 size_t i;
81 float **ports = (float **)module->data;
82
83 /* This module runs dsp in-place, so ports[0] == ports[2],
84 * ports[1] == ports[3]. Here we swap data on two channels.
85 */
86 for (i = 0; i < sample_count; i++) {
87 float temp = ports[0][i];
88 ports[2][i] = ports[1][i];
89 ports[3][i] = temp;
90 }
91 }
92
swap_lr_deinstantiate(struct dsp_module * module)93 static void swap_lr_deinstantiate(struct dsp_module *module)
94 {
95 free(module->data);
96 }
97
swap_lr_init_module(struct dsp_module * module)98 static void swap_lr_init_module(struct dsp_module *module)
99 {
100 module->instantiate = &swap_lr_instantiate;
101 module->connect_port = &swap_lr_connect_port;
102 module->get_delay = &empty_get_delay;
103 module->run = &swap_lr_run;
104 module->deinstantiate = &swap_lr_deinstantiate;
105 module->free_module = &empty_free_module;
106 module->get_properties = &empty_get_properties;
107 }
108
109 /*
110 * invert_lr module functions
111 */
invert_lr_instantiate(struct dsp_module * module,unsigned long sample_rate)112 static int invert_lr_instantiate(struct dsp_module *module,
113 unsigned long sample_rate)
114 {
115 module->data = calloc(4, sizeof(float*));
116 return 0;
117 }
118
invert_lr_connect_port(struct dsp_module * module,unsigned long port,float * data_location)119 static void invert_lr_connect_port(struct dsp_module *module,
120 unsigned long port, float *data_location)
121 {
122 float **ports;
123 ports = (float **)module->data;
124 ports[port] = data_location;
125 }
126
invert_lr_run(struct dsp_module * module,unsigned long sample_count)127 static void invert_lr_run(struct dsp_module *module,
128 unsigned long sample_count)
129 {
130 size_t i;
131 float **ports = (float **)module->data;
132
133 for (i = 0; i < sample_count; i++) {
134 ports[2][i] = -ports[0][i];
135 ports[3][i] = ports[1][i];
136 }
137 }
138
invert_lr_deinstantiate(struct dsp_module * module)139 static void invert_lr_deinstantiate(struct dsp_module *module)
140 {
141 free(module->data);
142 }
143
invert_lr_init_module(struct dsp_module * module)144 static void invert_lr_init_module(struct dsp_module *module)
145 {
146 module->instantiate = &invert_lr_instantiate;
147 module->connect_port = &invert_lr_connect_port;
148 module->get_delay = &empty_get_delay;
149 module->run = &invert_lr_run;
150 module->deinstantiate = &invert_lr_deinstantiate;
151 module->free_module = &empty_free_module;
152 module->get_properties = &empty_get_properties;
153 }
154
155 /*
156 * mix_stereo module functions
157 */
mix_stereo_instantiate(struct dsp_module * module,unsigned long sample_rate)158 static int mix_stereo_instantiate(struct dsp_module *module,
159 unsigned long sample_rate)
160 {
161 module->data = calloc(4, sizeof(float*));
162 return 0;
163 }
164
mix_stereo_connect_port(struct dsp_module * module,unsigned long port,float * data_location)165 static void mix_stereo_connect_port(struct dsp_module *module,
166 unsigned long port, float *data_location)
167 {
168 float **ports;
169 ports = (float **)module->data;
170 ports[port] = data_location;
171 }
172
mix_stereo_run(struct dsp_module * module,unsigned long sample_count)173 static void mix_stereo_run(struct dsp_module *module,
174 unsigned long sample_count)
175 {
176 size_t i;
177 float tmp;
178 float **ports = (float **)module->data;
179
180 for (i = 0; i < sample_count; i++) {
181 tmp = ports[0][i] + ports[1][i];
182 ports[2][i] = tmp;
183 ports[3][i] = tmp;
184 }
185 }
186
mix_stereo_deinstantiate(struct dsp_module * module)187 static void mix_stereo_deinstantiate(struct dsp_module *module)
188 {
189 free(module->data);
190 }
191
mix_stereo_init_module(struct dsp_module * module)192 static void mix_stereo_init_module(struct dsp_module *module)
193 {
194 module->instantiate = &mix_stereo_instantiate;
195 module->connect_port = &mix_stereo_connect_port;
196 module->get_delay = &empty_get_delay;
197 module->run = &mix_stereo_run;
198 module->deinstantiate = &mix_stereo_deinstantiate;
199 module->free_module = &empty_free_module;
200 module->get_properties = &empty_get_properties;
201 module->dump = &empty_dump;
202 }
203
204 /*
205 * dcblock module functions
206 */
207 struct dcblock_data {
208 struct dcblock *dcblockl;
209 struct dcblock *dcblockr;
210
211 /* One port for input, one for output, and 1 parameter */
212 float *ports[5];
213 };
214
dcblock_instantiate(struct dsp_module * module,unsigned long sample_rate)215 static int dcblock_instantiate(struct dsp_module *module,
216 unsigned long sample_rate)
217 {
218 module->data = calloc(1, sizeof(struct dcblock_data));
219 return 0;
220 }
221
dcblock_connect_port(struct dsp_module * module,unsigned long port,float * data_location)222 static void dcblock_connect_port(struct dsp_module *module,
223 unsigned long port, float *data_location)
224 {
225 struct dcblock_data *data = (struct dcblock_data *) module->data;
226 data->ports[port] = data_location;
227 }
228
dcblock_run(struct dsp_module * module,unsigned long sample_count)229 static void dcblock_run(struct dsp_module *module, unsigned long sample_count)
230 {
231 struct dcblock_data *data = (struct dcblock_data *) module->data;
232 if (!data->dcblockl)
233 data->dcblockl = dcblock_new(*data->ports[4]);
234 if (!data->dcblockr)
235 data->dcblockr = dcblock_new(*data->ports[4]);
236 if (data->ports[0] != data->ports[2])
237 memcpy(data->ports[2], data->ports[0],
238 sizeof(float) * sample_count);
239 if (data->ports[1] != data->ports[3])
240 memcpy(data->ports[3], data->ports[1],
241 sizeof(float) * sample_count);
242
243 dcblock_process(data->dcblockl, data->ports[2], (int) sample_count);
244 dcblock_process(data->dcblockr, data->ports[3], (int) sample_count);
245 }
246
dcblock_deinstantiate(struct dsp_module * module)247 static void dcblock_deinstantiate(struct dsp_module *module)
248 {
249 struct dcblock_data *data = (struct dcblock_data *) module->data;
250 if (data->dcblockl)
251 dcblock_free(data->dcblockl);
252 if (data->dcblockr)
253 dcblock_free(data->dcblockr);
254 free(data);
255 }
256
dcblock_init_module(struct dsp_module * module)257 static void dcblock_init_module(struct dsp_module *module)
258 {
259 module->instantiate = &dcblock_instantiate;
260 module->connect_port = &dcblock_connect_port;
261 module->get_delay = &empty_get_delay;
262 module->run = &dcblock_run;
263 module->deinstantiate = &dcblock_deinstantiate;
264 module->free_module = &empty_free_module;
265 module->get_properties = &empty_get_properties;
266 module->dump = &empty_dump;
267 }
268
269 /*
270 * eq module functions
271 */
272 struct eq_data {
273 int sample_rate;
274 struct eq *eq; /* Initialized in the first call of eq_run() */
275
276 /* One port for input, one for output, and 4 parameters per eq */
277 float *ports[2 + MAX_BIQUADS_PER_EQ * 4];
278 };
279
eq_instantiate(struct dsp_module * module,unsigned long sample_rate)280 static int eq_instantiate(struct dsp_module *module, unsigned long sample_rate)
281 {
282 struct eq_data *data;
283
284 module->data = calloc(1, sizeof(struct eq_data));
285 data = (struct eq_data *) module->data;
286 data->sample_rate = (int) sample_rate;
287 return 0;
288 }
289
eq_connect_port(struct dsp_module * module,unsigned long port,float * data_location)290 static void eq_connect_port(struct dsp_module *module,
291 unsigned long port, float *data_location)
292 {
293 struct eq_data *data = (struct eq_data *) module->data;
294 data->ports[port] = data_location;
295 }
296
eq_run(struct dsp_module * module,unsigned long sample_count)297 static void eq_run(struct dsp_module *module, unsigned long sample_count)
298 {
299 struct eq_data *data = (struct eq_data *) module->data;
300 if (!data->eq) {
301 float nyquist = data->sample_rate / 2;
302 int i;
303
304 data->eq = eq_new();
305 for (i = 2; i < 2 + MAX_BIQUADS_PER_EQ * 4; i += 4) {
306 if (!data->ports[i])
307 break;
308 int type = (int) *data->ports[i];
309 float freq = *data->ports[i+1];
310 float Q = *data->ports[i+2];
311 float gain = *data->ports[i+3];
312 eq_append_biquad(data->eq, type, freq / nyquist, Q,
313 gain);
314 }
315 }
316 if (data->ports[0] != data->ports[1])
317 memcpy(data->ports[1], data->ports[0],
318 sizeof(float) * sample_count);
319 eq_process(data->eq, data->ports[1], (int) sample_count);
320 }
321
eq_deinstantiate(struct dsp_module * module)322 static void eq_deinstantiate(struct dsp_module *module)
323 {
324 struct eq_data *data = (struct eq_data *) module->data;
325 if (data->eq)
326 eq_free(data->eq);
327 free(data);
328 }
329
eq_init_module(struct dsp_module * module)330 static void eq_init_module(struct dsp_module *module)
331 {
332 module->instantiate = &eq_instantiate;
333 module->connect_port = &eq_connect_port;
334 module->get_delay = &empty_get_delay;
335 module->run = &eq_run;
336 module->deinstantiate = &eq_deinstantiate;
337 module->free_module = &empty_free_module;
338 module->get_properties = &empty_get_properties;
339 module->dump = &empty_dump;
340 }
341
342 /*
343 * eq2 module functions
344 */
345 struct eq2_data {
346 int sample_rate;
347 struct eq2 *eq2; /* Initialized in the first call of eq2_run() */
348
349 /* Two ports for input, two for output, and 8 parameters per eq pair */
350 float *ports[4 + MAX_BIQUADS_PER_EQ2 * 8];
351 };
352
eq2_instantiate(struct dsp_module * module,unsigned long sample_rate)353 static int eq2_instantiate(struct dsp_module *module, unsigned long sample_rate)
354 {
355 struct eq2_data *data;
356
357 module->data = calloc(1, sizeof(struct eq2_data));
358 data = (struct eq2_data *) module->data;
359 data->sample_rate = (int) sample_rate;
360 return 0;
361 }
362
eq2_connect_port(struct dsp_module * module,unsigned long port,float * data_location)363 static void eq2_connect_port(struct dsp_module *module,
364 unsigned long port, float *data_location)
365 {
366 struct eq2_data *data = (struct eq2_data *) module->data;
367 data->ports[port] = data_location;
368 }
369
eq2_run(struct dsp_module * module,unsigned long sample_count)370 static void eq2_run(struct dsp_module *module, unsigned long sample_count)
371 {
372 struct eq2_data *data = (struct eq2_data *) module->data;
373 if (!data->eq2) {
374 float nyquist = data->sample_rate / 2;
375 int i, channel;
376
377 data->eq2 = eq2_new();
378 for (i = 4; i < 4 + MAX_BIQUADS_PER_EQ2 * 8; i += 8) {
379 if (!data->ports[i])
380 break;
381 for (channel = 0; channel < 2; channel++) {
382 int k = i + channel * 4;
383 int type = (int) *data->ports[k];
384 float freq = *data->ports[k+1];
385 float Q = *data->ports[k+2];
386 float gain = *data->ports[k+3];
387 eq2_append_biquad(data->eq2, channel, type,
388 freq / nyquist, Q, gain);
389 }
390 }
391 }
392
393
394 if (data->ports[0] != data->ports[2])
395 memcpy(data->ports[2], data->ports[0],
396 sizeof(float) * sample_count);
397 if (data->ports[3] != data->ports[1])
398 memcpy(data->ports[3], data->ports[1],
399 sizeof(float) * sample_count);
400
401 eq2_process(data->eq2, data->ports[2], data->ports[3],
402 (int) sample_count);
403 }
404
eq2_deinstantiate(struct dsp_module * module)405 static void eq2_deinstantiate(struct dsp_module *module)
406 {
407 struct eq2_data *data = (struct eq2_data *) module->data;
408 if (data->eq2)
409 eq2_free(data->eq2);
410 free(data);
411 }
412
eq2_init_module(struct dsp_module * module)413 static void eq2_init_module(struct dsp_module *module)
414 {
415 module->instantiate = &eq2_instantiate;
416 module->connect_port = &eq2_connect_port;
417 module->get_delay = &empty_get_delay;
418 module->run = &eq2_run;
419 module->deinstantiate = &eq2_deinstantiate;
420 module->free_module = &empty_free_module;
421 module->get_properties = &empty_get_properties;
422 module->dump = &empty_dump;
423 }
424
425 /*
426 * drc module functions
427 */
428 struct drc_data {
429 int sample_rate;
430 struct drc *drc; /* Initialized in the first call of drc_run() */
431
432 /* Two ports for input, two for output, one for disable_emphasis,
433 * and 8 parameters each band */
434 float *ports[4 + 1 + 8 * 3];
435 };
436
drc_instantiate(struct dsp_module * module,unsigned long sample_rate)437 static int drc_instantiate(struct dsp_module *module, unsigned long sample_rate)
438 {
439 struct drc_data *data;
440
441 module->data = calloc(1, sizeof(struct drc_data));
442 data = (struct drc_data *) module->data;
443 data->sample_rate = (int) sample_rate;
444 return 0;
445 }
446
drc_connect_port(struct dsp_module * module,unsigned long port,float * data_location)447 static void drc_connect_port(struct dsp_module *module,
448 unsigned long port, float *data_location)
449 {
450 struct drc_data *data = (struct drc_data *) module->data;
451 data->ports[port] = data_location;
452 }
453
drc_get_delay(struct dsp_module * module)454 static int drc_get_delay(struct dsp_module *module)
455 {
456 struct drc_data *data = (struct drc_data *) module->data;
457 return DRC_DEFAULT_PRE_DELAY * data->sample_rate;
458 }
459
drc_run(struct dsp_module * module,unsigned long sample_count)460 static void drc_run(struct dsp_module *module, unsigned long sample_count)
461 {
462 struct drc_data *data = (struct drc_data *) module->data;
463 if (!data->drc) {
464 int i;
465 float nyquist = data->sample_rate / 2;
466 struct drc *drc = drc_new(data->sample_rate);
467
468 data->drc = drc;
469 drc->emphasis_disabled = (int) *data->ports[4];
470 for (i = 0; i < 3; i++) {
471 int k = 5 + i * 8;
472 float f = *data->ports[k];
473 float enable = *data->ports[k+1];
474 float threshold = *data->ports[k+2];
475 float knee = *data->ports[k+3];
476 float ratio = *data->ports[k+4];
477 float attack = *data->ports[k+5];
478 float release = *data->ports[k+6];
479 float boost = *data->ports[k+7];
480 drc_set_param(drc, i, PARAM_CROSSOVER_LOWER_FREQ,
481 f / nyquist);
482 drc_set_param(drc, i, PARAM_ENABLED, enable);
483 drc_set_param(drc, i, PARAM_THRESHOLD, threshold);
484 drc_set_param(drc, i, PARAM_KNEE, knee);
485 drc_set_param(drc, i, PARAM_RATIO, ratio);
486 drc_set_param(drc, i, PARAM_ATTACK, attack);
487 drc_set_param(drc, i, PARAM_RELEASE, release);
488 drc_set_param(drc, i, PARAM_POST_GAIN, boost);
489 }
490 drc_init(drc);
491 }
492 if (data->ports[0] != data->ports[2])
493 memcpy(data->ports[2], data->ports[0],
494 sizeof(float) * sample_count);
495 if (data->ports[1] != data->ports[3])
496 memcpy(data->ports[3], data->ports[1],
497 sizeof(float) * sample_count);
498
499 drc_process(data->drc, &data->ports[2], (int) sample_count);
500 }
501
drc_deinstantiate(struct dsp_module * module)502 static void drc_deinstantiate(struct dsp_module *module)
503 {
504 struct drc_data *data = (struct drc_data *) module->data;
505 if (data->drc)
506 drc_free(data->drc);
507 free(data);
508 }
509
drc_init_module(struct dsp_module * module)510 static void drc_init_module(struct dsp_module *module)
511 {
512 module->instantiate = &drc_instantiate;
513 module->connect_port = &drc_connect_port;
514 module->get_delay = &drc_get_delay;
515 module->run = &drc_run;
516 module->deinstantiate = &drc_deinstantiate;
517 module->free_module = &empty_free_module;
518 module->get_properties = &empty_get_properties;
519 module->dump = &empty_dump;
520 }
521
522 /*
523 * sink module functions
524 */
525 struct sink_data {
526 struct ext_dsp_module *ext_module;
527 float *ports[MAX_EXT_DSP_PORTS];
528 };
529
sink_instantiate(struct dsp_module * module,unsigned long sample_rate)530 static int sink_instantiate(struct dsp_module *module,
531 unsigned long sample_rate)
532 {
533 module->data = (struct sink_data *)calloc(1, sizeof(struct sink_data));
534 return 0;
535 }
536
sink_deinstantiate(struct dsp_module * module)537 static void sink_deinstantiate(struct dsp_module *module)
538 {
539 struct sink_data *data = (struct sink_data *)module->data;
540 free(data);
541 }
542
sink_connect_port(struct dsp_module * module,unsigned long port,float * data_location)543 static void sink_connect_port(struct dsp_module *module, unsigned long port,
544 float *data_location)
545 {
546 struct sink_data *data = (struct sink_data *)module->data;
547 data->ports[port] = data_location;
548 }
549
sink_run(struct dsp_module * module,unsigned long sample_count)550 static void sink_run(struct dsp_module *module, unsigned long sample_count)
551 {
552 struct sink_data *data = (struct sink_data *)module->data;
553
554 if (!data->ext_module)
555 return;
556 data->ext_module->run(data->ext_module, sample_count);
557 }
558
sink_init_module(struct dsp_module * module)559 static void sink_init_module(struct dsp_module *module)
560 {
561 module->instantiate = &sink_instantiate;
562 module->connect_port = &sink_connect_port;
563 module->get_delay = &empty_get_delay;
564 module->run = &sink_run;
565 module->deinstantiate = &sink_deinstantiate;
566 module->free_module = &empty_free_module;
567 module->get_properties = &empty_get_properties;
568 module->dump = &empty_dump;
569 }
570
cras_dsp_module_set_sink_ext_module(struct dsp_module * module,struct ext_dsp_module * ext_module)571 void cras_dsp_module_set_sink_ext_module(struct dsp_module *module,
572 struct ext_dsp_module *ext_module)
573 {
574 struct sink_data *data = (struct sink_data *)module->data;
575 int i;
576 data->ext_module = ext_module;
577
578 for (i = 0; i < MAX_EXT_DSP_PORTS; i++)
579 ext_module->ports[i] = data->ports[i];
580 }
581
582 /*
583 * builtin module dispatcher
584 */
cras_dsp_module_load_builtin(struct plugin * plugin)585 struct dsp_module *cras_dsp_module_load_builtin(struct plugin *plugin)
586 {
587 struct dsp_module *module;
588 if (strcmp(plugin->library, "builtin") != 0)
589 return NULL;
590
591 module = calloc(1, sizeof(struct dsp_module));
592
593 if (strcmp(plugin->label, "mix_stereo") == 0) {
594 mix_stereo_init_module(module);
595 } else if (strcmp(plugin->label, "invert_lr") == 0) {
596 invert_lr_init_module(module);
597 } else if (strcmp(plugin->label, "dcblock") == 0) {
598 dcblock_init_module(module);
599 } else if (strcmp(plugin->label, "eq") == 0) {
600 eq_init_module(module);
601 } else if (strcmp(plugin->label, "eq2") == 0) {
602 eq2_init_module(module);
603 } else if (strcmp(plugin->label, "drc") == 0) {
604 drc_init_module(module);
605 } else if (strcmp(plugin->label, "swap_lr") == 0) {
606 swap_lr_init_module(module);
607 } else if (strcmp(plugin->label, "sink") == 0) {
608 sink_init_module(module);
609 } else {
610 empty_init_module(module);
611 }
612
613 return module;
614 }
615