Mercurial > audlegacy
annotate audacious/iir.c @ 348:f74bdb82f0a0 trunk
[svn] a lot of EQ tweaks, but the preamp still does not work right
author | nenolod |
---|---|
date | Mon, 26 Dec 2005 13:35:40 -0800 |
parents | cb178e5ad177 |
children | 67cd014f35a2 |
rev | line source |
---|---|
0 | 1 /* |
2 * PCM time-domain equalizer | |
3 * | |
4 * Copyright (C) 2002 Felipe Rivera <liebremx at users sourceforge net> | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
19 * | |
20 * $Id: iir.c,v 1.5 2004/06/20 18:48:54 mderezynski Exp $ | |
21 */ | |
22 | |
23 #include "equalizer.h" | |
24 #include "main.h" | |
25 #include <math.h> | |
26 #include <string.h> | |
27 #include "output.h" | |
28 | |
29 #include "iir.h" | |
30 | |
31 // Fixed Point Fractional bits | |
32 #define FP_FRBITS 28 | |
33 | |
34 // Conversions | |
35 #define EQ_REAL(x) ((gint)((x) * (1 << FP_FRBITS))) | |
36 | |
37 /* Floating point */ | |
38 typedef struct { | |
39 float beta; | |
40 float alpha; | |
41 float gamma; | |
42 } sIIRCoefficients; | |
43 | |
44 /* Coefficient history for the IIR filter */ | |
45 typedef struct { | |
46 float x[3]; /* x[n], x[n-1], x[n-2] */ | |
47 float y[3]; /* y[n], y[n-1], y[n-2] */ | |
48 } sXYData; | |
49 | |
50 /* BETA, ALPHA, GAMMA */ | |
51 static sIIRCoefficients iir_cforiginal10[] = { | |
52 {(9.9421504945e-01), (2.8924752745e-03), (1.9941421835e+00)}, /* 60.0 Hz */ | |
53 {(9.8335039428e-01), (8.3248028618e-03), (1.9827686547e+00)}, /* 170.0 Hz */ | |
54 {(9.6958094144e-01), (1.5209529281e-02), (1.9676601546e+00)}, /* 310.0 Hz */ | |
55 {(9.4163923306e-01), (2.9180383468e-02), (1.9345490229e+00)}, /* 600.0 Hz */ | |
56 {(9.0450844499e-01), (4.7745777504e-02), (1.8852109613e+00)}, /* 1000.0 Hz */ | |
57 {(7.3940088234e-01), (1.3029955883e-01), (1.5829158753e+00)}, /* 3000.0 Hz */ | |
58 {(5.4697667908e-01), (2.2651166046e-01), (1.0153238114e+00)}, /* 6000.0 Hz */ | |
59 {(3.1023210589e-01), (3.4488394706e-01), (-1.8142472036e-01)}, /* 12000.0 Hz */ | |
60 {(2.6718639778e-01), (3.6640680111e-01), (-5.2117742267e-01)}, /* 14000.0 Hz */ | |
61 {(2.4201241845e-01), (3.7899379077e-01), (-8.0847117831e-01)}, /* 16000.0 Hz */ | |
62 }; | |
63 | |
64 /* History for two filters */ | |
65 static sXYData data_history[EQ_MAX_BANDS][EQ_CHANNELS]; | |
66 static sXYData data_history2[EQ_MAX_BANDS][EQ_CHANNELS]; | |
67 | |
68 /* Coefficients */ | |
69 static sIIRCoefficients *iir_cf; | |
70 | |
71 /* Gain for each band | |
72 * values should be between -0.2 and 1.0 */ | |
73 float gain[10]; | |
74 float preamp; | |
75 | |
76 int round_trick(float floatvalue_to_round); | |
77 | |
78 /* Init the filter */ | |
79 void | |
80 init_iir() | |
81 { | |
82 iir_cf = iir_cforiginal10; | |
83 | |
84 /* Zero the history arrays */ | |
85 memset(data_history, 0, sizeof(sXYData) * EQ_MAX_BANDS * EQ_CHANNELS); | |
86 memset(data_history2, 0, sizeof(sXYData) * EQ_MAX_BANDS * EQ_CHANNELS); | |
87 | |
88 output_set_eq(cfg.equalizer_active, cfg.equalizer_preamp, | |
89 cfg.equalizer_bands); | |
90 } | |
91 | |
92 int | |
93 iir(gpointer * d, gint length) | |
94 { | |
95 gint16 *data = (gint16 *) * d; | |
96 static gint i = 0, j = 2, k = 1; | |
97 | |
98 gint index, band, channel; | |
99 gint tempgint, halflength; | |
100 float out[EQ_CHANNELS], pcm[EQ_CHANNELS]; | |
101 | |
102 halflength = (length >> 1); | |
103 for (index = 0; index < halflength; index += 2) { | |
104 /* For each channel */ | |
105 for (channel = 0; channel < EQ_CHANNELS; channel++) { | |
106 /* No need to scale when processing the PCM with the filter */ | |
107 pcm[channel] = data[index + channel]; | |
348
f74bdb82f0a0
[svn] a lot of EQ tweaks, but the preamp still does not work right
nenolod
parents:
0
diff
changeset
|
108 |
0 | 109 /* Preamp gain */ |
110 pcm[channel] *= preamp; | |
111 | |
112 out[channel] = 0; | |
113 /* For each band */ | |
114 for (band = 0; band < 10; band++) { | |
115 /* Store Xi(n) */ | |
116 data_history[band][channel].x[i] = pcm[channel]; | |
117 /* Calculate and store Yi(n) */ | |
118 data_history[band][channel].y[i] = | |
119 (iir_cf[band].alpha * (data_history[band][channel].x[i] | |
120 - data_history[band][channel].x[k]) | |
121 + iir_cf[band].gamma * data_history[band][channel].y[j] | |
348
f74bdb82f0a0
[svn] a lot of EQ tweaks, but the preamp still does not work right
nenolod
parents:
0
diff
changeset
|
122 - iir_cf[band].beta * data_history[band][channel].y[k]); |
0 | 123 /* |
124 * The multiplication by 2.0 was 'moved' into the coefficients to save | |
125 * CPU cycles here */ | |
126 /* Apply the gain */ | |
348
f74bdb82f0a0
[svn] a lot of EQ tweaks, but the preamp still does not work right
nenolod
parents:
0
diff
changeset
|
127 out[channel] += data_history[band][channel].y[i] * gain[band]; |
0 | 128 } /* For each band */ |
129 | |
130 if (cfg.eq_extra_filtering) { | |
131 /* Filter the sample again */ | |
132 for (band = 0; band < 10; band++) { | |
133 /* Store Xi(n) */ | |
134 data_history2[band][channel].x[i] = out[channel]; | |
135 /* Calculate and store Yi(n) */ | |
136 data_history2[band][channel].y[i] = | |
137 (iir_cf[band].alpha * | |
138 (data_history2[band][channel].x[i] | |
139 - data_history2[band][channel].x[k]) | |
140 + | |
141 iir_cf[band].gamma * | |
142 data_history2[band][channel].y[j] | |
143 - | |
144 iir_cf[band].beta * data_history2[band][channel].y[k] | |
145 ); | |
146 /* Apply the gain */ | |
147 out[channel] += | |
148 data_history2[band][channel].y[i] * gain[band]; | |
149 } /* For each band */ | |
150 } | |
151 | |
152 /* Volume stuff | |
153 Scale down original PCM sample and add it to the filters | |
154 output. This substitutes the multiplication by 0.25 | |
155 */ | |
156 | |
348
f74bdb82f0a0
[svn] a lot of EQ tweaks, but the preamp still does not work right
nenolod
parents:
0
diff
changeset
|
157 out[channel] += (data[index + channel]); |
0 | 158 tempgint = (int) out[channel]; |
159 | |
160 if (tempgint < -32768) | |
161 data[index + channel] = -32768; | |
162 else if (tempgint > 32767) | |
163 data[index + channel] = 32767; | |
164 else | |
165 data[index + channel] = tempgint; | |
348
f74bdb82f0a0
[svn] a lot of EQ tweaks, but the preamp still does not work right
nenolod
parents:
0
diff
changeset
|
166 } |
0 | 167 |
168 i++; | |
169 j++; | |
170 k++; | |
171 | |
172 /* Wrap around the indexes */ | |
173 if (i == 3) | |
174 i = 0; | |
175 else if (j == 3) | |
176 j = 0; | |
177 else | |
178 k = 0; | |
348
f74bdb82f0a0
[svn] a lot of EQ tweaks, but the preamp still does not work right
nenolod
parents:
0
diff
changeset
|
179 } |
0 | 180 |
181 return length; | |
182 } |