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/mem.h"
26 #include "libavutil/opt.h"
27 #include "libavutil/tx.h"
28 #include "audio.h"
29 #include "avfilter.h"
30 #include "filters.h"
31 #include "formats.h"
32 #include "internal.h"
33 #include "window_func.h"
34 
35 typedef struct AudioFIRSourceContext {
36  const AVClass *class;
37 
40  char *phase_str;
41  int nb_taps;
44  int win_func;
45  int preset;
46  int interp;
47  int phaset;
48 
50  float *freq;
51  float *magnitude;
52  float *phase;
53  int freq_size;
56  int nb_freq;
58  int nb_phase;
59 
60  float *taps;
61  float *win;
62  int64_t pts;
63 
67 
68 #define OFFSET(x) offsetof(AudioFIRSourceContext, x)
69 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
70 
71 static const AVOption afirsrc_options[] = {
72  { "taps", "set number of taps", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=1025}, 9, UINT16_MAX, FLAGS },
73  { "t", "set number of taps", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=1025}, 9, UINT16_MAX, FLAGS },
74  { "frequency", "set frequency points", OFFSET(freq_points_str), AV_OPT_TYPE_STRING, {.str="0 1"}, 0, 0, FLAGS },
75  { "f", "set frequency points", OFFSET(freq_points_str), AV_OPT_TYPE_STRING, {.str="0 1"}, 0, 0, FLAGS },
76  { "magnitude", "set magnitude values", OFFSET(magnitude_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, FLAGS },
77  { "m", "set magnitude values", OFFSET(magnitude_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, FLAGS },
78  { "phase", "set phase values", OFFSET(phase_str), AV_OPT_TYPE_STRING, {.str="0 0"}, 0, 0, FLAGS },
79  { "p", "set phase values", OFFSET(phase_str), AV_OPT_TYPE_STRING, {.str="0 0"}, 0, 0, FLAGS },
80  { "sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, FLAGS },
81  { "r", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, FLAGS },
82  { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS },
83  { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS },
84  WIN_FUNC_OPTION("win_func", OFFSET(win_func), FLAGS, WFUNC_BLACKMAN),
85  WIN_FUNC_OPTION("w", OFFSET(win_func), FLAGS, WFUNC_BLACKMAN),
86  {NULL}
87 };
88 
89 AVFILTER_DEFINE_CLASS(afirsrc);
90 
92 {
93  AudioFIRSourceContext *s = ctx->priv;
94 
95  if (!(s->nb_taps & 1)) {
96  av_log(s, AV_LOG_WARNING, "Number of taps %d must be odd length.\n", s->nb_taps);
97  s->nb_taps |= 1;
98  }
99 
100  return 0;
101 }
102 
104 {
105  AudioFIRSourceContext *s = ctx->priv;
106 
107  av_freep(&s->win);
108  av_freep(&s->taps);
109  av_freep(&s->freq);
110  av_freep(&s->magnitude);
111  av_freep(&s->phase);
112  av_freep(&s->complexf);
113  av_tx_uninit(&s->tx_ctx);
114  av_tx_uninit(&s->itx_ctx);
115 }
116 
118 {
119  AudioFIRSourceContext *s = ctx->priv;
120  static const AVChannelLayout chlayouts[] = { AV_CHANNEL_LAYOUT_MONO, { 0 } };
121  int sample_rates[] = { s->sample_rate, -1 };
122  static const enum AVSampleFormat sample_fmts[] = {
125  };
127  if (ret < 0)
128  return ret;
129 
131  if (ret < 0)
132  return ret;
133 
135 }
136 
137 static int parse_string(char *str, float **items, int *nb_items, int *items_size)
138 {
139  float *new_items;
140  char *tail;
141 
142  new_items = av_fast_realloc(NULL, items_size, sizeof(float));
143  if (!new_items)
144  return AVERROR(ENOMEM);
145  *items = new_items;
146 
147  tail = str;
148  if (!tail)
149  return AVERROR(EINVAL);
150 
151  do {
152  (*items)[(*nb_items)++] = av_strtod(tail, &tail);
153  new_items = av_fast_realloc(*items, items_size, (*nb_items + 2) * sizeof(float));
154  if (!new_items)
155  return AVERROR(ENOMEM);
156  *items = new_items;
157  if (tail && *tail)
158  tail++;
159  } while (tail && *tail);
160 
161  return 0;
162 }
163 
164 static void lininterp(AVComplexFloat *complexf,
165  const float *freq,
166  const float *magnitude,
167  const float *phase,
168  int m, int minterp)
169 {
170  for (int i = 0; i < minterp; i++) {
171  for (int j = 1; j < m; j++) {
172  const float x = i / (float)minterp;
173 
174  if (x <= freq[j]) {
175  const float mg = (x - freq[j-1]) / (freq[j] - freq[j-1]) * (magnitude[j] - magnitude[j-1]) + magnitude[j-1];
176  const float ph = (x - freq[j-1]) / (freq[j] - freq[j-1]) * (phase[j] - phase[j-1]) + phase[j-1];
177 
178  complexf[i].re = mg * cosf(ph);
179  complexf[i].im = mg * sinf(ph);
180  break;
181  }
182  }
183  }
184 }
185 
186 static av_cold int config_output(AVFilterLink *outlink)
187 {
188  AVFilterContext *ctx = outlink->src;
189  AudioFIRSourceContext *s = ctx->priv;
190  float overlap, scale = 1.f, compensation;
191  int fft_size, middle, ret;
192 
193  s->nb_freq = s->nb_magnitude = s->nb_phase = 0;
194 
195  ret = parse_string(s->freq_points_str, &s->freq, &s->nb_freq, &s->freq_size);
196  if (ret < 0)
197  return ret;
198 
199  ret = parse_string(s->magnitude_str, &s->magnitude, &s->nb_magnitude, &s->magnitude_size);
200  if (ret < 0)
201  return ret;
202 
203  ret = parse_string(s->phase_str, &s->phase, &s->nb_phase, &s->phase_size);
204  if (ret < 0)
205  return ret;
206 
207  if (s->nb_freq != s->nb_magnitude && s->nb_freq != s->nb_phase && s->nb_freq >= 2) {
208  av_log(ctx, AV_LOG_ERROR, "Number of frequencies, magnitudes and phases must be same and >= 2.\n");
209  return AVERROR(EINVAL);
210  }
211 
212  for (int i = 0; i < s->nb_freq; i++) {
213  if (i == 0 && s->freq[i] != 0.f) {
214  av_log(ctx, AV_LOG_ERROR, "First frequency must be 0.\n");
215  return AVERROR(EINVAL);
216  }
217 
218  if (i == s->nb_freq - 1 && s->freq[i] != 1.f) {
219  av_log(ctx, AV_LOG_ERROR, "Last frequency must be 1.\n");
220  return AVERROR(EINVAL);
221  }
222 
223  if (i && s->freq[i] < s->freq[i-1]) {
224  av_log(ctx, AV_LOG_ERROR, "Frequencies must be in increasing order.\n");
225  return AVERROR(EINVAL);
226  }
227  }
228 
229  fft_size = 1 << (av_log2(s->nb_taps) + 1);
230  s->complexf = av_calloc(fft_size * 2, sizeof(*s->complexf));
231  if (!s->complexf)
232  return AVERROR(ENOMEM);
233 
234  ret = av_tx_init(&s->tx_ctx, &s->tx_fn, AV_TX_FLOAT_FFT, 1, fft_size, &scale, 0);
235  if (ret < 0)
236  return ret;
237 
238  s->taps = av_calloc(s->nb_taps, sizeof(*s->taps));
239  if (!s->taps)
240  return AVERROR(ENOMEM);
241 
242  s->win = av_calloc(s->nb_taps, sizeof(*s->win));
243  if (!s->win)
244  return AVERROR(ENOMEM);
245 
246  generate_window_func(s->win, s->nb_taps, s->win_func, &overlap);
247 
248  lininterp(s->complexf, s->freq, s->magnitude, s->phase, s->nb_freq, fft_size / 2);
249 
250  s->tx_fn(s->tx_ctx, s->complexf + fft_size, s->complexf, sizeof(*s->complexf));
251 
252  compensation = 2.f / fft_size;
253  middle = s->nb_taps / 2;
254 
255  for (int i = 0; i <= middle; i++) {
256  s->taps[ i] = s->complexf[fft_size + middle - i].re * compensation * s->win[i];
257  s->taps[middle + i] = s->complexf[fft_size + i].re * compensation * s->win[middle + i];
258  }
259 
260  s->pts = 0;
261 
262  return 0;
263 }
264 
266 {
267  AVFilterLink *outlink = ctx->outputs[0];
268  AudioFIRSourceContext *s = ctx->priv;
269  AVFrame *frame;
270  int nb_samples;
271 
272  if (!ff_outlink_frame_wanted(outlink))
273  return FFERROR_NOT_READY;
274 
275  nb_samples = FFMIN(s->nb_samples, s->nb_taps - s->pts);
276  if (nb_samples <= 0) {
277  ff_outlink_set_status(outlink, AVERROR_EOF, s->pts);
278  return 0;
279  }
280 
281  if (!(frame = ff_get_audio_buffer(outlink, nb_samples)))
282  return AVERROR(ENOMEM);
283 
284  memcpy(frame->data[0], s->taps + s->pts, nb_samples * sizeof(float));
285 
286  frame->pts = s->pts;
287  s->pts += nb_samples;
288  return ff_filter_frame(outlink, frame);
289 }
290 
291 static const AVFilterPad afirsrc_outputs[] = {
292  {
293  .name = "default",
294  .type = AVMEDIA_TYPE_AUDIO,
295  .config_props = config_output,
296  },
297 };
298 
300  .name = "afirsrc",
301  .description = NULL_IF_CONFIG_SMALL("Generate a FIR coefficients audio stream."),
302  .init = init,
303  .uninit = uninit,
304  .activate = activate,
305  .priv_size = sizeof(AudioFIRSourceContext),
306  .inputs = NULL,
309  .priv_class = &afirsrc_class,
310 };
311 
312 #define DEFAULT_BANDS "25 40 63 100 160 250 400 630 1000 1600 2500 4000 6300 10000 16000 24000"
313 
314 typedef struct EqPreset {
315  char name[16];
316  float gains[16];
317 } EqPreset;
318 
319 static const EqPreset eq_presets[] = {
320  { "flat", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
321  { "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 } },
322  { "bass", { 10.0, 8.8, 8.5, 6.5, 2.5, 1.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
323  { "beats", { -5.5, -5.0, -4.5, -4.2, -3.5, -3.0, -1.9, 0, 0, 0, 0, 0, 0, 0, 0 } },
324  { "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 } },
325  { "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 } },
326  { "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 } },
327  { "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 } },
328  { "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 } },
329  { "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 } },
330  { "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 } },
331  { "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 } },
332  { "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 } },
333  { "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 } },
334  { "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 } },
335  { "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 } },
336  { "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 } },
337  { "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 } },
338 };
339 
340 static const AVOption afireqsrc_options[] = {
341  { "preset","set equalizer preset", OFFSET(preset), AV_OPT_TYPE_INT, {.i64=0}, -1, FF_ARRAY_ELEMS(eq_presets)-1, FLAGS, .unit = "preset" },
342  { "p", "set equalizer preset", OFFSET(preset), AV_OPT_TYPE_INT, {.i64=0}, -1, FF_ARRAY_ELEMS(eq_presets)-1, FLAGS, .unit = "preset" },
343  { "custom", NULL, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, .unit = "preset" },
344  { eq_presets[ 0].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 0}, 0, 0, FLAGS, .unit = "preset" },
345  { eq_presets[ 1].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 1}, 0, 0, FLAGS, .unit = "preset" },
346  { eq_presets[ 2].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 2}, 0, 0, FLAGS, .unit = "preset" },
347  { eq_presets[ 3].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 3}, 0, 0, FLAGS, .unit = "preset" },
348  { eq_presets[ 4].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 4}, 0, 0, FLAGS, .unit = "preset" },
349  { eq_presets[ 5].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 5}, 0, 0, FLAGS, .unit = "preset" },
350  { eq_presets[ 6].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 6}, 0, 0, FLAGS, .unit = "preset" },
351  { eq_presets[ 7].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 7}, 0, 0, FLAGS, .unit = "preset" },
352  { eq_presets[ 8].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 8}, 0, 0, FLAGS, .unit = "preset" },
353  { eq_presets[ 9].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64= 9}, 0, 0, FLAGS, .unit = "preset" },
354  { eq_presets[10].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=10}, 0, 0, FLAGS, .unit = "preset" },
355  { eq_presets[11].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=11}, 0, 0, FLAGS, .unit = "preset" },
356  { eq_presets[12].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=12}, 0, 0, FLAGS, .unit = "preset" },
357  { eq_presets[13].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=13}, 0, 0, FLAGS, .unit = "preset" },
358  { eq_presets[14].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=14}, 0, 0, FLAGS, .unit = "preset" },
359  { eq_presets[15].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=15}, 0, 0, FLAGS, .unit = "preset" },
360  { eq_presets[16].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=16}, 0, 0, FLAGS, .unit = "preset" },
361  { eq_presets[17].name, NULL, 0, AV_OPT_TYPE_CONST, {.i64=17}, 0, 0, FLAGS, .unit = "preset" },
362  { "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 },
363  { "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 },
364  { "bands", "set central frequency values per band", OFFSET(freq_points_str), AV_OPT_TYPE_STRING, {.str=DEFAULT_BANDS}, 0, 0, FLAGS },
365  { "b", "set central frequency values per band", OFFSET(freq_points_str), AV_OPT_TYPE_STRING, {.str=DEFAULT_BANDS}, 0, 0, FLAGS },
366  { "taps", "set number of taps", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=4096}, 16, UINT16_MAX, FLAGS },
367  { "t", "set number of taps", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=4096}, 16, UINT16_MAX, FLAGS },
368  { "sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, FLAGS },
369  { "r", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, FLAGS },
370  { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS },
371  { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS },
372  { "interp","set the interpolation", OFFSET(interp), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, .unit = "interp" },
373  { "i", "set the interpolation", OFFSET(interp), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, .unit = "interp" },
374  { "linear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, .unit = "interp" },
375  { "cubic", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, .unit = "interp" },
376  { "phase","set the phase", OFFSET(phaset), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, .unit = "phase" },
377  { "h", "set the phase", OFFSET(phaset), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, .unit = "phase" },
378  { "linear", "linear phase", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, .unit = "phase" },
379  { "min", "minimum phase", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, .unit = "phase" },
380  {NULL}
381 };
382 
383 AVFILTER_DEFINE_CLASS(afireqsrc);
384 
385 static void eq_interp(AVComplexFloat *complexf,
386  const float *freq,
387  const float *magnitude,
388  int m, int interp, int minterp,
389  const float factor)
390 {
391  for (int i = 0; i < minterp; i++) {
392  for (int j = 0; j < m; j++) {
393  const float x = factor * i;
394 
395  if (x <= freq[j+1]) {
396  float g;
397 
398  if (interp == 0) {
399  const float d = freq[j+1] - freq[j];
400  const float d0 = x - freq[j];
401  const float d1 = freq[j+1] - x;
402  const float g0 = magnitude[j];
403  const float g1 = magnitude[j+1];
404 
405  if (d0 && d1) {
406  g = (d0 * g1 + d1 * g0) / d;
407  } else if (d0) {
408  g = g1;
409  } else {
410  g = g0;
411  }
412  } else {
413  if (x <= freq[j]) {
414  g = magnitude[j];
415  } else {
416  float x1, x2, x3;
417  float a, b, c, d;
418  float m0, m1, m2, msum;
419  const float unit = freq[j+1] - freq[j];
420 
421  m0 = j != 0 ? unit * (magnitude[j] - magnitude[j-1]) / (freq[j] - freq[j-1]) : 0;
422  m1 = magnitude[j+1] - magnitude[j];
423  m2 = j != minterp - 1 ? unit * (magnitude[j+2] - magnitude[j+1]) / (freq[j+2] - freq[j+1]) : 0;
424 
425  msum = fabsf(m0) + fabsf(m1);
426  m0 = msum > 0.f ? (fabsf(m0) * m1 + fabsf(m1) * m0) / msum : 0.f;
427  msum = fabsf(m1) + fabsf(m2);
428  m1 = msum > 0.f ? (fabsf(m1) * m2 + fabsf(m2) * m1) / msum : 0.f;
429 
430  d = magnitude[j];
431  c = m0;
432  b = 3.f * magnitude[j+1] - m1 - 2.f * c - 3.f * d;
433  a = magnitude[j+1] - b - c - d;
434 
435  x1 = (x - freq[j]) / unit;
436  x2 = x1 * x1;
437  x3 = x2 * x1;
438 
439  g = a * x3 + b * x2 + c * x1 + d;
440  }
441  }
442 
443  complexf[i].re = g;
444  complexf[i].im = 0;
445  complexf[minterp * 2 - i - 1].re = g;
446  complexf[minterp * 2 - i - 1].im = 0;
447 
448  break;
449  }
450  }
451  }
452 }
453 
455 {
456  AVFilterContext *ctx = outlink->src;
457  AudioFIRSourceContext *s = ctx->priv;
458  int fft_size, middle, asize, ret;
459  float scale, factor;
460 
461  s->nb_freq = s->nb_magnitude = 0;
462  if (s->preset < 0) {
463  ret = parse_string(s->freq_points_str, &s->freq, &s->nb_freq, &s->freq_size);
464  if (ret < 0)
465  return ret;
466 
467  ret = parse_string(s->magnitude_str, &s->magnitude, &s->nb_magnitude, &s->magnitude_size);
468  if (ret < 0)
469  return ret;
470  } else {
471  char *freq_str;
472 
473  s->nb_magnitude = FF_ARRAY_ELEMS(eq_presets[s->preset].gains);
474 
475  freq_str = av_strdup(DEFAULT_BANDS);
476  if (!freq_str)
477  return AVERROR(ENOMEM);
478 
479  ret = parse_string(freq_str, &s->freq, &s->nb_freq, &s->freq_size);
480  av_free(freq_str);
481  if (ret < 0)
482  return ret;
483 
484  s->magnitude = av_calloc(s->nb_magnitude + 1, sizeof(*s->magnitude));
485  if (!s->magnitude)
486  return AVERROR(ENOMEM);
487  memcpy(s->magnitude, eq_presets[s->preset].gains, sizeof(*s->magnitude) * s->nb_magnitude);
488  }
489 
490  if (s->nb_freq != s->nb_magnitude || s->nb_freq < 2) {
491  av_log(ctx, AV_LOG_ERROR, "Number of bands and gains must be same and >= 2.\n");
492  return AVERROR(EINVAL);
493  }
494 
495  s->freq[s->nb_freq] = outlink->sample_rate * 0.5f;
496  s->magnitude[s->nb_freq] = s->magnitude[s->nb_freq-1];
497 
498  fft_size = s->nb_taps * 2;
499  factor = FFMIN(outlink->sample_rate * 0.5f, s->freq[s->nb_freq - 1]) / (float)fft_size;
500  asize = FFALIGN(fft_size, av_cpu_max_align());
501  s->complexf = av_calloc(asize * 2, sizeof(*s->complexf));
502  if (!s->complexf)
503  return AVERROR(ENOMEM);
504 
505  scale = 1.f;
506  ret = av_tx_init(&s->itx_ctx, &s->itx_fn, AV_TX_FLOAT_FFT, 1, fft_size, &scale, 0);
507  if (ret < 0)
508  return ret;
509 
510  s->taps = av_calloc(s->nb_taps, sizeof(*s->taps));
511  if (!s->taps)
512  return AVERROR(ENOMEM);
513 
514  eq_interp(s->complexf, s->freq, s->magnitude, s->nb_freq, s->interp, s->nb_taps, factor);
515 
516  for (int i = 0; i < fft_size; i++)
517  s->complexf[i].re = ff_exp10f(s->complexf[i].re / 20.f);
518 
519  if (s->phaset) {
520  const float threshold = powf(10.f, -100.f / 20.f);
521  const float logt = logf(threshold);
522 
523  scale = 1.f;
524  ret = av_tx_init(&s->tx_ctx, &s->tx_fn, AV_TX_FLOAT_FFT, 0, fft_size, &scale, 0);
525  if (ret < 0)
526  return ret;
527 
528  for (int i = 0; i < fft_size; i++)
529  s->complexf[i].re = s->complexf[i].re < threshold ? logt : logf(s->complexf[i].re);
530 
531  s->itx_fn(s->itx_ctx, s->complexf + asize, s->complexf, sizeof(float));
532  for (int i = 0; i < fft_size; i++) {
533  s->complexf[i + asize].re /= fft_size;
534  s->complexf[i + asize].im /= fft_size;
535  }
536 
537  for (int i = 1; i < s->nb_taps; i++) {
538  s->complexf[asize + i].re += s->complexf[asize + fft_size - i].re;
539  s->complexf[asize + i].im -= s->complexf[asize + fft_size - i].im;
540  s->complexf[asize + fft_size - i].re = 0.f;
541  s->complexf[asize + fft_size - i].im = 0.f;
542  }
543  s->complexf[asize + s->nb_taps - 1].im *= -1.f;
544 
545  s->tx_fn(s->tx_ctx, s->complexf, s->complexf + asize, sizeof(float));
546 
547  for (int i = 0; i < fft_size; i++) {
548  float eR = expf(s->complexf[i].re);
549 
550  s->complexf[i].re = eR * cosf(s->complexf[i].im);
551  s->complexf[i].im = eR * sinf(s->complexf[i].im);
552  }
553 
554  s->itx_fn(s->itx_ctx, s->complexf + asize, s->complexf, sizeof(float));
555 
556  for (int i = 0; i < s->nb_taps; i++)
557  s->taps[i] = s->complexf[i + asize].re / fft_size;
558  } else {
559  s->itx_fn(s->itx_ctx, s->complexf + asize, s->complexf, sizeof(float));
560 
561  middle = s->nb_taps / 2;
562  for (int i = 0; i < middle; i++) {
563  s->taps[middle - i] = s->complexf[i + asize].re / fft_size;
564  s->taps[middle + i] = s->complexf[i + asize].re / fft_size;
565  }
566  }
567 
568  s->pts = 0;
569 
570  return 0;
571 }
572 
573 static const AVFilterPad afireqsrc_outputs[] = {
574  {
575  .name = "default",
576  .type = AVMEDIA_TYPE_AUDIO,
577  .config_props = config_eq_output,
578  },
579 };
580 
582  .name = "afireqsrc",
583  .description = NULL_IF_CONFIG_SMALL("Generate a FIR equalizer coefficients audio stream."),
584  .uninit = uninit,
585  .activate = activate,
586  .priv_size = sizeof(AudioFIRSourceContext),
587  .inputs = NULL,
590  .priv_class = &afireqsrc_class,
591 };
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:40
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:164
AudioFIRSourceContext::nb_samples
int nb_samples
Definition: asrc_afirsrc.c:43
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:71
AudioFIRSourceContext
Definition: asrc_afirsrc.c:35
DEFAULT_BANDS
#define DEFAULT_BANDS
Definition: asrc_afirsrc.c:312
afireqsrc_options
static const AVOption afireqsrc_options[]
Definition: asrc_afirsrc.c:340
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1015
sample_fmts
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:948
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:38
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:816
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:385
activate
static int activate(AVFilterContext *ctx)
Definition: asrc_afirsrc.c:265
ph
static int FUNC() ph(CodedBitstreamContext *ctx, RWContext *rw, H266RawPH *current)
Definition: cbs_h266_syntax_template.c:3005
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:374
eq_presets
static const EqPreset eq_presets[]
Definition: asrc_afirsrc.c:319
AudioFIRSourceContext::nb_freq
int nb_freq
Definition: asrc_afirsrc.c:56
AVOption
AVOption.
Definition: opt.h:357
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:52
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:103
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:299
sample_rate
sample_rate
Definition: ffmpeg_filter.c:424
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:903
AudioFIRSourceContext::complexf
AVComplexFloat * complexf
Definition: asrc_afirsrc.c:49
formats.h
WFUNC_BLACKMAN
@ WFUNC_BLACKMAN
Definition: af_firequalizer.c:39
AVComplexFloat::im
float im
Definition: tx.h:28
AudioFIRSourceContext::nb_taps
int nb_taps
Definition: asrc_afirsrc.c:41
ff_asrc_afireqsrc
const AVFilter ff_asrc_afireqsrc
Definition: asrc_afirsrc.c:581
cosf
#define cosf(x)
Definition: libm.h:78
interp
interp
Definition: vf_curves.c:62
OFFSET
#define OFFSET(x)
Definition: asrc_afirsrc.c:68
config_eq_output
static av_cold int config_eq_output(AVFilterLink *outlink)
Definition: asrc_afirsrc.c:454
fabsf
static __device__ float fabsf(float a)
Definition: cuda_runtime.h:181
afireqsrc_outputs
static const AVFilterPad afireqsrc_outputs[]
Definition: asrc_afirsrc.c:573
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:33
preset
preset
Definition: vf_curves.c:47
AudioFIRSourceContext::magnitude
float * magnitude
Definition: asrc_afirsrc.c:51
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:497
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:137
g
const char * g
Definition: vf_curves.c:128
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:874
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:49
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:798
AudioFIRSourceContext::nb_phase
int nb_phase
Definition: asrc_afirsrc.c:58
AudioFIRSourceContext::interp
int interp
Definition: asrc_afirsrc.c:46
AudioFIRSourceContext::win_func
int win_func
Definition: asrc_afirsrc.c:44
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:57
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:270
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:64
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:316
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
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
powf
#define powf(x, y)
Definition: libm.h:50
AudioFIRSourceContext::itx_fn
av_tx_fn itx_fn
Definition: asrc_afirsrc.c:65
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:42
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:39
AudioFIRSourceContext::pts
int64_t pts
Definition: asrc_afirsrc.c:62
EqPreset
Definition: asrc_afirsrc.c:314
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:295
sample_rates
sample_rates
Definition: ffmpeg_filter.c:424
internal.h
AudioFIRSourceContext::preset
int preset
Definition: asrc_afirsrc.c:45
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
AudioFIRSourceContext::freq_size
int freq_size
Definition: asrc_afirsrc.c:53
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:315
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
query_formats
static av_cold int query_formats(AVFilterContext *ctx)
Definition: asrc_afirsrc.c:117
AVFilter
Filter definition.
Definition: avfilter.h:166
AudioFIRSourceContext::win
float * win
Definition: asrc_afirsrc.c:61
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:107
AudioFIRSourceContext::tx_fn
av_tx_fn tx_fn
Definition: asrc_afirsrc.c:65
window_func.h
channel_layout.h
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:245
avfilter.h
AudioFIRSourceContext::taps
float * taps
Definition: asrc_afirsrc.c:60
AudioFIRSourceContext::magnitude_size
int magnitude_size
Definition: asrc_afirsrc.c:54
ffmath.h
AVFilterContext
An instance of a filter.
Definition: avfilter.h:407
factor
static const int factor[16]
Definition: vf_pp7.c:79
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:272
mem.h
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
scale
static void scale(int *out, const int *in, const int w, const int h, const int shift)
Definition: intra.c:291
AudioFIRSourceContext::tx_ctx
AVTXContext * tx_ctx
Definition: asrc_afirsrc.c:64
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:424
FLAGS
#define FLAGS
Definition: asrc_afirsrc.c:69
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:55
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:47
init
static av_cold int init(AVFilterContext *ctx)
Definition: asrc_afirsrc.c:91
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:249
afirsrc_outputs
static const AVFilterPad afirsrc_outputs[]
Definition: asrc_afirsrc.c:291
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:254
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:186
tx.h
AudioFIRSourceContext::freq
float * freq
Definition: asrc_afirsrc.c:50