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