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