This program plays a multi-song music player using the BEEP command, rendering each note as a small rectangle drawn with PLOT and DRAW to create a scrolling visual display synchronized with the audio. Notes are encoded as pairs of pitch-height and duration values stored in DATA statements spanning lines 120–810, with sentinel value 99 marking the end of each song. Variables like tw, fr, f1, and f4 are pre-computed constants (2, 4, 51, 54) substituted into DATA values to save memory and reduce token overhead. The program tracks horizontal position i and wraps across two vertical bands (y=100 and y=0) using a flag variable to handle the full 256-pixel wide screen. The use of PI, NOT PI, and SGN PI as compact numeric literals (3.14159…, 0, and 1 respectively) throughout the DATA statements is a well-known Spectrum BASIC memory optimization.
Program Analysis
Program Structure
The program is organized into three logical sections: initialization (lines 10–30), the playback engine (lines 40–110), and a large bank of DATA statements (lines 120–810) encoding multiple songs. The playback loop reads pairs of values j (pitch/height) and k (duration) from DATA, draws a rectangle at the current screen position, plays a BEEP, then advances the horizontal cursor. A sentinel pair 99,0 triggers a pause and restart from the beginning of all DATA.
Playback Engine
Each iteration of the main loop (lines 40–110) reads a data pair and handles three cases:
- If
j=99: end of all songs — pause, clear screen, andGO TO 20to restart. - If
j=0: a rest — pause for3*kframes, advance position byk, skip drawing and BEEP. - Otherwise: draw a rectangle of width
kand heightjat position(i,u), playBEEP k/30, j-40, and advanceibyk.
The rectangle is drawn using PLOT i,u followed by four DRAW commands forming a closed box, providing a visual “piano roll” style display synchronized to the audio.
Screen Wrapping
Because the horizontal coordinate i can exceed the 255-pixel screen width, lines 70–80 implement a two-row wrapping scheme using the flag variable. When i reaches 250 and flag=0, i resets to 0 and u drops from 100 to 0, switching to the lower half of the display. When i reaches 250 again with flag=1, the screen is cleared and both i and u reset to their initial values, starting a new visual pass.
Compact Numeric Literals in DATA
Several techniques reduce the size of the DATA statements:
tw=2,fr=4,f1=51,f4=54are stored as variables and referenced by name in DATA, saving bytes over repeating multi-digit literals.PI(≈3.14159) is used as a duration value where approximately 3 is needed. BASIC evaluatesBEEP k/30, j-40with the floating-point value, which rounds acceptably for note timing.NOT PIevaluates to 0, used as a pitch value to represent a rest or as a zero-duration spacer.SGN PIevaluates to 1, used for very short durations.
This is a well-known Spectrum BASIC technique: using built-in functions that evaluate to small integers rather than storing numeric literals, since variable references and function calls can occupy fewer bytes in the tokenized program than the 5-byte floating-point format used for numeric constants.
Song Data Layout
The DATA bank contains multiple distinct songs, each terminated by the sentinel pair 99,0. The songs span the following approximate line ranges:
| Song # | Data Lines |
|---|---|
| 1 | 120–190 |
| 2 | 200–250 |
| 3 | 260–290 |
| 4 | 300–360 |
| 5 | 370–420 |
| 6 | 430–480 |
| 7 | 490–580 |
| 8 | 590–630 |
| 9 | 640–690 |
| 10 | 700–810 |
When the final sentinel 99,0 in the last song is reached, the program restores via GO TO 20, but since there is no RESTORE call, subsequent reads would run off the end of DATA. However, the GO TO 20 at line 50 only reinitializes variables without resetting the DATA pointer, meaning the program would error on the next READ. A RESTORE at line 20 or 50 would be needed for true looping — this is a latent bug.
BEEP Pitch Encoding
The BEEP statement takes the form BEEP duration, pitch where pitch is in semitones relative to middle A. The formula BEEP k/30, j-40 maps the raw DATA value j to a musical pitch by subtracting 40, placing the range of typical DATA values (roughly 30–66) across approximately a three-octave span from −10 to +26 semitones. Duration is similarly scaled by dividing k by 30 to yield values in seconds.
Notable Anomalies
- Line 80 sets
LET flag=iafter resettingi=0, soflagis always set to 0 here — this is functionally equivalent toLET flag=0and may be intentional compactness or a minor oversight. - The absence of a
RESTOREstatement means the program cannot loop through all songs more than once without a DATA exhaustion error. - Rest handling at line 60 uses
PAUSE 3*kfor timing but does not call BEEP, so rests are silent pauses only with no visual rectangle drawn.
Content
Source Code
10 INK 0: PAPER 7: BORDER 7: CLS
15 LET tw=2: LET fr=4: LET f1=51: LET f4=54
20 LET u=100: LET i=0
30 LET flag=i
40 READ j,k
50 IF j=99 THEN PAUSE 100: CLS : GO TO 20
60 IF j=0 THEN PAUSE 3*k: LET i=i+k: GO TO 40
70 IF i>=250 AND flag=0 THEN LET i=0: LET u=0: LET flag=1
80 IF i>=250 AND flag=1 THEN CLS : LET i=0: LET u=100: LET flag=i
90 PLOT i,u: DRAW 0,j: DRAW k,0: DRAW 0,-j: DRAW -k,0: LET i=i+k
100 BEEP k/30,j-40
110 GO TO 40
120 DATA 54,6,f4,6,52,PI,f1,PI,f1,6,50,PI,f1,PI,f1,16,NOT PI,tw,50,3
130 DATA f1,PI,f1,6,50,PI,f1,PI,f4,6,f1,PI,f4,PI,52,12,49,6,NOT PI,PI,49,PI,49,6,48,PI,49,3
140 DATA 49,6,48,PI,49,3
150 DATA 52,16,NOT PI,tw,f1,PI,49,PI,f1,PI,f4,9,56,9,56,PI,49,16,NOT PI,tw,f4,6
160 DATA 54,6,52,PI,f1,PI,f1,6,50,PI,f1,PI,f1,16,NOT PI,tw,50,PI,f1,PI,f1,6,50,PI,f1,3
170 DATA 52,PI,f1,PI,49,5,46,SGN PI,49,12,47,6,NOT PI,PI,47,PI,47,6,46,PI,47,PI,50,6,49,PI,47,3
180 DATA 59,15,NOT PI,PI,47,PI,49,PI,f1,PI,f4,SGN PI,NOT PI,tw,47,PI,49,PI,f1,PI,f4,SGN PI,NOT PI,tw,42,PI,44,5
190 DATA f1,SGN PI,49,12,47,SGN PI,99,0
200 DATA 52,tw,57,tw,NOT PI,tw,52,tw,57,tw,NOT PI,tw,52,tw,57,6,NOT PI,fr,52,tw,57,tw,59,tw,57,tw,56,4
210 DATA 57,tw,59,tw,NOT PI,8,52,tw,56,tw,NOT PI,tw,52,tw,56,tw,NOT PI,tw,52,tw,56,6,NOT PI,fr,52,2
220 DATA 56,tw,57,tw,56,tw,f4,fr,56,tw,57,tw,NOT PI,6,64,tw,63,tw,64,tw,61,tw,60,tw,61,2
230 DATA 57,tw,56,tw,57,tw,52,tw,NOT PI,fr,49,tw,50,tw,52,tw,f4,tw,56,tw,57,tw,59,tw,61,2
240 DATA 62,tw,59,tw,NOT PI,fr,62,tw,61,tw,62,tw,59,tw,58,tw,59,tw,56,tw,55,tw,56,tw,52,2
250 DATA NOT PI,fr,64,tw,63,tw,64,tw,66,tw,64,tw,62,tw,61,tw,59,tw,57,tw,99,0
260 DATA 49,8,49,8,f1,12,NOT PI,fr,49,8,49,8,f1,12,NOT PI,fr,49,8,f1,8,52,8,f1,8
270 DATA 49,8,f1,fr,49,fr,f4,16,44,8,40,8,44,8,45,8
280 DATA 44,8,44,fr,40,fr,39,16,49,8,49,8,f1,12,NOT PI,fr,49,8,49,8,f1,12,NOT PI,4
290 DATA 40,8,44,8,45,8,49,8,f1,fr,49,fr,45,8,44,16,99,0
300 DATA 37,SGN PI,NOT PI,tw,30,SGN PI,NOT PI,5,42,PI,42,PI,41,PI,39,PI,41,PI,NOT PI,PI,42,PI,44,PI,NOT PI,PI,37,SGN PI,NOT PI,2
310 DATA 30,SGN PI,NOT PI,5,42,PI,42,PI,41,PI,39,PI,41,PI,NOT PI,PI,42,PI,44,PI,NOT PI,PI,37,PI,42,PI,NOT PI,PI,45,3
320 DATA 49,6,47,PI,45,PI,NOT PI,PI,49,PI,52,6,50,PI,49,PI,NOT PI,PI,53,PI,56,6,f4,PI,53,PI,50,3
330 DATA 49,PI,47,PI,45,PI,44,PI,30,SGN PI,NOT PI,5,42,PI,42,PI,41,PI,39,PI,41,PI,NOT PI,PI,42,PI,44,3
340 DATA NOT PI,PI,37,SGN PI,NOT PI,tw,30,SGN PI,NOT PI,5,42,PI,42,PI,41,PI,39,PI,41,PI,NOT PI,PI,42,PI,44,PI,0
350 DATA PI,37,PI,NOT PI,PI,49,PI,52,6,50,PI,49,PI,47,PI,45,PI,43,PI,47,PI,50,PI,42,3
360 DATA 41,PI,42,PI,44,PI,NOT PI,PI,45,SGN PI,NOT PI,tw,44,9,42,SGN PI,99,0
370 DATA 47,tw,NOT PI,tw,47,tw,49,tw,NOT PI,tw,49,tw,f1,tw,f4,tw,f1,tw,47,tw,NOT PI,tw,42,2
380 DATA 47,tw,NOT PI,tw,47,tw,49,tw,NOT PI,tw,49,tw,f1,6,47,tw,NOT PI,tw,42,tw,47,tw,NOT PI,tw,47,tw,49,2
390 DATA NOT PI,tw,49,tw,f1,tw,f4,tw,f1,tw,47,tw,NOT PI,fr,56,tw,NOT PI,fr,49,tw,NOT PI,tw,52,tw,f1,6,47,2
400 DATA NOT PI,fr,59,tw,NOT PI,tw,59,tw,56,tw,NOT PI,tw,59,tw,58,tw,61,tw,58,tw,f4,tw,NOT PI,fr,59,tw,NOT PI,2
410 DATA 59,tw,56,tw,NOT PI,tw,59,tw,58,6,f4,tw,NOT PI,tw,f1,tw,52,tw,NOT PI,tw,f1,tw,52,tw,NOT PI,tw,f4,2
420 DATA 56,tw,NOT PI,tw,58,tw,59,tw,NOT PI,fr,56,tw,NOT PI,fr,49,tw,NOT PI,tw,52,tw,f1,6,47,tw,99,0
430 DATA 47,PI,NOT PI,tw,49,SGN PI,47,PI,NOT PI,tw,49,SGN PI,f1,PI,NOT PI,tw,f4,SGN PI,56,PI,NOT PI,tw,f4,1
440 DATA 59,PI,NOT PI,tw,58,SGN PI,61,PI,NOT PI,tw,59,SGN PI,58,PI,NOT PI,tw,61,SGN PI,59,PI,NOT PI,tw,56,1
450 DATA 54,PI,NOT PI,tw,f4,SGN PI,56,PI,NOT PI,tw,f4,SGN PI,59,PI,NOT PI,tw,56,SGN PI,f4,PI,NOT PI,tw,f1,1
460 DATA 49,24,47,PI,NOT PI,tw,49,SGN PI,47,PI,NOT PI,tw,49,SGN PI,f1,PI,NOT PI,tw,f4,SGN PI,56,PI,NOT PI,tw,f4,1
470 DATA 56,PI,NOT PI,tw,58,SGN PI,61,PI,NOT PI,tw,59,SGN PI,58,PI,NOT PI,tw,61,SGN PI,59,PI,NOT PI,tw,56,1
480 DATA 54,PI,NOT PI,tw,f4,SGN PI,59,PI,NOT PI,tw,47,SGN PI,49,6,f4,6,47,18,99,0
490 DATA 55,tw,f4,tw,f4,fr,55,tw,f4,tw,f4,fr,55,tw,f4,tw,f4,fr,62,fr,NOT PI,4
500 DATA 62,tw,61,tw,59,fr,59,tw,57,tw,55,fr,55,tw,f4,2
510 DATA 52,fr,52,fr,NOT PI,fr,f4,tw,52,tw,52,fr,f4,tw,52,tw,52,fr,f4,tw,52,2
520 DATA 52,fr,61,fr,NOT PI,fr,61,tw,59,tw,58,fr,58,tw,55,tw,f4,fr,f4,tw,52,2
530 DATA 50,fr,50,fr,NOT PI,fr,62,tw,61,tw,61,fr,64,fr,58,fr,61,4
540 DATA 59,fr,f4,fr,NOT PI,fr,62,tw,61,tw,61,fr,64,fr,58,fr,61,4
550 DATA 59,fr,62,fr,61,tw,59,tw,57,tw,55,tw,f4,fr,46,fr,47,fr,49,4
560 DATA 50,fr,52,tw,50,tw,49,fr,47,fr,f4,fr,NOT PI,fr,65,8
570 DATA 66,tw,NOT PI,6,65,8,66,tw,NOT PI,6,65,8
580 DATA 66,fr,65,fr,66,fr,65,fr,66,fr,99,0
590 DATA 50,PI,50,PI,52,PI,f4,PI,50,PI,f4,PI,52,PI,45,PI,50,PI,50,PI,52,PI,f4,PI,50,6
600 DATA 49,PI,NOT PI,PI,50,PI,50,PI,52,PI,f4,PI,55,PI,f4,PI,52,PI,50,PI,49,PI,45,PI,47,PI,49,PI,50,6
610 DATA 50,PI,NOT PI,PI,47,5,49,SGN PI,47,PI,45,PI,47,PI,49,PI,50,PI,NOT PI,PI,45,5,47,SGN PI,45,PI,43,PI,42,6
620 DATA 45,PI,NOT PI,PI,47,5,49,SGN PI,47,PI,45,PI,47,PI,49,PI,50,PI,47,fr,45,PI,50,PI,49,PI,52,PI,50,6,50,6
630 DATA 99,0
640 DATA 42,SGN PI,NOT PI,SGN PI,42,SGN PI,NOT PI,SGN PI,42,SGN PI,NOT PI,SGN PI,47,SGN PI,NOT PI,5,51,SGN PI,NOT PI,PI,42,SGN PI,NOT PI,SGN PI,42,SGN PI,NOT PI,1
650 DATA 42,SGN PI,NOT PI,SGN PI,47,SGN PI,NOT PI,5,51,SGN PI,NOT PI,5,30,SGN PI,NOT PI,SGN PI,30,SGN PI,NOT PI,SGN PI,35,SGN PI,NOT PI,PI,47,SGN PI,NOT PI,1
660 DATA 47,SGN PI,NOT PI,SGN PI,46,SGN PI,NOT PI,SGN PI,46,SGN PI,NOT PI,SGN PI,44,SGN PI,NOT PI,SGN PI,44,SGN PI,NOT PI,SGN PI,42,8,NOT PI,tw,42,SGN PI,NOT PI,1
670 DATA 42,SGN PI,NOT PI,SGN PI,42,SGN PI,NOT PI,SGN PI,46,SGN PI,NOT PI,5,49,SGN PI,NOT PI,PI,42,SGN PI,NOT PI,SGN PI,42,SGN PI,NOT PI,SGN PI,42,SGN PI,NOT PI,1
680 DATA 46,SGN PI,NOT PI,5,49,SGN PI,NOT PI,5,37,SGN PI,NOT PI,SGN PI,37,SGN PI,NOT PI,SGN PI,30,SGN PI,NOT PI,PI,f4,tw,56,tw,f4,tw,52,2
690 DATA f1,tw,49,tw,47,8,99,0
700 DATA 42,fr,42,fr,46,fr,49,fr,49,fr,NOT PI,fr,61,tw,NOT PI,tw,61,tw,NOT PI,6,58,tw,NOT PI,tw,58,tw,NOT PI,6,42,fr,42,4
710 DATA 46,fr,49,fr,49,fr,NOT PI,fr,61,tw,NOT PI,tw,61,tw,NOT PI,6,58,tw,NOT PI,tw,58,tw,NOT PI,tw,NOT PI,6,42,fr,42,4
720 DATA 46,fr,49,fr,49,fr,NOT PI,fr,61,tw,NOT PI,tw,61,tw,NOT PI,6,59,tw,NOT PI,tw,59,tw,NOT PI,6,41,fr,41,fr,44,fr,f1,fr,f1,4
730 DATA NOT PI,fr,63,tw,NOT PI,tw,63,tw,NOT PI,6,59,tw,NOT PI,2
740 DATA 59,tw,NOT PI,6,41,fr,41,fr,44,fr,f1,fr,f1,fr,NOT PI,fr,63,tw,NOT PI,tw,63,tw,NOT PI,6,58,tw,NOT PI,tw,58,2
750 DATA NOT PI,6,42,fr,42,fr,46,fr,49,fr,f4,fr,NOT PI,fr,66,tw,NOT PI,tw,66,tw,NOT PI,6,61,tw,NOT PI,tw,61,tw,NOT PI,6,42,4
760 DATA 42,fr,46,fr,49,fr,f4,fr,NOT PI,fr,66,tw,NOT PI,2
770 DATA 66,tw,NOT PI,6,63,tw,NOT PI,tw,63,tw,NOT PI,6,44,fr,44,fr,47,fr,f1,tw,NOT PI,tw,f1,14,NOT PI,tw,48,fr,49,fr,58,16
780 DATA 54,fr,46,fr,46,8,44,fr,f1,8,49,fr,42,fr,NOT PI,tw,42,tw,42,fr,NOT PI,8,49,tw,NOT PI,tw,47,2
790 DATA NOT PI,6,49,tw,NOT PI,tw,47,tw,NOT PI,6,49,fr,58,16,56,fr,49,tw,NOT PI,tw,46,tw,NOT PI,6,49,tw,NOT PI,tw,46,tw,NOT PI,6,49,4
800 DATA 56,16,f4,fr,49,tw,NOT PI,tw,47,tw,NOT PI,6,49,tw,NOT PI,tw,47,tw,NOT PI,6,49,fr,58,16
810 DATA 56,fr,49,fr,f4,fr,58,fr,61,8,59,fr,58,tw,58,tw,58,fr,56,tw,NOT PI,tw,f4,fr,NOT PI,8,99,0
1000 SAVE "MusicBeep1" LINE 1
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
