![]() |
Mozzi
alpha 0.01.1t
sound synthesis library for Arduino
|
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_ */