Classic Computer Magazine Archive COMPUTE! ISSUE 37 / JUNE 1983 / PAGE 122


MusicMaster

For The

Commodore 64


Chris Metcalf and Marc Sugiyama

This excellent program simulates a realtime, full function, synthesizer control panel for Commodore 64 sound and music. Your keyboard becomes the connection between you and the sounds you hear. The screen displays a double piano keyboard and the status of the other elements of the sounds you are creating.
    MusicMaster's functions include: slide, one-key access to all the primary chords, timbre, envelope, duration, octave, maintain, polyphony, waveform, and others. All available immediately and automatically from the keyboard.
    The power and versatility of the 64's "music synthesizer on a chip" offer the programmer-musician extraordinary control over sound: its shape, color, even interactions between sounds (modulation). There is much freedom, but this also means that there are many aspects of each sound for the programmer to control. MusicMaster automates this control: for example, you can play chords as easily as single notes. Above all, you'll learn the meaning of the various sound registers - because you'll hear the effect as you change the registers. Now you can begin to fully explore the amazing sounds of the 64.

Enter the MusicMaster program into your Commodore 64 as you would enter any other BASIC program. MusicMaster includes two short machine language subroutines in DATA statements, so be certain that all those numbers are entered correctly. After you have entered and saved the program, run it. Be sure that the volume of your television or audio output device is turned up enough so that you can hear the computer.
    Shortly before the message "PLEASE STAND BY" has left the screen, the computer will display the instructions. Across the top of the screen, you will find a row of indicators. The first item on this row is the OCTAVE, which has a range from one to eight. This is followed by the VOICE number, which indicates the particular timbre of your output. After this is a series of letters which indicate the current mode of operation. These modes will be described below. The last indicator is the VOLUME, with a range of 0 to 15.

The Double Keyboard
Under the indicator line are the two musical keyboards. They indicate where on the computer's keyboard the musical keyboards can be found. The lower keyboard is a continuation of the upper keyboard; thus the lower set of keys plays the higher notes.
    Below the keyboards is a description of the functions assigned to the programmable function keys. The left column describes the unshifted function keys, and the right column describes the shifted function keys.
    Fl and F3: These keys allow you to change the volume of the music. Pressing F1 will increase the volume one step, and pressing F3 will decrease the volume one step. Notice how the VOLUME indicator changes as you press either one of these keys. Remember that the volume ranges from 0 to 15; 0 is completely silent, and 15 is the maximum volume.
    F4: Pressing F4 will change the status of the Maintain mode, indicated by the "M" in the indicator row. When this mode is in operation, the "M" will be in reverse field. When this mode is activated, the computer does not release the tones after the keys have been pressed. Instead, the tones continue until other keys are pressed. To silence all the voices, press the space bar.
    F6: This key changes the status of the Multivoice mode. This mode is indicated by the "V" in the indicator row. A reverse field "V" indicates that the mode is in operation. The Multivoice mode enables more than one voice to be played at the same time. The program "powers on" with this mode activated. If this mode is not activated, then one tone follows the next on the same voice, and chords cannot be played. This has some disadvantages, but it is useful in conjunction with the Slide mode. With this mode, you can have up to three simultaneous voices.
    F7 and F5: Pressing these keys changes the status of the Slide and Chord modes. They will be described below.
    F2: This key allows you to define your own waveforms.

Making Music
Once the program is ready, press the following key sequence: QWERTYUI. You should hear a C major scale. If you do not, check the program for typing errors. Now try this key sequence: IOP@'*(up arrow)(RUN/STOP)Z. This time you should hear the same scale, but one octave higher.
    Pressing the sequence ZXCVBNM, produces another scale one octave higher than the last. Now try pressing the keys QET all at once to get a C-major chord. Each note of this chord is assigned one voice. Since there are only three voices, the computer can accept only three keys at one time as input.
    If you want to change octaves, press the control key and a number from one to eight, one being the lowest octave and eight the highest. Some of the voices do not work well in very low octaves. Pressing the Commodore key and a number will change the VOICE number. This, too, has a range of one to eight.
    The Slide mode is very interesting. A reversefield "S" on the status row indicates that the Slide mode is active. The Slide mode will work regardless of the Multivoice and Maintain modes. When in this mode, the computer steps smoothly through the tones rather than moving by half tones as a piano would. This can produce an intriguing, eerie effect with the Maintain mode activated. For example, enter the Slide mode, make sure that the Maintain and Multivoice modes are activated, and press the following key sequence: QETIP*ZCB, . As always, you can silence the voices by pressing the space bar.

