The Sound Of Music

FreeBASIC is a great language for informal messing around. In two lines of code, you can be drawing graphics in full-color 1080p. Now that FBC supports compiling for x64, you can allocate ridiculous size arrays using as much memory as you have available.

It’s the ideal modern back-of-the-envelope prototype language for those of us who grew up on BASICA, Tandy BASIC, and QBasic/QuickBasic. But as with most reboots of beloved childhood franchises, a few things seem to be missing.

Playing music, for one, was very easy back in the days of BASIC. Most languages included a “play” keyword that could be called to play various notes. Type something like “play cdefg” and you could make the speaker produce a simple scale.

FreeBasic, unfortunately, doesn’t have the “play” keyword (though, oddly, WinFBE still flags it as a keyword.) FreeBasic is cross-platform, being available for Windows, DOS, and Linux — and so hardware-specific things like speaker support weren’t included.

Fortunately, however, there’s a workaround that ends up being a significant upgrade. Windows provides various APIs that can be used by programs to request functionality from the OS. One of these is the ability to emulate General MIDI instruments, and to accept commands for these from programs. With a little setup, FreeBasic can have access to all of Windows’ General MIDI capabilities.

So now, instead of commanding simple beep melodies, we can produce almost-performance-quality music. The API is even relatively easy to set up once you know the right commands — and this is where Google helps immensely. After a brief search, I found an example by FreeBasic.net user “Mihail_B” that shows how to get Windows to play a couple of percussion samples via MIDI.

A quick look at the MIDI specification helped decode what was happening. For each note played, a MIDI “note on” command is sent. One of the relevant lines of code is:

midiOutShortMsg1(midihandle,&h403f90)

This calls the “midiOutShortMsg1” wrapper to the midiOutShortMsg() function provided by Windows. (See the code example above for the supporting API calls — there’s some setup needed.) The information as to what to play is contained in the three hex bytes at the end: 40, 3f, and 90.

Breaking these down, the “90” is the status byte, the “3f” is the note number, and “40” is the velocity. The first four bits of the status byte (the “9”) tell us that this is a Note On command, and the second four bits (the “0”) tell us that this command is being sent to MIDI channel zero.

The “3f” is the note number — decimal 63, where the notes are numbered from 0 to 127 with 60 being middle c. So note 63 (3f in hex) is three half-steps above Middle C, or D#4.

Finally, the “40” is the note-on velocity. This translates to 64 in decimal, which is halfway up the velocity scale (and the default velocity sent by keyboards and other instruments which don’t record velocity information.) A good electronic piano would send varying velocity information with the note commands; a harpsichord, which doesn’t have key-velocity dynamics, would probably just send 64 with each note.

With this understanding, a wrapper function can be written to play notes more easily. The FreeBasic code linked below (a spinoff using key pieces of the code linked above) implements the “playNote()” and “stopNote()” functions. Both take (note, velocity, channel) as arguments.

So, once MIDI is initialized and the instrument patch is selected (the default is grand piano), playing middle C is as simple as:

playNote(60, 64, 0)

It’s good MIDI practice to turn the notes off, as well. With patches like the grand piano, it may not matter much, since most instruments will automatically silence the oldest notes as needed if given more to play. But with other patches (pipe organ, violin, etc) which can play continuously, it becomes very important. Sending a Note Off command or a Note On with velocity zero will silence the selected note.

Here is a quick chord demo, easily modified to play whatever notes you like once you know the MIDI note numbers. Share and enjoy!

This entry was posted in BASIC, Coding, HOW-TO, Music and tagged , , , , , , , , . Bookmark the permalink.

Leave a Reply