42

Some time ago I found that the audio of a game called Ninja Gaiden 1 (NES) is around 1 hour. This is excluding the sound effects like jump and hit e.t.c. Then I found that the entire game size is actually quite small and the sound data is not stored as actual sound samples. Rather, it is stored as "instructions to a sound chip". Which is quite strange.

  1. How precisely was game music stored during the 8-bit console era that made it possible to store so much music without exceeding even 1MB of space in hardware!? I have heard that the sound data was stored as the note and duration for which it should be run. I am not aware of any hadware IC that I can use to learn more or any game code example to learn how it was programmed in the game code.

  2. If compression was used, what type of compression would that be?

  3. What are some examples of the most basic and most advanced "sound chips" that were used in those times?

8
  • 4
    Just a link is not an answer, so I'll leave this link here: en.wikipedia.org/wiki/General_Instrument_AY-3-8910
    – Leo B.
    Apr 5, 2020 at 23:35
  • 1
    Welcome to the site, and welcome @user17738 too (please do choose a username!). I converted your answer to a comment as it got flagged and it seems the better format for it.
    – Matt Lacey
    Apr 6, 2020 at 6:39
  • 7
    "Which is quite strange." why do you think that? I think you should check out the demoscene - it's still around even if it's nowhere near as big as it was - to see what people can cram into as small a space as possible :-) pouet.net and scene.org (currently being redone)
    – Aaron F
    Apr 6, 2020 at 7:47
  • 4
    8-Bit Guy has an episode on Oldschool Sound/Music you might enjoy: youtu.be/q_3d1x2VPxk Apr 6, 2020 at 13:48
  • 1
    While not exactly music, this video gives an extremely in-depth and technical look at how the sounds in pokemon are stored and reproduced. Apr 6, 2020 at 14:06

6 Answers 6

55

As you already say, it was stored as "instructions to a sound chip". So it's not a simple blob of data for DA-converters, but a procedural storage.

Think of it like music notes. Imagine someone playing a piano he doesn't need to hit some 44,000 keys per second but anywhere between two and eight, each with a certain duration and velocity and later release them again.

For playing (electronic) music instruments a protocol called MIDI was devised, using three byte packets to start and stop each note: channel address, note and pitch/release. A piece like Ode to Joy can, leaving out bells and whistles, be played with data as low as two bytes per second. So an hour of non repetitive music can be stored in as low as 8 KiB. Not really much. Of course, for a nice result one would use multiple channels and use instrument specific envelopes. Still, the result will be way less than 100 KiB for a hour of music.

In fact, MIDI is a good benchmark for bandwidth needed as a single 31.25 kbit/s (~3 KiB/s) interface is good for up to 500 notes per second - that's sufficient to play any actual band all the way to a reasonable sized orchestra.

Storing music as notes is in itself already a kind of compression. In addition, music is usually repetitive, so it's easy to structure the data needed like a program with loops and subroutines. Which again acts as further compression - application specific encoding often beats generic compression by far as it can use higher level of abstraction than simple data streams.

Of course, using a high level encoding like musical notes does require a processing level to turn them into commands for sound chips/processors. How much effort to be put here depends a lot on the chips used as well as the kind of sound desired. Essentially it's like implementing a synthesizer for Midi. At that level sound samples may as well be used to create output. Such a sample can again be quite small, as it just has to describe a certain wave form and envelope, that can be used to generate any tone.

Even rather complex musical instrument handling can be done in a few KiB of code and data.

Asking for spec ranges of sound hardware is rather fruitless, as it literally ranged from speakers that simply could be clicked on and off (like in the Apple II) and still being able to play multiple channels, all the way to MIDI controlled synthesizers like the Roland MPU-401. Also, as shown, with a sufficient sophisticated music generation software, the chip used becomes irrelevant for the amount of data needed to play. It only defines the playback quality.