Forming Chords
Another mode of operation is the Chord mode. This allows for single key control over different types of chords and their inversions. Once you activate the Chord mode, a second indicator row appears. On the left is the chord name, and on the right is the chord position - root, first inversion, or second inversion.
    The root chord is a chord in which the lowest note is also the key of the chord. For example, the C major triad is formed using the notes C, E, and G. When the notes are in that order, CEG, the chord is a root chord. If the notes of the chord start on a different note than C, then we have the inversions of the chord. For example, E and G, with high C, is the first inversion, and G, with high C and E, is the second inversion.
    To change the chord type, press the shift-key and a number from one to nine. The chords which are available correspond to the following numbers: (1) Major; (2) Minor; (3) Diminished; (4) Aug mented; (5) Major Seventh; (6) Minor Seventh; (7) Dominant Seventh; (8) Major Sixth; (9) Minor Sixth.
    The inversions are selected by pressing the shift key and the plus sign for root, the minus sign for the first inversion, and the pound sign for the second inversion.
    In order to play a chord, you must first select the chord type and inversion that you want, and then press the note on the keyboard which cor responds to the lowest note of your chord. For example, if you want to play a D flat minor second inversion chord, enter the Chord mode, select the minor chord and the second inversion (by pressing shift-2 and shift-pound-sign) and press "R", which corresponds to the note F on the musical keyboard. The chord that you will hear is comprised of the following notes: F, B flat, and high D flat. (Since the Slide mode can slide only one voice at a time, the Chord and Slide modes are incompatible, so turning on one automatically turns off the other.)

Attack, Decay, Sustain, Release
To define your own waveform, press F2. Once you are in this mode, the computer asks a series of questions that apply to the construction of a new waveform. The first question is which waveform you wish to change. Pressing RETURN with no other input returns program control to the play mode. After this question, the computer displays the current Attack, Decay, Sustain, and Release values, and asks for new values. Pressing RETURN with no other input or giving a bad input returns you to the first question.

The Envelope
the envelope

    The attack rate is the time that it takes the sound to reach its highest volume level. The larger the number, the more time it takes. Decay is the time it takes the sound to drop to the Sustain volume level. Sustain is the volume level at which the sound remains until the Release is initiated. The Release rate is the time that it takes the sound to soften from the sustain level to silence (see the figure).
    After these questions, the computer asks for the waveform type. You must enter the first letter of the type of waveform desired. If the Pulse waveform is selected, then the pulse rate must be entered. The authors of the Commodore 64 manual have written the pulse value as two numbers, the LOW pulse and the HIGH pulse. To obtain a single value for the pulse rate, take the HIGH pulse times 256 and add it to the LOW pulse. Once these questions have been answered, the computer returns to the playing mode with the voice set to the one you have just modified.

Program Structure
    The mechanics are fairly simple since most of the program is written in BASIC. The REMs identify the major sections of the program (see the table for a description of variables). However, some programming tricks are used. The POKE214,X command moves the cursor to line X on the screen. But a PRINT with no statement must follow this POKE or the cursor will not move to its new location. A POKE 788,53 disables the RUN/STOP key, but this can be annoying when listing programs. To re-enable the RUN/STOP key, POKE 788,49. WAIT is also employed when waiting for input (WAIT 198,255).

Variables

