3
TiMidity -- Experimental MIDI to WAVE converter
4
Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
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.
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.
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.
20
filter.c: written by Vincent Pagel ( pagel@loria.fr )
22
implements fir antialiasing filter : should help when setting sample
29
- modify "filter" so that it simulate leading and trailing 0 in the buffer
43
static float ino(float x)
53
de = de * y / (float) i;
56
} while (!( (e * 1.0e-08 - sde > 0) || (i++ > 25) ));
60
/* Kaiser Window (symetric) */
61
static void kaiser(float *w,int n,float beta)
66
xind = (2*n - 1) * (2*n - 1);
70
w[i] = ino((float)(beta * sqrt((double)(1. - 4 * xi * xi / xind))))
76
* fir coef in g, cuttoff frequency in fc
78
static void designfir(float *g , float fc)
81
float xi, omega, att, beta ;
84
for (i =0; i < ORDER2 ;i++)
88
g[i] = sin( (double) omega * fc) / omega;
91
att = 40.; /* attenuation in db */
92
beta = (float) exp(log((double)0.58417 * (att - 20.96)) * 0.4) + 0.07886
94
kaiser( w, ORDER2, beta);
97
for (i =0; i < ORDER2 ; i++)
102
* FIR filtering -> apply the filter given by coef[] to the data buffer
103
* Note that we simulate leading and trailing 0 at the border of the
106
static void filter(sample_t *result,sample_t *data, int32 length,float coef[])
108
int32 sample,i,sample_window;
112
/* Simulate leading 0 at the begining of the buffer */
113
for (sample = 0; sample < ORDER2 ; sample++ )
116
sample_window= sample - ORDER2;
118
for (i = 0; i < ORDER ;i++)
120
((sample_window<0)? 0.0 : data[sample_window++]) ;
123
if (sum> 32767.) { sum=32767.; peak++; }
124
if (sum< -32768.) { sum=-32768; peak++; }
125
result[sample] = (sample_t) sum;
128
/* The core of the buffer */
129
for (sample = ORDER2; sample < length - ORDER + ORDER2 ; sample++ )
132
sample_window= sample - ORDER2;
134
for (i = 0; i < ORDER ;i++)
135
sum += data[sample_window++] * coef[i];
138
if (sum> 32767.) { sum=32767.; peak++; }
139
if (sum< -32768.) { sum=-32768; peak++; }
140
result[sample] = (sample_t) sum;
143
/* Simulate 0 at the end of the buffer */
144
for (sample = length - ORDER + ORDER2; sample < length ; sample++ )
147
sample_window= sample - ORDER2;
149
for (i = 0; i < ORDER ;i++)
151
((sample_window>=length)? 0.0 : data[sample_window++]) ;
154
if (sum> 32767.) { sum=32767.; peak++; }
155
if (sum< -32768.) { sum=-32768; peak++; }
156
result[sample] = (sample_t) sum;
160
ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
161
"Saturation %2.3f %%.", 100.0*peak/ (float) length);
164
/***********************************************************************/
165
/* Prevent aliasing by filtering any freq above the output_rate */
167
/* I don't worry about looping point -> they will remain soft if they */
169
/***********************************************************************/
170
void antialiasing(Sample *sp, uint32 output_rate )
174
float fir_symetric[ORDER];
175
float fir_coef[ORDER2];
176
float freq_cut; /* cutoff frequency [0..1.0] FREQ_CUT/SAMP_FREQ*/
179
ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Antialiasing: Fsample=%iKHz",
182
/* No oversampling */
183
if (output_rate>=sp->sample_rate)
186
freq_cut= (float) output_rate / (float) sp->sample_rate;
187
ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Antialiasing: cutoff=%f%%",
190
designfir(fir_coef,freq_cut);
192
/* Make the filter symetric */
193
for (i = 0 ; i<ORDER2 ;i++)
194
fir_symetric[ORDER-1 - i] = fir_symetric[i] = fir_coef[ORDER2-1 - i];
196
/* We apply the filter we have designed on a copy of the patch */
197
temp = (sample_t *) safe_malloc(sp->data_length);
198
memcpy(temp,sp->data,sp->data_length);
200
filter(sp->data,temp,sp->data_length/sizeof(sample_t),fir_symetric);