FFmpeg
af_acrossover.c
Go to the documentation of this file.
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"
29 #include "libavutil/float_dsp.h"
30 #include "libavutil/internal.h"
31 #include "libavutil/mem.h"
32 #include "libavutil/opt.h"
33 
34 #include "audio.h"
35 #include "avfilter.h"
36 #include "filters.h"
37 #include "formats.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  char *gains_str;
58  int order_opt;
59  float level_in;
60  int precision;
61 
62  int order;
66  int nb_splits;
68 
69  float gains[MAX_BANDS];
70 
74 
76 
78 
79  int (*filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
80 
83 
84 #define OFFSET(x) offsetof(AudioCrossoverContext, x)
85 #define AF AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
86 
87 static const AVOption acrossover_options[] = {
88  { "split", "set split frequencies", OFFSET(splits_str), AV_OPT_TYPE_STRING, {.str="500"}, 0, 0, AF },
89  { "order", "set filter order", OFFSET(order_opt), AV_OPT_TYPE_INT, {.i64=1}, 0, 9, AF, .unit = "m" },
90  { "2nd", "2nd order (12 dB/8ve)", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, .unit = "m" },
91  { "4th", "4th order (24 dB/8ve)", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, .unit = "m" },
92  { "6th", "6th order (36 dB/8ve)", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, .unit = "m" },
93  { "8th", "8th order (48 dB/8ve)", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, .unit = "m" },
94  { "10th", "10th order (60 dB/8ve)",0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, AF, .unit = "m" },
95  { "12th", "12th order (72 dB/8ve)",0, AV_OPT_TYPE_CONST, {.i64=5}, 0, 0, AF, .unit = "m" },
96  { "14th", "14th order (84 dB/8ve)",0, AV_OPT_TYPE_CONST, {.i64=6}, 0, 0, AF, .unit = "m" },
97  { "16th", "16th order (96 dB/8ve)",0, AV_OPT_TYPE_CONST, {.i64=7}, 0, 0, AF, .unit = "m" },
98  { "18th", "18th order (108 dB/8ve)",0, AV_OPT_TYPE_CONST, {.i64=8}, 0, 0, AF, .unit = "m" },
99  { "20th", "20th order (120 dB/8ve)",0, AV_OPT_TYPE_CONST, {.i64=9}, 0, 0, AF, .unit = "m" },
100  { "level", "set input gain", OFFSET(level_in), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, AF },
101  { "gain", "set output bands gain", OFFSET(gains_str), AV_OPT_TYPE_STRING, {.str="1.f"}, 0, 0, AF },
102  { "precision", "set processing precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, AF, .unit = "precision" },
103  { "auto", "set auto processing precision", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, .unit = "precision" },
104  { "float", "set single-floating point processing precision", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, .unit = "precision" },
105  { "double","set double-floating point processing precision", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, .unit = "precision" },
106  { NULL }
107 };
108 
109 AVFILTER_DEFINE_CLASS(acrossover);
110 
112  AVFilterFormatsConfig **cfg_in,
113  AVFilterFormatsConfig **cfg_out)
114 {
115  const AudioCrossoverContext *s = ctx->priv;
116  static const enum AVSampleFormat auto_sample_fmts[] = {
120  };
121  enum AVSampleFormat sample_fmts[] = {
124  };
125  const enum AVSampleFormat *sample_fmts_list = sample_fmts;
126  int ret;
127 
128  switch (s->precision) {
129  case 0:
130  sample_fmts_list = auto_sample_fmts;
131  break;
132  case 1:
134  break;
135  case 2:
137  break;
138  default:
139  break;
140  }
141  ret = ff_set_common_formats_from_list2(ctx, cfg_in, cfg_out, sample_fmts_list);
142  if (ret < 0)
143  return ret;
144 
145  return 0;
146 }
147 
149 {
150  AudioCrossoverContext *s = ctx->priv;
151  char *p, *arg, *saveptr = NULL;
152  int i, ret = 0;
153 
154  saveptr = NULL;
155  p = s->gains_str;
156  for (i = 0; i < MAX_BANDS; i++) {
157  float gain;
158  char c[3] = { 0 };
159 
160  if (!(arg = av_strtok(p, " |", &saveptr)))
161  break;
162 
163  p = NULL;
164 
165  if (av_sscanf(arg, "%f%2s", &gain, c) < 1) {
166  av_log(ctx, AV_LOG_ERROR, "Invalid syntax for gain[%d].\n", i);
167  ret = AVERROR(EINVAL);
168  break;
169  }
170 
171  if (c[0] == 'd' && c[1] == 'B')
172  s->gains[i] = expf(gain * M_LN10 / 20.f);
173  else
174  s->gains[i] = gain;
175  }
176 
177  for (; i < MAX_BANDS; i++)
178  s->gains[i] = 1.f;
179 
180  return ret;
181 }
182 
184 {
185  AudioCrossoverContext *s = ctx->priv;
186  char *p, *arg, *saveptr = NULL;
187  int i, ret = 0;
188 
189  s->fdsp = avpriv_float_dsp_alloc(0);
190  if (!s->fdsp)
191  return AVERROR(ENOMEM);
192 
193  p = s->splits_str;
194  for (i = 0; i < MAX_SPLITS; i++) {
195  float freq;
196 
197  if (!(arg = av_strtok(p, " |", &saveptr)))
198  break;
199 
200  p = NULL;
201 
202  if (av_sscanf(arg, "%f", &freq) != 1) {
203  av_log(ctx, AV_LOG_ERROR, "Invalid syntax for frequency[%d].\n", i);
204  return AVERROR(EINVAL);
205  }
206  if (freq <= 0) {
207  av_log(ctx, AV_LOG_ERROR, "Frequency %f must be positive number.\n", freq);
208  return AVERROR(EINVAL);
209  }
210 
211  if (i > 0 && freq <= s->splits[i-1]) {
212  av_log(ctx, AV_LOG_ERROR, "Frequency %f must be in increasing order.\n", freq);
213  return AVERROR(EINVAL);
214  }
215 
216  s->splits[i] = freq;
217  }
218 
219  s->nb_splits = i;
220 
221  ret = parse_gains(ctx);
222  if (ret < 0)
223  return ret;
224 
225  for (i = 0; i <= s->nb_splits; i++) {
226  AVFilterPad pad = { 0 };
227  char *name;
228 
229  pad.type = AVMEDIA_TYPE_AUDIO;
230  name = av_asprintf("out%d", ctx->nb_outputs);
231  if (!name)
232  return AVERROR(ENOMEM);
233  pad.name = name;
234 
235  if ((ret = ff_append_outpad_free_name(ctx, &pad)) < 0)
236  return ret;
237  }
238 
239  return ret;
240 }
241 
242 static void set_lp(BiquadCoeffs *b, double fc, double q, double sr)
243 {
244  double omega = 2. * M_PI * fc / sr;
245  double cosine = cos(omega);
246  double alpha = sin(omega) / (2. * q);
247 
248  double b0 = (1. - cosine) / 2.;
249  double b1 = 1. - cosine;
250  double b2 = (1. - cosine) / 2.;
251  double a0 = 1. + alpha;
252  double a1 = -2. * cosine;
253  double a2 = 1. - alpha;
254 
255  b->cd[B0] = b0 / a0;
256  b->cd[B1] = b1 / a0;
257  b->cd[B2] = b2 / a0;
258  b->cd[A1] = -a1 / a0;
259  b->cd[A2] = -a2 / a0;
260 
261  b->cf[B0] = b->cd[B0];
262  b->cf[B1] = b->cd[B1];
263  b->cf[B2] = b->cd[B2];
264  b->cf[A1] = b->cd[A1];
265  b->cf[A2] = b->cd[A2];
266 }
267 
268 static void set_hp(BiquadCoeffs *b, double fc, double q, double sr)
269 {
270  double omega = 2. * M_PI * fc / sr;
271  double cosine = cos(omega);
272  double alpha = sin(omega) / (2. * q);
273 
274  double b0 = (1. + cosine) / 2.;
275  double b1 = -1. - cosine;
276  double b2 = (1. + cosine) / 2.;
277  double a0 = 1. + alpha;
278  double a1 = -2. * cosine;
279  double a2 = 1. - alpha;
280 
281  b->cd[B0] = b0 / a0;
282  b->cd[B1] = b1 / a0;
283  b->cd[B2] = b2 / a0;
284  b->cd[A1] = -a1 / a0;
285  b->cd[A2] = -a2 / a0;
286 
287  b->cf[B0] = b->cd[B0];
288  b->cf[B1] = b->cd[B1];
289  b->cf[B2] = b->cd[B2];
290  b->cf[A1] = b->cd[A1];
291  b->cf[A2] = b->cd[A2];
292 }
293 
294 static void set_ap(BiquadCoeffs *b, double fc, double q, double sr)
295 {
296  double omega = 2. * M_PI * fc / sr;
297  double cosine = cos(omega);
298  double alpha = sin(omega) / (2. * q);
299 
300  double a0 = 1. + alpha;
301  double a1 = -2. * cosine;
302  double a2 = 1. - alpha;
303  double b0 = a2;
304  double b1 = a1;
305  double b2 = a0;
306 
307  b->cd[B0] = b0 / a0;
308  b->cd[B1] = b1 / a0;
309  b->cd[B2] = b2 / a0;
310  b->cd[A1] = -a1 / a0;
311  b->cd[A2] = -a2 / a0;
312 
313  b->cf[B0] = b->cd[B0];
314  b->cf[B1] = b->cd[B1];
315  b->cf[B2] = b->cd[B2];
316  b->cf[A1] = b->cd[A1];
317  b->cf[A2] = b->cd[A2];
318 }
319 
320 static void set_ap1(BiquadCoeffs *b, double fc, double sr)
321 {
322  double omega = 2. * M_PI * fc / sr;
323 
324  b->cd[A1] = exp(-omega);
325  b->cd[A2] = 0.;
326  b->cd[B0] = -b->cd[A1];
327  b->cd[B1] = 1.;
328  b->cd[B2] = 0.;
329 
330  b->cf[B0] = b->cd[B0];
331  b->cf[B1] = b->cd[B1];
332  b->cf[B2] = b->cd[B2];
333  b->cf[A1] = b->cd[A1];
334  b->cf[A2] = b->cd[A2];
335 }
336 
337 static void calc_q_factors(int order, double *q)
338 {
339  double n = order / 2.;
340 
341  for (int i = 0; i < n / 2; i++)
342  q[i] = 1. / (-2. * cos(M_PI * (2. * (i + 1) + n - 1.) / (2. * n)));
343 }
344 
345 #define BIQUAD_PROCESS(name, type) \
346 static void biquad_process_## name(const type *const c, \
347  type *b, \
348  type *dst, const type *src, \
349  int nb_samples) \
350 { \
351  const type b0 = c[B0]; \
352  const type b1 = c[B1]; \
353  const type b2 = c[B2]; \
354  const type a1 = c[A1]; \
355  const type a2 = c[A2]; \
356  type z1 = b[0]; \
357  type z2 = b[1]; \
358  \
359  for (int n = 0; n + 1 < nb_samples; n++) { \
360  type in = src[n]; \
361  type out; \
362  \
363  out = in * b0 + z1; \
364  z1 = b1 * in + z2 + a1 * out; \
365  z2 = b2 * in + a2 * out; \
366  dst[n] = out; \
367  \
368  n++; \
369  in = src[n]; \
370  out = in * b0 + z1; \
371  z1 = b1 * in + z2 + a1 * out; \
372  z2 = b2 * in + a2 * out; \
373  dst[n] = out; \
374  } \
375  \
376  if (nb_samples & 1) { \
377  const int n = nb_samples - 1; \
378  const type in = src[n]; \
379  type out; \
380  \
381  out = in * b0 + z1; \
382  z1 = b1 * in + z2 + a1 * out; \
383  z2 = b2 * in + a2 * out; \
384  dst[n] = out; \
385  } \
386  \
387  b[0] = z1; \
388  b[1] = z2; \
389 }
390 
391 BIQUAD_PROCESS(fltp, float)
392 BIQUAD_PROCESS(dblp, double)
393 
394 #define XOVER_PROCESS(name, type, one, ff) \
395 static int filter_channels_## name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
396 { \
397  AudioCrossoverContext *s = ctx->priv; \
398  AVFrame *in = arg; \
399  AVFrame **frames = s->frames; \
400  const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; \
401  const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; \
402  const int nb_samples = in->nb_samples; \
403  const int nb_outs = ctx->nb_outputs; \
404  const int first_order = s->first_order; \
405  \
406  for (int ch = start; ch < end; ch++) { \
407  const type *src = (const type *)in->extended_data[ch]; \
408  type *xover = (type *)s->xover->extended_data[ch]; \
409  \
410  s->fdsp->vector_## ff ##mul_scalar((type *)frames[0]->extended_data[ch], src, \
411  s->level_in, FFALIGN(nb_samples, sizeof(type))); \
412  \
413  for (int band = 0; band < nb_outs; band++) { \
414  for (int f = 0; band + 1 < nb_outs && f < s->filter_count; f++) { \
415  const type *prv = (const type *)frames[band]->extended_data[ch]; \
416  type *dst = (type *)frames[band + 1]->extended_data[ch]; \
417  const type *hsrc = f == 0 ? prv : dst; \
418  type *hp = xover + nb_outs * 20 + band * 20 + f * 2; \
419  const type *const hpc = (type *)&s->hp[band][f].c ## ff; \
420  \
421  biquad_process_## name(hpc, hp, dst, hsrc, nb_samples); \
422  } \
423  \
424  for (int f = 0; band + 1 < nb_outs && f < s->filter_count; f++) { \
425  type *dst = (type *)frames[band]->extended_data[ch]; \
426  const type *lsrc = dst; \
427  type *lp = xover + band * 20 + f * 2; \
428  const type *const lpc = (type *)&s->lp[band][f].c ## ff; \
429  \
430  biquad_process_## name(lpc, lp, dst, lsrc, nb_samples); \
431  } \
432  \
433  for (int aband = band + 1; aband + 1 < nb_outs; aband++) { \
434  if (first_order) { \
435  const type *asrc = (const type *)frames[band]->extended_data[ch]; \
436  type *dst = (type *)frames[band]->extended_data[ch]; \
437  type *ap = xover + nb_outs * 40 + (aband * nb_outs + band) * 20; \
438  const type *const apc = (type *)&s->ap[aband][0].c ## ff; \
439  \
440  biquad_process_## name(apc, ap, dst, asrc, nb_samples); \
441  } \
442  \
443  for (int f = first_order; f < s->ap_filter_count; f++) { \
444  const type *asrc = (const type *)frames[band]->extended_data[ch]; \
445  type *dst = (type *)frames[band]->extended_data[ch]; \
446  type *ap = xover + nb_outs * 40 + (aband * nb_outs + band) * 20 + f * 2;\
447  const type *const apc = (type *)&s->ap[aband][f].c ## ff; \
448  \
449  biquad_process_## name(apc, ap, dst, asrc, nb_samples); \
450  } \
451  } \
452  } \
453  \
454  for (int band = 0; band < nb_outs; band++) { \
455  const type gain = s->gains[band] * ((band & 1 && first_order) ? -one : one); \
456  type *dst = (type *)frames[band]->extended_data[ch]; \
457  \
458  s->fdsp->vector_## ff ##mul_scalar(dst, dst, gain, \
459  FFALIGN(nb_samples, sizeof(type))); \
460  } \
461  } \
462  \
463  return 0; \
464 }
465 
466 XOVER_PROCESS(fltp, float, 1.f, f)
467 XOVER_PROCESS(dblp, double, 1.0, d)
468 
470 {
471  AVFilterContext *ctx = inlink->dst;
472  AudioCrossoverContext *s = ctx->priv;
473  int sample_rate = inlink->sample_rate;
474  double q[16];
475 
476  s->order = (s->order_opt + 1) * 2;
477  s->filter_count = s->order / 2;
478  s->first_order = s->filter_count & 1;
479  s->ap_filter_count = s->filter_count / 2 + s->first_order;
480  calc_q_factors(s->order, q);
481 
482  for (int band = 0; band <= s->nb_splits; band++) {
483  if (s->first_order) {
484  set_lp(&s->lp[band][0], s->splits[band], 0.5, sample_rate);
485  set_hp(&s->hp[band][0], s->splits[band], 0.5, sample_rate);
486  }
487 
488  for (int n = s->first_order; n < s->filter_count; n++) {
489  const int idx = s->filter_count / 2 - ((n + s->first_order) / 2 - s->first_order) - 1;
490 
491  set_lp(&s->lp[band][n], s->splits[band], q[idx], sample_rate);
492  set_hp(&s->hp[band][n], s->splits[band], q[idx], sample_rate);
493  }
494 
495  if (s->first_order)
496  set_ap1(&s->ap[band][0], s->splits[band], sample_rate);
497 
498  for (int n = s->first_order; n < s->ap_filter_count; n++) {
499  const int idx = (s->filter_count / 2 - ((n * 2 + s->first_order) / 2 - s->first_order) - 1);
500 
501  set_ap(&s->ap[band][n], s->splits[band], q[idx], sample_rate);
502  }
503  }
504 
505  switch (inlink->format) {
506  case AV_SAMPLE_FMT_FLTP: s->filter_channels = filter_channels_fltp; break;
507  case AV_SAMPLE_FMT_DBLP: s->filter_channels = filter_channels_dblp; break;
508  default: return AVERROR_BUG;
509  }
510 
511  s->xover = ff_get_audio_buffer(inlink, 2 * (ctx->nb_outputs * 10 + ctx->nb_outputs * 10 +
512  ctx->nb_outputs * ctx->nb_outputs * 10));
513  if (!s->xover)
514  return AVERROR(ENOMEM);
515 
516  return 0;
517 }
518 
520 {
521  AVFilterContext *ctx = inlink->dst;
522  AudioCrossoverContext *s = ctx->priv;
523  AVFrame **frames = s->frames;
524  int ret = 0;
525 
526  for (int i = 0; i < ctx->nb_outputs; i++) {
527  frames[i] = ff_get_audio_buffer(ctx->outputs[i], in->nb_samples);
528  if (!frames[i]) {
529  ret = AVERROR(ENOMEM);
530  break;
531  }
532 
533  frames[i]->pts = in->pts;
534  }
535 
536  if (ret < 0)
537  goto fail;
538 
539  ff_filter_execute(ctx, s->filter_channels, in, NULL,
540  FFMIN(inlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx)));
541 
542  for (int i = 0; i < ctx->nb_outputs; i++) {
543  if (ff_outlink_get_status(ctx->outputs[i])) {
545  continue;
546  }
547 
548  ret = ff_filter_frame(ctx->outputs[i], frames[i]);
549  frames[i] = NULL;
550  if (ret < 0)
551  break;
552  }
553 
554 fail:
555  for (int i = 0; i < ctx->nb_outputs; i++)
557 
558  return ret;
559 }
560 
562 {
563  AVFilterLink *inlink = ctx->inputs[0];
564  int status, ret;
565  AVFrame *in;
566  int64_t pts;
567 
568  for (int i = 0; i < ctx->nb_outputs; i++) {
570  }
571 
573  if (ret < 0)
574  return ret;
575  if (ret > 0) {
576  ret = filter_frame(inlink, in);
577  av_frame_free(&in);
578  if (ret < 0)
579  return ret;
580  }
581 
583  for (int i = 0; i < ctx->nb_outputs; i++) {
584  if (ff_outlink_get_status(ctx->outputs[i]))
585  continue;
586  ff_outlink_set_status(ctx->outputs[i], status, pts);
587  }
588  return 0;
589  }
590 
591  for (int i = 0; i < ctx->nb_outputs; i++) {
592  if (ff_outlink_get_status(ctx->outputs[i]))
593  continue;
594 
595  if (ff_outlink_frame_wanted(ctx->outputs[i])) {
597  return 0;
598  }
599  }
600 
601  return FFERROR_NOT_READY;
602 }
603 
605 {
606  AudioCrossoverContext *s = ctx->priv;
607 
608  av_freep(&s->fdsp);
609  av_frame_free(&s->xover);
610 }
611 
612 static const AVFilterPad inputs[] = {
613  {
614  .name = "default",
615  .type = AVMEDIA_TYPE_AUDIO,
616  .config_props = config_input,
617  },
618 };
619 
621  .name = "acrossover",
622  .description = NULL_IF_CONFIG_SMALL("Split audio into per-bands streams."),
623  .priv_size = sizeof(AudioCrossoverContext),
624  .priv_class = &acrossover_class,
625  .init = init,
626  .activate = activate,
627  .uninit = uninit,
629  .outputs = NULL,
633 };
ff_get_audio_buffer
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Definition: audio.c:98
AV_SAMPLE_FMT_FLTP
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition: samplefmt.h:66
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
OFFSET
#define OFFSET(x)
Definition: af_acrossover.c:84
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
BiquadCoeffs::cf
float cf[5]
Definition: af_acrossover.c:50
AudioCrossoverContext::lp
BiquadCoeffs lp[MAX_BANDS][20]
Definition: af_acrossover.c:71
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1062
sample_fmts
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:948
FFERROR_NOT_READY
return FFERROR_NOT_READY
Definition: filter_design.txt:204
int64_t
long long int64_t
Definition: coverity.c:34
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
av_asprintf
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:115
AudioCrossoverContext::hp
BiquadCoeffs hp[MAX_BANDS][20]
Definition: af_acrossover.c:72
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:162
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: filters.h:262
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:389
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:501
AVOption
AVOption.
Definition: opt.h:429
b
#define b
Definition: input.c:41
MAX_SPLITS
#define MAX_SPLITS
Definition: af_acrossover.c:39
expf
#define expf(x)
Definition: libm.h:283
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(acrossover)
fc
#define fc(width, name, range_min, range_max)
Definition: cbs_av1.c:472
B2
#define B2
Definition: af_acrossover.c:44
BIQUAD_PROCESS
#define BIQUAD_PROCESS(name, type)
Definition: af_acrossover.c:345
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:205
AudioCrossoverContext::frames
AVFrame * frames[MAX_BANDS]
Definition: af_acrossover.c:77
AudioCrossoverContext::filter_channels
int(* filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: af_acrossover.c:79
formats.h
AF
#define AF
Definition: af_acrossover.c:85
BiquadCoeffs
Definition: af_acrossover.c:48
ff_inlink_consume_frame
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
Definition: avfilter.c:1491
FF_FILTER_FORWARD_STATUS_BACK_ALL
#define FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, filter)
Forward the status on an output link to all input links.
Definition: filters.h:447
b1
static double b1(void *priv, double x, double y)
Definition: vf_xfade.c:2034
acrossover_options
static const AVOption acrossover_options[]
Definition: af_acrossover.c:87
fail
#define fail()
Definition: checkasm.h:188
frames
if it could not because there are no more frames
Definition: filter_design.txt:266
AudioCrossoverContext::xover
AVFrame * xover
Definition: af_acrossover.c:75
parse_gains
static int parse_gains(AVFilterContext *ctx)
Definition: af_acrossover.c:148
pts
static int64_t pts
Definition: transcode_aac.c:644
a2
static double a2(void *priv, double x, double y)
Definition: vf_xfade.c:2030
set_hp
static void set_hp(BiquadCoeffs *b, double fc, double q, double sr)
Definition: af_acrossover.c:268
AudioCrossoverContext
Definition: af_acrossover.c:53
AVFilterPad
A filter pad used for either input or output.
Definition: filters.h:38
B1
#define B1
Definition: af_acrossover.c:43
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
av_cold
#define av_cold
Definition: attributes.h:90
ff_outlink_set_status
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
Definition: filters.h:424
ff_inlink_request_frame
void ff_inlink_request_frame(AVFilterLink *link)
Mark that a frame is wanted on the link.
Definition: avfilter.c:1594
s
#define s(width, name)
Definition: cbs_vp9.c:198
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
av_strtok
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
Definition: avstring.c:178
filters.h
ff_af_acrossover
const AVFilter ff_af_acrossover
Definition: af_acrossover.c:620
AudioCrossoverContext::first_order
int first_order
Definition: af_acrossover.c:64
ctx
AVFormatContext * ctx
Definition: movenc.c:49
A2
#define A2
Definition: af_acrossover.c:46
arg
const char * arg
Definition: jacosubdec.c:67
av_sscanf
int av_sscanf(const char *string, const char *format,...)
See libc sscanf manual for more information.
Definition: avsscanf.c:961
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
NULL
#define NULL
Definition: coverity.c:32
B0
#define B0
Definition: af_acrossover.c:42
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: af_acrossover.c:519
AudioCrossoverContext::nb_splits
int nb_splits
Definition: af_acrossover.c:66
exp
int8_t exp
Definition: eval.c:73
ff_inlink_acknowledge_status
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
Definition: avfilter.c:1438
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
AVFilterFormatsConfig
Lists of formats / etc.
Definition: avfilter.h:111
AudioCrossoverContext::ap
BiquadCoeffs ap[MAX_BANDS][20]
Definition: af_acrossover.c:73
float_dsp.h
AVFILTER_FLAG_DYNAMIC_OUTPUTS
#define AVFILTER_FLAG_DYNAMIC_OUTPUTS
The number of the filter outputs is not determined just by AVFilter.outputs.
Definition: avfilter.h:147
f
f
Definition: af_crystalizer.c:122
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:94
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: af_acrossover.c:604
AV_SAMPLE_FMT_NONE
@ AV_SAMPLE_FMT_NONE
Definition: samplefmt.h:56
AudioCrossoverContext::splits
float splits[MAX_SPLITS]
Definition: af_acrossover.c:67
AVFloatDSPContext
Definition: float_dsp.h:24
b2
static double b2(void *priv, double x, double y)
Definition: vf_xfade.c:2035
a0
static double a0(void *priv, double x, double y)
Definition: vf_xfade.c:2028
calc_q_factors
static void calc_q_factors(int order, double *q)
Definition: af_acrossover.c:337
attributes.h
AudioCrossoverContext::order
int order
Definition: af_acrossover.c:62
M_PI
#define M_PI
Definition: mathematics.h:67
AV_OPT_TYPE_FLOAT
@ AV_OPT_TYPE_FLOAT
Underlying C type is float.
Definition: opt.h:271
AVFrame::nb_samples
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:469
AudioCrossoverContext::filter_count
int filter_count
Definition: af_acrossover.c:63
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
internal.h
ff_filter_get_nb_threads
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:841
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:55
query_formats
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition: af_acrossover.c:111
FILTER_QUERY_FUNC2
#define FILTER_QUERY_FUNC2(func)
Definition: filters.h:239
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
AVFilterPad::name
const char * name
Pad name.
Definition: filters.h:44
set_lp
static void set_lp(BiquadCoeffs *b, double fc, double q, double sr)
Definition: af_acrossover.c:242
inputs
static const AVFilterPad inputs[]
Definition: af_acrossover.c:612
AudioCrossoverContext::ap_filter_count
int ap_filter_count
Definition: af_acrossover.c:65
AVFilter
Filter definition.
Definition: avfilter.h:201
set_ap
static void set_ap(BiquadCoeffs *b, double fc, double q, double sr)
Definition: af_acrossover.c:294
ret
ret
Definition: filter_design.txt:187
AVFilterPad::type
enum AVMediaType type
AVFilterPad type.
Definition: filters.h:49
set_ap1
static void set_ap1(BiquadCoeffs *b, double fc, double sr)
Definition: af_acrossover.c:320
AudioCrossoverContext::gains_str
char * gains_str
Definition: af_acrossover.c:57
status
ov_status_e status
Definition: dnn_backend_openvino.c:100
init
static av_cold int init(AVFilterContext *ctx)
Definition: af_acrossover.c:183
ff_set_common_formats_from_list2
int ff_set_common_formats_from_list2(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out, const int *fmts)
Definition: formats.c:1016
channel_layout.h
ff_filter_execute
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition: avfilter.c:1667
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
avfilter.h
MAX_BANDS
#define MAX_BANDS
Definition: af_acrossover.c:40
AudioCrossoverContext::fdsp
AVFloatDSPContext * fdsp
Definition: af_acrossover.c:81
AV_SAMPLE_FMT_DBLP
@ AV_SAMPLE_FMT_DBLP
double, planar
Definition: samplefmt.h:67
activate
static int activate(AVFilterContext *ctx)
Definition: af_acrossover.c:561
ff_outlink_get_status
int ff_outlink_get_status(AVFilterLink *link)
Get the status on an output link.
Definition: avfilter.c:1619
AVFilterContext
An instance of a filter.
Definition: avfilter.h:457
AVFILTER_FLAG_SLICE_THREADS
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:152
A1
#define A1
Definition: af_acrossover.c:45
AudioCrossoverContext::gains
float gains[MAX_BANDS]
Definition: af_acrossover.c:69
mem.h
audio.h
M_LN10
#define M_LN10
Definition: mathematics.h:49
config_input
static int config_input(AVFilterLink *inlink)
Definition: af_acrossover.c:469
alpha
static const int16_t alpha[]
Definition: ilbcdata.h:55
ff_append_outpad_free_name
int ff_append_outpad_free_name(AVFilterContext *f, AVFilterPad *p)
Definition: avfilter.c:143
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
avpriv_float_dsp_alloc
av_cold AVFloatDSPContext * avpriv_float_dsp_alloc(int bit_exact)
Allocate a float DSP context.
Definition: float_dsp.c:146
XOVER_PROCESS
#define XOVER_PROCESS(name, type, one, ff)
Definition: af_acrossover.c:394
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:52
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AudioCrossoverContext::precision
int precision
Definition: af_acrossover.c:60
AudioCrossoverContext::level_in
float level_in
Definition: af_acrossover.c:59
b0
static double b0(void *priv, double x, double y)
Definition: vf_xfade.c:2033
a1
static double a1(void *priv, double x, double y)
Definition: vf_xfade.c:2029
ff_outlink_frame_wanted
the definition of that something depends on the semantic of the filter The callback must examine the status of the filter s links and proceed accordingly The status of output links is stored in the status_in and status_out fields and tested by the ff_outlink_frame_wanted() function. If this function returns true
AudioCrossoverContext::order_opt
int order_opt
Definition: af_acrossover.c:58
BiquadCoeffs::cd
double cd[5]
Definition: af_acrossover.c:49
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:276
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition: opt.h:299
AudioCrossoverContext::splits_str
char * splits_str
Definition: af_acrossover.c:56