Mozzi  version v2.0
sound synthesis library for Arduino
Line.h
1 /*
2  * Line.h
3  *
4  * This file is part of Mozzi.
5  *
6  * Copyright 2012-2024 Tim Barrass and the Mozzi Team
7  *
8  * Mozzi is licensed under the GNU Lesser General Public Licence (LGPL) Version 2.1 or later.
9  *
10  */
11 
12 
13 #ifndef LINE_H_
14 #define LINE_H_
15 
16 #include <Arduino.h>
17 
18 #include<FixMath.h>
19 
20 /** For linear changes with a minimum of calculation at each step. For instance,
21 you can use Line to make an oscillator glide from one frequency to another,
22 pre-calculating the required phase increments for each end and then letting your
23 Line change the phase increment with only a simple addition at each step.
24 @tparam T the type of numbers to use. For example, Line <int> myline; makes a
25 Line which uses ints.
26 @note Watch out for underflows in the internal calcualtion of Line() if you're not
27 using floats (but on the other hand try to avoid lots of floats, they're too slow!).
28 If it seems like the Line() is not working, there's a good chance you need to
29 scale up the numbers you're using, so internal calculations don't get truncated
30 away. Use Mozzi's fixed-point number types in mozzi_fixmath.h, which enable you to
31 represent fractional numbers. Google "fixed point arithmetic" if this is new to
32 you.
33 */
34 
35 
36 
37 
38 template <class T>
39 class Line
40 {
41 private:
42  T current_value;
43  T step_size;
44 
45 public:
46  /** Constructor. Use the template parameter to set the type of numbers you
47  want to use. For example, Line <int> myline; makes a Line which uses ints.
48  */
49  Line ()
50  {
51  ;
52  }
53 
54 
55 
56  /** Increments one step along the line.
57  @return the next value.
58  */
59  inline
60  T next()
61  {
62  current_value += step_size;
63  //Serial.println(current_value);
64  return current_value;
65  }
66 
67 
68 
69  /** Set the current value of the line.
70  The Line will continue incrementing from this
71  value using any previously calculated step size.
72  @param value the number to set the Line's current_value to.
73  */
74  inline
75  void set(T value)
76  {
77  current_value=value;
78  }
79 
80 
81 
82  /** Given a target value and the number of steps to take on the way, this calculates the step size needed to get there from the current value.
83  @param targetvalue the value to move towards.
84  @param num_steps how many steps to take to reach the target.
85  */
86  inline
87  void set(T targetvalue, T num_steps)
88  {
89  if(num_steps) {
90  T numerator = targetvalue-current_value;
91  step_size= numerator/num_steps;
92  } else {
93  step_size = 0;
94  current_value = targetvalue;
95  }
96  }
97 
98  /** Given a new starting value, target value and the number of steps to take on the way, this sets the step size needed to get there.
99  @param startvalue the number to set the Line's current_value to.
100  @param targetvalue the value to move towards.
101  @param num_steps how many steps to take to reach the target.
102  */
103  inline
104  void set(T startvalue, T targetvalue, T num_steps)
105  {
106  set(startvalue);
107  set(targetvalue, num_steps);
108  }
109 };
110 
111 
112 /* unsigned char specialisation (probably not very useful because step size will likely = 0) */
113 template <>
114 class Line <unsigned char>
115 {
116 private:
117  unsigned char current_value;
118  char step_size;
119 
120 public:
121  /** Constructor. Use the template parameter to set the type of numbers you
122  want to use. For example, Line <int> myline; makes a Line which uses ints.
123  */
124  Line ()
125  {
126  ;
127  }
128 
129 
130 
131  /** Increments one step along the line.
132  @return the next value.
133  */
134  inline
135  unsigned char next()
136  {
137  current_value += step_size;
138  return current_value;
139  }
140 
141 
142 
143  /** Set the current value of the line.
144  The Line will continue incrementing from this
145  value using any previously calculated step size.
146  @param value the number to set the Line's current_value to.
147  */
148  inline
149  void set(unsigned char value)
150  {
151  current_value=value;
152  }
153 
154 
155 
156  /** Given a target value and the number of steps to take on the way, this calculates the step size needed to get there from the current value.
157  @param targetvalue the value to move towards.
158  @param num_steps how many steps to take to reach the target.
159  */
160  inline
161  void set(unsigned char targetvalue, unsigned char num_steps)
162  {
163  step_size=(char)((((float)targetvalue-current_value)/num_steps));
164  }
165 
166  /** Given a new starting value, target value and the number of steps to take on the way, this sets the step size needed to get there.
167  @param startvalue the number to set the Line's current_value to.
168  @param targetvalue the value to move towards.
169  @param num_steps how many steps to take to reach the target.
170  */
171  inline
172  void set(unsigned char startvalue, unsigned char targetvalue, unsigned char num_steps)
173  {
174  set(startvalue);
175  set(targetvalue, num_steps);
176  }
177 
178 };
179 
180 
181 /* unsigned int specialisation */
182 template <>
183 class Line <unsigned int>
184 {
185 private:
186  unsigned int current_value;
187  int step_size;
188 
189 public:
190  /** Constructor. Use the template parameter to set the type of numbers you
191  want to use. For example, Line <int> myline; makes a Line which uses ints.
192  */
193  Line ()
194  {
195  ;
196  }
197 
198 
199 
200  /** Increments one step along the line.
201  @return the next value.
202  */
203  inline
204  unsigned int next()
205  {
206  current_value += step_size;
207  return current_value;
208  }
209 
210 
211 
212  /** Set the current value of the line.
213  The Line will continue incrementing from this
214  value using any previously calculated step size.
215  @param value the number to set the Line's current_value to.
216  */
217  inline
218  void set(unsigned int value)
219  {
220  current_value=value;
221  }
222 
223 
224 
225  /** Given a target value and the number of steps to take on the way, this calculates the step size needed to get there from the current value.
226  @param targetvalue the value to move towards.
227  @param num_steps how many steps to take to reach the target.
228  */
229  inline
230  void set(unsigned int targetvalue, unsigned int num_steps)
231  {
232  step_size=(int)((((float)targetvalue-current_value)/num_steps));
233  }
234 
235 
236  /** Given a new starting value, target value and the number of steps to take on the way, this sets the step size needed to get there.
237  @param startvalue the number to set the Line's current_value to.
238  @param targetvalue the value to move towards.
239  @param num_steps how many steps to take to reach the target.
240  */
241  inline
242  void set(unsigned int startvalue, unsigned int targetvalue, unsigned int num_steps)
243  {
244  set(startvalue);
245  set(targetvalue, num_steps);
246  }
247 };
248 
249 
250 
251 
252 
253 /* unsigned long specialisation */
254 template <>
255 class Line <unsigned long>
256 {
257 private:
258  unsigned long current_value;
259  long step_size;
260 
261 public:
262  /** Constructor. Use the template parameter to set the type of numbers you
263  want to use. For example, Line <int> myline; makes a Line which uses ints.
264  */
265  Line ()
266  {
267  ;
268  }
269 
270 
271 
272  /** Increments one step along the line.
273  @return the next value.
274  */
275  inline
276  unsigned long next()
277  {
278  current_value += step_size;
279  return current_value;
280  }
281 
282 
283 
284  /** Set the current value of the line.
285  The Line will continue incrementing from this
286  value using any previously calculated step size.
287  @param value the number to set the Line's current_value to.
288  */
289  inline
290  void set(unsigned long value)
291  {
292  current_value=value;
293  }
294 
295 
296 
297  /** Given a target value and the number of steps to take on the way, this calculates the step size needed to get there from the current value.
298  @param targetvalue the value to move towards.
299  @param num_steps how many steps to take to reach the target.
300  */
301  inline
302  void set(unsigned long targetvalue, unsigned long num_steps)
303  {
304  step_size=(long)((((float)targetvalue-current_value)/num_steps));
305  }
306 
307  /** Given a new starting value, target value and the number of steps to take on the way, this sets the step size needed to get there.
308  @param startvalue the number to set the Line's current_value to.
309  @param targetvalue the value to move towards.
310  @param num_steps how many steps to take to reach the target.
311  */
312  inline
313  void set(unsigned long startvalue, unsigned long targetvalue, unsigned long num_steps)
314  {
315  set(startvalue);
316  set(targetvalue, num_steps);
317  }
318 };
319 
320 
321 /* UFix specialisation */
322 template<int8_t NI, int8_t NF>
323 class Line<UFix<NI, NF>>
324 {
325 private:
326  typedef UFix<NI, NF> internal_type;
327  internal_type current_value;
328  SFix<NI,NF> step_size;
329 
330 public:
331  /** Constructor. Use the template parameter to set the type of numbers you
332  want to use. For example, Line <int> myline; makes a Line which uses ints.
333  */
334  Line (){;}
335 
336  /** Increments one step along the line.
337  @return the next value.
338  */
339  inline
340  internal_type next()
341  {
342  current_value = current_value + step_size;
343  return current_value;
344  }
345 
346  /** Set the current value of the line.
347  The Line will continue incrementing from this
348  value using any previously calculated step size.
349  @param value the number to set the Line's current_value to.
350  */
351  inline
352  void set(internal_type value)
353  {
354  current_value=value;
355  }
356 
357  /** Given a target value and the number of steps to take on the way, this calculates the step size needed to get there from the current value.
358  @param targetvalue the value to move towards.
359  @param num_steps how many steps to take to reach the target as a UFix<_NI,0>
360  */
361  template<int8_t _NI>
362  void set(internal_type targetvalue, UFix<_NI,0> num_steps)
363  {
364  if(num_steps.asRaw()) {
365  auto numerator = targetvalue-current_value;
366  step_size = numerator*num_steps.invAccurate();
367  } else {
368  step_size = 0;
369  current_value = targetvalue;
370  }
371  }
372 
373 
374  /** Given a target value and the number of steps to take on the way, this calculates the step size needed to get there from the current value.
375  @param targetvalue the value to move towards.
376  @param num_steps how many steps to take to reach the target.
377  */
378  template<typename T>
379  void set(internal_type targetvalue, T num_steps)
380  {
381  if(num_steps) {
382  auto numerator = targetvalue-current_value;
383  step_size = internal_type(numerator.asRaw()/num_steps,true);
384  } else {
385  step_size = 0;
386  current_value = targetvalue;
387  }
388  }
389 
390  /** Given a new starting value, target value and the number of steps to take on the way, this sets the step size needed to get there.
391  @param startvalue the number to set the Line's current_value to.
392  @param targetvalue the value to move towards.
393  @param num_steps how many steps to take to reach the target.
394  */
395  template<typename T>
396  void set(internal_type startvalue, internal_type targetvalue, T num_steps)
397  {
398  set(startvalue);
399  set(targetvalue, num_steps);
400  }
401 };
402 
403 
404 /* SFix specialisation (if someone has an idea to avoid duplication with UFix) */
405 template<int8_t NI, int8_t NF>
406 class Line<SFix<NI, NF>>
407 {
408 private:
409  typedef SFix<NI, NF> internal_type;
410  internal_type current_value;
411  SFix<NI+1, NF> step_size;
412 
413 public:
414  /** Constructor. Use the template parameter to set the type of numbers you
415  want to use. For example, Line <int> myline; makes a Line which uses ints.
416  */
417  Line (){;}
418 
419  /** Increments one step along the line.
420  @return the next value.
421  */
422  inline
423  internal_type next()
424  {
425  current_value = current_value + step_size;
426  return current_value;
427  }
428 
429  /** Set the current value of the line.
430  The Line will continue incrementing from this
431  value using any previously calculated step size.
432  @param value the number to set the Line's current_value to.
433  */
434  inline
435  void set(internal_type value)
436  {
437  current_value=value;
438  }
439 
440  /** Given a target value and the number of steps to take on the way, this calculates the step size needed to get there from the current value.
441  @param targetvalue the value to move towards.
442  @param num_steps how many steps to take to reach the target as a UFix<_NI,0>
443  */
444  template<int8_t _NI>
445  void set(internal_type targetvalue, UFix<_NI,0> num_steps)
446  {
447  if(num_steps.asRaw()) {
448  auto numerator = targetvalue-current_value;
449  step_size = numerator*num_steps.invAccurate();
450  } else {
451  step_size = 0;
452  current_value = targetvalue;
453  }
454  }
455 
456 
457  /** Given a target value and the number of steps to take on the way, this calculates the step size needed to get there from the current value.
458  @param targetvalue the value to move towards.
459  @param num_steps how many steps to take to reach the target.
460  */
461  template<typename T>
462  void set(internal_type targetvalue, T num_steps)
463  {
464  if(num_steps) {
465  auto numerator = targetvalue-current_value;
466  step_size = internal_type(numerator.asRaw()/num_steps,true);
467  } else {
468  step_size = 0;
469  current_value = targetvalue;
470  }
471  }
472 
473  /** Given a new starting value, target value and the number of steps to take on the way, this sets the step size needed to get there.
474  @param startvalue the number to set the Line's current_value to.
475  @param targetvalue the value to move towards.
476  @param num_steps how many steps to take to reach the target.
477  */
478  template<typename T>
479  void set(internal_type startvalue, internal_type targetvalue, T num_steps)
480  {
481  set(startvalue);
482  set(targetvalue, num_steps);
483  }
484 };
485 
486 
487 
488 /**
489 @example 02.Control/Control_Tremelo/Control_Tremelo.ino
490 This example demonstrates the Line class.
491 */
492 
493 #endif /* LINE_H_ */