Clemens Valens / SoundEngine

Dependencies:   inc

Dependents:   kinetisizer

Revision:
0:cb80470434eb
diff -r 000000000000 -r cb80470434eb envelope2.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/envelope2.c	Tue Oct 28 12:19:42 2014 +0000
@@ -0,0 +1,181 @@
+/*
+Copyright 2013 Paul Soulsby www.soulsbysynths.com
+    This file is part of Atmegatron.
+
+    Atmegatron is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    Atmegatron is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with Atmegatron.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+//****** BIPOLAR ENVELOPE - for filter and pitch***********
+
+#include "atmegatron.h"
+
+//lets and gets 
+int fenv_A = 0;                //attack (in ticks)  
+int fenv_DR = 400;             //decay AND release (in ticks)  (only reason for this is because there's not enough functions on function dial for both)
+signed char fenv_S = 0;        //sustain (-127 - 127)
+signed char fenv_level = 0;    //the current output level of the env.  between -127 and 127
+boolean fenv_invert = false;   //envelope invert mode
+
+//local filt env vars
+unsigned long  fenv_curtick;   //current tick through env shape
+unsigned long  fenv_starttick; //tick that env started at
+byte fenv_curstate = 0;        //0 = off, 1 = triggering, 2 = holding, 3 = releasing ;
+boolean fenv_changed = true;   //used to only calc Env when it's been triggered
+signed char fenv_Rstart = 0;   //incase key up before decay finishes
+
+//lets and gets
+//set attack (in ticks)
+void Fenv_Let_A(int newA)
+{
+	if (newA!=fenv_A)
+	{
+		fenv_A = newA;
+		fenv_changed = true;
+	}
+}
+
+
+int Fenv_Get_A(void)
+{
+	return fenv_A;
+}
+
+
+//set decay and release (in ticks)
+void Fenv_Let_DR(int newDR)
+{
+	if (newDR!=fenv_DR)
+	{
+		fenv_DR = newDR;
+		fenv_changed = true;
+	}
+}
+
+
+int Fenv_Get_DR(void)
+{
+	return fenv_DR;
+}
+
+
+//set sustain (0-127) -127 - 0 is obtained by turning on invert mode
+void Fenv_Let_S(signed char newS)
+{
+	if (newS!=fenv_S)
+	{  
+		fenv_S = newS;
+		fenv_changed = true;
+	}
+}
+
+
+signed char Fenv_Get_S(void)
+{
+	return fenv_S;
+}
+
+
+//set invert mode
+void Fenv_Let_Invert(boolean newinv)
+{
+	if (newinv!=fenv_invert)
+	{
+		fenv_invert = newinv;
+		fenv_changed = true;
+	}
+}
+
+
+boolean Fenv_Get_Invert(void)
+{
+	return fenv_invert;
+}
+
+
+//get current level of env (-127 - 127)
+signed char Fenv_Get_Level(void)
+{
+	//invert output value if invert mode is on
+	if (fenv_invert==true)
+	{    
+		return -fenv_level;
+	}
+	else
+	{
+		return fenv_level;  
+	}
+}
+
+
+//meat
+//trigger the (start of) envelope
+void FEnv_Trigger(void)
+{
+	fenv_curtick = 0;
+	fenv_starttick = master_tick;  
+	fenv_curstate = 1;
+	fenv_changed = true;
+}
+
+
+//trigger release stage of envelope
+void FEnv_Release(void)
+{
+	fenv_curtick = 0;
+	fenv_starttick = master_tick; 
+	fenv_Rstart = fenv_level;
+	fenv_curstate = 3;
+	fenv_changed = true;
+}
+
+
+//calculate env output level
+void FEnv_CalcVal(void)
+{
+  if (fenv_changed==true){                                                    //is envelope actually doing something?
+    switch (fenv_curstate){
+      case 0:                                                                 //idle
+        fenv_level = 0;
+        fenv_changed = false;
+        break;
+      case 1:
+        fenv_curtick = master_tick - fenv_starttick;                          //triggering
+        if (fenv_curtick>=fenv_A+fenv_DR){                                    //update tick
+          fenv_level = fenv_S;                                                //if attack + decay ticks passed, then onto sustain
+          fenv_curstate = 2;
+        }
+        else if (fenv_curtick>=fenv_A){                                       //if attack ticks passed, then onto decay
+          fenv_level = map(fenv_curtick,fenv_A,fenv_A+fenv_DR,127,fenv_S);
+        }
+        else{                                                                 //otherwise must be doing attack
+          fenv_level = map(fenv_curtick,0,fenv_A,0,127);
+        }
+        break;
+      case 2:                                                                 //holding
+        fenv_level = fenv_S;                                                  //make sure level = sustain level
+        fenv_changed = false;                                                 //only need to do this once
+        break;
+      case 3:                                                                 //releasing
+        fenv_curtick = master_tick - fenv_starttick;                
+        if (fenv_curtick>=fenv_DR){                                           //if release ticks passed, then go back to idle
+          fenv_level = 0;
+          fenv_curstate = 0;
+        }
+        else{                                                                 //otherwise must be releasing
+          fenv_level = map(fenv_curtick,0,fenv_DR,fenv_Rstart,0);
+        }
+        break;
+    }
+  }
+}