A     miscellaneous
A$    miscellaneous
AD    attack/decay for define waveform routine
AD()  table of attack/decay values
BF    constant pointer to buffer (198)
C$()  table of chord names
C()   table of chord note offsets
C1    chord number
C2    chord inversion
CH    chord mode flag
ER    INPUT routine error flag
ET    constant pointer for multikey input routine
FF    constant 255
FH()  table of high bytes of frequencies
FL()  table of low bytes of frequencies
HB    256 constant
I     miscellaneous
IK    constant for "inkey" or keyboard matrix value
IN    value for input from INPUT routine
IN$   input string from INPUT routine
J     miscellaneous
K()   conversion table for ASCII values
LL    polyphonic flag
LN$   constant line
MN    multivoice flag
NH    constant high byte location 901
NL    constant low byte location 900
NM$() "root," "first," or "second" (for chord inversion
      
display
OC    number of half steps offset (octave)
P     maintain mode flag
PH()  table of pulse high bytes
PL()  table of pulse low bytes
PU    pulse rate for define waveform routine
R     frequency number and miscellaneous
RA    slide mode register start pointer
RB    slide mode register end pointer
S     constant 54272
S1    constant 49152 (for multikey GET rou tine)
S2    constant 49403 (for music loader routine)
SL    slide mode flag
SP$   constant 39 spaces (for blanking)
SR    sustain/release value for define waveform routine
SR()  table of sustain/release values
T     current base address of SID
T()   table of last used base locations
V     computer voice number
VL    volume
VN    constant voice number location for music loader
     
251)
WF    waveform holder for define waveform routine
WV    current waveform
WV()  table of waveform values

All variables beginning with "Z" are low numeric constants.



    The SYSS1 (to 49152) is a full keyboard scan routine for the Commodore 64. This routine is very useful because it allows the user to enter more than one key at a time.
    The machine language routine returns the ASCII values of the keys being pressed to addresses 830, 831, and 832. (Due to a hardware problem involving the way the keyboard is wired, certain combinations of keys yield incorrect values.) The number of keys being pressed is stored in location 829. This routine could be used by games in which a multiple input is required. It could also be adapted to work on other Commodore computers, such as the VIC-20 and the PET/CBM series.
    A second machine language subroutine simply loads the values from 900-906 into the appropriate voice in the sound chip. Select the increment for voices 0, 1, and 2 (0, 7, or 14), POKE 251 with this value, then SYS(49408). The subroutine does not start the note, but leaves it to BASIC, via a POKE to the sound chip (SID), for the corresponding voice.
    If you find any problems in this program, or can offer any improvements or comments, please write to either of us at the addresses listed below. If you do not want to enter the program yourself, please send a standard (1541) floppy disk or a cassette tape, a self-addressed stamped mailer and $3 to either of the addresses listed below.

Chris Metcalf
123 Ardmore Rd.
Kennsington, CA 94707

Marc Sugiyama
5969 Chabolyn Terr.
Oakland, CA 94618

    Note: This program contains a number of characters which are not currently part of the listing conventions. To obtain any of the characters in the left column, type the keys indicated in the right column. ("Logo" indicates the Commodore logo key at the lower left of the keyboard.) For any underlined characters in the listing, see the table in "How To Type COMPUTE!'s Programs."

{ORG} LOGO & 1  {LTG} LOGO & 6
{BRN} LOGO & 2  {LTB} LOGO & 7
{LTR} LOGO & 3  {GY3} LOGO & 8
{GY1} LOGO & 4   {C}  CTRL & C
{GY2} LOGO & 5   {X}  CTRL & X


MusicMaster

200 GOTO460
210 :
220 :
230 REM SLIDE SUBROUTINE
240 IFRA<0THENRA=R
250 RB=R:T=S+V*Z7:POKEVN,V*Z7:POKENL,FL(RA
    )
:POKENH,FH(RA):SYSS2:POKET+Z4,WV
   
+Z1
260 FORI=RATORBSTEPSGN(RB-RA)/2:POKET,FL(I
   
):POKET+1,FH(I):NEXT
270 IFPEEK(IK)=JANDPEEK(IK)-64THEN270
280 RA=RB:POKET+Z4,WV+P:V=V+MN*(Z1+Z3*(V=Z
   
2)):RETURN
290 :
300 REM CHORD SUBROUTINE
310 POKEBF,Z0:FORI=ZOTOZ2:A=R+C(C1,C2,I):P
   
