'********************************************** '* < TOYPI > * '* musical automat by dr.Godfried-Willem Raes * '* 2008 * '* User interface code * '********************************************** '07.08.2008: start coding '09.08.2008: First version firmware in PIC controllers '20.08.2008: Further work on Linus' dream. ' Optional: vocal solo part (bocca chiussa), high voice. '21.08.2008: adjustments on Toypi. ' timing in Linus dream changed. ' Title of piece changed to 'Schroeders Dream' %Toypi_Scale_Test = 24 %Toypi_Dyna_Test = 25 %Toypi_Lites = 26 %Toypi_underlites = 27 %Linus = 48 ' demo composition for Toypi by gwr 48,49,50,51,52 TYPE Linus_Type DWORD cycle AS DWORD note1 AS BYTE note2 AS BYTE note3 AS BYTE note4 AS BYTE angle AS SINGLE END TYPE GLOBAL Linus AS Linus_Type DECLARE FUNCTION Init_Toypi () AS LONG DECLARE SUB Toypi_Scale_Test () DECLARE SUB Toypi_Dyna_Test () DECLARE SUB Toypi_Lites () ' yellow leds on keyboard panel DECLARE SUB Toypi_Lites_Off () DECLARE SUB Toypi_underlites () 'declare sub Toypi_underlites_Off () DECLARE SUB Linus_Main () DECLARE SUB Linus_One () DECLARE SUB Linus_Two () DECLARE SUB Linus_Three () DECLARE SUB Linus_end () FUNCTION Init_Toypi () AS LONG LOCAL m AS ASCIIZ * 40 LOCAL i AS DWORD LOCAL j AS LONG LOCAL retval AS LONG CONTROL SET TEXT gh.Cockpit,0, " test code " IF ISFALSE hMidiI(0) THEN ButnSw(0).tag0 = "" ButnSw(0).cptr = %False END IF ButnSW(2).tag0 = "Pow On" ' switches solenoid voltage on/off - not yet implemented ButnSW(2).tag1 = "Pow Off" ButnSW(2).cptr = CODEPTR(Toypi_Power) ButnSW(3).tag0 = "" ButnSW(4).tag0 = "" ' harm ButnSW(5).tag0 = "" ' melo ButnSW(6).tag0 = "" ' psy ButnSW(7).tag0 = "" 'spec ButnSW(8).tag0 = "" ButnSW(9).tag0 = "" ButnSW(10).tag0 = "" ButnSW(11).tag0 = "" ButnOS(5).tag = "" ButnOS(6).tag = "" CONTROL SET TEXT gh.cockpit, %GMT_TITLE, " CONTROL SET TEXT gh.cockpit, %GMT_AUTHOR, $gwr Task(%Toypi_Scale_Test).naam = "Scale" Task(%Toypi_Scale_Test).cptr = CODEPTR(Toypi_Scale_Test) Task(%Toypi_Scale_Test).freq = 4 Task(%Toypi_Scale_Test).flags = %False Task(%Toypi_Dyna_Test).naam = "Dyna" Task(%Toypi_Dyna_Test).cptr = CODEPTR(Toypi_Dyna_Test) Task(%Toypi_Dyna_Test).freq = 4 Task(%Toypi_Dyna_Test).flags = %False Task(%Toypi_lites).naam = "Yellow" Task(%Toypi_lites).cptr = CODEPTR(Toypi_lites) Task(%Toypi_lites).freq = 4 Task(%Toypi_lites).flags = %False Taskex(%Toypi_lites).stopcptr = CODEPTR(Toypi_lites_off) Task(%Toypi_underlites).naam = "BlueWhit" Task(%Toypi_underlites).cptr = CODEPTR(Toypi_underlites) Task(%Toypi_underlites).freq = 4 Task(%Toypi_underlites).flags = %False Taskex(%Toypi_underlites).stopcptr = CODEPTR(Toypi_lites_off) ' procedures for "Linus' Dream" by Godfried-Willem Raes Task(%Linus).naam = "Linus" Task(%Linus).cptr = CODEPTR(Linus_Main) Task(%Linus).freq = 2 Task(%Linus).flags = %False TaskEx(%Linus).stopcptr = CODEPTR(Linus_End) Task(%Linus+1).naam = "-V1" Task(%Linus+1).cptr = CODEPTR(Linus_One) Task(%Linus+1).freq = 10 Task(%Linus+1).flags = %False Task(%Linus+2).naam = "-V2" Task(%Linus+2).cptr = CODEPTR(Linus_Two) Task(%Linus+2).freq = 10 Task(%Linus+2).flags = %False Task(%Linus+3).naam = "-V3" Task(%Linus+3).cptr = CODEPTR(Linus_Three) Task(%Linus+3).freq = 2 Task(%Linus+3).flags = %False Task(%Linus+4).naam = "LinEnd" Task(%Linus+4).cptr = CODEPTR(Linus_End) Task(%Linus+4).freq = 2 Task(%Linus+4).flags = %False TaskEx(%Linus+4).stopcptr = CODEPTR(MM_Toypi_Off) Task(%Linus+5).naam = "Score" Task(%linus+5).cptr = CODEPTR(Linus_Score) Task(%Linus+5).freq = 100 Task(%Linus+5).flags = %False ' end procedures for Linus' dream. FUNCTION = %true END FUNCTION SUB Toypi_Power () ' buttonswitch handler IF ISFALSE ButnSW(2).flag THEN Toypi.ctrl(66) = %False Controller Toypi.channel, 123, %False 'Controller Toypi.channel, 66, Toypi.ctrl(66) ELSE Toypi.ctrl(66) = %True ' Controller Toypi.channel, 66, Toypi.ctrl(66) END IF END SUB SUB Toypi_Scale_test () STATIC note AS INTEGER STATIC qt AS INTEGER STATIC init AS LONG LOCAL velo AS DWORD STATIC slnr() AS INTEGER IF ISFALSE init THEN 'Task(%Toypi_Scale_Test).tog THEN init = 1 note = toypi.lowtes ' create sliders: DIM Slnr(0 TO 1) AS STATIC INTEGER DIM TaskParamLabels(0 TO 1) AS STATIC ASCIIZ*8 TaskParamLabels(0)="Velo" ' attack force for beaters TaskParamLabels(1)="Freq" ' speed IF ISFALSE Task(%Toypi_Scale_Test).hParam THEN MakeTaskParameterDialog BYVAL %Toypi_Scale_Test,2, Slider(),0,UdCtrl(), TaskParamLabels() END IF slnr(0) = TaskEX(%Toypi_Scale_Test).SliderNumbers(0) slnr(1) = TaskEX(%Toypi_Scale_Test).SliderNumbers(1) Slider(Slnr(0)).value = 1 Slider(Slnr(1)).value = 4 SendMessage Slider(Slnr(0)).h, %TBM_SETPOS,%True, Slider(Slnr(0)).value SendMessage Slider(Slnr(1)).h, %TBM_SETPOS,%True, Slider(Slnr(1)).value qt = %False Task(%Toypi_Scale_Test).tog = %True END IF velo = Slider(Slnr(0)).value IF velo THEN Play Toypi.channel, note, velo INCR note IF note > Toypi.hightes THEN note = Toypi.lowtes END IF Task(%Toypi_Scale_Test).freq = MAX(.5, Slider(Slnr(1)).value / 2!) END SUB SUB Toypi_Dyna_Test () STATIC note AS INTEGER LOCAL velo AS DWORD STATIC slnr() AS INTEGER STATIC ud AS INTEGER STATIC init AS LONG IF ISFALSE init THEN init = 1 ' create sliders: DIM Slnr(0 TO 1) AS STATIC INTEGER DIM TaskParamLabels(0 TO 2) AS STATIC ASCIIZ*8 TaskParamLabels(0)="Velo" ' attack force for beaters TaskParamLabels(1)="Freq" ' speed TaskParamLabels(2)="Note" ' up down for the note IF Task(%Toypi_Dyna_Test).hParam = %Null THEN MakeTaskParameterDialog BYVAL %Toypi_Dyna_Test,2, Slider(),1,UdCtrl(), TaskParamLabels() END IF slnr(0) = TaskEX(%Toypi_Dyna_Test).SliderNumbers(0) slnr(1) = TaskEX(%Toypi_Dyna_Test).SliderNumbers(1) ud = TaskEX(%Toypi_Dyna_Test).UpDownNumbers(0) Slider(Slnr(0)).value = 1 Slider(Slnr(1)).value = 4 UdCtrl(ud).value = 72 UdCtrl(ud).minval = 72 UdCtrl(ud).maxval = 107 UdCtrl(ud).resetval = 72 UdCtrl(ud).stap = 1 UDctrl(ud).cptr = CODEPTR(Toypi_UD_Noot_CB) SendMessage Slider(Slnr(0)).h, %TBM_SETPOS,%True, Slider(Slnr(0)).value SendMessage Slider(Slnr(1)).h, %TBM_SETPOS,%True, Slider(Slnr(1)).value Task(%Toypi_Dyna_Test).tog = %True END IF note = UdCtrl(ud).value velo = Slider(Slnr(0)).value 'was / 2 ' range 256micro sec to 16ms IF velo THEN Play Toypi.channel, note, velo Task(%Toypi_Dyna_Test).freq = MAX(.5, Slider(Slnr(1)).value / 2!) END SUB SUB Toypi_UD_Noot_CB () ' for callback on parameter UpDown. LOCAL note AS SINGLE note = UDCtrl(TaskEX(%Toypi_Dyna_Test).UpdownNumbers(0)).value CONTROL SET TEXT Task(%Toypi_Dyna_Test).hparam, %GMT_TEXT0_ID + 16, "N=" & STR$(note) END SUB SUB Toypi_Lites () ' yellow led's on keyboard panel STATIC n AS DWORD IF ISFALSE Task(%Toypi_lites).tog THEN n = 59 Task(%Toypi_lites).tog = %True END IF NoteOff Toypi.channel, n ' not working with play and zero velo ? INCR n IF n > 67 THEN n = 60 Play Toypi.channel, n, 127 END SUB SUB Toypi_UnderLites () ' leds under keyboard panel STATIC n AS DWORD IF ISFALSE Task(%Toypi_underlites).tog THEN n = 47 Task(%Toypi_underlites).tog = %True END IF NoteOff Toypi.channel, n ' not working with play and zero velo ? INCR n IF n > 55 THEN n = 48 Play Toypi.channel, n, 127 END SUB SUB Toypi_Lites_Off () ' all lites ' this also works simply with ctrl 123. LOCAL n AS BYTE FOR n = 60 TO 67 Noteoff Toypi.channel, n NEXT n FOR n = 48 TO 55 Noteoff Toypi.channel, n NEXT n END SUB SUB Linus_Main () STATIC tstart AS DWORD STATIC cnt AS DWORD STATIC n AS DWORD STATIC velo1, velo2 AS SINGLE STATIC lite1, lite2 AS BYTE STATIC oldlite1, oldlite2 AS BYTE STATIC cyc0, cyc1, cyc2, cyc3,cyc4,cyc5,cyc6,cyc7,cyc8,cyc9,cyc10,cyc11 AS INTEGER STATIC nidx AS INTEGER LOCAL t AS INTEGER LOCAL i AS INTEGER IF ISFALSE task(%linus).tog THEN DIM n1(0 TO 8) AS STATIC INTEGER DIM n2(0 TO 8) AS STATIC INTEGER cnt = %False n = %False linus.angle = %False linus.cycle = %False oldlite1 = %False oldlite2 = %False tstart = Timegettime Task(%linus).freq = 64 '256 ' bepaalt de duur van het stuk - veranderd in de taak zelf, ' waardoor de cycli een verschillende duur kunnen hebben n1(0) = 72 : n2(0) = 80 n1(1) = 74 : n2(1) = 79 n1(2) = 79 : n2(2) = 87 n1(3) = 79 : n2(3) = 86 n1(4) = 81 : n2(4) = 88 n1(5) = 79 : n2(5) = 87 n1(6) = 80 : n2(6) = 83 n1(7) = 79 : n2(7) = 81 n1(8) = 81 : n2(8) = 89 velo1 = 1 '64 '1 velo2 = 1 '64 '1 ' flags: cyc0 = 0 cyc1 = 0 cyc2 = 0 cyc3 = 0 cyc4 = 0 cyc5 = 0 cyc6 = 0 cyc7 = 0 cyc8 = 0 cyc9 = 0 cyc10 = 0 cyc11 = 0 nidx = %False SetDlgItemText gh.Cockpit, %GMT_TITLE, "" SetDlgItemText gh.Cockpit, %GMT_AUTHOR, $gwr ProgChange Toypi.channel, 0 ' default velo scaling MM_Toypi_On %MM_White Starttask %linus + 5 ' for score generation only!!! Task(%linus).tog = %True END IF 'chordal structures with very fast repetition on notes SELECT CASE nidx ' cnt CASE %False Task(%linus + 1).level = velo1 + (ABS(SIN(n/100)) * 5) ' n = fast counter 0-628= 2* Pi linus.note1 = n1(nidx) 'n1(cnt) - doorgeefluik voor de noot IF ISFALSE Task(%linus+1).swit THEN starttask %linus + 1 CASE ELSE ' vanaf de eerste cirkel Task(%linus + 1).level = velo1 + (ABS(SIN(n/50)) * 20) linus.note1 = n1(nidx-1) IF n2(nidx) <> n1(nidx-1) THEN Task(%linus + 2).level = velo2 + (ABS(SIN(n/66)) * 20) linus.note2 = n2(nidx) IF ISFALSE Task(%linus + 2).swit THEN starttask %linus + 2 ELSE linus.note2 = %False IF Task(%linus + 2).swit THEN stoptask %linus +2 END IF END SELECT ' trage noten: (afgeleid van de som en verschiltonen) IF Task(%linus +1).swit AND Task(%linus+2).swit THEN Task(%linus+3).freq = (Task(%linus + 1).freq + Task(%linus + 2).freq )/ 30 ' was: / 20 IF ISFALSE Task(%linus+3).swit THEN starttask %linus + 3 END IF ' lampjeskode: ---------------------------- SELECT CASE linus.note1 CASE 72 TO 76 lite1 = 60 CASE 77 TO 80 lite1 = 61 CASE 81 TO 85 lite1 = 62 CASE 86 TO 89 lite1 = 63 CASE 90 TO 94 lite1 = 64 CASE 95 TO 98 lite1 = 65 CASE 99 TO 103 lite1 = 66 CASE 104 TO 107 lite1 = 67 CASE ELSE lite1 = %False END SELECT SELECT CASE linus.note2 CASE 72 TO 76 lite2 = 60 CASE 77 TO 80 lite2 = 61 CASE 81 TO 85 lite2 = 62 CASE 86 TO 89 lite2 = 63 CASE 90 TO 94 lite2 = 64 CASE 95 TO 98 lite2 = 65 CASE 99 TO 103 lite2 = 66 CASE 104 TO 107 lite2 = 67 CASE ELSE lite2 = %False END SELECT IF lite1 <> oldlite1 THEN IF oldlite1 <> lite2 THEN NoteOff Toypi.channel, oldlite1 Play Toypi.channel, lite1, 127 oldlite1 = lite1 END IF IF lite2 <> oldlite2 THEN IF lite2 <> lite1 THEN IF oldlite2 <> lite1 THEN NoteOff Toypi.channel, oldlite2 Play Toypi.channel, lite2, 127 oldlite2 = lite2 END IF END IF ' ------------eind gele lampjeskode ----------------------------------------------- INCR n ' fast counter (ticks) linus.angle = n MOD 628 ' for pass to playing tasks. ' hoekteller (0-627, overeenkomstig een omwenteling in radialen * 100) cnt = n \ 628 ' aantal volledige cirkels linus.cycle = cnt \ 8 ' elke keer we het noten array doorlopen is er een cyclus voorbij nidx = 1 + (cnt MOD 8) ' noten-index. moet < ubound notes() SELECT CASE linus.cycle CASE 0 IF ISFALSE cyc0 THEN Task(%linus).freq = 64 SetDlgItemText gh.Cockpit, %GMT_MSG1, "Cyc=" & STR$(linus.cycle) & " cnt=" & STR$(cnt) cyc0 = %True END IF CASE 1 IF ISFALSE cyc1 THEN Task(%linus).freq = 128 FOR i = 0 TO 8 n1(i) = n1(i) + 7 IF n1(i) > 107 THEN n1(i) = 72 + (n1(i) MOD 12) n2(i) = n2(i) + 7 IF n2(i) > 107 THEN n2(i) = 72 + (n2(i) MOD 12) NEXT i cyc1 = %True SetDlgItemText gh.Cockpit, %GMT_MSG1, "Cyc=" & STR$(linus.cycle) & " cnt=" & STR$(cnt) END IF CASE 2 IF ISFALSE cyc2 THEN Task(%linus).freq = 256 FOR i = 0 TO 8 n1(i) = n1(i) + 7 IF n1(i) > 107 THEN n1(i) = 72 + (n1(i) MOD 12) n2(i) = n2(i) + 7 IF n2(i) > 107 THEN n2(i) = 72 + (n2(i) MOD 12) NEXT i cyc2 = %True SetDlgItemText gh.Cockpit, %GMT_MSG1, "Cyc=" & STR$(linus.cycle) & " cnt=" & STR$(cnt) END IF CASE 3 IF ISFALSE cyc3 THEN Task(%linus).freq = 333 FOR i = 0 TO 8 n1(i) = n1(i) + 7 IF n1(i) > 107 THEN n1(i) = 72 + (n1(i) MOD 12) n2(i) = n2(i) + 7 IF n2(i) > 107 THEN n2(i) = 72 + (n2(i) MOD 12) NEXT i cyc3 = %True SetDlgItemText gh.Cockpit, %GMT_MSG1, "Cyc=" & STR$(linus.cycle) & " cnt=" & STR$(cnt) END IF CASE 4 IF ISFALSE cyc4 THEN FOR i = 0 TO 8 n1(i) = n1(i) + 7 IF n1(i) > 107 THEN n1(i) = 72 + (n1(i) MOD 12) n2(i) = n2(i) + 7 IF n2(i) > 107 THEN n2(i) = 72 + (n2(i) MOD 12) NEXT i cyc4 = %True SetDlgItemText gh.Cockpit, %GMT_MSG1, "Cyc=" & STR$(linus.cycle) & " cnt=" & STR$(cnt) END IF CASE 5 IF ISFALSE cyc5 THEN FOR i = 0 TO 8 n1(i) = n1(i) + 7 IF n1(i) > 107 THEN n1(i) = 72 + (n1(i) MOD 12) n2(i) = n2(i) + 7 IF n2(i) > 107 THEN n2(i) = 72 + (n2(i) MOD 12) NEXT i cyc5 = %True SetDlgItemText gh.Cockpit, %GMT_MSG1, "Cyc=" & STR$(linus.cycle) & " cnt=" & STR$(cnt) END IF CASE 6 IF ISFALSE cyc6 THEN FOR i = 0 TO 8 n1(i) = n1(i) + 7 IF n1(i) > 107 THEN n1(i) = 72 + (n1(i) MOD 12) n2(i) = n2(i) + 7 IF n2(i) > 107 THEN n2(i) = 72 + (n2(i) MOD 12) NEXT i cyc6 = %True SetDlgItemText gh.Cockpit, %GMT_MSG1, "Cyc=" & STR$(linus.cycle) & " cnt=" & STR$(cnt) END IF CASE 7 IF ISFALSE cyc7 THEN FOR i = 0 TO 8 n1(i) = n1(i) + 7 IF n1(i) > 107 THEN n1(i) = 72 + (n1(i) MOD 12) n2(i) = n2(i) + 7 IF n2(i) > 107 THEN n2(i) = 72 + (n2(i) MOD 12) NEXT i cyc7 = %True SetDlgItemText gh.Cockpit, %GMT_MSG1, "Cyc=" & STR$(linus.cycle) & " cnt=" & STR$(cnt) END IF CASE 8 IF ISFALSE cyc8 THEN FOR i = 0 TO 8 n1(i) = n1(i) + 7 IF n1(i) > 107 THEN n1(i) = 72 + (n1(i) MOD 12) n2(i) = n2(i) + 7 IF n2(i) > 107 THEN n2(i) = 72 + (n2(i) MOD 12) NEXT i cyc8 = %True SetDlgItemText gh.Cockpit, %GMT_MSG1, "Cyc=" & STR$(linus.cycle) & " cnt=" & STR$(cnt) END IF CASE 9 IF ISFALSE cyc9 THEN Task(%linus).freq = 256 FOR i = 0 TO 8 n1(i) = n1(i) + 7 IF n1(i) > 107 THEN n1(i) = 72 + (n1(i) MOD 12) n2(i) = n2(i) + 7 IF n2(i) > 107 THEN n2(i) = 72 + (n2(i) MOD 12) NEXT i SetDlgItemText gh.Cockpit, %GMT_MSG1, "Cyc=" & STR$(linus.cycle) & " cnt=" & STR$(cnt) cyc9 = %True END IF CASE 10 IF ISFALSE cyc10 THEN Task(%Linus).freq = 128 FOR i = 0 TO 8 n1(i) = n1(i) + 7 IF n1(i) > 107 THEN n1(i) = 72 + (n1(i) MOD 12) n2(i) = n2(i) + 7 IF n2(i) > 107 THEN n2(i) = 72 + (n2(i) MOD 12) NEXT i SetDlgItemText gh.Cockpit, %GMT_MSG1, "Cyc=" & STR$(linus.cycle) & " cnt=" & STR$(cnt) cyc10 = %True END IF CASE 11 t = %False FOR i = 0 TO 7 IF n2(i+1) < n1(i) + 12 THEN INCR n2(i+1) : t = %True IF n2(i+1) > n1(i) + 12 THEN DECR n2(i+1) : t = %True IF ISTRUE t THEN EXIT FOR NEXT i Task(%linus).freq = task(%linus).freq * 0.95 IF ISFALSE t THEN stoptask %Linus stoptask %linus + 1 stoptask %linus + 2 stoptask %linus + 3 starttask %linus + 4 ' ending END IF IF ISFALSE cyc11 THEN SetDlgItemText gh.Cockpit, %GMT_MSG1, "Cyc=" & STR$(linus.cycle) & " cnt=" & STR$(cnt) cyc11 = %True END IF END SELECT END SUB SUB Linus_one () ' note repeat task for voice 1 LOCAL vmax AS INTEGER SELECT CASE linus.cycle CASE 0 TO 4 Task(%linus+1).freq = 16! + (14 * (SIN(linus.angle/ 100!))) ' patch heeft de hoekcounter CASE 5 TO 7 Task(%linus+1).freq = 16! + (14 * (SINC(linus.angle/ 100!))) ' patch heeft de hoekcounter CASE ELSE Task(%linus+1).freq = 16! + (14 * (SIN(linus.angle/ 100!))) ' patch heeft de hoekcounter END SELECT SELECT CASE Task(%linus + 1).freq CASE > 12 vmax =1 CASE > 8 vmax = 2 CASE > 6 vmax = 3 '4 CASE > 4 vmax = 6 '12 CASE > 2 vmax = 12 '24 CASE > 1 vmax = 27 '64 END SELECT Play Toypi.channel, linus.note1, MIN(Task(%linus+1).level, vmax) END SUB SUB Linus_Two () ' note repeat task for voice 2 LOCAL vmax AS INTEGER SELECT CASE linus.cycle CASE 5 TO 7 Task(%linus + 2).freq = 16! + ( 14! * (SINC(linus.angle/ 66!))) CASE ELSE Task(%linus + 2).freq = 16! + ( 14! * (SIN(linus.angle/ 66!))) END SELECT SELECT CASE Task(%linus + 2).freq CASE > 20 vmax = 1 CASE > 12 vmax = 2 CASE > 6 vmax = 3 '4 CASE > 4 vmax = 6 '12 CASE > 2 vmax = 12 '24 CASE > 1 vmax = 27 '64 END SELECT IF linus.note2 THEN Play Toypi.channel, linus.note2, MIN(Task(%linus+2).level, vmax) END IF END SUB SUB Linus_Three () ' long notes fill in STATIC n1 AS SINGLE STATIC n2 AS SINGLE STATIC cnt AS SINGLE linus.note3 = %False linus.note4 = %False n1 = DifNoteF (linus.note1, linus.note2) ' in g_mus n2 = SumNoteF (linus.note1, linus.note2) IF n1 < 72 THEN DO n1 = n1 + 12 LOOP UNTIL n1 > 71 END IF IF n1 THEN IF (n1 <> linus.note1) AND (n1 <> linus.note2) THEN Play Toypi.channel, n1 , 18 Linus.note3 = n1 END IF END IF IF n2 > 107 THEN DO n2 = n2 - 12 LOOP UNTIL n2 < 108 END IF IF n2 THEN IF n2 <> n1 THEN IF (n2 <> linus.note1) AND (n2 <> linus.note2) THEN Play Toypi.channel, n2 , 18 Linus.note4 = n2 END IF END IF END IF ' alternating blue lights: INCR cnt IF ISFALSE cnt MOD 2 THEN Play Toypi.channel, 48, 127 NoteOff Toypi.channel, 55 ELSE NoteOff Toypi.channel, 48 Play Toypi.channel, 55, 127 END IF END SUB SUB Linus_End () ' ending for Linus' Dream STATIC n AS INTEGER STATIC m AS INTEGER IF ISFALSE Task(%Linus+4).tog THEN m = 72 n= 107 Task(%Linus+4).tog = %TRue Task(%Linus + 4).freq = 64 END IF Play Toypi.channel, n, 20 Linus.note1 = n Play Toypi.channel, m, 20 Linus.note2 = m DECR n INCR m Task(%Linus+4).freq = Task(%Linus+4).freq * 0.9 IF n < 72 THEN Play Toypi.channel, 84, 20 Linus.note1 = 84 Play Toypi.channel, 96, 20 Linus.note2 = 96 stoptask %Linus + 4 Controller Toypi.channel, 123, %False StopTask %Linus + 5 ' score. END IF END SUB SUB Linus_Score () ' outputs a score as midi (without note repetitions) ' record on channel 0 only. ' no lites, no controllers. ' taskfreq = 100 STATIC on1 AS INTEGER STATIC on2 AS INTEGER STATIC on3 AS INTEGER STATIC on4 AS INTEGER STATIC cnt AS DWORD IF ISFALSE Task(%linus+5).tog THEN on1 = 0 on2 = 0 on3 = 0 on4 = 0 END IF ' metronome: (every second) MM60 IF ISFALSE cnt MOD 100 THEN Play 0,36,64 END IF IF cnt MOD 100 = 1 THEN Play 0,36,0 ' noteoff - metrome only. END IF ' main voices IF on1 <> linus.note1 THEN IF on1 THEN Noteoff 0,on1 Play 0,linus.note1, 64 on1 = linus.note1 END IF IF on2 <> linus.note2 THEN IF on2 THEN Noteoff 0, on2 Play 0,linus.note2,64 on2 = linus.note2 END IF ' additional notes: IF linus.note3 THEN Play 0, linus.note3, 18 on3 = linus.note3 ELSE IF on3 THEN Noteoff 0,on3 on3 = %False END IF END IF IF linus.note4 THEN Play 0, linus.note4, 18 on4 = linus.note4 ELSE IF on4 THEN Noteoff 0,on4 on4 = %False END IF END IF ' here we could calculate the vocal part as well... END SUB