avfilter/avf_avectorscope: add scale option
authorPaul B Mahol <onemda@gmail.com>
Thu, 11 Aug 2016 15:21:54 +0000 (17:21 +0200)
committerPaul B Mahol <onemda@gmail.com>
Thu, 11 Aug 2016 15:21:54 +0000 (17:21 +0200)
doc/filters.texi
libavfilter/avf_avectorscope.c

index 2dfe457..8cef0a0 100644 (file)
@@ -15060,6 +15060,25 @@ Draw line between previous and current sample.
 @end table
 
 Default value is @samp{dot}.
+
+@item scale
+Specify amplitude scale of audio samples.
+
+Available values are:
+@table @samp
+@item lin
+Linear.
+
+@item sqrt
+Square root.
+
+@item cbrt
+Cubic root.
+
+@item log
+Logarithmic.
+@end table
+
 @end table
 
 @subsection Examples
index 3ba044f..0db30d3 100644 (file)
@@ -46,6 +46,14 @@ enum VectorScopeDraw {
     DRAW_NB,
 };
 
+enum VectorScopeScale {
+    LIN,
+    SQRT,
+    CBRT,
+    LOG,
+    SCALE_NB,
+};
+
 typedef struct AudioVectorScopeContext {
     const AVClass *class;
     AVFrame *outpicref;
@@ -53,6 +61,7 @@ typedef struct AudioVectorScopeContext {
     int hw, hh;
     int mode;
     int draw;
+    int scale;
     int contrast[4];
     int fade[4];
     double zoom;
@@ -85,6 +94,11 @@ static const AVOption avectorscope_options[] = {
     { "draw", "set draw mode", OFFSET(draw), AV_OPT_TYPE_INT, {.i64=DOT}, 0, DRAW_NB-1, FLAGS, "draw" },
     { "dot",   "", 0, AV_OPT_TYPE_CONST, {.i64=DOT} , 0, 0, FLAGS, "draw" },
     { "line",  "", 0, AV_OPT_TYPE_CONST, {.i64=LINE}, 0, 0, FLAGS, "draw" },
+    { "scale", "set amplitude scale mode", OFFSET(scale), AV_OPT_TYPE_INT, {.i64=LIN}, 0, SCALE_NB-1, FLAGS, "scale" },
+    { "lin",   "linear",      0, AV_OPT_TYPE_CONST, {.i64=LIN},  0, 0, FLAGS, "scale" },
+    { "sqrt",  "square root", 0, AV_OPT_TYPE_CONST, {.i64=SQRT}, 0, 0, FLAGS, "scale" },
+    { "cbrt",  "cube root",   0, AV_OPT_TYPE_CONST, {.i64=CBRT}, 0, 0, FLAGS, "scale" },
+    { "log",   "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=LOG},  0, 0, FLAGS, "scale" },
     { NULL }
 };
 
@@ -239,69 +253,61 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
 
     fade(s);
 
-    switch (insamples->format) {
-    case AV_SAMPLE_FMT_S16:
-        for (i = 0; i < insamples->nb_samples; i++) {
-            int16_t *src = (int16_t *)insamples->data[0] + i * 2;
-
-            if (s->mode == LISSAJOUS) {
-                x = ((src[1] - src[0]) * zoom / (float)(UINT16_MAX) + 1) * hw;
-                y = (1.0 - (src[0] + src[1]) * zoom / (float)UINT16_MAX) * hh;
-            } else if (s->mode == LISSAJOUS_XY) {
-                x = (src[1] * zoom / (float)INT16_MAX + 1) * hw;
-                y = (src[0] * zoom / (float)INT16_MAX + 1) * hh;
-            } else {
-                float sx, sy, cx, cy;
-
-                sx = src[1] * zoom / (float)INT16_MAX;
-                sy = src[0] * zoom / (float)INT16_MAX;
-                cx = sx * sqrtf(1 - 0.5*sy*sy);
-                cy = sy * sqrtf(1 - 0.5*sx*sx);
-                x = hw + hw * FFSIGN(cx + cy) * (cx - cy) * .7;
-                y = s->h - s->h * fabsf(cx + cy) * .7;
-            }
+    for (i = 0; i < insamples->nb_samples; i++) {
+        int16_t *samples = (int16_t *)insamples->data[0] + i * 2;
+        float *samplesf = (float *)insamples->data[0] + i * 2;
+        float src[2];
 
-            if (s->draw == DOT) {
-                draw_dot(s, x, y);
-            } else {
-                draw_line(s, x, y, prev_x, prev_y);
-            }
-            prev_x = x;
-            prev_y = y;
+        switch (insamples->format) {
+        case AV_SAMPLE_FMT_S16:
+            src[0] = samples[0] / (float)INT16_MAX;
+            src[1] = samples[1] / (float)INT16_MAX;
+            break;
+        case AV_SAMPLE_FMT_FLT:
+            src[0] = samplesf[0];
+            src[1] = samplesf[1];
+            break;
         }
-        break;
-    case AV_SAMPLE_FMT_FLT:
-        for (i = 0; i < insamples->nb_samples; i++) {
-            float *src = (float *)insamples->data[0] + i * 2;
-
-            if (s->mode == LISSAJOUS) {
-                x = ((src[1] - src[0]) * zoom / 2 + 1) * hw;
-                y = (1.0 - (src[0] + src[1]) * zoom / 2) * hh;
-            } else if (s->mode == LISSAJOUS_XY){
-                x = (src[1] * zoom + 1) * hw;
-                y = (src[0] * zoom + 1) * hh;
-            } else {
-                float sx, sy, cx, cy;
-
-                sx = src[1] * zoom;
-                sy = src[0] * zoom;
-                cx = sx * sqrtf(1 - 0.5 * sy * sy);
-                cy = sy * sqrtf(1 - 0.5 * sx * sx);
-                x = hw + hw * FFSIGN(cx + cy) * (cx - cy) * .7;
-                y = s->h - s->h * fabsf(cx + cy) * .7;
-            }
 
-            if (s->draw == DOT) {
-                draw_dot(s, x, y);
-            } else {
-                draw_line(s, x, y, prev_x, prev_y);
-            }
-            prev_x = x;
-            prev_y = y;
+        switch (s->scale) {
+        case SQRT:
+            src[0] = FFSIGN(src[0]) * sqrtf(FFABS(src[0]));
+            src[1] = FFSIGN(src[1]) * sqrtf(FFABS(src[1]));
+            break;
+        case CBRT:
+            src[0] = FFSIGN(src[0]) * cbrtf(FFABS(src[0]));
+            src[1] = FFSIGN(src[1]) * cbrtf(FFABS(src[1]));
+            break;
+        case LOG:
+            src[0] = FFSIGN(src[0]) * logf(1 + FFABS(src[0])) / logf(2);
+            src[1] = FFSIGN(src[1]) * logf(1 + FFABS(src[1])) / logf(2);
+            break;
+        }
+
+        if (s->mode == LISSAJOUS) {
+            x = ((src[1] - src[0]) * zoom / 2 + 1) * hw;
+            y = (1.0 - (src[0] + src[1]) * zoom / 2) * hh;
+        } else if (s->mode == LISSAJOUS_XY) {
+            x = (src[1] * zoom + 1) * hw;
+            y = (src[0] * zoom + 1) * hh;
+        } else {
+            float sx, sy, cx, cy;
+
+            sx = src[1] * zoom;
+            sy = src[0] * zoom;
+            cx = sx * sqrtf(1 - 0.5 * sy * sy);
+            cy = sy * sqrtf(1 - 0.5 * sx * sx);
+            x = hw + hw * FFSIGN(cx + cy) * (cx - cy) * .7;
+            y = s->h - s->h * fabsf(cx + cy) * .7;
+        }
+
+        if (s->draw == DOT) {
+            draw_dot(s, x, y);
+        } else {
+            draw_line(s, x, y, prev_x, prev_y);
         }
-        break;
-    default:
-        av_assert0(0);
+        prev_x = x;
+        prev_y = y;
     }
 
     s->prev_x = x, s->prev_y = y;