Parakeet

Date: 198x
Type: Program
Platform(s): TS 2068

This program generates procedurally randomised synthesiser sounds using the SOUND statement, which maps directly to the AY-3-8912 sound chip. The first section (lines 10–50) produces a sweeping tone by iterating through a randomly determined frequency range with a random step value, then cuts the envelope. Lines 60–80 introduce probabilistic branching: a one-in-two chance of a random pause and a one-in-four chance of jumping to a second sound routine, otherwise looping via RUN. The second section (lines 90–160) creates percussive noise bursts by configuring the noise channel (register 6) and mixing registers, with randomised envelope period and shape values, separated by short busy-wait loops using empty FOR–NEXT. Both sections ultimately loop back with RUN, making the program a continuous generative ambient sound machine.


Program Structure

The program divides into two distinct sound-generation blocks, connected by probabilistic branching:

  1. Sweep section (lines 10–80): Configures the AY chip’s tone channel, sweeps through a random frequency range, then either loops (RUN) or falls through to the noise section.
  2. Noise burst section (lines 90–160): Generates rhythmic noise pulses with randomised envelope parameters inside a double FOR–NEXT loop, then unconditionally restarts via RUN.

AY-3-8912 Register Usage

The SOUND keyword on the TS2068 writes directly to AY-3-8912 registers. The following registers are referenced:

RegisterFunctionUsed at lines
0 (fine pitch)Channel A tone period low byte30
6Noise period120
7Mixer control (enable/disable tone & noise per channel)10, 120, 150
8Channel A amplitude / envelope flag10, 120, 150
9Channel B amplitude10, 120, 150
10Channel C amplitude10, 120, 150
11Envelope period fine30, 120
12Envelope period coarse30, 50, 120
13Envelope shape / cycle30, 50, 120

Line 10 sets the mixer (7,62) to enable all tone outputs while muting noise, and silences channels B and C. Line 50 halts the envelope by writing 12,1;13,0. Line 150 restores a silent mixer state after the noise bursts.

Sweep Mechanism (Lines 20–40)

The FOR I loop at line 20 computes a random start value INT(RND*75)+25 (range 25–99), a random end value INT(RND*75)+20 (range 20–94), and a step of INT(RND*4)*2-5. The step expression yields values from the set {−5, −3, −1, 1} depending on INT(RND*4) ∈ {0,1,2,3}, meaning the sweep can ascend or descend. A step of 0 is impossible because the even multiples are offset by −5 giving only odd and negative-odd results.

Each iteration writes the loop variable I to register 0 (channel A fine pitch) while holding the envelope period and shape constant, producing an audible glide effect on the tone channel.

Probabilistic Flow Control (Lines 60–80)

Two independent random branches control program flow after the sweep:

  • Line 60: 50% probability of a PAUSE lasting between 1 and 60 frames (~0.02–1.2 seconds at 50 Hz), adding irregular timing.
  • Line 70: 25% probability of jumping to the noise section at line 90; otherwise line 80 executes RUN, restarting the entire program and re-seeding randomness from the existing R register state.

Using RUN rather than GO TO 10 is a deliberate idiom: it clears variables and re-enters the program from scratch, which also resets any BASIC overhead but preserves the pseudo-random sequence implicitly via elapsed time affecting RND.

Noise Burst Section (Lines 90–160)

The outer loop FOR J=RND*1 TO RND*10 at line 90 iterates a random number of times (the non-integer bounds are handled by BASIC’s standard loop rules; the count is effectively 0 to ~10). Inner loops at lines 100–110 and 130–140 are empty busy-wait delays, their duration randomised by INT(RND*4) and INT(RND*10) respectively.

Line 120 is the core noise event: register 6 sets noise period to 16; register 7 value 7 enables noise on all three channels while disabling tone; registers 8–10 all set to 16 enable hardware envelope control for all channels. The envelope period coarse (11, 300+INT(RND*10)) gives a slowly varying period around 300–309. Register 12 receives either 0 or 1 via INT(((RND*2)+.5)/2), and register 13 selects envelope shape 0 or 8 via INT(RND*2)*8, toggling between a single-decay and a continuous-repeat envelope.

Notable Techniques and Anomalies

  • The SOUND statement’s semicolon-separated register pairs allow an entire chip configuration to be written in a single BASIC statement, minimising interpreter overhead during time-sensitive sound setup.
  • Empty FOR K … NEXT K loops (lines 100–110, 130–140) serve as deterministic busy-wait delays — a common TS2068 idiom where PAUSE resolution (one frame) is too coarse.
  • The expression INT(((RND*2)+.5)/2) on line 120 is an unusual way to produce a biased coin: it yields 0 when RND < 0.5 and 1 otherwise, equivalent to simply INT(RND*2), suggesting either stylistic preference or a copy/transcription artifact.
  • Both sections terminate with unconditional RUN (lines 80 and 170), ensuring the program never halts during normal execution paths.

Content

Appears On

Capital Area Timex Sinclair User Group’s Library Tape.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   10 SOUND 7,62;8,16;9,0;10,0
   20 FOR I=INT (RND*75)+25 TO INT (RND*75)+20 STEP INT (RND*4)*2-5
   30 SOUND 0,I;11,32;12,100;13,2
   40 NEXT I
   50 SOUND 12,1;13,0
   60 IF INT (RND*2)=1 THEN PAUSE INT ((RND*60)+1)
   70 IF INT (RND*4)=1 THEN GO TO 90
   80 RUN 
   90 FOR J=RND*1 TO RND*10
  100 FOR K=0 TO INT (RND*4)
  110 NEXT K
  120 SOUND 6,16;7,7;8,16;9,16;10,16;11,300+INT (RND*10);12,INT (((RND*2)+.5)/2);13,INT (RND*2)*8
  130 FOR K=0 TO INT (RND*10)
  140 NEXT K
  150 SOUND 7,63;8,0;9,0;10,0
  160 NEXT J
  170 RUN 

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top