7
  • 6
    MIDI is a great example to illustrate the concept, but I'm thinking that MIDI (and especially, MIDI interfaces for general-purpose computers) must have come along a few years later than the earliest home computer/game console "sound chips" such as the 6581 SID, mentioned in @retrograde's answer. Apr 6, 2020 at 0:34
  • 4
    @SolomonSlow MIDI is about as old as the C64 - I remember having an MPU-401 with my Apple II ca. 1984 or 85 (also sound chips go back into the mid 1970s). But more important, this is about explaining the way how musical data can and has be used to create great sound with a small amount of primary data instead of brute force recording. All methods described are independent of MIDI logic or hardware. I tried to describe the workings without diving deep into very specific hardware - after all, the chip is irrelevant for the method used for encoding/handling.
    – Raffzahn
    Apr 6, 2020 at 1:17
  • 3
    In addition to the "compression" aspects mentioned above, it's also the case that MIDI data (or any data similar to it, such as would have been used by all games that predate the MIDI spec, and many that came after) is highly compressible itself. Even a simple Huffman coding would work well, as would other compression techniques available at the time. Whether they bothered, I don't know...but it would've allowed for music data to be stored in even less space very efficiently. Apr 6, 2020 at 7:23
  • 1
    As far as sound hardware goes, there was even the TRS-80 Models I and III, which didn't have any sound hardware per se, but still had programs that manipulated the RF emissions and played music through a nearby AM radio tuned appropriately. In later years, hardware did play more of a part, as elements of the music playback were incorporated into hardware instead of software. But you're right...the exact hardware doesn't have much to do with "how was this possible?" Apr 6, 2020 at 7:24
  • 1
    For what it's worth, I've worked with a device that takes pitch and duration for a beep as two two-byte values, and converted the Mario and Zelda themes from MIDI to play on it. It only supports one channel (because that particular command blocks until the sound is done playing), but it worked surprisingly well.
    – Bobson
    Apr 6, 2020 at 21:45
27

You can think of the sound chip in devices such as this as a simple synthesizer, capable of emitting some basic waveforms at some designated frequency.

Capabilities of these devices varied in the 8-bit era, fx on number of simultaneous voices, available waveforms, hardware envelopes, filters and special modulation techniques (such as ring modulation and later, entering into the 16-bit era, amplitude and frequency modulation). One end of the spectrum having only simple square wave and/or noise capabilities (fx the venerable AY-3-8910) to something like the 6581 SID of C64 fame, which has a much wider range of waveforms, ADSR envelopes, ring modulation, custom duty cycle and programmable filters.

A sound track on these machines is basically a program running that continuously modulates the parameters of the sound chip, setting the frequencies of the notes and changing the available parameters to influence the sound generation with a richer sound as a result.

Typically, music was stored as tables for that program (you can kind of regard the player as an interpreter), representing notes and instruments and modulation commands. Some sound chips could play a limited form of digital samples as well; these are also tables of amplitudes over time but take up a lot more resources and was typically used sparsely.

While not typically compressed in the usual sense, table data/commands were often optimized to squeeze as much information into a byte as possible, with parameters only taking up a limited number of bits. Sound parameters were bundled up into instruments so that they could be reused without repeating the sound parameters over and over again, and the music itself was generally organized into tracks of patterns, where commands often existed to repeat and/or transpose a pattern, such that it could be reused and repeated without taking up much additional space. Using this technique, long pieces of music can be made that takes up relatively little space.

Composers of the time worked directly with these low level abstractions, sometimes programming the music directly in assembler, sometimes using specialised software to do so. Over time, patterns for getting richer sound evolved, such as using arpeggios, vibrato and dynamically changing waveforms and duty cycle to get richer harmonic content.

My description here is rooted in having written such music routines and music myself, mainly for the C64, but the same general principle applies to other sound devices of the era - right up to the OPL FM chips that were still found on SoundBlaster-family cards much, much later.

1
  • Some platforms and playback routines imposed "interesting" requirements upon what could be done musically, and composers had to work within such limitations. For example, Toyshop Trouble has 64 measures of of "happy" music and the same amount of "sad" music, but only 20 bytes of pitch data, and somewhere around 200 bytes of rhythm data.
    – supercat
    Apr 6, 2020 at 16:47
