Musical Christmas with TS 2068

Developer(s): Oleg D. Jefimenko
Date: 1985
Type: Program
Platform(s): TS 2068
Tags: Holiday, Music

This program plays three Christmas songs — Silent Night, Jingle Bells, and Joy to the World — using the BEEP command with note frequency and duration values stored in DATA statements. A table-of-contents menu lets the user select a song by number, and ON ERR is used to detect when the DATA stream is exhausted, signaling the end of a piece. A special sentinel value of 99 for the frequency triggers a pause (rest) rather than a tone, implemented by substituting PAUSE for BEEP. After playback, the user may replay the song, loop it continuously, or return to the song selection menu.


Program Analysis

Program Structure

The program is divided into a title/menu section (lines 10–230) and three song DATA blocks anchored at lines 1000, 1200, and 1400. Song selection uses a formula: RESTORE n*200+800, which maps song numbers 1, 2, and 3 to DATA line offsets 1000, 1200, and 1400 respectively. Each song block begins with a name string and a tempo scalar, followed by pairs of (frequency-semitone, duration-divisor) values.

Note Playback Engine

The playback loop at lines 130–160 reads two values per iteration: f (pitch in semitones above middle C) and v (a duration divisor). The actual duration passed to BEEP or PAUSE is t/v, where t is the tempo scalar read at line 90. A frequency value of 99 is used as a rest sentinel — when f=99, the program executes PAUSE t/v*60 (line 150) instead of BEEP, converting the beat duration to frames at 60 fields per second.

End-of-Song Detection via ON ERR

Rather than embedding an explicit terminator count or end marker in the DATA, the program uses ON ERR GO TO 170 (line 130) to catch the “Out of DATA” error that occurs when READ runs past the end of the current song’s data block. Line 170 then clears the error trap with ON ERR RESET and checks a flag variable z$ to decide whether to loop continuously.

Continuous Play Mode

When the user selects option “2” (play continuously), z$ is set to "2" at line 220. After the ON ERR fires and the check at line 170 passes, the program executes RESTORE n*200+810 — note the offset of +810 rather than +800 — which skips the name and tempo DATA entry and re-reads from the first note pair directly, then jumps back to the playback loop at line 130 for seamless looping.

Menu and Display

The title screen (lines 10–20) prints “CHRISTMAS MUSIC” alternating in INK 1 and INK 3 across 13 rows using a FOR loop. The table-of-contents loop at line 60 uses RESTORE i*200+800 and reads only the song name n$ for display, cleanly reusing the same offset formula used for playback. PAPER color attributes are used throughout for visual separation of UI regions.

Data Format

Each song’s DATA is structured as follows:

  1. Song name string (e.g., "Silent Night")
  2. Tempo scalar t (a floating-point value tuned per song)
  3. Alternating pairs: semitone offset f, duration divisor v

Duration divisors appear as arithmetic expressions directly in the DATA (e.g., 8/3, 4/3), which BASIC evaluates when read, providing fractional beat lengths for dotted notes without requiring floating-point literals to be hand-calculated.

Notable Techniques

  • Using ON ERR as a natural end-of-data signal avoids the need for a terminator value or note count.
  • Arithmetic expressions in DATA lines (e.g., 8/3) allow compact notation of triplet and dotted rhythms.
  • The RESTORE n*200+810 trick skips the song header to enable seamless looping without re-reading the name or tempo.
  • The rest sentinel value 99 is handled by branching at line 140 before BEEP is called, avoiding an out-of-range frequency error.
  • PAUSE 0 followed by INKEY$ at line 220 is used as an efficient single-keypress wait.

Potential Issues

  • The continuous-play RESTORE n*200+810 assumes the song name and tempo occupy exactly two DATA items starting at offset +800, which holds for all three songs but would break if the header DATA were on a different relative line.
  • Line 220 sets z$ and immediately checks it, but the ON ERR GO TO 170 is only re-armed when playback starts at line 130 — if the user re-selects via line 90, the trap is re-armed correctly on the next pass through line 130.

