avfilter/af_biquads: add different transform types

This commit is contained in:
Paul B Mahol 2020-08-21 22:42:45 +02:00
parent 999f5160c4
commit 2459c3f8f0
2 changed files with 287 additions and 8 deletions

View File

@ -1573,6 +1573,14 @@ Enabling it will normalize magnitude response at DC to 0dB.
@item order, o
Set the filter order, can be 1 or 2. Default is 2.
@item transform, a
Set transform type of IIR filter.
@table @option
@item di
@item dii
@item tdii
@end table
@end table
@subsection Commands
@ -2693,6 +2701,14 @@ Specify which channels to filter, by default all available are filtered.
@item normalize, n
Normalize biquad coefficients, by default is disabled.
Enabling it will normalize magnitude response at DC to 0dB.
@item transform, a
Set transform type of IIR filter.
@table @option
@item di
@item dii
@item tdii
@end table
@end table
@subsection Commands
@ -2756,6 +2772,14 @@ Specify which channels to filter, by default all available are filtered.
@item normalize, n
Normalize biquad coefficients, by default is disabled.
Enabling it will normalize magnitude response at DC to 0dB.
@item transform, a
Set transform type of IIR filter.
@table @option
@item di
@item dii
@item tdii
@end table
@end table
@subsection Commands
@ -2826,6 +2850,14 @@ Specify which channels to filter, by default all available are filtered.
@item normalize, n
Normalize biquad coefficients, by default is disabled.
Enabling it will normalize magnitude response at DC to 0dB.
@item transform, a
Set transform type of IIR filter.
@table @option
@item di
@item dii
@item tdii
@end table
@end table
@subsection Commands
@ -2884,6 +2916,14 @@ Specify which channels to filter, by default all available are filtered.
@item normalize, n
Normalize biquad coefficients, by default is disabled.
Enabling it will normalize magnitude response at DC to 0dB.
@item transform, a
Set transform type of IIR filter.
@table @option
@item di
@item dii
@item tdii
@end table
@end table
@section bs2b
@ -3607,6 +3647,14 @@ Specify which channels to filter, by default all available are filtered.
@item normalize, n
Normalize biquad coefficients, by default is disabled.
Enabling it will normalize magnitude response at DC to 0dB.
@item transform, a
Set transform type of IIR filter.
@table @option
@item di
@item dii
@item tdii
@end table
@end table
@subsection Examples
@ -4084,6 +4132,14 @@ Specify which channels to filter, by default all available are filtered.
@item normalize, n
Normalize biquad coefficients, by default is disabled.
Enabling it will normalize magnitude response at DC to 0dB.
@item transform, a
Set transform type of IIR filter.
@table @option
@item di
@item dii
@item tdii
@end table
@end table
@subsection Commands
@ -4410,6 +4466,14 @@ Specify which channels to filter, by default all available are filtered.
@item normalize, n
Normalize biquad coefficients, by default is disabled.
Enabling it will normalize magnitude response at DC to 0dB.
@item transform, a
Set transform type of IIR filter.
@table @option
@item di
@item dii
@item tdii
@end table
@end table
@subsection Examples
@ -5530,6 +5594,14 @@ Specify which channels to filter, by default all available are filtered.
@item normalize, n
Normalize biquad coefficients, by default is disabled.
Enabling it will normalize magnitude response at DC to 0dB.
@item transform, a
Set transform type of IIR filter.
@table @option
@item di
@item dii
@item tdii
@end table
@end table
@subsection Commands

View File

