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