It is when BASIC comes across a SOUND command that information is sent to the sound chip. The ENVELOPE command merely alters the volume and pitch characteristics of the note the SOUND command has been programmed to produce. In its simplest form, it must be followed by four parameters:
SOUND C,A,P ,D
These stand for the following and take the indicated values:
Channel: | 0 to 3 |
Amplitude: | normally - 15 to 0 but also 1 to 16 when used with ENVELOPE |
Pitch: | 0 to 255 |
Duration: | 0 to 255 |
The sound chip contains four sound channels numbered 0 to 3 and this parameter selects which channel is to be used to produce the sound. Channel 0 is the noise channel and channels 1, 2 and 3 produce the square wave tones described previously. As channel 0 produces a noise as opposed to a tone, the pitch parameters have a different effect, which we will look at later. All four channels can be programmed to sound together to produce quite sophisticated harmonies and effects.
This first sound parameter, the channel number, can be extended to four figures like this:
SOUND &HSFC, A, P, D
The ampersand (&) means the following numbers are hexadecimal digits (see page 71 of the User Guide) but, as the values used in the SOUND command are all in the range 0 to 3, we do not need to perform any decimal to hex conversions and can forget about it for practical purposes. We must not forget, however, to include the ampersand whenever we use more than one figure in the first SOUND parameter; otherwise the figure as a whole will be taken as a decimal number and will not produce the effect we want. The additional parameters and their ranges are as follows:
Hold: | 0 or 1 |
Synchronization: | 0 to 3 |
Flush: | 0 or 1 |
Channel: | 0 to 3 |
When we use the shortened form of the SOUND command as in:
SOUND 1,-15,53,20
the channel is specified - in this case I - and the other parameters default to 0. So, if we do not want to use them, we can ignore them.
Hold (or Continuation) is described in the User Guide on pages 187, 350 and 352. This is probably the least understood of the SOUND parameters - which isn't surprising because it is described inaccurately on pages 187 and 350 and all descriptions tell you what can be done with the command, not what the command actually does.
If H is 0, the default value, the SOUND command operates as normal. If H is set to 1, the amplitude and pitch parameters in the SOUND command are ignored, but the duration is obeyed. Normally this would just create a silence or a rest but, if this command follows a note on the same channel which is under envelope control, then the previous note may be extended. To understand this further we need to be aware of the ADSR functions of the ENVELOPE command.
If the amplitude A in a SOUND command is set to a value between 1 and 16, the volume of the sound is controlled by the envelope with that particular number. Without an envelope, each SOUND command will last for the duration set by its D parameter - no longer, no shorter. Once an envelope is used, D determines the value of the attack, decay and sustain periods only. If no other commands follow on the sarrye channel, it will be allowed to continue into the release phase of the envelope instead of terminating. Normally the next note in the sound queue will occur as soon as the SOUND command has completed its allotted duration and the release phase will not occur. The ENVELOPE command is described in detail in the next chapter.
A SOUND command with H set to 1 produces a 'dummy' note, as it is called in the User Guide, for the duration of the D parameter. This will allow the previous note to continue for this extra time and, if the previous note goes into a release phase, it will not be automatically terminated. Setting H to I does not automatically allow the release phase to complete but simply allows it to continue. If there is nothing left in the release phase, there will be nothing to sound and there will be silence for the duration of the D parameter. Conversely, if the additional time given by the D value of the dummy note is too short, the release phase will not reach its end.
In effect, setting H to 1 in a SOUND statement creates a time gap equal to the D parameter through which a previous note on that channel can play - assuming that there is something there to play.
Misunderstandings may have arisen because the User Guide states, incorrectly, on page 187 that the amplitude, pitch and duration are ignored, leading one to believe that this command calculates the release time on the previous note and allows it to play out. The description on page 350 is ambiguous and other writers have followed the wrong description.
In practice, this command is not often used. Its main function is to allow the release section of a sound to occur as the User Guide says. When you are experimenting with the ENVELOPE command and the parameters which alter the pitch values, you will find a lot of good noises, sounds and effects occur during the release part of the ADSR phase. If you want the release phases to occur in a series of notes, the easiest way to do this is with the Hold option. This short program illustrates its effect:
10 REM PROGRAM 4.1
20 REM HOLD PARAMETER DEMONSTRATION
30
40 ENVELOPE1,4,0,0,0,0,0,0,126,-1,0,-
1,126,60
50 TIME=0
60
70 SOUND1,1,53,40
80 PROCTime
90 SOUND1,1,69,20
100 PROCTime
110 END
120
130 DEF PROCTime
140 REPEAT
150 IF TIME/100=INT(TIME/100) PRINT TI
ME/100
160 UNTIL TIME>800
170 STOP
180 ENDPROC
Trying to time SOUND commands is difficult, because the commands are stored in a queue and a BASIC program simply moves through them - unless the buffer is full, in which case the BASIC program is held up. PROCTime begins after the commands have been issued and prints to the screen approximately every second.
When you run the program you will notice that the sound produced by line 70 lasts four seconds. Its D value is 40 which means that the attack, decay and sustain phases last two seconds, the other two seconds being the release phase. If you remove line 80 you will see that the new note produced by fine 90 occurs after two seconds, indicating that the release phase of the first note was cut short by the appearance of another note in the sound queue.
Enter another line 80 as follows:
80 SOUND&1001,0,0,40
The first note will now last for four seconds - its own two-second duration plus the extra two seconds afforded it by the dummy note in line 80. If you increase the duration parameter in line 80, you will hear the first note complete its release phase and then there will be silence, while the dummy note runs its time, before the note on line 90 sounds.
This allows two or more notes to sound at exactly the same time. If S is 0, the default value, notes are queued as usual and notes on each channel sound as soon as they reach the front of their respective queues. If S is 1, 2 or 3, then the note does not sound until there is a corresponding note or notes with the same S value on another channel or channels. If S is set to I the computer waits for one more note. If S equals 2 it waits for two more notes and if S equals 3 it waits for notes on all four channels.
The use of this command is quite well documented in the User Guide but it is not always so obvious how to use it. As a means of sounding notes at the same instant, it does not seem to be so different from the usual queuing method. Is this:
10 SOUND1,-15,73,30
20 SOUND2,-15,89,30
30 SOUND3,-15,101,30
so different from this:
10 SOUND&201,-15,73,30
20 SOUND&202,-15,89,30
30 SOUND&203,-15,101,30
The value of this command, however, lies in the fact that it allows us to execute other statements between sounds without throwing our sound out of synchronization, or 'sync' as it is often referred to. Insert this line in the two previous examples and observe the result:
15 FOR Delay=1 TO 400:NEXT Delay
This feature of the SOUND command can be used to ensure that programmed tunes play in sync and also to prevent individual channels wandering off due to the relative slowness of BASIC. Short sequences of notes may not need this to ensure synchronization. The whole topic is covered more fully in Chapter 9.
This, too, is well documented in the User Guide. When F is set to I and the SOUND statement in which it occurs is executed, it flushes the sound channel of any notes waiting in the sound queue and stops execution of whatever note may be sounding at that time. The sound channel with F set to 1 then executes its note. This can be thought of as jumping the queue and has several useful applications.
In a game which plays a background tune or which creates sound effects as objects move, at any point in the program the music can be interrupted and a different tune played. It does not have to wait until its present meanderings are completed. By using the F parameter, it flushes the relevant sound channels and plays something new. Explosions occur in the same way, exactly at the time an object is hit.
In a musical context, by issuing a command with F set to 1 we can stop notes sounding on a particular channel. The next program demonstrates the flushing facility.
10 REM PROGRAM 4.2
20 REM CHANNEL FLUSHING DEMONSTRATION
30 SOUND3,-10,5,245
40 SOUND1,-15,53,60:SOUND2,-12,5,60
50 SOUND1,-15,81,60:SOUND2,-12,53,60
60 SOUND1,-15,101,60:SOUND2,-12,53,60
70 SOUND1,-15,117,5:SOUND2,-12,69,5
80 SOUND1,-15,113,60:SOUND2,-12,65,60
90 PRINT"PRESS ANY KEY TO STOP"
100 IF INKEY(400)<>-1 THEN SOUND&11,0,
0,0:SOUND&12,0,0,0:SOUND&13,0,0,0 ELSE P
RINT"TOO LATE"
110 SOUND1,-15,149,2:SOUND1,-15,137,2
120 SOUND1,-15,129,2:SOUND1,-15,137,2
130 SOUND1,-15,145,2:SOUND1,-15,137,2
140 SOUND1,-15,145,2:SOUND1,-15,149,4
The INKEY delay in fine 100 gives you four seconds to hit the key. If you do so, it will flush all channels and proceed with the routine beginning at fine 110. If you do not press a key within the time limit, the first tune plays out and the second routine is queued in the normal way and will be heard after the first tune.
In practice, this program would be better written using DATA statements and the commands could even be synchronized, but the purpose is to illustrate the flushing procedure. You can experiment by flushing individual channels and listening to the effect.
This is well documented and generally well understood. Normal values vary from - 15 which is very loud (comparatively speaking) to 0 which is off. (-1 is quite quiet.)
If a positive value in the range 1 to 4 is substituted, this puts the SOUND command under envelope control, which permits far more sophisticated variations over volume. If you do not use the RS423 and cassette output buffers, ie the BPUT# command, then up to 16 envelopes can be used and A can take a value up to 16.
The volume of a sound is affected by many factors, as we saw in Chapter 1. If the amplitude of a waveform is doubled the sound does not appear to be twice as loud. This is because we perceive sound in a logarithmic fashion. If vibrato or tremolo is applied to a note it will seem louder, and volume varies with pitch, too, so that low notes need more power to sound as loud as higher notes.
The study of loudness and volume is a science in itself. For our purposes we only need remember that, because of the vagaries of the sound chip, the loudspeaker (whichever one we are using) and its enclosure, and the properties of sound itself, some notes may overpower others.
This can take values from 0 to 255 and selects tones in quarter of a semitone intervals. If we want to use the conventional western scale of music, we must work in increments of four. Figures 2.4 and 3.3 show how the values of P correspond to printed notes and the keyboard.
Channel 0, the noise channel, operates in a different way and the P parameter produces the following effects:
0 High frequency periodic noise.
1 Medium frequency periodic noise.
2 Low frequency periodic noise.
3 Periodic noise of a frequency determined by the pitch of channel 1.
4 High frequency white noise.
5 Medium frequency white noise.
6 Low frequency white noise.
7 White noise of a frequency determined by the pitch of channel 1.
Try the sounds to hear what they are like. The following demonstrates the effects of setting P to 3:
10 SOUNDO,-15,3,200
20 FOR Pitch=0 TO 200
30 SOUND1,0,Pitch,1
40 NEXT Pitch
Alter the P parameter in line 10 to 7. Experiment by putting channel 1 under envelope control.
The noise channel deserves a section to itself and is discussed in detail in Chapter 7.
This sets the length of time the note is to sound in twentieths of a second. If D is set to 255, the sound will continue indefinitely until stopped by pressing ESCAPE or by flushing the channel. With D set to 0, the note is given a duration of one two-hundredth of a second. This is very useful for separating notes of the same pitch. For example:
10 SOUND1,-15,53,20
20 SOUND1,-15,54,20
will sound as one note with a total duration of two seconds. If you insert:
15 SOUND1,0,0,0
this will cause a slight separation between the notes.
We can time the length of this duration by the following:
10 TIME=0
20 FOR X%=0 TO 500
30 NEXT
40 PRINT TIME/100
Run it a few tunes to get an average time for the completion of the loop. Insert line 25:
25 SOUNDl,0,0,0
This will hold up the loop for the length of the duration. If you subtract the first time from the second time and divide by 500, you will get a figure just over one two-hundredth of a second. The extra time is accounted for by the time, it takes the OS to sort out its instructions, and it is not very long.
If a tune is programmed in more than one part and this technique is used a lot, the tune may eventually run out of sync. There are other ways of separating notes and maintaining synchronization. One answer is to use envelope control.
Referring to Figure 2.6, if you assign the duration values there to the actual D parameter, you have a workable set of note durations which will be about right for tunes of moderate tempo. As tempos can vary widely you may find you have to increase or decrease these values but the relationship between note durations must be maintained. If you reduce the values to their lowest common denominator, you can add a 'tempo' variable for easy adjustment of the speed of the piece.
If an envelope has been selected, D determines the total of the attack, decay and sustain periods but not the release phase. This was mentioned in relation to the Hold parameter and is discussed more fully in the next chapter.
The User Guide gives the range of duration values as being between 0 and 255. On page 348 it says that setting D to -1 will make the note last indefinitely, and a duration of between 0 and 254 will give a note a duration of that number of twentieths of a second. The statement about 0 is not true as we have seen and, in fact, -1 has the same effect as 255. This is because the values are brought within the range the sound chip expects. If you try to go off the top of the range the values wrap around and you find yourself coming up from the bottom - and vice versa.
The reasons for this are a little technical and it is not necessary to know why this happens, but the curious may gain further insight from examination of the MOD and DIV commands in the User Guide.
All the SOUND command parameters are treated in a similar way and reasons need not concern us-so long as we keep our values within their allotted range. There is nothing to be gained by going outside the range, as the computer will simply reduce them to an acceptable value. Such instructions will not generate an error and the only time, apart from incorrect input of data, when we need to be aware of the limitations is if we are creating values through calculation. For example, trying to play a scale with pitches going beyond 255 will bring the pitch back down to 0 to start again from there.
All SOUND commands are expected in integers. If they are not given, the non-integer part is ignored, eg:
SOUND 1,-15,53,20
produces the same note as:
SOUND1,- 15,53.99999 ,20
This can be useful if we are calculating values.
Versatile though the SOUND command is on its own, the range of sounds it can produce can be expanded enormously by the use of the ENVELOPE command - which is what we look at in the next chapter.