@ -93,6 +93,13 @@ enum WidthType {
NB_WTYPE,
};
enum TransformType {
DI,
DII,
TDII,
NB_TTYPE,
};
typedef struct ChanCache {
double i1, i2;
double o1, o2;
@ -106,6 +113,7 @@ typedef struct BiquadsContext {
int width_type;
int poles;
int csg;
int transform_type;
double gain;
double frequency;
@ -258,6 +266,101 @@ BIQUAD_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1)
BIQUAD_FILTER(flt, float, -1., 1., 0)
BIQUAD_FILTER(dbl, double, -1., 1., 0)
#define BIQUAD_DII_FILTER(name, type, min, max, need_clipping) \
static void biquad_dii_## name (BiquadsContext *s, \
const void *input, void *output, int len, \
double *z1, double *z2, \
double *unused1, double *unused2, \
double b0, double b1, double b2, \
double a1, double a2, int *clippings, \
int disabled) \
{ \
const type *ibuf = input; \
type *obuf = output; \
double w1 = *z1; \
double w2 = *z2; \
double wet = s->mix; \
double dry = 1. - wet; \
double in, out, w0; \
\
a1 = -a1; \
a2 = -a2; \
\
for (int i = 0; i < len; i++) { \
in = ibuf[i]; \
w0 = in + a1 * w1 + a2 * w2; \
out = b0 * w0 + b1 * w1 + b2 * w2; \
w2 = w1; \
w1 = w0; \
out = out * wet + in * dry; \
if (disabled) { \
obuf[i] = in; \
} else if (need_clipping && out < min) { \
(*clippings)++; \
obuf[i] = min; \
} else if (need_clipping && out > max) { \
(*clippings)++; \
obuf[i] = max; \
} else { \
obuf[i] = out; \
} \
} \
*z1 = w1; \
*z2 = w2; \
}
BIQUAD_DII_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1)
BIQUAD_DII_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1)
BIQUAD_DII_FILTER(flt, float, -1., 1., 0)
BIQUAD_DII_FILTER(dbl, double, -1., 1., 0)
#define BIQUAD_TDII_FILTER(name, type, min, max, need_clipping) \
static void biquad_tdii_## name (BiquadsContext *s, \
const void *input, void *output, int len, \
double *z1, double *z2, \
double *unused1, double *unused2, \
double b0, double b1, double b2, \
double a1, double a2, int *clippings, \
int disabled) \
{ \
const type *ibuf = input; \
type *obuf = output; \
double w1 = *z1; \
double w2 = *z2; \
double wet = s->mix; \
double dry = 1. - wet; \
double in, out; \
\
a1 = -a1; \
a2 = -a2; \
\
for (int i = 0; i < len; i++) { \
in = ibuf[i]; \
out = b0 * in + w1; \
w1 = b1 * in + w2 + a1 * out; \
w2 = b2 * in + a2 * out; \
out = out * wet + in * dry; \
if (disabled) { \
obuf[i] = in; \
} else if (need_clipping && out < min) { \
(*clippings)++; \
obuf[i] = min; \
} else if (need_clipping && out > max) { \
(*clippings)++; \
obuf[i] = max; \
} else { \
obuf[i] = out; \
} \
} \
*z1 = w1; \
*z2 = w2; \
}
BIQUAD_TDII_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1)
BIQUAD_TDII_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1)
BIQUAD_TDII_FILTER(flt, float, -1., 1., 0)
BIQUAD_TDII_FILTER(dbl, double, -1., 1., 0)
static int config_filter(AVFilterLink *outlink, int reset)
{
AVFilterContext *ctx = outlink->src;
@ -437,15 +540,64 @@ static int config_filter(AVFilterLink *outlink, int reset)
if (reset)
memset(s->cache, 0, sizeof(ChanCache) * inlink->channels);
switch (inlink->format) {
case AV_SAMPLE_FMT_S16P: s->filter = biquad_s16; break;
case AV_SAMPLE_FMT_S32P: s->filter = biquad_s32; break;
case AV_SAMPLE_FMT_FLTP: s->filter = biquad_flt; break;
case AV_SAMPLE_FMT_DBLP: s->filter = biquad_dbl; break;
default: av_assert0(0);
}
s->block_align = av_get_bytes_per_sample(inlink->format);
switch (s->transform_type) {
case DI:
switch (inlink->format) {
case AV_SAMPLE_FMT_S16P:
s->filter = biquad_s16;
break;
case AV_SAMPLE_FMT_S32P:
s->filter = biquad_s32;
break;
case AV_SAMPLE_FMT_FLTP:
s->filter = biquad_flt;
break;
case AV_SAMPLE_FMT_DBLP:
s->filter = biquad_dbl;
break;
default: av_assert0(0);
}
break;
case DII:
switch (inlink->format) {
case AV_SAMPLE_FMT_S16P:
s->filter = biquad_dii_s16;
break;
case AV_SAMPLE_FMT_S32P:
s->filter = biquad_dii_s32;
break;
case AV_SAMPLE_FMT_FLTP:
s->filter = biquad_dii_flt;
break;
case AV_SAMPLE_FMT_DBLP:
s->filter = biquad_dii_dbl;
break;
default: av_assert0(0);
}
break;
case TDII:
switch (inlink->format) {
case AV_SAMPLE_FMT_S16P:
s->filter = biquad_tdii_s16;
break;
case AV_SAMPLE_FMT_S32P:
s->filter = biquad_tdii_s32;
break;
case AV_SAMPLE_FMT_FLTP:
s->filter = biquad_tdii_flt;
break;
case AV_SAMPLE_FMT_DBLP:
s->filter = biquad_tdii_dbl;
break;
default: av_assert0(0);
}
break;
default:
av_assert0(0);
}
s->block_align = av_get_bytes_per_sample(inlink->format);
return 0;
}
@ -610,6 +762,11 @@ static const AVOption equalizer_options[] = {
{"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
{"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"},
{"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"},
{"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"},
{NULL}
};
@ -636,6 +793,11 @@ static const AVOption bass_options[] = {
{"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
{"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"},
{"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"},
{"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"},
{NULL}
};
@ -662,6 +824,11 @@ static const AVOption treble_options[] = {
{"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
{"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"},
{"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"},
{"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"},
{NULL}
};
@ -687,6 +854,11 @@ static const AVOption bandpass_options[] = {
{"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
{"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"},
{"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"},
{"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"},
{NULL}
};
@ -711,6 +883,11 @@ static const AVOption bandreject_options[] = {
{"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
{"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"},
{"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"},
{"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"},
{NULL}
};
@ -737,6 +914,11 @@ static const AVOption lowpass_options[] = {
{"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
{"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"},
{"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"},
{"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"},
{NULL}
};
@ -763,6 +945,11 @@ static const AVOption highpass_options[] = {
{"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
{"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"},
{"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"},
{"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"},
{NULL}
};
@ -789,6 +976,11 @@ static const AVOption allpass_options[] = {
{"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"order", "set filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
{"o", "set filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
{"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"},
{"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"},
{"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"},
{NULL}
};
@ -815,6 +1007,11 @@ static const AVOption lowshelf_options[] = {
{"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
{"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"},
{"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"},
{"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"},
{NULL}
};
@ -841,6 +1038,11 @@ static const AVOption highshelf_options[] = {
{"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
{"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"},
{"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"},
{"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"},
{NULL}
};
@ -860,6 +1062,11 @@ static const AVOption biquad_options[] = {
{"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
{"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
{"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"},
{"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"},
{"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"},
{"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"},
{NULL}
};