Mozzi  version v2.0
sound synthesis library for Arduino
Portamento.h
1 /*
2  * Portamento.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 #ifndef PORTAMENTO_H_
13 #define PORTAMENTO_H_
14 
15 #include "mozzi_midi.h"
16 #include "mozzi_fixmath.h"
17 #include "Line.h"
18 
19 /** A simple portamento (pitch slide from one note to the next) effect, useful for note-based applications.
20 */
21 template <unsigned int CONTROL_UPDATE_RATE>
22 class
23  Portamento {
24 
25 public:
26 
27  /** Constructor.
28  */
30  MICROS_PER_CONTROL_STEP(1000000/CONTROL_UPDATE_RATE)
31  {
32  }
33 
34  /** Set how long it will take to slide from note to note, in milliseconds.
35  @param milliseconds
36  */
37  inline
38  void setTime(unsigned int milliseconds){
39  //control_steps_per_portamento = ((long)milliseconds*1000)/MICROS_PER_CONTROL_STEP; // more accurate but slower
40  control_steps_per_portamento = convertMsecToControlSteps(milliseconds);
41  }
42 
43  /** Call this at note-on, it initialises the portamento.
44  @param note a midi note number, a whole number.
45  */
46  inline
47  void start(uint8_t note) {
48  target_freq = Q16n16_mtof(Q8n0_to_Q16n16(note));
49  aPortamentoLine.set(target_freq, control_steps_per_portamento);
50  countdown = control_steps_per_portamento;
51  portamento_on=true;
52  }
53 
54  /** Call this at note-on, it initialises the portamento.
55  @param note a midi note number in Q16n16 fractional format. This is useful for non-whole note or detuned values.
56  */
57  inline
58  void start(Q16n16 note) {
59  target_freq = Q16n16_mtof(note);
60  aPortamentoLine.set(target_freq, control_steps_per_portamento);
61  countdown = control_steps_per_portamento;
62  portamento_on=true;
63  }
64 
65 
66  /** Use this in updateControl() to provide a frequency to the oscillator it's controlling.
67  For example:
68  myOscil.setFreq_Q16n16(myPortamento.next());
69  @return a Q16n16 fractional frequency value, progressing smoothly between successive notes.
70  */
71  inline
73  if (portamento_on==true){
74  if(--countdown < 0) {
75  // stay level when portamento has finished
76  aPortamentoLine.set(target_freq, target_freq, control_steps_per_portamento);
77  portamento_on=false;
78  }
79  }
80  return aPortamentoLine.next();
81  }
82 
83  private:
84 
85  int countdown;
86  int control_steps_per_portamento;
87  Q16n16 target_freq;
88  bool portamento_on;
89  const unsigned int MICROS_PER_CONTROL_STEP;
90  Line <Q16n16> aPortamentoLine;
91 
92 
93  // copied from ADSR.h
94  inline
95  static const unsigned int convertMsecToControlSteps(unsigned int msec){
96  return (uint16_t) (((uint32_t)msec*CONTROL_UPDATE_RATE)>>10); // approximate /1000 with shift
97  }
98 
99 };
100 
101 /**
102 @example 05.Control_Filters/Teensy_USB_MIDI_portamento/Teensy_USB_MIDI_portamento.ino
103 This example demonstrates the Portamento class.
104 */
105 
106 #endif /* PORTAMENTO_H_ */