minYMising
Shrinking your music driver data structures
In the 'goode olde dayes' almost every chipper had their own sound driver
- coded in assembler and hand optimised for each individual song or demo.
Whatever your views on this we must accept that these days are gone and most
chippers are using whatever sound driver and data structures their favourite
editor gives them. So sadly we have moved from being chip specialists into being
editor specialists.
Perhaps you want to take the next step from using editors to coding your own
sound driver, and really hit the YM hard - its not that complicated for raw YM
playback without timer effects... easier than you might believe, and it will be
a fun learning experience. Think of the satisfaction of making a tune with your
own codez! What is a massive pain in the backside though is taking the next step
and making an editor to go round this sound driver ;)
Anyway, heres some hints on ways to store your data if you do decide to
experiment with your own driver, or maybe if your just interested in this kind
of discussion.
Of course theres millions of ways to store the music data for your driver. But
we can broadly catagorise them into four groups which trade off speed for file
size, the ease of composition, and possible YM effects. Lets deal with them in
order of size efficiency:
Method One
eg .YM format
This is without question the fastest method to replay. The complete status of
the soundchip registers relevant to audio (14 for YM2149) is stored for each
time the sound driver is called, which is most usually 50Hz. But it has many
disadvantages, not least the huge amount of memory needed to store all the data.
This makes it suitable for smaller songs, or medium sized songs when combined
with some packing methods. The speed of this methods comes from the fact that as
the status of all registers is known, just some minimal calculations need to be
performed (for example buzzer waveform register). Strange as it may seem, a
number of YM effects cannot be captured with this approach, although it could
concievably be extended to include some timer based effects.
Obviously this method is pretty unfriendly to the composer (just imagine
deciding the state of all 14 YM registers 20 times a second!), but its possible
to easily record the status of the YM registers into this type of format from
any music player.
Method Two
eg ProTracker, SID Sound Designer
Although method two has a considerably smaller file size than the first, in my
opinion its still a little bloated, many composers like to work this way and its
supported by most editors. It means splitting your music up into a 1 dimensional
sequence of 4 bar patterns. Each pattern contains the music data for all
channels. I'm sure we've all used an editor like this at one time. As any
musician will tell you, the tracks in each pattern might be duplicated many
times throughout the song - so this method already has a great deal of data
redundancy.
If this data struture is used in something like a sample tracker then you might
say that the file size advantage of using a smaller data structure is not worth
the extra effort as your samples are already taking up alot of space... we all
have at least half a megabyte of RAM to play with anyway ;) But a chip musician
has all their sounds defined by small data structures, and the size of the music
data is often larger than the insruments.... Also I think its fair to say
chippers have a historic sense of pride at small music formats ;) So how can we
improve?
Method Three
eg XLR8, Magic Synth
Despite significantly reduced file size and some advantages to the composer,
this method is sadly not so common with Atari ST chip trackers these days. Here
the music is split up into a 2 dimensional sequence of patterns (number of
channels * song length), with each pattern containing music data for a single
channel only. As things like drum patterns and chord progressions need to
entered only once its easy to reduce data redundancy... not to mention composing
effort ;)
Method Four
eg Rob Hubbard
Methods 2 and 3 have one thing in common - many zeros thoughout the data
structures which suck file size. Even though we have packers to remove these
zeros we can still save bytes in memory with an alternative scheme.
Usually trackers leave blank space when there are no events, this makes things
easier to edit but it uses up needless space. To eliminate the need for this
classic chip musicians recorded each note with a length byte or nibble.
Earx/Lineout noted to me that this is equivalent to a form of basic run length
encoding to remove the unused zeros, although I'm sure Rob and friends didn't
regard it in this way.
This encoding can be taken steps further. Instead of recording always patterns
with fixed length its possible to have varible length patterns, even one bar or
less in length, and loop these repeatedly in the song list. Varible length
patterns however lead to an asynchronous song list, which can again be difficult
to work with, and its not so encouraging to program small fills and changes to
riffs and drum loops.
As you can see, options to reduce music filesize now starts to impose limits on
our creativity ;) Also usual is applying modify options to the patterns in the
song list, for example transpose and volume adjustment. Transpose is one with
interesting implications, and encourages songs in unusual keys, and octave
bassline sequences. These kinds of limitations definately lead to a special
style of composition (listen to any early c64 tune). Although I'd like to
compose tracks using data structures of these types, its not something I'd like
to do often, after being pampered by todays memory sucking trackers ;)
As you can probably see its pretty straight forward to convert method 3 to
include some advantages from these ideas and even the driver change is not as
complicated as you might think.... you might even save some CPU ;) In fact
variations on this kind of conversion have been done in the past by many chip
musicians, for example Tao or Mad Max.
Gareth Morris/gwEm, Jan 2005
|