Copyright © 1999-2015 by Tom Grandgent
MIDI stands for Musical Instrument Digital Interface. It is a protocol for communication between electronic instruments and computers, as well as a file format for storing a sequence of musical events. A "MIDI file" contains a description of a musical performance. This is vastly different from formats like MP3, which contain a recording of a musical performance. Having the music in the form of a description lets listeners see and control so much more of what's going on.
MIDI files can also be played back on a wide variety of different synthesizers (both hardware and software based), some of which support loading custom instrument banks (like Creative Labs' / Emu's SoundFont technology). I've listened to my MIDI collection on an FM synth (Adlib-based), then a good software wavetable synth (WinGroove), then a wavetable synth (Sound Blaster AWE64, 512k ROM), then some 8MB SoundFonts, then a more advanced professional wavetable synth (Roland Sound Canvas SCC-1, ~4MB ROM), then the Roland MT-32 for some old (late 80's, early 90's) MIDI files, the Sound Blaster Live! using up to 32MB of memory for SoundFonts, and finally the ultimate ... the Roland Sound Canvas SC-8850. Every synth has its own soul, with its own strengths and weaknesses, and it is similar with various instrument banks. You can get an awful lot of life out of a little 10k MIDI file by playing it on different synths and with different instrument banks!
TMIDI is a MIDI player for Windows. Unlike almost every other Windows-based MIDI player out there, it's written entirely from scratch instead of relying on the MIDI player built into Windows. Because of this, TMIDI offers enhanced display and control over the music playback. It can also play files that most other MIDI players choke on. For people who aren't too familiar with MIDI, TMIDI can be very educational: it lets you see in detail what's going on and how things work.
TMIDI is a single EXE file, approximately 64KB in size. No installation is necessary - just save the file to disk somewhere and run it. It is currently freeware, released under the MIT license, with source code available (see bottom of this page). By downloading and/or using TMIDI, you agree to this license.
Click here to download 32-bit TMIDI (recommended for normal people)
Click here to download 64-bit TMIDI (suitable for extreme MIDI activities)
Click here for the C++ source code!
I tried to keep the user interface as simple and intuitive as possible. Here are some tips on how to use TMIDI:
- Choose your MIDI Out device when you first run TMIDI. It will be remembered for the future.
- To open a MIDI file, you can either use the Open MIDI File button or drag and drop a file onto the TMIDI window. If you choose to associate MIDI files with TMIDI, you can also double-click on a MIDI file from a folder window.
- Click on an instrument or drum kit name to change it to something else. This change will last until you load another MIDI file. If you want to revert to the original instrument, choose "Default" from the instrument menu.
- To open a window showing text embedded in the current MIDI file, use the Display Text button or click on the text below the Song Length slider. Doing either one of those things while the text window is open will close it. This makes it easy to open the window and close it right afterwards.
- Drag the Tempo slider during playback to change the speed at which the music is played. If a tempo change event occurs in the MIDI file, your tempo will be overwritten with the new tempo.
Here are the known issues with TMIDI that I'm currently aware of:
- Timing and music interruption - Since TMIDI uses its own 32-bit playback engine, implemented in user mode (as opposed to kernel mode), it is susceptible to interruptions when other processes hog the CPU completely. I set the playback thread to have the highest priority possible without being time-critical, but Windows still does not give me CPU cycles on a regular enough basis during some CPU-intensive activities. This varies on different computers and different operating systems, but generally performance should be better under NT / 2000 / XP. TMIDI does not need much CPU time, but it needs timeslices on a very regular basis since MIDI data cannot be buffered. Programs outputting wave audio data, like Winamp, have it much easier - they just need to refresh a buffer every now and then. TMIDI needs to be given some CPU cycles close to when each note should be played.
I've been interested in MIDI ever since I encountered my first MIDI file and played it on my Sound Blaster 1.0. MIDI combines my two favorite interests: computers and music. Years ago, I read the MIDI specification and tried to write a player. This was during a vacation, using Borland C++ 3.1 for DOS on a 386/25 with a Sound Blaster Pro. My first player was able to parse the MIDI file format with no trouble, but it couldn't handle the timing very well at all. The tempo was never right and tracks went out of sync like crazy. Only the simplest MIDI files sounded intelligible with my player.
TMIDI ... The First Attempt
Forward to my Pentium II/400, Sound Blaster AWE64, and Visual C++ 5.0. I'd gained some experience doing Windows programming, so I started over with the MIDI specification in hand and tried to write a player. TMIDI was born. It had only Play, Stop, and Display Analysis buttons. Unfortunately, my new playback engine was flawed. Tracks often went out of sync and most MIDI files were not played properly at all. After some unsuccessful debugging attempts I gave up, discouraged with the results.
The Catalyst ("Necessity is the mother of invention...")
One day, the MIDI player I had been using for years (WGPlayer, which comes with the Wingroove soft-synth) stopped working. In fact, my new installation of Windows 2000 stopped being able to run any 16-bit applications at all! I was unable to figure out what caused this or how to fix it, so I set out to find a new MIDI player. I had been meaning to get a new one for a while anyway - WGPlayer was old! I wanted something that gave me real control and let me see what was going on, unlike Media Player or Winamp. After trying and discarding several cheesy programs, I arrived upon one called MegaMID. It had its own playback engine and a very nice graphical display of what was being played. It showed notes, certain controller values, and more. However, some parts of its user interface were not very polished (IMO) and, while it played the vast majority of MIDI files correctly, it choked on a few of the ones in my collection. I decided that it was time to revisit TMIDI.
Return to TMIDI
I looked over my old source code and tried to figure out what had gone so horribly wrong. I quickly found that my playback engine's design was ok, I had just made a few little mistakes that were wrecking everything. Running status wasn't being implemented properly, among other things. I fixed those problems and suddenly most MIDI files started playing properly! The last major problem was that tempo changes during playback were causing tracks to go out of sync in some cases. I did some calculations and figured out how outstanding events should have their delta-times adjusted when a tempo change occurs. After that it was just a few more bug fixes and a couple days of enjoyable development to get TMIDI into a very usable state. Once the playback engine was working properly I put the various displays and controls in and refined the look and feel. Then I stopped development work and I've been using the program ever since for all of my MIDI playing needs.
For several years I used TMIDI regularly and fixed small things here and there. Every once in a while I did something big, like make controller values visible and easily editable, but the program had pretty much stabilized.
Source Code Released
I don't have a need to play MIDI files much anymore, but I still use TMIDI occasionally. Due to the occasional request, I finally got around to releasing the source code! Hopefully it's of use to people who want to do their own MIDI programming or even just a few tweaks. Note that my newer program MIDICCI contains a C++ class for MIDI I/O. TMIDI is an older program (started in 1999) which is C++ but written in the C procedural style. And it's one big source file. (I don't code like this anymore!) However, it's split up into many functions and there are many comments throughout the code. I'm also willing to answer specific questions about it, although I haven't worked on it for a few years now.
Note: I developed this using Visual C++ 6.0. You can use another compiler, but I can't answer questions about how to make it compile for you. It really shouldn't be hard to compile, since it relies only on core Win32 APIs that all Windows compilers should support, but you never know until you try...
Click the link below to download the source code:
tmidisrc.zip - 59KB, from 2003
Update: In 2014 I ported TMIDI to 64-bit Windows using Visual Studio 2013. It needed only very minor changes. You can compare the old and new source code if you're curious.
tmidisrc_2015_04_24.zip - 93KB, from 2015