Skip to content

Commit d9ff2bf

Browse files
authored
Merge branch 'master' into MetaOsc
2 parents 193f7d4 + b55c9f1 commit d9ff2bf

File tree

568 files changed

+2718
-55644
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

568 files changed

+2718
-55644
lines changed

AudioConfigESP.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#error HIFI mode is not available for this CPU architecture (but check ESP_AUDIO_OUT_MODE, and PDM_RESOLUTION)
2424
#endif
2525

26-
#if (STEREO_HACK == true)
26+
#if (AUDIO_CHANNELS > 1)
2727
#if (ESP_AUDIO_OUT_MODE != EXTERNAL_DAC_VIA_I2S)
2828
#error Stereo is not available for the configured audio output mode
2929
#endif

AudioConfigRP2040.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#ifndef AUDIOCONFIGRP2040_H
2+
#define AUDIOCONFIGRP2040_H
3+
4+
#if not IS_RP2040()
5+
#error This header should be included for RP2040, only
6+
#endif
7+
8+
9+
// AUDIO output modes
10+
#define PWM_VIA_BARE_CHIP 1 // output using one of the gpio of the board
11+
#define EXTERNAL_DAC_VIA_I2S 2 // output via external DAC connected to I2S (PT8211 or similar)
12+
13+
//******* BEGIN: These are the defines you may want to change. Best not to touch anything outside this range. ************/
14+
#define RP2040_AUDIO_OUT_MODE PWM_VIA_BARE_CHIP
15+
//******* END: These are the defines you may want to change. Best not to touch anything outside this range. ************/
16+
17+
18+
#if (RP2040_AUDIO_OUT_MODE == PWM_VIA_BARE_CHIP)
19+
#define AUDIO_CHANNEL_1_PIN 0
20+
#if (AUDIO_CHANNELS > 1)
21+
// Audio channel pins for stereo or HIFI must be on the same PWM slice (which is the case for the pairs (0,1), (2,3), (4,5), etc.
22+
#define AUDIO_CHANNEL_2_PIN 1
23+
#endif
24+
25+
// The more audio bits you use, the slower the carrier frequency of the PWM signal. 11 bits yields ~ 60kHz on a 133Mhz CPU (which appears to be a reasonable compromise)
26+
#define AUDIO_BITS 11
27+
#endif
28+
29+
#if (RP2040_AUDIO_OUT_MODE == EXTERNAL_DAC_VIA_I2S)
30+
// ****** BEGIN: These are define you may want to change. Best not to touch anything outside this range. ************/
31+
#define BCLK_PIN 20
32+
#define WS_PIN (pBCLK+1) // CANNOT BE CHANGED, HAS TO BE NEXT TO pBCLK
33+
#define DOUT_PIN 22
34+
#define LSBJ_FORMAT false // some DAC, like the PT8211, use a variant of I2S data format called LSBJ
35+
// set this to true to use this kind of DAC or false for plain I2S.
36+
#define AUDIO_BITS 16 // available values are 8, 16, 24 (LEFT ALIGN in 32 bits type!!) and 32 bits
37+
// ****** END: These are define you may want to change. Best not to touch anything outside this range. ************/
38+
39+
#define BYPASS_MOZZI_OUTPUT_BUFFER true
40+
41+
// Configuration of the I2S port, especially DMA. Set in stone here as default of the library when this was written.
42+
// Probably do not change if you are not sure of what you are doing
43+
#define BUFFERS 8 // number of DMA buffers used
44+
#define BUFFER_SIZE 256 // total size of the buffer, in samples
45+
#endif
46+
47+
48+
#define AUDIO_BITS_PER_CHANNEL AUDIO_BITS
49+
50+
#define AUDIO_BIAS ((uint16_t) 1<<(AUDIO_BITS-1))
51+
52+
#endif // #ifndef AUDIOCONFIGRP2040_H
53+

AudioConfigSTM32.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
// The more audio bits you use, the slower the carrier frequency of the PWM signal. 10 bits yields ~ 70kHz on a 72Mhz CPU (which appears to be a reasonable compromise)
2323
#define AUDIO_BITS 10
2424
#define AUDIO_BITS_PER_CHANNEL AUDIO_BITS
25-
#if (STEREO_HACK == true)
25+
#if (AUDIO_CHANNELS > 1)
2626
#define AUDIO_CHANNEL_2_PIN PB9
2727
#endif
2828
#endif

AudioConfigTeensy3_12bit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef AUDIOCONFIGTEENSY3_12BIT_H
22
#define AUDIOCONFIGTEENSY3_12BIT_H
33

4+
#warning If you get a compilation error you should probably update Teensyduino to its latest version
45

56
/** @ingroup core
67
*/

AudioConfigTeensy4.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#ifndef AUDIOCONFIGTEENSY4_H
2+
#define AUDIOCONFIGTEENSY4_H
3+
4+
#warning If you get a compilation error you should probably update Teensyduino to its latest version
5+
6+
/** @ingroup core
7+
*/
8+
/* Used internally to put the 0-biased generated audio into the centre of the output range (10 bits on Teensy 4 using PWM) */
9+
#define AUDIO_BIAS ((uint16_t) 512)
10+
#define AUDIO_BITS 10
11+
12+
#define AUDIO_CHANNEL_1_PIN A8
13+
#define AUDIO_CHANNEL_2_PIN A9
14+
15+
16+
#endif // #ifndef AUDIOCONFIGTEENSY4_H
17+

AudioOutput.h

Lines changed: 21 additions & 195 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,13 @@
5555
#define CLIP_AUDIO(x) constrain((x), (-(AudioOutputStorage_t) AUDIO_BIAS), (AudioOutputStorage_t) AUDIO_BIAS-1)
5656
#endif
5757

