| Mozzi version v1.1.0 sound synthesis library for Arduino |

Oscil.h
1 /*
2 * Oscil.h
3 *
4 * Oscil.h owes much to AF_precision_synthesis.pde, 2009, Adrian Freed.
5 *
6 * Copyright 2012 Tim Barrass, 2009 Adrian Freed.
7 *
8 * This file is part of Mozzi.
9 *
10 * Mozzi is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
11 *
12 */
13
14 #ifndef OSCIL_H_
15 #define OSCIL_H_
16
17 #if ARDUINO >= 100
18 #include "Arduino.h"
19 #else
20 #include "WProgram.h"
21 #endif
22 #include "MozziGuts.h"
23 #include "mozzi_fixmath.h"
24 #include "mozzi_pgmspace.h"
25
26 #ifdef OSCIL_DITHER_PHASE
27 #include "mozzi_rand.h"
28 #endif
29
30 // fractional bits for oscillator index precision
31 #define OSCIL_F_BITS 16
32 #define OSCIL_F_BITS_AS_MULTIPLIER 65536
33
34 // phmod_proportion is an 15n16 fixed-point number
35 #define OSCIL_PHMOD_BITS 16
36
37 /**
38 Oscil plays a wavetable, cycling through the table to generate an audio or
39 control signal. The frequency of the signal can be set or changed with
40 setFreq(), and the output of an Oscil can be produced with next() for a simple
41 cycling oscillator, or atIndex() for a particular sample in the table.
42 @tparam NUM_TABLE_CELLS This is defined in the table ".h" file the Oscil will be
43 using. It's important that it's a power of 2, and either a literal number (eg. "8192") or a
44 defined macro, rather than a const or int, for the Oscil to run fast enough.
45 @tparam UPDATE_RATE This will be AUDIO_RATE if the Oscil is updated in
46 updateAudio(), or CONTROL_RATE if it's updated each time updateControl() is
47 called. It could also be a fraction of CONTROL_RATE if you are doing some kind
48 of cyclic updating in updateControl(), for example, to spread out the processor load.
49 @todo Use conditional compilation to optimise setFreq() variations for different table
50 sizes.
51 @note If you #define OSCIL_DITHER_PHASE before you #include <Oscil.h>,
52 the phase increments will be dithered, which reduces spurious frequency spurs
53 in the audio output, at the cost of some extra processing and memory.
54 @section int8_t2mozzi
55 Converting soundfiles for Mozzi
56 There is a python script called char2mozzi.py in the Mozzi/python folder.
57 The usage is:
58 char2mozzi.py infilename outfilename tablename samplerate
59 */
60 //template <unsigned int NUM_TABLE_CELLS, unsigned int UPDATE_RATE, bool DITHER_PHASE=false>
61 template <uint16_t NUM_TABLE_CELLS, uint16_t UPDATE_RATE>
62 class Oscil
63 {
64
65
66 public:
67 /** Constructor.
68 @param TABLE_NAME the name of the array the Oscil will be using. This
69 can be found in the table ".h" file if you are using a table made for
70 Mozzi by the int8_t2mozzi.py python script in Mozzi's python
71 folder.*/
72 Oscil(const int8_t * TABLE_NAME):table(TABLE_NAME)
73 {}
74
75
76 /** Constructor.
77 Declare an Oscil with template TABLE_NUM_CELLS and UPDATE_RATE
78 parameters, without specifying a particular wave table for it to play.
79 The table can be set or changed on the fly with setTable(). Any tables
80 used by the Oscil must be the same size.
81 */
82 Oscil()
83 {}
84
85
86 /** Updates the phase according to the current frequency and returns the sample at the new phase position.
87 @return the next sample.
88 */
89 inline
90 int8_t next()
91 {
92 incrementPhase();
93 return readTable();
94 }
95
96
97 /** Change the sound table which will be played by the Oscil.
98 @param TABLE_NAME is the name of the array in the table ".h" file you're using.
99 */
100 void setTable(const int8_t * TABLE_NAME)
101 {
102 table = TABLE_NAME;
103 }
104
105
106 /** Set the phase of the Oscil. This does the same thing as Sample::start(offset). Just different ways of thinking about oscillators and samples.
107 @param phase a position in the wavetable.
108 */
109 // This could be called in the control interrupt, so phase_fractional should really be volatile,
110 // but that could limit optimisation. Since phase_fractional gets changed often in updateAudio()
111 // (in loop()), it's probably worth keeping it nonvolatile until it causes problems
112 void setPhase(unsigned int phase)
113 {
114 phase_fractional = (unsigned long)phase << OSCIL_F_BITS;
115 }
116
117 /** Set the phase of the Oscil. Might be useful with getPhaseFractional().
118 @param phase a position in the wavetable.
119 */
120 // This could be called in the control interrupt, so phase_fractional should really be volatile,
121 // but that could limit optimisation. Since phase_fractional gets changed often in updateAudio()
122 // (in loop()), it's probably worth keeping it nonvolatile until it causes problems
123 void setPhaseFractional(unsigned long phase)
124 {
125 phase_fractional = phase;
126 }
127
128
129 /** Get the phase of the Oscil in fractional format.
130 @return position in the wavetable, shifted left by OSCIL_F_BITS (which is 16 when this was written).
131 */
132 unsigned long getPhaseFractional()
133 {
134 return phase_fractional;
135 }
136
137
138
139 /** Returns the next sample given a phase modulation value.
140 @param phmod_proportion a phase modulation value given as a proportion of the wave. The
141 phmod_proportion parameter is a Q15n16 fixed-point number where the fractional
142 n16 part represents almost -1 to almost 1, modulating the phase by one whole table length in
143 each direction.
144 @return a sample from the table.
145 */
146 // PM: cos((angle += incr) + change)
147 // FM: cos(angle += (incr + change))
148 // The ratio of deviation to modulation frequency is called the "index of modulation". ( I = d / Fm )
149 inline
150 int8_t phMod(Q15n16 phmod_proportion)
151 {
152 incrementPhase();
153 return FLASH_OR_RAM_READ<const int8_t>(table + (((phase_fractional+(phmod_proportion * NUM_TABLE_CELLS))>>OSCIL_F_BITS) & (NUM_TABLE_CELLS - 1)));
154 }
155
156
157 /** Set the oscillator frequency with an unsigned int. This is faster than using a
158 float, so it's useful when processor time is tight, but it can be tricky with
159 low and high frequencies, depending on the size of the wavetable being used. If
160 you're not getting the results you expect, try explicitly using a float, or try
161 setFreq_Q24n8() or or setFreq_Q16n16().
162 @param frequency to play the wave table.
163 */
164 inline
165 void setFreq (int frequency) {
166 // TB2014-8-20 change this following Austin Grossman's suggestion on user list
167 // https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/mozzi-users/u4D5NMzVnQs/pCmiWInFvrkJ
168 //phase_increment_fractional = ((((unsigned long)NUM_TABLE_CELLS<<ADJUST_FOR_NUM_TABLE_CELLS)*frequency)/UPDATE_RATE) << (OSCIL_F_BITS - ADJUST_FOR_NUM_TABLE_CELLS);
169 // to this:
170 phase_increment_fractional = ((unsigned long)frequency) * ((OSCIL_F_BITS_AS_MULTIPLIER*NUM_TABLE_CELLS)/UPDATE_RATE);
171 }
172
173
174 /** Set the oscillator frequency with a float. Using a float is the most reliable
175 way to set frequencies, -Might- be slower than using an int but you need either
176 this, setFreq_Q24n8() or setFreq_Q16n16() for fractional frequencies.
177 @param frequency to play the wave table.
178 */
179 inline
180 void setFreq(float frequency)
181 { // 1 us - using float doesn't seem to incur measurable overhead with the oscilloscope
182 phase_increment_fractional = (unsigned long)((((float)NUM_TABLE_CELLS * frequency)/UPDATE_RATE) * OSCIL_F_BITS_AS_MULTIPLIER);
183 }
184
185
186 /** Set the frequency using Q24n8 fixed-point number format.
187 This might be faster than the float version for setting low frequencies such as
188 1.5 Hz, or other values which may not work well with your table size. A Q24n8
189 representation of 1.5 is 384 (ie. 1.5 * 256). Can't be used with UPDATE_RATE
190 less than 64 Hz.
191 @param frequency in Q24n8 fixed-point number format.
192 */
193 inline
194 void setFreq_Q24n8(Q24n8 frequency)
195 {
196 //phase_increment_fractional = (frequency* (NUM_TABLE_CELLS>>3)/(UPDATE_RATE>>6)) << (F_BITS-(8-3+6));
197 // TB2016-10-2 line below might have been left in accidentally while making the 2014 change below, remove for now
198 // phase_increment_fractional = (((((unsigned long)NUM_TABLE_CELLS<<ADJUST_FOR_NUM_TABLE_CELLS)>>3)*frequency)/(UPDATE_RATE>>6))
199 // << (OSCIL_F_BITS - ADJUST_FOR_NUM_TABLE_CELLS - (8-3+6));
200
201 // TB2014-8-20 change this following Austin Grossman's suggestion on user list
202 // https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/mozzi-users/u4D5NMzVnQs/pCmiWInFvrkJ
203 if ((256UL*NUM_TABLE_CELLS) >= UPDATE_RATE) {
204 phase_increment_fractional = ((unsigned long)frequency) * ((256UL*NUM_TABLE_CELLS)/UPDATE_RATE);
205 } else {
206 phase_increment_fractional = ((unsigned long)frequency) / (UPDATE_RATE/(256UL*NUM_TABLE_CELLS));
207 }
208 }
209
210
211 /** Set the frequency using Q16n16 fixed-point number format. This is useful in
212 combination with Q16n16_mtof(), a fast alternative to mtof(), using Q16n16
213 fixed-point format instead of floats.
214 @note This should work OK with tables 2048 cells or smaller and
215 frequencies up to 4096 Hz. Can't be used with UPDATE_RATE less than 64 Hz.
216 @note This didn't run faster than float last time it was tested, after 2014 code changes. Need to see if 2014 changes improved or worsened performance.
217 @param frequency in Q16n16 fixed-point number format.
218 */
219 inline
220 void setFreq_Q16n16(Q16n16 frequency)
221 {
222 //phase_increment_fractional = ((frequency * (NUM_TABLE_CELLS>>7))/(UPDATE_RATE>>6)) << (F_BITS-16+1);
223 // TB2014-8-20 change this following Austin Grossman's suggestion on user list
224 // https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/mozzi-users/u4D5NMzVnQs/pCmiWInFvrkJ
225 //phase_increment_fractional = (((((uint32_t)NUM_TABLE_CELLS<<ADJUST_FOR_NUM_TABLE_CELLS)>>7)*frequency)/(UPDATE_RATE>>6))
226 // << (OSCIL_F_BITS - ADJUST_FOR_NUM_TABLE_CELLS - 16 + 1);
227 if (NUM_TABLE_CELLS >= UPDATE_RATE) {
228 phase_increment_fractional = ((unsigned long)frequency) * (NUM_TABLE_CELLS/UPDATE_RATE);
229 } else {
230 phase_increment_fractional = ((unsigned long)frequency) / (UPDATE_RATE/NUM_TABLE_CELLS);
231 }
232 }
233 /*
234 inline
235 void setFreqMidi(int8_t note_num) {
236 setFreq_Q16n16(mtof(note_num));
237 }
238 */
239 /** Returns the sample at the given table index.
240 @param index between 0 and the table size.The
241 index rolls back around to 0 if it's larger than the table size.
242 @return the sample at the given table index.
243 */
244 inline
245 int8_t atIndex(unsigned int index)
246 {
247 return FLASH_OR_RAM_READ<const int8_t>(table + (index & (NUM_TABLE_CELLS - 1)));
248 }
249
250
251 /** phaseIncFromFreq() and setPhaseInc() are for saving processor time when sliding between frequencies.
252 Instead of recalculating the phase increment for each
253 frequency in between, you can just calculate the phase increment for each end
254 frequency with phaseIncFromFreq(), then use a Line to interpolate on the fly and
255 use setPhaseInc() to set the phase increment at each step. (Note: I should
256 really profile this with the oscilloscope to see if it's worth the extra
257 confusion!)
258 @param frequency for which you want to calculate a phase increment value.
259 @return the phase increment value which will produce a given frequency.
260 */
261 inline
262 unsigned long phaseIncFromFreq(int frequency)
263 {
264 // TB2014-8-20 change this following Austin Grossman's suggestion on user list
265 // https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/mozzi-users/u4D5NMzVnQs/pCmiWInFvrkJ
266 //return (((unsigned long)frequency * NUM_TABLE_CELLS)/UPDATE_RATE) << OSCIL_F_BITS;
267 return ((unsigned long)frequency) * ((OSCIL_F_BITS_AS_MULTIPLIER*NUM_TABLE_CELLS)/UPDATE_RATE);
268 }
269
270
271 /** Set a specific phase increment. See phaseIncFromFreq().
272 @param phaseinc_fractional a phase increment value as calculated by phaseIncFromFreq().
273 */
274 inline
275 void setPhaseInc(unsigned long phaseinc_fractional)
276 {
277 phase_increment_fractional = phaseinc_fractional;
278 }
279
280
281
282 private:
283
284
285 /** Used for shift arithmetic in setFreq() and its variations.
286 */
287 static const uint8_t ADJUST_FOR_NUM_TABLE_CELLS = (NUM_TABLE_CELLS<2048) ? 8 : 0;
288
289
290 /** Increments the phase of the oscillator without returning a sample.
291 */
292 inline
293 void incrementPhase()
294 {
295 //phase_fractional += (phase_increment_fractional | 1); // odd phase incr, attempt to reduce frequency spurs in output
296 phase_fractional += phase_increment_fractional;
297 }
298
299
300 /** Returns the current sample.
301 */
302 inline
303 int8_t readTable()
304 {
305 #ifdef OSCIL_DITHER_PHASE
306 return FLASH_OR_RAM_READ<const int8_t>(table + (((phase_fractional + ((int)(xorshift96()>>16))) >> OSCIL_F_BITS) & (NUM_TABLE_CELLS - 1)));
307 #else
308 return FLASH_OR_RAM_READ<const int8_t>(table + ((phase_fractional >> OSCIL_F_BITS) & (NUM_TABLE_CELLS - 1)));
309 //return FLASH_OR_RAM_READ<int8_t>(table + (((phase_fractional >> OSCIL_F_BITS) | 1 ) & (NUM_TABLE_CELLS - 1))); odd phase, attempt to reduce frequency spurs in output
310 #endif
311 }
312
313
314 unsigned long phase_fractional;
315 unsigned long phase_increment_fractional;
316 const int8_t * table;
317
318 };
319
320
321 /**
322 @example 01.Basics/Vibrato/Vibrato.ino
323 This is an example using Oscil::phMod to produce vibrato using phase modulation.
324 */
325
326 #endif /* OSCIL_H_ */
Oscil::next
int8_t next()
Updates the phase according to the current frequency and returns the sample at the new phase position...
Definition: Oscil.h:90
Oscil::getPhaseFractional
unsigned long getPhaseFractional()
Get the phase of the Oscil in fractional format.
Definition: Oscil.h:132
Oscil
Oscil plays a wavetable, cycling through the table to generate an audio or control signal...
Definition: Oscil.h:62
Oscil::setFreq
void setFreq(int frequency)
Set the oscillator frequency with an unsigned int.
Definition: Oscil.h:165
Oscil::setPhaseFractional
void setPhaseFractional(unsigned long phase)
Set the phase of the Oscil.
Definition: Oscil.h:123
Oscil::phaseIncFromFreq
unsigned long phaseIncFromFreq(int frequency)
phaseIncFromFreq() and setPhaseInc() are for saving processor time when sliding between frequencies...
Definition: Oscil.h:262
Oscil::setPhase
void setPhase(unsigned int phase)
Set the phase of the Oscil.
Definition: Oscil.h:112
OSCIL_F_BITS
#define OSCIL_F_BITS
Definition: Oscil.h:31
Oscil::phMod
int8_t phMod(Q15n16 phmod_proportion)
Returns the next sample given a phase modulation value.
Definition: Oscil.h:150
Oscil::Oscil
Oscil(const int8_t *TABLE_NAME)
Constructor.
Definition: Oscil.h:72
Oscil::setTable
void setTable(const int8_t *TABLE_NAME)
Change the sound table which will be played by the Oscil.
Definition: Oscil.h:100
Oscil::setFreq
void setFreq(float frequency)
Set the oscillator frequency with a float.
Definition: Oscil.h:180
Oscil::atIndex
int8_t atIndex(unsigned int index)
Returns the sample at the given table index.
Definition: Oscil.h:245
OSCIL_F_BITS_AS_MULTIPLIER
#define OSCIL_F_BITS_AS_MULTIPLIER
Definition: Oscil.h:32
Q24n8
uint32_t Q24n8
unsigned fractional number using 24 integer bits and 8 fractional bits, represents 0 to 16777215 ...
Definition: mozzi_fixmath.h:45
Oscil::setFreq_Q16n16
void setFreq_Q16n16(Q16n16 frequency)
Set the frequency using Q16n16 fixed-point number format.
Definition: Oscil.h:220
Oscil::setPhaseInc
void setPhaseInc(unsigned long phaseinc_fractional)
Set a specific phase increment.
Definition: Oscil.h:275
Q16n16
uint32_t Q16n16
unsigned fractional number using 16 integer bits and 16 fractional bits, represents 0 to 65535...
Definition: mozzi_fixmath.h:46
Oscil::Oscil
Oscil()
Constructor.
Definition: Oscil.h:82
Oscil::setFreq_Q24n8
void setFreq_Q24n8(Q24n8 frequency)
Set the frequency using Q24n8 fixed-point number format.
Definition: Oscil.h:194