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
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
78class VS1053Stream : public AudioStream, public VolumeSupport {
82 class VS1053StreamOut : public AudioStream {
83 public:
84 VS1053StreamOut(VS1053* vs) { p_VS1053 = vs; }
85 size_t write(const uint8_t* data, size_t len) override {
86 if (p_VS1053 == nullptr) {
87 LOGE("NPE");
88 return 0;
89 }
90 TRACED();
91 p_VS1053->playChunk((uint8_t*)data, len);
92 return len;
93 }
94
95 protected:
96 VS1053* p_VS1053 = nullptr;
97 };
98
99 public:
100 VS1053Stream() = default;
101
103
106 TRACED();
108 // recording is rather inefficient so we use a low sample rate as default
109 if (mode == RX_MODE) {
110 c.sample_rate = 8000;
111 }
112 c.mode = mode;
113 return c;
114 }
115
121
127
129 bool begin() { return begin(cfg); }
130
133 TRACEI();
134 bool result = true;
135 // enfornce encoded data for midi mode
136 if (cfg.is_midi) {
137 cfg.is_encoded_data = true;
138 }
139 this->cfg = cfg;
141 cfg.logInfo();
142 LOGI("is_encoded_data: %s", cfg.is_encoded_data ? "true" : "false");
143 LOGI("is_midi: %s", cfg.is_midi ? "true" : "false");
144 LOGI("cs_pin: %d", cfg.cs_pin);
145 LOGI("dcs_pin: %d", cfg.dcs_pin);
146 LOGI("dreq_pin: %d", cfg.dreq_pin);
147 LOGI("reset_pin: %d", cfg.reset_pin);
148 LOGI("cs_sd_pin: %d", cfg.cs_sd_pin);
149
150 if (p_vs1053 == nullptr) {
152 p_vs1053_out = new VS1053StreamOut(p_vs1053);
153
154 if (cfg.is_start_spi) {
155 LOGI("SPI.begin()")
156 SPI.begin();
157 } else {
158 LOGI("SPI not started");
159 }
160
161 if (cfg.reset_pin != -1) {
162 LOGI("Setting reset pin to high: %d", cfg.reset_pin);
165 delay(800);
166 }
167 }
168
169 // Output Stream
170 if (p_out == nullptr) {
173 }
174
175 // hack to treat midi as separate mode
176 const int MIDI_MODE = 100;
177 int mode = cfg.mode;
178 if (cfg.is_midi) {
179 mode = MIDI_MODE;
180 }
181
182 switch (mode) {
183 case TX_MODE:
184 result = beginTx();
185 break;
186#if VS1053_EXT
187 case MIDI_MODE:
188 result = beginMidi();
189 break;
190
191 case RX_MODE:
192 result = beginRx();
193 break;
194#endif
195 default:
196 LOGD("Mode not supported");
197 result = false;
198 break;
199 }
200
201 // log error on failure
202 if (!result) LOGE("begin failed");
203 return result;
204 }
205
207 void end() {
208 TRACEI();
209 if (p_out != nullptr) {
210 delete p_out;
211 p_out = nullptr;
212 }
213 // free the wrapper before freeing the underlying HW object to avoid
214 // leaving a wrapper with a dangling pointer
215 if (p_vs1053_out != nullptr) {
216 delete p_vs1053_out;
217 p_vs1053_out = nullptr;
218 }
219 if (p_vs1053 != nullptr) {
220 // p_driver->end();
221 p_vs1053->stopSong();
222 p_vs1053->softReset();
223 delete p_vs1053;
224 p_vs1053 = nullptr;
225 }
226 }
227
229 bool setVolume(float vol) override {
230 // make sure that value is between 0 and 1
231 float volume = vol;
232 if (volume > 1.0f) volume = 1.0f;
233 if (volume < 0.0f) volume = 0.0f;
234 LOGD("setVolume: %f", volume);
235 if (p_vs1053 != nullptr) {
236 // Set the player volume.Level from 0-100, higher is louder
237 p_vs1053->setVolume(volume * 100.0f);
238 }
239 return true;
240 }
241
243 float volume() override {
244 TRACED();
245 if (p_vs1053 == nullptr) return -1.0f;
246 return p_vs1053->getVolume() / 100.0f;
247 }
248
251 void setBalance(float bal) {
252 float balance = bal;
253 if (balance < -1.0f) balance = -1.0f;
254 if (balance > 1.0f) balance = 1.0f;
255 LOGD("setBalance: %f", balance);
256 if (p_vs1053 != nullptr) {
257 p_vs1053->setBalance(balance * 100.0f);
258 }
259 }
261 float balance() {
262 TRACED();
263 if (p_vs1053 == nullptr) return -1.0f;
264 return static_cast<float>(p_vs1053->getBalance()) / 100.0f;
265 }
266
268 virtual size_t write(const uint8_t* data, size_t len) override {
269 TRACED();
270 if (len == 0) return 0;
271 if (p_out == nullptr) {
272 LOGE("vs1053 is closed");
273 return 0;
274 }
275 return p_out->write(data, len);
276 }
277
280 TRACED();
281 return *p_vs1053;
282 }
283
287 TRACEI();
288 if (p_out != nullptr) {
289 logError("setEncoder");
290 return false;
291 }
292 // If caller provides nullptr, fall back to the internal wav encoder.
293 // Note: ownership remains external (VS1053Stream does not delete the
294 // encoder pointer).
295 if (enc == nullptr) {
296 p_encoder = &wav;
297 } else {
298 p_encoder = enc;
299 }
300 return true;
301 }
302
303#if VS1053_EXT
304 int available() override {
305 int result = getVS1053().available();
306 LOGI("available: %d", result);
307 return result;
308 }
309 size_t readBytes(uint8_t* data, size_t len) override {
310 TRACED();
311 return getVS1053().readBytes(data, len);
312 }
313
315 float treble() {
316 TRACED();
317 return static_cast<float>(getVS1053().treble()) / 100.0;
318 }
319
321 void setTreble(float val) {
322 float value = val;
323 if (value < 0.0f) value = 0.0f;
324 if (value > 1.0f) value = 1.0f;
325 LOGD("setTreble: %f", value);
326 getVS1053().setTreble(value * 100.0f);
327 }
328
330 float bass() {
331 TRACED();
332 return static_cast<float>(getVS1053().bass()) / 100.0;
333 }
334
336 void setBass(float val) {
337 float value = val;
338 if (value < 0.0f) value = 0.0f;
339 if (value > 1.0f) value = 1.0f;
340 LOGD("setBass: %f", value);
341 getVS1053().setBass(value * 100.0f);
342 }
343
346 LOGD("setTrebleFrequencyLimit: %u", value);
347 getVS1053().setTrebleFrequencyLimit(value);
348 }
350 void setBassFrequencyLimit(uint16_t value) {
351 LOGD("setBassFrequencyLimit: %u", value);
352 getVS1053().setBassFrequencyLimit(value);
353 }
354
357 TRACEI();
358#if USE_MIDI
359 if (!cfg.is_midi) {
360 LOGE("start with is_midi=true");
361 return;
362 }
363 if (p_vs1053 == nullptr) {
365 return;
366 }
367 p_vs1053->sendMidiMessage(cmd, data1, data2);
368#endif
369 }
370
371#endif
372
373 protected:
375 VS1053* p_vs1053 = nullptr;
376 VS1053StreamOut* p_vs1053_out = nullptr;
379 AudioEncoder* p_encoder = &wav; // by default we send wav data
380 CopyEncoder copy; // used when is_encoded_data == true
381
382 bool beginTx() {
383 TRACEI();
384 p_out->begin(cfg);
385 bool result = p_vs1053->begin();
386 p_vs1053->startSong();
387 p_vs1053->switchToMp3Mode(); // optional, some boards require this
388 if (p_vs1053->getChipVersion() ==
389 4) { // Only perform an update if we really are using a VS1053, not.
390 // eg. VS1003
391 p_vs1053->loadDefaultVs1053Patches();
392 }
393 delay(500);
395 return result;
396 }
397
398#if VS1053_EXT
399
400 bool beginRx() {
401 TRACEI();
402 VS1053Recording rec;
403 rec.setSampleRate(cfg.sample_rate);
404 rec.setChannels(cfg.channels);
405 rec.setInput(cfg.input_device);
406 return p_vs1053->beginInput(rec);
407 }
408
409 bool beginMidi() {
410#if USE_MIDI
411 TRACEI();
412 p_out->begin(cfg);
413 bool result = p_vs1053->beginMidi();
414 delay(500);
416 return result;
417#else
418 return false;
419#endif
420 }
421
422#endif
423 void logError(const char* str) { LOGE("Call %s after begin()", str); }
424};
425
426} // namespace audio_tools
#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:257
#define HIGH
Definition NoArduino.h:50
#define OUTPUT
Definition NoArduino.h:42
void pinMode(int pin, int mode)
Definition NoArduino.h:210
void digitalWrite(int pin, int value)
Definition NoArduino.h:206
Encoding of PCM data.
Definition AudioCodecsBase.h:97
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:123
virtual size_t readBytes(uint8_t *data, size_t len) override
Definition BaseStream.h:147
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition BaseStream.h:131
virtual size_t write(uint8_t ch) override
Definition BaseStream.h:50
virtual int available() override
Definition BaseStream.h:58
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:271
size_t write(const uint8_t *data, size_t len) override
Definition AudioEncoded.h:373
bool begin(AudioInfo info)
Definition AudioEncoded.h:353
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:78
CopyEncoder copy
Definition VS1053Stream.h:380
void setBalance(float bal)
Definition VS1053Stream.h:251
void setAudioInfo(VS1053Config c)
defines the default configuration that is used with the next begin()
Definition VS1053Stream.h:117
VS1053 & getVS1053()
returns the VS1053 object
Definition VS1053Stream.h:279
virtual size_t write(const uint8_t *data, size_t len) override
Write audio data.
Definition VS1053Stream.h:268
VS1053Config defaultConfig(RxTxMode mode=TX_MODE)
Provides the default configuration for the indicated mod.
Definition VS1053Stream.h:105
bool setEncoder(AudioEncoder *enc)
Definition VS1053Stream.h:286
float balance()
Get the currenet balance setting (-1.0..1.0)
Definition VS1053Stream.h:261
VS1053StreamOut * p_vs1053_out
Definition VS1053Stream.h:376
void logError(const char *str)
Definition VS1053Stream.h:423
void setAudioInfo(AudioInfo c)
Updates the AudioInfo (sample rate, bits, channels)
Definition VS1053Stream.h:123
WAVEncoder wav
Definition VS1053Stream.h:378
bool begin()
Starts with the default config or restarts.
Definition VS1053Stream.h:129
VS1053Config cfg
Definition VS1053Stream.h:374
float volume() override
provides the volume
Definition VS1053Stream.h:243
VS1053 * p_vs1053
Definition VS1053Stream.h:375
bool beginTx()
Definition VS1053Stream.h:382
void end()
Stops the processing and releases the memory.
Definition VS1053Stream.h:207
bool setVolume(float vol) override
value from 0 to 1.0
Definition VS1053Stream.h:229
AudioEncoder * p_encoder
Definition VS1053Stream.h:379
bool begin(VS1053Config cfg)
Starts with the indicated configuration.
Definition VS1053Stream.h:132
~VS1053Stream()
Definition VS1053Stream.h:102
EncodedAudioStream * p_out
Definition VS1053Stream.h:377
Supports the setting and getting of the volume.
Definition AudioTypes.h:191
A simple WAV file encoder. If no AudioEncoderExt is specified the WAV file contains PCM data,...
Definition CodecWAV.h:521
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:30
@ TX_MODE
Definition AudioTypes.h:30
@ RX_MODE
Definition AudioTypes.h:30
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
void delay(unsigned long ms)
Definition Time.h:23
VS1053Mode
Definition VS1053Stream.h:16
@ ENCODED_MODE
Definition VS1053Stream.h:16
@ PCM_MODE
Definition VS1053Stream.h:16
@ MIDI_MODE
Definition VS1053Stream.h:16
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:512
#define VS1053_DREQ
Definition rp2040hower.h:44
#define VS1053_CS_SD
Definition rp2040hower.h:45
#define VS1053_DCS
Definition rp2040hower.h:43
#define VS1053_RESET
Definition rp2040hower.h:46
#define VS1053_CS
Definition rp2040hower.h:42
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:55
void copyFrom(AudioInfo info)
Same as set.
Definition AudioTypes.h:105
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:57
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:59
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:61
virtual void logInfo(const char *source="")
Definition AudioTypes.h:125