Mercurial > audlegacy
annotate src/audacious/iir_fpu.c @ 3121:3b6d316f8b09 trunk
GPL3 relicensing.
author | William Pitcock <nenolod@atheme-project.org> |
---|---|
date | Fri, 20 Jul 2007 08:59:47 -0500 |
parents | b210d1ea2084 |
children |
rev | line source |
---|---|
2313 | 1 /* |
2 * PCM time-domain equalizer | |
3 * | |
4 * Copyright (C) 2002-2005 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 | |
3121
3b6d316f8b09
GPL3 relicensing.
William Pitcock <nenolod@atheme-project.org>
parents:
2520
diff
changeset
|
8 * the Free Software Foundation; either version 3 of the License, or |
2313 | 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 | |
3121
3b6d316f8b09
GPL3 relicensing.
William Pitcock <nenolod@atheme-project.org>
parents:
2520
diff
changeset
|
17 * along with this program. If not, see <http://www.gnu.org/licenses>. |
2313 | 18 * |
19 * $Id: iir_fpu.c,v 1.3 2005/11/13 20:02:58 lisanet Exp $ | |
20 */ | |
21 | |
22 #include <strings.h> | |
23 #include <stdlib.h> | |
24 #include <glib.h> | |
25 #include "iir.h" | |
26 #include "iir_fpu.h" | |
27 | |
28 static sXYData data_history[EQ_MAX_BANDS][EQ_CHANNELS] __attribute__((aligned)); | |
29 static sXYData data_history2[EQ_MAX_BANDS][EQ_CHANNELS] __attribute__((aligned)); | |
30 float gain[EQ_MAX_BANDS][EQ_CHANNELS] __attribute__((aligned)); | |
31 /* random noise */ | |
32 sample_t dither[256]; | |
33 gint di; | |
34 | |
35 void set_gain(gint index, gint chn, float val) | |
36 { | |
37 gain[index][chn] = val; | |
38 } | |
39 | |
40 void clean_history() | |
41 { | |
42 gint n; | |
43 /* Zero the history arrays */ | |
44 bzero(data_history, sizeof(sXYData) * EQ_MAX_BANDS * EQ_CHANNELS); | |
45 bzero(data_history2, sizeof(sXYData) * EQ_MAX_BANDS * EQ_CHANNELS); | |
46 /* this is only needed if we use fpu code and there's no other place for | |
47 the moment to init the dither array*/ | |
48 for (n = 0; n < 256; n++) { | |
49 dither[n] = (rand() % 4) - 2; | |
50 } | |
51 di = 0; | |
52 } | |
53 | |
54 __inline__ int iir(gpointer * d, gint length, gint nch) | |
55 { | |
2520
b210d1ea2084
[svn] ui_main.h:92: warning: comma at end of enumerator list
nenolod
parents:
2313
diff
changeset
|
56 /* FTZ_ON; */ |
2313 | 57 gint16 *data = (gint16 *) * d; |
58 /* Indexes for the history arrays | |
59 * These have to be kept between calls to this function | |
60 * hence they are static */ | |
61 static gint i = 2, j = 1, k = 0; | |
62 | |
63 gint index, band, channel; | |
64 gint tempgint, halflength; | |
65 sample_t out[EQ_CHANNELS], pcm[EQ_CHANNELS]; | |
66 | |
67 #if 0 | |
2520
b210d1ea2084
[svn] ui_main.h:92: warning: comma at end of enumerator list
nenolod
parents:
2313
diff
changeset
|
68 /* Load the correct filter table according to the sampling rate if needed */ |
2313 | 69 if (srate != rate) |
70 { | |
71 band_count = eqcfg.band_num; | |
72 rate = srate; | |
73 iir_cf = get_coeffs(&band_count, rate, eqcfg.use_xmms_original_freqs); | |
74 clean_history(); | |
75 } | |
76 #endif | |
77 | |
78 #ifdef BENCHMARK | |
79 start_counter(); | |
2520
b210d1ea2084
[svn] ui_main.h:92: warning: comma at end of enumerator list
nenolod
parents:
2313
diff
changeset
|
80 #endif /* BENCHMARK */ |
2313 | 81 |
82 /** | |
83 * IIR filter equation is | |
84 * y[n] = 2 * (alpha*(x[n]-x[n-2]) + gamma*y[n-1] - beta*y[n-2]) | |
85 * | |
86 * NOTE: The 2 factor was introduced in the coefficients to save | |
87 * a multiplication | |
88 * | |
89 * This algorithm cascades two filters to get nice filtering | |
90 * at the expense of extra CPU cycles | |
91 */ | |
92 /* 16bit, 2 bytes per sample, so divide by two the length of | |
93 * the buffer (length is in bytes) | |
94 */ | |
95 halflength = (length >> 1); | |
96 for (index = 0; index < halflength; index+=nch) | |
97 { | |
98 /* For each channel */ | |
99 for (channel = 0; channel < nch; channel++) | |
100 { | |
101 pcm[channel] = data[index+channel] * 4; | |
102 /* Preamp gain */ | |
103 pcm[channel] *= (preamp[channel] / 2); | |
104 | |
105 /* add random noise */ | |
106 pcm[channel] += dither[di]; | |
107 | |
108 out[channel] = 0.0; | |
109 /* For each band */ | |
110 for (band = 0; band < band_count; band++) | |
111 { | |
112 /* Store Xi(n) */ | |
113 data_history[band][channel].x[i] = pcm[channel]; | |
114 /* Calculate and store Yi(n) */ | |
115 data_history[band][channel].y[i] = | |
116 ( | |
117 /* = alpha * [x(n)-x(n-2)] */ | |
118 iir_cf[band].alpha * ( data_history[band][channel].x[i] | |
119 - data_history[band][channel].x[k]) | |
120 /* + gamma * y(n-1) */ | |
121 + iir_cf[band].gamma * data_history[band][channel].y[j] | |
122 /* - beta * y(n-2) */ | |
123 - iir_cf[band].beta * data_history[band][channel].y[k] | |
124 ); | |
125 /* | |
126 * The multiplication by 2.0 was 'moved' into the coefficients to save | |
127 * CPU cycles here */ | |
128 /* Apply the gain */ | |
2520
b210d1ea2084
[svn] ui_main.h:92: warning: comma at end of enumerator list
nenolod
parents:
2313
diff
changeset
|
129 out[channel] += data_history[band][channel].y[i]*gain[band][channel]; /* * 2.0; */ |
2313 | 130 } /* For each band */ |
131 | |
132 if (cfg.eq_extra_filtering) | |
133 { | |
134 /* Filter the sample again */ | |
135 for (band = 0; band < band_count; band++) | |
136 { | |
137 /* Store Xi(n) */ | |
138 data_history2[band][channel].x[i] = out[channel]; | |
139 /* Calculate and store Yi(n) */ | |
140 data_history2[band][channel].y[i] = | |
141 ( | |
142 /* y(n) = alpha * [x(n)-x(n-2)] */ | |
143 iir_cf[band].alpha * (data_history2[band][channel].x[i] | |
144 - data_history2[band][channel].x[k]) | |
145 /* + gamma * y(n-1) */ | |
146 + iir_cf[band].gamma * data_history2[band][channel].y[j] | |
147 /* - beta * y(n-2) */ | |
148 - iir_cf[band].beta * data_history2[band][channel].y[k] | |
149 ); | |
150 /* Apply the gain */ | |
151 out[channel] += data_history2[band][channel].y[i]*gain[band][channel]; | |
152 } /* For each band */ | |
153 } | |
154 | |
155 /* Volume stuff | |
156 Scale down original PCM sample and add it to the filters | |
157 output. This substitutes the multiplication by 0.25 | |
158 Go back to use the floating point multiplication before the | |
159 conversion to give more dynamic range | |
160 */ | |
161 out[channel] += pcm[channel]*0.25; | |
162 | |
163 /* remove random noise */ | |
164 out[channel] -= dither[di]*0.25; | |
165 | |
166 /* Round and convert to integer */ | |
167 #ifdef ARCH_PPC | |
168 tempgint = round_ppc(out[channel]); | |
169 #else | |
170 #ifdef ARCH_X86 | |
171 tempgint = round_trick(out[channel]); | |
172 #else | |
173 tempgint = (int)out[channel]; | |
174 #endif | |
175 #endif | |
176 | |
177 /* Limit the output */ | |
178 if (tempgint < -32768) | |
179 data[index+channel] = -32768; | |
180 else if (tempgint > 32767) | |
181 data[index+channel] = 32767; | |
182 else | |
183 data[index+channel] = tempgint; | |
184 } /* For each channel */ | |
185 | |
186 /* Wrap around the indexes */ | |
187 i = (i+1)%3; | |
188 j = (j+1)%3; | |
189 k = (k+1)%3; | |
190 /* random noise index */ | |
191 di = (di + 1) % 256; | |
192 | |
193 }/* For each pair of samples */ | |
194 | |
195 #ifdef BENCHMARK | |
196 timex += get_counter(); | |
197 blength += length; | |
198 if (count++ == 1024) | |
199 { | |
200 printf("FLOATING POINT: %f %d\n",timex/1024.0, blength/1024); | |
201 blength = 0; | |
202 timex = 0.; | |
203 count = 0; | |
204 } | |
2520
b210d1ea2084
[svn] ui_main.h:92: warning: comma at end of enumerator list
nenolod
parents:
2313
diff
changeset
|
205 #endif /* BENCHMARK */ |
2313 | 206 |
2520
b210d1ea2084
[svn] ui_main.h:92: warning: comma at end of enumerator list
nenolod
parents:
2313
diff
changeset
|
207 /* FTZ_OFF; */ |
2313 | 208 return length; |
209 } |