acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
Audio.h (26309B)
1 /* 2 * Audio.h 3 * 4 * Created on: Oct 28,2018 5 * Updated on: Nov 22,2022 6 * Author: Wolle (schreibfaul1) 7 */ 8 9 //#define SDFATFS_USED // activate for SdFat 10 11 12 #pragma once 13 #pragma GCC optimize ("Ofast") 14 #include <vector> 15 #include <Arduino.h> 16 #include <libb64/cencode.h> 17 #include <esp32-hal-log.h> 18 19 #include <WiFi.h> 20 #include <WiFiClientSecure.h> 21 #include <vector> 22 #include <driver/i2s.h> 23 24 #ifndef AUDIO_NO_SD_FS 25 #include <SPI.h> 26 #ifdef SDFATFS_USED 27 #include <SdFat.h> // https://github.com/greiman/SdFat 28 #else 29 #include <SD.h> 30 #include <SD_MMC.h> 31 #include <SPIFFS.h> 32 #include <FS.h> 33 #include <FFat.h> 34 #endif // SDFATFS_USED 35 36 37 #ifdef SDFATFS_USED 38 //typedef File32 File; 39 typedef FsFile File; 40 41 namespace fs { 42 class FS : public SdFat { 43 public: 44 bool begin(SdCsPin_t csPin = SS, uint32_t maxSck = SD_SCK_MHZ(25)) { return SdFat::begin(csPin, maxSck); } 45 }; 46 47 class SDFATFS : public fs::FS { 48 public: 49 // sdcard_type_t cardType(); 50 uint64_t cardSize() { 51 return totalBytes(); 52 } 53 uint64_t usedBytes() { 54 // set SdFatConfig MAINTAIN_FREE_CLUSTER_COUNT non-zero. Then only the first call will take time. 55 return (uint64_t)(clusterCount() - freeClusterCount()) * (uint64_t)bytesPerCluster(); 56 } 57 uint64_t totalBytes() { 58 return (uint64_t)clusterCount() * (uint64_t)bytesPerCluster(); 59 } 60 }; 61 } 62 63 extern fs::SDFATFS SD_SDFAT; 64 65 using namespace fs; 66 #define SD SD_SDFAT 67 #endif //SDFATFS_USED 68 #endif // AUDIO_NO_SD_FS 69 70 using namespace std; 71 72 extern __attribute__((weak)) void audio_info(const char *); 73 extern __attribute__((weak)) void audio_id3data(const char *); // ID3 metadata 74 #ifndef AUDIO_NO_SD_FS 75 extern __attribute__((weak)) void audio_id3image(File& file, const size_t pos, const size_t size); // ID3 metadata image 76 #endif 77 extern __attribute__((weak)) void audio_eof_mp3(const char*); //end of mp3 file 78 extern __attribute__((weak)) void audio_showstreamtitle(const char*); 79 extern __attribute__((weak)) void audio_showstation(const char *); 80 extern __attribute__((weak)) void audio_bitrate(const char*); 81 extern __attribute__((weak)) void audio_commercial(const char*); 82 extern __attribute__((weak)) void audio_icyurl(const char*); 83 extern __attribute__((weak)) void audio_icydescription(const char*); 84 extern __attribute__((weak)) void audio_lasthost(const char*); 85 extern __attribute__((weak)) void audio_eof_speech(const char*); 86 extern __attribute__((weak)) void audio_eof_stream(const char*); // The webstream comes to an end 87 extern __attribute__((weak)) void audio_process_extern(int16_t* buff, uint16_t len, bool *continueI2S); // record audiodata or send via BT 88 extern __attribute__((weak)) void audio_process_i2s(uint32_t* sample, bool *continueI2S); // record audiodata or send via BT 89 90 #define AUDIO_INFO(...) {char buff[512 + 64]; sprintf(buff,__VA_ARGS__); if(audio_info) audio_info(buff);} 91 92 //---------------------------------------------------------------------------------------------------------------------- 93 94 class AudioBuffer { 95 // AudioBuffer will be allocated in PSRAM, If PSRAM not available or has not enough space AudioBuffer will be 96 // allocated in FlashRAM with reduced size 97 // 98 // m_buffer m_readPtr m_writePtr m_endPtr 99 // | |<------dataLength------->|<------ writeSpace ----->| 100 // ▼ ▼ ▼ ▼ 101 // --------------------------------------------------------------------------------------------------------------- 102 // | <--m_buffSize--> | <--m_resBuffSize --> | 103 // --------------------------------------------------------------------------------------------------------------- 104 // |<-----freeSpace------->| |<------freeSpace-------->| 105 // 106 // 107 // 108 // if the space between m_readPtr and buffend < m_resBuffSize copy data from the beginning to resBuff 109 // so that the mp3/aac/flac frame is always completed 110 // 111 // m_buffer m_writePtr m_readPtr m_endPtr 112 // | |<-------writeSpace------>|<--dataLength-->| 113 // ▼ ▼ ▼ ▼ 114 // --------------------------------------------------------------------------------------------------------------- 115 // | <--m_buffSize--> | <--m_resBuffSize --> | 116 // --------------------------------------------------------------------------------------------------------------- 117 // |<--- ------dataLength-- ------>|<-------freeSpace------->| 118 // 119 // 120 121 public: 122 AudioBuffer(size_t maxBlockSize = 0); // constructor 123 ~AudioBuffer(); // frees the buffer 124 size_t init(); // set default values 125 bool isInitialized() { return m_f_init; }; 126 void setBufsize(int ram, int psram); 127 void changeMaxBlockSize(uint16_t mbs); // is default 1600 for mp3 and aac, set 16384 for FLAC 128 uint16_t getMaxBlockSize(); // returns maxBlockSize 129 size_t freeSpace(); // number of free bytes to overwrite 130 size_t writeSpace(); // space fom writepointer to bufferend 131 size_t bufferFilled(); // returns the number of filled bytes 132 void bytesWritten(size_t bw); // update writepointer 133 void bytesWasRead(size_t br); // update readpointer 134 uint8_t* getWritePtr(); // returns the current writepointer 135 uint8_t* getReadPtr(); // returns the current readpointer 136 uint32_t getWritePos(); // write position relative to the beginning 137 uint32_t getReadPos(); // read position relative to the beginning 138 void resetBuffer(); // restore defaults 139 bool havePSRAM() { return m_f_psram; }; 140 141 protected: 142 size_t m_buffSizePSRAM = 300000; // most webstreams limit the advance to 100...300Kbytes 143 size_t m_buffSizeRAM = 1600 * 5; 144 size_t m_buffSize = 0; 145 size_t m_freeSpace = 0; 146 size_t m_writeSpace = 0; 147 size_t m_dataLength = 0; 148 size_t m_resBuffSizeRAM = 1600; // reserved buffspace, >= one mp3 frame 149 size_t m_resBuffSizePSRAM = 4096 * 4; // reserved buffspace, >= one flac frame 150 size_t m_maxBlockSize = 1600; 151 uint8_t* m_buffer = NULL; 152 uint8_t* m_writePtr = NULL; 153 uint8_t* m_readPtr = NULL; 154 uint8_t* m_endPtr = NULL; 155 bool m_f_start = true; 156 bool m_f_init = false; 157 bool m_f_psram = false; // PSRAM is available (and used...) 158 }; 159 //---------------------------------------------------------------------------------------------------------------------- 160 161 class Audio : private AudioBuffer{ 162 163 AudioBuffer InBuff; // instance of input buffer 164 165 public: 166 Audio(bool internalDAC = false, uint8_t channelEnabled = 3, uint8_t i2sPort = I2S_NUM_0); // #99 167 ~Audio(); 168 void setBufsize(int rambuf_sz, int psrambuf_sz); 169 bool connecttohost(const char* host, const char* user = "", const char* pwd = ""); 170 171 bool connecttospeech(const char* speech, const char* lang); 172 bool connecttomarytts(const char* speech, const char* lang, const char* voice); 173 #ifndef AUDIO_NO_SD_FS 174 bool connecttoFS(fs::FS &fs, const char* path, uint32_t resumeFilePos = 0); 175 bool connecttoSD(const char* path, uint32_t resumeFilePos = 0); 176 #endif // AUDIO_NO_SD_FS 177 bool setFileLoop(bool input);//TEST loop 178 void setConnectionTimeout(uint16_t timeout_ms, uint16_t timeout_ms_ssl); 179 bool setAudioPlayPosition(uint16_t sec); 180 bool setFilePos(uint32_t pos); 181 bool audioFileSeek(const float speed); 182 bool setTimeOffset(int sec); 183 bool setPinout(uint8_t BCLK, uint8_t LRC, uint8_t DOUT, int8_t DIN = I2S_PIN_NO_CHANGE, int8_t MCK = I2S_PIN_NO_CHANGE); 184 bool pauseResume(); 185 bool isRunning() {return m_f_running;} 186 void loop(); 187 uint32_t stopSong(); 188 void forceMono(bool m); 189 void setBalance(int8_t bal = 0); 190 void setVolume(uint8_t vol); 191 uint8_t getVolume(); 192 uint8_t getI2sPort(); 193 194 uint32_t getAudioDataStartPos(); 195 uint32_t getFileSize(); 196 uint32_t getFilePos(); 197 uint32_t getSampleRate(); 198 uint8_t getBitsPerSample(); 199 uint8_t getChannels(); 200 uint32_t getBitRate(bool avg = false); 201 uint32_t getAudioFileDuration(); 202 uint32_t getAudioCurrentTime(); 203 uint32_t getTotalPlayingTime(); 204 205 esp_err_t i2s_mclk_pin_select(const uint8_t pin); 206 uint32_t inBufferFilled(); // returns the number of stored bytes in the inputbuffer 207 uint32_t inBufferFree(); // returns the number of free bytes in the inputbuffer 208 void setTone(int8_t gainLowPass, int8_t gainBandPass, int8_t gainHighPass); 209 void setI2SCommFMT_LSB(bool commFMT); 210 int getCodec() {return m_codec;} 211 const char *getCodecname() {return codecname[m_codec];} 212 213 private: 214 215 #ifndef ESP_ARDUINO_VERSION_VAL 216 #define ESP_ARDUINO_VERSION_MAJOR 0 217 #define ESP_ARDUINO_VERSION_MINOR 0 218 #define ESP_ARDUINO_VERSION_PATCH 0 219 #endif 220 221 void UTF8toASCII(char* str); 222 bool latinToUTF8(char* buff, size_t bufflen); 223 void setDefaults(); // free buffers and set defaults 224 void initInBuff(); 225 bool httpPrint(const char* host); 226 #ifndef AUDIO_NO_SD_FS 227 void processLocalFile(); 228 #endif // AUDIO_NO_SD_FS 229 void processWebStream(); 230 void processWebFile(); 231 void processWebStreamTS(); 232 void processWebStreamHLS(); 233 void playAudioData(); 234 bool readPlayListData(); 235 const char* parsePlaylist_M3U(); 236 const char* parsePlaylist_PLS(); 237 const char* parsePlaylist_ASX(); 238 const char* parsePlaylist_M3U8(); 239 bool STfromEXTINF(char* str); 240 void showCodecParams(); 241 int findNextSync(uint8_t* data, size_t len); 242 int sendBytes(uint8_t* data, size_t len); 243 void compute_audioCurrentTime(int bd); 244 void printDecodeError(int r); 245 void showID3Tag(const char* tag, const char* val); 246 void unicode2utf8(char* buff, uint32_t len); 247 size_t readAudioHeader(uint32_t bytes); 248 int read_WAV_Header(uint8_t* data, size_t len); 249 int read_FLAC_Header(uint8_t *data, size_t len); 250 int read_ID3_Header(uint8_t* data, size_t len); 251 int read_M4A_Header(uint8_t* data, size_t len); 252 int read_OGG_Header(uint8_t *data, size_t len); 253 size_t process_m3u8_ID3_Header(uint8_t* packet); 254 bool setSampleRate(uint32_t hz); 255 bool setBitsPerSample(int bits); 256 bool setChannels(int channels); 257 bool setBitrate(int br); 258 bool playChunk(); 259 bool playSample(int16_t sample[2]) ; 260 void playI2Sremains(); 261 int32_t Gain(int16_t s[2]); 262 bool fill_InputBuf(); 263 void showstreamtitle(const char* ml); 264 bool parseContentType(char* ct); 265 bool parseHttpResponseHeader(); 266 bool initializeDecoder(); 267 esp_err_t I2Sstart(uint8_t i2s_num); 268 esp_err_t I2Sstop(uint8_t i2s_num); 269 void urlencode(char* buff, uint16_t buffLen, bool spacesOnly = false); 270 int16_t* IIR_filterChain0(int16_t iir_in[2], bool clear = false); 271 int16_t* IIR_filterChain1(int16_t* iir_in, bool clear = false); 272 int16_t* IIR_filterChain2(int16_t* iir_in, bool clear = false); 273 inline void setDatamode(uint8_t dm){m_datamode=dm;} 274 inline uint8_t getDatamode(){return m_datamode;} 275 inline uint32_t streamavail(){ return _client ? _client->available() : 0;} 276 void IIR_calculateCoefficients(int8_t G1, int8_t G2, int8_t G3); 277 bool ts_parsePacket(uint8_t* packet, uint8_t* packetStart, uint8_t* packetLength); 278 279 //+++ W E B S T R E A M - H E L P F U N C T I O N S +++ 280 uint16_t readMetadata(uint16_t b, bool first = false); 281 size_t chunkedDataTransfer(uint8_t* bytes); 282 bool readID3V1Tag(); 283 void slowStreamDetection(uint32_t inBuffFilled, uint32_t maxFrameSize); 284 void lostStreamDetection(uint32_t bytesAvail); 285 #ifndef AUDIO_NO_SD_FS 286 void seek_m4a_stsz(); 287 uint32_t m4a_correctResumeFilePos(uint32_t resumeFilePos); 288 uint32_t flac_correctResumeFilePos(uint32_t resumeFilePos); 289 uint32_t mp3_correctResumeFilePos(uint32_t resumeFilePos); 290 #endif // AUDIO_NO_SD_FS 291 292 //++++ implement several function with respect to the index of string ++++ 293 void trim(char *s) { 294 //fb trim in place 295 char *pe; 296 char *p = s; 297 while ( isspace(*p) ) p++; //left 298 pe = p; //right 299 while ( *pe != '\0' ) pe++; 300 do { 301 pe--; 302 } while ( (pe > p) && isspace(*pe) ); 303 if (p == s) { 304 *++pe = '\0'; 305 } else { //move 306 while ( p <= pe ) *s++ = *p++; 307 *s = '\0'; 308 } 309 } 310 311 bool startsWith (const char* base, const char* str) { 312 //fb 313 char c; 314 while ( (c = *str++) != '\0' ) 315 if (c != *base++) return false; 316 return true; 317 } 318 319 bool endsWith (const char* base, const char* str) { 320 //fb 321 int slen = strlen(str) - 1; 322 const char *p = base + strlen(base) - 1; 323 while(p > base && isspace(*p)) p--; // rtrim 324 p -= slen; 325 if (p < base) return false; 326 return (strncmp(p, str, slen) == 0); 327 } 328 329 int indexOf (const char* base, const char* str, int startIndex = 0) { 330 //fb 331 const char *p = base; 332 for (; startIndex > 0; startIndex--) 333 if (*p++ == '\0') return -1; 334 char* pos = strstr(p, str); 335 if (pos == nullptr) return -1; 336 return pos - base; 337 } 338 339 int indexOf (const char* base, char ch, int startIndex = 0) { 340 //fb 341 const char *p = base; 342 for (; startIndex > 0; startIndex--) 343 if (*p++ == '\0') return -1; 344 char *pos = strchr(p, ch); 345 if (pos == nullptr) return -1; 346 return pos - base; 347 } 348 349 int lastIndexOf(const char* haystack, const char* needle) { 350 //fb 351 int nlen = strlen(needle); 352 if (nlen == 0) return -1; 353 const char *p = haystack - nlen + strlen(haystack); 354 while (p >= haystack) { 355 int i = 0; 356 while (needle[i] == p[i]) 357 if (++i == nlen) return p - haystack; 358 p--; 359 } 360 return -1; 361 } 362 363 int lastIndexOf(const char* haystack, const char needle) { 364 //fb 365 const char *p = strrchr(haystack, needle); 366 return (p ? p - haystack : -1); 367 } 368 369 int specialIndexOf (uint8_t* base, const char* str, int baselen, bool exact = false){ 370 int result; // seek for str in buffer or in header up to baselen, not nullterninated 371 if (strlen(str) > baselen) return -1; // if exact == true seekstr in buffer must have "\0" at the end 372 for (int i = 0; i < baselen - strlen(str); i++){ 373 result = i; 374 for (int j = 0; j < strlen(str) + exact; j++){ 375 if (*(base + i + j) != *(str + j)){ 376 result = -1; 377 break; 378 } 379 } 380 if (result >= 0) break; 381 } 382 return result; 383 } 384 385 // some other functions 386 size_t bigEndian(uint8_t* base, uint8_t numBytes, uint8_t shiftLeft = 8){ 387 uint64_t result = 0; 388 if(numBytes < 1 || numBytes > 8) return 0; 389 for (int i = 0; i < numBytes; i++) { 390 result += *(base + i) << (numBytes -i - 1) * shiftLeft; 391 } 392 if(result > SIZE_MAX) {log_e("range overflow"); result = 0;} // overflow 393 return (size_t)result; 394 } 395 396 bool b64encode(const char* source, uint16_t sourceLength, char* dest){ 397 size_t size = base64_encode_expected_len(sourceLength) + 1; 398 char * buffer = (char *) malloc(size); 399 if(buffer) { 400 base64_encodestate _state; 401 base64_init_encodestate(&_state); 402 int len = base64_encode_block(&source[0], sourceLength, &buffer[0], &_state); 403 len = base64_encode_blockend((buffer + len), &_state); 404 memcpy(dest, buffer, strlen(buffer)); 405 dest[strlen(buffer)] = '\0'; 406 free(buffer); 407 return true; 408 } 409 return false; 410 } 411 size_t urlencode_expected_len(const char* source){ 412 size_t expectedLen = strlen(source); 413 for(int i = 0; i < strlen(source); i++) { 414 if(isalnum(source[i])){;} 415 else expectedLen += 2; 416 } 417 return expectedLen; 418 } 419 void vector_clear_and_shrink(vector<char*>&vec){ 420 uint size = vec.size(); 421 for (int i = 0; i < size; i++) { 422 if(vec[i]){ 423 free(vec[i]); 424 vec[i] = NULL; 425 } 426 } 427 vec.clear(); 428 vec.shrink_to_fit(); 429 } 430 uint32_t simpleHash(const char* str){ 431 if(str == NULL) return 0; 432 uint32_t hash = 0; 433 for(int i=0; i<strlen(str); i++){ 434 if(str[i] < 32) continue; // ignore control sign 435 hash += (str[i] - 31) * i * 32; 436 } 437 return hash; 438 } 439 440 private: 441 const char *codecname[9] = {"unknown", "WAV", "MP3", "AAC", "M4A", "FLAC", "OGG", "OGG FLAC", "OPUS"}; 442 enum : int { APLL_AUTO = -1, APLL_ENABLE = 1, APLL_DISABLE = 0 }; 443 enum : int { EXTERNAL_I2S = 0, INTERNAL_DAC = 1, INTERNAL_PDM = 2 }; 444 enum : int { FORMAT_NONE = 0, FORMAT_M3U = 1, FORMAT_PLS = 2, FORMAT_ASX = 3, FORMAT_M3U8 = 4}; 445 enum : int { AUDIO_NONE, HTTP_RESPONSE_HEADER, AUDIO_DATA, AUDIO_LOCALFILE, 446 AUDIO_PLAYLISTINIT, AUDIO_PLAYLISTHEADER, AUDIO_PLAYLISTDATA}; 447 enum : int { FLAC_BEGIN = 0, FLAC_MAGIC = 1, FLAC_MBH =2, FLAC_SINFO = 3, FLAC_PADDING = 4, FLAC_APP = 5, 448 FLAC_SEEK = 6, FLAC_VORBIS = 7, FLAC_CUESHEET = 8, FLAC_PICTURE = 9, FLAC_OKAY = 100}; 449 enum : int { M4A_BEGIN = 0, M4A_FTYP = 1, M4A_CHK = 2, M4A_MOOV = 3, M4A_FREE = 4, M4A_TRAK = 5, M4A_MDAT = 6, 450 M4A_ILST = 7, M4A_MP4A = 8, M4A_AMRDY = 99, M4A_OKAY = 100}; 451 enum : int { OGG_BEGIN = 0, OGG_MAGIC = 1, OGG_HEADER = 2, OGG_FIRST = 3, OGG_AMRDY = 99, OGG_OKAY = 100}; 452 enum : int { CODEC_NONE = 0, CODEC_WAV = 1, CODEC_MP3 = 2, CODEC_AAC = 3, CODEC_M4A = 4, CODEC_FLAC = 5, 453 CODEC_OGG = 6, CODEC_OGG_FLAC = 7, CODEC_OGG_OPUS = 8, CODEC_AACP = 9}; 454 enum : int { ST_NONE = 0, ST_WEBFILE = 1, ST_WEBSTREAM = 2}; 455 typedef enum { LEFTCHANNEL=0, RIGHTCHANNEL=1 } SampleIndex; 456 typedef enum { LOWSHELF = 0, PEAKEQ = 1, HIFGSHELF =2 } FilterType; 457 458 const uint8_t volumetable[22]={ 0, 1, 2, 3, 4 , 6 , 8, 10, 12, 14, 17, 459 20, 23, 27, 30 ,34, 38, 43 ,48, 52, 58, 64}; //22 elements 460 461 typedef struct _filter{ 462 float a0; 463 float a1; 464 float a2; 465 float b1; 466 float b2; 467 } filter_t; 468 469 typedef struct _pis_array{ 470 int number; 471 int pids[4]; 472 } pid_array; 473 474 #ifndef AUDIO_NO_SD_FS 475 File audiofile; // @suppress("Abstract class cannot be instantiated") 476 #endif // AUDIO_NO_SD_FS 477 WiFiClient client; // @suppress("Abstract class cannot be instantiated") 478 WiFiClientSecure clientsecure; // @suppress("Abstract class cannot be instantiated") 479 WiFiClient* _client = nullptr; 480 i2s_config_t m_i2s_config = {}; // stores values for I2S driver 481 i2s_pin_config_t m_pin_config = {}; 482 std::vector<char*> m_playlistContent; // m3u8 playlist buffer 483 std::vector<char*> m_playlistURL; // m3u8 streamURLs buffer 484 std::vector<uint32_t> m_hashQueue; 485 486 const size_t m_frameSizeWav = 1024; 487 const size_t m_frameSizeMP3 = 1600; 488 const size_t m_frameSizeAAC = 1600; 489 const size_t m_frameSizeFLAC = 4096 * 4; 490 491 static const uint8_t m_tsPacketSize = 188; 492 static const uint8_t m_tsHeaderSize = 4; 493 494 char* m_chbuf = NULL; 495 uint16_t m_chbufSize = 0; // will set in constructor (depending on PSRAM) 496 char m_lastHost[512]; // Store the last URL to a webstream 497 char* m_playlistBuff = NULL; // stores playlistdata 498 const uint16_t m_plsBuffEntryLen = 256; // length of each entry in playlistBuff 499 filter_t m_filter[3]; // digital filters 500 int m_LFcount = 0; // Detection of end of header 501 uint32_t m_sampleRate=16000; 502 uint32_t m_bitRate=0; // current bitrate given fom decoder 503 uint32_t m_avr_bitrate = 0; // average bitrate, median computed by VBR 504 int m_readbytes = 0; // bytes read 505 uint32_t m_metacount = 0; // counts down bytes between metadata 506 int m_controlCounter = 0; // Status within readID3data() and readWaveHeader() 507 int8_t m_balance = 0; // -16 (mute left) ... +16 (mute right) 508 uint8_t m_vol=64; // volume 509 uint8_t m_bitsPerSample = 16; // bitsPerSample 510 uint8_t m_channels = 2; 511 uint8_t m_i2s_num = I2S_NUM_0; // I2S_NUM_0 or I2S_NUM_1 512 uint8_t m_playlistFormat = 0; // M3U, PLS, ASX 513 uint8_t m_codec = CODEC_NONE; // 514 uint8_t m_expectedCodec = CODEC_NONE; // set in connecttohost (e.g. http://url.mp3 -> CODEC_MP3) 515 uint8_t m_expectedPlsFmt = FORMAT_NONE; // set in connecttohost (e.g. streaming01.m3u) -> FORMAT_M3U) 516 uint8_t m_filterType[2]; // lowpass, highpass 517 uint8_t m_streamType = ST_NONE; 518 uint8_t m_ID3Size = 0; // lengt of ID3frame - ID3header 519 int16_t m_outBuff[2048*2]; // Interleaved L/R 520 int16_t m_validSamples = 0; 521 int16_t m_curSample = 0; 522 uint16_t m_datamode = 0; // Statemaschine 523 uint16_t m_streamTitleHash = 0; // remember streamtitle, ignore multiple occurence in metadata 524 uint16_t m_timeout_ms = 250; 525 uint16_t m_timeout_ms_ssl = 2700; 526 uint8_t m_flacBitsPerSample = 0; // bps should be 16 527 uint8_t m_flacNumChannels = 0; // can be read out in the FLAC file header 528 uint32_t m_flacSampleRate = 0; // can be read out in the FLAC file header 529 uint16_t m_flacMaxFrameSize = 0; // can be read out in the FLAC file header 530 uint16_t m_flacMaxBlockSize = 0; // can be read out in the FLAC file header 531 uint32_t m_flacTotalSamplesInStream = 0; // can be read out in the FLAC file header 532 uint32_t m_metaint = 0; // Number of databytes between metadata 533 uint32_t m_chunkcount = 0 ; // Counter for chunked transfer 534 uint32_t m_t0 = 0; // store millis(), is needed for a small delay 535 uint32_t m_contentlength = 0; // Stores the length if the stream comes from fileserver 536 uint32_t m_bytesNotDecoded = 0; // pictures or something else that comes with the stream 537 uint32_t m_PlayingStartTime = 0; // Stores the milliseconds after the start of the audio 538 uint32_t m_resumeFilePos = 0; // the return value from stopSong() can be entered here 539 uint16_t m_m3u8_targetDuration = 10; // 540 uint32_t m_stsz_numEntries = 0; // num of entries inside stsz atom (uint32_t) 541 uint32_t m_stsz_position = 0; // pos of stsz atom within file 542 bool m_f_metadata = false; // assume stream without metadata 543 bool m_f_unsync = false; // set within ID3 tag but not used 544 bool m_f_exthdr = false; // ID3 extended header 545 bool m_f_ssl = false; 546 bool m_f_running = false; 547 bool m_f_firstCall = false; // InitSequence for processWebstream and processLokalFile 548 bool m_f_chunked = false ; // Station provides chunked transfer 549 bool m_f_firstmetabyte = false; // True if first metabyte (counter) 550 bool m_f_playing = false; // valid mp3 stream recognized 551 bool m_f_tts = false; // text to speech 552 bool m_f_loop = false; // Set if audio file should loop 553 bool m_f_forceMono = false; // if true stereo -> mono 554 bool m_f_internalDAC = false; // false: output vis I2S, true output via internal DAC 555 bool m_f_rtsp = false; // set if RTSP is used (m3u8 stream) 556 bool m_f_m3u8data = false; // used in processM3U8entries 557 bool m_f_Log = false; // set in platformio.ini -DAUDIO_LOG and -DCORE_DEBUG_LEVEL=3 or 4 558 bool m_f_continue = false; // next m3u8 chunk is available 559 bool m_f_ts = true; // transport stream 560 uint8_t m_f_channelEnabled = 3; // internal DAC, both channels 561 uint32_t m_audioFileDuration = 0; 562 float m_audioCurrentTime = 0; 563 uint32_t m_audioDataStart = 0; // in bytes 564 size_t m_audioDataSize = 0; // 565 float m_filterBuff[3][2][2][2]; // IIR filters memory for Audio DSP 566 size_t m_i2s_bytesWritten = 0; // set in i2s_write() but not used 567 size_t m_file_size = 0; // size of the file 568 uint16_t m_filterFrequency[2]; 569 int8_t m_gain0 = 0; // cut or boost filters (EQ) 570 int8_t m_gain1 = 0; 571 int8_t m_gain2 = 0; 572 573 pid_array m_pidsOfPMT; 574 int16_t m_pidOfAAC; 575 uint8_t m_packetBuff[m_tsPacketSize]; 576 int16_t m_pesDataLength = 0; 577 }; 578 579 //----------------------------------------------------------------------------------------------------------------------