
Build a MIDI Synth with FlashMIDI Synthesizer RequirementsThere are several fundamental components of a MIDI software synthesizer:
Let’s take a look at how to satisfy individually the requirements of each of these components within Flash. The first thing we need is some MIDI interpretation code. Having written several MIDI interpreters over the years in a number of languages, I decided to port some old C code into ActionScript. Although the details of this implementation are beyond the scope of this article, I present the code is in its entirety within the FLA accompanying this article (737k ZIP). Those who would like to delve more deeply into the subject can order The Complete Detailed MIDI 1.0 Specification directly from the MIDI Manufacturers Association (www.midi.org). The operative point is that I was able to move all of my MIDI code from C into Flash ActionScript with minimal effort and modification. Step 1 nailed! OK, almost. We still need to get an SMF into Flash before we can use this nice new ActionScript. This is easier said than done, because Flash has very limited file I/O capabilities. We can load a SWF or JPEG into the player with the ‘loadMovie’ command, a text file containing URL-encoded name value pairs using ‘loadVariables,’ an XML file using the XML object, and an MP3 file using ‘loadSound.’ That’s it. Since there is no method within Flash to bring in and read a binary SMF, we have to convert it into ASCII, preferably in hexadecimal format. We then have to load it by hand into a Flash array. This conversion is less complicated than it sounds, and we can facilitate this process by the using external tools such as HexDump32 (a handy utility available from many places, including www.saltybrine.com/hexdump32.htm). Using such a utility and a simple text editor, we can copy the newly ASCII-fied file into our internal Flash SMF array: //Peanuts theme var SMF = new Array( 0x4D, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x06, 0x00, 0x60, 0x4D, 0x54, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x25, 0x00, 0xFF, 0x03, 0x08, 0x75, 0x6E, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x64, 0x00, 0xFF, 0x58, 0x04, 0x04, 0x02, 0x18, 0x08, 0x00, 0xFF, 0x59, 0x02, 0x00, 0x00, ); Step 2 determines what digital audio sounds are going to be used for each MIDI note and channel combination in the score. External to Flash, it is necessary to prepare one file for each of these combinations, and then import all those sounds into the project library. Now you may be thinking with 16 MIDI channels and 128 notes per channel, that’s over 2000 sounds! Relax. Breathe. That’s the potential upper limit, and we’re only talking about the note and channel combinations present in the SMF. Remember that Flash can only play up to 8 sounds simultaneously. While this may seem limiting, there’s a lot of meaningful music to be made within this restriction. Unless you’re trying to cram a whole commercial sound set into this engine, you can do a lot with only tens of sounds. Complex scores with multiple patches and several patch changes could run into the hundreds of sounds. So it’s not that bad. All of the sounds should be at the same bit-depth and sampling rate. This requirement insures that the Flash Player won’t have to spend any unnecessary cycles doing sample-rate conversion at playback time. The second requirement is that we have to pad all sounds with 10 mS of silence at the head. I’ll explain why we need to do this later when we talk about timing issues. But for now, the reason is, ‘Because I said so.’ Don’t forget the silence pad. Once we prepare all of the note sounds, we can import them into the Flash project library. Critical for music is the ability to turn notes on and off independently. To get this level of control within Flash, we have to create an empty movie clip for each of the sounds we just imported. Note that this is not the same as the number of notes in the score, because we may re-use the same note over the course of the piece. We create a new Sound object for each pitch, specifying the movie clip instance on which that Sound object will operate: var note0032 = new Sound(emptymc0); Next, it is necessary to set the linkage properties for each of the imported sounds. Within the ‘Linkage Properties’ window, select ‘Export for ActionScript’ and ‘Export in first frame.’ Then set the identifier field for that sound, hereafter known as the ‘idName’ parameter of the sound. Finally, we attach each sound from the library to one of these Sound objects using the ‘attachSound’ method and the sound’s ‘idName’ parameter. Below is an example of the naming standard I used for samples in the library and Sound object note names:
note0032.attachSound("pnoG#2");
As you can see, I’ve adopted a standard of identifying the channel and note number within the name of the Sound objects. The idName I chose for each sample indicates its instrument type and pitch, the pno meaning piano and G#2 meaning the G# from Octave 2. While this is not absolutely necessary, such naming conventions can help to avoid confusion in a movie where there are hundreds of sounds to keep track of. |
Sonify.org is a community resource where Developers can unite with the common goals of adding interactive audio to the Web, Wireless and Digital Devices as well as advancing the development of the underlying interactive audio technologies. Read more. |
![]() ![]() |
![]() ![]() |