Beethoven

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

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:

LineChordNotes
1005A MajorChannels A & B
1015C MajorChannels A & B
1030F MajorChannels A & B
1035G MajorChannels A & B
1050D Minor (D, F♮, A)Channels A & B
1065G MinorChannels A & B
1105B♭ MajorChannels 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 C where C is 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,255 at 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,0 plays 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

Appears On

One of a series of library tapes. Programs on these tapes were renamed to a number series. This tape contained

Related Products

Related Articles

Related Content

Image Gallery

Beethoven

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.

People

No people associated with this content.

Scroll to Top