4 #error Only supports ESP32
15 #ifdef USE_WARBLER_DEBUG
16 #define WARBLER_DEBUG_PRINT(s) DEBUG_PRINT(s)
17 #define WARBLER_DEBUG_PRINTLN(s) DEBUG_PRINTLN(s)
18 #define WARBLER_DEBUG_PRINT_HEX(s) DEBUG_PRINT_HEX(s)
19 #define WARBLER_DEBUG_PRINTLN_HEX(s) DEBUG_PRINTLN_HEX(s)
21 #define WARBLER_DEBUG_PRINT(s)
22 #define WARBLER_DEBUG_PRINTLN(s)
23 #define WARBLER_DEBUG_PRINT_HEX(s)
24 #define WARBLER_DEBUG_PRINTLN_HEX(s)
27 #ifndef WARBLER_NUM_TRACKS
28 #define WARBLER_NUM_TRACKS 10
31 #ifndef WARBLER_QUEUE_DEPTH
32 #define WARBLER_QUEUE_DEPTH 10
35 #ifndef WARBLER_DECODE_BUFFER_SIZE
36 #define WARBLER_DECODE_BUFFER_SIZE 2048
40 #define I2S_DOUT_PIN 25 // I2S audio output
44 #define I2S_LRC_PIN 26 // I2S audio output
48 #define I2S_BCLK_PIN 27 // I2S audio output
56 fAudioBitmap(audioBitmap),
75 return fActiveRemaining == 0;
85 xTaskCreatePinnedToCore(
93 fPOD = esp_partition_find_first((esp_partition_type_t)0xBA, (esp_partition_subtype_t)0xBE, NULL);
100 if (fActiveRemaining != 0)
102 if (fNextTrack == -1 && fNextWarble == -1 && fNumQueue > 0)
104 uint32_t now = millis();
105 if (fQueue->fStartMS == 0)
106 fQueue->fStartMS = now;
107 if (fQueue->fStartMS + fQueue->fDelayMS <= now)
109 fNextTrack = fQueue->fTrack;
110 fNextWarble = fQueue->fWarble;
114 memmove(&fQueue[0], &fQueue[1], fNumQueue *
sizeof(fQueue[0]));
119 if (fNextTrack != -1 && fNextWarble != -1)
125 static uint32_t sPODOffset[110] = {
126 64000, 87040, 131328, 176640, 209152, 303104, 357888, 418560, 439296, 512512, 555776,
127 593408, 643328, 698112, 783872, 813056, 850944, 923136, 975104, 1055744, 1090304, 1150720,
128 1304064, 1555968, 1709568, 1837568, 1912064, 2061056, 2269184, 2422016, 2546688, 2652160, 2775808,
129 2843392, 2921216, 3008768, 3069952, 3136000, 3173120, 3241728, 3321856, 3341312, 3398656, 3410944,
130 3565568, 3630848, 3755264, 3881728, 4005376, 4120320, 4211968, 4301568, 4420608, 4509440, 4586496,
131 4640000, 4764672, 4835072, 4884480, 4943616, 5020928, 5113600, 5208064, 5277184, 5344000, 5417984,
132 5560320, 5673216, 5822464, 5968384, 6058496, 6175744, 6312704, 6471936, 6581248, 6676992, 6781184,
133 6813440, 6871808, 6924544, 6967040, 7025408, 7095808, 7159040, 7203328, 7293440, 7323392, 7346176,
134 7423744, 7536640, 7610880, 7708160, 7787776, 7863040, 8000256, 8076800, 8157952, 8200448, 8332288,
135 8492800, 8616704, 8713728, 8941568, 9273600, 9448704, 9582592, 9729536, 9876224, 10041344, 10285056
137 uint32_t warbleOffset = 0;
138 uint32_t warbleLength = 0;
139 uint32_t activeRemaining = 0;
141 if (fNextWarble > numWarbles)
142 fNextWarble = int(
float(fNextWarble) / fTrackCount[fNextTrack] * numWarbles);
143 uint32_t warbleTrack = fNextWarble + fNextTrack * numWarbles;
144 warbleOffset = (warbleTrack > 0) ? sPODOffset[warbleTrack-1] : 0;
145 warbleLength = sPODOffset[warbleTrack];
146 activeRemaining = warbleLength - warbleOffset;
148 fPODOffset = warbleOffset;
149 if (activeRemaining > 0)
151 fActiveRemaining = activeRemaining;
158 if (fNextTrack != fActiveTrack)
160 if (fActiveTrack != -1)
162 openTrack(fNextTrack);
165 if (fActiveTrack != -1)
167 uint32_t offsetTable;
168 uint32_t trackCount = 0;
169 uint32_t warbleOffset = 0;
170 uint32_t warbleLength = 0;
171 uint32_t activeRemaining = 0;
173 if (fTrackOffset[fActiveTrack] !=
nullptr)
175 warbleOffset = (fNextWarble > 0) ? fTrackOffset[fActiveTrack][fNextWarble-1] : 0;
176 warbleLength = fTrackOffset[fActiveTrack][fNextWarble];
177 activeRemaining = warbleLength - warbleOffset;
179 if (!fFile.seek(warbleOffset +
sizeof(offsetTable), SeekSet))
186 else if (fFile.seek(0, SeekSet) &&
187 fFile.read((uint8_t*)&offsetTable,
sizeof(offsetTable)) ==
sizeof(offsetTable) &&
188 fFile.seek(offsetTable, SeekSet) &&
189 fFile.read((uint8_t*)&trackCount,
sizeof(trackCount)) ==
sizeof(trackCount))
193 if (fFile.seek((fNextWarble-1)*
sizeof(warbleLength), SeekCur) &&
194 fFile.read((uint8_t*)&warbleOffset,
sizeof(warbleOffset)) ==
sizeof(warbleOffset) &&
195 fFile.read((uint8_t*)&warbleLength,
sizeof(warbleLength)) ==
sizeof(warbleLength))
197 activeRemaining = warbleLength - warbleOffset;
200 else if (fFile.read((uint8_t*)&warbleLength,
sizeof(warbleLength)) ==
sizeof(warbleLength))
202 activeRemaining = warbleLength;
204 if (!fFile.seek(warbleOffset +
sizeof(offsetTable), SeekSet))
213 if (activeRemaining > 0)
215 fActiveRemaining = activeRemaining;
220 fNextTrack = fNextWarble = -1;
231 strncpy(fNextSong, file,
sizeof(fNextSong)-1);
238 track = max(min(track,
int(
SizeOfArray(fTrackCount))), 0);
240 warble = random(fTrackCount[track]);
241 warble = max(min(warble, fTrackCount[track]), 0);
243 fNextWarble = warble;
246 void queue(uint32_t delayMS = 0,
int track = -1, int32_t warble = -1)
250 track = max(min(track,
int(
SizeOfArray(fTrackCount))), 0);
252 warble = random(fTrackCount[track]);
253 warble = max(min(warble, fTrackCount[track]), 0);
256 fQueue[fNumQueue].fTrack = track;
257 fQueue[fNumQueue].fWarble = warble;
258 fQueue[fNumQueue].fStartMS = 0;
259 fQueue[fNumQueue].fDelayMS = delayMS;
264 #ifdef MIX_AUDIO_FLOAT
270 static short sDecode[256] =
272 -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
273 -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
274 -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
275 -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
276 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
277 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
278 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
279 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
280 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
281 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
282 -876, -844, -812, -780, -748, -716, -684, -652,
283 -620, -588, -556, -524, -492, -460, -428, -396,
284 -372, -356, -340, -324, -308, -292, -276, -260,
285 -244, -228, -212, -196, -180, -164, -148, -132,
286 -120, -112, -104, -96, -88, -80, -72, -64,
287 -56, -48, -40, -32, -24, -16, -8, 0,
289 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
290 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
291 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
292 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
293 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
294 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
295 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
296 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
297 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
298 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
299 876, 844, 812, 780, 748, 716, 684, 652,
300 620, 588, 556, 524, 492, 460, 428, 396,
301 372, 356, 340, 324, 308, 292, 276, 260,
302 244, 228, 212, 196, 180, 164, 148, 132,
303 120, 112, 104, 96, 88, 80, 72, 64,
304 56, 48, 40, 32, 24, 16, 8, 0
306 #ifdef MIX_AUDIO_FLOAT
311 if (fActiveRemaining > 0)
313 if (fDecodePtr == &fDecodeBuffer[
sizeof(fDecodeBuffer)])
315 #ifdef MIX_AUDIO_FLOAT
316 sample = float(sDecode[*fDecodePtr++]) / SHRT_MAX;
318 sample = sDecode[*fDecodePtr++];
332 TaskHandle_t fAudioTask =
nullptr;
334 int fNextWarble = -1;
335 unsigned fNumQueue = 0;
336 bool fOTAInProgress =
false;
343 int8_t fActiveTrack = -1;
344 uint32_t fActiveRemaining = 0;
346 uint8_t* fDecodePtr = &fDecodeBuffer[
sizeof(fDecodeBuffer)];
350 const esp_partition_t* fPOD =
nullptr;
351 bool fPODActive =
false;
352 uint32_t fPODOffset = 0;
354 bool fStopStream =
false;
357 void clearDecodeBuffer()
359 fDecodePtr = &fDecodeBuffer[
sizeof(fDecodeBuffer)];
362 void fillDecodeBuffer()
365 fDecodePtr = fDecodeBuffer;
368 bytesRead = min(fActiveRemaining,
sizeof(fDecodeBuffer));
369 if (esp_partition_read(fPOD, fPODOffset, fDecodeBuffer, bytesRead) != ESP_OK)
373 fPODOffset += bytesRead;
378 bytesRead = fFile.readBytes((
char*)fDecodeBuffer,
sizeof(fDecodeBuffer));
383 if (bytesRead !=
sizeof(fDecodeBuffer))
385 memset(&fDecodeBuffer[bytesRead],
'\0',
sizeof(fDecodeBuffer) - bytesRead);
395 bool openTrack(
unsigned i)
398 snprintf(buf,
sizeof(buf),
"/sys%d.dat", i);
399 fFile = fFS.open(buf);
401 return (fFile ==
true);
414 bool success = (activeWarbler() ==
nullptr);
415 for (
unsigned i = 0; i <
SizeOfArray(fTrackCount); i++)
419 uint32_t offsetTable;
421 if (fFile.seek(0, SeekSet) &&
422 fFile.read((uint8_t*)&offsetTable,
sizeof(offsetTable)) ==
sizeof(offsetTable) &&
423 fFile.seek(offsetTable, SeekSet) &&
424 fFile.read((uint8_t*)&trackCount,
sizeof(trackCount)) ==
sizeof(trackCount))
426 fTrackCount[i] = trackCount;
427 fTrackOffset[i] =
nullptr;
461 activeWarbler() =
this;
465 static inline float mixSamples(
float s1,
float s2)
467 s1 = (s1 + s2) - (s1 * s2);
476 static void audioFilter(
unsigned numBits,
unsigned numChannels,
const int16_t* samples,
unsigned sampleCount)
479 if (active ==
nullptr)
481 if (active->fActiveRemaining == 0)
485 bitmap->
processSamples(numBits, numChannels, samples, sampleCount);
488 #ifdef MIX_AUDIO_FLOAT
489 static float sPlayVolume = 1.0f;
490 static float sTrackVolume = 1.0f;
493 uint8_t* outp = (uint8_t*)samples;
494 if (numChannels == 1)
496 for (
size_t i = 0; i < sampleCount*2; i++)
498 float s2 = active->
read() * sPlayVolume;
499 float s1 = (float(*outp) / UCHAR_MAX) * sTrackVolume;
500 *outp++ = uint8_t(mixSamples(s1, s2) * UCHAR_MAX);
505 for (
size_t i = 0; i < sampleCount*2; i++)
507 float s2 = active->
read() * sPlayVolume;
508 for (
size_t ci = 0; ci < numChannels; ci++)
510 float s1 = (float(*outp) / UCHAR_MAX) * sTrackVolume;
511 *outp++ = uint8_t(mixSamples(s1, s2) * UCHAR_MAX);
516 else if (numBits == 16)
518 int16_t* outp = (int16_t*)samples;
519 if (numChannels == 1)
521 for (
size_t i = 0; i < sampleCount; i++)
523 float s2 = active->
read();
524 float s1 = (float(*outp) / SHRT_MAX) * sTrackVolume;
525 *outp++ = int16_t(mixSamples(s1, s2) * SHRT_MAX);
530 for (
size_t i = 0; i < sampleCount; i++)
532 float s2 = active->
read() * sPlayVolume;
533 for (
size_t ci = 0; ci < numChannels; ci++)
535 float s1 = (float(*outp) / SHRT_MAX) * sTrackVolume;
536 *outp++ = int16_t(mixSamples(s1, s2) * SHRT_MAX);
544 uint8_t* outp = (uint8_t*)samples;
545 if (numChannels == 1)
547 for (
size_t i = 0; i < sampleCount*2; i++)
549 int32_t s2 = active->
read();
550 int32_t s1 = (*outp - 0x80) << 8;
551 *outp++ = uint8_t((
float((s1 + s2) - (s1 * s2)) / SHRT_MAX) * UCHAR_MAX);
556 for (
size_t i = 0; i < sampleCount*2; i++)
558 int32_t s2 = active->
read();
559 for (
size_t ci = 0; ci < numChannels; ci++)
561 int32_t s1 = (*outp - 0x80) << 8;
562 *outp++ = uint8_t((
float((s1 + s2) - (s1 * s2)) / SHRT_MAX) * UCHAR_MAX);
567 else if (numBits == 16)
569 int16_t* outp = (int16_t*)samples;
570 if (numChannels == 1)
572 for (
size_t i = 0; i < sampleCount; i++)
574 int32_t s2 = active->
read();
581 for (
size_t i = 0; i < sampleCount; i++)
583 int32_t s2 = active->
read();
584 for (
size_t ci = 0; ci < numChannels; ci++)
597 if (fStopStream || *fNextSong != 0)
601 if (*fNextSong ==
'\0')
616 static void audioLoopTask(
void*)
621 if (active !=
nullptr)