arduino-audio-tools
Loading...
Searching...
No Matches
VS1053Stream.h
Go to the documentation of this file.
1#pragma once
2
7
8#if VS1053_EXT
9#include "VS1053Driver.h"
10#else
11#include "VS1053.h"
12#endif
13
14namespace audio_tools {
15
17
23class VS1053Config : public AudioInfo {
24 public:
26 sample_rate = 44100;
27 channels = 2;
28 bits_per_sample = 16;
29 }
32
35 uint8_t cs_pin = VS1053_CS;
36
39
43
46 int16_t reset_pin = VS1053_RESET; // -1 is undefined
47
50
53 bool is_encoded_data = false;
54
56 bool is_midi = false;
57
60 bool is_start_spi = true;
61#if VS1053_EXT
62 VS1053_INPUT input_device = VS1053_MIC;
63#endif
64};
65
80class VS1053Stream : public AudioStream, public VolumeSupport {
84 class VS1053StreamOut : public AudioStream {
85 public:
86 VS1053StreamOut(VS1053* vs) { p_VS1053 = vs; }
87 size_t write(const uint8_t* data, size_t len) override {
88 if (p_VS1053 == nullptr) {
89 LOGE("NPE");
90 return 0;
91 }
92 TRACED();
93 p_VS1053->playChunk((uint8_t*)data, len);
94 return len;
95 }
96
97 protected:
98 VS1053* p_VS1053 = nullptr;
99 };
100
101 public:
102 VS1053Stream() = default;
103
107 explicit VS1053Stream(SPIClass& spi) { p_spi = &spi; }
108
110
113 TRACED();
114 VS1053Config c;
115 // recording is rather inefficient so we use a low sample rate as default
116 if (mode == RX_MODE) {
117 c.sample_rate = 8000;
118 }
119 c.mode = mode;
120 return c;
121 }
122
128
134
136 bool begin() { return begin(cfg); }
137
140 TRACEI();
141 bool result = true;
142 // enfornce encoded data for midi mode
143 if (cfg.is_midi) {
144 cfg.is_encoded_data = true;
145 }
146 this->cfg = cfg;
148 cfg.logInfo();
149 LOGI("is_encoded_data: %s", cfg.is_encoded_data ? "true" : "false");
150 LOGI("is_midi: %s", cfg.is_midi ? "true" : "false");
151 LOGI("cs_pin: %d", cfg.cs_pin);
152 LOGI("dcs_pin: %d", cfg.dcs_pin);
153 LOGI("dreq_pin: %d", cfg.dreq_pin);
154 LOGI("reset_pin: %d", cfg.reset_pin);
155 LOGI("cs_sd_pin: %d", cfg.cs_sd_pin);
156
157 if (p_vs1053 == nullptr) {
158#if VS1053_EXT
159 if (p_spi != nullptr) {
160 LOGI("Using custom SPI instance");
161 p_vs1053 = new VS1053(cfg.cs_pin, cfg.dcs_pin, cfg.dreq_pin,
162 (uint8_t)-1, *p_spi);
163 } else {
164 p_vs1053 = new VS1053(cfg.cs_pin, cfg.dcs_pin, cfg.dreq_pin);
165 }
166#else
167 if (p_spi != nullptr) {
168 LOGE("Custom SPI is only supported when using VS1053_EXT");
169 }
170 p_vs1053 = new VS1053(cfg.cs_pin, cfg.dcs_pin, cfg.dreq_pin);
171#endif
172 p_vs1053_out = new VS1053StreamOut(p_vs1053);
173
174 if (cfg.is_start_spi) {
175 if (p_spi != nullptr) {
176 LOGI("p_spi->begin()")
177 p_spi->begin();
178 } else {
179 LOGI("SPI.begin()")
180 SPI.begin();
181 }
182 } else {
183 LOGI("SPI not started");
184 }
185
186 if (cfg.reset_pin != -1) {
187 LOGI("Setting reset pin to high: %d", cfg.reset_pin);
190 delay(800);
191 }
192 }
193
194 // Output Stream
195 if (p_out == nullptr) {
198 }
199
200 // hack to treat midi as separate mode
201 const int MIDI_MODE = 100;
202 int mode = cfg.mode;
203 if (cfg.is_midi) {
204 mode = MIDI_MODE;
205 }
206
207 switch (mode) {
208 case TX_MODE:
209 result = beginTx();
210 break;
211#if VS1053_EXT
212 case MIDI_MODE:
213 result = beginMidi();
214 break;
215
216 case RX_MODE:
217 result = beginRx();
218 break;
219#endif
220 default:
221 LOGD("Mode not supported");
222 result = false;
223 break;
224 }
225
226 // log error on failure
227 if (!result) LOGE("begin failed");
228 return result;
229 }
230
232 void end() {
233 TRACEI();
234 if (p_out != nullptr) {
235 delete p_out;
236 p_out = nullptr;
237 }
238 // free the wrapper before freeing the underlying HW object to avoid
239 // leaving a wrapper with a dangling pointer
240 if (p_vs1053_out != nullptr) {
241 delete p_vs1053_out;
242 p_vs1053_out = nullptr;
243 }
244 if (p_vs1053 != nullptr) {
245 // p_driver->end();
246 p_vs1053->stopSong();
247 p_vs1053->softReset();
248 delete p_vs1053;
249 p_vs1053 = nullptr;
250 }
251 }
252
254 bool setVolume(float vol) override {
255 // make sure that value is between 0 and 1
256 float volume = vol;
257 if (volume > 1.0f) volume = 1.0f;
258 if (volume < 0.0f) volume = 0.0f;
259 LOGD("setVolume: %f", volume);
260 if (p_vs1053 != nullptr) {
261 // Set the player volume.Level from 0-100, higher is louder
262 p_vs1053->setVolume(volume * 100.0f);
263 }
264 return true;
265 }
266
268 float volume() override {
269 TRACED();
270 if (p_vs1053 == nullptr) return -1.0f;
271 return p_vs1053->getVolume() / 100.0f;
272 }
273
276 void setBalance(float bal) {
277 float balance = bal;
278 if (balance < -1.0f) balance = -1.0f;
279 if (balance > 1.0f) balance = 1.0f;
280 LOGD("setBalance: %f", balance);
281 if (p_vs1053 != nullptr) {
282 p_vs1053->setBalance(balance * 100.0f);
283 }
284 }
286 float balance() {
287 TRACED();
288 if (p_vs1053 == nullptr) return -1.0f;
289 return static_cast<float>(p_vs1053->getBalance()) / 100.0f;
290 }
291
293 virtual size_t write(const uint8_t* data, size_t len) override {
294 TRACED();
295 if (len == 0) return 0;
296 if (p_out == nullptr) {
297 LOGE("vs1053 is closed");
298 return 0;
299 }
300 return p_out->write(data, len);
301 }
302
304 VS1053& getVS1053() {
305 TRACED();
306 return *p_vs1053;
307 }
308
312 TRACEI();
313 if (p_out != nullptr) {
314 logError("setEncoder");
315 return false;
316 }
317 // If caller provides nullptr, fall back to the internal wav encoder.
318 // Note: ownership remains external (VS1053Stream does not delete the
319 // encoder pointer).
320 if (enc == nullptr) {
321 p_encoder = &wav;
322 } else {
323 p_encoder = enc;
324 }
325 return true;
326 }
327
328#if VS1053_EXT
329 int available() override {
330 if (p_vs1053 == nullptr) return 0;
331 TRACED();
332 return p_vs1053->available();
333 }
334 size_t readBytes(uint8_t* data, size_t len) override {
335 TRACED();
336 if (p_vs1053 == nullptr) return 0;
337 return p_vs1053->readBytes(data, len);
338 }
339
341 float treble() {
342 TRACED();
343 if (p_vs1053 == nullptr) return -1.0f;
344 return static_cast<float>(getVS1053().treble()) / 100.0;
345 }
346
348 void setTreble(float val) {
349 float value = val;
350 if (value < 0.0f) value = 0.0f;
351 if (value > 1.0f) value = 1.0f;
352 LOGD("setTreble: %f", value);
353 if (p_vs1053 == nullptr) return;
354 getVS1053().setTreble(value * 100.0f);
355 }
356
358 float bass() {
359 TRACED();
360 if (p_vs1053 == nullptr) return -1.0f;
361 return static_cast<float>(getVS1053().bass()) / 100.0;
362 }
363
365 void setBass(float val) {
366 float value = val;
367 if (value < 0.0f) value = 0.0f;
368 if (value > 1.0f) value = 1.0f;
369 LOGD("setBass: %f", value);
370 if (p_vs1053 == nullptr) return;
371 getVS1053().setBass(value * 100.0f);
372 }
373
375 void setTrebleFrequencyLimit(uint16_t value) {
376 LOGD("setTrebleFrequencyLimit: %u", value);
377 if (p_vs1053 == nullptr) return;
378 getVS1053().setTrebleFrequencyLimit(value);
379 }
381 void setBassFrequencyLimit(uint16_t value) {
382 LOGD("setBassFrequencyLimit: %u", value);
383 if (p_vs1053 == nullptr) return;
384 getVS1053().setBassFrequencyLimit(value);
385 }
386
388 void sendMidiMessage(uint8_t cmd, uint8_t data1, uint8_t data2) {
389 TRACEI();
390#if USE_MIDI
391 if (!cfg.is_midi) {
392 LOGE("start with is_midi=true");
393 return;
394 }
395 if (p_vs1053 == nullptr) {
396 logError(__FUNCTION__);
397 return;
398 }
399 p_vs1053->sendMidiMessage(cmd, data1, data2);
400#endif
401 }
402
403#endif
404
405 protected:
407 SPIClass* p_spi = nullptr;
408 VS1053* p_vs1053 = nullptr;
409 VS1053StreamOut* p_vs1053_out = nullptr;
412 AudioEncoder* p_encoder = &wav; // by default we send wav data
413 CopyEncoder copy; // used when is_encoded_data == true
414
415 bool beginTx() {
416 TRACEI();
417 p_out->begin(cfg);
418 bool result = p_vs1053->begin();
419 p_vs1053->startSong();
420 p_vs1053->switchToMp3Mode(); // optional, some boards require this
421 if (p_vs1053->getChipVersion() ==
422 4) { // Only perform an update if we really are using a VS1053, not.
423 // eg. VS1003
424 p_vs1053->loadDefaultVs1053Patches();
425 }
426 delay(500);
428 return result;
429 }
430
431#if VS1053_EXT
432
433 bool beginRx() {
434 TRACEI();
435 VS1053Recording rec;
436 rec.setSampleRate(cfg.sample_rate);
437 rec.setChannels(cfg.channels);
438 rec.setInput(cfg.input_device);
439 return p_vs1053->beginInput(rec);
440 }
441
442 bool beginMidi() {
443#if USE_MIDI
444 TRACEI();
445 p_out->begin(cfg);
446 bool result = p_vs1053->beginMidi();
447 delay(500);
449 return result;
450#else
451 return false;
452#endif
453 }
454
455#endif
456 void logError(const char* str) { LOGE("Call %s after begin()", str); }
457};
458
459} // namespace audio_tools
#define HIGH
Definition Arduino.h:46
#define OUTPUT
Definition Arduino.h:38
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define VS1053_DEFAULT_VOLUME
Definition AudioToolsConfig.h:279
Encoding of PCM data.
Definition AudioCodecsBase.h:98
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:120
virtual size_t readBytes(uint8_t *data, size_t len) override
Definition BaseStream.h:144
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition BaseStream.h:128
virtual size_t write(uint8_t ch) override
Definition BaseStream.h:47
virtual int available() override
Definition BaseStream.h:55
Dummy Encoder which just copies the provided data to the output.
Definition CodecCopy.h:66
A more natural Stream class to process encoded data (aac, wav, mp3...) which also supports the decodi...
Definition AudioEncoded.h:282
size_t write(const uint8_t *data, size_t len) override
Definition AudioEncoded.h:413
bool begin(AudioInfo info)
Definition AudioEncoded.h:364
Configuration for VS1053Stream.
Definition VS1053Stream.h:23
uint8_t dreq_pin
Definition VS1053Stream.h:42
VS1053Config()
Definition VS1053Stream.h:25
int16_t cs_sd_pin
Optional chip-select pin for an attached SD card (if present).
Definition VS1053Stream.h:49
bool is_encoded_data
Definition VS1053Stream.h:53
bool is_start_spi
Definition VS1053Stream.h:60
uint8_t dcs_pin
Data/command select (DCS) pin used by some VS1053 modules.
Definition VS1053Stream.h:38
RxTxMode mode
Operation mode (transmit/receive). Default: TX_MODE (playback).
Definition VS1053Stream.h:31
int16_t reset_pin
Definition VS1053Stream.h:46
bool is_midi
When true enable MIDI streaming mode (this also forces encoded mode).
Definition VS1053Stream.h:56
uint8_t cs_pin
Definition VS1053Stream.h:35
Output Interface which processes PCM data by default using a VS1053 audio module. If you want to writ...
Definition VS1053Stream.h:80
CopyEncoder copy
Definition VS1053Stream.h:413
void setBalance(float bal)
Definition VS1053Stream.h:276
void setAudioInfo(VS1053Config c)
defines the default configuration that is used with the next begin()
Definition VS1053Stream.h:124
VS1053 & getVS1053()
returns the VS1053 object
Definition VS1053Stream.h:304
virtual size_t write(const uint8_t *data, size_t len) override
Write audio data.
Definition VS1053Stream.h:293
VS1053Config defaultConfig(RxTxMode mode=TX_MODE)
Provides the default configuration for the indicated mod.
Definition VS1053Stream.h:112
bool setEncoder(AudioEncoder *enc)
Definition VS1053Stream.h:311
float balance()
Get the currenet balance setting (-1.0..1.0)
Definition VS1053Stream.h:286
VS1053StreamOut * p_vs1053_out
Definition VS1053Stream.h:409
void logError(const char *str)
Definition VS1053Stream.h:456
void setAudioInfo(AudioInfo c)
Updates the AudioInfo (sample rate, bits, channels)
Definition VS1053Stream.h:130
WAVEncoder wav
Definition VS1053Stream.h:411
bool begin()
Starts with the default config or restarts.
Definition VS1053Stream.h:136
VS1053Config cfg
Definition VS1053Stream.h:406
float volume() override
provides the volume
Definition VS1053Stream.h:268
VS1053 * p_vs1053
Definition VS1053Stream.h:408
SPIClass * p_spi
Definition VS1053Stream.h:407
bool beginTx()
Definition VS1053Stream.h:415
VS1053Stream(SPIClass &spi)
Definition VS1053Stream.h:107
void end()
Stops the processing and releases the memory.
Definition VS1053Stream.h:232
bool setVolume(float vol) override
value from 0 to 1.0
Definition VS1053Stream.h:254
AudioEncoder * p_encoder
Definition VS1053Stream.h:412
bool begin(VS1053Config cfg)
Starts with the indicated configuration.
Definition VS1053Stream.h:139
~VS1053Stream()
Definition VS1053Stream.h:109
EncodedAudioStream * p_out
Definition VS1053Stream.h:410
Supports the setting and getting of the volume.
Definition AudioTypes.h:187
A simple WAV file encoder. If no AudioEncoderExt is specified the WAV file contains PCM data,...
Definition CodecWAV.h:972
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:26
@ TX_MODE
Definition AudioTypes.h:26
@ RX_MODE
Definition AudioTypes.h:26
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
void digitalWrite(digital_pin_t pin, bool value)
Definition Arduino.h:317
void delay(uint32_t ms)
Definition Arduino.h:259
void pinMode(digital_pin_t pin, int mode)
Definition Arduino.h:286
VS1053Mode
Definition VS1053Stream.h:16
@ ENCODED_MODE
Definition VS1053Stream.h:16
@ PCM_MODE
Definition VS1053Stream.h:16
@ MIDI_MODE
Definition VS1053Stream.h:16
#define VS1053_DREQ
Definition rp2040hower.h:51
#define VS1053_CS_SD
Definition rp2040hower.h:52
#define VS1053_DCS
Definition rp2040hower.h:50
#define VS1053_RESET
Definition rp2040hower.h:53
#define VS1053_CS
Definition rp2040hower.h:49
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:51
void copyFrom(AudioInfo info)
Same as set.
Definition AudioTypes.h:101
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:53
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:55
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:57
virtual void logInfo(const char *source="")
Definition AudioTypes.h:121