| /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include <cutils/log.h> |
| #include <semaphore.h> |
| #include "cras_expr.h" |
| #include "cras_dsp_ini.h" |
| #include "cras_dsp_pipeline.h" |
| #include "dsp_util.h" |
| #include "utlist.h" |
| |
| #define LOG_TAG "audio_cras_dsp" |
| |
| /* We have a dsp_context for each pipeline. The context records the |
| * parameters used to create a pipeline, so the pipeline can be |
| * (re-)loaded later. The pipeline is (re-)loaded in the following |
| * cases: |
| * |
| * (1) The client asks to (re-)load it with cras_load_pipeline(). |
| * (2) The client asks to reload the ini with cras_reload_ini(). |
| * |
| */ |
| struct cras_dsp_context { |
| struct pipeline *pipeline; |
| |
| struct cras_expr_env env; |
| int sample_rate; |
| const char *purpose; |
| struct cras_dsp_context *prev, *next; |
| }; |
| |
| static const char *ini_filename; |
| static struct ini *ini; |
| static struct cras_dsp_context *context_list; |
| |
| static void initialize_environment(struct cras_expr_env *env) |
| { |
| cras_expr_env_install_builtins(env); |
| cras_expr_env_set_variable_boolean(env, "disable_eq", 0); |
| cras_expr_env_set_variable_boolean(env, "disable_drc", 0); |
| cras_expr_env_set_variable_string(env, "dsp_name", ""); |
| } |
| |
| static struct pipeline *prepare_pipeline(struct cras_dsp_context *ctx) |
| { |
| struct pipeline *pipeline; |
| const char *purpose = ctx->purpose; |
| |
| if (!ini) |
| return NULL; |
| |
| pipeline = cras_dsp_pipeline_create(ini, &ctx->env, purpose); |
| |
| if (pipeline) { |
| ALOGI("pipeline created"); |
| } else { |
| ALOGI("cannot create pipeline"); |
| goto bail; |
| } |
| |
| if (cras_dsp_pipeline_load(pipeline) != 0) { |
| ALOGE("cannot load pipeline"); |
| goto bail; |
| } |
| |
| if (cras_dsp_pipeline_instantiate(pipeline, ctx->sample_rate) != 0) { |
| ALOGE("cannot instantiate pipeline"); |
| goto bail; |
| } |
| |
| if (cras_dsp_pipeline_get_sample_rate(pipeline) != ctx->sample_rate) { |
| ALOGE("pipeline sample rate mismatch (%d vs %d)", |
| cras_dsp_pipeline_get_sample_rate(pipeline), |
| ctx->sample_rate); |
| goto bail; |
| } |
| |
| return pipeline; |
| |
| bail: |
| if (pipeline) |
| cras_dsp_pipeline_free(pipeline); |
| return NULL; |
| } |
| |
| /* Exported functions */ |
| void cras_dsp_set_variable(struct cras_dsp_context *ctx, const char *key, |
| const char *value) |
| { |
| cras_expr_env_set_variable_string(&ctx->env, key, value); |
| } |
| |
| void cras_dsp_load_pipeline(struct cras_dsp_context *ctx) |
| { |
| struct pipeline *pipeline, *old_pipeline; |
| |
| pipeline = prepare_pipeline(ctx); |
| |
| old_pipeline = ctx->pipeline; |
| ctx->pipeline = pipeline; |
| |
| if (old_pipeline) |
| cras_dsp_pipeline_free(old_pipeline); |
| } |
| |
| void cras_dsp_reload_ini() |
| { |
| struct ini *old_ini = ini; |
| struct cras_dsp_context *ctx; |
| |
| ini = cras_dsp_ini_create(ini_filename); |
| if (!ini) |
| ALOGE("cannot create dsp ini"); |
| |
| DL_FOREACH(context_list, ctx) { |
| cras_dsp_load_pipeline(ctx); |
| } |
| |
| if (old_ini) |
| cras_dsp_ini_free(old_ini); |
| } |
| |
| void cras_dsp_init(const char *filename) |
| { |
| dsp_enable_flush_denormal_to_zero(); |
| ini_filename = strdup(filename); |
| cras_dsp_reload_ini(); |
| } |
| |
| void cras_dsp_stop() |
| { |
| free((char *)ini_filename); |
| if (ini) { |
| cras_dsp_ini_free(ini); |
| ini = NULL; |
| } |
| } |
| |
| struct cras_dsp_context *cras_dsp_context_new(int sample_rate, |
| const char *purpose) |
| { |
| struct cras_dsp_context *ctx = calloc(1, sizeof(*ctx)); |
| |
| initialize_environment(&ctx->env); |
| ctx->sample_rate = sample_rate; |
| ctx->purpose = strdup(purpose); |
| |
| DL_APPEND(context_list, ctx); |
| return ctx; |
| } |
| |
| void cras_dsp_context_free(struct cras_dsp_context *ctx) |
| { |
| DL_DELETE(context_list, ctx); |
| |
| if (ctx->pipeline) { |
| cras_dsp_pipeline_free(ctx->pipeline); |
| ctx->pipeline = NULL; |
| } |
| cras_expr_env_free(&ctx->env); |
| free((char *)ctx->purpose); |
| free(ctx); |
| } |
| |
| struct pipeline *cras_dsp_get_pipeline(struct cras_dsp_context *ctx) |
| { |
| return ctx->pipeline; |
| } |
| |
| void cras_dsp_put_pipeline(struct cras_dsp_context *ctx) |
| { |
| } |
| |
| unsigned int cras_dsp_num_output_channels(const struct cras_dsp_context *ctx) |
| { |
| return cras_dsp_pipeline_get_num_output_channels(ctx->pipeline); |
| } |
| |
| unsigned int cras_dsp_num_input_channels(const struct cras_dsp_context *ctx) |
| { |
| return cras_dsp_pipeline_get_num_input_channels(ctx->pipeline); |
| } |
| |
| void cras_dsp_sync() |
| { |
| } |