OSDN Git Service

Merge branch 'master' of git.sourceforge.jp:/gitroot/karinto/karinto
[karinto/karinto.git] / Karinto / WindowFunction.cs
1 /*\r
2  *      Karinto Library Project\r
3  *\r
4  *      This software is distributed under a zlib-style license.\r
5  *      See license.txt for more information.\r
6  */\r
7 \r
8 using System;\r
9 using System.Collections.Generic;\r
10 using System.Text;\r
11 \r
12 namespace Karinto\r
13 {\r
14     public class WindowFunction\r
15     {\r
16         #region type definitions\r
17 \r
18         public enum FunctionType\r
19         {\r
20             UserDefined = -1,\r
21             Unknown = 0,\r
22             BartlettHann,\r
23             Blackman,\r
24             BlackmanNuttall,\r
25             FlatTop,\r
26             Gaussian,\r
27             Hamming,\r
28             Hann,\r
29             Kaiser,\r
30             Lanczos,\r
31             Nuttall,\r
32             Rectangular,\r
33             Triangular,\r
34         }\r
35         public delegate double Function(double x);\r
36 \r
37         #endregion\r
38 \r
39         #region private or protected fields\r
40 \r
41         private static Function[] library;\r
42         private Function function;\r
43         private double parameter;\r
44         private double powerCorrectionFactor;\r
45         private double amplitudeCorrectionFactor;\r
46 \r
47         #endregion\r
48 \r
49         #region constructors\r
50 \r
51         static WindowFunction()\r
52         {\r
53             library = new Function[]{\r
54                 null/*Unknown*/,\r
55                 BartlettHann,\r
56                 Blackman,\r
57                 BlackmanNuttall,\r
58                 FlatTop,\r
59                 null/*Gaussian*/,\r
60                 Hamming,\r
61                 Hann,\r
62                 null/*Kaiser*/,\r
63                 null/*Lanczos*/,\r
64                 Nuttall,\r
65                 Rectangular,\r
66                 Triangular,\r
67             };\r
68         }\r
69 \r
70         public WindowFunction(FunctionType type)\r
71             : this(type, null)\r
72         {\r
73         }\r
74 \r
75         public WindowFunction(FunctionType type, Range range)\r
76             : this(type, 0.0, range)\r
77         {\r
78             switch (type)\r
79             {\r
80                 case FunctionType.Gaussian:\r
81                     parameter = 0.4;\r
82                     break;\r
83                 case FunctionType.Kaiser:\r
84                     parameter = 2.0;\r
85                     break;\r
86                 case FunctionType.Lanczos:\r
87                     parameter = 1.0;\r
88                     break;\r
89                 default:\r
90                     break;\r
91             }\r
92         }\r
93 \r
94         public WindowFunction(FunctionType type, double parameter)\r
95             : this(type, parameter, null)\r
96         {\r
97         }\r
98 \r
99         public WindowFunction(FunctionType type, double parameter, Range range)\r
100         {\r
101             Type = type;\r
102             Range = range;\r
103             this.parameter = parameter;\r
104             switch (type)\r
105             {\r
106                 case FunctionType.UserDefined:\r
107                     Window = null;\r
108                     break;\r
109                 case FunctionType.Gaussian:\r
110                     Window = Gaussian;\r
111                     break;\r
112                 case FunctionType.Kaiser:\r
113                     Window = Kaiser;\r
114                     break;\r
115                 case FunctionType.Lanczos:\r
116                     Window = Lanczos;\r
117                     break;\r
118                 default:\r
119                     Window = library[(int)type];\r
120                     break;\r
121             }\r
122         }\r
123 \r
124         public WindowFunction(Function function)\r
125             : this(function, null)\r
126         {\r
127         }\r
128 \r
129         public WindowFunction(Function function, Range range)\r
130             : this(FunctionType.UserDefined, range)\r
131         {\r
132             Window = function;\r
133         }\r
134 \r
135         #endregion\r
136 \r
137         #region properties\r
138 \r
139         public FunctionType Type\r
140         {\r
141             get;\r
142             private set;\r
143         }\r
144 \r
145         public Range Range\r
146         {\r
147             get;\r
148             set;\r
149         }\r
150 \r
151         public Function Window\r
152         {\r
153             get\r
154             {\r
155                 return function;\r
156             }\r
157             private set\r
158             {\r
159                 function = value;\r
160                 if (function != null)\r
161                 {\r
162                     powerCorrectionFactor = CalculatePowerCorrectionFactor();\r
163                     amplitudeCorrectionFactor = CalculateAmplitudeCorrectionFactor();\r
164                 }\r
165             }\r
166         }\r
167 \r
168         public double PowerCorrectionFactor\r
169         {\r
170             get\r
171             {\r
172                 if (powerCorrectionFactor > 0.0)\r
173                 {\r
174                     return powerCorrectionFactor;\r
175                 }\r
176                 return CalculatePowerCorrectionFactor();\r
177             }\r
178         }\r
179 \r
180         public double AmplitudeCorrectionFactor\r
181         {\r
182             get\r
183             {\r
184                 if (amplitudeCorrectionFactor > 0.0)\r
185                 {\r
186                     return amplitudeCorrectionFactor;\r
187                 }\r
188                 return CalculateAmplitudeCorrectionFactor();\r
189             }\r
190         }\r
191 \r
192         #endregion\r
193 \r
194         #region public methods\r
195 \r
196         public double[] ApplyTo(double[] target)\r
197         {\r
198             if (!(Range.First is int)) throw new Exception();\r
199 \r
200             int n = (int)Range.Last - (int)Range.First;\r
201             double[] series = new double[n + (Range.ExcludesEnd ? 0 : 1)];\r
202 \r
203             double scale = 1.0 / n;\r
204             int i = 0;\r
205             foreach (int x in Range)\r
206             {\r
207                 series[i] = target[x] * function(scale * i);\r
208                 i++;\r
209             }\r
210             return series;\r
211         }\r
212 \r
213         #endregion\r
214 \r
215         #region private methods\r
216 \r
217         private double CalculatePowerCorrectionFactor()\r
218         {\r
219             if (Range == null) return 0.0;\r
220             if (!(Range.First is int)) throw new Exception();\r
221 \r
222             int n = (int)Range.Last - (int)Range.First;\r
223             int width = n + (Range.ExcludesEnd ? 0 : 1);\r
224 \r
225             double scale = 1.0 / n;\r
226             double pcf = 0.0;\r
227             for (int i = 0; i < width; ++i)\r
228             {\r
229                 double f = function(scale * i);\r
230                 pcf += f * f;\r
231             }\r
232             return pcf / width;\r
233         }\r
234 \r
235         private double CalculateAmplitudeCorrectionFactor()\r
236         {\r
237             if (Range == null) return 0.0;\r
238             if (!(Range.First is int)) throw new Exception();\r
239 \r
240             int n = (int)Range.Last - (int)Range.First;\r
241             int width = n + (Range.ExcludesEnd ? 0 : 1);\r
242 \r
243             double scale = 1.0 / n;\r
244             double acf = 0.0;\r
245             for (int i = 0; i < width; ++i)\r
246             {\r
247                 acf += function(scale * i);\r
248             }\r
249             return acf / width;\r
250         }\r
251 \r
252         private static double BartlettHann(double x)\r
253         {\r
254             throw new NotImplementedException();\r
255         }\r
256 \r
257         private static double Blackman(double x)\r
258         {\r
259             throw new NotImplementedException();\r
260         }\r
261 \r
262         private static double BlackmanNuttall(double x)\r
263         {\r
264             throw new NotImplementedException();\r
265         }\r
266 \r
267         private static double FlatTop(double x)\r
268         {\r
269             const double a0 = 1.0;\r
270             const double a1 = 1.93;\r
271             const double a2 = 1.29;\r
272             const double a3 = 0.388;\r
273             const double a4 = 0.032;\r
274             double theta = 2.0 * Math.PI * x;\r
275             return a0 - a1 * Cos2Pi(x) + a2 * Cos2Pi(x + x) -\r
276                                 a3 * Cos2Pi(3.0 * x) + a4 * Cos2Pi(4.0 * x);\r
277         }\r
278 \r
279         private double Gaussian(double x)\r
280         {\r
281             double r = (x - 0.5) / parameter;\r
282             return Math.Exp(-r * r);\r
283         }\r
284 \r
285         private static double Hamming(double x)\r
286         {\r
287             return 0.54 - 0.46 * Cos2Pi(x);\r
288         }\r
289 \r
290         private static double Hann(double x)\r
291         {\r
292             return 0.5 - 0.5 * Cos2Pi(x);\r
293         }\r
294 \r
295         private double Kaiser(double x)\r
296         {\r
297             throw new NotImplementedException();\r
298         }\r
299 \r
300         private double Lanczos(double x)\r
301         {\r
302             throw new NotImplementedException();\r
303         }\r
304 \r
305         private static double Nuttall(double x)\r
306         {\r
307             throw new NotImplementedException();\r
308         }\r
309 \r
310         private static double Rectangular(double x)\r
311         {\r
312             return 1.0;\r
313         }\r
314 \r
315         private static double Triangular(double x)\r
316         {\r
317             return (x < 0.5) ? x + x : 2.0 - x - x;\r
318         }\r
319 \r
320         private static double Cos2Pi(double x)\r
321         {\r
322             return Math.Cos(2.0 * Math.PI * x);\r
323         }\r
324 \r
325         #endregion\r
326     }\r
327 }\r