summaryrefslogtreecommitdiff
path: root/apps/eq.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/eq.c')
-rw-r--r--apps/eq.c60
1 files changed, 56 insertions, 4 deletions
diff --git a/apps/eq.c b/apps/eq.c
index 588c23f89f..1d74db790e 100644
--- a/apps/eq.c
+++ b/apps/eq.c
@@ -7,7 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2006 Thom Johansen 10 * Copyright (C) 2006-2007 Thom Johansen
11 * 11 *
12 * All files in this archive are subject to the GNU General Public License. 12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement. 13 * See the file COPYING in the source tree root for full license agreement.
@@ -127,7 +127,7 @@ static long fsincos(unsigned long phase, long *cos) {
127 * @param an gain at Nyquist frequency. s3.27 fixed point. 127 * @param an gain at Nyquist frequency. s3.27 fixed point.
128 * @param c pointer to coefficient storage. The coefs are s0.31 format. 128 * @param c pointer to coefficient storage. The coefs are s0.31 format.
129 */ 129 */
130void filter_bishelf_coefs(unsigned long cutoff, long ad, long an, int32_t *c) 130void filter_shelf_coefs(unsigned long cutoff, long ad, long an, int32_t *c)
131{ 131{
132 const long one = 1 << 27; 132 const long one = 1 << 27;
133 long a0, a1; 133 long a0, a1;
@@ -137,7 +137,7 @@ void filter_bishelf_coefs(unsigned long cutoff, long ad, long an, int32_t *c)
137 cs = one + (cs >> 4); 137 cs = one + (cs >> 4);
138 138
139 /* For max A = 4 (24 dB) */ 139 /* For max A = 4 (24 dB) */
140 b0 = FRACMUL_SHL(an, cs, 4) + FRACMUL_SHL(ad, s, 4); 140 b0 = FRACMUL_SHL(ad, s, 4) + FRACMUL_SHL(an, cs, 4);
141 b1 = FRACMUL_SHL(ad, s, 4) - FRACMUL_SHL(an, cs, 4); 141 b1 = FRACMUL_SHL(ad, s, 4) - FRACMUL_SHL(an, cs, 4);
142 a0 = s + cs; 142 a0 = s + cs;
143 a1 = s - cs; 143 a1 = s - cs;
@@ -147,6 +147,58 @@ void filter_bishelf_coefs(unsigned long cutoff, long ad, long an, int32_t *c)
147 c[2] = -DIV64(a1, a0, 31); 147 c[2] = -DIV64(a1, a0, 31);
148} 148}
149 149
150/**
151 * Calculate second order section filter consisting of one low-shelf and one
152 * high-shelf section.
153 * @param cutoff_low low-shelf midpoint frequency. See eq_pk_coefs for format.
154 * @param cutoff_high high-shelf midpoint frequency.
155 * @param A_low decibel value multiplied by ten, describing gain/attenuation of
156 * low-shelf part. Max value is 24 dB.
157 * @param A_high decibel value multiplied by ten, describing gain/attenuation of
158 * high-shelf part. Max value is 24 dB.
159 * @param A decibel value multiplied by ten, describing additional overall gain.
160 * @param c pointer to coefficient storage. Coefficients are s4.27 format.
161 */
162void filter_bishelf_coefs(unsigned long cutoff_low, unsigned long cutoff_high,
163 long A_low, long A_high, long A, int32_t *c)
164{
165 long sin1, cos2; /* s0.31 */
166 long cos1, sin2; /* s3.28 */
167 int32_t b0, b1, b2, b3; /* s3.28 */
168 int32_t a0, a1, a2, a3;
169 const long gd = get_replaygain_int(A_low*5) << 4; /* 10^(db/40), s3.28 */
170 const long gn = get_replaygain_int(A_high*5) << 4; /* 10^(db/40), s3.28 */
171 const long g = get_replaygain_int(A*10) << 7; /* 10^(db/20), s0.31 */
172
173 sin1 = fsincos(cutoff_low/2, &cos1);
174 sin2 = fsincos(cutoff_high/2, &cos2) >> 3;
175 cos1 >>= 3;
176
177 /* lowshelf filter, ranges listed are for all possible cutoffs */
178 b0 = FRACMUL(sin1, gd) + cos1; /* 0.25 .. 4.10 */
179 b1 = FRACMUL(sin1, gd) - cos1; /* -1 .. 3.98 */
180 a0 = DIV64(sin1, gd, 25) + cos1; /* 0.25 .. 4.10 */
181 a1 = DIV64(sin1, gd, 25) - cos1; /* -1 .. 3.98 */
182
183 /* highshelf filter */
184 b2 = sin2 + FRACMUL(cos2, gn); /* 0.25 .. 4.10 */
185 b3 = sin2 - FRACMUL(cos2, gn); /* -3.98 .. 1 */
186 a2 = sin2 + DIV64(cos2, gn, 25); /* 0.25 .. 4.10 */
187 a3 = sin2 - DIV64(cos2, gn, 25); /* -3.98 .. 1 */
188
189 /* now we cascade the two first order filters to one second order filter
190 * which can be used by eq_filter(). these resulting coefficients have a
191 * really wide numerical range, so we use a fixed point format which will
192 * work for the selected cutoff frequencies (in dsp.c) only.
193 */
194 const int32_t rcp_a0 = DIV64(1, FRACMUL(a0, a2), 53); /* s3.28 */
195 *c++ = FRACMUL(g, FRACMUL_SHL(FRACMUL(b0, b2), rcp_a0, 5));
196 *c++ = FRACMUL(g, FRACMUL_SHL(FRACMUL(b0, b3) + FRACMUL(b1, b2), rcp_a0, 5));
197 *c++ = FRACMUL(g, FRACMUL_SHL(FRACMUL(b1, b3), rcp_a0, 5));
198 *c++ = -FRACMUL_SHL(FRACMUL(a0, a3) + FRACMUL(a1, a2), rcp_a0, 5);
199 *c++ = -FRACMUL_SHL(FRACMUL(a1, a3), rcp_a0, 5);
200}
201
150/* Coef calculation taken from Audio-EQ-Cookbook.txt by Robert Bristow-Johnson. 202/* Coef calculation taken from Audio-EQ-Cookbook.txt by Robert Bristow-Johnson.
151 * Slightly faster calculation can be done by deriving forms which use tan() 203 * Slightly faster calculation can be done by deriving forms which use tan()
152 * instead of cos() and sin(), but the latter are far easier to use when doing 204 * instead of cos() and sin(), but the latter are far easier to use when doing
@@ -162,7 +214,7 @@ void filter_bishelf_coefs(unsigned long cutoff, long ad, long an, int32_t *c)
162 * @param Q Q factor value multiplied by ten. Lower bound is artificially set 214 * @param Q Q factor value multiplied by ten. Lower bound is artificially set
163 * at 0.5. 215 * at 0.5.
164 * @param db decibel value multiplied by ten, describing gain/attenuation at 216 * @param db decibel value multiplied by ten, describing gain/attenuation at
165 * peak freq. 217 * peak freq. Max value is 24 dB.
166 * @param c pointer to coefficient storage. Coefficients are s3.28 format. 218 * @param c pointer to coefficient storage. Coefficients are s3.28 format.
167 */ 219 */
168void eq_pk_coefs(unsigned long cutoff, unsigned long Q, long db, int32_t *c) 220void eq_pk_coefs(unsigned long cutoff, unsigned long Q, long db, int32_t *c)