2.1 KiB
2.1 KiB
Arduino MIDI Player
This program plays MIDI music on Arduino by generating analog/PWM waves on a port connected to a speaker/buzzer. We use timer 2 to do direct digital synthesis (DDS).
Features
- Chords/multiple notes! The DDS can add multiple waves together on a single timer and single port. Unlike
tone()
which you can only run one frequency at any time. - Sine waves! You can define any arbitrary function/wave sample to use as the instrument in
smf2seq.js
. No more square waves of the built-intone()
function. - Tested on UNO! Though it might not work directly on other models, after some modification the concept should work on any Arduino. (since UNO is the crappiest model)
How to use
Hardware
- Connect buzzer/speaker to PWM port 11. Use a proper resister.
- A variable-resistance resister is recommended to adjust the volume.
- (Optional) Connect LEDs to port 2-7.
- Ground everything.
Software
- Place your
.mid
file under the main directory - Run
node smf2seq.js <your_midi_song.mid>
to generatesequence.h
(You will need to install node.js if you don't have one) - Open
arduino-midi-player.ino
in Arduino IDE - Compile & Upload
Limitations
Due to the hardware of Arduino, your MIDI might not work perfectly. (Apparently an Arduino UNO will NEVER be able to handle a black MIDI)
- Large files. The max internal storage is 32KB and
smf2seq.js
use 6 bytes for each note. - Short time intervals/High BPM. 1/2048 notes will not likely to play because of the internal clock
- High/Low pitches. The clock might not be fast enough to generate a desired wave of the specified frequency
- Complex chords. The clock interrupt cannot only process a limit number (4-6) of notes within the clock interval. Lower notes that exceed the limit of
KEYBUF_SIZE
will be discarded - Instruments. MIDI instruments will be disregarded and everything will be sine waves
Notes
- macros like
sbi
,cbi
,OCR2A
are used instead of API functions likedigitalWrite
to improve performance. Google them for more details