Tuesday, March 31, 2009

Midi (part 4)

Today I released a new project, bmidi to wave.

It can be used to:

  • Turn midi files into great-sounding wav and mp3 files.
  • Play midi files, especially if you are unsatisfied with your current midi out quality.
  • Get information about SoundFont files and preview their voices.

You can find high quality SoundFonts online, and play each instrument in the midi with the SoundFont of your choice, resulting in the best possible sound. Use the mixer to fine-tune the volume and pan of each channel. Also, you can see a score view of notes in a particular track.

It is essentially a frontend for Timidity, the program that does the actual playback. Instead of having to edit the configuration files by hand, though, there is a gui.

This is a program I've been meaning to write for a long time. I first had the idea and initial designs in 2002, when midi files were more common. It didn't take very long to write.

Process management in Python is not too bad thanks to the subprocess module, which has a good interface. I also learned about Python threads through this project, primarily because one wants a responsive GUI while the song is playing and the time slider is moving.

Surprisingly, one of the more complicated parts of the program was allowing playback to start other places in the song. Timidity doesn't do this, and so I have to create a temporary truncated midi file for it to play. I would just chop off all events before a certain time, but because events like instrument change can occur at any time, all of the instruments would be wrong, let alone tempo and pitch bend. Tempo changes can occur at any time, and so it is not simple to correlate a midi tick with clock time.

Midi is a compact, but pretty well-designed format. Not many binary formats from 1982 are around today.

MS Paint Animation

I gave MS Paint the ability to make animations and save them as .avi files.

I wanted to write a "flipbook" program, where you could draw a series of frames and create a simple animation. I think this type of program could be fun for kids.

I was about to write the program in Pygame, but found myself re-implementing many of the standard bitmap editing tools. It's easy to make a rectangle and oval tool, but I didn't really feel like making the fill tool or selection tool. So, instead, I used MSPaint as part of the interface to the program. (This is completely a hack, and the resulting program isn't robust, but it was kind of interesting to do). See a video of how to use it - you can move from frame to frame, duplicate the current frame, and play the animation.

I'm trying to make this look like just one program. A lot is going on behind the scenes. The program is a c# app that, first, launches Paint. It has a window style that causes it to be on top of other windows. The program uses many Windows API SendKey calls to send key events to Paint. When you move from one frame to the next, it does the following:
  • Tell paint to select all (Ctrl A), and cut (Ctrl X)
  • Take that image from the clipboard and save it to a .png file
  • Open the next .png file in memory and put it in clipboard
  • Tell paint to paste (Ctrl V) and deselect (Esc)
The other operations are done with a similar series of events. I had to tune the timing; the c# program sleeps while waiting for Paint. The play preview actually opens up a borderless c# window that is positioned so that it appears above the image, and cycles through the images.

It ended up working. The Win api gives you almost too much to play with. Now I know that c# apps can send simulated keystrokes to other processes, for semi-practical purposes.

Friday, March 20, 2009


I made an arcade-style game. You have to quickly out-maneuver your enemies and push blocks to squish them.

I was influenced by an old Mac shareware game, but I've added some twists. The blocks have numbers, and if you can add to 15, it will stun your enemies and give you points.

The game is written using Pygame. I've also ported it to the One Laptop Per Child XO.

I'm going to replace the graphics and sound effects; the ones there now are essentially placeholders. I'll also rewrite some of the levels.

Download. To play it, you need a recent version of Python, and for Pygame to be installed. (Sorry, if you don't already have Pygame you'll have to get it.) Works in Windows and Linux.

When the game is more complete I'll post a Windows binary.