In the last chapter, we investigated some of the difficulties we need to overcome when writing programs to produce a melody. The programs produce melodies of various qualities but there is one thing they all lack - harmony.
Harmony is produced when more than one note sounds at the same time and it is easily achieved. To produce a harmony pleasing to our ears, however, is another matter altogether.
A harmonic framework or background to a piece of music can be provided by strumming a guitar or playing chords on a piano or organ. (See Chapter 2: Program 2.1 gives an aural indication of the harmonies produced by various chords.) Given a chord progression, any number of melody lines can be produced to fit over the top. Conversely, given a set of melody notes, any number of backing chords can be used to harmonise it. Just to illustrate the possible variety, each melody note could be given a different chord or a single note could be given two or more chords. The chords could change every bar, twice per bar or once every eight bars. Some of these combinations will sound distinctly unpleasant and others will be boring. The point is, anything goes, as long as it pleases someone, even if it's only the composer. Most music, however, follows a more agreeable (some might say predictable) harmonic structure.
Most popular tunes rely heavily upon their chord progressions for their appeal, and some musicians can take any melody line and work out a chordal accompaniment for it. It may not be the same as the original, but it will be close enough for most people to recognise the tune. It is unlikely that two musicians will harmonise a tune in exactly the same way and no way different to that determined by the composer would be regarded as more right or wrong.
The type of chord used to harmonise a tune is indicative of the level of harmonic appreciation we, the public, have reached. The wandering minstrel of a few hundred years ago would use a far less complicated set of chord progressions because that would be the level of harmonic appreciation (or tolerance) the public had reached at the time. We are now musically more tolerant, and more complicated and dissonant harmonies are finding increasing acceptance. (When two or more tones are played together and produce a sound unpleasant to the ear, it is said to be dissonant. If the sound is pleasing it is said to be consonant. Dissonant harmonies generally refer to sounds such as those produced by playing two notes only a semitone apart.)
Jazz musicians specialise in taking a melody and/or a chord progression and improvising or spontaneously inventing new melodies or harmonies for that piece. Often, these will deliberately be obscure and quite removed from the original tune which is why many people find it difficult to listen to and understand jazz.
Classical music had its own harmonic and compositional rules (most of the great musicians broke them) and you can hear how we have progressed, harmonically, if you listen to a piece of music by Purcell or Arne (who wrote 'Rule Britannia'.)
Within any particular genre of music, our ears expect to hear a certain type of chord sequence (or harmonic structure) and a melody ordered in a certain way. A program to produce a pop tune, for example, would necessarily be quite complex and intricate. It is perhaps slightly easier to produce music in a classical style which may be, apparently, less harmonically (and structurally) demanding.
In the field of computer compositions we can safely assume that anything which sounds vaguely pleasant and does not make the listener squirm in his seat is a success. The programs in this chapter go a little further, I hope, and produce compositions in up to three voices which will be musically acceptable to all but the most critical pedant.
Judging by the problems we needed to overcome to generate even a single series of notes, you might imagine that the production of a two- or three-voiced composition would be two or three times as difficult. If we were to try to implement some standard, academic rules of harmony, that would indeed be the case. If we were to attempt the composition of a classical three-part canon, it would be even more difficult although the rules could be found and formulated much more rigidly.
Our first aim will be to produce a series of two or three notes sounding together which are not dissonant and which form, in total, a reasonably pleasant harmonic (and melodic) progression.
After all this talk about compositions and rules, it is still difficult (if not impossible) to explain exactly what makes a piece of music good or bad, pleasant or unpleasant. It combines both order and disorder in various proportions. Any compositional program needs a random element, otherwise it would simply be playing pre-programmed music which would not be at all original. Our problem is to find a way of controlling the amount of randomness applied to the choice of notes.
The quickest, easiest and most effective way is to use the random function to select a note or series of notes which you know will harmonise with each other. This, obviously, will produce very good results but not very original compositions.
Mozart is reputed to have devised a compositional system based upon throwing a dice (I refuse to use the word die). His method could easily be converted to a computer program and would produce spectacular results, but the catch is, you need to do a certain amount of composing yourself.
The dice were used to select one of a number of bars of music which had previously been composed. For example, to compose a tune eight bars long, a table would be drawn up of eight columns and six rows, each containing a bar of music. The first throw of the dice would select a bar from column 1, the second throw from column 2, etc, until you had eight bars.
The initial problem is in composing 48 bars of music in such a way that any bar from column 2 can follow any bar from column 1, etc. No problem for Mozart but perhaps a little more daunting for us not-so-great composers. If you do attempt it, and it may not be as difficult as it sounds, the results would certainly be very good. In this case though, you are doing all the composing, not the computer.
You can apply other rules and modifications to a compositional program so that, for example, it periodically inserts a previously-written series of notes into its otherwise random output but, again, you are usually the one composing the most interesting parts.
When we turn the compositional process over to the computer we need a way to control the amount of randomness it uses to make its selection of notes without imposing our own compositions upon it.
As the computer does not know which combination of notes produces good results, our first step is to specify a list of permissible notes for it to choose from. Playing notes from this selection at random will still produce an unordered sequence of notes which could jump from one extreme of the range to the other. We need a way of softening the random factor.
Such an algorithm was devised some years ago by Richard Voss of IBM. For our purposes, we can liken the procedure to rolling a set of five four-sided dice. We add the numbers shown to get our random number. If we always roll the five dice we will still have a series of totally random numbers, but if we usually roll one or two dice and only sometimes three, four or five we will get a series of numbers which vary from each other only slightly but which are still capable of producing a large change. This idea is implemented in Program 11.1.
10 REM PROGRAM 11.1
20 REM Computer Composition
30 REM In 3-Part Harmony
40
50 MODE7
60
70 FOR X%=0 TO 1:PRINTTAB(0,X%)CHR$14
1;CHR$133;TAB(6)"3-PART HARMONY COMPOSIT
ION":NEXT X%
80 PRINTTAB(0,2)CHR$131;"Channel 1";T
AB(13);"Channel 2";TAB(26);"Channel 3"
90
100 FOR Col=3 TO 24
110 PRINTTAB(0,Col);CHR$(129+Col MOD 6
);
120 NEXT Col
130
140 REM Set text Window
150 VDU28,1,24,39,4
160
170 DIM Dice%(4),Key$(15)
180 Key=1
190 Tempo%=1
200 Scale$=" C C# D D# E F F# G
G# A A# B"
210
220 REM Chinese Sticks
230 ENVELOPE1,1,0,0,0,0,0,0,126,-10,-5
,-2,126,100
240
250 REM Slow Attack
260 ENVELOPE2,1,0,0,0,0,0,0,10,-1,0,-1
,126,100
270
280 REM Vibrato
290 ENVELOPE3,4,0,1,0,2,1,0,126,-10,-4
,-4,126,100
300 Env1=3:Env2=3:Env3=3
310
320 PROCSetScale
330 PROCDuration
340
350 REPEAT
360 IF ADVAL(-6)>0 PROCPlay1
370 IF ADVAL(-7)>0 PROCPlay2
380 IF ADVAL(-8)>0 PROCPlay3
390 UNTIL FALSE
400 END
410
420 DEF PROCSetScale
430
440 REM RESTORE To Required Scale
450 RESTORE 530
460
470 FOR I%=0 TO 15
480 READ Key$(I%)
490 NEXT I%
500 ENDPROC
510
520 REM Hornpipe
530 DATA C2,E2,G2,C3,E3,G3,C4,G3,A3,F3
,D3,A2,F2,D2,F2,A2
540
550 REM Chinese
560 DATA F#2,G#2,A#2,C#2,D#2,F#3,G#3,A
#3,C#3,D#3,F#2,G#2,A#2,C#2,D#2,F#2
570
580 REM Minor Key
590 DATA A#3,D3,G2,C2,D#2,G2,C3,G#3,G3
,C4,D#3,G#3,C4,D3,D#3,G#3
600
610 REM Minstrel
620 DATA B2,G2,D3,G2,A3,E3,C4,A2,C3,A2
,E3,C3,G3,D3,G3,B2
630
640 REM Minstrel 2
650 DATA F3,A3,G3,C2,E3,G2,C2,G2,E2,C3
,A2,G3,C3,A#2,G2,F2
660
670 DEF PROCDuration
680
690 REM GOTO Required Durations
700 REM See Text For Explanation
710 GOTO 770
720
730 REM Fast (Chinese)
740 X1=3:Y1=0:Dotted1=1:X2=1:Y2=2:Dott
ed2=9:X3=1:Y3=1:Dotted3=9:GOTO 820
750
760 REM Mad Hornpipe
770 X1=1:Y1=1:Dotted1=9:X2=1:Y2=1:Dott
ed2=9:X3=1:Y3=1:Dotted3=9:GOTO 820
780
790 REM Minstrel
800 X1=1:Y1=3:Dotted1=1:X2=2:Y2=3:Dott
ed2=1:X3=1:Y3=5:Dotted3=1:GOTO 820
810
820 ENDPROC
830
840 DEF PROCPlay1
850 PROCRollDice
860 PROCGetNote
870 D=1:IF RND(16)
890 IF X1>1 THEN Dur%=2^(RND(X1)+Y1)*D
900 SOUND1,Env1,Pitch%,Dur%*Tempo%
910 PROCPrint(3)
920 ENDPROC
930
940 DEF PROCPlay2
950 PROCRollDice
960 PROCGetNote
970 D=1:IF RND(16)
990 IF X2>1 THEN Dur%=2^(RND(X1)+Y1)*D
1000 SOUND2,Env2,Pitch%,Dur%*Tempo%
1010 PROCPrint(15)
1020 ENDPROC
1030
1040 DEF PROCPlay3
1050 PROCRollDice
1060 PROCGetNote
1070 D=1:IF RND(16)
1090 IF X3>1 THEN Dur%=2^(RND(X3)+Y3)*D
1100 SOUND3,Env3,Pitch%-48,Dur%*Tempo%
1110 PROCPrint(28)
1120 ENDPROC
1130
1140 DEF PROCRollDice
1150 Chance%=RND(100)
1160
1170 REM This Sets the Random Factor
1180 IF Chance%<84 Roll=1 ELSE IF Chanc
e%<88 Roll=2 ELSE IF Chance%<92 Roll=3 E
LSE IF Chance%<96 ROLL=4 ELSE Roll=5
1190
1200 IF Roll=1 Dice%(0)=RND(4)-1 ELSE P
ROCRoll
1210 PROCAddRolls
1220 ENDPROC
1230
1240 DEF PROCRoll
1250 FOR I%=0 TO Roll-1
1260 Dice%(I%)=RND(4)-1
1270 NEXT I%
1280 ENDPROC
1290
1300 DEF PROCAddRolls
1310 Note%=0
1320 FOR I%=0 TO 4
1330 Note%=Note%+Dice%(I%)
1340 NEXT I%
1350 ENDPROC
1360
1370 DEF PROCPrint(Tab)
1380 PRINTTAB(Tab)Key$(Note%);"-";Dur%*
Tempo%;
1390 ENDPROC
1400
1410 DEF PROCGetNote
1420 IF LEN(Key$(Note%))=2 THEN NoteNam
e$=LEFT$(Key$(Note%),1) ELSE NoteName$=L
EFT$(Key$(Note%),2)
1430 Octave%=VAL(RIGHT$(Key$(Note%),1))
1440 PositionInScale%=(INSTR(Scale$,Not
eName$))/3
1450 Pitch%=Key+PositionInScale%*4+(Oct
ave%-1)*48
1460 IF Pitch%<0 OR Pitch%>255 PRINT"ER
ROR IN PITCH DATA ";Key$(Note%);" Pitch
= ";Pitch%:STOP
1470 ENDPROC
When run, the program will compose music according to the various parameters set within it. These can all be altered and are explained below.
The program up to line 150 sets a screen display which gives us something to look at while the computer is churning out its composition.
PROCDuration calls the procedure at fine 670 to determine the permitted set of duration values. Each channel has three duration parameters which are used to determine the range of duration values. As the operation of each channel's duration values is the same, we will only look at those of channel 1.
The probability that a note will be dotted is related to a random value between 1 and 16 generated in line 870. This seems to tie in well with music whose note values tend to be in multiples of 2, 4, 8 and 16 (like the binary system) but you can alter it to run on a straight percentage basis if you wish. If Dotted1 is greater than or equal to the random value, the next note will be dotted. If Dotted1 is set to 1 the notes will never be dotted, and if it is set to 16 they will always be dotted.
All the variable parameters and DATA statements can be altered and adjusted to produce an almost infinite range of sounds. Much of it will be music but with extreme settings, especially of the duration parameters, the results will be disjointed.
1155 Chance%=80
and then:
1155 Chance%=100
you will be able to hear and observe the results of rolling only one dice and then of rolling all five. You can add values in between, to simulate rolling any specific number. If you temporarily blank out PROCPrint, eg by adding:
1375 ENDPROC
and add:
1345 PRINT Note%
you will see the range of totals produced by PROCAddRolls.
Although the variety of compositions produced by Program 11.1 is quite large, the computer is restricted to a choice of only 16 notes (although you can increase this). This is not such a disadvantage, as many tunes have been written containing far fewer notes, but it does tend to root the compositions in a particular key. Sometimes, depending upon the notes, the key may seem to shift and then revert back, but if we include unrelated accidentals in the scale we may hear too many dissonant sequences. Try it and see.
10 REM PROGRAM 11.2
20 REM Computer Composition
30 REM Based on Chord Sequences
40
50 MODE7
60
70 Scale$=" C C# D D# E F F# G
G# A A# B"
80 ChordRange$=" M 7 9 min mi
n6min7min9maj6maj7aug dim"
90
100 DIM NotesToChooseFrom$(11,6)
110
120 REM RESTORE To Requied Data
130 RESTORE 220
140 READ NoOfChords%
150
160 DIM Melody$(NoOfChords%)
170
180 FOR Tune=1 TO NoOfChords%
190 READ Melody$(Tune)
200 NEXT Tune
210
220 DATA 12
230 DATA C7,C7,C7,C7,F7,F7,C7,C7,G7,F7
,C7,G7
240
250 DATA 12
260 DATA C7,C9,C7,C9,F7,F9,C7,C9,G9,F9
,C9,G7
270
280 DATA 32
290 DATA Cmin,Cmin,G7,G7,G7,G7,Cmin
300 DATA Cmin,Cmin,Cmin,G7,G7,G7,G7
310 DATA Cmin,Cmin,Fmin,Fmin,Cmin,Cmin
320 DATA G7,G7,Cmin,Cmin,Fmin,Fmin
330 DATA Cmin,Cmin,G7,G7,Cmin,Cmin
340
350 DATA 16
360 DATA Amin7,D7,Gmaj6,Emin6,Gmin9,C7
370 DATA Fmaj7,Dmin6,Fmin7,G#min6
380 DATA Gmaj6,D#M,Cmin6,D7,Bmin,E7
390
400 RESTORE 1470
410 FOR N=1 TO 11
420 FOR C=1 TO 6
430 READ NotesToChooseFrom$(N,C)
440 NEXT C
450 NEXT N
460
470 ENVELOPE1,4,0,1,0,1,1,0,32,-2,0,-4
,126,100
480 ENVELOPE2,1,0,0,0,0,0,0,126,-4,-1,
-4,126,100
490 ENVELOPE3,4,0,0,0,0,0,0,106,-1,0,-
1,106,80
500 Env1%=2:Env2%=2:Env3%=3
510
520 PRINT''
530 PRINT"Please Enter Number of Beats
in Bar"
540 INPUT NoOfBeats%
550 PRINT"Please Enter Tempo (2 or gre
ater)"
560 INPUT Tempo1%
570 Tempo%=Tempo1%
580
590 PRINT"Do You Want Rhythm Variation
(Y/N)"
600 INPUT Sync$
610 IF Sync$="Y" OR Sync$="y" Sync=TRU
E ELSE Sync=FALSE
620
630 Comp=0
640 REPEAT
650
660 Comp=Comp+1
670 Col=128+(Comp MOD7)
680 PRINTTAB(2,10)CHR$Col;CHR$141;"Com
posing Opus 1 Variation ";Comp
690 PRINTTAB(2,11)CHR$Col;CHR$141;"Com
posing Opus 1 Variation ";Comp
700
710 FOR T%=1 TO NoOfChords%
720 SyncPoint=RND(4)
730 FOR Beat%=1 TO NoOfBeats%*2
740
750 IF Sync PROCSync
760 PROCPlay
770
780 NEXT Beat%
790 NEXT T%
800 UNTIL FALSE
810
820 END
830
840 DEF PROCPlay
850
860 PROCAnalyseChord
870 PROCGetNote(Note1$)
880 PROCPlayChord(&101,Env1%)
890 PROCGetNote(Note2$)
900 PROCPlayChord(&102,Env2%)
910 PROCBass(Key%+4)
920
930 ENDPROC
940
950 DEF PROCAnalyseChord
960 Chord$=Melody$(T%)
970 IF MID$(Chord$,2,1)="#" Key$=LEFT$
(Chord$,2):ChordType$=MID$(Chord$,3) ELS
E Key$=LEFT$(Chord$,1):ChordType$=MID$(C
hord$,2)
980 Key%=1+((INSTR(Scale$,Key$))/3-1)*
4
990 ChordNumber%=(INSTR(ChordRange$,Ch
ordType$))/4
1000
1010 Choice1%=RND(6)
1020 REPEAT
1030 Choice2%=RND(6)
1040 UNTIL Choice2%<>Choice1%
1050
1060 Note1$=NotesToChooseFrom$(ChordNum
ber%,Choice1%)
1070 Note2$=NotesToChooseFrom$(ChordNum
ber%,Choice2%)
1080 ENDPROC
1090
1100 DEF PROCGetNote(Note$)
1110 IF LEN(Note$)=2 THEN NoteName$=LEF
T$(Note$,1) ELSE NoteName$=LEFT$(Note$,2
)
1120 Octave%=VAL(RIGHT$(Note$,1))
1130 PositionInScale%=(INSTR(Scale$,Not
eName$))/3
1140 Pitch%=Key%+PositionInScale%*4+(Oc
tave%-1)*48
1150 IF Pitch%<0 OR Pitch%>255 PRINT"ER
ROR IN PITCH DATA ";Note$;" Pitch = ";Pi
tch%:STOP
1160 ENDPROC
1170
1180 DEF PROCPlayChord(Chan%,Env%)
1190 SOUNDChan%,Env%,Pitch%,Tempo%
1200 ENDPROC
1210
1220 DEF PROCBass(Pit%)
1230 IF ADVAL(-8)>0 SOUND3,Env3%,Pit%,T
empo%
1240 ENDPROC
1250
1260 DEF PROCSync
1270 REM GOTO Required Syncopation
1280 ON SyncPoint GOTO 1300,1370,1400,1
310
1290
1300 IF Beat%=1 Tempo%=Tempo1%*1.5 ELSE
IF Beat%=2 Tempo%=Tempo1%*.5 ELSE Tempo
%=Tempo1%
1310 ENDPROC
1320
1330 REM Out Of Sync
1340 IF Beat%=1 Tempo%=Tempo1%*2 ELSE I
F Beat%=2 Beat%=3 ELSE Tempo%=Tempo1%
1350 ENDPROC
1360
1370 IF Beat%=NoOfBeats% OR Beat%=NoOfB
eats%+1 Tempo%=Tempo1%*.5 ELSE IF Beat%=
1 Tempo%=Tempo1%*2 ELSE Tempo%=Tempo1%
1380 ENDPROC
1390
1400 IF Beat%=NoOfBeats% OR Beat%=NoOfB
eats%+1 OR Beat%=NoOfBeats%+2 OR Beat%=N
oOfBeats%+3 Tempo%=Tempo1%*.5:PROCPlay
1410 ENDPROC
1420
1430 IF Beat% MOD 2=1 Tempo%=Tempo1%*.7
5 ELSE IF Beat% MOD 2=0 Tempo%=Tempo1%*.
25
1440 ENDPROC
1450
1460 REM Major
1470 DATA G1,C2,E2,G2,C3,E3
1480
1490 REM Seventh
1500 DATA A#1,C2,E2,G2,A#2,C3
1510
1520 REM Major Ninth
1530 DATA D2,E2,G2,A#2,C3,D3
1540
1550 REM Minor
1560 DATA G1,C2,D#2,G2,C3,D#3
1570
1580 REM Minor 6th
1590 DATA A1,C2,D#2,G2,A2,C3
1600
1610 REM Minor 7th
1620 DATA A#1,C2,D#2,G2,A#2,C3
1630
1640 REM Minor Ninth
1650 DATA D2,D#2,G2,A#2,C3,D3
1660
1670 REM Major 6th
1680 DATA A1,C2,E2,G2,A2,C3
1690
1700 REM Major 7th
1710 DATA B1,C2,E2,G2,B2,C3
1720
1730 REM Augmented
1740 DATA G#1,C2,E2,G#2,C3,E3
1750
1760 REM Diminished
1770 DATA D#2,F#2,A2,C3,D#3,F#3
The program will prompt for the number of beats in a bar, tempo, and whether or not you want rhythmic variations. The compositions are based on a chord sequence resident in the DATA statements and the rhythm variations can be altered and ztdjusted within the program.
ChordRange$ at line 80 holds the available chords in much the same way that Scale$ holds the available notes. The program is supplied with details of the following chords:
The chord information is listed in DATA statements from line 1470 and relates to C chords. This information is adjusted for chords of other keys as we shall see. (See Chapter 2: Figure 2.11 illustrates some of the more common chords. )
There are two main ways you can alter the output other than varying the tempo and beats per bar values input. The first is through the selection of chords used in the tune which determines the overall harmonic progression of the piece and the second involves the complexity of the rhythmic variations you introduce.
The addition of rhythmic variations is a major part of the program and helps abolish the monotony of a sequence of quavers. The method used can be adapted to produce many varied rhythmic effects.
As you will have realised, the program produces a duophonic melody with a third note in the bass. The bass was introduced to reinforce the tonality of the chord, to provide a foundation for the tune and to add a little depth.
This chapter and Chapter 10 have both been looking at ways of controlling the random element in computer compositions. There must be a random element, otherwise there would be no original music, but we must be able to control it and shape it in order to produce the results we want.
The figures are based on rule of thumb and could be extended to cover at least one more octave. You could also include a B natural. Implementation of this set of rules will show a marked improvement in the melodic output but, if the choice of notes ranges over more than an octave, the melody will have a tendency to skip large intervals between notes, which is not common in normal composition. We can overcome this by applying another set of probability restrictions.
If you examine almost any piece of music, you will see that the melody line moves up and down the scale, usually a note or two at a time, and very seldom does it jump more than an interval of a fifth. (This is, again, a generalisation but applies to most classical music, a lot of jazz and many popular and standard songs.) Our program can jump the full range of available notes and will often cover intervals much larger than a fifth. This is the second way in which its melody production is not quite satisfactory. To this we can apply a set of probabilities in a similar way to the probabilities we gave to the notes of the scale.
Again, these figures should be used only as a starting point, and altered as results demand.
The bass notes can be controlled in two ways. First, their durations can be fixed to play four in a bar, ie four crotchets (or three in a bar if the piece was in 3/4 time, etc) and, secondly, you can restrict their choice of note. As the purpose of a bass line is to support a harmonic framework, if it is restricted to the root, fifth and possibly the third, the harmony will be reinforced. But by all means experiment.
Within the framework of rules set out above, you have scope to apply your own ideas. One thing to be aware of is not to ask the computer to get a note through the stepping procedure that it has been forbidden to get through the scale table. For example, if it was currently playing a 62 and it was ordered to move down a step, it may generate a percentage on the scale table which said that F2 is out of bounds. The overall note selection must take both these procedures into consideration. One way to do this would be to present the computer only with valid candidate notes to chose from.
If you do not have access to a musical instrument to prove this, you should easily be able to program your BBC micro to play through the cycle to confirm this harmonic behaviour. The Circle of Fifths is very useful in composition and shows how chord progressions tend to move.
The Note Analysis program in Chapter 10 produced an output which varied according to the note frequency of an existing tune. We can use existing tunes as an information base to produce a different output. One such method is to perform a mathematical operation upon the pitches representing the notes.
1 HiP=0:LoP=255
When the program has worked through the data, get the computer to print HiP and LoP in command mode and look up the notes in Figure 2.4.
855 Pitch=77+77-Pitch
F#2 with a pitch value of 77 has been taken as the pivot point. Try also 73 and 81.
855 Pitch=117+117-Pitch
and this for the Liberty Bell:
855 Pitch=85+85-Pitch
Again, try plus and minus four on the central values.
The duration values are the same, which is what makes the tunes half-recognisable, but you could apply a similar function to the duration values just to confuse your listeners.
As speech ROMs and voice production systems increase in variety and versatility, the day may not be too far off when such voices can be programmed with a pitch to enable production of a singing voice. If we could link a music composition program to a poetry generation program we would have the latest in singer-songwriters.Program notes
The array, Dice%, gives us five dice (0 to 4) to roll and Key$ stores 16 (0 to 15) notes. PROCSetScale initiates this and line 450 is used to set the data pointer to the scale of our choice. The notes fisted in lines 530 to 650 are sample scales for you to experiment with. You can alter these and add your own. The names are just for identification as the final output relies not only upon the scale but also upon the note durations and envelope parameters.
Line 300 allocates envelopes to each channel. Again, you can add to and alter each channel's envelopes as you wish.
Calculating the duration values
The permissible durations of a note are determined by the values of X1 and Y1. Cross-index them in Figure 11.1 to see some of the possible values and ranges which can occur. The actual durations which do occur are produced in the PROCPlay procedures. The other parameter, Dottedl, sets the probability that a note will be dotted, ie have its duration increased by half. If we look at lines 870 to 890 in PROCPlay1, we can examine a specific instance.
Lines 880 or 890 calculate the actual duration value depending upon the Xl and Y1 parameters. Refer to Figure 11.1 and try some examples and you will see how it works.
The REPEAT loop between lines 350 and 390 repeats the composition. The principle behind each channel's operation is the same. If there is room in the buffer, a new note is called through the PROCPlay procedures. As they are identical, we will only examine PROCPlay1.
The first thing it does is to call PROCRollDice at line 1140. This works on a percentage basis. You can alter line 1180 to determine how many 'dice' we roll and how often. The dice are assumed to be numbered 0 to 3, which will give us a value of from 0 to 15 to relate to the notes in Key$. Line 1200 will either roll one dice or call PROCRoll if more than one needs to be rolled. The dice are numbered 0 to 4.
PROCRoll at line 1240 runs through the required number of dice and allocates new random numbers to them in the range 0 to 3
PROCAddRolls at line 1300 runs through the Dice% array, adds up the total of the 'faces' and assigns it to the variable, Note'%. We are now back at line 850. The next fine calls PROCGetNote (at line 1410) with which you should now be familiar. Key$ is used to select our note.
PROCPrint at line 1370 prints out the note under the relevant channel heading and the process repeats.
Note line 1100 which plays channel 3 notes an octave lower than normal. This acts as a sort of bass which provides a tonal (providing the scale allows for a feeling of tonality) and rhythmic foundation.
Experimenting with the program
If you enter:
The note selections from line 530 onwards are important, too. The notes should be chosen so that they don't create a severe dissonance when sounded together. In general, a cluster of semitones will not produce musical results, but even notes a tone apart (and the odd semitone) will blend when played together, if the duration values are not too long.
The duration values themselves need a lot of consideration. Mixing an extreme selection will produce music which has no rhythmic base and this can be very firing for western ears. A regular four-in-a-bar bass line, such as that provided by channel 3, can be used to provide the listener with some sort of rhythmic foundation, even though the other channels may be going their own way.
ENVELOPE 1, the scale data at line 560 and the duration. parameters at line 740 will produce quite a hypnotic composition with a very eastern flavour.
You can try extending the scale range and altering the severity of the random selection. You could give each channel its own PROCRollDice for finer tuning of the melodic output.
Using chords as a compositional base
One way to broaden the output is to relate the choice of notes to particular chords and their relative constituent notes. Program 11.2 does this, and allows you to program the computer with any chord sequence and any chord type that you wish.
Program notes
M
= Major
7
= seventh (dominant seventh)
9
= Major Ninth
min
= Minor
min6
= Minor Sixth
min7
= Minor Seventh
min9
= Minor Ninth
maj6
= Major Sixth
maj7
= Major Seventh
aug
= Augmented
dim
= Diminished
The chord information is a list of notes which are included in the chord: it does not show how to construct a chord. The number has been arbitrarily restricted to six notes around octave 2 in Figure 2.4.
I have arranged the notes used to emphasise the dominant feature of the chord. For example, the pertinent feature of a minor ninth chord is the ninth and the notes in line 1650 have two ninths (D in this case for the key of C). The more complex a chord, the more notes of the scale it uses. The notes of the chords are read into the NotesToChooseFrom$ array in fines 400 to 450.
The melody is derived from the chord sequence held in DATA statements beginning at line 220. The first figure is the number of chords which is read into the variable, NoOfChords%, at line 140. The remainder of the data are chords which are read into Melody$ at line 190.
The NoOfBeats%, asked for at line 540 represents the number of beats per bar. This is doubled in line 730 to produce a composition based around eighth notes or quavers. For example, an entry of four will produce bars containing eight quavers.
The tempo is input at line 560. The rhythmic variations are produced by altering this input value, so it is also stored in a second variable, Tempo%.
Lines 670 to 690 produce a small screen display.
The REPEAT loop running from 640 to 800 controls the tune production. A tune will play through each chord in Melody$ once: this is controlled by line 710. Each chord lasts for the length of a bar. A bar consists of quavers equal to the number of beats in the bar (as assigned to the NoOfBeats% variable) multiplied by two.
If rhythmic variations have been selected, line 750 calls PROCSync (Sync for syncopation). Line 720 randomly selects one of four variations for one bar - unless it is selected again.
PROCPlay plays a single chord (comprised of three notes) of the tune and is called by fine 760. It has quite a lot of work to do, and tempo values of less than two will try to get hold of notes quicker than the BASIC program can supply them, causing uneven and hesitant results.
The first procedure called by PROCPlay is PROCAnalyseChord at line 950 which performs a similar analysis upon the chord to the one performed by our PROCAnalyseNote procedures on notes. The first thing it does is to look at the first two or three letters to find the key. The other letters are taken as the chord type. The key is calculated in the usual way at line 980, and line 990 gives us a chord number which simply shows how far along ChordRange$ it is. We then pick two different notes from the chord in fines 1010 to 1070 and end the procedure.
PROCGetNote at line 1100 is like the others in the book but it is called twice, once for each of the two notes we picked from the chord.
PROCPIayChord at line 1180 is called twice, too, and synchronizes the two notes so that they sound together.
The final act of PROCPlay is to call PROCBass at line 1220, which just sustains the root note of the chord, eg a C chord will produce a C bass note and a G# chord a G# bass note.
The last procedure is PROCSync at line 1260, which is only called if rhythmic variations have been asked for. If they have, this is called before every note to determine the duration - Tempo% as it is termed in this program. The variation in rhythm is produced by altering the value of Tempo%. according to the Beat% variable. Five examples are included and line 1280, along with line 720, selects the particular syncopation or variation for that bar.
Experimenting with the program
The data in lines 230 and 260 will play a 12 bar blues: the second set of data includes some ninth chords which produce a more jazzy feel. The data at fine 290 produces a chord sequence similar to that found on many electronic music albums and you may prefer the output here without any rhythm variations. The last set of data at line 360 is very jazzy and bluesy and works best with a slowish tempo and with variations. The use of minor ninth, minor sixth and major seventh chords produces some good jazz-style harmonies.
As the output is determined by the chords you put into the DATA statements, you have complete control over the chord progressions and you can experiment with whatever sequence of chords you wish. You can extend the range of chords by including new chord data at the end of the program. Insert the chord name in ChordRange$ at line 80 and increase the NotesToChooseFrom$ array at line 100 and the N variable at line 410 to suit. Be careful just exactly where in ChordRange$ you put the new chord name, eg if min6 came before min the program would return an incorrect chord number for min at fine 990 as it would find the min in min6 before arriving at the min we want.
For convenience, a major chord is represented by M. In standard notation a major chord, such as C or G#, will usually stand by itself. In our notation these would be CM and G#M. Giving every chord a symbol in this way simplifies PROCAnalyseChord.
For more variation, increase the number of notes allocated to each chord. This can simply be used to increase the range so that notes occur over, say, two octaves. More notes will also allow you to use more complex chords containing more than six notes. You can try substituting a complete scale for each chord. For example, CM would consist of a normal C scale. C7 would consist of an F major scale as it contains one flat, which is the key of F. Cmin would contain the notes of the D# (E flat) major scale. (Minor scales have been discussed in Chapter 2: you can mix harmonic and melodic scales as you wish.)
As the program picks notes from the chord at random, using complete scales may produce dissonant results. The principle of picking notes from the relevant scale used by the chords is another basis for tune production and we will look at some suggestions as to how this might be accomplished later in this chapter.
A value of four beats in the bar will produce music in 4/4 time and each chord will last for one bar. With a value of two, it will seem as if each chord lasts for half a bar, and so on. Actually, all we are doing is reducing the number of quavers in a bar, but by careful selection of this value and the chord data we can arrange an apparent change of chord at any point in the bar. You could arrange the envelopes so that the first beat of the bar sounds louder than the others.
Adding rhythmic variations
The variations are produced by PROCSync (assuming they are requested) and a look at the first example, at line 1300, will show how they work.
According to certain criteria which you set up - in this case the note number contained in Beat% - the duratlon of a note given by Tempo% is altered. Unless you want the bar to run out of sync, you must ensure that any extra time you give to one note is taken away from another. The example at line 1340 demonstrates what can happen when you don't. It still produces a good variation and keeps the listener on his toes because it is not obvious where the beat has gone. Too many out-of-sync rhythms may be too disorderly but one or two certainly add interest to a piece and are very effective.
If you look at the other examples in PROCSync, you will see how they work. The principle is easily adapted to produce almost any rhythm configuration you require. One aspect of the changes to be wary of is the eventual value of Tempo%. It will not hold a non-integer value. For example, the variation at fine 1430 will work with a Tempo1% value of four or eight but will otherwise produce strange results.
Instead of altering Tempo%, the variations could be stored in D AT A statements or in arrays. The above method, however, will adapt to whatever NoOfBeats% happens to be, although you could take this into account in any other system.
By setting more than one possible variation, which we have done, and by altering the sync pointer in line 720 and sync indicator in line 1280 the program will produce quite a varied output.
Further extensions and modifications
The two melody notes always have the same duration and could be altered so although they picked notes from the same chord, they would have independent durations. This would create a more truly polyphonic effect. The bass could also be given its own duration values and made to play, say, the root and fifth intervals of the chord. This would maintain the chord's tonality while providing yet more variation and interest.
To top it all, you could add channel 0 as a drum track.
As I mentioned earlier, there is another way of choosing notes from a scale relevant to a particular chord. In fact, there are probably many other ways to produce computerised music and several more chapters, if not books, could be written on the subject. However, so that computer composition does not dominate this book, and as we already have several programs to experiment with, I shall only discuss the principles of this method and leave you to work out the details. The programming should be only a little more complicated than the programs already listed.
Applying further control to random note selections
If you put complete scales into the DATA statements of Program 11.2, you will see that the results are quite different to those produced when we limited the choice to six notes (which would probably only contain three or four different notes). This is because the program is choosing the notes with equal probability. If you include eight notes in a scale, each note has a one-in-eight chance of being selected. This has two effects which detract from the melodic and harmonic effect.
First of all, the notes chosen are too random within any given harmonic framework, eg in most man-made compositions the melody over a Cmin chord will probably contain more C, G and D# notes than any others. (This is not always true but it is a fair assumption and it makes a good starting point.) In the program, all notes would be selected indiscriminately. Our first step, therefore, would be to arrange a probability table which gave more weight to notes which were in the chord or which were more likely to be heard with that chord.
Initially, for simplicity, we could ignore all accidentals. A probability table for the chord of Cmin might then look like this:
C2
20%
D2
5%
D#2
15%
F2
10%
G2
15%
G#2
10%
A#2
5%
C3
20%
Improving the melody
The most common interval jump is a scale step followed by two scale steps and three scale steps. If we measure melodic movement in scale steps we will avoid accidentals. A probability table for melodic intervals might then look like this:
+1
30%
-1
30%
+2
15%
-2
15%
+3
5%
-3
5%
When these two sets of rules are combined, you should see a tremendous improvement in the melodic output.
So far, we have not mentioned note durations. This is probably one of the most difficult areas of computer composition to program successfully. In such a program as that described, the best results will probably come from a pre-programmed set of note durations or simply a string of quavers. This will probably produce a Bach-like piece.
The output from a program like this would obviously be much improved if it played all three channels. As the two melody channels will be pursuing their own parts and as each output will be independent of the others (apart from their reliance on the common chord) you may well find that notes which may have tended to clash before seem to pass over one another as, for example, one channel plays a downward melody while the other pursues an upward path.
You can try restricting the secondary channel to playing the actual notes of the chord, to add support to the harmonic base.
Bass notes
Designing and developing programs
Like most computer programs and ideas, these compositional programs can be added to and developed. Here are some more ideas for further investigation. They are mentioned briefly simply as food for thought and as suggestions for further experiments. Detailed instructions and listings could quite easily consume the remaining pages of this book.
It would be interesting and useful to allow the operator or programmer to alter various parameters as the program is running. This could be accomplished by input from the keyboard or you could employ a more subjective form of control by allowing various parameters to be controlled by a joystick. This has fantastic possibilities as it would allow anyone to affect the way the music was being composed.
The User Guide provides details about joysticks and how to read values into the computer from them. The parameters you could control are key, tempo, rhythm variations and even the chords used. I shall describe one possible method of altering the chords.
There is a cycle of chord progressions known as the Circle of Fifths which is illustrated in Figure 11.2. Seventh chords, eg C7, have a tendency to want to move to the chord a fifth down the scale. So a C7 will want to move to an F, an E7 will want to move to an A# (Bb) the seventh of which will want to move to a D# (Eb), etc. The movement sounds satisfying, final and complete and so we say that a C7 chord resolves to F.
If movement of the joystick accessed the chords in a similar order to the circle (ie moving it right would move through C, F, A#, etc and if the joystick position was not exact, the change of key would not sound out of place as might be the case if the chords were arranged in chromatic (semitone) order. The purpose of joystick control is not necessarily to specify the exact chord, but rather to suggest a harmonic progression.
Once you (or rather, the computer) start to produce results you like, you may want to save them. All the programs fisted so far, apart from Program 10.1, are designed to play a continuous composition which is composed instantly, as the program runs. You could add a facility which would permit the computer to play a bar or a phrase (say four bars), then stop and ask if you wanted to save it. In this way you could build up a catalogue of the best of the BBC. Individual bars or phrases could be played again in any order you specify. The tune parameters would initially be stored in an array and later saved to tape or disk. (See the User Guide for details of file handling.)
The Amazing One Line Wonder Composer program
Notes and scales have a decidedly mathematical relationship with one another, and the computer provides an excellent means of rearranging notes according to mathematical rules. You can apply all sorts of mathematical functions to a set of notes to produce a wide range of results, but for simplicity only one example will be given here. This is the One Line Wonder, and reverses the pitch of the notes so that high notes will be played low and low notes will be played high. While it would be difficult to call the music produced by this example original (although what else can we call it?), the results are interesting and quite humorous. Other mathematical permutations will produce quite different results.
As we already have complete programs to play Mozart's Rondo, the Liberty Bell and the Dance of the Sugar-plum Fairy (from Chapter 9), we will try out our method on these. The first step is to find the highest and lowest notes in a piece and then find a central note around which these revolve. For example, if the highest and lowest notes were C4 and G#2, they would revolve around E3 which is half-way between the two. If you do not want to check through the music or DATA statements of a particular piece, you can find the highest and lowest notes by adding the following (to programs based on Program 9.2):
851 IF Pitch>HiP HiP=Pitch
852 IF Pitch<LoP LoP=Pitch
The central point does not have to be exact and you can offset it a little but, especially in multi-part tunes, you will probably find that an exact central pitch will play in tune better than offset values. Here is the fine to insert in Rondo:
For the Dance of the Sugar-plum Fairy insert:
The above example is very simple. Try modifying the notes with SIN and COS functions or an algebraic expression. You could also reverse the sequence of notes so that the tune plays backwards, or alter the Pitch values so that the music plays in steps of two (quarter tone intervals) instead of steps of four (semitone intervals). This should produce music with an eastern flavour.
In the music business, if a singer has a hit song, the writer is often asked to produce a follow-up. This will sometimes be a re-hash of the original song, using basically the same chord progressions and melodic movements although it is unlikely that the writers ever use a computer. No doubt you can think of lots of hits and follow-up singles which were very similar.
Sing-a-long-a-matic
Even if this technology is not available for the BBC micro - yet - we can still link a music program to a poetry generation program. At its simplest we could count the syllables in the verse and compose music with the same number of notes. Anyone lucky enough to have a speech system could let the computer talk the words over a musical background in the style of Leonard Cohen.
These suggestions are just the beginning. Computer compositions are one area in which relatively few experiments have been done. There is plenty of scope for new ideas.