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