Mozzi  alpha 0.01.1t
sound synthesis library for Arduino
 All Classes Functions Typedefs
Ead.h
00001 /*
00002  * Ead.h
00003  *
00004  * Adapted from ead~.c puredata external (creb library)
00005  * Copyright (c) 2000-2003 by Tom Schouten
00006  *
00007  * Copyright 2012 Tim Barrass, 2000-2003 Tom Schouten
00008  *
00009  * This file is part of Mozzi.
00010  *
00011  * Mozzi is free software: you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation, either version 3 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * Mozzi is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with Mozzi.  If not, see <http://www.gnu.org/licenses/>.
00023  *
00024  */
00025 
00026 #ifndef EAD_H_
00027 #define EAD_H_
00028 
00029 #include "math.h"
00030 #include "fixedMath.h"
00031 
00032 
00040 class Ead
00041 {
00042 
00043 public:
00044 
00052                 Ead(unsigned int update_rate);
00053 
00054 
00058                 inline
00059                 void setAttack(unsigned int attack_ms)
00060                 {
00061                                 Q8n8attack = float_to_Q8n8(millisToOneMinusRealPole(attack_ms));
00062                 }
00063 
00064 
00068                 inline
00069                 void setDecay(unsigned int decay_ms)
00070                 {
00071                                 Q8n8decay = float_to_Q8n8(millisToOneMinusRealPole(decay_ms));
00072                 }
00073 
00074 
00081                 inline
00082                 void set(unsigned int attack_ms, unsigned int decay_ms)
00083                 {
00084                                 setAttack(attack_ms);
00085                                 setDecay(decay_ms);
00086                 }
00087 
00088 
00091                 inline
00092                 void start()
00093                 {
00094                                 Q8n24state = 0;
00095                                 attack_phase = true;
00096                 }
00097 
00098 
00107                 inline
00108                 void start(unsigned int attack_ms, unsigned int decay_ms)
00109                 {
00110                                 set(attack_ms, decay_ms);
00111                                 Q8n24state = 0;
00112                                 attack_phase = true;
00113                 }
00114 
00115 
00120                 inline
00121                 unsigned char next()
00122                 {
00123                                 if(attack_phase)
00124                                 {
00125                                                 // signed multiply A(a1,b1) * A(a2,b2)=A(a1 +a2 +1,b1 +b2)
00126                                                 Q8n24state += ((Q8n24_FIX1 - Q8n24state) * Q8n8attack) >> 8; // Q8n24, shifts all back into n24
00127                                                 if (Q8n24state >= Q8n24_FIX1-256)
00128                                                 {
00129                                                                 Q8n24state = Q8n24_FIX1-256;
00130                                                                 attack_phase = false;
00131                                                 }
00132                                 }else{ /* decay phase */
00133                                                 Q8n24state -= (Q8n24state * Q8n8decay)>>8;
00134                                 }
00135                                 return Q8n24_to_Q0n8(Q8n24state);
00136                 }
00137 
00138 
00139 private:
00140 
00141                 Q8n8 Q8n8attack;
00142                 Q8n8 Q8n8decay;
00143                 Q8n24 Q8n24state;
00144                 bool attack_phase;
00145                 const unsigned int UPDATE_RATE;
00146 
00147 
00148                 /* convert milliseconds to 1-p, with p a real pole */
00149                 inline
00150                 float millisToOneMinusRealPole(unsigned int milliseconds)
00151                 {
00152                                 static const float NUMERATOR = 1000.0f * log(0.001f);
00153                                 return  -expm1(NUMERATOR / ((float)UPDATE_RATE * milliseconds));
00154                 }
00155 
00156 
00157                 // Compute exp(x) - 1 without loss of precision for small values of x.
00158                 inline
00159                 float expm1(float x)
00160                 {
00161                                 if (fabs(x) < 1e-5)
00162                                 {
00163                                                 return x + 0.5*x*x;
00164                                 }
00165                                 else
00166                                 {
00167                                                 return exp(x) - 1.0;
00168                                 }
00169                 }
00170 
00171 };
00172 
00173 #endif /* EAD_H_ */