arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
VS1053Stream.h
1#pragma once
2
3#include "AudioTools/CoreAudio/AudioStreams.h"
4#include "AudioTools/AudioCodecs/CodecCopy.h"
5#include "AudioTools/AudioCodecs/AudioEncoded.h"
6#include "AudioTools/AudioCodecs/CodecWAV.h"
7
8#if VS1053_EXT
9# include "VS1053Driver.h"
10#else
11# include "VS1053.h"
12#endif
13
14namespace audio_tools {
15
16enum VS1053Mode {ENCODED_MODE, PCM_MODE, MIDI_MODE };
17
23class VS1053Config : public AudioInfo {
24 public:
26 sample_rate = 44100;
27 channels = 2;
28 bits_per_sample = 16;
29 }
30 RxTxMode mode = TX_MODE;
32 uint8_t cs_pin = VS1053_CS;
33 uint8_t dcs_pin = VS1053_DCS;
34 uint8_t dreq_pin = VS1053_DREQ;
35 int16_t reset_pin = VS1053_RESET; // -1 is undefined
36 int16_t cs_sd_pin = VS1053_CS_SD;
38 bool is_encoded_data = false;
40 bool is_midi = false;
42 bool is_start_spi = true;
43#if VS1053_EXT
44 VS1053_INPUT input_device = VS1053_MIC;
45#endif
46};
47
55class VS1053Stream : public AudioStream, public VolumeSupport {
56
60 class VS1053StreamOut : public AudioStream {
61 public:
62 VS1053StreamOut(VS1053 *vs){
63 p_VS1053 = vs;
64 }
65 size_t write(const uint8_t *data, size_t len) override {
66 if (p_VS1053==nullptr) {
67 LOGE("NPE");
68 return 0;
69 }
70 TRACED();
71 p_VS1053->playChunk((uint8_t*)data, len);
72 return len;
73 }
74 protected:
75 VS1053 *p_VS1053=nullptr;
76 };
77
78public:
79
80 VS1053Stream() = default;
81
82 VS1053Config defaultConfig(RxTxMode mode=TX_MODE) {
83 TRACED();
85 // recording is rather inefficient so we use a low sample rate as default
86 if (mode==RX_MODE){
87 c.sample_rate = 8000;
88 }
89 c.mode = mode;
90 return c;
91 }
92
95 cfg = c;
96 }
97
99 cfg.copyFrom(c);
100 }
101
103 bool begin() {
104 return begin(cfg);
105 }
106
108 bool begin(VS1053Config cfg) {
109 TRACEI();
110 bool result = true;
111 // enfornce encoded data for midi mode
112 if (cfg.is_midi){
113 cfg.is_encoded_data = true;
114 }
115 this->cfg = cfg;
116 setAudioInfo(cfg);
117 cfg.logInfo();
118 LOGI("is_encoded_data: %s", cfg.is_encoded_data?"true":"false");
119 LOGI("is_midi: %s", cfg.is_midi?"true":"false");
120 LOGI("cs_pin: %d", cfg.cs_pin);
121 LOGI("dcs_pin: %d", cfg.dcs_pin);
122 LOGI("dreq_pin: %d", cfg.dreq_pin);
123 LOGI("reset_pin: %d", cfg.reset_pin);
124 LOGI("cs_sd_pin: %d", cfg.cs_sd_pin);
125
126 if (p_vs1053==nullptr){
127 p_vs1053 = new VS1053(cfg.cs_pin,cfg.dcs_pin,cfg.dreq_pin);
128 p_vs1053_out = new VS1053StreamOut(p_vs1053);
129
130 if (cfg.is_start_spi) {
131 LOGI("SPI.begin()")
132 SPI.begin();
133 } else {
134 LOGI("SPI not started");
135 }
136
137 if (cfg.reset_pin!=-1){
138 LOGI("Setting reset pin to high: %d", cfg.reset_pin);
139 pinMode(cfg.reset_pin, OUTPUT);
140 digitalWrite(cfg.reset_pin, HIGH);
141 delay(800);
142 }
143 }
144
145 // Output Stream
146 if (p_out==nullptr){
147 AudioEncoder *p_enc = cfg.is_encoded_data ? &copy:p_encoder;
148 p_out = new EncodedAudioStream(p_vs1053_out, p_enc);
149 }
150
151 // hack to treat midi as separate mode
152 const int MIDI_MODE = 100;
153 int mode = cfg.mode;
154 if (cfg.is_midi){
155 mode = MIDI_MODE;
156 }
157
158 switch(mode){
159
160 case TX_MODE:
161 result = beginTx();
162 break;
163#if VS1053_EXT
164 case MIDI_MODE:
165 result = beginMidi();
166 break;
167
168 case RX_MODE:
169 result = beginRx();
170 break;
171#endif
172 default:
173 LOGD("Mode not supported");
174 result = false;
175 break;
176 }
177 return result;
178 }
179
181 void end(){
182 TRACEI();
183 if (p_out!=nullptr){
184 delete p_out;
185 p_out = nullptr;
186 }
187 if (p_vs1053!=nullptr){
188 //p_driver->end();
189 p_vs1053->stopSong();
190 p_vs1053->softReset();
191 delete p_vs1053;
192 p_vs1053 = nullptr;
193 }
194 }
195
197 bool setVolume(float vol) override {
198 // make sure that value is between 0 and 1
199 float volume = vol;
200 if (volume>1.0) volume = 1.0;
201 if (volume<0.0) volume = 0.0;
202 LOGD("setVolume: %f", volume);
203 if (p_vs1053!=nullptr){
204 // Set the player volume.Level from 0-100, higher is louder
205 p_vs1053->setVolume(volume*100.0);
206 }
207 return true;
208 }
209
211 float volume() override {
212 TRACED();
213 if (p_vs1053==nullptr) return -1.0;
214 return p_vs1053->getVolume()/100.0;;
215 }
216
218 void setBalance(float bal){
219 float balance = bal;
220 if (balance<-1.0) balance = -1;
221 if (balance>1.0) balance = 1;
222 LOGD("setBalance: %f", balance);
223 if (p_vs1053!=nullptr){
224 p_vs1053->setBalance(balance*100.0);
225 }
226 }
228 float balance(){
229 TRACED();
230 if (p_vs1053==nullptr) return -1.0;
231 return static_cast<float>(p_vs1053->getBalance())/100.0;
232 }
233
235 virtual size_t write(const uint8_t *data, size_t len) override {
236 TRACED();
237 if (len==0) return 0;
238 if (p_out==nullptr) {
239 LOGE("vs1053 is closed");
240 return 0;
241 }
242 return p_out->write(data, len);
243 }
244
246 VS1053 &getVS1053() {
247 TRACED();
248 return *p_vs1053;
249 }
250
253 TRACEI();
254 if (p_out!=nullptr){
255 logError("setEncoder");
256 return false;
257 }
258 if (p_encoder!=nullptr){
259 delete p_encoder;
260 p_encoder = enc;
261 }
262 return true;
263 }
264
265#if VS1053_EXT
266 int available() override {
267 int result = getVS1053().available();
268 LOGI("available: %d", result);
269 return result;
270 }
271 size_t readBytes(uint8_t* data, size_t len) override {
272 TRACED();
273 return getVS1053().readBytes(data, len);
274 }
275
277 float treble() {
278 TRACED();
279 return static_cast<float>(getVS1053().treble())/100.0;
280 }
281
283 void setTreble(float val){
284 float value = val;
285 if (value<0.0) value = 0.0;
286 if (value>1.0) value = 1.0;
287 LOGD("setTreble: %f", value);
288 getVS1053().setTreble(value*100);
289 }
290
292 float bass() {
293 TRACED();
294 return static_cast<float>(getVS1053().bass())/100.0;
295 }
296
298 void setBass(float val){
299 float value = val;
300 if (value<0.0) value = 0.0;
301 if (value>1.0) value = 1.0;
302 LOGD("setBass: %f", value);
303 getVS1053().setBass(value*100.0);
304 }
305
307 void setTrebleFrequencyLimit(uint16_t value){
308 LOGD("setTrebleFrequencyLimit: %u", value);
309 getVS1053().setTrebleFrequencyLimit(value);
310 }
312 void setBassFrequencyLimit(uint16_t value){
313 LOGD("setBassFrequencyLimit: %u", value);
314 getVS1053().setBassFrequencyLimit(value);
315 }
316
318 void sendMidiMessage(uint8_t cmd, uint8_t data1, uint8_t data2) {
319 TRACEI();
320#if USE_MIDI
321 if (!cfg.is_midi){
322 LOGE("start with is_midi=true");
323 return;
324 }
325 if (p_vs1053==nullptr) {
326 logError(__FUNCTION__);
327 return;
328 }
329 p_vs1053->sendMidiMessage(cmd, data1, data2);
330#endif
331 }
332
333#endif
334
335protected:
336 VS1053Config cfg;
337 VS1053 *p_vs1053 = nullptr;
338 VS1053StreamOut *p_vs1053_out = nullptr;
339 EncodedAudioStream *p_out = nullptr;
340 AudioEncoder *p_encoder = new WAVEncoder(); // by default we send wav data
341 CopyEncoder copy; // used when is_encoded_data == true
342
343 bool beginTx() {
344 TRACEI();
345 p_out->begin(cfg);
346 bool result = p_vs1053->begin();
347 p_vs1053->startSong();
348 p_vs1053->switchToMp3Mode(); // optional, some boards require this
349 if (p_vs1053->getChipVersion() == 4) { // Only perform an update if we really are using a VS1053, not. eg. VS1003
350 p_vs1053->loadDefaultVs1053Patches();
351 }
352 delay(500);
353 setVolume(VS1053_DEFAULT_VOLUME);
354 return result;
355 }
356
357#if VS1053_EXT
358
359 bool beginRx() {
360 TRACEI();
361 VS1053Recording rec;
362 rec.setSampleRate(cfg.sample_rate);
363 rec.setChannels(cfg.channels);
364 rec.setInput(cfg.input_device);
365 return p_vs1053->beginInput(rec);
366 }
367
368 bool beginMidi(){
369#if USE_MIDI
370 TRACEI();
371 p_out->begin(cfg);
372 bool result = p_vs1053->beginMidi();
373 delay(500);
374 setVolume(VS1053_DEFAULT_VOLUME);
375 return result;
376#else
377 return false;
378#endif
379 }
380
381#endif
382 void logError(const char* str){
383 LOGE("Call %s after begin()", str);
384 }
385
386
387};
388
389}
Encoding of PCM data.
Definition AudioCodecsBase.h:90
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:119
A more natural Stream class to process encoded data (aac, wav, mp3...) which also supports the decodi...
Definition AudioEncoded.h:232
Configuration for VS1053Stream.
Definition VS1053Stream.h:23
bool is_encoded_data
The data is encoded as WAV, MPEG etc. By default this is false and supports PCM data.
Definition VS1053Stream.h:38
bool is_start_spi
SPI.begin is called by the driver (default setting)
Definition VS1053Stream.h:42
bool is_midi
set true for streaming midi
Definition VS1053Stream.h:40
uint8_t cs_pin
set to false if it is a pcm stream
Definition VS1053Stream.h:32
VS1053 Output Interface which processes PCM data by default. If you want to write encoded data set is...
Definition VS1053Stream.h:55
void setBalance(float bal)
Adjusting the left and right volume balance, higher to enhance the right side, lower to enhance the l...
Definition VS1053Stream.h:218
void setAudioInfo(VS1053Config c)
defines the default configuration that is used with the next begin()
Definition VS1053Stream.h:94
VS1053 & getVS1053()
returns the VS1053 object
Definition VS1053Stream.h:246
virtual size_t write(const uint8_t *data, size_t len) override
Write audio data.
Definition VS1053Stream.h:235
bool setEncoder(AudioEncoder *enc)
Defines an alternative encoder that will be used (e.g. MP3Encoder). It must be allocated on the heap!
Definition VS1053Stream.h:252
float balance()
Get the currenet balance setting (-1.0..1.0)
Definition VS1053Stream.h:228
void setAudioInfo(AudioInfo c)
Defines the input AudioInfo.
Definition VS1053Stream.h:98
bool begin()
Starts with the default config or restarts.
Definition VS1053Stream.h:103
float volume() override
provides the volume
Definition VS1053Stream.h:211
void end()
Stops the processing and releases the memory.
Definition VS1053Stream.h:181
bool setVolume(float vol) override
value from 0 to 1.0
Definition VS1053Stream.h:197
bool begin(VS1053Config cfg)
Starts with the indicated configuration.
Definition VS1053Stream.h:108
Supports the setting and getting of the volume.
Definition AudioTypes.h:189
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:28
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:53
void copyFrom(AudioInfo info)
Same as set.
Definition AudioTypes.h:103
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:55
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:57
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:59