Skip to content

Commit 1261b72

Browse files
committed
biquad: Add {low,high}pass_transform filters.
linkwitz_transform is now an alias for highpass_transform.
1 parent 06f7284 commit 1261b72

File tree

5 files changed

+32
-9
lines changed

5 files changed

+32
-9
lines changed

README.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,16 @@ Example:
185185
Second-order lowshelf filter.
186186
* `highshelf f0[k] width[q|s|d|o|h|k] gain`
187187
Second-order highshelf filter.
188+
* `lowpass_transform fz[k] qz fp[k] qp`
189+
Second-order lowpass transformation filter. Cancels the poles defined by
190+
`fz` and `qz` and replaces them with new poles defined by `fp` and `qp`.
191+
Gain is unity at DC.
192+
* `highpass_transform fz[k] qz fp[k] qp`
193+
Second-order highpass transformation filter. Also known as a Linkwitz
194+
transform (see http://www.linkwitzlab.com/filters.htm#9). Same as
195+
`lowpass_transform` except the gain is unity at Fs/2.
188196
* `linkwitz_transform fz[k] qz fp[k] qp`
189-
Linkwitz transform (see http://www.linkwitzlab.com/filters.htm#9).
197+
Alias for `highpass_transform`.
190198
* `deemph`
191199
Compact Disc de-emphasis filter.
192200
* `biquad b0 b1 b2 a0 a1 a2`

biquad.c

+7-5
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,15 @@ void biquad_reset(struct biquad_state *state)
7979
void biquad_init_using_type(struct biquad_state *b, int type, double fs, double arg0, double arg1, double arg2, double arg3, int width_type)
8080
{
8181
double b0 = 1.0, b1 = 0.0, b2 = 0.0, a0 = 1.0, a1 = 0.0, a2 = 0.0;
82-
if (type == BIQUAD_LINKWITZ_TRANSFORM) {
82+
if (type == BIQUAD_LOWPASS_TRANSFORM || type == BIQUAD_HIGHPASS_TRANSFORM) {
8383
const double fz = arg0, qz = arg1;
8484
const double fp = arg2, qp = arg3;
8585

8686
const double w0z = 2*M_PI*fz / fs, w0p = 2*M_PI*fp / fs;
8787
const double cos_w0z = cos(w0z), cos_w0p = cos(w0p);
8888
const double alpha_z = sin(w0z) / (2.0*qz), alpha_p = sin(w0p) / (2.0*qp);
89-
const double kz = 2.0/(1.0+cos_w0z), kp = 2.0/(1.0+cos_w0p);
89+
const double kz = (type == BIQUAD_LOWPASS_TRANSFORM) ? 2.0/(1.0-cos_w0z) : 2.0/(1.0+cos_w0z);
90+
const double kp = (type == BIQUAD_LOWPASS_TRANSFORM) ? 2.0/(1.0-cos_w0p) : 2.0/(1.0+cos_w0p);
9091

9192
b0 = (1.0 + alpha_z)*kz;
9293
b1 = (-2.0 * cos_w0z)*kz;
@@ -109,7 +110,7 @@ void biquad_init_using_type(struct biquad_state *b, int type, double fs, double
109110
}
110111

111112
const double a = pow(10.0, gain / 40.0);
112-
const double w0 = 2.0*M_PI*f0 / fs;
113+
const double w0 = 2*M_PI*f0 / fs;
113114
const double sin_w0 = sin(w0), cos_w0 = cos(w0);
114115

115116
switch (width_type) {
@@ -422,8 +423,9 @@ struct effect * biquad_effect_init(const struct effect_info *ei, const struct st
422423
if (ei->effect_number == BIQUAD_PEAK) CHECK_WIDTH_TYPE(BIQUAD_WIDTH_TEST_NO_SLOPE);
423424
GET_ARG(arg2, argv[3], "gain");
424425
break;
425-
case BIQUAD_LINKWITZ_TRANSFORM:
426-
INIT_COMMON(4, BIQUAD_LINKWITZ_TRANSFORM);
426+
case BIQUAD_LOWPASS_TRANSFORM:
427+
case BIQUAD_HIGHPASS_TRANSFORM:
428+
INIT_COMMON(4, ei->effect_number);
427429
GET_FREQ_ARG(arg0, argv[1], "fz");
428430
GET_ARG(arg1, argv[2], "qz");
429431
CHECK_RANGE(arg1 > 0.0, "qz", return NULL);

biquad.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ enum {
4444
BIQUAD_PEAK,
4545
BIQUAD_LOWSHELF,
4646
BIQUAD_HIGHSHELF,
47-
BIQUAD_LINKWITZ_TRANSFORM,
47+
BIQUAD_LOWPASS_TRANSFORM,
48+
BIQUAD_HIGHPASS_TRANSFORM,
4849
/* Only for effect_info->effect_number */
4950
BIQUAD_DEEMPH,
5051
BIQUAD_BIQUAD,

dsp.1

+11-1
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,18 @@ Second-order lowshelf filter.
168168
\fBhighshelf\fR \fIf0\fR[\fBk\fR] \fIwidth\fR[\fBq\fR|\fBs\fR|\fBd\fR|\fBo\fR|\fBh\fR|\fBk\fR] \fIgain\fR
169169
Second-order highshelf filter.
170170
.TP
171+
\fBlowpass_transform\fR \fIfz\fR[\fBk\fR] \fIqz\fR \fIfp\fR[\fBk\fR] \fIqp\fR
172+
Second-order lowpass transformation filter. Cancels the poles defined by
173+
\fIfz\fR and \fIqz\fR and replaces them with new poles defined by \fIfp\fR and \fIqp\fR.
174+
Gain is unity at DC.
175+
.TP
176+
\fBhighpass_transform\fR \fIfz\fR[\fBk\fR] \fIqz\fR \fIfp\fR[\fBk\fR] \fIqp\fR
177+
Second-order highpass transformation filter. Also known as a Linkwitz
178+
transform (see http://www.linkwitzlab.com/filters.htm#9). Same as
179+
\fBlowpass_transform\fR except the gain is unity at Fs/2.
180+
.TP
171181
\fBlinkwitz_transform\fR \fIfz\fR[\fBk\fR] \fIqz\fR \fIfp\fR[\fBk\fR] \fIqp\fR
172-
Linkwitz transform (see http://www.linkwitzlab.com/filters.htm#9).
182+
Alias for \fBhighpass_transform\fR.
173183
.TP
174184
\fBdeemph\fR
175185
Compact Disc de-emphasis filter.

effect.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ static const struct effect_info effects[] = {
5959
{ "eq", "eq f0[k] width[q|o|h|k] gain", biquad_effect_init, BIQUAD_PEAK },
6060
{ "lowshelf", "lowshelf f0[k] width[q|s|d|o|h|k] gain", biquad_effect_init, BIQUAD_LOWSHELF },
6161
{ "highshelf", "highshelf f0[k] width[q|s|d|o|h|k] gain", biquad_effect_init, BIQUAD_HIGHSHELF },
62-
{ "linkwitz_transform", "linkwitz_transform fz[k] qz fp[k] qp", biquad_effect_init, BIQUAD_LINKWITZ_TRANSFORM },
62+
{ "lowpass_transform", "lowpass_transform fz[k] qz fp[k] qp", biquad_effect_init, BIQUAD_LOWPASS_TRANSFORM },
63+
{ "highpass_transform", "highpass_transform fz[k] qz fp[k] qp", biquad_effect_init, BIQUAD_HIGHPASS_TRANSFORM },
64+
{ "linkwitz_transform", "linkwitz_transform fz[k] qz fp[k] qp", biquad_effect_init, BIQUAD_HIGHPASS_TRANSFORM },
6365
{ "deemph", "deemph", biquad_effect_init, BIQUAD_DEEMPH },
6466
{ "biquad", "biquad b0 b1 b2 a0 a1 a2", biquad_effect_init, BIQUAD_BIQUAD },
6567
{ "gain", "gain gain_dB", gain_effect_init, GAIN_EFFECT_NUMBER_GAIN },

0 commit comments

Comments
 (0)