This program plays Beethoven’s “Ode to Joy” with synchronized lyrics and chord accompaniment using the TS2068’s SOUND command. The main loop at line 75 reads four values per syllable — a lyric string, a chord subroutine line number, a duration, and a pitch offset — then prints the lyric at a horizontally scaled position and calls BEEP for the melody note. Chord voicings are programmed directly into the AY-3-8910 sound chip registers via SOUND, with named chords including F Major, C Major, A Major, B-flat Major, G Minor, and D Minor; subroutine 1900 is a no-op RETURN used to sustain the previous chord. The TAB INT(P*1.5) expression in line 100 gives a rough visual indication of pitch by indenting lyrics proportionally to their pitch value. POKE 23692,255 at line 50 suppresses the “scroll?” prompt that would otherwise interrupt the lyric display.
Program Analysis
Program Structure
The program is organized into three distinct regions: an introduction/title display (lines 5–10), a main playback loop (lines 75–270), and a set of chord subroutines (lines 1000–1999). Line 450 handles cleanup, silencing the sound chip and clearing the screen before stopping. The overall flow is linear — the loop at line 75 iterates 96 times, consuming all DATA entries, then falls through to line 450.
Main Playback Loop
Line 75 opens a FOR B=1 TO 96 loop. Each iteration READs four values: L$ (a lyric syllable), C (the line number of the chord subroutine), D (BEEP duration in seconds), and P (a pitch semitone offset used both for melody and visual layout). Line 100 prints the syllable at a tab position of INT(P*1.5), which maps the melody pitch loosely to a horizontal column, giving a crude visual contour of the melody. The chord subroutine is called via GO SUB C, then BEEP D,P sounds the melody note.
Chord Subroutines and SOUND Usage
Each subroutine from line 1005 to 1105 programs the AY-3-8910 chip registers directly using the SOUND command (TS2068 keyword). Registers 0–5 set the tone periods for channels A and B in pairs (low byte, high byte), producing two-voice chord voicings. Register 7 controls the mixer, and registers 8–13 set channel amplitudes. The subroutines are labeled by chord name in REMs:
| Line | Chord | Notes |
|---|---|---|
| 1005 | A Major | Channels A & B |
| 1015 | C Major | Channels A & B |
| 1030 | F Major | Channels A & B |
| 1035 | G Major | Channels A & B |
| 1050 | D Minor (D, F♮, A) | Channels A & B |
| 1065 | G Minor | Channels A & B |
| 1105 | B♭ Major | Channels A & B |
| 1900 | (sustain) | No-op RETURN |
Line 1000 sets up the AY mixer and amplitude registers (7–13) to enable tone output on two channels at a fixed volume. Line 1999 silences the chip by zeroing registers 7–10.
Notable Techniques
- GO SUB to a variable:
GO SUB CwhereCis a DATA value allows the chord to be selected entirely from the data stream without any conditional logic, keeping the loop compact. - Pitch-proportional TAB:
TAB INT(P*1.5)maps melody semitone values (0–12) to display columns 0–18, giving a visual pitch contour to the scrolling lyrics. - Scroll suppression:
POKE 23692,255at line 50 writes to the system variable CSCROLL, preventing the “scroll?” prompt from halting the display during the 96-iteration lyric output. - Sustained chord via no-op: Subroutine 1900 is simply
RETURN, leaving the AY registers unchanged so the previous chord continues sounding — an elegant way to hold a chord without extra logic. - Initialization subroutine: Line 1000 configures the AY mixer and volume registers once at startup; subsequent chord subroutines only update the tone period registers, relying on the mixer state set earlier.
Data Organization
The 96 syllables of the song are stored as comma-separated DATA across lines 125–270. Each record is a 4-tuple: (lyric$, chord_line, duration, pitch). Hyphenated syllables are split across separate DATA entries (e.g., “FREE-” and “DOM’S”), allowing fine-grained timing per syllable. Some DATA entries use L$="-" with a short duration to represent tied or continuation notes without printing a visible new word.
Bugs and Anomalies
- The REM on line 5 contains
QTR=.4, suggesting the author intended quarter-note duration to be 0.4 seconds; this is purely documentary and has no effect on execution. - Line 9997 (
STOP) is unreachable dead code that serves no functional purpose. - The pitch value for “THE EARTH.” (line 215) is 0 for the first instance and 5 for the second, meaning
BEEP D,0plays middle C — likely intentional as a phrase rest point rather than a bug. - Line 235 uses line number 1900 as the chord for “THE” and “AND”, sustaining the previous chord, which is musically appropriate at those lyric positions.
Content
Source Code
5 BORDER 1: INK 1: PAPER 6: CLS : PRINT AT 10,5;"""O D E T O J O Y""";AT 16,9;"WITH CHORDS": PAUSE 200: CLS : PRINT : REM QTR=.4
10 GO SUB 1000
50 POKE 23692,255
75 FOR B=1 TO 96: READ L$,C,D,P
100 PRINT TAB INT (P*1.5);L$: GO SUB C: BEEP D,P: NEXT B
125 DATA "SING",1030,.4,9
150 DATA "TO",1030,.4,9
155 DATA "JOY",1015,.4,10
160 DATA "AND",1030,.4,12
165 DATA "GLAD-",1015,.4,12,"NESS",1015,.4,10,"NOW",1030,.4,9
170 DATA "AND",1015,.4,7,"EV ",1030,.4,5,"ER",1030,.4,5
175 DATA "MORE",1015,.4,7,"TO",1050,.4,9,"FREE-",1030,.6,9,"DOM'S",1015,.2,7,"SONG.",1015,1,7
180 DATA "O-",1030,.4,9,"PEN",1030,.4,9,"UP",1030,.4,10,"OUR",1030,.4,12
185 DATA "HEART'S",1105,.4,12,"DE-",1105,.35,10,"SIRE",1105,.35,9,"WITH",1105,.35,7
190 DATA "LOVE",1030,.35,5,"THAT'S",1030,.35,5,"EV-",1015,.35,7,"ER-",1030,.35,9
195 DATA "LAST",1015,.52,7,"-",1030,.1,5,"ING.",1030,1,5
200 DATA "LET",1015,.35,7,"THIS",1015,.35,7,"MA-",1030,.35,9,"GIC",1030,.35,5
205 DATA "BRING",1015,.35,7,"TO",1015,.15,9,"-",1015,.1,10,"GETH-",1030,.35,9,"ER",1030,.35,5
210 DATA "ALL",1015,.35,7,"WHO",1015,.15,9,"-",1015,.1,10,"DWELL",1005,.35,9,"UP-",1005,.35,7,"ON",1050,.35,5
215 DATA "THE",1035,.35,7,"EARTH.",1015,.5,0,"ALL",1030,.7,9,"MAN-",1030,.35,9,"KIND",1030,.35,10,"SHALL",1030,.35,12
220 DATA "BE",1105,.35,12,"TO-",1105,.35,10,"GETH-",1105,.35,9,"ER",1105,.15,10,"AND",1105,.15,7
225 DATA "PEACE",1030,.35,5,"SHALL",1030,.35,5,"REIGN",1015,.35,7,"UP-",1030,.35,9
230 DATA "ON",1015,.5,7,"THE",1015,.15,5,"EARTH.",1030,.7,5
235 DATA "BLUE",1015,.35,7,"THE",1900,.35,7,"SKY,",1030,.35,9,"AND",1900,.35,5
240 DATA "GREEN",1015,.35,7,"THE",1900,.15,9,"-",1900,.1,10,"FOR-",1030,.35,9,"EST;",1900,.35,5
245 DATA "ALL",1015,.35,7,"OUR",1900,.15,9,"-",1900,.1,10,"CHIL-",1005,.35,9,"DREN",1900,.35,7
250 DATA "CAN",1050,.35,5,"RUN",1035,.35,7,"FREE",1015,.35,0,"AND",1030,1,9
255 DATA "THROUGH",1030,.35,9,"MU-",1105,.35,10,"SIC",1030,.35,12
260 DATA "BRING",1105,.35,12,"TO-",1900,.35,10,"GETH-",1900,.35,9,"ER",1065,.15,10,"-",1900,.1,7
265 DATA "ALL",1030,.35,5,"WHO",1900,.35,5,"SING",1015,.35,7,"THE",1030,.35,9
270 DATA "ODE",1015,.5,7,"TO",1030,.25,5,"JOY!",1900,1.5,5
450 GO SUB 1999: PAUSE 90: BRIGHT 0: PAPER 1: CLS : STOP
1000 SOUND 7,56;8,16;9,16;10,14;11,10;12,10;13,13: RETURN : REM ON
1005 SOUND 0,248;1,0;2,197;3,0;4,165;5,0: RETURN : REM A MAJ
1015 SOUND 0,209;1,0;2,165;3,0;4,139;5,0: RETURN : REM C MAJ
1030 SOUND 0,156;1,0;2,124;3,0;4,104;5,0: RETURN : REM F MAJ
1035 SOUND 0,139;1,0;2,110;3,0;4,93;5,0: RETURN : REM G MAJ
1050 SOUND 0,186;1,0;2,156;3,0;4,124;5,0: RETURN : REM D MINOR D FNATURAL A
1065 SOUND 0,23;1,1;2,234;3,0;4,186;5,0: RETURN : REM G MIN
1105 SOUND 0,234;1,0;2,186;3,0;4,156;5,0: RETURN : REM B FLAT MAJ
1900 RETURN : REM SAME CHORD
1999 SOUND 7,63;8,0;9,0;10,0: RETURN : REM OFF
9997 STOP
9998 CLEAR : SAVE "BEETHOVEN" LINE 1
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

