X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Favf_showfreqs.c;h=0b8067116cc345be728e48c5fecc1aa26d3e1e53;hb=a04ad248a05e7b613abe09b3bb067f555108d794;hp=e65aa60eecc839480ada90be48a74ffaa4f4cd4e;hpb=fc0de1c04be47ddb977eca449a3d62f3600466a4;p=ffmpeg diff --git a/libavfilter/avf_showfreqs.c b/libavfilter/avf_showfreqs.c index e65aa60eecc..0b8067116cc 100644 --- a/libavfilter/avf_showfreqs.c +++ b/libavfilter/avf_showfreqs.c @@ -36,6 +36,7 @@ #include "internal.h" #include "window_func.h" +enum DataMode { MAGNITUDE, PHASE, DELAY, NB_DATA }; enum DisplayMode { LINE, BAR, DOT, NB_MODES }; enum ChannelMode { COMBINED, SEPARATE, NB_CMODES }; enum FrequencyScale { FS_LINEAR, FS_LOG, FS_RLOG, NB_FSCALES }; @@ -45,7 +46,9 @@ typedef struct ShowFreqsContext { const AVClass *class; int w, h; int mode; + int data_mode; int cmode; + int fft_size; int fft_bits; int ascale, fscale; int avg; @@ -85,20 +88,7 @@ static const AVOption showfreqs_options[] = { { "lin", "linear", 0, AV_OPT_TYPE_CONST, {.i64=FS_LINEAR}, 0, 0, FLAGS, "fscale" }, { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=FS_LOG}, 0, 0, FLAGS, "fscale" }, { "rlog", "reverse logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=FS_RLOG}, 0, 0, FLAGS, "fscale" }, - { "win_size", "set window size", OFFSET(fft_bits), AV_OPT_TYPE_INT, {.i64=11}, 4, 16, FLAGS, "fft" }, - { "w16", 0, 0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, FLAGS, "fft" }, - { "w32", 0, 0, AV_OPT_TYPE_CONST, {.i64=5}, 0, 0, FLAGS, "fft" }, - { "w64", 0, 0, AV_OPT_TYPE_CONST, {.i64=6}, 0, 0, FLAGS, "fft" }, - { "w128", 0, 0, AV_OPT_TYPE_CONST, {.i64=7}, 0, 0, FLAGS, "fft" }, - { "w256", 0, 0, AV_OPT_TYPE_CONST, {.i64=8}, 0, 0, FLAGS, "fft" }, - { "w512", 0, 0, AV_OPT_TYPE_CONST, {.i64=9}, 0, 0, FLAGS, "fft" }, - { "w1024", 0, 0, AV_OPT_TYPE_CONST, {.i64=10}, 0, 0, FLAGS, "fft" }, - { "w2048", 0, 0, AV_OPT_TYPE_CONST, {.i64=11}, 0, 0, FLAGS, "fft" }, - { "w4096", 0, 0, AV_OPT_TYPE_CONST, {.i64=12}, 0, 0, FLAGS, "fft" }, - { "w8192", 0, 0, AV_OPT_TYPE_CONST, {.i64=13}, 0, 0, FLAGS, "fft" }, - { "w16384", 0, 0, AV_OPT_TYPE_CONST, {.i64=14}, 0, 0, FLAGS, "fft" }, - { "w32768", 0, 0, AV_OPT_TYPE_CONST, {.i64=15}, 0, 0, FLAGS, "fft" }, - { "w65536", 0, 0, AV_OPT_TYPE_CONST, {.i64=16}, 0, 0, FLAGS, "fft" }, + { "win_size", "set window size", OFFSET(fft_size), AV_OPT_TYPE_INT, {.i64=2048}, 16, 65536, FLAGS }, { "win_func", "set window function", OFFSET(win_func), AV_OPT_TYPE_INT, {.i64=WFUNC_HANNING}, 0, NB_WFUNC-1, FLAGS, "win_func" }, { "rect", "Rectangular", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_RECT}, 0, 0, FLAGS, "win_func" }, { "bartlett", "Bartlett", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BARTLETT}, 0, 0, FLAGS, "win_func" }, @@ -127,6 +117,10 @@ static const AVOption showfreqs_options[] = { { "combined", "show all channels in same window", 0, AV_OPT_TYPE_CONST, {.i64=COMBINED}, 0, 0, FLAGS, "cmode" }, { "separate", "show each channel in own window", 0, AV_OPT_TYPE_CONST, {.i64=SEPARATE}, 0, 0, FLAGS, "cmode" }, { "minamp", "set minimum amplitude", OFFSET(minamp), AV_OPT_TYPE_FLOAT, {.dbl=1e-6}, FLT_MIN, 1e-6, FLAGS }, + { "data", "set data mode", OFFSET(data_mode), AV_OPT_TYPE_INT, {.i64=MAGNITUDE}, 0, NB_DATA-1, FLAGS, "data" }, + { "magnitude", "show magnitude", 0, AV_OPT_TYPE_CONST, {.i64=MAGNITUDE}, 0, 0, FLAGS, "data" }, + { "phase", "show phase", 0, AV_OPT_TYPE_CONST, {.i64=PHASE}, 0, 0, FLAGS, "data" }, + { "delay", "show group delay",0, AV_OPT_TYPE_CONST, {.i64=DELAY}, 0, 0, FLAGS, "data" }, { NULL } }; @@ -144,20 +138,20 @@ static int query_formats(AVFilterContext *ctx) /* set input audio formats */ formats = ff_make_format_list(sample_fmts); - if ((ret = ff_formats_ref(formats, &inlink->out_formats)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.formats)) < 0) return ret; layouts = ff_all_channel_layouts(); - if ((ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0) return ret; formats = ff_all_samplerates(); - if ((ret = ff_formats_ref(formats, &inlink->out_samplerates)) < 0) + if ((ret = ff_formats_ref(formats, &inlink->outcfg.samplerates)) < 0) return ret; /* set output video format */ formats = ff_make_format_list(pix_fmts); - if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) + if ((ret = ff_formats_ref(formats, &outlink->incfg.formats)) < 0) return ret; return 0; @@ -180,6 +174,7 @@ static int config_output(AVFilterLink *outlink) float overlap; int i; + s->fft_bits = av_log2(s->fft_size); s->nb_freq = 1 << (s->fft_bits - 1); s->win_size = s->nb_freq << 1; av_audio_fifo_free(s->fifo); @@ -206,7 +201,7 @@ static int config_output(AVFilterLink *outlink) if (!s->fft_data) return AVERROR(ENOMEM); s->avg_data = av_calloc(s->nb_channels, sizeof(*s->avg_data)); - if (!s->fft_data) + if (!s->avg_data) return AVERROR(ENOMEM); for (i = 0; i < s->nb_channels; i++) { s->fft_data[i] = av_calloc(s->win_size, sizeof(**s->fft_data)); @@ -408,6 +403,7 @@ static int plot_freqs(AVFilterLink *inlink, AVFrame *in) #define RE(x, ch) s->fft_data[ch][x].re #define IM(x, ch) s->fft_data[ch][x].im #define M(a, b) (sqrt((a) * (a) + (b) * (b))) +#define P(a, b) (atan2((b), (a))) colors = av_strdup(s->colors); if (!colors) { @@ -424,13 +420,37 @@ static int plot_freqs(AVFilterLink *inlink, AVFrame *in) if (color) av_parse_color(fg, color, -1, ctx); - a = av_clipd(M(RE(0, ch), 0) / s->scale, 0, 1); - plot_freq(s, ch, a, 0, fg, &prev_y, out, outlink); - - for (f = 1; f < s->nb_freq; f++) { - a = av_clipd(M(RE(f, ch), IM(f, ch)) / s->scale, 0, 1); - - plot_freq(s, ch, a, f, fg, &prev_y, out, outlink); + switch (s->data_mode) { + case MAGNITUDE: + a = av_clipd(M(RE(0, ch), 0) / s->scale, 0, 1); + plot_freq(s, ch, a, 0, fg, &prev_y, out, outlink); + + for (f = 1; f < s->nb_freq; f++) { + a = av_clipd(M(RE(f, ch), IM(f, ch)) / s->scale, 0, 1); + + plot_freq(s, ch, a, f, fg, &prev_y, out, outlink); + } + break; + case PHASE: + a = av_clipd((M_PI + P(RE(0, ch), 0)) / (2. * M_PI), 0, 1); + plot_freq(s, ch, a, 0, fg, &prev_y, out, outlink); + + for (f = 1; f < s->nb_freq; f++) { + a = av_clipd((M_PI + P(RE(f, ch), IM(f, ch))) / (2. * M_PI), 0, 1); + + plot_freq(s, ch, a, f, fg, &prev_y, out, outlink); + } + break; + case DELAY: + plot_freq(s, ch, 0, 0, fg, &prev_y, out, outlink); + + for (f = 1; f < s->nb_freq; f++) { + a = av_clipd((M_PI - P(IM(f, ch) * RE(f-1, ch) - IM(f-1, ch) * RE(f, ch), + RE(f, ch) * RE(f-1, ch) + IM(f, ch) * IM(f-1, ch))) / (2. * M_PI), 0, 1); + + plot_freq(s, ch, a, f, fg, &prev_y, out, outlink); + } + break; } } @@ -486,6 +506,7 @@ static int activate(AVFilterContext *ctx) av_audio_fifo_write(s->fifo, (void **)in->extended_data, in->nb_samples); if (s->pts == AV_NOPTS_VALUE) s->pts = in->pts; + av_frame_free(&in); } if (av_audio_fifo_size(s->fifo) >= s->win_size) { @@ -535,7 +556,7 @@ static const AVFilterPad showfreqs_outputs[] = { { NULL } }; -AVFilter ff_avf_showfreqs = { +const AVFilter ff_avf_showfreqs = { .name = "showfreqs", .description = NULL_IF_CONFIG_SMALL("Convert input audio to a frequencies video output."), .init = init,