Added SpeedCalc and MelodyBuilder. Evaluation Pending
This commit is contained in:
1
SecondaryApps/MelodyBuilders/all_melodies.txt
Normal file
1
SecondaryApps/MelodyBuilders/all_melodies.txt
Normal file
@@ -0,0 +1 @@
|
||||
Esperinos-Adamn-1k: 1,0,1,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,0
|
||||
26
SecondaryApps/MelodyBuilders/builtin_melodies.txt
Normal file
26
SecondaryApps/MelodyBuilders/builtin_melodies.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
Doxology_Traditional: 1,2,1,2,1,3,0,0,1,2,1,2,1,4,0,0,1,2,1,2,1,2,1,2,1,2,1,3,1,4,0,0
|
||||
Doxology_Alternative: 1,0,2,3,0,4+5,0,1,0,2,3,0,4+5,0,1,0,2,3,0,4+5,0,1,2,1,2,3,0,4+5,0
|
||||
Doxology_Festive: 2,3,4+1,3,2,3,5+1,3,2,3,6+1,3,2,3,5+1,3
|
||||
Vesper_Traditional: 1,2,3,0,1,2,3,0,1,2,1,2,1,2,3,0
|
||||
Vesper_Alternative: 1,2,0,0,1,2,0,0,1,3,0,0,0,0,0,0,1,2,0,0,1,2,0,0,1,4,0,0,0,0,0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,3,0,0,1,4,0,0,0,0,0,0
|
||||
Catehetical: 1,2,3,4,5
|
||||
Orthros_Traditional: 1,0,2,0,3,4,0,5,0,6,0,7,8,0
|
||||
Orthros_Alternative: 1,0,2,1,0,2,0,1,0,1,2,1,0,3,0
|
||||
Mournfull_Toll: 1,0,0,0,0,0,0,1,0,0,0,0,0,0,3,0,0,0,0,0,0,3,0,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,4,0,0,0,0,0,0,4,0,0,0,0,0,0
|
||||
Mournfull_Toll_Alternative: 1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,3,0,0,0,0,0,0,3,3,0,0,0,0,0,0,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,4,0,0,0,0,0,0,4,4,0,0,0,0,0,0
|
||||
Mournfull_Toll_Meg_Par: 1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,3,0,0,0,0,0,0,3,0,0,0,0,0,0,3,3,0,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,4,0,0,0,0,0,0,4,0,0,0,0,0,0,4,4,0,0,0,0,0,0
|
||||
Sematron: 1,1,1,2,1,1,1,4,1,1,1,2,1,3,1,4
|
||||
Sematron_Alternative: 1,1,1,2,1,1,1,4,1,2,1,3,1,1,1,4
|
||||
Athonite_1_2_Voices: 1,2,1,1,2,1,1,2,1,1,2,1,2
|
||||
Athonite_3_Voices: 2,1,0,0,2,1,0,0,2,1,2,1,2,1,0,1,2,1,0,1,2,1,0,1,2,1,2,1,2,1,0,1,2,1,0,1,2,1,0,1,2,1,2,1,2,1,3,1,2,1,3,1,2,1,3,1,2,1,2,1,2,1,3,1,2,1,3,1,2,1,3,1,2,1,2,1,2,1,3
|
||||
Athonite_3_4_Voices: 2,1,0,0,2,1,0,0,2,1,2,1,2,1,0,1,2,1,0,1,2,1,0,1,2,1,2,1,2,1,0,1,2,1,0,1,2,1,0,1,2,1,2,1,2,1,3,1,2,1,0,3+1,2,1,0,3+1,2,1,0,3+1,2,1,2,3+1,2,1,4,3+1,2,1,0,3+1,2,1,0,3+1,2,1,2,3+1,2,1,4+1,2,1,3+1,2,1,4+2,2,1,3+2,2,1,4+1,2,1,3+1,2,1,4+2,2,1,3+2,2,1,4+1
|
||||
Athonite_4_8_Voices: 2,1,0,0,2,1,0,0,2,1,2,1,2,1,0,1,2,1,0,1,2,1,0,1,2,1,2,1,2,1,0,1,2,1,0,1,2,1,0,1,2,1,2,1,2,1,3,1,2,1,0,3+1,2,1,0,3+1,2,1,0,3+1,2,1,2,3+1,2,1,4,3+1,2,1,0,3+1,2,1,0,3+1,2,1,2,3+1,2,1,4+1,2,1,5+1,2,1,6+2,2,1,8+1,2,1,4+2,2,1,7+1,2,1,5+2,2,1,6+1,2,1,8+2,2,1,4+1,2,1,7+2,2,1,5+1,2,1,6+2,2,1,8+1,2,1,4+2,2,1,7+1,2,1,0,3+1,2,1,0,3+1,2,1,2,3+1,2,1,0,0,0
|
||||
OneByOne_2_3_Voices: 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,2,1,3,1,2,1,3,1,2,1,3,1,2,1,3,1,2,1,3,1,2,1,3,1,2,1,3,1,2,1,3,1,2,1,3,1,2,1,3,1,2,1,3,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2
|
||||
OneByOne_4_8_Voices: 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,2,1,3,1,2,1,3,1,2,1,3,2,3,4,3,2,5+1,2,3,4,3,2,6+1,2,3,4,3,2,7+1,2,3,4,3,2,8+1,2,3,4,3,2,7+1,2,3,4,3,2,6+1,2,3,4,3,2,7+1,2,3,4,3,2,8+1,2,3,4,3,2,7+1,2,3,4,3,2,6+1,2,3,4,3,2,1,2,1,3,1,2,1,3,1,2,1,3,1,2,1,3,1,2,1,3,1,2,1,2,1,2,1,2,1,2,1,2,1,0
|
||||
Festive_1Voice: 1,1,1,0,1,1,1,1,0,1,0,1,1,1,0,1,1,1,1,1,1,0,1,0
|
||||
Festive_4Voices: 1,2,3,4+1,2,1,3,4+1
|
||||
Festive_5Voices: 1,2,3,2,1,2,1,2,4,2,1,2,1,2,3,2,1,2,1,2,5,2,1,2
|
||||
Festive_5Voice_Alternative: 3,2,4,1,3,3,2,4,1,5,3,2,4,1,3,3,2,4,1,5+1,3,2,4,1,3,3,2,4,1,5+1,3,2,4,1,3+1,3,2,4,1,5+1,3,2,4,1,3+1,3,2,4,1,5+1,3,2,4,1,3,3,2,4,1,5,3,2,4,1,3,3,2,4,1,5
|
||||
Festive_6Voices: 1,2,3,2,1,2,1,2,4,2,1,2,1,2,3,2,1,2,1,2,5,2,1,2,1,2,4+1,2,1,2,5+1,2,1,2,3+1,2,1,2,6+1,2,1,2,4+1,2,1,2,5+1,2,1,2,3+1,2,1,2,6+1,2,1,2,4+1,2,1,2,5+1,2,1,2,3+1,2,1,2,6+1,2,1,2
|
||||
Festive_8Voices: 1,2,3,4,5,6,7,8
|
||||
Ormilia: 2,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2,1,0,1,2,1,0,1,2,1,0,1,0,1,0,1,2,1,2,1,2,1,2,1,0,1,0,1,0,1,0,1,2,4+1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2,3+1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2,4+1,0,1,2,3+1,0,1,2,4+1,0,1,2,3+1,0,1,2,5+1,2,1,2,6+1,2,1,2,5+1,2,1,2,6+1,2,7+1,2,8+1,2,4+1,2,7+1,2,8+1,2,4+1,2,7+1,2,8+1,2,3+1,2,1,0
|
||||
215
SecondaryApps/MelodyBuilders/convert_to_bin.py
Normal file
215
SecondaryApps/MelodyBuilders/convert_to_bin.py
Normal file
@@ -0,0 +1,215 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Bell Melody Converter
|
||||
Converts human-readable bell notation to binary .bsm files for ESP32
|
||||
|
||||
Format: MELODY_NAME: 1,2,3+4,0,5+6+7
|
||||
Output: MELODY_NAME.bsm (binary file, uint16_t big-endian)
|
||||
"""
|
||||
|
||||
import sys
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import List, Tuple
|
||||
|
||||
|
||||
def parse_bell_notation(notation: str) -> int:
|
||||
"""
|
||||
Convert human-readable bell notation to bit flag value
|
||||
|
||||
Examples:
|
||||
"2+8" → bells 2,8 → bits 1,7 → 0x0082 (130)
|
||||
"4" → bell 4 → bit 3 → 0x0008 (8)
|
||||
"1+2+3" → bells 1,2,3 → bits 0,1,2 → 0x0007 (7)
|
||||
"0" → no bells → 0x0000 (0)
|
||||
|
||||
Formula: Bell #N → Bit (N-1) → Value = 1 << (N-1)
|
||||
"""
|
||||
notation = notation.strip()
|
||||
|
||||
# Handle zero/silence
|
||||
if notation == '0' or not notation:
|
||||
return 0
|
||||
|
||||
# Split by + to get individual bell numbers
|
||||
bell_numbers = notation.split('+')
|
||||
|
||||
value = 0
|
||||
for bell_str in bell_numbers:
|
||||
try:
|
||||
bell_num = int(bell_str.strip())
|
||||
|
||||
if bell_num == 0:
|
||||
continue # Bell 0 means silence, contributes nothing
|
||||
|
||||
if bell_num < 1 or bell_num > 16:
|
||||
print(f"Warning: Bell number {bell_num} out of range (1-16), skipping")
|
||||
continue
|
||||
|
||||
# Convert bell number to bit position (1-indexed to 0-indexed)
|
||||
bit_position = bell_num - 1
|
||||
bit_value = 1 << bit_position
|
||||
value |= bit_value
|
||||
|
||||
except ValueError:
|
||||
print(f"Warning: Invalid bell number '{bell_str}', skipping")
|
||||
continue
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def parse_melody_line(line: str) -> Tuple[str, List[int]]:
|
||||
"""
|
||||
Parse a melody line in format: MELODY_NAME: step,step,step
|
||||
|
||||
Returns:
|
||||
(melody_name, list of uint16_t values)
|
||||
"""
|
||||
line = line.strip()
|
||||
|
||||
if not line or line.startswith('#'):
|
||||
return None, []
|
||||
|
||||
# Split by colon
|
||||
if ':' not in line:
|
||||
print(f"Warning: Invalid format (missing ':'): {line}")
|
||||
return None, []
|
||||
|
||||
parts = line.split(':', 1)
|
||||
melody_name = parts[0].strip()
|
||||
steps_str = parts[1].strip()
|
||||
|
||||
if not melody_name:
|
||||
print(f"Warning: Empty melody name in line: {line}")
|
||||
return None, []
|
||||
|
||||
# Parse steps (comma-separated)
|
||||
step_strings = steps_str.split(',')
|
||||
values = []
|
||||
|
||||
for i, step_str in enumerate(step_strings):
|
||||
value = parse_bell_notation(step_str)
|
||||
values.append(value)
|
||||
|
||||
return melody_name, values
|
||||
|
||||
|
||||
def write_binary_melody(filepath: str, values: List[int]):
|
||||
"""
|
||||
Write melody values as binary file (uint16_t, big-endian)
|
||||
|
||||
Args:
|
||||
filepath: Output file path
|
||||
values: List of uint16_t values (0-65535)
|
||||
"""
|
||||
with open(filepath, 'wb') as f:
|
||||
for value in values:
|
||||
# Ensure value fits in uint16_t
|
||||
if value > 0xFFFF:
|
||||
print(f"Warning: Value {value} exceeds uint16_t range, truncating")
|
||||
value = value & 0xFFFF
|
||||
|
||||
# Write as 2 bytes, big-endian (MSB first)
|
||||
f.write(value.to_bytes(2, byteorder='big'))
|
||||
|
||||
|
||||
def convert_melodies_file(input_path: str, output_dir: str = '.'):
|
||||
"""
|
||||
Convert multi-melody file to individual .bsm binary files
|
||||
|
||||
Args:
|
||||
input_path: Path to input text file
|
||||
output_dir: Directory for output .bsm files
|
||||
"""
|
||||
output_path = Path(output_dir)
|
||||
output_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
melodies_created = 0
|
||||
total_steps = 0
|
||||
|
||||
try:
|
||||
with open(input_path, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
print(f"Reading from: {input_path}")
|
||||
print(f"Output directory: {output_path.absolute()}\n")
|
||||
|
||||
for line_num, line in enumerate(lines, 1):
|
||||
melody_name, values = parse_melody_line(line)
|
||||
|
||||
if melody_name and values:
|
||||
# Create output filename
|
||||
output_file = output_path / f"{melody_name}.bsm"
|
||||
|
||||
# Write binary file
|
||||
write_binary_melody(str(output_file), values)
|
||||
|
||||
# Calculate file size
|
||||
file_size = len(values) * 2 # 2 bytes per uint16_t
|
||||
|
||||
# Show what bells are used
|
||||
all_bells = set()
|
||||
for value in values:
|
||||
for bit in range(16):
|
||||
if value & (1 << bit):
|
||||
all_bells.add(bit + 1) # Convert back to 1-indexed
|
||||
|
||||
bells_str = ','.join(map(str, sorted(all_bells))) if all_bells else 'none'
|
||||
|
||||
print(f"✓ {melody_name}.bsm")
|
||||
print(f" Steps: {len(values)}")
|
||||
print(f" Size: {file_size} bytes")
|
||||
print(f" Bells used: {bells_str}")
|
||||
print()
|
||||
|
||||
melodies_created += 1
|
||||
total_steps += len(values)
|
||||
|
||||
print(f"{'='*50}")
|
||||
print(f"✓ Successfully created {melodies_created} melody files")
|
||||
print(f" Total steps: {total_steps}")
|
||||
print(f" Total size: {total_steps * 2} bytes")
|
||||
|
||||
return True
|
||||
|
||||
except FileNotFoundError:
|
||||
print(f"Error: Input file '{input_path}' not found")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point"""
|
||||
print("=== Bell Melody Converter ===")
|
||||
print("Creates binary .bsm files for ESP32\n")
|
||||
|
||||
# Default input file
|
||||
input_file = "all_melodies.txt"
|
||||
output_dir = "."
|
||||
|
||||
# Check if file exists
|
||||
if not Path(input_file).exists():
|
||||
print(f"Error: '{input_file}' not found in current directory!")
|
||||
print("\nPlease create 'all_melodies.txt' with format:")
|
||||
print(" MELODY_NAME: step,step,step,...")
|
||||
print("\nStep notation:")
|
||||
print(" 0 - Silence")
|
||||
print(" 4 - Bell #4 only")
|
||||
print(" 2+8 - Bells #2 and #8 together")
|
||||
print(" 1+2+3 - Bells #1, #2, and #3 together")
|
||||
print("\nExample:")
|
||||
print(" JINGLE_BELLS: 4,4,4,0,4,4,4,0,4,8,1,2,4")
|
||||
print(" ALARM: 2+8,0,2+8,0,2+8,0")
|
||||
print(" HAPPY_BIRTHDAY: 1,1,2,1,4,3,0,1,1,2,1,8,4")
|
||||
sys.exit(1)
|
||||
|
||||
success = convert_melodies_file(input_file, output_dir)
|
||||
sys.exit(0 if success else 1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
300
SecondaryApps/MelodyBuilders/convert_to_builtin.py
Normal file
300
SecondaryApps/MelodyBuilders/convert_to_builtin.py
Normal file
@@ -0,0 +1,300 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Bell Melody to C Header Converter
|
||||
Converts human-readable bell notation to C header file with PROGMEM arrays
|
||||
|
||||
Input Format: MELODY_NAME: 1,2,3+4,0,5+6+7
|
||||
Output: melodies.h (C header with const uint16_t PROGMEM arrays)
|
||||
"""
|
||||
|
||||
import sys
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import List, Tuple
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def parse_bell_notation(notation: str) -> int:
|
||||
"""
|
||||
Convert human-readable bell notation to bit flag value
|
||||
|
||||
Examples:
|
||||
"2+8" → bells 2,8 → bits 1,7 → 0x0082 (130)
|
||||
"4" → bell 4 → bit 3 → 0x0008 (8)
|
||||
"1+2+3" → bells 1,2,3 → bits 0,1,2 → 0x0007 (7)
|
||||
"0" → no bells → 0x0000 (0)
|
||||
|
||||
Formula: Bell #N → Bit (N-1) → Value = 1 << (N-1)
|
||||
"""
|
||||
notation = notation.strip()
|
||||
|
||||
# Handle zero/silence
|
||||
if notation == '0' or not notation:
|
||||
return 0
|
||||
|
||||
# Split by + to get individual bell numbers
|
||||
bell_numbers = notation.split('+')
|
||||
|
||||
value = 0
|
||||
for bell_str in bell_numbers:
|
||||
try:
|
||||
bell_num = int(bell_str.strip())
|
||||
|
||||
if bell_num == 0:
|
||||
continue # Bell 0 means silence, contributes nothing
|
||||
|
||||
if bell_num < 1 or bell_num > 16:
|
||||
print(f"Warning: Bell number {bell_num} out of range (1-16), skipping")
|
||||
continue
|
||||
|
||||
# Convert bell number to bit position (1-indexed to 0-indexed)
|
||||
bit_position = bell_num - 1
|
||||
bit_value = 1 << bit_position
|
||||
value |= bit_value
|
||||
|
||||
except ValueError:
|
||||
print(f"Warning: Invalid bell number '{bell_str}', skipping")
|
||||
continue
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def parse_melody_line(line: str) -> Tuple[str, List[int]]:
|
||||
"""
|
||||
Parse a melody line in format: MELODY_NAME: step,step,step
|
||||
|
||||
Returns:
|
||||
(melody_name, list of uint16_t values)
|
||||
"""
|
||||
line = line.strip()
|
||||
|
||||
if not line or line.startswith('#'):
|
||||
return None, []
|
||||
|
||||
# Split by colon
|
||||
if ':' not in line:
|
||||
return None, []
|
||||
|
||||
parts = line.split(':', 1)
|
||||
melody_name = parts[0].strip()
|
||||
steps_str = parts[1].strip()
|
||||
|
||||
if not melody_name:
|
||||
return None, []
|
||||
|
||||
# Parse steps (comma-separated)
|
||||
step_strings = steps_str.split(',')
|
||||
values = []
|
||||
|
||||
for step_str in step_strings:
|
||||
value = parse_bell_notation(step_str)
|
||||
values.append(value)
|
||||
|
||||
return melody_name, values
|
||||
|
||||
|
||||
def format_melody_array(melody_name: str, values: List[int], values_per_line: int = 8) -> str:
|
||||
"""
|
||||
Format melody values as C PROGMEM array
|
||||
|
||||
Args:
|
||||
melody_name: Name of the melody (will be prefixed with "builtin_")
|
||||
values: List of uint16_t values
|
||||
values_per_line: Number of hex values per line
|
||||
|
||||
Returns:
|
||||
Formatted C array declaration
|
||||
"""
|
||||
array_name = f"melody_builtin_{melody_name.lower()}"
|
||||
|
||||
lines = []
|
||||
lines.append(f"const uint16_t PROGMEM {array_name}[] = {{")
|
||||
|
||||
# Format values in rows
|
||||
for i in range(0, len(values), values_per_line):
|
||||
chunk = values[i:i + values_per_line]
|
||||
hex_values = [f"0x{val:04X}" for val in chunk]
|
||||
|
||||
# Add comma after each value except the last one overall
|
||||
if i + len(chunk) < len(values):
|
||||
line = " " + ", ".join(hex_values) + ","
|
||||
else:
|
||||
line = " " + ", ".join(hex_values)
|
||||
|
||||
lines.append(line)
|
||||
|
||||
lines.append("};")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def format_melody_info_entry(melody_name: str, display_name: str, array_size: int) -> str:
|
||||
"""
|
||||
Format a single MelodyInfo struct entry
|
||||
|
||||
Args:
|
||||
melody_name: Technical name (will be prefixed with "builtin_")
|
||||
display_name: Human-readable name
|
||||
array_size: Number of elements in the melody array
|
||||
|
||||
Returns:
|
||||
Formatted struct entry
|
||||
"""
|
||||
array_name = f"melody_builtin_{melody_name.lower()}"
|
||||
id_name = f"builtin_{melody_name.lower()}"
|
||||
|
||||
return f""" {{
|
||||
"{display_name}",
|
||||
"{id_name}",
|
||||
{array_name},
|
||||
sizeof({array_name}) / sizeof(uint16_t)
|
||||
}}"""
|
||||
|
||||
|
||||
def convert_to_header(input_path: str, output_path: str = "melodies.h"):
|
||||
"""
|
||||
Convert multi-melody file to C header file
|
||||
|
||||
Args:
|
||||
input_path: Path to input text file
|
||||
output_path: Path to output .h file
|
||||
"""
|
||||
melodies = [] # List of (name, display_name, values)
|
||||
|
||||
try:
|
||||
with open(input_path, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
print(f"Reading from: {input_path}")
|
||||
print(f"Output file: {output_path}\n")
|
||||
|
||||
# Parse all melodies
|
||||
for line_num, line in enumerate(lines, 1):
|
||||
melody_name, values = parse_melody_line(line)
|
||||
|
||||
if melody_name and values:
|
||||
# Create display name (convert underscores to spaces, title case)
|
||||
display_name = melody_name.replace('_', ' ').title()
|
||||
melodies.append((melody_name, display_name, values))
|
||||
|
||||
print(f"✓ Parsed: {display_name} ({len(values)} steps)")
|
||||
|
||||
if not melodies:
|
||||
print("Error: No valid melodies found in input file")
|
||||
return False
|
||||
|
||||
# Generate header file
|
||||
print(f"\n{'='*50}")
|
||||
print(f"Generating C header file...\n")
|
||||
|
||||
with open(output_path, 'w', encoding='utf-8') as f:
|
||||
# Header guard and comments
|
||||
f.write("/*\n")
|
||||
f.write(" * Bell Melodies - Auto-generated\n")
|
||||
f.write(f" * Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
|
||||
f.write(f" * Source: {input_path}\n")
|
||||
f.write(" * \n")
|
||||
f.write(" * This file contains built-in melody definitions for the ESP32 bell controller\n")
|
||||
f.write(" */\n\n")
|
||||
f.write("#ifndef MELODIES_H\n")
|
||||
f.write("#define MELODIES_H\n\n")
|
||||
f.write("#include <Arduino.h>\n\n")
|
||||
|
||||
# Write melody arrays
|
||||
f.write("// ========================================\n")
|
||||
f.write("// Melody Data Arrays\n")
|
||||
f.write("// ========================================\n\n")
|
||||
|
||||
for melody_name, display_name, values in melodies:
|
||||
f.write(f"// {display_name}\n")
|
||||
f.write(format_melody_array(melody_name, values))
|
||||
f.write("\n\n")
|
||||
|
||||
# Write MelodyInfo structure definition
|
||||
f.write("// ========================================\n")
|
||||
f.write("// Melody Information Structure\n")
|
||||
f.write("// ========================================\n\n")
|
||||
f.write("struct MelodyInfo {\n")
|
||||
f.write(" const char* display_name;\n")
|
||||
f.write(" const char* id;\n")
|
||||
f.write(" const uint16_t* data;\n")
|
||||
f.write(" size_t length;\n")
|
||||
f.write("};\n\n")
|
||||
|
||||
# Write melody library array
|
||||
f.write("// ========================================\n")
|
||||
f.write("// Melody Library\n")
|
||||
f.write("// ========================================\n\n")
|
||||
f.write("const MelodyInfo MELODY_LIBRARY[] = {\n")
|
||||
|
||||
for i, (melody_name, display_name, values) in enumerate(melodies):
|
||||
entry = format_melody_info_entry(melody_name, display_name, len(values))
|
||||
|
||||
# Add comma except for last entry
|
||||
if i < len(melodies) - 1:
|
||||
f.write(entry + ",\n")
|
||||
else:
|
||||
f.write(entry + "\n")
|
||||
|
||||
f.write("};\n\n")
|
||||
|
||||
# Add library size constant
|
||||
f.write(f"const size_t MELODY_LIBRARY_SIZE = {len(melodies)};\n\n")
|
||||
|
||||
# Close header guard
|
||||
f.write("#endif // MELODIES_H\n")
|
||||
|
||||
# Summary
|
||||
print(f"✓ Successfully created {output_path}")
|
||||
print(f" Melodies: {len(melodies)}")
|
||||
|
||||
total_steps = sum(len(values) for _, _, values in melodies)
|
||||
print(f" Total steps: {total_steps}")
|
||||
print(f" Estimated PROGMEM usage: {total_steps * 2} bytes")
|
||||
|
||||
print(f"\n{'='*50}")
|
||||
print("Done! Include this file in your ESP32 project.")
|
||||
|
||||
return True
|
||||
|
||||
except FileNotFoundError:
|
||||
print(f"Error: Input file '{input_path}' not found")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point"""
|
||||
print("=== Bell Melody to C Header Converter ===")
|
||||
print("Creates melodies.h for ESP32 firmware\n")
|
||||
|
||||
# Default input file
|
||||
input_file = "builtin_melodies.txt"
|
||||
output_file = "melodies.h"
|
||||
|
||||
# Check if file exists
|
||||
if not Path(input_file).exists():
|
||||
print(f"Error: '{input_file}' not found in current directory!")
|
||||
print("\nPlease create 'builtin_melodies.txt' with format:")
|
||||
print(" MELODY_NAME: step,step,step,...")
|
||||
print("\nStep notation:")
|
||||
print(" 0 - Silence")
|
||||
print(" 4 - Bell #4 only")
|
||||
print(" 2+8 - Bells #2 and #8 together")
|
||||
print(" 1+2+3 - Bells #1, #2, and #3 together")
|
||||
print("\nExample:")
|
||||
print(" JINGLE_BELLS: 4,4,4,0,4,4,4,0,4,8,1,2,4")
|
||||
print(" ALARM: 2+8,0,2+8,0,2+8,0")
|
||||
print(" HAPPY_BIRTHDAY: 1,1,2,1,4,3,0,1,1,2,1,8,4")
|
||||
sys.exit(1)
|
||||
|
||||
success = convert_to_header(input_file, output_file)
|
||||
sys.exit(0 if success else 1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
475
SecondaryApps/MelodyBuilders/melodies.h
Normal file
475
SecondaryApps/MelodyBuilders/melodies.h
Normal file
@@ -0,0 +1,475 @@
|
||||
/*
|
||||
* Bell Melodies - Auto-generated
|
||||
* Generated: 2026-01-20 09:19:43
|
||||
* Source: builtin_melodies.txt
|
||||
*
|
||||
* This file contains built-in melody definitions for the ESP32 bell controller
|
||||
*/
|
||||
|
||||
#ifndef MELODIES_H
|
||||
#define MELODIES_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// ========================================
|
||||
// Melody Data Arrays
|
||||
// ========================================
|
||||
|
||||
// Doxology Traditional
|
||||
const uint16_t PROGMEM melody_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 melody_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 melody_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 melody_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 melody_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 melody_builtin_catehetical[] = {
|
||||
0x0001, 0x0002, 0x0004, 0x0008, 0x0010
|
||||
};
|
||||
|
||||
// Orthros Traditional
|
||||
const uint16_t PROGMEM melody_builtin_orthros_traditional[] = {
|
||||
0x0001, 0x0000, 0x0002, 0x0000, 0x0004, 0x0008, 0x0000, 0x0010,
|
||||
0x0000, 0x0020, 0x0000, 0x0040, 0x0080, 0x0000
|
||||
};
|
||||
|
||||
// Orthros Alternative
|
||||
const uint16_t PROGMEM melody_builtin_orthros_alternative[] = {
|
||||
0x0001, 0x0000, 0x0002, 0x0001, 0x0000, 0x0002, 0x0000, 0x0001,
|
||||
0x0000, 0x0001, 0x0002, 0x0001, 0x0000, 0x0004, 0x0000
|
||||
};
|
||||
|
||||
// Mournfull Toll
|
||||
const uint16_t PROGMEM melody_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 melody_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 melody_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 melody_builtin_sematron[] = {
|
||||
0x0001, 0x0001, 0x0001, 0x0002, 0x0001, 0x0001, 0x0001, 0x0008,
|
||||
0x0001, 0x0001, 0x0001, 0x0002, 0x0001, 0x0004, 0x0001, 0x0008
|
||||
};
|
||||
|
||||
// Sematron Alternative
|
||||
const uint16_t PROGMEM melody_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 melody_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 melody_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 melody_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 melody_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 melody_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 melody_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 melody_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 melody_builtin_festive_4voices[] = {
|
||||
0x0001, 0x0002, 0x0004, 0x0009, 0x0002, 0x0001, 0x0004, 0x0009
|
||||
};
|
||||
|
||||
// Festive 5Voices
|
||||
const uint16_t PROGMEM melody_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 melody_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 melody_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 melody_builtin_festive_8voices[] = {
|
||||
0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080
|
||||
};
|
||||
|
||||
// Ormilia
|
||||
const uint16_t PROGMEM melody_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 Information Structure
|
||||
// ========================================
|
||||
|
||||
struct MelodyInfo {
|
||||
const char* display_name;
|
||||
const char* id;
|
||||
const uint16_t* data;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// Melody Library
|
||||
// ========================================
|
||||
|
||||
const MelodyInfo MELODY_LIBRARY[] = {
|
||||
{
|
||||
"Doxology Traditional",
|
||||
"builtin_doxology_traditional",
|
||||
melody_builtin_doxology_traditional,
|
||||
sizeof(melody_builtin_doxology_traditional) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Doxology Alternative",
|
||||
"builtin_doxology_alternative",
|
||||
melody_builtin_doxology_alternative,
|
||||
sizeof(melody_builtin_doxology_alternative) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Doxology Festive",
|
||||
"builtin_doxology_festive",
|
||||
melody_builtin_doxology_festive,
|
||||
sizeof(melody_builtin_doxology_festive) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Vesper Traditional",
|
||||
"builtin_vesper_traditional",
|
||||
melody_builtin_vesper_traditional,
|
||||
sizeof(melody_builtin_vesper_traditional) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Vesper Alternative",
|
||||
"builtin_vesper_alternative",
|
||||
melody_builtin_vesper_alternative,
|
||||
sizeof(melody_builtin_vesper_alternative) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Catehetical",
|
||||
"builtin_catehetical",
|
||||
melody_builtin_catehetical,
|
||||
sizeof(melody_builtin_catehetical) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Orthros Traditional",
|
||||
"builtin_orthros_traditional",
|
||||
melody_builtin_orthros_traditional,
|
||||
sizeof(melody_builtin_orthros_traditional) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Orthros Alternative",
|
||||
"builtin_orthros_alternative",
|
||||
melody_builtin_orthros_alternative,
|
||||
sizeof(melody_builtin_orthros_alternative) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Mournfull Toll",
|
||||
"builtin_mournfull_toll",
|
||||
melody_builtin_mournfull_toll,
|
||||
sizeof(melody_builtin_mournfull_toll) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Mournfull Toll Alternative",
|
||||
"builtin_mournfull_toll_alternative",
|
||||
melody_builtin_mournfull_toll_alternative,
|
||||
sizeof(melody_builtin_mournfull_toll_alternative) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Mournfull Toll Meg Par",
|
||||
"builtin_mournfull_toll_meg_par",
|
||||
melody_builtin_mournfull_toll_meg_par,
|
||||
sizeof(melody_builtin_mournfull_toll_meg_par) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Sematron",
|
||||
"builtin_sematron",
|
||||
melody_builtin_sematron,
|
||||
sizeof(melody_builtin_sematron) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Sematron Alternative",
|
||||
"builtin_sematron_alternative",
|
||||
melody_builtin_sematron_alternative,
|
||||
sizeof(melody_builtin_sematron_alternative) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Athonite 1 2 Voices",
|
||||
"builtin_athonite_1_2_voices",
|
||||
melody_builtin_athonite_1_2_voices,
|
||||
sizeof(melody_builtin_athonite_1_2_voices) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Athonite 3 Voices",
|
||||
"builtin_athonite_3_voices",
|
||||
melody_builtin_athonite_3_voices,
|
||||
sizeof(melody_builtin_athonite_3_voices) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Athonite 3 4 Voices",
|
||||
"builtin_athonite_3_4_voices",
|
||||
melody_builtin_athonite_3_4_voices,
|
||||
sizeof(melody_builtin_athonite_3_4_voices) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Athonite 4 8 Voices",
|
||||
"builtin_athonite_4_8_voices",
|
||||
melody_builtin_athonite_4_8_voices,
|
||||
sizeof(melody_builtin_athonite_4_8_voices) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Onebyone 2 3 Voices",
|
||||
"builtin_onebyone_2_3_voices",
|
||||
melody_builtin_onebyone_2_3_voices,
|
||||
sizeof(melody_builtin_onebyone_2_3_voices) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Onebyone 4 8 Voices",
|
||||
"builtin_onebyone_4_8_voices",
|
||||
melody_builtin_onebyone_4_8_voices,
|
||||
sizeof(melody_builtin_onebyone_4_8_voices) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Festive 1Voice",
|
||||
"builtin_festive_1voice",
|
||||
melody_builtin_festive_1voice,
|
||||
sizeof(melody_builtin_festive_1voice) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Festive 4Voices",
|
||||
"builtin_festive_4voices",
|
||||
melody_builtin_festive_4voices,
|
||||
sizeof(melody_builtin_festive_4voices) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Festive 5Voices",
|
||||
"builtin_festive_5voices",
|
||||
melody_builtin_festive_5voices,
|
||||
sizeof(melody_builtin_festive_5voices) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Festive 5Voice Alternative",
|
||||
"builtin_festive_5voice_alternative",
|
||||
melody_builtin_festive_5voice_alternative,
|
||||
sizeof(melody_builtin_festive_5voice_alternative) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Festive 6Voices",
|
||||
"builtin_festive_6voices",
|
||||
melody_builtin_festive_6voices,
|
||||
sizeof(melody_builtin_festive_6voices) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Festive 8Voices",
|
||||
"builtin_festive_8voices",
|
||||
melody_builtin_festive_8voices,
|
||||
sizeof(melody_builtin_festive_8voices) / sizeof(uint16_t)
|
||||
},
|
||||
{
|
||||
"Ormilia",
|
||||
"builtin_ormilia",
|
||||
melody_builtin_ormilia,
|
||||
sizeof(melody_builtin_ormilia) / sizeof(uint16_t)
|
||||
}
|
||||
};
|
||||
|
||||
const size_t MELODY_LIBRARY_SIZE = 26;
|
||||
|
||||
#endif // MELODIES_H
|
||||
BIN
SecondaryApps/SpeedCalc/melodies_in_binary/1N_Esperinos_Adam.bsm
Normal file
BIN
SecondaryApps/SpeedCalc/melodies_in_binary/1N_Esperinos_Adam.bsm
Normal file
Binary file not shown.
BIN
SecondaryApps/SpeedCalc/melodies_in_binary/3N_MiaMia.bsm
Normal file
BIN
SecondaryApps/SpeedCalc/melodies_in_binary/3N_MiaMia.bsm
Normal file
Binary file not shown.
3
SecondaryApps/SpeedCalc/melodies_in_txt/melodies.txt
Normal file
3
SecondaryApps/SpeedCalc/melodies_in_txt/melodies.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
Esperinos-Adamn-1k [min 1426 / mid 572 / max 194]: 1,0,1,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,0
|
||||
Esperinos-Eortastikos-1k: 1,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0
|
||||
Orthros-1k [min 552 / mid 1402 / max 2229]: 1,0,1,0,1,1,0
|
||||
3
SecondaryApps/SpeedCalc/requirements.txt
Normal file
3
SecondaryApps/SpeedCalc/requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
PyQt6>=6.4.0
|
||||
numpy>=1.21.0
|
||||
sounddevice>=0.4.6
|
||||
1067
SecondaryApps/SpeedCalc/speedcalc.py
Normal file
1067
SecondaryApps/SpeedCalc/speedcalc.py
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user