Mozzi  alpha 0.01.1t
sound synthesis library for Arduino
 All Classes Functions Typedefs
ADSR.h
00001 /*
00002  * ADSR.h
00003  *
00004  * Copyright 2012 Tim Barrass.
00005  *
00006  * This file is part of Mozzi.
00007  *
00008  * Mozzi is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 3 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * Mozzi is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with Mozzi.  If not, see <http://www.gnu.org/licenses/>.
00020  *
00021  */
00022 
00023 #ifndef ADSR_H_
00024 #define ADSR_H_
00025 
00026 #include "Arduino.h"
00027 //#include <util/atomic.h>
00028 #include "Line.h"
00029 #include "fixedMath.h"
00030 
00037 template <unsigned int CONTROL_UPDATE_RATE>
00038 class ADSR
00039 {
00040 private:
00041 
00042                 const unsigned int AUDIO_TICKS_PER_CONTROL;
00043 
00044                 unsigned int phase_control_step_counter;
00045                 unsigned int phase_num_control_steps;
00046 
00047                 enum {ATTACK,DECAY,SUSTAIN,RELEASE,IDLE};
00048                 
00049                 
00050                 struct phase{
00051                                 byte phase_type;
00052                                 unsigned int control_steps;
00053                                 unsigned long audio_steps;
00054                                 Q8n0 level;
00055                 }attack,decay,sustain,release,idle;
00056                 
00057                 phase * current_phase;
00058                 
00059                 // Linear audio rate transitions for envelope
00060                 Line <unsigned long> transition;
00061 
00062                 inline
00063                 unsigned int convertMsecToControlSteps(unsigned int msec){
00064                                 return (uint) (((ulong)msec*CONTROL_UPDATE_RATE)>>10); // approximate /1000 with shift
00065                 }
00066 
00067                 inline
00068                 void setPhase(phase * next_phase) {
00069                                 phase_control_step_counter = 0;
00070                                 phase_num_control_steps = next_phase->control_steps;
00071                                 transition.set(Q8n0_to_Q16n16(next_phase->level),next_phase->audio_steps);
00072                                 current_phase = next_phase;
00073                 }
00074                 
00075                 
00076                 
00077                 inline
00078                 void checkForAndSetNextPhase(phase * next_phase) {
00079                                 if (++phase_control_step_counter >= phase_num_control_steps){
00080                                                 setPhase(next_phase);
00081                                 }
00082                 }
00083                                                                 
00084                 
00085                 inline
00086                 void checkForAndSetIdle() {
00087                                 if (++phase_control_step_counter >= phase_num_control_steps){
00088                                                 transition.set(0,0,1);
00089                                                 current_phase = &idle;
00090                                 }
00091                 }
00092                 
00093                 
00094                 
00095 inline
00096                 void setTime(phase * p, unsigned int msec)
00097                 {
00098                                 p->control_steps=convertMsecToControlSteps(msec);
00099                                 p->audio_steps = (ulong) p->control_steps * AUDIO_TICKS_PER_CONTROL;
00100                 }
00101                 
00102                 
00103 public:
00104 
00107                 ADSR():AUDIO_TICKS_PER_CONTROL(AUDIO_RATE/CONTROL_UPDATE_RATE)
00108                 {
00109                                 attack.phase_type = ATTACK;
00110                                 decay.phase_type = DECAY;
00111                                 sustain.phase_type = SUSTAIN;
00112                                 release.phase_type = RELEASE;
00113                                 idle.phase_type = IDLE;
00114                                 release.level = 0;
00115                 }
00116 
00117 
00121                 void update(){ // control rate
00122                                 
00123                                 switch(current_phase->phase_type) {
00124                                                 
00125                                                 case ATTACK:
00126                                                                 checkForAndSetNextPhase(&decay);
00127                                                                 break;
00128 
00129                                                 case DECAY:
00130                                                                                 checkForAndSetNextPhase(&sustain);
00131                                                                 break;
00132                                                                                 
00133                                                 case SUSTAIN:
00134                                                                                 checkForAndSetNextPhase(&release);                                                                                                                                                              
00135                                                                 break;
00136                                                                                 
00137                                                 case RELEASE:
00138                                                                                 checkForAndSetIdle();                                                                                                           
00139                                                                 break;
00140 
00141                                 }               
00142                 }
00143 
00148                 inline
00149                 unsigned int next()
00150                 {
00151                                 return Q16n16_to_Q16n0(transition.next());
00152                 }
00153 
00154 
00155 
00158                 inline
00159                 void noteOn(){
00160                                 setPhase(&attack);
00161                 }
00162 
00163 
00164 
00168                 inline
00169                 void noteOff(){                                 
00170                                 setPhase(&release);
00171                 }
00172 
00173 
00174 
00175 
00176 
00180                 inline
00181                 void setAttackLevel(byte value)
00182                 {
00183                                 attack.level=value;
00184                 }
00185 
00186 
00187 
00191                 inline
00192                 void setDecayLevel(byte value)
00193                 {
00194                                 decay.level=value;
00195                 }
00196 
00197 
00202                 inline
00203                 void setSustainLevel(byte value)
00204                 {
00205                                 sustain.level=value;
00206                 }
00207                 
00212                 inline
00213                 void setReleaseLevel(byte value)
00214                 {
00215                                 release.level=value;
00216                 }
00217                 
00218                 
00219                 
00225                 inline
00226                 void setADLevels(byte attack, byte decay)
00227                 {
00228                                 setAttackLevel(attack);
00229                                 setDecayLevel(decay);
00230                                 setSustainLevel(decay);
00231                                 setReleaseLevel(0);
00232                 }
00233                 
00234 
00235 
00236                 
00237                 
00238                 
00239                 
00244                 inline
00245                 void setAttackTime(unsigned int msec)
00246                 {
00247                                 setTime(&attack, msec);
00248                 }
00249 
00250 
00255                 inline
00256                 void setDecayTime(unsigned int msec)
00257                 {
00258                                 setTime(&decay, msec);
00259                 }
00260 
00261                 
00267                 inline
00268                 void setSustainTime(unsigned int msec)
00269                 {
00270                                 setTime(&sustain, msec);
00271                 }
00272                 
00273                 
00274 
00279                 inline
00280                 void setReleaseTime(unsigned int msec)
00281                 {
00282                                 setTime(&release, msec);
00283                 }
00284                 
00285 
00286 
00294                 inline
00295                 void setTimes(unsigned int attack_ms, unsigned int decay_ms, unsigned int sustain_ms, unsigned int release_ms)
00296                 {
00297                                 setAttackTime(attack_ms);
00298                                 setDecayTime(decay_ms);
00299                                 setSustainTime(sustain_ms);
00300                                 setReleaseTime(release_ms);
00301                 }
00302 
00303 
00304 };
00305 
00306 #endif /* ADSR_H_ */