6

Here's an example program from the C64 Programmer's Reference Guide that plays a tune. It works by writing values to specific memory locations, which are mapped to the SID chip. You might want to get a C64 emulator and type it in yourself:

5 S=54272                              sound registers start at S
10 FOR L=S to S+24:POKE L,0:NEXT       clear sound registers
20 POKE S+5,9:POKE S+6,0               set ADSR
30 POKE S+24,15                        set volume to max
40 READ HF,LF,DR                       read values HF,LF and DR from the DATA part
50 IF HF<0 THEN END                    quit on negative number
60 POKE S+1,HF:POKE S,LF               write to frequency registers
70 POKE S+4,33                         play note
80 FOR T=1 TO DR:NEXT                  wait
90 POKE S+4,32:FOR T=1 TO 50:NEXT      release note and wait
100 GOTO 40                            keep going
110 DATA 25,177,250,28,214,250
120 DATA 25,177,250,25,177,250
130 DATA 25,177,250,28,214,250
140 DATA 32,94,750,25,177,250
150 DATA 28,214,250,19,63,250
160 DATA 19,63,250,19,63,250
170 DATA 21,154,63,24,63,63
180 DATA 25,177,250,24,63,125
190 DATA 19,63,250,-1,-1,-1

That's three values per note, and all but one value is small enough to fit in a single byte. That's two bytes (a 16 bit value) for the frequency and one to specify the duration of the note.

For an actual product, it would also be necessary to specify the time between notes. So with this very simple encoding scheme, we need 4 bytes per note, which is quite economical.

Of course, we need a format that can alter the other registers on the SID chip, so we have some variety in the sounds we are producing. We can do this in a reasonably economical fashion by dividing the notes into sections of a bar or two. Each section would then have a list of notes and a list of register writes to perform before playing it.

The C code (though we would write this in assembler) might look something like this:

struct note{
    char delay;
    char frequency_high;
    char frequency_low;
    char duration;
};

struct sid_write{
    char offset;
    char value;
};

struct section{
    note* notes;
    sid_write* setup;
};

A nifty side effect of this format is that our arrays of notes and sid_writes can be reused. If the same few bars are repeated all over the piece, it only uses up a section for each case, which is just 4 bytes. And if many different sections use the same sound, they can use the same array of sid_writes.

This format is just an example, but you can see how easy it is to describe an 8 bit tune with a tiny amount of memory, especially if there is a lot of repetition. And 8 bit music generally has a lot of repetition.

If compression was used, what type of compression would that be?

Apart from the above, not much. Something like a Huffman decoder would itself require precious memory and music files were only a few kilobytes.

Because loading on a C64 was painfully slow, there might be some compression used on the whole program to speed up loading, but nothing specific to the sound files.

On a console like the NES, there would only be a tiny amount of memory to decompress the music into, and there would be far more important uses for that memory. It would therefore have to reside on the cartridge in a format that could be easily read while the game was running.

2
  • Including the short program is a great idea, and really makes for a nice answer, Good One!
    – Kingsley
    Apr 8, 2020 at 0:05
  • Isn't there a typo in line 80? I think there should be a colon : between DR and NEXT.
    – Schmuddi
    Apr 9, 2020 at 12:31
5

Music in the 8-bit era was mainly stored like in the MIDI file: tone pitch, tone length, effects, drums. A lot of "music routines" allow writing music like a program: with "subroutines", "parameters", "loops" etc. The principle is mainly the same for the ZX Spectrum's beeper or the ZXS128's AY-3-8910 music, or the C64 SID music, or ATARI's POKEY... Just a routine and a "tune data".

Later came the "pattern-based" routines, i.e. music organized in the form as MODs (from different XxTrackers on Amiga and PC) - I remember a program called "SoundTracker" for ZXS128.

