| @@ -32,7 +32,7 @@ enum DisplayScale { LINEAR, SQRT, CBRT, LOG, RLOG, NB_SCALES }; · 31 unmodified lines |
| 32 | 32 | enum AmplitudeScale { ALINEAR, ALOG, NB_ASCALES }; |
| 33 | 33 | enum SlideMode { REPLACE, SCROLL, NB_SLIDES }; |
| 34 | 34 | enum DisplayMode { SINGLE, SEPARATE, NB_DMODES }; |
| 35 | | −enum HistogramMode { ACCUMULATE, CURRENT, NB_HMODES }; |
| 35 | +enum HistogramMode { ABS, SIGN, NB_HMODES }; |
| 36 | 36 | |
| 37 | 37 | typedef struct AudioHistogramContext { |
| 38 | 38 | const AVClass *class; |
| @@ -49,6 +49,7 @@ typedef struct AudioHistogramContext { · 10 unmodified lines |
| 49 | 49 | int ypos; |
| 50 | 50 | int slide; |
| 51 | 51 | int dmode; |
| 52 | + int hmode; |
| 52 | 53 | int dchannels; |
| 53 | 54 | int count; |
| 54 | 55 | int frame_count; |
| @@ -56,6 +57,8 @@ typedef struct AudioHistogramContext { · 1 unmodified line |
| 56 | 57 | AVFrame *in[101]; |
| 57 | 58 | int first; |
| 58 | 59 | int nb_samples; |
| 60 | + |
| 61 | + int (*get_bin)(float in, int w); |
| 59 | 62 | } AudioHistogramContext; |
| 60 | 63 | |
| 61 | 64 | #define OFFSET(x) offsetof(AudioHistogramContext, x) |
| @@ -83,6 +86,9 @@ static const AVOption ahistogram_options[] = { · 21 unmodified lines |
| 83 | 86 | { "slide", "set sonogram sliding", OFFSET(slide), AV_OPT_TYPE_INT, {.i64=REPLACE}, 0, NB_SLIDES-1, FLAGS, "slide" }, |
| 84 | 87 | { "replace", "replace old rows with new", 0, AV_OPT_TYPE_CONST, {.i64=REPLACE}, 0, 0, FLAGS, "slide" }, |
| 85 | 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 | 92 | { NULL } |
| 87 | 93 | }; |
| 88 | 94 | |
| @@ -133,6 +139,26 @@ static int config_input(AVFilterLink *inlink) · 44 unmodified lines |
| 133 | 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 | 162 | static int config_output(AVFilterLink *outlink) |
| 137 | 163 | { |
| 138 | 164 | AudioHistogramContext *s = outlink->src->priv; |
| @@ -145,6 +171,27 @@ static int config_output(AVFilterLink *outlink) · 6 unmodified lines |
| 145 | 171 | s->histogram_h = s->h * s->phisto; |
| 146 | 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 | 195 | if (s->dmode == SEPARATE) { |
| 149 | 196 | s->combine_buffer = av_malloc_array(outlink->w * 3, sizeof(*s->combine_buffer)); |
| 150 | 197 | if (!s->combine_buffer) |
| @@ -207,7 +254,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 56 unmodified lines |
| 207 | 254 | uint64_t *achistogram = &s->achistogram[(s->dmode == SINGLE ? 0: c) * w]; |
| 208 | 255 | |
| 209 | 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 | 259 | achistogram[bin]++; |
| 213 | 260 | } |
| @@ -217,7 +264,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 3 unmodified lines |
| 217 | 264 | const float *src2 = (const float *)s->in[s->first]->extended_data[c]; |
| 218 | 265 | |
| 219 | 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 | 269 | shistogram[bin]++; |
| 223 | 270 | } |
| @@ -230,7 +277,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 6 unmodified lines |
| 230 | 277 | uint64_t *achistogram = &s->achistogram[(s->dmode == SINGLE ? 0: c) * w]; |
| 231 | 278 | |
| 232 | 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 | 282 | achistogram[bin]++; |
| 236 | 283 | } |
| @@ -240,7 +287,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 3 unmodified lines |
| 240 | 287 | const float *src2 = (const float *)s->in[s->first]->extended_data[c]; |
| 241 | 288 | |
| 242 | 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 | 292 | shistogram[bin]++; |
| 246 | 293 | } |
| @@ -265,7 +312,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 18 unmodified lines |
| 265 | 312 | float yf, uf, vf; |
| 266 | 313 | |
| 267 | 314 | if (s->dmode == SEPARATE) { |
| 268 | | − yf = 256.0f / s->dchannels; |
| 315 | + yf = 255.0f / s->dchannels; |
| 269 | 316 | uf = yf * M_PI; |
| 270 | 317 | vf = yf * M_PI; |
| 271 | 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 | 359 | if (s->h - H > 0) { |
| 313 | 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 | 363 | s->out->data[1][s->ypos * s->out->linesize[1] + n] = 127; |
| 317 | 364 | s->out->data[2][s->ypos * s->out->linesize[2] + n] = 127; |
| 318 | 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 | 373 | if (s->out->data[0][y * s->out->linesize[0] + n] != old) |
| 327 | 374 | break; |
| 328 | 375 | old = s->out->data[0][y * s->out->linesize[0] + n]; |
| 329 | | − s->out->data[0][y * s->out->linesize[0] + n] = yf; |
| 330 | | − s->out->data[1][y * s->out->linesize[1] + n] = 128+uf; |
| 331 | | − s->out->data[2][y * s->out->linesize[2] + n] = 128+vf; |
| 376 | + s->out->data[0][y * s->out->linesize[0] + n] = av_clip(yf, 0, 255); |
| 377 | + s->out->data[1][y * s->out->linesize[1] + n] = av_clip(128.f+uf, 0, 255); |
| 378 | + s->out->data[2][y * s->out->linesize[2] + n] = av_clip(128.f+vf, 0, 255); |
| 332 | 379 | s->out->data[3][y * s->out->linesize[3] + n] = 255; |
| 333 | 380 | } |
| 334 | 381 | |