                   Basic Sound Extension



       Richard Taylor improves the Spectrum's sound



This program adds a further four commands designed to

enhance its musical and sound capabilities to Spectrum

Basic. They start where Beep left off, providing a Play

instruction which allows tunes to be played by just speci-

fying the notes rather than having to labouriously convert

them into the numerical form required by Beep. Secondly,

the program facilitates the use of tone envelopes whereby

the pitch of a sound varies with time to produce the laser

sounds and zaps that are all too popular in commercial

games. Random "noise" can also be produced and, when used

in conjunction with envelopes, can be made to create some

convincing effects.

  The program occupies about the top 2.5K of memory just

below the UDG graphics area. [...] To load it, use:

        CLEAR 62682: LOAD ""CODE

  The new commands are used in a similar fashion to those

which are standard, except that the commands have to be

typed out in full - in either upper or lower case - there's

no lazy single key entry system. However, before any of the

commands will be accepted by the Spectrum the machine code

must be initialised with:

        RANDOMIZE USR 62683

This instruction completely resets the program and intro-

duces the new commands to the Spectrum so that when Basic

comes across them they'll be accepted without any quibbles.

Because of the somewhat obscure manner in which it opera-

tes, any errors reported by Interface 1 disconnect the

sound commands so that they are no longer part of Basic's

vocabulary. To reinitialise use:

        RANDOMIZE USR 62686

  The most mundane of the new instructions is *Sound. In

its simplest form it can be used as a substitute for Beep.

In an analogous manner to Beep, the command needs two

arguments, the first being the length of the sound (in

units of 1/100 of a second - so 300 means three seconds)

and the next argument is the pitch of the sound. The pitch

is described in a completely different way to that expected

by Beep - the smaller the number the higher the pitch! The

best way to produce a certain tone is by experimentation -

there's no easy method of getting a pitch number for a

specific frequency. If the pitch of a sound is made nega-

tive then noise is produced with a pitch of very approxi-

mately what it would have been if it wasn't negative, e.g.

        *SOUND 200,-300

produces noise for two seconds. In fact, the sound may not

last exactly two seconds. When generating noise, the dura-

tion you specify is only followed approximately - the sound

may last much longer. If this is a problem then you'll have

to compensate for it when defining sound lengths.

  The *Env command is used to define the envelopes I men-

tioned. The definition of an envelope describes how the

pitch of a sound varies from its initial value as time

progresses. These tone changes give rise to the laser/zap

effects which were previously unobtainable from Basic with-

out enlisting the help of machine-code routines. A helpful

aid in producing envelopes is to illustrate its effect

graphically with the aid of a graph. For instance, the

graphical form of a steadily increasing note would be:



  ^                                        ____/

 H|                                   ____/

 C|                              ____/

 T|                         ____/

 I|                    ____/

 P|               ____/

  |          ____/

  |     ____/

  |____/

  |

  +--------------------------------------------->

                                            TIME



  Notice how the graph shows the pitch undergoing a con-

tinuous, smooth change from the initial to the final pitch

value. [Well, it did in the original magazine print. ASCII

art isn't so smooth, of course, so you'll have to imagine

it.] In reality the computer cannot manage this but has to

break the change down into a number of small, discrete

pitch variations as illustrated below:



  ^                                    ________

 H|                                   |

 C|                           ________|

 T|                          |

 I|                  ________|

 P|                 |

  |         ________|

  |        |

  |________|

  |

  +--------------------------------------------->

                                            TIME



You decide how long each individual step will last and by

how much the pitch then "jumps" at the culmination of each

of the steps.

  Say you wanted to create an envelope similar to the one

above. We have to specify three quantities, namely the

total number of steps, the size of pitch variation after

each of them and the length of each step. From these values

the following can be calculated:

                   Total pitch change =

              number of steps x size of step

                   Total length of env =

             number of steps x length of step

  Consider that the envelope is to last a total of one

second and produce an increase in pitch of 100 units.

Because of the weird way in which the pitch is measured, an

increase is represented by a decreasing pitch number - *Env

uses the same method of pitch representation as *Sound. If

we wanted to have a total of five steps in the effect, then

each would have a length of 1/5th second and a step of -20.

To define the envelope,

        *ENV 0,5,-20,20

is used. The first expression after the command is the

number of the envelope, in this case 0. Up to 16 completely

independent envelopes can be stored in the Spectrum's

memory at one time, each one being specified by a number

between 0 and 15. The second expression is the number of

steps, the third the pitch variation per step and, finally,

the 20 is the step length in 1/100ths of a second. Since

each step lasts a comparatively lengthy 1/5th second, it's

quite easy to hear the individual steps composing the

envelope. To hear the envelope, type:

        *SOUND -1,250,0

Notice how a third argument has been tagged onto the end of

*Sound to specify the envelope to be used. The length of

the sound is given as -1. This means that the envelope

should be played only once. Similarly, if it was -2 then

the envelope would be repeated twice. Try

        *SOUND -5,250,0

The pitch value given in *Sound is the initial pitch which

is decreased down to 150 by the envelope. If an envelope is

being repeated then the pitch commences from its initial

value at the start of every recital of the envelope. There

is nothing to stop noise being enveloped in a similar

fashion; try:

        *SOUND -5,-250,0

Note that when using enveloped noise the pitch is varied as

though the negative sign in front of it didn't exist

(although noise is produced), otherwise decreasing -250 by

100 would produce -350 instead of -150, which is what we're

after. Enveloped noise is the basis of many of the sound

effects to be found in games, especially those of the

"space-war" genre. In order to produce a much smoother

envelope, the step length has to be drastically reduced.

Redefine envelope 0 with:

        *ENV 0,100,-2,1

If you try

        *SOUND -8,250,0

