Mozzi  version v2.0
sound synthesis library for Arduino
Ead.h
1 /*
2  * Ead.h
3  *
4  * Adapted from ead~.c puredata external (creb library)
5  *
6  * This file is part of Mozzi.
7  *
8  * Copyright (c) 2000-2003 by Tom Schouten
9  * Copyright 2012 Tim Barrass
10  * Copyright 2012-2024 Tim Barrass and the Mozzi Team
11  *
12  * Mozzi is licensed under the GNU Lesser General Public Licence (LGPL) Version 2.1 or later.
13  *
14  */
15 
16 #ifndef EAD_H_
17 #define EAD_H_
18 
19 #include "math.h"
20 #include "mozzi_fixmath.h"
21 
22 
30 class Ead
31 {
32 
33 public:
34 
42  Ead(unsigned int update_rate) : UPDATE_RATE(update_rate)
43  {
44  ;
45  }
46 
51  inline
52  void setAttack(unsigned int attack_ms)
53  {
54  Q8n8attack = float_to_Q8n8(millisToOneMinusRealPole(attack_ms));
55  }
56 
57 
62  inline
63  void setDecay(unsigned int decay_ms)
64  {
65  Q8n8decay = float_to_Q8n8(millisToOneMinusRealPole(decay_ms));
66  }
67 
68 
75  inline
76  void set(unsigned int attack_ms, unsigned int decay_ms)
77  {
78  setAttack(attack_ms);
79  setDecay(decay_ms);
80  }
81 
82 
86  inline
87  void start()
88  {
89  Q8n24state = 0;
90  attack_phase = true;
91  }
92 
93 
101  inline
102  void start(unsigned int attack_ms, unsigned int decay_ms)
103  {
104  set(attack_ms, decay_ms);
105  //Q8n24state = 0; // don't restart from 0, just go from whatever the current level is, to avoid glitches
106  attack_phase = true;
107  }
108 
109 
114  inline
115  uint8_t next()
116  {
117  if(attack_phase)
118  {
119  // multiply A(a1,b1) * A(a2,b2) = A(a1+a2, b1+b2)
120  Q8n24state += (((Q8n24)(Q8n24_FIX1 - Q8n24state) * Q8n8attack)) >> 8; // Q8n24, shifts all back into n24
121  if (Q8n24state >= Q8n24_FIX1-256)
122  {
123  Q8n24state = Q8n24_FIX1-256;
124  attack_phase = false;
125  }
126  }else{ /* decay phase */
127  Q8n24state -= (Q8n24state * Q8n8decay)>>8;
128  }
129  return Q8n24_to_Q0n8(Q8n24state);
130  }
131 
132 
133 private:
134 
135  Q8n8 Q8n8attack;
136  Q8n8 Q8n8decay;
137  Q8n24 Q8n24state;
138  bool attack_phase;
139  const unsigned int UPDATE_RATE;
140 
141 
142  /* convert milliseconds to 1-p, with p a real pole */
143  inline
144  float millisToOneMinusRealPole(unsigned int milliseconds)
145  {
146  static const float NUMERATOR = 1000.0f * log(0.001f);
147  return -expm1(NUMERATOR / ((float)UPDATE_RATE * milliseconds));
148  }
149 
150 
151  // Compute exp(x) - 1 without loss of precision for small values of x.
152  inline
153  float expm1(float x)
154  {
155  if (fabs(x) < 1e-5)
156  {
157  return x + 0.5*x*x;
158  }
159  else
160  {
161  return exp(x) - 1.0;
162  }
163  }
164 
165 };
166 
172 #endif /* EAD_H_ */
Exponential attack decay envelope.
Definition: Ead.h:31
void start(unsigned int attack_ms, unsigned int decay_ms)
Set attack and decay times in milliseconds, and start the envelope from the beginning.
Definition: Ead.h:102
Ead(unsigned int update_rate)
Constructor.
Definition: Ead.h:42
uint8_t next()
Calculate and return the next envelope value, in the range -128 to 127.
Definition: Ead.h:115
void setAttack(unsigned int attack_ms)
Set the attack time in milliseconds.
Definition: Ead.h:52
void setDecay(unsigned int decay_ms)
Set the decay time in milliseconds.
Definition: Ead.h:63
void start()
Start the envelope from the beginning.
Definition: Ead.h:87
void set(unsigned int attack_ms, unsigned int decay_ms)
Set attack and decay times in milliseconds.
Definition: Ead.h:76
Q0n8 Q8n24_to_Q0n8(Q8n24 a)
Convert Q8n24 fixed to Q0n8 uint8_t.
Q8n8 float_to_Q8n8(float a)
Convert float to Q8n8 fix.
#define Q8n24_FIX1
1 in Q8n24 format
Definition: mozzi_fixmath.h:70
uint32_t Q8n24
signed fractional number using 8 integer bits and 24 fractional bits, represents 0 to 255....
Definition: mozzi_fixmath.h:50
uint16_t Q8n8
unsigned fractional number using 8 integer bits and 8 fractional bits, represents 0 to 255....
Definition: mozzi_fixmath.h:41