14 #include "CircularBuffer.h"
15 #include "mozzi_analog.h"
16 #include "internal/mozzi_rand_p.h"
17 #include "AudioOutput.h"
28 #if (!BYPASS_MOZZI_OUTPUT_BUFFER)
29 static void CACHED_FUNCTION_ATTR defaultAudioOutput();
31 #if MOZZI_IS(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_STANDARD)
32 static void advanceADCStep();
33 static void startSecondADCReadOnCurrentChannel();
34 static uint8_t adc_count = 0;
38 template<
byte BITS_IN,
byte BITS_OUT,
typename T> constexpr T smartShift(T value) {
39 return (BITS_IN > BITS_OUT) ? value >> (BITS_IN - BITS_OUT) : (BITS_IN < BITS_OUT) ? value << (BITS_OUT - BITS_IN) : value;
45 # include "MozziGuts_impl_AVR.hpp"
47 # include "MozziGuts_impl_STM32.hpp"
49 # include "MozziGuts_impl_STM32duino.hpp"
51 # include "MozziGuts_impl_ESP32.hpp"
53 # include "MozziGuts_impl_ESP8266.hpp"
54 #elif (IS_TEENSY3() || IS_TEENSY4())
55 # include "MozziGuts_impl_TEENSY.hpp"
57 # include "MozziGuts_impl_SAMD.hpp"
59 # include "MozziGuts_impl_RP2040.hpp"
61 # include "MozziGuts_impl_MBED.hpp"
63 # include "MozziGuts_impl_RENESAS.hpp"
65 # include "MozziGuts_impl_CH32.hpp"
67 # error "Platform not (yet) supported. Check MozziGuts_impl_template.hpp and existing implementations for a blueprint for adding your favorite MCU."
73 #if !defined(MOZZI__LEGACY_AUDIO_INPUT_IMPL)
74 # if !MOZZI_IS(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE)
75 # define MOZZI__LEGACY_AUDIO_INPUT_IMPL 1
77 # define MOZZI__LEGACY_AUDIO_INPUT_IMPL 0
83 #if BYPASS_MOZZI_OUTPUT_BUFFER == true
84 uint64_t samples_written_to_buffer = 0;
86 inline void bufferAudioOutput(
const AudioOutput f) {
88 ++samples_written_to_buffer;
92 # define canBufferAudioOutput() (!output_buffer.isFull())
93 # define bufferAudioOutput(f) output_buffer.write(f)
94 static void CACHED_FUNCTION_ATTR defaultAudioOutput() {
96 #if MOZZI_IS(MOZZI__LEGACY_AUDIO_INPUT_IMPL, 1)
99 startSecondADCReadOnCurrentChannel();
101 audioOutput(output_buffer.read());
113 #if MOZZI_IS(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_STANDARD)
116 static volatile uint16_t analog_readings[NUM_ANALOG_INPUTS];
118 volatile static int8_t current_channel = -1;
122 void adcReadSelectedChannels() {
124 if((current_channel = adc_channels_to_read.
pop()) >= 0) adcStartConversion(current_channel);
130 __attribute__((noinline))
void adcStartReadCycle() {
131 if (current_channel < 0)
133 #if MOZZI_IS(MOZZI__LEGACY_AUDIO_INPUT_IMPL, 1)
136 adcReadSelectedChannels();
142 uint16_t mozziAnalogRead(uint8_t pin) {
143 pin = adcPinToChannelNum(pin);
144 adc_channels_to_read.
push(pin);
145 return analog_readings[channelNumToIndex(pin)];
148 #if !MOZZI_IS(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE)
149 static uint16_t audio_input;
153 #if MOZZI_IS(MOZZI__LEGACY_AUDIO_INPUT_IMPL, 1)
156 #define audioInputAvailable() (!input_buffer.isEmpty())
157 #define readAudioInput() (input_buffer.read())
159 inline void advanceADCStep() {
164 input_buffer.write(getADCReading());
165 adcReadSelectedChannels();
171 startSecondADCReadOnCurrentChannel();
176 analog_readings[channelNumToIndex(current_channel)] = getADCReading();
189 inline void advanceADCStep() {
192 startSecondADCReadOnCurrentChannel();
196 analog_readings[channelNumToIndex(current_channel)] = getADCReading();
197 adcReadSelectedChannels();
207 return analogRead(pin);
216 static uint16_t update_control_timeout;
217 static uint16_t update_control_counter;
219 inline void advanceControlLoop() {
220 if (!update_control_counter) {
221 update_control_counter = update_control_timeout;
223 #if MOZZI_IS(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_STANDARD)
227 --update_control_counter;
234 if (canBufferAudioOutput()) {
235 advanceControlLoop();
238 #if defined(LOOP_YIELD)
242 #if !MOZZI_IS(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE)
243 if (audioInputAvailable()) audio_input = readAudioInput();
247 #if defined(AUDIO_HOOK_HOOK)
259 #if (BYPASS_MOZZI_OUTPUT_BUFFER != true)
260 return output_buffer.count();
261 #elif defined(AUDIOTICK_ADJUSTMENT)
262 return samples_written_to_buffer - (AUDIOTICK_ADJUSTMENT);
264 return samples_written_to_buffer;
273 void startMozzi(
int control_rate_hz) {
274 #if !MOZZI_IS(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_NONE)
275 MozziPrivate::setupMozziADC(FAST_ADC);
283 uint32_t MozziRandPrivate::x=132456789;
284 uint32_t MozziRandPrivate::y=362436069;
285 uint32_t MozziRandPrivate::z=521288629;
292 #undef BYPASS_MOZZI_OUTPUT_BUFFER
293 #undef AUDIO_HOOK_HOOK
294 #undef AUDIOTICK_ADJUSTMENT
295 #undef MOZZI__LEGACY_AUDIO_INPUT_IMPL
302 unsigned long mozziMicros() {
return MozziPrivate::mozziMicros(); };
303 unsigned long audioTicks() {
return MozziPrivate::audioTicks(); };
304 void startMozzi(
int control_rate_hz) { MozziPrivate::startMozzi(control_rate_hz); };
306 template<
byte RES> uint16_t
mozziAnalogRead(uint8_t pin) {
return MozziPrivate::smartShift<MOZZI__INTERNAL_ANALOG_READ_RESOLUTION, RES>(MozziPrivate::mozziAnalogRead(pin));};
307 #if !MOZZI_IS(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE)
310 #if MOZZI_IS(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_STANDARD)
311 void setupMozziADC(int8_t speed) { MozziPrivate::setupMozziADC(speed); };
313 uint8_t adcPinToChannelNum(uint8_t pin) {
return MozziPrivate::adcPinToChannelNum(pin); };
318 #if !MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_EXTERNAL_TIMED, MOZZI_OUTPUT_EXTERNAL_CUSTOM)
319 MOZZI_DEPRECATED(
"n/a",
"Sketch has audioOutput() function, although external output is not configured.") void audioOutput(const
AudioOutput) {};
321 #if !MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_EXTERNAL_CUSTOM)
A simple stack, used internally for keeping track of analog input channels as they are read.
void push(T item)
Put an item on the stack.
T pop()
Get the item on top of the stack.
uint16_t getAudioInput()
See getAudioInput().
uint16_t mozziAnalogRead(uint8_t pin)
See mozziAnalogRead().
void setupFastAnalogRead(int8_t speed=FAST_ADC)
This is automatically called in startMozzi.
#define MOZZI_AUDIO_RATE
Defines the audio rate, i.e.
#define MOZZI_AUDIO_INPUT_PIN
This sets which analog input channel to use for audio input, if you have enabled MOZZI_AUDIO_INPUT,...
#define MOZZI_ANALOG_READ
Whether to compile in support for non-blocking analog reads.
void audioHook()
This is required in Arduino's loop().
unsigned long audioTicks()
An alternative for Arduino time functions like micros() and millis().
void updateControl()
This is where you put your control code.
void stopMozzi()
Stops audio and control interrupts and restores the timers to the values they had before Mozzi was st...
AudioOutput_t updateAudio()
This is where you put your audio code.
unsigned long mozziMicros()
An alternative for Arduino time functions like micros() and millis().
This struct encapsulates one frame of mono audio output.