Play Your Own Songs on Arduino/ESP32: MIDI-to-C-Array Converter

Hello everyone!

I'm excited to share a project designed to solve a common pain point: playing custom, complex melodies on Arduino or ESP32 boards without the tedious work of manually transcribing sheet music or note frequencies. The manual conversion process is slow and often inaccurate—that's where this tool comes in!

I've developed the MIDI-to-Arduino-Converter, a simple Python script that takes any standard single-track MIDI file and automatically generates the necessary C/C++ arrays (melody_data.h) for the Arduino tone() function.

1. :musical_note: Finding Your Single-Track MIDI File

The most critical step is the input file! Since the tone() function on Arduino boards is monophonic (it can only play one note at a time), your MIDI file must also be single-track. Polophonic files (multiple instruments or chords) will not convert correctly.

Look for MIDI files specifically labeled as "melody," "lead," or "solo."

Site Best For Tip
BitMidi General songs, video game music, classical pieces. Look for files labeled "Melody" or "Lead."
MidiDB Broad collection spanning various genres. Crucial: Avoid files over 50KB if you plan to use an Arduino Uno (see hardware section below).
The Official Forums Search the Arduino forums; sometimes users share MIDI files specifically for tone generation. Always listen to the file first to ensure it’s monophonic and sounds right.

2. :laptop: The Converter Tool (app.py) Explained

The heart of the project is the app.py script. It uses the Python mido library to efficiently parse the MIDI events:

  1. Note Extraction: It extracts the MIDI note number (0-127) and converts it into the corresponding standard frequency (Hz).
  2. Timing Calculation: It calculates the precise duration of each note and rest in milliseconds (ms).
  3. Output Generation: It compiles all this data into two aligned C arrays: melody[] (frequencies) and durations[].

This output file (melody_data.h) is then ready to be dropped straight into your Arduino IDE project folder.

Step 1: Get the Code and Files
All source code, example sketches, and documentation (including full wiring diagrams) are hosted on my GitHub. Please consider giving the repository a star if you find it useful!

GitHub Repository (Source Code, Sketches, Docs):
https://github.com/VihangaNethmaka/MIDI-To-Arduino-Converter

Quick Usage Steps:

  1. Prerequisite: Install the Mido library: pip install mido
  2. Configure: Edit the MIDI_FILENAME variable in app.py to match your MIDI file's name.
  3. Generate: Run python app.py.
  4. Output: Include the generated melody_data.h in your sketch.

3. :gear: Hardware Setup and Key Differences

The project includes two dedicated sketch files (.ino) designed for optimal performance on each microcontroller, relying on a passive buzzer connected via a protective resistor.

Board Pin Used Code Constant Important Note
Arduino Uno Digital Pin 8 const int BUZZZER_PIN = 8; :warning: Severe Memory Limit: The Uno has only 32KB of Flash memory. Since the music data is stored in PROGMEM, long or complex songs will quickly max out the available storage. This board is best for short jingles.
ESP32 GPIO Pin 25 const int BUZZZER_PIN = 25; Recommended Board. Although the sketch uses the standard Arduino tone() API, the ESP32's underlying core automatically utilizes the powerful LEDC peripheral for high-precision tone generation, resulting in cleaner audio and no memory issues.

Safety Reminder: Always use a current-limiting resistor (≈220Ω recommended) in series with your passive piezo buzzer to protect your microcontroller's digital output pin.

:memo: Included Files Overview

File Description
app.py MIDI to C array converter script. (The Core Tool)
Uno_Melody_Player.ino Dedicated playback sketch for the Arduino Uno.
ESP32_Melody_Player.ino Dedicated playback sketch for the ESP32.
melody_data.h Generated output file containing the note frequency and duration arrays.

Please try it out! Being able to convert and play your own custom music opens up a ton of possibilities for projects, alarms, and musical displays. Share your feedback, questions, or any cool songs you manage to convert—I’m happy to help troubleshoot!

2 Likes

Is this a library that I install in the IDE?

No. It's a Python script that runs on your computer. It generates the C/C++ code, which you then copy and paste into the IDE.

So you want me to run code that I don't read on my Mac to create Arduino C++ code. Why not just give us the C++ code?

This is due to the fact that scale and accuracy require the Python script.

It is impossible to maintain the C++ arrays for an entire song (often thousands of notes) by hand. To make sure the song plays back correctly, the script automatically determines the precise frequencies and millisecond durations from the MIDI data in seconds.

Before executing app.py, you can review its basic code on GitHub

Did you read the source code of the applications that you use on your Mac?

Because it's a tool. And tools generate output that differs based on the input. For each conversion of a different input file you will get a different melody_data.h as output.