FFmpeg
asrc_afirsrc.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Paul B Mahol
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License
8  * as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "libavutil/cpu.h"
23 #include "libavutil/ffmath.h"
24 #include "libavutil/eval.h"
25 #include "libavutil/opt.h"
26 #include "libavutil/tx.h"
27 #include "audio.h"
28 #include "avfilter.h"
29 #include "filters.h"
30 #include "formats.h"
31 #include "internal.h"
32 #include "window_func.h"
33 
34 typedef struct AudioFIRSourceContext {
35  const AVClass *class;
36 
39  char *phase_str;
40  int nb_taps;
43  int win_func;
44  int preset;
45  int interp;
46  int phaset;
47 
49  float *freq;
50  float *magnitude;
51  float *phase;
52  int freq_size;
55  int nb_freq;
57  int nb_phase;
58 
59  float *taps;
60  float *win;
61  int64_t pts;
62 
66 
67 #define OFFSET(x) offsetof(AudioFIRSourceContext, x)
68 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
69 
70 static const AVOption afirsrc_options[] = {
71  { "taps", "set number of taps", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=1025}, 9, UINT16_MAX, FLAGS },
72  { "t", "set number of taps", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=1025}, 9, UINT16_MAX, FLAGS },
73  { "frequency", "set frequency points", OFFSET(freq_points_str), AV_OPT_TYPE_STRING, {.str="0 1"}, 0, 0, FLAGS },
74  { "f", "set frequency points", OFFSET(freq_points_str), AV_OPT_TYPE_STRING, {.str="0 1"}, 0, 0, FLAGS },
75  { "magnitude", "set magnitude values", OFFSET(magnitude_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, FLAGS },
76  { "m", "set magnitude values", OFFSET(magnitude_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, FLAGS },
77  { "phase", "set phase values", OFFSET(phase_str), AV_OPT_TYPE_STRING, {.str="0 0"}, 0, 0, FLAGS },
78  { "p", "set phase values", OFFSET(phase_str), AV_OPT_TYPE_STRING, {.str="0 0"}, 0, 0, FLAGS },
79  { "sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, FLAGS },
80  { "r", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, FLAGS },
81  { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS },
82  { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS },
83  WIN_FUNC_OPTION("win_func", OFFSET(win_func), FLAGS, WFUNC_BLACKMAN),
84  WIN_FUNC_OPTION("w", OFFSET(win_func), FLAGS, WFUNC_BLACKMAN),
85  {NULL}
86 };
87 
88 AVFILTER_DEFINE_CLASS(afirsrc);
89 
91 {
92  AudioFIRSourceContext *s = ctx->priv;
93 
94  if (!(s->nb_taps & 1)) {
95  av_log(s, AV_LOG_WARNING, "Number of taps %d must be odd length.\n", s->nb_taps);
96  s->nb_taps |= 1;
97  }
98 
99  return 0;
100 }
101 
103 {
104  AudioFIRSourceContext *s = ctx->priv;
105 
106  av_freep(&s->win);
107  av_freep(&s->taps);
108  av_freep(&s->freq);
109  av_freep(&s->magnitude);
110  av_freep(&s->phase);
111  av_freep(&s->complexf);
112  av_tx_uninit(&s->tx_ctx);
113  av_tx_uninit(&s->itx_ctx);
114 }
115 
117 {
118  AudioFIRSourceContext *s = ctx->priv;
119  static const AVChannelLayout chlayouts[] = { AV_CHANNEL_LAYOUT_MONO, { 0 } };
120  int sample_rates[] = { s->sample_rate, -1 };
121  static const enum AVSampleFormat sample_fmts[] = {
124  };
126  if (ret < 0)
127  return ret;
128 
130  if (ret < 0)
131  return ret;
132 
134 }
135 
136 static int parse_string(char *str, float **items, int *nb_items, int *items_size)
137 {
138  float *new_items;
139  char *tail;
140 
141  new_items = av_fast_realloc(NULL, items_size, sizeof(float));
142  if (!new_items)
143  return AVERROR(ENOMEM);
144  *items = new_items;
145 
146  tail = str;
147  if (!tail)
148  return AVERROR(EINVAL);
149 
150  do {
151  (*items)[(*nb_items)++] = av_strtod(tail, &tail);
152  new_items = av_fast_realloc(*items, items_size, (*nb_items + 2) * sizeof(float));
153  if (!new_items)
154  return AVERROR(ENOMEM);
155  *items = new_items;
156  if (tail && *tail)
157  tail++;
158  } while (tail && *tail);
159 
160  return 0;
161 }
162 
163 static void lininterp(AVComplexFloat *complexf,
164  const float *freq,
165  const float *magnitude,
166  const float *phase,
167  int m, int minterp)
168 {
169  for (int i = 0; i < minterp; i++) {
170  for (int j = 1; j < m; j++) {
171  const float x = i / (float)minterp;
172 
173  if (x <= freq[j]) {
174  const float mg = (x - freq[j-1]) / (freq[j] - freq[j-1]) * (magnitude[j] - magnitude[j-1]) + magnitude[j-1];
175  const float ph = (x - freq[j-1]) / (freq[j] - freq[j-1]) * (phase[j] - phase[j-1]) + phase[j-1];
176 
177  complexf[i].re = mg * cosf(ph);
178  complexf[i].im = mg * sinf(ph);
179  break;
180  }
181  }
182  }
183 }
184 
185 static av_cold int config_output(AVFilterLink *outlink)
186 {
187  AVFilterContext *ctx = outlink->src;
188  AudioFIRSourceContext *s = ctx->priv;
189  float overlap, scale = 1.f, compensation;
190  int fft_size, middle, ret;
191 
192  s->nb_freq = s->nb_magnitude = s->nb_phase = 0;
193 
194  ret = parse_string(s->freq_points_str, &s->freq, &s->nb_freq, &s->freq_size);
195  if (ret < 0)
196  return ret;
197 
198  ret = parse_string(s->magnitude_str, &s->magnitude, &s->nb_magnitude, &s->magnitude_size);
199  if (ret < 0)
200  return ret;
201 
202  ret = parse_string(s->phase_str, &s->phase, &s->nb_phase, &s->phase_size);
203  if (ret < 0)
204  return ret;
205 
206  if (s->nb_freq != s->nb_magnitude && s->nb_freq != s->nb_phase && s->nb_freq >= 2) {
207  av_log(ctx, AV_LOG_ERROR, "Number of frequencies, magnitudes and phases must be same and >= 2.\n");
208  return AVERROR(EINVAL);
209  }
210 
211  for (int i = 0; i < s->nb_freq; i++) {
212  if (i == 0 && s->freq[i] != 0.f) {
213  av_log(ctx, AV_LOG_ERROR, "First frequency must be 0.\n");
214  return AVERROR(EINVAL);
215  }
216 
217  if (i == s->nb_freq - 1 && s->freq[i] != 1.f) {
218  av_log(ctx, AV_LOG_ERROR, "Last frequency must be 1.\n");
219  return AVERROR(EINVAL);
220  }
221 
222  if (i && s->freq[i] < s->freq[i-1]) {
223  av_log(ctx, AV_LOG_ERROR, "Frequencies must be in increasing order.\n");
224  return AVERROR(EINVAL);
225  }
226  }
227 
228  fft_size = 1 << (av_log2(s->nb_taps) + 1);
229  s->complexf = av_calloc(fft_size * 2, sizeof(*s->complexf));
230  if (!s->complexf)
231  return AVERROR(ENOMEM);
232 
233  ret = av_tx_init(&s->tx_ctx, &s->tx_fn, AV_TX_FLOAT_FFT, 1, fft_size, &scale, 0);
234  if (ret < 0)
235  return ret;
236 
237  s->taps = av_calloc(s->nb_taps, sizeof(*s->taps));
238  if (!s->taps)
239  return AVERROR(ENOMEM);
240 
241  s->win = av_calloc(s->nb_taps, sizeof(*s->win));
242  if (!s->win)
243  return AVERROR(ENOMEM);
244 
245  generate_window_func(s->win, s->nb_taps, s->win_func, &overlap);
246 
247  lininterp(s->complexf, s->freq, s->magnitude, s->phase, s->nb_freq, fft_size / 2);
248 
249  s->tx_fn(s->tx_ctx, s->complexf + fft_size, s->complexf, sizeof(*s->complexf));
250 
251  compensation = 2.f / fft_size;
252  middle = s->nb_taps / 2;
253 
254  for (int i = 0; i <= middle; i++) {
255  s->taps[ i] = s->complexf[fft_size + middle - i].re * compensation * s->win[i];
256  s->taps[middle + i] = s->complexf[fft_size + i].re * compensation * s->win[middle + i];
257  }
258 
259  s->pts = 0;
260 
261  return 0;
262 }
263 
265 {
266  AVFilterLink *outlink = ctx->outputs[0];
267  AudioFIRSourceContext *s = ctx->priv;
268  AVFrame *frame;
269  int nb_samples;
270 
271  if (!ff_outlink_frame_wanted(outlink))
272  return FFERROR_NOT_READY;
273 
274  nb_samples = FFMIN(s->nb_samples, s->nb_taps - s->pts);
275  if (nb_samples <= 0) {
276  ff_outlink_set_status(outlink, AVERROR_EOF, s->pts);
277  return 0;
278  }
279 
280  if (!(frame = ff_get_audio_buffer(outlink, nb_samples)))
281  return AVERROR(ENOMEM);
282 
283  memcpy(frame->data[0], s->taps + s->pts, nb_samples * sizeof(float));
284 
285  frame->pts = s->pts;
286  s->pts += nb_samples;
287  return ff_filter_frame(outlink, frame);
288 }
289 
290 static const AVFilterPad afirsrc_outputs[] = {
291  {
292  .name = "default",
293  .type = AVMEDIA_TYPE_AUDIO,
294  .config_props = config_output,
295  },
296 };
297 
299  .name = "afirsrc",
300  .description = NULL_IF_CONFIG_SMALL("Generate a FIR coefficients audio stream."),
301  .init = init,
302  .uninit = uninit,
303  .activate = activate,
304  .priv_size = sizeof(AudioFIRSourceContext),
305  .inputs = NULL,
308  .priv_class = &afirsrc_class,
309 };
310 
311 #define DEFAULT_BANDS "25 40 63 100 160 250 400 630 1000 1600 2500 4000 6300 10000 16000 24000"
312 
313 typedef struct EqPreset {
314  char name[16];
315  float gains[16];
316 } EqPreset;
317 
318 static const EqPreset eq_presets[] = {
319  { "flat", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
320  { "acoustic", { 5.0, 4.5, 4.0, 3.5, 1.5, 1.0, 1.5, 1.5, 2.0, 3.0, 3.5, 4.0, 3.7, 3.0, 3.0 } },
321  { "bass", { 10.0, 8.8, 8.5, 6.5, 2.5, 1.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
322  { "beats", { -5.5, -5.0, -4.5, -4.2, -3.5, -3.0, -1.9, 0, 0, 0, 0, 0, 0, 0, 0 } },
323  { "classic", { -0.3, 0.3, -3.5, -9.0, -1.0, 0.0, 1.8, 2.1, 0.0, 0.0, 0.0, 4.4, 9.0, 9.0, 9.0 } },
324  { "clear", { 3.5, 5.5, 6.5, 9.5, 8.0, 6.5, 3.5, 2.5, 1.3, 5.0, 7.0, 9.0, 10.0, 11.0, 9.0 } },
325  { "deep bass", { 12.0, 8.0, 0.0, -6.7, -12.0, -9.0, -3.5, -3.5, -6.1, 0.0, -3.0, -5.0, 0.0, 1.2, 3.0 } },
326  { "dubstep", { 12.0, 10.0, 0.5, -1.0, -3.0, -5.0, -5.0, -4.8, -4.5, -2.5, -1.0, 0.0, -2.5, -2.5, 0.0 } },
327  { "electronic", { 4.0, 4.0, 3.5, 1.0, 0.0, -0.5, -2.0, 0.0, 2.0, 0.0, 0.0, 1.0, 3.0, 4.0, 4.5 } },
328  { "hardstyle", { 6.1, 7.0, 12.0, 6.1, -5.0, -12.0, -2.5, 3.0, 6.5, 0.0, -2.2, -4.5, -6.1, -9.2, -10.0 } },
329  { "hip-hop", { 4.5, 4.3, 4.0, 2.5, 1.5, 3.0, -1.0, -1.5, -1.5, 1.5, 0.0, -1.0, 0.0, 1.5, 3.0 } },
330  { "jazz", { 0.0, 0.0, 0.0, 2.0, 4.0, 5.9, -5.9, -4.5, -2.5, 2.5, 1.0, -0.8, -0.8, -0.8, -0.8 } },
331  { "metal", { 10.5, 10.5, 7.5, 0.0, 2.0, 5.5, 0.0, 0.0, 0.0, 6.1, 0.0, 0.0, 6.1, 10.0, 12.0 } },
332  { "movie", { 3.0, 3.0, 6.1, 8.5, 9.0, 7.0, 6.1, 6.1, 5.0, 8.0, 3.5, 3.5, 8.0, 10.0, 8.0 } },
333  { "pop", { 0.0, 0.0, 0.0, 0.0, 0.0, 1.3, 2.0, 2.5, 5.0, -1.5, -2.0, -3.0, -3.0, -3.0, -3.0 } },
334  { "r&b", { 3.0, 3.0, 7.0, 6.1, 4.5, 1.5, -1.5, -2.0, -1.5, 2.0, 2.5, 3.0, 3.5, 3.8, 4.0 } },
335  { "rock", { 0.0, 0.0, 0.0, 3.0, 3.0, -10.0, -4.0, -1.0, 0.8, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0 } },
336  { "vocal booster", { -1.5, -2.0, -3.0, -3.0, -0.5, 1.5, 3.5, 3.5, 3.5, 3.0, 2.0, 1.5, 0.0, 0.0, -1.5 } },
337 };
338 
339 static const AVOption afireqsrc_options[] = {
340  { "preset","set equalizer preset", OFFSET(preset), AV_OPT_TYPE_INT, {.i64=0}, -1, FF_ARRAY_ELEMS(eq_presets)-1, FLAGS, .unit = "preset" },
341  { "p", "set equalizer preset", OFFSET(preset), AV_OPT_TYPE_INT, {.i64=0}, -1, FF_ARRAY_ELEMS(eq_presets)-1, FLAGS, .unit = "preset" },
342  { "custom", NULL, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, .unit = "preset" },
343  { eq_presets[ 0].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 0}, 0, 0, FLAGS, .unit = "preset" },
344  { eq_presets[ 1].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 1}, 0, 0, FLAGS, .unit = "preset" },
345  { eq_presets[ 2].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 2}, 0, 0, FLAGS, .unit = "preset" },
346  { eq_presets[ 3].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 3}, 0, 0, FLAGS, .unit = "preset" },
347  { eq_presets[ 4].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 4}, 0, 0, FLAGS, .unit = "preset" },
348  { eq_presets[ 5].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 5}, 0, 0, FLAGS, .unit = "preset" },
349  { eq_presets[ 6].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 6}, 0, 0, FLAGS, .unit = "preset" },
350  { eq_presets[ 7].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 7}, 0, 0, FLAGS, .unit = "preset" },
351  { eq_presets[ 8].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 8}, 0, 0, FLAGS, .unit = "preset" },
352  { eq_presets[ 9].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 9}, 0, 0, FLAGS, .unit = "preset" },
353  { eq_presets[10].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=10}, 0, 0, FLAGS, .unit = "preset" },
354  { eq_presets[11].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=11}, 0, 0, FLAGS, .unit = "preset" },
355  { eq_presets[12].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=12}, 0, 0, FLAGS, .unit = "preset" },
356  { eq_presets[13].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=13}, 0, 0, FLAGS, .unit = "preset" },
357  { eq_presets[14].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=14}, 0, 0, FLAGS, .unit = "preset" },
358  { eq_presets[15].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=15}, 0, 0, FLAGS, .unit = "preset" },
359  { eq_presets[16].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=16}, 0, 0, FLAGS, .unit = "preset" },
360  { eq_presets[17].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=17}, 0, 0, FLAGS, .unit = "preset" },
361  { "gains", "set gain values per band", OFFSET(magnitude_str), AV_OPT_TYPE_STRING, {.str="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"}, 0, 0, FLAGS },
362  { "g", "set gain values per band", OFFSET(magnitude_str), AV_OPT_TYPE_STRING, {.str="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"}, 0, 0, FLAGS },
363  { "bands", "set central frequency values per band", OFFSET(freq_points_str), AV_OPT_TYPE_STRING, {.str=DEFAULT_BANDS}, 0, 0, FLAGS },
364  { "b", "set central frequency values per band", OFFSET(freq_points_str), AV_OPT_TYPE_STRING, {.str=DEFAULT_BANDS}, 0, 0, FLAGS },
365  { "taps", "set number of taps", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=4096}, 16, UINT16_MAX, FLAGS },
366  { "t", "set number of taps", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=4096}, 16, UINT16_MAX, FLAGS },
367  { "sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, FLAGS },
368  { "r", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, FLAGS },
369  { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS },
370  { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS },
371  { "interp","set the interpolation", OFFSET(interp), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, .unit = "interp" },
372  { "i", "set the interpolation", OFFSET(interp), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, .unit = "interp" },
373  { "linear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, .unit = "interp" },
374  { "cubic", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, .unit = "interp" },
375  { "phase","set the phase", OFFSET(phaset), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, .unit = "phase" },
376  { "h", "set the phase", OFFSET(phaset), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, .unit = "phase" },
377  { "linear", "linear phase", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, .unit = "phase" },
378  { "min", "minimum phase", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, .unit = "phase" },
379  {NULL}
380 };
381 
382 AVFILTER_DEFINE_CLASS(afireqsrc);
383 
384 static void eq_interp(AVComplexFloat *complexf,
385  const float *freq,
386  const float *magnitude,
387  int m, int interp, int minterp,
388  const float factor)
389 {
390  for (int i = 0; i < minterp; i++) {
391  for (int j = 0; j < m; j++) {
392  const float x = factor * i;
393 
394  if (x <= freq[j+1]) {
395  float g;
396 
397  if (interp == 0) {
398  const float d = freq[j+1] - freq[j];
399  const float d0 = x - freq[j];
400  const float d1 = freq[j+1] - x;
401  const float g0 = magnitude[j];
402  const float g1 = magnitude[j+1];
403 
404  if (d0 && d1) {
405  g = (d0 * g1 + d1 * g0) / d;
406  } else if (d0) {
407  g = g1;
408  } else {
409  g = g0;
410  }
411  } else {
412  if (x <= freq[j]) {
413  g = magnitude[j];
414  } else {
415  float x1, x2, x3;
416  float a, b, c, d;
417  float m0, m1, m2, msum;
418  const float unit = freq[j+1] - freq[j];
419 
420  m0 = j != 0 ? unit * (magnitude[j] - magnitude[j-1]) / (freq[j] - freq[j-1]) : 0;
421  m1 = magnitude[j+1] - magnitude[j];
422  m2 = j != minterp - 1 ? unit * (magnitude[j+2] - magnitude[j+1]) / (freq[j+2] - freq[j+1]) : 0;
423 
424  msum = fabsf(m0) + fabsf(m1);
425  m0 = msum > 0.f ? (fabsf(m0) * m1 + fabsf(m1) * m0) / msum : 0.f;
426  msum = fabsf(m1) + fabsf(m2);
427  m1 = msum > 0.f ? (fabsf(m1) * m2 + fabsf(m2) * m1) / msum : 0.f;
428 
429  d = magnitude[j];
430  c = m0;
431  b = 3.f * magnitude[j+1] - m1 - 2.f * c - 3.f * d;
432  a = magnitude[j+1] - b - c - d;
433 
434  x1 = (x - freq[j]) / unit;
435  x2 = x1 * x1;
436  x3 = x2 * x1;
437 
438  g = a * x3 + b * x2 + c * x1 + d;
439  }
440  }
441 
442  complexf[i].re = g;
443  complexf[i].im = 0;
444  complexf[minterp * 2 - i - 1].re = g;
445  complexf[minterp * 2 - i - 1].im = 0;
446 
447  break;
448  }
449  }
450  }
451 }
452 
454 {
455  AVFilterContext *ctx = outlink->src;
456  AudioFIRSourceContext *s = ctx->priv;
457  int fft_size, middle, asize, ret;
458  float scale, factor;
459 
460  s->nb_freq = s->nb_magnitude = 0;
461  if (s->preset < 0) {
462  ret = parse_string(s->freq_points_str, &s->freq, &s->nb_freq, &s->freq_size);
463  if (ret < 0)
464  return ret;
465 
466  ret = parse_string(s->magnitude_str, &s->magnitude, &s->nb_magnitude, &s->magnitude_size);
467  if (ret < 0)
468  return ret;
469  } else {
470  char *freq_str;
471 
472  s->nb_magnitude = FF_ARRAY_ELEMS(eq_presets[s->preset].gains);
473 
474  freq_str = av_strdup(DEFAULT_BANDS);
475  if (!freq_str)
476  return AVERROR(ENOMEM);
477 
478  ret = parse_string(freq_str, &s->freq, &s->nb_freq, &s->freq_size);
479  av_free(freq_str);
480  if (ret < 0)
481  return ret;
482 
483  s->magnitude = av_calloc(s->nb_magnitude + 1, sizeof(*s->magnitude));
484  if (!s->magnitude)
485  return AVERROR(ENOMEM);
486  memcpy(s->magnitude, eq_presets[s->preset].gains, sizeof(*s->magnitude) * s->nb_magnitude);
487  }
488 
489  if (s->nb_freq != s->nb_magnitude || s->nb_freq < 2) {
490  av_log(ctx, AV_LOG_ERROR, "Number of bands and gains must be same and >= 2.\n");
491  return AVERROR(EINVAL);
492  }
493 
494  s->freq[s->nb_freq] = outlink->sample_rate * 0.5f;
495  s->magnitude[s->nb_freq] = s->magnitude[s->nb_freq-1];
496 
497  fft_size = s->nb_taps * 2;
498  factor = FFMIN(outlink->sample_rate * 0.5f, s->freq[s->nb_freq - 1]) / (float)fft_size;
499  asize = FFALIGN(fft_size, av_cpu_max_align());
500  s->complexf = av_calloc(asize * 2, sizeof(*s->complexf));
501  if (!s->complexf)
502  return AVERROR(ENOMEM);
503 
504  scale = 1.f;
505  ret = av_tx_init(&s->itx_ctx, &s->itx_fn, AV_TX_FLOAT_FFT, 1, fft_size, &scale, 0);
506  if (ret < 0)
507  return ret;
508 
509  s->taps = av_calloc(s->nb_taps, sizeof(*s->taps));
510  if (!s->taps)
511  return AVERROR(ENOMEM);
512 
513  eq_interp(s->complexf, s->freq, s->magnitude, s->nb_freq, s->interp, s->nb_taps, factor);
514 
515  for (int i = 0; i < fft_size; i++)
516  s->complexf[i].re = ff_exp10f(s->complexf[i].re / 20.f);
517 
518  if (s->phaset) {
519  const float threshold = powf(10.f, -100.f / 20.f);
520  const float logt = logf(threshold);
521 
522  scale = 1.f;
523  ret = av_tx_init(&s->tx_ctx, &s->tx_fn, AV_TX_FLOAT_FFT, 0, fft_size, &scale, 0);
524  if (ret < 0)
525  return ret;
526 
527  for (int i = 0; i < fft_size; i++)
528  s->complexf[i].re = s->complexf[i].re < threshold ? logt : logf(s->complexf[i].re);
529 
530  s->itx_fn(s->itx_ctx, s->complexf + asize, s->complexf, sizeof(float));
531  for (int i = 0; i < fft_size; i++) {
532  s->complexf[i + asize].re /= fft_size;
533  s->complexf[i + asize].im /= fft_size;
534  }
535 
536  for (int i = 1; i < s->nb_taps; i++) {
537  s->complexf[asize + i].re += s->complexf[asize + fft_size - i].re;
538  s->complexf[asize + i].im -= s->complexf[asize + fft_size - i].im;
539  s->complexf[asize + fft_size - i].re = 0.f;
540  s->complexf[asize + fft_size - i].im = 0.f;
541  }
542  s->complexf[asize + s->nb_taps - 1].im *= -1.f;
543 
544  s->tx_fn(s->tx_ctx, s->complexf, s->complexf + asize, sizeof(float));
545 
546  for (int i = 0; i < fft_size; i++) {
547  float eR = expf(s->complexf[i].re);
548 
549  s->complexf[i].re = eR * cosf(s->complexf[i].im);
550  s->complexf[i].im = eR * sinf(s->complexf[i].im);
551  }
552 
553  s->itx_fn(s->itx_ctx, s->complexf + asize, s->complexf, sizeof(float));
554 
555  for (int i = 0; i < s->nb_taps; i++)
556  s->taps[i] = s->complexf[i + asize].re / fft_size;
557  } else {
558  s->itx_fn(s->itx_ctx, s->complexf + asize, s->complexf, sizeof(float));
559 
560  middle = s->nb_taps / 2;
561  for (int i = 0; i < middle; i++) {
562  s->taps[middle - i] = s->complexf[i + asize].re / fft_size;
563  s->taps[middle + i] = s->complexf[i + asize].re / fft_size;
564  }
565  }
566 
567  s->pts = 0;
568 
569  return 0;
570 }
571 
572 static const AVFilterPad afireqsrc_outputs[] = {
573  {
574  .name = "default",
575  .type = AVMEDIA_TYPE_AUDIO,
576  .config_props = config_eq_output,
577  },
578 };
579 
581  .name = "afireqsrc",
582  .description = NULL_IF_CONFIG_SMALL("Generate a FIR equalizer coefficients audio stream."),
583  .uninit = uninit,
584  .activate = activate,
585  .priv_size = sizeof(AudioFIRSourceContext),
586  .inputs = NULL,
589  .priv_class = &afireqsrc_class,
590 };
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:97
AudioFIRSourceContext::phase_str
char * phase_str
Definition: asrc_afirsrc.c:39
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
lininterp
static void lininterp(AVComplexFloat *complexf, const float *freq, const float *magnitude, const float *phase, int m, int minterp)
Definition: asrc_afirsrc.c:163
AudioFIRSourceContext::nb_samples
int nb_samples
Definition: asrc_afirsrc.c:42
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
afirsrc_options
static const AVOption afirsrc_options[]
Definition: asrc_afirsrc.c:70
AudioFIRSourceContext
Definition: asrc_afirsrc.c:34
DEFAULT_BANDS
#define DEFAULT_BANDS
Definition: asrc_afirsrc.c:311
afireqsrc_options
static const AVOption afireqsrc_options[]
Definition: asrc_afirsrc.c:339
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1018
sample_fmts
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:947
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
FFERROR_NOT_READY
return FFERROR_NOT_READY
Definition: filter_design.txt:204
AudioFIRSourceContext::freq_points_str
char * freq_points_str
Definition: asrc_afirsrc.c:37
AVTXContext
Definition: tx_priv.h:235
ff_set_common_samplerates_from_list
int ff_set_common_samplerates_from_list(AVFilterContext *ctx, const int *samplerates)
Equivalent to ff_set_common_samplerates(ctx, ff_make_format_list(samplerates))
Definition: formats.c:815
eq_interp
static void eq_interp(AVComplexFloat *complexf, const float *freq, const float *magnitude, int m, int interp, int minterp, const float factor)
Definition: asrc_afirsrc.c:384
activate
static int activate(AVFilterContext *ctx)
Definition: asrc_afirsrc.c:264
ph
static int FUNC() ph(CodedBitstreamContext *ctx, RWContext *rw, H266RawPH *current)
Definition: cbs_h266_syntax_template.c:3000
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:375
eq_presets
static const EqPreset eq_presets[]
Definition: asrc_afirsrc.c:318
AudioFIRSourceContext::nb_freq
int nb_freq
Definition: asrc_afirsrc.c:55
AVOption
AVOption.
Definition: opt.h:346
b
#define b
Definition: input.c:41
FILTER_QUERY_FUNC
#define FILTER_QUERY_FUNC(func)
Definition: internal.h:159
AudioFIRSourceContext::phase
float * phase
Definition: asrc_afirsrc.c:51
expf
#define expf(x)
Definition: libm.h:283
AVComplexFloat
Definition: tx.h:27
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: asrc_afirsrc.c:102
WIN_FUNC_OPTION
#define WIN_FUNC_OPTION(win_func_opt_name, win_func_offset, flag, default_window_func)
Definition: window_func.h:37
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:170
ff_asrc_afirsrc
const AVFilter ff_asrc_afirsrc
Definition: asrc_afirsrc.c:298
sample_rate
sample_rate
Definition: ffmpeg_filter.c:410
av_tx_init
av_cold int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type, int inv, int len, const void *scale, uint64_t flags)
Initialize a transform context with the given configuration (i)MDCTs with an odd length are currently...
Definition: tx.c:902
AudioFIRSourceContext::complexf
AVComplexFloat * complexf
Definition: asrc_afirsrc.c:48
formats.h
WFUNC_BLACKMAN
@ WFUNC_BLACKMAN
Definition: af_firequalizer.c:38
AVComplexFloat::im
float im
Definition: tx.h:28
AudioFIRSourceContext::nb_taps
int nb_taps
Definition: asrc_afirsrc.c:40
ff_asrc_afireqsrc
const AVFilter ff_asrc_afireqsrc
Definition: asrc_afirsrc.c:580
cosf
#define cosf(x)
Definition: libm.h:78
interp
interp
Definition: vf_curves.c:61
OFFSET
#define OFFSET(x)
Definition: asrc_afirsrc.c:67
config_eq_output
static av_cold int config_eq_output(AVFilterLink *outlink)
Definition: asrc_afirsrc.c:453
fabsf
static __device__ float fabsf(float a)
Definition: cuda_runtime.h:181
afireqsrc_outputs
static const AVFilterPad afireqsrc_outputs[]
Definition: asrc_afirsrc.c:572
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:33
preset
preset
Definition: vf_curves.c:46
AudioFIRSourceContext::magnitude
float * magnitude
Definition: asrc_afirsrc.c:50
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
av_tx_fn
void(* av_tx_fn)(AVTXContext *s, void *out, void *in, ptrdiff_t stride)
Function pointer to a function to perform the transform.
Definition: tx.h:151
float
float
Definition: af_crystalizer.c:121
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:189
av_fast_realloc
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
Definition: mem.c:495
s
#define s(width, name)
Definition: cbs_vp9.c:198
parse_string
static int parse_string(char *str, float **items, int *nb_items, int *items_size)
Definition: asrc_afirsrc.c:136
g
const char * g
Definition: vf_curves.c:127
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
ff_set_common_formats_from_list
int ff_set_common_formats_from_list(AVFilterContext *ctx, const int *fmts)
Equivalent to ff_set_common_formats(ctx, ff_make_format_list(fmts))
Definition: formats.c:873
filters.h
AV_TX_FLOAT_FFT
@ AV_TX_FLOAT_FFT
Standard complex to complex FFT with sample data type of AVComplexFloat, AVComplexDouble or AVComplex...
Definition: tx.h:47
ctx
AVFormatContext * ctx
Definition: movenc.c:48
mg
#define mg
Definition: vf_colormatrix.c:104
ff_set_common_channel_layouts_from_list
int ff_set_common_channel_layouts_from_list(AVFilterContext *ctx, const AVChannelLayout *fmts)
Equivalent to ff_set_common_channel_layouts(ctx, ff_make_channel_layout_list(fmts))
Definition: formats.c:797
AudioFIRSourceContext::nb_phase
int nb_phase
Definition: asrc_afirsrc.c:57
AudioFIRSourceContext::interp
int interp
Definition: asrc_afirsrc.c:45
AudioFIRSourceContext::win_func
int win_func
Definition: asrc_afirsrc.c:43
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
AudioFIRSourceContext::nb_magnitude
int nb_magnitude
Definition: asrc_afirsrc.c:56
av_cpu_max_align
size_t av_cpu_max_align(void)
Get the maximum data alignment that may be required by FFmpeg.
Definition: cpu.c:268
generate_window_func
static void generate_window_func(float *lut, int N, int win_func, float *overlap)
Definition: window_func.h:63
sinf
#define sinf(x)
Definition: libm.h:419
AudioFIRSourceContext::itx_ctx
AVTXContext * itx_ctx
Definition: asrc_afirsrc.c:63
inputs
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
Definition: filter_design.txt:243
EqPreset::gains
float gains[16]
Definition: asrc_afirsrc.c:315
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
eval.h
f
f
Definition: af_crystalizer.c:121
scale
static void scale(int *out, const int *in, const int w, const int h, const int shift)
Definition: vvc_intra.c:291
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:106
powf
#define powf(x, y)
Definition: libm.h:50
AudioFIRSourceContext::itx_fn
av_tx_fn itx_fn
Definition: asrc_afirsrc.c:64
AVChannelLayout
An AVChannelLayout holds information about the channel layout of audio data.
Definition: channel_layout.h:303
cpu.h
AV_SAMPLE_FMT_NONE
@ AV_SAMPLE_FMT_NONE
Definition: samplefmt.h:56
AVComplexFloat::re
float re
Definition: tx.h:28
AudioFIRSourceContext::sample_rate
int sample_rate
Definition: asrc_afirsrc.c:41
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(afirsrc)
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
AudioFIRSourceContext::magnitude_str
char * magnitude_str
Definition: asrc_afirsrc.c:38
AudioFIRSourceContext::pts
int64_t pts
Definition: asrc_afirsrc.c:61
EqPreset
Definition: asrc_afirsrc.c:313
av_tx_uninit
av_cold void av_tx_uninit(AVTXContext **ctx)
Frees a context and sets *ctx to NULL, does nothing when *ctx == NULL.
Definition: tx.c:294
sample_rates
sample_rates
Definition: ffmpeg_filter.c:410
internal.h
AudioFIRSourceContext::preset
int preset
Definition: asrc_afirsrc.c:44
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
AudioFIRSourceContext::freq_size
int freq_size
Definition: asrc_afirsrc.c:52
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:55
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:39
EqPreset::name
char name[16]
Definition: asrc_afirsrc.c:314
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:262
query_formats
static av_cold int query_formats(AVFilterContext *ctx)
Definition: asrc_afirsrc.c:116
AVFilter
Filter definition.
Definition: avfilter.h:166
AudioFIRSourceContext::win
float * win
Definition: asrc_afirsrc.c:60
ret
ret
Definition: filter_design.txt:187
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
av_strtod
double av_strtod(const char *numstr, char **tail)
Parse the string in numstr and return its value as a double.
Definition: eval.c:108
AudioFIRSourceContext::tx_fn
av_tx_fn tx_fn
Definition: asrc_afirsrc.c:64
window_func.h
channel_layout.h
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:235
avfilter.h
AudioFIRSourceContext::taps
float * taps
Definition: asrc_afirsrc.c:59
AudioFIRSourceContext::magnitude_size
int magnitude_size
Definition: asrc_afirsrc.c:53
ffmath.h
AVFilterContext
An instance of a filter.
Definition: avfilter.h:407
factor
static const int factor[16]
Definition: vf_pp7.c:78
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:270
audio.h
AV_CHANNEL_LAYOUT_MONO
#define AV_CHANNEL_LAYOUT_MONO
Definition: channel_layout.h:378
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
AudioFIRSourceContext::tx_ctx
AVTXContext * tx_ctx
Definition: asrc_afirsrc.c:63
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:183
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
d
d
Definition: ffmpeg_filter.c:410
FLAGS
#define FLAGS
Definition: asrc_afirsrc.c:68
ff_exp10f
static av_always_inline float ff_exp10f(float x)
Definition: ffmath.h:47
AudioFIRSourceContext::phase_size
int phase_size
Definition: asrc_afirsrc.c:54
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
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
AudioFIRSourceContext::phaset
int phaset
Definition: asrc_afirsrc.c:46
init
static av_cold int init(AVFilterContext *ctx)
Definition: asrc_afirsrc.c:90
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:239
afirsrc_outputs
static const AVFilterPad afirsrc_outputs[]
Definition: asrc_afirsrc.c:290
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:244
av_log2
int av_log2(unsigned v)
Definition: intmath.c:26
AV_SAMPLE_FMT_FLT
@ AV_SAMPLE_FMT_FLT
float
Definition: samplefmt.h:60
config_output
static av_cold int config_output(AVFilterLink *outlink)
Definition: asrc_afirsrc.c:185
tx.h
AudioFIRSourceContext::freq
float * freq
Definition: asrc_afirsrc.c:49