Rollercoaster Sounds Owen and Audrey Bishop ride the ups and downs of glissando synthesis in a bid to improve the quality of Spectrum sound effects. The Spectrum has always lacked really good sound facilities such as are available on the Amstrad, the BBC micro, and particularly the CBM64. Although the sound chip of the 128 Spectrum offers its owners much more than the pathetic BEEP of the Spectrum 48 and Spectrum+, it is deficient in one essential feature, a tone envelope. By that we mean that it should be possible to vary the tone - or pitch - of a note while it is sounding. Notes which slide up or down in pitch, and possibly up and down again, are what we refer to as rollercoaster sounds. Musicians call this effect glissando. Examples include police sirens, the sound of falling bombs or the ricochet of bullets. If you are writing a games program which requires sound effects of this type, you find that the 128 PLAY command is satisfactory for generating triumphant little jingles to reward the winning player but virtually useless for producing the sound effects. No matter how hard you try, the sound which is supposed to be a siren emerges as a series of individual notes in upward and downward scales. Gliss is the name we have given to a short machine code routine, only 56 bytes long, which you can use to produce glissando - or rollercoaster - sounds on your Spectrum. It works equally well on 48K and 128K machines. Whether you are a games programmer or not, the program is fun but warn other members of your family to wear earplugs while you try it. When it is producing a sound effect, the Gliss routine uses a block of memory which we refer to as a period table. It contains a series of numbers which determine the period - length of time - of successive sound waves. Think of Gliss as a tape-player and the period table as the tape which Gliss plays. Figure one shows how the numbers in the table affect the sound produced. If all the numbers in the period table are equal, each sound wave has the same period and we obtain a sound of constant pitch. That gives a steady note similar to an ordinary BEEP. ___________________________________________________________ constant period -> constant pitch Figure ___ ___ ___ ___ ___ ___ 1 (a) 10 |10 |10 |10 |10 |10 |10 |10 |10 |10 |10 |___| |___| |___| |___| |___| ___________________________________________________________ If the first number is small and successive numbers are larger, the note has increasing period. That gives decreas- ing pitch. The pitch slides smoothly downward, as in the sound of a falling bomb. ___________________________________________________________ increasing period -> falling pitch Figure _ _ __ ___ ____ _____ ______ 1 (b) 1||3|4| 5| 6| 7 | 8 | 9 | 10 | 11 | 12 | 13 || |_| |__| |___| |____| |_____| ___________________________________________________________ A rising pitch is obtained by starting with a large number - not more than 255, as it has to be stored in a single byte - followed by progressively decreasing numbers. Using this principle, it is possible to create a period table to give the required effect. ___________________________________________________________ decreasing period -> rising pitch Figure ________ ______ ____ __ ___ 1 (c) 40 | 35 | 30 | 25 | 20 | 15|10|5| |_______| |_____| |___| |_| ___________________________________________________________ The Basic demonstration program Roller [which is on the .tzx which should accompany this text file under that name] has the code for Gliss in the form of data statements - lines 200-210. Type-in those numbers with care. When the program is run, lines 10 to 30 clear memory space to hold the period table and the machine code and put the code into memory ready for use. Those familiar with the Spectrum memory map will realise that the code has been located just below the region where the user-defined graphics are usually stored. Below the code, 1,000 bytes are set aside for the period table. Thus there still is plenty of room for your own games program. When using your program, use Roller as a guide to program- ming the sound effects. Lines 40 to 60 illustrate an easy way of generating a period table. This one puts the values 0 to 254 in succes- sive bytes of a period table 255 bytes long. That should give a descending screech when run. It is a good imitation of the sound of a ricochet. It is how we obtained the ricochet sound in the battle sequences of our wargame Gallipoli - CCS, 1986. As we shall see later, there are many other variations on lines 40 to 60, giving other types of sound. Lines 80 and 90 tell Gliss the length of the period table - count is the number of bytes in the table, 255 in this case. The address in memory at which the table starts is Start. Line 100 calls Gliss and the sound is produced. It makes the sound only once but you can add these lines to the program to make it repeat: 95 FOR j=1 TO 20 and 105 NEXT J It is a short step from the foregoing to a realistic police siren sound. Alter line 50 to: 50 POKE 65056+j,255-j and add the looping lines 95 and 105 listed. [Although it would probably be most instructive to do this yourself, for the lazy among you I've put this on the .tzx as "Siren".] The more mathematically inclined will leap at the chance of devising other ways of setting up the period table. The main point to remember is that the values poked into the table must be in the range 0 to 255. Negatives are not allowed. This line makes use of one of the Spectrum Basic func- tions: 50 POKE 65056+j,5*LN (j+1) The 'j+1' is necessary because the LN function does not accept zero as an argument. This sound gives a high-pitched tweet which, if repeated in a FOR...NEXT loop, sounds like a chattering bird-song. [On the .tzx as "tweet".] Having started on functions, what kind of effects can you obtain using SIN, COS, TAN or EXP? The first two always give values between -1 and +1, so it is essential to get rid of the negative sign and also to use a multiplier to obtain values in the range of, say, 40 to 230. Try this one: 50 POKE 65056+j,INT (150+90*SIN (j*.0246)) The call of the nocturnal Spectrum hacker to its mate? [Maybe... so it's on the .tzx as "MatingCall".] Now try playing with the values in the expression and see what effect that has. With such expressions, generating the period table may take an appreciable time. Note that once the period table has been generated and the POKEs for the routine have been done, there is no need to re-run Roller every time. The sound can be repeated by typing GO TO 100. The longer the period table, the longer the duration of the sound. The Basic program sets aside 1,000 bytes, of which we have used only 255 so far. It is a simple matter to amend the program so that we use all 1,000 bytes: 40 FOR j=0 to 999 50 POKE 64312+j,INT (ABS (j-500)/2) This pokes values starting from 250, falling to zero and then rising again to 249. Alter lines 80 and 90 to make count equal to 1000 and start equal to 64312. Can you pre- dict what the sound will be? Try it. [Called "1000".] With 1,000 bytes to play with, there is room to build more complex sequences of sounds. Pitch can be made to rise sharply, then fall slowly, and finally rise to its highest at the end of the sound. You can do that by using different FOR...NEXT loops for each section of the sound. If 1,000 bytes is not sufficient, set RAMTOP lower, to clear more space in memory. You can also use the 1,000 or more bytes to store the tables of several shorter sounds. In that way you can store all the sounds needed by a given games program and produce any one of those as required by setting count and start to appropriate values before calling the routine. With the 48K Spectrum there is a limit to how many sounds can conveniently be held in memory, especially if the game program is long. With the 128K Spectrum, that is no problem. Set aside, say, 1,000 bytes of main memory as a period table area and then use the overlay technique des- cribed last month. Period tables are stored in RAMdisc as binary files and called down into the period table of the main memory, using LOAD!, when required. Most sounds do not consist of a single note but of several notes of different pitch sounds simultaneously. In musical terms, the fundamental is accompanied by a number of harmonics. It is the presence or absence of the harmonics and the relative strengths of those present which allows us to distinguish the sound of a violin from that of an oboe. The effect of the combined sound of the fundamental and its harmonics is to produce a complex soundwave, as shown in figure two. [Alas, figure two is too complex to repre- sent in ASCII art. It was also rather sloppily drawn, so a .pgn would not be worth the trouble. Fret not, though, dear reader: I've written a little program which shows such a complex waveform on your Spectrum screen, and put it at the end of the .tzx under the name of "Figure 2".] Although the sound generated by this routine has an approximately square waveform, we can approximate to a com- plex sound by setting up the period table with a repeated sequence of numbers. The following line generates the simple sequence '125, 150, 125, 150, 125, 150...': 50 POKE 65056+j,125+50*(j/2-INT (j/2)) When j is even, j/2 equals INT (j/2), so the expression has the value 125+50*0 = 125. When j is odd, it has the value 125+50*.5 = 150. The effect is a complex sound which is similar to a ringing bell. If you put this into a FOR... NEXT loop, the telephone begins to ring. Now program it to make the characteristic British Telecom ring-ring... ring- ring. [This one is called "Ring".] Another approach is to let the routine operate on a random set of numbers. The Basic interpreter program of the Spectrum ROM is, in effect, a random series - apologies to those who wrote it. So omit lines 40 and 60 and set the start to 0 or some other address in the ROM area, 0 to 16384. The sound is a hiss, that caused by an exploding grenade. ["Grenade".] If you require different kinds of random noise for diffe- rent sound effects, you will need to generate your own random table. The result depends on the range of numbers in the table. This line, used to generate a table of 1,000 bytes starting at 64312, produces random numbers between 50 and 150 ["Random 1"]: 50 POKE 64312+j,50+INT (RND*101) Compare the sound of that table with this one, in which the random numbers are between 200 and 250 ["Random 2"]: 50 POKE 64312+j,200+INT (RND*51) You may have noticed that we have not explained previously the action of line 70, though you probably will have noticed that the border of the screen changes colour when the program is run. It flashes yellow every time a sound effect is heard, reverting to red afterwards. This is the result of the POKEs in line 70. The number POKEd to 65312 determines the colour of the border during the sound. The colour obtained is that marked on the Spectrum numeric keys 0 to 7. Similarly, the value POKEd to 65313 sets the colour to which the border returns after the sound is completed. Try the effect of altering the values POKEd by line 70. The examples will start you exploring the wide range of sound effects which can be produced by this short and simple routine - roller-coasting can become addictive. Of course, the routine may be a short and simple one but it is the period table which provides the sound. Here is where your creativity can really have its fling. There are innumerable variations on the kinds of table we have already described. Then, for the dedicated hacker, there is the task of generating a super-period table, say 30,000 bytes long. That would give scope for an intricate series of sound effects lasting several seconds - perhaps that of a rocket ship beginning its flight into outer space, or perhaps that of a kindly Dalek voice wishing all readers a happy birthday.