Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/slmml/Envelope.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 58 - (show annotations) (download)
Sat Apr 4 12:56:58 2009 UTC (14 years, 11 months ago) by hikarin
File size: 6473 byte(s)
[ocmml/slmml] * added a license and an $Id$ header

1 /*
2 Copyright (c) 2009, hkrn All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6
7 Redistributions of source code must retain the above copyright notice, this
8 list of conditions and the following disclaimer. Redistributions in binary
9 form must reproduce the above copyright notice, this list of conditions and
10 the following disclaimer in the documentation and/or other materials
11 provided with the distribution. Neither the name of the hkrn nor
12 the names of its contributors may be used to endorse or promote products
13 derived from this software without specific prior written permission.
14
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
19 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
25 DAMAGE.
26 */
27
28 //
29 // $Id$
30 //
31
32 using System;
33
34 namespace SlMML
35 {
36 public class Envelope
37 {
38 #region ���������������������������������������
39 private static void Initialize()
40 {
41 if (!s_initialized)
42 {
43 s_volumeMap[0] = 0.0;
44 for (int i = 0; i < s_volumeLength; i++)
45 s_volumeMap[i] = Math.Pow(10.0, (i - 255.0) * (48.0 / (255.0 * 20.0)));
46 s_initialized = true;
47 }
48 }
49 #endregion
50
51 #region ���������������������������������������������������������
52 public Envelope(double attack, double decay, double sustain, double release)
53 {
54 Initialize();
55 SetASDR(attack, decay, sustain, release);
56 Playing = false;
57 m_releasing = true;
58 m_currentValue = 0;
59 m_releaseStep = 0;
60 }
61 #endregion
62
63 #region ���������������������������
64 public void SetASDR(double attack, double decay, double sustain, double release)
65 {
66 if (attack != 0.0)
67 {
68 m_attackTime = (int)(attack * Sample.RATE);
69 m_attackRcpr = 1.0 / m_attackTime;
70 }
71 if (decay != 0.0)
72 {
73 m_decayTime = (int)(decay * Sample.RATE);
74 m_decayRcpr = 1.0 / m_decayTime;
75 }
76 m_sustainLevel = sustain;
77 m_releaseTime = (release > 0.0 ? release : (1.0 / Channel.VELOCITY_MAX2)) * Sample.RATE;
78 }
79
80 public void Trigger(bool zeroStart)
81 {
82 Playing = true;
83 m_releasing = false;
84 m_startAmplitude = zeroStart ? 0 : m_currentValue;
85 m_timeInSamples = 1;
86 }
87
88 public void Release()
89 {
90 m_releasing = true;
91 m_releaseStep = m_currentValue / m_releaseTime;
92 }
93
94 public void GetAmplitudeSamplesLinear(ref double[] samples, int start, int end, double velocity)
95 {
96 for (int i = start; i < end; i++)
97 {
98 if (!Playing)
99 {
100 samples[i] = 0.0;
101 continue;
102 }
103 double n = samples[i];
104 UpdateCurrentValue();
105 samples[i] = n * m_currentValue * velocity;
106 }
107 }
108
109 public void GetAmplitudeSamplesNonLinear(ref double[] samples, int start, int end, double velocity)
110 {
111 for (int i = start; i < end; i++)
112 {
113 if (!Playing)
114 {
115 samples[i] = (0.0).ToShort();
116 continue;
117 }
118 double n = samples[i];
119 UpdateCurrentValue();
120 samples[i] = n * s_volumeMap[(int)(Math.Min(m_currentValue, 1.0) * 255)] * velocity;
121 }
122 }
123 #endregion
124
125 #region ������������������������������
126 private void UpdateCurrentValue()
127 {
128 if (!m_releasing)
129 {
130 if (m_timeInSamples < m_attackTime)
131 m_currentValue = m_startAmplitude + (1 - m_startAmplitude) * m_timeInSamples * m_attackRcpr;
132 else if (m_timeInSamples < m_attackTime + m_decayTime)
133 m_currentValue = 1.0 - ((m_timeInSamples - m_attackTime) * m_decayRcpr) * (1.0 - m_sustainLevel);
134 else
135 m_currentValue = m_sustainLevel;
136 }
137 else
138 m_currentValue -= m_releaseStep;
139 if (m_currentValue <= 0)
140 {
141 Playing = false;
142 m_currentValue = 0;
143 }
144 ++m_timeInSamples;
145 }
146 #endregion
147
148 #region ������������������������������
149 public double NextAmplitudeLinear
150 {
151 get
152 {
153 if (!Playing)
154 return 0;
155 UpdateCurrentValue();
156 return m_currentValue;
157 }
158 }
159
160 public bool Playing
161 {
162 private set;
163 get;
164 }
165 #endregion
166
167 #region ���������������������������
168 private static int s_volumeLength = 256;
169 private static double[] s_volumeMap = new double[s_volumeLength];
170 private static bool s_initialized = false;
171 private int m_attackTime;
172 private double m_attackRcpr;
173 private int m_decayTime;
174 private double m_decayRcpr;
175 private double m_sustainLevel;
176 private double m_releaseTime;
177 private double m_currentValue;
178 private double m_releaseStep;
179 private bool m_releasing;
180 private int m_timeInSamples;
181 private double m_startAmplitude;
182 #endregion
183 }
184 }

Properties

Name Value
svn:keywords Id

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