FFmpeg
af_atilt.c
Go to the documentation of this file.
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 
20 #include "libavutil/ffmath.h"
21 #include "libavutil/opt.h"
22 #include "avfilter.h"
23 #include "audio.h"
24 
25 #define MAX_ORDER 30
26 
27 typedef struct Coeffs {
28  double g;
29  double a1;
30  double b0, b1;
31 } Coeffs;
32 
33 typedef struct ATiltContext {
34  const AVClass *class;
35 
36  double freq;
37  double level;
38  double slope;
39  double width;
40  int order;
41 
43 
45 
46  int (*filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
47 } ATiltContext;
48 
49 static double prewarp(double w, double T, double wp)
50 {
51  return wp * tan(w * T * 0.5) / tan(wp * T * 0.5);
52 }
53 
54 static double mz(int i, double w0, double r, double alpha)
55 {
56  return w0 * pow(r, -alpha + i);
57 }
58 
59 static double mp(int i, double w0, double r)
60 {
61  return w0 * pow(r, i);
62 }
63 
64 static double mzh(int i, double T, double w0, double r, double alpha)
65 {
66  return prewarp(mz(i, w0, r, alpha), T, w0);
67 }
68 
69 static double mph(int i, double T, double w0, double r)
70 {
71  return prewarp(mp(i, w0, r), T, w0);
72 }
73 
74 static void set_tf1s(Coeffs *coeffs, double b1, double b0, double a0,
75  double w1, double sr, double alpha)
76 {
77  double c = 1.0 / tan(w1 * 0.5 / sr);
78  double d = a0 + c;
79 
80  coeffs->b1 = (b0 - b1 * c) / d;
81  coeffs->b0 = (b0 + b1 * c) / d;
82  coeffs->a1 = (a0 - c) / d;
83  coeffs->g = a0 / b0;
84 }
85 
87  int order, double sr, double f0,
88  double bw, double alpha)
89 {
90  ATiltContext *s = ctx->priv;
91  const double w0 = 2. * M_PI * f0;
92  const double f1 = f0 + bw;
93  const double w1 = 1.;
94  const double r = pow(f1 / f0, 1.0 / (order - 1.0));
95  const double T = 1. / sr;
96 
97  for (int i = 0; i < order; i++) {
98  Coeffs *coeffs = &s->coeffs[i];
99 
100  set_tf1s(coeffs, 1.0, mzh(i, T, w0, r, alpha), mph(i, T, w0, r),
101  w1, sr, alpha);
102  }
103 }
104 
106 {
107  ATiltContext *s = ctx->priv;
108  AVFilterLink *inlink = ctx->inputs[0];
109 
110  set_filter(ctx, s->order, inlink->sample_rate, s->freq, s->width, s->slope);
111 
112  return 0;
113 }
114 
115 typedef struct ThreadData {
116  AVFrame *in, *out;
117 } ThreadData;
118 
119 #define FILTER(name, type) \
120 static int filter_channels_## name(AVFilterContext *ctx, void *arg, \
121  int jobnr, int nb_jobs) \
122 { \
123  ATiltContext *s = ctx->priv; \
124  ThreadData *td = arg; \
125  AVFrame *out = td->out; \
126  AVFrame *in = td->in; \
127  const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; \
128  const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; \
129  const type level = s->level; \
130  \
131  for (int ch = start; ch < end; ch++) { \
132  const type *src = (const type *)in->extended_data[ch]; \
133  type *dst = (type *)out->extended_data[ch]; \
134  \
135  for (int b = 0; b < s->order; b++) { \
136  Coeffs *coeffs = &s->coeffs[b]; \
137  const type g = coeffs->g; \
138  const type a1 = coeffs->a1; \
139  const type b0 = coeffs->b0; \
140  const type b1 = coeffs->b1; \
141  type *w = ((type *)s->w->extended_data[ch]) + b * 2; \
142  \
143  for (int n = 0; n < in->nb_samples; n++) { \
144  type sain = b ? dst[n] : src[n] * level; \
145  type saout = sain * b0 + w[0] * b1 - w[1] * a1; \
146  \
147  w[0] = sain; \
148  w[1] = saout; \
149  \
150  dst[n] = saout * g; \
151  } \
152  } \
153  } \
154  \
155  return 0; \
156 }
157 
158 FILTER(fltp, float)
159 FILTER(dblp, double)
160 
162 {
163  AVFilterContext *ctx = inlink->dst;
164  ATiltContext *s = ctx->priv;
165 
166  switch (inlink->format) {
167  case AV_SAMPLE_FMT_FLTP: s->filter_channels = filter_channels_fltp; break;
168  case AV_SAMPLE_FMT_DBLP: s->filter_channels = filter_channels_dblp; break;
169  }
170 
172  if (!s->w)
173  return AVERROR(ENOMEM);
174 
175  return get_coeffs(ctx);
176 }
177 
179 {
180  AVFilterContext *ctx = inlink->dst;
181  ATiltContext *s = ctx->priv;
182  AVFilterLink *outlink = ctx->outputs[0];
183  ThreadData td;
184  AVFrame *out;
185 
186  if (av_frame_is_writable(in)) {
187  out = in;
188  } else {
189  out = ff_get_audio_buffer(outlink, in->nb_samples);
190  if (!out) {
191  av_frame_free(&in);
192  return AVERROR(ENOMEM);
193  }
195  }
196 
197  td.in = in; td.out = out;
198  ff_filter_execute(ctx, s->filter_channels, &td, NULL, FFMIN(inlink->ch_layout.nb_channels,
200 
201  if (out != in)
202  av_frame_free(&in);
203  return ff_filter_frame(outlink, out);
204 }
205 
206 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
207  char *res, int res_len, int flags)
208 {
209  int ret;
210 
211  ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
212  if (ret < 0)
213  return ret;
214 
215  return get_coeffs(ctx);
216 }
217 
219 {
220  ATiltContext *s = ctx->priv;
221 
222  av_frame_free(&s->w);
223 }
224 
225 #define OFFSET(x) offsetof(ATiltContext, x)
226 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
227 
228 static const AVOption atilt_options[] = {
229  { "freq", "set central frequency",OFFSET(freq), AV_OPT_TYPE_DOUBLE, {.dbl=10000}, 20, 192000, FLAGS },
230  { "slope", "set filter slope", OFFSET(slope), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS },
231  { "width", "set filter width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1000}, 100, 10000, FLAGS },
232  { "order", "set filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=5}, 2,MAX_ORDER, FLAGS },
233  { "level", "set input level", OFFSET(level), AV_OPT_TYPE_DOUBLE, {.dbl=1.}, 0., 4., FLAGS },
234  { NULL }
235 };
236 
237 AVFILTER_DEFINE_CLASS(atilt);
238 
239 static const AVFilterPad inputs[] = {
240  {
241  .name = "default",
242  .type = AVMEDIA_TYPE_AUDIO,
243  .filter_frame = filter_frame,
244  .config_props = config_input,
245  },
246 };
247 
249  .name = "atilt",
250  .description = NULL_IF_CONFIG_SMALL("Apply spectral tilt to audio."),
251  .priv_size = sizeof(ATiltContext),
252  .priv_class = &atilt_class,
253  .uninit = uninit,
257  .process_command = process_command,
260 };
ff_get_audio_buffer
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Definition: audio.c:107
AV_SAMPLE_FMT_FLTP
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition: samplefmt.h:66
td
#define td
Definition: regdef.h:70
level
uint8_t level
Definition: svq3.c:204
r
const char * r
Definition: vf_curves.c:126
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
ff_af_atilt
const AVFilter ff_af_atilt
Definition: af_atilt.c:248
out
FILE * out
Definition: movenc.c:54
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:978
get_coeffs
static int get_coeffs(AVFilterContext *ctx)
Definition: af_atilt.c:105
Coeffs::b0
double b0
Definition: af_atilt.c:30
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:100
mp
static double mp(int i, double w0, double r)
Definition: af_atilt.c:59
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:340
w
uint8_t w
Definition: llviddspenc.c:38
ATiltContext
Definition: af_atilt.c:33
AVOption
AVOption.
Definition: opt.h:251
set_tf1s
static void set_tf1s(Coeffs *coeffs, double b1, double b0, double a0, double w1, double sr, double alpha)
Definition: af_atilt.c:74
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:170
ThreadData::out
AVFrame * out
Definition: af_adeclick.c:526
ThreadData::in
AVFrame * in
Definition: af_adecorrelate.c:153
set_filter
static void set_filter(AVFilterContext *ctx, int order, double sr, double f0, double bw, double alpha)
Definition: af_atilt.c:86
ATiltContext::freq
double freq
Definition: af_atilt.c:36
b1
static double b1(void *priv, double x, double y)
Definition: vf_xfade.c:2035
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:47
T
#define T(x)
Definition: vpx_arith.h:29
av_cold
#define av_cold
Definition: attributes.h:90
mzh
static double mzh(int i, double T, double w0, double r, double alpha)
Definition: af_atilt.c:64
Coeffs::g
double g
Definition: af_atilt.c:28
ATiltContext::order
int order
Definition: af_atilt.c:40
FILTER
#define FILTER(name, type)
Definition: af_atilt.c:119
width
#define width
s
#define s(width, name)
Definition: cbs_vp9.c:198
AV_OPT_TYPE_DOUBLE
@ AV_OPT_TYPE_DOUBLE
Definition: opt.h:227
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
ATiltContext::coeffs
Coeffs coeffs[MAX_ORDER]
Definition: af_atilt.c:42
ctx
AVFormatContext * ctx
Definition: movenc.c:48
mph
static double mph(int i, double T, double w0, double r)
Definition: af_atilt.c:69
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:192
FLAGS
#define FLAGS
Definition: af_atilt.c:226
arg
const char * arg
Definition: jacosubdec.c:67
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:736
process_command
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
Definition: af_atilt.c:206
ATiltContext::w
AVFrame * w
Definition: af_atilt.c:44
ff_audio_default_filterpad
const AVFilterPad ff_audio_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_AUDIO.
Definition: audio.c:32
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: af_atilt.c:218
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
config_input
static int config_input(AVFilterLink *inlink)
Definition: af_atilt.c:161
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:106
MAX_ORDER
#define MAX_ORDER
Definition: af_atilt.c:25
mz
static double mz(int i, double w0, double r, double alpha)
Definition: af_atilt.c:54
av_frame_is_writable
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
Definition: frame.c:666
ATiltContext::slope
double slope
Definition: af_atilt.c:38
ff_filter_process_command
int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Generic processing of user supplied commands that are set in the same way as the filter options.
Definition: avfilter.c:851
a0
#define a0
Definition: regdef.h:46
Coeffs::b1
double b1
Definition: af_atilt.c:30
M_PI
#define M_PI
Definition: mathematics.h:67
AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
Definition: avfilter.h:147
AVFrame::nb_samples
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:420
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
inputs
static const AVFilterPad inputs[]
Definition: af_atilt.c:239
prewarp
static double prewarp(double w, double T, double wp)
Definition: af_atilt.c:49
ff_filter_get_nb_threads
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:786
ThreadData
Used for passing data between threads.
Definition: dsddec.c:69
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:53
atilt_options
static const AVOption atilt_options[]
Definition: af_atilt.c:228
AVFilter
Filter definition.
Definition: avfilter.h:166
ret
ret
Definition: filter_design.txt:187
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: af_atilt.c:178
Coeffs::a1
double a1
Definition: af_atilt.c:29
ATiltContext::filter_channels
int(* filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: af_atilt.c:46
Coeffs
Definition: af_atilt.c:27
channel_layout.h
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
avfilter.h
AV_SAMPLE_FMT_DBLP
@ AV_SAMPLE_FMT_DBLP
double, planar
Definition: samplefmt.h:67
ffmath.h
OFFSET
#define OFFSET(x)
Definition: af_atilt.c:225
ATiltContext::level
double level
Definition: af_atilt.c:37
AVFilterContext
An instance of a filter.
Definition: avfilter.h:397
AVFILTER_FLAG_SLICE_THREADS
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:117
audio.h
alpha
static const int16_t alpha[]
Definition: ilbcdata.h:55
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:193
d
d
Definition: ffmpeg_filter.c:368
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:474
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(atilt)
b0
static double b0(void *priv, double x, double y)
Definition: vf_xfade.c:2034
ff_filter_execute
static av_always_inline int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition: internal.h:144
int
int
Definition: ffmpeg_filter.c:368
ATiltContext::width
double width
Definition: af_atilt.c:39
FILTER_SAMPLEFMTS
#define FILTER_SAMPLEFMTS(...)
Definition: internal.h:180