/* * ═══════════════════════════════════════════════════════════════════════════════════ * BUILTINMELODIES.HPP - Firmware-Baked Melody Library * ═══════════════════════════════════════════════════════════════════════════════════ * * 🎵 BUILT-IN MELODY LIBRARY FOR VESPER 🎵 * * This file contains melodies baked directly into the firmware, eliminating * the need for SD card downloads. Each melody is stored in PROGMEM to save RAM. * * 🏗️ ARCHITECTURE: * • Melodies stored in PROGMEM (Flash memory, not RAM) * • Each melody step is 2 bytes (uint16_t bitmask) * • Metadata includes name, UID, default speed * • Easy to add new melodies * * 📦 STORAGE EFFICIENCY: * • Small melodies (~30 steps = 60 bytes) * • Large melodies (~200 steps = 400 bytes) * • 40 melodies average = ~6-10KB total (Flash, not RAM!) * * 🎶 MELODY FORMAT: * Each uint16_t is a bitmask: * - Bit 0-15: Which bells/notes to activate * - Example: 0x0001 = Bell 0, 0x0003 = Bells 0+1, 0x8000 = Bell 15 * * 📋 VERSION: 1.0 * 📅 DATE: 2025-12-28 * 👨‍💻 AUTHOR: Advanced Bell Systems * ═══════════════════════════════════════════════════════════════════════════════════ */ #pragma once #include #include #include namespace BuiltInMelodies { // ═════════════════════════════════════════════════════════════════════════════════ // MELODY METADATA STRUCTURE // ═════════════════════════════════════════════════════════════════════════════════ struct MelodyInfo { const char* name; // Display name const char* uid; // Unique identifier const uint16_t* data; // Pointer to melody data in PROGMEM uint16_t stepCount; // Number of steps }; // ═════════════════════════════════════════════════════════════════════════════════ // BuiltIn Melodies // More can be added here // ═════════════════════════════════════════════════════════════════════════════════ // 1 Bell Test Melody const uint16_t PROGMEM builtin_1bell_test[] = { 0x0001, 0x0000, 0x0001, 0x0000 }; // Doxology Traditional const uint16_t PROGMEM builtin_doxology_traditional[] = { 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0004, 0x0000, 0x0000, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0008, 0x0000, 0x0000, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0008, 0x0000, 0x0000 }; // Doxology Alternative const uint16_t PROGMEM builtin_doxology_alternative[] = { 0x0001, 0x0000, 0x0002, 0x0004, 0x0000, 0x0018, 0x0000, 0x0001, 0x0000, 0x0002, 0x0004, 0x0000, 0x0018, 0x0000, 0x0001, 0x0000, 0x0002, 0x0004, 0x0000, 0x0018, 0x0000, 0x0001, 0x0002, 0x0001, 0x0002, 0x0004, 0x0000, 0x0018, 0x0000 }; // Doxology Festive const uint16_t PROGMEM builtin_doxology_festive[] = { 0x0002, 0x0004, 0x0009, 0x0004, 0x0002, 0x0004, 0x0011, 0x0004, 0x0002, 0x0004, 0x0021, 0x0004, 0x0002, 0x0004, 0x0011, 0x0004 }; // Vesper Traditional const uint16_t PROGMEM builtin_vesper_traditional[] = { 0x0001, 0x0002, 0x0004, 0x0000, 0x0001, 0x0002, 0x0004, 0x0000, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0004, 0x0000 }; // Vesper Alternative const uint16_t PROGMEM builtin_vesper_alternative[] = { 0x0001, 0x0002, 0x0000, 0x0000, 0x0001, 0x0002, 0x0000, 0x0000, 0x0001, 0x0004, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0000, 0x0000, 0x0001, 0x0002, 0x0000, 0x0000, 0x0001, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0000, 0x0000, 0x0001, 0x0002, 0x0000, 0x0000, 0x0001, 0x0002, 0x0000, 0x0000, 0x0001, 0x0002, 0x0000, 0x0000, 0x0001, 0x0002, 0x0000, 0x0000, 0x0001, 0x0004, 0x0000, 0x0000, 0x0001, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; // Catehetical const uint16_t PROGMEM builtin_catehetical[] = { 0x0001, 0x0002, 0x0004, 0x0008, 0x0010 }; // Orthros Traditional const uint16_t PROGMEM builtin_orthros_traditional[] = { 0x0001, 0x0000, 0x0002, 0x0000, 0x0004, 0x0008, 0x0000, 0x0010, 0x0000, 0x0020, 0x0000, 0x0040, 0x0080, 0x0000 }; // Orthros Alternative const uint16_t PROGMEM builtin_orthros_alternative[] = { 0x0001, 0x0000, 0x0002, 0x0001, 0x0000, 0x0002, 0x0000, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0004, 0x0000 }; // Mournfull Toll const uint16_t PROGMEM builtin_mournfull_toll[] = { 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; // Mournfull Toll Alternative const uint16_t PROGMEM builtin_mournfull_toll_alternative[] = { 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0004, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; // Mournfull Toll Meg Par const uint16_t PROGMEM builtin_mournfull_toll_meg_par[] = { 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0004, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; // Sematron const uint16_t PROGMEM builtin_sematron[] = { 0x0001, 0x0001, 0x0001, 0x0002, 0x0001, 0x0001, 0x0001, 0x0008, 0x0001, 0x0001, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0008 }; // Sematron Alternative const uint16_t PROGMEM builtin_sematron_alternative[] = { 0x0001, 0x0001, 0x0001, 0x0002, 0x0001, 0x0001, 0x0001, 0x0008, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0001, 0x0001, 0x0008 }; // Athonite 1 2 Voices const uint16_t PROGMEM builtin_athonite_1_2_voices[] = { 0x0001, 0x0002, 0x0001, 0x0001, 0x0002, 0x0001, 0x0001, 0x0002, 0x0001, 0x0001, 0x0002, 0x0001, 0x0002 }; // Athonite 3 Voices const uint16_t PROGMEM builtin_athonite_3_voices[] = { 0x0002, 0x0001, 0x0000, 0x0000, 0x0002, 0x0001, 0x0000, 0x0000, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0004 }; // Athonite 3 4 Voices const uint16_t PROGMEM builtin_athonite_3_4_voices[] = { 0x0002, 0x0001, 0x0000, 0x0000, 0x0002, 0x0001, 0x0000, 0x0000, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0000, 0x0005, 0x0002, 0x0001, 0x0000, 0x0005, 0x0002, 0x0001, 0x0000, 0x0005, 0x0002, 0x0001, 0x0002, 0x0005, 0x0002, 0x0001, 0x0008, 0x0005, 0x0002, 0x0001, 0x0000, 0x0005, 0x0002, 0x0001, 0x0000, 0x0005, 0x0002, 0x0001, 0x0002, 0x0005, 0x0002, 0x0001, 0x0009, 0x0002, 0x0001, 0x0005, 0x0002, 0x0001, 0x000A, 0x0002, 0x0001, 0x0006, 0x0002, 0x0001, 0x0009, 0x0002, 0x0001, 0x0005, 0x0002, 0x0001, 0x000A, 0x0002, 0x0001, 0x0006, 0x0002, 0x0001, 0x0009 }; // Athonite 4 8 Voices const uint16_t PROGMEM builtin_athonite_4_8_voices[] = { 0x0002, 0x0001, 0x0000, 0x0000, 0x0002, 0x0001, 0x0000, 0x0000, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0000, 0x0005, 0x0002, 0x0001, 0x0000, 0x0005, 0x0002, 0x0001, 0x0000, 0x0005, 0x0002, 0x0001, 0x0002, 0x0005, 0x0002, 0x0001, 0x0008, 0x0005, 0x0002, 0x0001, 0x0000, 0x0005, 0x0002, 0x0001, 0x0000, 0x0005, 0x0002, 0x0001, 0x0002, 0x0005, 0x0002, 0x0001, 0x0009, 0x0002, 0x0001, 0x0011, 0x0002, 0x0001, 0x0022, 0x0002, 0x0001, 0x0081, 0x0002, 0x0001, 0x000A, 0x0002, 0x0001, 0x0041, 0x0002, 0x0001, 0x0012, 0x0002, 0x0001, 0x0021, 0x0002, 0x0001, 0x0082, 0x0002, 0x0001, 0x0009, 0x0002, 0x0001, 0x0042, 0x0002, 0x0001, 0x0011, 0x0002, 0x0001, 0x0022, 0x0002, 0x0001, 0x0081, 0x0002, 0x0001, 0x000A, 0x0002, 0x0001, 0x0041, 0x0002, 0x0001, 0x0000, 0x0005, 0x0002, 0x0001, 0x0000, 0x0005, 0x0002, 0x0001, 0x0002, 0x0005, 0x0002, 0x0001, 0x0000, 0x0000, 0x0000 }; // Onebyone 2 3 Voices const uint16_t PROGMEM builtin_onebyone_2_3_voices[] = { 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002 }; // Onebyone 4 8 Voices const uint16_t PROGMEM builtin_onebyone_4_8_voices[] = { 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0002, 0x0004, 0x0008, 0x0004, 0x0002, 0x0011, 0x0002, 0x0004, 0x0008, 0x0004, 0x0002, 0x0021, 0x0002, 0x0004, 0x0008, 0x0004, 0x0002, 0x0041, 0x0002, 0x0004, 0x0008, 0x0004, 0x0002, 0x0081, 0x0002, 0x0004, 0x0008, 0x0004, 0x0002, 0x0041, 0x0002, 0x0004, 0x0008, 0x0004, 0x0002, 0x0021, 0x0002, 0x0004, 0x0008, 0x0004, 0x0002, 0x0041, 0x0002, 0x0004, 0x0008, 0x0004, 0x0002, 0x0081, 0x0002, 0x0004, 0x0008, 0x0004, 0x0002, 0x0041, 0x0002, 0x0004, 0x0008, 0x0004, 0x0002, 0x0021, 0x0002, 0x0004, 0x0008, 0x0004, 0x0002, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0000 }; // Festive 1Voice const uint16_t PROGMEM builtin_festive_1voice[] = { 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0000 }; // Festive 4Voices const uint16_t PROGMEM builtin_festive_4voices[] = { 0x0001, 0x0002, 0x0004, 0x0009, 0x0002, 0x0001, 0x0004, 0x0009 }; // Festive 5Voices const uint16_t PROGMEM builtin_festive_5voices[] = { 0x0001, 0x0002, 0x0004, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0008, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0004, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0010, 0x0002, 0x0001, 0x0002 }; // Festive 5Voice Alternative const uint16_t PROGMEM builtin_festive_5voice_alternative[] = { 0x0004, 0x0002, 0x0008, 0x0001, 0x0004, 0x0004, 0x0002, 0x0008, 0x0001, 0x0010, 0x0004, 0x0002, 0x0008, 0x0001, 0x0004, 0x0004, 0x0002, 0x0008, 0x0001, 0x0011, 0x0004, 0x0002, 0x0008, 0x0001, 0x0004, 0x0004, 0x0002, 0x0008, 0x0001, 0x0011, 0x0004, 0x0002, 0x0008, 0x0001, 0x0005, 0x0004, 0x0002, 0x0008, 0x0001, 0x0011, 0x0004, 0x0002, 0x0008, 0x0001, 0x0005, 0x0004, 0x0002, 0x0008, 0x0001, 0x0011, 0x0004, 0x0002, 0x0008, 0x0001, 0x0004, 0x0004, 0x0002, 0x0008, 0x0001, 0x0010, 0x0004, 0x0002, 0x0008, 0x0001, 0x0004, 0x0004, 0x0002, 0x0008, 0x0001, 0x0010 }; // Festive 6Voices const uint16_t PROGMEM builtin_festive_6voices[] = { 0x0001, 0x0002, 0x0004, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0008, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0004, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0010, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0009, 0x0002, 0x0001, 0x0002, 0x0011, 0x0002, 0x0001, 0x0002, 0x0005, 0x0002, 0x0001, 0x0002, 0x0021, 0x0002, 0x0001, 0x0002, 0x0009, 0x0002, 0x0001, 0x0002, 0x0011, 0x0002, 0x0001, 0x0002, 0x0005, 0x0002, 0x0001, 0x0002, 0x0021, 0x0002, 0x0001, 0x0002, 0x0009, 0x0002, 0x0001, 0x0002, 0x0011, 0x0002, 0x0001, 0x0002, 0x0005, 0x0002, 0x0001, 0x0002, 0x0021, 0x0002, 0x0001, 0x0002 }; // Festive 8Voices const uint16_t PROGMEM builtin_festive_8voices[] = { 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080 }; // Ormilia const uint16_t PROGMEM builtin_ormilia[] = { 0x0002, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0002, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0002, 0x0009, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0002, 0x0005, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0002, 0x0009, 0x0000, 0x0001, 0x0002, 0x0005, 0x0000, 0x0001, 0x0002, 0x0009, 0x0000, 0x0001, 0x0002, 0x0005, 0x0000, 0x0001, 0x0002, 0x0011, 0x0002, 0x0001, 0x0002, 0x0021, 0x0002, 0x0001, 0x0002, 0x0011, 0x0002, 0x0001, 0x0002, 0x0021, 0x0002, 0x0041, 0x0002, 0x0081, 0x0002, 0x0009, 0x0002, 0x0041, 0x0002, 0x0081, 0x0002, 0x0009, 0x0002, 0x0041, 0x0002, 0x0081, 0x0002, 0x0005, 0x0002, 0x0001, 0x0000 }; // ═════════════════════════════════════════════════════════════════════════════════ // MELODY LIBRARY - Array of all built-in melodies // ═════════════════════════════════════════════════════════════════════════════════ const MelodyInfo MELODY_LIBRARY[] = { { "1 Bell Test", "builtin_1bell_test", builtin_1bell_test, sizeof(builtin_1bell_test) / sizeof(uint16_t) }, { "Doxology Traditional", "builtin_doxology_traditional", builtin_doxology_traditional, sizeof(builtin_doxology_traditional) / sizeof(uint16_t) }, { "Doxology Alternative", "builtin_doxology_alternative", builtin_doxology_alternative, sizeof(builtin_doxology_alternative) / sizeof(uint16_t) }, { "Doxology Festive", "builtin_doxology_festive", builtin_doxology_festive, sizeof(builtin_doxology_festive) / sizeof(uint16_t) }, { "Vesper Traditional", "builtin_vesper_traditional", builtin_vesper_traditional, sizeof(builtin_vesper_traditional) / sizeof(uint16_t) }, { "Vesper Alternative", "builtin_vesper_alternative", builtin_vesper_alternative, sizeof(builtin_vesper_alternative) / sizeof(uint16_t) }, { "Catehetical", "builtin_catehetical", builtin_catehetical, sizeof(builtin_catehetical) / sizeof(uint16_t) }, { "Orthros Traditional", "builtin_orthros_traditional", builtin_orthros_traditional, sizeof(builtin_orthros_traditional) / sizeof(uint16_t) }, { "Orthros Alternative", "builtin_orthros_alternative", builtin_orthros_alternative, sizeof(builtin_orthros_alternative) / sizeof(uint16_t) }, { "Mournfull Toll", "builtin_mournfull_toll", builtin_mournfull_toll, sizeof(builtin_mournfull_toll) / sizeof(uint16_t) }, { "Mournfull Toll Alternative", "builtin_mournfull_toll_alternative", builtin_mournfull_toll_alternative, sizeof(builtin_mournfull_toll_alternative) / sizeof(uint16_t) }, { "Mournfull Toll Meg Par", "builtin_mournfull_toll_meg_par", builtin_mournfull_toll_meg_par, sizeof(builtin_mournfull_toll_meg_par) / sizeof(uint16_t) }, { "Sematron", "builtin_sematron", builtin_sematron, sizeof(builtin_sematron) / sizeof(uint16_t) }, { "Sematron Alternative", "builtin_sematron_alternative", builtin_sematron_alternative, sizeof(builtin_sematron_alternative) / sizeof(uint16_t) }, { "Athonite 1 2 Voices", "builtin_athonite_1_2_voices", builtin_athonite_1_2_voices, sizeof(builtin_athonite_1_2_voices) / sizeof(uint16_t) }, { "Athonite 3 Voices", "builtin_athonite_3_voices", builtin_athonite_3_voices, sizeof(builtin_athonite_3_voices) / sizeof(uint16_t) }, { "Athonite 3 4 Voices", "builtin_athonite_3_4_voices", builtin_athonite_3_4_voices, sizeof(builtin_athonite_3_4_voices) / sizeof(uint16_t) }, { "Athonite 4 8 Voices", "builtin_athonite_4_8_voices", builtin_athonite_4_8_voices, sizeof(builtin_athonite_4_8_voices) / sizeof(uint16_t) }, { "Onebyone 2 3 Voices", "builtin_onebyone_2_3_voices", builtin_onebyone_2_3_voices, sizeof(builtin_onebyone_2_3_voices) / sizeof(uint16_t) }, { "Onebyone 4 8 Voices", "builtin_onebyone_4_8_voices", builtin_onebyone_4_8_voices, sizeof(builtin_onebyone_4_8_voices) / sizeof(uint16_t) }, { "Festive 1Voice", "builtin_festive_1voice", builtin_festive_1voice, sizeof(builtin_festive_1voice) / sizeof(uint16_t) }, { "Festive 4Voices", "builtin_festive_4voices", builtin_festive_4voices, sizeof(builtin_festive_4voices) / sizeof(uint16_t) }, { "Festive 5Voices", "builtin_festive_5voices", builtin_festive_5voices, sizeof(builtin_festive_5voices) / sizeof(uint16_t) }, { "Festive 5Voice Alternative", "builtin_festive_5voice_alternative", builtin_festive_5voice_alternative, sizeof(builtin_festive_5voice_alternative) / sizeof(uint16_t) }, { "Festive 6Voices", "builtin_festive_6voices", builtin_festive_6voices, sizeof(builtin_festive_6voices) / sizeof(uint16_t) }, { "Festive 8Voices", "builtin_festive_8voices", builtin_festive_8voices, sizeof(builtin_festive_8voices) / sizeof(uint16_t) }, { "Ormilia", "builtin_ormilia", builtin_ormilia, sizeof(builtin_ormilia) / sizeof(uint16_t) } }; const uint16_t MELODY_COUNT = sizeof(MELODY_LIBRARY) / sizeof(MelodyInfo); // ═════════════════════════════════════════════════════════════════════════════════ // HELPER FUNCTIONS // ═════════════════════════════════════════════════════════════════════════════════ /** * @brief Check if a UID is a built-in melody * @param uid The melody UID to check * @return true if it's a built-in melody (starts with "builtin_") */ inline bool isBuiltInMelody(const String& uid) { return uid.startsWith("builtin_"); } /** * @brief Find a built-in melody by UID * @param uid The melody UID to find * @return Pointer to MelodyInfo if found, nullptr otherwise */ inline const MelodyInfo* findMelodyByUID(const String& uid) { for (uint16_t i = 0; i < MELODY_COUNT; i++) { if (uid == MELODY_LIBRARY[i].uid) { return &MELODY_LIBRARY[i]; } } return nullptr; } /** * @brief Load a built-in melody into a vector * @param uid The melody UID to load * @param melodySteps Vector to fill with melody data * @return true if melody was found and loaded, false otherwise */ inline bool loadBuiltInMelody(const String& uid, std::vector& melodySteps) { const MelodyInfo* melody = findMelodyByUID(uid); if (!melody) { return false; } // Resize vector and copy data from PROGMEM melodySteps.resize(melody->stepCount); for (uint16_t i = 0; i < melody->stepCount; i++) { melodySteps[i] = pgm_read_word(&(melody->data[i])); } return true; } /** * @brief Get list of all built-in melodies as JSON string * @return JSON array string of melody names and UIDs */ inline String getBuiltInMelodiesJSON() { String json = "["; for (uint16_t i = 0; i < MELODY_COUNT; i++) { if (i > 0) json += ","; json += "{"; json += "\"name\":\"" + String(MELODY_LIBRARY[i].name) + "\","; json += "\"uid\":\"" + String(MELODY_LIBRARY[i].uid) + "\","; json += "}"; } json += "]"; return json; } }