| @@ -32,7 +32,7 @@ enum DisplayScale { LINEAR, SQRT, CBRT, LOG, RLOG, NB_SCALES }; · 31 unmodified lines |
| 32 | enum AmplitudeScale { ALINEAR, ALOG, NB_ASCALES }; | 32 | enum AmplitudeScale { ALINEAR, ALOG, NB_ASCALES }; |
| 33 | enum SlideMode { REPLACE, SCROLL, NB_SLIDES }; | 33 | enum SlideMode { REPLACE, SCROLL, NB_SLIDES }; |
| 34 | enum DisplayMode { SINGLE, SEPARATE, NB_DMODES }; | 34 | enum DisplayMode { SINGLE, SEPARATE, NB_DMODES }; |
| 35 | enum HistogramMode { ACCUMULATE, CURRENT, NB_HMODES }; | 35 | enum HistogramMode { ABS, SIGN, NB_HMODES }; |
| 36 | | 36 | |
| 37 | typedef struct AudioHistogramContext { | 37 | typedef struct AudioHistogramContext { |
| 38 | const AVClass *class; | 38 | const AVClass *class; |
| @@ -49,6 +49,7 @@ typedef struct AudioHistogramContext { · 10 unmodified lines |
| 49 | int ypos; | 49 | int ypos; |
| 50 | int slide; | 50 | int slide; |
| 51 | int dmode; | 51 | int dmode; |
| | 52 | int hmode; |
| 52 | int dchannels; | 53 | int dchannels; |
| 53 | int count; | 54 | int count; |
| 54 | int frame_count; | 55 | int frame_count; |
| @@ -56,6 +57,8 @@ typedef struct AudioHistogramContext { · 1 unmodified line |
| 56 | AVFrame *in[101]; | 57 | AVFrame *in[101]; |
| 57 | int first; | 58 | int first; |
| 58 | int nb_samples; | 59 | int nb_samples; |
| | 60 | |
| | 61 | int (*get_bin)(float in, int w); |
| 59 | } AudioHistogramContext; | 62 | } AudioHistogramContext; |
| 60 | | 63 | |
| 61 | #define OFFSET(x) offsetof(AudioHistogramContext, x) | 64 | #define OFFSET(x) offsetof(AudioHistogramContext, x) |
| @@ -83,6 +86,9 @@ static const AVOption ahistogram_options[] = { · 21 unmodified lines |
| 83 | { "slide", "set sonogram sliding", OFFSET(slide), AV_OPT_TYPE_INT, {.i64=REPLACE}, 0, NB_SLIDES-1, FLAGS, "slide" }, | 86 | { "slide", "set sonogram sliding", OFFSET(slide), AV_OPT_TYPE_INT, {.i64=REPLACE}, 0, NB_SLIDES-1, FLAGS, "slide" }, |
| 84 | { "replace", "replace old rows with new", 0, AV_OPT_TYPE_CONST, {.i64=REPLACE}, 0, 0, FLAGS, "slide" }, | 87 | { "replace", "replace old rows with new", 0, AV_OPT_TYPE_CONST, {.i64=REPLACE}, 0, 0, FLAGS, "slide" }, |
| 85 | { "scroll", "scroll from top to bottom", 0, AV_OPT_TYPE_CONST, {.i64=SCROLL}, 0, 0, FLAGS, "slide" }, | 88 | { "scroll", "scroll from top to bottom", 0, AV_OPT_TYPE_CONST, {.i64=SCROLL}, 0, 0, FLAGS, "slide" }, |
| | 89 | { "hmode", "set histograms mode", OFFSET(hmode), AV_OPT_TYPE_INT, {.i64=ABS}, 0, NB_HMODES-1, FLAGS, "hmode" }, |
| | 90 | { "abs", "use absolute samples", 0, AV_OPT_TYPE_CONST, {.i64=ABS}, 0, 0, FLAGS, "hmode" }, |
| | 91 | { "sign", "use unchanged samples", 0, AV_OPT_TYPE_CONST, {.i64=SIGN},0, 0, FLAGS, "hmode" }, |
| 86 | { NULL } | 92 | { NULL } |
| 87 | }; | 93 | }; |
| 88 | | 94 | |
| @@ -133,6 +139,26 @@ static int config_input(AVFilterLink *inlink) · 44 unmodified lines |
| 133 | return 0; | 139 | return 0; |
| 134 | } | 140 | } |
| 135 | | 141 | |
| | 142 | static int get_lin_bin_abs(float in, int w) |
| | 143 | { |
| | 144 | return lrintf(av_clipf(fabsf(in), 0.f, 1.f) * (w - 1)); |
| | 145 | } |
| | 146 | |
| | 147 | static int get_lin_bin_sign(float in, int w) |
| | 148 | { |
| | 149 | return lrintf((1.f + av_clipf(in, -1.f, 1.f)) * 0.5f * (w - 1)); |
| | 150 | } |
| | 151 | |
| | 152 | static int get_log_bin_abs(float in, int w) |
| | 153 | { |
| | 154 | return lrintf(av_clipf(1.f + log10f(fabsf(in)) / 6.f, 0.f, 1.f) * (w - 1)); |
| | 155 | } |
| | 156 | |
| | 157 | static int get_log_bin_sign(float in, int w) |
| | 158 | { |
| | 159 | return (w / 2) + FFSIGN(in) * lrintf(av_clipf(1.f + log10f(fabsf(in)) / 6.f, 0.f, 1.f) * (w / 2)); |
| | 160 | } |
| | 161 | |
| 136 | static int config_output(AVFilterLink *outlink) | 162 | static int config_output(AVFilterLink *outlink) |
| 137 | { | 163 | { |
| 138 | AudioHistogramContext *s = outlink->src->priv; | 164 | AudioHistogramContext *s = outlink->src->priv; |
| @@ -145,6 +171,27 @@ static int config_output(AVFilterLink *outlink) · 6 unmodified lines |
| 145 | s->histogram_h = s->h * s->phisto; | 171 | s->histogram_h = s->h * s->phisto; |
| 146 | s->ypos = s->h * s->phisto; | 172 | s->ypos = s->h * s->phisto; |
| 147 | | 173 | |
| | 174 | switch (s->ascale) { |
| | 175 | case ALINEAR: |
| | 176 | switch (s->hmode) { |
| | 177 | case ABS: s->get_bin = get_lin_bin_abs; break; |
| | 178 | case SIGN: s->get_bin = get_lin_bin_sign; break; |
| | 179 | default: |
| | 180 | return AVERROR_BUG; |
| | 181 | } |
| | 182 | break; |
| | 183 | case ALOG: |
| | 184 | switch (s->hmode) { |
| | 185 | case ABS: s->get_bin = get_log_bin_abs; break; |
| | 186 | case SIGN: s->get_bin = get_log_bin_sign; break; |
| | 187 | default: |
| | 188 | return AVERROR_BUG; |
| | 189 | } |
| | 190 | break; |
| | 191 | default: |
| | 192 | return AVERROR_BUG; |
| | 193 | } |
| | 194 | |
| 148 | if (s->dmode == SEPARATE) { | 195 | if (s->dmode == SEPARATE) { |
| 149 | s->combine_buffer = av_malloc_array(outlink->w * 3, sizeof(*s->combine_buffer)); | 196 | s->combine_buffer = av_malloc_array(outlink->w * 3, sizeof(*s->combine_buffer)); |
| 150 | if (!s->combine_buffer) | 197 | if (!s->combine_buffer) |
| @@ -207,7 +254,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 56 unmodified lines |
| 207 | uint64_t *achistogram = &s->achistogram[(s->dmode == SINGLE ? 0: c) * w]; | 254 | uint64_t *achistogram = &s->achistogram[(s->dmode == SINGLE ? 0: c) * w]; |
| 208 | | 255 | |
| 209 | for (n = 0; n < in->nb_samples; n++) { | 256 | for (n = 0; n < in->nb_samples; n++) { |
| 210 | bin = lrint(av_clipf(fabsf(src[n]), 0, 1) * (w - 1)); | 257 | bin = s->get_bin(src[n], w); |
| 211 | | 258 | |
| 212 | achistogram[bin]++; | 259 | achistogram[bin]++; |
| 213 | } | 260 | } |
| @@ -217,7 +264,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 3 unmodified lines |
| 217 | const float *src2 = (const float *)s->in[s->first]->extended_data[c]; | 264 | const float *src2 = (const float *)s->in[s->first]->extended_data[c]; |
| 218 | | 265 | |
| 219 | for (n = 0; n < in->nb_samples; n++) { | 266 | for (n = 0; n < in->nb_samples; n++) { |
| 220 | bin = lrint(av_clipf(fabsf(src2[n]), 0, 1) * (w - 1)); | 267 | bin = s->get_bin(src2[n], w); |
| 221 | | 268 | |
| 222 | shistogram[bin]++; | 269 | shistogram[bin]++; |
| 223 | } | 270 | } |
| @@ -230,7 +277,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 6 unmodified lines |
| 230 | uint64_t *achistogram = &s->achistogram[(s->dmode == SINGLE ? 0: c) * w]; | 277 | uint64_t *achistogram = &s->achistogram[(s->dmode == SINGLE ? 0: c) * w]; |
| 231 | | 278 | |
| 232 | for (n = 0; n < in->nb_samples; n++) { | 279 | for (n = 0; n < in->nb_samples; n++) { |
| 233 | bin = lrint(av_clipf(1 + log10(fabsf(src[n])) / 6, 0, 1) * (w - 1)); | 280 | bin = s->get_bin(src[n], w); |
| 234 | | 281 | |
| 235 | achistogram[bin]++; | 282 | achistogram[bin]++; |
| 236 | } | 283 | } |
| @@ -240,7 +287,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 3 unmodified lines |
| 240 | const float *src2 = (const float *)s->in[s->first]->extended_data[c]; | 287 | const float *src2 = (const float *)s->in[s->first]->extended_data[c]; |
| 241 | | 288 | |
| 242 | for (n = 0; n < in->nb_samples; n++) { | 289 | for (n = 0; n < in->nb_samples; n++) { |
| 243 | bin = lrint(av_clipf(1 + log10(fabsf(src2[n])) / 6, 0, 1) * (w - 1)); | 290 | bin = s->get_bin(src2[n], w); |
| 244 | | 291 | |
| 245 | shistogram[bin]++; | 292 | shistogram[bin]++; |
| 246 | } | 293 | } |
| @@ -265,7 +312,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 18 unmodified lines |
| 265 | float yf, uf, vf; | 312 | float yf, uf, vf; |
| 266 | | 313 | |
| 267 | if (s->dmode == SEPARATE) { | 314 | if (s->dmode == SEPARATE) { |
| 268 | yf = 256.0f / s->dchannels; | 315 | yf = 255.0f / s->dchannels; |
| 269 | uf = yf * M_PI; | 316 | uf = yf * M_PI; |
| 270 | vf = yf * M_PI; | 317 | vf = yf * M_PI; |
| 271 | uf *= 0.5 * sin((2 * M_PI * c) / s->dchannels); | 318 | uf *= 0.5 * sin((2 * M_PI * c) / s->dchannels); |
| @@ -312,7 +359,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 40 unmodified lines |
| 312 | if (s->h - H > 0) { | 359 | if (s->h - H > 0) { |
| 313 | h = aa * 255; | 360 | h = aa * 255; |
| 314 | | 361 | |
| 315 | s->out->data[0][s->ypos * s->out->linesize[0] + n] = h; | 362 | s->out->data[0][s->ypos * s->out->linesize[0] + n] = av_clip(h, 0, 255); |
| 316 | s->out->data[1][s->ypos * s->out->linesize[1] + n] = 127; | 363 | s->out->data[1][s->ypos * s->out->linesize[1] + n] = 127; |
| 317 | s->out->data[2][s->ypos * s->out->linesize[2] + n] = 127; | 364 | s->out->data[2][s->ypos * s->out->linesize[2] + n] = 127; |
| 318 | s->out->data[3][s->ypos * s->out->linesize[3] + n] = 255; | 365 | s->out->data[3][s->ypos * s->out->linesize[3] + n] = 255; |
| @@ -326,9 +373,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 7 unmodified lines |
| 326 | if (s->out->data[0][y * s->out->linesize[0] + n] != old) | 373 | if (s->out->data[0][y * s->out->linesize[0] + n] != old) |
| 327 | break; | 374 | break; |
| 328 | old = s->out->data[0][y * s->out->linesize[0] + n]; | 375 | old = s->out->data[0][y * s->out->linesize[0] + n]; |
| 329 | s->out->data[0][y * s->out->linesize[0] + n] = yf; | 376 | s->out->data[0][y * s->out->linesize[0] + n] = av_clip(yf, 0, 255); |
| 330 | s->out->data[1][y * s->out->linesize[1] + n] = 128+uf; | 377 | s->out->data[1][y * s->out->linesize[1] + n] = av_clip(128.f+uf, 0, 255); |
| 331 | s->out->data[2][y * s->out->linesize[2] + n] = 128+vf; | 378 | s->out->data[2][y * s->out->linesize[2] + n] = av_clip(128.f+vf, 0, 255); |
| 332 | s->out->data[3][y * s->out->linesize[3] + n] = 255; | 379 | s->out->data[3][y * s->out->linesize[3] + n] = 255; |
| 333 | } | 380 | } |
| 334 | | 381 | |