| 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 */ |