Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /trunk/slmml/Filter.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 37 - (hide annotations) (download)
Sun Mar 29 15:10:03 2009 UTC (15 years ago) by hikarin
File size: 6602 byte(s)
[ocmml/slmml] * imported SlMML
1 hikarin 37 using System;
2    
3     namespace SlMML
4     {
5     public enum FilterType
6     {
7     LPFFast = 2,
8     LPFQuality = 1,
9     None = 0,
10     HPFQuality = -1,
11     HPFFast = -2
12     };
13    
14     public class Filter
15     {
16     #region 公開メソッドの定義
17     public void Reset()
18     {
19     m_t1 = 0;
20     m_t2 = 0;
21     m_b0 = 0;
22     m_b1 = 0;
23     m_b2 = 0;
24     m_b3 = 0;
25     m_b4 = 0;
26     }
27    
28     public void GetSample(ref double[] samples, int start, int end)
29     {
30     double cut = 0, k = GetKeyValue(Key), fb = 0;
31     switch (Switch)
32     {
33     case FilterType.HPFFast:
34     for (int i = start; i < end; i++)
35     {
36     double input = 0;
37     cut = Channel.FrequencyFromIndex((int)(Frequency + Amount * Envelope.NextAmplitudeLinear)) * k;
38     UpdateValueForFast(ref cut, out input, samples[i]);
39     samples[i] = input - m_b4;
40     }
41     break;
42     case FilterType.HPFQuality:
43     fb = 0;
44     if (Amount > 0.0001 || Amount < -0.0001)
45     {
46     for (int i = start; i < end; i++)
47     {
48     cut = Channel.FrequencyFromIndex((int)(Frequency + Amount * Envelope.NextAmplitudeLinear)) * k;
49     UpdateCutAndFb(ref cut, ref fb);
50     UpdateSamplesForHPF1(ref samples, i, cut, fb);
51     }
52     }
53     else
54     {
55     cut = Channel.FrequencyFromIndex((int)(Frequency)) * k;
56     UpdateCutAndFb(ref cut, ref fb);
57     for (int i = start; i < end; i++)
58     UpdateSamplesForHPF1(ref samples, i, cut, fb);
59     }
60     break;
61     case FilterType.LPFQuality:
62     fb = 0;
63     if (Amount > 0.0001 || Amount < -0.0001)
64     {
65     for (int i = start; i < end; i++)
66     {
67     cut = Channel.FrequencyFromIndex((int)(Frequency + Amount * Envelope.NextAmplitudeLinear)) * k;
68     UpdateCutAndFb(ref cut, ref fb);
69     UpdateSamplesForLPF1(ref samples, i, cut, fb);
70     }
71     }
72     else
73     {
74     cut = Channel.FrequencyFromIndex((int)(Frequency)) * k;
75     UpdateCutAndFb(ref cut, ref fb);
76     for (int i = start; i < end; i++)
77     UpdateSamplesForLPF1(ref samples, i, cut, fb);
78     }
79     break;
80     case FilterType.LPFFast:
81     for (int i = start; i < end; i++)
82     {
83     double input = 0;
84     cut = Channel.FrequencyFromIndex((int)(Frequency + Amount * Envelope.NextAmplitudeLinear)) * k;
85     UpdateValueForFast(ref cut, out input, samples[i]);
86     samples[i] = m_b4;
87     }
88     break;
89     }
90     }
91     #endregion
92    
93     #region 非公開メソッドの定義
94     private void UpdateCutValue(ref double cut)
95     {
96     if (cut < 1.0 / 127.0)
97     cut = 0;
98     cut = Math.Min(cut, 1.0 - 0.0001);
99     }
100    
101     private void UpdateCutAndFb(ref double cut, ref double fb)
102     {
103     UpdateCutValue(ref cut);
104     fb = Resonance + Resonance / (1.0 - cut);
105     }
106    
107     private double GetKeyValue(double key)
108     {
109     return key * (2.0 * Math.PI / (Sample.RATE * Sample.FREQUENCY_BASE));
110     }
111    
112     private void UpdateSamplesForHPF1(ref double[] samples, int index, double cut, double fb)
113     {
114     double input = samples[index];
115     m_b0 = m_b0 + cut * (input - m_b0 + fb * (m_b0 - m_b1));
116     m_b1 = m_b1 + cut * (m_b0 - m_b1);
117     samples[index] = input - m_b0;
118     }
119    
120     private void UpdateSamplesForLPF1(ref double[] samples, int index, double cut, double fb)
121     {
122     m_b0 = m_b0 + cut * (samples[index] - m_b0 + fb * (m_b0 - m_b1));
123     samples[index] = m_b1 = m_b1 + cut * (m_b0 - m_b1);
124     }
125    
126     private void UpdateValueForFast(ref double cut, out double input, double sample)
127     {
128     UpdateCutValue(ref cut);
129     double q = 1.0 - cut;
130     double p = cut + 0.8 * cut * q;
131     double f = p + p - 1.0;
132     q = Resonance * (1.0 + 0.5 * q * (1.0 - q + 5.6 * q * q));
133     input = sample;
134     input -= q * m_b4;
135     m_t1 = m_b1;
136     m_b1 = (input + m_b0) * p - m_b1 * f;
137     m_t2 = m_b2;
138     m_b2 = (m_b1 + m_t1) * p - m_b2 * f;
139     m_t1 = m_b3;
140     m_b3 = (m_b2 + m_t2) * p - m_b3 * f;
141     m_b4 = (m_b3 + m_t1) * p - m_b4 * f;
142     m_b4 = m_b4 - m_b4 * m_b4 * m_b4 * 0.16667;
143     m_b0 = input;
144     }
145     #endregion
146    
147     #region 公開プロパティの定義
148     public FilterType Switch
149     {
150     private get
151     {
152     return m_type;
153     }
154     set
155     {
156     Reset();
157     m_type = value;
158     }
159     }
160    
161     public Envelope Envelope
162     {
163     private get;
164     set;
165     }
166    
167     public double Frequency
168     {
169     private get;
170     set;
171     }
172    
173     public double Amount
174     {
175     private get;
176     set;
177     }
178    
179     public double Resonance
180     {
181     private get;
182     set;
183     }
184    
185     public double Key
186     {
187     private get;
188     set;
189     }
190     #endregion
191    
192     #region メンバー変数の定義
193     private FilterType m_type;
194     private double m_t1;
195     private double m_t2;
196     private double m_b0;
197     private double m_b1;
198     private double m_b2;
199     private double m_b3;
200     private double m_b4;
201     #endregion
202     }
203     }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26