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

AudioOutput.h
1 /** @file AudioOutput
2 *
3 * Platform independent audio output and adding support for new platforms or output methods.
4 *
5 * Mozzi provides support for audio ouput on a range of different boards and CPUs. This page is about the following related topics:
6 *
7 * - adding a custom output method (importantly using external DACs) to your sketch
8 * - writing sketches that will work on different platforms / with different output methods
9 * - extending Mozzi for a new architecture
10 *
11 * For all of these topics, it is helpful to have a basic understanding of the basic output steps in Mozzi:
12 *
13 * 1. Inside the loop() function in your sketch you call audioHook(). This function is responsible for calling updateAudio(), whenever there is room in the output buffer,
14 * adding the generated sample to the output buffer, calling updateControl() at an appropriate rate, and a few other details that are not important for this discussion.
15 *
16 * 2. A platform-specific timer is triggered at audio rate (usually), takes a sample from the output buffer and sends it to audioOutput().
17 *
18 * 3. The audioOutput() function - usually predefined inside Mozzi - takes care of sending the sample to the hardware.
19 *
20 * This basic output pipeline can be customized in several ways. First, defining EXTERNAL_AUDIO_OUTPUT to true in mozzi_config.h will allow you to define your own audioOutput()
21 * fuction. The library ships with some sample sketches for output to external DACs using this mechanism.
22 *
23 * In some cases, you will additionally want to bypass Mozzis output buffer, for example, if your board, or your external DAC already comes with an efficient built-in buffer.
24 * In this case, define BYPASS_MOZZI_OUTPUT_BUFFER to true. You will then have to provide a custom definition of canBufferAudioOutput(), returning true whenever your hardware
25 * is ready toaccept a new sample of output. This is called from inside audioHook(), and whenever there is room for a new sample, it is generated and sent to audioOutput(),
26 * immediately. In this case, should you need a timer running at AUDIO_RATE, you will have to set up one, yourself, if needed.
27 *
28 * In custom code, setting BYPASS_MOZZI_OUTPUT_BUFFER does not make much sense without EXTERNAL_AUDIO_OUTPUT also set to true. However, some platform ports (e.g. ESP32) actually
29 * use this combination, internally.
30 *
31 * Different output methods often support a different resolution of output samples. To provide best performance on slow boards, Mozzi expects your updateAudio() function to
32 * return samples in exactly the width that is needed at the output stage. Thus, defining this naively, an updateAudio() function designed for 8 bit output will produce very
33 * low volume output on a 16 bit DAC, while the other way around overflows will result in way too loud and heavily distored output. Fortunately, all that is needed to write
34 * portable sketches is to specify how many bits your updateAudio() function provides. The (inline) functions in the AudioOutput namespace do just that. Using them makes sure
35 * your audio output is shifted if, and as much as needed on all platforms.
36 */
37
38 #ifndef AUDIOOUTPUT
39 #define AUDIOOUTPUT
40
41 #include "MozziGuts.h"
42
43 #if IS_AVR() && ((AUDIO_MODE == STANDARD_PLUS) || (AUDIO_MODE == STANDARD))
44 #define SCALE_AUDIO(x,bits) (bits > 8 ? (x) >> (bits - 8) : (x) << (8 - bits))
45 #define SCALE_AUDIO_NEAR(x,bits) (bits > 9 ? (x) >> (bits - 9) : (x) << (9 - bits))
46 #define CLIP_AUDIO(x) constrain((x), -244,243)
47 #else
48 #define SCALE_AUDIO(x,bits) (bits > AUDIO_BITS ? (x) >> (bits - AUDIO_BITS) : (x) << (AUDIO_BITS - bits))
49 #define SCALE_AUDIO_NEAR(x,bits) SCALE_AUDIO(x,bits)
50 #define CLIP_AUDIO(x) constrain((x), -AUDIO_BIAS, AUDIO_BIAS-1)
51 #endif
52
53 /** The type used to store a single channel of a single frame, internally. For compatibility with earlier versions of Mozzi this is defined as int.
54 * If you do not care about keeping old sketches working, you may be able to save some RAM by using int16_t, instead (on boards where int is larger
55 * than 16 bits). */
56 #define AudioOutputStorage_t int
57
58 #if (STEREO_HACK == true)
59 #define AudioOutput_t void
60 #define AudioOutput StereoOutput
61 #else
62 /** Representation of an single audio output sample/frame. For mono output, this is really just a single zero-centered int,
63 * but for stereo it's a struct containing two ints.
64 *
65 * While it may be tempting (and is possible) to use an int, directly, using AudioOutput_t and the functions AudioOutput::from8Bit(),
66 * AudioOutput::fromNBit(), or AudioOutput::fromAlmostNBit() will allow you to write code that will work across different platforms, even
67 * when those use a different output resolution.
68 *
69 * @note The only place where you should be using AudioOutput_t, directly, is in your updateAudio() function signature. It's really just a
70 * dummy used to make the "same" function signature work across different configurations (importantly mono/stereo). It's true value
71 * might be subject to change, and it may even be void. Use either MonoOutput or StereoOutput to represent a piece of audio output.
72 */
73 #define AudioOutput_t AudioOutputStorage_t
74 /** Representation of an single audio output sample/frame. This #define maps to either MonoOutput or StereoOutput, depending on what is configured
75 * in mozzi_config.h. Since the two are source compatible to a large degree, it often isn't even necessary to test, which it is, in your code. E.g.
76 * both have functions l() and r(), to return "two" audio channels (which will be the same in case of mono).
77 *
78 * You will not usually use or encounter this definition, unless using EXTERNAL_AUDIO_OUTPUT.
79 */
80 #define AudioOutput MonoOutput
81 #endif
82
83 /** This struct encapsulates one frame of mono audio output. Internally, it really just boils down to two int values, but the struct provides
84 * useful API an top of that. For more detail @see MonoOutput . */
85 struct StereoOutput {
86 /** Construct an audio frame from raw values (zero-centered) */
87 StereoOutput(AudioOutputStorage_t l, AudioOutputStorage_t r) : _l(l), _r(r) {};
88 /** Default contstructor */
89 StereoOutput() : _l(0), _r(0) {};
90 #if (STEREO_HACK != true)
91 /** Conversion to int operator: If used in a mono config, returns only the left channel (and gives a compile time warning). */
92 inline operator AudioOutput_t() const __attribute__((deprecated("Sketch generates stereo output, but Mozzi is configured for mono. Check mozzi_config.h."))) { return _l; };
93 #endif
94 AudioOutputStorage_t l() const { return _l; };
95 AudioOutputStorage_t r() const { return _r; };
96 /** @see MonoOutput::clip(). Clips both channels. */
97 StereoOutput& clip() { _l = CLIP_AUDIO(_l); _r = CLIP_AUDIO(_r); return *this; };
98
99 /** @see MonoOutput::fromNBit(), stereo variant */
100 static inline StereoOutput fromNBit(uint8_t bits, int16_t l, int16_t r) { return StereoOutput(SCALE_AUDIO(l, bits), SCALE_AUDIO(r, bits)); }
101 /** @see MonoOutput::fromNBit(), stereo variant, 32 bit overload */
102 static inline StereoOutput fromNBit(uint8_t bits, int32_t l, int32_t r) { return StereoOutput(SCALE_AUDIO(l, bits), SCALE_AUDIO(r, bits)); }
103 /** @see MonoOutput::from8Bit(), stereo variant */
104 static inline StereoOutput from8Bit(int16_t l, int16_t r) { return fromNBit(8, l, r); }
105 /** @see MonoOutput::from16Bit(), stereo variant */
106 static inline StereoOutput from16Bit(int16_t l, int16_t r) { return fromNBit(16, l, r); }
107 /** @see MonoOutput::fromAlmostNBit(), stereo variant */
108 static inline StereoOutput fromAlmostNBit(uint8_t bits, int16_t l, int16_t r) { return StereoOutput(SCALE_AUDIO_NEAR(l, bits), SCALE_AUDIO_NEAR(r, bits)); }
109 /** @see MonoOutput::fromAlmostNBit(), stereo variant, 32 bit overload */
110 static inline StereoOutput fromAlmostNBit(uint8_t bits, int32_t l, int32_t r) { return StereoOutput(SCALE_AUDIO_NEAR(l, bits), SCALE_AUDIO_NEAR(r, bits)); }
111 private:
112 AudioOutputStorage_t _l;
113 AudioOutputStorage_t _r;
114 };
115
116 /** This struct encapsulates one frame of mono audio output. Internally, it really just boils down to a single int value, but the struct provides
117 * useful API an top of that, for the following:
118 *
119 * a) To construct an output frame, you should use one of the from8Bit(), fromNBit(), etc. functions. Given a raw input value, at a known resolution (number of bits),
120 * this scales the output efficiently to whatever is needed on the target platform. Using this, your updateAudio() function will be portable across different CPU and
121 * different output methods, including external DACs.
122 * b) The struct provides some convenience API on top of this. Right now, this is the function clip(), replacing the more verbose, and non-portable constrain(x, -244, 243)
123 * found in some old sketches.
124 * c) The struct provides accessors l() and r() that are source-compatible with StereoOutput, making it easy to e.g. implement support for an external DAC in both mono
125 * and stereo.
126 * d) Finally, an automatic conversion operator to int aka AudioOutput_t provides backward compatibility with old Mozzi sketches. Internally, the compiler will actually
127 * do away with this wholw struct, leaving just the same basic fast integer operations as in older Mozzi sketches. However, now, you don't have to rewrite those for
128 * different configurations.
129 */
130 struct MonoOutput {
131 /** Construct an audio frame from raw values (zero-centered) */
132 MonoOutput(AudioOutputStorage_t l=0) : _l(l) {};
133 #if (STEREO_HACK == true)
134 /** Conversion to stereo operator: If used in a stereo config, returns identical channels (and gives a compile time warning). */
135 inline operator StereoOutput() const __attribute__((deprecated("Sketch generates mono output, but Mozzi is configured for stereo. Check mozzi_config.h."))) { return StereoOutput(_l, _l); };
136 #else
137 /** Conversion to int operator. */
138 inline operator AudioOutput_t() const { return _l; };
139 #endif
140 AudioOutputStorage_t l() const { return _l; };
141 AudioOutputStorage_t r() const { return _l; };
142 /** Clip frame to supported range. This is useful when at times, but only rarely, the signal may exceed the usual range. Using this function does not avoid
143 * artifacts, entirely, but gives much better results than an overflow. */
144 MonoOutput& clip() { _l = CLIP_AUDIO(_l); return *this; };
145
146 /** Construct an audio frame a zero-centered value known to be in the N bit range. Appropriate left- or right-shifting will be performed, based on the number of output
147 * bits available. While this function takes care of the shifting, beware of potential overflow issues, if your intermediary results exceed the 16 bit range. Use proper
148 * casts to int32_t or larger in that case (and the compiler will automatically pick the 32 bit overload in this case) */
149 static inline MonoOutput fromNBit(uint8_t bits, int16_t l) { return MonoOutput(SCALE_AUDIO(l, bits)); }
150 /** 32bit overload. See above. */
151 static inline MonoOutput fromNBit(uint8_t bits, int32_t l) { return MonoOutput(SCALE_AUDIO(l, bits)); }
152 /** Construct an audio frame from a zero-centered value known to be in the 8 bit range. On AVR, STANDADR or STANDARD_PLUS mode, this is effectively the same as calling the
153 * constructor, directly (no scaling gets applied). On platforms/configs using more bits, an appropriate left-shift will be performed. */
154 static inline MonoOutput from8Bit(int16_t l) { return fromNBit(8, l); }
155 /** Construct an audio frame a zero-centered value known to be in the 16 bit range. This is jsut a shortcut for fromNBit(16, ...) provided for convenience. */
156 static inline MonoOutput from16Bit(int16_t l) { return fromNBit(16, l); }
157 /** Construct an audio frame a zero-centered value known to be above at almost but not quite the N bit range, e.g. at N=8 bits and a litte. On most platforms, this is
158 * exactly the same as fromNBit(), shifting up or down to the platforms' available resolution.
159 *
160 * However, on AVR, STANDARD(_PLUS) (where about 8.5 bits are usable), the value will be shifted to the (almost) 9 bit range, instead of to the 8 bit range. allowing to
161 * make use of that extra half bit of resolution. In many cases it is useful to follow up this call with clip().
162 *
163 * @example fromAlmostNBit(10, oscilA.next() + oscilB.next() + oscilC.next());
164 */
165 static inline MonoOutput fromAlmostNBit(uint8_t bits, int16_t l) { return MonoOutput(SCALE_AUDIO_NEAR(l, bits)); }
166 /** 32bit overload. See above. */
167 static inline MonoOutput fromAlmostNBit(uint8_t bits, int32_t l) { return MonoOutput(SCALE_AUDIO_NEAR(l, bits)); }
168 private:
169 AudioOutputStorage_t _l;
170 };
171
172
173 /** When setting EXTERNAL_AUDIO_OUTPUT to true, implement this function to take care of writing samples to the hardware. */
174 void audioOutput(const AudioOutput f);
175 #if BYPASS_MOZZI_OUTPUT_BUFFER
176 /** When setting BYPASS_MOZZI_OUTPUT_BUFFER to true, implement this function to return true, if and only if your hardware (or custom buffer) is ready to accept the next sample. */
177 inline bool canBufferAudioOutput();
178 #endif
179
180 /** Perform one step of (fast) pdm encoding, returning 8 "bits" (i.e. 8 ones and zeros).
181 * You will usually call this at least four or eight times for a single input sample.
182 *
183 * The return type is defined as uint32_t to avoid conversion steps. Actually, only the 8 lowest
184 * bits of the return value are set. */
185 inline uint32_t pdmCode8(uint16_t sample) {
186 // lookup table for fast pdm coding on 8 output bits at a time
187 static const byte fast_pdm_table[]{0, 0b00010000, 0b01000100,
188 0b10010010, 0b10101010, 0b10110101,
189 0b11011101, 0b11110111, 0b11111111};
190
191 static uint32_t lastwritten = 0;
192 static uint32_t nexttarget = 0;
193 // in each iteration, code the highest 3-and-a-little bits.
194 // Note that sample only has 16 bits, while the
195 // highest bit we consider for writing is bit 17.
196 // Thus, if the highest bit is set, the next
197 // three bits cannot be.
198 nexttarget += sample;
199 nexttarget -= lastwritten;
200 lastwritten = nexttarget & 0b11110000000000000;
201 return fast_pdm_table[lastwritten >> 13];
202 }
203
204 /** Convenience function to perform four iterations of pdmCode8() */
205 inline uint32_t pdmCode32(uint16_t sample) {
206 uint32_t outbits = 0;
207 for (uint8_t i = 0; i < 4; ++i) {
208 outbits = outbits << 8;
209 outbits |= pdmCode8(sample);
210 }
211 return outbits;
212 }
213
214 #if (EXTERNAL_AUDIO_OUTPUT != true)
215
216 ///////////////////// SAMD21
217 #if IS_SAMD21()
218 #include "AudioConfigSAMD21.h"
219 inline void audioOutput(const AudioOutput f)
220 {
221 analogWrite(AUDIO_CHANNEL_1_PIN, f.l()+AUDIO_BIAS);
222 }
223 #endif
224
225
226 ///////////////////// TEENSY3
227 #if IS_TEENSY3()
228 #include "AudioConfigTeensy3_12bit.h"
229 inline void audioOutput(const AudioOutput f)
230 {
231 analogWrite(AUDIO_CHANNEL_1_PIN, f.l()+AUDIO_BIAS);
232 }
233 #endif
234
235
236 ///////////////////// STM32
237 #if IS_STM32()
238 #include "AudioConfigSTM32.h"
239 inline void audioOutput(const AudioOutput f)
240 {
241 #if (AUDIO_MODE == HIFI)
242 pwmWrite(AUDIO_CHANNEL_1_PIN, (f.l()+AUDIO_BIAS) & ((1 << AUDIO_BITS_PER_CHANNEL) - 1));
243 pwmWrite(AUDIO_CHANNEL_1_PIN_HIGH, (f.l()+AUDIO_BIAS) >> AUDIO_BITS_PER_CHANNEL);
244 #else
245 pwmWrite(AUDIO_CHANNEL_1_PIN, f.l()+AUDIO_BIAS);
246 #if (STEREO_HACK == true)
247 pwmWrite(AUDIO_CHANNEL_2_PIN, f.r()+AUDIO_BIAS);
248 #endif
249 #endif
250 }
251 #endif
252
253
254 ///////////////////// ESP8266
255 #if IS_ESP8266()
256 #include "AudioConfigESP.h"
257 #if (ESP_AUDIO_OUT_MODE == PDM_VIA_I2S)
258 #include <i2s.h>
259 inline bool canBufferAudioOutput() {
260 return (i2s_available() >= PDM_RESOLUTION);
261 }
262 inline void audioOutput(const AudioOutput f) {
263 for (uint8_t words = 0; words < PDM_RESOLUTION; ++words) {
264 i2s_write_sample(pdmCode32(f.l()));
265 }
266 }
267 #elif (ESP_AUDIO_OUT_MODE == EXTERNAL_DAC_VIA_I2S)
268 #include <i2s.h>
269 inline bool canBufferAudioOutput() {
270 return (i2s_available() >= PDM_RESOLUTION);
271 }
272 inline void audioOutput(const AudioOutput f) {
273 i2s_write_lr(f.l(), f.r()); // Note: i2s_write expects zero-centered output
274 }
275 #else
276 inline void audioOutput(const AudioOutput f) {
277 // optimized version of: Serial1.write(...);
278 for (uint8_t i = 0; i < PDM_RESOLUTION*4; ++i) {
279 U1F = pdmCode8(f);
280 }
281 }
282 #endif
283 #endif
284
285
286
287 ///////////////////// ESP32
288 #if IS_ESP32()
289 #include "AudioConfigESP32.h"
290 // On ESP32 we cannot test wether the DMA buffer has room. Instead, we have to use a one-sample mini buffer. In each iteration we
291 // _try_ to write that sample to the DMA buffer, and if successful, we can buffer the next sample. Somewhat cumbersome, but works.
292 // TODO: Should ESP32 gain an implemenation of i2s_available(), we should switch to using that, instead.
293 static bool _esp32_can_buffer_next = true;
294 #if (ESP32_AUDIO_OUT_MODE == INTERNAL_DAC)
295 static uint16_t _esp32_prev_sample[2];
296 #define ESP_SAMPLE_SIZE (2*sizeof(uint16_t))
297 #elif (ESP32_AUDIO_OUT_MODE == PT8211_DAC)
298 static int16_t _esp32_prev_sample[2];
299 #define ESP_SAMPLE_SIZE (2*sizeof(int16_t))
300 #elif (ESP32_AUDIO_OUT_MODE == PDM_VIA_I2S)
301 static uint32_t _esp32_prev_sample[PDM_RESOLUTION];
302 #define ESP_SAMPLE_SIZE (PDM_RESOLUTION*sizeof(uint32_t))
303 #endif
304
305 inline bool esp32_tryWriteSample() {
306 size_t bytes_written;
307 i2s_write(i2s_num, &_esp32_prev_sample, ESP_SAMPLE_SIZE, &bytes_written, 0);
308 return (bytes_written != 0);
309 }
310
311 inline bool canBufferAudioOutput() {
312 if (_esp32_can_buffer_next) return true;
313 _esp32_can_buffer_next = esp32_tryWriteSample();
314 return _esp32_can_buffer_next;
315 }
316
317 inline void audioOutput(const AudioOutput f) {
318 #if (ESP32_AUDIO_OUT_MODE == INTERNAL_DAC)
319 _esp32_prev_sample[0] = (f.l() + AUDIO_BIAS) << 8;
320 #if (STEREO_HACK == true)
321 _esp32_prev_sample[1] = (f.r() + AUDIO_BIAS) << 8;
322 #else
323 // For simplicity of code, even in mono, we're writing stereo samples
324 _esp32_prev_sample[1] = _esp32_prev_sample[0];
325 #endif
326 #elif (ESP32_AUDIO_OUT_MODE == PDM_VIA_I2S)
327 for (uint8_t i=0; i<PDM_RESOLUTION; ++i) {
328 _esp32_prev_sample[i] = pdmCode32(f.l() + AUDIO_BIAS);
329 }
330 #else
331 // PT8211 takes signed samples
332 _esp32_prev_sample[0] = f.l();
333 _esp32_prev_sample[1] = f.r();
334 #endif
335 _esp32_can_buffer_next = esp32_tryWriteSample();
336 }
337
338 #endif
339
340
341
342 ///////////////////// AVR STANDARD
343 #if IS_AVR() && (AUDIO_MODE == STANDARD_PLUS)
344 #include "AudioConfigStandardPlus.h"
345 inline void audioOutput(const AudioOutput f)
346 {
347 AUDIO_CHANNEL_1_OUTPUT_REGISTER = f.l()+AUDIO_BIAS;
348 #if (STEREO_HACK == true)
349 AUDIO_CHANNEL_2_OUTPUT_REGISTER = f.r()+AUDIO_BIAS;
350 #endif
351 }
352
353
354
355 ///////////////////// AVR HIFI
356 #elif IS_AVR() && (AUDIO_MODE == HIFI)
357 #include "AudioConfigHiSpeed14bitPwm.h"
358 inline void audioOutput(const AudioOutput f)
359 {
360 // read about dual pwm at
361 // http://www.openmusiclabs.com/learning/digital/pwm-dac/dual-pwm-circuits/
362 // sketches at http://wiki.openmusiclabs.com/wiki/PWMDAC,
363 // http://wiki.openmusiclabs.com/wiki/MiniArDSP
364 // if (!output_buffer.isEmpty()){
365 //unsigned int out = output_buffer.read();
366 // 14 bit, 7 bits on each pin
367 // AUDIO_CHANNEL_1_highByte_REGISTER = out >> 7; // B00111111 10000000 becomes
368 // B1111111
369 // try to avoid looping over 7 shifts - need to check timing or disassemble to
370 // see what really happens unsigned int out_high = out<<1; // B00111111
371 // 10000000 becomes B01111111 00000000
372 // AUDIO_CHANNEL_1_highByte_REGISTER = out_high >> 8; // B01111111 00000000
373 // produces B01111111 AUDIO_CHANNEL_1_lowByte_REGISTER = out & 127;
374 /* Atmega manual, p123
375 The high byte (OCR1xH) has to be written first.
376 When the high byte I/O location is written by the CPU,
377 the TEMP Register will be updated by the value written.
378 Then when the low byte (OCR1xL) is written to the lower eight bits,
379 the high byte will be copied into the upper 8-bits of
380 either the OCR1x buffer or OCR1x Compare Register in
381 the same system clock cycle.
382 */
383 AUDIO_CHANNEL_1_highByte_REGISTER = (f.l()+AUDIO_BIAS) >> AUDIO_BITS_PER_REGISTER;
384 AUDIO_CHANNEL_1_lowByte_REGISTER = (f.l()+AUDIO_BIAS) & ((1 << AUDIO_BITS_PER_REGISTER) - 1);
385 }
386 #endif
387
388
389 #else
390 #warning "Mozzi is configured to use an external void 'audioOutput(const AudioOutput f)' function. Please define one in your sketch"
391 #endif
392
393 #endif
MonoOutput::from16Bit
static MonoOutput from16Bit(int16_t l)
Construct an audio frame a zero-centered value known to be in the 16 bit range.
Definition: AudioOutput.h:156
StereoOutput::clip
StereoOutput & clip()
Definition: AudioOutput.h:97
SCALE_AUDIO_NEAR
#define SCALE_AUDIO_NEAR(x, bits)
Definition: AudioOutput.h:49
MonoOutput::operator StereoOutput
operator StereoOutput() const __attribute__((deprecated("Sketch generates mono output
Conversion to stereo operator: If used in a stereo config, returns identical channels (and gives a co...
StereoOutput::StereoOutput
StereoOutput()
Default contstructor.
Definition: AudioOutput.h:89
MonoOutput::from8Bit
static MonoOutput from8Bit(int16_t l)
Construct an audio frame from a zero-centered value known to be in the 8 bit range.
Definition: AudioOutput.h:154
AUDIO_MODE
#define AUDIO_MODE
AUDIO_MODE holds the audio mode setting.
Definition: mozzi_config.h:28
HIFI
#define HIFI
Definition: MozziGuts.h:155
MonoOutput::MonoOutput
MonoOutput(AudioOutputStorage_t l=0)
Construct an audio frame from raw values (zero-centered)
Definition: AudioOutput.h:132
STEREO_HACK
#define STEREO_HACK
This sets an option for stereo output, a hack which requires variables audio_signal_1 and audio_signa...
Definition: mozzi_config.h:92
StereoOutput::from8Bit
static StereoOutput from8Bit(int16_t l, int16_t r)
Definition: AudioOutput.h:104
IS_SAMD21
#define IS_SAMD21()
Definition: hardware_defines.h:16
MonoOutput::fromNBit
static MonoOutput fromNBit(uint8_t bits, int32_t l)
32bit overload.
Definition: AudioOutput.h:151
IS_STM32
#define IS_STM32()
Definition: hardware_defines.h:18
STANDARD_PLUS
#define STANDARD_PLUS
Definition: MozziGuts.h:154
MonoOutput::clip
MonoOutput & clip()
Clip frame to supported range.
Definition: AudioOutput.h:144
AudioOutput
#define AudioOutput
Definition: AudioOutput.h:60
IS_AVR
#define IS_AVR()
Definition: hardware_defines.h:15
IS_TEENSY3
#define IS_TEENSY3()
Definition: hardware_defines.h:17
SCALE_AUDIO
#define SCALE_AUDIO(x, bits)
Definition: AudioOutput.h:48
StereoOutput
This struct encapsulates one frame of mono audio output.
Definition: AudioOutput.h:85
StereoOutput::from16Bit
static StereoOutput from16Bit(int16_t l, int16_t r)
Definition: AudioOutput.h:106
StereoOutput::fromNBit
static StereoOutput fromNBit(uint8_t bits, int32_t l, int32_t r)
Definition: AudioOutput.h:102
MonoOutput::fromAlmostNBit
static MonoOutput fromAlmostNBit(uint8_t bits, int32_t l)
32bit overload.
Definition: AudioOutput.h:167
StereoOutput::StereoOutput
StereoOutput(AudioOutputStorage_t l, AudioOutputStorage_t r)
Construct an audio frame from raw values (zero-centered)
Definition: AudioOutput.h:87
AudioOutput_t
#define AudioOutput_t
Definition: AudioOutput.h:59
STANDARD
#define STANDARD
Used to set AUDIO_MODE to STANDARD, STANDARD_PLUS, or HIFI.
Definition: MozziGuts.h:153
EXTERNAL_AUDIO_OUTPUT
#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
StereoOutput::fromAlmostNBit
static StereoOutput fromAlmostNBit(uint8_t bits, int32_t l, int32_t r)
Definition: AudioOutput.h:110
IS_ESP8266
#define IS_ESP8266()
Definition: hardware_defines.h:19
IS_ESP32
#define IS_ESP32()
Definition: hardware_defines.h:20
CLIP_AUDIO
#define CLIP_AUDIO(x)
Definition: AudioOutput.h:50
AudioOutputStorage_t
#define AudioOutputStorage_t
The type used to store a single channel of a single frame, internally.
Definition: AudioOutput.h:56