Mercurial > hg > x
comparison windowfunctions.cpp @ 2:fc19d45615d1
* Make all file names lower-case to avoid case ambiguity
(some includes differed in case from the filenames they were
trying to include). Also replace MinGW-specific mem.h with
string.h
author | Chris Cannam |
---|---|
date | Tue, 05 Oct 2010 11:04:40 +0100 |
parents | WindowFunctions.cpp@6422640a802f |
children | 5f3c32dc6e17 |
comparison
equal
deleted
inserted
replaced
1:6422640a802f | 2:fc19d45615d1 |
---|---|
1 //--------------------------------------------------------------------------- | |
2 #include <math.h> | |
3 #include <string.h> | |
4 #include "windowfunctions.h" | |
5 #include "align8.h" | |
6 //--------------------------------------------------------------------------- | |
7 | |
8 /* | |
9 function I0: Bessel function of order zero | |
10 | |
11 Returns the Bessel function of x. | |
12 */ | |
13 double I0(double x) | |
14 { | |
15 const double eps=1e-9; | |
16 | |
17 int n=1; | |
18 double S=1, D=1, T; | |
19 | |
20 while (D>eps*S) | |
21 { | |
22 T=x/(2*n++); | |
23 D*=T*T; | |
24 S+=D; | |
25 } | |
26 return S; | |
27 }//I0 | |
28 | |
29 /* | |
30 function FillWindow: fills a buffer $Result with a window function. | |
31 | |
32 In: wt:window type | |
33 Count: window size | |
34 ips & ups: extra window specificatin parameters | |
35 Out: newwindow[Count+1]: the window function. | |
36 | |
37 No return value. This function is designed assuming Count being even, and Count/2 is the symmetry | |
38 centre of newwindow. newwindow has physical size Count+1 for compatibility purpose. For all vanishing | |
39 windows (e.g. Hann) newwindow[0]=newwindow[Count]=0. | |
40 */ | |
41 void FillWindow(double* Result, WindowType wt, int Count, int* ips, double* dps) | |
42 { | |
43 switch(wt) | |
44 { | |
45 case wtRectangle: | |
46 for (int i=0; i<=Count; i++) | |
47 Result[i]=1; | |
48 break; | |
49 case wtTriangular: | |
50 for (int i=0; i<=Count; i++) | |
51 Result[i]=1-2*fabs(i-Count/2.0)/Count; | |
52 break; | |
53 case wtHamming: | |
54 for (int i=0; i<=Count; i++) | |
55 Result[i]=(0.54-0.46*cos(2*M_PI*i/Count)); | |
56 break; | |
57 case wtBlackman: | |
58 for (int i=0; i<=Count; i++) | |
59 Result[i]=0.42-0.5*cos(2*M_PI*i/Count)+0.08*cos(4*M_PI*i/Count); | |
60 break; | |
61 case wtGaussian: | |
62 { | |
63 double num=*dps*M_PI*M_PI/2/Count/Count; | |
64 for (int i=0; i<=Count; i++) | |
65 Result[i]=exp(-(i-Count/2.0)*(i-Count/2.0)*num); | |
66 break; | |
67 } | |
68 case wtKaiser: | |
69 { | |
70 double ldps=*dps*M_PI*M_PI/2/Count; | |
71 double den=I0(0.5*Count*ldps); | |
72 for (int i=0; i<=Count; i++) | |
73 Result[i]=I0(ldps*sqrt(0.25*Count*Count-(i-Count*0.5)*(i-Count*0.5)))/den; | |
74 break; | |
75 } | |
76 case wtHalfCosine: | |
77 { | |
78 for (int i=0; i<=Count; i++) | |
79 Result[i]=sin(M_PI*i/Count); | |
80 break; | |
81 } | |
82 case wtHann: | |
83 { | |
84 for (int i=0; i<=Count; i++) | |
85 Result[i]=(0.5-cos(M_PI*2*i/Count)/2); | |
86 break; | |
87 } | |
88 case wtHannSqr: | |
89 { | |
90 for (int i=0; i<=Count; i++) | |
91 Result[i]=(3-4*cos(M_PI*2*i/Count)+cos(M_PI*4*i/Count))/8; | |
92 break; | |
93 } | |
94 case wtHann3sqrt: | |
95 { | |
96 for (int i=0; i<=Count; i++) | |
97 { | |
98 double tmp=sin(M_PI*i/Count); | |
99 Result[i]=tmp*tmp*tmp; | |
100 } | |
101 break; | |
102 } | |
103 } | |
104 }//FillWindow | |
105 | |
106 /* | |
107 function NewWindow: creates a window function. | |
108 | |
109 In: wt: window type | |
110 Count: window size | |
111 ips & ups: extra window specificatin parameters | |
112 Out: newwindow[Count+1]: the window function. | |
113 | |
114 Returns pointer to newwindow. newwindow is created anew if newwindow=0 is specified on start. | |
115 */ | |
116 double* NewWindow(WindowType wt, int Count, int* ips, double* dps, double* newwindow) | |
117 { | |
118 double* Result=newwindow; if (!Result) Result=new double[Count+1]; | |
119 FillWindow(Result, wt, Count, ips, dps); | |
120 return Result; | |
121 }//NewWindow | |
122 | |
123 /* | |
124 function NewWindow8: 8-byte aligned version of NewWindow. | |
125 | |
126 In: wt: window type | |
127 Count: window size | |
128 ips & ups: extra window specificatin parameters | |
129 Out: newwindow[Count+1]: the window function. | |
130 | |
131 Returns pointer to newwindow. newwindow is created anew and 8-byte aligned if newwindow=0 is | |
132 specified on start. However, if newwindow is not 8-byte aligned on start, the unaligned buffer is | |
133 returned. | |
134 */ | |
135 double* NewWindow8(WindowType wt, int Count, int* ips, double* dps, double* newwindow) | |
136 { | |
137 double* Result=newwindow; if (!Result) Result=(double*)malloc8(sizeof(double)*(Count+1)); | |
138 FillWindow(Result, wt, Count, ips, dps); | |
139 return Result; | |
140 }//NewWindow8 | |
141 | |
142 /* | |
143 function NewdWindow: computes the derivative of a window function. | |
144 | |
145 In: wt: window type | |
146 Count: window size | |
147 ips & ups: extra window specificatin parameters | |
148 Out: newdwindow[Count+1]: the derivative window function. | |
149 | |
150 Returns pointer to newdwindow. newdwindow is created anew if newdwindow=0 is specified on start. | |
151 */ | |
152 double* NewdWindow(WindowType wt, int Count, int* ips, double* dps, double* newdwindow) | |
153 { | |
154 double* Result=newdwindow; if (!Result) Result=new double[Count+1]; | |
155 double piiCount=M_PI/Count; | |
156 switch(wt) | |
157 { | |
158 case wtRectangle: | |
159 memset(Result, 0, sizeof(double)*(Count+1)); | |
160 break; | |
161 case wtTriangular: | |
162 throw("Trying to differentiate triangular window."); | |
163 break; | |
164 case wtHamming: | |
165 for (int i=0; i<=Count; i++) | |
166 Result[i]=0.92*piiCount*sin(2*piiCount*i); | |
167 break; | |
168 case wtBlackman: | |
169 for (int i=0; i<=Count; i++) | |
170 Result[i]=piiCount*sin(2*piiCount*i)-0.32*piiCount*sin(4*piiCount*i); | |
171 break; | |
172 case wtGaussian: | |
173 throw("Trying to differentiate Gaussian window."); | |
174 break; | |
175 case wtKaiser: | |
176 throw("Trying to differentiate Kaiser window."); | |
177 break; | |
178 case wtHalfCosine: | |
179 { | |
180 for (int i=0; i<=Count; i++) | |
181 Result[i]=piiCount*cos(piiCount*i); | |
182 break; | |
183 } | |
184 case wtHann: | |
185 { | |
186 for (int i=0; i<=Count; i++) | |
187 Result[i]=piiCount*sin(2*piiCount*i); | |
188 break; | |
189 } | |
190 case wtHannSqr: | |
191 { | |
192 for (int i=0; i<=Count; i++) | |
193 Result[i]=piiCount*sin(2*piiCount*i)-0.5*piiCount*sin(4*piiCount*i); | |
194 break; | |
195 } | |
196 case wtHann3sqrt: | |
197 { | |
198 for (int i=0; i<=Count; i++) | |
199 { | |
200 double s=sin(M_PI*i/Count), c=cos(M_PI*i/Count); | |
201 Result[i]=3*piiCount*s*s*c; | |
202 } | |
203 } | |
204 } | |
205 return Result; | |
206 }//NewdWindow | |
207 | |
208 /* | |
209 function NewddWindow: computes the 2nd-order derivative of a window function. | |
210 | |
211 In: wt: window type | |
212 Count: window size | |
213 ips & ups: extra window specificatin parameters | |
214 Out: newddwindow[Count+1]: the 2nd-order derivative window function. | |
215 | |
216 Returns pointer to newddwindow. newddwindow is created anew if newddwindow=0 is specified on start. | |
217 */ | |
218 double* NewddWindow(WindowType wt, int Count, int* ips, double* dps, double* newddwindow) | |
219 { | |
220 double* Result=newddwindow; if (!Result) Result=new double[Count+1]; | |
221 double piiCount=M_PI/Count; | |
222 double piC2=piiCount*piiCount; | |
223 switch(wt) | |
224 { | |
225 case wtRectangle: | |
226 memset(Result, 0, sizeof(double)*(Count+1)); | |
227 break; | |
228 case wtTriangular: | |
229 throw("Trying to double-differentiate triangular window."); | |
230 break; | |
231 case wtHamming: | |
232 for (int i=0; i<=Count; i++) | |
233 Result[i]=1.84*piC2*cos(2*piiCount*i); | |
234 break; | |
235 case wtBlackman: | |
236 for (int i=0; i<=Count; i++) | |
237 Result[i]=2*piC2*cos(2*piiCount*i)-1.28*piC2*cos(4*piiCount*i); | |
238 break; | |
239 case wtGaussian: | |
240 throw("Trying to double-differentiate Gaussian window."); | |
241 break; | |
242 case wtKaiser: | |
243 throw("Trying to double-differentiate Kaiser window."); | |
244 break; | |
245 case wtHalfCosine: | |
246 { | |
247 for (int i=0; i<=Count; i++) | |
248 Result[i]=-piC2*sin(piiCount*i); | |
249 break; | |
250 } | |
251 case wtHann: | |
252 { | |
253 for (int i=0; i<=Count; i++) | |
254 Result[i]=2*piC2*cos(2*piiCount*i); | |
255 break; | |
256 } | |
257 case wtHannSqr: | |
258 { | |
259 for (int i=0; i<=Count; i++) | |
260 Result[i]=2*piC2*cos(2*piiCount*i)-2*piC2*cos(4*piiCount*i); | |
261 break; | |
262 } | |
263 case wtHann3sqrt: | |
264 { | |
265 for (int i=0; i<=Count; i++) | |
266 { | |
267 double s=sin(M_PI*i/Count), c=cos(M_PI*i/Count); | |
268 Result[i]=3*piC2*(2*c*c-s*s)*s; | |
269 } | |
270 break; | |
271 } | |
272 } | |
273 return Result; | |
274 }//NewddWindow | |
275 | |
276 /* | |
277 function NewdddWindow: computes the 3rd-order derivative of a window function. | |
278 In: wt: window type | |
279 Count: window size | |
280 ips & ups: extra window specificatin parameters | |
281 Out: newdddwindow[Count+1]: the 3rd-order derivative window function. | |
282 | |
283 Returns pointer to newdddwindow. newdddwindow is created anew if newdddwindow=0 is specified on start. | |
284 */ | |
285 double* NewdddWindow(WindowType wt, int Count, int* ips, double* dps, double* newdddwindow) | |
286 { | |
287 double* Result=newdddwindow; if (!Result) Result=new double[Count+1]; | |
288 double piiCount=M_PI/Count; | |
289 double piC2=piiCount*piiCount; | |
290 double piC3=piiCount*piC2; | |
291 switch(wt) | |
292 { | |
293 case wtRectangle: | |
294 memset(Result, 0, sizeof(double)*(Count+1)); | |
295 break; | |
296 case wtTriangular: | |
297 throw("Trying to triple-differentiate triangular window."); | |
298 break; | |
299 case wtHamming: | |
300 for (int i=0; i<=Count; i++) | |
301 Result[i]=-3.68*piC3*sin(2*piiCount*i); | |
302 break; | |
303 case wtBlackman: | |
304 for (int i=0; i<=Count; i++) | |
305 Result[i]=-4*piC3*sin(2*piiCount*i)+5.12*piC3*sin(4*piiCount*i); | |
306 break; | |
307 case wtGaussian: | |
308 throw("Trying to triple-differentiate Gaussian window."); | |
309 break; | |
310 case wtKaiser: | |
311 throw("Trying to triple-differentiate Kaiser window."); | |
312 break; | |
313 case wtHalfCosine: | |
314 { | |
315 for (int i=0; i<=Count; i++) | |
316 Result[i]=-piC3*cos(piiCount*i); | |
317 break; | |
318 } | |
319 case wtHann: | |
320 { | |
321 for (int i=0; i<=Count; i++) | |
322 Result[i]=-4*piC3*sin(2*piiCount*i); | |
323 break; | |
324 } | |
325 case wtHannSqr: | |
326 { | |
327 for (int i=0; i<=Count; i++) | |
328 Result[i]=-4*piC3*sin(2*piiCount*i)+8*piC3*sin(4*piiCount*i); | |
329 break; | |
330 } | |
331 case wtHann3sqrt: | |
332 throw("Trying to triple-differentiate Hann^1.5 window."); | |
333 break; | |
334 } | |
335 return Result; | |
336 }//NewdddWindow | |
337 | |
338 //--------------------------------------------------------------------------- | |
339 /* | |
340 function windowspec: computes a few descriptors of a cosine family window. A window function in the | |
341 cosine window family is the linear combination of a few cosine functions, therefore has a cosine | |
342 decomposition. | |
343 | |
344 In: wt: window type | |
345 N: window size | |
346 Out: c[M+1], coefficients of cosine decomposition | |
347 iH2: reciprocal of square of L2 norm, | |
348 d[2M+1]: self-convolution of c[], optional | |
349 | |
350 No return value. | |
351 */ | |
352 void windowspec(WindowType wt, int N, int* M, double* c, double* iH2, double* d) | |
353 { | |
354 switch(wt) | |
355 { | |
356 case wtRectangle: | |
357 M[0]=0, c[0]=1, iH2[0]=1.0/N/N; | |
358 if (d) d[0]=1; | |
359 break; | |
360 case wtHamming: | |
361 M[0]=1, c[0]=0.54, c[1]=0.23, iH2[0]=1.0/(0.3974*N*N); | |
362 if (d) d[0]=0.3974, d[1]=0.2484, d[2]=0.0529; | |
363 break; | |
364 case wtBlackman: | |
365 M[0]=2, c[0]=0.42, c[1]=0.25, c[2]=0.04, iH2[0]=1.0/(0.3046*N*N); | |
366 if (d) d[0]=0.3046, d[1]=0.23, d[2]=0.0961, d[4]=0.02, d[5]=0.0016; | |
367 break; | |
368 case wtHann: | |
369 M[0]=1, c[0]=0.5, c[1]=0.25, iH2[0]=1.0/(0.375*N*N); | |
370 if (d) d[0]=0.375, d[1]=0.25, d[2]=0.0625; | |
371 break; | |
372 default: | |
373 M[0]=1, c[0]=0.5, c[1]=0.25, iH2[0]=1.0/(0.375*N*N); | |
374 if (d) d[0]=0.375, d[1]=0.25, d[2]=0.0625; | |
375 break; | |
376 } | |
377 }//windowspec |