CHORDIZE is a utility that enriches BEEP-based music with three-voice triad chords using the TS2068’s AY-3-8912 sound chip, accessed via the SOUND command. The program provides 27 pre-calculated chord subroutines (lines 1005–1130) covering major, minor, diminished, and augmented triads, each setting the AY chip’s tone registers directly with raw frequency divider values for all three channels. A built-in demo at line 100 plays “Just a Closer Walk with Thee,” demonstrating how GOSUB calls to chord subroutines can be interspersed with BEEP statements for the melody. The program includes an optional printed staff diagram (subroutine 5000) referencing pitch numbering from a specific BASIC programming guide to assist with transcription from sheet music. Lines 1000 and 1001 configure the AY chip’s mixer and amplitude registers, while line 1999 silences all channels by zeroing the amplitude registers.
Program Analysis
Program Structure
The program is divided into four broad sections:
- Lines 1–50: Title screen, instructional text, chord index printout, and an automated demonstration that cycles through all chord subroutines in order.
- Lines 55–205: The built-in musical demo (“Just a Closer Walk with Thee”), using
READ/DATApairs for note duration and pitch, interspersed withGO SUBcalls to chord subroutines. Ends withLIST 100so the user can study the demo’s structure. - Lines 1000–1999: The chord library itself — 29 subroutines that write frequency-divider values directly into the AY chip’s tone registers via
SOUND. - Lines 5000–5030: Optional staff diagram subroutine (the “Blechman” chart), triggered from line 5 by pressing
B.
AY Chip Register Usage
Each chord subroutine writes six consecutive SOUND register pairs (registers 0–5) to set the 12-bit frequency dividers for channels A, B, and C. Because each channel’s divider spans two 8-bit registers (low byte in even register, high byte in odd), the pattern is always SOUND 0,lo_A;1,hi_A;2,lo_B;3,hi_B;4,lo_C;5,hi_C. The initialization subroutines at lines 1000 and 1001 configure the mixer register (register 7) and the amplitude registers (8, 9, 10), and also set the envelope shape (register 13).
| Register | Function |
|---|---|
| 0–1 | Channel A tone period (low/high) |
| 2–3 | Channel B tone period (low/high) |
| 4–5 | Channel C tone period (low/high) |
| 7 | Mixer control (tone/noise enables) |
| 8–10 | Channel amplitude / envelope enable |
| 11–12 | Envelope period |
| 13 | Envelope shape |
Line 1000 sets register 7 to 56 (binary 00111000), enabling all three tone channels while disabling noise. Line 1001 uses a slightly different configuration (register 7 = 56 but different amplitude values), suggesting a softer attack variant. Line 1999 silences the chip by zeroing amplitude registers 8, 9, and 10 while setting register 7 to 63 (all channels off).
Chord Subroutine Library
The 27 named chords span lines 1005 to 1130, plus an undocumented lower-octave D# diminished variant at line 1122. The frequency divider values implement equal-temperament triads one octave below the BEEP range, so they blend as accompaniment without clashing with the melody channel. The programmer notes in comments that minor chords are derived by flattening the third, and diminished chords drop the sixth or seventh to fit three voices.
| Line | Chord | Ch A (divider) | Ch B (divider) | Ch C (divider) |
|---|---|---|---|---|
| 1005 | A Major | 248 | 197 | 165 |
| 1015 | C Major | 209 | 165 | 139 |
| 1020 | D Major | 186 | 147 | 124 |
| 1030 | F Major | 156 | 124 | 104 |
| 1035 | G Major | 139 | 110 | 93 |
| 1050 | D Minor | 186 | 156 | 124 |
| 1065 | G Minor | 279 (23+256) | 234 | 186 |
| 1105 | B♭ Major | 234 | 186 | 156 |
| 1120 | D#/E♭ Dim | 175 | 117 | 124 |
For chords requiring a divider value greater than 255, the high byte register is set to 1 (e.g., G Minor channel A: SOUND 0,23;1,1 gives divider 23 + 256 = 279; G Augmented similarly uses 279 for its root).
Demo Playback Technique
The demo (lines 100–205) uses a FOR/READ/BEEP/NEXT loop pattern to play groups of notes from DATA statements, breaking the melody into phrases separated by GO SUB chord-change calls. Variable B is the loop counter and D, P hold duration and pitch. RESTORE at line 100 ensures the DATA pointer is reset. Some notes are played individually outside loops (e.g., line 140) for phrases too short or irregular to justify a loop.
Chord Cycling Demo (Lines 40–50)
Before the musical demo, lines 40–50 audition every chord subroutine in sequence. Variable N starts at 1005 and increments by 5 each iteration; GO SUB N is used as a computed subroutine call, a valid TS2068 BASIC technique. The loop terminates when N reaches 1125, at which point the musical demo begins.
Staff Diagram Subroutine (Lines 5000–5030)
Triggered by pressing B at the second instruction screen, this subroutine draws a five-line treble staff using PLOT and DRAW commands and annotates note positions with their corresponding BEEP pitch numbers (C=0, D=2, E=4, etc.). It references the pitch numbering system from chapter 16 of a BASIC programming guide (“Blechman”), providing a visual transcription aid. The finished chart is sent to a TS2040 thermal printer via COPY.
Notable Techniques and Idioms
- Computed
GO SUB:GO SUB Nat line 42 uses a numeric variable as the target, allowing all chord subroutines to be auditioned with a single incrementing loop. POKE 23658,8(line 2): Sets the system variable FLAGS2 bit 3, which enables the lower-case mode flag — likely ensuring consistent display behavior during the text-heavy instruction screens.- Line 165 mixer tweak:
SOUND 9,15mid-melody adjusts channel B amplitude independently, providing a brief dynamic variation without reloading the full chord. - Line 195 envelope use: Near the end of the demo, registers 1, 2, 8–10, and 13 are configured to apply an envelope shape to the final held note, adding a fade or swell effect.
- Two-byte dividers: Chords with roots below approximately 122 Hz require a high byte of 1 in the odd register; the programmer handles these consistently (lines 1065, 1095, 1122, 1130).
Bugs and Anomalies
- Line 1045 (F Minor): The subroutine ends with
SOUND 0,156;1,0;2,131;3,0;4,104, missing the trailing:5,0present in other subroutines. While the AY chip retains the previous value of register 5, this is an inconsistency that could cause channel C pitch to drift between chord changes if register 5 was previously set to a non-zero value. - Line 55 is missing: Line 45 jumps to line 55 (
GO TO 55), but line 55 does not exist in the listing; execution falls through to line 60. This is likely intentional (a well-known BASIC technique) since line 60 contains the correct continuation text about the demo listing. - Line 1125 comment says “Eb” but the REM at line 1075 also maps to E Dim: Lines 1075 and 1125 have identical register values (165, 139, 117), meaning the “Eb” chord at 1125 is acoustically identical to E Diminished at 1075. This appears to be a copy-paste oversight in the frequency calculations.
Content
Source Code
1 SOUND 7,63: BORDER 6: PAPER 6: CLS : PRINT AT 5,7; INVERSE 1; FLASH 1;"C H O R D I Z E R"; INVERSE 0; FLASH 0;AT 12,0; PAPER 5; BRIGHT 1;"ADDS TRIAD CHORDS TO BEEP MUSIC FOR EASY TRANSCRIPTION FROM SHEET MUSIC TO TS2068 "; PAPER 6; BRIGHT 0;AT 21,3;"PRESS ANY KEY TO CONTINUE"
2 POKE 23658,8
3 PAUSE 0: CLS : PRINT '''"USE ANY SYSTEM YOU LIKE TO ENTERBEEPS, BUT YOU WILL ALSO FLESH OUT BEEPS WITH ANY OF 27 CHORDS";' PAPER 2; INK 7;" AS YOU ENTER BEEPS! ": PAPER 6: INK 0
5 PRINT '''" FOR INSTANCE, USE BLECHMAN'S CHAPTER 16 OF ";'" BEGINNER/INTERMED-IATE GUIDE ": PRINT AT 20,0;"PRESS <B> TO COPY ALA BLECHMAN ANY OTHER KEY TO CONTINUE": PAUSE 0: IF INKEY$="B" THEN GO SUB 5000
8 CLS
10 PRINT ''"YOU WILL ENTER THE TOP NOTE FROMTHE TREBLE CLEFF AS THE LEAD TO BE BEEPED ONLY AFTER YOU HAVE GONE SUB TO THE PROPER CHORD."
12 PRINT ''"USUALLY CHORD ACCOMPANIMENT WILLSHOWUP ABOVE STAFF AT START OF AMEASURE BUT OCCASIONALLY WITHINSO BE ALERT FOR THIS. CHORD WILLCONTINUE TILL A CHANGE OF CHORD.YOU WILL GOSUB 1000 TO TURN ONTHE SOUND & GOSUB 1999 TO TURN OFF AT END OF TUNE."
15 PRINT AT 21,3;"PRESS ANY KEY TO CONTINUE": PAUSE 0: CLS
20 PRINT "BECAUSE THERE ARE ONLY 3 SOUND CHANNELS YOU WILL HAVE TO FORGET4 NOTE CHORDS SO IF YOU SEE G7, FOR INSTANCE, JUST USE G CHORD; THUS YOU WILL GET GBD INSTEAD OFGBDF# FOR THE CHORD--STILL MUCH NICER THAN PLAIN BEEPS."
22 PRINT '"DIMINISHED CHORDS WILL DROP THE 6TH or 7TH AUTOMATICALLY FOR A TRIAD."
25 PRINT '"SURELY YOU CAN DELETE LINES 1- 250 AND MERGE THE CHORD ROUTINE WITH YOUR OWN PROGRAMS OR USE THE TABLES pp. 186-7 OF 2068 MANUAL TO LOWER PITCH OF CHORDS."
28 PRINT '"AFTER TUNE BUILT DELETE CHORDS UNUSED; ABOUT 1/4 OF 27 NEEDED FOR A SIMPLE TUNE.";AT 21,8;"PRESS ANY KEY"
30 PAUSE 0: CLS : PRINT INVERSE 1;"TURN ON TS2040 TO COPY THIS INFO"; INVERSE 0;''"AT 1000--ON","AT 1005--A MAJ";'"AT 1010--B MAJ","AT 1015--C MAJ";'"AT 1020--D MAJ","AT 1025--E MAJ";'"AT 1030--F MAJ","AT 1035--G MAJ"
32 PRINT '"MINOR, DIMINISHED, & AUGMENTED;";''"AT 1040--C MIN","AT 1045--F MIN";'"AT 1050--D MIN","AT 1055--A MIN";'"AT 1060--E MIN","AT 1065--G MIN";'"AT 1070--B DIM","AT 1075--E DIM"
34 PRINT "AT 1080--D DIM","AT 1085--F AUG";'"AT 1090--D AUG","AT 1095--G AUG";'"AT 1100--C AUG","AT 1105--Bb MAJ";'"AT 1110--B MIN","AT 1115--F# MIN";'"AT 1120--D# DIM OR Eb DIM"
36 PRINT "AT 1125--Eb","AT 1130--Ab";'"AT 1999--OFF"
38 PRINT '"PRESS ANY KEY TO COPY": PAUSE 0: COPY
40 CLS : LET N=1005: PRINT AT 0,1;"PLAYING CHORD CHOICES FOR YOU";''"PROP 2068 ONE INCH OFF DESK TO CLEAR SPEAKER FOR BEST TONE! ": GO SUB 1000
42 GO SUB N: PAUSE 90
45 LET N=N+5: IF N=1125 THEN CLS : SOUND 7,63: PRINT AT 5,0;"PLAYING DEMO:"; PAPER 5; '"""JUST A CLOSER WALK""": GO TO 55
50 GO TO 42
60 PRINT '"PROG WILL LIST DEMO TO SHOW HOW TO USE READY-MADE CHORDS AS YOU ENTER BEEPS."
100 RESTORE : REM DEMO FOR "CHORDIZE"
105 GO SUB 1001: GO SUB 1015
110 FOR B=1 TO 6: READ D,P: BEEP D,P: NEXT B
115 DATA 1.5,7,.5,8,.5,9,.5,4,.5,7,.5,6
120 GO SUB 1050: GO SUB 1030: FOR B=1 TO 7: READ D,P: BEEP D,P: NEXT B
125 DATA 2,5,1.5,14,.5,12,.5,11,.5,7,.5,9,.5,12
130 GO SUB 1015: FOR B=1 TO 9: READ D,P: BEEP D,P: NEXT B
135 DATA .25,12,.25,9,1.5,7,1.5,16,.5,16,.5,16,.5,12,.5,14,.5,16
140 GO SUB 1030: BEEP .25,16: BEEP .25,14: BEEP 2,12: GO SUB 1020: BEEP .5,12: BEEP .5,9: GO SUB 1015: BEEP 1.5,7: BEEP .5,7
145 GO SUB 1035: BEEP 1,7: BEEP .5,7: BEEP .5,7
150 GO SUB 1015: BEEP 3,7: BEEP 3,16: BEEP .5,16: BEEP .5,15: GO SUB 1050: BEEP 3,14
155 GO SUB 1035: FOR B=1 TO 8: READ D,P: BEEP D,P: NEXT B
160 DATA 1.5,14,.5,7,1,9,.5,12,.5,11,.5,7,.5,9,.5,12
165 SOUND 9,15: GO SUB 1015: FOR B=1 TO 9: READ D,P: BEEP D,P: NEXT B
170 DATA .25,12,.25,9,2.5,7,1.5,16,.5,16,.5,16,.5,12,.5,14,.5,16
175 GO SUB 1030: BEEP .25,16: BEEP .25,14: BEEP 2,9: GO SUB 1020: BEEP 2,6: BEEP .5,12: BEEP .5,9
180 GO SUB 1015: BEEP 1.5,7: BEEP .5,7
185 GO SUB 1050: FOR B=1 TO 5: READ D,P: BEEP D,P: NEXT B
190 DATA 1.5,7,.5,7,.5,9,1,12,.5,12
195 GO SUB 1015: SOUND 1,1;2,75;3,1;8,10;9,15;10,5;13,13: BEEP 4,12
200 GO SUB 1999
205 LIST 100: STOP
1000 SOUND 7,56;8,15;9,15;10,15;11,255;12,255;13,13: RETURN : REM ON
1001 SOUND 7,56;8,15;9,16;10,12;11,128;12,128;13,9: RETURN : REM ON
1005 SOUND 0,248;1,0;2,197;3,0;4,165;5,0: RETURN : REM A MAJ
1010 SOUND 0,221;1,0;2,175;3,0;4,147;5,0: RETURN : REM B MAJ
1015 SOUND 0,209;1,0;2,165;3,0;4,139;5,0: RETURN : REM C MAJ
1020 SOUND 0,186;1,0;2,147;3,0;4,124;5,0: RETURN : REM D MAJ
1025 SOUND 0,165;1,0;2,131;3,0;4,110;5,0: RETURN : REM E 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
1040 SOUND 0,209;1,0;2,175;3,0;4,139;5,0: RETURN : REM C MINOR (FLAT THE 3RD ANY MINOR)
1045 SOUND 0,156;1,0;2,131;3,0;4,104: RETURN : REM F MINOR
1050 SOUND 0,186;1,0;2,156;3,0;4,124;5,0: RETURN : REM D MINOR D FNATURAL A
1055 SOUND 0,248;1,0;2,209;3,0;4,165;5,0: RETURN : REM A MIN
1060 SOUND 0,165;1,0;2,139;3,0;4,110;5,0: RETURN : REM E MIN
1065 SOUND 0,23;1,1;2,234;3,0;4,186;5,0: RETURN : REM G MIN
1070 SOUND 0,221;1,0;2,186;3,0;4,156;5,0: RETURN : REM B DIMINISHED FLAT 3RD & 5TH
1075 SOUND 0,165;1,0;2,139;3,0;4,117;5,0: RETURN : REM E DIM
1080 SOUND 0,186;1,0;2,156;3,0;4,131;5,0: RETURN : REM D DIM
1085 SOUND 0,156;1,0;2,124;3,0;4,98;5,0: RETURN : REM F AUGMENTED(MAJOR SHARP THE 5TH)
1090 SOUND 0,186;1,0;2,147;3,0;4,117;5,0: RETURN : REM D AUG
1095 SOUND 0,23;1,1;2,221;3,0;4,175;5,0: RETURN : REM G AUG
1100 SOUND 0,209;1,0;2,165;3,0;4,131;5,0: RETURN : REM C AUG
1105 SOUND 0,234;1,0;2,186;3,0;4,156;5,0: RETURN : REM B FLAT MAJ
1110 SOUND 0,221;1,0;2,186;3,0;4,147;5,0: RETURN : REM B MIN
1115 SOUND 0,147;1,0;2,124;3,0;4,98;5,0: RETURN : REM F# MIN
1120 SOUND 0,175;1,0;2,117;3,0;4,124;5,0: RETURN : REM D# DIM OR Eb DIM
1122 SOUND 0,95;1,1;2,39;3,1;4,248;5,0: RETURN : REM D# DIM(D#F#A)lower version
1125 SOUND 0,165;1,0;2,139;3,0;4,117;5,0: RETURN : REM Eb
1130 SOUND 0,7;1,1;2,209;3,0;4,175;5,0: RETURN : REM Ab
1999 SOUND 7,63;8,0;9,0;10,0: RETURN : REM OFF
5000 CLS : PRINT "D#=3;Bb=10;KEY UNIMPORTANT;HALF STEPS(12 EVERY OCTAVE) EACH HALF WORTH 1 IN PITCH ": LET X=60: LET Y=20: PLOT X,Y: DRAW 30,0
5005 FOR S=1 TO 5: LET Y=Y+24: PLOT X,Y: DRAW 150,0: NEXT S
5010 PRINT AT 4,18;"F 17";AT 5,8;"E 16";AT 7,18;"D 14";AT 8,8;"C 12";AT 10,18;"B 11";AT 11,8;"A 9";AT 13,18;"G 7";AT 14,8;"F 5";AT 16,18;"E 4";AT 17,8;"D 2";AT 19,5;"C 0";AT 20,8;"B -1"
5015 PRINT AT 19,10; PAPER 1; INK 5;"LINE BELOW STAFF"
5020 PRINT PAPER 3; INK 6;AT 4,0;"T";AT 5,30;"P";AT 6,2;"C";AT 7,0;"R";AT 8,30;"I";AT 9,2;"L";AT 10,0;"E";AT 11,30;"T";AT 12,2;"E";AT 13,0;"B";AT 14,30;"C";AT 15,2;"F";AT 16,0;"L";AT 17,30;"H";AT 19,0;"E"
5025 PRINT PAPER 5; BRIGHT 1;AT 21,10;"ALA BLECHMAN": PAPER 6: BRIGHT 0: COPY
5030 RETURN
9997 STOP : REM to enable Channel A:}7,62;B-SOUND 7,61;C-SOUND 7,59;A & B-SOUND 7,60;A & C-SOUND 7,58;B & C-SOUND 7,57;A,B,C--SOUND 7,56 MOST FREQUENT
9998 CLEAR : SAVE "CHORDIZE" LINE 1
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
