' Fuga Falafel ' ' Kopyleft Kristof Lauwers 20031104 ' ' algorithmic fugue, written in in ' for '________________________________________ %fg_v0 = 17 %fg_v1 = %fg_v0 + 1 %fg_v2 = %fg_v1 + 1 %fg_v3 = %fg_v2 + 1 %fg_v4 = %fg_v3 + 1 %fg_vAll = %fg_v4 + 2 %FG_Mute = 0 %FG_Subject = &B100 %FG_Spiegel = &B001 %FG_KREEFT = &B010 %FG_CounterSubject = &B1000 %FG_CounterSubject2 = &B10000 %FG_FreeForm = &H20 %FG_notify = -1000 'for fg_nextstate: means we shoudln't start a new theme, just notification that countersubject couldn't find a note to play '%usesoundcard = 1 #IF NOT %DEF(%kl_dbg_logfile) #INCLUDE "C:\b\pb\gmt\kristof\kl_debug.inc" ' GLOBAL insdbg AS LONG #ENDIF GLOBAL insdbg AS LONG TYPE pattype noot AS INTEGER vel AS INTEGER '0 for rest ' percent of max for voice / max for voice @ fugastuff.scaline duur AS SINGLE 'ms END TYPE TYPE fugastuff scaling AS pattype ' noot as offset, vel as max(inifile), duur as multiplier instrum AS musician thcount AS LONG 'counter within theme, backwarths for inversion, -1 if not playing a theme nextstateoncount AS LONG 'for stretto's: if this note in pattern reached, call nextstate -this lastnote AS INTEGER stat AS INTEGER END TYPE GLOBAL fg_voice() AS fugastuff GLOBAL globstat AS INTEGER 'pos: expositie n; neg: divertimento n GLOBAL fg_theme() AS pattype 'them of fuga GLOBAL fg_order AS STRING 'order in wich voices get theme in exposition GLOBAL centralnote AS LONG GLOBAL maxfreq AS SINGLE GLOBAL neck2neck AS LONG 'for last stretto only.. DECLARE FUNCTION fg_init AS LONG DECLARE SUB fg_voice_doevents(BYVAL this AS LONG, OPT BYVAL tijd AS SINGLE) DECLARE SUB fg_nextstate(this AS LONG) DECLARE FUNCTION nextstate_doBasics(cnt AS LONG, newstat AS LONG) AS LONG DECLARE FUNCTION fg_readinifile AS LONG DECLARE SUB fg_v0 DECLARE SUB fg_v1 DECLARE SUB fg_v2 DECLARE SUB fg_v3 DECLARE SUB fg_v4 DECLARE SUB fg_vAll DECLARE SUB fg_monitor(this AS LONG) DECLARE SUB FG_Silence(OPT BYVAL i AS LONG) MACRO BoundNote(noot, instrum) DO WHILE noot < instrum.lowtes: noot = noot + 12: LOOP DO WHILE noot > instrum.hightes: noot = noot - 12: LOOP END MACRO FUNCTION fg_init AS LONG LOCAL i AS LONG IF ISFALSE fg_readinifile THEN EXIT FUNCTION MSGBOX "wind harma aanzetten!?",,FUNCNAME$ 'create debug window insdbg = kl_debug(0, "fugue debug window") kl_debug %kl_dbg_size, STR$(insdbg)+", 20, 20, 250, 300" kl_debug %kl_dbg_logfile, STR$(insdbg) + ", c:\b\pb\gmt\kristof\FUGUEDEBUG.log" 'init tasks task(%fg_v0).naam = "v0": task(%fg_v0).freq = 1: task(%fg_v0).flags = 0: task(%fg_v0).cptr = CODEPTR(fg_v0) task(%fg_v1).naam = "v1": task(%fg_v1).freq = .5: task(%fg_v1).flags = 0: task(%fg_v1).cptr = CODEPTR(fg_v1) task(%fg_v2).naam = "v2": task(%fg_v2).freq = .5: task(%fg_v2).flags = 0: task(%fg_v2).cptr = CODEPTR(fg_v2) task(%fg_v3).naam = "v3": task(%fg_v3).freq = .5: task(%fg_v3).flags = 0: task(%fg_v3).cptr = CODEPTR(fg_v3) task(%fg_v4).naam = "v4": task(%fg_v4).freq = .5: task(%fg_v4).flags = 0: task(%fg_v4).cptr = CODEPTR(fg_v4) task(%fg_vAll).naam = "Sinc": task(%fg_vAll).freq = 200: task(%fg_vAll).flags = 0: task(%fg_vAll).cptr = CODEPTR(fg_vAll) 'init fuga type specific params fg_order = CHR$(0, 1, 2, 3, 4) 'permutate after first exposition globstat = 1 ' fg_voice(%fg_v0).scaling.noot = 0 FOR i = %fg_v0 TO %fg_v4 fg_voice(i).scaling.duur = .5 '1 fg_voice(i).thcount = -1: fg_voice(i).nextstateoncount = -2 fg_voice(i).scaling.noot = (fg_voice(i).instrum.lowtes + fg_voice(i).instrum.hightes) / 2 + 2 IF UCASE$(TRIM$(fg_voice(i).instrum.naam)) = "PIPEROLA" THEN fg_voice(i).instrum.ctrl(7)= 100 : Piperolawind fg_voice(i).instrum ', 100 'panicbutton ButnOS(1 + i - %fg_v0).tag = "Off" + fg_voice(i).instrum.naam ButnOS(1 + i - %fg_v0).cptr = CODEPTR(fg_silence) '%False NEXT centralnote = fg_voice(%fg_v0).scaling.noot ModeMess 10, 64, 1 'dampers off #IF %DEF(%usesoundcard) 'for debug without instruments fg_voice(%fg_v1).instrum.channel= 2 #ENDIF FUNCTION = 1 END FUNCTION FUNCTION fg_readinifile AS LONG LOCAL f AS LONG LOCAL b$ LOCAL i AS LONG LOCAL ub AS LONG ub = 13 DIM fg_theme(ub) DIM fg_voice(%fg_v0 TO %fg_v4) ERRCLEAR f = FREEFILE OPEN "c:\b\pb\gmt\kristof\fugue\fugue.dat" FOR INPUT ACCESS READ LOCK WRITE AS f IF ERRCLEAR THEN EXIT FUNCTION DO UNTIL EOF(f) LINE INPUT #f, b$ b$ = TRIM$(PARSE$(b$, "'", 1)) IF b$ = "[EOF]" THEN EXIT LOOP SELECT CASE UCASE$(b$) CASE "[PATTERN]" DO UNTIL EOF(f) LINE INPUT #f, b$ b$ = TRIM$(PARSE$(b$, "'", 1)) IF b$ = "[END_PATTERN]" THEN EXIT LOOP IF b$="" THEN ITERATE LOOP SELECT CASE TRIM$(UCASE$(PARSE$(b$, ":", 1))) CASE "NOOT" b$ = PARSE$(b$, ":", 2): FOR i = 1 TO ub + 1: fg_theme(i-1).noot = VAL(PARSE$(b$, ",", i)): NEXT CASE "VEL" b$ = PARSE$(b$, ":", 2): FOR i = 1 TO ub + 1: fg_theme(i-1).vel = VAL(PARSE$(b$, ",", i)): NEXT CASE "DUUR" b$ = PARSE$(b$, ":", 2): FOR i = 1 TO ub + 1: fg_theme(i-1).duur = VAL(PARSE$(b$, ",", i)): NEXT END SELECT LOOP CASE "[VOICES] DO UNTIL EOF(f) LINE INPUT #f, b$: b$ = TRIM$(PARSE$(b$, "'", 1)) IF b$ = "[END_VOICES]" THEN EXIT LOOP IF b$="" THEN ITERATE LOOP SELECT CASE UCASE$(TRIM$(PARSE$(b$, ":", 1))) CASE "ID": i = VAL(PARSE$(b$, ":", 2)) CASE "INSTRUM" GetInstrumentParams fg_voice(i).instrum, VAL(PARSE$(b$, ":", 2)) #IF NOT %DEF(%usesoundcard) SetRobotPort fg_voice(i).instrum, "", hMidiO() #ENDIF CASE "MAXVEL": fg_voice(i).scaling.vel = VAL(PARSE$(b$, ":", 2)) CASE "" 'do nothing CASE ELSE: MSGBOX "unknown entry in [voices]@nifile:" + b$,, FUNCNAME$ END SELECT LOOP END SELECT LOOP CLOSE f IF ISFALSE fg_theme(ub).duur OR ISFALSE fg_voice(%fg_v4).instrum.channel THEN MSGBOX "fatal error reading inifile",, FUNCNAME$: EXIT FUNCTION 'bsic check.. b$ = "" FOR i = %fg_v0 TO %fg_v4 SELECT CASE UCASE$(TRIM$(fg_voice(i).instrum.naam)) CASE "TUBI": fg_voice(i).instrum.lowtes = 72: fg_voice(i).instrum.minvel = 24 CASE "PLAYPIAN": fg_voice(i).instrum.minvel = 22 CASE "VIBI": fg_voice(i).instrum.minvel = 20 CASE "PIPEROLA" fg_voice(i).instrum.lowtes = 36: fg_voice(i).instrum.hightes = 100 fg_voice(i).instrum.ctrl(7) = 100 PiperolaWind fg_voice(i).instrum CASE "HARMA": Progchange fg_voice(i).instrum.channel, 15: Modemess fg_voice(i).instrum.channel, 7, 100 CASE ELSE END SELECT ' b$ = b$ + STR$(i) + fg_voice(i).instrum.naam +STR$(fg_voice(i).instrum.lowtes) + STR$(fg_voice(i).instrum.hightes) NEXT FUNCTION = 1 END FUNCTION SUB fg_voice_doevents(BYVAL this AS LONG, OPT BYVAL tijd AS SINGLE) LOCAL i AS INTEGER LOCAL j AS INTEGER LOCAL noot AS BYTE LOCAL avrfreq AS SINGLE STATIC init AS LONG LOCAL f AS SINGLE LOCAL lh AS harmtype STATIC leakyvel() AS SINGLE LOCAL vel() AS INTEGER 'BYTE LOCAL llvel() AS SINGLE 'temp copy of leakyvel IF ISFALSE init THEN init = 1 fg_voice(%fg_v0).stat = %FG_SUBJECT: fg_voice(%fg_v1).stat = %FG_SUBJECT DIM leakyvel(127) 'leakymax of all instrum.har(0) velocities EXIT SUB END IF DIALOG DOEVENTS REDIM vel(127): REDIM llvel(127) ' fg_monitor FOR i = %fg_v0 TO %fg_v4: avrfreq = avrfreq + task(i).freq: NEXT avrfreq = avrfreq / 5 SELECT CASE fg_voice(this).stat CASE %FG_Subject INCR fg_voice(this).thcount IF fg_voice(this).thcount > UBOUND(fg_theme) THEN GOTO ThFinished noot = fg_theme(fg_voice(this).thcount).noot + fg_voice(this).scaling.noot BoundNote(noot, fg_voice(this).instrum) fg_voice(this).lastnote = noot AddNote2Har fg_voice(this).instrum.har(1), noot,_ MAX(fg_voice(this).instrum.minvel, fg_theme(fg_voice(this).thcount).vel * fg_voice(this).scaling.vel / 100) task(this).freq = fg_voice(this).scaling.duur /fg_theme(fg_voice(this).thcount).duur CASE %FG_Spiegel INCR fg_voice(this).thcount IF fg_voice(this).thcount > UBOUND(fg_theme) THEN GOTO ThFinished noot = - fg_theme(fg_voice(this).thcount).noot + fg_voice(this).scaling.noot BoundNote(noot, fg_voice(this).instrum) fg_voice(this).lastnote = noot AddNote2Har fg_voice(this).instrum.har(1), noot ,_ MAX(fg_voice(this).instrum.minvel, fg_theme(fg_voice(this).thcount).vel * fg_voice(this).scaling.vel / 100) task(this).freq = fg_voice(this).scaling.duur /fg_theme(fg_voice(this).thcount).duur 'fg_theme(fg_voice(this).thcount).duur / fg_voice(this).scaling.duur CASE %FG_Kreeft DECR fg_voice(this).thcount IF fg_voice(this).thcount < LBOUND(fg_theme) THEN GOTO ThFinished noot = fg_theme(fg_voice(this).thcount).noot + fg_voice(this).scaling.noot BoundNote(noot, fg_voice(this).instrum) fg_voice(this).lastnote = noot AddNote2Har fg_voice(this).instrum.har(1), fg_theme(fg_voice(this).thcount).noot + fg_voice(this).scaling.noot,_ MAX(fg_voice(this).instrum.minvel, fg_theme(fg_voice(this).thcount).vel * fg_voice(this).scaling.vel / 100) task(this).freq = fg_voice(this).scaling.duur /fg_theme(fg_voice(this).thcount).duur CASE %FG_Kreeft OR %FG_Spiegel DECR fg_voice(this).thcount IF fg_voice(this).thcount < LBOUND(fg_theme) THEN GOTO ThFinished noot = -fg_theme(fg_voice(this).thcount).noot + fg_voice(this).scaling.noot BoundNote(noot, fg_voice(this).instrum) fg_voice(this).lastnote = noot AddNote2Har fg_voice(this).instrum.har(1), fg_voice(this).scaling.noot - fg_theme(fg_voice(this).thcount).noot ,_ MAX(fg_voice(this).instrum.minvel, fg_theme(fg_voice(this).thcount).vel * fg_voice(this).scaling.vel / 100) task(this).freq = fg_voice(this).scaling.duur /fg_theme(fg_voice(this).thcount).duur CASE %FG_Countersubject 'note selection from hist buffer leakyvel 'criterium = melodic intervals for this voice POKE$ VARPTR(llvel(0)), PEEK$(VARPTR(leakyvel(0)), SIZEOF(leakyvel(0)) *(UBOUND(leakyvel) + 1)) FOR i = 1 TO 127: vel(i) = i: NEXT ARRAY SORT llvel(), TAGARRAY vel(), DESCEND IF llvel(0) < 8 THEN fg_nextstate %fg_notify: GOTO speelhet FOR i = 1 TO 7 '3 TO 7 IF llvel(i) < 6 THEN EXIT FOR SELECT CASE ABS(fg_voice(this).lastnote - vel(i)) CASE 2, 3, 11, 14, 15, 23: GOTO sel2ok END SELECT NEXT FOR i = 1 TO 7 '3 TO 7 IF llvel(i) < 6 THEN EXIT FOR SELECT CASE ABS(fg_voice(this).lastnote - vel(i)) CASE 5, 6, 8, 10, 17, 18, 20, 22, 29 : GOTO sel2ok END SELECT NEXT FOR i = 1 TO 7 '3 TO 7 IF llvel(i) < 6 THEN EXIT FOR SELECT CASE ABS(fg_voice(this).lastnote - vel(i)) CASE 1, 4, 9, 13, 16, 25 : GOTO sel2ok END SELECT NEXT FOR i = 1 TO 7 '3 TO 7 IF llvel(i) < 6 THEN fg_nextstate %fg_notify: GOTO speelhet IF fg_voice(this).lastnote MOD 12 <> vel(i)MOD 12 THEN GOTO sel2ok NEXT sel2ok: IF i < 0 THEN GOTO speelhet 'no note to play leakyvel(vel(i)) = leakyvel(vel(i)) * .6 '.66 '.7 vel(i) = fg_voice(this).scaling.noot + vel(i) MOD 12 fg_voice(this).lastnote = vel(i) BoundNote (vel(i), fg_voice(this).instrum) AddNote2Har fg_voice(this).instrum.har(1), vel(i), _ MIN(fg_voice(this).scaling.vel, MAX(fg_voice(this).instrum.minvel, _ fg_theme(fg_voice(this).thcount).vel * fg_voice(this).scaling.vel / 100)) 'new freq, exp rescaled average of all task freqs ' f = 2.2 * SQR(avrfreq) - .6 f = 2.2 * (avrfreq)^.4 - 1 task(this).freq = MIN(3, MAX(.2, task(this).freq + 2.5 * (f - task(this).freq))) '2.5 was 3 IF avrfreq < .21 THEN task(this).freq = task(this).freq + .5 'the above two rules replace:: task(this).freq = MAX(.3, 2.2 * SQR(f/5) - 1) CASE %FG_Mute : Stoptask this CASE ELSE MSGBOX "invalid stat" + BIN$(fg_voice(this).stat) + "@ "+STR$(this) END SELECT speelhet: SELECT CASE UCASE$(TRIM$(fg_voice(this).instrum.naam)) CASE "HARMA" modemess fg_voice(this).instrum.channel, 7, MAX(15, .7 * SQR(ABS(SIN(llvel(i) * .0628))) * fg_voice(this).scaling.vel) CASE "PIPEROLA" fg_voice(this).instrum.ctrl(7) = MAX(15, .6 * SQR(ABS(SIN(llvel(i) * .0628))) * fg_voice(this).scaling.vel) piperolawind fg_voice(this).instrum CASE "VIBI" lh.vel = fg_voice(this).instrum.har(1).vel Transharm lh, 12 fg_voice(this).instrum.har(1).vel = Sumhar(fg_voice(this).instrum.har(1), lh) Transharm lh, -24 fg_voice(this).instrum.har(1).vel = Sumhar(fg_voice(this).instrum.har(1), lh) END SELECT InstrumPlay fg_voice(this).instrum IF fg_voice(this).nextstateoncount = fg_voice(this).thcount THEN fg_nextstate -this 'stretto '+ send wind to harma.. 'update leaky strongest notes IF fg_voice(this).stat <> %FG_COUNTERSUBJECT AND fg_voice(this).stat <> %FG_COUNTERSUBJECT2 THEN FOR i = 1 TO 127: leakyvel(i) = MAX( leakyvel(i), ASC(MID$(fg_voice(this).instrum.har(0).vel, i, 1)) * 100 / fg_voice(this).scaling.vel ): NEXT leakyvel(fg_voice(this).scaling.noot) = leakyvel(fg_voice(this).scaling.noot)/2 END IF IF neck2neck THEN fg_nextstate 0 fg_monitor this EXIT SUB ThFinished: fg_voice(this).thcount = -1 fg_nextstate this fg_monitor this END SUB SUB fg_nextstate(this AS LONG) STATIC mastercount AS LONG, interncount AS LONG LOCAL i AS LONG LOCAL nxt AS LONG IF ISFALSE mastercount THEN mastercount = 1: interncount = 1 'change status for this voice 'if this < 0 we're in a stretto - don't change status for this, only start new 'set status for next voice 'if no next voice: start next divertimento 'set new fg_voice.scaling.duur 'set scaling for next voice 'set count for next voice: -1 or max for subj resp kreeft, -1 for countersubj 'set countersubjects SELECT CASE mastercount CASE 1 'exposition 1 INCR interncount IF interncount > 5 THEN 'prepare for and goto divertimento 1 fg_voice(this).stat = %FG_COUNTERSUBJECT fg_voice(%fg_v0).stat = %FG_COUNTERSUBJECT FOR i = %fg_v0 TO %fg_v4 centralnote = 60 + 2 * i - 2 * %fg_v0: boundnote(centralnote, fg_voice(i).instrum) fg_voice(i).scaling.noot = centralnote: fg_voice(i).lastnote = centralnote task(i).freq = .7 NEXT task(%FG_v1).freq = 5 interncount = 0: INCR mastercount ELSE fg_voice(this).stat = %FG_COUNTERSUBJECT centralnote = centralnote + 7 nxt = nextstate_dobasics(interncount, %FG_SUBJECT) task(nxt).freq = 20 IF interncount > 2 THEN fg_voice(%FG_V0 + ASC(MID$(fg_order, interncount - 2, 1))).stat = %FG_COUNTERSUBJECT StartTask nxt END IF CASE 2 'divertimento 1 INCR interncount ' here we het this = %fg_notify == no note to play for countersubj IF interncount > 4 THEN fg_order = CHR$(4, 3, 0, 1, 2) 'permutate after first exposition FOR i = %fg_v0 TO %fg_v4 fg_voice(i).scaling.duur = .3 fg_voice(i).thcount = -1 task(i).freq = .2 * SQR((1 + i - %FG_v0)) AddNote2Har fg_voice(i).instrum.har(1), fg_voice(i).scaling.noot - 1, MAX(fg_voice(i).instrum.minvel, fg_voice(i).scaling.vel / 3) InstrumPlay fg_voice(i).instrum NEXT fg_voice(%fg_v4).nextstateoncount = 8: fg_voice(%fg_v1).nextstateoncount = 8 centralnote = centralnote - 6 interncount = 0: INCR mastercount END IF CASE 3 'exposition 2 - per 2 voice stretto on 2/3rd - with spiegel IF (interncount > 0) AND (interncount<8) AND (this <= %fg_notify) THEN EXIT SUB INCR interncount centralnote = centralnote -7 SELECT CASE interncount CASE 1: nextstate_dobasics interncount, %FG_SUBJECT 'stem 1 thema (params: count in fg_order, type of exp) CASE 2: nextstate_dobasics interncount, %FG_SPIEGEL 'stretto fg_order.1 & fg_order.2 CASE 3: fg_voice(%fg_v0 + ASC(MID$(fg_order, 1, 1))).stat = %FG_COUNTERSUBJECT 'stop fg_order.1 - fg_order.2 heeft thema CASE 4: fg_voice(this).stat = %FG_COUNTERSUBJECT: nextstate_dobasics 3, %FG_SPIEGEL 'spiegel in fg_order 3 CASE 5: fg_voice(this).stat = %FG_COUNTERSUBJECT: nextstate_dobasics 4, %FG_SUBJECT 'thema in fg_order, 4 CASE 6: nextstate_dobasics 5, %FG_SPIEGEL 'stretto fg_order.4, .5 CASE 7: fg_voice(this).stat = %FG_COUNTERSUBJECT 'spiegel@ fg_order.5 blijft CASE 8 fg_voice(this).stat = %FG_COUNTERSUBJECT task(this).freq = 1'0 FOR i = %fg_v0 TO %fg_v4: StopTask i: NEXT StartTask %fg_vAll 'perfroms same as other four but together and in quantized to variable time.. interncount = 0: INCR mastercount CASE ELSE: MSGBOX "shouldn't get here..." END SELECT CASE 4 'divertimento 2 INCR interncount IF interncount > 10 THEN interncount = 0: INCR mastercount fg_order = CHR$(4, 3, 0, 1, 0, 1, 2, 4) centralnote = (fg_voice(%fg_v2).instrum.lowtes + fg_voice(%fg_v2).instrum.hightes) / 2 StopTask %fg_vAll FOR i = %fg_v0 TO %fg_v4 fg_voice(i).scaling.duur = .3 + .1 * (i - %fg_v0) fg_voice(i).thcount = -1 fg_voice(i).nextstateoncount = UBOUND(fg_theme) - 3 'beetje stretto dus task(i).freq = .4 AddNote2Har fg_voice(i).instrum.har(1), fg_voice(i).scaling.noot - 1, MAX(fg_voice(i).instrum.minvel, fg_voice(i).scaling.vel / 3) InstrumPlay fg_voice(i).instrum StartTask i NEXT task(%fg_v4).freq = 20 'keep avg high END IF CASE 5 'exposition 3 - spiegel and kreeft and both - licht stretterend IF (interncount > 0) AND (interncount < 16) AND this = %FG_NOTIFY THEN EXIT SUB INCR interncount centralnote = centralnote + 3 + interncount MOD 2 'afisselend + kl/grote terts SELECT CASE interncount CASE 1: nextstate_dobasics 1, %FG_SUBJECT 'stem1 thema CASE 2: nextstate_dobasics 2, %FG_KREEFT 'stem1 + 2 stretto CASE 3, 5, 7, 9, 11, 13, 15, 16 'thema done in voice this fg_voice(this).stat = %FG_COUNTERSUBJECT DO WHILE (centralnote > fg_voice(nxt).instrum.hightes - 7): centralnote = centralnote - 12: LOOP DO WHILE centralnote < fg_voice(nxt).instrum.lowtes: centralnote = centralnote + 12: LOOP fg_voice(nxt).scaling.noot = centralnote CASE 4: nextstate_dobasics 3, %FG_SPIEGEL 'stem2 + 3 stretto CASE 6: nextstate_dobasics 4, %FG_SPIEGEL OR %FG_KREEFT 'stem 3 + 4 stretto CASE 8: nextstate_dobasics 5, %FG_SUBJECT 'stem 4 en 5 stretto CASE 10: nextstate_dobasics 6, %FG_SPIEGEL '5 & 6 CASE 12: nextstate_dobasics 7, %FG_KREEFT '6 & 7 CASE 14: nextstate_dobasics 8, %FG_SUBJECT '7 en 8 CASE >= 17 '8 af > next divertimento IF this > 0 THEN: fg_voice(this).stat = %FG_COUNTERSUBJECT: task(this).freq = 5 task(this).freq = 1'0 centralnote = 48 FOR i = %fg_v0 TO %fg_v4: StopTask i DECR centralnote: BoundNote(centralnote, fg_voice(i).instrum) fg_voice(i).lastnote = centralnote: fg_voice(i).scaling.noot = centralnote task(i).freq = .7 NEXT StartTask %fg_vAll 'perfroms same as other four but together and in quantized to variable time.. interncount = 0: INCR mastercount END SELECT CASE 6 'divertimento 3 - START QUANTIZING THIS ONE?? INCR interncount IF interncount > 1 THEN interncount = 0: INCR mastercount fg_order = CHR$(1, 2, 4, 3, 4, 0, 2) centralnote = fg_voice(%fg_v0).instrum.lowtes + 18 FOR i = %fg_v0 TO %fg_v4 fg_voice(i).scaling.duur = 1.5 - .1 * (i - %fg_v0) fg_voice(i).thcount = -1 task(i).freq = 3 fg_voice(i).stat = %FG_COUNTERSUBJECT fg_voice(i).nextstateoncount = 0 NEXT nextstate_dobasics 1, %FG_KREEFT OR %FG_SPIEGEL 'stem 0 - kreeftspiegel fg_voice(%fg_v0).nextstateoncount = 6: fg_voice(%fg_v2).nextstateoncount = 7 END IF CASE 7 'exposition 4 - per 2 voice stretto on 1/2 IF interncount AND this = %FG_NOTIFY THEN EXIT SUB IF this => %fg_v0 AND this <= %fg_v4 THEN fg_voice(this).stat = %FG_COUNTERSUBJECT INCR interncount centralnote = centralnote + 1 + ABS(this) MOD 2 SELECT CASE interncount CASE 1: nextstate_dobasics 1, %FG_KREEFT OR %FG_SPIEGEL 'stem 0 - kreeftspiegel CASE 2: nextstate_dobasics 2, %FG_SUBJECT ' + stem1 kreeft CASE 3: nextstate_dobasics 3, %FG_SPIEGEL ' + stem2 spiegel '4: -stem1, 5: -stem2 CASE 6: nextstate_dobasics 4, %FG_KREEFT OR %FG_SPIEGEL: nextstate_doBasics 5, %FG_SUBJECT 'stem 4 + 5 kreeftspiegel + spiegel '7: -stem4 CASE 8: nextstate_dobasics 6, %FG_KREEFT: nextstate_doBasics 7, %FG_SUBJECT 'stem 1 + 2 kreeft + subject '8: -1 CASE 9 FOR i = %fg_v0 TO %fg_v4: fg_voice(i).stat = %FG_COUNTERSUBJECT: NEXT 'SHOULDN't BE NECESSARY!! interncount = 0: INCR mastercount END SELECT task(%fg_v2).freq = 3 CASE 8 'divertimento 4 INCR interncount ' kl_debug insdbg, "stat 8:" + st IF interncount > 1 THEN interncount = 0: INCR mastercount StopTask %fg_vAll fg_order = CHR$(3, 1,0,2,4) 'piperola - harma - vibi - piano - tubi centralnote = fg_voice(%fg_v3).instrum.lowtes + 12 fg_voice(%fg_v3).scaling.duur = .07: fg_voice(%fg_v1).scaling.duur = .4: fg_voice(%fg_v0).scaling.duur = .7 fg_voice(%fg_v2).scaling.duur = .85: fg_voice(%fg_v4).scaling.duur = .85 FOR i = %fg_v0 TO %fg_v4:fg_voice(i).nextstateoncount = 11: fg_voice(i).thcount = -1: NEXT fg_voice(%fg_v3).nextstateoncount = 2: fg_voice(%fg_v1).nextstateoncount = 6 nextstate_dobasics 1, %FG_SUBJECT StartTask %fg_v3 END IF CASE 9 'last exposition supastretto on INCR interncount INCR centralnote IF this >= %fg_v0 AND this <= %fg_v4 THEN fg_voice(this).stat = %FG_COUNTERSUBJECT END IF i = interncount MOD 5 IF i = 0 THEN i = 5 nxt = 0 DO WHILE fg_voice(%fg_v0 + ASC(MID$(fg_order, i, 1))).stat <> %FG_COUNTERSUBJECT IF fg_voice(ASC(MID$(fg_order, i, 1))).scaling.duur > 1 AND _ fg_voice(ASC(MID$(fg_order, i, 1))).nextstateoncount < 6 AND _ fg_voice(ASC(MID$(fg_order, i, 1))).thcount > 6 THEN EXIT LOOP INCR i: i = i MOD 5: INCR nxt IF i = 0 THEN i = 5 IF nxt > 5 THEN neck2neck = %true: EXIT SUB LOOP neck2neck = %false SELECT CASE interncount MOD 2 CASE 0: nextstate_dobasics i, %FG_SUBJECT ' CASE 2: nextstate_dobasics i, %FG_KREEFT OR %FG_SPIEGEL CASE 1: nextstate_Dobasics i, %FG_SPIEGEL CASE 3: nextstate_dobasics i, %FG_KREEFT END SELECT i = ASC(MID$(fg_order, i, 1)) DECR fg_voice(%fg_v0 + i).nextstateoncount fg_voice(%fg_v0 + i).scaling.noot = centralnote fg_voice(%fg_v0 + i).scaling.duur = fg_voice(%fg_v0 + i).scaling.duur * 1.1 IF TRIM$(UCASE$(fg_voice(%fg_v0 + i).instrum.naam)) = "PIPEROLA" THEN fg_voice(%fg_v0 + i).scaling.noot = fg_voice(%fg_v0 + i).instrum.lowtes + fg_voice(%fg_v0 + i).scaling.noot MOD 12 END IF IF fg_voice(%fg_v0 + i).nextstateoncount <= 0 THEN StopTask %fg_v0 + i 'guaranteed playing countersubject if we get here.. fg_silence %fg_v0 + i ELSE task(%fg_v0 + i).freq = task(%fg_v0 + i).freq * 1.1 StartTask %fg_v0 + i END IF END SELECT CONTROL SET TEXT gh.Cockpit, %GMT_MSG1, "State:" + STR$(mastercount) + "." + TRIM$(STR$(interncount)) END SUB FUNCTION nextstate_doBasics(cnt AS LONG, newstat AS LONG) AS LONG LOCAL nxt AS LONG nxt = %FG_V0 + ASC(MID$(FG_order, cnt ,1)) 'don't use boundnote here!! DO WHILE (centralnote > fg_voice(nxt).instrum.hightes - 7): centralnote = centralnote - 12: LOOP DO WHILE centralnote < fg_voice(nxt).instrum.lowtes: centralnote = centralnote + 12: LOOP fg_voice(nxt).scaling.noot = centralnote IF (newstat AND %FG_KREEFT) = %FG_KREEFT THEN fg_voice(nxt).thcount = UBOUND(fg_theme) + 1 IF fg_voice(nxt).nextstateoncount THEN fg_voice(nxt).nextstateoncount = UBOUND(fg_theme) - fg_voice(nxt).nextstateoncount END IF fg_voice(nxt).stat = newstat FUNCTION = nxt END FUNCTION SUB fg_monitor(this AS LONG) STATIC hw AS LONG LOCAL i AS LONG LOCAL b$ IF ISFALSE hw THEN DIALOG NEW 0, "fugue monitor",, , 200, 80 TO hw FOR i = %fg_v0 TO %fg_v4 CONTROL ADD LABEL, hw, i, "",1, (i - %fg_v0) * 12, 198, 12 NEXT DIALOG SHOW MODELESS hw END IF ' FOR i = %fg_v0 TO %fg_v4 DIALOG DOEVENTS: DIALOG DOEVENTS:DIALOG DOEVENTS SELECT CASE fg_voice(this).stat CASE %fg_subject: b$ = "subject" CASE %fg_spiegel: b$ = "spiegel" CASE %fg_kreeft: b$ = "kreeft" CASE %fg_kreeft OR %FG_spiegel: b$ = "spiegel * kreeft" CASE %FG_FREEFORM: b$ = "free" CASE %fg_countersubject: b$ = "counter" CASE %fg_countersubject2: b$ = "counter2" CASE ELSE: b$ = "no" END SELECT b$ = b$ + STR$(this) + " - " + STR$(fg_voice(this).thcount) + " - f:"+ STR$(task(this).freq) CONTROL SET TEXT hw, this, b$ ' NEXT END SUB SUB fg_v0 STATIC this AS LONG IF ISFALSE this THEN this = %fg_v0 END IF fg_voice_doevents this END SUB SUB fg_v1 STATIC this AS LONG IF ISFALSE this THEN this = %fg_v1 END IF fg_voice_doevents this END SUB SUB fg_v2 STATIC this AS LONG IF ISFALSE this THEN this = %fg_v2 END IF fg_voice_doevents this END SUB SUB fg_v3 STATIC this AS LONG IF ISFALSE this THEN this = %fg_v3 END IF fg_voice_doevents this END SUB SUB fg_v4 STATIC this AS LONG IF ISFALSE this THEN this = %fg_v4 END IF fg_voice_doevents this END SUB SUB fg_vAll STATIC this AS LONG LOCAL i AS LONG LOCAL f AS SINGLE STATIC tims() AS SINGLE IF ISFALSE this THEN this = %fg_vAll task(this).freq = 200 DIM tims(%fg_V0 TO %fg_v4) FOR i = LBOUND(tims) TO UBOUND(tims): tims(i) = timegettime + 1000/task(i).freq: NEXT END IF f = 0 FOR i = %fg_v0 TO %fg_v4 IF fg_voice(i).stat < %FG_COUNTERSUBJECT THEN f = f + 2 * task(i).freq IF task(i).freq < 0.21 THEN task(i).freq = .5 IF tims(i) < timegettime THEN fg_voice_doevents i: tims(i) = timegettime + 1000/task(i).freq NEXT IF ISFALSE f THEN FOR i = %fg_v0 TO %fg_v4: f = f + task(i).freq: NEXT f = (5 * task(this).freq + f) / 6 'sic - leaky average + rescaling END IF task(this).freq = f CONTROL SET TEXT gh.cockpit, %GMT_MSG2, STR$(task(this).freq) END SUB SUB FG_Silence(OPT BYVAL i AS LONG) LOCAL n AS BYTE IF ISFALSE i THEN i = App.butnOSParam - %GMT_BUTNOS_ID + %fg_v0 - 1 FOR n = fg_voice(i).instrum.lowtes TO fg_voice(i).instrum.hightes Play fg_voice(i).instrum.channel, n, 0 SLEEP 10 NEXT END SUB 'EOF