Mozzi  version v1.1.0
sound synthesis library for Arduino
MetaOscil.h
1 /*
2  * MetaOscil.h
3  *
4  * A wrap-up to swap between different oscillators seemlessly, allowing to produce non-aliased sounds by automatically switching between oscillators.
5  *
6  * This file is part of Mozzi.
7  */
8 
9 #ifndef META_OSCIL_H
10 #define META_OSCIL_H
11 
12 
13 #if ARDUINO >= 100
14 #include "Arduino.h"
15 #else
16 #include "WProgram.h"
17 #endif
18 
19 #include "Oscil.h"
20 #include "mozzi_fixmath.h"
21 
22 
23 /**
24  MetaOscil is a wrapper for several Oscil. Once constructed it will behave exactly as an Oscil except that it will automatically switch between Oscil depending on the asked frequency. This allows to produce non-aliased sounds by switching between tables with less and less harmonics as the frequency increases.
25 */
26 
27 
28 template<uint16_t NUM_TABLE_CELLS, uint16_t UPDATE_RATE, byte N_OSCIL>
29  class MetaOscil
30 
31 {
32  public:
33  /** Constructor
34  Declare a MetaOscil containing any number of Oscil pointers. Every Oscil should have the same TABLE_NUM_CELLS and UPDATE_RATE which are also passed in the MetaOscil constructor.
35  @param N_OSCIL is the number of Oscil contained in the MetaOscil. This cannot be changed after construction. */
36  template<class... T> MetaOscil(Oscil<NUM_TABLE_CELLS, UPDATE_RATE>* first, T*... elements):oscillators{first, elements...} {
38 
39  MetaOscil(){};
40 
41  /* Add one oscil to the MetaOscil.
42  @param osc is a pointer toward an Oscil
43  @param cutoff_freq is the cutoff frequency of this Oscil
44  void addOscil(Oscil<NUM_TABLE_CELLS, UPDATE_RATE>* osc, int cutoff_freq)
45  {
46  oscillators[current_rank] = osc;
47  cutoff_freqs[current_rank] = cutoff_freq;
48  if (current_rank == 0) current_osc=oscillators[0];
49  current_rank += 1;
50  }*/
51 
52 
53  /** Set all Oscil of a MetaOscil.
54  @param first... is a list of pointers towards several Oscil */
55  template<typename ... T > void setOscils(Oscil<NUM_TABLE_CELLS, UPDATE_RATE>* first,T... elements)
56  {
57  oscillators[current_rank]=first;
58  if (current_rank == 0) current_osc=oscillators[0];
59  current_rank+=1;
60  setOscils(elements...);
61  current_rank = 0;
62  }
63 
64  void setOscils(){};
65 
66 
67  /** Set all the cutoff frequencies for changing between Oscil. They have to be sorted in increasing values and contain at least N_OSCIL-1 values. Note that the last Oscil will be used by default for frequencies higher than the higher cutoff, hence the last value can be discarded.
68  @param first, elements... a set of int cutoff frequencies.*/
69  template<typename ... T > void setCutoffFreqs(int first,T... elements)
70  {
71  cutoff_freqs[current_rank]=first;
72  current_rank+=1;
73  setCutoffFreqs(elements...);
74  current_rank = 0;
75  }
76 
77  void setCutoffFreqs() {};
78 
79  /** Set or change the cutoff frequency of one Oscil.
80  @param rank is the rank of the Oscil.
81  @param freq is the cutoff frequency. */
82  void setCutoffFreq(int freq, byte rank)
83  {
84  cutoff_freqs[rank] = freq;
85  }
86 
87  /** Updates the phase according to the current frequency and returns the sample at the new phase position.
88  @return the next sample.
89  */
90  inline
91  int8_t next() {return current_osc->next();}
92 
93  /** Change the sound table which will be played by the Oscil of rank.
94  @param TABLE_NAME is the name of the array in the table ".h" file you're using.
95  @param rank is the Oscil.*/
96  void setTable(const int8_t * TABLE_NAME, byte rank) {oscillators[rank]->setTable(TABLE_NAME);}
97 
98 
99  /** Set the phase of the currently playing Oscil.
100  @param phase a position in the wavetable.*/
101  void setPhase(unsigned int phase) {current_osc->setPhase(phase);}
102 
103 
104  /** Set the phase of the currently playing Oscil in fractional format.
105  @param phase a position in the wavetable.*/
106  void setPhaseFractional(unsigned long phase) {current_osc->setPhaseFractional(phase);}
107 
108 
109  /** Get the phase of the currently playin Oscil in fractional format.
110  @return position in the wavetable, shifted left by OSCIL_F_BITS (which is 16 when this was written).
111  */
112  unsigned long getPhaseFractional() {return current_osc->getPhaseFractional();}
113 
114 
115 
116  /** Returns the next sample given a phase modulation value.
117  @param phmod_proportion a phase modulation value given as a proportion of the wave. The
118  phmod_proportion parameter is a Q15n16 fixed-point number where the fractional
119  n16 part represents almost -1 to almost 1, modulating the phase by one whole table length in
120  each direction.
121  @return a sample from the table.*/
122  inline
123  int8_t phMod(Q15n16 phmod_proportion) {return current_osc->phMod(phmod_proportion);}
124 
125 
126  /** Set the MetaOsc frequency with an unsigned int.
127  @param frequency to play the wave table.*/
128  inline
129  void setFreq(int frequency, bool apply = true)
130  {
131  if (frequency < cutoff_freqs[0]) //getting out the extreme cases
132  {
133  oscillators[0]->setPhaseFractional(current_osc->getPhaseFractional());
134  current_osc = oscillators[0];
135  current_osc->setFreq(frequency);
136  }
137 
138  else if (frequency > cutoff_freqs[N_OSCIL-1])
139  {
140  oscillators[N_OSCIL-1]->setPhaseFractional(current_osc->getPhaseFractional());
141  current_osc = oscillators[N_OSCIL-1];
142  current_osc->setFreq(frequency);
143  }
144  else // dichotomic search
145  {
146  byte low_point = 0, high_point = N_OSCIL-1, mid_point = (N_OSCIL-1)>>1;
147  while(low_point != high_point)
148  {
149  if (frequency > cutoff_freqs[mid_point]) low_point = mid_point+1;
150  else if (frequency < cutoff_freqs[mid_point]) high_point = mid_point;
151  else
152  {
153  break;
154  }
155  mid_point = (low_point + high_point)>>1;
156  }
157  oscillators[mid_point]->setPhaseFractional(current_osc->getPhaseFractional());
158  current_osc = oscillators[mid_point];
159  if (apply) current_osc->setFreq(frequency);
160  }
161 
162  }
163 
164 
165  /** Set the MetaOsc frequency with a float.
166  @param frequency to play the wave table.*/
167  inline
168  void setFreq(float frequency)
169  {
170  setFreq((int) frequency, false);
171  current_osc->setFreq(frequency);
172  }
173 
174 
175  /** Set the MetaOsc frequency with a Q24n8 fixed-point number format.
176  @param frequency to play the wave table.*/
177  inline
178  void setFreq_Q24n8(Q24n8 frequency)
179  {
180  setFreq((int) (frequency>>8), false);
181  current_osc->setFreq_Q24n8(frequency);
182  }
183 
184 
185  /** Set the MetaOsc frequency with a Q16n16 fixed-point number format.
186  @param frequency to play the wave table.*/
187  inline
188  void setFreq_Q16n16(Q16n16 frequency)
189  {
190  setFreq((int) (frequency>>16), false);
191  current_osc->setFreq_Q16n16(frequency);
192  }
193 
194 
195  /** Returns the sample at the given table index of the current Oscil.
196  @param index between 0 and the table size.The
197  index rolls back around to 0 if it's larger than the table size.
198  @return the sample at the given table index.
199  */
200  inline
201  int8_t atIndex(unsigned int index) {return current_osc->atIndex(index);}
202 
203 
204  /** phaseIncFromFreq() and setPhaseInc() are for saving processor time when sliding between frequencies.
205  @param frequency for which you want to calculate a phase increment value.
206  @return the phase increment value which will produce a given frequency.*/
207  inline
208  unsigned long phaseIncFromFreq(int frequency) {return current_osc->phaseIncFromFreq(frequency);}
209 
210  /** Set a specific phase increment.
211  @param phaseinc_fractional a phase increment value as calculated by phaseIncFromFreq().
212  */
213  inline
214  void setPhaseInc(unsigned long phaseinc_fractional) {current_osc->setPhaseInc(phaseinc_fractional);}
215 
216 
217 
218  private:
219  Oscil<NUM_TABLE_CELLS, UPDATE_RATE> * oscillators[N_OSCIL];
220  Oscil<NUM_TABLE_CELLS, UPDATE_RATE> * current_osc = NULL;
221  int cutoff_freqs[N_OSCIL];
222  byte current_rank = 0;
223 
224 };
225 
226 /**
227 @example 06.Synthesis/NonAlias_MetaOscil/NonAlias_MetaOscil.ino
228 This example demonstrates the Meta_Oscil class.
229 */
230 
231 #endif /* META_OSCIL_H */
void setPhaseInc(unsigned long phaseinc_fractional)
Set a specific phase increment.
Definition: MetaOscil.h:214
void setFreq(int frequency, bool apply=true)
Set the MetaOsc frequency with an unsigned int.
Definition: MetaOscil.h:129
void setFreq(float frequency)
Set the MetaOsc frequency with a float.
Definition: MetaOscil.h:168
void setFreq_Q24n8(Q24n8 frequency)
Set the MetaOsc frequency with a Q24n8 fixed-point number format.
Definition: MetaOscil.h:178
Oscil plays a wavetable, cycling through the table to generate an audio or control signal...
Definition: Oscil.h:62
void setCutoffFreqs(int first, T... elements)
Set all the cutoff frequencies for changing between Oscil.
Definition: MetaOscil.h:69
void setCutoffFreq(int freq, byte rank)
Set or change the cutoff frequency of one Oscil.
Definition: MetaOscil.h:82
int8_t atIndex(unsigned int index)
Returns the sample at the given table index of the current Oscil.
Definition: MetaOscil.h:201
void setOscils(Oscil< NUM_TABLE_CELLS, UPDATE_RATE > *first, T... elements)
Set all Oscil of a MetaOscil.
Definition: MetaOscil.h:55
unsigned long getPhaseFractional()
Get the phase of the currently playin Oscil in fractional format.
Definition: MetaOscil.h:112
int8_t phMod(Q15n16 phmod_proportion)
Returns the next sample given a phase modulation value.
Definition: MetaOscil.h:123
void setPhaseFractional(unsigned long phase)
Set the phase of the currently playing Oscil in fractional format.
Definition: MetaOscil.h:106
MetaOscil(Oscil< NUM_TABLE_CELLS, UPDATE_RATE > *first, T *... elements)
Constructor Declare a MetaOscil containing any number of Oscil pointers.
Definition: MetaOscil.h:36
uint32_t Q24n8
unsigned fractional number using 24 integer bits and 8 fractional bits, represents 0 to 16777215 ...
Definition: mozzi_fixmath.h:45
void setPhase(unsigned int phase)
Set the phase of the currently playing Oscil.
Definition: MetaOscil.h:101
unsigned long phaseIncFromFreq(int frequency)
phaseIncFromFreq() and setPhaseInc() are for saving processor time when sliding between frequencies...
Definition: MetaOscil.h:208
uint32_t Q16n16
unsigned fractional number using 16 integer bits and 16 fractional bits, represents 0 to 65535...
Definition: mozzi_fixmath.h:46
void setTable(const int8_t *TABLE_NAME, byte rank)
Change the sound table which will be played by the Oscil of rank.
Definition: MetaOscil.h:96
MetaOscil is a wrapper for several Oscil.
Definition: MetaOscil.h:29
int8_t next()
Updates the phase according to the current frequency and returns the sample at the new phase position...
Definition: MetaOscil.h:91
void setFreq_Q16n16(Q16n16 frequency)
Set the MetaOsc frequency with a Q16n16 fixed-point number format.
Definition: MetaOscil.h:188