]> git.sesse.net Git - ffmpeg/blob - libavfilter/af_acrossover.c
0be2f3a76f2c91a90a44f3c6648a0d19ee6c7cc1
[ffmpeg] / libavfilter / af_acrossover.c
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 /**
20  * @file
21  * Crossover filter
22  *
23  * Split an audio stream into several bands.
24  */
25
26 #include "libavutil/attributes.h"
27 #include "libavutil/avstring.h"
28 #include "libavutil/channel_layout.h"
29 #include "libavutil/eval.h"
30 #include "libavutil/float_dsp.h"
31 #include "libavutil/internal.h"
32 #include "libavutil/opt.h"
33
34 #include "audio.h"
35 #include "avfilter.h"
36 #include "formats.h"
37 #include "internal.h"
38
39 #define MAX_SPLITS 16
40 #define MAX_BANDS MAX_SPLITS + 1
41
42 #define B0 0
43 #define B1 1
44 #define B2 2
45 #define A1 3
46 #define A2 4
47
48 typedef struct BiquadCoeffs {
49     double cd[5];
50     float cf[5];
51 } BiquadCoeffs;
52
53 typedef struct AudioCrossoverContext {
54     const AVClass *class;
55
56     char *splits_str;
57     int order_opt;
58     float level_in;
59
60     int order;
61     int filter_count;
62     int first_order;
63     int ap_filter_count;
64     int nb_splits;
65     float *splits;
66
67     BiquadCoeffs lp[MAX_BANDS][20];
68     BiquadCoeffs hp[MAX_BANDS][20];
69     BiquadCoeffs ap[MAX_BANDS][20];
70
71     AVFrame *xover;
72
73     AVFrame *input_frame;
74     AVFrame *frames[MAX_BANDS];
75
76     int (*filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
77
78     AVFloatDSPContext *fdsp;
79 } AudioCrossoverContext;
80
81 #define OFFSET(x) offsetof(AudioCrossoverContext, x)
82 #define AF AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
83
84 static const AVOption acrossover_options[] = {
85     { "split", "set split frequencies", OFFSET(splits_str), AV_OPT_TYPE_STRING, {.str="500"}, 0, 0, AF },
86     { "order", "set order",             OFFSET(order_opt),  AV_OPT_TYPE_INT,    {.i64=1},     0, 9, AF, "m" },
87     { "2nd",   "2nd order",             0,                  AV_OPT_TYPE_CONST,  {.i64=0},     0, 0, AF, "m" },
88     { "4th",   "4th order",             0,                  AV_OPT_TYPE_CONST,  {.i64=1},     0, 0, AF, "m" },
89     { "6th",   "6th order",             0,                  AV_OPT_TYPE_CONST,  {.i64=2},     0, 0, AF, "m" },
90     { "8th",   "8th order",             0,                  AV_OPT_TYPE_CONST,  {.i64=3},     0, 0, AF, "m" },
91     { "10th",  "10th order",            0,                  AV_OPT_TYPE_CONST,  {.i64=4},     0, 0, AF, "m" },
92     { "12th",  "12th order",            0,                  AV_OPT_TYPE_CONST,  {.i64=5},     0, 0, AF, "m" },
93     { "14th",  "14th order",            0,                  AV_OPT_TYPE_CONST,  {.i64=6},     0, 0, AF, "m" },
94     { "16th",  "16th order",            0,                  AV_OPT_TYPE_CONST,  {.i64=7},     0, 0, AF, "m" },
95     { "18th",  "18th order",            0,                  AV_OPT_TYPE_CONST,  {.i64=8},     0, 0, AF, "m" },
96     { "20th",  "20th order",            0,                  AV_OPT_TYPE_CONST,  {.i64=9},     0, 0, AF, "m" },
97     { "level", "set input gain",        OFFSET(level_in),   AV_OPT_TYPE_FLOAT,  {.dbl=1},     0, 1, AF },
98     { NULL }
99 };
100
101 AVFILTER_DEFINE_CLASS(acrossover);
102
103 static av_cold int init(AVFilterContext *ctx)
104 {
105     AudioCrossoverContext *s = ctx->priv;
106     char *p, *arg, *saveptr = NULL;
107     int i, ret = 0;
108
109     s->fdsp = avpriv_float_dsp_alloc(0);
110     if (!s->fdsp)
111         return AVERROR(ENOMEM);
112
113     s->splits = av_calloc(MAX_SPLITS, sizeof(*s->splits));
114     if (!s->splits)
115         return AVERROR(ENOMEM);
116
117     p = s->splits_str;
118     for (i = 0; i < MAX_SPLITS; i++) {
119         float freq;
120
121         if (!(arg = av_strtok(p, " |", &saveptr)))
122             break;
123
124         p = NULL;
125
126         if (av_sscanf(arg, "%f", &freq) != 1) {
127             av_log(ctx, AV_LOG_ERROR, "Invalid syntax for frequency[%d].\n", i);
128             return AVERROR(EINVAL);
129         }
130         if (freq <= 0) {
131             av_log(ctx, AV_LOG_ERROR, "Frequency %f must be positive number.\n", freq);
132             return AVERROR(EINVAL);
133         }
134
135         if (i > 0 && freq <= s->splits[i-1]) {
136             av_log(ctx, AV_LOG_ERROR, "Frequency %f must be in increasing order.\n", freq);
137             return AVERROR(EINVAL);
138         }
139
140         s->splits[i] = freq;
141     }
142
143     s->nb_splits = i;
144
145     for (i = 0; i <= s->nb_splits; i++) {
146         AVFilterPad pad  = { 0 };
147         char *name;
148
149         pad.type = AVMEDIA_TYPE_AUDIO;
150         name = av_asprintf("out%d", ctx->nb_outputs);
151         if (!name)
152             return AVERROR(ENOMEM);
153         pad.name = name;
154
155         if ((ret = ff_insert_outpad(ctx, i, &pad)) < 0) {
156             av_freep(&pad.name);
157             return ret;
158         }
159     }
160
161     return ret;
162 }
163
164 static void set_lp(BiquadCoeffs *b, double fc, double q, double sr)
165 {
166     double omega = 2. * M_PI * fc / sr;
167     double cosine = cos(omega);
168     double alpha = sin(omega) / (2. * q);
169
170     double b0 = (1. - cosine) / 2.;
171     double b1 = 1. - cosine;
172     double b2 = (1. - cosine) / 2.;
173     double a0 = 1. + alpha;
174     double a1 = -2. * cosine;
175     double a2 = 1. - alpha;
176
177     b->cd[B0] =  b0 / a0;
178     b->cd[B1] =  b1 / a0;
179     b->cd[B2] =  b2 / a0;
180     b->cd[A1] = -a1 / a0;
181     b->cd[A2] = -a2 / a0;
182
183     b->cf[B0] = b->cd[B0];
184     b->cf[B1] = b->cd[B1];
185     b->cf[B2] = b->cd[B2];
186     b->cf[A1] = b->cd[A1];
187     b->cf[A2] = b->cd[A2];
188 }
189
190 static void set_hp(BiquadCoeffs *b, double fc, double q, double sr)
191 {
192     double omega = 2. * M_PI * fc / sr;
193     double cosine = cos(omega);
194     double alpha = sin(omega) / (2. * q);
195
196     double b0 = (1. + cosine) / 2.;
197     double b1 = -1. - cosine;
198     double b2 = (1. + cosine) / 2.;
199     double a0 = 1. + alpha;
200     double a1 = -2. * cosine;
201     double a2 = 1. - alpha;
202
203     b->cd[B0] =  b0 / a0;
204     b->cd[B1] =  b1 / a0;
205     b->cd[B2] =  b2 / a0;
206     b->cd[A1] = -a1 / a0;
207     b->cd[A2] = -a2 / a0;
208
209     b->cf[B0] = b->cd[B0];
210     b->cf[B1] = b->cd[B1];
211     b->cf[B2] = b->cd[B2];
212     b->cf[A1] = b->cd[A1];
213     b->cf[A2] = b->cd[A2];
214 }
215
216 static void set_ap(BiquadCoeffs *b, double fc, double q, double sr)
217 {
218     double omega = 2. * M_PI * fc / sr;
219     double cosine = cos(omega);
220     double alpha = sin(omega) / (2. * q);
221
222     double a0 = 1. + alpha;
223     double a1 = -2. * cosine;
224     double a2 = 1. - alpha;
225     double b0 = a2;
226     double b1 = a1;
227     double b2 = a0;
228
229     b->cd[B0] =  b0 / a0;
230     b->cd[B1] =  b1 / a0;
231     b->cd[B2] =  b2 / a0;
232     b->cd[A1] = -a1 / a0;
233     b->cd[A2] = -a2 / a0;
234
235     b->cf[B0] = b->cd[B0];
236     b->cf[B1] = b->cd[B1];
237     b->cf[B2] = b->cd[B2];
238     b->cf[A1] = b->cd[A1];
239     b->cf[A2] = b->cd[A2];
240 }
241
242 static void set_ap1(BiquadCoeffs *b, double fc, double sr)
243 {
244     double omega = 2. * M_PI * fc / sr;
245
246     b->cd[A1] = exp(-omega);
247     b->cd[A2] = 0.;
248     b->cd[B0] = -b->cd[A1];
249     b->cd[B1] = 1.;
250     b->cd[B2] = 0.;
251
252     b->cf[B0] = b->cd[B0];
253     b->cf[B1] = b->cd[B1];
254     b->cf[B2] = b->cd[B2];
255     b->cf[A1] = b->cd[A1];
256     b->cf[A2] = b->cd[A2];
257 }
258
259 static void calc_q_factors(int order, double *q)
260 {
261     double n = order / 2.;
262
263     for (int i = 0; i < n / 2; i++)
264         q[i] = 1. / (-2. * cos(M_PI * (2. * (i + 1) + n - 1.) / (2. * n)));
265 }
266
267 static int query_formats(AVFilterContext *ctx)
268 {
269     AVFilterFormats *formats;
270     AVFilterChannelLayouts *layouts;
271     static const enum AVSampleFormat sample_fmts[] = {
272         AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP,
273         AV_SAMPLE_FMT_NONE
274     };
275     int ret;
276
277     layouts = ff_all_channel_counts();
278     if (!layouts)
279         return AVERROR(ENOMEM);
280     ret = ff_set_common_channel_layouts(ctx, layouts);
281     if (ret < 0)
282         return ret;
283
284     formats = ff_make_format_list(sample_fmts);
285     if (!formats)
286         return AVERROR(ENOMEM);
287     ret = ff_set_common_formats(ctx, formats);
288     if (ret < 0)
289         return ret;
290
291     formats = ff_all_samplerates();
292     if (!formats)
293         return AVERROR(ENOMEM);
294     return ff_set_common_samplerates(ctx, formats);
295 }
296
297 #define BIQUAD_PROCESS(name, type)                             \
298 static void biquad_process_## name(const type *const c,        \
299                                    type *b,                    \
300                                    type *dst, const type *src, \
301                                    int nb_samples)             \
302 {                                                              \
303     const type b0 = c[B0];                                     \
304     const type b1 = c[B1];                                     \
305     const type b2 = c[B2];                                     \
306     const type a1 = c[A1];                                     \
307     const type a2 = c[A2];                                     \
308     type z1 = b[0];                                            \
309     type z2 = b[1];                                            \
310                                                                \
311     for (int n = 0; n + 1 < nb_samples; n++) {                 \
312         type in = src[n];                                      \
313         type out;                                              \
314                                                                \
315         out = in * b0 + z1;                                    \
316         z1 = b1 * in + z2 + a1 * out;                          \
317         z2 = b2 * in + a2 * out;                               \
318         dst[n] = out;                                          \
319                                                                \
320         n++;                                                   \
321         in = src[n];                                           \
322         out = in * b0 + z1;                                    \
323         z1 = b1 * in + z2 + a1 * out;                          \
324         z2 = b2 * in + a2 * out;                               \
325         dst[n] = out;                                          \
326     }                                                          \
327                                                                \
328     if (nb_samples & 1) {                                      \
329         const int n = nb_samples - 1;                          \
330         const type in = src[n];                                \
331         type out;                                              \
332                                                                \
333         out = in * b0 + z1;                                    \
334         z1 = b1 * in + z2 + a1 * out;                          \
335         z2 = b2 * in + a2 * out;                               \
336         dst[n] = out;                                          \
337     }                                                          \
338                                                                \
339     b[0] = z1;                                                 \
340     b[1] = z2;                                                 \
341 }
342
343 BIQUAD_PROCESS(fltp, float)
344 BIQUAD_PROCESS(dblp, double)
345
346 #define XOVER_PROCESS(name, type, one, ff)                                                  \
347 static int filter_channels_## name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
348 {                                                                                           \
349     AudioCrossoverContext *s = ctx->priv;                                                   \
350     AVFrame *in = s->input_frame;                                                           \
351     AVFrame **frames = s->frames;                                                           \
352     const int start = (in->channels * jobnr) / nb_jobs;                                     \
353     const int end = (in->channels * (jobnr+1)) / nb_jobs;                                   \
354     const int nb_samples = in->nb_samples;                                                  \
355     const int nb_outs = ctx->nb_outputs;                                                    \
356                                                                                             \
357     for (int ch = start; ch < end; ch++) {                                                  \
358         const type *src = (const type *)in->extended_data[ch];                              \
359         type *xover = (type *)s->xover->extended_data[ch];                                  \
360                                                                                             \
361         s->fdsp->vector_## ff ##mul_scalar((type *)frames[0]->extended_data[ch], src,       \
362                                     s->level_in, FFALIGN(nb_samples, sizeof(type)));        \
363                                                                                             \
364         for (int band = 0; band < nb_outs; band++) {                                        \
365             for (int f = 0; band + 1 < nb_outs && f < s->filter_count; f++) {               \
366                 const type *prv = (const type *)frames[band]->extended_data[ch];            \
367                 type *dst = (type *)frames[band + 1]->extended_data[ch];                    \
368                 const type *hsrc = f == 0 ? prv : dst;                                      \
369                 type *hp = xover + nb_outs * 20 + band * 20 + f * 2;                        \
370                 const type *const hpc = (type *)&s->hp[band][f].c ## ff;                    \
371                                                                                             \
372                 biquad_process_## name(hpc, hp, dst, hsrc, nb_samples);                     \
373             }                                                                               \
374                                                                                             \
375             for (int f = 0; band + 1 < nb_outs && f < s->filter_count; f++) {               \
376                 type *dst = (type *)frames[band]->extended_data[ch];                        \
377                 const type *lsrc = dst;                                                     \
378                 type *lp = xover + band * 20 + f * 2;                                       \
379                 const type *const lpc = (type *)&s->lp[band][f].c ## ff;                    \
380                                                                                             \
381                 biquad_process_## name(lpc, lp, dst, lsrc, nb_samples);                     \
382             }                                                                               \
383                                                                                             \
384             for (int aband = band + 1; aband + 1 < nb_outs; aband++) {                      \
385                 if (s->first_order) {                                                       \
386                     const type *asrc = (const type *)frames[band]->extended_data[ch];       \
387                     type *dst = (type *)frames[band]->extended_data[ch];                    \
388                     type *ap = xover + nb_outs * 40 + (aband * nb_outs + band) * 20;        \
389                     const type *const apc = (type *)&s->ap[aband][0].c ## ff;               \
390                                                                                             \
391                     biquad_process_## name(apc, ap, dst, asrc, nb_samples);                 \
392                 }                                                                           \
393                                                                                             \
394                 for (int f = s->first_order; f < s->ap_filter_count; f++) {                 \
395                     const type *asrc = (const type *)frames[band]->extended_data[ch];       \
396                     type *dst = (type *)frames[band]->extended_data[ch];                    \
397                     type *ap = xover + nb_outs * 40 + (aband * nb_outs + band) * 20 + f * 2;\
398                     const type *const apc = (type *)&s->ap[aband][f].c ## ff;               \
399                                                                                             \
400                     biquad_process_## name(apc, ap, dst, asrc, nb_samples);                 \
401                 }                                                                           \
402             }                                                                               \
403         }                                                                                   \
404                                                                                             \
405         for (int band = 0; band < nb_outs && s->first_order; band++) {                      \
406             if (band & 1) {                                                                 \
407                 type *dst = (type *)frames[band]->extended_data[ch];                        \
408                 s->fdsp->vector_## ff ##mul_scalar(dst, dst, -one,                          \
409                                                    FFALIGN(nb_samples, sizeof(type)));      \
410             }                                                                               \
411         }                                                                                   \
412     }                                                                                       \
413                                                                                             \
414     return 0;                                                                               \
415 }
416
417 XOVER_PROCESS(fltp, float, 1.f, f)
418 XOVER_PROCESS(dblp, double, 1.0, d)
419
420 static int config_input(AVFilterLink *inlink)
421 {
422     AVFilterContext *ctx = inlink->dst;
423     AudioCrossoverContext *s = ctx->priv;
424     int sample_rate = inlink->sample_rate;
425     double q[16];
426
427     s->order = (s->order_opt + 1) * 2;
428     s->filter_count = s->order / 2;
429     s->first_order = s->filter_count & 1;
430     s->ap_filter_count = s->filter_count / 2 + s->first_order;
431     calc_q_factors(s->order, q);
432
433     for (int band = 0; band <= s->nb_splits; band++) {
434         if (s->first_order) {
435             set_lp(&s->lp[band][0], s->splits[band], 0.5, sample_rate);
436             set_hp(&s->hp[band][0], s->splits[band], 0.5, sample_rate);
437         }
438
439         for (int n = s->first_order; n < s->filter_count; n++) {
440             const int idx = s->filter_count / 2 - ((n + s->first_order) / 2 - s->first_order) - 1;
441
442             set_lp(&s->lp[band][n], s->splits[band], q[idx], sample_rate);
443             set_hp(&s->hp[band][n], s->splits[band], q[idx], sample_rate);
444         }
445
446         if (s->first_order)
447             set_ap1(&s->ap[band][0], s->splits[band], sample_rate);
448
449         for (int n = s->first_order; n < s->ap_filter_count; n++) {
450             const int idx = (s->filter_count / 2 - ((n * 2 + s->first_order) / 2 - s->first_order) - 1);
451
452             set_ap(&s->ap[band][n], s->splits[band], q[idx], sample_rate);
453         }
454     }
455
456     switch (inlink->format) {
457     case AV_SAMPLE_FMT_FLTP: s->filter_channels = filter_channels_fltp; break;
458     case AV_SAMPLE_FMT_DBLP: s->filter_channels = filter_channels_dblp; break;
459     }
460
461     s->xover = ff_get_audio_buffer(inlink, 2 * (ctx->nb_outputs * 10 + ctx->nb_outputs * 10 +
462                                                 ctx->nb_outputs * ctx->nb_outputs * 10));
463     if (!s->xover)
464         return AVERROR(ENOMEM);
465
466     return 0;
467 }
468
469 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
470 {
471     AVFilterContext *ctx = inlink->dst;
472     AudioCrossoverContext *s = ctx->priv;
473     AVFrame **frames = s->frames;
474     int i, ret = 0;
475
476     for (i = 0; i < ctx->nb_outputs; i++) {
477         frames[i] = ff_get_audio_buffer(ctx->outputs[i], in->nb_samples);
478
479         if (!frames[i]) {
480             ret = AVERROR(ENOMEM);
481             break;
482         }
483
484         frames[i]->pts = in->pts;
485     }
486
487     if (ret < 0)
488         goto fail;
489
490     s->input_frame = in;
491     ctx->internal->execute(ctx, s->filter_channels, NULL, NULL, FFMIN(inlink->channels,
492                                                                       ff_filter_get_nb_threads(ctx)));
493
494     for (i = 0; i < ctx->nb_outputs; i++) {
495         ret = ff_filter_frame(ctx->outputs[i], frames[i]);
496         frames[i] = NULL;
497         if (ret < 0)
498             break;
499     }
500
501 fail:
502     for (i = 0; i < ctx->nb_outputs; i++)
503         av_frame_free(&frames[i]);
504     av_frame_free(&in);
505     s->input_frame = NULL;
506
507     return ret;
508 }
509
510 static av_cold void uninit(AVFilterContext *ctx)
511 {
512     AudioCrossoverContext *s = ctx->priv;
513     int i;
514
515     av_freep(&s->fdsp);
516     av_freep(&s->splits);
517     av_frame_free(&s->xover);
518
519     for (i = 0; i < ctx->nb_outputs; i++)
520         av_freep(&ctx->output_pads[i].name);
521 }
522
523 static const AVFilterPad inputs[] = {
524     {
525         .name         = "default",
526         .type         = AVMEDIA_TYPE_AUDIO,
527         .filter_frame = filter_frame,
528         .config_props = config_input,
529     },
530     { NULL }
531 };
532
533 AVFilter ff_af_acrossover = {
534     .name           = "acrossover",
535     .description    = NULL_IF_CONFIG_SMALL("Split audio into per-bands streams."),
536     .priv_size      = sizeof(AudioCrossoverContext),
537     .priv_class     = &acrossover_class,
538     .init           = init,
539     .uninit         = uninit,
540     .query_formats  = query_formats,
541     .inputs         = inputs,
542     .outputs        = NULL,
543     .flags          = AVFILTER_FLAG_DYNAMIC_OUTPUTS |
544                       AVFILTER_FLAG_SLICE_THREADS,
545 };