Mozzi  version 2016-12-11-17:03
sound synthesis library for Arduino
MultiLine.h
1 /*
2  * MultiLine.h
3  *
4  * Copyright 2012-2015 Tim Barrass.
5  *
6  * This file is part of Mozzi.
7  *
8  * Mozzi is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
9  *
10  */
11 
12 #ifndef MultiLine_H_
13 #define MultiLine_H_
14 
15 #if ARDUINO >= 100
16  #include "Arduino.h"
17 #else
18  #include "WProgram.h"
19 #endif
20 //#include <util/atomic.h>
21 #include "Line.h"
22 #include "mozzi_fixmath.h"
23 
24 
44 template <unsigned int CONTROL_UPDATE_RATE, unsigned int LERP_RATE>
45 class MultiLine
46 {
47 private:
48 
49  const unsigned int LERPS_PER_CONTROL;
50 
51  unsigned int update_step_counter;
52  unsigned int num_update_steps;
53 
54  enum {LINE1,LINE2,LINE3,LINE4,IDLE};
55 
56 
57  struct phase{
58  byte phase_type;
59  unsigned int update_steps;
60  long lerp_steps; // signed, to match params to transition (line) type Q15n16, below
61  Q15n16 level;
62  }target1,target2,target3,target4,idle;
63 
64  phase * current_phase;
65  Line <Q15n16> transition;
66 
67  inline
68  unsigned int convertMsecToControlUpdateSteps(unsigned int msec){
69  return (uint16_t) (((uint32_t)msec*CONTROL_UPDATE_RATE)>>10); // approximate /1000 with shift
70  }
71 
72 
73  inline
74  void setPhase(phase * next_phase) {
75  update_step_counter = 0;
76  num_update_steps = next_phase->update_steps;
77  transition.set(next_phase->level, next_phase->lerp_steps);
78  current_phase = next_phase;
79  }
80 
81 
82 
83  inline
84  void checkForAndSetNextPhase(phase * next_phase) {
85  if (++update_step_counter >= num_update_steps){
86  setPhase(next_phase);
87  }
88  }
89 
90 
91 
92  inline
93  void setTime(phase * p, unsigned int msec)
94  {
95  p->update_steps = convertMsecToControlUpdateSteps(msec);
96  p->lerp_steps = (long) p->update_steps * LERPS_PER_CONTROL;
97  }
98 
99 
100  inline
101  void setUpdateSteps(phase * p, unsigned int steps)
102  {
103  p->update_steps = steps;
104  p->lerp_steps = (long) steps * LERPS_PER_CONTROL;
105  }
106 
107 
108 
109 public:
110 
113  MultiLine():LERPS_PER_CONTROL(LERP_RATE/CONTROL_UPDATE_RATE)
114  {
115  target1.phase_type = LINE1;
116  target2.phase_type = LINE2;
117  target3.phase_type = LINE3;
118  target4.phase_type = LINE4;
119  idle.phase_type = IDLE;
120  target4.level = 0;
121  }
122 
123 
124 
128  void update(){ // control rate
129 
130  switch(current_phase->phase_type) {
131 
132  case LINE1:
133  checkForAndSetNextPhase(&target2);
134  break;
135 
136  case LINE2:
137  checkForAndSetNextPhase(&target3);
138  break;
139 
140  case LINE3:
141  checkForAndSetNextPhase(&target4);
142  break;
143 
144  case LINE4:
145  checkForAndSetNextPhase(&idle);
146  //checkForAndSetIdle();
147  break;
148 
149  case IDLE:
150  break;
151  }
152  }
153 
154 
155 
160  inline
162  {
163  return transition.next();
164  }
165 
166 
167 
170  inline
171  void start(){
172  setPhase(&target1);
173  }
174 
175 
176 
180  inline
181  void stop(){
182  setPhase(&target4);
183  }
184 
185 
186 
190  inline
192  {
193  target1.level=value;
194  }
195 
196 
197 
201  inline
203  {
204  target2.level=value;
205  }
206 
207 
212  inline
214  {
215  target3.level=value;
216  }
217 
222  inline
224  {
225  target4.level=value;
226  }
227 
228 
229  inline
230  void setIdleLevel(Q15n16 value)
231  {
232  idle.level=value;
233  }
234 
235 
242  inline
243  void setLevels(Q15n16 target1, Q15n16 target2, Q15n16 target3, Q15n16 target4)
244  {
245  setTarget1Level(target1);
246  setTarget2Level(target2);
247  setTarget3Level(target3);
248  setTarget4Level(target4);
249  setIdleLevel(0);
250  }
251 
252 
259  inline
260  void setTarget1Time(unsigned int msec)
261  {
262  setTime(&target1, msec);
263  }
264 
265 
272  inline
273  void setTarget2Time(unsigned int msec)
274  {
275  setTime(&target2, msec);
276  }
277 
278 
286  inline
287  void setTarget3Time(unsigned int msec)
288  {
289  setTime(&target3, msec);
290  }
291 
292 
293 
300  inline
301  void setTarget4Time(unsigned int msec)
302  {
303  setTime(&target4, msec);
304  }
305 
306 
307  inline
308  void setIdleTime(unsigned int msec)
309  {
310  setTime(&idle, msec);
311  }
312 
313 
323  inline
324  void setTimes(unsigned int target1_ms, unsigned int target2_ms, unsigned int target3_ms, unsigned int target4_ms)
325  {
326  setTarget1Time(target1_ms);
327  setTarget2Time(target2_ms);
328  setTarget3Time(target3_ms);
329  setTarget4Time(target4_ms);
330  setIdleTime(65535); // guarantee step size of line will be 0
331  }
332 
333 
334 
338  inline
339  void setTarget1UpdateSteps(unsigned int steps)
340  {
341  setUpdateSteps(&target1, steps);
342  }
343 
344 
348  inline
349  void setTarget2UpdateSteps(unsigned int steps)
350  {
351  setUpdateSteps(&target2, steps);
352  }
353 
354 
358  inline
359  void setTarget3UpdateSteps(unsigned int steps)
360  {
361  setUpdateSteps(&target3, steps);
362  }
363 
364 
368  inline
369  void setTarget4UpdateSteps(unsigned int steps)
370  {
371  setUpdateSteps(&target4, steps);
372  }
373 
374 
375  inline
376  void setIdleUpdateSteps(unsigned int steps)
377  {
378  setUpdateSteps(&idle, steps);
379  }
380 
387  inline
388  void setAllUpdateSteps(unsigned int target1_steps, unsigned int target2_steps, unsigned int target3_steps, unsigned int target4_steps)
389  {
390  setTarget1UpdateSteps(target1_steps);
391  setTarget2UpdateSteps(target2_steps);
392  setTarget3UpdateSteps(target3_steps);
393  setTarget4UpdateSteps(target4_steps);
394  setIdleUpdateSteps(65535); // guarantee? step size of line will be 0?
395  }
396 
397 
398 
402  inline
403  bool playing()
404  {
405  return !(current_phase->phase_type==IDLE);
406  }
407 
408 
409 };
410 
411 
416 #endif /* MultiLine_H_ */
void set(T value)
Set the current value of the line.
Definition: Line.h:77
void setTarget3Level(Q15n16 value)
Set the target3 level of the MultiLine.
Definition: MultiLine.h:213
void setTarget3Time(unsigned int msec)
Set the target3 time of the MultiLine in milliseconds.
Definition: MultiLine.h:287
int32_t Q15n16
signed fractional number using 15 integer bits and 16 fractional bits, represents -32767...
Definition: mozzi_fixmath.h:40
void setTarget2Level(Q15n16 value)
Set the target2 level of the MultiLine.
Definition: MultiLine.h:202
void stop()
Start the target4 phase of the MultiLine.
Definition: MultiLine.h:181
bool playing()
Tells if the envelope is currently playing.
Definition: MultiLine.h:403
MultiLine()
Constructor.
Definition: MultiLine.h:113
void setTarget4UpdateSteps(unsigned int steps)
Set the target4 time of the MultiLine, expressed as the number of update steps (not MultiLine::next()...
Definition: MultiLine.h:369
void setTarget4Time(unsigned int msec)
Set the target4 time of the MultiLine in milliseconds.
Definition: MultiLine.h:301
void update()
Updates the internal controls of the MultiLine.
Definition: MultiLine.h:128
void setTarget2Time(unsigned int msec)
Set the target2 time of the MultiLine in milliseconds.
Definition: MultiLine.h:273
A simple MultiLine envelope generator.
Definition: MultiLine.h:45
void setTarget1Level(Q15n16 value)
Set the target1 level of the MultiLine.
Definition: MultiLine.h:191
void setTarget3UpdateSteps(unsigned int steps)
Set the target3 time of the MultiLine, expressed as the number of update steps (not MultiLine::next()...
Definition: MultiLine.h:359
Q15n16 next()
Advances one step along the MultiLine and returns the level.
Definition: MultiLine.h:161
void setTimes(unsigned int target1_ms, unsigned int target2_ms, unsigned int target3_ms, unsigned int target4_ms)
Set the target1, target2 and target4 times of the MultiLine in milliseconds.
Definition: MultiLine.h:324
void setTarget4Level(Q15n16 value)
Set the target4 level of the MultiLine.
Definition: MultiLine.h:223
void setTarget2UpdateSteps(unsigned int steps)
Set the target2 time of the MultiLine, expressed as the number of update steps (not MultiLine::next()...
Definition: MultiLine.h:349
void setAllUpdateSteps(unsigned int target1_steps, unsigned int target2_steps, unsigned int target3_steps, unsigned int target4_steps)
Set the target1, target2 and target4 times of the MultiLine, expressed in update steps (not MultiLine...
Definition: MultiLine.h:388
void start()
Start the target1 phase of the MultiLine.
Definition: MultiLine.h:171
void setTarget1Time(unsigned int msec)
Set the target1 time of the MultiLine in milliseconds.
Definition: MultiLine.h:260
void setTarget1UpdateSteps(unsigned int steps)
Set the target1 time of the MultiLine, expressed as the number of update steps (not MultiLine::next()...
Definition: MultiLine.h:339
void setLevels(Q15n16 target1, Q15n16 target2, Q15n16 target3, Q15n16 target4)
Set the target1, target2, target3 and target4 levels.
Definition: MultiLine.h:243
T next()
Increments one step along the line.
Definition: Line.h:59