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
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
105
108 TRACED();
110 // recording is rather inefficient so we use a low sample rate as default
111 if (mode == RX_MODE) {
112 c.sample_rate = 8000;
113 }
114 c.mode = mode;
115 return c;
116 }
117
123
129
131 bool begin() { return begin(cfg); }
132
135 TRACEI();
136 bool result = true;
137 // enfornce encoded data for midi mode
138 if (cfg.is_midi) {
139 cfg.is_encoded_data = true;
140 }
141 this->cfg = cfg;
143 cfg.logInfo();
144 LOGI("is_encoded_data: %s", cfg.is_encoded_data ? "true" : "false");
145 LOGI("is_midi: %s", cfg.is_midi ? "true" : "false");
146 LOGI("cs_pin: %d", cfg.cs_pin);
147 LOGI("dcs_pin: %d", cfg.dcs_pin);
148 LOGI("dreq_pin: %d", cfg.dreq_pin);
149 LOGI("reset_pin: %d", cfg.reset_pin);
150 LOGI("cs_sd_pin: %d", cfg.cs_sd_pin);
151
152 if (p_vs1053 == nullptr) {
154 p_vs1053_out = new VS1053StreamOut(p_vs1053);
155
156 if (cfg.is_start_spi) {
157 LOGI("SPI.begin()")
158 SPI.begin();
159 } else {
160 LOGI("SPI not started");
161 }
162
163 if (cfg.reset_pin != -1) {
164 LOGI("Setting reset pin to high: %d", cfg.reset_pin);
167 delay(800);
168 }
169 }
170
171 // Output Stream
172 if (p_out == nullptr) {
175 }
176
177 // hack to treat midi as separate mode
178 const int MIDI_MODE = 100;
179 int mode = cfg.mode;
180 if (cfg.is_midi) {
181 mode = MIDI_MODE;
182 }
183
184 switch (mode) {
185 case TX_MODE:
186 result = beginTx();
187 break;
188#if VS1053_EXT
189 case MIDI_MODE:
190 result = beginMidi();
191 break;
192
193 case RX_MODE:
194 result = beginRx();
195 break;
196#endif
197 default:
198 LOGD("Mode not supported");
199 result = false;
200 break;
201 }
202
203 // log error on failure
204 if (!result) LOGE("begin failed");
205 return result;
206 }
207
209 void end() {
210 TRACEI();
211 if (p_out != nullptr) {
212 delete p_out;
213 p_out = nullptr;
214 }
215 // free the wrapper before freeing the underlying HW object to avoid
216 // leaving a wrapper with a dangling pointer
217 if (p_vs1053_out != nullptr) {
218 delete p_vs1053_out;
219 p_vs1053_out = nullptr;
220 }
221 if (p_vs1053 != nullptr) {
222 // p_driver->end();
223 p_vs1053->stopSong();
224 p_vs1053->softReset();
225 delete p_vs1053;
226 p_vs1053 = nullptr;
227 }
228 }
229
231 bool setVolume(float vol) override {
232 // make sure that value is between 0 and 1
233 float volume = vol;
234 if (volume > 1.0f) volume = 1.0f;
235 if (volume < 0.0f) volume = 0.0f;
236 LOGD("setVolume: %f", volume);
237 if (p_vs1053 != nullptr) {
238 // Set the player volume.Level from 0-100, higher is louder
239 p_vs1053->setVolume(volume * 100.0f);
240 }
241 return true;
242 }
243
245 float volume() override {
246 TRACED();
247 if (p_vs1053 == nullptr) return -1.0f;
248 return p_vs1053->getVolume() / 100.0f;
249 }
250
253 void setBalance(float bal) {
254 float balance = bal;
255 if (balance < -1.0f) balance = -1.0f;
256 if (balance > 1.0f) balance = 1.0f;
257 LOGD("setBalance: %f", balance);
258 if (p_vs1053 != nullptr) {
259 p_vs1053->setBalance(balance * 100.0f);
260 }
261 }
263 float balance() {
264 TRACED();
265 if (p_vs1053 == nullptr) return -1.0f;
266 return static_cast<float>(p_vs1053->getBalance()) / 100.0f;
267 }
268
270 virtual size_t write(const uint8_t* data, size_t len) override {
271 TRACED();
272 if (len == 0) return 0;
273 if (p_out == nullptr) {
274 LOGE("vs1053 is closed");
275 return 0;
276 }
277 return p_out->write(data, len);
278 }
279
282 TRACED();
283 return *p_vs1053;
284 }
285
289 TRACEI();
290 if (p_out != nullptr) {
291 logError("setEncoder");
292 return false;
293 }
294 // If caller provides nullptr, fall back to the internal wav encoder.
295 // Note: ownership remains external (VS1053Stream does not delete the
296 // encoder pointer).
297 if (enc == nullptr) {
298 p_encoder = &wav;
299 } else {
300 p_encoder = enc;
301 }
302 return true;
303 }
304
305#if VS1053_EXT
306 int available() override {
307 int result = getVS1053().available();
308 LOGI("available: %d", result);
309 return result;
310 }
311 size_t readBytes(uint8_t* data, size_t len) override {
312 TRACED();
313 return getVS1053().readBytes(data, len);
314 }
315
317 float treble() {
318 TRACED();
319 return static_cast<float>(getVS1053().treble()) / 100.0;
320 }
321
323 void setTreble(float val) {
324 float value = val;
325 if (value < 0.0f) value = 0.0f;
326 if (value > 1.0f) value = 1.0f;
327 LOGD("setTreble: %f", value);
328 getVS1053().setTreble(value * 100.0f);
329 }
330
332 float bass() {
333 TRACED();
334 return static_cast<float>(getVS1053().bass()) / 100.0;
335 }
336
338 void setBass(float val) {
339 float value = val;
340 if (value < 0.0f) value = 0.0f;
341 if (value > 1.0f) value = 1.0f;
342 LOGD("setBass: %f", value);
343 getVS1053().setBass(value * 100.0f);
344 }
345
348 LOGD("setTrebleFrequencyLimit: %u", value);
349 getVS1053().setTrebleFrequencyLimit(value);
350 }
352 void setBassFrequencyLimit(uint16_t value) {
353 LOGD("setBassFrequencyLimit: %u", value);
354 getVS1053().setBassFrequencyLimit(value);
355 }
356
359 TRACEI();
360#if USE_MIDI
361 if (!cfg.is_midi) {
362 LOGE("start with is_midi=true");
363 return;
364 }
365 if (p_vs1053 == nullptr) {
367 return;
368 }
369 p_vs1053->sendMidiMessage(cmd, data1, data2);
370#endif
371 }
372
373#endif
374
375 protected:
377 VS1053* p_vs1053 = nullptr;
378 VS1053StreamOut* p_vs1053_out = nullptr;
381 AudioEncoder* p_encoder = &wav; // by default we send wav data
382 CopyEncoder copy; // used when is_encoded_data == true
383
384 bool beginTx() {
385 TRACEI();
386 p_out->begin(cfg);
387 bool result = p_vs1053->begin();
388 p_vs1053->startSong();
389 p_vs1053->switchToMp3Mode(); // optional, some boards require this
390 if (p_vs1053->getChipVersion() ==
391 4) { // Only perform an update if we really are using a VS1053, not.
392 // eg. VS1003
393 p_vs1053->loadDefaultVs1053Patches();
394 }
395 delay(500);
397 return result;
398 }
399
400#if VS1053_EXT
401
402 bool beginRx() {
403 TRACEI();
404 VS1053Recording rec;
405 rec.setSampleRate(cfg.sample_rate);
406 rec.setChannels(cfg.channels);
407 rec.setInput(cfg.input_device);
408 return p_vs1053->beginInput(rec);
409 }
410
411 bool beginMidi() {
412#if USE_MIDI
413 TRACEI();
414 p_out->begin(cfg);
415 bool result = p_vs1053->beginMidi();
416 delay(500);
418 return result;
419#else
420 return false;
421#endif
422 }
423
424#endif
425 void logError(const char* str) { LOGE("Call %s after begin()", str); }
426};
427
428} // 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:284
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: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:382
void setBalance(float bal)
Definition VS1053Stream.h:253
void setAudioInfo(VS1053Config c)
defines the default configuration that is used with the next begin()
Definition VS1053Stream.h:119
VS1053 & getVS1053()
returns the VS1053 object
Definition VS1053Stream.h:281
virtual size_t write(const uint8_t *data, size_t len) override
Write audio data.
Definition VS1053Stream.h:270
VS1053Config defaultConfig(RxTxMode mode=TX_MODE)
Provides the default configuration for the indicated mod.
Definition VS1053Stream.h:107
bool setEncoder(AudioEncoder *enc)
Definition VS1053Stream.h:288
float balance()
Get the currenet balance setting (-1.0..1.0)
Definition VS1053Stream.h:263
VS1053StreamOut * p_vs1053_out
Definition VS1053Stream.h:378
void logError(const char *str)
Definition VS1053Stream.h:425
void setAudioInfo(AudioInfo c)
Updates the AudioInfo (sample rate, bits, channels)
Definition VS1053Stream.h:125
WAVEncoder wav
Definition VS1053Stream.h:380
bool begin()
Starts with the default config or restarts.
Definition VS1053Stream.h:131
VS1053Config cfg
Definition VS1053Stream.h:376
float volume() override
provides the volume
Definition VS1053Stream.h:245
VS1053 * p_vs1053
Definition VS1053Stream.h:377
bool beginTx()
Definition VS1053Stream.h:384
void end()
Stops the processing and releases the memory.
Definition VS1053Stream.h:209
bool setVolume(float vol) override
value from 0 to 1.0
Definition VS1053Stream.h:231
AudioEncoder * p_encoder
Definition VS1053Stream.h:381
bool begin(VS1053Config cfg)
Starts with the indicated configuration.
Definition VS1053Stream.h:134
~VS1053Stream()
Definition VS1053Stream.h:104
EncodedAudioStream * p_out
Definition VS1053Stream.h:379
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:653
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 AudioCodecsBase.h:10
void digitalWrite(digital_pin_t pin, bool value)
Definition Arduino.h:313
void delay(uint32_t ms)
Definition Arduino.h:255
void pinMode(digital_pin_t pin, int mode)
Definition Arduino.h:282
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:508
#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: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