From 0cfe90ff99d53defc154c6bbc0889e0c73130b31 Mon Sep 17 00:00:00 2001 From: acidvegas Date: Wed, 5 Jun 2024 18:07:54 -0400 Subject: [PATCH] Improved RTTTL processing with the ESP8266Audio library --- platformio.ini | 2 + src/Speaker.h | 112 +++++++------------------------------------------ src/main.ino | 6 ++- 3 files changed, 22 insertions(+), 98 deletions(-) diff --git a/platformio.ini b/platformio.ini index e1a690c..ac4f58b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -24,4 +24,6 @@ build_flags = -DARDUINO_USB_CDC_ON_BOOT=1 -DDISABLE_ALL_LIBRARY_WARNINGS lib_deps = + ArduinoWebsockets + earlephilhower/ESP8266Audio lib_extra_dirs = lib \ No newline at end of file diff --git a/src/Speaker.h b/src/Speaker.h index 08dbf42..c874c26 100644 --- a/src/Speaker.h +++ b/src/Speaker.h @@ -2,6 +2,9 @@ #include #include +#include +#include +#include #include "pins.h" @@ -9,31 +12,6 @@ #define SAMPLE_RATE 44100 -const float NOTE_FREQS[] = { - 261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 493.88, // C4 to B4 - 523.25, 554.37, 587.33, 622.25, 659.25, 698.46, 739.99, 783.99, 830.61, 880.00, 932.33, 987.77, // C5 to B5 - 1046.50, 1108.73, 1174.66, 1244.51, 1318.51, 1396.91, 1480.00, 1568.00, 1661.22, 1760.00, 1864.66, 1975.53, // C6 to B6 - 2093.00, 2217.46, 2349.32, 2489.02, 2637.02, 2793.83, 2960.00, 3136.00, 3322.44, 3520.00, 3729.31, 3951.07 // C7 to B7 -}; - - -float getNoteFrequency(char note, int octave) { - if (note == 'p') return 0; // Pause - int noteIndex = 0; - switch (note) { - case 'c': noteIndex = 0; break; - case 'd': noteIndex = 2; break; - case 'e': noteIndex = 4; break; - case 'f': noteIndex = 5; break; - case 'g': noteIndex = 7; break; - case 'a': noteIndex = 9; break; - case 'b': noteIndex = 11; break; - default: return 0; - } - return NOTE_FREQS[noteIndex + ((octave - 4) * 12)]; -} - - void setupI2S() { i2s_config_t i2s_config = { .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), @@ -41,7 +19,7 @@ void setupI2S() { .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, .communication_format = I2S_COMM_FORMAT_STAND_I2S, - .intr_alloc_flags = 0, // Default interrupt priority + .intr_alloc_flags = 0, .dma_buf_count = 8, .dma_buf_len = 64, .use_apll = false, @@ -61,9 +39,8 @@ void setupI2S() { i2s_set_clk(BOARD_I2S_PORT, SAMPLE_RATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO); } - void playTone(float frequency, int duration, int volume = 16383) { - volume = constrain(volume, 0, 32767); // Max volume is 32767, we default to half volume if not specified + volume = constrain(volume, 0, 32767); const int wave_period = SAMPLE_RATE / frequency; int16_t sample_buffer[wave_period]; @@ -80,81 +57,24 @@ void playTone(float frequency, int duration, int volume = 16383) { } } +void playRTTTL(const char* rtttl) { + static AudioGeneratorRTTTL *rtttlGenerator = new AudioGeneratorRTTTL(); + static AudioOutputI2S *audioOutput = new AudioOutputI2S(); + static AudioFileSourcePROGMEM *fileSource = new AudioFileSourcePROGMEM(rtttl, strlen(rtttl)); -void playRTTTL(const char* rtttl, int volume = 16383, int bpm = -1) { - int default_duration = 4; - int default_octave = 6; - int internal_bpm = 63; - - const char* p = rtttl; - - // Skip name - while (*p && *p != ':') p++; - if (*p == ':') p++; - - while (*p && *p != ':') { - char param = *p++; - if (*p == '=') p++; - int value = atoi(p); - while (*p && isdigit(*p)) p++; - if (*p == ',') p++; - switch (param) { - case 'd': default_duration = value; break; - case 'o': default_octave = value; break; - case 'b': internal_bpm = value; break; - } - } - - if (*p == ':') p++; - - if (bpm != -1) - internal_bpm = bpm; - - int beat_duration = 60000 / internal_bpm; - - while (*p) { - int duration = 0; - if (isdigit(*p)) { - duration = atoi(p); - while (isdigit(*p)) p++; - } else { - duration = default_duration; - } - - char note = *p++; - int frequency = getNoteFrequency(note, default_octave); - - if (*p == '#') { - frequency = getNoteFrequency(note + 1, default_octave); - p++; - } - - int octave = default_octave; - - if (isdigit(*p)) - octave = *p++ - '0'; - - if (*p == '.') { - duration = duration * 1.5; - p++; - } - - int note_duration = (beat_duration * 4) / duration; - - if (frequency > 0) - playTone(frequency, note_duration, volume); - else - delay(note_duration); - - if (*p == ',') p++; + audioOutput->begin(); + rtttlGenerator->begin(fileSource, audioOutput); + while (rtttlGenerator->isRunning()) { + rtttlGenerator->loop(); } + rtttlGenerator->stop(); + fileSource->close(); } - void playNotificationSound() { playTone(1000, 200); delay(100); playTone(1500, 200); delay(100); playTone(2000, 200); -} \ No newline at end of file +} diff --git a/src/main.ino b/src/main.ino index e432842..ee97bc1 100644 --- a/src/main.ino +++ b/src/main.ino @@ -113,7 +113,6 @@ void displayXBM() { void setup() { // Initialize serial communication Serial.begin(115200); - while (!Serial); Serial.println("Booting device..."); // Turn on the power to the board @@ -141,7 +140,8 @@ void setup() { // Initialize the speaker setupI2S(); // Do we want to keep this open or uninstall after each use to keep resources free? - const char* rtttl_boot = "ff6_victory:d=4,o=5,b=100:32d6,32p,32d6,32p,32d6,32p,d6,a#,c6,16d6,8p,16c6,2d6"; // This will go in preferences soon + //const char* rtttl_boot = "ff6_victory:d=4,o=5,b=120:32d6,32p,32d6,32p,32d6,32p,d6,a#,c6,16d6,8p,16c6,2d6"; // This will go in preferences soon + const char* rtttl_boot = "TakeOnMe:d=4,o=4,b=375:8f#5,8f#5,8f#5,8d5,8p,8b,8p,8e5,8p,8e5,8p,8e5,8g#5,8g#5,8a5,8b5"; playRTTTL(rtttl_boot); // Setup the WiFi @@ -1204,6 +1204,8 @@ void parseAndDisplay(String line) { addLine("ERROR", "ERR_ERRONEUSNICKNAME", "error", TFT_RED, TFT_DARKGREY); } else if (command == "433") { // ERR_NICKNAMEINUSE addLine("ERROR", "ERR_NICKNAMEINUSE", "error", TFT_RED, TFT_DARKGREY); + irc_nickname = "ACID_" + String(random(1000, 9999)); // Generate a random nickname + sendIRC("NICK " + irc_nickname); // Attempt to change to the random nickname } } }