From 2009d922db7aeaffd73e23e56580d8d34322ae65 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 10 Jan 2016 14:20:59 +0100 Subject: [PATCH] avfilter/avf_showspectrum: add posibility to display phase Signed-off-by: Paul B Mahol --- doc/filters.texi | 3 ++ libavfilter/avf_showspectrum.c | 56 +++++++++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index efb050d303..45d22f49db 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -14712,6 +14712,9 @@ window function currently used. @item gain Set scale gain for calculating intensity color values. Default value is @code{1}. + +@item data +Set which data to display. Can be @code{magnitude}, default or @code{phase}. @end table The usage is very similar to the showwaves filter; see the examples in that diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c index 36cbdb2e69..7fd0ea99d0 100644 --- a/libavfilter/avf_showspectrum.c +++ b/libavfilter/avf_showspectrum.c @@ -42,6 +42,7 @@ #include "window_func.h" enum DisplayMode { COMBINED, SEPARATE, NB_MODES }; +enum DataMode { D_MAGNITUDE, D_PHASE, NB_DMODES }; enum DisplayScale { LINEAR, SQRT, CBRT, LOG, FOURTHRT, FIFTHRT, NB_SCALES }; enum ColorMode { CHANNEL, INTENSITY, RAINBOW, MORELAND, NEBULAE, FIRE, FIERY, FRUIT, COOL, NB_CLMODES }; enum SlideMode { REPLACE, SCROLL, FULLFRAME, RSCROLL, NB_SLIDES }; @@ -60,12 +61,14 @@ typedef struct { int color_mode; ///< display color scheme int scale; float saturation; ///< color saturation multiplier + int data; int xpos; ///< x position (current column) FFTContext *fft; ///< Fast Fourier Transform context int fft_bits; ///< number of bits (FFT window size = 1<magnitudes); av_frame_free(&s->outpicref); av_audio_fifo_free(s->fifo); + if (s->phases) { + for (i = 0; i < s->nb_display_channels; i++) + av_freep(&s->phases[i]); + } + av_freep(&s->phases); } static int query_formats(AVFilterContext *ctx) @@ -329,6 +340,15 @@ static int config_output(AVFilterLink *outlink) return AVERROR(ENOMEM); } + s->phases = av_calloc(s->nb_display_channels, sizeof(*s->magnitudes)); + if (!s->phases) + return AVERROR(ENOMEM); + for (i = 0; i < s->nb_display_channels; i++) { + s->phases[i] = av_calloc(s->orientation == VERTICAL ? s->h : s->w, sizeof(**s->phases)); + if (!s->phases[i]) + return AVERROR(ENOMEM); + } + s->fft_data = av_calloc(s->nb_display_channels, sizeof(*s->fft_data)); if (!s->fft_data) return AVERROR(ENOMEM); @@ -427,6 +447,7 @@ static void run_fft(ShowSpectrumContext *s, AVFrame *fin) #define RE(y, ch) s->fft_data[ch][y].re #define IM(y, ch) s->fft_data[ch][y].im #define MAGNITUDE(y, ch) hypot(RE(y, ch), IM(y, ch)) +#define PHASE(y, ch) atan2(IM(y, ch), RE(y, ch)) static void calc_magnitudes(ShowSpectrumContext *s) { @@ -440,6 +461,18 @@ static void calc_magnitudes(ShowSpectrumContext *s) } } +static void calc_phases(ShowSpectrumContext *s) +{ + int ch, y, h = s->orientation == VERTICAL ? s->h : s->w; + + for (ch = 0; ch < s->nb_display_channels; ch++) { + float *phases = s->phases[ch]; + + for (y = 0; y < h; y++) + phases[y] = (PHASE(y, ch) / M_PI + 1) / 2; + } +} + static void acalc_magnitudes(ShowSpectrumContext *s) { int ch, y, h = s->orientation == VERTICAL ? s->h : s->w; @@ -578,7 +611,7 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples) AVFilterLink *outlink = ctx->outputs[0]; ShowSpectrumContext *s = ctx->priv; AVFrame *outpicref = s->outpicref; - const double w = s->win_scale; + const double w = s->data == D_PHASE ? 1 : s->win_scale; const float g = s->gain; int h = s->orientation == VERTICAL ? s->channel_height : s->channel_width; @@ -590,6 +623,7 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples) for (ch = 0; ch < s->nb_display_channels; ch++) { float *magnitudes = s->magnitudes[ch]; + float *phases = s->phases[ch]; float yf, uf, vf; /* decide color range */ @@ -599,9 +633,20 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples) for (y = 0; y < h; y++) { int row = (s->mode == COMBINED) ? y : ch * h + y; float *out = &s->combine_buffer[3 * row]; + float a; - /* get magnitude */ - float a = g * w * magnitudes[y]; + switch (s->data) { + case D_MAGNITUDE: + /* get magnitude */ + a = g * w * magnitudes[y]; + break; + case D_PHASE: + /* get phase */ + a = phases[y]; + break; + default: + av_assert0(0); + } /* apply scale */ switch (s->scale) { @@ -766,7 +811,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) av_assert0(fin->nb_samples == s->win_size); run_fft(s, fin); - calc_magnitudes(s); + if (s->data == D_MAGNITUDE) + calc_magnitudes(s); + if (s->data == D_PHASE) + calc_phases(s); ret = plot_spectrum_column(inlink, fin); av_frame_free(&fin);