So long story short: No sampling in those days. Just simple tones and noises and basic effects did all that "chiptune" era feeling. No compression was needed, or better say: it was "procedural compression", based on the fact that music is full of repeating...

The most used sound chips were AY-3-8910/8912 (ZXS128, MSX, etc. - Yamaha made nearly the same chip, labeled YM2149), Commodore SID (6581/6582/8580), Atari POKEY (not only sound), Texas Instruments SN76489 or Philips SAA1099.

1
  • Music data of 8-bit playroutines is pattern based too, but individual patterns for each track, and some playroutines even allow transposition so you can reuse the timing and relative pitch information of the note sequence snippets. It's a lot more musical and efficient way to store music data than MOD which is a rather dumb format in comparison. Apr 7, 2020 at 21:20
0

Wow, so many blast-from-the-past terms here! In terms of the "what chip was top-dog" in "computer sound module" terms it was likely the Amiga chipset (can't remember which lady's name was the sound module).
To simplify the entire discussion, any old-school (non-sampler) synthesizer, is nothing but a dedicated computer sound module. Most old (early 80s) synths that were digital, in fact had tiny memories (if they were programmable). In most cases, you had to overwrite existing patches with new ones in fact (after backing up the factory sound patches if they weren't backed up in ROM). Yet from synthesizers that had much less computing capacity and storage than most watches today, came all the soundtracks for movies, music, etc. "Blinded me with Science" or AxelF (Beverly Hills Cop theme), the synths likely had a total of 16-64kb in total for all parts of the entire compositions. It was (as mentioned in some fashion by others) the mixing and "playing" of the sounds that made them interesting.
Obviously music synths have more hardware (analog or digital) to process, filter, combine, etc the base sounds, but even an original IBM-PC (or TRS, etc) had only an internal speaker with a "beep" sound by default. But if you cycle that "beep" at a certain pulse rate, frequency, etc, you can make it "sound" like something. In fact, early "Speech synthesizers" for C-64, and I believe IBM and a few others, could actually overdrive the A/D converters in the sound generation path, to "synthesize" voices, even though there was zero sample storage for a voice. (This trick in some cases depended on how old your system was, as chip designers often would "clean up" their designs over the years removing the ability to exceed bounds, etc). Tap on a sheet of metal. It sounds like a metallic tap. Now "wave" that sheet of metal... it can sound like a thunderstorm, bang on the edge of it, sounds like a car crash, it's all about how you modulate the basics that gives character, even with a mono-channel, single waveform ("beep" is often nothing more than a square wave, as it's dirt-simple to make with an R/C circuit). Take a square wave with adjustable frequency, now you can make music. Take the square wave generator, cycle it on/off at programmed pulses, now it's got variety (FM synthesis (the original soundblaster soundcards, based on the Yamaha DX-11/21/TX81Z/etc series music synthesizer modules, were built around 4 "waveform" oscillators (square, sawtooth, sine, triangle, I believe from memory) and, with some filters (LFO) and envelope generators to modify them, was the basis for "PC soundcards" (Apple/Mac, Atari, and Amiga were far beyond them capability wise) for many years (used to own a DX-21 keyboard myself, loved that synth even though it was "basic" and was supplanted by more powerful ones, still enjoyed the sounds I could get out of basic FM synthesis.) Here is how a basic PC speaker (single waveform, modulated by a timing chip basically) made sounds for many years (thanks Wikipedia)... https://en.wikipedia.org/wiki/PC_speaker

0

Several answers have already noted how little information it takes to instruct a sound chip. There's another factor here: how little music the chip is really making. What I mean by that is there were very few hardware "voices". This was of course due to hardware limitations, but it also reduced how much data was used per second to create music.

How did they sound like they had far more voices than they did? The short answer is rapidly switching what each voice did, so that in a few seconds a human ear hears far more variety than the voices can simultaneously support. This video explains it in detail.

The same channel has similar videos on how graphics were kept small. In understanding any of these videos, bear in mind this was as much about requiring little RAM as requiring little storage.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .