-
Notifications
You must be signed in to change notification settings - Fork 4
/
filter.cs
239 lines (211 loc) · 7.28 KB
/
filter.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
// Implements Power integration filters of different kind
// Special Notes
// Flat - just flat, as the name says ;-)
// Flat10k - Flat, but bandwidth limited to 10kHz
// A - Classic A-Weighting Filter
// A10k - Classic A with reduced bandwidth (to 10kHz)
// B, C - Classic B and C-Weighting filters
// Phone - simple A-Type filter with reduced bandwidth from 300 to 3400 Hz (kind of standard telephone line)
// HDPhone - simpla A-Type filter with reduced bandwidth from 50 to 7000 Hz (kind of HD telephony)
// The formulas for A, B and C-Type filters were taken from http://en.wikipedia.org/wiki/A-weighting
namespace audio_test
{
public enum filter_type
{
Flat,
Flat10k,
A,
A10k,
B,
C,
Phone,
HDPhone
}
class filter
{
public int N;
public double[] f; // Frequency in Hz
public double[] w; // weighting - As Voltage ratio (NOT POWER)
filter_type type;
public filter(int n, double fmax, filter_type ft)
{
N = n;
f = new double[N];
w = new double[N];
type = ft;
for (int i = 0; i < N; i++) f[i] = (double)i * fmax / N;
build_filter();
}
public filter(int n, double fmax)
{
N = n;
f = new double[N];
w = new double[N];
type = filter_type.Flat;
for (int i = 0; i < N; i++) f[i] = (double)i * fmax / N;
build_filter();
}
public static List<String> getList()
{
List<String> L;
L = new List<string>();
L.Add("Flat");
L.Add("Flat10k");
L.Add("A");
L.Add("A10k");
L.Add("B");
L.Add("C");
L.Add("Phone");
L.Add("HDPhone");
return L;
}
public static String getName(filter_type ft)
{
switch (ft)
{
case filter_type.Flat: return "Flat";
case filter_type.Flat10k: return "Flat10k";
case filter_type.A: return "A";
case filter_type.A10k: return "A10k";
case filter_type.B: return "B";
case filter_type.C: return "C";
case filter_type.Phone: return "Phone";
case filter_type.HDPhone: return "HDPhone";
default: return "unknown";
}
}
public static filter_type getID(String s)
{
if (s.Equals("Flat")) return filter_type.Flat;
if (s.Equals("Flat10k")) return filter_type.Flat10k;
if (s.Equals("A")) return filter_type.A;
if (s.Equals("A10k")) return filter_type.A10k;
if (s.Equals("B")) return filter_type.B;
if (s.Equals("C")) return filter_type.C;
if (s.Equals("Phone")) return filter_type.Phone;
if (s.Equals("HDPhone")) return filter_type.HDPhone;
// Default
return filter_type.Flat;
}
public static int getIndex(filter_type ft)
{
return (int)ft;
}
public static int getIndex(String s)
{
return (int)getID(s);
}
public int getIndex() {
return (int)type;
}
public String get_filter_unit(String baseunit)
{
switch (type)
{
default:
case filter_type.Flat:
return baseunit;
case filter_type.Flat10k:
return baseunit + "*";
case filter_type.A:
return baseunit + "(A)";
case filter_type.A10k:
return baseunit + "(A)*";
case filter_type.B:
return baseunit + "(B)";
case filter_type.C:
return baseunit + "(C)";
case filter_type.Phone:
return baseunit + "(P)";
case filter_type.HDPhone:
return baseunit + "(HDP)";
}
}
private double filter_A_dB(double f)
{
if (f <= 0) return -999;
double ra = 12200 * 12200 * f * f * f * f /
((f * f + 20.6 * 20.6) * Math.Sqrt((f * f + 107.7 * 107.7) * (f * f + 737.9 * 737.9)) * (f * f + 12200 * 12200));
return 2.0 + 20 * Math.Log10(ra);
}
private double filter_B_dB(double f)
{
if (f <= 0) return -999;
double rb = 12200 * 12200 * f * f * f /
((f * f + 20.6 * 20.6) * Math.Sqrt(f * f + 158.2 * 158.2) * (f * f + 12200 * 12200));
return 0.17 + 20 * Math.Log10(rb);
}
private double filter_C_dB(double f)
{
if (f <= 0) return -999;
double rc = 12200 * 12200 * f * f /
((f * f + 20.6 * 20.6) * (f * f + 12200 * 12200));
return 0.06 + 20 * Math.Log10(rc);
}
private void build_filter() {
w[0] = 0.0; // DC component alway zero
switch (type)
{
default:
case filter_type.Flat:
for (int i = 1; i < N; i++)
w[i] = 1.0;
break;
case filter_type.Flat10k:
for (int i = 1; i < N; i++)
{
if (f[i] <= 10000) w[i] = 1.0; else w[i] = 0.0;
}
break;
case filter_type.A:
for (int i = 1; i < N; i++)
{
w[i] = Math.Pow(10, filter_A_dB(f[i]) / 20);
}
break;
case filter_type.A10k:
for (int i = 1; i < N; i++)
{
if (f[i] <= 10000)
w[i] = Math.Pow(10, filter_A_dB(f[i]) / 20);
else
w[i] = 0.0;
}
break;
case filter_type.B:
for (int i = 1; i < N; i++)
{
w[i] = Math.Pow(10, filter_B_dB(f[i]) / 20);
}
break;
case filter_type.C:
for (int i = 1; i < N; i++)
{
w[i] = Math.Pow(10, filter_C_dB(f[i]) / 20);
}
break;
case filter_type.Phone:
for (int i = 1; i < N; i++)
{
if ((f[i] >= 300) && (f[i] <= 3400)) w[i] = Math.Pow(10, filter_A_dB(f[i]) / 20); else w[i] = 0.0;
}
break;
case filter_type.HDPhone:
for (int i = 1; i < N; i++)
{
if ((f[i] >= 50) && (f[i] <= 7000)) w[i] = Math.Pow(10, filter_A_dB(f[i]) / 20); else w[i] = 0.0;
}
break;
}
}
public void update_to(filter_type ft)
{
type = ft;
build_filter();
}
}
}