This is a part of the Kinetiszer project.

Dependencies:   inc

Dependents:   kinetisizer

Revision:
0:cb80470434eb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/envelope.c	Tue Oct 28 12:19:42 2014 +0000
@@ -0,0 +1,176 @@
+/*
+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/>.
+*/
+
+//******UNIPOLAR ENVELOPE - for amplitude***********
+
+#include "atmegatron.h"
+
+//lets and gets
+int aenv_A = 0;         //attack (in ticks)               
+int aenv_D = 0;         //decay  (in ticks)
+byte aenv_S = 255;      //sustain (0-255)
+int aenv_R = 0;         //release (in ticks)
+byte aenv_level = 0;    //current output level (0-255)
+
+//local variables
+unsigned long  aenv_curtick;      //current tick through env shape
+unsigned long  aenv_starttick;    //tick that env started at
+byte aenv_curstate = 0;           //0 = off, 1 = triggering, 2 = holding, 3 = releasing 
+boolean aenv_changed = true;      //used to only calc Env when it's been triggered
+byte aenv_Rstart = 0;             //incase key up before decay finishes
+
+// lets and gets
+
+//set attack (in ticks)
+void Aenv_Let_A(int newA){        
+  if (newA!=aenv_A){
+    aenv_A = newA;
+    aenv_changed = true;
+  }
+}
+
+
+int Aenv_Get_A(void)
+{
+  return aenv_A;
+}
+
+
+//set decay (in ticks)
+void Aenv_Let_D(int newD)
+{
+  if (newD!=aenv_D){
+    aenv_D = newD;
+    aenv_changed = true;
+  }
+}
+
+
+int Aenv_Get_D(void)
+{
+  return aenv_D;
+}
+
+
+//set sustain (0-255)
+void Aenv_Let_S(byte newS)
+{
+  if (newS!=aenv_S){  
+    aenv_S = newS;
+    aenv_changed = true;
+  }
+}
+
+
+byte Aenv_Get_S(void)
+{
+  return aenv_S;
+}
+
+
+//set release (in ticks)
+void Aenv_Let_R(int newR)
+{
+  if (newR!=aenv_R){
+    aenv_R = newR;
+    aenv_changed = true;
+  }
+}
+
+
+int Aenv_Get_R(void)
+{
+  return aenv_R;
+}
+
+
+//get current state of env (0 = off, 1 = triggering, 2 = holding, 3 = releasing)
+byte Aenv_Get_State()
+{
+  return aenv_curstate;
+}
+
+
+//get current level of env (0-255)
+byte Aenv_Get_Level(void)
+{
+  return aenv_level;  
+}
+
+
+//ENVELOPE MEAT
+//trigger the (start of) envelope
+void AEnv_Trigger(void)
+{
+  aenv_curtick = 0;              //reset curtick
+  aenv_starttick = master_tick;  //set starttick = master tick
+  aenv_curstate = 1;             //set state to attack
+  aenv_changed = true;           //so calcval does something
+}
+
+
+//trigger release stage of envelope
+void AEnv_Release(void)
+{
+  aenv_curtick = 0;              //reset curtick
+  aenv_starttick = master_tick;  //set starttick = master tick
+  aenv_curstate = 3;             //set state to release
+  aenv_Rstart = aenv_level;      //set release start level = current level.  This may NOT be sustain level, if still in decay stage
+  aenv_changed = true;           //so calcval does something
+}
+
+
+//calculate env output level
+void AEnv_CalcVal(void)
+{
+  if (aenv_changed==true){                                                      //is envelope actually doing something?
+    switch (aenv_curstate){
+      case 0:                                                                   //idle
+        aenv_level = 0;
+        aenv_changed = false;
+        break;
+      case 1:                                                                   //triggering
+        aenv_curtick = master_tick - aenv_starttick;                            //update tick
+        if (aenv_curtick>=aenv_A+aenv_D){                                       //if attack + decay ticks passed, then onto sustain
+          aenv_level = aenv_S;
+          aenv_curstate = 2;
+        }
+        else if (aenv_curtick>=aenv_A){                                          //if attack ticks passed, then onto decay
+          aenv_level = map(aenv_curtick,aenv_A,aenv_A+aenv_D,255,aenv_S);        
+        }
+        else{
+          aenv_level = map(aenv_curtick,0,aenv_A,0,255);                          //otherwise must be doing attack
+        }
+        break;
+      case 2:                                                                     //holding
+        aenv_level = aenv_S;                                                      //make sure level = sustain level
+        aenv_changed = false;                                                     //only need to do this once
+        break;
+      case 3:
+        aenv_curtick = master_tick - aenv_starttick;                              //releasing
+        if (aenv_curtick>=aenv_R){                                                //if release ticks passed, then go back to idle
+          aenv_level = 0;
+          aenv_curstate = 0;
+        }
+        else{                                                                      //otherwise must be releasing
+          aenv_level = map(aenv_curtick,0,aenv_R,aenv_Rstart,0);
+        }
+        break;
+    } 
+  }
+}