[FFmpeg-cvslog] avfilter/af_silenceremove: add median silence detector
Paul B Mahol
git at videolan.org
Sat May 27 01:35:39 EEST 2023
ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Fri May 26 14:10:38 2023 +0200| [5a13b133f8effe2a2bac07b17f591d8ca7f6c1de] | committer: Paul B Mahol
avfilter/af_silenceremove: add median silence detector
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=5a13b133f8effe2a2bac07b17f591d8ca7f6c1de
---
doc/filters.texi | 2 +-
libavfilter/af_silenceremove.c | 6 ++++
libavfilter/silenceremove_template.c | 69 ++++++++++++++++++++++++++++++++++--
3 files changed, 74 insertions(+), 3 deletions(-)
diff --git a/doc/filters.texi b/doc/filters.texi
index 6f15b54d10..ea42c127da 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -6461,7 +6461,7 @@ With @var{all}, only if all channels are detected as non-silence will cause
stopped trimming of silence.
@item detection
-Set how is silence detected. Can be @code{avg}, @code{rms} or @code{peak}.
+Set how is silence detected. Can be @code{avg}, @code{rms}, @code{median} or @code{peak}.
Default value is @code{rms}.
@item window
diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c
index a3ad0eea13..fa182fc9f3 100644
--- a/libavfilter/af_silenceremove.c
+++ b/libavfilter/af_silenceremove.c
@@ -36,6 +36,7 @@ enum SilenceDetect {
D_AVG,
D_RMS,
D_PEAK,
+ D_MEDIAN,
D_NB
};
@@ -132,6 +133,7 @@ static const AVOption silenceremove_options[] = {
{ "avg", "use mean absolute values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_AVG}, 0, 0, AF, "detection" },
{ "rms", "use root mean squared values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_RMS}, 0, 0, AF, "detection" },
{ "peak", "use max absolute values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_PEAK},0, 0, AF, "detection" },
+ { "median", "use median of absolute values of samples", 0, AV_OPT_TYPE_CONST, {.i64=D_MEDIAN},0, 0, AF, "detection" },
{ "window", "set duration of window for silence detection", OFFSET(window_duration_opt), AV_OPT_TYPE_DURATION, {.i64=20000}, 0, 100000000, AF },
{ NULL }
};
@@ -234,6 +236,10 @@ static int config_output(AVFilterLink *outlink)
s->compute_flt = compute_avg_flt;
s->compute_dbl = compute_avg_dbl;
break;
+ case D_MEDIAN:
+ s->compute_flt = compute_median_flt;
+ s->compute_dbl = compute_median_dbl;
+ break;
case D_PEAK:
s->compute_flt = compute_peak_flt;
s->compute_dbl = compute_peak_dbl;
diff --git a/libavfilter/silenceremove_template.c b/libavfilter/silenceremove_template.c
index be51beb300..143d399f9e 100644
--- a/libavfilter/silenceremove_template.c
+++ b/libavfilter/silenceremove_template.c
@@ -22,6 +22,7 @@
#undef SAMPLE_FORMAT
#undef SQRT
#undef ZERO
+#undef ONE
#if DEPTH == 32
#define SAMPLE_FORMAT flt
#define SQRT sqrtf
@@ -29,6 +30,7 @@
#define FABS fabsf
#define ftype float
#define ZERO 0.f
+#define ONE 1.f
#else
#define SAMPLE_FORMAT dbl
#define SQRT sqrt
@@ -36,6 +38,7 @@
#define FABS fabs
#define ftype double
#define ZERO 0.0
+#define ONE 1.0
#endif
#define fn3(a,b) a##_##b
@@ -111,6 +114,68 @@ static ftype fn(compute_avg)(ftype *cache, ftype sample, ftype wsample,
return r / window_size;
}
+static ftype fn(compute_median)(ftype *peak, ftype sample, ftype wsample,
+ int size, int *ffront, int *bback)
+{
+ ftype r, abs_sample = FABS(sample);
+ int front = *ffront;
+ int back = *bback;
+ int empty = front == back && peak[front] == -ONE;
+ int idx;
+
+ if (!empty && FABS(wsample) == peak[front]) {
+ peak[front] = -ONE;
+ if (back != front) {
+ front--;
+ if (front < 0)
+ front = size - 1;
+ }
+ empty = front == back;
+ }
+
+ if (!empty && abs_sample > peak[front]) {
+ while (1) {
+ peak[front] = -ONE;
+ if (back == front) {
+ empty = 1;
+ break;
+ }
+ front--;
+ if (front < 0)
+ front = size - 1;
+ }
+ }
+
+ while (!empty && abs_sample > peak[back]) {
+ peak[back] = -ONE;
+ if (back == front) {
+ empty = 1;
+ break;
+ }
+ back++;
+ if (back >= size)
+ back = 0;
+ }
+
+ if (!empty) {
+ back--;
+ if (back < 0)
+ back = size - 1;
+ }
+
+ peak[back] = abs_sample;
+ idx = (back <= front) ? back + (front - back + 1) / 2 : back + (size + front - back + 1) / 2;
+ if (idx >= size)
+ idx -= size;
+ av_assert2(idx >= 0 && idx < size);
+ r = peak[idx];
+
+ *ffront = front;
+ *bback = back;
+
+ return r;
+}
+
static ftype fn(compute_peak)(ftype *peak, ftype sample, ftype wsample,
int size, int *ffront, int *bback)
{
@@ -216,7 +281,7 @@ static void fn(filter_start)(AVFilterContext *ctx,
if (s->start_found_periods < 0)
goto skip;
- if (s->detection != D_PEAK)
+ if (s->detection != D_PEAK && s->detection != D_MEDIAN)
window_size = s->start_window_size;
for (int ch = 0; ch < nb_channels; ch++) {
@@ -308,7 +373,7 @@ static void fn(filter_stop)(AVFilterContext *ctx,
stop_nb_samples,
stop_window_nb_samples);
- if (s->detection != D_PEAK)
+ if (s->detection != D_PEAK && s->detection != D_MEDIAN)
window_size = s->stop_window_size;
for (int ch = 0; ch < nb_channels; ch++) {
More information about the ffmpeg-cvslog
mailing list