Expandmenu Shrunk


First Software Envelope Generator

This is my first software based Envelope Generator (ADSR).
For better debugging and testing i have implemented this on my PC with VisualStudio.

Here my uncommented source code and a simple test:

#include "stdafx.h"
#include <stdio.h> 

// Max Level of the Attack Phase
#define MAXVALUE 100

//Envelope States
enum {idle,attack, decay, sustain, release};

//Parameters
volatile int A_Rate = 50;
volatile int D_Rate = 20;
volatile int S_Level = 60;
volatile int R_Rate = 10;

volatile int State = idle;
volatile int SumAttack = 0;
volatile int DiffDecay = MAXVALUE;
volatile int DiffRelease;
volatile int ZEIT = 0;
volatile int Env_Out =0;

int CalcEnvelope(int Gate);

//Calculates a simple ADSR Envelope
int CalcEnvelope(int Gate)
{
    switch(State) {

        case IDLE:
        
        #ifdef DEBUG_0
            printf("Idle\n");
        #endif
        
        if(Gate == 1)
        {
            State = ATTACK;
        }
        break;

        case ATTACK:
        
        #ifdef DEBUG_0
            printf("Attack\n");
        #endif
        
        if(Gate == 0)
        {
            State = RELEASE;
            DiffRelease = Env_Out;
        }
        else
        {
            SumAttack+=A_Rate;
            if(SumAttack >= MAXVALUE)
            {
                SumAttack = MAXVALUE;
                State = DECAY;
            }
            Env_Out = SumAttack;
        }
        break;

        case DECAY:
        
        #ifdef DEBUG_0
            printf("Decay\n");
        #endif
        
        if(Gate == 0)
        {
            State = RELEASE;
            DiffRelease = Env_Out;
        }
        else
        {
            DiffDecay-=D_Rate;
            if(DiffDecay > S_Level)
            {
                
                Env_Out = DiffDecay;
            }
            else
            {
                Env_Out = S_Level;
                State = SUSTAIN;
            }
            
            
        }
        
        break;

        case SUSTAIN:
        
        #ifdef DEBUG_0
            printf("Sustain\n");
        #endif
        
        if(Gate == 0)
        {
            State = RELEASE;
            DiffRelease= S_Level;
            DiffDecay = MAXVALUE;
        }
        break;

        case RELEASE:
        
        #ifdef DEBUG_0
            printf("Release\n");
        #endif
        
        if(Gate == 0)
        {
            DiffRelease-=R_Rate;
            if(DiffRelease > 0 )
            {
                
                Env_Out = DiffRelease;
            }
            else
            {
                State= IDLE;
                Env_Out = 0;
                DiffRelease = 0;
                DiffDecay = 0;
                SumAttack = 0;
            }

        }
        else
        {
            State=ATTACK;
            SumAttack = Env_Out;
        }
        break;

        default:
        
        #ifdef DEBUG_0
            printf("default\n");
        #endif
        
        ;
            
    }
    return Env_out;
}

    



int _tmain(int argc, _TCHAR* argv[])
{


    printf("-------------------------------------------------------------------\n");
    printf("A_Rate= %d, D_Rate= %d, S_Level= %d, R_Rate= %d \n\n",A_Rate,D_Rate,S_Level,R_Rate);

    printf("-------------------------------------------------------------------\n");
    printf("Time--Gate--Value---State\n");
    for(int i=0;i<10;i++)
    {
        printf("%03d   On    %03d     ",ZEIT, CalcEnvelope(1));
        ZEIT++;
    }


    for(int i=0;i<3;i++)
    {
        printf("%03d   Off   %03d     ",ZEIT, CalcEnvelope(0));
        ZEIT++;
    }


    for(int i=0;i<10;i++)
    {
        printf("%03d   On    %03d     ",ZEIT, CalcEnvelope(1));
        ZEIT++;
    }


    for(int i=0;i<10;i++)
    {
        printf("%03d   Off   %03d     ",ZEIT, CalcEnvelope(0));
        ZEIT++;
    }


    for(int i=0;i<2;i++)
    {
        printf("%03d   On    %03d     ",ZEIT, CalcEnvelope(1));
        ZEIT++;
    }

    for(int i=0;i<10;i++)
    {
        printf("%03d   Off   %03d     ",ZEIT, CalcEnvelope(0));
        ZEIT++;
    }

    getchar();
    return 0;
}

This is the console Output:
Envelope_test1
The test shows a key down with an retrigger in the release phase (time013) followed by a complete run (finished at030) then you see a aborted attack phase (time035).

Update 26.08.2015

First tests with my controller board ATMEGA 32, 8Mhz LTC2756 18Bit DA

Made some changes in the coding.

 

MAXVALUE=262144 A_Rate = 1000 D_Rate = 500 S_Level= 131072 R_Rate = 250 Update Rate: 1ms Oscilloscope Setting: 200ms/cm
MAXVALUE=262144
A_Rate = 1000
D_Rate = 500
S_Level= 131072
R_Rate = 250
Update Rate: 1ms
Oscilloscope Setting: 200ms/cm

 

MAXVALUE=262144 A_Rate = 10000 D_Rate = 500 S_Level= 131072 R_Rate = 250 Update Rate: 1ms Oscilloscope Setting: 50ms/cm
MAXVALUE=262144
A_Rate = 10000
D_Rate = 500
S_Level= 131072
R_Rate = 250
Update Rate: 1ms
Oscilloscope Setting: 50ms/cm

 

MAXVALUE=262144 A_Rate = 100000 D_Rate = 500 S_Level= 131072 R_Rate = 250 Update Rate: 1ms Oscilloscope Setting: 1ms/cm
MAXVALUE=262144
A_Rate = 100000
D_Rate = 500
S_Level= 131072
R_Rate = 250
Update Rate: 1ms
Oscilloscope Setting: 1ms/cm

 

UPDATE 27.08.2015

Fixed The MAXVALUE Problem Set this value to (2^18) -1

MAXVALUE=262143 A_Rate = 1000 D_Rate = 500 S_Level= 131072 R_Rate = 250 Update Rate: 1ms Oscilloscope Setting: 200ms/cm
MAXVALUE=262143
A_Rate = 1000
D_Rate = 500
S_Level= 131072
R_Rate = 250
Update Rate: 1ms
Oscilloscope Setting: 200ms/cm
Share Button