--- title: "Beethoven" id: 55960 type: "computer_media" slug: "beethoven" url: "http://localhost/computer_media/beethoven/" markdown_url: "http://localhost/computer_media/beethoven.md" published_at: "2024-07-14T12:51:59+00:00" modified_at: "2026-03-30T21:41:06+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/07/beethoven.jpeg" caption: "Oil painting vintage cassette inlay art, Drew Struzan style airbrushed acrylic, heroic portrait of Ludwig van Beethoven in dramatic three-quarter profile, wild silver hair and fierce passionate gaze, conducting baton raised against a blazing orchestral hall, swirling choral singers in montage vignette below, glowing musical staves and notes radiating outward like fire, rich warm golds and deep cobalt blues, fiery orange spotlights, chrome-like sheen on brass instruments, triumphant Ode to Joy energy, dynamic diagonal composition, painterly photorealistic finish, warm dramatic lighting, 1980s Ocean Software cassette cover aesthetic --ar 3:4 --raw --v 6 Job ID: 903b2c75-87f2-47c4-bc55-c0a47838e61c" excerpt: "A full choral arrangement of \"Ode to Joy\" plays syllable by syllable, with melody, named chord accompaniment, and pitch-proportional lyric positioning all driven from a single DATA loop." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Music" slug: "music" taxonomy: "genre" url: "http://localhost/type/music/" media_contents: - id: 55923 title: "Timex Sinclair Public Domain Library Tape 2003" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-2003/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Beethoven%20%28198x%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/07/beethoven.jpeg" caption: "Oil painting vintage cassette inlay art, Drew Struzan style airbrushed acrylic, heroic portrait of Ludwig van Beethoven in dramatic three-quarter profile, wild silver hair and fierce passionate gaze, conducting baton raised against a blazing orchestral hall, swirling choral singers in montage vignette below, glowing musical staves and notes radiating outward like fire, rich warm golds and deep cobalt blues, fiery orange spotlights, chrome-like sheen on brass instruments, triumphant Ode to Joy energy, dynamic diagonal composition, painterly photorealistic finish, warm dramatic lighting, 1980s Ocean Software cassette cover aesthetic --ar 3:4 --raw --v 6 Job ID: 903b2c75-87f2-47c4-bc55-c0a47838e61c" - url: "http://localhost/wp-content/uploads/2024/07/SCR-20240714-igmv.png" related_content: - id: 55967 title: "Endless Love" type: "computer_media" url: "http://localhost/computer_media/endless-love/" media_type_tags: "Music" --- # Beethoven 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 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. ## 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 ```