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_INFO,
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 		return -1;
472 	instance->module = module;
473 	instance->properties = module->get_properties(module);
474 	return 0;
475 }
476 
use_buffers(char * busy,audio_port_array * audio_ports)477 static void use_buffers(char *busy, audio_port_array *audio_ports)
478 {
479 	int i, k = 0;
480 	struct audio_port *audio_port;
481 
482 	FOR_ARRAY_ELEMENT(audio_ports, i, audio_port) {
483 		while (busy[k])
484 			k++;
485 		audio_port->buf_index = k;
486 		busy[k] = 1;
487 	}
488 }
489 
unuse_buffers(char * busy,audio_port_array * audio_ports)490 static void unuse_buffers(char *busy, audio_port_array *audio_ports)
491 {
492 	int i;
493 	struct audio_port *audio_port;
494 
495 	FOR_ARRAY_ELEMENT(audio_ports, i, audio_port) {
496 		busy[audio_port->buf_index] = 0;
497 	}
498 }
499 
500 /* assign which buffer each audio port on each instance should use */
allocate_buffers(struct pipeline * pipeline)501 static int allocate_buffers(struct pipeline *pipeline)
502 {
503 	int i;
504 	struct instance *instance;
505 	int need_buf = 0, peak_buf = 0;
506 	char *busy;
507 
508 	/* first figure out how many buffers do we need */
509 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
510 		int in = ARRAY_COUNT(&instance->input_audio_ports);
511 		int out = ARRAY_COUNT(&instance->output_audio_ports);
512 
513 		if (instance->properties & MODULE_INPLACE_BROKEN) {
514 			/* We cannot reuse input buffer as output
515 			 * buffer, so we need to use extra buffers */
516 			need_buf += out;
517 			peak_buf = MAX(peak_buf, need_buf);
518 			need_buf -= in;
519 		} else {
520 			need_buf += out - in;
521 			peak_buf = MAX(peak_buf, need_buf);
522 		}
523 	}
524 
525 	/* then allocate the buffers */
526 	pipeline->peak_buf = peak_buf;
527 	pipeline->buffers = (float **)calloc(peak_buf, sizeof(float *));
528 
529 	if (!pipeline->buffers) {
530 		syslog(LOG_ERR, "failed to allocate buffers");
531 		return -1;
532 	}
533 
534 	for (i = 0; i < peak_buf; i++) {
535 		size_t size = DSP_BUFFER_SIZE * sizeof(float);
536 		float *buf = calloc(1, size);
537 		if (!buf) {
538 			syslog(LOG_ERR, "failed to allocate buf");
539 			return -1;
540 		}
541 		pipeline->buffers[i] = buf;
542 	}
543 
544 	/* Now assign buffer index for each instance's input/output ports */
545 	busy = calloc(peak_buf, sizeof(*busy));
546 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
547 		int j;
548 		struct audio_port *audio_port;
549 
550 		/* Collect input buffers from upstream */
551 		FOR_ARRAY_ELEMENT(&instance->input_audio_ports, j, audio_port) {
552 			audio_port->buf_index = audio_port->peer->buf_index;
553 		}
554 
555 		/* If the module has the MODULE_INPLACE_BROKEN flag,
556 		 * we cannot reuse input buffers as output buffers, so
557 		 * we need to use extra buffers. For example, in this graph
558 		 *
559 		 * [A]
560 		 * output_0={x}
561 		 * output_1={y}
562 		 * output_2={z}
563 		 * output_3={w}
564 		 * [B]
565 		 * input_0={x}
566 		 * input_1={y}
567 		 * input_2={z}
568 		 * input_3={w}
569 		 * output_4={u}
570 		 *
571 		 * Then peak_buf for this pipeline is 4. However if
572 		 * plugin B has the MODULE_INPLACE_BROKEN flag, then
573 		 * peak_buf is 5 because plugin B cannot output to the
574 		 * same buffer used for input.
575 		 *
576 		 * This means if we don't have the flag, we can free
577 		 * the input buffers then allocate the output buffers,
578 		 * but if we have the flag, we have to allocate the
579 		 * output buffers before freeing the input buffers.
580 		 */
581 		if (instance->properties & MODULE_INPLACE_BROKEN) {
582 			use_buffers(busy, &instance->output_audio_ports);
583 			unuse_buffers(busy, &instance->input_audio_ports);
584 		} else {
585 			unuse_buffers(busy, &instance->input_audio_ports);
586 			use_buffers(busy, &instance->output_audio_ports);
587 		}
588 	}
589 	free(busy);
590 
591 	return 0;
592 }
593 
cras_dsp_pipeline_load(struct pipeline * pipeline)594 int cras_dsp_pipeline_load(struct pipeline *pipeline)
595 {
596 	int i;
597 	struct instance *instance;
598 
599 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
600 		struct plugin *plugin = instance->plugin;
601 		if (load_module(plugin, instance) != 0)
602 			return -1;
603 	}
604 
605 	if (allocate_buffers(pipeline) != 0)
606 		return -1;
607 
608 	return 0;
609 }
610 
611 /* Calculates the total buffering delay of each instance from the source */
calculate_audio_delay(struct pipeline * pipeline)612 static void calculate_audio_delay(struct pipeline *pipeline)
613 {
614 	int i;
615 	struct instance *instance;
616 
617 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
618 		struct dsp_module *module = instance->module;
619 		audio_port_array *audio_in = &instance->input_audio_ports;
620 		struct audio_port *audio_port;
621 		int delay = 0;
622 		int j;
623 
624 		/* Finds the max delay of all modules that provide input to this
625 		 * instance. */
626 		FOR_ARRAY_ELEMENT(audio_in, j, audio_port) {
627 			struct instance *upstream = find_instance_by_plugin(
628 				&pipeline->instances, audio_port->peer->plugin);
629 			delay = MAX(upstream->total_delay, delay);
630 		}
631 
632 		instance->total_delay = delay + module->get_delay(module);
633 	}
634 }
635 
cras_dsp_pipeline_instantiate(struct pipeline * pipeline,int sample_rate)636 int cras_dsp_pipeline_instantiate(struct pipeline *pipeline, int sample_rate)
637 {
638 	int i;
639 	struct instance *instance;
640 
641 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
642 		struct dsp_module *module = instance->module;
643 		if (module->instantiate(module, sample_rate) != 0)
644 			return -1;
645 		instance->instantiated = 1;
646 		syslog(LOG_DEBUG, "instantiate %s", instance->plugin->label);
647 	}
648 	pipeline->sample_rate = sample_rate;
649 
650 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
651 		audio_port_array *audio_in = &instance->input_audio_ports;
652 		audio_port_array *audio_out = &instance->output_audio_ports;
653 		control_port_array *control_in = &instance->input_control_ports;
654 		control_port_array *control_out =
655 			&instance->output_control_ports;
656 		int j;
657 		struct audio_port *audio_port;
658 		struct control_port *control_port;
659 		struct dsp_module *module = instance->module;
660 
661 		/* connect audio ports */
662 		FOR_ARRAY_ELEMENT(audio_in, j, audio_port) {
663 			float *buf = pipeline->buffers[audio_port->buf_index];
664 			module->connect_port(module,
665 					     audio_port->original_index,
666 					     buf);
667 			syslog(LOG_DEBUG, "connect audio buf %d to %s:%d (in)",
668 			       audio_port->buf_index, instance->plugin->title,
669 			       audio_port->original_index);
670 		}
671 		FOR_ARRAY_ELEMENT(audio_out, j, audio_port) {
672 			float *buf = pipeline->buffers[audio_port->buf_index];
673 			module->connect_port(module,
674 					     audio_port->original_index,
675 					     buf);
676 			syslog(LOG_DEBUG, "connect audio buf %d to %s:%d (out)",
677 			       audio_port->buf_index, instance->plugin->title,
678 			       audio_port->original_index);
679 		}
680 
681 		/* connect control ports */
682 		FOR_ARRAY_ELEMENT(control_in, j, control_port) {
683 			/* Note for input control ports which has a
684 			 * peer, we use &control_port->peer->value, so
685 			 * we can get the peer port's output value
686 			 * directly */
687 			float *value = control_port->peer ?
688 				&control_port->peer->value :
689 				&control_port->value;
690 			module->connect_port(module,
691 					     control_port->original_index,
692 					     value);
693 			syslog(LOG_DEBUG,
694 			       "connect control (val=%g) to %s:%d (in)",
695 			       control_port->value, instance->plugin->title,
696 			       control_port->original_index);
697 		}
698 		FOR_ARRAY_ELEMENT(control_out, j, control_port) {
699 			module->connect_port(module,
700 					     control_port->original_index,
701 					     &control_port->value);
702 			syslog(LOG_DEBUG,
703 			       "connect control (val=%g) to %s:%d (out)",
704 			       control_port->value, instance->plugin->title,
705 			       control_port->original_index);
706 		}
707 	}
708 
709 	calculate_audio_delay(pipeline);
710 	return 0;
711 }
712 
cras_dsp_pipeline_deinstantiate(struct pipeline * pipeline)713 void cras_dsp_pipeline_deinstantiate(struct pipeline *pipeline)
714 {
715 	int i;
716 	struct instance *instance;
717 
718 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
719 		struct dsp_module *module = instance->module;
720 		if (instance->instantiated) {
721 			module->deinstantiate(module);
722 			instance->instantiated = 0;
723 		}
724 	}
725 	pipeline->sample_rate = 0;
726 }
727 
cras_dsp_pipeline_get_delay(struct pipeline * pipeline)728 int cras_dsp_pipeline_get_delay(struct pipeline *pipeline)
729 {
730 	return pipeline->sink_instance->total_delay;
731 }
732 
cras_dsp_pipeline_get_sample_rate(struct pipeline * pipeline)733 int cras_dsp_pipeline_get_sample_rate(struct pipeline *pipeline)
734 {
735 	return pipeline->sample_rate;
736 }
737 
cras_dsp_pipeline_get_num_input_channels(struct pipeline * pipeline)738 int cras_dsp_pipeline_get_num_input_channels(struct pipeline *pipeline)
739 {
740 	return pipeline->input_channels;
741 }
742 
cras_dsp_pipeline_get_num_output_channels(struct pipeline * pipeline)743 int cras_dsp_pipeline_get_num_output_channels(struct pipeline *pipeline)
744 {
745 	return pipeline->output_channels;
746 }
747 
cras_dsp_pipeline_get_peak_audio_buffers(struct pipeline * pipeline)748 int cras_dsp_pipeline_get_peak_audio_buffers(struct pipeline *pipeline)
749 {
750 	return pipeline->peak_buf;
751 }
752 
find_buffer(struct pipeline * pipeline,audio_port_array * audio_ports,int index)753 static float *find_buffer(struct pipeline *pipeline,
754 			  audio_port_array *audio_ports,
755 			  int index)
756 {
757 	int i;
758 	struct audio_port *audio_port;
759 
760 	FOR_ARRAY_ELEMENT(audio_ports, i, audio_port) {
761 		if (audio_port->original_index == index)
762 			return pipeline->buffers[audio_port->buf_index];
763 	}
764 	return NULL;
765 }
766 
cras_dsp_pipeline_get_source_buffer(struct pipeline * pipeline,int index)767 float *cras_dsp_pipeline_get_source_buffer(struct pipeline *pipeline, int index)
768 {
769 	return find_buffer(pipeline,
770 			   &pipeline->source_instance->output_audio_ports,
771 			   index);
772 }
773 
cras_dsp_pipeline_get_sink_buffer(struct pipeline * pipeline,int index)774 float *cras_dsp_pipeline_get_sink_buffer(struct pipeline *pipeline, int index)
775 {
776 	return find_buffer(pipeline,
777 			   &pipeline->sink_instance->input_audio_ports,
778 			   index);
779 }
780 
cras_dsp_pipeline_run(struct pipeline * pipeline,int sample_count)781 void cras_dsp_pipeline_run(struct pipeline *pipeline, int sample_count)
782 {
783 	int i;
784 	struct instance *instance;
785 
786 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
787 		struct dsp_module *module = instance->module;
788 		module->run(module, sample_count);
789 	}
790 }
791 
cras_dsp_pipeline_add_statistic(struct pipeline * pipeline,const struct timespec * time_delta,int samples)792 void cras_dsp_pipeline_add_statistic(struct pipeline *pipeline,
793 				     const struct timespec *time_delta,
794 				     int samples)
795 {
796 	int64_t t;
797 	if (samples <= 0)
798 		return;
799 
800 	t = time_delta->tv_sec * 1000000000LL + time_delta->tv_nsec;
801 
802 	if (pipeline->total_blocks == 0) {
803 		pipeline->max_time = t;
804 		pipeline->min_time = t;
805 	} else {
806 		pipeline->max_time = MAX(pipeline->max_time, t);
807 		pipeline->min_time = MIN(pipeline->min_time, t);
808 	}
809 
810 	pipeline->total_blocks++;
811 	pipeline->total_samples += samples;
812 	pipeline->total_time += t;
813 }
814 
cras_dsp_pipeline_apply(struct pipeline * pipeline,uint8_t * buf,unsigned int frames)815 void cras_dsp_pipeline_apply(struct pipeline *pipeline,
816 			     uint8_t *buf, unsigned int frames)
817 {
818 	size_t remaining;
819 	size_t chunk;
820 	size_t i;
821 	int16_t *target;
822 	unsigned int input_channels = pipeline->input_channels;
823 	unsigned int output_channels = pipeline->output_channels;
824 	float *source[input_channels];
825 	float *sink[output_channels];
826 	//struct timespec begin, end, delta;
827 
828 	if (!pipeline || frames == 0)
829 		return;
830 
831 	//clock_gettime(CLOCK_THREAD_CPUTIME_ID, &begin);
832 
833 	target = (int16_t *)buf;
834 
835 	/* get pointers to source and sink buffers */
836 	for (i = 0; i < input_channels; i++)
837 		source[i] = cras_dsp_pipeline_get_source_buffer(pipeline, i);
838 	for (i = 0; i < output_channels; i++)
839 		sink[i] = cras_dsp_pipeline_get_sink_buffer(pipeline, i);
840 
841 	remaining = frames;
842 
843 	/* process at most DSP_BUFFER_SIZE frames each loop */
844 	while (remaining > 0) {
845 		chunk = MIN(remaining, (size_t)DSP_BUFFER_SIZE);
846 
847 		/* deinterleave and convert to float */
848 		dsp_util_deinterleave(target, source, input_channels, chunk);
849 
850 		/* Run the pipeline */
851 		cras_dsp_pipeline_run(pipeline, chunk);
852 
853 		/* interleave and convert back to int16_t */
854 		dsp_util_interleave(sink, target, output_channels, chunk);
855 
856 		target += chunk * output_channels;
857 		remaining -= chunk;
858 	}
859 
860 	//clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end);
861 	//subtract_timespecs(&end, &begin, &delta);
862 	//cras_dsp_pipeline_add_statistic(pipeline, &delta, frames);
863 }
864 
cras_dsp_pipeline_free(struct pipeline * pipeline)865 void cras_dsp_pipeline_free(struct pipeline *pipeline)
866 {
867 	int i;
868 	struct instance *instance;
869 
870 	FOR_ARRAY_ELEMENT(&pipeline->instances, i, instance) {
871 		struct dsp_module *module = instance->module;
872 		instance->plugin = NULL;
873 		ARRAY_FREE(&instance->input_audio_ports);
874 		ARRAY_FREE(&instance->input_control_ports);
875 		ARRAY_FREE(&instance->output_audio_ports);
876 		ARRAY_FREE(&instance->output_control_ports);
877 
878 		if (module) {
879 			if (instance->instantiated) {
880 				module->deinstantiate(module);
881 				instance->instantiated = 0;
882 			}
883 			module->free_module(module);
884 			instance->module = NULL;
885 		}
886 	}
887 
888 	pipeline->ini = NULL;
889 	ARRAY_FREE(&pipeline->instances);
890 
891 	for (i = 0; i < pipeline->peak_buf; i++)
892 		free(pipeline->buffers[i]);
893 	free(pipeline->buffers);
894 	free(pipeline);
895 }
896