I need a song to be made

https://musescore.com/user/33186954/scores/6147994

@UnsignedArduino, can you help make this music for my game? Thanks!

1 Like

This time it was slightly annoying because Musescore has decided to disable the playback feature. :thinking:

1 Like

Hey @UnsignedArduino. How exactly do you make these tracks? They sound really good and I want to try making some on my own.

1 Like
  1. I first download the song from Musescore (website)
  2. Open it in Musescore (software)
  3. If necessary, I combine all staffs into one staff.
  4. If necessary, I convert the instrument into a piano.
  5. If necessary, I modify the song so it sounds better, etc.
  6. I export as a midi file. (.mid)
  7. I convert the .mid file into a .json file using the mid_to_json.py script.
  8. I convert the .json file into a .ts file using the json_to_ts.py script.
  9. I copy the .ts file into an Arcade project.
  10. I import the timers extension.

You are going to need some Python knowledge to use these scripts.

# mid_to_json.py
# Install mido with pip install mido
# PyPI page: https://pypi.org/project/mido/

from mido import MidiFile, open_output
from pathlib import Path
from json import dumps
from time import sleep

# The path to the midi file. 
# vvv CHANGE THIS!!! vvv
midi_path = Path.cwd() /  "midi_file.mid"
# ^^^ CHANGE THIS!!! ^^^
json_path = Path.cwd() / (midi_path.stem + ".json")  
midi_file = MidiFile(str(midi_path))

json_dict = {"midi": []}


def midi_to_name(midi: int = 0):
    note_names = ["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"]
    return note_names[midi % 12] + str(int(((midi / 12) - 1)))


print(f"Input midi file path is '{midi_path}'")

# port = open_output("Microsoft GS Wavetable Synth 0")

# for msg in midi_file:
    # sleep(msg.time)
    # if msg.type == "note_on":
        # port.send(msg)
        # print(msg)

# port.close()

notes = []

for msg in midi_file:
    if msg.type == "note_on":
        if msg.velocity == 0:
            for index in range(len(notes)):
                notes[index]["time"] = msg.time
            if len(notes) > 0:
                json_dict["midi"].append(notes)
            notes = []
        else:
            notes.append({
                "note": msg.note,
                "name": midi_to_name(msg.note),
                "velocity": msg.velocity,
                "time": msg.time
            })
        # print(msg)


json_path.write_text(dumps(json_dict, indent=4))

print(f"Output json file path is '{json_path}'")

# json_to_ts.py

from pathlib import Path
from json import loads

# The path to the json file that mid_to_json exported. 
# vvv CHANGE THIS!!! vvv
json_path = Path.cwd() / "json_file.json"
# ^^^ CHANGE THIS!!! ^^^
ts_path = Path.cwd() / "Quietude by Mary Sue Brock" / (json_path.stem + ".ts")


def get_frequency(note, A4=440):
    notes = ['A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#']
    octave = int(note[2]) if len(note) == 3 else int(note[1])
    keyNumber = notes.index(note[0:-1]);
    if (keyNumber < 3) :
        keyNumber = keyNumber + 12 + ((octave - 1) * 12) + 1; 
    else:
        keyNumber = keyNumber + ((octave - 1) * 12) + 1; 
    return A4 * 2** ((keyNumber- 49) / 12)


print(f"Input json file path is '{json_path}'")

json_dict = loads(json_path.read_text())
ts = "function play_song() {\n"
current_velocity = None
speed_multiplier = 1

for chord in json_dict["midi"]:
    block = "{indent}// [notes]\n{indent}".format(indent=" "*4)
    block += "{\n"
    notes_in_chord = 0
    notes = []
    for index, note in enumerate(chord):
        notes_in_chord += 1
        if notes_in_chord > 5:
            continue
        if note["time"] == 0:
            continue
        if not current_velocity == note["velocity"]:
            current_velocity = note["velocity"]
            block += "{indent}music.setVolume({velocity})\n".format(
                indent = " " * 8, velocity = current_velocity
            )
        if len(chord) - 1 == index:
            block += "{indent}// {note}\n".format(indent=" "*8, note=note["name"])
            length = int((note["time"] * 1000) * speed_multiplier)
            delay = 0
            if length > 2000:
                delay = length - 2000
                length = 2000
            block += "{indent}music.playTone({hertz}, {duration})\n".format(
                indent = " " * 8,
                hertz = int(get_frequency(note=note["name"])),
                duration = length
            )
            if not delay == 0:
                block += "{indent}pause({delay})\n".format(
                    indent = " " * 8, delay = delay
                )
        else:
            block += "{indent}// {note}\n".format(indent=" "*8, note=note["name"])
            block += "{indent}timer.background(function() ".format(indent=" "*8)
            block += "{\n"
            length = int(note["time"] * 1000) * speed_multiplier
            delay = 0
            if length > 2000:
                delay = length - 2000
                length = 2000
            block += "{indent}music.playTone({hertz}, {duration})\n".format(
                indent = " " * 12,
                hertz = int(get_frequency(note=note["name"])),
                duration = length
            )
            if not delay == 0:
                block += "{indent}pause({delay})\n".format(
                    indent = " " * 12, delay = delay
                )
            block += " " * 8
            block += "})\n"
        notes.append(note["name"])
    block = block.replace("[notes]", str(notes))
    block += " " * 4
    block += "}\n"
    ts += block

ts += "}\n"
ts += "play_song()"

ts_path.write_text(ts)
print(f"Output ts file path is '{ts_path}'")

2 Likes

This is way to much for me to understand at once. Maybe @richard and the team can try showing an example, or a tool to convert audio to rtttl