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 #include "formats.h"
25 
26 #define MAX_ORDER 30
27 
28 typedef struct Coeffs {
29  double g;
30  double a1;
31  double b0, b1;
32 } Coeffs;
33 
34 typedef struct ATiltContext {
35  const AVClass *class;
36 
37  double freq;
38  double level;
39  double slope;
40  double width;
41  int order;
42 
44 
46 
47  int (*filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
48 } ATiltContext;
49 
50 static double prewarp(double w, double T, double wp)
51 {
52  return wp * tan(w * T * 0.5) / tan(wp * T * 0.5);
53 }
54 
55 static double mz(int i, double w0, double r, double alpha)
56 {
57  return w0 * pow(r, -alpha + i);
58 }
59 
60 static double mp(int i, double w0, double r)
61 {
62  return w0 * pow(r, i);
63 }
64 
65 static double mzh(int i, double T, double w0, double r, double alpha)
66 {
67  return prewarp(mz(i, w0, r, alpha), T, w0);
68 }
69 
70 static double mph(int i, double T, double w0, double r)
71 {
72  return prewarp(mp(i, w0, r), T, w0);
73 }
74 
75 static void set_tf1s(Coeffs *coeffs, double b1, double b0, double a0,
76  double w1, double sr, double alpha)
77 {
78  double c = 1.0 / tan(w1 * 0.5 / sr);
79  double d = a0 + c;
80 
81  coeffs->b1 = (b0 - b1 * c) / d;
82  coeffs->b0 = (b0 + b1 * c) / d;
83  coeffs->a1 = (a0 - c) / d;
84  coeffs->g = a0 / b0;
85 }
86 
88  int order, double sr, double f0,
89  double bw, double alpha)
90 {
91  ATiltContext *s = ctx->priv;
92  const double w0 = 2. * M_PI * f0;
93  const double f1 = f0 + bw;
94  const double w1 = 1.;
95  const double r = pow(f1 / f0, 1.0 / (order - 1.0));
96  const double T = 1. / sr;
97 
98  for (int i = 0; i < order; i++) {
99  Coeffs *coeffs = &s->coeffs[i];
100 
101  set_tf1s(coeffs, 1.0, mzh(i, T, w0, r, alpha), mph(i, T, w0, r),
102  w1, sr, alpha);
103  }
104 }
105 
107 {
108  ATiltContext *s = ctx->priv;
109  AVFilterLink *inlink = ctx->inputs[0];
110 
111  set_filter(ctx, s->order, inlink->sample_rate, s->freq, s->width, s->slope);
112 
113  return 0;
114 }
115 
116 typedef struct ThreadData {
117  AVFrame *in, *out;
118 } ThreadData;
119 
120 #define FILTER(name, type) \
121 static int filter_channels_## name(AVFilterContext *ctx, void *arg, \
122  int jobnr, int nb_jobs) \
123 { \
124  ATiltContext *s = ctx->priv; \
125  ThreadData *td = arg; \
126  AVFrame *out = td->out; \
127  AVFrame *in = td->in; \
128  const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; \
129  const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; \
130  const type level = s->level; \
131  \
132  for (int ch = start; ch < end; ch++) { \
133  const type *src = (const type *)in->extended_data[ch]; \
134  type *dst = (type *)out->extended_data[ch]; \
135  \
136  for (int b = 0; b < s->order; b++) { \
137  Coeffs *coeffs = &s->coeffs[b]; \
138  const type g = coeffs->g; \
139  const type a1 = coeffs->a1; \
140  const type b0 = coeffs->b0; \
141  const type b1 = coeffs->b1; \
142  type *w = ((type *)s->w->extended_data[ch]) + b * 2; \
143  \
144  for (int n = 0; n < in->nb_samples; n++) { \
145  type sain = b ? dst[n] : src[n] * level; \
146  type saout = sain * b0 + w[0] * b1 - w[1] * a1; \
147  \
148  w[0] = sain; \
149  w[1] = saout; \
150  \
151  dst[n] = saout * g; \
152  } \
153  } \
154  } \
155  \
156  return 0; \
157 }
158 
159 FILTER(fltp, float)
160 FILTER(dblp, double)
161 
163 {
164  AVFilterContext *ctx = inlink->dst;
165  ATiltContext *s = ctx->priv;
166 
167  switch (inlink->format) {
168  case AV_SAMPLE_FMT_FLTP: s->filter_channels = filter_channels_fltp; break;
169  case AV_SAMPLE_FMT_DBLP: s->filter_channels = filter_channels_dblp; break;
170  }
171 
173  if (!s->w)
174  return AVERROR(ENOMEM);
175 
176  return get_coeffs(ctx);
177 }
178 
180 {
181  AVFilterContext *ctx = inlink->dst;
182  ATiltContext *s = ctx->priv;
183  AVFilterLink *outlink = ctx->outputs[0];
184  ThreadData td;
185  AVFrame *out;
186 
187  if (av_frame_is_writable(in)) {
188  out = in;
189  } else {
190  out = ff_get_audio_buffer(outlink, in->nb_samples);
191  if (!out) {
192  av_frame_free(&in);
193  return AVERROR(ENOMEM);
194  }
196  }
197 
198  td.in = in; td.out = out;
199  ff_filter_execute(ctx, s->filter_channels, &td, NULL, FFMIN(inlink->ch_layout.nb_channels,
201 
202  if (out != in)
203  av_frame_free(&in);
204  return ff_filter_frame(outlink, out);
205 }
206 
207 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
208  char *res, int res_len, int flags)
209 {
210  int ret;
211 
212  ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
213  if (ret < 0)
214  return ret;
215 
216  return get_coeffs(ctx);
217 }
218 
220 {
221  ATiltContext *s = ctx->priv;
222 
223  av_frame_free(&s->w);
224 }
225 
226 #define OFFSET(x) offsetof(ATiltContext, x)
227 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
228 
229 static const AVOption atilt_options[] = {
230  { "freq", "set central frequency",OFFSET(freq), AV_OPT_TYPE_DOUBLE, {.dbl=10000}, 20, 192000, FLAGS },
231  { "slope", "set filter slope", OFFSET(slope), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1, 1, FLAGS },
232  { "width", "set filter width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1000}, 100, 10000, FLAGS },
233  { "order", "set filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=5}, 2,MAX_ORDER, FLAGS },
234  { "level", "set input level", OFFSET(level), AV_OPT_TYPE_DOUBLE, {.dbl=1.}, 0., 4., FLAGS },
235  { NULL }
236 };
237 
238 AVFILTER_DEFINE_CLASS(atilt);
239 
240 static const AVFilterPad inputs[] = {
241  {
242  .name = "default",
243  .type = AVMEDIA_TYPE_AUDIO,
244  .filter_frame = filter_frame,
245  .config_props = config_input,
246  },
247 };
248 
249 static const AVFilterPad outputs[] = {
250  {
251  .name = "default",
252  .type = AVMEDIA_TYPE_AUDIO,
253  },
254 };
255 
257  .name = "atilt",
258  .description = NULL_IF_CONFIG_SMALL("Apply spectral tilt to audio."),
259  .priv_size = sizeof(ATiltContext),
260  .priv_class = &atilt_class,
261  .uninit = uninit,
265  .process_command = process_command,
268 };
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:100
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:256
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:969
get_coeffs
static int get_coeffs(AVFilterContext *ctx)
Definition: af_atilt.c:106
Coeffs::b0
double b0
Definition: af_atilt.c:31
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:99
mp
static double mp(int i, double w0, double r)
Definition: af_atilt.c:60
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:330
w
uint8_t w
Definition: llviddspenc.c:38
ATiltContext
Definition: af_atilt.c:34
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:75
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:165
ThreadData::out
AVFrame * out
Definition: af_adeclick.c:473
ThreadData::in
AVFrame * in
Definition: af_adecorrelate.c:154
set_filter
static void set_filter(AVFilterContext *ctx, int order, double sr, double f0, double bw, double alpha)
Definition: af_atilt.c:87
ATiltContext::freq
double freq
Definition: af_atilt.c:37
formats.h
b1
static double b1(void *priv, double x, double y)
Definition: vf_xfade.c:1771
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:49
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:65
Coeffs::g
double g
Definition: af_atilt.c:29
ATiltContext::order
int order
Definition: af_atilt.c:41
FILTER
#define FILTER(name, type)
Definition: af_atilt.c:120
width
#define width
s
#define s(width, name)
Definition: cbs_vp9.c:256
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:43
ctx
AVFormatContext * ctx
Definition: movenc.c:48
mph
static double mph(int i, double T, double w0, double r)
Definition: af_atilt.c:70
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:194
FLAGS
#define FLAGS
Definition: af_atilt.c:227
arg
const char * arg
Definition: jacosubdec.c:67
outputs
static const AVFilterPad outputs[]
Definition: af_atilt.c:249
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:594
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:207
ATiltContext::w
AVFrame * w
Definition: af_atilt.c:45
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: af_atilt.c:219
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:162
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:115
MAX_ORDER
#define MAX_ORDER
Definition: af_atilt.c:26
mz
static double mz(int i, double w0, double r, double alpha)
Definition: af_atilt.c:55
av_frame_is_writable
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
Definition: frame.c:524
ATiltContext::slope
double slope
Definition: af_atilt.c:39
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:842
a0
#define a0
Definition: regdef.h:46
Coeffs::b1
double b1
Definition: af_atilt.c:31
M_PI
#define M_PI
Definition: mathematics.h:52
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:142
AVFrame::nb_samples
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:410
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
inputs
static const AVFilterPad inputs[]
Definition: af_atilt.c:240
prewarp
static double prewarp(double w, double T, double wp)
Definition: af_atilt.c:50
ff_filter_get_nb_threads
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:777
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:55
atilt_options
static const AVOption atilt_options[]
Definition: af_atilt.c:229
AVFilter
Filter definition.
Definition: avfilter.h:161
ret
ret
Definition: filter_design.txt:187
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: af_atilt.c:179
Coeffs::a1
double a1
Definition: af_atilt.c:30
ATiltContext::filter_channels
int(* filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: af_atilt.c:47
Coeffs
Definition: af_atilt.c:28
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:226
ATiltContext::level
double level
Definition: af_atilt.c:38
AVFilterContext
An instance of a filter.
Definition: avfilter.h:392
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:195
d
d
Definition: ffmpeg_filter.c:156
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(atilt)
b0
static double b0(void *priv, double x, double y)
Definition: vf_xfade.c:1770
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:146
int
int
Definition: ffmpeg_filter.c:156
ATiltContext::width
double width
Definition: af_atilt.c:40
FILTER_SAMPLEFMTS
#define FILTER_SAMPLEFMTS(...)
Definition: internal.h:182