Text to Melodie
Code
# Morse Code Mapping
MORSE_CODE_DICT = {
'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.',
'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..',
'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.',
'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-',
'Y': '-.--', 'Z': '--..',
'0': '-----', '1': '.----', '2': '..---', '3': '...--', '4': '....-',
'5': '.....', '6': '-....', '7': '--...', '8': '---..', '9': '----.',
'.': '.-.-.-', ',': '--..--', '?': '..--..', "'": '.----.', '!': '-.-.--',
'/': '-..-.', '(': '-.--.', ')': '-.--.-', '&': '.-...', ':': '---...',
';': '-.-.-.', '=': '-...-', '+': '.-.-.', '-': '-....-',
'_': '..--.-', '"': '.-..-.', '@': '.--.-.', ' ': '/'
}
# Note mapping including enharmonic equivalents
NOTE_MAP = {
'C': 0, 'C#': 1, 'Db': 1, 'D': 2, 'D#': 3, 'Eb': 3, 'E': 4, 'F': 5,
'F#': 6, 'Gb': 6, 'G': 7, 'G#': 8, 'Ab': 8, 'A': 9, 'A#': 10, 'Bb': 10,
'B': 11
}
# Function to encode text to Morse code
def text_to_morse(text):
"""Convert text to Morse code."""
morse_code = []
for char in text:
code = MORSE_CODE_DICT.get(char.upper(), None)
if code:
morse_code.append(code)
else:
print(f"Skipping unsupported character: {char}")
return morse_code
# Function to calculate the pitch based on the key and intervals
def morse_to_pitch(morse_code, key, dot_interval, dash_interval):
"""Convert Morse code to musical pitches based on the key."""
pitch_list = []
current_pitch = NOTE_MAP.get(key.upper(), 0) # Starting note in semitones
octave = 4 # Start in the 4th octave
for code in morse_code:
symbol_pitches = []
for symbol in code:
if symbol == '.':
current_pitch += dot_interval
if current_pitch >= 12: # Move up one octave if needed
current_pitch -= 12
octave += 1
elif current_pitch < 0: # Move down one octave if negative
current_pitch += 12
octave -= 1
symbol_pitches.append((current_pitch, octave))
elif symbol == '-':
current_pitch += dash_interval
if current_pitch >= 12:
current_pitch -= 12
octave += 1
elif current_pitch < 0:
current_pitch += 12
octave -= 1
symbol_pitches.append((current_pitch, octave))
elif symbol == '/': # For space in Morse code
symbol_pitches.append('rest') # Add a rest for space
pitch_list.append(symbol_pitches)
return pitch_list
# Function to format and display pitches per letter
def display_pitches_with_labels(text, morse_code_list, pitch_list, key):
"""Displays the formatted output for Morse code and pitch list with labels."""
print(f"\nMorse Code: {' '.join(morse_code_list)}")
print(f"Key: {key}4") # Display the entered key with octave 4
# Group output by words and rest in Morse code
for i, char in enumerate(text):
if char == ' ':
print(" : rest")
else:
morse_letter = morse_code_list[i]
pitches = pitch_list[i]
# Convert pitch list to note names with octave info
note_names = []
for pitch in pitches:
if isinstance(pitch, tuple):
note_names.append(f"{list(NOTE_MAP.keys())[pitch[0]]}{pitch[1]}")
else:
note_names.append(pitch)
print(f" {char.upper()}: {' '.join(note_names)}")
# Main program
def main():
user_input = input("Enter text to encode to Morse code: ").strip()
morse_code_list = text_to_morse(user_input)
key = input("Enter the Key (C, D, D#, Eb, A, etc.): ").strip()
# Get intervals for dot and dash and whether to go up or down
dot_interval = int(input("Enter the interval (in semitones) for dots: ").strip())
dot_direction = input("Should the dot interval go up or down? (up/down): ").strip().lower()
if dot_direction == "down":
dot_interval = -dot_interval
dash_interval = int(input("Enter the interval (in semitones) for dashes: ").strip())
dash_direction = input("Should the dash interval go up or down? (up/down): ").strip().lower()
if dash_direction == "down":
dash_interval = -dash_interval
# Convert Morse code to pitches
pitch_list = morse_to_pitch(morse_code_list, key, dot_interval, dash_interval)
# Display formatted output with labels
display_pitches_with_labels(user_input, morse_code_list, pitch_list, key)
if __name__ == "__main__":
main()