19c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
29c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid * Use of this source code is governed by a BSD-style license that can be
39c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid * found in the LICENSE file.
49c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid */
59c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
69c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid#include <cutils/log.h>
79c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid#include <semaphore.h>
89c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid#include "cras_expr.h"
99c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid#include "cras_dsp_ini.h"
109c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid#include "cras_dsp_pipeline.h"
119c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid#include "dsp_util.h"
129c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid#include "utlist.h"
139c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
149c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid#define LOG_TAG "audio_cras_dsp"
159c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
169c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid/* We have a dsp_context for each pipeline. The context records the
179c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid * parameters used to create a pipeline, so the pipeline can be
189c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid * (re-)loaded later. The pipeline is (re-)loaded in the following
199c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid * cases:
209c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid *
219c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid * (1) The client asks to (re-)load it with cras_load_pipeline().
229c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid * (2) The client asks to reload the ini with cras_reload_ini().
239c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid *
249c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid */
259c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidstruct cras_dsp_context {
269c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	struct pipeline *pipeline;
279c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
289c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	struct cras_expr_env env;
299c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	int sample_rate;
309c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	const char *purpose;
319c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	struct cras_dsp_context *prev, *next;
329c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid};
339c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
349c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidstatic const char *ini_filename;
359c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidstatic struct ini *ini;
369c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidstatic struct cras_dsp_context *context_list;
379c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
389c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidstatic void initialize_environment(struct cras_expr_env *env)
399c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid{
409c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	cras_expr_env_install_builtins(env);
419c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	cras_expr_env_set_variable_boolean(env, "disable_eq", 0);
429c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	cras_expr_env_set_variable_boolean(env, "disable_drc", 0);
439c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	cras_expr_env_set_variable_string(env, "dsp_name", "");
449c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid}
459c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
469c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidstatic struct pipeline *prepare_pipeline(struct cras_dsp_context *ctx)
479c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid{
489c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	struct pipeline *pipeline;
499c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	const char *purpose = ctx->purpose;
509c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
519c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	if (!ini)
529c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		return NULL;
539c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
549c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	pipeline = cras_dsp_pipeline_create(ini, &ctx->env, purpose);
559c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
569c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	if (pipeline) {
57e4ad4b7a4f64de6721fff11ae0b57a7267279468Dylan Reid		ALOGI("pipeline created");
589c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	} else {
59e4ad4b7a4f64de6721fff11ae0b57a7267279468Dylan Reid		ALOGI("cannot create pipeline");
609c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		goto bail;
619c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	}
629c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
639c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	if (cras_dsp_pipeline_load(pipeline) != 0) {
649c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		ALOGE("cannot load pipeline");
659c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		goto bail;
669c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	}
679c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
689c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	if (cras_dsp_pipeline_instantiate(pipeline, ctx->sample_rate) != 0) {
699c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		ALOGE("cannot instantiate pipeline");
709c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		goto bail;
719c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	}
729c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
739c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	if (cras_dsp_pipeline_get_sample_rate(pipeline) != ctx->sample_rate) {
749c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		ALOGE("pipeline sample rate mismatch (%d vs %d)",
759c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		       cras_dsp_pipeline_get_sample_rate(pipeline),
769c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		       ctx->sample_rate);
779c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		goto bail;
789c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	}
799c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
809c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	return pipeline;
819c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
829c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidbail:
839c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	if (pipeline)
849c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		cras_dsp_pipeline_free(pipeline);
859c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	return NULL;
869c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid}
879c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
889c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid/* Exported functions */
899c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidvoid cras_dsp_set_variable(struct cras_dsp_context *ctx, const char *key,
909c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid			     const char *value)
919c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid{
929c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	cras_expr_env_set_variable_string(&ctx->env, key, value);
939c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid}
949c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
959c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidvoid cras_dsp_load_pipeline(struct cras_dsp_context *ctx)
969c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid{
979c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	struct pipeline *pipeline, *old_pipeline;
989c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
999c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	pipeline = prepare_pipeline(ctx);
1009c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1019c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	old_pipeline = ctx->pipeline;
1029c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	ctx->pipeline = pipeline;
1039c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1049c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	if (old_pipeline)
1059c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		cras_dsp_pipeline_free(old_pipeline);
1069c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid}
1079c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1089c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidvoid cras_dsp_reload_ini()
1099c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid{
1109c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	struct ini *old_ini = ini;
1119c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	struct cras_dsp_context *ctx;
1129c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1139c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	ini = cras_dsp_ini_create(ini_filename);
1149c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	if (!ini)
1159c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		ALOGE("cannot create dsp ini");
1169c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1179c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	DL_FOREACH(context_list, ctx) {
1189c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		cras_dsp_load_pipeline(ctx);
1199c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	}
1209c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1219c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	if (old_ini)
1229c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		cras_dsp_ini_free(old_ini);
1239c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid}
1249c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1259c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidvoid cras_dsp_init(const char *filename)
1269c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid{
1279c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	dsp_enable_flush_denormal_to_zero();
1289c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	ini_filename = strdup(filename);
1299c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	cras_dsp_reload_ini();
1309c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid}
1319c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1329c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidvoid cras_dsp_stop()
1339c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid{
1349c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	free((char *)ini_filename);
1359c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	if (ini) {
1369c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		cras_dsp_ini_free(ini);
1379c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		ini = NULL;
1389c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	}
1399c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid}
1409c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1419c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidstruct cras_dsp_context *cras_dsp_context_new(int sample_rate,
1429c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid					      const char *purpose)
1439c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid{
1449c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	struct cras_dsp_context *ctx = calloc(1, sizeof(*ctx));
1459c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1469c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	initialize_environment(&ctx->env);
1479c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	ctx->sample_rate = sample_rate;
1489c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	ctx->purpose = strdup(purpose);
1499c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1509c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	DL_APPEND(context_list, ctx);
1519c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	return ctx;
1529c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid}
1539c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1549c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidvoid cras_dsp_context_free(struct cras_dsp_context *ctx)
1559c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid{
1569c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	DL_DELETE(context_list, ctx);
1579c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1589c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	if (ctx->pipeline) {
1599c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		cras_dsp_pipeline_free(ctx->pipeline);
1609c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid		ctx->pipeline = NULL;
1619c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	}
1629c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	cras_expr_env_free(&ctx->env);
1639c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	free((char *)ctx->purpose);
1649c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	free(ctx);
1659c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid}
1669c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1679c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidstruct pipeline *cras_dsp_get_pipeline(struct cras_dsp_context *ctx)
1689c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid{
1699c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	return ctx->pipeline;
1709c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid}
1719c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1729c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidvoid cras_dsp_put_pipeline(struct cras_dsp_context *ctx)
1739c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid{
1749c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid}
1759c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1769c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidunsigned int cras_dsp_num_output_channels(const struct cras_dsp_context *ctx)
1779c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid{
1789c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	return cras_dsp_pipeline_get_num_output_channels(ctx->pipeline);
1799c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid}
1809c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1819c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidunsigned int cras_dsp_num_input_channels(const struct cras_dsp_context *ctx)
1829c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid{
1839c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid	return cras_dsp_pipeline_get_num_input_channels(ctx->pipeline);
1849c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid}
1859c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid
1869c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reidvoid cras_dsp_sync()
1879c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid{
1889c94a7e4053538cacb9695b15da4b1cc7857d09dDylan Reid}
189