Mozzi  version v2.0
sound synthesis library for Arduino
AudioOutput.h
1 /*
2  * AudioOutput.h
3  *
4  * This file is part of Mozzi.
5  *
6  * Copyright 2021-2024 Thomas Friedrichsmeier and the Mozzi Team
7  *
8  * Mozzi is licensed under the GNU Lesser General Public Licence (LGPL) Version 2.1 or later.
9  *
10  */
11 
58 #ifndef AUDIOOUTPUT_H
59 #define AUDIOOUTPUT_H
60 #include <FixMath.h>
61 
65 #define AudioOutputStorage_t int
66 
67 template<typename T> constexpr AudioOutputStorage_t SCALE_AUDIO(T x, byte bits) { return (bits > MOZZI_AUDIO_BITS ? (x) >> (bits - MOZZI_AUDIO_BITS) : (x) << (MOZZI_AUDIO_BITS - bits)); }
68 template<typename T> constexpr AudioOutputStorage_t SCALE_AUDIO_NEAR(T x, byte bits) { return (bits > MOZZI_AUDIO_BITS_OPTIMISTIC ? (x) >> (bits - MOZZI_AUDIO_BITS_OPTIMISTIC) : (x) << (MOZZI_AUDIO_BITS_OPTIMISTIC - bits)); }
69 template<typename T> constexpr AudioOutputStorage_t CLIP_AUDIO(T x) { return (constrain((x), (-(AudioOutputStorage_t) MOZZI_AUDIO_BIAS), (AudioOutputStorage_t) (MOZZI_AUDIO_BIAS-1))); }
70 
71 struct MonoOutput;
72 struct StereoOutput;
73 
74 #if MOZZI_IS(MOZZI_AUDIO_CHANNELS, MOZZI_STEREO)
76 #else
83 typedef MonoOutput AudioOutput;
84 #endif
85 
86 #if MOZZI_COMPATIBILITY_LEVEL < MOZZI_COMPATIBILITY_LATEST
87 #if (MOZZI_COMPATIBILITY_LEVEL <= MOZZI_COMPATIBILITY_1_1) && MOZZI_IS(MOZZI_AUDIO_CHANNELS, MOZZI_MONO)
88 typedef int AudioOutput_t; // Note: Needed for pre 1.1 backwards compatibility
89 #else
93 MOZZI_DEPRECATED("2.0", "Replace AudioOutput_t with simple AudioOutput") typedef AudioOutput AudioOutput_t;
94 #endif
95 #endif
96 
111 struct MonoOutput {
115  MonoOutput(AudioOutputStorage_t l) : _l(l) {};
116 #if (MOZZI_AUDIO_CHANNELS > 1)
120  StereoOutput portable() const __attribute__((deprecated("Sketch generates mono output, but Mozzi is configured for stereo. Check MOZZI_AUDIO_CHANNELS setting."))); // Note: defintion below
121 #endif
123  operator AudioOutputStorage_t() const { return _l; };
124 
125  AudioOutputStorage_t l() const { return _l; };
126  AudioOutputStorage_t r() const { return _l; };
129  MonoOutput& clip() { _l = CLIP_AUDIO(_l); return *this; };
130 
134  template<typename T> static inline MonoOutput fromNBit(uint8_t bits, T l) { return MonoOutput(SCALE_AUDIO(l, bits)); }
137  static inline MonoOutput from8Bit(int16_t l) { return fromNBit(8, l); }
139  static inline MonoOutput from16Bit(int16_t l) { return fromNBit(16, l); }
141  template<int8_t NI, int8_t NF, uint64_t RANGE>
142  static inline MonoOutput fromSFix(SFix<NI,NF,RANGE> l) { return MonoOutput(SCALE_AUDIO(l.asRaw(), (NI+NF+1))) ;}
153  template<typename A, typename B> static inline MonoOutput fromAlmostNBit(A bits, B l) { return MonoOutput(SCALE_AUDIO_NEAR(l, bits)); }
154 
155 private:
156  AudioOutputStorage_t _l;
157 };
158 
161 struct StereoOutput {
163  StereoOutput(AudioOutputStorage_t l, AudioOutputStorage_t r) : _l(l), _r(r) {};
166 #if !MOZZI_IS(MOZZI_AUDIO_CHANNELS, MOZZI_STEREO)
170  inline AudioOutput portable() const __attribute__((deprecated("Sketch generates stereo output, but Mozzi is configured for mono. Check MOZZI_AUDIO_CHANNELS setting."))) { return _l; };
171 # if GITHUB_RUNNER_ACCEPT_STEREO_IN_MONO
172  inline operator AudioOutput() const __attribute__((deprecated("Stereo converted to mono on github runner"))) { return _l; };
173 # endif
174 #endif
175  AudioOutputStorage_t l() const { return _l; };
176  AudioOutputStorage_t r() const { return _r; };
178  StereoOutput& clip() { _l = CLIP_AUDIO(_l); _r = CLIP_AUDIO(_r); return *this; };
179 
181 template<typename T> static inline StereoOutput fromNBit(uint8_t bits, T l, T r) { return StereoOutput(SCALE_AUDIO(l, bits), SCALE_AUDIO(r, bits)); }
183  static inline StereoOutput from8Bit(int16_t l, int16_t r) { return fromNBit(8, l, r); }
185  static inline StereoOutput from16Bit(int16_t l, int16_t r) { return fromNBit(16, l, r); }
187  template<int8_t NI, int8_t NF, uint64_t RANGE, int8_t _NI, int8_t _NF, uint64_t _RANGE>
188  static inline StereoOutput fromSFix(SFix<NI,NF,RANGE> l, SFix<_NI,_NF,_RANGE> r) { return StereoOutput(SCALE_AUDIO(l.asRaw(), (NI+NF+1)), SCALE_AUDIO(r.asRaw(), (_NI+_NF+1))); }
190  template<typename A, typename B> static inline StereoOutput fromAlmostNBit(A bits, B l, B r) { return StereoOutput(SCALE_AUDIO_NEAR(l, bits), SCALE_AUDIO_NEAR(r, bits)); }
191 private:
192  AudioOutputStorage_t _l;
193  AudioOutputStorage_t _r;
194 };
195 
196 #if MOZZI_AUDIO_CHANNELS > 1
197 StereoOutput MonoOutput::portable() const { return StereoOutput(_l, _l); };
198 #endif
199 
200 #if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_EXTERNAL_TIMED, MOZZI_OUTPUT_EXTERNAL_CUSTOM)
203 void audioOutput(const AudioOutput f);
204 #endif
205 #if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_EXTERNAL_CUSTOM)
207 inline bool canBufferAudioOutput();
208 #endif
209 
216 inline uint32_t pdmCode8(uint16_t sample) {
217  // lookup table for fast pdm coding on 8 output bits at a time
218  static const byte fast_pdm_table[]{0, 0b00010000, 0b01000100,
219  0b10010010, 0b10101010, 0b10110101,
220  0b11011101, 0b11110111, 0b11111111};
221 
222  static uint32_t lastwritten = 0;
223  static uint32_t nexttarget = 0;
224  // in each iteration, code the highest 3-and-a-little bits.
225  // Note that sample only has 16 bits, while the
226  // highest bit we consider for writing is bit 17.
227  // Thus, if the highest bit is set, the next
228  // three bits cannot be. (highest possible values:
229  // nexttarget-lastwritten == 0b00001111111111111,
230  // sample == 0b01111111111111111)
231  nexttarget += sample;
232  nexttarget -= lastwritten;
233  lastwritten = nexttarget & 0b11110000000000000;
234  return fast_pdm_table[lastwritten >> 13];
235 }
236 
238 inline uint32_t pdmCode32(uint16_t sample) {
239  uint32_t outbits = 0;
240  for (uint8_t i = 0; i < 4; ++i) {
241  outbits = outbits << 8;
242  outbits |= pdmCode8(sample);
243  }
244  return outbits;
245 }
246 
247 #endif
#define MOZZI_AUDIO_BITS
Output resolution of audio samples.
#define MOZZI_AUDIO_CHANNELS
This sets allows to change from a single/mono audio output channel to stereo output.
This struct encapsulates one frame of mono audio output.
Definition: AudioOutput.h:111
static MonoOutput fromNBit(uint8_t bits, T l)
Construct an audio frame a zero-centered value known to be in the N bit range.
Definition: AudioOutput.h:134
MonoOutput(AudioOutputStorage_t l)
Construct an audio frame from raw values (zero-centered)
Definition: AudioOutput.h:115
MonoOutput & clip()
Clip frame to supported range.
Definition: AudioOutput.h:129
static MonoOutput from16Bit(int16_t l)
Construct an audio frame from a zero-centered value known to be in the 16 bit range.
Definition: AudioOutput.h:139
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:137
MonoOutput()
Default constructor.
Definition: AudioOutput.h:113
static MonoOutput fromAlmostNBit(A bits, B l)
Construct an audio frame a zero-centered value known to be above at almost but not quite the N bit ra...
Definition: AudioOutput.h:153
static MonoOutput fromSFix(SFix< NI, NF, RANGE > l)
Construct an audio frame from a SFix type from FixMath.
Definition: AudioOutput.h:142
This struct encapsulates one frame of mono audio output.
Definition: AudioOutput.h:161
static StereoOutput fromAlmostNBit(A bits, B l, B r)
See MonoOutput::fromAlmostNBit(), stereo variant.
Definition: AudioOutput.h:190
StereoOutput(AudioOutputStorage_t l, AudioOutputStorage_t r)
Construct an audio frame from raw values (zero-centered)
Definition: AudioOutput.h:163
static StereoOutput from8Bit(int16_t l, int16_t r)
See MonoOutput::from8Bit(), stereo variant.
Definition: AudioOutput.h:183
StereoOutput()
Default constructor.
Definition: AudioOutput.h:165
AudioOutput portable() const __attribute__((deprecated("Sketch generates stereo output
Conversion to int operator: If used in a mono config, returns only the left channel (and gives a comp...
static StereoOutput from16Bit(int16_t l, int16_t r)
See MonoOutput::from16Bit(), stereo variant.
Definition: AudioOutput.h:185
static StereoOutput fromNBit(uint8_t bits, T l, T r)
See MonoOutput::fromNBit(), stereo variant.
Definition: AudioOutput.h:181
StereoOutput & clip()
See MonoOutput::clip().
Definition: AudioOutput.h:178
static StereoOutput fromSFix(SFix< NI, NF, RANGE > l, SFix< _NI, _NF, _RANGE > r)
See MonoOutput::fromSFix(), stereo variant.
Definition: AudioOutput.h:188