diff options
author | Paul B Mahol <onemda@gmail.com> | 2020-11-27 18:32:56 +0100 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2020-11-27 18:46:23 +0100 |
commit | cf98822b66ac298e165dfd845766303d95062001 (patch) | |
tree | ef59ce3cc70c98f245c347b17221734bf74ee968 | |
parent | a83098ab03a47179d54a9b9c8bcefc81b9c6aafd (diff) | |
download | ffmpeg-cf98822b66ac298e165dfd845766303d95062001.tar.gz |
avfilter/af_acrossover: add support for float sample format
-rw-r--r-- | libavfilter/af_acrossover.c | 245 |
1 files changed, 130 insertions, 115 deletions
diff --git a/libavfilter/af_acrossover.c b/libavfilter/af_acrossover.c index 550d4ddbaf..3b31031c43 100644 --- a/libavfilter/af_acrossover.c +++ b/libavfilter/af_acrossover.c @@ -67,6 +67,8 @@ typedef struct AudioCrossoverContext { AVFrame *input_frame; AVFrame *frames[MAX_BANDS]; + + int (*filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } AudioCrossoverContext; #define OFFSET(x) offsetof(AudioCrossoverContext, x) @@ -228,58 +230,12 @@ static void calc_q_factors(int order, double *q) q[i] = 1. / (-2. * cos(M_PI * (2. * (i + 1) + n - 1.) / (2. * n))); } -static int config_input(AVFilterLink *inlink) -{ - AVFilterContext *ctx = inlink->dst; - AudioCrossoverContext *s = ctx->priv; - int sample_rate = inlink->sample_rate; - double q[16]; - - s->xover = av_calloc(inlink->channels, sizeof(*s->xover)); - if (!s->xover) - return AVERROR(ENOMEM); - - s->order = (s->order_opt + 1) * 2; - s->filter_count = s->order / 2; - s->first_order = s->filter_count & 1; - s->ap_filter_count = s->filter_count / 2 + s->first_order; - calc_q_factors(s->order, q); - - for (int ch = 0; ch < inlink->channels; ch++) { - for (int band = 0; band <= s->nb_splits; band++) { - if (s->first_order) { - set_lp(&s->xover[ch].lp[band][0], s->splits[band], 0.5, sample_rate); - set_hp(&s->xover[ch].hp[band][0], s->splits[band], 0.5, sample_rate); - } - - for (int n = s->first_order; n < s->filter_count; n++) { - const int idx = s->filter_count / 2 - ((n + s->first_order) / 2 - s->first_order) - 1; - - set_lp(&s->xover[ch].lp[band][n], s->splits[band], q[idx], sample_rate); - set_hp(&s->xover[ch].hp[band][n], s->splits[band], q[idx], sample_rate); - } - - for (int x = 0; x <= s->nb_splits && s->first_order; x++) - set_ap1(&s->xover[ch].ap[x][band][0], s->splits[band], sample_rate); - - for (int n = s->first_order; n < s->ap_filter_count; n++) { - const int idx = (s->filter_count / 2 - ((n * 2 + s->first_order) / 2 - s->first_order) - 1); - - for (int x = 0; x <= s->nb_splits; x++) - set_ap(&s->xover[ch].ap[x][band][n], s->splits[band], q[idx], sample_rate); - } - } - } - - return 0; -} - static int query_formats(AVFilterContext *ctx) { AVFilterFormats *formats; AVFilterChannelLayouts *layouts; static const enum AVSampleFormat sample_fmts[] = { - AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE }; int ret; @@ -304,90 +260,149 @@ static int query_formats(AVFilterContext *ctx) return ff_set_common_samplerates(ctx, formats); } -static void biquad_process(BiquadContext *b, - double *dst, const double *src, - int nb_samples) -{ - const double b0 = b->b0; - const double b1 = b->b1; - const double b2 = b->b2; - const double a1 = b->a1; - const double a2 = b->a2; - double z1 = b->z1; - double z2 = b->z2; - - for (int n = 0; n < nb_samples; n++) { - const double in = src[n]; - double out; - - out = in * b0 + z1; - z1 = b1 * in + z2 + a1 * out; - z2 = b2 * in + a2 * out; - dst[n] = out; - } +#define BIQUAD_PROCESS(name, type) \ +static void biquad_process_## name(BiquadContext *b, \ + type *dst, const type *src, \ + int nb_samples) \ +{ \ + const type b0 = b->b0; \ + const type b1 = b->b1; \ + const type b2 = b->b2; \ + const type a1 = b->a1; \ + const type a2 = b->a2; \ + type z1 = b->z1; \ + type z2 = b->z2; \ + \ + for (int n = 0; n < nb_samples; n++) { \ + const type in = src[n]; \ + type out; \ + \ + out = in * b0 + z1; \ + z1 = b1 * in + z2 + a1 * out; \ + z2 = b2 * in + a2 * out; \ + dst[n] = out; \ + } \ + \ + b->z1 = z1; \ + b->z2 = z2; \ +} - b->z1 = z1; - b->z2 = z2; +BIQUAD_PROCESS(fltp, float) +BIQUAD_PROCESS(dblp, double) + +#define XOVER_PROCESS(name, type, one) \ +static int filter_channels_## name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ +{ \ + AudioCrossoverContext *s = ctx->priv; \ + AVFrame *in = s->input_frame; \ + AVFrame **frames = s->frames; \ + const int start = (in->channels * jobnr) / nb_jobs; \ + const int end = (in->channels * (jobnr+1)) / nb_jobs; \ + const int nb_samples = in->nb_samples; \ + \ + for (int ch = start; ch < end; ch++) { \ + CrossoverChannel *xover = &s->xover[ch]; \ + \ + for (int band = 0; band < ctx->nb_outputs; band++) { \ + for (int f = 0; band + 1 < ctx->nb_outputs && f < s->filter_count; f++) { \ + const type *src = band == 0 ? (const type *)in->extended_data[ch] : (const type *)frames[band]->extended_data[ch]; \ + type *dst = (type *)frames[band + 1]->extended_data[ch]; \ + const type *hsrc = f == 0 ? src : dst; \ + BiquadContext *hp = &xover->hp[band][f]; \ + \ + biquad_process_## name(hp, dst, hsrc, nb_samples); \ + } \ + \ + for (int f = 0; band + 1 < ctx->nb_outputs && f < s->filter_count; f++) { \ + const type *src = band == 0 ? (const type *)in->extended_data[ch] : (const type *)frames[band]->extended_data[ch]; \ + type *dst = (type *)frames[band]->extended_data[ch]; \ + const type *lsrc = f == 0 ? src : dst; \ + BiquadContext *lp = &xover->lp[band][f]; \ + \ + biquad_process_## name(lp, dst, lsrc, nb_samples); \ + } \ + \ + for (int aband = band + 1; aband < ctx->nb_outputs; aband++) { \ + if (s->first_order) { \ + const type *src = (const type *)frames[band]->extended_data[ch]; \ + type *dst = (type *)frames[band]->extended_data[ch]; \ + BiquadContext *ap = &xover->ap[band][aband][0]; \ + \ + biquad_process_## name(ap, dst, src, nb_samples); \ + } \ + \ + for (int f = s->first_order; f < s->ap_filter_count; f++) { \ + const type *src = (const type *)frames[band]->extended_data[ch]; \ + type *dst = (type *)frames[band]->extended_data[ch]; \ + BiquadContext *ap = &xover->ap[band][aband][f]; \ + \ + biquad_process_## name(ap, dst, src, nb_samples); \ + } \ + } \ + } \ + \ + for (int band = 0; band < ctx->nb_outputs && s->first_order; band++) { \ + if (band & 1) { \ + type *dst = (type *)frames[band]->extended_data[ch]; \ + \ + for (int n = 0; n < nb_samples; n++) \ + dst[n] *= -one; \ + } \ + } \ + } \ + \ + return 0; \ } -static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +XOVER_PROCESS(fltp, float, 1.f) +XOVER_PROCESS(dblp, double, 1.0) + +static int config_input(AVFilterLink *inlink) { + AVFilterContext *ctx = inlink->dst; AudioCrossoverContext *s = ctx->priv; - AVFrame *in = s->input_frame; - AVFrame **frames = s->frames; - const int start = (in->channels * jobnr) / nb_jobs; - const int end = (in->channels * (jobnr+1)) / nb_jobs; - const int nb_samples = in->nb_samples; + int sample_rate = inlink->sample_rate; + double q[16]; - for (int ch = start; ch < end; ch++) { - CrossoverChannel *xover = &s->xover[ch]; + s->xover = av_calloc(inlink->channels, sizeof(*s->xover)); + if (!s->xover) + return AVERROR(ENOMEM); - for (int band = 0; band < ctx->nb_outputs; band++) { - for (int f = 0; band + 1 < ctx->nb_outputs && f < s->filter_count; f++) { - const double *src = band == 0 ? (const double *)in->extended_data[ch] : (const double *)frames[band]->extended_data[ch]; - double *dst = (double *)frames[band + 1]->extended_data[ch]; - const double *hsrc = f == 0 ? src : dst; - BiquadContext *hp = &xover->hp[band][f]; + s->order = (s->order_opt + 1) * 2; + s->filter_count = s->order / 2; + s->first_order = s->filter_count & 1; + s->ap_filter_count = s->filter_count / 2 + s->first_order; + calc_q_factors(s->order, q); - biquad_process(hp, dst, hsrc, nb_samples); + for (int ch = 0; ch < inlink->channels; ch++) { + for (int band = 0; band <= s->nb_splits; band++) { + if (s->first_order) { + set_lp(&s->xover[ch].lp[band][0], s->splits[band], 0.5, sample_rate); + set_hp(&s->xover[ch].hp[band][0], s->splits[band], 0.5, sample_rate); } - for (int f = 0; band + 1 < ctx->nb_outputs && f < s->filter_count; f++) { - const double *src = band == 0 ? (const double *)in->extended_data[ch] : (const double *)frames[band]->extended_data[ch]; - double *dst = (double *)frames[band]->extended_data[ch]; - const double *lsrc = f == 0 ? src : dst; - BiquadContext *lp = &xover->lp[band][f]; + for (int n = s->first_order; n < s->filter_count; n++) { + const int idx = s->filter_count / 2 - ((n + s->first_order) / 2 - s->first_order) - 1; - biquad_process(lp, dst, lsrc, nb_samples); + set_lp(&s->xover[ch].lp[band][n], s->splits[band], q[idx], sample_rate); + set_hp(&s->xover[ch].hp[band][n], s->splits[band], q[idx], sample_rate); } - for (int aband = band + 1; aband < ctx->nb_outputs; aband++) { - if (s->first_order) { - const double *src = (const double *)frames[band]->extended_data[ch]; - double *dst = (double *)frames[band]->extended_data[ch]; - BiquadContext *ap = &xover->ap[band][aband][0]; - - biquad_process(ap, dst, src, nb_samples); - } + for (int x = 0; x <= s->nb_splits && s->first_order; x++) + set_ap1(&s->xover[ch].ap[x][band][0], s->splits[band], sample_rate); - for (int f = s->first_order; f < s->ap_filter_count; f++) { - const double *src = (const double *)frames[band]->extended_data[ch]; - double *dst = (double *)frames[band]->extended_data[ch]; - BiquadContext *ap = &xover->ap[band][aband][f]; + for (int n = s->first_order; n < s->ap_filter_count; n++) { + const int idx = (s->filter_count / 2 - ((n * 2 + s->first_order) / 2 - s->first_order) - 1); - biquad_process(ap, dst, src, nb_samples); - } + for (int x = 0; x <= s->nb_splits; x++) + set_ap(&s->xover[ch].ap[x][band][n], s->splits[band], q[idx], sample_rate); } } + } - for (int band = 0; band < ctx->nb_outputs && s->first_order; band++) { - if (band & 1) { - double *dst = (double *)frames[band]->extended_data[ch]; - - for (int n = 0; n < nb_samples; n++) - dst[n] *= -1.; - } - } + switch (inlink->format) { + case AV_SAMPLE_FMT_FLTP: s->filter_channels = filter_channels_fltp; break; + case AV_SAMPLE_FMT_DBLP: s->filter_channels = filter_channels_dblp; break; } return 0; @@ -415,8 +430,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) goto fail; s->input_frame = in; - ctx->internal->execute(ctx, filter_channels, NULL, NULL, FFMIN(inlink->channels, - ff_filter_get_nb_threads(ctx))); + ctx->internal->execute(ctx, s->filter_channels, NULL, NULL, FFMIN(inlink->channels, + ff_filter_get_nb_threads(ctx))); for (i = 0; i < ctx->nb_outputs; i++) { ret = ff_filter_frame(ctx->outputs[i], frames[i]); |