Skip to content
Go back

Playing Midi Music on Arduino

Edit page

Turning a MIDI File into Arduino Music with PlatformIO

🎵 Project Overview

In this project, we created a simple workflow to convert a standard .mid MIDI file into binary note data suitable for playback on an Arduino Mega 2560 using PlatformIO.
The Arduino reads the notes from memory and plays them using the tone() function on a PWM output pin.


📝 Step 1 — Convert MIDI to Arduino Header File

We used Python with the mido library to parse MIDI files and extract note_on events.
These were saved into a header file as an array of [note, duration] pairs.

✅ Python MIDI Converter Code

import mido

MIDI_FILE = "input.mid"
TICK_DIV = 10  # ms per duration unit
OUTPUT_HEADER = "midi_song.h"

mid = mido.MidiFile(MIDI_FILE)
events = []

for msg in mid:
    if not msg.is_meta and msg.type == 'note_on' and msg.velocity > 0:
        note = msg.note
        duration = int(msg.time * 1000 / TICK_DIV)
        duration = max(1, min(duration, 255))
        events.append((note, duration))

with open(OUTPUT_HEADER, "w") as f:
    f.write("#pragma once\n\n")
    f.write("#include <stdint.h>  // ✅ This works on all Arduino platforms")
    f.write(f"const uint16_t SONG_LENGTH = {{len(events)}};\n")
    f.write("const uint8_t songData[][2] = {\n")
    for note, duration in events:
        f.write(f"  {{{note}, {duration}}},\n")
    f.write("};\n")

print(f"Generated {{OUTPUT_HEADER}} with {{len(events)}} notes.")

🛠️ Step 2 — Play the Notes with Arduino Code

This Arduino code reads the generated header file and plays each note using tone().
We used PlatformIO with the Arduino Mega 2560.

✅ Arduino Sketch Example

#include "midi_song.h"

const uint8_t speakerPin = 8;

uint16_t midiNoteToFreq(uint8_t note) {
  return 440 * pow(2, (note - 69) / 12.0);
}

void setup() {
  pinMode(speakerPin, OUTPUT);
  Serial.begin(115200);
  Serial.println("Starting MIDI Playback");
}

void loop() {
  for (uint16_t i = 0; i < SONG_LENGTH; i++) {
    uint8_t note = songData[i][0];
    uint8_t duration = songData[i][1];

    Serial.print("Note: "); Serial.print(note);
    Serial.print(" Duration: "); Serial.println(duration);

    if (note > 0) tone(speakerPin, midiNoteToFreq(note));
    delay(duration * 10);
    noTone(speakerPin);
  }

  delay(1000);  // Pause before repeating the song
}

✅ Final Thoughts

This project gave us a simple way to turn a standard MIDI file into an embedded music box running on an Arduino Mega.
Using PlatformIO allowed for better workflow and serial debugging, and the Python script made conversion fast and repeatable.


Happy hacking!


Edit page
Share this post on:

Next Post
Driving Lcd Display From Node Red