Content

Appears On

Related Products

Related Content

Image Gallery

Source Code

   10 BORDER 4: PAPER 6: CLS : FOR a=0 TO 12
   20 PRINT INK 1;"CHRISTMAS MUSIC";TAB 17; INK 3;"CHRISTMAS MUSIC": NEXT a
   30 PRINT AT 18,1; PAPER 5;"Press ENTER to select a song"
   40 PAUSE 0
   50 CLS : PRINT PAPER 5;"****** Table of Contents *******": PRINT '''''''
   60 FOR i=1 TO 3: RESTORE i*200+800: READ n$: PRINT i;TAB 4;n$: NEXT i
   70 PRINT PAPER 5;AT 20,0;"Enter the number of the composi-tion that you want to play      "
   80 INPUT n: CLS : LET z$=""
   90 RESTORE n*200+800: READ n$,t
  100 CLS : PRINT PAPER 5;"********* Now Playing **********";AT 21,0;"********* Now Playing **********"
  110 PRINT AT 10,(31-LEN n$)/2;n$
  120 PRINT PAPER 3; INK 7;AT 20,0;" To stop, press SHIFT + BREAK   "
  130 READ f,v: ON ERR GO TO 170
  140 IF f<>99 THEN GO TO 160
  150 PAUSE t/v*60: GO TO 130
  160 BEEP t/v,f: GO TO 130
  170 ON ERR RESET : IF z$="2" THEN RESTORE n*200+810: GO TO 130
  180 CLS : PAPER 7: PRINT AT 7,0;"Press 1 to play again.          "
  190 PRINT "Press 2 to play continuously.   "
  200 PRINT ;"Press 0 to play another song.   "
  210 PAPER 6
  220 PAUSE 0: LET z$=INKEY$: IF z$="1" OR z$="2" THEN GO TO 90
  230 IF z$="0" THEN GO TO 50
 1000 DATA "Silent Night",1.8
 1010 DATA 7,8/3,9,8,7,4,4,4/3,7,8/3,9,8,7,4,4,4/3,14,2,14,4,11,4/3,12,2,12,4,7,4/3,9,2,9,4,12,8/3,11,8,9,4,7,8/3
 1020 DATA 9,8,7,4,4,4/3,9,2,9,4,12,8/3,11,8,9,4,7,8/2,9,8,7,4,4,4/3,14,2,14,4,17,4,14,4,11,4,12,4/3,16,1,12,4
 1030 DATA 7,4,4,4,7,4,5,4,2,4,0,1
 1200 DATA "Jingle Bells",.8
 1210 DATA 13,4,13,4,13,4,99,4,13,4,13,4,13,4,99,4,13,4,16,4,9,4,11,4,13,4/3,99,4,14,4,14,4,14,4,14,4,14,4,13,4
 1220 DATA 13,4,99,4,13,4,11,4,11,4,13,4,11,4,99,4,16,4,99,4,13,4,13,4,13,4,99,4,13,4,13,4,13,4,99,4,13,4,16,4
 1230 DATA 9,4,11,4,13,4/3,99,4,14,4,14,4,14,4,14,4,14,4,13,4,13,4,99,4,16,4,16,4,14,4,11,4,9,4,99,4,21,4,99,4
 1400 DATA "Joy to the World",2.5
 1410 DATA 24,4,23,5.33,21,16,19,2.67,17,8,16,4,14,4,12,8/3,19,8,21,2.67,21,8,23,2.67,23,8,24,2,99,16,24,8,24,8,23,8,21,8,19,8,19,5.33
 1420 DATA 17,16,16,8,24,8,24,8,23,8,21,8,19,8,19,5.33,17,16,16,8,16,8,16,8,16,8,16,8,16,16,17,16,19,16/5,99,16,17,16,16,16,14,8
 1430 DATA 14,8,14,8,14,16,16,16,17,16/5,99,16,16,16,14,16,12,8,24,4,21,8,19,5.33,17,16,16,8,17,8,16,4,14,4,12,2

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

Scroll to Top