diff options
author | Paul B Mahol <onemda@gmail.com> | 2016-01-10 14:20:59 +0100 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2016-01-12 21:21:50 +0100 |
commit | 2009d922db7aeaffd73e23e56580d8d34322ae65 (patch) | |
tree | 08e884cfdf1a6162e4169b16d5c18ff2967aeb03 /libavfilter/avf_showspectrum.c | |
parent | 405abdbaee5239e301d3ed5370b059f9b0c2da16 (diff) | |
download | ffmpeg-2009d922db7aeaffd73e23e56580d8d34322ae65.tar.gz |
avfilter/avf_showspectrum: add posibility to display phase
Signed-off-by: Paul B Mahol <onemda@gmail.com>
Diffstat (limited to 'libavfilter/avf_showspectrum.c')
-rw-r--r-- | libavfilter/avf_showspectrum.c | 56 |
1 files changed, 52 insertions, 4 deletions
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<<fft_bits) FFTComplex **fft_data; ///< bins holder for each (displayed) channels float *window_func_lut; ///< Window function LUT float **magnitudes; + float **phases; int win_func; int win_size; double win_scale; @@ -134,6 +137,9 @@ static const AVOption showspectrum_options[] = { { "horizontal", NULL, 0, AV_OPT_TYPE_CONST, {.i64=HORIZONTAL}, 0, 0, FLAGS, "orientation" }, { "overlap", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_FLOAT, {.dbl = 0}, 0, 1, FLAGS }, { "gain", "set scale gain", OFFSET(gain), AV_OPT_TYPE_FLOAT, {.dbl = 1}, 0, 128, FLAGS }, + { "data", "set data mode", OFFSET(data), AV_OPT_TYPE_INT, {.i64 = 0}, 0, NB_DMODES-1, FLAGS, "data" }, + { "magnitude", NULL, 0, AV_OPT_TYPE_CONST, {.i64=D_MAGNITUDE}, 0, 0, FLAGS, "data" }, + { "phase", NULL, 0, AV_OPT_TYPE_CONST, {.i64=D_PHASE}, 0, 0, FLAGS, "data" }, { NULL } }; @@ -231,6 +237,11 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->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); |