Mercurial > audlegacy
annotate src/audacious/iir_fpu.c @ 3395:df609e7e7bcf
updated romanian translation
| author | Cristi Magherusan <majeru@atheme-project.org> |
|---|---|
| date | Sun, 26 Aug 2007 03:06:40 +0300 |
| parents | 3b6d316f8b09 |
| 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 } |
