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
initialize_environment(struct cras_expr_env * env)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
prepare_pipeline(struct cras_dsp_context * ctx)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 */
cras_dsp_set_variable(struct cras_dsp_context * ctx,const char * key,const char * value)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
cras_dsp_load_pipeline(struct cras_dsp_context * ctx)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
cras_dsp_reload_ini()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
cras_dsp_init(const char * filename)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
cras_dsp_stop()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
cras_dsp_context_new(int sample_rate,const char * purpose)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
cras_dsp_context_free(struct cras_dsp_context * ctx)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
cras_dsp_get_pipeline(struct cras_dsp_context * ctx)167 struct pipeline *cras_dsp_get_pipeline(struct cras_dsp_context *ctx)
168 {
169 return ctx->pipeline;
170 }
171
cras_dsp_put_pipeline(struct cras_dsp_context * ctx)172 void cras_dsp_put_pipeline(struct cras_dsp_context *ctx)
173 {
174 }
175
cras_dsp_num_output_channels(const struct cras_dsp_context * ctx)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
cras_dsp_num_input_channels(const struct cras_dsp_context * ctx)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
cras_dsp_sync()186 void cras_dsp_sync()
187 {
188 }
189