58+
#if (AUDIO_CHANNELS == STEREO)
59+
#define AudioOutput StereoOutput
5860
#if (STEREO_HACK == true)
5961
#define AudioOutput_t void
60-
#define AudioOutput StereoOutput
62+
#else
63+
#define AudioOutput_t StereoOutput
64+
#endif
6165
#else
6266
/** Representation of an single audio output sample/frame. For mono output, this is really just a single zero-centered int,
6367
* but for stereo it's a struct containing two ints.
@@ -87,27 +91,25 @@ struct StereoOutput {
8791
StereoOutput(AudioOutputStorage_t l, AudioOutputStorage_t r) : _l(l), _r(r) {};
8892
/** Default contstructor */
8993
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; };
94+
#if (AUDIO_CHANNELS != STEREO)
95+
/** Conversion to int operator: If used in a mono config, returns only the left channel (and gives a compile time warning).
96+
This _could_ be turned into an operator for implicit conversion in this case. For now we chose to apply conversion on demand, only, as most of the time
97+
using StereoOutput in a mono config, is not intended. */
98+
inline AudioOutput_t portable() const __attribute__((deprecated("Sketch generates stereo output, but Mozzi is configured for mono. Check mozzi_config.h."))) { return _l; };
9399
#endif
94100
AudioOutputStorage_t l() const { return _l; };
95101
AudioOutputStorage_t r() const { return _r; };
96102
/** @see MonoOutput::clip(). Clips both channels. */
97103
StereoOutput& clip() { _l = CLIP_AUDIO(_l); _r = CLIP_AUDIO(_r); return *this; };
98104

99105
/** @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)); }
106+
template<typename T> static inline StereoOutput fromNBit(uint8_t bits, T l, T r) { return StereoOutput(SCALE_AUDIO(l, bits), SCALE_AUDIO(r, bits)); }
103107
/** @see MonoOutput::from8Bit(), stereo variant */
104108
static inline StereoOutput from8Bit(int16_t l, int16_t r) { return fromNBit(8, l, r); }
105109
/** @see MonoOutput::from16Bit(), stereo variant */
106110
static inline StereoOutput from16Bit(int16_t l, int16_t r) { return fromNBit(16, l, r); }
107111
/** @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)); }
112+
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)); }
111113
private:
112114
AudioOutputStorage_t _l;
113115
AudioOutputStorage_t _r;
@@ -130,9 +132,11 @@ struct StereoOutput {
130132
struct MonoOutput {
131133
/** Construct an audio frame from raw values (zero-centered) */
132134
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); };
135+
#if (AUDIO_CHANNELS > 1)
136+
/** Conversion to stereo operator: If used in a stereo config, returns identical channels (and gives a compile time warning).
137+
This _could_ be turned into an operator for implicit conversion in this case. For now we chose to apply conversion on demand, only, as most of the time
138+
using StereoOutput in a mono config, is not intended. */
139+
inline StereoOutput portable() const __attribute__((deprecated("Sketch generates mono output, but Mozzi is configured for stereo. Check mozzi_config.h."))) { return StereoOutput(_l, _l); };
136140
#else
137141
/** Conversion to int operator. */
138142
inline operator AudioOutput_t() const { return _l; };
@@ -146,9 +150,7 @@ struct MonoOutput {
146150
/** 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
147151
* 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
148152
* 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)); }
153+
template<typename T> static inline MonoOutput fromNBit(uint8_t bits, T l) { return MonoOutput(SCALE_AUDIO(l, bits)); }
152154
/** 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
153155
* constructor, directly (no scaling gets applied). On platforms/configs using more bits, an appropriate left-shift will be performed. */
154156
static inline MonoOutput from8Bit(int16_t l) { return fromNBit(8, l); }
@@ -162,9 +164,8 @@ struct MonoOutput {
162164
*
163165
* @example fromAlmostNBit(10, oscilA.next() + oscilB.next() + oscilC.next());
164166
*/
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)); }
167+
template<typename A, typename B> static inline MonoOutput fromAlmostNBit(A bits, B l) { return MonoOutput(SCALE_AUDIO_NEAR(l, bits)); }
168+
168169
private:
169170
AudioOutputStorage_t _l;
170171
};
@@ -211,182 +212,7 @@ inline uint32_t pdmCode32(uint16_t sample) {
211212
return outbits;
212213
}
213214

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
215+
#if (EXTERNAL_AUDIO_OUTPUT == true)
390216
#warning "Mozzi is configured to use an external void 'audioOutput(const AudioOutput f)' function. Please define one in your sketch"
391217
#endif
392218

IntegerType.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
template<uint8_t BYTES> struct IntegerType {
3+
// at an odd value, such as 3 bytes? Add one more byte (up to at most 8 bytes)..
4+
typedef typename IntegerType<(BYTES < 8) ? (BYTES+1) : 8>::unsigned_type unsigned_type;
5+
typedef typename IntegerType<(BYTES < 8) ? (BYTES+1) : 8>::signed_type signed_type;
6+
};
7+
8+
// These are the specializations for the types that we actually assume to exist:
9+
template<> struct IntegerType<1> {
10+
typedef uint8_t unsigned_type;
11+
typedef int8_t signed_type;
12+
};
13+
14+
template<> struct IntegerType<2> {
15+
typedef uint16_t unsigned_type;
16+
typedef int16_t signed_type;
17+
};
18+
19+
template<> struct IntegerType<4> {
20+
typedef uint32_t unsigned_type;
21+
typedef int32_t signed_type;
22+
};
23+
24+
template<> struct IntegerType<8> {
25+
typedef uint64_t unsigned_type;
26+
typedef int64_t signed_type;
27+
};

0 commit comments

Comments
 (0)