1 /*
2 * Copyleft (C) 2000 David Griffiths <dave@pawfal.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include "Envelope.h"
20
Envelope()21 Envelope::Envelope() :
22 m_Attack(0.0f),
23 m_Decay(0.5f),
24 m_Sustain(1.0f),
25 m_Release(1.0f),
26 m_Volume(0.5f)
27 {
28 m_Trigger=new bool[SpiralInfo::POLY];
29 m_t=new double[SpiralInfo::POLY];
30
31 for (int n=0; n<SpiralInfo::POLY; n++)
32 {
33 m_Trigger[n]=false;
34 m_t[n]=-1.0f;
35 }
36
37 m_SampleTime=1.0/(double)(SpiralInfo::SAMPLERATE);
38 }
39
~Envelope()40 Envelope::~Envelope()
41 {
42 delete[] m_Trigger;
43 delete[] m_t;
44 }
45
GetOutput(int V,short * data)46 void Envelope::GetOutput(int V, short *data)
47 {
48 float Vol=0;
49 bool Freeze=false;
50 // find out what part of the envelope we are in
51
52 // if the env hasn't been triggered
53 if (m_t[V]<0)
54 {
55 Zero(data);
56 return;
57 }
58
59 // if we've run off the end
60 if (m_t[V]>m_Attack+m_Decay+m_Release)
61 {
62 m_t[V]=-1;
63 Zero(data);
64 return;
65 }
66
67 float temp=0;
68
69 // we are in the envelope then...
70 for (int n=0; n<SpiralInfo::BUFSIZE; n++)
71 {
72 // in the attack
73 if (m_t[V]<m_Attack)
74 {
75 //if (n==0) cerr<<"in attack"<<endl;
76 // get normalised position to
77 // get the volume between 0 and 1
78 temp=m_t[V]/m_Attack;
79 }
80 else
81 // in the decay
82 if (m_t[V]<m_Attack+m_Decay)
83 {
84 //if (n==0) cerr<<"in decay"<<endl;
85 // normalised position in m_Attack->m_Decay range
86 float nt=(m_t[V]-m_Attack)/m_Decay;
87
88 // volume between 1 and m_Sustain
89 temp=(1-nt)+(m_Sustain*nt);
90 }
91 else
92 // in the release
93 {
94 //if (n==0) cerr<<"in release"<<endl;
95 // normalised position in m_Decay->m_Release range
96 float nt=(m_t[V]-(m_Attack+m_Decay))/m_Release;
97
98 // volume between m_Sustain and 0
99 temp=m_Sustain*(1-nt);
100
101 if (m_Release<0.2f)
102 {
103 temp=m_Sustain;
104 }
105
106 if (m_Trigger[V]) Freeze=true;
107 }
108
109 // multiply up to fixed short representation
110 // and scale by volume
111
112 data[n]=static_cast<short>(temp*SpiralInfo::MAXSAMPLE*m_Volume);
113
114 if (!Freeze) m_t[V]+=m_SampleTime;
115 }
116
117
118
119 }
120
Zero(short * data)121 void Envelope::Zero(short *data)
122 {
123 for (int n=0; n<SpiralInfo::BUFSIZE; n++)
124 {
125 data[n]=0;
126 }
127 }
128
Randomise()129 void Envelope::Randomise()
130 {
131 m_Attack=RandFloat();
132 m_Decay=RandFloat();
133 m_Sustain=RandFloat();
134 m_Release=RandFloat();
135 m_Volume=RandFloat();
136 }
137
138 istream &operator>>(istream &s, Envelope &o)
139 {
140 s>>o.m_Attack>>o.m_Decay>>o.m_Sustain>>o.m_Release>>o.m_Volume;
141 return s;
142 }
143
144 ostream &operator<<(ostream &s, Envelope &o)
145 {
146 s<<o.m_Attack<<" "<<o.m_Decay<<" "<<o.m_Sustain<<" "<<o.m_Release<<" "<<o.m_Volume<<" ";
147 return s;
148 }
149