FFmpeg
vaf_spectrumsynth.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 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
8  * License 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /**
22  * @file
23  * SpectrumSynth filter
24  * @todo support float pixel format
25  */
26 
27 #include "libavcodec/avfft.h"
28 #include "libavutil/avassert.h"
30 #include "libavutil/ffmath.h"
31 #include "libavutil/opt.h"
32 #include "libavutil/parseutils.h"
33 #include "avfilter.h"
34 #include "formats.h"
35 #include "audio.h"
36 #include "video.h"
37 #include "internal.h"
38 #include "window_func.h"
39 
43 
44 typedef struct SpectrumSynthContext {
45  const AVClass *class;
47  int channels;
48  int scale;
49  int sliding;
50  int win_func;
51  float overlap;
53 
55  FFTContext *fft; ///< Fast Fourier Transform context
56  int fft_bits; ///< number of bits (FFT window size = 1<<fft_bits)
57  FFTComplex **fft_data; ///< bins holder for each (displayed) channels
58  int win_size;
59  int size;
60  int nb_freq;
61  int hop_size;
62  int start, end;
63  int xpos;
64  int xend;
65  int64_t pts;
66  float factor;
68  float *window_func_lut; ///< Window function LUT
70 
71 #define OFFSET(x) offsetof(SpectrumSynthContext, x)
72 #define A AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM
73 #define V AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
74 
75 static const AVOption spectrumsynth_options[] = {
76  { "sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 44100}, 15, INT_MAX, A },
77  { "channels", "set channels", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = 1}, 1, 8, A },
78  { "scale", "set input amplitude scale", OFFSET(scale), AV_OPT_TYPE_INT, {.i64 = LOG}, 0, NB_SCALES-1, V, "scale" },
79  { "lin", "linear", 0, AV_OPT_TYPE_CONST, {.i64=LINEAR}, 0, 0, V, "scale" },
80  { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=LOG}, 0, 0, V, "scale" },
81  { "slide", "set input sliding mode", OFFSET(sliding), AV_OPT_TYPE_INT, {.i64 = FULLFRAME}, 0, NB_SLIDES-1, V, "slide" },
82  { "replace", "consume old columns with new", 0, AV_OPT_TYPE_CONST, {.i64=REPLACE}, 0, 0, V, "slide" },
83  { "scroll", "consume only most right column", 0, AV_OPT_TYPE_CONST, {.i64=SCROLL}, 0, 0, V, "slide" },
84  { "fullframe", "consume full frames", 0, AV_OPT_TYPE_CONST, {.i64=FULLFRAME}, 0, 0, V, "slide" },
85  { "rscroll", "consume only most left column", 0, AV_OPT_TYPE_CONST, {.i64=RSCROLL}, 0, 0, V, "slide" },
86  { "win_func", "set window function", OFFSET(win_func), AV_OPT_TYPE_INT, {.i64 = 0}, 0, NB_WFUNC-1, A, "win_func" },
87  { "rect", "Rectangular", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_RECT}, 0, 0, A, "win_func" },
88  { "bartlett", "Bartlett", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BARTLETT}, 0, 0, A, "win_func" },
89  { "hann", "Hann", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HANNING}, 0, 0, A, "win_func" },
90  { "hanning", "Hanning", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HANNING}, 0, 0, A, "win_func" },
91  { "hamming", "Hamming", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HAMMING}, 0, 0, A, "win_func" },
92  { "sine", "Sine", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_SINE}, 0, 0, A, "win_func" },
93  { "overlap", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, A },
94  { "orientation", "set orientation", OFFSET(orientation), AV_OPT_TYPE_INT, {.i64=VERTICAL}, 0, NB_ORIENTATIONS-1, V, "orientation" },
95  { "vertical", NULL, 0, AV_OPT_TYPE_CONST, {.i64=VERTICAL}, 0, 0, V, "orientation" },
96  { "horizontal", NULL, 0, AV_OPT_TYPE_CONST, {.i64=HORIZONTAL}, 0, 0, V, "orientation" },
97  { NULL }
98 };
99 
100 AVFILTER_DEFINE_CLASS(spectrumsynth);
101 
103 {
104  SpectrumSynthContext *s = ctx->priv;
107  AVFilterLink *magnitude = ctx->inputs[0];
108  AVFilterLink *phase = ctx->inputs[1];
109  AVFilterLink *outlink = ctx->outputs[0];
111  static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16,
114  int ret, sample_rates[] = { 48000, -1 };
115 
116  formats = ff_make_format_list(sample_fmts);
117  if ((ret = ff_formats_ref (formats, &outlink->in_formats )) < 0 ||
118  (ret = ff_add_channel_layout (&layout, FF_COUNT2LAYOUT(s->channels))) < 0 ||
119  (ret = ff_channel_layouts_ref (layout , &outlink->in_channel_layouts)) < 0)
120  return ret;
121 
122  sample_rates[0] = s->sample_rate;
123  formats = ff_make_format_list(sample_rates);
124  if (!formats)
125  return AVERROR(ENOMEM);
126  if ((ret = ff_formats_ref(formats, &outlink->in_samplerates)) < 0)
127  return ret;
128 
129  formats = ff_make_format_list(pix_fmts);
130  if (!formats)
131  return AVERROR(ENOMEM);
132  if ((ret = ff_formats_ref(formats, &magnitude->out_formats)) < 0)
133  return ret;
134 
135  formats = ff_make_format_list(pix_fmts);
136  if (!formats)
137  return AVERROR(ENOMEM);
138  if ((ret = ff_formats_ref(formats, &phase->out_formats)) < 0)
139  return ret;
140 
141  return 0;
142 }
143 
144 static int config_output(AVFilterLink *outlink)
145 {
146  AVFilterContext *ctx = outlink->src;
147  SpectrumSynthContext *s = ctx->priv;
148  int width = ctx->inputs[0]->w;
149  int height = ctx->inputs[0]->h;
150  AVRational time_base = ctx->inputs[0]->time_base;
151  AVRational frame_rate = ctx->inputs[0]->frame_rate;
152  int i, ch, fft_bits;
153  float factor, overlap;
154 
155  outlink->sample_rate = s->sample_rate;
156  outlink->time_base = (AVRational){1, s->sample_rate};
157 
158  if (width != ctx->inputs[1]->w ||
159  height != ctx->inputs[1]->h) {
160  av_log(ctx, AV_LOG_ERROR,
161  "Magnitude and Phase sizes differ (%dx%d vs %dx%d).\n",
162  width, height,
163  ctx->inputs[1]->w, ctx->inputs[1]->h);
164  return AVERROR_INVALIDDATA;
165  } else if (av_cmp_q(time_base, ctx->inputs[1]->time_base) != 0) {
166  av_log(ctx, AV_LOG_ERROR,
167  "Magnitude and Phase time bases differ (%d/%d vs %d/%d).\n",
168  time_base.num, time_base.den,
169  ctx->inputs[1]->time_base.num,
170  ctx->inputs[1]->time_base.den);
171  return AVERROR_INVALIDDATA;
172  } else if (av_cmp_q(frame_rate, ctx->inputs[1]->frame_rate) != 0) {
173  av_log(ctx, AV_LOG_ERROR,
174  "Magnitude and Phase framerates differ (%d/%d vs %d/%d).\n",
175  frame_rate.num, frame_rate.den,
176  ctx->inputs[1]->frame_rate.num,
177  ctx->inputs[1]->frame_rate.den);
178  return AVERROR_INVALIDDATA;
179  }
180 
181  s->size = s->orientation == VERTICAL ? height / s->channels : width / s->channels;
182  s->xend = s->orientation == VERTICAL ? width : height;
183 
184  for (fft_bits = 1; 1 << fft_bits < 2 * s->size; fft_bits++);
185 
186  s->win_size = 1 << fft_bits;
187  s->nb_freq = 1 << (fft_bits - 1);
188 
189  s->fft = av_fft_init(fft_bits, 1);
190  if (!s->fft) {
191  av_log(ctx, AV_LOG_ERROR, "Unable to create FFT context. "
192  "The window size might be too high.\n");
193  return AVERROR(EINVAL);
194  }
195  s->fft_data = av_calloc(s->channels, sizeof(*s->fft_data));
196  if (!s->fft_data)
197  return AVERROR(ENOMEM);
198  for (ch = 0; ch < s->channels; ch++) {
199  s->fft_data[ch] = av_calloc(s->win_size, sizeof(**s->fft_data));
200  if (!s->fft_data[ch])
201  return AVERROR(ENOMEM);
202  }
203 
204  s->buffer = ff_get_audio_buffer(outlink, s->win_size * 2);
205  if (!s->buffer)
206  return AVERROR(ENOMEM);
207 
208  /* pre-calc windowing function */
210  sizeof(*s->window_func_lut));
211  if (!s->window_func_lut)
212  return AVERROR(ENOMEM);
214  if (s->overlap == 1)
215  s->overlap = overlap;
216  s->hop_size = (1 - s->overlap) * s->win_size;
217  for (factor = 0, i = 0; i < s->win_size; i++) {
218  factor += s->window_func_lut[i] * s->window_func_lut[i];
219  }
220  s->factor = (factor / s->win_size) / FFMAX(1 / (1 - s->overlap) - 1, 1);
221 
222  return 0;
223 }
224 
225 static int request_frame(AVFilterLink *outlink)
226 {
227  AVFilterContext *ctx = outlink->src;
228  SpectrumSynthContext *s = ctx->priv;
229  int ret;
230 
231  if (!s->magnitude) {
232  ret = ff_request_frame(ctx->inputs[0]);
233  if (ret < 0)
234  return ret;
235  }
236  if (!s->phase) {
237  ret = ff_request_frame(ctx->inputs[1]);
238  if (ret < 0)
239  return ret;
240  }
241  return 0;
242 }
243 
245  int x, int y, int f, int ch)
246 {
247  const int m_linesize = s->magnitude->linesize[0];
248  const int p_linesize = s->phase->linesize[0];
249  const uint16_t *m = (uint16_t *)(s->magnitude->data[0] + y * m_linesize);
250  const uint16_t *p = (uint16_t *)(s->phase->data[0] + y * p_linesize);
251  float magnitude, phase;
252 
253  switch (s->scale) {
254  case LINEAR:
255  magnitude = m[x] / (double)UINT16_MAX;
256  break;
257  case LOG:
258  magnitude = ff_exp10(((m[x] / (double)UINT16_MAX) - 1.) * 6.);
259  break;
260  default:
261  av_assert0(0);
262  }
263  phase = ((p[x] / (double)UINT16_MAX) * 2. - 1.) * M_PI;
264 
265  s->fft_data[ch][f].re = magnitude * cos(phase);
266  s->fft_data[ch][f].im = magnitude * sin(phase);
267 }
268 
270  int x, int y, int f, int ch)
271 {
272  const int m_linesize = s->magnitude->linesize[0];
273  const int p_linesize = s->phase->linesize[0];
274  const uint8_t *m = (uint8_t *)(s->magnitude->data[0] + y * m_linesize);
275  const uint8_t *p = (uint8_t *)(s->phase->data[0] + y * p_linesize);
276  float magnitude, phase;
277 
278  switch (s->scale) {
279  case LINEAR:
280  magnitude = m[x] / (double)UINT8_MAX;
281  break;
282  case LOG:
283  magnitude = ff_exp10(((m[x] / (double)UINT8_MAX) - 1.) * 6.);
284  break;
285  default:
286  av_assert0(0);
287  }
288  phase = ((p[x] / (double)UINT8_MAX) * 2. - 1.) * M_PI;
289 
290  s->fft_data[ch][f].re = magnitude * cos(phase);
291  s->fft_data[ch][f].im = magnitude * sin(phase);
292 }
293 
294 static void read_fft_data(AVFilterContext *ctx, int x, int h, int ch)
295 {
296  SpectrumSynthContext *s = ctx->priv;
297  AVFilterLink *inlink = ctx->inputs[0];
298  int start = h * (s->channels - ch) - 1;
299  int end = h * (s->channels - ch - 1);
300  int y, f;
301 
302  switch (s->orientation) {
303  case VERTICAL:
304  switch (inlink->format) {
306  case AV_PIX_FMT_GRAY16:
307  for (y = start, f = 0; y >= end; y--, f++) {
308  read16_fft_bin(s, x, y, f, ch);
309  }
310  break;
311  case AV_PIX_FMT_YUVJ444P:
312  case AV_PIX_FMT_YUV444P:
313  case AV_PIX_FMT_GRAY8:
314  for (y = start, f = 0; y >= end; y--, f++) {
315  read8_fft_bin(s, x, y, f, ch);
316  }
317  break;
318  }
319  break;
320  case HORIZONTAL:
321  switch (inlink->format) {
323  case AV_PIX_FMT_GRAY16:
324  for (y = end, f = 0; y <= start; y++, f++) {
325  read16_fft_bin(s, y, x, f, ch);
326  }
327  break;
328  case AV_PIX_FMT_YUVJ444P:
329  case AV_PIX_FMT_YUV444P:
330  case AV_PIX_FMT_GRAY8:
331  for (y = end, f = 0; y <= start; y++, f++) {
332  read8_fft_bin(s, y, x, f, ch);
333  }
334  break;
335  }
336  break;
337  }
338 }
339 
340 static void synth_window(AVFilterContext *ctx, int x)
341 {
342  SpectrumSynthContext *s = ctx->priv;
343  const int h = s->size;
344  int nb = s->win_size;
345  int y, f, ch;
346 
347  for (ch = 0; ch < s->channels; ch++) {
348  read_fft_data(ctx, x, h, ch);
349 
350  for (y = h; y <= s->nb_freq; y++) {
351  s->fft_data[ch][y].re = 0;
352  s->fft_data[ch][y].im = 0;
353  }
354 
355  for (y = s->nb_freq + 1, f = s->nb_freq - 1; y < nb; y++, f--) {
356  s->fft_data[ch][y].re = s->fft_data[ch][f].re;
357  s->fft_data[ch][y].im = -s->fft_data[ch][f].im;
358  }
359 
360  av_fft_permute(s->fft, s->fft_data[ch]);
361  av_fft_calc(s->fft, s->fft_data[ch]);
362  }
363 }
364 
365 static int try_push_frame(AVFilterContext *ctx, int x)
366 {
367  SpectrumSynthContext *s = ctx->priv;
368  AVFilterLink *outlink = ctx->outputs[0];
369  const float factor = s->factor;
370  int ch, n, i, ret;
371  int start, end;
372  AVFrame *out;
373 
374  synth_window(ctx, x);
375 
376  for (ch = 0; ch < s->channels; ch++) {
377  float *buf = (float *)s->buffer->extended_data[ch];
378  int j, k;
379 
380  start = s->start;
381  end = s->end;
382  k = end;
383  for (i = 0, j = start; j < k && i < s->win_size; i++, j++) {
384  buf[j] += s->fft_data[ch][i].re;
385  }
386 
387  for (; i < s->win_size; i++, j++) {
388  buf[j] = s->fft_data[ch][i].re;
389  }
390 
391  start += s->hop_size;
392  end = j;
393 
394  if (start >= s->win_size) {
395  start -= s->win_size;
396  end -= s->win_size;
397 
398  if (ch == s->channels - 1) {
399  float *dst;
400  int c;
401 
402  out = ff_get_audio_buffer(outlink, s->win_size);
403  if (!out) {
405  av_frame_free(&s->phase);
406  return AVERROR(ENOMEM);
407  }
408 
409  out->pts = s->pts;
410  s->pts += s->win_size;
411  for (c = 0; c < s->channels; c++) {
412  dst = (float *)out->extended_data[c];
413  buf = (float *)s->buffer->extended_data[c];
414 
415  for (n = 0; n < s->win_size; n++) {
416  dst[n] = buf[n] * factor;
417  }
418  memmove(buf, buf + s->win_size, s->win_size * 4);
419  }
420 
421  ret = ff_filter_frame(outlink, out);
422  if (ret < 0)
423  return ret;
424  }
425  }
426  }
427 
428  s->start = start;
429  s->end = end;
430 
431  return 0;
432 }
433 
435 {
436  SpectrumSynthContext *s = ctx->priv;
437  int ret, x;
438 
439  if (!(s->magnitude && s->phase))
440  return 0;
441 
442  switch (s->sliding) {
443  case REPLACE:
444  ret = try_push_frame(ctx, s->xpos);
445  s->xpos++;
446  if (s->xpos >= s->xend)
447  s->xpos = 0;
448  break;
449  case SCROLL:
450  s->xpos = s->xend - 1;
451  ret = try_push_frame(ctx, s->xpos);
452  break;
453  case RSCROLL:
454  s->xpos = 0;
455  ret = try_push_frame(ctx, s->xpos);
456  break;
457  case FULLFRAME:
458  for (x = 0; x < s->xend; x++) {
459  ret = try_push_frame(ctx, x);
460  if (ret < 0)
461  break;
462  }
463  break;
464  default:
465  av_assert0(0);
466  }
467 
469  av_frame_free(&s->phase);
470  return ret;
471 }
472 
474 {
475  AVFilterContext *ctx = inlink->dst;
476  SpectrumSynthContext *s = ctx->priv;
477 
478  s->magnitude = magnitude;
479  return try_push_frames(ctx);
480 }
481 
483 {
484  AVFilterContext *ctx = inlink->dst;
485  SpectrumSynthContext *s = ctx->priv;
486 
487  s->phase = phase;
488  return try_push_frames(ctx);
489 }
490 
492 {
493  SpectrumSynthContext *s = ctx->priv;
494  int i;
495 
497  av_frame_free(&s->phase);
498  av_frame_free(&s->buffer);
499  av_fft_end(s->fft);
500  if (s->fft_data) {
501  for (i = 0; i < s->channels; i++)
502  av_freep(&s->fft_data[i]);
503  }
504  av_freep(&s->fft_data);
506 }
507 
509  {
510  .name = "magnitude",
511  .type = AVMEDIA_TYPE_VIDEO,
512  .filter_frame = filter_frame_magnitude,
513  .needs_fifo = 1,
514  },
515  {
516  .name = "phase",
517  .type = AVMEDIA_TYPE_VIDEO,
518  .filter_frame = filter_frame_phase,
519  .needs_fifo = 1,
520  },
521  { NULL }
522 };
523 
525  {
526  .name = "default",
527  .type = AVMEDIA_TYPE_AUDIO,
528  .config_props = config_output,
529  .request_frame = request_frame,
530  },
531  { NULL }
532 };
533 
535  .name = "spectrumsynth",
536  .description = NULL_IF_CONFIG_SMALL("Convert input spectrum videos to audio output."),
537  .uninit = uninit,
538  .query_formats = query_formats,
539  .priv_size = sizeof(SpectrumSynthContext),
540  .inputs = spectrumsynth_inputs,
541  .outputs = spectrumsynth_outputs,
542  .priv_class = &spectrumsynth_class,
543 };
float, planar
Definition: samplefmt.h:69
#define NULL
Definition: coverity.c:32
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
#define av_realloc_f(p, o, n)
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
AVOption.
Definition: opt.h:246
av_cold void av_fft_end(FFTContext *s)
Definition: avfft.c:48
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
Main libavfilter public API header.
AVFILTER_DEFINE_CLASS(spectrumsynth)
channels
Definition: aptx.c:30
int num
Numerator.
Definition: rational.h:59
uint8_t pi<< 24) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_U8,(uint64_t)((*(const uint8_t *) pi-0x80U))<< 56) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16,(*(const int16_t *) pi >>8)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16,(uint64_t)(*(const int16_t *) pi)<< 48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32,(*(const int32_t *) pi >>24)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S32,(uint64_t)(*(const int32_t *) pi)<< 32) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S64,(*(const int64_t *) pi >>56)+0x80) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S64,*(const int64_t *) pi *(1.0f/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64,*(const int64_t *) pi *(1.0/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(const float *) pi *(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(const double *) pi *(INT64_C(1)<< 63)))#define FMT_PAIR_FUNC(out, in) static conv_func_type *const fmt_pair_to_conv_functions[AV_SAMPLE_FMT_NB *AV_SAMPLE_FMT_NB]={FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64),};static void cpy1(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, len);}static void cpy2(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 2 *len);}static void cpy4(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 4 *len);}static void cpy8(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 8 *len);}AudioConvert *swri_audio_convert_alloc(enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, const int *ch_map, int flags){AudioConvert *ctx;conv_func_type *f=fmt_pair_to_conv_functions[av_get_packed_sample_fmt(out_fmt)+AV_SAMPLE_FMT_NB *av_get_packed_sample_fmt(in_fmt)];if(!f) return NULL;ctx=av_mallocz(sizeof(*ctx));if(!ctx) return NULL;if(channels==1){in_fmt=av_get_planar_sample_fmt(in_fmt);out_fmt=av_get_planar_sample_fmt(out_fmt);}ctx->channels=channels;ctx->conv_f=f;ctx->ch_map=ch_map;if(in_fmt==AV_SAMPLE_FMT_U8||in_fmt==AV_SAMPLE_FMT_U8P) memset(ctx->silence, 0x80, sizeof(ctx->silence));if(out_fmt==in_fmt &&!ch_map){switch(av_get_bytes_per_sample(in_fmt)){case 1:ctx->simd_f=cpy1;break;case 2:ctx->simd_f=cpy2;break;case 4:ctx->simd_f=cpy4;break;case 8:ctx->simd_f=cpy8;break;}}if(HAVE_X86ASM &&1) swri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels);if(ARCH_ARM) swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels);if(ARCH_AARCH64) swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels);return ctx;}void swri_audio_convert_free(AudioConvert **ctx){av_freep(ctx);}int swri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, int len){int ch;int off=0;const int os=(out->planar?1:out->ch_count)*out->bps;unsigned misaligned=0;av_assert0(ctx->channels==out->ch_count);if(ctx->in_simd_align_mask){int planes=in->planar?in->ch_count:1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) in->ch[ch];misaligned|=m &ctx->in_simd_align_mask;}if(ctx->out_simd_align_mask){int planes=out->planar?out->ch_count:1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) out->ch[ch];misaligned|=m &ctx->out_simd_align_mask;}if(ctx->simd_f &&!ctx->ch_map &&!misaligned){off=len &~15;av_assert1(off >=0);av_assert1(off<=len);av_assert2(ctx->channels==SWR_CH_MAX||!in->ch[ctx->channels]);if(off >0){if(out->planar==in->planar){int planes=out->planar?out->ch_count:1;for(ch=0;ch< planes;ch++){ctx->simd_f(out-> ch ch
Definition: audioconvert.c:56
FFTSample re
Definition: avfft.h:38
void av_fft_permute(FFTContext *s, FFTComplex *z)
Do the permutation needed BEFORE calling ff_fft_calc().
Definition: avfft.c:38
static void generate_window_func(float *lut, int N, int win_func, float *overlap)
Definition: window_func.h:36
static const AVOption spectrumsynth_options[]
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:244
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
const char * name
Pad name.
Definition: internal.h:60
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:346
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
int ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
Add *ref as a new reference to f.
Definition: formats.c:435
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1080
float * window_func_lut
Window function LUT.
FFTComplex ** fft_data
bins holder for each (displayed) channels
uint8_t
#define av_cold
Definition: attributes.h:82
AVOptions.
#define f(width, name)
Definition: cbs_vp9.c:255
static int query_formats(AVFilterContext *ctx)
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
static const AVFilterPad spectrumsynth_outputs[]
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:388
static int try_push_frames(AVFilterContext *ctx)
static void read16_fft_bin(SpectrumSynthContext *s, int x, int y, int f, int ch)
#define height
#define AV_PIX_FMT_YUV444P16
Definition: pixfmt.h:400
#define av_log(a,...)
SlideMode
A filter pad used for either input or output.
Definition: internal.h:54
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
static av_always_inline double ff_exp10(double x)
Compute 10^x for floating point values.
Definition: ffmath.h:42
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
static void read8_fft_bin(SpectrumSynthContext *s, int x, int y, int f, int ch)
int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout)
Definition: formats.c:343
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Definition: audio.c:86
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
void * priv
private data for use by the filter
Definition: avfilter.h:353
static const AVFilterPad spectrumsynth_inputs[]
simple assert() macros that are a bit more flexible than ISO C assert().
#define V
static void read_fft_data(AVFilterContext *ctx, int x, int h, int ch)
FFTContext * av_fft_init(int nbits, int inverse)
Set up a complex FFT.
Definition: avfft.c:28
#define FFMAX(a, b)
Definition: common.h:94
Definition: fft.h:88
FFTContext * fft
Fast Fourier Transform context.
audio channel layout utility functions
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:371
#define width
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add *ref as a new reference to formats.
Definition: formats.c:440
AVFormatContext * ctx
Definition: movenc.c:48
#define s(width, name)
Definition: cbs_vp9.c:257
static int filter_frame_magnitude(AVFilterLink *inlink, AVFrame *magnitude)
int n
Definition: avisynth_c.h:760
MagnitudeScale
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
A list of supported channel layouts.
Definition: formats.h:85
static av_cold void uninit(AVFilterContext *ctx)
Orientation
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:326
FFT functions.
#define A
void * buf
Definition: avisynth_c.h:766
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
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:144
Rational number (pair of numerator and denominator).
Definition: rational.h:58
int fft_bits
number of bits (FFT window size = 1<<fft_bits)
const char * name
Filter name.
Definition: avfilter.h:148
misc parsing utilities
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:275
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:309
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
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition: rational.h:89
static int request_frame(AVFilterLink *outlink)
internal math functions header
Y , 8bpp.
Definition: pixfmt.h:74
sample_rates
FFTSample im
Definition: avfft.h:38
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:80
int den
Denominator.
Definition: rational.h:60
static int try_push_frame(AVFilterContext *ctx, int x)
AVFilter ff_vaf_spectrumsynth
A list of supported formats for one end of a filter link.
Definition: formats.h:64
An instance of a filter.
Definition: avfilter.h:338
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:701
FILE * out
Definition: movenc.c:54
#define av_freep(p)
#define FF_COUNT2LAYOUT(c)
Encode a channel count as a channel layout.
Definition: formats.h:102
#define M_PI
Definition: mathematics.h:52
static int filter_frame_phase(AVFilterLink *inlink, AVFrame *phase)
int ff_request_frame(AVFilterLink *link)
Request an input frame from the filter at the other end of the link.
Definition: avfilter.c:407
formats
Definition: signature.h:48
internal API functions
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
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:342
static int config_output(AVFilterLink *outlink)
static void synth_window(AVFilterContext *ctx, int x)
void av_fft_calc(FFTContext *s, FFTComplex *z)
Do a complex FFT with the parameters defined in av_fft_init().
Definition: avfft.c:43
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
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 layout
for(j=16;j >0;--j)
#define OFFSET(x)