1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

avfilter/avf_showspectrum: add posibility to display phase

Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
Paul B Mahol 2016-01-10 14:20:59 +01:00
parent 405abdbaee
commit 2009d922db
2 changed files with 55 additions and 4 deletions

View File

@ -14712,6 +14712,9 @@ window function currently used.
@item gain @item gain
Set scale gain for calculating intensity color values. Set scale gain for calculating intensity color values.
Default value is @code{1}. Default value is @code{1}.
@item data
Set which data to display. Can be @code{magnitude}, default or @code{phase}.
@end table @end table
The usage is very similar to the showwaves filter; see the examples in that The usage is very similar to the showwaves filter; see the examples in that

View File

@ -42,6 +42,7 @@
#include "window_func.h" #include "window_func.h"
enum DisplayMode { COMBINED, SEPARATE, NB_MODES }; 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 DisplayScale { LINEAR, SQRT, CBRT, LOG, FOURTHRT, FIFTHRT, NB_SCALES };
enum ColorMode { CHANNEL, INTENSITY, RAINBOW, MORELAND, NEBULAE, FIRE, FIERY, FRUIT, COOL, NB_CLMODES }; enum ColorMode { CHANNEL, INTENSITY, RAINBOW, MORELAND, NEBULAE, FIRE, FIERY, FRUIT, COOL, NB_CLMODES };
enum SlideMode { REPLACE, SCROLL, FULLFRAME, RSCROLL, NB_SLIDES }; enum SlideMode { REPLACE, SCROLL, FULLFRAME, RSCROLL, NB_SLIDES };
@ -60,12 +61,14 @@ typedef struct {
int color_mode; ///< display color scheme int color_mode; ///< display color scheme
int scale; int scale;
float saturation; ///< color saturation multiplier float saturation; ///< color saturation multiplier
int data;
int xpos; ///< x position (current column) int xpos; ///< x position (current column)
FFTContext *fft; ///< Fast Fourier Transform context FFTContext *fft; ///< Fast Fourier Transform context
int fft_bits; ///< number of bits (FFT window size = 1<<fft_bits) int fft_bits; ///< number of bits (FFT window size = 1<<fft_bits)
FFTComplex **fft_data; ///< bins holder for each (displayed) channels FFTComplex **fft_data; ///< bins holder for each (displayed) channels
float *window_func_lut; ///< Window function LUT float *window_func_lut; ///< Window function LUT
float **magnitudes; float **magnitudes;
float **phases;
int win_func; int win_func;
int win_size; int win_size;
double win_scale; 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" }, { "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 }, { "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 }, { "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 } { NULL }
}; };
@ -231,6 +237,11 @@ static av_cold void uninit(AVFilterContext *ctx)
av_freep(&s->magnitudes); av_freep(&s->magnitudes);
av_frame_free(&s->outpicref); av_frame_free(&s->outpicref);
av_audio_fifo_free(s->fifo); 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) static int query_formats(AVFilterContext *ctx)
@ -329,6 +340,15 @@ static int config_output(AVFilterLink *outlink)
return AVERROR(ENOMEM); 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)); s->fft_data = av_calloc(s->nb_display_channels, sizeof(*s->fft_data));
if (!s->fft_data) if (!s->fft_data)
return AVERROR(ENOMEM); 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 RE(y, ch) s->fft_data[ch][y].re
#define IM(y, ch) s->fft_data[ch][y].im #define IM(y, ch) s->fft_data[ch][y].im
#define MAGNITUDE(y, ch) hypot(RE(y, ch), IM(y, ch)) #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) 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) static void acalc_magnitudes(ShowSpectrumContext *s)
{ {
int ch, y, h = s->orientation == VERTICAL ? s->h : s->w; 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]; AVFilterLink *outlink = ctx->outputs[0];
ShowSpectrumContext *s = ctx->priv; ShowSpectrumContext *s = ctx->priv;
AVFrame *outpicref = s->outpicref; 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; const float g = s->gain;
int h = s->orientation == VERTICAL ? s->channel_height : s->channel_width; 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++) { for (ch = 0; ch < s->nb_display_channels; ch++) {
float *magnitudes = s->magnitudes[ch]; float *magnitudes = s->magnitudes[ch];
float *phases = s->phases[ch];
float yf, uf, vf; float yf, uf, vf;
/* decide color range */ /* decide color range */
@ -599,9 +633,20 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples)
for (y = 0; y < h; y++) { for (y = 0; y < h; y++) {
int row = (s->mode == COMBINED) ? y : ch * h + y; int row = (s->mode == COMBINED) ? y : ch * h + y;
float *out = &s->combine_buffer[3 * row]; float *out = &s->combine_buffer[3 * row];
float a;
switch (s->data) {
case D_MAGNITUDE:
/* get magnitude */ /* get magnitude */
float a = g * w * magnitudes[y]; a = g * w * magnitudes[y];
break;
case D_PHASE:
/* get phase */
a = phases[y];
break;
default:
av_assert0(0);
}
/* apply scale */ /* apply scale */
switch (s->scale) { switch (s->scale) {
@ -766,7 +811,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
av_assert0(fin->nb_samples == s->win_size); av_assert0(fin->nb_samples == s->win_size);
run_fft(s, fin); run_fft(s, fin);
if (s->data == D_MAGNITUDE)
calc_magnitudes(s); calc_magnitudes(s);
if (s->data == D_PHASE)
calc_phases(s);
ret = plot_spectrum_column(inlink, fin); ret = plot_spectrum_column(inlink, fin);
av_frame_free(&fin); av_frame_free(&fin);