FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/af_adynamicsmooth.c
Date: 2026-09-25 17:25:24
Exec Total Coverage
Lines: 0 47 0.0%
Functions: 0 3 0.0%
Branches: 0 14 0.0%

Line Branch Exec Source
1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include "libavutil/ffmath.h"
20 #include "libavutil/opt.h"
21 #include "avfilter.h"
22 #include "audio.h"
23 #include "filters.h"
24
25 typedef struct AudioDynamicSmoothContext {
26 const AVClass *class;
27
28 double sensitivity;
29 double basefreq;
30
31 AVFrame *coeffs;
32 } AudioDynamicSmoothContext;
33
34 ✗ static int config_input(AVFilterLink *inlink)
35 {
36 ✗ AVFilterContext *ctx = inlink->dst;
37 ✗ AudioDynamicSmoothContext *s = ctx->priv;
38
39 ✗ s->coeffs = ff_get_audio_buffer(inlink, 3);
40 ✗ if (!s->coeffs)
41 ✗ return AVERROR(ENOMEM);
42
43 ✗ return 0;
44 }
45
46 ✗ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
47 {
48 ✗ AVFilterContext *ctx = inlink->dst;
49 ✗ AVFilterLink *outlink = ctx->outputs[0];
50 ✗ AudioDynamicSmoothContext *s = ctx->priv;
51 ✗ const double sensitivity = s->sensitivity;
52 ✗ const double wc = s->basefreq / in->sample_rate;
53 AVFrame *out;
54
55 ✗ if (av_frame_is_writable(in)) {
56 ✗ out = in;
57 } else {
58 ✗ out = ff_get_audio_buffer(outlink, in->nb_samples);
59 ✗ if (!out) {
60 ✗ av_frame_free(&in);
61 ✗ return AVERROR(ENOMEM);
62 }
63 ✗ av_frame_copy_props(out, in);
64 }
65
66 ✗ for (int ch = 0; ch < out->ch_layout.nb_channels; ch++) {
67 ✗ const double *src = (const double *)in->extended_data[ch];
68 ✗ double *dst = (double *)out->extended_data[ch];
69 ✗ double *coeffs = (double *)s->coeffs->extended_data[ch];
70 ✗ double low1 = coeffs[0];
71 ✗ double low2 = coeffs[1];
72 ✗ double inz = coeffs[2];
73
74 ✗ for (int n = 0; n < out->nb_samples; n++) {
75 ✗ double low1z = low1;
76 ✗ double low2z = low2;
77 ✗ double bandz = low2z - low1z;
78 ✗ double wd = wc + sensitivity * fabs(bandz);
79 ✗ double g = fmin(1., wd * (5.9948827 + wd * (-11.969296 + wd * 15.959062)));
80
81 ✗ low1 = low1z + g * (0.5 * (src[n] + inz) - low1z);
82 ✗ low2 = low2z + g * (0.5 * (low1 + low1z) - low2z);
83 ✗ inz = src[n];
84 ✗ dst[n] = ctx->is_disabled ? src[n] : low2;
85 }
86
87 ✗ coeffs[0] = low1;
88 ✗ coeffs[1] = low2;
89 ✗ coeffs[2] = inz;
90 }
91
92 ✗ if (out != in)
93 ✗ av_frame_free(&in);
94 ✗ return ff_filter_frame(outlink, out);
95 }
96
97 ✗ static av_cold void uninit(AVFilterContext *ctx)
98 {
99 ✗ AudioDynamicSmoothContext *s = ctx->priv;
100
101 ✗ av_frame_free(&s->coeffs);
102 ✗ }
103
104 #define OFFSET(x) offsetof(AudioDynamicSmoothContext, x)
105 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
106
107 static const AVOption adynamicsmooth_options[] = {
108 { "sensitivity", "set smooth sensitivity", OFFSET(sensitivity), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 0, 1000000, FLAGS },
109 { "basefreq", "set base frequency", OFFSET(basefreq), AV_OPT_TYPE_DOUBLE, {.dbl=22050}, 2, 1000000, FLAGS },
110 { NULL }
111 };
112
113 AVFILTER_DEFINE_CLASS(adynamicsmooth);
114
115 static const AVFilterPad inputs[] = {
116 {
117 .name = "default",
118 .type = AVMEDIA_TYPE_AUDIO,
119 .filter_frame = filter_frame,
120 .config_props = config_input,
121 },
122 };
123
124 const FFFilter ff_af_adynamicsmooth = {
125 .p.name = "adynamicsmooth",
126 .p.description = NULL_IF_CONFIG_SMALL("Apply Dynamic Smoothing of input audio."),
127 .p.priv_class = &adynamicsmooth_class,
128 .p.flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
129 .priv_size = sizeof(AudioDynamicSmoothContext),
130 .uninit = uninit,
131 FILTER_INPUTS(inputs),
132 FILTER_OUTPUTS(ff_audio_default_filterpad),
133 FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_DBLP),
134 .process_command = ff_filter_process_command,
135 };
136