MIDI is a famous audio sequence protocol to turn: Music Inputs into Digital Interfaces.
Standard computer files storing MIDI data in binary and standard MIDI protocol can be accessed from specialized website (e.g. bitmidi,…)
These file can be played by specific applications that can read and sequence this .mid format into audio sound output. Depending on the quality of the file and of the sound generated, the final quality can be very bad, or very close to real audio songs.
My initial goal is to use js with Max-MSP framework (Max 7 ) to more refinedly exploit the content of these .Mid file to extract only what I need from it, e.g. just th drums track or the bass track for example in a file containing also other tracks.
Then I can generate new files and use these in real-time for musical performance with PapierLogik Sensors, my guitar and my voice or other instruments.
FIRST STEP: convert .Mid to JSON
After a few attempts trying to directly parse the .Mis file in JS for MaxMSP, it turned out the Max7 framework is getting old and I could not easily make use of the programs and libraries output through copilot.
A fine alternative, consist in first producing JSON files from the .Mid files. Indeed, these JSON files will be much easier to parse in Max7.
For this step, we then first need to write a script tha will convert a .mid file input in to a JSON file output.
I could build the following working procedure:
1- Create a project folder and Add the input .Mid file in the project folder
2- Create and store a script.py file in ou project folder: this file will contain the following code:
# Python script
# converts MIDI .Mid files to JSON files
# Rodolphe Koehly, March 2025
import json
# Read the binary MIDI file
with open("Test_Buckley.mid", "rb") as f:
data = f.read()
# Save the binary data as a JSON array (for testing)
with open("Test_Buckley.json", "w") as f_json:
json.dump(list(data), f_json)
print("MIDI data saved as JSON!")
Step 2: Parse MIDI data from the created JSON in MaxMSP
I explore here the production of Javascript JS code to parse data from a JSON file containing MIDI data issued from a .Mid FIle.
This JS file can then be used in the MaxMSP application framework (Max7) to control and trigger in real-time sensor control data and MIDI outupt data, generating sounds from included or added sequencers.
This work involved many development steps I could manage using copilot to create a program and itterate it until it worked as expected. I stored these attempts as JS files to use in Max for various applications.
{Link to github}
A first success was to be able to indentify key MIDI file infos, such as the Header Message. This could be done with the following code:
// Custom_Mid_File_JS_Parser.js
// Custom function to pad numbers as strings
function padStart(str, targetLength, padChar) {
str = String(str); // Ensure input is a string
while (str.length < targetLength) {
str = padChar + str;
}
return str;
}
function readJson(filename) {
try {
// Open the JSON file using Max's File object
var f = new File(filename, "read");
if (!f.isopen) {
post("Error: Unable to open file. Check the path or permissions.\n");
return;
} else {
post("Debug: JSON file successfully opened.\n");
}
// Read the entire JSON content
var jsonData = "";
while (f.position < f.eof) {
jsonData += f.readstring(256); // Read chunks as a string
}
f.close();
// Parse the JSON content to retrieve the MIDI data as an array
var midiDataArray = JSON.parse(jsonData);
post("Debug: JSON data successfully parsed. Length: " + midiDataArray.length + "\n");
// Convert the array back to a Uint8Array
var rawData = new Uint8Array(midiDataArray);
// Debug: Print the first 16 bytes of the MIDI data
post("Debug: First 16 bytes of the MIDI data:\n");
for (var i = 0; i < 16 && i < rawData.length; i++) {
post(padStart(rawData[i].toString(16), 2, '0') + " "); // Use custom padStart
}
post("\n");
// (Optional) Pass rawData to a MIDI parsing function
// var midiFile = parseMidi(rawData);
// outlet(0, JSON.stringify(midiFile));
} catch (error) {
post("Error reading or processing JSON: " + error.message + "\n");
}
}
The above code returns:
js: Debug: JSON file successfully opened.
js: Debug: JSON data successfully parsed.
Length: 13211 js: MIDI Header Info: Format Type: 1 Number of Tracks: 1 Time Division: 480
This means the mid file I asked to examine was successfully opened and recongnised has having the features of a MIDI file of frmat type 1 and containing track over 480 time divisions (the song id a binary mid file of Hallelujah song played by Jeff Buckley in the Grace album).
Download File: Buckley-Halleluyah.mid