OKEVN,I*Z7:POKENL,FL(A)
320 POKENH,FH(A):SYSS2:NEXT:POKES+Z4,WV+Z1
   
:POKES+11,WV+ZI:POKES+18,WV+Z1
330 IFPEEK(IK)=JANDPEEK(IK)-64THEN330
340 POKES+Z4,WV+P:POKES+11,WV+P:POKES+18,W
   
V+P:RETURN
350 :
360 REM POLYPHONIC SUBROUTINE
370 A=PEEK(IK):SYSS1:J=PEEK(ET):IFJ=Z0ORA=
   
ZSTHENRETURN
380 FORI=ZITOJ:R=K(PEEK(ET+I))+OC:IFR=OCTH
   
ENNEXT:RETURN
390 T(I)=V*Z7:POKEVN,T(I):POKENL,FL(R):POK
   
ENH,FH(R):SYSS2
400 IFMNTHENV=V+ZI:IFV=Z3THENV=Z0
410 NEXT:FORI=Z1TOJ:POKES+T(I)+Z4,WV+Z1:NE
   
XT
420 SYSS1:IFJ=PEEK(ET)ANDA=PEEK(IK)THEN420
430 FORI=Z1TOJ:POKES+T(I)+Z4,WV+P:NEXT:GOT
    O
370
440 :
450 :
460 REM INITIALIZE VARIABLES
470 PRINT"{CLEAR}"CHR$(142);CHR$(8);:POKE5
   
3280,0:POKE53281,0:POKE788,52:REM
    
IGNORE RUN/STOP
480 FORI=1TO39:SP$=SP$+" ":LN$=LN$+"#":NEX
   
T
490 PRINT"{WHT}OCTAVE=5 VOICE=1 :C:S:M:(
   
REV}V{OFF}:{REV}P{OFF}: VOLUME=10
   
{RIGHT}"LN$
500 POKE214,23:PRINT:PRINTTAB(15)"MUSICMAS
   
TER{HOME}{02 DOWN)
510 A$="PLEASE STAND BY(WHT}":POKE214,21:P
   
RINT:PRINTTAB(13)"(GRN}"A$:S=5427
   
2:GOSUB1580
520 DIMFL(134),FH(134),K(255),C(8,2,2):OC=
   
48:VL=10:MN=1:LL=1:RA=-1
530 Z1=1:Z2=2:Z3=3:Z4=4:Z7=7:ZS=64:FF=255:
   
HB=256
540 IK=197:BF=198:VN=251:NL=900:NH=901:ET=
   
