filter-chain: add biquad to dsp functions

This commit is contained in:
Wim Taymans 2022-11-24 19:14:34 +01:00
parent 01b2552b71
commit ca8bc59d0a
4 changed files with 51 additions and 28 deletions

View file

@ -260,14 +260,11 @@ static struct fc_port bq_ports[] = {
static void bq_run(struct builtin *impl, unsigned long samples, int type) static void bq_run(struct builtin *impl, unsigned long samples, int type)
{ {
struct biquad *bq = &impl->bq; struct biquad *bq = &impl->bq;
unsigned long i;
float *out = impl->port[0]; float *out = impl->port[0];
float *in = impl->port[1]; float *in = impl->port[1];
float freq = impl->port[2][0]; float freq = impl->port[2][0];
float Q = impl->port[3][0]; float Q = impl->port[3][0];
float gain = impl->port[4][0]; float gain = impl->port[4][0];
float x1, x2, y1, y2;
float b0, b1, b2, a1, a2;
if (impl->freq != freq || impl->Q != Q || impl->gain != gain) { if (impl->freq != freq || impl->Q != Q || impl->gain != gain) {
impl->freq = freq; impl->freq = freq;
@ -275,30 +272,7 @@ static void bq_run(struct builtin *impl, unsigned long samples, int type)
impl->gain = gain; impl->gain = gain;
biquad_set(bq, type, freq * 2 / impl->rate, Q, gain); biquad_set(bq, type, freq * 2 / impl->rate, Q, gain);
} }
x1 = bq->x1; dsp_ops_biquad_run(&dsp_ops, bq, out, in, samples);
x2 = bq->x2;
y1 = bq->y1;
y2 = bq->y2;
b0 = bq->b0;
b1 = bq->b1;
b2 = bq->b2;
a1 = bq->a1;
a2 = bq->a2;
for (i = 0; i < samples; i++) {
float x = in[i];
float y = b0 * x + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2;
out[i] = y;
x2 = x1;
x1 = x;
y2 = y1;
y1 = y;
}
#define F(x) (-FLT_MIN < (x) && (x) < FLT_MIN ? 0.0f : (x))
bq->x1 = F(x1);
bq->x2 = F(x2);
bq->y1 = F(y1);
bq->y2 = F(y2);
#undef F
} }
/** bq_lowpass */ /** bq_lowpass */

View file

@ -25,6 +25,7 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <math.h> #include <math.h>
#include <float.h>
#include <spa/utils/defs.h> #include <spa/utils/defs.h>
@ -98,3 +99,37 @@ void dsp_mix_gain_c(struct dsp_ops *ops,
} }
} }
} }
void dsp_biquad_run_c(struct dsp_ops *ops, struct biquad *bq,
float *out, const float *in, uint32_t n_samples)
{
float x1, x2, y1, y2;
float b0, b1, b2, a1, a2;
uint32_t i;
x1 = bq->x1;
x2 = bq->x2;
y1 = bq->y1;
y2 = bq->y2;
b0 = bq->b0;
b1 = bq->b1;
b2 = bq->b2;
a1 = bq->a1;
a2 = bq->a2;
for (i = 0; i < n_samples; i++) {
float x = in[i];
float y = b0 * x + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2;
out[i] = y;
x2 = x1;
x1 = x;
y2 = y1;
y1 = y;
}
#define F(x) (-FLT_MIN < (x) && (x) < FLT_MIN ? 0.0f : (x))
bq->x1 = F(x1);
bq->x2 = F(x2);
bq->y1 = F(y1);
bq->y2 = F(y2);
#undef F
}

View file

