Commit | Line | Data |
---|---|---|
2ba45a60 DM |
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 { | |
98 | const AVClass *class; | |
99 | ||
100 | enum FilterType filter_type; | |
101 | enum WidthType 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 | ||
114 | void (*filter)(const void *ibuf, void *obuf, int len, | |
115 | double *i1, double *i2, double *o1, double *o2, | |
116 | double b0, double b1, double b2, double a1, double a2); | |
117 | } BiquadsContext; | |
118 | ||
119 | static av_cold int init(AVFilterContext *ctx) | |
120 | { | |
121 | BiquadsContext *p = ctx->priv; | |
122 | ||
123 | if (p->filter_type != biquad) { | |
124 | if (p->frequency <= 0 || p->width <= 0) { | |
125 | av_log(ctx, AV_LOG_ERROR, "Invalid frequency %f and/or width %f <= 0\n", | |
126 | p->frequency, p->width); | |
127 | return AVERROR(EINVAL); | |
128 | } | |
129 | } | |
130 | ||
131 | return 0; | |
132 | } | |
133 | ||
134 | static int query_formats(AVFilterContext *ctx) | |
135 | { | |
136 | AVFilterFormats *formats; | |
137 | AVFilterChannelLayouts *layouts; | |
138 | static const enum AVSampleFormat sample_fmts[] = { | |
139 | AV_SAMPLE_FMT_S16P, | |
140 | AV_SAMPLE_FMT_S32P, | |
141 | AV_SAMPLE_FMT_FLTP, | |
142 | AV_SAMPLE_FMT_DBLP, | |
143 | AV_SAMPLE_FMT_NONE | |
144 | }; | |
145 | ||
146 | layouts = ff_all_channel_layouts(); | |
147 | if (!layouts) | |
148 | return AVERROR(ENOMEM); | |
149 | ff_set_common_channel_layouts(ctx, layouts); | |
150 | ||
151 | formats = ff_make_format_list(sample_fmts); | |
152 | if (!formats) | |
153 | return AVERROR(ENOMEM); | |
154 | ff_set_common_formats(ctx, formats); | |
155 | ||
156 | formats = ff_all_samplerates(); | |
157 | if (!formats) | |
158 | return AVERROR(ENOMEM); | |
159 | ff_set_common_samplerates(ctx, formats); | |
160 | ||
161 | return 0; | |
162 | } | |
163 | ||
164 | #define BIQUAD_FILTER(name, type, min, max, need_clipping) \ | |
165 | static void biquad_## name (const void *input, void *output, int len, \ | |
166 | double *in1, double *in2, \ | |
167 | double *out1, double *out2, \ | |
168 | double b0, double b1, double b2, \ | |
169 | double a1, double a2) \ | |
170 | { \ | |
171 | const type *ibuf = input; \ | |
172 | type *obuf = output; \ | |
173 | double i1 = *in1; \ | |
174 | double i2 = *in2; \ | |
175 | double o1 = *out1; \ | |
176 | double o2 = *out2; \ | |
177 | int i; \ | |
178 | a1 = -a1; \ | |
179 | a2 = -a2; \ | |
180 | \ | |
181 | for (i = 0; i+1 < len; i++) { \ | |
182 | o2 = i2 * b2 + i1 * b1 + ibuf[i] * b0 + o2 * a2 + o1 * a1; \ | |
183 | i2 = ibuf[i]; \ | |
184 | if (need_clipping && o2 < min) { \ | |
185 | av_log(NULL, AV_LOG_WARNING, "clipping\n"); \ | |
186 | obuf[i] = min; \ | |
187 | } else if (need_clipping && o2 > max) { \ | |
188 | av_log(NULL, AV_LOG_WARNING, "clipping\n"); \ | |
189 | obuf[i] = max; \ | |
190 | } else { \ | |
191 | obuf[i] = o2; \ | |
192 | } \ | |
193 | i++; \ | |
194 | o1 = i1 * b2 + i2 * b1 + ibuf[i] * b0 + o1 * a2 + o2 * a1; \ | |
195 | i1 = ibuf[i]; \ | |
196 | if (need_clipping && o1 < min) { \ | |
197 | av_log(NULL, AV_LOG_WARNING, "clipping\n"); \ | |
198 | obuf[i] = min; \ | |
199 | } else if (need_clipping && o1 > max) { \ | |
200 | av_log(NULL, AV_LOG_WARNING, "clipping\n"); \ | |
201 | obuf[i] = max; \ | |
202 | } else { \ | |
203 | obuf[i] = o1; \ | |
204 | } \ | |
205 | } \ | |
206 | if (i < len) { \ | |
207 | double o0 = ibuf[i] * b0 + i1 * b1 + i2 * b2 + o1 * a1 + o2 * a2; \ | |
208 | i2 = i1; \ | |
209 | i1 = ibuf[i]; \ | |
210 | o2 = o1; \ | |
211 | o1 = o0; \ | |
212 | if (need_clipping && o0 < min) { \ | |
213 | av_log(NULL, AV_LOG_WARNING, "clipping\n"); \ | |
214 | obuf[i] = min; \ | |
215 | } else if (need_clipping && o0 > max) { \ | |
216 | av_log(NULL, AV_LOG_WARNING, "clipping\n"); \ | |
217 | obuf[i] = max; \ | |
218 | } else { \ | |
219 | obuf[i] = o0; \ | |
220 | } \ | |
221 | } \ | |
222 | *in1 = i1; \ | |
223 | *in2 = i2; \ | |
224 | *out1 = o1; \ | |
225 | *out2 = o2; \ | |
226 | } | |
227 | ||
228 | BIQUAD_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1) | |
229 | BIQUAD_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) | |
230 | BIQUAD_FILTER(flt, float, -1., 1., 0) | |
231 | BIQUAD_FILTER(dbl, double, -1., 1., 0) | |
232 | ||
233 | static int config_output(AVFilterLink *outlink) | |
234 | { | |
235 | AVFilterContext *ctx = outlink->src; | |
236 | BiquadsContext *p = ctx->priv; | |
237 | AVFilterLink *inlink = ctx->inputs[0]; | |
238 | double A = exp(p->gain / 40 * log(10.)); | |
239 | double w0 = 2 * M_PI * p->frequency / inlink->sample_rate; | |
240 | double alpha; | |
241 | ||
242 | if (w0 > M_PI) { | |
243 | av_log(ctx, AV_LOG_ERROR, | |
244 | "Invalid frequency %f. Frequency must be less than half the sample-rate %d.\n", | |
245 | p->frequency, inlink->sample_rate); | |
246 | return AVERROR(EINVAL); | |
247 | } | |
248 | ||
249 | switch (p->width_type) { | |
250 | case NONE: | |
251 | alpha = 0.0; | |
252 | break; | |
253 | case HERTZ: | |
254 | alpha = sin(w0) / (2 * p->frequency / p->width); | |
255 | break; | |
256 | case OCTAVE: | |
257 | alpha = sin(w0) * sinh(log(2.) / 2 * p->width * w0 / sin(w0)); | |
258 | break; | |
259 | case QFACTOR: | |
260 | alpha = sin(w0) / (2 * p->width); | |
261 | break; | |
262 | case SLOPE: | |
263 | alpha = sin(w0) / 2 * sqrt((A + 1 / A) * (1 / p->width - 1) + 2); | |
264 | break; | |
265 | default: | |
266 | av_assert0(0); | |
267 | } | |
268 | ||
269 | switch (p->filter_type) { | |
270 | case biquad: | |
271 | break; | |
272 | case equalizer: | |
273 | p->a0 = 1 + alpha / A; | |
274 | p->a1 = -2 * cos(w0); | |
275 | p->a2 = 1 - alpha / A; | |
276 | p->b0 = 1 + alpha * A; | |
277 | p->b1 = -2 * cos(w0); | |
278 | p->b2 = 1 - alpha * A; | |
279 | break; | |
280 | case bass: | |
281 | p->a0 = (A + 1) + (A - 1) * cos(w0) + 2 * sqrt(A) * alpha; | |
282 | p->a1 = -2 * ((A - 1) + (A + 1) * cos(w0)); | |
283 | p->a2 = (A + 1) + (A - 1) * cos(w0) - 2 * sqrt(A) * alpha; | |
284 | p->b0 = A * ((A + 1) - (A - 1) * cos(w0) + 2 * sqrt(A) * alpha); | |
285 | p->b1 = 2 * A * ((A - 1) - (A + 1) * cos(w0)); | |
286 | p->b2 = A * ((A + 1) - (A - 1) * cos(w0) - 2 * sqrt(A) * alpha); | |
287 | break; | |
288 | case treble: | |
289 | p->a0 = (A + 1) - (A - 1) * cos(w0) + 2 * sqrt(A) * alpha; | |
290 | p->a1 = 2 * ((A - 1) - (A + 1) * cos(w0)); | |
291 | p->a2 = (A + 1) - (A - 1) * cos(w0) - 2 * sqrt(A) * alpha; | |
292 | p->b0 = A * ((A + 1) + (A - 1) * cos(w0) + 2 * sqrt(A) * alpha); | |
293 | p->b1 =-2 * A * ((A - 1) + (A + 1) * cos(w0)); | |
294 | p->b2 = A * ((A + 1) + (A - 1) * cos(w0) - 2 * sqrt(A) * alpha); | |
295 | break; | |
296 | case bandpass: | |
297 | if (p->csg) { | |
298 | p->a0 = 1 + alpha; | |
299 | p->a1 = -2 * cos(w0); | |
300 | p->a2 = 1 - alpha; | |
301 | p->b0 = sin(w0) / 2; | |
302 | p->b1 = 0; | |
303 | p->b2 = -sin(w0) / 2; | |
304 | } else { | |
305 | p->a0 = 1 + alpha; | |
306 | p->a1 = -2 * cos(w0); | |
307 | p->a2 = 1 - alpha; | |
308 | p->b0 = alpha; | |
309 | p->b1 = 0; | |
310 | p->b2 = -alpha; | |
311 | } | |
312 | break; | |
313 | case bandreject: | |
314 | p->a0 = 1 + alpha; | |
315 | p->a1 = -2 * cos(w0); | |
316 | p->a2 = 1 - alpha; | |
317 | p->b0 = 1; | |
318 | p->b1 = -2 * cos(w0); | |
319 | p->b2 = 1; | |
320 | break; | |
321 | case lowpass: | |
322 | if (p->poles == 1) { | |
323 | p->a0 = 1; | |
324 | p->a1 = -exp(-w0); | |
325 | p->a2 = 0; | |
326 | p->b0 = 1 + p->a1; | |
327 | p->b1 = 0; | |
328 | p->b2 = 0; | |
329 | } else { | |
330 | p->a0 = 1 + alpha; | |
331 | p->a1 = -2 * cos(w0); | |
332 | p->a2 = 1 - alpha; | |
333 | p->b0 = (1 - cos(w0)) / 2; | |
334 | p->b1 = 1 - cos(w0); | |
335 | p->b2 = (1 - cos(w0)) / 2; | |
336 | } | |
337 | break; | |
338 | case highpass: | |
339 | if (p->poles == 1) { | |
340 | p->a0 = 1; | |
341 | p->a1 = -exp(-w0); | |
342 | p->a2 = 0; | |
343 | p->b0 = (1 - p->a1) / 2; | |
344 | p->b1 = -p->b0; | |
345 | p->b2 = 0; | |
346 | } else { | |
347 | p->a0 = 1 + alpha; | |
348 | p->a1 = -2 * cos(w0); | |
349 | p->a2 = 1 - alpha; | |
350 | p->b0 = (1 + cos(w0)) / 2; | |
351 | p->b1 = -(1 + cos(w0)); | |
352 | p->b2 = (1 + cos(w0)) / 2; | |
353 | } | |
354 | break; | |
355 | case allpass: | |
356 | p->a0 = 1 + alpha; | |
357 | p->a1 = -2 * cos(w0); | |
358 | p->a2 = 1 - alpha; | |
359 | p->b0 = 1 - alpha; | |
360 | p->b1 = -2 * cos(w0); | |
361 | p->b2 = 1 + alpha; | |
362 | break; | |
363 | default: | |
364 | av_assert0(0); | |
365 | } | |
366 | ||
367 | p->a1 /= p->a0; | |
368 | p->a2 /= p->a0; | |
369 | p->b0 /= p->a0; | |
370 | p->b1 /= p->a0; | |
371 | p->b2 /= p->a0; | |
372 | ||
373 | p->cache = av_realloc_f(p->cache, sizeof(ChanCache), inlink->channels); | |
374 | if (!p->cache) | |
375 | return AVERROR(ENOMEM); | |
376 | memset(p->cache, 0, sizeof(ChanCache) * inlink->channels); | |
377 | ||
378 | switch (inlink->format) { | |
379 | case AV_SAMPLE_FMT_S16P: p->filter = biquad_s16; break; | |
380 | case AV_SAMPLE_FMT_S32P: p->filter = biquad_s32; break; | |
381 | case AV_SAMPLE_FMT_FLTP: p->filter = biquad_flt; break; | |
382 | case AV_SAMPLE_FMT_DBLP: p->filter = biquad_dbl; break; | |
383 | default: av_assert0(0); | |
384 | } | |
385 | ||
386 | return 0; | |
387 | } | |
388 | ||
389 | static int filter_frame(AVFilterLink *inlink, AVFrame *buf) | |
390 | { | |
391 | BiquadsContext *p = inlink->dst->priv; | |
392 | AVFilterLink *outlink = inlink->dst->outputs[0]; | |
393 | AVFrame *out_buf; | |
394 | int nb_samples = buf->nb_samples; | |
395 | int ch; | |
396 | ||
397 | if (av_frame_is_writable(buf)) { | |
398 | out_buf = buf; | |
399 | } else { | |
400 | out_buf = ff_get_audio_buffer(inlink, nb_samples); | |
401 | if (!out_buf) | |
402 | return AVERROR(ENOMEM); | |
403 | av_frame_copy_props(out_buf, buf); | |
404 | } | |
405 | ||
406 | for (ch = 0; ch < av_frame_get_channels(buf); ch++) | |
407 | p->filter(buf->extended_data[ch], | |
408 | out_buf->extended_data[ch], nb_samples, | |
409 | &p->cache[ch].i1, &p->cache[ch].i2, | |
410 | &p->cache[ch].o1, &p->cache[ch].o2, | |
411 | p->b0, p->b1, p->b2, p->a1, p->a2); | |
412 | ||
413 | if (buf != out_buf) | |
414 | av_frame_free(&buf); | |
415 | ||
416 | return ff_filter_frame(outlink, out_buf); | |
417 | } | |
418 | ||
419 | static av_cold void uninit(AVFilterContext *ctx) | |
420 | { | |
421 | BiquadsContext *p = ctx->priv; | |
422 | ||
423 | av_freep(&p->cache); | |
424 | } | |
425 | ||
426 | static const AVFilterPad inputs[] = { | |
427 | { | |
428 | .name = "default", | |
429 | .type = AVMEDIA_TYPE_AUDIO, | |
430 | .filter_frame = filter_frame, | |
431 | }, | |
432 | { NULL } | |
433 | }; | |
434 | ||
435 | static const AVFilterPad outputs[] = { | |
436 | { | |
437 | .name = "default", | |
438 | .type = AVMEDIA_TYPE_AUDIO, | |
439 | .config_props = config_output, | |
440 | }, | |
441 | { NULL } | |
442 | }; | |
443 | ||
444 | #define OFFSET(x) offsetof(BiquadsContext, x) | |
445 | #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM | |
446 | ||
447 | #define DEFINE_BIQUAD_FILTER(name_, description_) \ | |
448 | AVFILTER_DEFINE_CLASS(name_); \ | |
449 | static av_cold int name_##_init(AVFilterContext *ctx) \ | |
450 | { \ | |
451 | BiquadsContext *p = ctx->priv; \ | |
452 | p->class = &name_##_class; \ | |
453 | p->filter_type = name_; \ | |
454 | return init(ctx); \ | |
455 | } \ | |
456 | \ | |
457 | AVFilter ff_af_##name_ = { \ | |
458 | .name = #name_, \ | |
459 | .description = NULL_IF_CONFIG_SMALL(description_), \ | |
460 | .priv_size = sizeof(BiquadsContext), \ | |
461 | .init = name_##_init, \ | |
462 | .uninit = uninit, \ | |
463 | .query_formats = query_formats, \ | |
464 | .inputs = inputs, \ | |
465 | .outputs = outputs, \ | |
466 | .priv_class = &name_##_class, \ | |
467 | } | |
468 | ||
469 | #if CONFIG_EQUALIZER_FILTER | |
470 | static const AVOption equalizer_options[] = { | |
471 | {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS}, | |
472 | {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS}, | |
473 | {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, | |
474 | {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, | |
475 | {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, | |
476 | {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, | |
477 | {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, | |
478 | {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 999, FLAGS}, | |
479 | {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 999, FLAGS}, | |
480 | {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, | |
481 | {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, | |
482 | {NULL} | |
483 | }; | |
484 | ||
485 | DEFINE_BIQUAD_FILTER(equalizer, "Apply two-pole peaking equalization (EQ) filter."); | |
486 | #endif /* CONFIG_EQUALIZER_FILTER */ | |
487 | #if CONFIG_BASS_FILTER | |
488 | static const AVOption bass_options[] = { | |
489 | {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS}, | |
490 | {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS}, | |
491 | {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, | |
492 | {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, | |
493 | {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, | |
494 | {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, | |
495 | {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, | |
496 | {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, | |
497 | {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, | |
498 | {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, | |
499 | {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, | |
500 | {NULL} | |
501 | }; | |
502 | ||
503 | DEFINE_BIQUAD_FILTER(bass, "Boost or cut lower frequencies."); | |
504 | #endif /* CONFIG_BASS_FILTER */ | |
505 | #if CONFIG_TREBLE_FILTER | |
506 | static const AVOption treble_options[] = { | |
507 | {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, | |
508 | {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, | |
509 | {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, | |
510 | {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, | |
511 | {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, | |
512 | {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, | |
513 | {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, | |
514 | {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, | |
515 | {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, | |
516 | {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, | |
517 | {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS}, | |
518 | {NULL} | |
519 | }; | |
520 | ||
521 | DEFINE_BIQUAD_FILTER(treble, "Boost or cut upper frequencies."); | |
522 | #endif /* CONFIG_TREBLE_FILTER */ | |
523 | #if CONFIG_BANDPASS_FILTER | |
524 | static const AVOption bandpass_options[] = { | |
525 | {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, | |
526 | {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, | |
527 | {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, | |
528 | {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, | |
529 | {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, | |
530 | {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, | |
531 | {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, | |
532 | {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS}, | |
533 | {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS}, | |
534 | {"csg", "use constant skirt gain", OFFSET(csg), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS}, | |
535 | {NULL} | |
536 | }; | |
537 | ||
538 | DEFINE_BIQUAD_FILTER(bandpass, "Apply a two-pole Butterworth band-pass filter."); | |
539 | #endif /* CONFIG_BANDPASS_FILTER */ | |
540 | #if CONFIG_BANDREJECT_FILTER | |
541 | static const AVOption bandreject_options[] = { | |
542 | {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, | |
543 | {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, | |
544 | {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, | |
545 | {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, | |
546 | {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, | |
547 | {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, | |
548 | {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, | |
549 | {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS}, | |
550 | {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS}, | |
551 | {NULL} | |
552 | }; | |
553 | ||
554 | DEFINE_BIQUAD_FILTER(bandreject, "Apply a two-pole Butterworth band-reject filter."); | |
555 | #endif /* CONFIG_BANDREJECT_FILTER */ | |
556 | #if CONFIG_LOWPASS_FILTER | |
557 | static const AVOption lowpass_options[] = { | |
558 | {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS}, | |
559 | {"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS}, | |
560 | {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, | |
561 | {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, | |
562 | {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, | |
563 | {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, | |
564 | {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, | |
565 | {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS}, | |
566 | {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS}, | |
567 | {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, | |
568 | {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, | |
569 | {NULL} | |
570 | }; | |
571 | ||
572 | DEFINE_BIQUAD_FILTER(lowpass, "Apply a low-pass filter with 3dB point frequency."); | |
573 | #endif /* CONFIG_LOWPASS_FILTER */ | |
574 | #if CONFIG_HIGHPASS_FILTER | |
575 | static const AVOption highpass_options[] = { | |
576 | {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, | |
577 | {"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, | |
578 | {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, SLOPE, FLAGS, "width_type"}, | |
579 | {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, | |
580 | {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, | |
581 | {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, | |
582 | {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, | |
583 | {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS}, | |
584 | {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS}, | |
585 | {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, | |
586 | {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, | |
587 | {NULL} | |
588 | }; | |
589 | ||
590 | DEFINE_BIQUAD_FILTER(highpass, "Apply a high-pass filter with 3dB point frequency."); | |
591 | #endif /* CONFIG_HIGHPASS_FILTER */ | |
592 | #if CONFIG_ALLPASS_FILTER | |
593 | static const AVOption allpass_options[] = { | |
594 | {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, | |
595 | {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS}, | |
596 | {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HERTZ}, HERTZ, SLOPE, FLAGS, "width_type"}, | |
597 | {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"}, | |
598 | {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"}, | |
599 | {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"}, | |
600 | {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"}, | |
601 | {"width", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS}, | |
602 | {"w", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS}, | |
603 | {NULL} | |
604 | }; | |
605 | ||
606 | DEFINE_BIQUAD_FILTER(allpass, "Apply a two-pole all-pass filter."); | |
607 | #endif /* CONFIG_ALLPASS_FILTER */ | |
608 | #if CONFIG_BIQUAD_FILTER | |
609 | static const AVOption biquad_options[] = { | |
610 | {"a0", NULL, OFFSET(a0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, | |
611 | {"a1", NULL, OFFSET(a1), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, | |
612 | {"a2", NULL, OFFSET(a2), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, | |
613 | {"b0", NULL, OFFSET(b0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, | |
614 | {"b1", NULL, OFFSET(b1), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, | |
615 | {"b2", NULL, OFFSET(b2), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MIN, INT16_MAX, FLAGS}, | |
616 | {NULL} | |
617 | }; | |
618 | ||
619 | DEFINE_BIQUAD_FILTER(biquad, "Apply a biquad IIR filter with the given coefficients."); | |
620 | #endif /* CONFIG_BIQUAD_FILTER */ |