Created
January 31, 2013 16:46
-
-
Save anonymous/4684260 to your computer and use it in GitHub Desktop.
stdin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 671953c992bd8a86f70034dee78e1d577329b1d5 Mon Sep 17 00:00:00 2001 | |
From: Rudolf Polzer <divverent@xonotic.org> | |
Date: Thu, 31 Jan 2013 17:43:14 +0100 | |
Subject: [PATCH 1/5] lavfi/showspectrum: display multiple channels in separate | |
row | |
A behaviour similar to the old one can be selected by specifying | |
"combined=0" as options to the filter. However, multichannel support is | |
provided in both views. | |
Signed-off-by: Rudolf Polzer <divverent@xonotic.org> | |
--- | |
doc/filters.texi | 4 ++ | |
libavfilter/avf_showspectrum.c | 135 +++++++++++++++++++++++++++++++---------- | |
2 files changed, 106 insertions(+), 33 deletions(-) | |
diff --git a/doc/filters.texi b/doc/filters.texi | |
index 21e2cff..73674cb 100644 | |
--- a/doc/filters.texi | |
+++ b/doc/filters.texi | |
@@ -5709,6 +5709,10 @@ Specify the video size for the output. Default value is @code{640x480}. | |
@item slide | |
Specify if the spectrum should slide along the window. Default value is | |
@code{0}. | |
+ at item compat | |
+Specify if the old mode, where up to 2 channels are displayed in same row, | |
+should be used. Default value is | |
+ at code{0}. | |
@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 977fca9..4355b3b 100644 | |
--- a/libavfilter/avf_showspectrum.c | |
+++ b/libavfilter/avf_showspectrum.c | |
@@ -37,14 +37,17 @@ typedef struct { | |
int w, h; | |
AVFilterBufferRef *outpicref; | |
int req_fullfilled; | |
+ int nb_display_channels; | |
int sliding; ///< 1 if sliding mode, 0 otherwise | |
+ int combined; ///< use old-style combined channel display mode | |
int xpos; ///< x position (current column) | |
RDFTContext *rdft; ///< Real Discrete Fourier Transform context | |
int rdft_bits; ///< number of bits (RDFT window size = 1<<rdft_bits) | |
- FFTSample *rdft_data; ///< bins holder for each (displayed) channels | |
+ FFTSample **rdft_data; ///< bins holder for each (displayed) channels | |
int filled; ///< number of samples (per channel) filled in current rdft_buffer | |
int consumed; ///< number of samples (per channel) consumed from the input frame | |
float *window_func_lut; ///< Window function LUT | |
+ float *combine_buffer; ///< color combining buffer (3 * h items) | |
} ShowSpectrumContext; | |
#define OFFSET(x) offsetof(ShowSpectrumContext, x) | |
@@ -54,6 +57,7 @@ static const AVOption showspectrum_options[] = { | |
{ "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "640x480"}, 0, 0, FLAGS }, | |
{ "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "640x480"}, 0, 0, FLAGS }, | |
{ "slide", "set sliding mode", OFFSET(sliding), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS }, | |
+ { "combined", "set combined mode", OFFSET(combined), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS }, | |
{ NULL }, | |
}; | |
@@ -76,8 +80,12 @@ static av_cold int init(AVFilterContext *ctx, const char *args) | |
static av_cold void uninit(AVFilterContext *ctx) | |
{ | |
ShowSpectrumContext *showspectrum = ctx->priv; | |
+ int i; | |
+ av_freep(&showspectrum->combine_buffer); | |
av_rdft_end(showspectrum->rdft); | |
+ for (i = 0; i < showspectrum->nb_display_channels; i++) | |
+ av_freep(&showspectrum->rdft_data[i]); | |
av_freep(&showspectrum->rdft_data); | |
av_freep(&showspectrum->window_func_lut); | |
avfilter_unref_bufferp(&showspectrum->outpicref); | |
@@ -90,7 +98,7 @@ static int query_formats(AVFilterContext *ctx) | |
AVFilterLink *inlink = ctx->inputs[0]; | |
AVFilterLink *outlink = ctx->outputs[0]; | |
static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }; | |
- static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_RGB24, AV_PIX_FMT_NONE }; | |
+ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_NONE }; | |
/* set input audio formats */ | |
formats = ff_make_format_list(sample_fmts); | |
@@ -120,14 +128,17 @@ static int query_formats(AVFilterContext *ctx) | |
static int config_output(AVFilterLink *outlink) | |
{ | |
AVFilterContext *ctx = outlink->src; | |
+ AVFilterLink *inlink = ctx->inputs[0]; | |
ShowSpectrumContext *showspectrum = ctx->priv; | |
- int i, rdft_bits, win_size; | |
+ int i, rdft_bits, win_size, h; | |
outlink->w = showspectrum->w; | |
outlink->h = showspectrum->h; | |
+ h = showspectrum->combined ? outlink->h : outlink->h / inlink->channels; | |
+ | |
/* RDFT window size (precision) according to the requested output frame height */ | |
- for (rdft_bits = 1; 1<<rdft_bits < 2*outlink->h; rdft_bits++); | |
+ for (rdft_bits = 1; 1 << rdft_bits < 2 * h; rdft_bits++); | |
win_size = 1 << rdft_bits; | |
/* (re-)configuration if the video output changed (or first init) */ | |
@@ -142,12 +153,23 @@ static int config_output(AVFilterLink *outlink) | |
/* RDFT buffers: x2 for each (display) channel buffer. | |
* Note: we use free and malloc instead of a realloc-like function to | |
* make sure the buffer is aligned in memory for the FFT functions. */ | |
+ for (i = 0; i < showspectrum->nb_display_channels; i++) | |
+ av_freep(&showspectrum->rdft_data[i]); | |
av_freep(&showspectrum->rdft_data); | |
- if (av_size_mult(sizeof(*showspectrum->rdft_data), 2 * win_size, &rdft_size) < 0) | |
+ showspectrum->nb_display_channels = inlink->channels; | |
+ | |
+ if (av_size_mult(sizeof(*showspectrum->rdft_data), | |
+ showspectrum->nb_display_channels * win_size, &rdft_size) < 0) | |
return AVERROR(EINVAL); | |
- showspectrum->rdft_data = av_malloc(rdft_size); | |
+ showspectrum->rdft_data = av_malloc(showspectrum->nb_display_channels * | |
+ sizeof(*showspectrum->rdft_data)); | |
if (!showspectrum->rdft_data) | |
return AVERROR(ENOMEM); | |
+ for (i = 0; i < showspectrum->nb_display_channels; i++) { | |
+ showspectrum->rdft_data[i] = av_malloc(rdft_size); | |
+ if (!showspectrum->rdft_data[i]) | |
+ return AVERROR(ENOMEM); | |
+ } | |
showspectrum->filled = 0; | |
/* pre-calc windowing function (hann here) */ | |
@@ -173,6 +195,10 @@ static int config_output(AVFilterLink *outlink) | |
if (showspectrum->xpos >= outlink->w) | |
showspectrum->xpos = 0; | |
+ showspectrum->combine_buffer = av_realloc(showspectrum->combine_buffer, | |
+ outlink->h * 3 * | |
+ sizeof(*showspectrum->combine_buffer)); | |
+ | |
av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d RDFT window size:%d\n", | |
showspectrum->w, showspectrum->h, win_size); | |
return 0; | |
@@ -213,62 +239,105 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFilterBufferRef *insampl | |
AVFilterLink *outlink = ctx->outputs[0]; | |
ShowSpectrumContext *showspectrum = ctx->priv; | |
AVFilterBufferRef *outpicref = showspectrum->outpicref; | |
- const int nb_channels = av_get_channel_layout_nb_channels(insamples->audio->channel_layout); | |
/* nb_freq contains the power of two superior or equal to the output image | |
* height (or half the RDFT window size) */ | |
const int nb_freq = 1 << (showspectrum->rdft_bits - 1); | |
const int win_size = nb_freq << 1; | |
+ const double w = 1. / sqrt(nb_freq); | |
- int ch, n, y; | |
- FFTSample *data[2]; | |
- const int nb_display_channels = FFMIN(nb_channels, 2); | |
+ int ch, plane, n, y; | |
const int start = showspectrum->filled; | |
const int add_samples = FFMIN(win_size - start, nb_samples); | |
/* fill RDFT input with the number of samples available */ | |
- for (ch = 0; ch < nb_display_channels; ch++) { | |
+ for (ch = 0; ch < showspectrum->nb_display_channels; ch++) { | |
const int16_t *p = (int16_t *)insamples->extended_data[ch]; | |
p += showspectrum->consumed; | |
- data[ch] = showspectrum->rdft_data + win_size * ch; // select channel buffer | |
for (n = 0; n < add_samples; n++) | |
- data[ch][start + n] = p[n] * showspectrum->window_func_lut[start + n]; | |
+ showspectrum->rdft_data[ch][start + n] = p[n] * showspectrum->window_func_lut[start + n]; | |
} | |
showspectrum->filled += add_samples; | |
/* complete RDFT window size? */ | |
if (showspectrum->filled == win_size) { | |
+ /* channel height */ | |
+ int h = showspectrum->combined ? outlink->h : outlink->h / showspectrum->nb_display_channels; | |
+ | |
/* run RDFT on each samples set */ | |
- for (ch = 0; ch < nb_display_channels; ch++) | |
- av_rdft_calc(showspectrum->rdft, data[ch]); | |
+ for (ch = 0; ch < showspectrum->nb_display_channels; ch++) | |
+ av_rdft_calc(showspectrum->rdft, showspectrum->rdft_data[ch]); | |
/* fill a new spectrum column */ | |
-#define RE(ch) data[ch][2*y + 0] | |
-#define IM(ch) data[ch][2*y + 1] | |
-#define MAGNITUDE(re, im) sqrt((re)*(re) + (im)*(im)) | |
+#define RE(y,ch) showspectrum->rdft_data[ch][2*y + 0] | |
+#define IM(y,ch) showspectrum->rdft_data[ch][2*y + 1] | |
+#define CPLX_MAGNITUDE(re, im) sqrt((re)*(re) + (im)*(im)) /* is actually hypot(re, im) */ | |
+#define MAGNITUDE(y,ch) CPLX_MAGNITUDE(RE(y,ch), IM(y,ch)) | |
+ /* initialize buffer for combining to black */ | |
for (y = 0; y < outlink->h; y++) { | |
- // FIXME: bin[0] contains first and last bins | |
- uint8_t *p = outpicref->data[0] + (outlink->h - y - 1) * outpicref->linesize[0]; | |
- const double w = 1. / sqrt(nb_freq); | |
- int a = sqrt(w * MAGNITUDE(RE(0), IM(0))); | |
- int b = nb_display_channels > 1 ? sqrt(w * MAGNITUDE(RE(1), IM(1))) : a; | |
- | |
- if (showspectrum->sliding) { | |
- memmove(p, p + 3, (outlink->w - 1) * 3); | |
- p += (outlink->w - 1) * 3; | |
+ showspectrum->combine_buffer[3*y] = 0; | |
+ showspectrum->combine_buffer[3*y+1] = 127.5; | |
+ showspectrum->combine_buffer[3*y+2] = 127.5; | |
+ } | |
+ | |
+ for (ch = 0; ch < showspectrum->nb_display_channels; ch++) { | |
+ float yf, uf, vf; | |
+ | |
+ /* decide channel colors */ | |
+ if (showspectrum->combined) { | |
+ // reduce range by channel count | |
+ yf = 1.0f / showspectrum->nb_display_channels; | |
+ uf = yf; | |
+ vf = yf; | |
} else { | |
- p += showspectrum->xpos * 3; | |
+ // full range | |
+ yf = 1.0f; | |
+ uf = 0.5f; | |
+ vf = 0.5f; | |
+ } | |
+ if (showspectrum->nb_display_channels >= 2) { | |
+ uf *= cos((2 * M_PI * ch) / showspectrum->nb_display_channels); | |
+ vf *= sin((2 * M_PI * ch) / showspectrum->nb_display_channels); | |
+ } else { | |
+ uf = 0.0f; | |
+ vf = 0.0f; | |
} | |
- a = FFMIN(a, 255); | |
- b = FFMIN(b, 255); | |
- p[0] = a; | |
- p[1] = b; | |
- p[2] = (a + b) / 2; | |
+ /* draw the channel */ | |
+ for (y = 0; y < h; y++) { | |
+ int row = showspectrum->combined ? y : ch * h + y; | |
+ float a = sqrt(w * MAGNITUDE(y, ch)); | |
+ float *out = &showspectrum->combine_buffer[3 * row]; | |
+ out[0] += a * yf; | |
+ out[1] += a * vf; | |
+ out[2] += a * uf; | |
+ } | |
} | |
+ | |
+ /* copy to output */ | |
+ if (showspectrum->sliding) { | |
+ for (plane = 0; plane < 3; plane++) { | |
+ for (y = 0; y < outlink->h; y++) { | |
+ uint8_t *p = outpicref->data[plane] + | |
+ y * outpicref->linesize[plane]; | |
+ memmove(p, p + 1, outlink->w - 1); | |
+ } | |
+ } | |
+ showspectrum->xpos = outlink->w - 1; | |
+ } | |
+ for (plane = 0; plane < 3; plane++) { | |
+ uint8_t *p = outpicref->data[plane] + | |
+ (outlink->h - 1) * outpicref->linesize[plane] + | |
+ showspectrum->xpos; | |
+ for (y = 0; y < outlink->h; y++) { | |
+ *p = rint(FFMAX(0, FFMIN(showspectrum->combine_buffer[3*y + plane], 255))); | |
+ p -= outpicref->linesize[plane]; | |
+ } | |
+ } | |
+ | |
outpicref->pts = insamples->pts + | |
av_rescale_q(showspectrum->consumed, | |
(AVRational){ 1, inlink->sample_rate }, | |
-- | |
1.8.1.1 | |
From 0b6e1930e7cc0087d1439044fc94ce5a73ad8ae1 Mon Sep 17 00:00:00 2001 | |
From: Rudolf Polzer <divverent@xonotic.org> | |
Date: Thu, 31 Jan 2013 14:11:24 +0100 | |
Subject: [PATCH 2/5] lavfi/showspectrum: add a "saturation" option to tune | |
coloring | |
Signed-off-by: Rudolf Polzer <divverent@xonotic.org> | |
--- | |
libavfilter/avf_showspectrum.c | 4 ++++ | |
1 file changed, 4 insertions(+) | |
diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c | |
index 4355b3b..59f9891 100644 | |
--- a/libavfilter/avf_showspectrum.c | |
+++ b/libavfilter/avf_showspectrum.c | |
@@ -40,6 +40,7 @@ typedef struct { | |
int nb_display_channels; | |
int sliding; ///< 1 if sliding mode, 0 otherwise | |
int combined; ///< use old-style combined channel display mode | |
+ float saturation; ///< color saturation multiplier | |
int xpos; ///< x position (current column) | |
RDFTContext *rdft; ///< Real Discrete Fourier Transform context | |
int rdft_bits; ///< number of bits (RDFT window size = 1<<rdft_bits) | |
@@ -58,6 +59,7 @@ static const AVOption showspectrum_options[] = { | |
{ "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "640x480"}, 0, 0, FLAGS }, | |
{ "slide", "set sliding mode", OFFSET(sliding), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS }, | |
{ "combined", "set combined mode", OFFSET(combined), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS }, | |
+ { "saturation", "color saturation multiplier", OFFSET(saturation), AV_OPT_TYPE_FLOAT, {.dbl = 1}, -10, 10, FLAGS }, | |
{ NULL }, | |
}; | |
@@ -305,6 +307,8 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFilterBufferRef *insampl | |
uf = 0.0f; | |
vf = 0.0f; | |
} | |
+ uf *= showspectrum->saturation; | |
+ vf *= showspectrum->saturation; | |
/* draw the channel */ | |
for (y = 0; y < h; y++) { | |
-- | |
1.8.1.1 | |
From b753ebde75f0ccfb69a9795ca372c2b1a144b42e Mon Sep 17 00:00:00 2001 | |
From: Rudolf Polzer <divverent@xonotic.org> | |
Date: Thu, 31 Jan 2013 14:03:39 +0100 | |
Subject: [PATCH 3/5] lavfi/showspectrum: replace sqrt() using macro by a call | |
to hypot() | |
hypot() exists on most libcs even before C99, and thus shouldn't be a | |
problem to use. This avoids a bad case of multiple argument evaluation. | |
Signed-off-by: Rudolf Polzer <divverent@xonotic.org> | |
--- | |
libavfilter/avf_showspectrum.c | 3 +-- | |
1 file changed, 1 insertion(+), 2 deletions(-) | |
diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c | |
index 59f9891..c15a158 100644 | |
--- a/libavfilter/avf_showspectrum.c | |
+++ b/libavfilter/avf_showspectrum.c | |
@@ -275,8 +275,7 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFilterBufferRef *insampl | |
/* fill a new spectrum column */ | |
#define RE(y,ch) showspectrum->rdft_data[ch][2*y + 0] | |
#define IM(y,ch) showspectrum->rdft_data[ch][2*y + 1] | |
-#define CPLX_MAGNITUDE(re, im) sqrt((re)*(re) + (im)*(im)) /* is actually hypot(re, im) */ | |
-#define MAGNITUDE(y,ch) CPLX_MAGNITUDE(RE(y,ch), IM(y,ch)) | |
+#define MAGNITUDE(y,ch) hypot(RE(y,ch), IM(y,ch)) | |
/* initialize buffer for combining to black */ | |
for (y = 0; y < outlink->h; y++) { | |
-- | |
1.8.1.1 | |
From 0e7c76b2720a9b46510796c347b774d3f3b809ad Mon Sep 17 00:00:00 2001 | |
From: Rudolf Polzer <divverent@xonotic.org> | |
Date: Thu, 31 Jan 2013 17:22:50 +0100 | |
Subject: [PATCH 4/5] lavfi/showspectrum: logarithmic scale, intensity based | |
coloring | |
Signed-off-by: Rudolf Polzer <divverent@xonotic.org> | |
--- | |
libavfilter/avf_showspectrum.c | 106 ++++++++++++++++++++++++++++++++++------- | |
1 file changed, 88 insertions(+), 18 deletions(-) | |
diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c | |
index c15a158..80ec6e6 100644 | |
--- a/libavfilter/avf_showspectrum.c | |
+++ b/libavfilter/avf_showspectrum.c | |
@@ -39,7 +39,9 @@ typedef struct { | |
int req_fullfilled; | |
int nb_display_channels; | |
int sliding; ///< 1 if sliding mode, 0 otherwise | |
- int combined; ///< use old-style combined channel display mode | |
+ int combined; ///< use combined channel display mode | |
+ int intensity_colors; ///< use intensity-based coloring | |
+ int logscale; ///< use logarithmic scale | |
float saturation; ///< color saturation multiplier | |
int xpos; ///< x position (current column) | |
RDFTContext *rdft; ///< Real Discrete Fourier Transform context | |
@@ -59,12 +61,30 @@ static const AVOption showspectrum_options[] = { | |
{ "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "640x480"}, 0, 0, FLAGS }, | |
{ "slide", "set sliding mode", OFFSET(sliding), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS }, | |
{ "combined", "set combined mode", OFFSET(combined), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS }, | |
+ { "intensity", "set intensity based coloring", OFFSET(intensity_colors), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS }, | |
+ { "logscale", "set logarithmic scale", OFFSET(logscale), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, FLAGS }, | |
{ "saturation", "color saturation multiplier", OFFSET(saturation), AV_OPT_TYPE_FLOAT, {.dbl = 1}, -10, 10, FLAGS }, | |
{ NULL }, | |
}; | |
AVFILTER_DEFINE_CLASS(showspectrum); | |
+struct intensity_color_table_item | |
+{ | |
+ float a, y, u, v; | |
+}; | |
+static const struct intensity_color_table_item intensity_color_table[] = | |
+{ | |
+ { 0, 0, 0, 0 }, | |
+ { 0.13, .03587126228984074, .1573300977624594, -.02548747583751842 }, | |
+ { 0.3, .1857228179456802, .1772436246393981, .1747555484041475 }, | |
+ { 0.6, .2818498058365613, -.1593064119945782, .4713207455460892 }, | |
+ { 0.73, .6583062117554781, -.3716070802232764, .2435275933125293 }, | |
+ { 0.78, 0.763185357582429, -.4307467689263783, .1686649662231043 }, | |
+ { 0.91, .9533636363636364, -.2045454545454546, .03313636363636363 }, | |
+ { 1, 1, 0, 0 } | |
+}; | |
+ | |
static av_cold int init(AVFilterContext *ctx, const char *args) | |
{ | |
ShowSpectrumContext *showspectrum = ctx->priv; | |
@@ -246,7 +266,7 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFilterBufferRef *insampl | |
* height (or half the RDFT window size) */ | |
const int nb_freq = 1 << (showspectrum->rdft_bits - 1); | |
const int win_size = nb_freq << 1; | |
- const double w = 1. / sqrt(nb_freq); | |
+ const double w = 1. / sqrt(nb_freq) / 32768.; | |
int ch, plane, n, y; | |
const int start = showspectrum->filled; | |
@@ -287,36 +307,86 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFilterBufferRef *insampl | |
for (ch = 0; ch < showspectrum->nb_display_channels; ch++) { | |
float yf, uf, vf; | |
- /* decide channel colors */ | |
+ /* decide color range */ | |
if (showspectrum->combined) { | |
// reduce range by channel count | |
- yf = 1.0f / showspectrum->nb_display_channels; | |
+ yf = 256.0f / showspectrum->nb_display_channels; | |
uf = yf; | |
vf = yf; | |
- } else { | |
+ } else if (showspectrum->intensity_colors) { | |
// full range | |
- yf = 1.0f; | |
- uf = 0.5f; | |
- vf = 0.5f; | |
- } | |
- if (showspectrum->nb_display_channels >= 2) { | |
- uf *= cos((2 * M_PI * ch) / showspectrum->nb_display_channels); | |
- vf *= sin((2 * M_PI * ch) / showspectrum->nb_display_channels); | |
+ yf = 256.0f; | |
+ uf = 256.0f; | |
+ vf = 256.0f; | |
} else { | |
- uf = 0.0f; | |
- vf = 0.0f; | |
+ // full range | |
+ yf = 256.0f; | |
+ uf = 128.0f; | |
+ vf = 128.0f; | |
} | |
+ | |
uf *= showspectrum->saturation; | |
vf *= showspectrum->saturation; | |
+ /* decide channel colors */ | |
+ if (!showspectrum->intensity_colors) { | |
+ if (showspectrum->nb_display_channels >= 2) { | |
+ uf *= sin((2 * M_PI * ch) / showspectrum->nb_display_channels); | |
+ vf *= cos((2 * M_PI * ch) / showspectrum->nb_display_channels); | |
+ } else { | |
+ uf = 0.0f; | |
+ vf = 0.0f; | |
+ } | |
+ } | |
+ | |
/* draw the channel */ | |
for (y = 0; y < h; y++) { | |
int row = showspectrum->combined ? y : ch * h + y; | |
- float a = sqrt(w * MAGNITUDE(y, ch)); | |
float *out = &showspectrum->combine_buffer[3 * row]; | |
- out[0] += a * yf; | |
- out[1] += a * vf; | |
- out[2] += a * uf; | |
+ | |
+ /* get magnitude */ | |
+ float a = w * MAGNITUDE(y, ch); | |
+ | |
+ /* apply scale */ | |
+ if (showspectrum->logscale) | |
+ a = 1 - log(FFMAX(FFMIN(1, a), 1e-6)) / log(1e-6); // zero = -120dBFS | |
+ else | |
+ a = sqrt(a); | |
+ | |
+ if (showspectrum->intensity_colors) { | |
+ float y, u, v; | |
+ int i; | |
+ | |
+ for (i = 1; i < sizeof(intensity_color_table) / sizeof(*intensity_color_table) - 1; i++) | |
+ if (intensity_color_table[i].a >= a) | |
+ break; | |
+ // i now is the first item >= the color | |
+ // now we know to interpolate between item i-1 and i | |
+ if (a <= intensity_color_table[i-1].a) { | |
+ y = intensity_color_table[i-1].y; | |
+ u = intensity_color_table[i-1].u; | |
+ v = intensity_color_table[i-1].v; | |
+ } else if (a >= intensity_color_table[i].a) { | |
+ y = intensity_color_table[i].y; | |
+ u = intensity_color_table[i].u; | |
+ v = intensity_color_table[i].v; | |
+ } else { | |
+ float start = intensity_color_table[i-1].a; | |
+ float end = intensity_color_table[i].a; | |
+ float lerpfrac = (a - start) / (end - start); | |
+ y = intensity_color_table[i-1].y * (1.0f - lerpfrac) + intensity_color_table[i].y * lerpfrac; | |
+ u = intensity_color_table[i-1].u * (1.0f - lerpfrac) + intensity_color_table[i].u * lerpfrac; | |
+ v = intensity_color_table[i-1].v * (1.0f - lerpfrac) + intensity_color_table[i].v * lerpfrac; | |
+ } | |
+ | |
+ out[0] += y * yf; | |
+ out[1] += u * uf; | |
+ out[2] += v * vf; | |
+ } else { | |
+ out[0] += a * yf; | |
+ out[1] += a * uf; | |
+ out[2] += a * vf; | |
+ } | |
} | |
} | |
-- | |
1.8.1.1 | |
From 0f55c57379d4a037f32ef4575210d06d117b9897 Mon Sep 17 00:00:00 2001 | |
From: Rudolf Polzer <divverent@xonotic.org> | |
Date: Thu, 31 Jan 2013 17:35:26 +0100 | |
Subject: [PATCH 5/5] lavfi/showspectrum: simplify saturation logic | |
Signed-off-by: Rudolf Polzer <divverent@xonotic.org> | |
--- | |
libavfilter/avf_showspectrum.c | 32 +++++++++++++++++--------------- | |
1 file changed, 17 insertions(+), 15 deletions(-) | |
diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c | |
index 80ec6e6..4798173 100644 | |
--- a/libavfilter/avf_showspectrum.c | |
+++ b/libavfilter/avf_showspectrum.c | |
@@ -309,36 +309,38 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFilterBufferRef *insampl | |
/* decide color range */ | |
if (showspectrum->combined) { | |
- // reduce range by channel count | |
+ /* reduce range by channel count */ | |
yf = 256.0f / showspectrum->nb_display_channels; | |
uf = yf; | |
vf = yf; | |
- } else if (showspectrum->intensity_colors) { | |
- // full range | |
+ if (!showspectrum->intensity_colors) { | |
+ /* adjust saturation for mixed UV coloring */ | |
+ /* this factor is correct for infinite channels, an approximation otherwise */ | |
+ uf *= M_PI; | |
+ vf *= M_PI; | |
+ } | |
+ } else { | |
+ /* full range */ | |
yf = 256.0f; | |
uf = 256.0f; | |
vf = 256.0f; | |
- } else { | |
- // full range | |
- yf = 256.0f; | |
- uf = 128.0f; | |
- vf = 128.0f; | |
} | |
- uf *= showspectrum->saturation; | |
- vf *= showspectrum->saturation; | |
- | |
/* decide channel colors */ | |
if (!showspectrum->intensity_colors) { | |
if (showspectrum->nb_display_channels >= 2) { | |
- uf *= sin((2 * M_PI * ch) / showspectrum->nb_display_channels); | |
- vf *= cos((2 * M_PI * ch) / showspectrum->nb_display_channels); | |
+ uf *= 0.5 * sin((2 * M_PI * ch) / showspectrum->nb_display_channels); | |
+ vf *= 0.5 * cos((2 * M_PI * ch) / showspectrum->nb_display_channels); | |
} else { | |
uf = 0.0f; | |
vf = 0.0f; | |
} | |
} | |
+ /* apply saturation */ | |
+ uf *= showspectrum->saturation; | |
+ vf *= showspectrum->saturation; | |
+ | |
/* draw the channel */ | |
for (y = 0; y < h; y++) { | |
int row = showspectrum->combined ? y : ch * h + y; | |
@@ -360,8 +362,8 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFilterBufferRef *insampl | |
for (i = 1; i < sizeof(intensity_color_table) / sizeof(*intensity_color_table) - 1; i++) | |
if (intensity_color_table[i].a >= a) | |
break; | |
- // i now is the first item >= the color | |
- // now we know to interpolate between item i-1 and i | |
+ /* i now is the first item >= the color */ | |
+ /* now we know to interpolate between item i-1 and i */ | |
if (a <= intensity_color_table[i-1].a) { | |
y = intensity_color_table[i-1].y; | |
u = intensity_color_table[i-1].u; | |
-- | |
1.8.1.1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment