Mozzi  version v2.0
sound synthesis library for Arduino
MozziGuts_impl_MBED.hpp
1 /*
2  * MozziGuts_impl_MBED.hpp
3  *
4  * This file is part of Mozzi.
5  *
6  * Copyright 2023-2024 T. Combriat 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 
12 #if !(IS_MBED())
13 # error "Wrong implementation included for this platform"
14 #endif
15 
16 #define CHUNKSIZE 64
17 
18 namespace MozziPrivate {
19 
21 
22 #if MOZZI_IS(MOZZI_AUDIO_INPUT, MOZZI_AUDIO_INPUT_STANDARD)
23 #define MOZZI__LEGACY_AUDIO_INPUT_IMPL 0
24 
25 } // namespace MozziPrivate
26 #include <Arduino_AdvancedAnalog.h>
27 namespace MozziPrivate {
28 
29 AdvancedADC adc(MOZZI_AUDIO_INPUT_PIN);
30 Sample inbuf[CHUNKSIZE];
31 int inbufpos=0;
32 
33 bool audioInputAvailable() {
34  if (inbufpos >= CHUNKSIZE) {
35  if (!adc.available()) return false;
36  SampleBuffer buf = adc.read();
37  memcpy(inbuf,buf.data(), CHUNKSIZE*sizeof(Sample));
38  inbufpos = 0;
39  buf.release();
40  return true;
41  }
42  else return true;
43 }
44 AudioOutputStorage_t readAudioInput(){
45  return inbuf[inbufpos++];
46 }
47 
48 
49 static void startAudioInput() {
50  if (!adc.begin(AN_RESOLUTION_12, MOZZI_AUDIO_RATE, CHUNKSIZE, 256/CHUNKSIZE)) {
51  Serial.println("Failed to start analog acquisition!");
52  while (1);
53  }
54 }
55 #else
56 static void startAudioInput() {}; // dummy to ease coding
57 #endif
58 
59 #if MOZZI_IS(MOZZI_ANALOG_READ, MOZZI_ANALOG_READ_STANDARD)
60 #error not yet implemented
65 // Insert here code to read the result of the latest asynchronous conversion, when it is finished.
66 // You can also provide this as a function returning unsigned int, should it be more complex on your platform
67 #define getADCReading() 0
68 
81 // NOTE: Theoretically, adcPinToChannelNum is public API for historical reasons, thus cannot be replaced by a define
82 uint8_t adcPinToChannelNum(uint8_t pin) {
83  return pin;
84 }
85 
87 void adcStartConversion(uint8_t channel) {
88 }
89 
92 void startSecondADCReadOnCurrentChannel() {
93 }
94 
97 void setupFastAnalogRead(int8_t speed) {
98 }
99 
102 void setupMozziADC(int8_t speed) {
103 }
104 
105 #endif
106 
108 
110 #if MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_EXTERNAL_TIMED)
111 
112 #define US_PER_AUDIO_TICK (1000000L / MOZZI_AUDIO_RATE)
113 } // namespace MozziPrivate
114 #include <mbed.h>
115 namespace MozziPrivate {
116 mbed::Ticker audio_output_timer;
117 
118 volatile bool audio_output_requested = false;
119 inline void defaultAudioOutputCallback() {
120  audio_output_requested = true;
121 }
122 
123 #define AUDIO_HOOK_HOOK { if (audio_output_requested) { audio_output_requested = false; defaultAudioOutput(); } }
124 
125 static void startAudio() {
126  audio_output_timer.attach_us(&defaultAudioOutputCallback, US_PER_AUDIO_TICK);
127  startAudioInput();
128 }
129 
130 void stopMozzi() {
131  audio_output_timer.detach();
132 }
133 
134 #elif MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_INTERNAL_DAC)
135 
136 } // namespace MozziPrivate
137 #include <Arduino_AdvancedAnalog.h>
138 namespace MozziPrivate {
139 
140 AdvancedDAC dac1(MOZZI_AUDIO_PIN_1);
141 Sample buf1[CHUNKSIZE];
142 #if (MOZZI_AUDIO_CHANNELS > 1)
143 AdvancedDAC dac2(MOZZI_AUDIO_PIN_2);
144 Sample buf2[CHUNKSIZE];
145 #endif
146 int bufpos = 0;
147 
148 inline void commitBuffer(Sample buffer[], AdvancedDAC &dac) {
149  SampleBuffer dmabuf = dac.dequeue();
150  // NOTE: Yes, this is silly code, and originated as an accident. Somehow it appears to help _a little_ against current problem wrt DAC stability
151  for (unsigned int i=0;i<CHUNKSIZE;i++) memcpy(dmabuf.data(), buffer, CHUNKSIZE*sizeof(Sample));
152  dac.write(dmabuf);
153 }
154 
155 inline void audioOutput(const AudioOutput f) {
156  if (bufpos >= CHUNKSIZE) {
157  commitBuffer(buf1, dac1);
158 #if (MOZZI_AUDIO_CHANNELS > 1)
159  commitBuffer(buf2, dac2);
160 #endif
161  bufpos = 0;
162  }
163  buf1[bufpos] = f.l()+MOZZI_AUDIO_BIAS;
164 #if (MOZZI_AUDIO_CHANNELS > 1)
165  buf2[bufpos] = f.r()+MOZZI_AUDIO_BIAS;
166 #endif
167  ++bufpos;
168 }
169 
170 bool canBufferAudioOutput() {
171  return (bufpos < CHUNKSIZE || (dac1.available()
172 #if (MOZZI_AUDIO_CHANNELS > 1)
173  && dac2.available()
174 #endif
175  ));
176 }
177 
178 static void startAudio() {
179  //NOTE: DAC setup currently affected by https://github.com/arduino-libraries/Arduino_AdvancedAnalog/issues/35 . Don't expect this to work, until using a fixed version fo Arduino_AdvancedAnalog!
180  if (!dac1.begin(AN_RESOLUTION_12, MOZZI_AUDIO_RATE, CHUNKSIZE, 256/CHUNKSIZE)) {
181  Serial.println("Failed to start DAC1 !");
182  while (1);
183  }
184 #if (MOZZI_AUDIO_CHANNELS > 1)
185  if (!dac2.begin(AN_RESOLUTION_12, MOZZI_AUDIO_RATE, CHUNKSIZE, 256/CHUNKSIZE)) {
186  Serial.println("Failed to start DAC2 !");
187  while (1);
188  }
189 #endif
190  startAudioInput();
191 }
192 
193 void stopMozzi() {
194  dac1.stop();
195 #if (MOZZI_AUDIO_CHANNELS > 1)
196  dac2.stop();
197 #endif
198 }
199 
200 #elif MOZZI_IS(MOZZI_AUDIO_MODE, MOZZI_OUTPUT_PDM_VIA_SERIAL)
201 
202 } // namespace MozziPrivate
203 #include <mbed.h>
204 namespace MozziPrivate {
205 
206 mbed::BufferedSerial serial_out1(digitalPinToPinName(MOZZI_SERIAL_PIN_TX), digitalPinToPinName(MOZZI_SERIAL_PIN_RX));
207 uint8_t buf[MOZZI_PDM_RESOLUTION*4];
208 
209 bool canBufferAudioOutput() {
210  return serial_out1.writable();
211 }
212 
213 inline void audioOutput(const AudioOutput f) {
214  for (uint8_t i = 0; i < MOZZI_PDM_RESOLUTION*4; ++i) {
215  buf[i] = pdmCode8(f.l()+MOZZI_AUDIO_BIAS);
216  }
217  serial_out1.write(&buf, MOZZI_PDM_RESOLUTION*4);
218 }
219 
220 static void startAudio() {
221  serial_out1.set_baud(MOZZI_AUDIO_RATE*MOZZI_PDM_RESOLUTION*40); // NOTE: 40 == 4 * (8 bits + stop-bits)
222  serial_out1.set_format(8, mbed::BufferedSerial::None, 1);
223 }
224 
225 void stopMozzi() {
226 #warning implement me
227 }
228 
229 
230 #endif
232 
234 void MozziRandPrivate::autoSeed() {
235 #warning Automatic random seeding is not implemented on this platform
236 }
238 
239 } // namespace MozziPrivate
240 
241 #undef CHUNKSIZE
242 #undef US_PER_AUDIO_TICK
Sample is like Oscil, it plays a wavetable.
Definition: Sample.h:49
#define MOZZI_AUDIO_CHANNELS
This sets allows to change from a single/mono audio output channel to stereo output.
#define MOZZI_AUDIO_PIN_1
Only for MOZZI_AUDIO_MODE s MOZZI_OUTPUT_PWM and MOZZI_OUTPUT_2PIN_PWM: The IO pin to use as (first) ...
#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,...
void stopMozzi()
Stops audio and control interrupts and restores the timers to the values they had before Mozzi was st...
Definition: MozziGuts.hpp:303
Internal.
Definition: mozzi_rand_p.h:15
This struct encapsulates one frame of mono audio output.
Definition: AudioOutput.h:111