Mozzi  version 2016-12-11-17:03
sound synthesis library for Arduino
MultiLine2.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 
45 template <unsigned int NUM_PHASES, unsigned int CONTROL_UPDATE_RATE, unsigned int LERP_RATE>
46 class MultiLine
47 {
48 private:
49 
50  const unsigned int LERPS_PER_CONTROL;
51 
52  unsigned int update_step_counter;
53  unsigned int num_update_steps;
54 
55  //enum {LINE1,LINE2,LINE3,LINE4,IDLE};
56 
57 
58  struct phase{
59  byte phase_type;
60  unsigned int update_steps;
61  long lerp_steps; // signed, to match params to transition (line) type Q15n16, below
62  Q15n16 level;
63  };//target1,target2,target3,target4,idle;
64 
65  phase phases[NUM_PHASES];
66  unsigned int current_phase_num;
67 
68  phase * current_phase;
69 
70  Line <Q15n16> transition;
71 
72 
73  inline
74  unsigned int convertMsecToControlUpdateSteps(unsigned int msec){
75  return (uint16_t) (((uint32_t)msec*CONTROL_UPDATE_RATE)>>10); // approximate /1000 with shift
76  }
77 
78 
79  inline
80  void setPhase(phase * next_phase) {
81  update_step_counter = 0;
82  num_update_steps = next_phase->update_steps;
83  transition.set(next_phase->level, next_phase->lerp_steps);
84  current_phase = next_phase;
85  }
86 
87 
88 
89  inline
90  void checkForAndSetNextPhase() {
91  if (++update_step_counter >= num_update_steps){
92  if(current_phase_num < NUM_PHASES) current_phase_num++;
93  setPhase(&(phases[current_phase_num]));
94  }
95  }
96 
97 
98 
99  inline
100  void setTime(phase * p, unsigned int msec)
101  {
102  p->update_steps = convertMsecToControlUpdateSteps(msec);
103  p->lerp_steps = (long) p->update_steps * LERPS_PER_CONTROL;
104  }
105 
106 
107  inline
108  void setUpdateSteps(phase * p, unsigned int steps)
109  {
110  p->update_steps = steps;
111  p->lerp_steps = (long) steps * LERPS_PER_CONTROL;
112  }
113 
114 
115 
116 public:
117 
120  MultiLine():LERPS_PER_CONTROL(LERP_RATE/CONTROL_UPDATE_RATE)
121  {
122  //for(int i=0;i++;i<NUM_PHASES-1) phases[i].phase_type =
123  // target1.phase_type = LINE1;
124  // target2.phase_type = LINE2;
125  // target3.phase_type = LINE3;
126  // target4.phase_type = LINE4;
127  // idle.phase_type = IDLE;
128  // target4.level = 0;
129  }
130 
131 
132 
136  void update(){ // control rate
137  checkForAndSetNextPhase();
138  //checkForAndSetNextPhase(&(phases[current_phase_num]));
139  /*
140  switch(current_phase->phase_type) {
141 
142  case LINE1:
143  checkForAndSetNextPhase(&target2);
144  break;
145 
146  case LINE2:
147  checkForAndSetNextPhase(&target3);
148  break;
149 
150  case LINE3:
151  checkForAndSetNextPhase(&target4);
152  break;
153 
154  case LINE4:
155  checkForAndSetNextPhase(&idle);
156  //checkForAndSetIdle();
157  break;
158 
159  case IDLE:
160  break;
161  }
162  */
163  }
164 
165 
166 
171  inline
173  {
174  return transition.next();
175  }
176 
177 
178 
181  inline
182  void start(){
183  current_phase_num = 0;
184  setPhase(&(phases[current_phase_num]));
185  }
186 
187 
188 
192  inline
193  void stop(){
194  setPhase(&(phases[NUM_PHASES-1]));
195  }
196 
197 
198 
202  inline
203  void setTargetLevel(uint8_t phase_num, Q15n16 value)
204  {
205  phases[phase_num].level=value;
206  }
207 
208 
209  // /** Set the target levels.
210  // @param target1 the new target1 level.
211  // @param target2 the new target3 level.
212  // @param target1 the new target3 level.
213  // @param target2 the new target4 level.
214  // */
215  // inline
216  // void setLevels(Q15n16 target1, Q15n16 target2, Q15n16 target3, Q15n16 target4)
217  // {
218  // setTarget1Level(target1);
219  // setTarget2Level(target2);
220  // setTarget3Level(target3);
221  // setTarget4Level(target4);
222  // setIdleLevel(0);
223  // }
224 
225 
232  inline
233  void setTargetTime(uint8_t phase_num, unsigned int msec)
234  {
235  setTime(&(phases[phase_num]), msec);
236  }
237 
238 //
239  // /** Set the target1, target2 and target4 times of the MultiLine in milliseconds.
240  // The actual times will be resolved within the resolution of CONTROL_RATE.
241  // @param target1_ms the new target1 time in milliseconds.
242  // @param target2_ms the new target2 time in milliseconds.
243  // @param target3_ms the new target3 time in milliseconds.
244  // @param target4_ms the new target4 time in milliseconds.
245  // @note Beware of low values (less than 20 or so, depending on how many steps are being taken),
246  // in case internal step size gets calculated as 0, which would mean nothing happens.
247  // */
248  // inline
249  // void setTimes(unsigned int target1_ms, unsigned int target2_ms, unsigned int target3_ms, unsigned int target4_ms)
250  // {
251  // setTarget1Time(target1_ms);
252  // setTarget2Time(target2_ms);
253  // setTarget3Time(target3_ms);
254  // setTarget4Time(target4_ms);
255  // setIdleTime(65535); // guarantee step size of line will be 0
256  // }
257 
258 
259 
263  inline
264  void setTargetUpdateSteps(uint8_t phase_num, unsigned int steps)
265  {
266  setUpdateSteps(&(phases[phase_num]), steps);
267  }
268 
269 
270  // /** Set the target1, target2 and target4 times of the MultiLine, expressed in update steps (not MultiLine::next() interpolation steps).
271  // @param target1_steps the number of update steps in the target1 phase
272  // @param target2_steps the number of update steps in the target2 phase
273  // @param target3_steps the number of update steps in the target3 phase
274  // @param target4_steps the number of update steps in the target4 phase
275  // */
276  // inline
277  // void setAllUpdateSteps(unsigned int target1_steps, unsigned int target2_steps, unsigned int target3_steps, unsigned int target4_steps)
278  // {
279  // setTarget1UpdateSteps(target1_steps);
280  // setTarget2UpdateSteps(target2_steps);
281  // setTarget3UpdateSteps(target3_steps);
282  // setTarget4UpdateSteps(target4_steps);
283  // setIdleUpdateSteps(65535); // guarantee? step size of line will be 0?
284  // }
285 
286 
287 
291  inline
292  bool playing()
293  {
294  return current_phase_num != NUM_PHASES-1;
295  }
296 
297 
298 };
299 
300 
305 #endif /* MultiLine_H_ */
void set(T value)
Set the current value of the line.
Definition: Line.h:77
void setTargetLevel(uint8_t phase_num, Q15n16 value)
Set the target1 level of the MultiLine.
Definition: MultiLine2.h:203
int32_t Q15n16
signed fractional number using 15 integer bits and 16 fractional bits, represents -32767...
Definition: mozzi_fixmath.h:40
void stop()
Start the target4 phase of the MultiLine.
Definition: MultiLine2.h:193
bool playing()
Set the target1, target2 and target4 times of the MultiLine, expressed in update steps (not MultiLine...
Definition: MultiLine2.h:292
MultiLine()
Constructor.
Definition: MultiLine2.h:120
void setTargetTime(uint8_t phase_num, unsigned int msec)
Set the target levels.
Definition: MultiLine2.h:233
void update()
Updates the internal controls of the MultiLine.
Definition: MultiLine2.h:136
A simple MultiLine envelope generator.
Definition: MultiLine.h:45
void setTargetUpdateSteps(uint8_t phase_num, unsigned int steps)
Set the target1, target2 and target4 times of the MultiLine in milliseconds.
Definition: MultiLine2.h:264
Q15n16 next()
Advances one step along the MultiLine and returns the level.
Definition: MultiLine2.h:172
void start()
Start the target1 phase of the MultiLine.
Definition: MultiLine2.h:182
T next()
Increments one step along the line.
Definition: Line.h:59