Commit b70ea49c authored by Paul B Mahol's avatar Paul B Mahol

Port biquads filters from SoX

Adds allpass, bass, bandpass, bandreject, biquad,
equalizer, highpass, lowpass and treble filter.
Signed-off-by: 's avatarPaul B Mahol <onemda@gmail.com>
parent ff23b768
...@@ -10,6 +10,8 @@ version <next>: ...@@ -10,6 +10,8 @@ version <next>:
- EVRC decoder - EVRC decoder
- audio fade filter - audio fade filter
- filtering audio with unknown channel layout - filtering audio with unknown channel layout
- allpass, bass, bandpass, bandreject, biquad, equalizer, highpass, lowpass
and treble audio filter
version 1.1: version 1.1:
......
...@@ -282,6 +282,274 @@ aconvert=u8:auto ...@@ -282,6 +282,274 @@ aconvert=u8:auto
@end example @end example
@end itemize @end itemize
@section allpass
Apply a two-pole all-pass filter with central frequency (in Hz)
@var{frequency}, and filter-width @var{width}.
An all-pass filter changes the audio's frequency to phase relationship
without changing its frequency to amplitude relationship.
The filter accepts parameters as a list of @var{key}=@var{value}
pairs, separated by ":".
A description of the accepted parameters follows.
@table @option
@item frequency, f
Set frequency in Hz.
@item width_type
Set method to specify band-width of filter.
@table @option
@item @var{h} (Hz)
@item @var{q} (Q-Factor)
@item @var{o} (octave)
@item @var{s} (slope)
@end table
@item width, w
Specify the band-width of a filter in width_type units.
@end table
@section highpass
Apply a high-pass filter with 3dB point frequency.
The filter can be either single-pole, or double-pole (the default).
The filter roll off at 6dB per pole per octave (20dB per pole per decade).
The filter accepts parameters as a list of @var{key}=@var{value}
pairs, separated by ":".
A description of the accepted parameters follows.
@table @option
@item frequency, f
Set frequency in Hz. Default is 3000.
@item poles, p
Set number of poles. Default is 2.
@item width_type
Set method to specify band-width of filter.
@table @option
@item @var{h} (Hz)
@item @var{q} (Q-Factor)
@item @var{o} (octave)
@item @var{s} (slope)
@end table
@item width, w
Specify the band-width of a filter in width_type units.
Applies only to double-pole filter.
The default is 0.707q and gives a Butterworth response.
@end table
@section lowpass
Apply a low-pass filter with 3dB point frequency.
The filter can be either single-pole or double-pole (the default).
The filter roll off at 6dB per pole per octave (20dB per pole per decade).
The filter accepts parameters as a list of @var{key}=@var{value}
pairs, separated by ":".
A description of the accepted parameters follows.
@table @option
@item frequency, f
Set frequency in Hz. Default is 500.
@item poles, p
Set number of poles. Default is 2.
@item width_type
Set method to specify band-width of filter.
@table @option
@item @var{h} (Hz)
@item @var{q} (Q-Factor)
@item @var{o} (octave)
@item @var{s} (slope)
@end table
@item width, w
Specify the band-width of a filter in width_type units.
Applies only to double-pole filter.
The default is 0.707q and gives a Butterworth response.
@end table
@section bass
Boost or cut the bass (lower) frequencies of the audio using a two-pole
shelving filter with a response similar to that of a standard
hi-fi's tone-controls. This is also known as shelving equalisation (EQ).
The filter accepts parameters as a list of @var{key}=@var{value}
pairs, separated by ":".
A description of the accepted parameters follows.
@table @option
@item gain, g
Give the gain at 0 Hz. Its useful range is about -20
(for a large cut) to +20 (for a large boost).
Beware of clipping when using a positive gain.
@item frequency, f
Set the filter's central frequency and so can be used
to extend or reduce the frequency range to be boosted or cut.
The default value is @code{100} Hz.
@item width_type
Set method to specify band-width of filter.
@table @option
@item @var{h} (Hz)
@item @var{q} (Q-Factor)
@item @var{o} (octave)
@item @var{s} (slope)
@end table
@item width, w
Determine how steep is the filter's shelf transition.
@end table
@section treble
Boost or cut treble (upper) frequencies of the audio using a two-pole
shelving filter with a response similar to that of a standard
hi-fi's tone-controls. This is also known as shelving equalisation (EQ).
The filter accepts parameters as a list of @var{key}=@var{value}
pairs, separated by ":".
A description of the accepted parameters follows.
@table @option
@item gain, g
Give the gain at whichever is the lower of ~22 kHz and the
Nyquist frequency. Its useful range is about -20 (for a large cut)
to +20 (for a large boost). Beware of clipping when using a positive gain.
@item frequency, f
Set the filter's central frequency and so can be used
to extend or reduce the frequency range to be boosted or cut.
The default value is @code{3000} Hz.
@item width_type
Set method to specify band-width of filter.
@table @option
@item @var{h} (Hz)
@item @var{q} (Q-Factor)
@item @var{o} (octave)
@item @var{s} (slope)
@end table
@item width, w
Determine how steep is the filter's shelf transition.
@end table
@section bandpass
Apply a two-pole Butterworth band-pass filter with central
frequency @var{frequency}, and (3dB-point) band-width width.
The @var{csg} option selects a constant skirt gain (peak gain = Q)
instead of the default: constant 0dB peak gain.
The filter roll off at 6dB per octave (20dB per decade).
The filter accepts parameters as a list of @var{key}=@var{value}
pairs, separated by ":".
A description of the accepted parameters follows.
@table @option
@item frequency, f
Set the filter's central frequency. Default is @code{3000}.
@item csg
Constant skirt gain if set to 1. Defaults to 0.
@item width_type
Set method to specify band-width of filter.
@table @option
@item @var{h} (Hz)
@item @var{q} (Q-Factor)
@item @var{o} (octave)
@item @var{s} (slope)
@end table
@item width, w
Specify the band-width of a filter in width_type units.
@end table
@section bandreject
Apply a two-pole Butterworth band-reject filter with central
frequency @var{frequency}, and (3dB-point) band-width @var{width}.
The filter roll off at 6dB per octave (20dB per decade).
The filter accepts parameters as a list of @var{key}=@var{value}
pairs, separated by ":".
A description of the accepted parameters follows.
@table @option
@item frequency, f
Set the filter's central frequency. Default is @code{3000}.
@item width_type
Set method to specify band-width of filter.
@table @option
@item @var{h} (Hz)
@item @var{q} (Q-Factor)
@item @var{o} (octave)
@item @var{s} (slope)
@end table
@item width, w
Specify the band-width of a filter in width_type units.
@end table
@section biquad
Apply a biquad IIR filter with the given coefficients.
Where @var{b0}, @var{b1}, @var{b2} and @var{a0}, @var{a1}, @var{a2}
are the numerator and denominator coefficients respectively.
@section equalizer
Apply a two-pole peaking equalisation (EQ) filter. With this
filter, the signal-level at and around a selected frequency can
be increased or decreased, whilst (unlike bandpass and bandreject
filters) that at all other frequencies is unchanged.
In order to produce complex equalisation curves, this filter can
be given several times, each with a different central frequency.
The filter accepts parameters as a list of @var{key}=@var{value}
pairs, separated by ":".
A description of the accepted parameters follows.
@table @option
@item frequency, f
Set the filter's central frequency in Hz.
@item width_type
Set method to specify band-width of filter.
@table @option
@item @var{h} (Hz)
@item @var{q} (Q-Factor)
@item @var{o} (octave)
@item @var{s} (slope)
@end table
@item width, w
Specify the band-width of a filter in width_type units.
@item gain, g
Set the required gain or attenuation in dB.
Beware of clipping when using a positive gain.
@end table
@section afade @section afade
Apply fade-in/out effect to input audio. Apply fade-in/out effect to input audio.
......
...@@ -53,6 +53,7 @@ OBJS-$(CONFIG_SWSCALE) += lswsutils.o ...@@ -53,6 +53,7 @@ OBJS-$(CONFIG_SWSCALE) += lswsutils.o
OBJS-$(CONFIG_ACONVERT_FILTER) += af_aconvert.o OBJS-$(CONFIG_ACONVERT_FILTER) += af_aconvert.o
OBJS-$(CONFIG_AFADE_FILTER) += af_afade.o OBJS-$(CONFIG_AFADE_FILTER) += af_afade.o
OBJS-$(CONFIG_AFORMAT_FILTER) += af_aformat.o OBJS-$(CONFIG_AFORMAT_FILTER) += af_aformat.o
OBJS-$(CONFIG_ALLPASS_FILTER) += af_biquads.o
OBJS-$(CONFIG_AMERGE_FILTER) += af_amerge.o OBJS-$(CONFIG_AMERGE_FILTER) += af_amerge.o
OBJS-$(CONFIG_AMIX_FILTER) += af_amix.o OBJS-$(CONFIG_AMIX_FILTER) += af_amix.o
OBJS-$(CONFIG_ANULL_FILTER) += af_anull.o OBJS-$(CONFIG_ANULL_FILTER) += af_anull.o
...@@ -68,14 +69,22 @@ OBJS-$(CONFIG_ASPLIT_FILTER) += split.o ...@@ -68,14 +69,22 @@ OBJS-$(CONFIG_ASPLIT_FILTER) += split.o
OBJS-$(CONFIG_ASTREAMSYNC_FILTER) += af_astreamsync.o OBJS-$(CONFIG_ASTREAMSYNC_FILTER) += af_astreamsync.o
OBJS-$(CONFIG_ASYNCTS_FILTER) += af_asyncts.o OBJS-$(CONFIG_ASYNCTS_FILTER) += af_asyncts.o
OBJS-$(CONFIG_ATEMPO_FILTER) += af_atempo.o OBJS-$(CONFIG_ATEMPO_FILTER) += af_atempo.o
OBJS-$(CONFIG_BANDPASS_FILTER) += af_biquads.o
OBJS-$(CONFIG_BANDREJECT_FILTER) += af_biquads.o
OBJS-$(CONFIG_BASS_FILTER) += af_biquads.o
OBJS-$(CONFIG_BIQUAD_FILTER) += af_biquads.o
OBJS-$(CONFIG_CHANNELMAP_FILTER) += af_channelmap.o OBJS-$(CONFIG_CHANNELMAP_FILTER) += af_channelmap.o
OBJS-$(CONFIG_CHANNELSPLIT_FILTER) += af_channelsplit.o OBJS-$(CONFIG_CHANNELSPLIT_FILTER) += af_channelsplit.o
OBJS-$(CONFIG_EARWAX_FILTER) += af_earwax.o OBJS-$(CONFIG_EARWAX_FILTER) += af_earwax.o
OBJS-$(CONFIG_EBUR128_FILTER) += f_ebur128.o OBJS-$(CONFIG_EBUR128_FILTER) += f_ebur128.o
OBJS-$(CONFIG_EQUALIZER_FILTER) += af_biquads.o
OBJS-$(CONFIG_HIGHPASS_FILTER) += af_biquads.o
OBJS-$(CONFIG_JOIN_FILTER) += af_join.o OBJS-$(CONFIG_JOIN_FILTER) += af_join.o
OBJS-$(CONFIG_LOWPASS_FILTER) += af_biquads.o
OBJS-$(CONFIG_PAN_FILTER) += af_pan.o OBJS-$(CONFIG_PAN_FILTER) += af_pan.o
OBJS-$(CONFIG_RESAMPLE_FILTER) += af_resample.o OBJS-$(CONFIG_RESAMPLE_FILTER) += af_resample.o
OBJS-$(CONFIG_SILENCEDETECT_FILTER) += af_silencedetect.o OBJS-$(CONFIG_SILENCEDETECT_FILTER) += af_silencedetect.o
OBJS-$(CONFIG_TREBLE_FILTER) += af_biquads.o
OBJS-$(CONFIG_VOLUME_FILTER) += af_volume.o OBJS-$(CONFIG_VOLUME_FILTER) += af_volume.o
OBJS-$(CONFIG_VOLUMEDETECT_FILTER) += af_volumedetect.o OBJS-$(CONFIG_VOLUMEDETECT_FILTER) += af_volumedetect.o
......
/*
* Copyright (c) 2013 Paul B Mahol
* Copyright (c) 2006-2008 Rob Sykes <robs@users.sourceforge.net>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* 2-pole filters designed by Robert Bristow-Johnson <rbj@audioimagination.com>
* see http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
*
* 1-pole filters based on code (c) 2000 Chris Bagwell <cbagwell@sprynet.com>
* Algorithms: Recursive single pole low/high pass filter
* Reference: The Scientist and Engineer's Guide to Digital Signal Processing
*
* low-pass: output[N] = input[N] * A + output[N-1] * B
* X = exp(-2.0 * pi * Fc)
* A = 1 - X
* B = X
* Fc = cutoff freq / sample rate
*
* Mimics an RC low-pass filter:
*
* ---/\/\/\/\----------->
* |
* --- C
* ---
* |
* |
* V
*
* high-pass: output[N] = A0 * input[N] + A1 * input[N-1] + B1 * output[N-1]
* X = exp(-2.0 * pi * Fc)
* A0 = (1 + X) / 2
* A1 = -(1 + X) / 2
* B1 = X
* Fc = cutoff freq / sample rate
*
* Mimics an RC high-pass filter:
*
* || C
* ----||--------->
* || |
* <
* > R
* <
* |
* V
*/
#include "libavutil/opt.h"
#include "libavutil/avassert.h"
#include "audio.h"
#include "avfilter.h"
#include "internal.h"
enum FilterType {
biquad,
equalizer,
bass,
treble,
band,
bandpass,
bandreject,
allpass,
highpass,
lowpass,
};
enum WidthType {
NONE,
HZ,
OCTAVE,
QFACTOR,
SLOPE,
};
typedef struct ChanCache {
double i1, i2;
double o1, o2;
} ChanCache;
typedef struct {
const AVClass *class;
enum FilterType filter_type;
enum WidthType width_type;
int poles;
int csg;
double gain;
double frequency;
double width;
double a0, a1, a2;
double b0, b1, b2;
ChanCache *cache;
void (*filter)(const void *ibuf, void *obuf, int len,
double *i1, double *i2, double *o1, double *o2,
double b0, double b1, double b2, double a1, double a2);
} BiquadsContext;
static av_cold int init(AVFilterContext *ctx, const char *args)
{
BiquadsContext *p = ctx->priv;
int ret;
av_opt_set_defaults(p);
if ((ret = av_set_options_string(p, args, "=", ":")) < 0)
return ret;
if (p->filter_type != biquad) {
if (p->frequency <= 0 || p->width <= 0) {
av_log(ctx, AV_LOG_ERROR, "Invalid frequency %f and/or width %f <= 0\n",
p->frequency, p->width);
return AVERROR(EINVAL);
}
}
return 0;
}
static int query_formats(AVFilterContext *ctx)
{
AVFilterFormats *formats;
AVFilterChannelLayouts *layouts;
static const enum AVSampleFormat sample_fmts[] = {
AV_SAMPLE_FMT_S16P,
AV_SAMPLE_FMT_S32P,
AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_DBLP,
AV_SAMPLE_FMT_NONE
};
layouts = ff_all_channel_layouts();
if (!layouts)
return AVERROR(ENOMEM);
ff_set_common_channel_layouts(ctx, layouts);
formats = ff_make_format_list(sample_fmts);
if (!formats)
return AVERROR(ENOMEM);
ff_set_common_formats(ctx, formats);
formats = ff_all_samplerates();
if (!formats)
return AVERROR(ENOMEM);
ff_set_common_samplerates(ctx, formats);
return 0;
}
#define BIQUAD_FILTER(name, type, min, max) \
static void biquad_## name (const void *input, void *output, int len, \
double *in1, double *in2, \
double *out1, double *out2, \
double b0, double b1, double b2, \
double a1, double a2) \
{ \
const type *ibuf = input; \
type *obuf = output; \
double i1 = *in1; \
double i2 = *in2; \
double o1 = *out1; \
double o2 = *out2; \
int i; \
\
for (i = 0; i < len; i++) { \
double o0 = ibuf[i] * b0 + i1 * b1 + i2 * b2 - o1 * a1 - o2 * a2; \
i2 = i1; \
i1 = ibuf[i]; \
o2 = o1; \
o1 = o0; \
if (o0 < min) { \
av_log(NULL, AV_LOG_WARNING, "clipping\n"); \
obuf[i] = min; \
} else if (o0 > max) { \
av_log(NULL, AV_LOG_WARNING, "clipping\n"); \
obuf[i] = max; \
} else { \
obuf[i] = o0; \
} \
} \
*in1 = i1; \
*in2 = i2; \
*out1 = o1; \
*out2 = o2; \
}
BIQUAD_FILTER(s16, int16_t, INT16_MIN, INT16_MAX)
BIQUAD_FILTER(s32, int32_t, INT32_MIN, INT32_MAX)
BIQUAD_FILTER(flt, float, -1., 1.)
BIQUAD_FILTER(dbl, double, -1., 1.)
static int config_output(AVFilterLink *outlink)
{
AVFilterContext *ctx = outlink->src;
BiquadsContext *p = ctx->priv;
AVFilterLink *inlink = ctx->inputs[0];
double A = exp(p->gain / 40 * log(10.));
double w0 = 2 * M_PI * p->frequency / inlink->sample_rate;
double alpha;
if (w0 > M_PI) {
av_log(ctx, AV_LOG_ERROR,
"Invalid frequency %f. Frequency must be less than half the sample-rate %d.\n",
p->frequency, inlink->sample_rate);
return AVERROR(EINVAL);
}
switch (p->width_type) {
case NONE:
alpha = 0.0;
break;
case HZ:
alpha = sin(w0) / (2 * p->frequency / p->width);
break;
case OCTAVE:
alpha = sin(w0) * sinh(log(2.) / 2 * p->width * w0 / sin(w0));
break;
case QFACTOR:
alpha = sin(w0) / (2 * p->width);
break;
case SLOPE:
alpha = sin(w0) / 2 * sqrt((A + 1 / A) * (1 / p->width - 1) + 2);
break;
default:
av_assert0(0);
}
switch (p->filter_type) {
case biquad:
break;
case equalizer:
p->a0 = 1 + alpha / A;
p->a1 = -2 * cos(w0);
p->a2 = 1 - alpha / A;
p->b0 = 1 + alpha * A;
p->b1 = -2 * cos(w0);
p->b2 = 1 - alpha * A;
break;
case bass:
p->a0 = (A + 1) + (A - 1) * cos(w0) + 2 * sqrt(A) * alpha;
p->a1 = -2 * ((A - 1) + (A + 1) * cos(w0));
p->a2 = (A + 1) + (A - 1) * cos(w0) - 2 * sqrt(A) * alpha;
p->b0 = A * ((A + 1) - (A - 1) * cos(w0) + 2 * sqrt(A) * alpha);
p->b1 = 2 * A * ((A - 1) - (A + 1) * cos(w0));
p->b2 = A * ((A + 1) - (A - 1) * cos(w0) - 2 * sqrt(A) * alpha);
break;
case treble:
p->a0 = (A + 1) - (A - 1) * cos(w0) + 2 * sqrt(A) * alpha;
p->a1 = 2 * ((A - 1) - (A + 1) * cos(w0));
p->a2 = (A + 1) - (A - 1) * cos(w0) - 2 * sqrt(A) * alpha;
p->b0 = A * ((A + 1) + (A - 1) * cos(w0) + 2 * sqrt(A) * alpha);
p->b1 =-2 * A * ((A - 1) + (A + 1) * cos(w0));
p->b2 = A * ((A + 1) + (A - 1) * cos(w0) - 2 * sqrt(A) * alpha);
break;
case bandpass:
if (p->csg) {
p->a0 = 1 + alpha;
p->a1 = -2 * cos(w0);
p->a2 = 1 - alpha;
p->b0 = sin(w0) / 2;
p->b1 = 0;
p->b2 = -sin(w0) / 2;
} else {
p->a0 = 1 + alpha;
p->a1 = -2 * cos(w0);
p->a2 = 1 - alpha;
p->b0 = alpha;
p->b1 = 0;
p->b2 = -alpha;
}
break;
case bandreject:
p->a0 = 1 + alpha;
p->a1 = -2 * cos(w0);
p->a2 = 1 - alpha;
p->b0 = 1;
p->b1 = -2 * cos(w0);
p->b2 = 1;
break;
case lowpass:
if (p->poles == 1) {
p->a0 = 1;
p->a1 = -exp(-w0);
p->a2 = 0;
p->b0 = 1 + p->a1;
p->b1 = 0;
p->b2 = 0;
} else {
p->a0 = 1 + alpha;
p->a1 = -2 * cos(w0);
p->a2 = 1 - alpha;
p->b0 = (1 - cos(w0)) / 2;
p->b1 = 1 - cos(w0);
p->b2 = (1 - cos(w0)) / 2;
}
break;
case highpass:
if (p->poles == 1) {
p->a0 = 1;
p->a1 = -exp(-w0);
p->a2 = 0;
p->b0 = (1 - p->a1) / 2;
p->b1 = -p->b0;
p->b2 = 0;
} else {
p->a0 = 1 + alpha;
p->a1 = -2 * cos(w0);
p->a2 = 1 - alpha;
p->b0 = (1 + cos(w0)) / 2;
p->b1 = -(1 + cos(w0));
p->b2 = (1 + cos(w0)) / 2;
}
break;
case allpass:
p->a0 = 1 + alpha;
p->a1 = -2 * cos(w0);
p->a2 = 1 - alpha;
p->b0 = 1 - alpha;
p->b1 = -2 * cos(w0);
p->b2 = 1 + alpha;
break;
default:
av_assert0(0);
}
p->a1 /= p->a0;
p->a2 /= p->a0;
p->b0 /= p->a0;
p->b1 /= p->a0;
p->b2 /= p->a0;
p->cache = av_realloc_f(p->cache, sizeof(ChanCache), inlink->channels);
if (!p->cache)
return AVERROR(ENOMEM);
switch (inlink->format) {
case AV_SAMPLE_FMT_S16P: p->filter = biquad_s16; break;
case AV_SAMPLE_FMT_S32P: p->filter = biquad_s32; break;
case AV_SAMPLE_FMT_FLTP: p->filter = biquad_flt; break;
case AV_SAMPLE_FMT_DBLP: p->filter = biquad_dbl; break;
default: av_assert0(0);
}
return 0;
}
static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
{
BiquadsContext *p = inlink->dst->priv;
AVFilterLink *outlink = inlink->dst->outputs[0];
AVFilterBufferRef *out_buf;
int nb_samples = buf->audio->nb_samples;
int ch;
if (buf->perms & AV_PERM_WRITE) {
out_buf = buf;
} else {
out_buf = ff_get_audio_buffer(inlink, AV_PERM_WRITE, nb_samples);
if (!out_buf)
return AVERROR(ENOMEM);
out_buf->pts = buf->pts;
}
for (ch = 0; ch < buf->audio->channels; ch++)
p->filter((const float *)buf->extended_data[ch],
(float *)out_buf->extended_data[ch], nb_samples,
&p->cache[ch].i1, &p->cache[ch].i2,
&p->cache[ch].o1, &p->cache[ch].o2,
p->b0, p->b1, p->b2, p->a1, p->a2);
if (buf != out_buf)
avfilter_unref_buffer(buf);
return ff_filter_frame(outlink, out_buf);
}
static av_cold void uninit(AVFilterContext *ctx)
{
BiquadsContext *p = ctx->priv;
av_freep(&p->cache);
av_opt_free(p);
}
static const AVFilterPad inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
.filter_frame = filter_frame,
},
{ NULL }
};
static const AVFilterPad outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
.config_props = config_output,
},
{ NULL }
};
#define OFFSET(x) offsetof(BiquadsContext, x)
#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
#define DEFINE_BIQUAD_FILTER(name_, description_) \
AVFILTER_DEFINE_CLASS(name_); \
static av_cold int name_##_init(AVFilterContext *ctx, const char *args) \
{ \
BiquadsContext *p = ctx->priv; \
p->class = &name_##_class; \
p->filter_type = name_; \
return init(ctx, args); \
} \
\
AVFilter avfilter_af_##name_ = { \
.name = #name_, \
.description = NULL_IF_CONFIG_SMALL(description_), \
.priv_size = sizeof(BiquadsContext), \
.init = name_##_init, \
.uninit = uninit, \
.query_formats = query_formats, \
.inputs = inputs, \
.outputs = outputs, \
.priv_class = &name_##_class, \
}
#if CONFIG_EQUALIZER_FILTER
static const AVOption equalizer_options[] = {
{"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS},
{"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS},
{"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HZ, SLOPE, FLAGS, "width_type"},
{"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HZ}, 0, 0, FLAGS, "width_type"},
{"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
{"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
{"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
{"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 999, FLAGS},
{"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 999, FLAGS},
{"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
{"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
{NULL},
};
DEFINE_BIQUAD_FILTER(equalizer, "Apply two-pole peaking equalization (EQ) filter.");
#endif /* CONFIG_EQUALIZER_FILTER */
#if CONFIG_BASS_FILTER
static const AVOption bass_options[] = {
{"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
{"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
{"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HZ, SLOPE, FLAGS, "width_type"},
{"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HZ}, 0, 0, FLAGS, "width_type"},
{"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
{"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
{"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
{"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
{"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
{"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
{"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
{NULL},
};
DEFINE_BIQUAD_FILTER(bass, "Boost or cut lower frequencies.");
#endif /* CONFIG_BASS_FILTER */
#if CONFIG_TREBLE_FILTER
static const AVOption treble_options[] = {
{"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
{"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
{"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HZ, SLOPE, FLAGS, "width_type"},
{"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HZ}, 0, 0, FLAGS, "width_type"},
{"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
{"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
{"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
{"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
{"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
{"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
{"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
{NULL},
};
DEFINE_BIQUAD_FILTER(treble, "Boost or cut upper frequencies.");
#endif /* CONFIG_TREBLE_FILTER */
#if CONFIG_BANDPASS_FILTER
static const AVOption bandpass_options[] = {
{"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
{"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
{"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HZ, SLOPE, FLAGS, "width_type"},
{"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HZ}, 0, 0, FLAGS, "width_type"},
{"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
{"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
{"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
{"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS},
{"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS},
{"csg", "use constant skirt gain", OFFSET(csg), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS},
{NULL},
};
DEFINE_BIQUAD_FILTER(bandpass, "Apply a two-pole Butterworth band-pass filter.");
#endif /* CONFIG_BANDPASS_FILTER */
#if CONFIG_BANDREJECT_FILTER
static const AVOption bandreject_options[] = {
{"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
{"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
{"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HZ, SLOPE, FLAGS, "width_type"},
{"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HZ}, 0, 0, FLAGS, "width_type"},
{"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
{"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
{"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
{"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS},
{"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS},
{NULL},
};
DEFINE_BIQUAD_FILTER(bandreject, "Apply a two-pole Butterworth band-reject filter.");
#endif /* CONFIG_BANDREJECT_FILTER */
#if CONFIG_LOWPASS_FILTER
static const AVOption lowpass_options[] = {
{"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS},
{"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS},
{"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HZ, SLOPE, FLAGS, "width_type"},
{"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HZ}, 0, 0, FLAGS, "width_type"},
{"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
{"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
{"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
{"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
{"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
{"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
{"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
{NULL},
};
DEFINE_BIQUAD_FILTER(lowpass, "Apply a low-pass filter with 3dB point frequency.");
#endif /* CONFIG_LOWPASS_FILTER */
#if CONFIG_HIGHPASS_FILTER
static const AVOption highpass_options[] = {
{"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
{"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
{"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HZ, SLOPE, FLAGS, "width_type"},
{"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HZ}, 0, 0, FLAGS, "width_type"},
{"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
{"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
{"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
{"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
{"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
{"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
{"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
{NULL},
};
DEFINE_BIQUAD_FILTER(highpass, "Apply a high-pass filter with 3dB point frequency.");
#endif /* CONFIG_HIGHPASS_FILTER */
#if CONFIG_ALLPASS_FILTER
static const AVOption allpass_options[] = {
{"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
{"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
{"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HZ}, HZ, SLOPE, FLAGS, "width_type"},
{"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HZ}, 0, 0, FLAGS, "width_type"},
{"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
{"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
{"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
{"width", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS},
{"w", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS},
{NULL},
};
DEFINE_BIQUAD_FILTER(allpass, "Apply a two-pole all-pass filter.");
#endif /* CONFIG_ALLPASS_FILTER */
#if CONFIG_BIQUAD_FILTER
static const AVOption biquad_options[] = {
{"a0", NULL, OFFSET(a0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MAX, INT16_MAX, FLAGS},
{"a1", NULL, OFFSET(a1), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MAX, INT16_MAX, FLAGS},
{"a2", NULL, OFFSET(a2), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MAX, INT16_MAX, FLAGS},
{"b0", NULL, OFFSET(b0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MAX, INT16_MAX, FLAGS},
{"b1", NULL, OFFSET(b1), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MAX, INT16_MAX, FLAGS},
{"b2", NULL, OFFSET(b2), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MAX, INT16_MAX, FLAGS},
{NULL},
};
DEFINE_BIQUAD_FILTER(biquad, "Apply a biquad IIR filter with the given coefficients.");
#endif /* CONFIG_BIQUAD_FILTER */
...@@ -47,6 +47,7 @@ void avfilter_register_all(void) ...@@ -47,6 +47,7 @@ void avfilter_register_all(void)
REGISTER_FILTER(ACONVERT, aconvert, af); REGISTER_FILTER(ACONVERT, aconvert, af);
REGISTER_FILTER(AFADE, afade, af); REGISTER_FILTER(AFADE, afade, af);
REGISTER_FILTER(AFORMAT, aformat, af); REGISTER_FILTER(AFORMAT, aformat, af);
REGISTER_FILTER(ALLPASS, allpass, af);
REGISTER_FILTER(AMERGE, amerge, af); REGISTER_FILTER(AMERGE, amerge, af);
REGISTER_FILTER(AMIX, amix, af); REGISTER_FILTER(AMIX, amix, af);
REGISTER_FILTER(ANULL, anull, af); REGISTER_FILTER(ANULL, anull, af);
...@@ -62,14 +63,22 @@ void avfilter_register_all(void) ...@@ -62,14 +63,22 @@ void avfilter_register_all(void)
REGISTER_FILTER(ASTREAMSYNC, astreamsync, af); REGISTER_FILTER(ASTREAMSYNC, astreamsync, af);
REGISTER_FILTER(ASYNCTS, asyncts, af); REGISTER_FILTER(ASYNCTS, asyncts, af);
REGISTER_FILTER(ATEMPO, atempo, af); REGISTER_FILTER(ATEMPO, atempo, af);
REGISTER_FILTER(BANDPASS, bandpass, af);
REGISTER_FILTER(BANDREJECT, bandreject, af);
REGISTER_FILTER(BASS, bass, af);
REGISTER_FILTER(BIQUAD, biquad, af);
REGISTER_FILTER(CHANNELMAP, channelmap, af); REGISTER_FILTER(CHANNELMAP, channelmap, af);
REGISTER_FILTER(CHANNELSPLIT, channelsplit, af); REGISTER_FILTER(CHANNELSPLIT, channelsplit, af);
REGISTER_FILTER(EARWAX, earwax, af); REGISTER_FILTER(EARWAX, earwax, af);
REGISTER_FILTER(EBUR128, ebur128, af); REGISTER_FILTER(EBUR128, ebur128, af);
REGISTER_FILTER(EQUALIZER, equalizer, af);
REGISTER_FILTER(HIGHPASS, highpass, af);
REGISTER_FILTER(JOIN, join, af); REGISTER_FILTER(JOIN, join, af);
REGISTER_FILTER(LOWPASS, lowpass, af);
REGISTER_FILTER(PAN, pan, af); REGISTER_FILTER(PAN, pan, af);
REGISTER_FILTER(RESAMPLE, resample, af); REGISTER_FILTER(RESAMPLE, resample, af);
REGISTER_FILTER(SILENCEDETECT, silencedetect, af); REGISTER_FILTER(SILENCEDETECT, silencedetect, af);
REGISTER_FILTER(TREBLE, treble, af);
REGISTER_FILTER(VOLUME, volume, af); REGISTER_FILTER(VOLUME, volume, af);
REGISTER_FILTER(VOLUMEDETECT, volumedetect, af); REGISTER_FILTER(VOLUMEDETECT, volumedetect, af);
......
...@@ -29,8 +29,8 @@ ...@@ -29,8 +29,8 @@
#include "libavutil/avutil.h" #include "libavutil/avutil.h"
#define LIBAVFILTER_VERSION_MAJOR 3 #define LIBAVFILTER_VERSION_MAJOR 3
#define LIBAVFILTER_VERSION_MINOR 34 #define LIBAVFILTER_VERSION_MINOR 35
#define LIBAVFILTER_VERSION_MICRO 101 #define LIBAVFILTER_VERSION_MICRO 100
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
LIBAVFILTER_VERSION_MINOR, \ LIBAVFILTER_VERSION_MINOR, \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment