Language to Midi

My fascination with linguistics stems from growing up with three languages and the creative urge to experiment with language. This naturally led me to explore the relationship between music and language. Singing has been a part of my life since childhood and adolescence, and recently, I have rekindled my passion for it in a more serious way.

Wanting to take this exploration further, I began researching existing practices that integrate words—or even just syllables—into structured musical frameworks. In Western music, we recognize this through solfège (do-re-mi-fa-so-la-ti-do). Similarly, in jazz, scat singing allows vocalists to use nonsensical syllables to mimic instruments and improvise melodies freely.

This project draws inspiration from South Asian musical traditions, particularly the rhythmic intricacies of Carnatic music and its concept of rhythmic speech, such as Konnakol. Given my Southeast Asian heritage, I feel naturally drawn to what is often referred to as “non-Western” musical traditions. Unlike jazz scat singing, which is more melodic and fluid, Konnakol is highly structured, following precise tala (rhythmic cycles). My goal is to recreate and experiment with these rhythmic patterns using a coding language, thus a very mathematical approach, translating these ancient vocal traditions into a digital framework.

Concept:

The core of this project is the development of a system where written text is transformed into a musical composition. Each letter of the alphabet is assigned a musical note, and punctuation marks are treated as different kind of rests, allowing the text to be translated into a full musical piece. Drawing from the Carnatic tradition’s emphasis on rhythmic speaking and the South Asian focus on the relationship between sound and language, this system bridges the gap between exact linguistic expression and exact musical notation. It could be used in installations, where users are asked to type in individual words or whole sentences into the program and are then provided a musical output. A conversational approach could be used as well, where two people hold a conversation through text which is translated into music.

Technical Approach:

To bring this concept to life, I used Python to create a program that:

  • Assigns musical notes to each letter in the alphabet (using a starting pitch of C4). Optionally, note duration can be assigned too.
  • Transforms punctuation marks into different lengths of musical rests.

The output is a MIDI file, which can be played back or further manipulated in a digital audio workstation (DAW), and if opened on a notation program provides a lead sheet for musicians.

Code:

from midiutil import MIDIFile

def assign_notes_to_alphabet():
    """Assigns each letter of the alphabet a musical note"""
    notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
    alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    octave = 4

    note_mapping = {}
    note_index = 0

    for letter in alphabet:
        note_mapping[letter] = f"{notes[note_index]}{octave}"
        note_index += 1
        if note_index == len(notes):
            note_index = 0
            octave += 1

    return note_mapping

def convert_note_to_midi(note):
    """Converts a note into a MIDI note number."""
    pitch_class, octave = note[:-1], int(note[-1])
    midi_note_number = {
        "C": 0, "C#": 1, "D": 2, "D#": 3, "E": 4, "F": 5,
        "F#": 6, "G": 7, "G#": 8, "A": 9, "A#": 10, "B": 11
    }[pitch_class] + (octave + 1) * 12
    return midi_note_number

def text_to_midi(text, output_file="output.mid"):
    """Converts text into a MIDI file where each note has a unique duration."""
    # Assign notes to letters
    note_mapping = assign_notes_to_alphabet()

    # Define unique lengths for each note, can be varied
    note_length_mapping = {
        "C": 0.25,   # Quarter note
        "C#": 0.5,   # Half note
        "D": 0.75,   # Dotted quarter note
        "D#": 1,     # Whole note
        "E": 0.125,  # Eighth note
        "F": 0.25,
        "F#": 0.5,
        "G": 0.75,
        "G#": 1,
        "A": 0.125,
        "A#": 0.25,
        "B": 0.5
    }

    # Define rest lengths for punctuation and spaces
    punctuation_rest_mapping = {
        ".": 1,    # Whole rest
        ",": 0.5,  # Half rest
        "!": 0.25, # Quarter rest
        "?": 0.125,# Eighth rest
        " ": 0.25  # Quarter rest for spaces
    }

    # Create MIDI file
    midi = MIDIFile(1)  # One track
    track = 0
    channel = 0
    time = 0  # Start time
    volume = 100
    tempo = 120
    midi.addTempo(track, time, tempo)  # Set tempo

    for char in text.upper():
        if char in note_mapping:
            note = note_mapping[char]
            pitch_class = note[:-1]  # Extract note name without octave
            midi_note = convert_note_to_midi(note)
            note_length = note_length_mapping[pitch_class]  # Get pre-defined length
            midi.addNote(track, channel, midi_note, time, note_length, volume)
            time += note_length  # Advance time by this note's length
        elif char in punctuation_rest_mapping:
            time += punctuation_rest_mapping[char]  # Advance time for rests

    # Write the MIDI file
    with open(output_file, "wb") as f:
        midi.writeFile(f)
    print(f"MIDI file saved as {output_file}!")

# Example text
input_text = "ra ta ra ta rata, rata, ratatatata! ua, ua, ua, uuaa, ua ua ua ua, uauauauaua! sehe, sehe, sehe, sehe!!! leilala leilala leilala lei. ho-ho, ho-ho, ho-ho, hooo? ra ta ta ra tata ratatata"
text_to_midi(input_text, "text_to_music_varied_lengths.mid")
Generated lead sheet (with Dorico)
Audio (Midi)

Example with an original poem:

Calypso

Swimming headlessly in the streams

Underneath a pool of night

Pearls and shells reflecting light beams

Radiating white

Siren voices echoing

Guiding through the turbulent tides

Her longing for the surface grows

Numbed by the cold she glides

With the dolphins who arose

From a kingdom

Neptun’s knights

His face already long forgotten

Still lingers on her mind

Her body remembers

When he had forsaken

her to return back to his kind

‘Release me from my pain

Oh, mother of seas

Aphrodite, oh, lover

I’m over feeling shades of blue

Alleviate the one to suffer’

The seagulls laughing mockingly

As her body stranded on the shore

Drowned in the sun

Her skin laced with blisters

Her body forgot

What it was longing for

Generated lead sheet (with Dorico)
Audio (Midi)