mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-05 13:30:02 -05:00
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:
parent
3c221f49a0
commit
d8bd84183d
4 changed files with 35 additions and 24 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue