Mozzi  version v1.1.0
sound synthesis library for Arduino
MozziGuts.h
1 /*
2  * MozziGuts.h
3  *
4  * Copyright 2012 Tim Barrass.
5  *
6  * This file is part of Mozzi.
7  *
8  * Mozzi by Tim Barrass is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
9  *
10  */
11 
12 #ifndef MOZZIGUTS_H_
13 #define MOZZIGUTS_H_
14 
15 //#define F_CPU 8000000 // testing
16 
17 #if ARDUINO >= 100
18  #include "Arduino.h"
19 #else
20  #include "WProgram.h"
21 #endif
22 
23 #include "hardware_defines.h"
24 
25 #if IS_TEENSY3() || IS_TEENSY4()
26 // required from http://github.com/pedvide/ADC for Teensy 3.*
27 #include <ADC.h>
28 #endif
29 
30 #include "mozzi_analog.h"
31 
32 #if not defined (CONTROL_RATE)
33 /** @ingroup core
34 Control rate setting.
35 Mozzi's CONTROL_RATE sets how many times per second updateControl() is called.
36 CONTROL_RATE has a default of 64 Hz, but it can be changed at the top of your sketch,
37 (before the \#includes), for example: \#define CONTROL_RATE 256.
38 It is useful to have CONTROL_RATE set at a power of 2 (such as 64,128,256 etc),
39 to have exact timing of audio and control operations.
40 Non-power-of-2 CONTROL_RATE can cause glitches due to audio and control
41 events not lining up precisely. If this happens a power of two CONTROL_RATE might solve it.
42 Try to keep CONTROL_RATE low, for efficiency, though higher rates up to about 1000
43 can sometimes give smoother results, avoiding the need to interpolate
44 sensitive variables at audio rate in updateAudio().
45 */
46 #define CONTROL_RATE 64
47 #endif
48 
49 
50 
51 /** @ingroup core
52 Used to set AUDIO_MODE to STANDARD, STANDARD_PLUS, or HIFI.
53 
54 STANDARD / STANDARD_PLUS
55 ---------------
56 Use \#define AUDIO_MODE STANDARD_PLUS in Mozzi/config.h to select this
57 output configuration, which is nearly 9 bit sound (-244 to 243) at 16384 Hz sample rate (AUDIO_RATE) and
58 32768 Hz PWM rate. It uses Timer 1 for PWM and the sample updating routine (as an interrupt).
59 
60 STANDARD is obsolete now, replaced by STANDARD_PLUS which is the default audio mode.
61 STANDARD mode uses 16384 Hz PWM rate with an output interrupt at the same frequency.
62 Some people can hear the PWM carrier frequency as an annoying whine.
63 
64 STANDARD_PLUS mode uses 32768 Hz PWM rate, so the PWM carrier is out of hearing range.
65 In this mode every alternate interrupt is used for the sample update (unless you /#define AUDIO_RATE 32768 in mozzi_config.h),
66 which makes it slightly less efficient than STANDARD, but almost always better.
67 
68 Advantages: Only uses one timer for audio, and one output pin.
69 Disadvantages: low dynamic range.
70 
71 Below is a list of the Digital Pins used by Mozzi for STANDARD and STANDARD_PLUS audio out on different boards.
72 Those which have been tested and reported to work have an x.
73 Feedback about others is welcome.
74 
75 Model | Pin | Tested
76 ----- | --- | ------
77 Arduino Uno | 9 | yes
78 Arduino Duemilanove | 9 | yes
79 Arduino Nano | 9 | yes
80 Arduino Pro Mini | 9 | yes
81 Arduino Leonardo | 9 | yes
82 Arduino Mega | 11 | yes
83 Freetronics EtherMega | 11 | yes
84 Ardweeny | 9 | yes
85 Boarduino | 9 | yes
86 Teensy | 14 | -
87 Teensy2 | B5 | yes
88 Teensy2++ | B5(25) | yes
89 Teensy 3.0 3.1 LC 3.2 | DAC/D | yes
90 Teensy 3.4, 3.5 | DAC/D | -
91 Teensy 4.0 4.1 | A8 | yes
92 Gemma M0 | A0 | yes
93 Adafruit Playground Express | Built in Speaker | yes
94 Sanguino | 13 | -
95 STM32duino (see "Hardware specific notes", below) | PB8 | yes
96 ESP8266 *see details in README* | GPIO2 | yes
97 RP2040 | 0 | yes
98 
99 
100 On Teensy 3.* STANDARD and STANDARD_PLUS are the same, providing 16384Hz sample rate and 12 bit resolution on pin A14/ADC.
101 The Teensy 3.* DAC output does not rely on PWM.
102 
103 
104 @ingroup core
105 
106 Used to set AUDIO_MODE to HIFI.
107 
108 HIFI for AVR and STM32 (not for Teensy 3.*)
109 ----
110 Use \#define AUDIO_MODE HIFI in Mozzi/config.h to set the audio mode to HIFI for output 14 bit sound at 16384 Hz sample rate and 125kHz PWM rate.
111 The high PWM rate of HIFI mode places the carrier frequency beyond audible range.
112 
113 Also, 14 bits of dynamic range in HIFI mode provides more definition than the nearly 9 bits in STANDARD_PLUS mode.
114 HIFI mode takes about the same amount of processing time as STANDARD_PLUS mode, and should sound clearer and brighter.
115 However, it requires an extra timer to be used on the Arduino, which could increase the chances of
116 conflicts with other libraries or processes if they rely on Timer 2.
117 
118 Timer 1 is used to provide the PWM output at 125kHz.
119 Timer 2 generates an interrupt at AUDIO_RATE 16384 Hz, which sets the Timer1 PWM levels.
120 HIFI mode uses 2 output pins, and sums their outputs with resistors, so is slightly less convenient for
121 rapid prototyping where you could listen to STANDARD_PLUS mode by connecting the single output pin
122 directly to a speaker or audio input (though a resistor of about 100 ohms is recommended).
123 
124 The resistors needed for HIFI output are 3.9k and 499k, with 0.5% or better tolerance.
125 If you can only get 1% resistors, use a multimeter to find the most accurate.
126 Use two 1M resistors in parallel if you can't find 499k.
127 
128 On 328 based Arduino boards, output is on Timer1, with the high byte on Pin 9 and low byte on Pin 10.
129 Add the signals through a 3.9k resistor on high byte pin (9) and 499k resistor on low byte pin (10).
130 Also, a 4.7nF capacitor is recommended between the summing junction of the resistors and ground.
131 
132 This dual PWM technique is discussed on http://www.openmusiclabs.com/learning/digital/pwm-dac/dual-pwm-circuits/
133 Also, there are higher quality output circuits are on the site.
134 
135 Advantages: should be higher quality sound than STANDARD_PLUS mode. Doesn't need a notch filter on
136 the audio signal (like STANDARD which is now obsolete) because the carrier frequency is out of hearing range.
137 
138 Disadvantages: requires 2 pins, 2 resistors and a capacitor, so it's not so quick to set up compared
139 to a rough, direct single-pin output in STANDARD_PLUS mode.
140 
141 Pins and where to put the resistors on various boards for HIFI mode.
142 Boards tested in HIFI mode have an x, though most of these have been tested in STANDARD_PLUS mode
143 and there's no reason for them not to work in HIFI (unless the pin number is wrong or something).
144 Any reports are welcome. \n
145 
146 resistor.....3.9k......499k \n
147 x................9..........10...............Arduino Uno \n
148 x................9..........10...............Arduino Duemilanove \n
149 x................9..........10...............Arduino Nano \n
150 x................9..........10...............Arduino Leonardo \n
151 x................9..........10...............Ardweeny \n
152 x................9..........10...............Boarduino \n
153 x...............11.........12...............Freetronics EtherMega \n
154 .................11.........12...............Arduino Mega \n
155 .................14.........15...............Teensy \n
156 .............B5(14)...B6(15)...........Teensy2 \n
157 x...........B5(25)...B6(26)...........Teensy2++ \n
158 .................13.........12...............Sanguino \n
159 
160 HIFI is not available/not required on Teensy 3.* or ARM.
161 */
162 
163 //enum audio_modes {STANDARD,STANDARD_PLUS,HIFI};
164 #define STANDARD 0
165 #define STANDARD_PLUS 1
166 #define HIFI 2
167 
168 //enum audio_channels {MONO,STEREO,...};
169 #define MONO 1
170 #define STEREO 2
171 
172 #include "mozzi_config.h" // User can change the config file to set audio mode
173 
174 #if (AUDIO_MODE == STANDARD) && (AUDIO_RATE == 32768)
175 #error AUDIO_RATE 32768 does not work when AUDIO_MODE is STANDARD, try setting the AUDIO_MODE to STANDARD_PLUS in Mozzi/mozzi_config.h
176 #endif
177 
178 #if (STEREO_HACK == true)
179 #warning Use of STEREO_HACK is deprecated. Use AUDIO_CHANNELS STEREO, instead.
180 #define AUDIO_CHANNELS STEREO
181 #endif
182 #if !defined(AUDIO_CHANNELS)
183 #define AUDIO_CHANNELS MONO
184 #endif
185 
186 #define CLOCK_TICKS_PER_AUDIO_TICK (F_CPU / AUDIO_RATE)
187 
188 
189 #if AUDIO_RATE == 16384
190 #define AUDIO_RATE_AS_LSHIFT 14
191 #define MICROS_PER_AUDIO_TICK 61 // 1000000 / 16384 = 61.035, ...* 256 = 15625
192 #elif AUDIO_RATE == 32768
193 #define AUDIO_RATE_AS_LSHIFT 15
194 #define MICROS_PER_AUDIO_TICK 31 // = 1000000 / 32768 = 30.518, ...* 256 = 7812.6
195 #endif
196 
197 // for compatibility with old (local) versions of mozzi_config.h
198 #if !defined(EXTERNAL_AUDIO_OUTPUT)
199 #define EXTERNAL_AUDIO_OUTPUT false
200 #endif
201 
202 #if (EXTERNAL_AUDIO_OUTPUT != true)
203 #if IS_TEENSY3()
204 #include "AudioConfigTeensy3_12bit.h"
205 #elif IS_TEENSY4()
206 #include "AudioConfigTeensy4.h"
207 #elif IS_STM32()
208 #include "AudioConfigSTM32.h"
209 #elif IS_ESP8266()
210 #include "AudioConfigESP.h"
211 #elif IS_ESP32()
212 #include "AudioConfigESP32.h"
213 #elif IS_SAMD21()
214 #include "AudioConfigSAMD21.h"
215 #elif IS_RP2040()
216 #include "AudioConfigRP2040.h"
217 #elif IS_AVR() && (AUDIO_MODE == STANDARD)
218 #include "AudioConfigStandard9bitPwm.h"
219 #elif IS_AVR() && (AUDIO_MODE == STANDARD_PLUS)
220 #include "AudioConfigStandardPlus.h"
221 #elif IS_AVR() && (AUDIO_MODE == HIFI)
222 #include "AudioConfigHiSpeed14bitPwm.h"
223 #endif
224 #else // EXTERNAL_AUDIO_OUTPUT==true
225 #if !defined(EXTERNAL_AUDIO_BITS)
226 #define EXTERNAL_AUDIO_BITS 16
227 #endif
228 #define AUDIO_BITS EXTERNAL_AUDIO_BITS
229 #define AUDIO_BIAS (1 << (AUDIO_BITS - 1))
230 #endif
231 
232 #if (STEREO_HACK == true)
233 extern int audio_out_1, audio_out_2;
234 #endif
235 
236 #include "AudioOutput.h"
237 
238 // common numeric types
239 typedef unsigned char uchar;
240 typedef unsigned int uint;
241 typedef unsigned long ulong;
242 
243 #if defined(__AVR__)
244 typedef unsigned char byte; // for arduino ide
245 typedef unsigned char uint8_t;
246 typedef signed char int8_t;
247 typedef unsigned int uint16_t;
248 typedef signed int int16_t;
249 typedef unsigned long uint32_t;
250 typedef signed long int32_t;
251 #else
252 // Other supported arches add typedefs, here, unless already defined for that platform needed
253 #endif
254 
255 
256 /** @ingroup core
257 Sets up the timers for audio and control rate processes, storing the timer
258 registers so they can be restored when Mozzi stops. startMozzi() goes in your sketch's
259 setup() routine.
260 
261 Contrary to earlier versions of Mozzi, this version does not take over Timer 0, and thus Arduino
262 functions delay(), millis(), micros() and delayMicroseconds() remain usable in theory. That said,
263 you should avoid these functions, as they are slow (or even blocking). For measuring time, refer
264 to mozziMircos(). For delaying events, you can use Mozzi's EventDelay() unit instead
265 (not to be confused with AudioDelay()).
266 
267 In STANDARD mode, startMozzi() starts Timer 1 for PWM output and audio output interrupts,
268 and in STANDARD_PLUS and HIFI modes, Mozzi uses Timer 1 for PWM and Timer2 for audio interrupts.
269 
270 The audio rate defaults to 16384 Hz, but you can experiment with 32768 Hz by changing AUDIO_RATE in mozzi_config.h.
271 
272 @param control_rate_hz Sets how often updateControl() is called. It must be a power of 2.
273 If no parameter is provided, control_rate_hz is set to CONTROL_RATE,
274 which has a default value of 64 (you can re-\#define it in your sketch).
275 The practical upper limit for control rate depends on how busy the processor is,
276 and you might need to do some tests to find the best setting.
277 
278 @note startMozzi calls setupMozziADC(), which calls setupFastAnalogRead() and adcDisconnectAllDigitalIns(),
279 which disables digital inputs on all analog input pins. All in mozzi_analog.h and easy to change if you need to (hack).
280 They are all called automatically and hidden away because it keeps things simple for a STANDARD_PLUS set up,
281 but if it turns out to be confusing, they might need to become visible again.
282 */
283 void startMozzi(int control_rate_hz = CONTROL_RATE);
284 
285 
286 
287 /** @ingroup core
288 Stops audio and control interrupts and restores the timers to the values they
289 had before Mozzi was started. This could be useful when using sensor libraries
290 which depend on the same timers as Mozzi.
291 
292 A potentially better option for resolving timer conflicts involves using
293 non-blocking methods, such as demonstrated by the twowire_nonblock code in the
294 forked version of Mozzi on github, so sound production can continue while
295 reading sensors.
296 
297 As it is, stopMozzi restores all the Timers used by Mozzi to their previous
298 settings. Another scenario which could be easily hacked in MozziGuts.cpp could
299 involve individually saving and restoring particular Timer registers depending
300 on which one(s) are required for other tasks. */
301 void stopMozzi();
302 
303 
304 /** @ingroup core
305 Obsolete function, use stopMozzi() instead.
306 */
307 void pauseMozzi();
308 
309 //TB2017-19
310 /** @ingroup core
311 Obsolete function, use startMozzi() instead.
312 Restores Mozzi audio and control interrupts, if they have been temporarily
313 disabled with pauseMozzi().
314 */
315 void unPauseMozzi();
316 
317 
318 /** @ingroup core
319 This is where you put your audio code. updateAudio() has to keep up with the
320 AUDIO_RATE of 16384 Hz, so to keep things running smoothly, avoid doing any
321 calculations here which could be done in setup() or updateControl().
322 @return an audio sample. In STANDARD modes this is between -244 and 243 inclusive.
323 In HIFI mode, it's a 14 bit number between -16384 and 16383 inclusive.
324 */
326 
327 /** @ingroup core
328 This is where you put your control code. You need updateControl() somewhere in
329 your sketch, even if it's empty. updateControl() is called at the control rate
330 you set in startMozzi(). To save processor load, avoid any calculations here
331 which could be done in setup().
332 */
333 void updateControl();
334 
335 
336 /** @ingroup core
337 This is required in Arduino's loop(). If there is room in Mozzi's output buffer,
338 audioHook() calls updateAudio() once and puts the result into the output
339 buffer. Also, if \#define USE_AUDIO_INPUT true is in Mozzi/mozzi_config.h,
340 audioHook() takes care of moving audio input from the input buffer so it can be
341 accessed with getAudioInput() in your updateAudio() routine.
342 If other functions are called in loop() along with audioHook(), see if
343 they can be called less often by moving them into updateControl(),
344 to save processing power. Otherwise it may be most efficient to
345 calculate a block of samples at a time by putting audioHook() in a loop of its
346 own, rather than calculating only 1 sample for each time your other functions
347 are called.
348 */
349 void audioHook();
350 
351 
352 
353 /** @ingroup analog
354 This returns audio input from the input buffer, if
355 \#define USE_AUDIO_INPUT true is in the Mozzi/mozzi_config.h file.
356 The pin used for audio input is set in Mozzi/mozzi_config.h with
357 \#define AUDIO_INPUT_PIN 0 (or other analog input pin).
358 The audio signal needs to be in the range 0 to 5 volts.
359 Circuits and discussions about biasing a signal
360 in the middle of this range can be found at
361 http://electronics.stackexchange.com/questions/14404/dc-biasing-audio-signal
362 and
363 http://interface.khm.de/index.php/lab/experiments/arduino-realtime-audio-processing/ .
364 A circuit and instructions for amplifying and biasing a microphone signal can be found at
365 http://www.instructables.com/id/Arduino-Audio-Input/?ALLSTEPS
366 @return audio data from the input buffer
367 */
368 #if (USE_AUDIO_INPUT == true)
369 int getAudioInput();
370 #endif
371 
372 
373 /** @ingroup core
374 An alternative for Arduino time functions like micros() and millis(). This is slightly faster than micros(),
375 and also it is synchronized with the currently processed audio sample (which, due to the audio
376 output buffer, could diverge up to 256/AUDIO_RATE seconds from the current time).
377 audioTicks() is updated each time an audio sample
378 is output, so the resolution is 1/AUDIO_RATE microseconds (61 microseconds when AUDIO_RATE is
379 16384 Hz).
380 @return the number of audio ticks since the program began.
381 */
382 unsigned long audioTicks();
383 
384 
385 
386 /** @ingroup core
387 An alternative for Arduino time functions like micros() and millis(). This is slightly faster than micros(),
388 and also it is synchronized with the currently processed audio sample (which, due to the audio
389 output buffer, could diverge up to 256/AUDIO_RATE seconds from the current time).
390 audioTicks() is updated each time an audio sample
391 is output, so the resolution is 1/AUDIO_RATE microseconds (61 microseconds when AUDIO_RATE is
392 16384 Hz).
393 @return the approximate number of microseconds since the program began.
394 @todo incorporate mozziMicros() in a more accurate EventDelay()?
395 */
396 unsigned long mozziMicros();
397 
398 #endif /* MOZZIGUTS_H_ */
unsigned long mozziMicros()
An alternative for Arduino time functions like micros() and millis().
Definition: MozziGuts.cpp:229
void stopMozzi()
Stops audio and control interrupts and restores the timers to the values they had before Mozzi was st...
#define AUDIO_MODE
AUDIO_MODE holds the audio mode setting.
Definition: mozzi_config.h:28
#define AUDIO_CHANNELS
This sets allows to change from a single/mono audio output channel to stereo output.
Definition: mozzi_config.h:92
#define HIFI
Definition: MozziGuts.h:166
#define IS_SAMD21()
AudioOutput_t updateAudio()
This is where you put your audio code.
#define IS_TEENSY4()
void updateControl()
This is where you put your control code.
#define AUDIO_RATE
Holds the audio rate setting.
Definition: mozzi_config.h:62
#define IS_STM32()
#define STANDARD_PLUS
Definition: MozziGuts.h:165
void audioHook()
This is required in Arduino&#39;s loop().
Definition: MozziGuts.cpp:190
#define IS_AVR()
#define IS_TEENSY3()
#define IS_RP2040()
void unPauseMozzi()
Obsolete function, use startMozzi() instead.
unsigned long audioTicks()
An alternative for Arduino time functions like micros() and millis().
Definition: MozziGuts.cpp:219
#define AudioOutput_t
Representation of an single audio output sample/frame.
Definition: AudioOutput.h:77
void pauseMozzi()
Obsolete function, use stopMozzi() instead.
void startMozzi(int control_rate_hz=CONTROL_RATE)
Sets up the timers for audio and control rate processes, storing the timer registers so they can be r...
Definition: MozziGuts.cpp:234
#define STANDARD
Used to set AUDIO_MODE to STANDARD, STANDARD_PLUS, or HIFI.
Definition: MozziGuts.h:164
#define EXTERNAL_AUDIO_OUTPUT
Defining this option as true in mozzi_config.h allows to completely customize the audio output...
Definition: mozzi_config.h:99
#define IS_ESP8266()
#define IS_ESP32()