829:S1=49152:S2=49408:FORI=Z1TO41
550 K(ASC(MID$("Q2W3ER5T6Y7UI9O0P@-*£↑{
   
HOME}{C}ZSXDCVGBHNJM,L.:/",I)))=I:NEXT
560 PRINTTAB(13)"{CYN}(UP}"A$:R=5.8:A=1078
   
7.4138:J=Z2(-Z1/12)
570 FORI=94TO0STEP-1:FH(I)=INT(A*R/HB):FL(
   
I)=A*R-HB*FH(I):A=A*J:NEXT
580 PRINTTAB(13)"(UP}"A$:GOSUB1310
590 :
600 REM READ ALL DATA
610 FORI=Z0TO8:FORD=Z0TOZ2:READC(I,J,0),C(
   
I,J,1),C(I,J,2):NEXT:READC$(I):NEXT
620 READNM$(0),NM$(1),NM$(2):FORI=1TO8:REA
   
DAD(I),SR(I),WV(I),PL(I),PH(I):NEXT
630 FORR=1TO2:READI,J:FORA=ITOJ:READIN:POK
   
EA,IN:NEXT:NEXT
640 PRINTTAB(9)"{DOWN}(USE CONTROL-X TO EX
   
IT)":I=1:GOSUB860
650 :
660 :
670 REM NUCLEUS
680 WAITBF,FF:J=PEEK(IK):GETA$:R=K(ASC(A$)
   
+OC:IFR=OCTHENGOSUB800:GOTO680
690 IFSLTHENGOSUB240:GOTO680
700 IFCHTHENGOSUB310:GOTO680
710 IFLLTHENGOSUB370:GOTO680
720 T=S+V*Z7:POKEVN,V*Z7:POKENL,FL(R):POKE
   
NH,FH(R):SYSS2:POKET+Z4,WV+Z1
730 IFMNTHENV=V+ZI:IFV=Z3THENV=Z0
740 IFPEEK(IK)=JANDPEEK(IK)-64THEN740
750 POKET+Z4,WV+P:WAITBF,FF:GETA$:J=PEEK(I
   
K):R=K(ASC(A$))+OC:IFR-OCTHEN720
760 GOSUB800:GOTO680
770 :
780 :
790 REM PARAMETER FUNCTIONS
800 IFCH=0THEN830
810 FORI=0T02:IFA$=MID$("[])",I+1,1)THENC2
   
=I:PRINT"{HOME}{DOWN}"TAB(23)NM$(
   
I):RETURN
820 NEXT:A=ASC(A$):IFA>32ANDA<42THENCI=A-3
   
3:PRINT"{HOME}{DOWN}"TAB(11)C$(Cl
   
):RETURN
830 FORI=1TO8:IFA$<>MID$("{BLK}{WHT}{RED}{
   
CYN}(PUR}{GRN}{BLU}{YEL}",I,1)THE
   
NNEXT:GOTO850
840 OC=12*(I-Z1):PRINT"{HOME}"TAB(7)MID$(S
   
TR$(I),2):RETURN
850 FORI=1T08:IFA$<>MID$("{ORG}{BRN}{LTR}{
   
GY1}{GY2}{LTG}{LTB}{GY3}",I,1)THEN
   
NEXT:GOTO880
860 POKE902,PL(I):POKE903,PH(I):WV=WV(I):P
   
OKE904,WV:POKE905,AD(I):POKE906,S
   
R(I)
870 PRINT"{HOME}"TAB(16)MID$(STR$(I),2):RE
   
TURN
880 IFA$<>"{Fl}"ANDA$<>"{F3}"THEN930
890 VL=VL-(VL<15ANDA$="{F1}")+(VL>0ANDA$="
   
{F3}"):POKES+24,VL
900 PRINT"{HOME}"TAB(37)RIGHT$("0"+MID$(ST
   
R$(VL),2),2):RETURN
910 :
920 REM STYLE FUNCTIONS
930 IFA$="{F4}"THENP=1-P:POKE1047,13+128*P
   
:GOTO1580
940 IFA$="{F6}"THENMN=1-MN:POKE1049,22+128
   
*MN:GOTO1580
950 IFA$="{F8}"THENLL=1-LL:POKE1051,16+128
   
*LL:RETURN
960 IFA$="{F7}"THENSL=1-SL:RA=-1:POKE1045,
   
19+128*SL:CH=1:GOTO990
970 IFA$<>"{F5}"THEN1010
980 POKE1045,19:SL=0
990 CH=1-CH:POKE1043,3+128*CH:IFCH=0THENPR
   
INT"{HOME}{DOWN}"LN$:PRINTSP$:RET
   
URN
1000 PRINT"{HOME}{DOWN}"SP$"{RIGHT}{UP}CHOR
   
D TYPE:"C$(Cl)TAB(23)NM$(C2)" INV
   
ERSION{RIGHT}"LN$:RETURN
1010 IFA$=" "THENGOSUB1580:RA=-1:POKEBF,Z0:
   
RETURN
1020 IFA$="{X}"THENGOSUB1580:PRINT"{CLEAR}"
   
;:POKE788,49:END
1030 IFA$<>"{F2}"THENRETURN
1040 :
1050 :
1060 REM DISPLAY WAVEFORM PARAMETERS
1070 GOSUB1470:POKE214,13:PRINT
1080 PRINT"VOICE TO BE DEFINED (1-8)";:J=1:
   
GOSUB1500
1090 IFIN<1ORIN>STHENGOSUB1470:GOT01400
1100 I=IN:PRINTTAB(31)"ATT:"MID$(STR$(INT(A
   
D(I)/16)),2)
1110 PRINTTAB(31)"DEC:"MID$(STR$(AD(I)AND15
   
),2)
1120 PRINTTAB(31)"SUS:"MID$(STR$(INT(SR(I)/
   
16)),2)
1130 PRINTTAB(31)"REL:"MID$(STR$(SR(I)AND15
   
),2)
1140 PRINTTAB(31)"WVF:{CYN}"MID$("SAWTRIPUL
   
NSE",3*LOG(WV(I))/LOG(2)-11,3)"{WHT}
1150 IFWV(I)=64THENPRINTTAB(31)"PLS:"MID$(S
   
TR$(PH(I)*HB+PL(I)),2)
1160 :
1170 REM DEFINE A NEW WAVEFORM
1180 POKE214,14:PRINT:PRINT"ATTACK RATE (0-
   
15)";:J=2:GOSUB1500:IFERTHEN1070
1190 AD=IN:PRINT"DECAY RATE (0-15)";:GOSUB1
   
500:IFERTHEN1070
1200 AD=AD*16ORIN:PRINT"SUSTAIN LEVEL (0-15
    )
";:GOSUB1500:IFERTHEN1070
1210 SR=IN:PRINT"RELEASE RATE (0-15)";:GOSU
   
B1500:IFERTHEN1070
1220 SR=SR*16ORIN:PRINT"{CYN}S{WHT}AW {CYN}
   
T(WHT)RIANGLE {CYN}P{WHT}ULSE {
   
CYN}N{WHT}OISE";:J=1:GOSUB1500
1230 FORJ=1TO4:IFIN$<>MID$("STPN",J,1)THENN
   
EXT:GOTO1070
1240 WF=2(J+3):IFWF<>64THEN1260
1250 PRINT"PULSE RATE (0-4095)";:J=4:GOSUB1
   
500:PU=IN:IFIN<0ORIN>4095THEN1070
1260 WV(I)=WF:PL(I)=PU-HB*INT(PU/HB):PH(I)=
   
INT(PU/HB):AD(I)=AD:SR(I)=SR
1270 GOSUB1470:GOSUB1410:GOT0860
1280 :
1290 :
1300 REM DISPLAY KEYBOARDS
1310 POKES+24,VL:PRINT"{HOME}{03 DOWN}"TAB(
   
9)"'{REV} {RIGHT} {RIGHT} ] {
   
RIGHT} {RIGHT} {RIGHT} ] {RIGHT} ~
   
