diff --git a/src/modules/module-filter-chain/biquad.c b/src/modules/module-filter-chain/biquad.c index c11f76e0d..644276bb0 100644 --- a/src/modules/module-filter-chain/biquad.c +++ b/src/modules/module-filter-chain/biquad.c @@ -326,10 +326,9 @@ void biquad_set(struct biquad *bq, enum biquad_type type, double freq, double Q, double gain) { /* Clear history values. */ + bq->type = type; bq->x1 = 0; bq->x2 = 0; - bq->y1 = 0; - bq->y2 = 0; switch (type) { case BQ_LOWPASS: diff --git a/src/modules/module-filter-chain/biquad.h b/src/modules/module-filter-chain/biquad.h index 650b26395..3344598e6 100644 --- a/src/modules/module-filter-chain/biquad.h +++ b/src/modules/module-filter-chain/biquad.h @@ -10,21 +10,6 @@ extern "C" { #endif -/* The biquad filter parameters. The transfer function H(z) is (b0 + b1 * z^(-1) - * + b2 * z^(-2)) / (1 + a1 * z^(-1) + a2 * z^(-2)). The previous two inputs - * are stored in x1 and x2, and the previous two outputs are stored in y1 and - * y2. - * - * We use double during the coefficients calculation for better accuracy, but - * float is used during the actual filtering for faster computation. - */ -struct biquad { - float b0, b1, b2; - float a1, a2; - float x1, x2; - float y1, y2; -}; - /* The type of the biquad filters */ enum biquad_type { BQ_NONE, @@ -35,7 +20,23 @@ enum biquad_type { BQ_HIGHSHELF, BQ_PEAKING, BQ_NOTCH, - BQ_ALLPASS + BQ_ALLPASS, + BQ_RAW, +}; + +/* The biquad filter parameters. The transfer function H(z) is (b0 + b1 * z^(-1) + * + b2 * z^(-2)) / (1 + a1 * z^(-1) + a2 * z^(-2)). The previous two inputs + * are stored in x1 and x2, and the previous two outputs are stored in y1 and + * y2. + * + * We use double during the coefficients calculation for better accuracy, but + * float is used during the actual filtering for faster computation. + */ +struct biquad { + enum biquad_type type; + float b0, b1, b2; + float a1, a2; + float x1, x2; }; /* Initialize a biquad filter parameters from its type and parameters. diff --git a/src/modules/module-filter-chain/builtin_plugin.c b/src/modules/module-filter-chain/builtin_plugin.c index 0d2ecaa1a..ba76f3267 100644 --- a/src/modules/module-filter-chain/builtin_plugin.c +++ b/src/modules/module-filter-chain/builtin_plugin.c @@ -287,7 +287,8 @@ static void bq_raw_update(struct builtin *impl, float b0, float b1, float b2, bq->b2 = impl->b2 * a0; bq->a1 = impl->a1 * a0; bq->a2 = impl->a2 * a0; - bq->x1 = bq->x2 = bq->y1 = bq->y2 = 0.0; + bq->x1 = bq->x2 = 0.0f; + bq->type = BQ_RAW; } /* @@ -1869,8 +1870,9 @@ static void *param_eq_instantiate(const struct fc_descriptor * Descriptor, struct spa_json it[3]; const char *val; char key[256], filename[PATH_MAX]; - int i, len, res; + int len, res; struct param_eq_impl *impl; + uint32_t i, n_bq = 0; if (config == NULL) { pw_log_error("param_eq: requires a config section"); @@ -1888,6 +1890,8 @@ static void *param_eq_instantiate(const struct fc_descriptor * Descriptor, return NULL; impl->rate = SampleRate; + for (i = 0; i < SPA_N_ELEMENTS(impl->bq); i++) + biquad_set(&impl->bq[i], BQ_NONE, 0.0f, 0.0f, 0.0f); while ((len = spa_json_object_next(&it[0], key, sizeof(key), &val)) > 0) { int32_t idx = 0; @@ -1901,12 +1905,13 @@ static void *param_eq_instantiate(const struct fc_descriptor * Descriptor, if (spa_atoi32(key+8, &idx, 0)) bq = &impl->bq[(SPA_CLAMP(idx, 1, 8) - 1) * PARAM_EQ_MAX]; - res = load_eq_bands(filename, impl->rate, bq, PARAM_EQ_MAX, &impl->n_bq); + res = load_eq_bands(filename, impl->rate, bq, PARAM_EQ_MAX, &n_bq); if (res < 0) { pw_log_error("param_eq: failed to parse configuration from '%s'", filename); goto error; } - pw_log_info("loaded %d biquads for channel %d", impl->n_bq, idx); + pw_log_info("loaded %d biquads for channel %d", n_bq, idx); + impl->n_bq = SPA_MAX(impl->n_bq, n_bq); } else if (spa_strstartswith(key, "filters")) { if (!spa_json_is_array(val, len)) { @@ -1918,12 +1923,13 @@ static void *param_eq_instantiate(const struct fc_descriptor * Descriptor, if (spa_atoi32(key+7, &idx, 0)) bq = &impl->bq[(SPA_CLAMP(idx, 1, 8) - 1) * PARAM_EQ_MAX]; - res = parse_filters(&it[1], impl->rate, bq, PARAM_EQ_MAX, &impl->n_bq); + res = parse_filters(&it[1], impl->rate, bq, PARAM_EQ_MAX, &n_bq); if (res < 0) { pw_log_error("param_eq: failed to parse configuration"); goto error; } - pw_log_info("parsed %d biquads for channel %d", impl->n_bq, idx); + pw_log_info("parsed %d biquads for channel %d", n_bq, idx); + impl->n_bq = SPA_MAX(impl->n_bq, n_bq); } else { pw_log_warn("param_eq: ignoring config key: '%s'", key); } diff --git a/src/modules/module-filter-chain/dsp-ops-c.c b/src/modules/module-filter-chain/dsp-ops-c.c index 0a576ce9a..86dd9c779 100644 --- a/src/modules/module-filter-chain/dsp-ops-c.c +++ b/src/modules/module-filter-chain/dsp-ops-c.c @@ -115,6 +115,11 @@ void dsp_biquad_run_c(struct dsp_ops *ops, struct biquad *bq, float b0, b1, b2, a1, a2; uint32_t i; + if (bq->type == BQ_NONE) { + dsp_copy_c(ops, out, in, n_samples); + return; + } + x1 = bq->x1; x2 = bq->x2; b0 = bq->b0;