|  | @@ -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; | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | /* 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 */ |  |  | /* 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); | 
														
													
														
															
																|  |  | 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); |  |  | ret = plot_spectrum_column(inlink, fin); | 
														
													
														
															
																|  |  | av_frame_free(&fin); |  |  | av_frame_free(&fin); | 
														
													
												
													
														
															
																|  | 
 |