{RIGHT} ] {RIGHT} {RIGHT} {RIGHT}
     "
1320 PRINT"  LOW    '{REV} {OFF}2{REV} {
   
OFF}3{REV} ] {OFF}5{REV} {OFF}6{
   
REV} {OFF}7{REV) ] {OFF}9{REV} {
   
OFF}0{REV} ] (OFF}-{REV} {OFF)£{
   
REV} S "
1330 PRINT"KEYBOARD '{REV} ] ] ] ] ] ] ] ]
   
] ] ] ] ] "
1340 PRINTTAB(9)"'{REV}Q]W]E]R]T]Y]U]I]O]P]
   
@]*]r] "
1350 PRINTTAB(13)"{DOWN}*{REV} {RIGHT) {
   
RIGHT} ] {RIGHT} {RIGHT} {RIGHT) ~
   
] {RIGHT} {RIGHT} {OFF}4"
1360 PRINT" HIGH        *{REV) {OFF}S{REV}
   
{OFF}D{REV} ] {OFF}G{REV} {OFF}H{
   
REV} {OFF}J{REV} ] {OFF}L{REV} {
   
OFF}:{REV} {OFF}4"
1370 PRINT"KEYBOARD     '{REV} ] ] ] ] ] ]
   
] ] ] {OFF}4"
1380 PRINTTAB(13)"_*{REV}Z]X]C]V]B]N]M],].]/
   
{OFF}4"
1390 :
1400 REM DISPLAY FUNCTION MENU
1410 POKE214,13:PRINT:PRINT"F1 -- LOUDER
     
