How To Write ZX Spectrum Games – Chapter 3

Loudspeaker Sound Effects

Note: This article was originally written by Jonathan Cauldwell and is reproduced here with permission.

The Loudspeaker

There are two ways of generating sound and music on the ZX Spectrum, the best and most complicated of which is via the AY38912 sound chip in the 128K models. This method is described in detail in a later chapter, but for now we will concern ourselves with the 48K loudspeaker. Simple it may be, but this method does have its uses especially for short sharp sound effects during games.

Beep

First of all we need to know how to produce a beep of a certain pitch and duration, and the Sinclair ROM has a fairly accessible routine to do the job for us at address 949, all that is required is to pass the parameters for pitch in the HL register pair and duration in DE, call 949 and we get an appropriate “beep”.

Alas, the way in which we work out the parameters required is a little tricky as it needs a little calculation. We need to know the Hertz value for the frequency of note to emit, essentially just the number of times the loudspeaker needs to be toggled each second to produce the desired pitch. A suitable table is located below (# stands for ‘sharp’):

Middle C 261.63

C# 277.18

D 293.66

D# 311.13

E 329.63

F 349.23

F# 369.99

G 392.00

G# 415.30

A 440.00

A# 466.16

B 493.88

For each octave higher, simply double the frequency, to go an octave lower halve it. For example, to produce a note C one octave higher than middle C we take the value for Middle C – 261.63, and double it to 523.26.

Once the frequency is established we multiply it by the number of seconds required and pass this to the ROM routine in the DE register pair as the duration – so to play the note at middle C for one tenth of a second the duration required would be 261.63 * 0.1 = 26. The pitch is worked out by first dividing the 437500 by the frequency, subtracting 30.125 and passing the result in the HL registers. For middle C this would mean a value of 437500 / 261.63 – 30.125 = 1642.

In other words:

DE = Duration = Frequency * Seconds

HL = Pitch = 437500 / Frequency – 30.125

So to play note G# one octave above that of middle C for one quarter of one second:

Have a play with the above routine – by fiddling with it it’s pretty easy to adjust the pitch up and down, and to change the starting frequency and pitch bend and length producing a number of interesting effects. One word of warning though – Don’t go too crazy with your pitch or duration values or the beeper routine will get stuck and you won’t be able to regain control of your Spectrum without resetting it.

White Noise

When using the loudspeaker we don’t even have to stick with the routines in the ROM, it is easy enough to write our own sound effects routines, especially if we want to generate white noise for crashes and bangs. White noise is usually a lot more fun to play with.

To generate white noise all we need is a quick and simple random number generator (a Fibonacci sequence might work, but I’d recommend stepping a pointer through the first 8K of ROM and fetching the byte at each location to get a reasonably random 8-bit number). Then write this value to port 254. Remember this port also controls the border colour so if you don’t want a striped multicolour border effect we need to mask off the border bits with AND 248 and add the number for the border colour we want (1 for blue, 2 for red etc.) before performing an OUT (254) instruction. When we’ve done this we need to put in a small delay loop (short for high pitch, long for lower pitch) and repeat the process a few hundred times. This will give us a nice “crash” effect.