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 <cutils/log.h>
      7 #include <semaphore.h>
      8 #include "cras_expr.h"
      9 #include "cras_dsp_ini.h"
     10 #include "cras_dsp_pipeline.h"
     11 #include "dsp_util.h"
     12 #include "utlist.h"
     13 
     14 #define LOG_TAG "audio_cras_dsp"
     15 
     16 /* We have a dsp_context for each pipeline. The context records the
     17  * parameters used to create a pipeline, so the pipeline can be
     18  * (re-)loaded later. The pipeline is (re-)loaded in the following
     19  * cases:
     20  *
     21  * (1) The client asks to (re-)load it with cras_load_pipeline().
     22  * (2) The client asks to reload the ini with cras_reload_ini().
     23  *
     24  */
     25 struct cras_dsp_context {
     26 	struct pipeline *pipeline;
     27 
     28 	struct cras_expr_env env;
     29 	int sample_rate;
     30 	const char *purpose;
     31 	struct cras_dsp_context *prev, *next;
     32 };
     33 
     34 static const char *ini_filename;
     35 static struct ini *ini;
     36 static struct cras_dsp_context *context_list;
     37 
     38 static void initialize_environment(struct cras_expr_env *env)
     39 {
     40 	cras_expr_env_install_builtins(env);
     41 	cras_expr_env_set_variable_boolean(env, "disable_eq", 0);
     42 	cras_expr_env_set_variable_boolean(env, "disable_drc", 0);
     43 	cras_expr_env_set_variable_string(env, "dsp_name", "");
     44 }
     45 
     46 static struct pipeline *prepare_pipeline(struct cras_dsp_context *ctx)
     47 {
     48 	struct pipeline *pipeline;
     49 	const char *purpose = ctx->purpose;
     50 
     51 	if (!ini)
     52 		return NULL;
     53 
     54 	pipeline = cras_dsp_pipeline_create(ini, &ctx->env, purpose);
     55 
     56 	if (pipeline) {
     57 		ALOGI("pipeline created");
     58 	} else {
     59 		ALOGI("cannot create pipeline");
     60 		goto bail;
     61 	}
     62 
     63 	if (cras_dsp_pipeline_load(pipeline) != 0) {
     64 		ALOGE("cannot load pipeline");
     65 		goto bail;
     66 	}
     67 
     68 	if (cras_dsp_pipeline_instantiate(pipeline, ctx->sample_rate) != 0) {
     69 		ALOGE("cannot instantiate pipeline");
     70 		goto bail;
     71 	}
     72 
     73 	if (cras_dsp_pipeline_get_sample_rate(pipeline) != ctx->sample_rate) {
     74 		ALOGE("pipeline sample rate mismatch (%d vs %d)",
     75 		       cras_dsp_pipeline_get_sample_rate(pipeline),
     76 		       ctx->sample_rate);
     77 		goto bail;
     78 	}
     79 
     80 	return pipeline;
     81 
     82 bail:
     83 	if (pipeline)
     84 		cras_dsp_pipeline_free(pipeline);
     85 	return NULL;
     86 }
     87 
     88 /* Exported functions */
     89 void cras_dsp_set_variable(struct cras_dsp_context *ctx, const char *key,
     90 			     const char *value)
     91 {
     92 	cras_expr_env_set_variable_string(&ctx->env, key, value);
     93 }
     94 
     95 void cras_dsp_load_pipeline(struct cras_dsp_context *ctx)
     96 {
     97 	struct pipeline *pipeline, *old_pipeline;
     98 
     99 	pipeline = prepare_pipeline(ctx);
    100 
    101 	old_pipeline = ctx->pipeline;
    102 	ctx->pipeline = pipeline;
    103 
    104 	if (old_pipeline)
    105 		cras_dsp_pipeline_free(old_pipeline);
    106 }
    107 
    108 void cras_dsp_reload_ini()
    109 {
    110 	struct ini *old_ini = ini;
    111 	struct cras_dsp_context *ctx;
    112 
    113 	ini = cras_dsp_ini_create(ini_filename);
    114 	if (!ini)
    115 		ALOGE("cannot create dsp ini");
    116 
    117 	DL_FOREACH(context_list, ctx) {
    118 		cras_dsp_load_pipeline(ctx);
    119 	}
    120 
    121 	if (old_ini)
    122 		cras_dsp_ini_free(old_ini);
    123 }
    124 
    125 void cras_dsp_init(const char *filename)
    126 {
    127 	dsp_enable_flush_denormal_to_zero();
    128 	ini_filename = strdup(filename);
    129 	cras_dsp_reload_ini();
    130 }
    131 
    132 void cras_dsp_stop()
    133 {
    134 	free((char *)ini_filename);
    135 	if (ini) {
    136 		cras_dsp_ini_free(ini);
    137 		ini = NULL;
    138 	}
    139 }
    140 
    141 struct cras_dsp_context *cras_dsp_context_new(int sample_rate,
    142 					      const char *purpose)
    143 {
    144 	struct cras_dsp_context *ctx = calloc(1, sizeof(*ctx));
    145 
    146 	initialize_environment(&ctx->env);
    147 	ctx->sample_rate = sample_rate;
    148 	ctx->purpose = strdup(purpose);
    149 
    150 	DL_APPEND(context_list, ctx);
    151 	return ctx;
    152 }
    153 
    154 void cras_dsp_context_free(struct cras_dsp_context *ctx)
    155 {
    156 	DL_DELETE(context_list, ctx);
    157 
    158 	if (ctx->pipeline) {
    159 		cras_dsp_pipeline_free(ctx->pipeline);
    160 		ctx->pipeline = NULL;
    161 	}
    162 	cras_expr_env_free(&ctx->env);
    163 	free((char *)ctx->purpose);
    164 	free(ctx);
    165 }
    166 
    167 struct pipeline *cras_dsp_get_pipeline(struct cras_dsp_context *ctx)
    168 {
    169 	return ctx->pipeline;
    170 }
    171 
    172 void cras_dsp_put_pipeline(struct cras_dsp_context *ctx)
    173 {
    174 }
    175 
    176 unsigned int cras_dsp_num_output_channels(const struct cras_dsp_context *ctx)
    177 {
    178 	return cras_dsp_pipeline_get_num_output_channels(ctx->pipeline);
    179 }
    180 
    181 unsigned int cras_dsp_num_input_channels(const struct cras_dsp_context *ctx)
    182 {
    183 	return cras_dsp_pipeline_get_num_input_channels(ctx->pipeline);
    184 }
    185 
    186 void cras_dsp_sync()
    187 {
    188 }
    189