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) */
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:
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) */
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:
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
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()
Definition: AudioOutput.h:97
#define SCALE_AUDIO_NEAR(x, bits)
Definition: AudioOutput.h:49
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()
Default contstructor.
Definition: AudioOutput.h:89
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
#define AUDIO_MODE
AUDIO_MODE holds the audio mode setting.
Definition: mozzi_config.h:28
#define HIFI
Definition: MozziGuts.h:155
MonoOutput(AudioOutputStorage_t l=0)
Construct an audio frame from raw values (zero-centered)
Definition: AudioOutput.h:132
#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
static StereoOutput from8Bit(int16_t l, int16_t r)
Definition: AudioOutput.h:104
#define IS_SAMD21()
static MonoOutput fromNBit(uint8_t bits, int32_t l)
32bit overload.
Definition: AudioOutput.h:151
#define IS_STM32()
#define STANDARD_PLUS
Definition: MozziGuts.h:154
MonoOutput & clip()
Clip frame to supported range.
Definition: AudioOutput.h:144
#define AudioOutput
Definition: AudioOutput.h:60
#define IS_AVR()
#define IS_TEENSY3()
#define SCALE_AUDIO(x, bits)
Definition: AudioOutput.h:48
This struct encapsulates one frame of mono audio output.
Definition: AudioOutput.h:85
static StereoOutput from16Bit(int16_t l, int16_t r)
Definition: AudioOutput.h:106
static StereoOutput fromNBit(uint8_t bits, int32_t l, int32_t r)
Definition: AudioOutput.h:102
static MonoOutput fromAlmostNBit(uint8_t bits, int32_t l)
32bit overload.
Definition: AudioOutput.h:167
StereoOutput(AudioOutputStorage_t l, AudioOutputStorage_t r)
Construct an audio frame from raw values (zero-centered)
Definition: AudioOutput.h:87
#define AudioOutput_t
Definition: AudioOutput.h:59
#define STANDARD
Used to set AUDIO_MODE to STANDARD, STANDARD_PLUS, or HIFI.
Definition: MozziGuts.h:153
#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
static StereoOutput fromAlmostNBit(uint8_t bits, int32_t l, int32_t r)
Definition: AudioOutput.h:110
#define IS_ESP8266()
#define IS_ESP32()
#define CLIP_AUDIO(x)
Definition: AudioOutput.h:50
#define AudioOutputStorage_t
The type used to store a single channel of a single frame, internally.
Definition: AudioOutput.h:56