filter-chain: optimize the identity biquad

Store the biquad type in the biquad, remove some unused fields.

Init all the biquads with the identify before loading the channel
specific biquads. We will process the max of all the channel biquads.
Make sure we skip processing for the indentity ones.
This commit is contained in:
Wim Taymans 2024-10-16 12:33:35 +02:00
parent 3c221f49a0
commit d8bd84183d
4 changed files with 35 additions and 24 deletions

View file

@ -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:

View file

@ -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.

View file

@ -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);
}

View file

@ -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;