This is a part of the Kinetiszer project.

Dependencies:   inc

Dependents:   kinetisizer

envelope2.c

Committer:
Clemo
Date:
2014-10-28
Revision:
1:8ae4ab73ca6a
Parent:
0:cb80470434eb

File content as of revision 1:8ae4ab73ca6a:

/*
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;
    }
  }
}