1 /*  SpiralSound
2  *  Copyleft (C) 2001 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 #include "EnvelopePlugin.h"
19 #include "EnvelopePluginGUI.h"
20 #include <FL/Fl_Button.H>
21 #include "SpiralIcon.xpm"
22 
23 using namespace std;
24 
25 extern "C" {
SpiralPlugin_CreateInstance()26 SpiralPlugin* SpiralPlugin_CreateInstance()
27 {
28 	return new EnvelopePlugin;
29 }
30 
SpiralPlugin_GetIcon()31 char** SpiralPlugin_GetIcon()
32 {
33 	return SpiralIcon_xpm;
34 }
35 
SpiralPlugin_GetID()36 int SpiralPlugin_GetID()
37 {
38 	return 0x0005;
39 }
40 
SpiralPlugin_GetGroupName()41 string SpiralPlugin_GetGroupName()
42 {
43 	return "Control";
44 }
45 }
46 
47 ///////////////////////////////////////////////////////
48 
EnvelopePlugin()49 EnvelopePlugin::EnvelopePlugin() :
50 m_Trigger(false),
51 m_t(-1.0f),
52 m_Attack(0.0f),
53 m_Decay(0.5f),
54 m_Sustain(1.0f),
55 m_Release(1.0f),
56 m_Volume(0.5f),
57 m_TrigThresh(0.01)
58 {
59 	m_PluginInfo.Name="Envelope";
60 	m_PluginInfo.Width=142;
61 	m_PluginInfo.Height=132;
62 	m_PluginInfo.NumInputs=2;
63 	m_PluginInfo.NumOutputs=2;
64 	m_PluginInfo.PortTips.push_back("Trigger CV");
65 	m_PluginInfo.PortTips.push_back("Input");
66 	m_PluginInfo.PortTips.push_back("CV");
67 	m_PluginInfo.PortTips.push_back("Output");
68 
69 	m_AudioCH->Register("Attack",&m_Attack);
70 	m_AudioCH->Register("Decay",&m_Decay);
71 	m_AudioCH->Register("Sustain",&m_Sustain);
72 	m_AudioCH->Register("Release",&m_Release);
73 	m_AudioCH->Register("Volume",&m_Volume);
74 	m_AudioCH->Register("Trig",&m_TrigThresh);
75 }
76 
~EnvelopePlugin()77 EnvelopePlugin::~EnvelopePlugin()
78 {
79 }
80 
Initialise(const HostInfo * Host)81 PluginInfo &EnvelopePlugin::Initialise(const HostInfo *Host)
82 {
83 	PluginInfo& Info = SpiralPlugin::Initialise(Host);
84 	m_SampleTime=1.0/(float)(m_HostInfo->SAMPLERATE);
85 	return Info;
86 }
87 
CreateGUI()88 SpiralGUIType *EnvelopePlugin::CreateGUI()
89 {
90 	return new EnvelopePluginGUI(m_PluginInfo.Width,
91 								  	    m_PluginInfo.Height,
92 										this,m_AudioCH,m_HostInfo);
93 }
94 
Execute()95 void EnvelopePlugin::Execute()
96 {
97 	float temp=0;
98 	bool Freeze=false;
99 
100 	// Early out?
101 	/*if (m_t<0 && (!m_Input[0] || m_Input[0]->IsEmpty()))
102 	{
103 		m_Output[0]->Zero();
104 		m_Output[1]->Zero();
105 		return;
106 	}*/
107 
108 	for (int n=0; n<m_HostInfo->BUFSIZE; n++)
109 	{
110 		// Check the trigger CV values
111 		if (GetInput(0,n)>m_TrigThresh)
112 		{
113 			if (m_Trigger==false)
114 			{
115 				m_t=0.0f;
116 				m_Trigger=true;
117 			}
118 		}
119 		else
120 		{
121 			m_Trigger=false;
122 		}
123 
124 		// if we are in the envelope...
125 		if (m_t>=0 && m_t<m_Attack+m_Decay+m_Release)
126 		{
127 			// find out what part of the envelope we are in
128 			// in the attack
129 			if (m_t<m_Attack)
130 			{
131 				// get normalised position to
132 				// get the volume between 0 and 1
133 				temp=m_t/m_Attack;
134 			}
135 			else
136 			// in the decay
137 			if (m_t<m_Attack+m_Decay)
138 			{
139 				//if (n==0) cerr<<"in decay"<<endl;
140 				// normalised position in m_Attack->m_Decay range
141 				float nt=(m_t-m_Attack)/m_Decay;
142 
143 				// volume between 1 and m_Sustain
144 				temp=(1-nt)+(m_Sustain*nt);
145 			}
146 			else
147 			// in the release
148 			{
149 				//if (n==0) cerr<<"in release"<<endl;
150 				// normalised position in m_Decay->m_Release range
151 				float nt=(m_t-(m_Attack+m_Decay))/m_Release;
152 
153 				// volume between m_Sustain and 0
154 				temp=m_Sustain*(1-nt);
155 
156 				if (m_Release<0.2f)
157 				{
158 					temp=m_Sustain;
159 				}
160 
161 				if (m_Trigger) Freeze=true;
162 			}
163 
164 			temp*=m_Volume;
165 
166 			SetOutput(0,n,temp);
167 			SetOutput(1,n,GetInput(1,n)*temp);
168 
169 			if (!Freeze) m_t+=m_SampleTime;
170 		}
171 		else
172 		{
173 			SetOutput(0,n,0);
174 			SetOutput(1,n,0);
175 
176 			// if we've run off the end
177 			if (m_t>m_Attack+m_Decay+m_Release)
178 			{
179 				m_t=-1;
180 				//m_Output[0]->Zero();
181 				//m_Output[1]->Zero();
182 				return;
183 			}
184 
185 		}
186 	}
187 }
188 
StreamOut(ostream & s)189 void EnvelopePlugin::StreamOut(ostream &s)
190 {
191 	s<<m_Version<<" "<<m_Attack<<" "<<m_Decay<<" "<<m_Sustain<<" "<<
192 	m_Release<<" "<<m_Volume<<" "<<m_TrigThresh;
193 }
194 
StreamIn(istream & s)195 void EnvelopePlugin::StreamIn(istream &s)
196 {
197 	int version;
198 	s>>version;
199 	s>>m_Attack>>m_Decay>>m_Sustain>>m_Release>>m_Volume>>m_TrigThresh;
200 }
201