This is a part of the Kinetiszer project.
envelope2.c@1:8ae4ab73ca6a, 2014-10-28 (annotated)
- Committer:
- Clemo
- Date:
- Tue Oct 28 20:09:12 2014 +0000
- Revision:
- 1:8ae4ab73ca6a
- Parent:
- 0:cb80470434eb
First publication (untested)
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Clemo | 0:cb80470434eb | 1 | /* |
Clemo | 0:cb80470434eb | 2 | Copyright 2013 Paul Soulsby www.soulsbysynths.com |
Clemo | 0:cb80470434eb | 3 | This file is part of Atmegatron. |
Clemo | 0:cb80470434eb | 4 | |
Clemo | 0:cb80470434eb | 5 | Atmegatron is free software: you can redistribute it and/or modify |
Clemo | 0:cb80470434eb | 6 | it under the terms of the GNU General Public License as published by |
Clemo | 0:cb80470434eb | 7 | the Free Software Foundation, either version 3 of the License, or |
Clemo | 0:cb80470434eb | 8 | (at your option) any later version. |
Clemo | 0:cb80470434eb | 9 | |
Clemo | 0:cb80470434eb | 10 | Atmegatron is distributed in the hope that it will be useful, |
Clemo | 0:cb80470434eb | 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
Clemo | 0:cb80470434eb | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
Clemo | 0:cb80470434eb | 13 | GNU General Public License for more details. |
Clemo | 0:cb80470434eb | 14 | |
Clemo | 0:cb80470434eb | 15 | You should have received a copy of the GNU General Public License |
Clemo | 0:cb80470434eb | 16 | along with Atmegatron. If not, see <http://www.gnu.org/licenses/>. |
Clemo | 0:cb80470434eb | 17 | */ |
Clemo | 0:cb80470434eb | 18 | |
Clemo | 0:cb80470434eb | 19 | //****** BIPOLAR ENVELOPE - for filter and pitch*********** |
Clemo | 0:cb80470434eb | 20 | |
Clemo | 0:cb80470434eb | 21 | #include "atmegatron.h" |
Clemo | 0:cb80470434eb | 22 | |
Clemo | 0:cb80470434eb | 23 | //lets and gets |
Clemo | 0:cb80470434eb | 24 | int fenv_A = 0; //attack (in ticks) |
Clemo | 0:cb80470434eb | 25 | 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) |
Clemo | 0:cb80470434eb | 26 | signed char fenv_S = 0; //sustain (-127 - 127) |
Clemo | 0:cb80470434eb | 27 | signed char fenv_level = 0; //the current output level of the env. between -127 and 127 |
Clemo | 0:cb80470434eb | 28 | boolean fenv_invert = false; //envelope invert mode |
Clemo | 0:cb80470434eb | 29 | |
Clemo | 0:cb80470434eb | 30 | //local filt env vars |
Clemo | 0:cb80470434eb | 31 | unsigned long fenv_curtick; //current tick through env shape |
Clemo | 0:cb80470434eb | 32 | unsigned long fenv_starttick; //tick that env started at |
Clemo | 0:cb80470434eb | 33 | byte fenv_curstate = 0; //0 = off, 1 = triggering, 2 = holding, 3 = releasing ; |
Clemo | 0:cb80470434eb | 34 | boolean fenv_changed = true; //used to only calc Env when it's been triggered |
Clemo | 0:cb80470434eb | 35 | signed char fenv_Rstart = 0; //incase key up before decay finishes |
Clemo | 0:cb80470434eb | 36 | |
Clemo | 0:cb80470434eb | 37 | //lets and gets |
Clemo | 0:cb80470434eb | 38 | //set attack (in ticks) |
Clemo | 0:cb80470434eb | 39 | void Fenv_Let_A(int newA) |
Clemo | 0:cb80470434eb | 40 | { |
Clemo | 0:cb80470434eb | 41 | if (newA!=fenv_A) |
Clemo | 0:cb80470434eb | 42 | { |
Clemo | 0:cb80470434eb | 43 | fenv_A = newA; |
Clemo | 0:cb80470434eb | 44 | fenv_changed = true; |
Clemo | 0:cb80470434eb | 45 | } |
Clemo | 0:cb80470434eb | 46 | } |
Clemo | 0:cb80470434eb | 47 | |
Clemo | 0:cb80470434eb | 48 | |
Clemo | 0:cb80470434eb | 49 | int Fenv_Get_A(void) |
Clemo | 0:cb80470434eb | 50 | { |
Clemo | 0:cb80470434eb | 51 | return fenv_A; |
Clemo | 0:cb80470434eb | 52 | } |
Clemo | 0:cb80470434eb | 53 | |
Clemo | 0:cb80470434eb | 54 | |
Clemo | 0:cb80470434eb | 55 | //set decay and release (in ticks) |
Clemo | 0:cb80470434eb | 56 | void Fenv_Let_DR(int newDR) |
Clemo | 0:cb80470434eb | 57 | { |
Clemo | 0:cb80470434eb | 58 | if (newDR!=fenv_DR) |
Clemo | 0:cb80470434eb | 59 | { |
Clemo | 0:cb80470434eb | 60 | fenv_DR = newDR; |
Clemo | 0:cb80470434eb | 61 | fenv_changed = true; |
Clemo | 0:cb80470434eb | 62 | } |
Clemo | 0:cb80470434eb | 63 | } |
Clemo | 0:cb80470434eb | 64 | |
Clemo | 0:cb80470434eb | 65 | |
Clemo | 0:cb80470434eb | 66 | int Fenv_Get_DR(void) |
Clemo | 0:cb80470434eb | 67 | { |
Clemo | 0:cb80470434eb | 68 | return fenv_DR; |
Clemo | 0:cb80470434eb | 69 | } |
Clemo | 0:cb80470434eb | 70 | |
Clemo | 0:cb80470434eb | 71 | |
Clemo | 0:cb80470434eb | 72 | //set sustain (0-127) -127 - 0 is obtained by turning on invert mode |
Clemo | 0:cb80470434eb | 73 | void Fenv_Let_S(signed char newS) |
Clemo | 0:cb80470434eb | 74 | { |
Clemo | 0:cb80470434eb | 75 | if (newS!=fenv_S) |
Clemo | 0:cb80470434eb | 76 | { |
Clemo | 0:cb80470434eb | 77 | fenv_S = newS; |
Clemo | 0:cb80470434eb | 78 | fenv_changed = true; |
Clemo | 0:cb80470434eb | 79 | } |
Clemo | 0:cb80470434eb | 80 | } |
Clemo | 0:cb80470434eb | 81 | |
Clemo | 0:cb80470434eb | 82 | |
Clemo | 0:cb80470434eb | 83 | signed char Fenv_Get_S(void) |
Clemo | 0:cb80470434eb | 84 | { |
Clemo | 0:cb80470434eb | 85 | return fenv_S; |
Clemo | 0:cb80470434eb | 86 | } |
Clemo | 0:cb80470434eb | 87 | |
Clemo | 0:cb80470434eb | 88 | |
Clemo | 0:cb80470434eb | 89 | //set invert mode |
Clemo | 0:cb80470434eb | 90 | void Fenv_Let_Invert(boolean newinv) |
Clemo | 0:cb80470434eb | 91 | { |
Clemo | 0:cb80470434eb | 92 | if (newinv!=fenv_invert) |
Clemo | 0:cb80470434eb | 93 | { |
Clemo | 0:cb80470434eb | 94 | fenv_invert = newinv; |
Clemo | 0:cb80470434eb | 95 | fenv_changed = true; |
Clemo | 0:cb80470434eb | 96 | } |
Clemo | 0:cb80470434eb | 97 | } |
Clemo | 0:cb80470434eb | 98 | |
Clemo | 0:cb80470434eb | 99 | |
Clemo | 0:cb80470434eb | 100 | boolean Fenv_Get_Invert(void) |
Clemo | 0:cb80470434eb | 101 | { |
Clemo | 0:cb80470434eb | 102 | return fenv_invert; |
Clemo | 0:cb80470434eb | 103 | } |
Clemo | 0:cb80470434eb | 104 | |
Clemo | 0:cb80470434eb | 105 | |
Clemo | 0:cb80470434eb | 106 | //get current level of env (-127 - 127) |
Clemo | 0:cb80470434eb | 107 | signed char Fenv_Get_Level(void) |
Clemo | 0:cb80470434eb | 108 | { |
Clemo | 0:cb80470434eb | 109 | //invert output value if invert mode is on |
Clemo | 0:cb80470434eb | 110 | if (fenv_invert==true) |
Clemo | 0:cb80470434eb | 111 | { |
Clemo | 0:cb80470434eb | 112 | return -fenv_level; |
Clemo | 0:cb80470434eb | 113 | } |
Clemo | 0:cb80470434eb | 114 | else |
Clemo | 0:cb80470434eb | 115 | { |
Clemo | 0:cb80470434eb | 116 | return fenv_level; |
Clemo | 0:cb80470434eb | 117 | } |
Clemo | 0:cb80470434eb | 118 | } |
Clemo | 0:cb80470434eb | 119 | |
Clemo | 0:cb80470434eb | 120 | |
Clemo | 0:cb80470434eb | 121 | //meat |
Clemo | 0:cb80470434eb | 122 | //trigger the (start of) envelope |
Clemo | 0:cb80470434eb | 123 | void FEnv_Trigger(void) |
Clemo | 0:cb80470434eb | 124 | { |
Clemo | 0:cb80470434eb | 125 | fenv_curtick = 0; |
Clemo | 0:cb80470434eb | 126 | fenv_starttick = master_tick; |
Clemo | 0:cb80470434eb | 127 | fenv_curstate = 1; |
Clemo | 0:cb80470434eb | 128 | fenv_changed = true; |
Clemo | 0:cb80470434eb | 129 | } |
Clemo | 0:cb80470434eb | 130 | |
Clemo | 0:cb80470434eb | 131 | |
Clemo | 0:cb80470434eb | 132 | //trigger release stage of envelope |
Clemo | 0:cb80470434eb | 133 | void FEnv_Release(void) |
Clemo | 0:cb80470434eb | 134 | { |
Clemo | 0:cb80470434eb | 135 | fenv_curtick = 0; |
Clemo | 0:cb80470434eb | 136 | fenv_starttick = master_tick; |
Clemo | 0:cb80470434eb | 137 | fenv_Rstart = fenv_level; |
Clemo | 0:cb80470434eb | 138 | fenv_curstate = 3; |
Clemo | 0:cb80470434eb | 139 | fenv_changed = true; |
Clemo | 0:cb80470434eb | 140 | } |
Clemo | 0:cb80470434eb | 141 | |
Clemo | 0:cb80470434eb | 142 | |
Clemo | 0:cb80470434eb | 143 | //calculate env output level |
Clemo | 0:cb80470434eb | 144 | void FEnv_CalcVal(void) |
Clemo | 0:cb80470434eb | 145 | { |
Clemo | 0:cb80470434eb | 146 | if (fenv_changed==true){ //is envelope actually doing something? |
Clemo | 0:cb80470434eb | 147 | switch (fenv_curstate){ |
Clemo | 0:cb80470434eb | 148 | case 0: //idle |
Clemo | 0:cb80470434eb | 149 | fenv_level = 0; |
Clemo | 0:cb80470434eb | 150 | fenv_changed = false; |
Clemo | 0:cb80470434eb | 151 | break; |
Clemo | 0:cb80470434eb | 152 | case 1: |
Clemo | 0:cb80470434eb | 153 | fenv_curtick = master_tick - fenv_starttick; //triggering |
Clemo | 0:cb80470434eb | 154 | if (fenv_curtick>=fenv_A+fenv_DR){ //update tick |
Clemo | 0:cb80470434eb | 155 | fenv_level = fenv_S; //if attack + decay ticks passed, then onto sustain |
Clemo | 0:cb80470434eb | 156 | fenv_curstate = 2; |
Clemo | 0:cb80470434eb | 157 | } |
Clemo | 0:cb80470434eb | 158 | else if (fenv_curtick>=fenv_A){ //if attack ticks passed, then onto decay |
Clemo | 0:cb80470434eb | 159 | fenv_level = map(fenv_curtick,fenv_A,fenv_A+fenv_DR,127,fenv_S); |
Clemo | 0:cb80470434eb | 160 | } |
Clemo | 0:cb80470434eb | 161 | else{ //otherwise must be doing attack |
Clemo | 0:cb80470434eb | 162 | fenv_level = map(fenv_curtick,0,fenv_A,0,127); |
Clemo | 0:cb80470434eb | 163 | } |
Clemo | 0:cb80470434eb | 164 | break; |
Clemo | 0:cb80470434eb | 165 | case 2: //holding |
Clemo | 0:cb80470434eb | 166 | fenv_level = fenv_S; //make sure level = sustain level |
Clemo | 0:cb80470434eb | 167 | fenv_changed = false; //only need to do this once |
Clemo | 0:cb80470434eb | 168 | break; |
Clemo | 0:cb80470434eb | 169 | case 3: //releasing |
Clemo | 0:cb80470434eb | 170 | fenv_curtick = master_tick - fenv_starttick; |
Clemo | 0:cb80470434eb | 171 | if (fenv_curtick>=fenv_DR){ //if release ticks passed, then go back to idle |
Clemo | 0:cb80470434eb | 172 | fenv_level = 0; |
Clemo | 0:cb80470434eb | 173 | fenv_curstate = 0; |
Clemo | 0:cb80470434eb | 174 | } |
Clemo | 0:cb80470434eb | 175 | else{ //otherwise must be releasing |
Clemo | 0:cb80470434eb | 176 | fenv_level = map(fenv_curtick,0,fenv_DR,fenv_Rstart,0); |
Clemo | 0:cb80470434eb | 177 | } |
Clemo | 0:cb80470434eb | 178 | break; |
Clemo | 0:cb80470434eb | 179 | } |
Clemo | 0:cb80470434eb | 180 | } |
Clemo | 0:cb80470434eb | 181 | } |