Browse code

avfilter/avf_showcqt: add attack option

Signed-off-by: Muhammad Faiz <mfcc64@gmail.com>

Muhammad Faiz authored on 2017/04/08 11:55:06
Showing 4 changed files
... ...
@@ -17192,6 +17192,11 @@ event in time domain is represented more accurately (such as fast bass drum),
17192 17192
 otherwise event in frequency domain is represented more accurately
17193 17193
 (such as bass guitar). Acceptable range is @code{[0.002, 1]}. Default value is @code{0.17}.
17194 17194
 
17195
+@item attack
17196
+Set attack time in seconds. The default is @code{0} (disabled). Otherwise, it
17197
+limits future samples by applying asymmetric windowing in time domain, useful
17198
+when low latency is required. Accepted range is @code{[0, 1]}.
17199
+
17195 17200
 @item basefreq
17196 17201
 Specify the transform base frequency. Default value is @code{20.01523126408007475},
17197 17202
 which is frequency 50 cents below E0. Acceptable range is @code{[10, 100000]}.
... ...
@@ -78,6 +78,7 @@ static const AVOption showcqt_options[] = {
78 78
     { "bar_t",  "set bar transparency", OFFSET(bar_t),      AV_OPT_TYPE_FLOAT, { .dbl = 1.0 },            0.0, 1.0,      FLAGS },
79 79
     { "timeclamp",     "set timeclamp", OFFSET(timeclamp), AV_OPT_TYPE_DOUBLE, { .dbl = 0.17 },         0.002, 1.0,      FLAGS },
80 80
     { "tc",            "set timeclamp", OFFSET(timeclamp), AV_OPT_TYPE_DOUBLE, { .dbl = 0.17 },         0.002, 1.0,      FLAGS },
81
+    { "attack",      "set attack time", OFFSET(attack),    AV_OPT_TYPE_DOUBLE, { .dbl = 0 },              0.0, 1.0,      FLAGS },
81 82
     { "basefreq", "set base frequency", OFFSET(basefreq),  AV_OPT_TYPE_DOUBLE, { .dbl = BASEFREQ },      10.0, 100000.0, FLAGS },
82 83
     { "endfreq",   "set end frequency", OFFSET(endfreq),   AV_OPT_TYPE_DOUBLE, { .dbl = ENDFREQ },       10.0, 100000.0, FLAGS },
83 84
     { "coeffclamp",   "set coeffclamp", OFFSET(coeffclamp), AV_OPT_TYPE_FLOAT, { .dbl = 1.0 },            0.1, 10.0,     FLAGS },
... ...
@@ -152,6 +153,7 @@ static void common_uninit(ShowCQTContext *s)
152 152
     av_freep(&s->fft_data);
153 153
     av_freep(&s->fft_result);
154 154
     av_freep(&s->cqt_result);
155
+    av_freep(&s->attack_data);
155 156
     av_freep(&s->c_buf);
156 157
     av_freep(&s->h_buf);
157 158
     av_freep(&s->rcp_h_buf);
... ...
@@ -1138,6 +1140,14 @@ static int plot_cqt(AVFilterContext *ctx, AVFrame **frameout)
1138 1138
     last_time = av_gettime();
1139 1139
 
1140 1140
     memcpy(s->fft_result, s->fft_data, s->fft_len * sizeof(*s->fft_data));
1141
+    if (s->attack_data) {
1142
+        int k;
1143
+        for (k = 0; k < s->remaining_fill_max; k++) {
1144
+            s->fft_result[s->fft_len/2+k].re *= s->attack_data[k];
1145
+            s->fft_result[s->fft_len/2+k].im *= s->attack_data[k];
1146
+        }
1147
+    }
1148
+
1141 1149
     av_fft_permute(s->fft_ctx, s->fft_result);
1142 1150
     av_fft_calc(s->fft_ctx, s->fft_result);
1143 1151
     s->fft_result[s->fft_len] = s->fft_result[0];
... ...
@@ -1377,6 +1387,21 @@ static int config_output(AVFilterLink *outlink)
1377 1377
     if (!s->fft_ctx || !s->fft_data || !s->fft_result || !s->cqt_result)
1378 1378
         return AVERROR(ENOMEM);
1379 1379
 
1380
+    s->remaining_fill_max = s->fft_len / 2;
1381
+    if (s->attack > 0.0) {
1382
+        int k;
1383
+
1384
+        s->remaining_fill_max = FFMIN(s->remaining_fill_max, ceil(inlink->sample_rate * s->attack));
1385
+        s->attack_data = av_malloc_array(s->remaining_fill_max, sizeof(*s->attack_data));
1386
+        if (!s->attack_data)
1387
+            return AVERROR(ENOMEM);
1388
+
1389
+        for (k = 0; k < s->remaining_fill_max; k++) {
1390
+            double y = M_PI * k / (inlink->sample_rate * s->attack);
1391
+            s->attack_data[k] = 0.355768 + 0.487396 * cos(y) + 0.144232 * cos(2*y) + 0.012604 * cos(3*y);
1392
+        }
1393
+    }
1394
+
1380 1395
     s->cqt_align = 1;
1381 1396
     s->cqt_calc = cqt_calc;
1382 1397
     s->permute_coeffs = NULL;
... ...
@@ -1435,7 +1460,7 @@ static int config_output(AVFilterLink *outlink)
1435 1435
     s->sono_count = 0;
1436 1436
     s->next_pts = 0;
1437 1437
     s->sono_idx = 0;
1438
-    s->remaining_fill = s->fft_len / 2;
1438
+    s->remaining_fill = s->remaining_fill_max;
1439 1439
     s->remaining_frac = 0;
1440 1440
     s->step_frac = av_div_q(av_make_q(inlink->sample_rate, s->count) , s->rate);
1441 1441
     s->step = (int)(s->step_frac.num / s->step_frac.den);
... ...
@@ -1463,15 +1488,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
1463 1463
     AVFrame *out = NULL;
1464 1464
 
1465 1465
     if (!insamples) {
1466
-        while (s->remaining_fill < s->fft_len / 2) {
1467
-            memset(&s->fft_data[s->fft_len - s->remaining_fill], 0, sizeof(*s->fft_data) * s->remaining_fill);
1466
+        while (s->remaining_fill < s->remaining_fill_max) {
1467
+            memset(&s->fft_data[s->fft_len/2 + s->remaining_fill_max - s->remaining_fill], 0, sizeof(*s->fft_data) * s->remaining_fill);
1468 1468
             ret = plot_cqt(ctx, &out);
1469 1469
             if (ret < 0)
1470 1470
                 return ret;
1471 1471
 
1472 1472
             step = s->step + (s->step_frac.num + s->remaining_frac) / s->step_frac.den;
1473 1473
             s->remaining_frac = (s->step_frac.num + s->remaining_frac) % s->step_frac.den;
1474
-            for (x = 0; x < (s->fft_len-step); x++)
1474
+            for (x = 0; x < (s->fft_len/2 + s->remaining_fill_max - step); x++)
1475 1475
                 s->fft_data[x] = s->fft_data[x+step];
1476 1476
             s->remaining_fill += step;
1477 1477
 
... ...
@@ -1486,7 +1511,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
1486 1486
 
1487 1487
     while (remaining) {
1488 1488
         i = insamples->nb_samples - remaining;
1489
-        j = s->fft_len - s->remaining_fill;
1489
+        j = s->fft_len/2 + s->remaining_fill_max - s->remaining_fill;
1490 1490
         if (remaining >= s->remaining_fill) {
1491 1491
             for (m = 0; m < s->remaining_fill; m++) {
1492 1492
                 s->fft_data[j+m].re = audio_data[2*(i+m)];
... ...
@@ -1500,7 +1525,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
1500 1500
             remaining -= s->remaining_fill;
1501 1501
             if (out) {
1502 1502
                 int64_t pts = av_rescale_q(insamples->pts, inlink->time_base, av_make_q(1, inlink->sample_rate));
1503
-                pts += insamples->nb_samples - remaining - s->fft_len/2;
1503
+                pts += insamples->nb_samples - remaining - s->remaining_fill_max;
1504 1504
                 pts = av_rescale_q(pts, av_make_q(1, inlink->sample_rate), outlink->time_base);
1505 1505
                 if (FFABS(pts - out->pts) > PTS_TOLERANCE) {
1506 1506
                     av_log(ctx, AV_LOG_DEBUG, "changing pts from %"PRId64" (%.3f) to %"PRId64" (%.3f).\n",
... ...
@@ -1518,7 +1543,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
1518 1518
             }
1519 1519
             step = s->step + (s->step_frac.num + s->remaining_frac) / s->step_frac.den;
1520 1520
             s->remaining_frac = (s->step_frac.num + s->remaining_frac) % s->step_frac.den;
1521
-            for (m = 0; m < s->fft_len-step; m++)
1521
+            for (m = 0; m < s->fft_len/2 + s->remaining_fill_max - step; m++)
1522 1522
                 s->fft_data[m] = s->fft_data[m+step];
1523 1523
             s->remaining_fill = step;
1524 1524
         } else {
... ...
@@ -55,6 +55,7 @@ typedef struct {
55 55
     AVRational          step_frac;
56 56
     int                 remaining_frac;
57 57
     int                 remaining_fill;
58
+    int                 remaining_fill_max;
58 59
     int64_t             next_pts;
59 60
     double              *freq;
60 61
     FFTContext          *fft_ctx;
... ...
@@ -62,6 +63,7 @@ typedef struct {
62 62
     FFTComplex          *fft_data;
63 63
     FFTComplex          *fft_result;
64 64
     FFTComplex          *cqt_result;
65
+    float               *attack_data;
65 66
     int                 fft_bits;
66 67
     int                 fft_len;
67 68
     int                 cqt_len;
... ...
@@ -104,6 +106,7 @@ typedef struct {
104 104
     float               bar_g;
105 105
     float               bar_t;
106 106
     double              timeclamp;
107
+    double              attack;
107 108
     double              basefreq;
108 109
     double              endfreq;
109 110
     float               coeffclamp; /* deprecated - ignored */
... ...
@@ -31,7 +31,7 @@
31 31
 
32 32
 #define LIBAVFILTER_VERSION_MAJOR   6
33 33
 #define LIBAVFILTER_VERSION_MINOR  84
34
-#define LIBAVFILTER_VERSION_MICRO 100
34
+#define LIBAVFILTER_VERSION_MICRO 101
35 35
 
36 36
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
37 37
                                                LIBAVFILTER_VERSION_MINOR, \