F2 -- DEFINE WAVEFORM
1420 PRINT"{DOWN}F3 -- SOFTER     F4 -- {
   
CYN}MAINTAIN{WHT)
1430 PRINT"{DOWN)F5 -- {CYN}CHORDS{WHT)
    
F6 -- {CYN}MULTIVOICE(WHT)
1440 PRINT"{DOWN}F7 -- {CYN}SLIDES{WHT}
    
F8 -- {CYN}POLYPHONIC{WHT}":RETURN
1450 :
1460 REM CLEAR DISPLAY AREA
1470 POKE214,12:PRINT:FORJ=1TO11:PRINTSP$:N
   
EXT:RETURN
1480 :
1490 REM INPUT SUBROUTINE
1500 IN$="":PRINT"? ";
1510 PRINT"{REV} {OFF}{LEFT}";:WAITBF,FF:
   
GETA$:IFA$="{X}"THEN1020
1520 A=ASC(A$):IFA=13THENPRINT" ":IN=VAL(IN
   
$):ER=(IN<0ORIN>15)ORIN$="":RETURN
1530 IFA=20ANDLEN(IN$)THENPRINT" {02 LEFT}
   
{LEFT}";:IN$=LEFT$(IN$,LEN(IN$)-1)
1540 IF(AAND127)<35ORLEN(IN$)=JTHEN1510
1550 PRINTA$;:IN$=IN$+A$:GOTO1510
1560 :
1570 REM CLEAR MUSIC CHIP
1580 FORI=4TO18STEP7:POKES+I,0:NEXT:FORI=0T
   
O23:POKES+I,0:NEXT:RETURN
1590 :
1600 :
1610 REM CHORD DATA
1620 DATA,4,7,,3,8,,5,9,"MAJOR      ",,3,7,,
   
4,9,,5,8,"MINOR     "
1630 DATA,3,6,,3,9,,6,9,"DIMINISHED",,4,8,,
   
4,8,,4,8,"AUGMENTED "
1640 DATA,4,11,,4,11,,4,11,"MAJOR 7TH ",,3,
   
10,,3,10,,3,10,"MINOR 7TH "
1650 DATA,4,10,,4,10,,4,10,"DOMIN 7TH",4,7,
   
9,4,7,9,4,7,9,"MAJOR 6TH "
1660 DATA3,7,9,3,7,9,3,7,9,"MINOR 6TH","  R
   
OOT","  FIRST",SECOND
1670 :
1680 REM WAVEFORM PARAMETER DATA
1690 DATA,249,16,,,,249,32,,,,249,64,160,15
    ,,
249,128,,,,240,16,,,204,204,16,,
1700 DATA,252,64,200,,192,240,32,,
1710 :
1720 REM MULTI-INPUT ASSEMBLY CODE
1730 DATA49152,49294,120,169,,141,61,3,170,
   
169,254,133,252,165,252,141,,220,173
1740 DATA1,220,157,143,192,232,56,38,252,17
   
6,239,162,,160,,189,143,192,42,176
1750 DATA29,72,132,253,138,10,10,10,5,253,1
   
68,185,79,192,238,61,3,172,61,3,153
1760 DATA61,3,104,192,3,240,12,164,253,200,
   
192,8,208,219,232,224,8,208,209,88
1770 DATA96,17,135,134,133,136,29,13,20,0,6
   
9,83,90,52,65,87,51,88,84,70,67,54
1780 DATA68,82,53,86,85,72,66,56,71,89,55,7
   
8,79,75,77,48,74,73,57,44,64,58,46
1790 DATA45,76,80,43,47,94,61,1,19,59,42,92
   
,3,81,2,32,50,4,95,49
1800 :
1810 REM MUSICLOADER ASSEMBLY CODE
1820 DATA49408,49454,169,212,133,252,169,,1
   
60,6,145,251,136,145,251,170,169,8
1830 DATA136,145,251,138,145,251,136,192,1,
   
208,249,188,41,193,185,132,3,145,
   
251
1840 DATA232,224,6,208,243,96,2,3,,1,6,5