Home | History | Annotate | Download | only in hal
      1 /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
      2  * Use of this source code is governed by a BSD-style license that can be
      3  * found in the LICENSE file.
      4  */
      5 
      6 #include <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 
    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 */
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 */
    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 
    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 */
    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 
    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 
    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 
    728 int cras_dsp_pipeline_get_delay(struct pipeline *pipeline)
    729 {
    730 	return pipeline->sink_instance->total_delay;
    731 }
    732 
    733 int cras_dsp_pipeline_get_sample_rate(struct pipeline *pipeline)
    734 {
    735 	return pipeline->sample_rate;
    736 }
    737 
    738 int cras_dsp_pipeline_get_num_input_channels(struct pipeline *pipeline)
    739 {
    740 	return pipeline->input_channels;
    741 }
    742 
    743 int cras_dsp_pipeline_get_num_output_channels(struct pipeline *pipeline)
    744 {
    745 	return pipeline->output_channels;
    746 }
    747 
    748 int cras_dsp_pipeline_get_peak_audio_buffers(struct pipeline *pipeline)
    749 {
    750 	return pipeline->peak_buf;
    751 }
    752 
    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 
    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 
    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 
    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 
    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 
    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 
    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