GameBoy Book Reader -
Midi Support

[Last Modified: 13 March 2003]

The MIDI capabilities are as follows:

  • up to 8 simultaneous voices
  • digitally sampled instrument sounds

MIDI playing is currently only available to regsistered users of Makebook, and only on the Gameboy Advance.

For a short time only, here is a quick demo ROM for GBA, containing 3 MIDIs and some pictures and text with some probable copyright violations which I suspect no-one will really object to.


How the MIDI file is added

The MIDI file is processed by Makebook to make it more suitable for playing in the Gameboy Advance.

  • It is converted into a mode 0, single track file.
  • It is retimed so that the unit of delta time is 1/60 second; the frame rate of the Gameboy Advance.
  • All events which are unused in the music engine of the Book Reader, are removed.
  • Only one instance of any given instrument is allowed in the music engine, so if a note is already on for a given instrument, a further 'Note On' event is removed. Similarly for 'Note Off'.
  • The 16 channels are checked for usage, and a guess is made as to which channel carries percussion. By default this is assumed to be channel 10, but if channel 16 is used while not have an instrument defined, it is assumed to be the percussion channel. (This can be defeated but works for most MIDI files I have found).
  • What is transferred to the book is a byte specifying the percussion channel, and a (still playable) MIDI file. This allowed the validity of the processed file to be tested by stripping it out and playing it in the PC media player. In most cases the result sounds identical to the original MIDI file.
  • A set of instrument samples is added to the 'book' if any MIDIs are to be played. Also a table mapping all the 128 MIDI instruments and 47 percussion instruments onto the (much smaller) set of available instrument samples.

How the MIDI file is played

The Book Reader music engine has been simpified, for speed reasons, to play just one track midi files. It assumes that the delta time period is 1/60 second, so that is is in synchronism with the music engine rate. The midi file is traversed at this rate and the 'Note On' and 'Note Off' commands are detected. These cause changes to an 8 voice wide array of currently playing notes. If a note is to be started, the array is searched for an unused voice. If none is found then the oldest playing note is stopped to make room.

The mixer uses this array to determine which samples to mix for the current frame. Two 304 byte buffers are used for the mixer to write to on a given frame, and another two are simultaneously being transferred to the sound FIFOs using DMA at 18157Hz. Each buffer has 4 voices mixed into it. The output of the 2 FIFOs is mixed into both left and right channel to produce a mono sound output.

This approach allows more accurate sound samples than if 8 voices were mixed into the one buffer. The original samples have to be restricted in amplitude so that adding several channels together does not cause the sum to exceed the available range. The more channels mixed together, the lower the permissible amplitude of each channel and the more distortion (digital noise) which will be produced.

The mixer is written in C, so is not particularly fast. It is completely sufficient for the Book Reader in this form. I may optimise it in assembler for something to do in the future.

Other MIDI commands which are currently processed are Set Channel Volume, and Set Tempo.


  • The available sound samples currently include Organ, Harpsichord, Strings, Trumpet, 2 drum sounds and a cymbal sound.
  • The relative sample volumes are not very consistent.
  • Note endings after release are abrupt cutoffs, rather than proper release fading (although the normal decay during a sounding [e.g. piano] note is handled properly).
  • The strings have too long an attack time, so on some pieces the strings sound like they're being played backwards.
  • The organ sample chosen was very compact, but has too little harmonic content. The result is that low frequency notes, played through the Gameboy Advance 'speaker' sound more like distortion than musical notes.

Tools available in Makebook

  • A 'play MIDI' link can be applied to selected text by selecting 'Insert link to play' from the edit menu, or clicking the 'Link to Play' icon on the toolbar.

  • To allow you to add a number of MIDI files at once, to a book (perhaps to test them) you can click on the Edit menu selection: 'Insert List of MIDI links'. This allows a multiple midi file selection, and inserts the filenames correctly marked up with links to play the appropriate files.


  • Automatic association of MIDI files with sections of the book (background music).
  • More Instrument Samples7444



Game Design Organisation


How do you arrange the components of a Gameboy Advance Game to ensure that everything gets done on time?


Here is my current view of the top level structure of a game. Please note that I have never written a game, only the Book Reader. If anyone has anything to add or suggest I am interested to hear.

  • Use the display frame rate as the basis of the game timing and organisation. This is approximately 1/60 second.
  • If making a music or sound player arrange its design such that events start or stop at this 1/60 sec rate.
  • Use 2 buffers for sound, one buffer is output to the FIFO during the frame using DMA, while the other is being prepared for the next frame (see below).
  • Use the Vertical Blanking Interrupt to control every aspect of the game progress.

During VBLANK do the following:

  • First process the DMA control for sound (switch buffers).
  • Next process anything which must be done during VBLANK (e.g. DMA copies to the screen)
  • Advance any timers which are based on counting frames (usually the best way to do timers)
  • Do music processing (filling the buffer which is not currently being output)
  • Do any game 'artificial intelligence' for as long as you don't risk hitting the next VBLANK. You can examine the current display line number to check this.

Address for comments, etc: