Pilot Your Atari
Sounder
by Ken HarmsAtari PILOT was designed as an easy-to-use language giving "reasonable control of the machines' capabilities." PILOT's SO:und command, however, isn't very reasonable. This article will show you how to get the great sounds ATARI can produce in spite of PILOT. We'll also generate a good random number (PILOT's is almost useless for most purposes), produce animated character graphics, use the joystick to move large cursors, and give you a start on translating BASIC sound effects to PILOT modules.
The ATARI hardware system is the consummate sound computer. Even BASIC lets you use only a small fraction of the hardware's ability. Normal PILOT lets you use almost none. But, with special C:ompute commands, PILOT can give you everything BASIC can. That special command is "Compute at byte" or, in PILOT, C:@Bxxx. The "xxx" refers to the "address" of a "byte" (or character) of memory. The ATARI uses values in certain "addresses" to turn sounds on or off, set margins, etc. For instance, to tell ATARI that the left margin should be at column 3, we issue a C:@B82 = 3.
Under PILOT, the SO:und command controls only the frequency (pitch) of each voice. The distortion and loudness are set to give a dear, bell-like tone. However, two registers are available to control each of the four voices' pitch and distortion / loudness. The addresses of these registers are:
Function Voice 0 Voice 1 Voice 2 Voice 3 Pitch 53760 53762 53764 53766 Control 53761 53763 53765 53767
Numbers used in the pitch register are different from PILOT's SO:und command. They are especially confusing because larger numbers in the pitch register produce lower tones (opposite of normal PILOT). Luckily for translators, the pitch numbers are the same as BASIC's sound command.
The real fun starts with the control register. ATARI cleverly uses these values to control both the loudness and distortion of the voices. Different distortion values produce machine guns, laser swords, locomotives, and many other special sounds.
Loudness values run from 0 to 15 (16 values). Distortion values occur every 32 points from 0 to 224 (8 values). To get numbers for the control register, simply add the distortion and loudness numbers you want, and assign them to the appropriate control register with a C:@Bxxx command. (See your BASIC manual for more information on distortion and loudness.) The table below gives the BASIC SOUND command values for each distortion number:
BASIC DISTORTION NUMBER 0 2 4 6 8 10 14 CONTROL REGISTER VALUES 0 32 64 128 160 192 224
So, to produce a sound at pitch 100 with loudness 8 (medium) in distortion 4 for voice 0, execute the following instructions:
C:@B53760 = 100
C:@B53761 = 8 + 64
You could wear out several keyboards typing the various combinations to test them out. To help you pilot your way through sounds, I've included PILOT SOUNDER. It's really much easier to type than it looks, since over half of it repeats and the AUTO command makes it almost automatic. Just type through line 700, then up-cursor to 610, change the ~FVOICE0 to ~FVOICE1, return, change #Qs to #Ss, etc., through all the FVOICES. Remember to change the C:@B values on the 80 lines. Then do the same for the CVOICEs. You'll have hours of fun planning sounds for your next PILOT program, or just sounding off-my kids love it!
PILOT SOUNDER displays all eight registers and shows actions between the registers.
Lines 240 and 250 C:ompute values for the trigger (%T8 = 1 if pressed, 0 if not) and the position of the joystick (%J0-see PILOT Primer, appendix D). I move them into numeric variables so that the values don't change as we proceed through the program. If the trigger is pressed, *CURSORMOVE blanks the old cursor (line 330), calculates the new position, and prints a new cursor (lines 460-470).
If the trigger was not pressed, *VALUECHANGE calculates a new value for the register where the cursor is. This is tricky. The A:ccept in line 520 puts the row value into the accept register where it's M:atched against line 530. If the cursor is in column #2 (pitches), line 540 jumps to a frequency (pitch) calculator for voice 0,1, 2, or 3, depending on the match. Line 570 does the same thing for control values if the cursor was in column 3. See the PILOT Primer, pages 64 and 65 for more data on the JM: command. The *CVOICE modules use a little modulo math to calculate the distortion and loudness values stored in each register. They then call *FACTOR which increases or decreases these values based on the joystick position. Note that loudness values between 16 and 32, inclusive, are not allowed -in essence, we're using a base 16 (hexidecimal) counting system.
Now look at that long condition in line 210. When you ADD conditions, it's the same as "or-in"" them. That line says "if JO = 0 or if JO = 5 or if JO = 6 or if JO = 10 (any one of them) J:ump to #SENSE. Multiplying conditions [(JO = 0)* (JO = 5). . .] ANDs them and requires all to be true before the statement is executed.
SPECIAL EFFECTS presents a few simple sounds and graphics. Jackhammer was inspired by the ATARI Connection, Volume 1, Number 2 (which has 10 other neat sounds for ambulances, etc., in BASIC). Jackhammer C:omputes address 84 to set the cursor on row 8 and then address 82 to set the left margin on column 14. If the margin hadn't been changed, you'd have to use a POS:ition command before each T:ype command in *PICTURE-a lot of work! The neatest trick occurs on lines 1110 and 1150 which uses one of ATARI's many internal clocks to generate a semi-random number to control the length of the PA:use. The random number generated by the ? is just too big (+32768 to -32768) for most purposes. Address 20 always contains a number between 255 and 0-and counts down every 60th of a second. Interestingly, the sound registers (and many other locations) are "read-only" registers which also contain random numbers between 0 and 255. They are even better for this purpose since they are more random than the count-down clock in address 20.
Jackhammer illustrates a simple counter to replace BASIC's FOR/NEXT loop. Here's how the two languages compare:
BASIC
For Z = 0 to 15
program . . .
Next Z
more program
PILOT
C:#Z =0
*LOOPNAME
program . . .
C:#Z=#Z+1
E(#Z = 15):
J: *LOOPNAME
more program
PILOT uses more lines. It also runs much faster than BASIC-you'll probably have to slow down the BASIC routines you code.
The *BOUNCINC BALL and *LIGHTNING modules were translated from Jerry White's excellent MUSIC LESSONS (available from Swifty Software-the package is jam-packed, two-sided disk in BASIC with many more special effects, player pianos, etc., in a tutorial format).
The ball translation shows how to handle non-integer loops (i.e., a FOR / NEXT loop using steps or values which . are not whole numbers). I just multiplied them up to integers, as well as all values used for pitches, etc. Here's how it was done:
BASIC
For Y = 22 to 20 Step -0.5
program
NEXT Y
PILOT
C:#Y = 22*2
*BALL 1
program
C:#Y=#Y+1
J(#Y >20):*BALL 1
E:
Since there are 24 steps of 0.5 between 22 and 10, and 24 steps of 1 between 44 and 20, the loops are equivalent.
Throughout SPECIAL EFFECTS, I used numeric variables for register addresses rather than type them in each time (see *REGISTERS).
Another good source for special effects is Educational Software's TRICKY TUTORIAL #10 which codes about 50! As always, the most satisfying source is your imagination...assisted by PILOT SOUNDER!
[CODE]