blob: 79f1b7cf4c0361249ab2d8e3422039696618cb82
1 | /* |
2 | * Copyright (c) 2013 Paul B Mahol |
3 | * Copyright (c) 2006-2008 Rob Sykes <robs@users.sourceforge.net> |
4 | * |
5 | * This file is part of FFmpeg. |
6 | * |
7 | * FFmpeg is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 of the License, or (at your option) any later version. |
11 | * |
12 | * FFmpeg is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with FFmpeg; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ |
21 | |
22 | /* |
23 | * 2-pole filters designed by Robert Bristow-Johnson <rbj@audioimagination.com> |
24 | * see http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt |
25 | * |
26 | * 1-pole filters based on code (c) 2000 Chris Bagwell <cbagwell@sprynet.com> |
27 | * Algorithms: Recursive single pole low/high pass filter |
28 | * Reference: The Scientist and Engineer's Guide to Digital Signal Processing |
29 | * |
30 | * low-pass: output[N] = input[N] * A + output[N-1] * B |
31 | * X = exp(-2.0 * pi * Fc) |
32 | * A = 1 - X |
33 | * B = X |
34 | * Fc = cutoff freq / sample rate |
35 | * |
36 | * Mimics an RC low-pass filter: |
37 | * |
38 | * ---/\/\/\/\-----------> |
39 | * | |
40 | * --- C |
41 | * --- |
42 | * | |
43 | * | |
44 | * V |
45 | * |
46 | * high-pass: output[N] = A0 * input[N] + A1 * input[N-1] + B1 * output[N-1] |
47 | * X = exp(-2.0 * pi * Fc) |
48 | * A0 = (1 + X) / 2 |
49 | * A1 = -(1 + X) / 2 |
50 | * B1 = X |
51 | * Fc = cutoff freq / sample rate |
52 | * |
53 | * Mimics an RC high-pass filter: |
54 | * |
55 | * || C |
56 | * ----||---------> |
57 | * || | |
58 | * < |
59 | * > R |
60 | * < |
61 | * | |
62 | * V |
63 | */ |
64 | |
65 | #include "libavutil/avassert.h" |
66 | #include "libavutil/opt.h" |
67 | #include "audio.h" |
68 | #include "avfilter.h" |
69 | #include "internal.h" |
70 | |
71 | enum FilterType { |
72 | biquad, |
73 | equalizer, |
74 | bass, |
75 | treble, |
76 | band, |
77 | bandpass, |
78 | bandreject, |
79 | allpass, |
80 | highpass, |
81 | lowpass, |
82 | }; |
83 | |
84 | enum WidthType { |
85 | NONE, |
86 | HERTZ, |
87 | OCTAVE, |
88 | QFACTOR, |
89 | SLOPE, |
90 | }; |
91 | |
92 | typedef struct ChanCache { |
93 | double i1, i2; |
94 | double o1, o2; |
95 | } ChanCache; |
96 | |
97 | typedef struct BiquadsContext { |
98 | const AVClass *class; |
99 | |
100 | enum FilterType filter_type; |
101 | int width_type; |
102 | int poles; |
103 | int csg; |
104 | |
105 | double gain; |
106 | double frequency; |
107 | double width; |
108 | |
109 | double a0, a1, a2; |
110 | double b0, b1, b2; |
111 | |
112 | ChanCache *cache; |
113 | int clippings; |
114 | |
115 | void (*filter)(struct BiquadsContext *s, const void *ibuf, void *obuf, int len, |
116 | double *i1, double *i2, double *o1, double *o2, |
117 | double b0, double b1, double b2, double a1, double a2); |
118 | } BiquadsContext; |
119 | |
120 | static av_cold int init(AVFilterContext *ctx) |
121 | { |
122 | BiquadsContext *s = ctx->priv; |
123 | |
124 | if (s->filter_type != biquad) { |
125 | if (s->frequency <= 0 || s->width <= 0) { |
126 | av_log(ctx, AV_LOG_ERROR, "Invalid frequency %f and/or width %f <= 0\n", |
127 | s->frequency, s->width); |
128 | return AVERROR(EINVAL); |
129 | } |
130 | } |
131 | |
132 | return 0; |
133 | } |
134 | |
135 | static int query_formats(AVFilterContext *ctx) |
136 | { |
137 | AVFilterFormats *formats; |
138 | AVFilterChannelLayouts *layouts; |
139 | static const enum AVSampleFormat sample_fmts[] = { |
140 | AV_SAMPLE_FMT_S16P, |
141 | AV_SAMPLE_FMT_S32P, |
142 | AV_SAMPLE_FMT_FLTP, |
143 | AV_SAMPLE_FMT_DBLP, |
144 | AV_SAMPLE_FMT_NONE |
145 | }; |
146 | int ret; |
147 | |
148 | layouts = ff_all_channel_counts(); |
149 | if (!layouts) |
150 | return AVERROR(ENOMEM); |
151 | ret = ff_set_common_channel_layouts(ctx, layouts); |
152 | if (ret < 0) |
153 | return ret; |
154 | |
155 | formats = ff_make_format_list(sample_fmts); |
156 | if (!formats) |
157 | return AVERROR(ENOMEM); |
158 | ret = ff_set_common_formats(ctx, formats); |
159 | if (ret < 0) |
160 | return ret; |
161 | |
162 | formats = ff_all_samplerates(); |
163 | if (!formats) |
164 | return AVERROR(ENOMEM); |
165 | return ff_set_common_samplerates(ctx, formats); |
166 | } |
167 | |
168 | #define BIQUAD_FILTER(name, type, min, max, need_clipping) \ |
169 | static void biquad_## name (BiquadsContext *s, \ |
170 | const void *input, void *output, int len, \ |
171 | double *in1, double *in2, \ |
172 | double *out1, double *out2, \ |
173 | double b0, double b1, double b2, \ |
174 | double a1, double a2) \ |
175 | { \ |
176 | const type *ibuf = input; \ |
177 | type *obuf = output; \ |
178 | double i1 = *in1; \ |
179 | double i2 = *in2; \ |
180 | double o1 = *out1; \ |
181 | double o2 = *out2; \ |
182 | int i; \ |
183 | a1 = -a1; \ |
184 | a2 = -a2; \ |
185 | \ |
186 | for (i = 0; i+1 < len; i++) { \ |
187 | o2 = i2 * b2 + i1 * b1 + ibuf[i] * b0 + o2 * a2 + o1 * a1; \ |
188 | i2 = ibuf[i]; \ |
189 | if (need_clipping && o2 < min) { \ |
190 | s->clippings++; \ |
191 | obuf[i] = min; \ |
192 | } else if (need_clipping && o2 > max) { \ |
193 | s->clippings++; \ |
194 | obuf[i] = max; \ |
195 | } else { \ |
196 | obuf[i] = o2; \ |
197 | } \ |
198 | i++; \ |
199 | o1 = i1 * b2 + i2 * b1 + ibuf[i] * b0 + o1 * a2 + o2 * a1; \ |
200 | i1 = ibuf[i]; \ |
201 | if (need_clipping && o1 < min) { \ |
202 | s->clippings++; \ |
203 | obuf[i] = min; \ |
204 | } else if (need_clipping && o1 > max) { \ |
205 | s->clippings++; \ |
206 | obuf[i] = max; \ |
207 | } else { \ |
208 | obuf[i] = o1; \ |
209 | } \ |
210 | } \ |
211 | if (i < len) { \ |
212 | double o0 = ibuf[i] * b0 + i1 * b1 + i2 * b2 + o1 * a1 + o2 * a2; \ |
213 | i2 = i1; \ |
214 | i1 = ibuf[i]; \ |
215 | o2 = o1; \ |
216 | o1 = o0; \ |
217 | if (need_clipping && o0 < min) { \ |
218 | s->clippings++; \ |
219 | obuf[i] = min; \ |
220 | } else if (need_clipping && o0 > max) { \ |
221 | s->clippings++; \ |
222 | obuf[i] = max; \ |
223 | } else { \ |
224 | obuf[i] = o0; \ |
225 | } \ |
226 | } \ |
227 | *in1 = i1; \ |
228 | *in2 = i2; \ |
229 | *out1 = o1; \ |
230 | *out2 = o2; \ |
231 | } |
232 | |
233 | BIQUAD_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1) |
234 | BIQUAD_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) |
235 | BIQUAD_FILTER(flt, float, -1., 1., 0) |
236 | BIQUAD_FILTER(dbl, double, -1., 1., 0) |
237 | |
238 | static int config_output(AVFilterLink *outlink) |
239 | { |
240 | AVFilterContext *ctx = outlink->src; |
241 | BiquadsContext *s = ctx->priv; |
242 | AVFilterLink *inlink = ctx->inputs[0]; |
243 | double A = exp(s->gain / 40 * log(10.)); |
244 | double w0 = 2 * M_PI * s->frequency / inlink->sample_rate; |
245 | double alpha; |
246 | |
247 | if (w0 > M_PI) { |
248 | av_log(ctx, AV_LOG_ERROR, |
249 | "Invalid frequency %f. Frequency must be less than half the sample-rate %d.\n", |
250 | s->frequency, inlink->sample_rate); |
251 | return AVERROR(EINVAL); |
252 | } |
253 | |
254 | switch (s->width_type) { |
255 | case NONE: |
256 | alpha = 0.0; |
257 | break; |
258 | case HERTZ: |
259 | alpha = sin(w0) / (2 * s->frequency / s->width); |
260 | break; |
261 | case OCTAVE: |
262 | alpha = sin(w0) * sinh(log(2.) / 2 * s->width * w0 / sin(w0)); |
263 | break; |
264 | case QFACTOR: |
265 | alpha = sin(w0) / (2 * s->width); |
266 | break; |
267 | case SLOPE: |
268 | alpha = sin(w0) / 2 * sqrt((A + 1 / A) * (1 / s->width - 1) + 2); |
269 | break; |
270 | default: |
271 | av_assert0(0); |
272 | } |
273 | |
274 | switch (s->filter_type) { |
275 | case biquad: |
276 | break; |
277 | case equalizer: |
278 | s->a0 = 1 + alpha / A; |
279 | s->a1 = -2 * cos(w0); |
280 | s->a2 = 1 - alpha / A; |
281 | s->b0 = 1 + alpha * A; |
282 | s->b1 = -2 * cos(w0); |
283 | s->b2 = 1 - alpha * A; |
284 | break; |
285 | case bass: |
286 | s->a0 = (A + 1) + (A - 1) * cos(w0) + 2 * sqrt(A) * alpha; |
287 | s->a1 = -2 * ((A - 1) + (A + 1) * cos(w0)); |
288 | s->a2 = (A + 1) + (A - 1) * cos(w0) - 2 * sqrt(A) * alpha; |
289 | s->b0 = A * ((A + 1) - (A - 1) * cos(w0) + 2 * sqrt(A) * alpha); |
290 | s->b1 = 2 * A * ((A - 1) - (A + 1) * cos(w0)); |
291 | s->b2 = A * ((A + 1) - (A - 1) * cos(w0) - 2 * sqrt(A) * alpha); |
292 | break; |
293 | case treble: |
294 | s->a0 = (A + 1) - (A - 1) * cos(w0) + 2 * sqrt(A) * alpha; |
295 | s->a1 = 2 * ((A - 1) - (A + 1) * cos(w0)); |
296 | s->a2 = (A + 1) - (A - 1) * cos(w0) - 2 * sqrt(A) * alpha; |
297 | s->b0 = A * ((A + 1) + (A - 1) * cos(w0) + 2 * sqrt(A) * alpha); |
298 | s->b1 =-2 * A * ((A - 1) + (A + 1) * cos(w0)); |
299 | s->b2 = A * ((A + 1) + (A - 1) * cos(w0) - 2 * sqrt(A) * alpha); |
300 | break; |
301 | case bandpass: |
302 | if (s->csg) { |
303 | s->a0 = 1 + alpha; |
304 | s->a1 = -2 * cos(w0); |
305 | s->a2 = 1 - alpha; |
306 | s->b0 = sin(w0) / 2; |
307 | s->b1 = 0; |
308 | s->b2 = -sin(w0) / 2; |
309 | } else { |
310 | s->a0 = 1 + alpha; |
311 | s->a1 = -2 * cos(w0); |
312 | s->a2 = 1 - alpha; |
313 | s->b0 = alpha; |
314 | s->b1 = 0; |
315 | s->b2 = -alpha; |
316 | } |
317 | break; |
318 | case bandreject: |
319 | s->a0 = 1 + alpha; |
320 | s->a1 = -2 * cos(w0); |
321 | s->a2 = 1 - alpha; |
322 | s->b0 = 1; |
323 | s->b1 = -2 * cos(w0); |
324 | s->b2 = 1; |
325 | break; |
326 | case lowpass: |
327 | if (s->poles == 1) { |
328 | s->a0 = 1; |
329 | s->a1 = -exp(-w0); |
330 | s->a2 = 0; |
331 | s->b0 = 1 + s->a1; |
332 | s->b1 = 0; |
333 | s->b2 = 0; |
334 | } else { |
335 | s->a0 = 1 + alpha; |
336 | s->a1 = -2 * cos(w0); |
337 | s->a2 = 1 - alpha; |
338 | s->b0 = (1 - cos(w0)) / 2; |
339 | s->b1 = 1 - cos(w0); |
340 | s->b2 = (1 - cos(w0)) / 2; |
341 | } |
342 | break; |
343 | case highpass: |
344 | if (s->poles == 1) { |
345 | s->a0 = 1; |
346 | s->a1 = -exp(-w0); |
347 | s->a2 = 0; |
348 | s->b0 = (1 - s->a1) / 2; |
349 | s->b1 = -s->b0; |
350 | s->b2 = 0; |
351 | } else { |
352 | s->a0 = 1 + alpha; |
353 | s->a1 = -2 * cos(w0); |
354 | s->a2 = 1 - alpha; |
355 | s->b0 = (1 + cos(w0)) / 2; |
356 | s->b1 = -(1 + cos(w0)); |
357 | s->b2 = (1 + cos(w0)) / 2; |
358 | } |
359 | break; |
360 | case allpass: |
361 | s->a0 = 1 + alpha; |
362 | s->a1 = -2 * cos(w0); |
363 | s->a2 = 1 - alpha; |
364 | s->b0 = 1 - alpha; |
365 | s->b1 = -2 * cos(w0); |
366 | s->b2 = 1 + alpha; |
367 | break; |
368 | default: |
369 | av_assert0(0); |
370 | } |
371 | |
372 | s->a1 /= s->a0; |
373 | s->a2 /= s->a0; |
374 | s->b0 /= s->a0; |
375 | s->b1 /= s->a0; |
376 | s->b2 /= s->a0; |
377 | |
378 | s->cache = av_realloc_f(s->cache, sizeof(ChanCache), inlink->channels); |
379 | if (!s->cache) |
380 | return AVERROR(ENOMEM); |
381 | memset(s->cache, 0, sizeof(ChanCache) * inlink->channels); |
382 | |
383 | switch (inlink->format) { |
384 | case AV_SAMPLE_FMT_S16P: s->filter = biquad_s16; break; |
385 | case AV_SAMPLE_FMT_S32P: s->filter = biquad_s32; break; |
386 | case AV_SAMPLE_FMT_FLTP: s->filter = biquad_flt; break; |
387 | case AV_SAMPLE_FMT_DBLP: s->filter = biquad_dbl; break; |
388 | default: av_assert0(0); |
389 | } |
390 | |
391 | return 0; |
392 | } |
393 | |
394 | static int filter_frame(AVFilterLink *inlink, AVFrame *buf) |
395 | { |
396 | AVFilterContext *ctx = inlink->dst; |
397 | BiquadsContext *s = ctx->priv; |
398 | AVFilterLink *outlink = ctx->outputs[0]; |
399 | AVFrame *out_buf; |
400 | int nb_samples = buf->nb_samples; |
401 | int ch; |
402 | |
403 | if (av_frame_is_writable(buf)) { |
404 | out_buf = buf; |
405 | } else { |
406 | out_buf = ff_get_audio_buffer(inlink, nb_samples); |
407 | if (!out_buf) { |
408 | av_frame_free(&buf); |
409 | return AVERROR(ENOMEM); |
410 | } |
411 | av_frame_copy_props(out_buf, buf); |
412 | } |
413 | |
414 | for (ch = 0; ch < av_frame_get_channels(buf); ch++) |
415 | s->filter(s, buf->extended_data[ch], |
416 | out_buf->extended_data[ch], nb_samples, |
417 | &s->cache[ch].i1, &s->cache[ch].i2, |
418 | &s->cache[ch].o1, &s->cache[ch].o2, |
419 | s->b0, s->b1, s->b2, s->a1, s->a2); |
420 | |
421 | if (s->clippings > 0) |
422 | av_log(ctx, AV_LOG_WARNING, "clipping %d times. Please reduce gain.\n", s->clippings); |
423 | s->clippings = 0; |
424 | |
425 | if (buf != out_buf) |
426 | av_frame_free(&buf); |
427 | |
428 | return ff_filter_frame(outlink, out_buf); |
429 | } |
430 | |
431 | static av_cold void uninit(AVFilterContext *ctx) |
432 | { |
433 | BiquadsContext *s = ctx->priv; |
434 | |
435 | av_freep(&s->cache); |
436 | } |
437 | |
438 | static const AVFilterPad inputs[] = { |
439 | { |
440 | .name = "default", |
441 | .type = AVMEDIA_TYPE_AUDIO, |
442 | .filter_frame = filter_frame, |
443 | }, |
444 | { NULL } |
445 | }; |
446 | |
447 | static const AVFilterPad outputs[] = { |
448 | { |
449 | .name = "default", |
450 | .type = AVMEDIA_TYPE_AUDIO, |
451 | .config_props = config_output, |
452 | }, |
453 | { NULL } |
454 | }; |
455 | |
456 | #define OFFSET(x) offsetof(BiquadsContext, x) |
457 | #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM |
458 | |
459 | #define DEFINE_BIQUAD_FILTER(name_, description_) \ |
460 | AVFILTER_DEFINE_CLASS(name_); \ |
461 | static av_cold int name_##_init(AVFilterContext *ctx) \ |
462 | { \ |
463 | BiquadsContext *s = ctx->priv; \ |
464 | s->class = &name_##_class; \ |
465 | s->filter_type = name_; \ |
466 | return init(ctx); \ |
467 | } \ |
468 | \ |
469 | AVFilter ff_af_##name_ = { \ |
470 | .name = #name_, \ |
471 | .description = NULL_IF_CONFIG_SMALL(description_), \ |
472 | .priv_size = sizeof(BiquadsContext), \ |
473 | .init = name_##_init, \ |
474 | .uninit = uninit, \ |
475 | .query_formats = query_formats, \ |
476 | .inputs = inputs, \ |
477 | .outputs = outputs, \ |
478 | .priv_class = &name_##_class, \ |
479 | } |
480 | |
481 | #if CONFIG_EQUALIZER_FILTER |
482 | static const AVOption equalizer_options[] = { |
483 | {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS}, |
484 | {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS}, |
485 | {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, |
486 | {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, |
487 | {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, |
488 | {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, |
489 | {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, |
490 | {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 999, FLAGS}, |
491 | {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 999, FLAGS}, |
492 | {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, |
493 | {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, |
494 | {NULL} |
495 | }; |
496 | |
497 | DEFINE_BIQUAD_FILTER(equalizer, "Apply two-pole peaking equalization (EQ) filter."); |
498 | #endif /* CONFIG_EQUALIZER_FILTER */ |
499 | #if CONFIG_BASS_FILTER |
500 | static const AVOption bass_options[] = { |
501 | {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS}, |
502 | {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS}, |
503 | {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, |
504 | {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, |
505 | {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, |
506 | {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, |
507 | {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, |
508 | {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, |
509 | {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, |
510 | {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, |
511 | {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, |
512 | {NULL} |
513 | }; |
514 | |
515 | DEFINE_BIQUAD_FILTER(bass, "Boost or cut lower frequencies."); |
516 | #endif /* CONFIG_BASS_FILTER */ |
517 | #if CONFIG_TREBLE_FILTER |
518 | static const AVOption treble_options[] = { |
519 | {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, |
520 | {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, |
521 | {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, |
522 | {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, |
523 | {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, |
524 | {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, |
525 | {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, |
526 | {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, |
527 | {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, |
528 | {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, |
529 | {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, |
530 | {NULL} |
531 | }; |
532 | |
533 | DEFINE_BIQUAD_FILTER(treble, "Boost or cut upper frequencies."); |
534 | #endif /* CONFIG_TREBLE_FILTER */ |
535 | #if CONFIG_BANDPASS_FILTER |
536 | static const AVOption bandpass_options[] = { |
537 | {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, |
538 | {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, |
539 | {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, |
540 | {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, |
541 | {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, |
542 | {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, |
543 | {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, |
544 | {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS}, |
545 | {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS}, |
546 | {"csg", "use constant skirt gain", OFFSET(csg), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, |
547 | {NULL} |
548 | }; |
549 | |
550 | DEFINE_BIQUAD_FILTER(bandpass, "Apply a two-pole Butterworth band-pass filter."); |
551 | #endif /* CONFIG_BANDPASS_FILTER */ |
552 | #if CONFIG_BANDREJECT_FILTER |
553 | static const AVOption bandreject_options[] = { |
554 | {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, |
555 | {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, |
556 | {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, |
557 | {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, |
558 | {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, |
559 | {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, |
560 | {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, |
561 | {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS}, |
562 | {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS}, |
563 | {NULL} |
564 | }; |
565 | |
566 | DEFINE_BIQUAD_FILTER(bandreject, "Apply a two-pole Butterworth band-reject filter."); |
567 | #endif /* CONFIG_BANDREJECT_FILTER */ |
568 | #if CONFIG_LOWPASS_FILTER |
569 | static const AVOption lowpass_options[] = { |
570 | {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS}, |
571 | {"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS}, |
572 | {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, |
573 | {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, |
574 | {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, |
575 | {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, |
576 | {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, |
577 | {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS}, |
578 | {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS}, |
579 | {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, |
580 | {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, |
581 | {NULL} |
582 | }; |
583 | |
584 | DEFINE_BIQUAD_FILTER(lowpass, "Apply a low-pass filter with 3dB point frequency."); |
585 | #endif /* CONFIG_LOWPASS_FILTER */ |
586 | #if CONFIG_HIGHPASS_FILTER |
587 | static const AVOption highpass_options[] = { |
588 | {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, |
589 | {"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, |
590 | {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, |
591 | {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, |
592 | {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, |
593 | {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, |
594 | {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, |
595 | {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS}, |
596 | {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS}, |
597 | {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, |
598 | {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, |
599 | {NULL} |
600 | }; |
601 | |
602 | DEFINE_BIQUAD_FILTER(highpass, "Apply a high-pass filter with 3dB point frequency."); |
603 | #endif /* CONFIG_HIGHPASS_FILTER */ |
604 | #if CONFIG_ALLPASS_FILTER |
605 | static const AVOption allpass_options[] = { |
606 | {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, |
607 | {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, |
608 | {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HERTZ}, HERTZ, SLOPE, FLAGS, "width_type"}, |
609 | {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, |
610 | {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, |
611 | {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, |
612 | {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, |
613 | {"width", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS}, |
614 | {"w", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS}, |
615 | {NULL} |
616 | }; |
617 | |
618 | DEFINE_BIQUAD_FILTER(allpass, "Apply a two-pole all-pass filter."); |
619 | #endif /* CONFIG_ALLPASS_FILTER */ |
620 | #if CONFIG_BIQUAD_FILTER |
621 | static const AVOption biquad_options[] = { |
622 | {"a0", NULL, OFFSET(a0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, |
623 | {"a1", NULL, OFFSET(a1), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, |
624 | {"a2", NULL, OFFSET(a2), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, |
625 | {"b0", NULL, OFFSET(b0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, |
626 | {"b1", NULL, OFFSET(b1), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, |
627 | {"b2", NULL, OFFSET(b2), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, |
628 | {NULL} |
629 | }; |
630 | |
631 | DEFINE_BIQUAD_FILTER(biquad, "Apply a biquad IIR filter with the given coefficients."); |
632 | #endif /* CONFIG_BIQUAD_FILTER */ |
633 |