29 #include "config_components.h"
53 enum ColorMode {
CHANNEL,
INTENSITY,
RAINBOW,
MORELAND,
NEBULAE,
FIRE,
FIERY,
FRUIT,
COOL,
MAGMA,
GREEN,
VIRIDIS,
PLASMA,
CIVIDIS,
TERRAIN,
NB_CLMODES };
57 #define DEFAULT_LENGTH 300
120 #define OFFSET(x) offsetof(ShowSpectrumContext, x)
121 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
190 { 0.13, .03587126228984074, .1573300977624594, -.02548747583751842 },
191 { 0.30, .18572281794568020, .1772436246393981, .17475554840414750 },
192 { 0.60, .28184980583656130, -.1593064119945782, .47132074554608920 },
193 { 0.73, .65830621175547810, -.3716070802232764, .24352759331252930 },
194 { 0.78, .76318535758242900, -.4307467689263783, .16866496622310430 },
195 { 0.91, .95336363636363640, -.2045454545454546, .03313636363636363 },
199 { 0.13, 44/256., (189-128)/256., (138-128)/256. },
200 { 0.25, 29/256., (186-128)/256., (119-128)/256. },
201 { 0.38, 119/256., (194-128)/256., (53-128)/256. },
202 { 0.60, 111/256., (73-128)/256., (59-128)/256. },
203 { 0.73, 205/256., (19-128)/256., (149-128)/256. },
204 { 0.86, 135/256., (83-128)/256., (200-128)/256. },
205 { 1, 73/256., (95-128)/256., (225-128)/256. }},
207 { 0, 44/256., (181-128)/256., (112-128)/256. },
208 { 0.13, 126/256., (177-128)/256., (106-128)/256. },
209 { 0.25, 164/256., (163-128)/256., (109-128)/256. },
210 { 0.38, 200/256., (140-128)/256., (120-128)/256. },
211 { 0.60, 201/256., (117-128)/256., (141-128)/256. },
212 { 0.73, 177/256., (103-128)/256., (165-128)/256. },
213 { 0.86, 136/256., (100-128)/256., (183-128)/256. },
214 { 1, 68/256., (117-128)/256., (203-128)/256. }},
216 { 0, 10/256., (134-128)/256., (132-128)/256. },
217 { 0.23, 21/256., (137-128)/256., (130-128)/256. },
218 { 0.45, 35/256., (134-128)/256., (134-128)/256. },
219 { 0.57, 51/256., (130-128)/256., (139-128)/256. },
220 { 0.67, 104/256., (116-128)/256., (162-128)/256. },
221 { 0.77, 120/256., (105-128)/256., (188-128)/256. },
222 { 0.87, 140/256., (105-128)/256., (188-128)/256. },
226 { 0.23, 44/256., (132-128)/256., (127-128)/256. },
227 { 0.45, 62/256., (116-128)/256., (140-128)/256. },
228 { 0.57, 75/256., (105-128)/256., (152-128)/256. },
229 { 0.67, 95/256., (91-128)/256., (166-128)/256. },
230 { 0.77, 126/256., (74-128)/256., (172-128)/256. },
231 { 0.87, 164/256., (73-128)/256., (162-128)/256. },
235 { 0.23, 36/256., (116-128)/256., (163-128)/256. },
236 { 0.45, 52/256., (102-128)/256., (200-128)/256. },
237 { 0.57, 116/256., (84-128)/256., (196-128)/256. },
238 { 0.67, 157/256., (67-128)/256., (181-128)/256. },
239 { 0.77, 193/256., (40-128)/256., (155-128)/256. },
240 { 0.87, 221/256., (101-128)/256., (134-128)/256. },
244 { 0.20, 29/256., (136-128)/256., (119-128)/256. },
245 { 0.30, 60/256., (119-128)/256., (90-128)/256. },
246 { 0.40, 85/256., (91-128)/256., (85-128)/256. },
247 { 0.50, 116/256., (70-128)/256., (105-128)/256. },
248 { 0.60, 151/256., (50-128)/256., (146-128)/256. },
249 { 0.70, 191/256., (63-128)/256., (178-128)/256. },
250 { 1, 98/256., (80-128)/256., (221-128)/256. }},
257 { 0.10, 23/256., (175-128)/256., (120-128)/256. },
258 { 0.23, 43/256., (158-128)/256., (144-128)/256. },
259 { 0.35, 85/256., (138-128)/256., (179-128)/256. },
260 { 0.48, 96/256., (128-128)/256., (189-128)/256. },
261 { 0.64, 128/256., (103-128)/256., (214-128)/256. },
262 { 0.92, 205/256., (80-128)/256., (152-128)/256. },
270 { 0.10, 0x39/255., (0x9D -128)/255., (0x8F -128)/255. },
271 { 0.23, 0x5C/255., (0x9A -128)/255., (0x68 -128)/255. },
272 { 0.35, 0x69/255., (0x93 -128)/255., (0x57 -128)/255. },
273 { 0.48, 0x76/255., (0x88 -128)/255., (0x4B -128)/255. },
274 { 0.64, 0x8A/255., (0x72 -128)/255., (0x4F -128)/255. },
275 { 0.80, 0xA3/255., (0x50 -128)/255., (0x66 -128)/255. },
276 { 1, 0xCC/255., (0x2F -128)/255., (0x87 -128)/255. }},
279 { 0.10, 0x27/255., (0xC2 -128)/255., (0x82 -128)/255. },
280 { 0.58, 0x5B/255., (0x9A -128)/255., (0xAE -128)/255. },
281 { 0.70, 0x89/255., (0x44 -128)/255., (0xAB -128)/255. },
282 { 0.80, 0xB4/255., (0x2B -128)/255., (0x9E -128)/255. },
283 { 0.91, 0xD2/255., (0x38 -128)/255., (0x92 -128)/255. },
287 { 0.20, 0x28/255., (0x98 -128)/255., (0x6F -128)/255. },
288 { 0.50, 0x48/255., (0x95 -128)/255., (0x74 -128)/255. },
289 { 0.63, 0x69/255., (0x84 -128)/255., (0x7F -128)/255. },
290 { 0.76, 0x89/255., (0x75 -128)/255., (0x84 -128)/255. },
291 { 0.90, 0xCE/255., (0x35 -128)/255., (0x95 -128)/255. },
296 { 0.60, 1, -.5, -.5 },
297 { 0.85, 1, -.5, .5 },
308 for (
i = 0;
i <
s->nb_display_channels;
i++)
313 for (
i = 0;
i <
s->nb_display_channels;
i++)
318 for (
i = 0;
i <
s->nb_display_channels;
i++)
323 for (
i = 0;
i <
s->nb_display_channels;
i++)
327 if (
s->fft_scratch) {
328 for (
i = 0;
i <
s->nb_display_channels;
i++)
332 if (
s->color_buffer) {
333 for (
i = 0;
i <
s->nb_display_channels;
i++)
339 for (
i = 0;
i <
s->nb_display_channels;
i++)
346 for (
i = 0;
i <
s->nb_display_channels;
i++)
351 while (
s->nb_frames > 0) {
394 const float *window_func_lut =
s->window_func_lut;
396 const int ch = jobnr;
401 float *in_frame = (
float *)
s->in_frame->extended_data[ch];
403 memmove(in_frame, in_frame +
s->hop_size, (
s->fft_size -
s->hop_size) *
sizeof(
float));
404 memcpy(in_frame +
s->fft_size -
s->hop_size, p, fin->
nb_samples *
sizeof(
float));
407 in_frame[
i +
s->fft_size -
s->hop_size] = 0.f;
410 float theta, phi, psi,
a,
b,
S,
c;
416 int M =
s->win_size / 2;
418 for (n = 0; n <
s->win_size; n++) {
419 s->fft_data[ch][n].re = in_frame[n] * window_func_lut[n];
420 s->fft_data[ch][n].im = 0;
423 phi = 2.f *
M_PI * (
s->stop -
s->start) / (
float)
inlink->sample_rate / (
M - 1);
426 for (
int n = 0; n <
M; n++) {
427 h[n].re =
cosf(n * n / 2.
f * phi);
428 h[n].im =
sinf(n * n / 2.
f * phi);
431 for (
int n =
M; n <
L; n++) {
436 for (
int n =
L -
N; n <
L; n++) {
437 h[n].re =
cosf((
L - n) * (
L - n) / 2.
f * phi);
438 h[n].im =
sinf((
L - n) * (
L - n) / 2.
f * phi);
441 for (
int n =
N; n <
L; n++) {
446 for (
int n = 0; n <
N; n++) {
447 psi = n * theta + n * n / 2.f * phi;
450 a =
c *
g[n].re -
S *
g[n].im;
451 b =
S *
g[n].re +
c *
g[n].im;
456 memcpy(
f,
h,
s->buf_size *
sizeof(*
f));
457 s->tx_fn(
s->fft[ch],
h,
f,
sizeof(
float));
459 memcpy(
f,
g,
s->buf_size *
sizeof(*
f));
460 s->tx_fn(
s->fft[ch],
g,
f,
sizeof(
float));
462 for (
int n = 0; n <
L; n++) {
465 a =
c *
h[n].re -
S *
h[n].im;
466 b =
S *
h[n].re +
c *
h[n].im;
472 memcpy(
f,
g,
s->buf_size *
sizeof(*
f));
473 s->itx_fn(
s->ifft[ch],
g,
f,
sizeof(
float));
475 for (
int k = 0; k <
M; k++) {
476 psi = k * k / 2.f * phi;
479 a =
c *
g[k].re -
S *
g[k].im;
480 b =
S *
g[k].re +
c *
g[k].im;
481 s->fft_data[ch][k].re =
a;
482 s->fft_data[ch][k].im =
b;
485 for (n = 0; n <
s->win_size; n++) {
486 s->fft_in[ch][n].re = in_frame[n] * window_func_lut[n];
487 s->fft_in[ch][n].im = 0;
491 s->tx_fn(
s->fft[ch],
s->fft_data[ch],
s->fft_in[ch],
sizeof(
float));
504 for (
int i = 0; txt[
i];
i++) {
508 for (char_y = font_height - 1; char_y >= 0; char_y--) {
509 uint8_t *p = pic->
data[0] + (y +
i * 10) * pic->
linesize[0] + x;
511 if (font[txt[
i] * font_height + font_height - 1 - char_y] &
mask)
512 p[char_y] = ~p[char_y];
518 for (char_y = 0; char_y < font_height; char_y++) {
520 if (font[txt[
i] * font_height + char_y] &
mask)
529 for (
int i = 0; txt[
i] && pic->
data[3];
i++) {
533 for (char_y = font_height - 1; char_y >= 0; char_y--) {
534 uint8_t *p = pic->
data[3] + (y +
i * 10) * pic->
linesize[3] + x;
536 for (
int k = 0; k < 8; k++)
543 for (char_y = 0; char_y < font_height; char_y++) {
553 float *yf,
float *uf,
float *vf)
558 *yf = 256.0f /
s->nb_display_channels;
559 switch (
s->color_mode) {
598 if (
s->nb_display_channels > 1) {
599 *uf *= 0.5f *
sinf((2 *
M_PI * ch) /
s->nb_display_channels +
M_PI *
s->rotation);
600 *vf *= 0.5f *
cosf((2 *
M_PI * ch) /
s->nb_display_channels +
M_PI *
s->rotation);
610 *uf *=
s->saturation;
611 *vf *=
s->saturation;
615 float yf,
float uf,
float vf,
618 const float af =
s->opacity_factor * 255.f;
621 const int cm =
s->color_mode;
641 float lerpfrac = (
a - start) / (end - start);
668 else if (log10(seconds) > 6)
670 else if (log10(seconds) > 3)
678 const float bmin,
const float bmax,
679 const float min,
const float max)
684 static float get_hz(
const float bin,
const float bmax,
685 const float min,
const float max,
699 float bmin,
float bmax,
705 static float bin_pos(
const int bin,
const int num_bins,
const float min,
const float max)
713 const float dmin =
s->dmin;
714 const float dmax =
s->dmax;
718 a = (
a - dmin) / (dmax - dmin);
736 a = (
s->drange -
s->limit +
log10f(
a) * 20.f) /
s->drange;
748 const float dmin =
s->dmin;
749 const float dmax =
s->dmax;
774 a =
a * (dmax - dmin) + dmin;
784 int ch, y, x = 0, sz =
s->orientation ==
VERTICAL ?
s->w :
s->h;
789 char chlayout_str[128];
797 drawtext(
s->outpicref, 2, outlink->
h - 10,
"CREATED BY LIBAVFILTER", 0);
798 drawtext(
s->outpicref, outlink->
w - 2 - strlen(text) * 10, outlink->
h - 10, text, 0);
801 text =
av_asprintf(
"Zoom: %d Hz - %d Hz",
s->start,
s->stop);
804 drawtext(
s->outpicref, outlink->
w - 2 - strlen(text) * 10, 3, text, 0);
808 dst =
s->outpicref->data[0] + (
s->start_y - 1) *
s->outpicref->linesize[0] +
s->start_x - 1;
809 for (x = 0; x <
s->w + 1; x++)
811 dst =
s->outpicref->data[0] + (
s->start_y +
s->h) *
s->outpicref->linesize[0] +
s->start_x - 1;
812 for (x = 0; x <
s->w + 1; x++)
814 for (y = 0; y <
s->h + 2; y++) {
815 dst =
s->outpicref->data[0] + (y +
s->start_y - 1) *
s->outpicref->linesize[0];
816 dst[
s->start_x - 1] = 200;
817 dst[
s->start_x +
s->w] = 200;
820 int h =
s->mode ==
SEPARATE ?
s->h /
s->nb_display_channels :
s->h;
821 int hh =
s->mode ==
SEPARATE ? -(
s->h %
s->nb_display_channels) + 1 : 1;
822 for (ch = 0; ch < (
s->mode ==
SEPARATE ?
s->nb_display_channels : 1); ch++) {
823 for (y = 0; y <
h; y += 20) {
824 dst =
s->outpicref->data[0] + (
s->start_y +
h * (ch + 1) - y - hh) *
s->outpicref->linesize[0];
825 dst[
s->start_x - 2] = 200;
826 dst[
s->start_x +
s->w + 1] = 200;
828 for (y = 0; y <
h; y += 40) {
829 dst =
s->outpicref->data[0] + (
s->start_y +
h * (ch + 1) - y - hh) *
s->outpicref->linesize[0];
830 dst[
s->start_x - 3] = 200;
831 dst[
s->start_x +
s->w + 2] = 200;
833 dst =
s->outpicref->data[0] + (
s->start_y - 2) *
s->outpicref->linesize[0] +
s->start_x;
834 for (x = 0; x <
s->w; x+=40)
836 dst =
s->outpicref->data[0] + (
s->start_y - 3) *
s->outpicref->linesize[0] +
s->start_x;
837 for (x = 0; x <
s->w; x+=80)
839 dst =
s->outpicref->data[0] + (
s->h +
s->start_y + 1) *
s->outpicref->linesize[0] +
s->start_x;
840 for (x = 0; x <
s->w; x+=40) {
843 dst =
s->outpicref->data[0] + (
s->h +
s->start_y + 2) *
s->outpicref->linesize[0] +
s->start_x;
844 for (x = 0; x <
s->w; x+=80) {
847 for (y = 0; y <
h; y += 40) {
848 float range =
s->stop ?
s->stop -
s->start :
inlink->sample_rate / 2;
849 float hertz =
get_hz(y,
h,
s->start,
s->start + range,
s->fscale);
859 drawtext(
s->outpicref,
s->start_x - 8 * strlen(units) - 4,
h * (ch + 1) +
s->start_y - y - 4 - hh, units, 0);
864 for (x = 0; x <
s->w &&
s->single_pic; x+=80) {
865 float seconds = x * spp /
inlink->sample_rate;
870 drawtext(
s->outpicref,
s->start_x + x - 4 * strlen(units),
s->h +
s->start_y + 6, units, 0);
871 drawtext(
s->outpicref,
s->start_x + x - 4 * strlen(units),
s->start_y - 12, units, 0);
875 drawtext(
s->outpicref, outlink->
w / 2 - 4 * 4, outlink->
h -
s->start_y / 2,
"TIME", 0);
876 drawtext(
s->outpicref,
s->start_x / 7, outlink->
h / 2 - 14 * 4,
"FREQUENCY (Hz)", 1);
878 int w =
s->mode ==
SEPARATE ?
s->w /
s->nb_display_channels :
s->w;
879 for (y = 0; y <
s->h; y += 20) {
880 dst =
s->outpicref->data[0] + (
s->start_y + y) *
s->outpicref->linesize[0];
881 dst[
s->start_x - 2] = 200;
882 dst[
s->start_x +
s->w + 1] = 200;
884 for (y = 0; y <
s->h; y += 40) {
885 dst =
s->outpicref->data[0] + (
s->start_y + y) *
s->outpicref->linesize[0];
886 dst[
s->start_x - 3] = 200;
887 dst[
s->start_x +
s->w + 2] = 200;
889 for (ch = 0; ch < (
s->mode ==
SEPARATE ?
s->nb_display_channels : 1); ch++) {
890 dst =
s->outpicref->data[0] + (
s->start_y - 2) *
s->outpicref->linesize[0] +
s->start_x +
w * ch;
891 for (x = 0; x <
w; x+=40)
893 dst =
s->outpicref->data[0] + (
s->start_y - 3) *
s->outpicref->linesize[0] +
s->start_x +
w * ch;
894 for (x = 0; x <
w; x+=80)
896 dst =
s->outpicref->data[0] + (
s->h +
s->start_y + 1) *
s->outpicref->linesize[0] +
s->start_x +
w * ch;
897 for (x = 0; x <
w; x+=40) {
900 dst =
s->outpicref->data[0] + (
s->h +
s->start_y + 2) *
s->outpicref->linesize[0] +
s->start_x +
w * ch;
901 for (x = 0; x <
w; x+=80) {
904 for (x = 0; x <
w - 79; x += 80) {
905 float range =
s->stop ?
s->stop -
s->start :
inlink->sample_rate / 2;
906 float hertz =
get_hz(x,
w,
s->start,
s->start + range,
s->fscale);
916 drawtext(
s->outpicref,
s->start_x - 4 * strlen(units) + x +
w * ch,
s->start_y - 12, units, 0);
917 drawtext(
s->outpicref,
s->start_x - 4 * strlen(units) + x +
w * ch,
s->h +
s->start_y + 6, units, 0);
921 for (y = 0; y <
s->h &&
s->single_pic; y+=40) {
922 float seconds = y * spp /
inlink->sample_rate;
927 drawtext(
s->outpicref,
s->start_x - 8 * strlen(units) - 4,
s->start_y + y - 4, units, 0);
930 drawtext(
s->outpicref,
s->start_x / 7, outlink->
h / 2 - 4 * 4,
"TIME", 1);
931 drawtext(
s->outpicref, outlink->
w / 2 - 14 * 4, outlink->
h -
s->start_y / 2,
"FREQUENCY (Hz)", 0);
934 for (ch = 0; ch < (multi ?
s->nb_display_channels : 1); ch++) {
935 int h = multi ?
s->h /
s->nb_display_channels :
s->h;
937 for (y = 0; y <
h; y++) {
938 float out[4] = { 0., 127.5, 127.5, 0.f};
941 for (chn = 0; chn < (
s->mode ==
SEPARATE ? 1 :
s->nb_display_channels); chn++) {
943 int channel = (multi) ?
s->nb_display_channels - ch - 1 : chn;
953 memset(
s->outpicref->data[0]+(
s->start_y +
h * (ch + 1) - y - 1) *
s->outpicref->linesize[0] +
s->w +
s->start_x + 20,
av_clip_uint8(
out[0]), 10);
954 memset(
s->outpicref->data[1]+(
s->start_y +
h * (ch + 1) - y - 1) *
s->outpicref->linesize[1] +
s->w +
s->start_x + 20,
av_clip_uint8(
out[1]), 10);
955 memset(
s->outpicref->data[2]+(
s->start_y +
h * (ch + 1) - y - 1) *
s->outpicref->linesize[2] +
s->w +
s->start_x + 20,
av_clip_uint8(
out[2]), 10);
956 if (
s->outpicref->data[3])
957 memset(
s->outpicref->data[3]+(
s->start_y +
h * (ch + 1) - y - 1) *
s->outpicref->linesize[3] +
s->w +
s->start_x + 20,
av_clip_uint8(
out[3]), 10);
960 for (y = 0; ch == 0 && y <
h + 5; y += 25) {
961 static const char *log_fmt =
"%.0f";
962 static const char *lin_fmt =
"%.3f";
963 const float a =
av_clipf(1.
f - y / (
float)(
h - 1), 0.
f, 1.
f);
970 drawtext(
s->outpicref,
s->w +
s->start_x + 35,
s->start_y + y - 3, text, 0);
976 drawtext(
s->outpicref,
s->w +
s->start_x + 22,
s->start_y +
s->h + 20,
"dBFS", 0);
984 float *magnitudes =
s->magnitudes[ch];
985 float *phases =
s->phases[ch];
1008 const int h =
s->orientation ==
VERTICAL ?
s->channel_height :
s->channel_width;
1009 const int ch = jobnr;
1017 for (y = 0; y <
h; y++) {
1018 int row = (
s->mode ==
COMBINED) ? y : ch *
h + y;
1019 float *
out = &
s->color_buffer[ch][4 * row];
1032 const int h =
s->orientation ==
VERTICAL ?
s->channel_height :
s->channel_width;
1033 const int ch = jobnr;
1040 for (
int yy = 0; yy <
h; yy++) {
1041 float range =
s->stop ?
s->stop -
s->start :
inlink->sample_rate / 2;
1049 int row = (
s->mode ==
COMBINED) ? yy : ch *
h + yy;
1050 float *
out = &
s->color_buffer[ch][4 * row];
1064 int i, fft_size,
h,
w,
ret;
1071 switch (
s->fscale) {
1078 if ((
s->stop ||
s->start) &&
s->stop <=
s->start) {
1083 if (!strcmp(
ctx->filter->name,
"showspectrumpic"))
1091 s->start_x = (log10(
inlink->sample_rate) + 1) * 25;
1093 outlink->
w +=
s->start_x * 2;
1094 outlink->
h +=
s->start_y * 2;
1099 s->channel_height =
h;
1100 s->channel_width =
w;
1110 s->win_size = fft_size;
1128 if (fft_size !=
s->fft_size) {
1131 s->fft_size = fft_size;
1136 for (
i = 0;
i <
s->nb_display_channels;
i++) {
1147 s->nb_display_channels =
inlink->ch_layout.nb_channels;
1148 for (
i = 0;
i <
s->nb_display_channels;
i++) {
1156 "The window size might be too high.\n");
1162 "The window size might be too high.\n");
1167 s->magnitudes =
av_calloc(
s->nb_display_channels,
sizeof(*
s->magnitudes));
1170 for (
i = 0;
i <
s->nb_display_channels;
i++) {
1172 if (!
s->magnitudes[
i])
1176 s->phases =
av_calloc(
s->nb_display_channels,
sizeof(*
s->phases));
1179 for (
i = 0;
i <
s->nb_display_channels;
i++) {
1186 s->color_buffer =
av_calloc(
s->nb_display_channels,
sizeof(*
s->color_buffer));
1187 if (!
s->color_buffer)
1189 for (
i = 0;
i <
s->nb_display_channels;
i++) {
1191 if (!
s->color_buffer[
i])
1195 s->fft_in =
av_calloc(
s->nb_display_channels,
sizeof(*
s->fft_in));
1198 s->fft_data =
av_calloc(
s->nb_display_channels,
sizeof(*
s->fft_data));
1201 s->fft_scratch =
av_calloc(
s->nb_display_channels,
sizeof(*
s->fft_scratch));
1202 if (!
s->fft_scratch)
1204 for (
i = 0;
i <
s->nb_display_channels;
i++) {
1209 s->fft_data[
i] =
av_calloc(
s->buf_size,
sizeof(**
s->fft_data));
1210 if (!
s->fft_data[
i])
1213 s->fft_scratch[
i] =
av_calloc(
s->buf_size,
sizeof(**
s->fft_scratch));
1214 if (!
s->fft_scratch[
i])
1219 s->window_func_lut =
1221 sizeof(*
s->window_func_lut));
1222 if (!
s->window_func_lut)
1225 if (
s->overlap == 1)
1226 s->overlap = overlap;
1227 s->hop_size = (1.f -
s->overlap) *
s->win_size;
1228 if (
s->hop_size < 1) {
1233 for (
s->win_scale = 0,
i = 0; i < s->win_size;
i++) {
1234 s->win_scale +=
s->window_func_lut[
i] *
s->window_func_lut[
i];
1236 s->win_scale = 1.f /
sqrtf(
s->win_scale);
1240 s->outpicref = outpicref =
1245 for (
i = 0;
i < outlink->
h;
i++) {
1246 memset(outpicref->
data[0] +
i * outpicref->
linesize[0], 0, outlink->
w);
1247 memset(outpicref->
data[1] +
i * outpicref->
linesize[1], 128, outlink->
w);
1248 memset(outpicref->
data[2] +
i * outpicref->
linesize[2], 128, outlink->
w);
1249 if (outpicref->
data[3])
1250 memset(outpicref->
data[3] +
i * outpicref->
linesize[3], 0, outlink->
w);
1254 if (!
s->single_pic &&
s->legend)
1258 if ((
s->orientation ==
VERTICAL &&
s->xpos >=
s->w) ||
1274 if (!
s->single_pic && strcmp(
s->rate_str,
"auto")) {
1278 }
else if (
s->single_pic) {
1281 s->frame_rate =
s->auto_frame_rate;
1289 sizeof(*
s->combine_buffer));
1293 sizeof(*
s->combine_buffer));
1297 s->w,
s->h,
s->win_size);
1311 #define RE(y, ch) s->fft_data[ch][y].re
1312 #define IM(y, ch) s->fft_data[ch][y].im
1313 #define MAGNITUDE(y, ch) hypotf(RE(y, ch), IM(y, ch))
1314 #define PHASE(y, ch) atan2f(IM(y, ch), RE(y, ch))
1319 const double w =
s->win_scale * (
s->scale ==
LOG ?
s->win_scale : 1);
1321 const float f =
s->gain *
w;
1322 const int ch = jobnr;
1323 float *magnitudes =
s->magnitudes[ch];
1325 for (y = 0; y <
h; y++)
1334 const int h =
s->orientation ==
VERTICAL ?
s->h :
s->w;
1335 const int ch = jobnr;
1336 float *phases =
s->phases[ch];
1339 for (y = 0; y <
h; y++)
1340 phases[y] = (
PHASE(y, ch) /
M_PI + 1) / 2;
1347 const float rng = 2.f *
M_PI;
1349 float max = -FLT_MAX;
1350 float min = FLT_MAX;
1352 for (
int i = 0;
i <
N;
i++) {
1353 const float d = x[
FFMIN(
i + 1,
N)] - x[
i];
1354 const float p =
ceilf(
fabsf(
d) / rng) * rng * (((d < tol) > 0.f) - ((
d > -tol) > 0.f));
1369 const int h =
s->orientation ==
VERTICAL ?
s->h :
s->w;
1370 const int ch = jobnr;
1371 float *phases =
s->phases[ch];
1375 for (y = 0; y <
h; y++)
1376 phases[y] =
PHASE(y, ch);
1379 for (y = 0; y <
h; y++)
1387 const double w =
s->win_scale * (
s->scale ==
LOG ?
s->win_scale : 1);
1388 int ch, y,
h =
s->orientation ==
VERTICAL ?
s->h :
s->w;
1389 const float f =
s->gain *
w;
1391 for (ch = 0; ch <
s->nb_display_channels; ch++) {
1392 float *magnitudes =
s->magnitudes[ch];
1394 for (y = 0; y <
h; y++)
1401 int ch, y,
h =
s->orientation ==
VERTICAL ?
s->h :
s->w;
1403 for (ch = 0; ch <
s->nb_display_channels; ch++) {
1404 float *magnitudes =
s->magnitudes[ch];
1406 for (y = 0; y <
h; y++)
1407 magnitudes[y] *=
scale;
1415 for (y = 0; y <
size; y++) {
1416 s->combine_buffer[4 * y ] = 0;
1417 s->combine_buffer[4 * y + 1] = 127.5;
1418 s->combine_buffer[4 * y + 2] = 127.5;
1419 s->combine_buffer[4 * y + 3] = 0;
1429 int ret, plane, x, y, z =
s->orientation ==
VERTICAL ?
s->h :
s->w;
1438 for (y = 0; y < z * 4; y++) {
1439 for (x = 0; x <
s->nb_display_channels; x++) {
1440 s->combine_buffer[y] +=
s->color_buffer[x][y];
1448 for (plane = 0; plane < 3 +
alpha; plane++) {
1449 for (y = 0; y <
s->h; y++) {
1450 uint8_t *p = outpicref->
data[plane] +
s->start_x +
1451 (y +
s->start_y) * outpicref->
linesize[plane];
1452 memmove(p, p + 1,
s->w - 1);
1456 }
else if (
s->sliding ==
RSCROLL) {
1457 for (plane = 0; plane < 3 +
alpha; plane++) {
1458 for (y = 0; y <
s->h; y++) {
1459 uint8_t *p = outpicref->
data[plane] +
s->start_x +
1460 (y +
s->start_y) * outpicref->
linesize[plane];
1461 memmove(p + 1, p,
s->w - 1);
1466 for (plane = 0; plane < 3; plane++) {
1467 uint8_t *p = outpicref->
data[plane] +
s->start_x +
1468 (outlink->
h - 1 -
s->start_y) * outpicref->
linesize[plane] +
1470 for (y = 0; y <
s->h; y++) {
1476 uint8_t *p = outpicref->
data[3] +
s->start_x +
1477 (outlink->
h - 1 -
s->start_y) * outpicref->
linesize[3] +
1479 for (y = 0; y <
s->h; y++) {
1486 for (plane = 0; plane < 3 +
alpha; plane++) {
1487 for (y = 1; y <
s->h; y++) {
1488 memmove(outpicref->
data[plane] + (y-1 +
s->start_y) * outpicref->
linesize[plane] +
s->start_x,
1489 outpicref->
data[plane] + (y +
s->start_y) * outpicref->
linesize[plane] +
s->start_x,
1494 }
else if (
s->sliding ==
RSCROLL) {
1495 for (plane = 0; plane < 3 +
alpha; plane++) {
1496 for (y =
s->h - 1; y >= 1; y--) {
1497 memmove(outpicref->
data[plane] + (y +
s->start_y) * outpicref->
linesize[plane] +
s->start_x,
1498 outpicref->
data[plane] + (y-1 +
s->start_y) * outpicref->
linesize[plane] +
s->start_x,
1504 for (plane = 0; plane < 3; plane++) {
1505 uint8_t *p = outpicref->
data[plane] +
s->start_x +
1506 (
s->xpos +
s->start_y) * outpicref->
linesize[plane];
1507 for (x = 0; x <
s->w; x++) {
1513 uint8_t *p = outpicref->
data[3] +
s->start_x +
1514 (
s->xpos +
s->start_y) * outpicref->
linesize[3];
1515 for (x = 0; x <
s->w; x++) {
1527 if (
s->orientation ==
VERTICAL &&
s->xpos < 0)
1533 if (
s->orientation ==
VERTICAL &&
s->xpos >=
s->w)
1539 if (!
s->single_pic && (
s->sliding !=
FULLFRAME ||
s->xpos == 0)) {
1549 for (y = 0; y < 10; y++) {
1550 memset(
s->outpicref->data[0] + outlink->
w / 2 - 4 *
s->old_len +
1551 (outlink->
h -
s->start_y / 2 - 20 + y) *
s->outpicref->linesize[0], 0, 10 *
s->old_len);
1554 outlink->
w / 2 - 4 * strlen(units),
1555 outlink->
h -
s->start_y / 2 - 20,
1558 for (y = 0; y < 10 *
s->old_len; y++) {
1559 memset(
s->outpicref->data[0] +
s->start_x / 7 + 20 +
1560 (outlink->
h / 2 - 4 *
s->old_len + y) *
s->outpicref->linesize[0], 0, 10);
1563 s->start_x / 7 + 20,
1564 outlink->
h / 2 - 4 * strlen(units),
1567 s->old_len = strlen(units);
1570 s->old_pts = outpicref->
pts;
1584 #if CONFIG_SHOWSPECTRUM_FILTER
1615 s->in_pts = fin->
pts;
1625 s->xpos > 0 &&
s->outpicref) {
1628 for (
int i = 0;
i < outlink->
h;
i++) {
1629 memset(
s->outpicref->data[0] +
i *
s->outpicref->linesize[0] +
s->xpos, 0, outlink->
w -
s->xpos);
1630 memset(
s->outpicref->data[1] +
i *
s->outpicref->linesize[1] +
s->xpos, 128, outlink->
w -
s->xpos);
1631 memset(
s->outpicref->data[2] +
i *
s->outpicref->linesize[2] +
s->xpos, 128, outlink->
w -
s->xpos);
1632 if (
s->outpicref->data[3])
1633 memset(
s->outpicref->data[3] +
i *
s->outpicref->linesize[3] +
s->xpos, 0, outlink->
w -
s->xpos);
1636 for (
int i =
s->xpos; i < outlink->
h;
i++) {
1637 memset(
s->outpicref->data[0] +
i *
s->outpicref->linesize[0], 0, outlink->
w);
1638 memset(
s->outpicref->data[1] +
i *
s->outpicref->linesize[1], 128, outlink->
w);
1639 memset(
s->outpicref->data[2] +
i *
s->outpicref->linesize[2], 128, outlink->
w);
1640 if (
s->outpicref->data[3])
1641 memset(
s->outpicref->data[3] +
i *
s->outpicref->linesize[3], 0, outlink->
w);
1645 pts =
s->outpicref->pts;
1647 s->outpicref =
NULL;
1672 static const AVFilterPad showspectrum_inputs[] = {
1679 static const AVFilterPad showspectrum_outputs[] = {
1688 .
name =
"showspectrum",
1696 .priv_class = &showspectrum_class,
1699 #endif // CONFIG_SHOWSPECTRUM_FILTER
1701 #if CONFIG_SHOWSPECTRUMPIC_FILTER
1703 static const AVOption showspectrumpic_options[] = {
1753 static int showspectrumpic_request_frame(
AVFilterLink *outlink)
1763 int x = 0, sz =
s->orientation ==
VERTICAL ?
s->w :
s->h;
1764 unsigned int nb_frame = 0;
1769 spf =
s->win_size * (
s->samples / ((
s->win_size * sz) *
ceil(
s->samples / (
float)(
s->win_size * sz))));
1770 spf =
FFMAX(1, spf);
1772 spb = (
s->samples / (spf * sz)) * spf;
1779 int acc_samples = 0;
1782 while (nb_frame <= s->nb_frames) {
1783 AVFrame *cur_frame =
s->frames[nb_frame];
1784 int cur_frame_samples = cur_frame->
nb_samples;
1787 if (acc_samples < spf) {
1788 nb_samples =
FFMIN(spf - acc_samples, cur_frame_samples - src_offset);
1789 acc_samples += nb_samples;
1791 dst_offset, src_offset, nb_samples,
1795 src_offset += nb_samples;
1796 dst_offset += nb_samples;
1797 if (cur_frame_samples <= src_offset) {
1803 if (acc_samples == spf)
1811 if (consumed >= spb) {
1818 for (ch = 0; ch <
s->nb_display_channels; ch++)
1819 memset(
s->magnitudes[ch], 0,
h *
sizeof(
float));
1824 s->outpicref->pts = 0;
1830 s->outpicref =
NULL;
1842 if (
s->nb_frames + 1ULL >
s->frames_size /
sizeof(*(
s->frames))) {
1849 s->frames[
s->nb_frames] = insamples;
1856 static const AVFilterPad showspectrumpic_inputs[] = {
1860 .filter_frame = showspectrumpic_filter_frame,
1864 static const AVFilterPad showspectrumpic_outputs[] = {
1869 .request_frame = showspectrumpic_request_frame,
1874 .
name =
"showspectrumpic",
1875 .description =
NULL_IF_CONFIG_SMALL(
"Convert input audio to a spectrum video output single picture."),
1881 .priv_class = &showspectrumpic_class,
1885 #endif // CONFIG_SHOWSPECTRUMPIC_FILTER