a greatly improved effect will be heard.

  So far the envelopes that have been utilised are rela-

tively simple, in that they consist of only a single type

of pitch change. In reality we may wish to use more complex

envelopes, such as:



  ^  

 H|                   ______

 C|            ______/ C    \_

 T|         __/               \_

 I|      __/ B                 D\_

 P|   __/                         \__

  |  /                               \__

  | /A                                E \__ 

  |/                                       \__

  |

  +--------------------------------------------->

                                            TIME



  The envelope can be subdivided into five discernable

different sections, A-E. We could define a separate enve-

lope for each of A-E and play them together using a string

of *Sound commands. This method, as well as being unelegant

and cumbersome, is further complicated because we need to

calculate the value envelope A, say, leaves the pitch at

when it terminates so that we know what to use as the

starting pitch for envelope B. Thankfully the *Env command

allows an envelope to be composed of up to eight individual

sections. We could define the above envelope as follows:

        *ENV 1,20,-4,2,20,-1,2,10,-1,4,20,4,2,20,2,2

As you can hear, such an envelope provides a much more

complex sound.



The Beep instruction was designed for playing music rather

than making explosion sounds etc. However, life still isn't

easy if you're converting music, since all the note values

have to be converted into the relevant numbers required by

the somewhat awkward Beep. The *Play command enables music

to be converted without the need for any number crunching.

It has a string argument which is used to contain the notes

you wish to play and other associated information. Any

letter from A to G found in the string is played as that

particular musical note - so:

        *PLAY "abcdefg"

plays all the seven notes available. Of course it would be

extremely limiting if you only had seven notes to play

with, so there is a facility to change octave.

  Although the program supports eight octaves, those at the

extreme levels of pitch are of little use for musical pur-

poses. In fact, the upper few notes in the top octave will

produce an error if you try to play them, for the simple

reason that the computer can't manage to produce such a

high-pitched sound. To change octave, an O is simply put

in the string, followed by the new octave number - 1 to 8.

All subsequent notes in that string are then played in the

new octave. At the start of every new *Play the octave is

reset to 3. To further increase the quantity of notes

available, sharps are also supported. A sharp note has a

pitch slightly above - one semitone in fact, whatever that

is - its ordinary value. To play a sharp note simply suffix

the note with a hash character (#):

        *PLAY "c#"

gives C sharp.

        10 FOR a=1 TO 7

        20 *PLAY "o"+STR$ a+"c#dd#eff#gg#aa#b"

        30 NEXT a

  This short program demonstrates the full scope of the

notes available in the lower seven octaves. The O "direc-

tive" - or any other directive that needs an argument,

you'll meet some more in a moment - must be followed by a

number, no variables or expressions are allowed. You can,

however, circumvent this difficulty by using STR$ to

construct the numerical part of the string - as in the

above program - out of an expression, variable or whatever.

  You can play noise instead of plain notes by utilising

the n directive: n0 turns noise off while n1 switches it

on. To hear the effect, try the above program with n1

preceding the o in the string.

  The pause (p) directive enables a silent gap, equivalent

to a musical "rest", to be placed in a tune. The number

following p is the length of the pause measured in 1/100ths

of a second. The pause can be up to 2.55 seconds.

  It is possible to modify the duration of each note using

the L directive. The L is succeeded by a number between

1 and 255 representing the new length, in 1/100ths of a

second, of each note. At the start of each new *Play

command the note length is reset to 0.2 seconds. Dotted

notes are also supported by the program. A dotted note is

played for 1.5 times as long as an ordinary note. To make

a dotted note, simply put a full stop after the letter in

much the same way as you would with a #:

        *PLAY "L100c#."

plays c# for 1.5 seconds. If you require a dotted sharp

note then the full stop should come after the #.

  To add a little more interest to a tune it is possible to

use an envelope. So far all the notes have kept the same

tone value throughout their duration, like the sound pro-

duced by Beep. To turn envelopes on, a Y directive is used.

The number following the Y is the envelope you wish to use,

or 16 to turn envelopes off. All subsequent notes are

played using that envelope. By experimenting with a number

of different envelope effects it is often possible to

enhance the sound of a tune considerably from its flat,

unenveloped beginnings.

  To summarise, these are the directives available in a

*Play string - actually, there is still one to come - I'll

mention that one soon.



A-G  = The notes.

#    = If placed after a note will make it a sharp.

.    = If placed after a note will play it 1.5 times as

       long.

On   = Lets you play subsequent notes in octave n.

Pn   = Pauses for n 1/100ths of a second.

Nn   = If n=0 then noise is turned off.

       If n=1 then it is switched on.

Ln   = Makes the duration of subsequent notes n 1/100ths

       of a second.

Yn   = Makes following notes to be played in envelope n

       (or normal if n=16).



If a sequence of sound commands are always used together

then they can be made into a single unit called an effect.

An effect is a construction of up to eight separate

"sounds" strung together. Like envelopes, effects can be

defined and stored in the Spectrum's memory for later, and

repeated, use. You can have up to eight effects defined at

any one time.

        *EFFECT 0,1,100,200,16,100,150,16

This effect is equivalent to

        *SOUND 100,200:*SOUND 100,150

  The first value in an *Effect is the effect (0-7) and

the next is the number of times the whole effect is to be

repeated when used. Every block of three expressions from

there onwards represents one of the maximum eight indivi-

dual sounds that compose the effect. They are given in the

same format as that expected by *Sound, i.e. length, pitch

and then the envelope number.

  In an effect sequence it is mandatory to specify an

envelope number; it cannot simply be left off. If no enve-

lope is required then 16 should be specified. The only

way to play an effect is by using the *Play command. An X

directive, followed by an effect number, will sound the

appropriate effect.