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 # error "Platform not (yet) supported. Check MozziGuts_impl_template.hpp and existing implementations for a blueprint for adding your favorite MCU."
71 #if !defined(MOZZI__LEGACY_AUDIO_INPUT_IMPL)
72 # if !MOZZI_IS(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE)
73 # define MOZZI__LEGACY_AUDIO_INPUT_IMPL 1
75 # define MOZZI__LEGACY_AUDIO_INPUT_IMPL 0
81 #if BYPASS_MOZZI_OUTPUT_BUFFER == true
82 uint64_t samples_written_to_buffer = 0;
84 inline void bufferAudioOutput(
const AudioOutput f) {
86 ++samples_written_to_buffer;
90 # define canBufferAudioOutput() (!output_buffer.isFull())
91 # define bufferAudioOutput(f) output_buffer.write(f)
92 static void CACHED_FUNCTION_ATTR defaultAudioOutput() {
94 #if MOZZI_IS(MOZZI__LEGACY_AUDIO_INPUT_IMPL, 1)
97 startSecondADCReadOnCurrentChannel();
99 audioOutput(output_buffer.read());
111 #if MOZZI_IS(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_STANDARD)
114 static volatile uint16_t analog_readings[NUM_ANALOG_INPUTS];
116 volatile static int8_t current_channel = -1;
120 void adcReadSelectedChannels() {
122 if((current_channel = adc_channels_to_read.
pop()) >= 0) adcStartConversion(current_channel);
128 __attribute__((noinline))
void adcStartReadCycle() {
129 if (current_channel < 0)
131 #if MOZZI_IS(MOZZI__LEGACY_AUDIO_INPUT_IMPL, 1)
134 adcReadSelectedChannels();
140 uint16_t mozziAnalogRead(uint8_t pin) {
141 pin = adcPinToChannelNum(pin);
142 adc_channels_to_read.
push(pin);
143 return analog_readings[channelNumToIndex(pin)];
146 #if !MOZZI_IS(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE)
147 static uint16_t audio_input;
151 #if MOZZI_IS(MOZZI__LEGACY_AUDIO_INPUT_IMPL, 1)
154 #define audioInputAvailable() (!input_buffer.isEmpty())
155 #define readAudioInput() (input_buffer.read())
157 inline void advanceADCStep() {
162 input_buffer.write(getADCReading());
163 adcReadSelectedChannels();
169 startSecondADCReadOnCurrentChannel();
174 analog_readings[channelNumToIndex(current_channel)] = getADCReading();
187 inline void advanceADCStep() {
190 startSecondADCReadOnCurrentChannel();
194 analog_readings[channelNumToIndex(current_channel)] = getADCReading();
195 adcReadSelectedChannels();
205 return analogRead(pin);
214 static uint16_t update_control_timeout;
215 static uint16_t update_control_counter;
217 inline void advanceControlLoop() {
218 if (!update_control_counter) {
219 update_control_counter = update_control_timeout;
221 #if MOZZI_IS(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_STANDARD)
225 --update_control_counter;
232 if (canBufferAudioOutput()) {
233 advanceControlLoop();
236 #if defined(LOOP_YIELD)
240 #if !MOZZI_IS(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE)
241 if (audioInputAvailable()) audio_input = readAudioInput();
245 #if defined(AUDIO_HOOK_HOOK)
257 #if (BYPASS_MOZZI_OUTPUT_BUFFER != true)
258 return output_buffer.count();
259 #elif defined(AUDIOTICK_ADJUSTMENT)
260 return samples_written_to_buffer - (AUDIOTICK_ADJUSTMENT);
262 return samples_written_to_buffer;
271 void startMozzi(
int control_rate_hz) {
272 #if !MOZZI_IS(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_NONE)
273 MozziPrivate::setupMozziADC(FAST_ADC);
281 uint32_t MozziRandPrivate::x=132456789;
282 uint32_t MozziRandPrivate::y=362436069;
283 uint32_t MozziRandPrivate::z=521288629;
290 #undef BYPASS_MOZZI_OUTPUT_BUFFER
291 #undef AUDIO_HOOK_HOOK
292 #undef AUDIOTICK_ADJUSTMENT
293 #undef MOZZI__LEGACY_AUDIO_INPUT_IMPL
300 unsigned long mozziMicros() {
return MozziPrivate::mozziMicros(); };
301 unsigned long audioTicks() {
return MozziPrivate::audioTicks(); };
302 void startMozzi(
int control_rate_hz) { MozziPrivate::startMozzi(control_rate_hz); };
304 template<
byte RES> uint16_t
mozziAnalogRead(uint8_t pin) {
return MozziPrivate::smartShift<MOZZI__INTERNAL_ANALOG_READ_RESOLUTION, RES>(MozziPrivate::mozziAnalogRead(pin));};
305 #if !MOZZI_IS(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_NONE)
308 #if MOZZI_IS(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_STANDARD)
309 void setupMozziADC(int8_t speed) { MozziPrivate::setupMozziADC(speed); };
311 uint8_t adcPinToChannelNum(uint8_t pin) {
return MozziPrivate::adcPinToChannelNum(pin); };
316 #if !MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_EXTERNAL_TIMED, MOZZI_OUTPUT_EXTERNAL_CUSTOM)
317 MOZZI_DEPRECATED(
"n/a",
"Sketch has audioOutput() function, although external output is not configured.") void audioOutput(const
AudioOutput) {};
319 #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.