home *** CD-ROM | disk | FTP | other *** search
- #
- # compufunk
- #
- # setup:
- # 3 voicelists
- # vco 1: bass voice
- # Determines overall harmonic structure. Current chord note
- # is stored in a global. Melody uses this to improvise off of.
- # There are two base forms. Both consist of various bass riffs
- # stored as procedural data (coded up). The first form has
- # very little improv. The second pieces its riffs together
- # in a random fashion.
- # vco 2: keyboard reader, maps a key to various changes
- # should be plugged into melody player channel at MIDI level
- # since various keys may change the melody patches.
- # vco 3: melody player, there are a number of melody forms. See
- # the key description. The melody follows the bass voice.
- # vco 4: optional double of melody code.
- #
- # various keys cause various transformations.
- #
- # Idea is to play bass and jam against it with solo instrument.
- # melody can be switched in and out, can play duet with it.
-
- #
- # harmonic structure:
- #
- # Two parts
- # 1. 8 bar melody lead. Melody plays horns in fifths and
- # uses fairly staid melody form.
- # 2. 12 bar blues form.
- # Harmonic structure is
- # E E E E A A E E C D E E
- # all minor 7th chords. Suggest using polytonality by
- # playing chord notes of minor 7th that is a fifth higher.
- #
-
- # key transformations
- #
- # a key: - force one round of "theme" 8 bar melody lead.
- # c key: - melody form 1. dorian/blues pentatonic random melody
- # d key: - turn melody generation OFF
- # e key: - melody form 2. pentatonic chords
- # f key: - melody form 3. "wave" melody, ascending arpeggios
- # g key: - melody form 4. fractal melody
- # h key: - melody form 5. dorian/polytonal melody (add a 7th sometimes)
- # p key: - enable random switches between patches for melody voice.
- # o key: - enable random switches between melody forms.
- # m key: - make random change on patch for melody - use melody patch set.
- # r key: - make random change on patch for melody - use rhythm patch set.
- # s key: - turn second melody on (toggle)
-
-
- #
- # constants
- #
- NOMODES = 4
- OCTAVE = 12
- FIFTH = 7
- PENTA = 5
- JAZZMINOR = 7
- MAXRHYTHM = 5 # random rhythmic patches to choose from
- MAXMEL = 15 # random melody patches to choose from
-
- ACHAR = 0x61
- BCHAR = 0x62
- CCHAR = 0x63
- DCHAR = 0x64
- ECHAR = 0x65
- FCHAR = 0x66
- GCHAR = 0x67
- HCHAR = 0x68
- ICHAR = 0x69
- JCHAR = 0x6a
- KCHAR = 0x6b
- LCHAR = 0x6c
- MCHAR = 0x6d
- NCHAR = 0x6e
- OCHAR = 0x6f
- PCHAR = 0x70
- QCHAR = 0x71 # don't use
- RCHAR = 0x72
- SCHAR = 0x73
-
-
- # global vars
-
- uchar mode # melody mode
- uchar chordbase # fundamental of current chord
- uchar pentascale[5]
- uchar minorscale[7]
- uchar solocount
- uchar basemode # bass harmonic/tempo mode
- uchar pkey # set if patch change desired
- uchar okey # set if mode changes should be automatic
- uchar lastnote
- uchar solo2on
- uchar solopatch
-
- uchar chordProg[12]
-
- # fb01 patch groups
- #
- uchar fbrhythm[MAXRHYTHM]
- uchar fbmelody[MAXMEL]
-
- # functions
-
- # setup fb01 patches to randomly choose from
- # all are bank 1
- #
- riff initpatch()
- fbrhythm[0] = 31 # steeldrum
- fbrhythm[1] = 32 # timpani
- fbrhythm[2] = 22 # xylo
- fbrhythm[3] = 43 # snare
- fbrhythm[4] = 45 # tomtom
-
- fbmelody[0] = 33
- fbmelody[1] = 34
- fbmelody[2] = 37
- fbmelody[3] = 38
- fbmelody[4] = 40
- fbmelody[5] = 41
- fbmelody[6] = 42
- fbmelody[7] = 2
-
- fbmelody[8] = 8
- fbmelody[9] = 9
- fbmelody[10] = 16
-
- fbmelody[11] = 18
- fbmelody[12] = 20
- fbmelody[13] = 7
- fbmelody[14] = 11
-
- end
-
- riff initHarmony()
- chordProg[0] = LE
- chordProg[1] = LE
- chordProg[2] = LE
- chordProg[3] = LE
- chordProg[4] = LA
- chordProg[5] = LA
- chordProg[6] = LE
- chordProg[7] = LE
- chordProg[8] = LC
- chordProg[9] = LD
- chordProg[10] = LE
- chordProg[11] = LE
- end
-
- riff init()
- pentascale[0] = 3
- pentascale[1] = 5
- pentascale[2] = 7
- pentascale[3] = 10
- pentascale[4] = 12
-
- minorscale[0] = 2
- minorscale[1] = 3
- minorscale[2] = 5
- minorscale[3] = 7
- minorscale[4] = 9
- minorscale[5] = 10
- minorscale[6] = 12
- end
-
- riff choosetwo(t1,t2)
- if ( mrand() < 127 )
- return(t1)
- else
- return(t2)
- end
- end
-
- ########################################
- # base melody fragments
- #
-
- # helper function for below b1, simple variation
- riff subb1()
- LE tq 105
- LE te 90
- E tq choosetwo(105,100)
- LE te 90
- D tq choosetwo(105,100)
- LE te 90
- E tq choosetwo(105,100)
- LB te 94
- # m2
- LE tq choosetwo(110,105)
- LE te
- E q choosetwo(105,95)
- LD tq choosetwo(100,90)
- LB te 90
- if ( mrand() < 120 )
- LD tq 100
- LB te 90
- else
- LA tq 100
- LG te 90
- end
- end
-
- # 2 measures
- riff b1(base)
- chordbase = base
- if ( base == LE && mrand() < 50 )
- void subb1()
- return(1)
- end
- if ( mrand() < 50 )
- base q mrandrange(115,121)
- else
- base tq mrandrange(115,117)
- base te 90
- end
- base+12 q 100
- base+10 h mrandrange(90,100)
- # m2
- base q mrandrange(110,117)
- base+12 q 100
- #
- base+10 tq mrandrange(90,110)
- base+7 te 100
- # m2, b4
- base+5 tq 100
- if ( mrand() < 100 )
- base+3 te 100
- else
- base+3 te 90
- end
- end
-
-
- # similar to b1, but only a measure long
- riff b5(base)
- chordbase = base
- base q 120
- base+12 q 100
- if ( mrand() < 100 )
- base+10 h 100
- else
- base+10 tq mrandrange(115,100)
- base+10 te 90
- base+7 q
- end
- end
-
- # second measure of b1
- riff b6(base)
- chordbase = base
- base q 115
- base+12 q 100
- base+10 tq 105
- base+7 te 100
- base+5 tq 100
- base+3 te 100
- end
-
- # 1 measure
- riff b3(base)
- chordbase = base
- base tq mrandrange(90,115)
- base te mrandrange(80,95)
- base+12 tq mrandrange(90,105)
- base+12 te 85
- base+10 te 105
- base+12 te 90
- base+10 te
- base+5 te 105
- base+7 te
- base+10 te
- end
-
- #1 measures
- riff b4(base)
- chordbase = base
- base+12 tq 110
- base+12 te 100
- base+3 tq 105
- base+3 te 100
- base+5 tq 110
- base+5 te 100
- base+7 tq 110
- base+7 te 100
- end
-
- riff b7(base)
- chordbase = base
- base tq 110
- base te 90
- base+3 tq 105
- base+3 te 90
- base+5 tq 100
- base+5 te 107
- base+7 tq mrandrange(110,115)
- base+7 te 100
- end
-
- riff specialB()
- chordbase = LC
- LC q 110
- LC+12 q 100
- LC+10 h 95
- chordbase = LD
- LD q 110
- LD+12 q 90
- LD+10 tq 105
- LD+7 te 100
- LD+5 tq 100
- LD+3 te 100
- end
-
- # end of bass melody fragments
- #
-
- riff solotime()
- if ( {mrand()%2} == 0 )
- return(tq)
- else
- return(te)
- end
- end
-
-
- riff choosethree(t1,t2,t3)
- uchar rno
- rno = mrand()
- if ( rno < 85 )
- return(t1)
- end
- if ( rno < 170 )
- return(t2)
- end
- return(t3)
- end
-
- #
- # choose a note out of one of the two scales
- # add an octave to base to get note up into middle range
- #
- riff solonote()
- uchar index
-
- if ( {solocount % 4} < 2)
- return(pentascale[mrand()%PENTA]+ OCTAVE + chordbase)
- else
- return(minorscale[mrand()%JAZZMINOR] + OCTAVE + chordbase)
- end
- end
-
- #
- # play so many measures of solo melody
- #
- riff dosolo()
- uchar mcount
- uchar time
- uchar solocount
- uchar tcount
- uchar nnote
- uchar vel
-
- solocount++
- if ( mode == 5 )
- solopatch = 0
- patch 0
- end
- for ( mcount = 0; mcount < 6; mcount++)
- # check to see if random mode changes are
- # desired
- if ( mcount == 3 && okey )
- mode = {mrand() % NOMODES} + 1
- end
- for ( tcount = 0; tcount < w; )
- time = solotime()
- if ( mode == 1 )
- solonote() time mrandrange(90,115)
- else
- if ( mode == 2 )
- vel = mrandrange(90,120)
- nnote = solonote()
- if ( mrand() < 150 )
- chord nnote,nnote+12,nnote+24 end time + 12
- else
- chord nnote,nnote+7,nnote+12,nnote+14,nnote+24 end time + 12
- end
- time = time + 12
- else # mode is 3
- if ( mode == 3 )
- nnote = solonote()
- vel = mrandrange(80,110)
- nnote s vel
- nnote + 2 t vel + 2
- nnote + 5 s vel + 4
- nnote + 7 t vel + 6
- nnote + 12 s vel + 8
- nnote + 17 t vel + 10
- nnote + 19 s vel + 12
- nnote + 24 t vel + 14
- else # mode is 4, fractal melody
- if ( mode == 4 )
- lastnote = mfractal1(lastnote)
- vel++
- if ( vel > 115 )
- vel = 85
- end
- chordbase+pentascale[lastnote%PENTA]+24 choosethree(s,e,h) vel
- else # mode is 5, basemode special melody
- if ( mode == 5 )
- if ( solopatch != 0 )
- patch 0
- solopatch = 0
- end
- nnote = solonote()
- time = solotime()
- vel = mrandrange(100,120)
- chord nnote,nnote+7 end time vel
- # mode 6, venture into polytonal up a 5th
- else
- if ( mrand() < 190 )
- nnote = solonote() + 7
- else
- nnote = solonote()
- end
- nnote solotime() mrandrange(90,120)
- end
- end
- end
- end
- end
- tcount = tcount + time
- end
- end
- # if pkey set however random changes 1..33
- if ( pkey )
- solopatch = {mrand() % 32} + 1
- patch solopatch
- end
- end
-
- # first baseform
- # not much variation in riffs
- #
- riff baseform1()
- void b1(LE)
- void b1(LE)
- void b1(LA)
- void b1(LE)
- if ( mrand() < 200 )
- void specialB()
- else
- void b1(LB)
- end
- void b1(LE)
- end
-
- # in charge of varying the bass melody
- #
- riff baseform2()
- uchar rval
- uchar chordindex
- uchar lastval
-
- lastval = 1
- for ( chordindex = 0; chordindex < 12; chordindex++)
- rval = mrand() % 5
- # try again if riff number matches, should reduce
- # frequency of repeats
- if (lastval == rval)
- rval = mrand() % 5
- end
-
- if ( rval == 1 )
- void b3(chordProg[chordindex])
- else
- if ( rval == 2 )
- void b4(chordProg[chordindex])
- else
- if ( rval == 3 )
- void b5(chordProg[chordindex])
- else
- if ( rval == 4 )
- void b6(chordProg[chordindex])
- else
- void b7(chordProg[chordindex])
- end
- end
- end
- end
- lastval = rval
- end # for
- end
-
- ######################################################
- # VOICELISTS
- ###################
- #
- # bass is first voice.
- #
- # determines harmonic structure.
- # The base tone of the current chord is saved by any routines
- # called by the "bass" voicelist. Melody generation uses this
- # to generate melodic fragments.
- #
- vco bass
- uchar index
- uchar firstcall
-
- okey = 0
- pkey = 0
- mode = 0 # solo starts off
- basemode = 1
- solocount = 0
- lastnote = LE
- void init()
- void initHarmony()
- void initpatch()
- firstcall = 1
-
- # now start to play bass variations unless n key is
- # typed.
- # 'n' means normal form again
- for (;;)
- # if basemode is set then play 8 bar "line"
-
- if ( basemode )
- mode = 5
- void b1(LE)
- void b1(LG)
- void b1(LA)
- void b1(LE)
- void b1(LE)
- void b1(LC)
- void b1(LD)
- void b1(LE)
- mode = 4
- basemode = 0
- # else normal improv section
- else
- if ( firstcall )
- firstcall = 0
- void baseform1()
- else
- # small percent of normal base playing
- if ( mrand() < 10 )
- void baseform1()
- else
- # great deal of improv base playing
- void baseform2()
- end
- end
- end
- end
- end
-
- #
- # check the keyboard
- # if a char is received turn on the solo channel
- # or turnoff the solo if it is playing
- #
- vco readKey
-
- uchar input
- uchar patchVal
-
- #
- # check every quarter note
- for(;;)
- if (misch())
- input = mgetch()
- if ( input == ACHAR )
- void printf("%d\n",1)
- basemode = 1
- okey = 0
- pkey = 0
- end
- if ( input == CCHAR )
- mode = 1
- end
- if ( input == DCHAR )
- mode = 0
- end
- if ( input == ECHAR )
- mode = 2
- end
- if ( input == FCHAR )
- mode = 3
- end
- if ( input == GCHAR )
- mode = 4
- end
- if ( input == HCHAR )
- mode = 6
- end
- if ( input == PCHAR )
- pkey = ~pkey # toggle
- void printf("%d\n",pkey)
- end
- if ( input == OCHAR )
- okey = ~okey # toggle
- void printf("%d\n",okey)
- end
- # random change of melody patch
- if ( input == MCHAR )
- solopatch = fbmelody[mrand()%MAXMEL]-1
- patch solopatch
- end
- # random change to rhythm patch
- if ( input == RCHAR )
- solopatch = fbrhythm[mrand()%MAXRHYTHM]-1
- patch solopatch
- void printf("%d\n",patchVal)
- end
- if ( input == SCHAR )
- solo2on = ~solo2on
- end
- else
- REST q
- end
- end
- end
-
- #
- # play a solo when mode is non-zero
- #
- vco solo
- for(;;)
- if ( mode )
- void dosolo()
- else
- REST w
- end
- end
- end
-
- # optional double of solo voice
- #
- vco solo2
- solo2on = 0
-
- for(;;)
- if ( solo2on )
- void dosolo()
- else
- REST w
- end
- end
- end
-
-