100 REM ========================================================= 110 REM 1MATOP 120 REM ========================================================= 130 REM These subroutines deal with single 2-d matrix 140 REM operations. MATRIX PRINT sends matrix data to the 150 REM screen in ordered rows and columns, MATRIX SCALAR 160 REM MULTIPLICATION multiplies each matrix element by 170 REM a constant value, and MATRIX TRANSPOSITION exchanges 180 REM matrix rows and columns. 190 REM ========================================================= 200 REM Variable Descriptions 210 REM D: full row counter 220 REM F: flag to print transposed matrix 230 REM M: scalar multiplication factor 240 REM X(n,n): matrix 1 to hold primary & multiplied data 250 REM Y(n,n): matrix 2 to hold transposed data 260 REM J1: loop index, pointer to matrix rows 270 REM J2: loop index, pointer to matrix columns 280 REM K9: subroutine loop index 290 REM L9: subroutine loop index 300 REM ========================================================= 310 REM ================== DRIVER PROGRAM ======================= 320 REM ========================================================= 330 DIM X(8,8),Y(8,8) 340 D = 0 350 F = 0 360 M = 8 370 PRINT "A 2-DIMENTIONAL MATRIX OF SEQUENTIAL NUMBERS --" 380 FOR J1 = 1 TO 8 390 FOR J2 = 1 TO 8 400 X(J1,J2) = J2 + D 410 NEXT J2 420 D = D + 8 430 NEXT J1 440 GOSUB 1000 '<< call matrix print 450 PRINT 460 GOSUB 2010 '<< call matrix scalar multiplication 470 PRINT 480 PRINT "MATRIX MULTIPLIED BY 8 --" 490 GOSUB 1000 '<< call matrix print 500 PRINT 510 GOSUB 3010 '<< call matrix transposition 520 PRINT 530 PRINT "TRANSPOSED MATRIX (ROWS & COLUMNS EXCHANGED) --" 540 GOSUB 1000 '<< call matrix print 550 PRINT 560 GOSUB 4000 '<< call matrix reset 570 PRINT "MATRICES RESET TO ZERO --" 580 GOSUB 1000 590 END 1000 REM ======================================================== 1010 REM ******************>> MATRIX PRINT <<******************** 1020 REM ======================================================== 1030 FOR K9 = 1 TO 8 1040 FOR L9 = 1 TO 8 1050 IF F = 0 THEN PRINT TAB(8*(L9-1))X(K9,L9); ELSE PRINT TAB(8*(L9-1))Y(K9,L9); 1060 NEXT L9 1070 PRINT 1080 NEXT K9 1090 RETURN 2000 REM ======================================================== 2010 REM **********>> MATRIX SCALAR MULTIPLICATION <<*********** 2020 REM ======================================================== 2030 FOR K9 = 1 TO 8 2040 FOR L9 = 1 TO 8 2050 X(K9,L9) = X(K9,L9) * M 2060 NEXT L9 2070 NEXT K9 2080 RETURN 3000 REM ======================================================== 3010 REM *************>> MATRIX TRANSPOSITION <<**************** 3020 REM ======================================================== 3030 FOR K9 = 1 TO 8 3040 FOR L9 = 1 TO 8 3050 Y(K9,L9) = X(L9,K9) 3060 NEXT L9 3070 NEXT K9 3080 F = 1 3090 RETURN 4000 REM ======================================================== 4010 REM ********************>> ZEROMAT <<*********************** 4020 REM ======================================================== 4030 REM This subroutine resets all matrix addresses to 0 4040 REM for further processing, or for initialization if 4050 REM required by your particular system. 4060 REM ======================================================== 4070 FOR K9 = 1 TO 8 4080 FOR L9 = 1 TO 8 4090 X(K9,L9) = 0 4100 Y(K9,L9) = 0 4110 NEXT L9 4120 NEXT K9 4130 RETURN
100 REM ========================================================= 110 REM 2MATOP 120 REM ========================================================= 130 REM These subroutines deal with operations on 140 REM two discrete matrices. MATRIX PRINT sends 150 REM each matrix to the screen, ADD MATRICES 160 REM adds corresponding address contents, and 170 REM MULTIPLY MATRICES multiplies address contents. 180 REM ========================================================= 190 REM Variable Descriptions 200 REM 210 REM D: full row counter 220 REM X(n,n): matrix 1 230 REM Y(n,n): matrix 2 240 REM Z(n,n): matrix holding operation result 250 REM J1: driver loop index, pointer to matrix rows 260 REM J2: driver loop index, pointer to matrix columns 270 REM K9: subroutine loop index 280 REM L9: subroutine loop index 290 REM 300 REM ========================================================= 310 REM ==================== DRIVER PROGRAM ===================== 320 REM ========================================================= 330 DIM X(10,10),Y(10,10),Z(10,10) 340 D = 0 350 FOR J1 = 1 TO 10 360 FOR J2 = 1 TO 10 370 X(J1,J2) = J2+D '<< fill with numbers 1-100 380 Y(J1,J2) = J2+D+100 '<< fill with nums 101-200 390 NEXT J2 400 D = D + 10 410 NEXT J1 420 GOSUB 1000 '<< print original matrices 430 PRINT 440 GOSUB 2000 '<< add matrix x to matrix y and print 450 PRINT 460 GOSUB 3000 '<< multiply matrix x by matrix y and print 470 END 1000 REM ======================================================== 1010 REM ******************>> MATRIX PRINT <<******************** 1020 REM ======================================================== 1030 PRINT "MATRIX X --" 1040 FOR K9 = 1 TO 10 1050 FOR L9 = 1 TO 10 1060 PRINT TAB(8*(L9-1))X(K9,L9); 1070 NEXT L9 1080 PRINT 1090 NEXT K9 1100 PRINT 1110 PRINT "MATRIX Y --" 1120 FOR K9 = 1 TO 10 1130 FOR L9 = 1 TO 10 1140 PRINT TAB(8*(L9-1))Y(K9,L9); 1150 NEXT L9 1160 PRINT 1170 NEXT K9 1180 RETURN 2000 REM ======================================================== 2010 REM ****************>> ADD MATRICES <<********************** 2020 REM ======================================================== 2030 PRINT "THE SUM OF MATRICES X & Y --" 2040 FOR K9 = 1 TO 10 2050 FOR L9 = 1 TO 10 2060 Z(K9,L9) = X(K9,L9) + Y(K9,L9) 2070 PRINT TAB(8*(L9-1))Z(K9,L9); 2080 NEXT L9 2090 PRINT 2100 NEXT K9 2110 RETURN 3000 REM ======================================================== 3010 REM ****************>> MULTIPLY MATRICES <<***************** 3020 REM ======================================================== 3030 PRINT "THE PRODUCT OF MATRICES X AND Y --" 3040 FOR K9 = 1 TO 10 3050 FOR L9 = 1 TO 10 3060 Z(K9,L9) = X(K9,L9) * Y(K9,L9) 3070 PRINT TAB(8*(L9-1))Z(K9,L9); 3080 NEXT L9 3090 NEXT K9 3100 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 111 REM (Addshufl) 120 REM ========================================================= 130 DIM TABLE(20),X(20) 140 TOTAL = 20 150 FOR J = 1 TO TOTAL 160 TABLE(J) = J '<< fill array with number sequence 170 X(J) = J '<< load pointer array 180 NEXT J 190 GOSUB 1000 200 FOR J = 1 TO TOTAL 210 PRINT TABLE(X(J));'<<send randomized table to screen 220 NEXT J 230 END 1000 REM ======================================================== 1010 REM *********************>> ADDSHUFL <<********************* 1020 REM ======================================================== 1030 REM This subroutine randomizes (shuffles) a list of 1040 REM pointers to a reference array. The original list 1050 REM of values remains unchanged for future access. 1060 REM Thus, many random reorderings may be accomplished 1070 REM without destroying the original list's prime order. 1080 REM ======================================================= 1090 REM Variable Descriptions 1100 REM 1110 REM Entering - 1120 REM TOTAL: number of values in the list 1130 REM X(): array of ordered address pointers 1140 REM Exiting - 1150 REM X(): randomized array of pointers to list 1160 REM Local - 1170 REM R9: random number 1180 REM S9: temporary storage variable 1190 REM K9: loop index, pointer to array X() 1200 REM 1210 REM ======================================================== 1220 RANDOMIZE 1230 FOR K9 = 1 TO TOTAL 1240 R9 = INT(RND * TOTAL) + 1 1250 S9 = X(K9) 1260 X(K9) = X(R9) 1270 X(R9) = S9 1280 NEXT K9 1290 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (ALINTSEQ) 130 REM ========================================================= 140 DIM INTSET(11),PCLASS(12) 150 TOTAL = 5 160 RANDOMIZE(212) 170 FOR J = 1 TO 11 180 INTSET(J) = (J) 190 NEXT J 200 FOR J = 1 TO TOTAL 210 GOSUB 2000 '<< call interval array shuffler 220 PRINT "RANDOM-ORDER INTERVALCLASS SERIES # ";J ":" 230 FOR J1 = 1 TO 11 240 PRINT INTSET(J1); 250 NEXT J1 260 PRINT 270 GOSUB 1000 '<< call interval to pitchclass mapping 280 PRINT "--- MAPPED TO PITCHCLASS NUMBERS ---" 290 FOR J1 = 0 TO 11 300 PRINT PCLASS(J1); 310 NEXT J1 320 PRINT 330 NEXT J 340 END 1000 REM ======================================================== 1010 REM ********************>> ALINTSEQ <<********************** 1020 REM ======================================================== 1030 REM This subroutine maps a set of 11 unique intervals 1040 REM (in semitones, size 1-11) to the pitchclasses of 1050 REM the chromatic scale. Although the interval set is 1060 REM non-redundant, there is a high probability that 1070 REM the resultant pitchclass sequence will contain at 1080 REM least one repeated tone, thus producing a 12-note 1090 REM sequence rather than a 12-note series. 1100 REM ======================================================== 1110 REM Variable Descriptions 1120 REM Entering - 1130 REM INTSET(): array of unique interval-sizes 1-11 1140 REM Exiting - 1150 REM PCLASS(): pitchclass sequence array 1160 REM Local - 1170 REM K9: loop index, pointer to intset(),PCLASS() 1180 REM ======================================================== 1190 PCLASS(0)=0 1200 FOR K9 = 1 TO 11 1210 PCLASS(K9) = (PCLASS(K9-1) + INTSET(K9)) MOD 12 1220 NEXT K9 1230 RETURN 2000 REM ======================================================== 2010 REM ********************>> CONSHUFL) <<********************* 2020 REM (adapted to program specs) 2030 REM ======================================================== 2040 FOR K9 = 1 TO 11 2050 R9 = INT(RND * 11) + 1 2060 S9 = INTSET(K9) 2070 INTSET(K9) = INTSET(R9) 2080 INTSET(R9) = S9 2090 NEXT K9 2100 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (ALINTSET) 130 REM ========================================================= 140 DIM PCLASS(12),PCUM(12),ICUM(12),TEMP(12),ALSET$(10) 150 TOTAL = 10 160 SETCOUNT = 0 170 RANDOMIZE(-1923) 180 FOR J = 1 TO TOTAL 190 PRINT "COMPUTING -- ALL-INTERVAL 12-TONE SET #";J 200 GOSUB 1000 210 IF FLAG = 1 THEN PRINT ALSET$(SETCOUNT)ELSE GOSUB 1000 220 NEXT J 230 END 1000 REM ======================================================= 1010 REM ********************>> ALINTSET <<********************* 1020 REM ======================================================= 1030 REM This subroutine generates all-interval 12-note 1040 REM series by the sample-test-discard/keep method. 1050 REM Although this "brute force" approach is rather 1060 REM slow, it can produce satisfactory results over 1070 REM short runs. Runs approaching 100 output sets 1080 REM can best be achieved by executing a compiled 1090 REM version of the program. 1100 REM ======================================================= 1110 REM Variable Descriptions 1120 REM Entering - 1130 REM none 1140 REM Exiting - 1150 REM PCLASS(): array holding all-interval series 1160 REM Local - 1170 REM PCUM(): array of note redundancy flags 1180 REM ICUM(): array of interval redundancy flags 1190 REM TEMP(): array holding temporary trial series 1200 REM INTSIZE: interval (in 1/2-steps) between notes 1210 REM R9: random integer for test series 1220 REM K9: loop index, pointer to TEMP() 1230 REM L9: loop index, pointer to TEMP(), PCLASS() 1240 REM M9: loop index, pointer to TEMP(), PCLASS() 1250 REM ======================================================= 1260 PCLASS(1) = 1 : PCLASS(12) = 7 1270 FOR K9 = 2 TO 11 1280 R9 = INT(RND * 11) + 2 1290 IF R9 = 7 THEN 1280 1300 IF PCUM(R9) = 1 THEN 1280 1310 TEMP(K9) = R9 1320 PCUM(R9) = 1 1330 NEXT K9 1340 FOR L9 = 2 TO 12 1350 FOR M9 = 2 TO 11 1360 IF TEMP(M9) > 0
THEN INTSIZE = TEMP(M9) - PCLASS(L9-1)
ELSE 1390 1370 IF INTSIZE < 0 THEN INTSIZE = 12 + INTSIZE 1380 IF ICUM(INTSIZE) < 1
THEN PCLASS(L9) = TEMP(M9) : TEMP(M9) = 0 : ICUM(INTSIZE) = 1 : GOTO 1410
ELSE 1390 1390 NEXT M9 1400 IF PCLASS(L9) = 0
THEN GOSUB 2000 : GOTO 1200 1410 NEXT L9 1420 GOSUB 3000 : GOSUB 2000 1430 RETURN 210 2000 REM ======================================================== 2010 REM *********************>> ZEROMAT <<********************** 2020 REM ======================================================== 2030 FOR L9 = 1 TO 12 2040 PCUM(L9) = 0 : ICUM(L9) = 0 : PCLASS(L9) = 0 2050 NEXT L9 2060 RETURN 3000 REM ======================================================== 3010 REM ********************>> SETSTORE <<********************** 3020 REM ======================================================== 3030 REM This subroutine stores and maintains an identity 3040 REM check on the all-interval series generated by the 3050 REM subroutine ALINTSET. Each output set is converted 3060 REM to a character string, tested against all prev- 3070 REM iously stored sets for uniqueness, then put in 3080 REM an character string array. 3090 REM ======================================================== 3100 REM Variable Descriptions 3110 REM Entering - 3120 REM PCLASS(): holds current pitchclass (integer) set 3130 REM Exiting - 3140 REM ALSET$(): string array holding all unique sets 3150 REM SETCOUNT: index of unique all-interval sets 3160 REM FLAG: indicator of set uniqueness 3170 REM Local - 3180 REM L9: loop index, pointer to PCLASS() 3190 REM CURSET$: string buffer holding current set 3200 REM ======================================================== 3210 CURSET$ = "" 3220 FOR L9=1 TO 12 3230 CURSET$ = CURSET$ + STR$(PCLASS(L9)-1) 3240 NEXT L9 3250 SETCOUNT = SETCOUNT + 1 3260 FOR L9 = 1 TO SETCOUNT - 1 3270 IF ALSET$(L9) = CURSET$ THEN FLAG = 0 : RETURN 3280 NEXT L9 3290 ALSET$(SETCOUNT)=CURSET$ 3300 FLAG = 1 3310 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Alterseq) 130 REM ========================================================= 140 DIM X(12),Y(12) 150 RANDOMIZE 160 TOTAL = 12 170 LOW = 22 180 HIGH = 66 190 RANGE = HIGH - LOW + 1 200 INTSIZE = 5 210 PRINT "A RANDOM-ORDER SEQUENCE --" 220 FOR J = 1 TO TOTAL 230 X(J) = INT(RND * RANGE)+ LOW 240 PRINT X(J); '<< send prime sequence to screen 250 NEXT J 260 PRINT : PRINT 270 FOR J = 1 TO 2 280 PRINT "PASS";J 290 PRINT "ALTERATION INTEGER =";INTSIZE" 300 PRINT "ALTERED SEQUENCE --" 310 GOSUB 1000 320 FOR J1 = 1 TO TOTAL 330 PRINT Y(J1); '<< send altered sequence to screen 340 NEXT J1 350 INTSIZE = - 5 360 PRINT 370 NEXT J 380 END 1000 REM ======================================================== 1010 REM *********************>> ALTERSEQ <<********************* 1020 REM ======================================================== 1030 REM This subroutine alters a value sequence by interval 1040 REM expansion or contraction. Positive integers expand 1050 REM the sequence, negative integers contract it. 1060 REM ======================================================== 1070 REM Variable Descriptions 1080 REM Entering - 1090 REM X(): primary value sequence 1100 REM TOTAL: length of sequence 1110 REM INTSIZE: size of alteration interval in units 1120 REM Exiting - 1130 REM X(): primary value sequence 1140 REM Y(): altered value sequence 1150 REM Local - 1160 REM INTDIR: direction of alteration 1170 REM INTVAL: altered interval 1180 REM K9: loop index, pointer to X(),Y() 1190 REM ======================================================== 1200 Y(1) = X(1) 1210 FOR K9 = 2 TO TOTAL 1220 IF X(K9) <> X(K9-1)THEN 1230 ELSE Y(K9) = Y(K9-1) : GOTO 1270 1230 INTDIR = SGN(X(K9)-X(K9-1)) 1240 INTVAL=ABS(X(K9)-X(K9-1))+INTSIZE 1250 IF INTVAL <1 THEN INTVAL = 1 1260 Y(K9)=Y(K9-1)+INTDIR * INTVAL 1270 NEXT K9 1280 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Beta) 130 REM ========================================================= 140 DIM X(50) 150 RANDOMIZE 160 TOTAL = 50 170 PROB0 = .4 180 PROB1 = .2 190 GOSUB 1000 '<< call Eulerian Beta distribution 200 FOR J = 1 TO TOTAL 210 PRINT X(J); '<< sequence to screen 220 NEXT J 230 END 1000 REM ======================================================== 1010 REM **********************>> BETA <<************************ 1020 REM ======================================================== 1030 REM The Eulerian Beta Distribution Function 1040 REM generates continuous, random-order values 1050 REM > 0 & < 1. The shape of its curve changes 1060 REM with the values of its controlling parameters 1070 REM PROB0 and PROB1. 1080 REM ======================================================== 1090 REM Variable Descriptions 1100 REM 1110 REM Entering - 1120 REM TOTAL: length of sequence 1130 REM PROB0: controls occurrence of values nearer to 0 1140 REM PROB1: controls occurrence of values nearer to 1 1150 REM Exiting - 1160 REM X(): array holding BETA distribution 1170 REM Local - 1180 REM R8: random number 1 1190 REM R9: random number 2 1200 REM T1: computed probability 1 1210 REM T2: computed probability 2 1220 REM SUM: total of probabilities 1 & 2 1230 REM K9: loop index, pointer to array X() 1240 REM ======================================================== 1250 PROB0 = 1 / PROB0 1260 PROB1 = 1 / PROB1 1270 FOR K9 = 1 TO TOTAL 1280 R8 = RND 1290 R9 = RND 1300 T1 = R8 ^ PROB0 1310 T2 = R9 ^ PROB1 1320 SUM = T1 + T2 1330 IF SUM > 1 THEN 1280 ELSE X(K9) = T1 / SUM 1340 NEXT K9 1350 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Bilexp) 130 REM ========================================================= 140 DIM X(100) 150 RANDOMIZE 160 TOTAL = 100 170 SPREAD = 1.5 180 GOSUB 1010 '<< bilateral exponential distribution 190 FOR J = 1 TO TOTAL 200 PRINT X(J); '<< sequence to screen 210 NEXT J 220 END 1000 REM ======================================================== 1010 REM *********************>> BILEXP <<*********************** 1020 REM (D)===================================================== 1030 REM The Bilateral Exponential Distribution Function 1040 REM generates random-order negative and positive 1050 REM real numbers centered about zero. Horizontal 1060 REM scale is controlled by the variable, SPREAD, 1070 REM which increase the range of generated values in 1080 REM inverse proportion to its magnitude (must be > 0). 1090 REM ======================================================== 1100 REM Variable Descriptions 1110 REM Entering - 1120 REM TOTAL: sequence length 1130 REM SPREAD: horizontal scaling value 1140 REM Exiting - 1150 REM X(): array holding BILEXP real numbers sequence 1160 REM Local - 1170 REM R9: random number > 0 & < 2 1180 REM K9: loop index, pointer to array X() 1190 REM ======================================================== 1200 FOR K9 = 1 TO TOTAL 1210 R9 = 2 * RND 1220 IF R9 > 1 THEN R9 = 2 - R9 1230 X(K9) = LOG(R9)/SPREAD 1240 NEXT K9 1250 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Cauchy) 130 REM ========================================================= 140 DIM X(50) 150 RANDOMIZE 160 TOTAL = 50 165 SPREAD = 2 170 GOSUB 1000 '<< call Cauchy distribution function 180 FOR J = 1 TO TOTAL 190 PRINT X(J); '<< sequence to screen 200 NEXT J 210 END 1000 REM ======================================================== 1010 REM *********************>> CAUCHY <<*********************** 1020 REM ======================================================== 1030 REM The Cauchy Probability Distribution Function 1040 REM generates random-order, continuous, real numbers 1050 REM centered about zero. The variable SPREAD controls 1060 REM the range of generated values. 1070 REM ======================================================== 1080 REM Variable Descriptions 1090 REM Entering - 1100 REM TOTAL: length of sequence 1110 REM SPREAD: scaling parameter 1120 REM Exiting - 1130 REM X(): array holding cauchy distribution 1140 REM Local - 1150 REM R9: uniform random number 1160 REM K9: loop index, pointer to array X() 1170 REM ======================================================== 1171 PI = 3.1415927# 1180 FOR K9 = 1 TO TOTAL 1200 R9# = RND 1210 IF R9# = .5 THEN 1200 1220 R9# = R9# * PI 1230 X(K9) = SPREAD * TAN(R9#) 1240 NEXT K9 1250 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Combntot) 130 REM ========================================================= 140 ELEMENTS = 10 150 MANY = 2 160 FOR J = 1 TO 10 170 GOSUB 1000 '<< call combinations 180 PRINT "COMBINATIONS OF";ELEMENTS;"THINGS TAKEN";MANY;"AT A TIME IS";COMBINS 190 ELEMENTS= ELEMENTS+ 3 200 MANY = MANY + 3 210 NEXT J 220 END 1000 REM SS2ST5 ================================================= 1010 REM ********************>> COMBINS <<*********************** 1020 REM ======================================================== 1030 REM This subroutine computes the number of possible 1040 REM combinations of n elements taken n at a time. 1050 REM It relies on Stirling's approximation to calculate 1060 REM the requisite factorials. 1070 REM ======================================================== 1080 REM Variable Descriptions 1090 REM Entering - 1100 REM ELEMENTS: nunber of items 1110 REM MANY: taken at a time 1120 REM Exiting - 1130 REM COMBINS : combination of ELEMENTS, taken MANY at 1140 REM a time 1150 REM Local - 1160 REM NUM: 1170 REM ELEMFACT: log of ELEMENTS factorial 1180 REM MANYFACT: log of MANY factorial 1190 REM DIFFACT : log of (ELEMFACT - MANYFACT) factorial 1200 REM ======================================================== 1210 NUM = ELEMENTS 1220 GOSUB 2000 '<< call Stirling's approximation 1230 ELEMFACT = APPR 1240 NUM = MANY 1250 GOSUB 2000 '<< call Stirling's approximation 1260 MANYFACT = APPR 1270 NUM = ELEMENTS - MANY 1280 GOSUB 2000 '<< call Stirling's approximation 1290 DIFFACT = APPR 1300 COMBINS = INT(EXP(ELEMFACT-(MANYFACT+DIFFACT))+.5) 1310 RETURN 2000 REM ======================================================== 2010 REM ********************>> STIRLING <<********************** 2020 REM ======================================================== 2030 APPR = 1 2040 IF NUM <= 0 THEN APPR = 0 : RETURN 2050 FOR K9 = 1 TO 10 2060 APPR = APPR * K9 2070 IF NUM = K9 THEN APPR = LOG(APPR) : RETURN 2080 NEXT K9 2090 APPR = LOG(6.283186)/2+LOG(NUM)*(NUM+.5)-NUM+1/(12*NUM) 2100 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Conshufl) 130 REM ========================================================= 140 DIM X(20) 150 TOTAL = 20 160 FOR J = 1 TO TOTAL 170 X(J) = J '<< fill array with number sequence 180 NEXT J 190 GOSUB 1000 200 FOR J = 1 TO TOTAL 210 PRINT X(J); '<< send shuffled array to screen 220 NEXT J 230 END 1000 REM ======================================================== 1010 REM ********************>> CONSHUFL <<********************** 1020 REM ======================================================== 1030 REM This subroutine shuffles array contents by first 1040 REM generating a random sequence of address pointers, 1050 REM then swapping corresponding address contents. 1060 REM However, in the shuffling process, original 1070 REM prime order is destroyed. (See subroutine 1080 REM ADDSHUF for non-disruptive randomization.) 1090 REM ======================================================= 1100 REM Variable Descriptions 1110 REM Entering - 1120 REM X(): array of sequential values 1130 REM TOTAL: length of list (array) 1140 REM Exiting - 1150 REM X(): randomized array of values 1160 REM Local - 1170 REM R9: random number 1180 REM S9: temporary storage variable 1190 REM K9: loop index, pointer to array X() 1200 REM ======================================================== 1210 RANDOMIZE 1220 FOR K9 = 1 TO TOTAL 1230 R9 = INT(RND * TOTAL) + 1 1240 REM+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1250 REM a more thorough shuffling can be achieved with 1260 REM the next statement substitiuted for line 1250 1270 REM R9 = INT(RND * (TOTAL - (K9 - 1)))+K9 1280 REM Why is this true? 1290 REM+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1300 S9 = X(K9) 1310 X(K9) = X(R9) 1320 X(R9) = S9 1330 NEXT K9 1340 RETURN
100 REM ========================================================= 110 REM CURVES 120 REM ========================================================= 130 REM The subroutines LINCURVE, EXPCURVE, and LOGCURVE 140 REM return positive values along three discrete curves: 150 REM linear, exponential, and logarithmic. Control 160 REM parameters are starting and ending values, and 170 REM number of values to be included in the curve. 180 REM ========================================================= 190 REM Variable Descriptions 200 REM DRIVER 210 REM S: starting curve value 220 REM E: ending curve value 230 REM N: number of values contained in curve 240 REM J1: loop index, pointer to subroutines 250 REM J2: loop index, pointer to array X() 260 REM X(): array holding curve values 270 REM 280 REM SUBROUTINES 1000,2000,3000 290 REM Entering - 300 REM S: starting curve value 310 REM E: ending curve value 320 REM N: number of values contained in curve 330 REM Exiting - 340 REM X(): array holding curve values 350 REM Local - 360 REM K9: loop index 370 REM L9: loop index, pointer to array X() 380 REM ========================================================= 390 REM ==================== DRIVER PROGRAM ===================== 400 REM ========================================================= 410 DIM X(100) 420 S = 1 430 E = 100 440 N = 100 450 FOR J1 = 1 TO 3 460 REM >> sequentially call LINCURVE, EXPCURVE, LOGCURVE subrs. 470 ON J1 GOSUB 1000,2000,3000 480 FOR J2 = 1 TO N 490 PRINT X(J2); '<< send curve values to screen 500 NEXT J2 510 PRINT 520 NEXT J1 530 END 1000 REM ======================================================== 1010 REM ********************>> LINCURVE <<********************** 1020 REM ======================================================== 1030 PRINT "LINEAR CURVE:" 1040 FOR K9 = 1 TO N STEP 10 1050 FOR L9 = K9 TO K9 + 9 1060 REM >> store current computed curve value 1070 X(L9) = ABS(S + INT(((L9-1)/(N-1)) * (E-S)+.5)) 1080 IF L9 = N THEN 1100 1090 NEXT L9 1100 NEXT K9 1110 RETURN 2000 REM ======================================================== 2010 REM ********************>> EXPCURVE <<********************** 2020 REM ======================================================== 2030 PRINT "EXPONENTIAL CURVE:" 2040 FOR K9 = 1 TO N STEP 10 2050 FOR L9 = K9 TO K9 + 9 2060 REM >> store current computed curve value 2070 X(L9) = ABS(S+INT((((L9-1)^2)/((N-1)^2))*(E-S)+.5)) 2080 IF L9 = N THEN 2100 2090 NEXT L9 2100 NEXT K9 2110 RETURN 3000 REM ======================================================== 3010 REM ********************>> LOGCURVE <<********************** 3020 REM ======================================================== 3030 PRINT "LOGARITHMIC CURVE:" 3040 FOR K9 = 1 TO N STEP 10 3050 FOR L9 = K9 TO K9 + 9 3060 REM >> store current computed curve value 3070 X(L9)=ABS(S + INT(((LOG(L9))/(LOG(N)))*(E-S)+.5)) 3080 IF L9 = N THEN 3100 3090 NEXT L9 3100 NEXT K9 3110 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM CYCLTEXT 130 REM ========================================================= 140 PRINT "ORIGINAL LINE OF TEXT:" 150 LIN$ = "apples sound beautiful" 160 PRINT LIN$ 170 PRINT 180 PNUM = 13 '<< a prime number smaller than length of LIN$ 190 NUM2 = 8 '<< an integer between 1 and length of LIN$ 200 GOSUB 1000 '<< call cyclical text shifter 210 PRINT "PRIME-SHIFTED TEXT:" 220 PRINT NEWLIN$ 230 END 1000 REM ==================================================CTB5.9 1010 REM *********************>> CYCLTEXT <<********************* 1020 REM ======================================================== 1030 REM Cyclical (prime number) Text Shift Subroutine 1040 REM ======================================================== 1050 REM Variable Desciptions 1060 REM Entering - 1070 REM LIN$: line of text to be shifted 1080 REM PNUM: prime number smaller than length of LIN$ 1090 REM NUM2: an integer between 1 and length of LIN$ 1100 REM Exiting: 1110 REM NEWLINE$: shifted line of text 1120 REM Local - 1130 REM SHIFTCHAR: LINE$ substring pointer 1140 REM NUMCHARS: length of LIN$ 1150 REM POSNUM: loop index, NEWLINE$ substring pointer 1160 REM ======================================================== 1170 SHIFTCHAR = NUM2 - PNUM 1180 NUMCHARS = LEN(LIN$) 1190 IF NUMCHARS-INT(NUMCHARS/PNUM)*PNUM = 0
THEN NUMCHARS=NUMCHARS+1 1200 NEWLIN$ = STRING$(NUMCHARS," ") 1210 FOR POSNUM = 1 TO NUMCHARS 1220 SHIFTCHAR = SHIFTCHAR + PNUM 1230 IF SHIFTCHAR > NUMCHARS
THEN SHIFTCHAR = SHIFTCHAR - NUMCHARS 1240 MID$(NEWLIN$,POSNUM,1) = MID$(LIN$,SHIFTCHAR,1) 1250 NEXT POSNUM 1260 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (DecBiDec) 130 REM ========================================================= 140 DIM X(10),X$(10) 150 PRINT "AN ARRAY OF DECIMAL NUMBERS --" 160 FOR J = 1 TO 10 170 DECNUM = J * 10 180 X(J) = DECNUM 190 PRINT X(J);" "; '<< send to screen 200 NEXT J 210 PRINT 220 PRINT "THE ARRAY CONVERTED TO BINARY NUMBERS --" 230 GOSUB 1000 '<< call decimal-to-binary conversion 240 FOR J = 1 TO 10 250 PRINT X$(J);" "; '<< send to screen 260 NEXT J 270 PRINT 280 GOSUB 1250 '<< call binary-to-decimal conversion 290 PRINT "THE BINARY NUMBERS CONVERTED BACK TO DECIMAL --" 300 FOR J = 1 TO 10 310 PRINT X(J);" "; '<< send to screen 320 NEXT J 330 END 1000 REM SS1MA1 ================================================= 1010 REM ********************>> DEC-BIN <<*********************** 1020 REM ======================================================== 1030 REM This subroutine converts positive decimal integers 1040 REM to their binary equivalents, which are placed in 1050 REM a character array as successions of "0" and "1" 1060 REM characters. 1070 REM ======================================================== 1080 REM Variable Descriptions 1090 REM Entering - 1091 REM X(): array holding decimal integers 1092 REM Exiting - 1093 REM X$(): array holding string representation of 1094 REM binary numbers corresponding to decimal 1095 REM integers. 1096 REM Local - 1097 REM P9: temporary version of decimal integer, 1098 REM successively divided by 2. 1099 REM Q9: quotient of P9/2 1100 REM R9: remainder of X9/2 1101 REM K9: loop index, pointer to array X$() 1110 REM ======================================================== 1120 FOR K9 = 1 TO 10 1130 P9=X(K9) 1140 BINUM$ = "" 1150 Q9 = P9 1160 WHILE Q9 > 0 1170 Q9=INT(P9/2) 1180 R9 = P9 - 2 * Q9 1190 BINUM$=MID$("01",R9+1,1)+BINUM$ 1200 P9=Q9 1210 WEND 1220 X$(K9) = BINUM$ 1230 NEXT K9 1240 RETURN 1250 REM SS2MA1 ================================================= 1260 REM ********************>> BIN-DEC <<*********************** 1270 REM ======================================================== 1280 REM This subroutine converts binary numbers (stored as 1290 REM character strings) to their decimal equivalents. 1300 REM The INSTR function is used to ascertain the value 1310 REM and location of each binary bit within the number 1320 REM string. Line ----- examines the first bit: if it 1330 REM is "0" then DECNUM is set to 0; if it is "1", 1340 REM DECNUM is 1. The remaining bits are scanned, and 1350 REM as long as there is another bit, DECNUM is doubled 1360 REM and a 1 or 0 is added to it. 1370 REM ======================================================== 1380 REM Variable Descriptions 1390 REM Entering - 1400 REM X$(): array of binary numbers stored as character 1410 REM strings of 1s and 0s 1420 REM Exiting - 1430 REM X(): array of converted decimal integers 1440 REM Local - 1450 REM DECNUM: decimal integer 1460 REM K9: loop index, pointer to array X() 1470 REM L9: loop index 1480 REM ======================================================== 1490 FOR K9 = 1 TO 10 1500 DECNUM = 0 1510 FOR L9 = 1 TO LEN(X$(K9)) 1520 DECNUM = INSTR("01",MID$(X$(K9),L9,1)) - 1 + DECNUM + DECNUM 1530 NEXT L9 1540 X(K9) = DECNUM 1550 NEXT K9 1560 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Decfrac) 130 REM ========================================================= 140 DIM X(50),FRACTION$(50) 150 RANDOMIZE(22321) 160 TOTAL = 50 170 FOR J = 1 TO TOTAL 180 X(J)= (INT(RND * 99)+1)/100'<<< load decimal values 190 PRINT X(J), '<<< send to screen 200 NEXT J 210 PRINT 220 GOSUB 1000 '<<< call decimal to fraction conversion 230 FOR J = 1 TO TOTAL 240 PRINT FRACTION$(J), '<<< send to screen 250 NEXT J 260 END 1000 REM ======================================================== 1010 REM ********************>> DECFRAC <<*********************** 1020 REM ======================================================== 1030 REM This subroutine converts decimal values (%) to 1040 REM fractions for use as rhythmic durations. 1050 REM ======================================================== 1060 REM 1070 REM Variable Descriptions 1080 REM 1090 REM Entering - 1100 REM X(): array of decimal values to be converted 1110 REM 1120 REM Exiting - 1130 REM FRACTION$(): character string array of fractions 1140 REM 1150 REM Local - 1160 REM B9: temporary storage of computation result 1170 REM C9: holds integer computation result 1180 REM D9: holds non-integer portion of decimal value 1190 REM E9: temporary storage of real number result 1200 REM F9: temporary storage of integer computation 1210 REM K9: loop index, pointer to array X() 1220 REM ======================================================== 1230 FOR K9 = 1 TO TOTAL 1240 B9= 0 1250 C9 = 1 1260 D9= ABS(X(K9)-INT(X(K9))) 1270 IF D9 = 0 THEN 1340 1280 E9 = 1 / D9 1290 F9 = C9 1300 C9 = INT(E9) * C9 + B9 1310 B9 = F9 1320 D9 = E9 - INT(E9) 1330 IF X(K9) * C9 <> INT(X(K9) * C9) THEN 1280 1340 FRACTION$(K9)=STR$(X(K9) * C9)+"/"+STR$(C9) 1350 NEXT K9 1360 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (DELREPL) 130 REM ========================================================= 140 DIM X(50) 150 TOTAL = 50 160 RANDOMIZE 170 PRINT "ARRAY OF RANDOM-ORDER REAL NUMBERS (RANGE 0-1) --" 180 FOR J = 1 TO TOTAL 190 X(J) = RND 200 PRINT X(J); 210 NEXT J 220 PRINT 230 PRINT "ARRAY SORTED IN ASCENDING ORDER --" 240 GOSUB 1000 '<< call delayed replacement sort 250 FOR J = 1 TO TOTAL 260 PRINT X(J); '<< list to screen 270 NEXT J 280 END 1000 REM SS2TM1 ================================================= 1010 REM *********************>> DELREPL <<********************** 1020 REM ======================================================== 1030 REM This Delayed Replacement Sort subroutine is an 1040 REM improved version of the standard replacement sort. 1050 REM In this case, the switch between two items is 1060 REM delayed until that item is confirmed to be the 1070 REM smallest. The savings in time is one-half. 1080 REM However, for long lists either replacement sort 1090 REM is less appropriate than other sorts, because as 1100 REM the number of items to be sorted grows linearly, 1110 REM sorting time increases exponentially. 1120 REM ======================================================== 1130 REM Variable Descriptions 1140 REM Entering - 1150 REM X(): array of values to be sorted 1160 REM TOTAL: length of array X() 1170 REM Exiting - 1180 REM X(): array sorted in ascending order 1190 REM Local - 1200 REM K9: loop index, pointer to X() 1210 REM L9: loop index, pointer to X() 1220 REM COMPVAL: indicator for switch of values 1230 REM ======================================================= 1240 FOR K9=1 TO TOTAL - 1 1250 COMPVAL= K9 1260 FOR L9=K9+1 TO TOTAL 1270 IF X(L9) < X(COMPVAL) THEN COMPVAL=L9 1280 NEXT L9 1290 IF K9 <> COMPVAL THEN SWAP X(K9),X(COMPVAL) 1300 NEXT K9 1310 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Displace) 130 REM ========================================================= 140 DIM P$(84) 150 DIM X(20),Y(20) 160 DIM DISP(20) 170 RANDOMIZE 180 GOSUB 530 '<< call pitch table 190 TOTAL = 10 200 FOR J= 1 TO TOTAL 210 X(J) = INT(RND * 12) + 1 '<< load random pitches 220 DISP(J) = INT(RND * 6)+1'<< load random octave displ. 230 PRINT P$(X(J));" WILL BE DISPLACED BY ";DISP(J);"OCTAVE(S)" 240 NEXT J 250 GOSUB 300 '<< call registral displacement 260 FOR J = 1 TO TOTAL 270 PRINT P$(Y(J));" "; 280 NEXT J 290 END 300 REM ========================================================= 310 REM *******************>> DISPLACE <<************************ 320 REM ========================================================= 330 REM This subroutine (individually) displaces the pitches 340 REM of an input sequence by a specific number of octaves. 350 REM ========================================================= 360 REM Variable Descriptions 370 REM Entering - 380 REM X(): array holding undisplaced pitch sequence 390 REM DISP(): array holding individual pitch displacements 400 REM TOTAL: sequence length 430 REM Exiting - 440 REM Y(): array containing octave-displaced pitches 450 REM Local - 460 REM K9: loop index, pointer to DISP(),X(),Y() 470 REM ======================================================== 480 REM 490 FOR K9 = 1 TO TOTAL 500 Y(K9)=X(K9) + 12 * DISP(K9) 510 NEXT K9 520 RETURN 530 REM ======================================================== 540 REM ********************>> PITCHTAB <<*********************** 550 REM ========================================================= 560 NOTE$ = " CC# DD# E FF# GG# AA# B" 570 OCTAVE$ = "1234567" 600 FOR K9 = 1 TO 7 610 FOR L9 = 1 TO 12 620 P$(L9+(K9-1)*12) = MID$(NOTE$,(L9*2-1),2)+MID$(OCTAVE$,K9,1) 630 NEXT L9 640 NEXT K9 650 RETURN
100 REM ========================================================= 110 REM =================== DRIVER PROGRAM ====================== 120 REM ========================================================= 130 DIM X(50),Y(50),FRACTION$(50) 140 TOTAL = 50 150 CLS 160 RANDOMIZE 170 REM >> randomly choose fractions between 1/50 & 50/1 180 FOR J= 1 TO TOTAL 190 X(J) = INT(RND * TOTAL)+1 '<< load numerators 200 Y(J) = 32 '<< load denominators 210 PRINT X(J);"/";Y(J), '<< send to screen 220 NEXT J 230 PRINT:PRINT 240 GOSUB 1000 '<<< call fraction reduction 250 FOR J = 1 TO TOTAL 260 PRINT FRACTION$(J), '<<send fraction to screen 270 NEXT J 280 END 1000 REM ======================================================== 1010 REM *****************>> DURRED <<*************************** 1020 REM ======================================================== 1030 REM This subroutine reduces fractions in a manner 1040 REM consistent with rhythmic pulse subdivision. 1050 REM For instance, a fractional duration such as 1060 REM 6/12 will be reduced to 3/6 (as opposed to 1070 REM 1/2) in order to preserve subdivisional clarity. 1080 REM This results in duration patterns which are 1090 REM metrically simpler to reconcile when output is to be 1100 REM transcribed for standard musical instruments 1110 REM ======================================================== 1120 REM Variable Descriptions 1130 REM Entering - 1140 REM X(): array of fraction numerators 1150 REM Y(): array of fraction denominators 1160 REM TOTAL: number of fractions to be converted 1170 REM 1180 REM Exiting - 1190 REM FRACTION$(): character string array of fractions 1210 REM 1220 REM Local - 1230 REM K9: loop index, pointer to arrays X(),Y(),FRACTION$ 1240 REM ======================================================== 1250 FOR K9 = 1 TO TOTAL 1260 IF X(K9) / 2 <> INT(X(K9) / 2)OR Y(K9) / 2 <> INT(Y(K9) / 2)THEN 1280 1270 X(K9) = X(K9) / 2 : Y(K9) = Y(K9) / 2 : GOTO 1260 1280 FRACTION$(K9) = STR$(X(K9)) + "/" + STR$(Y(K9)) 1285 NEXT K9 1290 RETURN
100 REM ========================================================= 110 REM =================== DRIVER PROGRAM ====================== 120 REM ========================================================= 130 DIM X(50),Y(50),FRACTION$(50) 140 TOTAL = 50 150 CLS 160 RANDOMIZE 170 REM >> randomly choose fractions between 1/50 & 50/1 180 FOR J= 1 TO TOTAL 190 X(J) = INT(RND * TOTAL)+1 '<< load numerators 200 Y(J) = 32 '<< load denominators 210 PRINT X(J);"/";Y(J), '<< send fraction to screen 220 NEXT J 230 PRINT 240 GOSUB 1000 '<<< call fraction reduction 250 FOR J = 1 TO TOTAL 260 PRINT FRACTION$(J), '<< send fraction to screen 270 NEXT J 280 END 1000 REM ======================================================== 1010 REM ********************>> EUCREDUC <<********************** 1020 REM ======================================================== 1030 REM This subroutine uses Euclid's algorithm to reduce 1040 REM rhythmic duration fractions to absolute lowest terms. 1050 REM It does not preserve metrical pulse consistency, in 1060 REM that a fraction such as 9/12 will convert to 3/4. 1070 REM ======================================================== 1080 REM Variable Descriptions 1090 REM Entering - 1100 REM X(): array of fraction numerators 1110 REM Y(): array of fraction denominators 1120 REM TOTAL: number of fractions to be reduced 1130 REM 1140 REM Exiting - 1150 REM FRACTION$(): character string array of fractions 1160 REM 1170 REM Local - 1180 REM K9: loop index, pointer to arrays X(),Y(),FRACTION$ 1190 REM ======================================================== 1200 FOR K9 = 1 TO TOTAL 1210 IF Y(K9) = 1 THEN 1330 1220 A9 = X(K9) 1230 B9 = Y(K9) 1240 IF A9 > B9 THEN SWAP A9,B9 1250 WHILE A9 > 0 1260 C9 = INT(B9/A9) 1270 D9 = B9-A9*C9 1280 B9 = A9 1290 A9 = D9 1300 WEND 1310 REM >> convert fraction to char string and load in array 1320 FRACTION$(K9) = STR$(X(K9)/B9) + "/" + STR$(Y(K9)/B9) 1330 NEXT K9 1340 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Expon) 130 REM ========================================================= 140 DIM X(50) 150 RANDOMIZE 160 TOTAL = 50 170 SPREAD = 2 180 GOSUB 1000 '<< call exponential distribution function 190 FOR J = 1 TO TOTAL 200 PRINT X(J); '<< sequence to screen 210 NEXT J 220 END 1000 REM ======================================================== 1010 REM ********************>> EXPON <<************************ 1020 REM (L)===================================================== 1030 REM The Exponential Distribution Function generates 1040 REM continuous, random-order real numbers > 0 & < 1. 1050 REM Results closer to 0 are most likely to occur, 1060 REM with probability of higher numbers falling off 1070 REM exponentially. The variable SPREAD controls 1080 REM horizontal value scaling. 1090 REM ======================================================== 1100 REM Variable Descriptions 1110 REM Entering - 1120 REM SPREAD: horizontal scaling parameter 1130 REM TOTAL: length of sequence 1140 REM Exiting - 1150 REM X(): array holding exponential distribution 1160 REM Local - 1170 REM R9 : uniform random number 1180 REM K9: loop index, pointer to array X() 1190 REM ======================================================== 1200 FOR K9 = 1 TO TOTAL 1210 R9 = RND 1220 X(K9) = -LOG(R9) / SPREAD 1230 NEXT K9 1240 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM ========================================================= 130 DIM X(50),Y(50),Z(50) 140 TOTAL = 50 150 CLS 160 RANDOMIZE 170 FOR J= 1 TO TOTAL 180 X(J) = INT(RND * TOTAL)+1 '<< random numerators 190 Y(J) = INT(RND * TOTAL)+1 '<< random denominators 200 NEXT J 210 GOSUB 1000 '<<< call fraction to decimal conversion 220 FOR J = 1 TO TOTAL 230 PRINT X(J);"/";Y(J);"=";'<<send fraction to screen 240 PRINT Z(J) '<<send decimal equivalent to screen 250 NEXT J 260 PRINT "SUM OF DURATIONS =";SUM;"WHOLE NOTES" 270 END 1000 REM ======================================================== 1010 REM *******************>> FRACDEC <<*********************** 1020 REM ======================================================== 1030 REM This subroutine converts fractional values to 1040 REM decimal for use in rhythmic applications. It also 1050 REM computes the total of all durations in whole notes. 1060 REM ======================================================== 1070 REM Variable Descriptions 1080 REM Entering - 1090 REM X(): array of fraction numerators 1100 REM Y(): array of fraction denominators 1110 REM TOTAL: number of fractions to be converted 1120 REM Exiting - 1130 REM Z(): array of decimal equivalents 1140 REM SUM: sum of all durations in decimal 1150 REM Local - 1160 REM K9: loop index, pointer to arrays X(),Y() 1170 REM ======================================================== 1180 SUM = 0 1190 FOR K9 = 1 TO TOTAL 1200 Z(K9) = X(K9) / Y(K9) '<< load decimal equivalent 1210 SUM = SUM + Z(K9) 1220 NEXT K9 1230 RETURN
100 REM ======================================================== 110 REM ================= DRIVER PROGRAM ======================= 120 REM ======================================================== 130 DIM X(50) 140 TOTAL = 50 150 CLS 160 PRINT "HERE IS A SERIES OF DURATION FRACTIONS:" 170 FOR J = 1 TO TOTAL 180 X(J) = J '<<< load denominators in array 190 PRINT "1/";X(J), '<<< send to screen as fractions 200 NEXT J 210 PRINT : PRINT 220 GOSUB 1000 '<<< call duration tabulation 230 PRINT "SUM OF DURATIONS IS:";SUM#;"WHOLE NOTES" 240 END 1000 REM ======================================================= 1010 REM ******************>> FRACTAB <<********************** 1020 REM ======================================================= 1030 REM This subroutine tabulates rhythmic duration values 1040 REM in cases where each value can be expressed as a 1050 REM fraction which has 1 as the numerator (e.g. 1/8). 1060 REM The sum of all durations is returned in decimal 1070 REM (e.g., 4.499205391854048 whole notes). 1080 REM ======================================================= 1100 REM Variable Descriptions 1120 REM Entering - 1140 REM X(): array of fraction denominators to be summed 1150 REM TOTAL: number of elements in array X() 1160 REM 1170 REM Exiting - 1190 REM SUM#: (double precision) decimal sum of 1200 REM durations, expressed in whole notes 1210 REM 1220 REM Local - 1240 REM K9: loop index, pointer to array X() 1260 REM ======================================================= 1280 SUM# = 0 1290 FOR K9 = 1 TO TOTAL 1300 SUM# = SUM# + 1 / X(K9) 1310 NEXT K9 1320 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Fractsum) 130 REM ========================================================= 140 REM The subroutines below have a number of individual 150 REM uses; they are grouped together in this program 160 REM for the purpose of totaling a sequence of rhythm 170 REM duration fractions. 180 REM 190 REM An alternative subroutine, FRACDEC, (presented 200 REM elsewhere) sums fractions and expresses the 210 REM the result in decimal in decimal whole note 220 REM values, e.g., 1.23143. 230 REM 240 REM Contrastingly, FRACTSUM places no restriction 250 REM on fraction type, and produces fractional, not 260 REM decimal, output, e.g., 2/1 + 11/16 = 2 11/16. 270 REM The subroutine LCM (Least Common Multiple) is 280 REM coupled with EUCREDUC (which is Euclid's Algorithm 290 REM for finding the Greatest Common Divisor of two 300 REM numbers) to do the work of summing the fraction 310 REM sequence. However, there is one serious drawback 320 REM to FRACTSUM - when a computer with a small word 330 REM size is used, overflow condition is quickly reached. 340 REM ========================================================= 350 DIM X(20),Y(20) 360 RANDOMIZE 370 PRINT "ARRAY OF DURATION FRACTIONS TO BE TOTALED -- " 380 FOR J = 0 TO 20 390 X(J) = INT(RND * 10)+1 400 Y(J) = INT(RND * 10)+1 410 PRINT X(J);"/";Y(J), '<< send fraction to screen 420 NEXT J 430 PRINT 440 PRINT 450 FOR J = 1 TO 20 460 GOSUB 1000 470 X(0) = NUM 480 Y(0) = DEN 490 NEXT J 500 IF NUM MOD DEN = 0
THEN PRINT NUM/DEN
ELSE IF NUM > DEN
THEN PRINT INT(NUM/DEN);"+";NUM MOD DEN;"/";DEN;
ELSE PRINT NUM;"/";DEN; 510 END 1000 REM SS1MA5 ================================================= 1010 REM ***********************>> LCM <<************************ 1020 REM ======================================================== 1030 REM This subroutine determines the least common 1040 REM multiple of two integers by calling the 1050 REM greatest common divisor subroutine to supply 1060 REM that value, then divides the product of the 1070 REM two integers by the gcd. 1080 REM ======================================================== 1090 REM Variable Descriptions 1100 REM Entering - 1110 REM X(0): current fraction numerator sum 1120 REM X(n): next fraction numerator 1130 REM Y(0): current fraction denominator sum 1140 REM Y(n): next fraction denominator 1150 REM LCM: least common multiple 1160 REM Exiting - 1170 REM NUM: reduced fraction numerator total 1180 REM DEN: reduced fraction denominator total 1190 REM Local - 1200 REM M9: temp storage for denominator total 1210 REM N9: temp storage for next denominator 1220 REM GCD: greatest common divisor 1230 REM LCM: least common multiple 1240 REM ======================================================== 1250 M9 = Y(0) 1260 N9 = Y(J) 1270 GOSUB 2000 '<< call Greatest Common Divisor 1280 LCM = M9 * N9 / GCD 1290 M9 = LCM / Y(0) 1300 N9 = LCM / Y(J) 1310 NUM = (X(0) * M9) + (X(J) * N9) 1320 DEN = LCM 1330 M9 = NUM 1340 N9 = DEN 1350 GOSUB 2000 '<< call Greatest Common Divisor 1360 NUM = M9 / GCD 1370 DEN = N9 / GCD 1380 RETURN 2000 REM ======================================================== 2010 REM ***********************>> GCD <<************************ 2020 REM (EUCREDUC adapted to program specs.) 2030 REM ======================================================== 2040 A9 = M9 2050 B9 = N9 2060 IF A9 > B9 THEN SWAP A9,B9 2070 WHILE A9 > 0 2080 C9=INT(B9/A9) 2090 D9 = B9 - A9 * C9 2100 B9 = A9 2110 A9 = D9 2120 WEND 2130 GCD = B9 2140 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 130 REM (Gamma) 140 REM ========================================================= 150 DIM X(50) 160 RANDOMIZE 170 TOTAL = 50 180 SPREAD = 5 190 GOSUB 1000 '<< call gamma distribution function 200 FOR J = 1 TO TOTAL 210 PRINT X(J); '<< sequence to screen 220 NEXT J 230 END 1000 REM ======================================================== 1010 REM **********************>> GAMMA <<*********************** 1020 REM ======================================================== 1030 REM The Gamma Probability Distribution Function returns 1040 REM random-order, continuous real numbers over an 1050 REM assymetrical curve. It has particular usefulness 1060 REM in rhythmic applications, where it can produce a 1070 REM sense of 'rubato'. 1080 REM ======================================================== 1090 REM Variable Descriptions 1100 REM Entering - 1110 REM TOTAL: length of sequence 1120 REM SPREAD: control parameter 1130 REM Exiting - 1140 REM X(): array holding gamma distribution 1150 REM Local - 1160 REM SUM: accumulator 1170 REM GAMMA: current distribution value 1180 REM K9: loop index, pointer to array X() 1190 REM ======================================================== 1200 FOR K9 = 1 TO TOTAL 1210 SUM = 1 1220 FOR L9 = 1 TO SPREAD 1230 SUM = SUM * RND 1240 NEXT L9 1250 X(K9) = -LOG(SUM) 1260 NEXT K9 1270 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Gauss) 130 REM ========================================================= 140 DIM X(50) 150 RANDOMIZE 160 TOTAL = 50 170 DEV = 2 180 MEAN = 10 190 GOSUB 1000 '<< call gaussian distribution function 200 FOR J = 1 TO TOTAL 210 PRINT X(J); '<< sequence to screen 220 NEXT J 230 END 1000 REM ======================================================== 1010 REM **********************>> GAUSS <<*********************** 1020 REM ======================================================== 1030 REM The Gaussian Probability Distribution Function 1040 REM is also referred to as the 'normal distribution'. 1050 REM Its curve is bell-shaped, and is arrived at by 1060 REM an approximation resulting from the summation of 1070 REM uniform random numbers. The standard deviation - 1080 REM DEV - and the mean - MEAN - are the control 1090 REM parameters. It generates random-order real 1100 REM numbers centered about the mean. 1110 REM ======================================================== 1120 REM Variable Descriptions 1130 REM Entering - 1140 REM TOTAL: length of sequence 1150 REM DEV: statistical standard deviation 1160 REM MEAN: statistical mean 1170 REM Exiting - 1180 REM X(): array holding gaussian distribution 1190 REM Local - 1200 REM NUM: number of random values used in computation 1210 REM HALFNUM: NUM / 2 1220 REM SCALE: scaling factor (varies with NUM as 1230 REM SCALE = 1 / SQR(NUM/12) 1240 REM K9: loop index, pointer to array X() 1250 REM ======================================================== 1260 NUM = 12 1270 HALFNUM = NUM/2 1280 SCALE=1 1290 FOR K9= 1 TO TOTAL 1300 SUM=0 1310 FOR L9 = 1 TO NUM 1320 SUM = SUM + RND 1330 NEXT L9 1340 X(K9) = DEV * SCALE * (SUM - HALFNUM) + MEAN 1350 NEXT K9 1360 RETURN
1 REM in text explain how forms contain info for eol & eop (-1) 100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM Gen-con 130 REM ========================================================= 140 REM This group of subroutines composes 4 poems (somewhat 150 REM resembling Haiku), then maps the ASCII values of the 160 REM constituent letters onto the pitch domain. 170 REM +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 180 DIM P$(84),VOCAB$(300),W(15),SET(300) 190 REM >>> assign parts of speech totals (see DATA categories) 200 AR = 2 210 AD = 72 220 NO = 103 230 VE = 55 240 PR = 15 250 WORDTOT = AR + AD + NO + VE + PR 260 GOSUB 4000 '<< initialize pitch data table 270 RANDOMIZE 280 PRINT "EACH LINE OF EACH POEM WILL BE PRINTED, THEN " :
PRINT "CONVERTED TO CORRESPONDING PITCH SEQUENCE" 290 FOR J = 1 TO 4 300 PRINT "POEM ";J 310 GOSUB 1000 '<< call poem generator 320 PRINT:PRINT 330 NEXT J 340 END 1000 REM ================================================== CTB5.8 1010 REM ******************>> GENPOEM <<************************** 1020 REM ========================================================= 1030 REM This subroutine generates 3-line poems which bear 1040 REM a resemblance to Haiku. It consults 1 of four 1050 REM poem form schemes to provide proper syntax, then 1060 REM randomly selects conforming words from program 1070 REM vocabulary. Words can be added to the DATA state- 1080 REM ments, but be sure to change DRIVER PROGRAM variable 1090 REM values accordingly (or mayhem will result). 1100 REM ========================================================= 1110 REM Variable Descriptions 1120 REM Entering - 1130 REM J: flag from DRIVER to load program vocabulary 1140 REM WORDTOT: vocabulary size 1150 REM AR: number of articles in vocabulary 1160 REM AD: number of adjectives in vocabulary 1170 REM NO: number of nouns in vocabulary 1180 REM VE: number of verbs in vocabulary 1190 REM PR: number of prepositions in vocabulary 1200 REM Exiting - 1210 REM LIN$: full poem line 1220 REM Local - 1230 REM VOCAB$(): array of program vocabulary 1240 REM SET(): flag array to prevent word repetition 1250 REM W(): array storing current poem formal structure 1260 REM W: current part of speech, or blank space 1270 REM L: low end vocabulary delimiter 1280 REM S: range span for parts of speech categories 1290 REM RNDWRD: randomly selected word 1300 REM K9: loop index, pointer to W() 1310 REM ======================================================== 1320 LIN$ = "" 1330 IF J > 1 THEN 1370 1340 FOR K9 = 1 TO WORDTOT 1350 READ VOCAB$(K9) '<< load vocabulary 1360 NEXT K9 1370 FOR K9 = 1 TO 15 1380 READ W(K9) '<< load 1 of 4 unique poem forms 1390 NEXT K9 1400 FOR K9 = 1 TO 15 1410 W = W(K9) 1420 REM << if end-of-text (W=-1) or end-of-line (W=0), call >> 1430 REM << article-checking subroutine, print line of text, >> 1440 REM << call text-to-pitch conversion subroutine to print >> 1450 REM << resulting pitch sequence. >> 1460 IF W = -1 THEN GOSUB 2000 :
PRINT LIN$ : GOSUB 3000 :
RETURN 1470 IF W = 0 THEN GOSUB 2000 :
PRINT LIN$ : GOSUB 3000 :
LIN$= "" : GOTO 1550 1480 REM >>> locate vocab range for selected part of speech 1490 IF W=1 THEN L=1:S=AR
ELSE IF W=2 THEN L=AR+1:S=AD
ELSE IF W=3 THEN L=AR+AD+1:S=NO
ELSE IF W=4 THEN L=AR+AD+NO+1:S=VE
ELSE L=AR+AD+NO+VE+1:S=PR 1500 RNDWRD = INT(RND * S) + L 1510 IF RNDWRD <= AR THEN 1540 '<<permit article repetit. 1520 IF SET(RNDWRD) = 1 THEN 1500 '<<prevent word repetit. 1530 SET(RNDWRD) = 1 1540 LIN$ = LIN$ + " " + VOCAB$(RNDWRD) '<< build a line 1550 NEXT K9 1560 RETURN 2000 REM =================================================== CTB5.9 2010 REM ********************>> ARTCHECK <<************************ 2020 REM ========================================================== 2030 REM This subroutine checks for article-adjective agreement. 2040 REM It scans the line of poetry most recently created by 2050 REM subroutine GENPOEM. If it finds the article A before 2060 REM a vowel, it changes it to the article AN. 2070 REM ========================================================== 2080 REM Variable Descriptions 2090 REM Entering - 2100 REM LIN$: uncorrected line of text 2110 REM Exiting - 2120 REM LIN$: text line after article checking/correction 2130 REM Local - 2140 REM B$: stores indicator to add letter N to article 2150 REM I: loop index, pointer to LIN$ substring 2160 REM ========================================================== 2170 FOR I = 1 TO LEN(LIN$) - 2 2180 IF MID$(LIN$,I,3) = " A " THEN B$ = MID$(LIN$,I+3,1)ELSE 2200 2190 IF B$="A" OR B$="E" OR B$="I" OR B$="O" OR B$="U"
THEN LIN$ = LEFT$(LIN$,I+1) + "N" + MID$(LIN$,I+2) 2200 NEXT I 2210 RETURN 3000 REM ================================================= CTB5.2 3010 REM ********************>> SNDTEXT2 <<********************** 3020 REM (Adapted to program specs) 3030 REM ======================================================== 3040 LINELENGTH = LEN(LIN$) 3050 FOR M9 = 1 TO LINELENGTH 3060 NOTENUM = ASC(MID$(LIN$,M9,1))-32 '<<convert to int 3070 PRINT P$(NOTENUM);" "; '<< convert to pitch 3080 NEXT M9 3090 PRINT 3100 RETURN 4000 REM ================================================= CTB1.3 4010 REM ********************>> PITCHTAB <<********************** 4020 REM (Adapted to program specs) 4030 REM ======================================================== 4040 P$(0) = " R " '<< blank spaces will print as rests 4050 NOTE$ = " CC# DD# E FF# GG# AA# B" 4060 OCTAVE$ = "1234567" 4070 FOR K9 = 1 TO 7 4080 FOR L9 = 1 TO 12 4090 P$(L9+(K9-1) * 12) = MID$(NOTE$,(L9*2-1),2) + MID$(OCTAVE$,K9,1) 4100 NEXT L9 4110 NEXT K9 4120 RETURN 4130 REM ========================================================= 5000 REM +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5010 REM PROGRAM VOCABULARY 5020 REM ++++++++++++++++++ 5030 REM 5040 REM ARTICLES 5050 REM +++++++++++++++++++ 5060 DATA A,THE 5070 REM +++++++++++++++++++ 5080 REM ADJECTIVES 5090 REM +++++++++++++++++++ 5100 DATA AUTUMN,HIDDEN,BITTER, MISTY,SILENT,EMPTY,VERDANT 5110 DATA DRY,DARK,SUMMER,ICY,DELICATE,QUIET,BEMUSED,DIMPLED 5120 DATA WHITE,COOL,SPRING,WINTER,DAPPLED,MOLTEN,FLORAL,DAMP 5130 DATA TWILIGHT,DAWN,CRIMSON,WISPY,AZURE,FRIGID,ASHEN,WHITE 5140 DATA BLUE,BILLOWING,BROKEN,COLD,DAMP,FALLING,INDIGO,SILKEN 5150 DATA FROSTY,GREEN,LONG,LATE,LINGERING,LIMPID,DUSTY,MIDNIGHT 5160 DATA LITTLE,EVENING,MUDDY,OLD,RED,ROUGH,TRANQUILL,WISTFUL 5170 DATA STILL,SMALL,SPARKLING,THROBBING,VERMILION,SOUR,LEMON 5180 DATA WANDERING,WITHERED,WILD,BLACK,YOUNG,STRICKEN,FLEECY 5190 DATA RADIANT,TENDER,DARK 5200 REM +++++++++++++++++++ 5210 REM NOUNS 5220 REM +++++++++++++++++++ 5230 DATA WATERFALL,RIVER,BREEZE,MOON,CAVE,MOON,DREAMSCAPE,DEER 5240 DATA RAIN,WIND,SEA,TABLEAU,SNOWFLAKE,LAKE,SUNSET,SAND-GRAIN 5250 DATA PINE,SHADOW,LEAF,DAWN,GROTTO,FOREST,TROUT,POOL,WIND,ASH 5260 DATA HILL,CLOUD,MEADOW,SUN,GLADE,BIRD,BROOK,MILKWEED,WILLOW 5270 DATA BUTTERFLY,BUSH,DEW,STORMCLOUD,FIELD,FIR,BRANCH,FLAME 5280 DATA FLOWER,FIREFLY,FEATHER,GRASSBED,HAZE,MOUNTAIN,HONEYDEW 5290 DATA NIGHT,POND,SHADE,SNOWFLAKE,DRAGONFLY,LAUREL,COMET,STAR 5300 DATA SILENCE,SOUND,SKY,SHAPE,SURF,THUNDERCLAP,MEADOW,GLOW 5310 DATA VIOLET,PLUME,WILDFLOWER,WAVE,SPIRIT,TWILIGHT,HALO,OWL 5320 DATA SPIDER WEB,LONLINESS,MIST,IVY,DREAM,LIGHT,WOOD,SEASHELL 5330 DATA SWAN,CEDAR,ICE,ROSE,THORN,SUNBEAM,BLOSSOM,GULL,PETAL 5340 DATA STONE,BEE,LEAF,HORIZON,SHOWER,AIR,ROOT,LILAC,HEART 5350 DATA WHISPER,BREATH,SCENT 5360 REM ++++++++++++++++++ 5370 REM VERBS 5380 REM ++++++++++++++++++ 5390 DATA SHAKES,DRIFTS,HAS STOPPED,STRUGGLES,IS DEPARTING 5400 DATA HAS FALLEN,HAS PASSED,SLEEPS,CREEPS,RECLINES,SIGHS 5410 DATA FLUTTERS,HAS RISEN,IS FALLING,IS TRICKLING,DAMPENS 5420 DATA DRINKS IN,TREMBLES,SWALLOWS,TRANSCENDS,MOCKS,LINGERS 5430 DATA MURMURS,IS FLOATING,DREAMS,RETURNS,WAS GLEAMING,RESTS 5440 DATA IS SWEETENING,FLICKERS,SHIVERS,VANISHES,SPARKS,WEAVES 5450 DATA IS GLOWING,HAS EMBARKED,IS PLUNGING,SHINES,IS PRAYING 5460 DATA HAS HIDDEN,DROWNS,BEAMS DOWN,TWITTERS,HAS DANCED,GLIDES 5470 DATA IS WHISPERING,HAS BURNT,BREATHES,EMBRACES,DRONES,DESCENDS 5480 DATA LIFTS,CREEPS,DWELLS,FLICKERS 5490 REM ++++++++++++++++++ 5500 REM PREPOSITIONS 5510 REM ++++++++++++++++++ 5520 DATA ON,IN,FROM,UNDER,OVER,NEAR,BENEATH,ATOP,WITH,ACROSS 5530 DATA BESIDE,ASTRIDE,IMMERSED IN,INSIDE,THROUGH 5540 REM ++++++++++++++++++ 5550 REM FORMAL STRUCTURES 5560 REM ++++++++++++++++++ 5570 DATA 1,2,3,0,1,3,4,5,1,3,0,2,2,3,-1 5580 DATA 3,5,1,3,0,1,2,3,5,1,3,0,2,3,-1 5590 DATA 1,2,3,0,5,1,2,3,0,1,3,4,-1,-1,-1 5600 DATA 1,2,3,4,0,1,2,2,3,0,5,1,2,3,-1
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Grafplot) 130 REM ========================================================= 140 DIM X(50),Y(50) 150 SUM = 0 160 TOTAL = 21 '<< num of array elements in X() + Y() 170 C$ = "o" '<< character for graph 180 FOR J = 1 TO TOTAL 190 X(J) = SUM '<< load x-axis array 200 Y(J) = SIN(X(J)) '<< load y-axis array 210 SUM = SUM + .314159 220 NEXT J 230 PRINT "0 <= x <= 2pi : sin(x)" 240 GOSUB 1000 '<< call x-y graph plotting 250 END 1000 REM SS1PL2 ================================================= 1010 REM *********************>> XY-PLOT <<********************** 1020 REM ======================================================== 1030 REM This subroutine produces an X-Y line graph of 1040 REM two interdependent parameters (e.g., musical waveform 1050 REM cycle over a time period). It performs its own 1060 REM scaling, which means that any set of data, positive 1070 REM negative, of any range, may be graphed without 1080 REM concern for compression or expansion. 1090 REM ======================================================== 1100 REM Variable Descriptions 1110 REM Entering - 1120 REM X(): array holding the x-axis elements 1130 REM Y(): array holding the y-axis elements 1140 REM TOTAL : number of elements in arrays X(),Y() 1150 REM C$ : plotting character 1160 REM Exiting - 1170 REM none (subroutine is procedural) 1180 REM Local - 1190 REM LOWVAL: lowest value in array Y() 1200 REM HIGHVAL: highest value in array Y() 1210 REM SCDISP: scale displacement between LOWVAL,HIGHVAL 1220 REM LEFTDISP: leftmargin displacement for X position 1230 REM K9: loop index, pointer to arrays X(),Y() 1240 REM ======================================================== 1250 LOWVAL = Y(1) 1260 HIGHVAL = Y(1) 1270 FOR K9 = 2 TO TOTAL 1280 IF Y(K9) < LOWVAL THEN LOWVAL = Y(K9) 1290 IF Y(K9) < HIGHVAL THEN HIGHVAL = Y(K9) 1300 NEXT K9 1310 SCDISP = HIGHVAL - LOWVAL 1320 IF SCDISP = 0 THEN SCDISP = 1 1330 FOR K9 = 1 TO TOTAL 1340 LEFTDISP = INT(1+(Y(K9)-LOWVAL) / SCDISP * 20+.5) 1350 PRINT X(K9);TAB(15 + LEFTDISP);C$ 1360 NEXT K9 1370 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Histo) 130 REM ========================================================= 140 DIM X(20) 150 RANGE = 20 '<< set random number range 1-20 160 TOTAL = 400 '<< return 400 values 170 RANDOMIZE 180 GOSUB 1000 '<< generate frequency table 190 GOSUB 2000 '<< call bargraph display 200 END 1000 REM ======================================================== 1010 REM *******************>> FREQTABL <<*********************** 1020 REM ======================================================== 1030 REM This subroutine computes a table of occurrence 1040 REM frequency for each value generated during a run. 1050 REM ======================================================== 1060 REM Variable Descriptions 1070 REM Entering - 1080 REM TOTAL: number of samples to return 1090 REM RANGE: numeric range of samples 1100 REM Exiting - 1110 REM X(): array holding frequency table 1120 REM Local - 1130 REM VALUE: random integer, pointer to array X() 1140 REM K9: loop index 1150 REM ======================================================== 1160 FOR K9 = 1 TO TOTAL 1170 VALUE = INT(RND * RANGE)+1 '<< gen random value 1180 X(VALUE)=X(VALUE)+1 '<< record occurrence of value 1190 NEXT K9 1200 RETURN 2000 REM ======================================================== 2010 REM *******************>> BARGRAPH <<*********************** 2020 REM ======================================================== 2030 REM This procedural subroutine prints a simple 2040 REM bargraph. In this case the bargraph represents 2050 REM an occurance frequency table of random integers 2060 REM generated during program execution. 2070 REM ======================================================== 2080 REM Variable Descriptions 2090 REM Entering - 2100 REM X(): occurence frequency table, 2110 REM address = random number, 2120 REM contents = frequency of occurance 2130 REM RANGE: range of integer values in table 2140 REM Exiting - 2150 REM none (subroutine is procedural) 2160 REM Local - 2170 REM K9: loop index, pointer to frequency table 2180 REM ======================================================== 2190 FOR K9 = 1 TO RANGE 2200 PRINT K9;TAB(10);STRING$(X(K9),">") 2210 NEXT K9 2220 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Hypcosin) 130 REM ========================================================= 140 DIM X(50) 150 RANDOMIZE 160 TOTAL = 50 170 GOSUB 1000 '<< call hyperbolic cosine distribution 180 FOR J = 1 TO TOTAL 190 PRINT X(J); '<< sequence to screen 200 NEXT J 210 END 1000 REM ======================================================== 1010 REM ******************>> HYPCOSIN <<************************ 1020 REM ======================================================== 1030 REM The Hyperbolic Cosine Probability Distribution 1040 REM function produces a symmetrical curve; however, 1050 REM although centered about zero, it has no mean value. 1060 REM ======================================================== 1070 REM Variable Descriptions 1080 REM Entering - 1090 REM TOTAL: length of sequence 1100 REM Exiting - 1110 REM X(): array holding Hypercosine distribution 1120 REM Local - 1130 REM R9: uniform random number 1140 REM K9: loop index, pointer to array X() 1150 REM ======================================================== 1160 FOR K9 = 1 TO TOTAL 1170 R9 = RND 1180 X(K9) = LOG(TAN(3.14159 * R9 /2))+4 1190 NEXT K9 1200 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (INSORT) 130 REM ========================================================= 140 DIM X(50) 150 TOTAL = 50 160 RANDOMIZE 170 PRINT "ARRAY OF RANDOM-ORDER REAL NUMBERS (RANGE 0-1) --" 180 FOR J = 1 TO TOTAL 190 X(J) = RND 200 PRINT X(J); 210 NEXT J 220 PRINT 230 PRINT "ARRAY SORTED IN ASCENDING ORDER --" 240 GOSUB 1000 '<< call insertion sort 250 FOR J = 1 TO TOTAL 260 PRINT X(J); '<< list to screen 270 NEXT J 280 END 1000 REM SS2TM2 ================================================= 1010 REM ***********************>> INSORT <<********************* 1020 REM ======================================================== 1030 REM This algorithm is surprisingly fast, yet simple 1040 REM to code and comprehend. It is also called the 1050 REM card players sort, because during sorting each 1060 REM unsorted element is inserted in its appropriate 1070 REM slot relative to already sorted values. 1080 REM ======================================================== 1090 REM Variable Descriptions 1100 REM Entering - 1110 REM X(): array of values to be sorted 1120 REM TOTAL: length of array X() 1130 REM Exiting - 1140 REM X(): array sorted in ascending order 1150 REM Local - 1160 REM K9: loop index, pointer to X() 1170 REM L9: loop index, pointer to X() 1180 REM FIRSTVAL: first value in unsorted list 1190 REM ======================================================== 1200 FOR K9=1 TO TOTAL - 1 1210 FIRSTVAL = X(K9+1) 1220 FOR L9=K9 TO 1 STEP -1 1230 IF FIRSTVAL >= X(L9) THEN 1270 1240 X(L9+1) = X(L9) 1250 NEXT L9 1260 L9=0 1270 X(L9+1) = FIRSTVAL 1280 NEXT K9 1290 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM ========================================================= 130 DIM GAMINTS(12),P$(96) 140 RANDOMIZE 150 TOTAL = 5 160 INTOTAL = 6 '<< number of intervals in set 170 GOSUB 2000 '<< call pitch table 180 FOR J = 1 TO INTOTAL 190 GAMINTS(J) = INT(RND * 3)+1 '<< select interval set 200 NEXT J 210 FOR J = 1 TO TOTAL 220 PRINT "CHORD";J 230 ROOT = INT(RND * 12)+1 240 OCTAVE = INT(RND * 3)+1 250 CHORDMEMS = INT(RND * 14)+6 260 GOSUB 1000 '<< call interval gamut generator 270 PRINT 280 NEXT J 290 END 1000 REM ======================================================== 1010 REM *******************>> INTGAM <<************************* 1020 REM ======================================================== 1030 REM This subroutine generates non octave-repeating 1040 REM chords/gamuts from a set of intervals. 1050 REM ======================================================== 1060 REM Variable Descriptions 1070 REM Entering - 1080 REM P$(): pitch name table 1090 REM GAMINTS(): array of interval sizes 1100 REM ROOT: lowest chord/gamut member 1110 REM OCTAVE: octave register for chord initiation 1120 REM CHORDMEMS: number of tones contained in gamut 1130 REM INTOTAL: number of intervals in GAMINTS() 1140 REM Exiting - 1150 REM none (subroutine is procedural) 1160 REM Local - 1170 REM COUNT: tabulates chordtone generation 1180 REM CHORDTONE: next chord/gamut member 1190 REM K9: loop index 1200 REM L9: loop index, pointer to array GAMINTS() 1210 REM ======================================================== 1220 COUNT = 0 1230 CHORDTONE = ROOT + ((OCTAVE - 1) * 12) 1240 FOR K9 = 1 TO 100 1250 FOR L9 = 1 TO INTOTAL 1260 PRINT P$(CHORDTONE);" "; 1270 COUNT = COUNT + 1 1280 IF COUNT = CHORDMEMS THEN RETURN 1290 CHORDTONE = CHORDTONE + GAMINTS(L9) 1300 NEXT L9 1310 NEXT K9 1320 RETURN 2000 REM ======================================================== 2010 REM *******************>> PITCHTAB <<*********************** 2020 REM ======================================================== 2030 REM This subroutine initializes a pitch data table 2040 REM corresponding to integer values 1-n. 2050 REM ======================================================== 2070 NOTE$ = " CC# DD# E FF# GG# AA# B" 2080 OCTAVE$ = "1234567" 2090 FOR K9 = 1 TO 7 2100 FOR L9 = 1 TO 12 2110 P$(L9+(K9-1)*12) = MID$(NOTE$,(L9*2-1),2)+MID$(OCTAVE$,K9,1) 2120 NEXT L9 2130 NEXT K9 2140 RETURN
100 REM ========================================================== 110 REM DRIVER PROGRAM 120 REM (INTLINK) 130 REM ========================================================== 140 DIM PCUM(12),ICUM(12),PCLASS(12) 150 RANDOMIZE(1) 160 TOTAL = 10 170 GOSUB 1000 '<< call interval-linked PC series generator 180 END 1000 REM ========================================================= 1010 REM **********************>> INTLINK <<********************** 1020 REM ========================================================= 1030 REM This subroutine generates a random-order series, 1040 REM locates the series position at which interval-size 1050 REM redundancy occurs, then links subsequent set 1060 REM permutations by moving remaining values from flag- 1070 REM point in the current series to the beginning of the 1080 REM next series to form its nucleus. Appropriate values 1090 REM are then permutated to complete the (now) current 1100 REM series. Thus, value-group repetitions of various 1110 REM lengths are produced - within an overall serial 1120 REM context - as a method of generating new related 1130 REM sequences for use as pointers to pitch, rhythm, 1140 REM volume, articulation, or other parameter elements. 1150 REM ======================================================== 1160 REM Variable Descriptions 1170 REM Entering - 1180 REM TOTAL: number of series to generate & link 1190 REM Exiting - 1200 REM (to ZEROMAT) 1210 REM PCUM: array of pitchclass flags 1220 REM ICUM: array of intervalclass flags 1230 REM (to MATPRINT) 1240 REM PCLASS(): array holding current series 1250 REM REDPT: interval redundancy point marker 1260 REM Local - 1270 REM INTSIZE: interval between consecutive pitchclasses 1280 REM SHIFT: number of places to shift remaining setmems 1290 REM R9: random integer 1300 REM K9: loop index 1310 REM L9: loop index, pointer to PCLASS() 1320 REM ======================================================== 1330 REDPT = 1 1340 FOR K9 = 1 TO TOTAL '<< flag carried-over set members 1350 FOR L9 = 1 TO 12 1360 IF PCLASS(L9) > 0 THEN PCUM(PCLASS(L9)) = 1 1370 NEXT L9 1380 FOR L9 = 1 TO 12 '<< gen required new setmembers 1390 IF PCLASS(L9) > 0 THEN 1440 1400 R9 = INT(RND * 12) + 1 1410 IF PCUM(R9) = 1 THEN 1400 1420 PCUM(R9) = 1 1430 PCLASS(L9) = R9 1440 NEXT L9 1450 FOR L9 = 1 TO 11 '<< find intervals btwn setmembers 1460 INTSIZE = PCLASS(L9+1) - PCLASS(L9) 1470 IF INTSIZE < 0 THEN INTSIZE = 12 - ABS(INTSIZE) 1480 IF ICUM(INTSIZE) = 1 THEN 1510'<<mark redundancy 1490 ICUM(INTSIZE) = 1 1500 NEXT L9 1510 REDPT = L9 + 1 1520 PRINT "INTERVAL REDUNDANCY OCCURS"; 1530 PRINT " AT POSITION -->";REDPT 1540 GOSUB 2000 1550 GOSUB 3000 1560 SHIFT = 1 1570 FOR L9 = REDPT TO 12 '<< shift set balance forward 1580 PCLASS(SHIFT) = PCLASS(L9) 1590 SHIFT = SHIFT + 1 1600 NEXT L9 1610 FOR L9 = SHIFT TO 12'<< zero remaining array places 1620 PCLASS(L9) = 0 1630 NEXT L9 1640 NEXT K9 1650 RETURN 2000 REM ======================================================== 2010 REM *********************>> MATPRINT <<********************* 2020 REM (adapted to program specs) 2030 REM ======================================================== 2040 PRINT "PC SET: "; 2050 FOR M9 = 1 TO 12 2060 PRINT PCLASS(M9); 2070 IF M9 = REDPT - 1 THEN PRINT "||"; 2080 NEXT M9 2090 PRINT 2100 RETURN 3000 REM ======================================================== 3010 REM *********************>> ZEROMAT <<********************** 3020 REM (adapted to program specs) 3030 REM ======================================================== 3040 FOR N9 = 1 TO 12 3050 PCUM(N9) = 0 : ICUM(N9) = 0 3060 NEXT N9 3070 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Linear) 130 REM ========================================================= 140 DIM X(50) 150 RANDOMIZE 160 TOTAL = 50 170 GOSUB 1000 '<< call linear distribution 180 FOR J = 1 TO TOTAL 190 PRINT X(J); '<< sequence to screen 200 NEXT J 210 END 1000 REM ======================================================== 1010 REM **********************>> LINEAR <<********************** 1020 REM (D)===================================================== 1030 REM The Linear Distribution Function generates 1040 REM continuous,random-order real numbers > 0 & < 1. 1050 REM Results closer to 0 are most likely to occur. 1060 REM The reverse condition may be obtained by altering 1070 REM the algorithm to select the larger rather than 1080 REM the smaller random value in line 1230. 1090 REM ======================================================== 1100 REM Variable Descriptions 1110 REM Entering - 1120 REM TOTAL: length of sequence 1130 REM Exiting - 1140 REM X(): array holding LINEAR real number sequence 1150 REM Local - 1160 REM R8: random number 1 1170 REM R9: random number 2 1180 REM K9: loop index, pointer to array X() 1190 REM ======================================================== 1200 FOR K9 = 1 TO TOTAL 1210 R8 = RND 1220 R9 = RND 1230 IF R9 < R8 THEN R8=R9 1240 X(K9) = R8 1250 NEXT K9 1260 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (LINEFIT) 130 REM ========================================================= 140 DIM X(100),Y(100) 150 RANDOMIZE(-2438) 160 C$ = "o" '<< character for graph 170 TOTAL = 50 180 PRINT TOTAL;"RANDOM NUMBERS" 190 PRINT 200 FOR J = 1 TO TOTAL 210 X(J)=J '<< data point ordinate 220 Y(J)= INT(RND * 88) + 1 '<< data point coordinate 230 PRINT Y(J), '<< random-order data to screen 240 NEXT J 250 GOSUB 1000 '<< call linear least squares fit 260 PRINT 270 PRINT "STRAIGHT LINE THAT BEST FITS THE DATA:" 280 PRINT 290 PRINT "Y=";SLOPE;"X"; 300 IF INTERCEPT < 0 THEN PRINT "-"; ELSE PRINT "+"; 310 PRINT ABS(INTERCEPT) 320 FOR K9 = 1 TO TOTAL '<< scale line for graph plotting 330 Y(K9) = SLOPE * K9 + INTERCEPT 340 NEXT K9 350 GOSUB 2000 '<< call x-y graph plot 360 END 1000 REM ======================================================== 1010 REM *********************>> LINEFIT <<********************** 1020 REM ======================================================== 1030 REM This subroutine calculates the equation of the 1040 REM straight line that best fits a set of data. 1050 REM Its proper name is the Linear Least Squares Fit. 1060 REM When the data is a collection of musical parameter 1070 REM values, this algorithm provides a quick picture of 1080 REM (statistical) direction tendency over the sequence 1090 REM of values. 1100 REM ======================================================== 1110 REM Variable Descriptions 1120 REM Entering- 1130 REM X(): array of ordinate increments 1140 REM Y(): array of random integers for coordinate 1150 REM TOTAL: number of data points 1160 REM Exiting - 1170 REM SLOPE: slope of linear least squares fit 1180 REM INTERCEPT: (coordinate) intercept of linear least 1190 REM squares fit line 1200 REM Local - 1210 REM XERR: sum of x errors 1220 REM XSQERR: sum of x-squared errors 1230 REM YERR: sum of y errors 1240 REM XYPRODERR: sum of x-y (cross-product) errors 1250 REM K9: loop index, pointer to X(),Y() 1260 REM ======================================================== 1270 XERR = 0 1280 XSQERR = 0 1290 YERR = 0 1300 XYPRODERR = 0 1310 FOR K9 = 1 TO TOTAL 1320 XERR = XERR + X(K9) 1330 XSQERR = XSQERR + X(K9) ^ 2 1340 YERR = YERR + Y(K9) 1350 XYPRODERR = XYPRODERR + X(K9) * Y(K9) 1360 NEXT K9 1370 SLOPE=(TOTAL * XYPRODERR - XERR * YERR) / (TOTAL * XSQERR - XERR ^ 2) 1380 INTERCEPT = (XSQERR * YERR - XERR * XYPRODERR) / (TOTAL * XSQERR - XERR ^ 2) 1390 RETURN 2000 REM ======================================================== 2010 REM *********************>> XY-PLOT <<********************** 2020 REM ======================================================== 2030 LOWVAL = Y(1) 2040 HIGHVAL = Y(1) 2050 FOR K9 = 2 TO TOTAL 2060 IF Y(K9) < LOWVAL THEN LOWVAL = Y(K9) 2070 IF Y(K9) < HIGHVAL THEN HIGHVAL = Y(K9) 2080 NEXT K9 2090 SCDISP = HIGHVAL - LOWVAL 2100 IF SCDISP = 0 THEN SCDISP = 1 2110 FOR K9 = 1 TO TOTAL 2120 LEFTDISP = INT(1+(Y(K9)-LOWVAL) / SCDISP * 2+.5) 2130 PRINT X(K9);TAB(5+LEFTDISP);C$ 2140 NEXT K9 2150 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Logistic) 130 REM ========================================================= 140 DIM X(50) 150 RANDOMIZE 160 TOTAL = 50 170 PAR1 = 1 180 PAR2 = 5 190 GOSUB 1000 '<< call logistic distribution function 200 FOR J = 1 TO TOTAL 210 PRINT X(J); '<< sequence to screen 220 NEXT J 230 END 1000 REM ======================================================== 1010 REM *********************>> LOGISTIC <<********************* 1020 REM ======================================================== 1030 REM The Logistic Probability Distribution function is 1040 REM controlled by the variables PAR1 and PAR2. 1050 REM Output takes the form of continuously variable 1060 REM random-order real numbers (negative to positive). 1070 REM The control parameters determine mean and 1080 REM dispersion of the distribution. 1090 REM ======================================================== 1100 REM Variable Descriptions 1110 REM Entering - 1120 REM TOTAL: length of sequence 1130 REM PAR1: control value 1 1140 REM PAR2: control value 2 1150 REM Exiting - 1160 REM X(): array holding Logistic distribution 1170 REM Local - 1180 REM R9: uniform random number 1190 REM K9: loop index, pointer to array X() 1200 REM ======================================================== 1210 FOR K9 = 1 TO TOTAL 1220 R9 = RND 1230 X(K9) =(-PAR1 * -LOG(1 / R9 - 1)) / PAR2 1240 NEXT K9 1250 RETURN
100 REM ========================================================= 200 REM DRIVER PROGRAM 205 REM ========================================================= 220 DIM NUM(20) 230 PERIOD = 2 240 FACTOR = 3 250 STARTNUM = 20 260 NOTES = 20 270 MANY = 10 280 MODE$ = "S" 290 FOR J = 1 TO NOTES 300 NUM(J) = J 310 NEXT J 320 GOSUB 1000 '<< call loop generator (subtractive mode) 330 MODE$ = "A" 340 STARTNUM = 1 350 PRINT:PRINT 360 GOSUB 1000 '<< call loop generator (additive mode) 370 END 1000 REM ======================================================== 1010 REM *******************>> LOOPGEN1 <<*********************** 1020 REM ======================================================== 1030 REM This subroutine is pattern/process oriented. 1040 REM It generates a given number of copies (loops) 1050 REM of an input sequence while processing the 1060 REM sequence in terms of length. The two modes 1070 REM of loop alteration are additive and subtractive. 1080 REM In additive mode, the loop copies grow longer 1090 REM with successive iteration, beginning with a 1100 REM melodic nucleus. In Subtractive mode, loop 1110 REM copies begin with the complete sequence, and 1120 REM grow shorter by a constant factor with each 1130 REM iteration. The loop copies are printed out 1140 REM within the subroutine, rather than being passed 1150 REM back to the main program. 1160 REM ======================================================== 1170 REM Variable Descriptions 1180 REM Entering - 1190 REM NUM(): array containing numeric sequence 1200 REM PERIOD: number of cycles between loop change 1210 REM FACTOR: number of values to add/subtr 1220 REM STARTNUM: sequence nucleus in additive mode 1230 REM NOTES: number of values in original sequence 1240 REM MANY: number of loop iterations 1250 REM MODE$: holds flag for additive/subtractive mode 1260 REM 1270 REM Exiting - 1280 REM none 1290 REM 1300 REM Local - 1310 REM ALTER: stores current sequence length 1320 REM SHORT: holds number of values to add/subtract 1330 REM ITER: counts cycles, controls loop growth/trunc. 1340 REM COPIES: loop index 1350 REM ======================================================== 1360 SHORT = FACTOR 1370 ITER = PERIOD 1380 IF MODE$ = "A" THEN ALTER = STARTNUM ELSE ALTER = NOTES 1390 IF MODE$ = "S" THEN PRINT "SUBTRACTIVE MODE -" ELSE PRINT "ADDITIVE MODE -" 1400 FOR COPIES = 0 TO MANY-1 1410 IF COPIES < ITER THEN 1440 1420 IF MODE$ = "A" THEN ALTER = STARTNUM + SHORT ELSE ALTER = NOTES - SHORT 1430 IF ALTER > NOTES THEN ALTER = NOTES 1440 FOR DUP = 1 TO ALTER 1450 PRINT NUM(DUP); 1460 NEXT DUP 1470 PRINT "/**/"; 1480 IF COPIES = MANY THEN 1530 1490 IF COPIES < ITER THEN 1520 1500 SHORT = SHORT + FACTOR 1510 ITER = ITER + PERIOD 1520 NEXT COPIES 1530 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM ========================================================= 130 DIM X(20),TEMP(20) 140 NUMVALS = 20 150 FACTOR = 6 160 MANY = 6 170 REVERSE$ = "Y" 180 PRINT "ORIGINAL SEQUENCE -" 190 FOR J = 1 TO NUMVALS 200 PRINT J; 210 X(J) = J '<< load array with number sequence 220 NEXT J 230 PRINT 240 PRINT MANY;"COPIES TO BE MADE. DURING EACH CYCLE" 250 PRINT FACTOR;"VALUES WILL BE SHIFTED, REVERSE ORDER -" 260 GOSUB 1000 '<< call loop generator 270 END 1000 REM ======================================================== 1010 REM *******************>> LOOPGEN2 <<*********************** 1020 REM ======================================================== 1030 REM This is a pattern/process oriented subroutine which 1040 REM shifts a specific number of values from the end of 1050 REM a group while generating a given number of loop copies. 1060 REM The shifted values may be placed in reverse order. 1070 REM ======================================================== 1080 REM Variable Descriptions 1090 REM Entering - 1100 REM X(): holds original number sequence 1110 REM NUMVALS: total in sequence 1120 REM FACTOR: number of values to shift 1130 REM MANY: number of loops to return 1140 REM REVERSE$: flag to reverse shifted values 1150 REM Exiting - 1160 REM none (original X() array contents are destroyed) 1170 REM 1180 REM Local - 1190 REM TEMP(): stores values to be shifted 1200 REM X(): stores loops, rearranged each cycle 1210 REM COPIES: loop index 1212 REM HOLD: loop index, pointer to array TEMP() 1220 REM GROUP: loop index 1230 REM SHIFT: loop index, pointer to array X() 1240 REM REPLACE: loop index, pointer to array X() 1250 REM CURRLOOP: loop index, pointer to array X() 1260 REM ======================================================== 1270 FOR COPIES = 1 TO MANY 1280 REM >>> remove array values to be shifted 1290 FOR HOLD = 0 TO FACTOR - 1 1300 TEMP(HOLD + 1) = X(NUMVALS - HOLD) 1310 NEXT HOLD 1320 REM >>> slide remaining values to end of array 1330 FOR GROUP = 1 TO FACTOR 1340 FOR SHIFT = NUMVALS TO 1 STEP - 1 1350 X(SHIFT) = X(SHIFT - 1) 1360 NEXT SHIFT 1370 NEXT GROUP 1380 REM >>> place values to be moved at head of array 1390 REM >>> if flagged, reverse them 1400 FOR REPLACE = 1 TO FACTOR 1410 IF REVERSE$ = "Y" THEN X(REPLACE) = TEMP(REPLACE) ELSE X(REPLACE) = TEMP(FACTOR + 1 - REPLACE) 1420 NEXT REPLACE 1430 PRINT "/*"; 1440 FOR CURRLOOP = 1 TO NUMVALS 1450 PRINT X(CURRLOOP); 1460 NEXT CURRLOOP 1470 PRINT "*/" 1480 NEXT COPIES 1490 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Markov) 130 REM ========================================================= 140 DIM CYCLE(5000), SEED(88), FREQ(88) 150 ORDER = 2 '<<nmbr of preceding terms to sum for next term 160 MODULUS = 12 '<< set modulus of residue cycle 170 APPLY$ = "INCLUSIVE" '<< apply to all seeds 180 FOR J = 1 TO 2 '<< generate 2 separate cycles 190 PRINT APPLY$;" ADDITION; SEEDS ARE :"; 200 FOR J1 = 1 TO ORDER 210 READ SEED(J1) 220 PRINT SEED(J1); '<< send seeds to screen 230 NEXT J1 240 REM ++++++++++++++++++++ 250 DATA 0,1,1,4,5 260 REM ++++++++++++++++++++ 270 PRINT 280 GOSUB 1000 '<< call Markovian summation subroutine 290 PRINT 300 PRINT TOTAL; " - MEMBER CYCLE:" 310 PRINT 320 FOR J1 = 1 TO TOTAL 330 PRINT CYCLE(J1), '<< display completed cycle 340 NEXT J1 350 PRINT : PRINT 360 PRINT "FREQUENCY TABLE:" 370 PRINT 380 FOR J1 = 1 TO MODULUS 390 PRINT (J1-1); ":"; FREQ(J1), 400 NEXT J1 410 ORDER = 3 '<< number of preceding terms to sum 420 APPLY$ = "EXCLUSIVE" '<< add outside seed pairs only 430 PRINT 440 PRINT 450 NEXT J 460 END 1000 REM ======================================================== 1010 REM MARKOV 1020 REM ======================================================== 1030 REM Markovian Integer Summation Residual Cycle Generator 1040 REM ======================================================== 1050 REM Variable Descriptions 1060 REM Entering - 1070 REM ORDER: number of immediately preceding terms 1080 REM whose sum determines next term 1090 REM MODULUS: Integer-range modulus; cycle-creating 1100 REM factor to be imposed on each sum 1110 REM SEED(): array of seeds (initial "Order" number 1120 REM of integers to be summed) 1130 REM APPLY$: string to signal inclusive or exclusive 1140 REM addition of series seeds 1150 REM Exiting - 1160 REM CYCLE(): array holding generated integer cycle 1170 REM FREQ(): array of integer occurrence frequencies 1180 REM Local - 1190 REM NXTERM: next term to be computed 1200 REM TOTAL: total number of terms generated 1210 REM K9: loop index 1220 REM L9: loop index 1230 REM ======================================================== 1240 FOR K9 = 1 TO ORDER 1250 CYCLE(K9) = SEED(K9) '<< start cycle with seeds 1260 NEXT K9 1270 TOTAL = ORDER 1280 FOR K9 = 1 TO 5000 '<< compute next new term 1290 NXTERM = SEED(ORDER) 1300 FOR L9 = 1 TO (ORDER-1) 1310 NXTERM = NXTERM + SEED(L9) 1320 NEXT L9 1330 IF APPLY$ = "EXCLUSIVE"
THEN NXTERM = SEED(ORDER) + SEED(1) 1340 NXTERM = NXTERM - INT(NXTERM/MODULUS) * MODULUS 1350 CYCLE(K9+ORDER) = NXTERM 1360 FOR L9 = 1 TO (ORDER-1) 1370 SEED(L9) = SEED(L9+1) '<< update seeds 1380 NEXT L9 1390 SEED(ORDER) = NXTERM 1400 TOTAL = TOTAL + 1 1410 FOR L9 = 1 TO ORDER 1420 IF SEED(L9) <> CYCLE(L9) THEN 1470 '<< finished? 1430 NEXT L9 1440 L9 = ORDER 1450 K9 = 5000 1460 TOTAL = TOTAL - ORDER 1470 NEXT K9 1475 GOSUB 2000 ' << call zeromat 1480 FOR K9 = 1 TO MODULUS '<< compute occurrence frequencies 1490 FOR L9 = 1 TO TOTAL 1500 IF CYCLE(L9) + 1 = K9 THEN FREQ(K9) = FREQ(K9) + 1 1510 NEXT L9 1520 NEXT K9 1530 RETURN 2000 REM================================================= CTB1.9 2010 REM *******************>> ZEROMAT <<*********************** 2020 REM ======================================================= 2030 FOR K9 = 1 TO MODULUS 2040 FREQ(K9) = 0 2050 NEXT K9 2060 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM ========================================================= 130 DIM W(10,10) 140 COUNT = 0 150 TOTAL = 40 160 XLOC = 5 : YLOC = 5 '<< matrix start coordinates 170 ROWS = 10 : COLS = 10 180 PRINT "THE MATRIX FOR THIS RANDOM WALK -" 190 FOR J1 = 1 TO ROWS 200 FOR J2 = 1 TO COLS 210 W(J1,J2)=((J1-1) * COLS) + J2 220 COUNT = COUNT + 1 230 IF (COUNT/COLS) = J1 THEN PRINT W(J1,J2)ELSE PRINT W(J1,J2); 240 IF COUNT < 9 THEN PRINT " "; 250 NEXT J2 260 NEXT J1 270 PRINT "START COORDINATES ARE: ROW ";XLOC;"COLUMN ";YLOC 280 RANDOMIZE 290 GOSUB 1000 '<< call matrix walk 300 END 1000 REM ======================================================== 1010 REM *********************>> MATWALK <<********************** 1020 REM ======================================================== 1030 REM This subroutine simulates a random walk within the 1040 REM boundaries of a two-dimensional matrix. The walker 1050 REM is free to step up, down, sideways, or diagonally. 1060 REM By shaping the matrix in various proportions, the 1070 REM user can influence the numeric interval sequence. 1080 REM Applied to pitch content, the effect is one of 1090 REM generating melodies with interval class succession 1100 REM which vary with the matrix shape & size. 1110 REM ======================================================== 1120 REM Variable Descriptions 1130 REM Entering - 1140 REM W(n,n): random walk matrix 1150 REM TOTAL: number of random steps to be taken 1160 REM XLOC: stores current location on horizontal 1170 REM YLOC: stores current location on vertical 1180 REM ROWS: length of matrix 1190 REM COLS: width of matrix 1200 REM Exiting - 1210 REM none (subroutine is procedural) 1220 REM Local - 1230 REM XSTEP: random number -1, 0, or + 1 1240 REM YSTEP: random number -1. 0, or + 1 1250 REM K9: loop index 1260 REM ======================================================== 1270 FOR K9 = 1 TO TOTAL 1280 PRINT W(XLOC,YLOC);" "; 1290 XSTEP = INT(RND * 3) - 1 1300 YSTEP = INT(RND * 3) - 1 1310 XLOC = XLOC + XSTEP 1320 YLOC = YLOC + YSTEP 1330 IF XLOC <= 0 THEN XLOC = 2 ELSE IF XLOC > ROWS THEN XLOC = ROWS - 1 1340 IF YLOC <= 0 THEN YLOC = 2 ELSE IF YLOC > COLS THEN YLOC = COLS - 1 1350 NEXT K9 1360 RETURN
100 REM ========================================================= 110 REM PROGRAM DRIVER 120 REM (Meline) 130 REM ========================================================= 140 DIM NOTE$(100),P$(84) 150 RANDOMIZE 160 TOTAL = 10 '<< length of sequence 170 SMALL = 1 180 LARGE = 3 190 UP = 80 200 REST = 0 210 START = 48 220 GOSUB 3010 '<< call pitch table 230 FOR J = 1 TO 4 240 NOTE$(1) = P$(START) 250 NOTE = START 260 PRINT "PASS";J 270 PRINT "TOTAL =";TOTAL;";SMALL=";SMALL;";LARGE =";LARGE;";UP =";UP;";REST=";REST;";START =";START 280 PRINT NOTE$(1);" "; 290 FOR J1 = 2 TO TOTAL 300 GOSUB 1000 '<<call rest probability 310 IF FLAG = 0 THEN GOSUB 2000 '<< call interval generator 320 PRINT NOTE$(J1);" "; '<< send array to screen 330 NEXT J1 340 PRINT 350 TOTAL = TOTAL + 10 360 SMALL = SMALL + 1 370 LARGE = LARGE + 2 380 INTVALRANGE = LARGE-SMALL+1 390 UP = UP - 20 400 REST = REST + 10 410 NEXT J 420 END 1000 REM ========================================================= 1010 REM ***********************>> REST <<************************ 1020 REM ========================================================= 1030 REM This subroutine is similar to ADDORN, in that 1040 REM it checks a rest percentage threshold value 1050 REM before deciding whether to insert a rest note 1060 REM ========================================================= 1070 REM Variable Descriptions 1080 REM Entering - 1090 REM REST: threshold test value (% of rest) 1100 REM NOTE$(): array to receive rest string (if selected) 1110 REM P$(0): pitchtable array address holding rest string 1120 REM J1: pointer to NOTE$() array 1130 REM Exiting - 1140 REM FLAG: signal to DRIVER not to call pitch generator 1150 REM NOTE$(): 1160 REM Local - none 1170 REM ========================================================= 1180 FLAG = 0 1190 IF RND * 100 <= REST THEN NOTE$(J1) = P$(0) : FLAG = 1 1200 RETURN 2000 REM ========================================================= 2010 REM *********************>> MELINT <<************************ 2020 REM ========================================================= 2030 REM This subroutine resembles RDINTCHD in concept. 2040 REM However, it generates an interval-contained 2050 REM melodic sequence which is bi-directional 2060 REM as opposed to RDINTCHD's harmonic, unidirectional 2070 REM orientation. 2080 REM ========================================================= 2090 REM Variable Descriptions 2100 REM Entering - 2110 REM SMALL: smallest allowable interval-size 2120 REM INTVALRANGE: span of allowable interval-sizes 2130 REM NOTE: most recent note generated 2140 REM UP: probability of upward interval motion 2150 REM NOTE$(): array to be filled with notes/rests 2160 REM P$(): pitch table array 2170 REM J1: pointer to NOTE$() array 2180 REM Exiting - 2190 REM NOTE$(): 2200 REM Local - 2210 REM U: range-controlled random integer 2220 REM ======================================================= 2230 U = INT(RND * INTVALRANGE) + SMALL 2240 IF RND * 100 <= UP THEN NOTE = NOTE + U ELSE NOTE = NOTE - U 2250 IF NOTE > 84 THEN NOTE = NOTE - 12 ELSE IF NOTE < 1 THEN NOTE = NOTE + 12 '<< in bounds? 2260 NOTE$(J1) = P$(NOTE) 2270 RETURN 3000 REM ========================================================= 3010 REM ********************>> PITCHTAB <<*********************** 3020 REM ========================================================= 3030 NOTE$ = " CC# DD# E FF# GG# AA# B" 3040 OCTAVE$ = "1234567" 3050 P$(0) = " R " 3060 FOR K9 = 1 TO 7 3070 FOR L9 = 1 TO 12 3080 P$(L9+(K9-1)*12) = MID$(NOTE$,(L9*2-1),2)+MID$(OCTAVE$,K9,1) 3090 NEXT L9 3100 NEXT K9 3110 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Modops) 130 REM ========================================================= 140 DIM P$(12) 150 DIM X(12),Y(12) 160 RANDOMIZE 170 TOTAL = 12 180 OP = 5 '<< value for m5 operation 190 GOSUB 1000 '<< call pitch table 200 GOSUB 2000 '<< call random shuffle 210 PRINT 220 PRINT "RANDOM-ORDER 12-TONE SET --" 230 FOR J = 0 TO TOTAL-1 240 PRINT P$(X(J));" "; '<< random 12-tone set to screen 250 NEXT J 260 PRINT : PRINT 270 FOR J = 1 TO 2 280 GOSUB 3000 '<< call m5/m7 permutation 290 PRINT "THE PERMUTATION RESULTING FROM ";"M";OP;" OPERATION" 300 FOR J1 = 0 TO TOTAL-1 310 PRINT P$(Y(J1));" "; '<< send perm to screen 320 NEXT J1 330 PRINT : PRINT 340 OP = 7 '<< value for m7 operation 350 NEXT J 360 END 1000 REM ======================================================== 1010 REM *******************>> PITCHTAB <<*********************** 1020 REM (modified to load pitch classes only) 1030 REM ======================================================== 1040 FOR J = 0 TO TOTAL-1 1050 X(J) = J '<< load set elements 1060 READ P$(J) '<< load pitch class equivalents 1070 NEXT J 1080 REM+++++++++++++++++++++++++++++++++ 1090 DATA C,C#,D,D#,E,F,F#,G,G#,A,A#,B 1100 REM+++++++++++++++++++++++++++++++++ 1110 RETURN 2000 REM ======================================================== 2010 REM ********************>> CONSHUFL <<********************** 2020 REM ======================================================== 2030 FOR K9 = 0 TO TOTAL-1 2040 R9 = INT(RND * TOTAL) 2050 S9 = X(K9) 2060 X(K9) = X(R9) 2070 X(R9) = S9 2080 NEXT K9 2090 RETURN 3000 REM ======================================================== 3010 REM *********************>> M5SETM7 <<********************** 3020 REM ======================================================== 3030 REM This subroutine outputs a permutation of an input 3040 REM set (series) by the "M5" or "M7" operation. 3050 REM ======================================================== 3060 REM Variable Descriptions 3070 REM Entering - 3080 REM X(): array holding random 12-tone set 3090 REM OP: value for m5 or m7 operation 3100 REM Exiting - 3110 REM Y(): array holding m5 or m7 permutation 3120 REM Local - 3130 REM K9: loop index, pointer to X(),Y() 3140 REM ======================================================= 3150 FOR K9 = 0 TO 11 3160 Y(K9) = (X(K9) * OP) MOD 12 3170 NEXT 3180 RETURN
100 REM ======================================================== 110 REM DRIVER PROGRAM 120 REM ======================================================== 125 M = 12 '<< set modulus to 12 130 FOR J = 0 TO 83 '<< values to be converted mod M 140 M = 12 '<< set modulus to 12 150 GOSUB 1000 '<< call mod function 160 PRINT R; '<< send remainder to screen 170 IF R = 11 THEN PRINT '<< start newline 180 NEXT J 190 END 1000 REM ======================================================== 1010 REM ********************>> MODULO <<************************ 1020 REM ======================================================== 1030 REM This subroutine is actually a function which 1040 REM receives an integer and returns the value of the 1050 REM integer modulo n. A more practical alternative 1060 REM is to code it as a user-defined funcion: 1070 REM DEF FNM(J,M) = J - INT(J / M) * M 1080 REM ======================================================== 1090 REM 1100 REM Variable Descriptions 1110 REM Entering - 1120 REM M: the modulus to be applied 1130 REM J: the integer to be returned mod M 1140 REM Exiting - 1150 REM R: the remainder mod I to be returned 1160 REM Local - 1170 REM none 1180 REM 1190 REM ======================================================== 1200 R = J-INT(J/M)*M 1210 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM Motforms 130 REM ========================================================= 140 DIM X(15),Y(15),P$(84) 150 RANDOMIZE(967) 160 GOSUB 1000 '<< call pitch table 170 TOTAL = 15 180 PRINT "ORIGINAL PITCH MOTIF --" 190 FOR J = 1 TO TOTAL 200 X(J) = INT(RND * 12) + 1 210 PRINT P$(X(J));" "; '<< random motif to screen 220 NEXT J 230 PRINT 240 GOSUB 3000 '<< call retrograde 250 PRINT "THE RETROGRADE MOTIF --" 260 GOSUB 2000 '<< call table print 270 PRINT 280 GOSUB 4000 '<< call motif inversion 290 PRINT "THE INVERTED MOTIF --" 300 GOSUB 2000 '<< call table print 310 PRINT 320 INTVAL = 1 '<< (set transposition interval 330 PRINT "ORIGINAL MOTIF TRANSPOSITIONS" 340 FOR J = 1 TO 11 350 PRINT "NUMBER ";J 360 GOSUB 5000 '<< call motif transposition 370 GOSUB 2000 '<< call table print 380 PRINT 390 INTVAL = INTVAL + 1 400 NEXT J 410 END 1000 REM ========================================================= 1010 REM ********************>> PITCHTAB <<*********************** 1020 REM ========================================================= 1030 NOTE$ = " CC# DD# E FF# GG# AA# B" 1040 OCTAVE$ = "1234567" 1050 FOR K9 = 1 TO 7 1060 FOR L9 = 1 TO 12 1070 P$(L9+(K9-1)*12) = MID$(NOTE$,(L9*2-1),2)+MID$(OCTAVE$,K9,1) 1080 NEXT L9 1090 NEXT K9 1100 RETURN 2000 REM ======================================================== 2010 REM ********************>> TABLPRNT <<********************** 2020 REM ======================================================== 2030 FOR K9 = 1 TO TOTAL 2040 PRINT P$(Y(K9));" "; 2050 NEXT K9 2060 RETURN 3000 REM ======================================================== 3010 REM *********************>> MOTRETRO <<********************* 3020 REM ======================================================== 3030 REM This subroutine accepts an input pitch sequence 3040 REM and outputs its retrograde form. 3050 REM ======================================================== 3060 REM Variable Descriptions 3070 REM Entering - 3080 REM X(): prime motif array 3090 REM TOTAL: motif length 3100 REM Exiting - 3110 REM Y(): retrograde motif array 3120 REM Local - 3130 REM L: pointer to Y() 3140 REM K9; loop index, pointer to X() 3150 REM ======================================================== 3160 FOR K9 = 1 TO TOTAL 3170 L = TOTAL-K9+1 3180 Y(L)=X(K9) 3190 NEXT K9 3200 RETURN 4000 REM ======================================================== 4010 REM ********************>> MOTINVRT <<********************** 4020 REM ======================================================== 4030 REM This subroutine accepts an input pitch sequence 4040 REM and outputs its mirror image form. 4050 REM ======================================================== 4060 REM Variable Descriptions 4070 REM Entering - 4080 REM X(): prime motif array 4090 REM TOTAL: motif length 4100 REM Exiting - 4110 REM Y(): inverted motif array 4120 REM Local - 4130 REM K9: loop index, pointer to X(),Y() 4140 REM ======================================================== 4150 Y(1)=X(1) 4160 FOR K9 = 2 TO TOTAL 4170 Y(K9) = Y(K9-1)-(X(K9)-X(K9-1)) 4180 NEXT K9 4190 RETURN 5000 REM ======================================================== 5010 REM ********************>> MOTRNPZ <<*********************** 5020 REM ======================================================== 5030 REM This subroutine transposes an input motif by 5040 REM a specified number of 1/2 steps. Transposition 5050 REM direction is determined by the sign of the 5060 REM transposition interval. 5070 REM ======================================================== 5080 REM Variable Descriptions 5090 REM Entering - 5100 REM X(): array holding random motif 5110 REM TOTAL: motif length 5120 REM INTVAL: interval of transposition in 1/2-steps 5130 REM Exiting - 5140 REM Y(): array holding transposed motif 5150 REM Local - 5160 REM K9: loop index, pointer to Y() 5170 REM ======================================================== 5180 FOR K9 = 1 TO TOTAL 5190 Y(K9) = X(K9) + INTVAL 5200 NEXT K9 5210 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Normhist) 130 REM ========================================================= 140 DIM X(20) 150 RANGE = 20 '<< set random number range 1-20 160 TOTAL = 1000 '<< return 1000 values 170 RANDOMIZE 180 CLS 190 PRINT "INTEGER VALUE";TAB(20);"NORM. VALUE";TAB(40);"BAR MAP" 200 GOSUB 1000 '<< generate frequency table 210 GOSUB 2000 '<< call data normalization 220 GOSUB 3000 '<< call bargraph display 230 END 1000 REM ======================================================== 1010 REM *******************>> FREQTABL <<*********************** 1020 REM ======================================================== 1030 FOR K9 = 1 TO TOTAL 1040 VALUE = INT(RND * RANGE)+1 '<< gen random value 1050 X(VALUE)=X(VALUE)+1 '<< record occurrence of value 1060 NEXT K9 1070 RETURN 2000 REM SS1ST6 ================================================= 2010 REM ********************>> DATANORM <<********************** 2020 REM ======================================================== 2030 REM This subroutine compresses wide-range data to 2040 REM fit within the range of 0 to 1. It is especially 2050 REM helpful when printing histograms of huge amounts 2060 REM of data which would otherwise cause the bars to 2070 REM wrap-around the screen. 2080 REM 2090 REM To adequately test probability distribution 2100 REM functions for musical uses, it often is necessary 2110 REM to generate thousands of values to flesh out a 2120 REM curve. When this is the goal, it is important 2130 REM to observe the shape of the distribution, not 2140 REM specific integer frequencies. 2150 REM ======================================================= 2160 REM Variable Descriptions 2170 REM Entering - 2180 REM X(): frequency table to be normalized 2190 REM RANGE: range of integers in frequency table 2200 REM Exiting - 2210 REM X(): normalized frequency table 2220 REM Local - 2230 REM SUM: total of values frequency table 2240 REM K9: loop index,pointer to array X() 2250 REM ======================================================== 2260 SUM = 0 2270 FOR K9 = 1 TO RANGE 2280 SUM = SUM + X(K9) 2290 NEXT K9 2300 FOR K9=1 TO RANGE 2310 X(K9) = X(K9)/ SUM 2320 NEXT K9 2330 PRINT 2340 RETURN 3000 REM ======================================================== 3010 REM *******************>> BARGRAPH <<*********************** 3020 REM (adapted to program specs) 3030 REM ======================================================== 3040 FOR K9=1 TO RANGE 3050 MAP = INT(100*X(K9)+.5) 3060 PRINT K9;"=";TAB(20);X(K9);TAB(40);STRING$(MAP,">") 3070 NEXT K9 3080 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM ========================================================= 130 DIM GAMINTS(12),P$(96) 140 GAMUTS = 3 '<< number of unique gamuts 150 RANDOMIZE 160 SEGTOTAL = 3 '<< # of scale segments to return per gamut 170 INTOTAL = 6 '<< number of intervals in scale 180 GOSUB 2000 '<< call pitch table 190 FOR J1 = 1 TO GAMUTS 200 PRINT "SCALE GAMUT";J1;"INTERVAL SET ---"; 210 HIGHOCTAVE = 7 220 EXCEED = 0 230 REM >>> select an octave-containable (scale) interval set 240 FOR J2 = 1 TO INTOTAL 250 GAMINTS(J2) = INT(RND * 3) + 1 260 EXCEED = EXCEED + GAMINTS(J2) 270 IF EXCEED > 11 THEN 220 '<< within octave? 280 NEXT J2 290 FOR J = 1 TO INTOTAL 300 PRINT GAMINTS(J); 310 NEXT J 320 PRINT 330 GOSUB 1000 '<< call scale generator 340 NEXT J1 350 END 1000 REM ======================================================== 1010 REM *******************>> OCTSCALE <<*********************** 1020 REM ======================================================== 1030 REM This subroutine generates octave-repeating 1040 REM scales from a set of intervals. 1050 REM ======================================================== 1060 REM Variable Descriptions 1070 REM Entering - 1080 REM P$(): pitch name table 1090 REM GAMINTS(): array of interval sizes 1100 REM TONIC: lowest scale/gamut member 1110 REM HIGHOCTAVE: upper register octave limit 1120 REM INTOTAL: number of intervals in GAMINTS() 1130 REM SEGTOTAL: numeric length of scale segment 1140 REM Exiting - 1150 REM none (subroutine is procedural) 1160 REM Local - 1170 REM COUNT: tabulates chordtone generation 1180 REM SCALETONE: next chord/gamut member 1190 REM STARTOCTAVE: scale segment beginning register 1200 REM SCALEMEMS: number of tones in scale segment 1210 REM K9: loop index 1220 REM L9: loop index, pointer to array GAMINTS() 1230 REM M9: loop index, pointer to array P$() 1240 REM ======================================================== 1250 FOR K9 = 1 TO SEGTOTAL 1260 TONIC= INT(RND * 12)+1 1270 STARTOCTAVE = INT(RND * 3)+1 1280 SCALEMEMS = INT(RND * 17)+4 1290 PRINT "scale segment";K9;"=";SCALEMEMS;"notes" 1300 COUNT = 0 1310 FOR L9 = STARTOCTAVE TO HIGHOCTAVE 1320 SCALETONE = TONIC 1330 FOR M9 = 1 TO INTOTAL+1 1340 PRINT P$(SCALETONE + ((L9-1) * 12));" "; 1350 COUNT = COUNT + 1 1360 IF COUNT = SCALEMEMS THEN 1410 1370 IF M9 > INTOTAL THEN 1400 1380 SCALETONE = SCALETONE + GAMINTS(M9) 1390 NEXT M9 1400 NEXT L9 1410 PRINT 1420 NEXT K9 1430 PRINT 1440 RETURN 2000 REM ======================================================== 2010 REM *******************>> PITCHTAB <<*********************** 2020 REM ======================================================== 2030 REM This subroutine initializes a pitch data table 2040 REM corresponding to integer values 1-n. 2050 REM ======================================================== 2060 NOTE$ = " CC# DD# E FF# GG# AA# B" 2070 OCTAVE$ = "1234567" 2080 FOR K9 = 1 TO 7 2090 FOR L9 = 1 TO 12 2100 P$(L9+(K9-1)*12) = MID$(NOTE$,(L9*2-1),2)+MID$(OCTAVE$,K9,1) 2110 NEXT L9 2120 NEXT K9 2130 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Ornament) 130 REM ========================================================= 140 DIM P$(84),TEMP(200),NOTE$(500) 150 DIM DEC(6),ORN(4),EMBTABLE(4) 160 ORN(1) = 1002 : ORN(2) = 2003 170 ORN(3) = 2004 : ORN(4) = 4006 180 DEC(1) = -1 : DEC(2) = 0 : DEC(3) = -1 190 DEC(4) = 0 : DEC(5) = 1 : DEC(6) = 0 200 DECO = 100 '<< % of sequence notes to decorate 210 RANDOMIZE(-11001) 220 GOSUB 3000 '<< call pitch table 230 MELENGTH = 20 240 PRINT "UNEMBELLISHED PITCH SEQUENCE =";MELENGTH;"NOTES --" 250 FOR J = 1 TO MELENGTH 260 TEMP(J) = INT(RND * 81) + 2 270 PRINT P$(TEMP(J));" "; '<< random sequence to screen 280 NEXT J 290 PRINT : PRINT 300 GOSUB 1000 '<< call ornament selection 310 PRINT "EMBELLISHED PITCH SEQUENCE =";T3;"NOTES ---" 320 FOR J = 0 TO T3 330 PRINT NOTE$(J);" "; '<< embellished seq. to screen 340 NEXT J 350 END 1000 REM ======================================================== 1010 REM *******************>> ORNSELEC <<*********************** 1020 REM ********* (variation of PROBTABL subroutine) ********** 1030 REM ======================================================== 1040 REM This subroutine loads a probability table 1050 REM with weights for each of 4 ornament patterns, 1060 REM then calls ADDORN subroutine to interpolate 1070 REM the selected embellishments. 1080 REM ======================================================== 1090 REM Variable Descriptions 1100 REM Entering - 1110 REM P$(): pitch table array 1120 REM TEMP(): stores sequence prior to decoration 1130 REM MELENGTH: number of notes in original sequence 1140 REM DECO: percentage of sequence notes to decorate 1150 REM Exiting - 1160 REM NOTE$(): stores final, embellished sequence 1170 REM T3: final number of notes in sequence 1180 REM Local - 1190 REM EMBTABLE(): stores ornament pattern probabilities 1200 REM WSUM: sum of ornament probability weights 1210 REM K9: loop index, pointer to array TEMP() 1220 REM ======================================================== 1230 T3 = 0 1240 IF DECO = 0 THEN 1360 1250 PRINT "ORNAMENTS BEING ADDED (PROB. WEIGHTS 4,3,2,1) ---" 1260 PRINT "1) _ - 2) - _ 3) - _ - 4) _ - _" 1270 WSUM = 0 1280 FOR K9 = 1 TO 4 1290 READ EMBTABLE(K9) 1300 EMBTABLE(K9) = EMBTABLE(K9) + WSUM 1310 WSUM = EMBTABLE(K9) 1320 NEXT K9 1330 REM +++++++++++++++++++ 1340 DATA 4,3,2,1 1350 REM +++++++++++++++++++ 1360 FOR K9 = 1 TO MELENGTH 1370 IF RND * 100 > DECO THEN NOTE$(T3) = P$(TEMP(K9)) ELSE GOSUB 2000 1380 T3 = T3 + 1 1390 NEXT K9 1400 PRINT 1410 RETURN 2000 REM ======================================================== 2010 REM *********************>> ADDORN <<*********************** 2020 REM ======================================================== 2030 REM This subroutine adds selected embellishment 2040 REM patterns to a pre-existant melodic sequence. 2050 REM In the process, the sequence is transferred 2060 REM to a pitch character string array. 2070 REM ======================================================== 2080 REM Variable Descriptions 2090 REM Entering - 2100 REM P$(): pitch table array 2110 REM TEMP(): stores sequence prior to decoration 2120 REM EMBTABLE(): 2130 REM ORN(): array of ornament patterns 2140 REM DEC(): array of values for pattern reference 2150 REM NOTE$(): stores final, embellished sequence 2160 REM WSUM: sum of ornament probability weights 2170 REM K9: pointer to array TEMP() 2180 REM Exiting - 2190 REM NOTE$(): (above) 2200 REM T3: pointer to array NOTE$() 2210 REM Local - 2220 REM I8: loop index, pointer to array DEC() 2230 REM I9: loop index, pointer to array DEC() 2240 REM M9: loop index, pointer to array ORN() 2250 REM N9: loop index, pointer to array DEC() 2260 REM ======================================================== 2270 FOR M9 = 1 TO 4 2280 IF RND * WSUM > EMBTABLE(M9) THEN 2350 2290 I8 = INT(ORN(M9) / 1000) : I9 = CINT((ORN(M9) / 1000 - INT(ORN(M9) / 1000)) * 1000) 2300 FOR N9 = I8 TO I9 2310 NOTE$(T3) = P$(TEMP(K9) + DEC(N9)) 2320 T3 = T3 + 1 2330 NEXT N9 2340 RETURN 1390 2350 NEXT M9 2360 RETURN 1390 3000 REM ========================================================= 3010 REM ********************>> PITCHTAB <<*********************** 3020 REM ========================================================= 3030 REM This subroutine initializes a pitch data table 3040 REM corresponding to integer values 1-n. 3050 REM ========================================================= 3060 NOTE$ = " CC# DD# E FF# GG# AA# B" 3070 OCTAVE$ = "1234567" 3080 FOR K9 = 1 TO 7 3090 FOR L9 = 1 TO 12 3100 P$(L9+(K9-1)*12) = MID$(NOTE$,(L9*2-1),2)+MID$(OCTAVE$,K9,1) 3110 NEXT L9 3120 NEXT K9 3130 RETURN
100 REM ======================================================== 110 REM DRIVER PROGRAM 120 REM (Partspan) 130 REM ======================================================== 140 DIM P$(84),NOTE(48),PART(4),ADJUST(4) 150 CHORDLENGTH = 48 '<< pitchbank 160 VOICES = 4 '<< nmbr of parts 170 MELENGTH = 30 '<< notes in each derived part 180 RANDOMIZE 190 FOR J = 1 TO CHORDLENGTH 200 NOTE(J) = J '<< load pitchbank pointers 210 NEXT J 220 GOSUB 2000 '<< call pitch table 230 PRINT "PITCHBANK UPON WHICH MELODIES WILL BE BASED --" 240 FOR J = 1 TO CHORDLENGTH 250 PRINT P$(J);" "; '<< send pitchbank to screen 260 NEXT J 270 PRINT : PRINT 280 GOSUB 1000 '<< call part range computation 290 FOR J1 = 1 TO 2 300 IF J1 = 2 THEN PRINT "PASS 2, INTERLOCKING -" : D$ = "I" ELSE PRINT "PASS 1, STRATIFIED -" : D$ = "S" 310 FOR J2 = 1 TO VOICES 320 PRINT "VOICE";J2;"MELODY" 330 PRINT "RANGE =";P$(ADJUST(J2));" TO "; 340 PRINT P$(ADJUST(J2) + PART(J2) - 1) 350 FOR J3 = 1 TO MELENGTH 360 R = INT(RND * PART(J2)) + ADJUST(J2) 370 PRINT P$(NOTE(R));" "; 380 NEXT J3 390 PRINT 400 NEXT J2 410 PRINT 420 NEXT J1 430 END 1000 REM ======================================================= 1010 REM ********************>> PARTSPAN <<********************* 1020 REM ======================================================= 1030 REM This subroutine computes stratified or interlocking 1040 REM instrumental part ranges in reference to a pitch 1050 REM bank which will be used to generate melodic lines. 1060 REM ======================================================= 1070 REM Variable Descriptions 1080 REM Entering - 1090 REM VOICES: number of part ranges 1100 REM CHORDLENGTH: number of notes in source pitch bank 1110 REM D$: flag to indicate stratified or interlocking 1120 REM Exiting - 1130 REM ADJUST(): array of part low pitches 1140 REM PART(): array of part ranges 1150 REM Local - 1160 REM SPAN: subdivision of total pitch bank range 1170 REM EXTRA: any remainder from subdivision 1180 REM COMP: compensatory value added to part(s) 1190 REM K9: loop index, pointer to arrays PART(),ADJUST() 1200 REM ======================================================= 1210 SPAN = INT(CHORDLENGTH / VOICES) 1220 EXTRA = CHORDLENGTH-(VOICES*SPAN) 1230 FOR K9 = 1 TO VOICES 1240 IF EXTRA <= 0 THEN COMP = 0 ELSE COMP = 1 1250 PART(K9) = SPAN + COMP 1260 EXTRA = EXTRA - 1 1270 ADJUST(1) = 1 1280 IF K9 < VOICES THEN ADJUST(K9+1) = ADJUST(K9) + PART(K9) 1290 NEXT K9 1300 IF D$ = "S" THEN 1350 1310 REM >>> interlock part pitch ranges 1320 FOR K9 = 1 TO VOICES-1 1330 PART(K9) = PART(K9) + INT(PART(K9) * .5) 1340 NEXT K9 1350 RETURN 2000 REM ======================================================== 2010 REM ********************>> PITCHTAB <<********************** 2020 REM ======================================================== 2030 REM This subroutine initializes a pitch data table 2040 REM corresponding to integer values 1-n. 2050 REM ======================================================== 2060 NOTE$ = " CC# DD# E FF# GG# AA# B" 2070 OCTAVE$ = "1234567" 2080 FOR K9 = 1 TO 7 2090 FOR L9 = 1 TO 12 2100 P$(L9+(K9-1)*12) = MID$(NOTE$,(L9*2-1),2)+MID$(OCTAVE$,K9,1) 2110 NEXT L9 2120 NEXT K9 2130 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Permutot) 130 REM ========================================================= 140 ELEMENTS = 1 150 MANY = 1 160 FOR J = 1 TO 10 170 GOSUB 1000 '<< call combinations 180 PRINT "PERMUTATIONS OF";ELEMENTS;"THINGS TAKEN";MANY;"AT A TIME IS";PERMUTS 190 ELEMENTS= ELEMENTS+ 3 200 MANY = MANY + 2 210 NEXT J 220 END 1000 REM SS2ST6 ================================================= 1010 REM ********************>> PERMUTS <<*********************** 1020 REM ======================================================== 1030 REM This subroutine computes the number of possible 1040 REM permutations of n elements taken n at a time. 1050 REM It relies on Stirling's approximation to calculate 1060 REM the requisite factorials. 1070 REM ======================================================== 1080 REM Variable Descriptions 1090 REM Entering - 1100 REM ELEMENTS: nunber of items 1110 REM MANY: taken at a time 1120 REM Exiting - 1130 REM PERMUTS : permutation of ELEMENTS, taken MANY at 1140 REM a time 1150 REM Local - 1160 REM NUM: 1170 REM ELEMFACT: log of ELEMENTS factorial 1180 REM MANYFACT: log of MANY factorial 1190 REM ======================================================== 1200 NUM = ELEMENTS 1210 GOSUB 2000 '<< call Stirling's approximation 1220 ELEMFACT = APPR 1230 NUM = ELEMENTS - MANY 1240 GOSUB 2000 '<< call Stirling's approximation 1250 MANYFACT = APPR 1260 PERMUTS = INT(EXP(ELEMFACT-MANYFACT)+.5) 1270 RETURN 2000 REM ======================================================== 2010 REM ********************>> STIRLING <<********************** 2020 REM ======================================================== 2030 APPR = 1 2040 IF NUM <= 0 THEN APPR = 0 : RETURN 2050 FOR K9 = 1 TO 10 2060 APPR = APPR * K9 2070 IF NUM = K9 THEN APPR = LOG(APPR) : RETURN 2080 NEXT K9 2090 APPR = LOG(6.283186)/2+LOG(NUM)*(NUM+.5)-NUM+1/(12*NUM) 2100 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM ========================================================= 130 DIM P$(84) '<< prepare array to hold 7 octaves 140 GOSUB 1000 '<< initialize pitch table 150 FOR J = 1 TO 84 160 PRINT "NUM";J;"="; '<< send a number to screen 170 PRINT P$(J), '<< send corresponding pitch to screen 180 NEXT J 190 END 1000 REM ========================================================= 1010 REM ********************>> PITCHTAB <<*********************** 1020 REM ========================================================= 1030 REM This subroutine initializes a pitch data table 1040 REM corresponding to integer values 1-n. 1050 REM ========================================================= 1060 REM Variable Descriptions 1070 REM 1080 REM Entering - 1090 REM none 1100 REM 1110 REM Exiting - 1120 REM P$(): hold pitch element table 1130 REM 1140 REM Local - 1150 REM NOTE$: char string holding pitch class names 1160 REM OCTAVE$: char string holding octave registers 1170 REM K9: loop index, pointer to NOTE$ substring 1180 REM L9: loop index, pointer to OCTAVE$ substring 1190 REM 1200 REM ========================================================= 1210 NOTE$ = " CC# DD# E FF# GG# AA# B" 1220 OCTAVE$ = "1234567" 1230 FOR K9 = 1 TO 7 1240 FOR L9 = 1 TO 12 1250 P$(L9+(K9-1)*12) = MID$(NOTE$,(L9*2-1),2)+MID$(OCTAVE$,K9,1) 1260 NEXT L9 1270 NEXT K9 1280 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Poisson) 130 REM ========================================================= 140 DIM X(100) 150 RANDOMIZE 160 TOTAL = 100 165 SPREAD = 5 170 GOSUB 1000 '<< call Poisson distribution function 180 FOR J = 1 TO TOTAL 190 PRINT X(J); '<< sequence to screen 200 NEXT J 210 END 1000 REM ======================================================== 1010 REM ********************>> POISSON <<*********************** 1020 REM ======================================================== 1030 REM The Poisson Probability Distribution returns 1040 REM non-negatve, random-order, integers. The control 1050 REM variable, SPREAD, determines the distribution 1060 REM of values. 1070 REM ======================================================== 1080 REM Variable Descriptions 1090 REM Entering - 1100 REM TOTAL: length of sequence 1110 REM SPREAD: scaling parameter 1120 REM Exiting - 1130 REM X(): array holding poisson distribution 1140 REM Local - 1150 REM NUM: 1160 REM R9: uniform random number 1170 REM T9: while loop limit 1180 REM K9: loop index, pointer to array X() 1190 REM ======================================================== 1200 FOR K9 = 1 TO TOTAL 1210 NUM = 0 1220 R9 = RND 1230 T9 = EXP(-SPREAD) 1240 WHILE R9 > T9 1250 NUM = NUM + 1 1260 R9 = R9 * RND 1270 WEND 1280 X(K9) = NUM 1290 NEXT K9 1300 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Polyrhy) 130 REM ========================================================= 140 DIM DUR(100), FRACTION$(100) 150 RANDOMIZE 160 TOTAL = 10 170 M1= 3 180 LEVEL = 1 190 TIMESCALE = 10 200 FOR J = 1 TO 4 210 PRINT "PASS ";J 220 PRINT "LENGTH OF RHYTHM SEQUENCE = ";TOTAL 230 PRINT "MEDIAN =";M1 240 PRINT "TIMESCALE = ";TIMESCALE;"(scale = 1-10)" 250 PRINT "LEVEL = ";LEVEL; 260 PRINT "(from a choice of 1-2-4-8)" 270 GOSUB 1000 280 FOR J1 = 1 TO TOTAL 290 PRINT FRACTION$(J1); 300 NEXT J1 310 PRINT:PRINT 320 LEVEL = LEVEL + LEVEL 330 TOTAL = TOTAL + 10 340 M1 = M1 + 1 350 NEXT J 360 END 1000 REM ======================================================== 1010 REM ********************>> POLYRHY <<*********************** 1020 REM ======================================================== 1030 REM This subroutine computes random-order rhythm 1040 REM duration sequences on 4 selectable levels of 1050 REM complexity. It produces polyrhythmic/metric 1060 REM output layers which occupy identical time frames; 1070 REM That is, as long as the timescale remains 1080 REM constant, all independent output layers will 1090 REM end synchronously, regardless of metrical 1100 REM orientation (3/4,4/4,5/4,7/4,9/4,etc.). 1110 REM ======================================================= 1120 REM Variable Descriptions 1130 REM Entering - 1140 REM TOTAL: length of rhythm sequence 1150 REM TIMESCALE: arbitrary time reference 1160 REM M1: basic metrical unit 1170 REM LEVEL: degree of complexity (1-2-4-8) 1180 REM Exiting - (to DRIVER) 1190 REM FRACTION$(): array storing duration fractions 1200 REM Exiting - (to DURRED subroutine) 1210 REM DUR(): array storing fraction numerators 1220 REM NEWMED: reduced fraction denominator 1230 REM K9:loop index, pointer to DUR() 1240 REM Local - 1250 REM ODD: holds flag for odd number of values 1260 REM SUM: total of micropulses in raw sequence 1270 REM BASE: number of micropulses to distribute 1280 REM MEDIAN: metrical base value (3,4,5,7,9,etc) 1290 REM FACTOR: determinant of rnd generator range 1300 REM RANGE: span of rnd generator 1310 REM WEDGE: low bias of rnd generator 1320 REM RCOMP: rnd generator overrun or underrun 1330 REM U,R0,F0: random values for duration numerators 1340 REM K9: loop index, pointer to DUR(), FRACTION$() 1350 REM L9: loop index, pointer to DUR() 1360 REM ======================================================== 1370 ODD = 0 1380 SUM = 0 1390 MEDIAN = M1 1400 REM ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1410 REM Lines 1440-1530 reconcile sequence length with 1420 REM metrical base value and timescale. 1430 REM ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1440 BASE = MEDIAN * TIMESCALE 1450 IF TOTAL = 1 THEN DUR(1) = TIMESCALE : GOTO 1840 ELSE IF TIMESCALE - TOTAL > 0 THEN 1490 1460 FOR K9 = 1 TO 30 1470 IF TOTAL > BASE THEN MEDIAN = MEDIAN * 2 : BASE = BASE * 2 ELSE 1580 1480 NEXT K9 1490 IF BASE/2 <> INT(BASE/2)THEN BASE = BASE - 1 : ODD = M1 1500 FOR K9 = 1 TO 100 1510 IF BASE/2 <> INT(BASE/2)OR MEDIAN/2 <> INT(MEDIAN/2) THEN 1580 1520 IF TOTAL <= BASE / 2 THEN MEDIAN = MEDIAN / 2 : BASE = BASE / 2 ELSE 1580 1530 NEXT K9 1540 REM ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1550 REM Lines 1580-1790 compute micropulse (subdivision) 1560 REM level and generate random-order durations. 1570 REM ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1580 BASE = BASE * LEVEL 1590 MEDIAN = MEDIAN * LEVEL 1600 IF LEVEL = 4 THEN FACTOR = 3 ELSE IF LEVEL = 8 THEN FACTOR = 4 ELSE FACTOR = LEVEL 1610 WEDGE = FACTOR 1620 RANGE = (FACTOR + LEVEL) + INT(BASE/TOTAL) 1630 FOR K9 = 1 TO TOTAL 1640 U = INT(RND * RANGE) + WEDGE 1650 DUR(K9) = U 1660 SUM = SUM + U 1670 NEXT K9 1680 RCOMP = BASE - SUM 1690 FOR K9 = 1 TO 10000 1700 FOR L9 = 1 TO TOTAL 1710 IF RCOMP < 0 THEN 1730 1720 IF RCOMP = 0 THEN 1760 ELSE DUR(L9) = DUR(L9) + 1 : RCOMP = RCOMP - 1 : GOTO 1740 1730 IF DUR(L9) < 2 THEN 1740 ELSE DUR(L9) = DUR(L9) - 1 : RCOMP = RCOMP + 1 1740 NEXT L9 1750 NEXT K9 1760 IF ODD < 1 THEN 1840 1770 R0 = INT(RND * TOTAL) + 1 1780 F0 = INT(RND * TOTAL) + 1 1790 IF TOTAL > 1 AND F0 = R0 THEN 1780 ELSE DUR(R0) = DUR(R0) + DUR(F0) : DUR(F0) = -1 1800 REM ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1810 REM Lines 1140-1880 reduce duration fraction and 1820 REM load the sequence into a character string array 1830 REM ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1840 FOR K9 = 1 TO TOTAL 1850 NEWMED = MEDIAN 1860 IF DUR(K9)/2 = INT(DUR(K9)/2)AND NEWMED/2 = INT(NEWMED/2) THEN GOSUB 2000 '<< call fraction reduction 1870 IF DUR(K9) < 0 THEN FRACTION$(K9) = STR$(1)+"/"+MID$(STR$(ODD),2) ELSE FRACTION$(K9) = STR$(DUR(K9)) + "/" + MID$(STR$(NEWMED),2) 1880 NEXT K9 1890 RETURN 2000 REM ======================================================== 2010 REM *****************>> DURRED <<*************************** 2020 REM (modified form) 2030 REM ======================================================== 2040 DUR(K9) = DUR(K9)/2 2050 NEWMED = NEWMED/2 2060 IF DUR(K9)/2 = INT(DUR(K9)/2) AND NEWMED/2 = INT(NEWMED/2)THEN 2040 ELSE RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Primops) 130 REM ========================================================= 140 DIM X(100), Y(100) 150 LOW = 500 160 HIGH = 800 170 PRINT "PRIME NUMBERS WITHIN RANGE ";LOW;"TO";HIGH;" --" 180 GOSUB 1000 '<< call prime interval generator 190 FOR J = 1 TO PCNT 200 PRINT X(J); 210 NEXT J 220 PRINT 230 PRINT "NUMERIC INTERVALS BETWEEN PRIMES --" 240 FOR J = 1 TO PCNT-1 250 PRINT Y(J); 260 NEXT J 270 END 1000 REM ========================================================= 1010 REM ********************>> PRIMINTV <<*********************** 1020 REM ========================================================= 1030 REM This subroutine invokes the prime number indicator 1040 REM subroutine to locate primes, then creates two 1050 REM array sequences: 1) a list of the primes, and 1060 REM 2) a list of numeric intervals separating primes. 1070 REM The list can be mapped to various musical parameters, 1080 REM and can be modified in scale by addition or 1090 REM subtraction of a numerical constant. 1100 REM ========================================================= 1110 REM Variable Descriptions 1120 REM Entering - 1130 REM LOW: smallest integer within test range 1140 REM HIGH: largest integer within test range 1150 REM PRIM: (from SR 2000) prime flag 1160 REM Exiting - 1170 REM NUM: (to SR 2000) current integer to be tested 1180 REM X(): list of prime numbers 1190 REM Y(): list of numeric intervals between primes 1200 REM Local - 1210 REM PCNT: prime number counter, pointer to X(),Y() 1220 REM ========================================================= 1230 PCNT = 0 1240 FOR NUM = LOW TO HIGH 1250 GOSUB 2000 '<< call prime number indicator 1260 IF PRIM <> 1 THEN 1300 1270 PCNT = PCNT + 1 1280 X(PCNT) = NUM 1290 IF PCNT >= 2 THEN Y(PCNT-1) = X(PCNT)-X(PCNT-1) 1300 NEXT NUM 1310 RETURN 2000 REM ======================================================= 2010 REM *******************>> PRIMENUM <<********************** 2020 REM ======================================================= 2030 REM This subroutine locates and returns prime numbers 2040 REM from a stream of consecutive numbers within a 2050 REM specified range. (Prime numbers are integers 2060 REM which have only themselves or the number 1 2070 REM as a factor.) 2080 REM ======================================================= 2090 REM Variable Descriptions 2100 REM Entering - 2110 REM NUM: number to be tested for prime 2120 REM Exiting - 2130 REM PRIM: flag indicating a prime number 2140 REM Local - 2150 REM DIVISOR: loop index, divisor for prime test 2160 REM ======================================================= 2170 PRIM = 1 2180 IF NUM = 1 THEN PRIM = 0 : RETURN ELSE IF NUM = 2 OR NUM = 3 THEN RETURN 2190 IF NUM = INT(NUM/2) * 2 THEN PRIM = 0 : RETURN 2200 FOR DIVISOR = 3 TO INT(SQR(NUM)) STEP 2 2210 IF NUM = INT(NUM/DIVISOR) * DIVISOR THEN PRIM = 0 : RETURN 2220 NEXT DIVISOR 2230 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Pstnperm) 130 REM ========================================================= 140 DIM SET(12),POSIT(12),CUM(12) 150 RANDOMIZE 160 TOTAL = 12 170 LOW = 1 180 HIGH = 12 190 RANGE = HIGH-LOW+1 200 GOSUB 1000 '<< call series generator 210 PRINT "PRIME ORDER SERIES --" 220 FOR J = 1 TO TOTAL 230 PRINT SET(J);" "; '<< send series to screen 240 NEXT J 250 GOSUB 2000 '<< call position permutator 260 PRINT 270 PRINT "SET PERMUTATION RESULTING FROM ";"SWAP OF PC NMBR AND POSITION 280 FOR J = 1 TO TOTAL 290 PRINT POSIT(J);" "; '<< send permutation to screen 300 NEXT J 310 END 1000 REM ======================================================= 1010 REM *********************>> SETFLAG <<********************* 1020 REM ======================================================= 1030 FOR K9 = 1 TO TOTAL 1040 R9 = INT(RND * RANGE) + LOW 1050 IF CUM(R9) = 1 THEN 1040 1060 CUM(R9) = 1 1070 SET(K9) = R9 1080 NEXT K9 1090 RETURN 2000 REM ======================================================== 2010 REM *********************>> PSTNPERM <<********************* 2020 REM ======================================================== 2030 REM This subroutine generates a permutation of a 2040 REM prime order series by swapping pitch class numbers 2050 REM with position-in-set numbers. (If the series is 2060 REM the chromatic scale, then, of course, no alteration 2070 REM of the set will take place - the retrograde will 2080 REM be returned.) 2090 REM ======================================================== 2100 REM Variable Descriptions 2110 REM Entering - 2120 REM SET(): array containing series, pointer to POSIT() 2130 REM TOTAL: length of series 2140 REM Exiting - 2150 REM POSIT(): array containing set permutation 2160 REM Local - 2170 REM K9: loop index, pointer to SET() 2180 REM ======================================================== 2190 FOR K9 = 1 TO TOTAL 2200 POSIT(SET(K9)) = K9 2210 NEXT K9 2220 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Quicksrt) 130 REM ========================================================= 140 DIM X(60),STACK(40) 150 TOTAL = 60 160 RANDOMIZE 170 PRINT "ARRAY OF RANDOM-ORDER INTEGERS --" 180 FOR J= 1 TO TOTAL 190 X(J) = INT(RND*60)+1 200 PRINT X(J); 210 NEXT J 220 PRINT 230 PRINT "ARRAY SORTED IN ASCENDING ORDER --" 240 GOSUB 1000 '<< call Quicksort algorithm 250 FOR J = 1 TO TOTAL 260 PRINT X(J); 270 NEXT J 280 END 1000 REM SS2TM3 ================================================= 1010 REM *********************>> QUICKSRT <<********************* 1020 REM ======================================================== 1030 REM This subroutine is one of the fastest sorting 1040 REM algorithms; however, its drawbacks are that it 1050 REM is lengthy, complex, and difficult to decipher. 1060 REM BASIC language does not offer a stack, and this 1070 REM algorithm requires one. Therefore, a stack 1080 REM has been coded within the subroutine. In 1090 REM languages such as C or Pascal the stack code can 1100 REM be eliminated. 1110 REM ======================================================== 1120 REM Variable Descriptions 1130 REM Entering - 1140 REM X(): array of values to be sorted 1150 REM STACK(): stack to hold array X() pointers 1160 REM TOTAL: length of array X() 1170 REM Exiting - 1180 REM X(): array sorted in ascending order 1190 REM Local - 1200 REM FIN : indicator. When zero the sort is done 1210 REM PTR: stack pointer. PTR+1 points to the top of the segment, PTR+2 to bottom of segment 1220 REM TOPVAL: value at top of segment 1230 REM BOTTOMVAL: value at bottom of segment 1240 REM SEGTOP: pointer to top of segment 1250 REM SEGBOTTOM: pointer to bottom of segment 1260 REM COMPVAL: value being compared against current X() 1270 REM ======================================================== 1280 FIN = 1 1290 PTR = 0 1300 STACK(PTR+1)=1 1310 STACK(PTR+2)=TOTAL 1320 WHILE FIN <> 0 1330 FIN=FIN-1 1340 PTR=FIN+FIN 1350 TOPVAL=STACK(PTR+1) 1360 BOTTOMVAL=STACK(PTR+2) 1370 COMPVAL=X(TOPVAL) 1380 SEGTOP=TOPVAL 1390 SEGBOTTOM=BOTTOMVAL+1 1400 WHILE SEGBOTTOM-1 <> SEGTOP 1410 SEGBOTTOM=SEGBOTTOM-1 1420 IF COMPVAL <=X(SEGBOTTOM)THEN 1450 ELSE X(SEGTOP) = X(SEGBOTTOM) 1430 SEGTOP=SEGTOP+1 1440 IF SEGBOTTOM = SEGTOP
THEN 1460
ELSE IF COMPVAL >= X(SEGTOP)
THEN 1430
ELSE X(SEGBOTTOM) = X(SEGTOP) 1450 WEND 1460 X(SEGTOP)=COMPVAL 1470 IF BOTTOMVAL-SEGTOP < 2 THEN 1520 1480 PTR=FIN+FIN 1490 STACK(PTR+1)=SEGTOP+1 1500 STACK(PTR+2)=BOTTOMVAL 1510 FIN=FIN+1 1520 IF SEGBOTTOM - TOPVAL < 2 THEN 1570 1530 PTR=FIN+FIN 1540 STACK(PTR+1)=TOPVAL 1550 STACK(PTR+2)=SEGBOTTOM-1 1560 FIN=FIN+1 1570 WEND 1580 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM ========================================================= 130 RANDOMIZE 140 LASTLOC = 7 150 PRINT "START POSITION = ";LASTLOC 160 FOR J = 1 TO 40 170 GOSUB 1000 '<< call random walk 180 PRINT CURRLOC; 190 LASTLOC = CURRLOC 200 NEXT J 210 END 1000 REM ======================================================== 1010 REM ********************>> RANDWALK <<********************** 1020 REM ======================================================== 1030 REM This subroutine simulates a simple, bi-directional 1040 REM random walk which is restricted at both ends. 1050 REM ======================================================== 1060 REM Variable Descriptions 1070 REM 1080 REM Entering - 1090 REM LASTLOC: previous location of walker 1100 REM Exiting - 1110 REM CURRLOC: present location of walker 1120 REM Local - 1130 REM D: step direction storage 1140 REM U: random number determining step direction 1150 REM S: next step value after computation 1160 REM 1170 REM ======================================================== 1180 D=1 1190 U=RND 1200 IF U < .5 THEN D = -1 1210 S = LASTLOC + D 1220 IF S > 15 THEN S = 14 '<< upper boundary test & reset 1230 IF S < 1 THEN S = 2 '<< lower boundary test & reset 1240 CURRLOC = S 1250 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM ========================================================= 130 DIM P$(96) 140 RANDOMIZE 150 TOTAL = 5 '<< number of discrete chords 160 GOSUB 2000 '<< call pitch table 170 FOR J = 1 TO TOTAL 180 PRINT "CHORD";J 190 ROOT = INT(RND * 12)+1 '<< chord start pitch (C-B) 200 OCTAVE = INT(RND * 3)+1 '<< chord start octave (1-3) 210 CHORDMEMS = INT(RND * 7)+3 '<< number of chordtones 220 SMALL = INT(RND * 5)+1 '<< smallest rnd interval 230 LARGE = INT(RND * 8)+5 '<< largest rnd interval 240 INTVALRANGE = LARGE - SMALL + 1 250 GOSUB 1000 '<< call random-interval chord generator 260 PRINT 270 NEXT J 280 END 1000 REM ======================================================== 1010 REM *********************>> RDINTCHD <<********************* 1020 REM ======================================================== 1030 REM This subroutine generates constrained 1040 REM random-interval chords. 1050 REM ======================================================== 1060 REM Variable Descriptions 1070 REM Entering - 1080 REM ROOT: lowest chordmember 1090 REM OCTAVE: octave register for chord initiation 1100 REM CHORDMEMS: number of tones contained in chord 1110 REM SMALL: smallest interval size selected 1120 REM INTVALRANGE: overall range for interval choice 1130 REM Exiting - 1140 REM none (subroutine is procedural) 1150 REM Local - 1160 REM INTVAL: selected interval size for next chordmem 1170 REM CHORDTONE: next chordmember 1180 REM K9: loop index 1190 REM ======================================================== 1200 CHORDTONE = ROOT 1210 FOR K9 = 1 TO CHORDMEMS 1220 PRINT P$(CHORDTONE + ((OCTAVE-1) * 12));" "; 1230 INTVAL = INT(RND * (INTVALRANGE))+SMALL 1240 CHORDTONE = CHORDTONE + INTVAL 1250 NEXT K9 1260 PRINT 1270 RETURN 2000 REM ========================================================= 2010 REM ********************>> PITCHTAB <<*********************** 2020 REM ========================================================= 2030 REM This subroutine initializes a pitch data table 2040 REM corresponding to integer values 1-n. 2050 REM ========================================================= 2060 NOTE$ = " CC# DD# E FF# GG# AA# B" 2070 OCTAVE$ = "1234567" 2080 FOR K9 = 1 TO 7 2090 FOR L9 = 1 TO 12 2100 P$(L9+(K9-1)*12) = MID$(NOTE$,(L9*2-1),2)+MID$(OCTAVE$,K9,1) 2110 NEXT L9 2120 NEXT K9 2130 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Rhyprops) 130 REM ========================================================= 140 CLS 150 PRINT "THIS PROGRAM CONVERTS RHYTHMIC INFORMATION" 160 PRINT " - EXPRESSED AS NUMERIC PROPORTIONS - " 170 PRINT "INTO TIME DURATIONS." 180 PRINT 190 PRINT "THE PROPORTION(S) WILL BE REALIZED ";"AS A FRACTION" 200 PRINT "OR SEQUENCE OF FRACTIONS OF A WHOLE NOTE." 210 PRINT "FOR EXAMPLE, 4/1 MEANS A DURATION EQUAL ";"TO 4 WHOLE NOTES;" 220 PRINT "1/4 MEANS A DURATION EQUAL TO ONE QUARTER NOTE." 230 PRINT 240 PRINT "- PRESS ANY KEY TO CONTINUE -" 250 A$=INKEY$ 260 IF A$ = "" THEN 250 270 PRINT 280 PRINT "----------- A NOTE ABOUT PROPORTIONS -----------" 290 PRINT 300 PRINT "WHEN VALUE 1 > VALUE 2 (E.G., 9:8)," 310 PRINT "VALUE 2 SHOULD CONFORM TO ONE OF THE FOLLOWING" 320 PRINT "NUMBERS - 1,2,4,8,16 ." 330 PRINT 340 PRINT 350 PRINT "WHEN VALUE 2 > VALUE 1 (E.G.,4:9), VALUE 1" 360 PRINT "SHOULD CONFORM TO ONE OF THE ABOVE NUMBERS." 370 PRINT 380 PRINT 390 PRINT "ON THE OTHER HAND, ANY PROPORTION CAN BE INPUT." 400 PRINT "THE COMPUTATION WILL BE MADE," 410 PRINT "BUT THE RESULT MAY BE TOO COMPLEX TO USE." 420 PRINT 430 PRINT "FOR EXAMPLE, IF THE PROPORTION 10,9,4 ";"(MEANING 10 NOTES" 440 PRINT "IN THE TIME OCCUPIED BY NINE ";"QUARTER NOTES) IS INPUT," 450 PRINT "ORIGINAL FORM OUTPUT WILL BE ";"TEN IDENTICAL FRACTIONS -" 460 PRINT " 524288/2330169 470 PRINT 480 PRINT " - PRESS ANY KEY TO CONTINUE - " 490 A$ = INKEY$ 500 IF A$ = "" THEN 490 510 CLS 520 TOTAL = 3 530 GOSUB 1010 '<< call multiple value storage 540 E = 0: I = 1: F = TOTAL: G = 1 550 PRINT "ORIGINAL FORM --" 560 GOSUB 2000 '<< call value extraction 570 PRINT 580 PRINT"RETROGRADE FORM -- " 590 E = 0: I = TOTAL: F = 1: G = -1 600 GOSUB 2000 '<< call value extraction 610 PRINT 620 PRINT "INVERTED FORM -- " 630 E = 1: I = 1: F = TOTAL: G = 1 640 GOSUB 2000 '<< call value extraction 650 PRINT 660 PRINT "RETROGRADE INVERSION FORM -- " 670 E= 1: I = TOTAL: F = 1: G = -1 680 GOSUB 2000 '<< call value extraction 690 PRINT 700 END 1000 REM ======================================================== 1010 REM **********************>> SEQSTORE <<******************** 1020 REM (adapted to program specs) 1030 REM ======================================================== 1040 PRINT "+++++++ VALUE 1, VALUE 2, METRICAL BASE ++++++ " 1050 FOR K9 = 1 TO TOTAL 1060 R1# = K9 * K9 1070 R2# = K9 + 3 1080 B# = 8 1090 PRINT "SELECTED PROPORTION";K9;"-->";R1#;":";R2#;", ";"BASE";B# 1100 R1#= R1# * 1000000! 1110 R2#=R2# * 1000 1120 C#(K9) = R1#+ R2#+ B# 1130 NEXT K9 1140 RETURN 2000 REM ======================================================= 2010 REM *******************>> SEQXTRCT <<********************** 2020 REM (adapted to program specs) 2030 REM ======================================================= 2040 FOR K9 = I TO F STEP G 2050 D# = C#(K9) 2060 D# = D#/1000000! 2070 R1 = INT(D#) 2080 R2 = INT((D# - INT(D#)) * 1000) 2090 D# = D# * 1000 2100 B = INT((D# - INT(D#)) * 1000+.5) 2110 GOSUB 3000 '<< call proportion/rhythm conversion 2120 NEXT K9 2130 RETURN 3000 REM ======================================================= 3010 REM ******************>> RHYPROPS <<*********************** 3020 REM ======================================================= 3030 REM This subroutine converts numeric proportions 3040 REM into rhythm duration values. 3050 REM ======================================================= 3060 REM Variable Descriptions 3070 REM Entering - 3080 REM R1: proportion value #1 3090 REM R2: proportion value #2 3100 REM B: rhythm median value 3110 REM E: flag to invert proportion 3120 REM Exiting - 3130 REM none (subroutine is procedural) 3140 REM Local - 3150 REM CUM: converted duration numerator 3160 REM DUR: converted duration denominator 3170 REM L9: loop index 3180 REM ======================================================= 3190 IF E = 1 THEN SWAP R1,R2 3200 IF R1 < R2 THEN 3280 3210 CUM = 1 3220 DUR = R1 * B / R2 3230 IF DUR <> INT(DUR)THEN CUM = CUM * 2 : DUR = DUR * 2 : GOTO 3230 3240 FOR L9 = 1 TO R1 3250 PRINT CUM;"/";DUR; 3260 NEXT L9 3270 RETURN 3280 DUR = R2/R1 3290 IF INT(DUR) <> DUR THEN DUR = DUR * 2 : B = B * 2 : GOTO 3290 3300 FOR L9 = 1 TO R1 3310 PRINT DUR;"/";B; 3320 NEXT L9 3330 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Rnd-Rnd) 130 REM ========================================================= 140 DIM X(50) 150 RANDOMIZE 160 TOTAL = 50 161 LOW = 1 162 HIGH = 12 163 RANGE = HIGH - LOW + 1 170 GOSUB 1000 '<< call recursive random distribution 180 FOR J = 1 TO TOTAL 190 PRINT X(J); '<< sequence to screen 200 NEXT J 210 END 1000 REM ======================================================== 1010 REM *********************>> RND-RND <<********************** 1020 REM ======================================================== 1021 REM The RND-RND probability distribution generates 1022 REM a range of integers whose occurrence frequency 1023 REM falls off with magnitude. It's distribution 1024 REM curve is similar to the exponential curve. 1029 REM ======================================================== 1030 REM Variable Descriptions 1040 REM Entering - 1050 REM TOTAL: 1060 REM RANGE: 1070 REM LOW: 1080 REM Exiting - 1090 REM X(): 1100 REM Local - 1110 REM K9: loop index, pointer to array X() 1111 REM ======================================================== 1120 FOR K9 = 1 TO TOTAL 1130 X(K9) = INT(RND * RND * (RANGE)) + LOW 1140 NEXT K9 1150 RETURN
100 REM ======================================================== 110 REM DRIVER PROGRAM 120 REM (Rotation) 130 REM ======================================================== 140 REM This set of subroutines performs rotation and 150 REM transposition operations on a 12-element set 160 REM of values. This program deals with number sets 170 REM to point out applications to parameters other 180 REM than pitch; however, the values may be printed 190 REM as pitch classes simply by adding a pitch 200 REM conversion subroutine. 210 REM ======================================================== 220 DIM CUM(12),SET(12),MAT1(12,12),MAT2(12,12),MAT3(12,12) 230 RANDOMIZE 240 SET = 12 250 PRINT "A RANDOM-ORDER SET -->" 260 GOSUB 1000 '<< call set generator 270 FOR J = 0 TO SET-1 280 PRINT SET(J);" "; 290 NEXT J 300 PRINT 310 PRINT 320 ROTEGROUP = 4 330 PRINT "UNPARTITIONED ARRAY, ELEMENT/GROUP ROTATION -->" 340 PRINT "(";ROTEGROUP;"SET MEMBERS PER CYCLE ROTATED )" 350 GOSUB 5000 '<< call Euclid's Algorithm 360 PRINT "TOTAL NUMBER OF UNIQUE CYCLES =";CYCLES 370 GOSUB 2000 '<< call unpartitioned set group rotation 380 FOR J1 = 0 TO CYCLES-1 390 FOR J2 = 0 TO SET-1 400 PRINT MAT1(J1,J2); 410 NEXT J2 420 PRINT 430 PRINT 440 NEXT J1 450 PRINT "'0' START POINT TRANSPOSITION -->" 460 GOSUB 3000 '<< call set transposition 470 FOR J1 = 0 TO CYCLES-1 480 FOR J2 = 0 TO SET-1 490 PRINT MAT2(J1,J2); 500 NEXT J2 510 PRINT 520 PRINT 530 NEXT J1 540 NUMSEGS = 4 550 SEGMEMS = SET/NUMSEGS 560 PRINT "PARTITIONED ARRAY, ROTATION WITHIN SEGMENT -->" 570 PRINT "(DIVIDED INTO";NUMSEGS;"EQUAL SEGMENTS)" 580 GOSUB 4000 '<< call set segment member rotation 590 FOR J1 = 0 TO SEGMEMS - 1 600 PRINT "|"; 610 FOR J2 = 0 TO SET - 1 620 PRINT MAT3(J1,J2); 630 IF (J2+1) MOD SEGMEMS = 0 THEN PRINT "|"; 640 NEXT J2 650 PRINT 660 PRINT 670 NEXT J1 680 END 1000 REM ======================================================== 1010 REM **********************>> SETFLAG <<********************* 1020 REM ======================================================== 1030 FOR K9 = 0 TO SET - 1 1040 R9 = INT(RND * SET) 1050 IF CUM(R9) = 1 THEN 1040 1060 CUM(R9) = 1 1070 SET(K9) = R9 1080 NEXT K9 1090 RETURN 2000 REM ======================================================== 2010 REM *********************>> SETROTAT <<********************* 2020 REM ======================================================== 2030 REM This subroutine rotates set members by moving a 2040 REM specified group of notes from the beginning to the 2050 REM end of the series. 2060 REM ======================================================== 2070 REM Variable Descriptions 2080 REM Entering - 2090 REM SET: length of series 2100 REM ROTEGROUP: # of contiguous set members to rotate 2110 REM Exiting - 2120 REM MAT1: matrix of rotated sets 2130 REM Local - 2140 REM R9: rotation factor marker 2150 REM S9: counter, pointer to MAT1(n,n) 2160 REM T9: pointer to SET() 2170 REM K9: loop index 2180 REM L9: loop index, pointer to MAT(n,n) 2190 REM ======================================================== 2200 ROTEGROUP = ROTEGROUP - 1 2210 R9 = 0 2220 S9 = 0 2230 FOR K9 = ROTEGROUP TO SET-1 + ROTEGROUP 2240 FOR L9 = 1 TO SET 2250 T9 = (K9+L9+R9) MOD SET 2260 MAT1(S9,L9-1) = SET(T9) 2270 NEXT L9 2280 R9 = R9 + ROTEGROUP 2290 S9 = S9 + 1 2295 IF S9 = CYCLES THEN RETURN 2300 NEXT K9 2310 RETURN 3000 REM ======================================================== 3010 REM *******************>> ZEROTRNP <<*********************** 3020 REM ======================================================== 3030 REM This subroutine transposes a collection of sets 3040 REM sets to '0' start point. 3050 REM ======================================================== 3060 REM Variable Descriptions 3070 REM Entering - 3080 REM MAT1(n,n): matrix of rotated sets 3090 REM SET: length of series 3100 REM Exiting - 3110 REM MAT2(n,n): matrix of transposed sets 3120 REM Local - 3130 REM INTVAL: interval of transposition 3140 REM S9: set member after transposition 3150 REM K9: loop index, pointer to MAT1(n,n) & MAT2(n,n) 3160 REM L9: loop index, pointer to MAT1(n,n) & MAT2(n,n) 3170 REM ======================================================== 3180 FOR K9 = 0 TO CYCLES-1 3190 INTVAL = MAT1(K9,0) 3200 FOR L9 = 0 TO SET-1 3210 S9 = MAT1(K9,L9)-INTVAL 3220 IF S9 < 0 THEN S9 = S9 + 12 3230 MAT2(K9,L9) = S9 3240 NEXT L9 3250 NEXT K9 3260 RETURN 4000 REM ======================================================== 4010 REM **********************>> SEGROTAT <<******************** 4020 REM ======================================================== 4030 REM This subroutine rotates partitioned-set segment 4040 REM members. 4050 REM ======================================================== 4060 REM Variable Descriptions 4070 REM Entering - 4080 REM SET(): prime set 4090 REM SET: length of series 4100 REM NUMSEGS: symmetrical set partitioning 4110 REM Exiting - 4120 REM MAT3(n,n): matrix of sets after internal rotation 4130 REM Local - 4140 REM SEGMEMS: number of members in each segment 4150 REM S9: counter, pointer to MAT(n,n) 4160 REM T9: counter, pointer to MAT(n,n) 4170 REM K9: loop index 4180 REM L9: loop index, pointer to SET() 4190 REM M9: loop index, pointer to SET() 4200 REM ======================================================== 4210 S9 = 0 4220 SEGMEMS = SET/NUMSEGS 4230 FOR K9 = 1 TO SEGMEMS 4240 T9 = 0 4250 FOR L9 = 0 TO SET-1 STEP SEGMEMS 4260 FOR M9 = S9 + 1 TO SEGMEMS + S9 4270 MAT3(S9,T9) = SET(M9 MOD SEGMEMS + L9) 4280 T9 = T9 + 1 4290 NEXT M9 4300 NEXT L9 4310 S9 = S9 + 1 4320 NEXT K9 4330 RETURN 5000 REM ======================================================== 5010 REM ********************>> EUCREDUC <<********************** 5020 REM (modified to meet program specs) 5030 REM ======================================================== 5040 A9 = SET 5050 B9 = ROTEGROUP 5060 IF A9 > B9 THEN SWAP A9,B9 5070 WHILE A9 > 0 5080 C9 = INT(B9/A9) 5090 D9 = B9-A9*C9 5100 B9 = A9 5110 A9 = D9 5120 WEND 5130 CYCLES = SET/B9 5140 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Rowforms) 130 REM ========================================================= 140 REM This set of subroutines produces commonly found 150 REM 12-tone row forms - original, retrograde, inversion, 160 REM and transpositions. Because the processes are well 170 REM known and simple, variable descriptions have been 180 REM dispensed with. 190 REM ========================================================= 200 DIM P$(12) 210 DIM X(12),Y(12) 220 INTVAL = 4 230 RANDOMIZE 240 GOSUB 1000 '<< load element tables 250 GOSUB 2000 '<< call random shuffle 260 PRINT 270 PRINT "RANDOM-ORDER 12-TONE ROW --" 280 FOR J = 0 TO 11 290 PRINT P$(X(J));" "; '<< random 12-tone row to screen 300 NEXT J 310 PRINT : PRINT 320 FOR J = 1 TO 3 330 ON J GOSUB 3000,4000,5000 '<< call retro,invrt,trnpz 340 FOR J1 = 0 TO 11 350 PRINT P$(Y(J1));" "; '<< row forms to screen 360 NEXT J1 370 PRINT : PRINT 380 NEXT J 390 END 1000 REM ======================================================== 1010 REM *********************<< PITCHTAB <<********************* 1020 REM (modified to program specs) 1030 REM ======================================================== 1040 FOR J = 0 TO 11 1050 X(J) = J '<< load row elements 1060 READ P$(J) '<< load pitch class equivalents 1070 NEXT J 1080 REM+++++++++++++++++++++++++++++++++ 1090 DATA C,C#,D,D#,E,F,F#,G,G#,A,A#,B 1100 REM+++++++++++++++++++++++++++++++++ 1110 RETURN 2000 REM ======================================================== 2010 REM ********************>> CONSHUFL <<********************** 2020 REM ======================================================== 2030 FOR K9 = 0 TO 11 2040 R9 = INT(RND * 12) 2050 S9 = X(K9) 2060 X(K9) = X(R9) 2070 X(R9) = S9 2080 NEXT K9 2090 RETURN 3000 REM ======================================================== 3010 REM **********************>> ROWRETRO <<******************** 3020 REM ======================================================= 3030 REM This subroutine outputs retrograde form. 3040 REM ======================================================= 3050 PRINT "RETROGRADE ORDER --" 3060 FOR K9 = 0 TO 11 3070 L = (11 - K9) MOD 12 3080 Y(L) = X(K9) 3090 NEXT K9 3100 RETURN 4000 REM ======================================================== 4010 REM ********************>> ROWINVRT <<********************** 4020 REM ======================================================== 4030 REM This subroutine outputs inverted form. 4040 REM ======================================================== 4050 PRINT "INVERTED ORDER --" 4060 FOR K9 = 0 TO 11 4070 Y(K9) = (12 - X(K9)) MOD 12 4080 NEXT K9 4090 RETURN 5000 REM ======================================================= 5010 REM ********************>> ROWTRNPZ <<********************* 5020 REM ======================================================= 5030 REM This subroutine outputs row form transpositions. 5040 REM ======================================================= 5050 PRINT "TRANSPOSED (UP MAJOR 3RD) ORIGINAL FORM --" 5060 FOR K9 = 0 TO 11 5070 Y(K9) = (X(K9) + INTVAL) MOD 12 5080 NEXT K9 5090 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Rowsquar) 130 REM ========================================================= 140 DIM P$(12),CUM(12),X(12),Y(12) 150 RANDOMIZE 160 GOSUB 1000 '<< call pitch table 170 GOSUB 2000 '<< call set generator 180 GOSUB 3000 '<< call composite row form printout 190 END 1000 REM ======================================================== 1010 REM *********************>> PITCHTAB <<********************* 1020 REM (modified to load pitch classes only) 1030 REM ======================================================== 1040 FOR J = 0 TO 11 1050 READ P$(J) '<< load pitch table 1060 NEXT J 1070 REM++++++++++++++++++++++++++++++++++++++++ 1080 DATA "C ","C# ","D ","D# ","E ","F " 1090 DATA "F# ","G ","G# ","A ","A# ","B " 1100 REM++++++++++++++++++++++++++++++++++++++++ 1110 RETURN 2000 REM ======================================================== 2010 REM *********************>> SETFLAG <<********************** 2020 REM (modified to program specs) 2030 REM ======================================================== 2040 FOR K9 = 0 TO 11 2050 F = INT(RND*12) 2060 IF CUM(F) = 1 THEN 2050 2070 CUM(F) = 1 2080 IF K9 = 0 THEN TRANS = F 2090 IF F-TRANS < 0 THEN X(K9) = F-TRANS+ 12 ELSE X(K9) = F-TRANS 2100 Y(K9) = (12-X(K9)) MOD 12 2110 NEXT K9 2120 RETURN 3000 REM ======================================================== 3010 REM *********************>> ROWSQUAR <<********************* 3020 REM ======================================================== 3030 REM This subroutine prints a square matrix containing 3040 REM composite 12-tone row forms: Original (Prime), 3050 REM Retrograde, Inversion, and Retrograde-Inversion. 3060 REM ======================================================== 3070 REM Variable Descriptions 3080 REM Entering - 3090 REM X(): original order set array 3100 REM Y(): inverted order set array 3110 REM P$(): pitch table array 3120 REM Exiting - 3130 REM none (subroutine is procedural) 3140 REM Local - 3150 REM INTVAL: transposition interval 3160 REM K9: loop index, pointer to Y() 3170 REM L9: loop index, pointer to X() 3180 REM ======================================================= 3190 CLS 3200 PRINT " MATRIX OF TRANSPOSITIONS YIELDING O,RO,I,RI " 3210 PRINT "++++++++++++++++++++++++++++++++++++++++++++++++++" 3220 PRINT "+ ORIGINAL ----> +" 3230 PRINT "+ | INVERSION +" 3240 PRINT "+ V +" 3250 FOR K9= 0 TO 11 3260 PRINT "+";TAB(8); 3270 INTVAL = Y(K9) 3280 FOR L9= 0 TO 11 3290 PRINT P$((X(L9) + INTVAL) MOD 12); 3300 NEXT L9 3310 PRINT TAB(50);"+" 3320 NEXT K9 3330 PRINT "+ ^ +" 3340 PRINT "+ | RETROGRADE INVERSION +" 3350 PRINT "+ <--- RETROGRADE +" 3360 PRINT "++++++++++++++++++++++++++++++++++++++++++++++++++" 3370 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Samplset) 130 REM ========================================================= 140 DIM SET(100),A(100),B(100) 150 PERMUT = 5 160 TOTAL = 12 170 PRINT "A SEQUENTIAL SET -" 180 FOR J = 1 TO TOTAL 190 SET(J) = J : PRINT SET(J); 200 NEXT J 210 PRINT 220 FACTOR = 2 230 FOR CYCLE = 1 TO PERMUT 240 PRINT "PERMUTATION ";CYCLE 250 TARGET = 1 260 PRINT "SET START POSITION = ";TARGET;"; ""SET TARGET FACTOR= ";FACTOR 270 GOSUB 1000 '<< call sampling 280 FACTOR = FACTOR + 2 290 NEXT CYCLE 300 END 1000 REM ========================================================= 1010 REM *******************>> SAMPLSET <<************************ 1020 REM ========================================================= 1030 REM This subroutine produces numeric series permutations 1040 REM by cyclical set sampling at a selected interval. 1050 REM (start at set member n and remove every nth element, 1060 REM looping back through the series until reordered.) 1070 REM The algorithm is derived from the classic 'Josephus' 1080 REM Problem', which is expressed below in pseudo-code: 1090 REM 1100 REM Arrange a group of men in a circle; 1110 REM move around the circle; 1120 REM shoot and remove every nth man; 1130 REM repeat until none remains. 1140 REM 1150 REM ======================================================== 1160 REM Variable Descriptions 1170 REM Entering - 1180 REM SET(): initial value series 1190 REM TOTAL: series length 1200 REM TARGET: current set sample 1210 REM FACTOR: sampling interval 1220 REM Exiting - 1230 REM none: (subroutine is procedural) 1240 REM Local - 1250 REM SETL: current set length (shrinks every iteration) 1270 REM A(): bounce array 1 1280 REM B(): bounce array 2 1290 REM ACNT: pointer to A() 1300 REM BCNT: pointer to B() 1310 REM K9: loop index, pointer to A(),B() 1320 REM ======================================================== 1330 SETL = TOTAL 1340 FOR K9 = 1 TO SETL 1350 A(K9)=SET(K9) 1360 NEXT K9 1370 BCNT = 0 1380 FOR K9 = 1 TO SETL 1390 IF K9 = TARGET THEN PRINT A(K9); : TARGET = TARGET + FACTOR ELSE BCNT = BCNT + 1 : B(BCNT) = A(K9) 1400 NEXT K9 1410 IF BCNT < 1 THEN 1530 1420 TARGET = TARGET - SETL 1430 ACNT = 0 1440 IF TARGET MOD BCNT <> 0 THEN TARGET = TARGET MOD BCNT ELSE TARGET = BCNT 1450 FOR K9 = 1 TO BCNT 1460 IF K9 = TARGET THEN PRINT B(K9); : TARGET = TARGET + FACTOR ELSE ACNT = ACNT + 1 : A(ACNT) = B(K9) 1470 NEXT K9 1480 IF ACNT < 1 THEN 1530 1490 SETL = ACNT 1500 TARGET = TARGET - BCNT 1510 IF TARGET MOD SETL <> 0 THEN TARGET = TARGET MOD SETL ELSE TARGET = SETL 1520 GOTO 1370 1530 PRINT 1540 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Scorform) 130 REM ========================================================= 140 PRINT "FIFTY RANDOM VALUES FROM 1-50 ARE BEING PUT IN" 150 PRINT "PITCH, RHYTHM, ARTICULATION, AND VOLUME FILES" 160 PRINT "NAMED 'P1.DAT','R1.DAT','A1.DAT','V1.DAT' -----" 170 FOR J1 = 1 TO 4 180 IF J1 = 1
THEN OPEN "O",#1,"P1.DAT"
ELSE
IF J1 = 2
THEN OPEN "O",#2,"R1.DAT"
ELSE
IF J1 = 3
THEN OPEN "O",#3,"A1.DAT"
ELSE OPEN "O",#4,"V1.DAT" 190 FOR J2 = 1 TO 50 200 NUM = INT(RND * 50)+1 210 PRINT #J1,NUM; '<< put 50 values in each file 220 IF J2 MOD 15 = 0 THEN PRINT #J1, '<< 10 per line 230 NEXT J2 240 CLOSE #J1 250 NEXT J1 260 PRINT 270 PRINT "NOW THE 4 SEPARATE PARAMETER FILES ARE BEING" 280 PRINT "PLACED IN FINAL SCORE FILE NAMED 'SCORE.DAT' ---" 290 PRINT 300 GOSUB 1000 '<< call score formatting 310 END 1000 REM ======================================================== 1010 REM *******************>> SCORFORM <<*********************** 1020 REM ======================================================== 1030 REM Formatted-Score-Filing Subroutine 1040 REM ======================================================== 1050 X$ = "+" 1060 Z$ = "SCORE.DAT" 1070 OPEN "I",#1,"P1.DAT" 1080 OPEN "I",#2,"R1.DAT" 1090 OPEN "I",#3,"A1.DAT" 1100 OPEN "I",#4,"V1.DAT" 1110 OPEN "O",#5,Z$ 1120 PRINT #5,"NOTELIST:" 1130 WHILE NOT EOF(1) 1140 LINE INPUT #1,A$ 1150 PRINT #5,"P ";A$ 1160 LINE INPUT #2,B$ 1170 PRINT #5,"R ";B$ 1180 LINE INPUT #3,C$ 1190 PRINT #5,"A ";C$ 1200 LINE INPUT #4,D$ 1210 PRINT #5,"V ";D$ 1220 PRINT #5,"/*";STRING$(55,X$);"*/" 1230 WEND 1240 CLOSE #1,#2,#3,#4,#5 1250 PRINT "HERE IS FINAL SCORE --" 1260 OPEN "I",#5,Z$ 1270 WHILE NOT EOF(5) 1280 LINE INPUT #5,A$ 1290 PRINT A$ 1300 WEND 1310 CLOSE #5 1320 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Seqfile) 130 REM ========================================================= 140 DIM X(200) 150 SEQTOTAL = 5 160 OPEN "O",#1,"SEQ.DAT" '<< prepare file for writing 170 PRINT "FILE LOOKS LIKE THIS ---" 180 GOSUB 1000 '<< call sequence filing routine 190 CLOSE #1 200 OPEN "I",#1,"SEQ.DAT" '<< prepare file for reading 210 PRINT "EXTRACTED SEQUENCES LOOK LIKE THIS --" 220 GOSUB 2000 '<< call sequence extraction routine 230 CLOSE #1 240 END 1000 REM ======================================================== 1010 REM ********************>> SEQSTORE <<********************** 1020 REM ======================================================== 1030 REM Discrete Sequence Store and File Subroutine 1040 REM ======================================================== 1050 REM Variable Descriptions 1060 REM Entering - 1070 REM SEQTOTAL: number of sequences to store 1080 REM Exiting - 1090 REM X(): array containing sequence and keys 1100 REM Local - 1110 REM SEQLEN: random-length number sequence 1120 REM FILEVAL: integer for array storage & filing 1130 REM K9: loop index 1140 REM L9: loop index, pointer to array X() 1150 REM T8: counter, pointer to array X() 1160 REM ======================================================== 1170 FOR K9 = 1 TO SEQTOTAL 1180 SEQLEN = INT(RND * 20)+5 1190 FOR L9 = 1 TO SEQLEN 1200 FILEVAL = L9 * K9 1210 IF L9 = 1 THEN X(L9+T8) = FILEVAL * 1000 + SEQLEN ELSE X(L9+T8) = FILEVAL 1220 PRINT X(L9+T8);:PRINT #1,X(L9+T8); 1230 NEXT L9 1240 T8 = T8 + SEQLEN 1250 NEXT K9 1260 PRINT 1270 RETURN 2000 REM ======================================================== 2010 REM ********************>> SEQXTRCT <<********************** 2020 REM ======================================================== 2030 REM Discrete Sequence Retrieval Subroutine 2040 REM ======================================================== 2050 REM Variable Descriptions 2060 REM Entering - 2070 REM X(): array containing sequence & keys 2080 REM Exiting - 2090 REM none (subroutine is procedural) 2100 REM Local - 2110 REM S8: sequence counter 2120 REM K9: loop index, pointer to array X() 2130 REM ======================================================== 2140 S8 = 0 2150 FOR K9= 1 TO 10000 2160 IF EOF(1) THEN 2190 ELSE INPUT #1,X(K9) 2170 IF X(K9) < 1000 THEN PRINT X(K9); ELSE PRINT : S8 = S8 + 1 :PRINT "SEQUENCE";S8 : PRINT INT(X(K9)/1000); 2180 NEXT K9 2190 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM ========================================================= 130 DIM SET(12),CUM(12) 140 RANDOMIZE 150 TOTAL = 12 160 LOW = 1 170 HIGH = 12 180 RANGE = HIGH-LOW+1 190 GOSUB 1000 200 FOR J = 1 TO TOTAL 210 PRINT SET(J);" "; '<< send series to screen 220 NEXT J 230 END 1000 REM ======================================================= 1010 REM *********************>> SETFLAG <<********************* 1020 REM ======================================================= 1030 REM This subroutine generates random-order series by 1040 REM the array flag method. That is, when a random 1050 REM integer is generated, the subroutine checks the 1060 REM content of the CUM() address pointed to by the 1070 REM random number to determine whether a flag (1) 1080 REM is present. If the address is empty, it receives 1090 REM the flag, and the random number is placed in SET() 1100 REM as a series member. If the address has the flag, 1110 REM the number is discarded and another generated. 1120 REM ======================================================= 1130 REM Variable Descriptions 1140 REM Entering - 1150 REM TOTAL: length of set 1160 REM LOW: lowest value 1170 REM RANGE: set value range 1180 REM Exiting - 1190 REM SET(): final set of values 1200 REM Local - 1210 REM CUM(): array holding occurrence flags 1220 REM R9: random value to be tested for occurrence 1230 REM K9: loop index, pointer to array SET() 1240 REM ======================================================= 1250 FOR K9 = 1 TO TOTAL 1260 R9 = INT(RND * RANGE) + LOW 1270 IF CUM(R9) = 1 THEN 1260 1280 CUM(R9) = 1 1290 SET(K9) = R9 1300 NEXT K9 1310 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Shellsrt) 130 REM ========================================================= 140 DIM X(50) 150 TOTAL = 50 160 RANDOMIZE 170 PRINT "ARRAY OF RANDOM-ORDER REAL NUMBERS (RANGE 0-1) --" 180 FOR J = 1 TO TOTAL 190 X(J) = RND 200 PRINT X(J); 210 NEXT J 220 PRINT 230 PRINT "ARRAY SORTED IN ASCENDING ORDER --" 240 GOSUB 1000 '<< call Shell sort algorithm 250 FOR J = 1 TO TOTAL 260 PRINT X(J); '<< list to screen 270 NEXT J 280 END 1000 REM SS1TM2 ================================================= 1010 REM *********************>> SHELLSRT <<********************* 1020 REM ======================================================== 1030 REM This in-place binary sorting subroutine is fast, 1040 REM compact, and easy to understand. The algorithm 1050 REM works by successively splitting the list into 1060 REM smaller halves, rearranging contents along the way. 1070 REM ======================================================== 1080 REM Variable Descriptions 1090 REM Entering - 1100 REM X(): array of values to be sorted 1110 REM TOTAL: length of list 1120 REM Exiting - 1130 REM X(): array sorted in ascending order 1140 REM Local - 1150 REM SUBDIV: list subdivision size 1160 REM REMAINDER: original list size less SUBDIV 1170 REM FLAG: 0 or 1 condition indicates switch or no 1180 REM switch has occurred 1190 REM TEMP: temporary storage 1200 REM K9: loop index, first sublist pointer 1210 REM COMPTR: second sublist pointer for comparison 1220 REM and switch 1230 REM ======================================================== 1240 SUBDIV = TOTAL 1241 SUBDIV = INT(SUBDIV / 2) 1250 WHILE SUBDIV > 0 1270 REMAINDER = TOTAL - SUBDIV 1280 FLAG = 0 1290 FOR K9=1 TO REMAINDER 1300 COMPTR = K9+SUBDIV 1310 IF X(K9) <= X(COMPTR)THEN 1360 1320 TEMP = X(K9) 1330 X(K9) = X(COMPTR) 1340 X(COMPTR) = TEMP 1350 FLAG = 1 1360 NEXT K9 1370 IF FLAG > 0 THEN 1280 1371 SUBDIV = INT(SUBDIV / 2) 1372 WEND 1373 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (S-MSORT) 130 REM ========================================================= 140 DIM X(50) 150 TOTAL = 50 160 RANDOMIZE 170 PRINT "ARRAY OF RANDOM-ORDER REAL NUMBERS (RANGE 0-1) --" 180 FOR J = 1 TO TOTAL 190 X(J) = RND 200 PRINT X(J); 210 NEXT J 220 PRINT 230 PRINT "ARRAY SORTED IN ASCENDING ORDER --" 240 GOSUB 1010 '<< call Shell-Metzner sort 250 FOR J = 1 TO TOTAL 260 PRINT X(J); '<< list to screen 270 NEXT J 280 END 1000 REM SS1TM3 ================================================= 1010 REM ********************>> S-MSORT << ********************** 1020 REM ======================================================== 1030 REM The shell-Metzner sorting algorithm is a variation 1040 REM on the Shell sort. It rearranges an array of values 1050 REM into ascending order. It is a binary sort, very 1060 REM fast, and does the sorting in place. It does not 1070 REM require a stack, as does the Quicksort algorithm. 1080 REM ======================================================== 1090 REM Variable Descriptions 1100 REM Entering - 1110 REM X(): array of values to be sorted 1120 REM TOTAL: length of array X() 1130 REM Exiting - 1140 REM X(): array sorted in ascending order 1150 REM Local - 1160 REM SUBDIV: list subdivision size 1170 REM REMAINDER: original list size minus SUBDIV 1180 REM PTR1: loop index, first sublist pointer 1190 REM COMPTR: second sublist pointer for comparison 1200 REM and switch 1210 REM K9: loop index 1220 REM TEMP: temporary storage 1230 REM ======================================================== 1240 SUBDIV = TOTAL 1250 SUBDIV = INT(SUBDIV / 2) 1260 WHILE SUBDIV > 0 1270 REMAINDER =TOTAL - SUBDIV 1280 FOR K9 = 1 TO REMAINDER 1290 PTR1 = K9 1300 COMPTR = PTR1 + SUBDIV 1310 IF X(PTR1) <= X(COMPTR) THEN 1350 1320 TEMP = X(PTR1) 1321 X(PTR1) = X(COMPTR) 1330 X(COMPTR) = TEMP 1331 PTR1 = PTR1 - SUBDIV 1340 IF PTR1 >= 1 THEN 1300 1350 NEXT K9 1360 SUBDIV = INT(SUBDIV / 2) 1370 WEND 1380 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (SNDTEXT) 130 REM ========================================================= 140 DIM X(51),Y(100) 150 TOTAL = 50 160 RANGE = 26 '<< letters of alphabet 170 BLANKS = 10 '<< additional codes to be filtered as blanks 180 X(0) = TOTAL 190 RANDOMIZE 200 PRINT "RANDOM INTEGERS TO INTERPRET AS ASCII CODES --" 210 FOR J = 1 TO TOTAL 220 X(J) = INT(RND * (RANGE+BLANKS)) + 97 230 PRINT X(J); 240 NEXT J 250 PRINT 260 PRINT "THE NUMBER-TO-CHARACTER CONVERTED TEXT --" 270 GOSUB 1000 '<< call numeric-to-character conversion 280 PRINT TEXT$ '<< text-converted sequence to screen 290 PRINT "THE TEXT CONVERTED BACK TO INTEGERS "; 300 PRINT "WITH NON ALPHABET-RANGE VALUES AS BLANKS --" 310 GOSUB 2000 320 FOR J = 1 TO TOTAL 330 PRINT Y(J); 340 NEXT J 350 END 1000 REM SS1WP3 ================================================== 1010 REM *********************>> SNDTEXT1 <<********************** 1020 REM ========================================================= 1030 REM This subroutine converts integers to their 1040 REM corresponding character representation using 1050 REM the CHR$ function. It also adds blanks randomly 1060 REM to simulate the appearance of normal text. It may 1070 REM be adapted to a number of applications which 1080 REM correlate text and musical parameters in some 1090 REM fashion. For example, a sequence of pitch values, 1100 REM transposed to the approprate ASCII code range, can 1110 REM be converted to alphabetic characters whose codes 1120 REM represent the mapping of pitch onto text. The result, 1130 REM however, will probably not conform to any known 1140 REM language because of the absence of syntactical rules. 1150 REM ======================================================== 1160 REM Variable Descriptions 1170 REM Entering - 1180 REM X(): sequence of integer values, to be interpreted 1190 REM as ASCII codes 1200 REM TOTAL: length of array X() 1210 REM Exiting - 1220 REM TEXT$: string of alphabet characters representing 1230 REM mapping of numbers to text 1240 REM Local - 1250 REM K9: loop index, pointer to array X() 1260 REM ======================================================== 1270 TEXT$ = "" 1280 FOR K9 = 1 TO X(0) 1290 IF X(K9) > 122 THEN TEXT$ = TEXT$ + " " ELSE TEXT$ = TEXT$ + CHR$(X(K9)) 1300 NEXT K9 1310 RETURN 2000 REM SS1WP2================================================= 2010 REM *********************>> SNDTEXT2 <<******************** 2020 REM ======================================================= 2030 REM This subroutine is the converse of SNDTEXT1 - a 2040 REM character-to-number conversion algorithm. Text 2050 REM strings may be input and translated to integers, 2060 REM which in turn may be assigned to pitch, rhythm, 2070 REM volume, or any musical parameter. 2080 REM ======================================================= 2090 REM Variable Descriptions 2100 REM Entering - 2110 REM TEXT$: character string 2120 REM Exiting - 2130 REM Y(): array holding integer-converted sequence 2140 REM Local - 2150 REM K9: loop index, pointer to array Y() 2160 REM ======================================================= 2170 Y(0) = LEN(TEXT$) 2180 FOR K9 = 1 TO Y(0) 2190 Y(K9) = ASC(MID$(TEXT$,K9,1)) 2200 NEXT K9 2210 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Stats) 130 REM ========================================================= 140 DIM X(200),Y(15)'<< sequence array, frequency table array 150 RANGE = 15 '<< set random number range 1-15 160 TOTAL = 200 '<< return 200 values 170 RANDOMIZE 180 GOSUB 1000 '<< generate sequence array & frequency table 190 GOSUB 2000 '<< call bargraph display 200 GOSUB 3000 '<< call statistical mode (maxval) 210 GOSUB 4000 '<< call least frequent (minval) 220 GOSUB 5000 '<< call arithmetic mean 230 GOSUB 6000 '<< call statistical variance 240 GOSUB 7000 '<< call standard deviation 250 END 1000 REM ======================================================== 1010 REM *******************>> FREQTABL <<*********************** 1020 REM ======================================================== 1030 FOR K9 = 1 TO TOTAL 1040 VALUE = INT(RND * RANGE)+1 '<< gen random value 1050 X(K9) = VALUE '<< load sequence array 1060 Y(VALUE)=Y(VALUE)+1 '<< record occurrence of value 1070 NEXT K9 1080 RETURN 2000 REM ======================================================== 2010 REM *******************>> BARGRAPH <<*********************** 2020 REM ======================================================== 2030 FOR K9 = 1 TO RANGE 2040 PRINT K9;TAB(10);STRING$(Y(K9),">") 2050 NEXT K9 2060 RETURN 3000 REM ======================================================== 3010 REM *********************>> MAXVAL <<*********************** 3020 REM ======================================================== 3030 REM This subroutine finds the statistical mode of 3040 REM a collection of values. It scans the integer 3050 REM frequency table, then records the address and 3060 REM number of occurrence of the most frequent value(s). 3070 REM ======================================================== 3080 REM Variable Descriptions 3090 REM Entering - 3100 REM Y(): occurrence frequency table 3110 REM RANGE: range of integer values in table 3120 REM Exiting - 3130 REM none (subroutine is procedural) 3140 REM Local - 3150 REM MAX: statistical mode 3160 REM K9: loop index, pointer to frequency table 3170 REM ======================================================== 3180 MAX = Y(1) 3190 FOR K9 = 2 TO RANGE 3200 IF MAX < Y(K9) THEN MAX = Y(K9) 3210 NEXT K9 3220 FOR K9 = 1 TO RANGE 3230 IF Y(K9) = MAX THEN PRINT "THE INTEGER";K9;"= MODE;";" FREQ =";MAX 3240 NEXT K9 3250 RETURN 4000 REM ======================================================== 4010 REM ********************>> MINVAL <<************************ 4020 REM ======================================================== 4030 REM This subroutine scans the occurrence frequency 4040 REM table, then records the address and number of 4050 REM occurrences of the least frequent value. 4060 REM ======================================================== 4070 REM Variable Descriptions 4080 REM Entering - 4090 REM Y(): occurrence frequency table 4100 REM RANGE: range of integer values in table 4110 REM Exiting - 4120 REM none (subroutine is procedural) 4130 REM Local - 4140 REM MIN: least frequent integer 4150 REM K9: loop index, pointer to array Y() 4160 REM ======================================================== 4170 MIN = Y(1) 4180 FOR K9 = 2 TO RANGE 4190 IF MIN > Y(K9) THEN MIN = Y(K9) 4200 NEXT K9 4210 FOR K9 = 1 TO RANGE 4220 IF Y(K9) = MIN THEN PRINT "THE INTEGER";K9;" = LEAST FREQUENT;";" FREQ =";MIN 4230 NEXT K9 4240 RETURN 5000 REM ======================================================== 5010 REM **********************>> MEAN <<************************ 5020 REM ======================================================== 5030 REM This subroutine finds the arithmetic mean of 5040 REM a sample collection. 5050 REM ======================================================== 5060 REM Variable Descriptions 5070 REM Entering - 5080 REM TOTAL: length of sequence 5090 REM Exiting - 5100 REM none (subroutine is procedural) 5110 REM Local - 5120 REM SUM: sum of sequence values 5130 REM MEAN: arithmetic mean of values 5140 REM K9: loop index, pointer to sequence array X() 5150 REM ======================================================== 5160 SUM = 0 5170 FOR K9 = 1 TO TOTAL 5180 SUM = SUM + X(K9) 5190 NEXT K9 5200 MEAN = SUM / TOTAL 5210 PRINT "MEAN =";MEAN;" "; 5220 RETURN 6000 REM ======================================================== 6010 REM *******************>> VARIANCE <<*********************** 6020 REM ======================================================== 6030 REM This subroutine computes statistical variance of 6040 REM a collection of samples. 6050 REM ======================================================== 6060 REM Variable Descriptions 6070 REM Entering - 6080 REM TOTAL: length of sequence 6090 REM MEAN: arithmetic mean of sequence values 6100 REM Exiting - 6110 REM none (subroutine is procedural) 6120 REM Local - 6130 REM VARIANCE: statistical variance 6140 REM TEMP: temporary storage of computation 6150 REM K9: loop index, pointer to sequence array X() 6160 REM ======================================================== 6170 VARIANCE = 0 6180 FOR K9 = 1 TO TOTAL 6190 TEMP = (X(K9) - MEAN) ^ 2 6200 VARIANCE = VARIANCE + TEMP 6210 NEXT K9 6220 VARIANCE = VARIANCE / (TOTAL - 1) 6230 PRINT "VARIANCE = ";VARIANCE 6240 RETURN 7000 REM ======================================================== 7010 REM ********************>> STDEV <<************************* 7020 REM ======================================================== 7030 REM This subroutine computes standard deviation and 7040 REM standard error of the mean. 7050 REM ======================================================== 7060 REM Variable Descriptions 7070 REM Entering - 7080 REM VARIANCE: statistical variance 7090 REM Exiting - 7100 REM none (subroutine is procedural) 7110 REM Local - 7120 REM DEV: standard deviation 7130 REM STDERR: standard error of the mean 7140 REM ======================================================== 7150 DEV = SQR(VARIANCE) 7160 STDERR = DEV / SQR(TOTAL) 7170 PRINT "STANDARD DEVIATION = ";DEV 7180 PRINT "STANDARD ERROR OF THE MEAN = ";STDERR 7190 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Stirling) 130 REM ========================================================= 140 FOR J = 9 TO 12 150 NUM = J 160 PRINT "INTEGER FOR WHICH FACTORIAL ";"WILL BE COMPUTED IS";NUM 170 GOSUB 1000 '<< call stirling's approximation 180 PRINT "LOG OF FACTORIAL IS APPROXIMATELY";APPR 190 IF NUM < 34 THEN PRINT "FACTORIAL IS APPROXIMATELY";INT(EXP(APPR)+.5) 200 PRINT 210 NEXT J 220 END 1000 REM ======================================================== 1010 REM ********************>> STIRLING <<********************** 1020 REM ======================================================== 1030 REM Stirling's approximation is useful in applications 1040 REM which require calculation of porbabilities, combin- 1050 REM ations, and permutations. The subroutine returns 1060 REM the exact log of N factorial for values <= 10, and 1070 REM returns the approximation of the log of n factorial 1080 REM for values larger than 10. 1090 REM Stirling's approximation is useful in applications 1100 REM ======================================================== 1110 REM Variable Descriptions 1120 REM Entering - 1130 REM NUM: integer for which factorial is to be computed 1140 REM Exiting - 1150 REM APPR: Stirling's approximation of log of NUM 1160 REM Local - 1170 REM K9: loop index for factorial up to 10 1180 REM ======================================================== 1190 APPR = 1 1200 IF NUM <= 0 THEN APPR = 0 : RETURN 1210 FOR K9 = 1 TO 10 1220 APPR = APPR * K9 1230 IF NUM = K9 THEN APPR = LOG(APPR) : RETURN 1240 NEXT K9 1250 APPR = LOG(6.283186)/2+LOG(NUM)*(NUM+.5)-NUM+1/(12*NUM) 1260 RETURN
100 REM ======================================================== 110 REM DRIVER PROGRAM 111 REM ======================================================== 120 REM This subroutine is a set of subroutines which 130 REM produce systematic(as opposed to random-order) 140 REM permutations of a series of values. 150 REM If program structure appears strange to you, 160 REM it is because the algorithm was directly adapted 170 REM from the original, written in Pascal language. 180 REM ======================================================== 190 DIM A(12), S(500),T(500) 220 PRINT "ENTER NUMBER OF SET MEMBERS TO BE PERMUTATED:" 230 INPUT N 240 PRINT "HOW MANY PERMUTATIONS TO BE RETURNED?" 250 INPUT T 260 K = N 270 FOR I = 1 TO N 280 A(I) = I 290 NEXT I 300 GOSUB 1030 '<< call permute 310 END 1000 REM ======================================================= 1010 REM ******************>> SYSTPERM <<*********************** 1020 REM ======================================================= 1030 IF K = 1 THEN 4010 '<< call print 1040 GOSUB 2010 '<< call stack push 1050 K = K - 1 1060 GOSUB 1030 '<< call permute 1070 I = 1 1080 IF I = K THEN 1200 1090 X = A(I) 1100 A(I) = A(K) 1110 A(K) = X 1120 GOSUB 2010 '<< call stack push 1130 K = K - 1 1140 GOSUB 1030 '<< call permute 1150 X = A(I) 1160 A(I) = A(K) 1170 A(K) = X 1180 I = I + 1 1190 GOTO 1080 1200 GOSUB 3010 '<< call stack pop 1210 RETURN 1220 REM: 2000 REM ======================================================= 2010 REM ***********************>> PUSH <<********************** 2020 REM ======================================================= 2030 P = P + 1 2040 S(P) = K 2050 T(P) = I 2060 RETURN 3000 REM ======================================================== 3010 REM ***********************>> POP <<*********************** 3020 REM ======================================================== 3030 K = S(P) 3040 I = T(P) 3050 P = P - 1 3060 RETURN 4000 REM ======================================================== 4010 REM ********************>> PRINT <<************************** 4020 REM ======================================================== 4030 FOR J = 1 TO N 4040 PRINT A(J); 4050 NEXT J 4060 PRINT 4070 Z = Z + 1 4080 IF Z = T THEN END ELSE 1200
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Timpoint) 130 REM ========================================================= 140 DIM SET(12),CUM(12) 150 DIM P$(12),FRACTION$(12) 160 RANDOMIZE 170 MEDIAN = 16 180 GOSUB 1000 '<< call pitch class table 190 FOR J = 1 TO 4 200 GOSUB 2000 '<< call set generator 210 PRINT "RANDOM-ORDER 12-TONE ROW #";J;"MOD";MDLS;"--" 220 FOR J1 = 0 TO 11 230 PRINT P$(SET(J1));" "; '<< series to screen 240 NEXT J1 250 PRINT 260 PRINT "THE NUMERIC EQUIVALENT --" 270 FOR J1 = 0 TO 11 280 PRINT SET(J1); 290 NEXT J1 300 PRINT 310 PRINT "DURATIONS REPRESENTING THE DISTANCE";" BETWEEN TIME POINTS --" 320 PRINT "(USING A 16TH-NOTE PULSE BASE ";"AND A MEASURE OF ";MDLS;"-16THS)" 330 GOSUB 3000 '<< call timepoint generator 340 FOR J1 = 0 TO 11 350 PRINT FRACTION$(J1); '<< timepoints to screen 360 NEXT J1 370 PRINT "TOTAL OF DURATIONS =";TALLY; 380 PRINT 390 PRINT 400 NEXT J 410 END 1000 REM ======================================================== 1010 REM ********************>> PITCHTAB <<********************** 1020 REM (modified to load pitch classes only) 1030 REM ======================================================== 1040 FOR J = 0 TO 11 1050 READ P$(J) '<< load pitch classes 1060 NEXT J 1070 REM+++++++++++++++++++++++++++++++++ 1080 DATA C,C#,D,D#,E,F,F#,G,G#,A,A#,B 1090 REM+++++++++++++++++++++++++++++++++ 1100 RETURN 2000 REM ======================================================== 2010 REM ********************>> SETFLAG <<*********************** 2020 REM (modified to generate modulus-converted 2030 REM series and reset flag array) 2040 REM ======================================================== 2050 MDLS = 12/J '<< change modulus for each new series 2060 FOR K9 = 0 TO 11 2070 R9 = INT(RND * 12) 2080 IF CUM(R9) = 1 THEN 2070 2090 CUM(R9) = 1 2100 SET(K9) = R9 MOD MDLS 2110 NEXT K9 2120 FOR K9 = 0 TO 12 2130 CUM(K9) = 0 '<< zero flags prior to next call 2140 NEXT K9 2150 RETURN 3000 REM ======================================================== 3010 REM *********************>> TIMPOINT <<********************* 3020 REM ======================================================== 3030 REM This subroutine produces rhythm duration values 3040 REM using the serial 'timepoint system'. That is, 3050 REM a sequence of time durations,mod n,is derived 3060 REM from the distance between consecutive set 3070 REM members. The modulus determines the number of 3080 REM metrical pulses contained within one measure. 3090 REM ======================================================== 3100 REM Variable Descriptions 3110 REM Entering - 3120 REM SET(): array of series values 3130 REM MDLS: modulus for computation 3140 REM MEDIAN: basic pulse unit 3150 REM Exiting - 3160 REM FRACTION$(): character array of time durations 3170 REM TALLY: total of time durations 3180 REM Local - 3190 REM DUR: fraction numerator 3200 REM K9: loop index, pointer to SET() 3210 REM ======================================================= 3220 TALLY = 0 3230 FOR K9 = 0 TO 10 3240 IF SET(K9+1) <= SET(K9) THEN DUR = MDLS - SET(K9) + SET(K9+1)ELSE DUR = SET(K9+1) - SET(K9) 3250 TALLY = TALLY + DUR 3260 FRACTION$(K9) = STR$(DUR) + "/" + STR$(MEDIAN) 3270 NEXT K9 3280 DUR = MDLS - SET(K9) 3290 TALLY = TALLY + DUR 3300 FRACTION$(11) = STR$(DUR) + "/" + STR$(MEDIAN) 3310 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM ========================================================= 130 REM To change the probabilities in this program, edit 140 REM the DATA statements which are read into the table. 150 REM ========================================================= 160 DIM P(4,4),P$(4) 170 REM >> load pitch character set 180 P$(1)="C" 190 P$(2)="F" 200 P$(3)="G" 210 P$(4)="B" 220 TOTAL = 25 230 LASTPITCH = 3 240 PRINT 250 PRINT "CURRENT PROBABILITY TABLE --" 260 FOR J1 = 1 TO 4 270 FOR J2 = 1 TO 4 280 READ P(J1,J2) '<< load probability table 290 PRINT P(J1,J2), '<< send to screen 300 NEXT J2 310 PRINT 320 NEXT J1 330 REM ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 340 DATA .0,.5,.1,.0 350 DATA .1,.2,.5,.1 360 DATA .6,.3,.1,.5 370 DATA .3,.0,.3,.4 380 REM ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 390 RANDOMIZE 400 PRINT P$(LASTPITCH);" "; 410 FOR J = 1 TO TOTAL-1 420 GOSUB 1000 '<< call transition probability 430 PRINT P$(NEXTPITCH);" "; '<< send choice to screen 440 LASTPITCH = NEXTPITCH 450 NEXT J 460 END 1000 REM ======================================================== 1010 REM *********************>> TRANTABL <<********************* 1020 REM ======================================================== 1030 REM This subroutine incorporates a first-order 1040 REM transitional probability table to determine 1050 REM melodic pitch class sequence. 1060 REM 1070 REM A 2-dimensional matrix holds occurence frequency 1080 REM probabilities which make the current note choice 1090 REM conditional on the previous choice. 1100 REM The appropriate probabilities are entered in the 1110 REM matrix P(), either as program DATA statements, 1120 REM or via user INPUT statements. 1130 REM 1140 REM For output data to be accurate, it is important 1150 REM that the sum of each column be 1.0. Moreover, 1160 REM the data table should be well thought out to 1170 REM prevent situations with no exit. For instance, 1180 REM if, in the following table, the probability that C 1190 REM follows F is changed to 0.0, the probability that 1200 REM F follows F is changed to 1.0, and the probability 1210 REM that G follows F is changed to 0.0, nothing but the 1220 REM pitch F will be generated once F is selected. 1230 REM 1240 REM ================== example of concept ================== 1250 REM 1260 REM L A S T P I T C H 1270 REM C F G B 1280 REM |--------|--------|--------|---------| 1290 REM C | 0.0 | 0.5 | 0.1 | 0.0 | 1300 REM NEXT |--------|--------|--------|---------| 1310 REM F | 0.1 | 0.2 | 0.5 | 0.1 | 1320 REM PITCH |--------|--------|--------|---------| 1330 REM G | 0.6 | 0.3 | 0.1 | 0.5 | 1340 REM |--------|--------|--------|---------| 1350 REM B | 0.3 | 0.0 | 0.3 | 0.4 | 1360 REM |--------|--------|--------|---------| 1370 REM 1380 REM Read the columns for last pitch, rows for next pitch. 1390 REM For instance, if the last pitch returned was B 1400 REM (col 4), then the probability of the next pitch being 1410 REM B (row 4) is 0.1. This principle can be extended to 1420 REM three, four, or more dimensions, but quickly becomes 1430 REM difficult to comprehend. 1440 REM ======================================================== 1450 REM Variable Descriptions 1460 REM Entering - 1470 REM LASTPITCH: holds last note choice 1480 REM Exiting - 1490 REM NEXTPITCH: holds the current note choice 1500 REM Local - 1510 REM U: uniform random number 1520 REM T9: threshold test value 1530 REM K9: loop index, pointer to data table 1540 REM ======================================================= 1550 U = RND 1560 T9 = 0 1570 FOR K9 = 1 TO 4 1580 T9 = P(K9,LASTPITCH) + T9 1590 IF U <= T9 THEN 1610 1600 NEXT K9 1610 NEXTPITCH = K9 1620 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Triangle) 130 REM ========================================================= 140 DIM X(50) 150 RANDOMIZE 160 TOTAL = 50 170 GOSUB 1000 '<< call triangular distribution function 180 FOR J = 1 TO TOTAL 190 PRINT X(J); '<< sequence to screen 200 NEXT J 210 END 1000 REM ======================================================== 1010 REM ********************>> TRIANGLE <<********************** 1020 REM ======================================================== 1030 REM The Triangular Distribution Function generates 1040 REM continuous, random-order real numbers > 0 & < 1. 1050 REM Middle-valued results are most likely to occur. 1060 REM ======================================================== 1070 REM Variable Descriptions 1080 REM Entering - 1090 REM TOTAL: length of sequence 1100 REM Exiting - 1110 REM X(): array holding triangular distribution 1120 REM Local - 1130 REM R8: random number 1 1140 REM 1150 REM R9: random number 2 1160 REM ======================================================== 1170 FOR K9 = 1 TO TOTAL 1180 R8 = RND 1190 R9 = RND 1200 X(K9) = .5 * (R8+R9) 1210 NEXT K9 1220 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (TSEARCH1) 130 REM ========================================================= 140 DIM X(200) 150 TOTAL = 200 160 LOW = 1 170 HIGH = 60 180 RANGE = HIGH - LOW + 1 190 RANDOMIZE 200 PRINT "ARRAY OF RANDOM-ORDER NUMBERS (RANGE 1-";RANGE;")" 210 FOR J = 1 TO TOTAL 220 X(J) = INT(RND * RANGE)+1 230 PRINT X(J); 240 NEXT J 250 PRINT 260 PRINT 270 TABLKEY = LOW 280 PRINT "LOWEST VALUE -";LOW 290 GOSUB 1000 '<< call linear unsorted table search 300 TABLKEY = HIGH 310 PRINT "HIGHEST VALUE -";HIGH 320 GOSUB 1000 '<< call linear unsorted table search 330 END 1000 REM SS2TL1 ================================================= 1010 REM *********************>> TSEARCH1 <<********************* 1020 REM ======================================================== 1030 REM This linear unsorted table search subroutine 1040 REM scans a value sequence (list) for occurrences of 1050 REM keyed values. In this implementation, the search 1060 REM is for array positions where the low and high 1070 REM boundaries of the random generator range are stored. 1080 REM If the values are not found to be present at all, 1090 REM a message to that effect is printed. Although not 1100 REM strictly a part of the searching algorithm, an 1110 REM value occurrence counter (ITEMCOUNT) has been 1120 REM included . 1130 REM 1140 REM If TSEARCH is to be applied to pitch, then the 1150 REM indicated key positions would be used to reference 1160 REM the appropriate addresses in the pitch character 1170 REM string array (table). 1180 REM ======================================================== 1190 REM Variable Descriptions 1200 REM Entering - 1210 REM X(): array of bounded random integers 1220 REM TOTAL: length of sequence 1230 REM TABLKEY: search argument (key to search for) 1240 REM Exiting - 1250 REM none (subroutine is procedural) 1260 REM Local - 1270 REM ITEMCOUNT: occurrence frequency tabulator 1280 REM K9: loop index, pointer to X(), 1290 REM key position indicator 1300 REM ======================================================= 1310 ITEMCOUNT = 0 1320 FOR K9 = 1 TO TOTAL 1330 IF TABLKEY = X(K9)THEN PRINT "FOUND AT POSITION ";K9 ELSE 1350 1340 ITEMCOUNT = ITEMCOUNT + 1 1350 NEXT K9 1360 PRINT "KEY ITEM OCCURRED";ITEMCOUNT;"TIME(S)" 1370 PRINT 1380 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (TSEARCH2) 130 REM ========================================================= 140 DIM X(50) 150 TOTAL = 50 160 PRINT "A SORTED ARRAY OF INTEGERS (RANGE 1-100) --" 170 FOR J = 1 TO TOTAL 180 X(J) = J * 2 190 PRINT X(J); 200 NEXT J 210 PRINT 220 PRINT 230 ARG = 58 240 PRINT "THE INTEGER";ARG; "WILL BE THE ITEM TO SEARCH FOR" 250 GOSUB 1000 260 IF KPOS = 0 THEN PRINT "NOT FOUND" ELSE PRINT "KEY ";ARG;"= POS"KPOS; 270 END 1000 REM SS1TL2 ================================================ 1010 REM *******************>> TSEARCH2 <<********************** 1020 REM ======================================================= 1030 REM This binary search subroutine requires a sorted 1040 REM table with unique entry keys. It is the fastest 1050 REM algorithm in common use, and have a variety of 1060 REM compositional application - from simple boundary 1070 REM searches to test condition retrieval. 1080 REM ======================================================= 1090 REM Variable Descriptions 1100 REM Entering - 1110 REM X() array of sorted items (keys) 1120 REM TOTAL: length of array X() 1130 REM ARG: search argument (item to look for) 1140 REM Exiting - 1150 REM KPOS: location (address) of item if found, 1160 REM 0 if not found 1170 REM Local - 1180 REM LL: lower limit for current search portion 1190 REM UL: upper limit for current search portion 1200 REM KVAL: computed value of key 1210 REM MP: computed halfway point 1220 REM ======================================================== 1230 LL=0 1240 UL=TOTAL+1 1250 KPOS=0 1260 IF ARG < X(1) OR ARG > X(TOTAL)THEN RETURN 1270 IF UL >=LL
THEN MP=INT((UL+LL)/2) : KV=X(MP) :
IF KV <> ARG
THEN IF KV >= ARG
THEN UL=MP-1 : GOTO 1270
ELSE LL=MP+1 : GOTO 1270
ELSE KPOS=MP
ELSE KPOS=UL 1280 IF ARG <> X(KPOS)
THEN KPOS = 0 1290 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (TSEARCH3) 130 REM ========================================================= 140 DIM X(52) 150 TOTAL = 50 160 PRINT "A SORTED ARRAY OF INTEGERS (RANGE 1-100) --" 170 FOR J = 1 TO TOTAL 180 X(J) = J * 2 190 PRINT X(J); 200 NEXT J 210 PRINT 220 PRINT 230 ARG = 96 240 PRINT "THE INTEGER";ARG; "WILL BE THE ITEM TO SEARCH FOR" 250 GOSUB 1000 '<< call interpolation search 260 IF KPOS = 0 THEN PRINT "NOT FOUND" ELSE PRINT "KEY ";ARG;"= POS";KPOS; 270 END 1000 REM SS2TL2 ================================================= 1010 REM *********************>> TSEARCH3 <<********************* 1020 REM ======================================================== 1030 REM This Interpolation Search subroutine requires a 1040 REM sorted list of unique keys (elements). It is 1050 REM faster than the Binary Search in some cases, 1060 REM particularly when the distribution of items is 1070 REM highly skewed. It uses the key's value as an 1080 REM indicator of where to begin the search. which is 1090 REM similar to the method most people use to index 1100 REM an element in a sorted list. Musical applications 1110 REM range from analysis of random-order data to 1120 REM retrieval of stored condition in rule-based 1130 REM compositional procedures. 1140 REM ======================================================== 1150 REM Variable Descriptions 1160 REM Entering - 1170 REM X(): array of sorted items (keys) 1180 REM TOTAL: length of array X() 1190 REM Exiting - 1200 REM KPOS: location (address) of item if found, 1210 REM 0 if not found 1220 REM Local - 1230 REM LL: lower search boundary 1240 REM UL: upper search boundary 1250 REM LOKEY: key at lower boundary 1260 REM UPKEY: key at upper boundary 1270 REM INTPOS: interpolated position in array for 1280 REM next comparison 1290 REM INTKEY: key at interpolated position 1300 REM ======================================================== 1310 LL = 0 1320 UL = TOTAL + 1 1330 X(LL) = X(1) - 1 1340 X(UL) = X(TOTAL) + 1 1350 LOKEY = X(1) 1360 UPKEY = X(TOTAL) 1370 KPOS = 0 1380 IF ARG < LOKEY OR ARG > UPKEY THEN RETURN 1390 IF UL < LL THEN RETURN 1400 INTPOS = LL + INT((UL - LL) * (ARG - LOKEY) / (UPKEY - LOKEY)) 1410 INTKEY = X(INTPOS) 1420 IF INTKEY <> ARG
THEN IF INTKEY >= ARG
THEN UL = INTPOS - 1: UPKEY = INTKEY: GOTO 1390
ELSE LL = INTPOS + 1: LOKEY = INTKEY: GOTO 1390
ELSE KPOS = INTPOS 1430 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (TSEARCH4) 130 REM ========================================================= 140 DIM X(52) 150 TOTAL = 50 160 PRINT "A SORTED ARRAY OF INTEGERS (RANGE 1-100) --" 170 FOR J = 1 TO TOTAL 180 X(J) = J * 2 190 PRINT X(J); 200 NEXT J 210 PRINT 220 PRINT 230 ARG = 42 240 SWIDTH = 5 250 PRINT "THE INTEGER";ARG;"WILL BE THE ITEM TO SEARCH FOR" 260 GOSUB 1000 '<< call interpolation search 270 FOR J =LLL TO LUL 280 PRINT X(J) '<< send returned segment to screen 290 NEXT J 300 END 1000 REM SS1TL3 ================================================= 1010 REM *********************>> TSEARCH4 <<********************* 1020 REM ======================================================== 1030 REM This Proximity Search subroutine requires a 1040 REM sorted list of unique keys (elements). It is 1050 REM more powerful than the Binary Search in that 1060 REM it returns a subset of the array on either side 1070 REM of the key (even if the requested item is missing 1080 REM from the list. This method may be preferable for 1090 REM compositional applications which require searching 1100 REM of rule-groups for prioritized solutions to compos- 1110 REM itional problems, an approach gaining popularity 1120 REM as an alternative to the Monte Carlo method of 1130 REM random number parameter generation. 1140 REM ======================================================== 1150 REM Variable Descriptions 1160 REM Entering - 1170 REM X(): array of sorted items (keys) 1180 REM TOTAL: length of array X() 1190 REM ARG: search argument (item to look for) 1200 REM SWIDTH: width of search below & above item 1210 REM Exiting - 1220 REM LUL: upper limit of list of items returned 1230 REM LLL: lower limit of list of items returned 1240 REM Local - 1250 REM K9: loop index, pointer to array X() 1260 REM ======================================================== 1270 FOR K9=1 TO TOTAL 1280 IF ARG <= X(K9) THEN 1310 1290 NEXT K9 1300 K9=TOTAL+1 1310 IF ARG=X(K9) THEN LUL=K9+SWIDTH ELSE LUL=K9+SWIDTH-1 1320 LLL=K9-SWIDTH 1330 IF LUL > TOTAL THEN LUL=TOTAL 1340 IF LLL < 1 THEN LLL=1 1350 RETURN
100 REM ========================================================= 110 REM ==================== DRIVER PROGRAM ===================== 120 REM ========================================================= 130 DIM TONE(84) 140 NUMTONES = 84 150 OCTDIV = 19 '<< specify a 19-tone per octave scale 160 FREQ1 = 61.735 170 GOSUB 1000 '<< call tuning compiler 180 FOR J= 1 TO NUMTONES 190 PRINT TONE(J), '<< send scale frequencies to screen 200 NEXT J 210 END 1000 REM ======================================================== 1010 REM ********************>> TUNINGS <<*********************** 1020 REM ======================================================== 1030 REM This subroutine compiles a data table containing 1040 REM equal-tempered, octave-repeating tunings. 1050 REM ======================================================== 1060 REM Variable Descriptions 1070 REM 1080 REM Entering - 1090 REM FREQ1: frequency in Herz (cps) of scale tonic 1100 REM NUMTONES: number of pitches to compute 1110 REM OCTDIV: number of equalsize steps within octave 1120 REM Exiting - 1130 REM TONE(): array of computed scale frequencies 1140 REM Local - 1150 REM COEFF: coefficient for specified octave division 1160 REM K9: loop index, pointer to array TONE() 1170 REM 1180 REM ======================================================== 1190 COEFF = 2^(1/OCTDIV) 1200 TONE(1) = INT(FREQ1+.5) 1210 FOR K9= 2 TO NUMTONES 1220 TONE(K9) = INT(TONE(K9-1)*COEFF+.5) 1230 NEXT K9 1240 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 115 REM (Valratio) 120 REM ========================================================= 130 DIM P(12),X(100) 140 RANDOMIZE(-29312) 150 TOTAL = 100 160 RANGE = 12 170 WINDO = 4 180 GOSUB 1000 '<< call value ratio control 185 PRINT "SIZE OF VALUE WINDOW IS ";WINDO 190 FOR J = 1 TO 100 200 PRINT X(J), 210 NEXT J 220 END 1000 REM ======================================================== 1010 REM ******************>> REPRATIO <<*********************** 1020 REM ======================================================== 1030 REM This algorithm prevents repetition of values which 1040 REM fall within a specified 'window' of predetermined 1050 REM size. For instance, if 100 values are to be 1060 REM returned, a window of 9 is specified, and a 1070 REM random number value range of 1-10 is entered, 1080 REM then the sequence which is generated will be a 1090 REM non-repeating series (set). However, if a smaller 1100 REM window is entered, then only the values falling 1110 REM within the sliding 'window' will be prevented 1120 REM from containing repetitions. 1130 REM ======================================================== 1140 REM Variable Descriptions 1150 REM 1160 REM Entering - 1170 REM TOTAL: number of values to be returned 1180 REM RANGE: 1-n inclusive limits for random numbers 1190 REM WINDO: size of window for repetition prevention 1200 REM Exiting - 1210 REM X(): array holding sequence of values 1220 REM Local - 1230 REM U: random number, pointer to array P() 1240 REM P(): array which records value occurence 1250 REM K9: loop index, pointer to array X() 1260 REM 1270 REM ======================================================== 1280 FOR K9 = 1 TO TOTAL 1290 U = INT(RND * RANGE)+1 1300 IF P(U) = 1 THEN 1290 1310 P(U) = 1 1320 X(K9) = U 1330 IF K9 <= WINDO THEN 1350 1340 P(X(K9-WINDO)) = 0 1350 NEXT K9 1360 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 115 REM (Valuprobs) 120 REM ========================================================= 130 DIM WTABLE(5), X(40) 140 RANDOMIZE 150 PROBS = 5 160 TOTAL = 40 170 GOSUB 1000 '<< call probability table subr. 180 GOSUB 2000 '<< call table look-up & test 190 FOR J = 1 TO TOTAL 200 PRINT X(J), '<< send choices to screen 210 NEXT J 220 END 1000 REM ======================================================== 1010 REM *******************>> PROBTABL <<********************** 1020 REM ======================================================== 1030 REM This subroutine reads relative weights into a 1040 REM cumulative probability table (array). 1050 REM ======================================================== 1060 REM Variable Descriptions 1070 REM Entering - 1080 REM PROBS: number of relative probability weights 1090 REM Exiting - 1100 REM WTABLE(): data table containing relative weights 1110 REM Local - 1120 REM WSUM: holds current sum of probability weights 1130 REM K9: loop index, pointer to array WTABLE() 1140 REM ======================================================== 1150 WSUM = 0 1160 FOR K9 = 1 TO PROBS 1170 READ WTABLE(K9) 1180 WTABLE(K9)=WTABLE(K9)+WSUM 1190 WSUM=WTABLE(K9) 1200 NEXT K9 1210 REM ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1220 DATA 1,2,3,4,5 1230 REM ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1240 RETURN 2000 REM ======================================================== 2010 REM *******************>> PROBCALC <<*********************** 2020 REM ======================================================== 2030 REM This subroutine generates the numbers 1-n over a 2040 REM run of n values in relative proportion to the 2050 REM probability weights contained in WTABLE(). 2060 REM The numbers may be used directly, or they may 2070 REM serve as pointers to pitch class characters, 2080 REM rhythmic duration, volume, or articulation 2090 REM arrays. 2100 REM ======================================================== 2110 REM Variable Descriptions 2120 REM Entering - 2130 REM TOTAL: number of values to be returned 2140 REM WTABLE(): array containing relative weights 2150 REM PROBS: number of relative probability weights 2160 REM WSUM: holds current sum of probability weights 2170 REM Exiting - 2180 REM X(): array containing selected values 2190 REM Local - 2200 REM WSUM: stores current sum of probability weights 2210 REM R: random number, scaled to sum of weights 2220 REM L9: loop index, pointer to WTABLE() 2230 REM K9: loop index, pointer to array X() 2240 REM ======================================================== 2250 FOR K9 = 1 TO TOTAL 2260 R = RND * WSUM 2270 FOR L9 = 1 TO PROBS 2280 IF R <= WTABLE(L9) THEN 2300 2290 NEXT L9 2300 X(K9) = L9 2310 NEXT K9 2320 RETURN
100 REM ========================================================= 110 REM VECTORS 120 REM ========================================================= 130 REM The subroutine VECTSTOR creates 'event vectors' 140 REM by storing pitch, rhythm and volume data for a 150 REM single musical event in one double precision number. 170 REM The subroutine PARXTRCT extracts the event attributes 180 REM from the composite value. 200 REM ========================================================= 210 REM ========================================================= 220 REM Variable Descriptions 230 REM 240 REM P: holds value of event vector pitch parameter 250 REM R: holds value of event vector rhythm parameter 260 REM V: holds value of event vector volume parameter 270 REM COMP#(): double precision vector (values P,R,V) 280 REM K9: loop index, pointer to array COMP#() 290 REM 300 REM ========================================================= 310 REM =================== DRIVER PROGRAM ====================== 320 REM ========================================================= 330 DIM COMP#(10) 340 GOSUB 1000 '<< call event vector storage 350 PRINT 360 GOSUB 2000 '<< call event vector extract 370 END 1000 REM ======================================================== 1010 REM ******************>> VECTSTOR <<************************ 1020 REM ======================================================== 1030 PRINT "STORE EVENT PARAMETERS IN DBL PRECIS. NUMBER -- 1040 FOR K9= 1 TO 10 1050 P = K9 '<< assign pitch value 1060 R = K9 * 5 '<< assign rhythm duration value 1070 V = K9 * 10 '<< assign volume level value 1080 PRINT "PITCH = ";P,"RHYTHM = ";R, "VOLUME =";V, 1090 COMP#(K9) = (P * 1000000!) + (R * 1000) + V 1100 PRINT "COMPOSITE NUMBER IS ";COMP#(K9) 1110 NEXT K9 1120 RETURN 2000 REM ======================================================== 2010 REM *******************>> PARXTRCT <<*********************** 2020 REM ======================================================== 2030 PRINT "EXTRACT EVENT PARAMETERS FROM COMPOSITE NUMBER--" 2040 FOR K9 = 1 TO 10 2050 COMP#(K9) = COMP#(K9)/1000000! 2060 P = INT(COMP#(K9)) 2070 PRINT "P=";P , 2080 R = INT((COMP#(K9) - INT(COMP#(K9))) * 1000) 2090 PRINT "R=";R , 2100 COMP#(K9) = COMP#(K9) * 1000 2110 V = INT((COMP#(K9) - INT(COMP#(K9))) * 1000+.5) 2120 PRINT "V=";V 2130 NEXT K9 2140 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Voss) 130 REM ========================================================= 140 DIM X(50) 150 RANDOMIZE 160 TOTAL = 50 170 LAST = 24 180 GOSUB 1000 '<< call one-over-f distribution function 190 FOR J = 1 TO TOTAL 200 PRINT X(J); '<< sequence to screen 210 NEXT J 220 END 1000 REM ======================================================== 1010 REM ********************>> VOSS <<************************** 1020 REM ======================================================== 1030 REM This subroutine generates 1/f fractional noise 1040 REM patterns for use in any musical parameter. Each 1050 REM subsequent value is conditional on the last value 1060 REM generated, and all generated values correlate 1070 REM logarithmically with the past, resulting in a 1080 REM process which has longe-range memory. 1090 REM ======================================================== 1100 REM Variable Descriptions 1110 REM Entering - 1120 REM TOTAL: length of sequence 1130 REM LAST: last value generated 1140 REM Exiting - 1150 REM X(): array holding one-over-f distribution 1160 REM Local - 1170 REM FRACT: current one-over-f value 1180 REM HALFVALS: 1/2 the number of possible values 1190 REM PROB: 1 / number of possible values 1200 REM R9: uniform random number 1210 REM S9: stores in-progress computation 1220 REM K9: loop index, pointer to array X() 1230 REM ======================================================== 1240 REM 1250 REM 1260 FOR K9 = 1 TO TOTAL 1270 FRACT = 0 1280 HALFVALS = 16 ' = 1/2 number of poss values 1290 PROB = .03125 ' = 1/num poss values 1300 WHILE HALFVALS > = 1 1310 S9 = INT(LAST/HALFVALS) 1320 IF S9 = 1 THEN LAST = LAST-HALFVALS 1330 R9 = RND 1340 IF R9 < PROB THEN S9 = 1-S9 1350 FRACT= FRACT + S9 * HALFVALS 1360 HALFVALS = HALFVALS/2 1370 PROB = PROB * 2 1380 WEND 1390 X(K9) = FRACT 1400 LAST = FRACT 1410 NEXT K9 1420 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Weibull) 130 REM ========================================================= 140 DIM X(50) 150 RANDOMIZE 160 TOTAL = 50 161 SPREAD = 20 162 DENSHAPE = 1 170 GOSUB 1000 '<< call Weibull distribution function 180 FOR J = 1 TO TOTAL 190 PRINT X(J); '<< sequence to screen 200 NEXT J 210 END 990 REM ========================================================= 1000 REM **********************>> WEIBULL <<********************* 1010 REM ======================================================== 1020 REM The Weibull Probability Distribution function 1030 REM generates random-order real numbers greater than 1040 REM zero. Its curve can assume a variety of shapes in 1050 REM accordance with the value of its input parameter, 1060 REM DENSHAPE. The SPREAD parameter controls only the 1070 REM horizontal scale. 1080 REM ======================================================== 1090 REM Variable Descriptions 1100 REM Entering - 1110 REM TOTAL: length of sequence 1120 REM SPREAD: horizontal scaling parameter 1130 REM DENSHAPE : curve shaping parameter 1140 REM Exiting - 1150 REM X(): array holding Weibull distribution 1160 REM Local - 1170 REM R9: uniform random number 1180 REM K9: loop index, pointer to array X() 1189 REM ======================================================== 1190 FOR K9 = 1 TO TOTAL 1200 R9 = RND 1210 R9=1/(1-R9) 1220 X(K9) = SPREAD * LOG(R9)^(1/DENSHAPE) 1230 NEXT K9 1240 RETURN
100 REM ========================================================= 110 REM DRIVER PROGRAM 120 REM (Wordplay) 130 REM ========================================================= 140 DIM WORD$(200),TEXT$(13) 150 DIM TXTLN(12),TXTWD(200),X(20),WTABL(20) 160 FOR J = 1 TO 20 170 X(J) = J 180 NEXT J 190 READ TOTAL 200 PRINT "THE ORIGINAL TEXT --" 210 FOR J = 1 TO TOTAL 220 READ TEXT$(J) 230 PRINT TEXT$(J) 240 NEXT J 250 PRINT 260 RANDOMIZE 270 PRINT "A RANDOM ORDERING OF THE TEXT LINES --" 280 GOSUB 1000 290 TEXT$(TOTAL) = TEXT$(TOTAL) + " #" 300 PRINT "WORDS IN TEXT" : PRINT 310 CHARSET$ =" abcdefghijklmnopqrstuvwxyz0123456789" 320 CHARSET$ = CHARSET$ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 330 ENDFLAG = 0 : PHRPTR = 1 : POSIT = 1 : COUNT = 0 340 WHILE ENDFLAG <> 1 350 GOSUB 2000 '<< call next word 360 CLNWORD$ = NXTWORD$ 370 GOSUB 3000 '<< call string clean-up & compress 380 WRDCNT = WRDCNT + 1 390 NXTWORD$ = CLNWORD$ 400 PRINT NXTWORD$, 410 WORD$(WRDCNT) = NXTWORD$ 420 SIZE = LEN(NXTWORD$) 430 WTABL(SIZE) = WTABL(SIZE) + 1 440 WEND 450 PRINT 460 P$=" ## ### ## ###" 470 PRINT "length frequency length frequency" 480 FOR J = 1 TO 20 STEP 2 490 PRINT USING P$;J,WTABL(J),J+1,WTABL(J+1) 500 NEXT J 510 GOSUB 4000 '<< call weighted average 520 PRINT 530 PRINT "AVERAGE WORD LENGTH = ";AVERAGE 540 PRINT "A RANDOM ORDERING OF THE TEXT WORDS --" 550 GOSUB 5000 '<< call random word-walk 560 PRINT 570 END 580 REM +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 590 DATA 12 600 DATA "At morn -at noon -at twilight dim-" 610 DATA "Maria! thou hast heard my hymn!" 620 DATA "In joy and woe -in good and ill-" 630 DATA "Mother of God, be with me still!" 640 DATA "When the hours flew brightly by," 650 DATA "And not a cloud obscured the sky," 660 DATA "My soul, lest it should truant be," 670 DATA "Thy grace did guide to thine and thee;" 680 DATA "Now, when storms of Fate o'rcast" 690 DATA "Darkly my Present and my Past," 700 DATA "Let my Future radiant shine" 710 DATA "With sweet hopes of thee and thine!" 720 REM +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1000 REM ======================================================== 1010 REM ********************>> RANDLINE <<********************** 1020 REM ======================================================== 1030 REM This subroutine is an adaptation of the sampling- 1040 REM without-replacement algorithm. It simply uses the 1050 REM ARRAYFLAG method of serializing the lines, then 1060 REM returns one copy of each line in random-order. 1070 REM ======================================================== 1080 REM Variable Descriptions 1090 REM Entering - 1100 REM TEXT$(): array holding lines of text 1110 REM TOTAL: number of lines in TEXT$() 1120 REM Exiting - 1130 REM none (subroutine is procedural) 1140 REM Local - 1150 REM LINSTEP: random number 1160 REM TXTLN(): array to store occurrence flags 1170 REM K9: loop index 1180 REM ======================================================== 1190 FOR K9 = 1 TO TOTAL 1200 LINSTEP = INT(RND * TOTAL)+1 1210 IF TXTLN(LINSTEP)= 1 THEN 1200 1220 PRINT TEXT$(LINSTEP) 1230 TXTLN(LINSTEP) = 1 1240 NEXT K9 1250 RETURN 2000 REM ======================================================== 2010 REM ********************>> NEXTWORD <<********************** 2020 REM ======================================================== 2030 REM This subroutine extracts the next word in line 2040 REM from the list of phrases supplied by the DRIVER 2050 REM PROGRAM, which also passes several flags to 2060 REM signal the processing status. End-of-word is 2070 REM indicated by (" "), end-of-phrase by ("_#"). 2080 REM ======================================================== 2090 REM Variable Descriptions 2100 REM Entering - 2110 REM TEXT$(): list of phrases to be broken into words 2120 REM PHRPTR: phrase pointer 2130 REM POSIT: position in phrase being analyzed 2140 REM Exiting - 2150 REM ENDFLAG: signal for end of processing (if = 1) 2160 REM NXTWORD$: next word (extracted) 2170 REM Local - 2180 REM SCANCHAR$: character being scanned 2190 REM K9: phrase loop index 2200 REM L9: word loop index 2210 REM ======================================================== 2220 NXTWORD$ = "" 2230 FOR K9 = POSIT TO LEN(TEXT$(PHRPTR)) 2240 SCANCHAR$ = MID$(TEXT$(PHRPTR),K9,1) 2250 IF SCANCHAR$ = "#" THEN ENDFLAG = 1 : RETURN 2260 IF SCANCHAR$ <> " " THEN 2300 2270 NEXT K9 2280 PHRPTR = PHRPTR + 1 : POSIT = 1 2290 IF NXTWORD$ = "" THEN 2230 ELSE ENDFLAG = 0 : RETURN 2300 NXTWORD$ = NXTWORD$ + SCANCHAR$ 2310 IF K9 = LEN(TEXT$(PHRPTR)) THEN PHRPTR = PHRPTR + 1 : POSIT = 1 :ENDFLAG = 0 : RETURN 2320 FOR L9 = K9 + 1 TO LEN(TEXT$(PHRPTR)) 2330 SCANCHAR$ = MID$(TEXT$(PHRPTR),L9,1) 2340 IF SCANCHAR$ = " " THEN POSIT = L9 : GOTO 2380 2350 NXTWORD$ = NXTWORD$ + SCANCHAR$ 2360 NEXT L9 2370 PHRPTR = PHRPTR + 1 : POSIT = 1 2380 ENDFLAG = 0 2390 RETURN 3000 REM ======================================================== 3010 REM **********************>> STRCLEAN <<******************** 3020 REM ======================================================== 3030 REM This subroutine strips all special characters from 3040 REM a string, then compresses it. 3050 REM ======================================================== 3060 REM Variable Descriptions 3070 REM Entering - 3080 REM CLNWORD$: string to be cleaned 3090 REM CHARSET$: string of legal characters to be kept 3100 REM Exiting - 3110 REM CLNWORD$: cleaned string 3120 REM Local - 3130 REM TBUFF$: temporary string buffer 3140 REM K9: loop index, pointer to CLNWORD$ characters 3150 REM ======================================================== 3160 TBUFF$ = "" 3170 FOR K9 = 1 TO LEN(CLNWORD$) 3180 IF INSTR(CHARSET$,MID$(CLNWORD$,K9,1)) <> 0 THEN TBUFF$ = TBUFF$+MID$(CLNWORD$,K9,1) 3190 NEXT K9 3200 CLNWORD$ = TBUFF$ 3210 RETURN 4000 REM ======================================================== 4010 REM **********************>> AVERAGE <<********************* 4020 REM ======================================================== 4030 REM This subroutine computes the weighted average length 4040 REM of all words contained in the text. 4050 REM ======================================================== 4060 REM Variable Descriptions 4070 REM Entering - 4080 REM X(): array of values to be averaged 4090 REM WTABL(): array of weights corresponding to each X() 4100 REM TOTAL: number of values in X() and WTABL() 4110 REM Exiting - 4120 REM AVERAGE: weighted average length of words 4130 REM Local - 4140 REM PRODSUM: sum of products of value and weight 4150 REM WEIGHTSUM: sum of weights 4160 REM K9: loop index, pointer to WTABLE() 4170 REM ======================================================== 4180 PRODSUM = 0 : WEIGHTSUM = 0 4190 FOR K9 = 1 TO TOTAL 4200 PRODSUM = PRODSUM + WTABL(K9) * X(K9) 4210 WEIGHTSUM = WEIGHTSUM + WTABL(K9) 4220 NEXT K9 4230 AVERAGE = PRODSUM / WEIGHTSUM 4240 RETURN 5000 REM ======================================================== 5010 REM *********************>> RANDWORD <<********************* 5020 REM ======================================================== 5030 REM This subroutine is identical in function to 5040 REM RANDLINE, except that it randomizes word order. 5050 REM ======================================================== 5060 REM Variable Descriptions 5070 REM Entering - 5080 REM WORD$(): array holding words of text 5090 REM WRDCNT: number of words in array WORD$() 5100 REM Exiting - 5110 REM none (subroutine is procedural) 5120 REM Local - 5130 REM TXTWD(): array to store occurrence flags 5140 REM WRDSTEP: random number 5150 REM K9: loop index 5160 REM ======================================================== 5170 FOR K9 = 1 TO WRDCNT 5180 WRDSTEP = INT(RND * WRDCNT)+1 5190 IF TXTWD(WRDSTEP) = 1 THEN 5180 5200 PRINT WORD$(WRDSTEP);" "; 5210 TXTWD(WRDSTEP) = 1 5220 IF K9 MOD 10 = 0 THEN PRINT 5230 NEXT K9 5240 RETURN