@ -42,6 +42,8 @@ struct dsp_info {
void * SPA_RESTRICT dst, void * SPA_RESTRICT dst,
const void * SPA_RESTRICT src[], const void * SPA_RESTRICT src[],
float gain[], uint32_t n_src, uint32_t n_samples); float gain[], uint32_t n_src, uint32_t n_samples);
void (*biquad_run) (struct dsp_ops *ops, struct biquad *bq,
float *out, const float *in, uint32_t n_samples);
}; };
static struct dsp_info dsp_table[] = static struct dsp_info dsp_table[] =
@ -50,11 +52,13 @@ static struct dsp_info dsp_table[] =
{ SPA_CPU_FLAG_SSE, { SPA_CPU_FLAG_SSE,
.copy = dsp_copy_c, .copy = dsp_copy_c,
.mix_gain = dsp_mix_gain_sse, .mix_gain = dsp_mix_gain_sse,
.biquad_run = dsp_biquad_run_c,
}, },
#endif #endif
{ 0, { 0,
.copy = dsp_copy_c, .copy = dsp_copy_c,
.mix_gain = dsp_mix_gain_c, .mix_gain = dsp_mix_gain_c,
.biquad_run = dsp_biquad_run_c,
}, },
}; };
@ -86,6 +90,7 @@ int dsp_ops_init(struct dsp_ops *ops)
ops->cpu_flags = info->cpu_flags; ops->cpu_flags = info->cpu_flags;
ops->copy = info->copy; ops->copy = info->copy;
ops->mix_gain = info->mix_gain; ops->mix_gain = info->mix_gain;
ops->biquad_run = info->biquad_run;
ops->free = impl_dsp_ops_free; ops->free = impl_dsp_ops_free;
return 0; return 0;

View file

@ -24,6 +24,8 @@
#include <spa/utils/defs.h> #include <spa/utils/defs.h>
#include "biquad.h"
struct dsp_ops { struct dsp_ops {
uint32_t cpu_flags; uint32_t cpu_flags;
@ -35,6 +37,8 @@ struct dsp_ops {
void * SPA_RESTRICT dst, void * SPA_RESTRICT dst,
const void * SPA_RESTRICT src[], const void * SPA_RESTRICT src[],
float gain[], uint32_t n_src, uint32_t n_samples); float gain[], uint32_t n_src, uint32_t n_samples);
void (*biquad_run) (struct dsp_ops *ops, struct biquad *bq,
float *out, const float *in, uint32_t n_samples);
void (*free) (struct dsp_ops *ops); void (*free) (struct dsp_ops *ops);
const void *priv; const void *priv;
@ -44,19 +48,24 @@ int dsp_ops_init(struct dsp_ops *ops);
#define dsp_ops_copy(ops,...) (ops)->copy(ops, __VA_ARGS__) #define dsp_ops_copy(ops,...) (ops)->copy(ops, __VA_ARGS__)
#define dsp_ops_mix_gain(ops,...) (ops)->mix_gain(ops, __VA_ARGS__) #define dsp_ops_mix_gain(ops,...) (ops)->mix_gain(ops, __VA_ARGS__)
#define dsp_ops_biquad_run(ops,...) (ops)->biquad_run(ops, __VA_ARGS__)
#define dsp_ops_free(ops) (ops)->free(ops) #define dsp_ops_free(ops) (ops)->free(ops)
#define MAKE_COPY_FUNC(arch) \ #define MAKE_COPY_FUNC(arch) \
void dsp_copy_##arch(struct dsp_ops *ops, void * SPA_RESTRICT dst, \ void dsp_copy_##arch(struct dsp_ops *ops, void * SPA_RESTRICT dst, \
const void * SPA_RESTRICT src, uint32_t n_samples) const void * SPA_RESTRICT src, uint32_t n_samples)
#define MAKE_MIX_GAIN_FUNC(arch) \ #define MAKE_MIX_GAIN_FUNC(arch) \
void dsp_mix_gain_##arch(struct dsp_ops *ops, void * SPA_RESTRICT dst, \ void dsp_mix_gain_##arch(struct dsp_ops *ops, void * SPA_RESTRICT dst, \
const void * SPA_RESTRICT src[], float gain[], uint32_t n_src, uint32_t n_samples) const void * SPA_RESTRICT src[], float gain[], uint32_t n_src, uint32_t n_samples)
#define MAKE_BIQUAD_RUN_FUNC(arch) \
void dsp_biquad_run_##arch (struct dsp_ops *ops, struct biquad *bq, \
float *out, const float *in, uint32_t n_samples)
MAKE_COPY_FUNC(c); MAKE_COPY_FUNC(c);
MAKE_MIX_GAIN_FUNC(c); MAKE_MIX_GAIN_FUNC(c);
MAKE_BIQUAD_RUN_FUNC(c);
#if defined (HAVE_SSE) #if defined (HAVE_SSE)
MAKE_MIX_GAIN_FUNC(sse); MAKE_MIX_GAIN_FUNC(sse);
#endif #endif