diff options
Diffstat (limited to 'apps/eq.c')
-rw-r--r-- | apps/eq.c | 60 |
1 files changed, 56 insertions, 4 deletions
@@ -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 | */ |
130 | void filter_bishelf_coefs(unsigned long cutoff, long ad, long an, int32_t *c) | 130 | void 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 | */ | ||
162 | void 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 | */ |
168 | void eq_pk_coefs(unsigned long cutoff, unsigned long Q, long db, int32_t *c) | 220 | void eq_pk_coefs(unsigned long cutoff, unsigned long Q, long db, int32_t *c) |