• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <inttypes.h>
7 #include <sys/param.h>
8 #include <syslog.h>
9 
10 #include "cras_util.h"
11 #include "cras_dsp_module.h"
12 #include "cras_dsp_pipeline.h"
13 #include "dsp_util.h"
14 
15 /* We have a static representation of the dsp graph in a "struct ini",
16  * and here we will construct a dynamic representation of it in a
17  * "struct pipeline". The difference between the static one and the
18  * dynamic one is that we will only include the subset of the dsp
19  * graph actually needed in the dynamic one (so those plugins that are
20  * disabled will not be included). Here are the mapping between the
21  * static representation and the dynamic representation:
22  *
23  *      static                      dynamic
24  *  -------------    --------------------------------------
25  *  struct ini       struct pipeline
26  *  struct plugin    struct instance
27  *  strict port      struct audio_port, struct control_port
28  *
29  * For example, if the ini file specifies these plugins and their
30  * connections:
31  *
32  * [A]
33  * output_0={audio}
34  * [B]
35  * input_0={audio}
36  * output_1={result}
37  * [C]
38  * input_0={result}
39  *
40  * That is, A connects to B, and B connects to C. If the plugin B is
41  * now disabled, in the pipeline we construct there will only be two
42  * instances (A and C) and the audio ports on these instances will
43  * connect to each other directly, bypassing B.
44  */
45 
46 /* This represents an audio port on an instance. */
47 struct audio_port {
48 	struct audio_port *peer;  /* the audio port this port connects to */
49 	struct plugin *plugin;  /* the plugin corresponds to the instance */
50 	int original_index;  /* the port index in the plugin */
51 	int buf_index; /* the buffer index in the pipeline */
52 };
53 
54 /* This represents a control port on an instance. */
55 struct control_port {
56 	struct control_port *peer;  /* the control port this port connects to */
57 	struct plugin *plugin;  /* the plugin corresponds to the instance */
58 	int original_index;  /* the port index in the plugin */
59 	float value;  /* the value of the control port */
60 };
61 
62 DECLARE_ARRAY_TYPE(struct audio_port, audio_port_array);
63 DECLARE_ARRAY_TYPE(struct control_port, control_port_array);
64 
65 /* An instance is a dynamic representation of a plugin. We only create
66  * an instance when a plugin is needed (data actually flows through it
67  * and it is not disabled). An instance also contains a pointer to a
68  * struct dsp_module, which is the implementation of the plugin */
69 struct instance {
70 	/* The plugin this instance corresponds to */
71 	struct plugin *plugin;
72 
73 	/* These are the ports on this instance. The difference
74 	 * between this and the port array in a struct plugin is that
75 	 * the ports skip disabled plugins and connect to the upstream
76 	 * ports directly.
77 	 */
78 	audio_port_array input_audio_ports;
79 	audio_port_array output_audio_ports;
80 	control_port_array input_control_ports;
81 	control_port_array output_control_ports;
82 
83 	/* The implementation of the plugin */
84 	struct dsp_module *module;
85 
86 	/* Whether this module's instantiate() function has been called */
87 	int instantiated;
88 
89 	/* This caches the value returned from get_properties() of a module */
90 	int properties;
91 
92 	/* This is the total buffering delay from source to this instance. It is
93 	 * in number of frames. */
94 	int total_delay;
95 };
96 
97 DECLARE_ARRAY_TYPE(struct instance, instance_array)
98 
99 /* An pipeline is a dynamic representation of a dsp ini file. */
100 struct pipeline {
101 	/* The purpose of the pipeline. "playback" or "capture" */
102 	const char *purpose;
103 
104 	/* The ini file this pipeline comes from */
105 	struct ini *ini;
106 
107 	/* All needed instances for this pipeline. It is sorted in an
108 	 * order that if instance B depends on instance A, then A will
109 	 * appear in front of B. */
110 	instance_array instances;
111 
112 	/* The maximum number of audio buffers that will be used at
113 	 * the same time for this pipeline */
114 	int peak_buf;
115 
116 	/* The audio data buffers */
117 	float **buffers;
118 
119 	/* The instance where the audio data flow in */
120 	struct instance *source_instance;
121 
122 	/* The instance where the audio data flow out */
123 	struct instance *sink_instance;
124 
125 	/* The number of audio channels for this pipeline */
126 	int input_channels;
127 	int output_channels;
128 
129 	/* The audio sampling rate for this pipleine. It is zero if
130 	 * cras_dsp_pipeline_instantiate() has not been called. */
131 	int sample_rate;
132 
133 	/* The total time it takes to run the pipeline, in nanoseconds. */
134 	int64_t total_time;
135 
136 	/* The max/min time it takes to run the pipeline, in nanoseconds. */
137 	int64_t max_time;
138 	int64_t min_time;
139 
140 	/* The number of blocks the pipeline. */
141 	int64_t total_blocks;
142 
143 	/* The total number of sample frames the pipeline processed */
144 	int64_t total_samples;
145 };
146 
find_instance_by_plugin(instance_array * instances,struct plugin * plugin)147 static struct instance *find_instance_by_plugin(instance_array *instances,
148 						struct plugin *plugin)
149 {
150 	int i;
151 	struct instance *instance;
152 
153 	FOR_ARRAY_ELEMENT(instances, i, instance) {
154 		if (instance->plugin == plugin)
155 			return instance;
156 	}
157 
158 	return NULL;
159 }
160 
161 /* Finds out where the data sent to plugin:index come from. The issue
162  * we need to handle here is the previous plugin may be disabled, so
163  * we need to go upstream until we find the real origin */
find_origin_port(struct ini * ini,instance_array * instances,struct plugin * plugin,int index,struct plugin ** origin,int * origin_index)164 static int find_origin_port(struct ini *ini, instance_array *instances,
165 			    struct plugin *plugin, int index,
166 			    struct plugin **origin, int *origin_index)
167 {
168 	enum port_type type;
169 	struct port *port;
170 	int flow_id;
171 	struct flow *flow;
172 	int i, k;
173 	int found;
174 
175 	port = ARRAY_ELEMENT(&plugin->ports, index);
176 	type = port->type;
177 	flow_id = port->flow_id;
178 	if (flow_id == INVALID_FLOW_ID)
179 		return -1;
180 	flow = ARRAY_ELEMENT(&ini->flows, flow_id);
181 
182 	/* move to the previous plugin */
183 	plugin = flow->from;
184 	index = flow->from_port;
185 
186 	/* if the plugin is not disabled, it will be pointed by some instance */
187 	if (find_instance_by_plugin(instances, plugin)) {
188 		*origin = plugin;
189 		*origin_index = index;
190 		return 0;
191 	}
192 
193 	/* Now we know the previous plugin is disabled, we need to go
194 	 * upstream. We assume the k-th output port of the plugin
195 	 * corresponds to the k-th input port of the plugin (with the
196 	 * same type) */
197 
198 	k = 0;
199 	found = 0;
200 	FOR_ARRAY_ELEMENT(&plugin->ports, i, port) {
201 		if (index == i) {
202 			found = 1;
203 			break;
204 		}
205 		if (port->direction == PORT_OUTPUT && port->type == type)
206 			k++;
207 	}
208 	if (!found)
209 		return -1;
210 
211 	found = 0;
212 	FOR_ARRAY_ELEMENT(&plugin->ports, i, port) {
213 		if (port->direction == PORT_INPUT && port->type == type) {
214 			if (k-- == 0) {
215 				index = i;
216 				found = 1;
217 				break;
218 			}
219 		}
220 	}
221 	if (!found)
222 		return -1;
223 
224 	return find_origin_port(ini, instances, plugin, index, origin,
225 				origin_index);
226 }
227 
find_output_audio_port(instance_array * instances,struct plugin * plugin,int index)228 static struct audio_port *find_output_audio_port(instance_array *instances,
229 						 struct plugin *plugin,
230 						 int index)
231 {
232 	int i;
233 	struct instance *instance;
234 	struct audio_port *audio_port;
235 
236 	instance = find_instance_by_plugin(instances, plugin);
237 	if (!instance)
238 		return NULL;
239 
240 	FOR_ARRAY_ELEMENT(&instance->output_audio_ports, i, audio_port) {
241 		if (audio_port->original_index == index)
242 			return audio_port;
243 	}
244 
245 	return NULL;
246 }
247 
find_output_control_port(instance_array * instances,struct plugin * plugin,int index)248 static struct control_port *find_output_control_port(instance_array *instances,
249 						     struct plugin *plugin,
250 						     int index)
251 {
252 	int i;
253 	struct instance *instance;
254 	struct control_port *control_port;
255 
256 	instance = find_instance_by_plugin(instances, plugin);
257 	if (!instance)
258 		return NULL;
259 
260 	FOR_ARRAY_ELEMENT(&instance->output_control_ports, i, control_port) {
261 		if (control_port->original_index == index)
262 			return control_port;
263 	}
264 
265 	return NULL;
266 }
267 
is_disabled(struct plugin * plugin,struct cras_expr_env * env)268 static char is_disabled(struct plugin *plugin, struct cras_expr_env *env)
269 {
270 	char disabled;
271 	return (plugin->disable_expr &&
272 		cras_expr_expression_eval_boolean(
273 			plugin->disable_expr, env, &disabled) == 0 &&
274 		disabled == 1);
275 }
276 
topological_sort(struct pipeline * pipeline,struct cras_expr_env * env,struct plugin * plugin,char * visited)277 static int topological_sort(struct pipeline *pipeline,
278 			    struct cras_expr_env *env,
279 			    struct plugin *plugin, char* visited)
280 {
281 	struct port *port;
282 	struct flow *flow;
283 	int index;
284 	int i;
285 	int flow_id;
286 	struct instance *instance;
287 	struct ini *ini = pipeline->ini;
288 
289 	index = ARRAY_INDEX(&ini->plugins, plugin);
290 	if (visited[index])
291 		return 0;
292 	visited[index] = 1;
293 
294 	FOR_ARRAY_ELEMENT(&plugin->ports, i, port) {
295 		if (port->flow_id == INVALID_FLOW_ID)
296 			continue;
297 		flow_id = port->flow_id;
298 		flow = ARRAY_ELEMENT(&ini->flows, flow_id);
299 		if (!flow->from) {
300 			syslog(LOG_ERR, "no plugin flows to %s:%d",
301 			       plugin->title, i);
302 			return -1;
303 		}
304 		if (topological_sort(pipeline, env, flow->from, visited) < 0)
305 			return -1;
306 	}
307 
308 	/* if the plugin is disabled, we don't construct an instance for it */
309 	if (is_disabled(plugin, env))
310 		return 0;
311 
312 	instance = ARRAY_APPEND_ZERO(&pipeline->instances);
313 	instance->plugin = plugin;
314 
315 	/* constructs audio and control ports for the instance */
316 	FOR_ARRAY_ELEMENT(&plugin->ports, i, port) {
317 		int need_connect = (port->flow_id != INVALID_FLOW_ID &&
318 				    port->direction == PORT_INPUT);
319                 struct plugin *origin = NULL;
320 		int origin_index = 0;
321 
322 		if (need_connect) {
323 			if (find_origin_port(ini, &pipeline->instances, plugin,
324 					     i, &origin, &origin_index) < 0)
325 				return -1;
326 		}
327 
328 		if (port->type == PORT_AUDIO) {
329 			audio_port_array *audio_port_array =
330 				(port->direction == PORT_INPUT) ?
331 				&instance->input_audio_ports :
332 				&instance->output_audio_ports;
333 			struct audio_port *audio_port =
334 				ARRAY_APPEND_ZERO(audio_port_array);
335 			audio_port->plugin = plugin;
336 			audio_port->original_index = i;
337 			if (need_connect) {
338 				struct audio_port *from;
339 				from = find_output_audio_port(
340 					&pipeline->instances, origin,
341 					origin_index);
342 				if (!from)
343 					return -1;
344 				from->peer = audio_port;
345 				audio_port->peer = from;
346 			}
347 		} else if (port->type == PORT_CONTROL) {
348 			control_port_array *control_port_array =
349 				(port->direction == PORT_INPUT) ?
350 				&instance->input_control_ports :
351 				&instance->output_control_ports;
352 			struct control_port *control_port =
353 				ARRAY_APPEND_ZERO(control_port_array);
354 			control_port->plugin = plugin;
355 			control_port->original_index = i;
356 			control_port->value = port->init_value;
357 			if (need_connect) {
358 				struct control_port *from;
359 				from = find_output_control_port(
360 					&pipeline->instances, origin,
361 					origin_index);
362 				if (!from)
363 					return -1;
364 				from->peer = control_port;
365 				control_port->peer = from;
366 			}
367 		}
368 	}
369 
370 	return 0;
371 }
372 
find_enabled_builtin_plugin(struct ini * ini,const char * label,const char * purpose,struct cras_expr_env * env)373 static struct plugin *find_enabled_builtin_plugin(struct ini *ini,
374 						  const char *label,
375 						  const char *purpose,
376 						  struct cras_expr_env *env)
377 {
378 	int i;
379 	struct plugin *plugin, *found = NULL;
380 
381 	FOR_ARRAY_ELEMENT(&ini->plugins, i, plugin) {
382 		if (strcmp(plugin->library, "builtin") != 0)
383 			continue;
384 		if (strcmp(plugin->label, label) != 0)
385 			continue;
386 		if (!plugin->purpose || strcmp(plugin->purpose, purpose) != 0)
387 			continue;
388 		if (is_disabled(plugin, env))
389 			continue;
390 		if (found) {
391 			syslog(LOG_ERR, "two %s plugins enabled: %s and %s",
392 			       label, found->title, plugin->title);
393 			return NULL;
394 		}
395 		found = plugin;
396 	}
397 
398 	return found;
399 }
400 
cras_dsp_pipeline_create(struct ini * ini,struct cras_expr_env * env,const char * purpose)401 struct pipeline *cras_dsp_pipeline_create(struct ini *ini,
402 					  struct cras_expr_env *env,
403 					  const char *purpose)
404 {
405 	struct pipeline *pipeline;
406 	int n;
407 	char *visited;
408 	int rc;
409 	struct plugin *source = find_enabled_builtin_plugin(
410 		ini, "source", purpose, env);
411 	struct plugin *sink = find_enabled_builtin_plugin(
412 		ini, "sink", purpose, env);
413 
414 	if (!source || !sink) {
415 		syslog(LOG_DEBUG,
416 		       "no enabled source or sink found %p/%p for %s",
417 		       source, sink, purpose);
418 		return NULL;
419 	}
420 
421 	pipeline = calloc(1, sizeof(struct pipeline));
422 	if (!pipeline) {
423 		syslog(LOG_ERR, "no memory for pipeline");
424 		return NULL;
425 	}
426 
427 	pipeline->ini = ini;
428 	pipeline->purpose = purpose;
429 	/* create instances for needed plugins, in the order of dependency */
430 	n = ARRAY_COUNT(&ini->plugins);
431 	visited = calloc(1, n);
432 	rc = topological_sort(pipeline, env, sink, visited);
433 	free(visited);
434 
435 	if (rc < 0) {
436 		syslog(LOG_ERR, "failed to construct pipeline");
437 		return NULL;
438 	}
439 
440 	pipeline->source_instance = find_instance_by_plugin(
441 		&pipeline->instances, source);
442 	pipeline->sink_instance = find_instance_by_plugin(
443 		&pipeline->instances, sink);
444 
445 	if (!pipeline->source_instance || !pipeline->sink_instance) {
446 		syslog(LOG_ERR, "source(%p) or sink(%p) missing/disabled?",
447 		       source, sink);
448 		cras_dsp_pipeline_free(pipeline);
449 		return NULL;
450 	}
451 
452 	pipeline->input_channels = ARRAY_COUNT(
453 		&pipeline->source_instance->output_audio_ports);
454 	pipeline->output_channels = ARRAY_COUNT(
455 		&pipeline->sink_instance->input_audio_ports);
456 	if (pipeline->output_channels > pipeline->input_channels) {
457 		/* Can't increase channel count, no where to put them. */
458 		syslog(LOG_ERR, "DSP output more channels than input\n");
459 		cras_dsp_pipeline_free(pipeline);
460 		return NULL;
461 	}
462 
463 	return pipeline;
464 }
465 
load_module(struct plugin * plugin,struct instance * instance)466 static int load_module(struct plugin *plugin, struct instance *instance)
467 {
468 	struct dsp_module *module;
469 	module = cras_dsp_module_load_builtin(plugin);
470 	if (!module)
471 		module = cras_dsp_module_load_ladspa(plugin);
472 	if (!module)
473 		return -1;
474 	instance->module = module;
475 	instance->properties = module->get_properties(module);
476 	return 0;
477 }
478 
use_buffers(char * busy,audio_port_array * audio_ports)479 static void use_buffers(char *busy, audio_port_array *audio_ports)
480 {
481 	int i, k = 0;
482 	struct audio_port *audio_port;
483 
484 	FOR_ARRAY_ELEMENT(audio_ports, i, audio_port) {
485 		while (busy[k])
486 			k++;
487 		audio_port->buf_index = k;
488 		busy[k] = 1;
489 	}
490 }
491 
unuse_buffers(char * busy,audio_port_array * audio_ports)492 static void unuse_buffers(char *busy, audio_port_array *audio_ports)
493 {
494 	int i;
495 	struct audio_port *audio_port;
496 
497 	FOR_ARRAY_ELEMENT(audio_ports, i, audio_port) {
498 		busy[audio_port->buf_index] = 0;
499 	}
500 }
501 
502 /* assign which buffer each audio port on each instance should use */
allocate_buffers(struct pipeline * pipeline)503 static int allocate_buffers(struct pipeline *pipeline)
504 {
505 	int i;
506 	struct instance *instance;
507 	int need_buf = 0, peak_buf = 0;
508 	char *busy;
509 
510 	/* first figure out how many buffers do we need */
511 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
512 		int in = ARRAY_COUNT(&instance->input_audio_ports);
513 		int out = ARRAY_COUNT(&instance->output_audio_ports);
514 
515 		if (instance->properties & MODULE_INPLACE_BROKEN) {
516 			/* We cannot reuse input buffer as output
517 			 * buffer, so we need to use extra buffers */
518 			need_buf += out;
519 			peak_buf = MAX(peak_buf, need_buf);
520 			need_buf -= in;
521 		} else {
522 			need_buf += out - in;
523 			peak_buf = MAX(peak_buf, need_buf);
524 		}
525 	}
526 
527 	/* then allocate the buffers */
528 	pipeline->peak_buf = peak_buf;
529 	pipeline->buffers = (float **)calloc(peak_buf, sizeof(float *));
530 
531 	if (!pipeline->buffers) {
532 		syslog(LOG_ERR, "failed to allocate buffers");
533 		return -1;
534 	}
535 
536 	for (i = 0; i < peak_buf; i++) {
537 		size_t size = DSP_BUFFER_SIZE * sizeof(float);
538 		float *buf = calloc(1, size);
539 		if (!buf) {
540 			syslog(LOG_ERR, "failed to allocate buf");
541 			return -1;
542 		}
543 		pipeline->buffers[i] = buf;
544 	}
545 
546 	/* Now assign buffer index for each instance's input/output ports */
547 	busy = calloc(peak_buf, sizeof(*busy));
548 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
549 		int j;
550 		struct audio_port *audio_port;
551 
552 		/* Collect input buffers from upstream */
553 		FOR_ARRAY_ELEMENT(&instance->input_audio_ports, j, audio_port) {
554 			audio_port->buf_index = audio_port->peer->buf_index;
555 		}
556 
557 		/* If the module has the MODULE_INPLACE_BROKEN flag,
558 		 * we cannot reuse input buffers as output buffers, so
559 		 * we need to use extra buffers. For example, in this graph
560 		 *
561 		 * [A]
562 		 * output_0={x}
563 		 * output_1={y}
564 		 * output_2={z}
565 		 * output_3={w}
566 		 * [B]
567 		 * input_0={x}
568 		 * input_1={y}
569 		 * input_2={z}
570 		 * input_3={w}
571 		 * output_4={u}
572 		 *
573 		 * Then peak_buf for this pipeline is 4. However if
574 		 * plugin B has the MODULE_INPLACE_BROKEN flag, then
575 		 * peak_buf is 5 because plugin B cannot output to the
576 		 * same buffer used for input.
577 		 *
578 		 * This means if we don't have the flag, we can free
579 		 * the input buffers then allocate the output buffers,
580 		 * but if we have the flag, we have to allocate the
581 		 * output buffers before freeing the input buffers.
582 		 */
583 		if (instance->properties & MODULE_INPLACE_BROKEN) {
584 			use_buffers(busy, &instance->output_audio_ports);
585 			unuse_buffers(busy, &instance->input_audio_ports);
586 		} else {
587 			unuse_buffers(busy, &instance->input_audio_ports);
588 			use_buffers(busy, &instance->output_audio_ports);
589 		}
590 	}
591 	free(busy);
592 
593 	return 0;
594 }
595 
cras_dsp_pipeline_load(struct pipeline * pipeline)596 int cras_dsp_pipeline_load(struct pipeline *pipeline)
597 {
598 	int i;
599 	struct instance *instance;
600 
601 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
602 		struct plugin *plugin = instance->plugin;
603 		if (load_module(plugin, instance) != 0)
604 			return -1;
605 	}
606 
607 	if (allocate_buffers(pipeline) != 0)
608 		return -1;
609 
610 	return 0;
611 }
612 
613 /* Calculates the total buffering delay of each instance from the source */
calculate_audio_delay(struct pipeline * pipeline)614 static void calculate_audio_delay(struct pipeline *pipeline)
615 {
616 	int i;
617 	struct instance *instance;
618 
619 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
620 		struct dsp_module *module = instance->module;
621 		audio_port_array *audio_in = &instance->input_audio_ports;
622 		struct audio_port *audio_port;
623 		int delay = 0;
624 		int j;
625 
626 		/* Finds the max delay of all modules that provide input to this
627 		 * instance. */
628 		FOR_ARRAY_ELEMENT(audio_in, j, audio_port) {
629 			struct instance *upstream = find_instance_by_plugin(
630 				&pipeline->instances, audio_port->peer->plugin);
631 			delay = MAX(upstream->total_delay, delay);
632 		}
633 
634 		instance->total_delay = delay + module->get_delay(module);
635 	}
636 }
637 
cras_dsp_pipeline_instantiate(struct pipeline * pipeline,int sample_rate)638 int cras_dsp_pipeline_instantiate(struct pipeline *pipeline, int sample_rate)
639 {
640 	int i;
641 	struct instance *instance;
642 
643 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
644 		struct dsp_module *module = instance->module;
645 		if (module->instantiate(module, sample_rate) != 0)
646 			return -1;
647 		instance->instantiated = 1;
648 		syslog(LOG_DEBUG, "instantiate %s", instance->plugin->label);
649 	}
650 	pipeline->sample_rate = sample_rate;
651 
652 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
653 		audio_port_array *audio_in = &instance->input_audio_ports;
654 		audio_port_array *audio_out = &instance->output_audio_ports;
655 		control_port_array *control_in = &instance->input_control_ports;
656 		control_port_array *control_out =
657 			&instance->output_control_ports;
658 		int j;
659 		struct audio_port *audio_port;
660 		struct control_port *control_port;
661 		struct dsp_module *module = instance->module;
662 
663 		/* connect audio ports */
664 		FOR_ARRAY_ELEMENT(audio_in, j, audio_port) {
665 			float *buf = pipeline->buffers[audio_port->buf_index];
666 			module->connect_port(module,
667 					     audio_port->original_index,
668 					     buf);
669 			syslog(LOG_DEBUG, "connect audio buf %d to %s:%d (in)",
670 			       audio_port->buf_index, instance->plugin->title,
671 			       audio_port->original_index);
672 		}
673 		FOR_ARRAY_ELEMENT(audio_out, j, audio_port) {
674 			float *buf = pipeline->buffers[audio_port->buf_index];
675 			module->connect_port(module,
676 					     audio_port->original_index,
677 					     buf);
678 			syslog(LOG_DEBUG, "connect audio buf %d to %s:%d (out)",
679 			       audio_port->buf_index, instance->plugin->title,
680 			       audio_port->original_index);
681 		}
682 
683 		/* connect control ports */
684 		FOR_ARRAY_ELEMENT(control_in, j, control_port) {
685 			/* Note for input control ports which has a
686 			 * peer, we use &control_port->peer->value, so
687 			 * we can get the peer port's output value
688 			 * directly */
689 			float *value = control_port->peer ?
690 				&control_port->peer->value :
691 				&control_port->value;
692 			module->connect_port(module,
693 					     control_port->original_index,
694 					     value);
695 			syslog(LOG_DEBUG,
696 			       "connect control (val=%g) to %s:%d (in)",
697 			       control_port->value, instance->plugin->title,
698 			       control_port->original_index);
699 		}
700 		FOR_ARRAY_ELEMENT(control_out, j, control_port) {
701 			module->connect_port(module,
702 					     control_port->original_index,
703 					     &control_port->value);
704 			syslog(LOG_DEBUG,
705 			       "connect control (val=%g) to %s:%d (out)",
706 			       control_port->value, instance->plugin->title,
707 			       control_port->original_index);
708 		}
709 	}
710 
711 	calculate_audio_delay(pipeline);
712 	return 0;
713 }
714 
cras_dsp_pipeline_deinstantiate(struct pipeline * pipeline)715 void cras_dsp_pipeline_deinstantiate(struct pipeline *pipeline)
716 {
717 	int i;
718 	struct instance *instance;
719 
720 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
721 		struct dsp_module *module = instance->module;
722 		if (instance->instantiated) {
723 			module->deinstantiate(module);
724 			instance->instantiated = 0;
725 		}
726 	}
727 	pipeline->sample_rate = 0;
728 }
729 
cras_dsp_pipeline_get_delay(struct pipeline * pipeline)730 int cras_dsp_pipeline_get_delay(struct pipeline *pipeline)
731 {
732 	return pipeline->sink_instance->total_delay;
733 }
734 
cras_dsp_pipeline_get_sample_rate(struct pipeline * pipeline)735 int cras_dsp_pipeline_get_sample_rate(struct pipeline *pipeline)
736 {
737 	return pipeline->sample_rate;
738 }
739 
cras_dsp_pipeline_get_num_input_channels(struct pipeline * pipeline)740 int cras_dsp_pipeline_get_num_input_channels(struct pipeline *pipeline)
741 {
742 	return pipeline->input_channels;
743 }
744 
cras_dsp_pipeline_get_num_output_channels(struct pipeline * pipeline)745 int cras_dsp_pipeline_get_num_output_channels(struct pipeline *pipeline)
746 {
747 	return pipeline->output_channels;
748 }
749 
cras_dsp_pipeline_get_peak_audio_buffers(struct pipeline * pipeline)750 int cras_dsp_pipeline_get_peak_audio_buffers(struct pipeline *pipeline)
751 {
752 	return pipeline->peak_buf;
753 }
754 
find_buffer(struct pipeline * pipeline,audio_port_array * audio_ports,int index)755 static float *find_buffer(struct pipeline *pipeline,
756 			  audio_port_array *audio_ports,
757 			  int index)
758 {
759 	int i;
760 	struct audio_port *audio_port;
761 
762 	FOR_ARRAY_ELEMENT(audio_ports, i, audio_port) {
763 		if (audio_port->original_index == index)
764 			return pipeline->buffers[audio_port->buf_index];
765 	}
766 	return NULL;
767 }
768 
cras_dsp_pipeline_get_source_buffer(struct pipeline * pipeline,int index)769 float *cras_dsp_pipeline_get_source_buffer(struct pipeline *pipeline, int index)
770 {
771 	return find_buffer(pipeline,
772 			   &pipeline->source_instance->output_audio_ports,
773 			   index);
774 }
775 
cras_dsp_pipeline_get_sink_buffer(struct pipeline * pipeline,int index)776 float *cras_dsp_pipeline_get_sink_buffer(struct pipeline *pipeline, int index)
777 {
778 	return find_buffer(pipeline,
779 			   &pipeline->sink_instance->input_audio_ports,
780 			   index);
781 }
782 
cras_dsp_pipeline_set_sink_ext_module(struct pipeline * pipeline,struct ext_dsp_module * ext_module)783 void cras_dsp_pipeline_set_sink_ext_module(struct pipeline *pipeline,
784 					   struct ext_dsp_module *ext_module)
785 {
786 	cras_dsp_module_set_sink_ext_module(
787 			pipeline->sink_instance->module,
788 			ext_module);
789 }
790 
cras_dsp_pipeline_run(struct pipeline * pipeline,int sample_count)791 void cras_dsp_pipeline_run(struct pipeline *pipeline, int sample_count)
792 {
793 	int i;
794 	struct instance *instance;
795 
796 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
797 		struct dsp_module *module = instance->module;
798 		module->run(module, sample_count);
799 	}
800 }
801 
cras_dsp_pipeline_add_statistic(struct pipeline * pipeline,const struct timespec * time_delta,int samples)802 void cras_dsp_pipeline_add_statistic(struct pipeline *pipeline,
803 				     const struct timespec *time_delta,
804 				     int samples)
805 {
806 	int64_t t;
807 	if (samples <= 0)
808 		return;
809 
810 	t = time_delta->tv_sec * 1000000000LL + time_delta->tv_nsec;
811 
812 	if (pipeline->total_blocks == 0) {
813 		pipeline->max_time = t;
814 		pipeline->min_time = t;
815 	} else {
816 		pipeline->max_time = MAX(pipeline->max_time, t);
817 		pipeline->min_time = MIN(pipeline->min_time, t);
818 	}
819 
820 	pipeline->total_blocks++;
821 	pipeline->total_samples += samples;
822 	pipeline->total_time += t;
823 }
824 
cras_dsp_pipeline_apply(struct pipeline * pipeline,uint8_t * buf,snd_pcm_format_t format,unsigned int frames)825 int cras_dsp_pipeline_apply(struct pipeline *pipeline, uint8_t *buf,
826 			    snd_pcm_format_t format, unsigned int frames)
827 {
828 	size_t remaining;
829 	size_t chunk;
830 	size_t i;
831 	unsigned int input_channels = pipeline->input_channels;
832 	unsigned int output_channels = pipeline->output_channels;
833 	float *source[input_channels];
834 	float *sink[output_channels];
835 	struct timespec begin, end, delta;
836 	int rc;
837 
838 	if (!pipeline || frames == 0)
839 		return 0;
840 
841 	clock_gettime(CLOCK_THREAD_CPUTIME_ID, &begin);
842 
843 	/* get pointers to source and sink buffers */
844 	for (i = 0; i < input_channels; i++)
845 		source[i] = cras_dsp_pipeline_get_source_buffer(pipeline, i);
846 	for (i = 0; i < output_channels; i++)
847 		sink[i] = cras_dsp_pipeline_get_sink_buffer(pipeline, i);
848 
849 	remaining = frames;
850 
851 	/* process at most DSP_BUFFER_SIZE frames each loop */
852 	while (remaining > 0) {
853 		chunk = MIN(remaining, (size_t)DSP_BUFFER_SIZE);
854 
855 		/* deinterleave and convert to float */
856 		rc = dsp_util_deinterleave(buf, source, input_channels,
857 					   format, chunk);
858 		if (rc)
859 			return rc;
860 
861 		/* Run the pipeline */
862 		cras_dsp_pipeline_run(pipeline, chunk);
863 
864 		/* interleave and convert back to int16_t */
865 		rc = dsp_util_interleave(sink, buf, output_channels,
866 					 format, chunk);
867 		if (rc)
868 			return rc;
869 
870 		buf += chunk * output_channels * PCM_FORMAT_WIDTH(format) / 8;
871 		remaining -= chunk;
872 	}
873 
874 	clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end);
875 	subtract_timespecs(&end, &begin, &delta);
876 	cras_dsp_pipeline_add_statistic(pipeline, &delta, frames);
877 	return 0;
878 }
879 
cras_dsp_pipeline_free(struct pipeline * pipeline)880 void cras_dsp_pipeline_free(struct pipeline *pipeline)
881 {
882 	int i;
883 	struct instance *instance;
884 
885 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
886 		struct dsp_module *module = instance->module;
887 		instance->plugin = NULL;
888 		ARRAY_FREE(&instance->input_audio_ports);
889 		ARRAY_FREE(&instance->input_control_ports);
890 		ARRAY_FREE(&instance->output_audio_ports);
891 		ARRAY_FREE(&instance->output_control_ports);
892 
893 		if (module) {
894 			if (instance->instantiated) {
895 				module->deinstantiate(module);
896 				instance->instantiated = 0;
897 			}
898 			module->free_module(module);
899 			instance->module = NULL;
900 		}
901 	}
902 
903 	pipeline->ini = NULL;
904 	ARRAY_FREE(&pipeline->instances);
905 
906 	for (i = 0; i < pipeline->peak_buf; i++)
907 		free(pipeline->buffers[i]);
908 	free(pipeline->buffers);
909 	free(pipeline);
910 }
911 
dump_audio_ports(struct dumper * d,const char * name,audio_port_array * audio_ports)912 static void dump_audio_ports(struct dumper *d, const char *name,
913 			     audio_port_array *audio_ports)
914 {
915 	int i;
916 	struct audio_port *audio_port;
917 	int n = ARRAY_COUNT(audio_ports);
918 
919 	if (n == 0)
920 		return;
921 	dumpf(d, "   %s (%d) =\n", name, n);
922 
923 	FOR_ARRAY_ELEMENT(audio_ports, i, audio_port) {
924 		dumpf(d, "   %p, peer %p, orig=%d, buf=%d\n",
925 		      audio_port, audio_port->peer,
926 		      audio_port->original_index, audio_port->buf_index);
927 	}
928 }
929 
dump_control_ports(struct dumper * d,const char * name,control_port_array * control_ports)930 static void dump_control_ports(struct dumper *d, const char *name,
931 			       control_port_array *control_ports)
932 {
933 	int i;
934 	struct control_port *control_port;
935 	int n = ARRAY_COUNT(control_ports);
936 
937 	if (n == 0)
938 		return;
939 	dumpf(d, "   %s (%d) =\n", name, ARRAY_COUNT(control_ports));
940 
941 	FOR_ARRAY_ELEMENT(control_ports, i, control_port) {
942 		dumpf(d, "   %p, peer %p, orig=%d, value=%g\n",
943 		      control_port, control_port->peer,
944 		      control_port->original_index, control_port->value);
945 	}
946 }
947 
cras_dsp_pipeline_dump(struct dumper * d,struct pipeline * pipeline)948 void cras_dsp_pipeline_dump(struct dumper *d, struct pipeline *pipeline)
949 {
950 	int i;
951 	struct instance *instance;
952 
953 	dumpf(d, "---- pipeline dump begin ----\n");
954 	dumpf(d, "pipeline (%s):\n", pipeline->purpose);
955 	dumpf(d, " input channels: %d\n", pipeline->input_channels);
956 	dumpf(d, " output channels: %d\n", pipeline->output_channels);
957 	dumpf(d, " sample_rate: %d\n", pipeline->sample_rate);
958 	dumpf(d, " processed samples: %" PRId64 "\n", pipeline->total_samples);
959 	dumpf(d, " processed blocks: %" PRId64 "\n", pipeline->total_blocks);
960 	dumpf(d, " total processing time: %" PRId64 "ns\n",
961 	      pipeline->total_time);
962 	if (pipeline->total_blocks) {
963 		dumpf(d, " average block size: %" PRId64 "\n",
964 		      pipeline->total_samples / pipeline->total_blocks);
965 		dumpf(d, " avg processing time per block: %" PRId64 "ns\n",
966 		      pipeline->total_time / pipeline->total_blocks);
967 	}
968 	dumpf(d, " min processing time per block: %" PRId64 "ns\n",
969 	      pipeline->min_time);
970 	dumpf(d, " max processing time per block: %" PRId64 "ns\n",
971 	      pipeline->max_time);
972 	dumpf(d, " cpu load: %g%%\n", pipeline->total_time * 1e-9
973 	      / pipeline->total_samples * pipeline->sample_rate * 100);
974 	dumpf(d, " instances (%d):\n",
975 	      ARRAY_COUNT(&pipeline->instances));
976 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
977 		struct dsp_module *module = instance->module;
978 		dumpf(d, "  [%d]%s mod=%p, total delay=%d\n",
979 		      i, instance->plugin->title, module,
980 		      instance->total_delay);
981 		if (module)
982 			module->dump(module, d);
983 		dump_audio_ports(d, "input_audio_ports",
984 				 &instance->input_audio_ports);
985 		dump_audio_ports(d, "output_audio_ports",
986 				 &instance->output_audio_ports);
987 		dump_control_ports(d, "input_control_ports",
988 				   &instance->input_control_ports);
989 		dump_control_ports(d, "output_control_ports",
990 				   &instance->output_control_ports);
991 	}
992 	dumpf(d, " peak_buf = %d\n", pipeline->peak_buf);
993 	dumpf(d, "---- pipeline dump end ----\n");
994 }
995