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