' ************************************************************ ' * Namuda Study #71 * ' * Logos 50 years * ' * 2018 * ' ************************************************************ ' For november 2018, Namuda 50-years logos, with ' RatNumPat funktie toegevoegd aan g_indep voor ondersteuning van de algoritmiek hier. ' 01.10.2018: support voor duodecimale getallen (dozenal numbers) toegevoegd in g_indep ' 07.11.2018: lichtjes toegevoegd. ' 08.11.2018: Trouble with the limitations on the number of tasks that can be active together. ' Per-related tasks: %L50_Per = 17 '16 geeft autostart problemen? ' rational melodies: %L50_AlgoMeta = 32 %L50_AlgoX = 33 ' korn %L50_AlgoY = 34 ' asa %L50_AlgoZ = 35 ' fa %L50_DozMeta = 36 %L50_DozX = 37 ' ob %L50_DozY = 38 ' autosax %L50_DozZ = 39 ' heli %L50_Meta = 40 %L50_X = 41 ' spiro %L50_Y = 42 ' vibi %L50_Z = 43 ' hybr ' extra elements: %L50_Chi = 48 ' chi %L50_Tinti = 49 ' tinti %L50_ThCol_Chi = 50 %L50_Tinti_Smt = 51 ' other possible instruments: So, HybrLo, PP2 ' Vibi, Toypi, Spiro ' Pi, 2Pi, HybrHi or piperola ' Tubi, Xy, Puff FUNCTION Init_Logos50 AS LONG Task(%L50_Per).naam="Sm_Bass" Task(%L50_Per).freq = 17 Task(%L50_Per).cptr = CODEPTR(L50_Per_bass) TaskEX(%L50_Per).stopcptr = CODEPTR(L50_Per_Bass_Stop) Task(%L50_Per + 1).naam="Edg_Cym" Task(%L50_Per + 1).freq = 7 Task(%L50_Per + 1).cptr = CODEPTR(L50_Per_cymbal) Task(%L50_Per + 2).naam="Drums" Task(%L50_Per + 2).freq = 8 Task(%L50_Per + 2).cptr = CODEPTR(L50_Per_Bongo) Task(%L50_Per + 3).naam="Col_Tamb" Task(%L50_Per + 3).freq = 9 Task(%L50_Per + 3).cptr = CODEPTR(L50_Per_Tambourine) Task(%L50_Per + 4).naam="Propell" Task(%L50_Per + 4).freq = 8 Task(%L50_Per + 4).cptr = CODEPTR(L50_Per_Vent) TaskEX(%L50_Per + 4).stopcptr = CODEPTR(L50_Per_Vent_Stop) ' ------------------------------------------------------------ Task(%L50_Per + 5).naam="ImpPuf" Task(%L50_Per + 5).freq = 14 Task(%L50_Per + 5).cptr = CODEPTR(L50_Puff) TaskEX(%L50_Per + 5).stopcptr = CODEPTR(L50_Puff_Stop) Task(%L50_Per + 6).naam="ThcTem" Task(%L50_Per + 6).freq = 14 Task(%L50_Per + 6).cptr = CODEPTR(L50_Temblo) TaskEX(%L50_Per + 6).stopcptr = CODEPTR(L50_Temblo_Stop) Task(%L50_Per + 7).naam="SldToyp" Task(%L50_Per + 7).freq = 15 Task(%L50_Per + 7).cptr = CODEPTR(L50_Toypi) TaskEX(%L50_Per + 7).stopcptr = CODEPTR(L50_Toypi_Stop) Task(%L50_Per + 8).naam="ExplQt" Task(%L50_Per + 8).freq = 8 Task(%L50_Per + 8).cptr = CODEPTR(L50_Qt) TaskEX(%L50_Per + 8).stopcptr = CODEPTR(L50_Qt_Stop) ' ---------------------------------------------------- Task(%L50_AlgoMeta).naam = "NuPaMeta" Task(%L50_AlgoMeta).freq = 50 Task(%L50_AlgoMeta).cptr = CODEPTR(L50_AlgoMeta) Task(%L50_AlgoX).naam = "NumPatX" Task(%L50_AlgoX).freq = 4 Task(%L50_AlgoX).cptr = CODEPTR(L50_AlgoX) Task(%L50_AlgoY).naam = "NumPatY" Task(%L50_AlgoY).freq = 4 Task(%L50_AlgoY).cptr = CODEPTR(L50_AlgoY) Task(%L50_AlgoZ).naam = "NumPatZ" Task(%L50_AlgoZ).freq = 4 Task(%L50_AlgoZ).cptr = CODEPTR(L50_AlgoZ) Task(%L50_DozMeta).naam = "DozMeta" Task(%L50_DozMeta).freq = 50 Task(%L50_DozMeta).cptr = CODEPTR(L50_DozMeta) Task(%L50_DozX).naam = "DozPatX" Task(%L50_DozX).freq = 4 Task(%L50_DozX).cptr = CODEPTR(L50_DozX) Task(%L50_DozY).naam = "DozPatY" Task(%L50_DozY).freq = 4 Task(%L50_DozY).cptr = CODEPTR(L50_DozY) Task(%L50_DozZ).naam = "DozPatZ" Task(%L50_DozZ).freq = 4 Task(%L50_DozZ).cptr = CODEPTR(L50_DozZ) Task(%L50_Meta).naam = "Meta" Task(%L50_Meta).freq = 50 Task(%L50_Meta).cptr = CODEPTR(L50_Meta) Task(%L50_X).naam = "Doz_X" Task(%L50_X).freq = 4 Task(%L50_X).cptr = CODEPTR(L50_X) Task(%L50_Y).naam = "Doz_Y" Task(%L50_Y).freq = 4 Task(%L50_Y).cptr = CODEPTR(L50_Y) Task(%L50_Z).naam = "Doz_Z" Task(%L50_Z).freq = 4 Task(%L50_Z).cptr = CODEPTR(L50_Z) '------------------------------------------ Task(%L50_Chi).naam = "Chi" Task(%L50_Chi).freq = 10 Task(%L50_Chi).cptr = CODEPTR(L50_Chi) TaskEX(%L50_chi).stopCptr = CODEPTR(MM_Chi_Off) Task(%L50_Tinti).naam = "Tinti" Task(%L50_Tinti).freq = 20 Task(%L50_Tinti).cptr = CODEPTR(L50_Tinti) TaskEX(%L50_Tinti).stopCptr = CODEPTR(L50_Tinti_Stop) Task(%L50_ThCol_Chi).naam = "TeCo_Chi" Task(%L50_ThCol_Chi).freq = 7 Task(%L50_ThCol_Chi).cptr = CODEPTR(L50_ThCol_Chi) TaskEX(%L50_ThCol_Chi).stopcptr = CODEPTR(MM_Chi_Off) Task(%L50_Tinti_Smt).naam = "Tin_Smt" Task(%L50_Tinti_Smt).freq = 5 Task(%L50_Tinti_Smt).cptr = CODEPTR(L50_Tinti_Smt) TaskEX(%L50_Tinti_Smt).stopCptr = CODEPTR(L50_Tinti_Stop) MM_Per_On FUNCTION = 1 END FUNCTION ' interactive procs. ' to do: add pedal (note 24) ' add cymbal beaters ' add bass drum damper ' add lights ' it should be a demo for ALL possibilities! SUB L50_Per_bass ' bass on smooth ' 03.11.2018: improved gwr. using all beaters ' 07.11.2018: Lights added. STATIC n AS LONG STATIC sens AS SINGLE IF ISFALSE task(%L50_Per).tog THEN sens = 0.1 n = 25 task(%L50_Per).tog = %True mPlay Per.channel, 120, 127 mPlay Per.channel, 121, 127 END IF ' logfile STR$(Gesture.Edgy(3)) + STR$(Gesture.Smooth(3)) + STR$(MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za)) IF (Gesture.Edgy(3) < Gesture.Smooth(3)) AND (MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) > sens )THEN mPlay Per.channel, n, MIN((@pDoppler.xa + @pDoppler.ya + @pDoppler.za) * 4, 127) ' mPlay Per.channel, n + 95, 127 'light ' n = IIF(n = 25, 26, 25) ' warning STR$(n) INCR n IF n > 27 THEN n = 24 ' 24 = pedal END IF END SUB SUB L50_Per_Bass_Stop () NoteOff Per.channel, 120 NoteOff Per.channel, 121 END SUB SUB L50_Per_Cymbal 'runs very slow as we only want sporadic notes 'mapped on the edgy property STATIC sens AS SINGLE STATIC alt AS DWORD IF ISFALSE sens THEN sens = .2 END IF INCR alt SELECT CASE alt MOD 3 CASE 0 IF (Gesture.Edgy(0) > Gesture.Smooth(0) * 1.5) AND (@pDoppler.xa > sens) THEN ' mPlay Per.channel, 71, BIT(alt, 8) * 127 'open / close -seems to give just a pulse instead of leaving it closed?? mPlay Per.channel,65, @pDoppler.xa * 127 '80 END IF CASE 1 IF (Gesture.Edgy(1) > Gesture.Smooth(1) * 1.5) AND (@pDoppler.ya > sens) THEN mPlay Per.channel, 67, @pDoppler.ya* 80 CASE 2 IF (Gesture.Edgy(2) > Gesture.Smooth(2) * 1.5) AND (@pDoppler.za > sens) THEN mPlay Per.channel, 95, @pDoppler.za* 80 ' crotale END SELECT END SUB SUB L50_Per_Bongo () ' slechts 2 drums? ' 03.11.2018 all drums added and recoded gwr. STATIC sens AS SINGLE IF ISFALSE sens THEN sens = 10 ' was 60 END IF ' IF (gesture.speedup(0) > gesture.slowdown(0) + sens) THEN ' mPlay Per.channel, 44, @pDoppler.xa * 100 ' ELSEIF (gesture.speedup(1) > gesture.slowdown(1) + sens) THEN ' mPlay Per.channel, 46, @pDoppler.ya * 100 ' END IF ' better coding: IF (gesture.speedup(0) > gesture.slowdown(0) + sens) THEN mPlay Per.channel, 44, @pDoppler.xa * 127 ' low bongo END IF IF (gesture.speedup(1) > gesture.slowdown(1) + sens) THEN mPlay Per.channel, 34, @pDoppler.ya * 127 ' darbukkah END IF IF (gesture.speedup(2) > gesture.slowdown(2) + sens) THEN mPlay Per.channel, 38, @pDoppler.xa * 127 ' mini darbukkah END IF IF (gesture.speedup(3) > gesture.slowdown(3) + sens) THEN mPlay Per.channel, 41, MAX(@pDoppler.xa,@pDoppler.ya,@pDoppler.za) * 127 ' LP darbukkah END IF IF (gesture.speedup(0) > 5) AND (gesture.speedup(1) > 5) AND (gesture.speedup(2) > 5) THEN mPlay Per.channel, 46, 127 ' high bongo END IF END SUB SUB L50_Per_Tambourine () ' 03.11.2018: crotale added gwr ' 07.11.2018: velo scaling improved. STATIC sens AS SINGLE IF ISFALSE sens THEN sens = 1 ' 1.2 END IF IF Gesture.collision(0) > sens THEN mPlay Per.channel, 77, 64 + (@pDoppler.xa * 63) ELSEIF Gesture.collision(1) > sens THEN mPlay Per.channel, 77, 64 + (@pDoppler.ya * 63) END IF IF Gesture.collision(2) > sens THEN mPlay Per.channel, 95, 27 + (@pDoppler.za * 100) ' crotale END IF END SUB SUB L50_Per_Vent () ' propeller motors on notes 58 59 STATIC sens AS SINGLE IF ISFALSE Task(%L50_Per+4).tog THEN sens = 0.3 ' 0.6 Task(%L50_Per+4).tog = %True END IF IF gesture.flue(0) > sens THEN mPlay Per.channel, 58, 64 + (SQR(@pDoppler.xa) * 63) ' modif. gwr 07.11 ELSE mPlay Per.channel, 58, 0 END IF IF gesture.flue(1) > sens THEN mPlay Per.channel, 59, 64 + (SQR(@pDoppler.ya) * 63) ELSE mPlay Per.channel, 59, 0 END IF END SUB SUB L50_Per_Vent_Stop () NoteOff Per.channel, 58 NoteOff Per.channel, 59 END SUB SUB L50_Puff () IF ISFALSE Task(%L50_Per + 5).tog THEN ' lights on: MM_Puff_On %MM_Lights Task(%L50_Per + 5).tog = %True END IF IF (ISFALSE(gesture.explo(0))) AND (gesture.implo(0)> @pDoppler.noise) THEN AddNote2Har Puff.har(1), 55 + @pDoppler.xf/10, 5 + SQR(@pDoppler.xa) * 16 END IF IF (ISFALSE(gesture.explo(1))) AND (gesture.implo(1)> @pDoppler.noise) THEN AddNote2Har Puff.har(1), 55 + @pDoppler.yf/10, 5 + SQR(@pDoppler.ya) * 16 END IF IF (ISFALSE(gesture.explo(2))) AND (gesture.implo(2)> @pDoppler.noise) THEN AddNote2Har Puff.har(1), 55 + @pDoppler.zf/10, 5 + SQR(@pDoppler.za) * 16 END IF InstrumTransposeToRange Puff, 55, 96 InstrumPlay Puff END SUB SUB L50_Puff_Stop () MM_Puff_Off %MM_Lights END SUB SUB L50_Temblo () STATIC c1 AS LONG, c2 AS LONG IF ISFALSE Task(%L50_PER + 6).tog THEN MM_Temblo_On %MM_Lights Task(%L50_Per + 6).tog = %True END IF IF ((@pDoppler.xa > .1) AND (gesture.theacol(0) > .1)) THEN mPlay Temblo.channel, 60 + INT(RND * 6), @pDoppler.xa * 127 END IF IF ((@pDoppler.ya > .1) AND (gesture.theacol(1) > .1)) THEN mPlay Temblo.channel, 72 + INT(RND * 6), @pDoppler.ya * 127 END IF END SUB SUB L50_Temblo_Stop () MM_Temblo_Off %MM_Lights END SUB SUB L50_Toypi () STATIC sens AS LONG IF ISFALSE Task(%L50_Per + 7).tog THEN sens = 60 '40 - more then usual - shouldn't trigger too much MM_Toypi_On %MM_Lights Task(%L50_Per + 7).tog = %True END IF IF (gesture.slowdown(0) > gesture.speedup(0) + sens) THEN AddNote2Har Toypi.Har(1), Toypi.lowtes + 1.2 * SQR(@pDoppler.xf), @pDoppler.xa * 127 IF (gesture.slowdown(1) > gesture.speedup(1) + sens) THEN AddNote2Har Toypi.Har(1),Toypi.lowtes + 1.2 * SQR(@pDoppler.Yf), @pDoppler.Ya * 127 IF (gesture.slowdown(2) > gesture.speedup(2) + sens) THEN AddNote2Har Toypi.Har(1),Toypi.lowtes + 1.2 * SQR(@pDoppler.Zf), @pDoppler.Za * 127 InstrumTransposeToRange Toypi InstrumPlay toypi END SUB SUB L50_Toypi_Stop () MM_Toypi_Off %MM_Lights END SUB SUB L50_Qt () LOCAL note AS CURRENCY IF ISFALSE Task(%L50_Per + 8).tog THEN MM_Qt_ON %MM_Motor MM_Qt_On %MM_Lights Task(%L50_Per + 8).tog = %True END IF IF (ISFALSE gesture.implo(0)) AND (gesture.explo(0)> @pDoppler.noise) THEN note = qt.LowTes + gesture.Explo(0) * 40 DO WHILE note > qt.HighTes: note = note - 12: LOOP note = MatchSpecNote(note, 24, .7) AddNote2Har qt.Har(1), note, 40 END IF IF (ISFALSE gesture.implo(1)) AND (gesture.explo(1)> @pDoppler.noise) THEN note = qt.LowTes + gesture.Explo(1) * 40 DO WHILE note > qt.HighTes: note = note - 12: LOOP note = MatchSpecNote(note, 27, .7) AddNote2Har qt.Har(1), note, 40 END IF IF (ISFALSE gesture.implo(2)) AND (gesture.explo(2)> @pDoppler.noise) THEN note = qt.LowTes + gesture.Explo(2) * 40 DO WHILE note > qt.HighTes: note = note - 12: LOOP note = MatchSpecNote(note, 30, .7) AddNote2Har qt.Har(1), note, 40 END IF Controller Qt.channel, 7, 20 + MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) * 40 InstrumPlay qt END SUB SUB L50_Qt_Stop () MM_Qt_Off ' motor and lights END SUB 'SUB L50_Algo () ' ' melodic patterns based on repeating sequences in rational numbers ' STATIC pat$ ' STATIC num, tog, i, cnt AS LONG ' STATIC oldnote, newnote AS INTEGER ' DIM Mel(0) AS STATIC INTEGER ' ' IF ISFALSE task(%L50_algo).tog THEN ' if isfalse num then num = 5 ' zo dat we met 7 starten: patroon = 142857 ' Task(%L50_algo).tog = %True ' END IF ' IF tog = %False THEN ' ' get a new pattern ' num = NextPrime(num) ' pat$ = RatNumPat(num) ' ' now turn this into a melody ' REDIM Mel(LEN(pat$)) AS STATIC INTEGER ' FOR i = 1 TO LEN(pat$) ' Mel(i) = 60 + VAL(MID$(pat$,i,1)) ' 60 has to become movement speed dependent ' NEXT i ' RESET cnt ' tog = %True ' END IF ' ' newnote = Mel(cnt) ' IF newnote = oldnote THEN ' ' dan verlengen we de duur van de noot... ' ' we zenden dus geen midi kommando ' ELSE ' IF oldnote THEN ' 'NoteOff 0, oldnote ' for test only ' NoteOff Korn.channel, oldnote ' oldnote = %False ' END IF ' 'mPlay 0, newnote, 64 ' for test only ' mPlay Korn.channel, newnote,17 + (MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) * 110) ' oldnote = newnote ' END IF ' ' INCR cnt ' IF cnt > LEN(pat$) THEN ' ' this should stop the task. ' ' task start and restart should happen on collission or jump recognition ' 'NoteOff 0, oldnote ' tog = %False ' Task(%L50_algo).freq = 0.2 ' ELSE ' Task(%L50_algo).freq = 1 + (gesture.velocity(3) * 16) ' moet gesture dependent worden ' END IF 'END SUB SUB L50_AlgoMeta () ' gwr ' this task should start the x,y,z, tasks on collision detection ' 04.10.2018: the slider in this task will steer the sensitivity 'for all other L50 pattern tasks. STATIC slnr AS LONG STATIC sens AS SINGLE IF ISFALSE Task(%L50_Algometa).tog THEN IF ISFALSE Task(%L50_AlgoMeta).hParam THEN DIM TaskParamLabels(0) AS STATIC ASCIIZ * 8 TaskParamLabels(0) = "sens" ' trigger level MakeTaskParameterDialog %L50_AlgoMeta,1,Slider(),0,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(%L50_AlgoMeta).SliderNumbers(0) Slider(slnr).value = 12 SendMessage Slider(slnr).h, %TBM_SETPOS,%True, Slider(slnr).value END IF Task(%L50_Algometa).tog = %True END IF ' STATIC sens AS SINGLE ' IF ISFALSE sens THEN ' sens = 1.2 ' END IF sens = Slider(slnr).value / 10 IF Gesture.collision(0) > sens THEN IF ISFALSE Task(%L50_AlgoX).tog THEN Task(%L50_AlgoX).freq = 4 starttask %L50_AlgoX END IF END IF IF Gesture.collision(1) > sens THEN IF ISFALSE Task(%L50_AlgoY).tog THEN Task(%L50_AlgoY).freq = 4 starttask %L50_AlgoY END IF END IF IF Gesture.collision(2) > sens THEN IF ISFALSE Task(%L50_AlgoZ).tog THEN Task(%L50_AlgoZ).freq = 4 starttask %L50_AlgoZ END IF END IF END SUB SUB L50_AlgoX () ' melodic patterns based on repeating sequences in rational numbers ' Korn part STATIC pat$ STATIC num, tog, i, cnt, init AS LONG STATIC oldnote, newnote, einde AS INTEGER DIM Mel(0) AS STATIC INTEGER IF ISFALSE task(%L50_algoX).tog THEN IF ISFALSE init THEN ' send controllers for Korn once Controller Korn.channel, 66, 64 Controller Korn.channel, 17, 127 Controller Korn.channel, 18, 105 init = %True END IF einde = 0 IF ISFALSE num THEN num = 5 ' zo dat we met 7 starten: patroon = 142857 'mPlay Korn.channel, 124, 127 ' licht MM_Korn_On %MM_Blue ' tungsten kan ook Task(%L50_algoX).tog = %True END IF IF einde = 1 THEN einde = 0 IF oldnote THEN NoteOff Korn.channel, oldnote oldnote = %False 'NoteOff Korn.channel, 124 MM_Korn_Off %MM_Blue stoptask %L50_algoX EXIT SUB END IF IF tog = %False THEN ' get a new pattern num = NextPrime(num) pat$ = RatNumPat(num) ' now turn this into a melody REDIM Mel(LEN(pat$)) AS STATIC INTEGER FOR i = 1 TO LEN(pat$) Mel(i) = 60 + VAL(MID$(pat$,i,1)) ' 60 has to become movement speed dependent NEXT i RESET cnt tog = %True END IF newnote = Mel(cnt) IF newnote = oldnote THEN ' dan verlengen we de duur van de noot... ' we zenden dus geen midi kommando ELSE IF oldnote THEN 'NoteOff 0, oldnote ' for test only NoteOff Korn.channel, oldnote oldnote = %False END IF 'mPlay 0, newnote, 64 ' for test only mPlay Korn.channel, newnote,17 + (@pDoppler.xa * 110) '(MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) * 110) oldnote = newnote END IF INCR cnt IF cnt > LEN(pat$) THEN ' this should stop the task. ' task start and restart should happen on collission or jump recognition 'NoteOff 0, oldnote tog = %False Task(%L50_algoX).freq = 0.2 einde = 1 ELSE Task(%L50_algoX).freq = 1 + (gesture.velocity(0) * 16) ' moet gesture dependent worden END IF END SUB SUB L50_AlgoY () ' melodic patterns based on repeating sequences in rational numbers ' asa part STATIC pat$ STATIC num, tog, i, cnt, init AS LONG STATIC oldnote, newnote, einde AS INTEGER DIM Mel(0) AS STATIC INTEGER IF ISFALSE task(%L50_algoY).tog THEN IF ISFALSE init THEN ' send controllers for Asa once Controller Asa.channel, 66, 64 Controller Asa.channel, 1, 6 Controller Asa.channel, 2, 1 Controller Asa.channel, 3, 20 Controller Asa.channel, 4, 8 Controller Asa.channel, 5, 2 Controller Asa.channel, 6, 14 Controller Asa.channel, 7, 127 Controller Asa.channel, 16, 20 Controller Asa.channel, 17, 120 Controller Asa.channel, 18, 85 Controller Asa.channel, 19, 89 Controller Asa.channel, 25, 100 Controller Asa.channel, 26, 81 Controller Asa.channel, 29, 10 init = %True END IF einde = 0 IF ISFALSE num THEN num = 5 ' zo dat we met 7 starten: patroon = 142857 MM_Asa_On %MM_White Task(%L50_algoY).tog = %True END IF IF einde = 1 THEN einde = 0 IF oldnote THEN NoteOff Asa.channel, oldnote oldnote = %False MM_Asa_Off %MM_White stoptask %L50_algoY EXIT SUB END IF IF tog = %False THEN ' get a new pattern num = NextPrime(num) pat$ = RatNumPat(num) ' now turn this into a melody REDIM Mel(LEN(pat$)) AS STATIC INTEGER FOR i = 1 TO LEN(pat$) Mel(i) = 60 + VAL(MID$(pat$,i,1)) ' 60 has to become movement speed dependent NEXT i RESET cnt tog = %True END IF newnote = Mel(cnt) IF newnote = oldnote THEN ' dan verlengen we de duur van de noot... ' we zenden dus geen midi kommando ELSE IF oldnote THEN 'NoteOff 0, oldnote ' for test only NoteOff Asa.channel, oldnote oldnote = %False END IF 'mPlay 0, newnote, 64 ' for test only mPlay Asa.channel, newnote,17 + (@pDoppler.ya * 110) '(MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) * 110) oldnote = newnote END IF INCR cnt IF cnt > LEN(pat$) THEN ' this should stop the task. ' task start and restart should happen on collission or jump recognition 'NoteOff 0, oldnote tog = %False Task(%L50_algoY).freq = 0.2 einde = 1 ELSE Task(%L50_algoY).freq = 1 + (gesture.velocity(1) * 16) ' moet gesture dependent worden END IF END SUB SUB L50_AlgoZ () ' melodic patterns based on repeating sequences in rational numbers ' fa part, as klar is not available... STATIC pat$ STATIC num, tog, i, cnt, init AS LONG STATIC oldnote, newnote, einde AS INTEGER DIM Mel(0) AS STATIC INTEGER IF ISFALSE task(%L50_algoZ).tog THEN IF ISFALSE num THEN num = 5 ' zo dat we met 7 starten: patroon = 142857 IF ISFALSE init THEN ' send controllers for once Controller Fa.channel, 66, 64 Controller Fa.channel, 1, 3 ' noise Controller Fa.channel, 2, 2 Controller Fa.channel, 3, 20 ' vibrato Controller Fa.channel, 4, 8 Controller Fa.channel, 7, 9 ' volume - checked. Controller Fa.channel, 16, 80 Controller Fa.channel, 17, 127 Controller Fa.channel, 18, 90 Controller Fa.channel, 25, 75 Controller Fa.channel, 26, 100 Controller Fa.channel, 29, 21 ' lfo init = %True END IF MM_Fa_On %MM_Yellow Task(%L50_algoZ).tog = %True END IF IF einde = 1 THEN einde = 0 IF oldnote THEN NoteOff Fa.channel, oldnote oldnote = %False MM_Fa_Off %MM_Yellow stoptask %L50_algoZ EXIT SUB END IF IF tog = %False THEN ' get a new pattern num = NextPrime(num) pat$ = RatNumPat(num) ' now turn this into a melody REDIM Mel(LEN(pat$)) AS STATIC INTEGER FOR i = 1 TO LEN(pat$) Mel(i) = 60 + VAL(MID$(pat$,i,1)) ' 60 has to become movement speed dependent NEXT i RESET cnt tog = %True END IF newnote = Mel(cnt) IF newnote = oldnote THEN ' dan verlengen we de duur van de noot... ' we zenden dus geen midi kommando ELSE IF oldnote THEN 'NoteOff 0, oldnote ' for test only NoteOff Fa.channel, oldnote oldnote = %False END IF 'mPlay 0, newnote, 64 ' for test only mPlay Fa.channel, newnote,17 + (@pDoppler.za * 110) '(MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) * 110) oldnote = newnote END IF INCR cnt IF cnt > LEN(pat$) THEN ' this should stop the task. ' task start and restart should happen on collission or jump recognition 'NoteOff 0, oldnote tog = %False Task(%L50_algoZ).freq = 0.2 einde = 1 ELSE Task(%L50_algoZ).freq = 1 + (gesture.velocity(1) * 16) ' moet gesture dependent worden END IF END SUB SUB L50_DozMeta () ' this task should start the x,y,z, tasks on collision detection STATIC sens AS SINGLE STATIC slnr AS LONG IF ISFALSE Task(%L50_Dozmeta).tog THEN IF ISFALSE Task(%L50_AlgoMeta).hParam THEN ' not a bug! DIM TaskParamLabels(0) AS STATIC ASCIIZ * 8 TaskParamLabels(0) = "sens" ' trigger level MakeTaskParameterDialog %L50_AlgoMeta,1,Slider(),0,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(%L50_AlgoMeta).SliderNumbers(0) Slider(slnr).value = 12 SendMessage Slider(slnr).h, %TBM_SETPOS,%True, Slider(slnr).value END IF Task(%L50_Dozmeta).tog = %True END IF ' IF ISFALSE sens THEN ' sens = 1.2 ' END IF sens = Slider(slnr).value / 10.0 IF Gesture.collision(0) > sens THEN IF ISFALSE Task(%L50_DozX).tog THEN Task(%L50_DozX).freq = 4 starttask %L50_DozX END IF END IF IF Gesture.collision(1) > sens THEN IF ISFALSE Task(%L50_DozY).tog THEN Task(%L50_DozY).freq = 4 starttask %L50_DozY END IF END IF IF Gesture.collision(2) > sens THEN IF ISFALSE Task(%L50_DozZ).tog THEN Task(%L50_DozZ).freq = 4 starttask %L50_DozZ END IF END IF END SUB SUB L50_DozX () ' melodic patterns based on repeating sequences in rational numbers ' using dozenal numbers STATIC pat$, d$ STATIC num, tog, i, cnt, init AS LONG STATIC oldnote, newnote, einde AS INTEGER DIM Mel(0) AS STATIC INTEGER IF ISFALSE task(%L50_dozX).tog THEN IF ISFALSE init THEN ' send controllers for Ob once Controller Ob.channel, 66, 64 Controller Ob.channel, 17, 127 Controller Ob.channel, 18, 105 init = %True END IF einde = 0 IF ISFALSE num THEN num = 5 ' zo dat we met 7 starten: patroon = 142857 MM_Ob_On %MM_White Task(%L50_dozX).tog = %True END IF IF einde = 1 THEN einde = 0 IF oldnote THEN NoteOff Ob.channel, oldnote oldnote = %False MM_Ob_Off %MM_White stoptask %L50_dozX EXIT SUB END IF IF tog = %False THEN ' get a new pattern num = NextPrime(num) pat$ = RatNumPat(num) ' convert this to a dozenal number string: pat$ = DecStr2DuoDec(pat$) ' new in g_indep.dll ' now turn this into a melody REDIM Mel(LEN(pat$)) AS STATIC INTEGER FOR i = 1 TO LEN(pat$) d$ = MID$(pat$,i,1) d$ = "&H" & d$ Mel(i) = 60 + VAL(d$) ' 60 has to become movement speed dependent NEXT i RESET cnt tog = %True END IF newnote = Mel(cnt) IF newnote = oldnote THEN ' dan verlengen we de duur van de noot... ' we zenden dus geen midi kommando ELSE IF oldnote THEN NoteOff Ob.channel, oldnote oldnote = %False END IF mPlay Ob.channel, newnote,17 + (@pDoppler.xa * 110) '(MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) * 110) oldnote = newnote END IF INCR cnt IF cnt > LEN(pat$) THEN ' this should stop the task. ' task start and restart should happen on collission or jump recognition 'NoteOff 0, oldnote tog = %False Task(%L50_dozX).freq = 0.3 ' somewhat shorter than in the AlgoX version einde = 1 ELSE Task(%L50_dozX).freq = 1 + (gesture.velocity(0) * 16) ' moet gesture dependent worden END IF END SUB SUB L50_DozY () ' melodic patterns based on repeating sequences in rational numbers ' using dozenal numbers STATIC pat$, d$ STATIC num, tog, i, cnt, init AS LONG STATIC oldnote, newnote, einde AS INTEGER DIM Mel(0) AS STATIC INTEGER IF ISFALSE task(%L50_dozY).tog THEN IF ISFALSE init THEN ' send controllers for Ob once Controller Autosax.channel, 66, 64 Controller Autosax.channel, 17, 127 Controller Autosax.channel, 18, 105 init = %True END IF einde = 0 IF ISFALSE num THEN num = 5 ' zo dat we met 7 starten: patroon = 142857 MM_Autosax_On %MM_Lights Task(%L50_dozY).tog = %True END IF IF einde = 1 THEN einde = 0 IF oldnote THEN NoteOff Autosax.channel, oldnote oldnote = %False MM_Autosax_Off %MM_Lights stoptask %L50_dozY EXIT SUB END IF IF tog = %False THEN ' get a new pattern num = NextPrime(num) pat$ = RatNumPat(num) ' convert this to a dozenal number string: pat$ = DecStr2DuoDec(pat$) ' new in g_indep.dll ' now turn this into a melody REDIM Mel(LEN(pat$)) AS STATIC INTEGER FOR i = 1 TO LEN(pat$) d$ = MID$(pat$,i,1) d$ = "&H" & d$ ' 0 - 11 Mel(i) = 60 + VAL(d$) ' 60 has to become movement speed dependent NEXT i RESET cnt tog = %True END IF newnote = Mel(cnt) IF newnote = oldnote THEN ' dan verlengen we de duur van de noot... ' we zenden dus geen midi kommando ELSE IF oldnote THEN NoteOff Autosax.channel, oldnote oldnote = %False END IF mPlay Autosax.channel, newnote,17 + (@pDoppler.ya * 110) '(MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) * 110) oldnote = newnote END IF INCR cnt IF cnt > LEN(pat$) THEN ' this should stop the task. ' task start and restart should happen on collission or jump recognition 'NoteOff 0, oldnote tog = %False Task(%L50_dozY).freq = 0.3 ' somewhat shorter than in the AlgoY version einde = 1 ELSE Task(%L50_dozY).freq = 1 + (gesture.velocity(1) * 16) 'gesture dependent END IF END SUB SUB L50_DozZ () ' melodic patterns based on repeating sequences in rational numbers ' using dozenal numbers ' 04.20.2018: controller init corrected. STATIC pat$, d$ STATIC num, tog, i, cnt, init AS LONG STATIC oldnote, newnote, einde AS INTEGER DIM Mel(0) AS STATIC INTEGER IF ISFALSE task(%L50_dozZ).tog THEN IF ISFALSE init THEN ' send controllers for Heli once Controller Heli.channel, 66, 64 Controller Heli.channel, 7, 12 Controller Heli.channel, 17, 40 Controller Heli.channel, 18, 125 Controller Heli.channel, 19, 119 init = %True END IF einde = 0 IF ISFALSE num THEN num = 5 ' zo dat we met 7 starten: patroon = 142857 MM_Heli_On %MM_Lights Task(%L50_dozZ).tog = %True END IF IF einde = 1 THEN einde = 0 IF oldnote THEN NoteOff Heli.channel, oldnote oldnote = %False MM_Heli_Off %MM_Lights stoptask %L50_dozZ EXIT SUB END IF IF tog = %False THEN ' get a new pattern num = NextPrime(num) pat$ = RatNumPat(num) ' convert this to a dozenal number string: pat$ = DecStr2DuoDec(pat$) ' new in g_indep.dll ' now turn this into a melody REDIM Mel(LEN(pat$)) AS STATIC INTEGER FOR i = 1 TO LEN(pat$) d$ = MID$(pat$,i,1) d$ = "&H" & d$ ' 0 - 11 Mel(i) = 60 + VAL(d$) ' 60 has to become movement speed dependent NEXT i RESET cnt tog = %True END IF newnote = Mel(cnt) IF newnote = oldnote THEN ' dan verlengen we de duur van de noot... ' we zenden dus geen midi kommando ELSE IF oldnote THEN NoteOff Heli.channel, oldnote oldnote = %False END IF mPlay Heli.channel, newnote,64 + (@pDoppler.za * 63) 'scale adjusted 04.10.2018 oldnote = newnote END IF INCR cnt IF cnt > LEN(pat$) THEN ' this should stop the task. ' task start and restart should happen on collission or jump recognition 'NoteOff 0, oldnote tog = %False Task(%L50_dozZ).freq = 0.3 ' somewhat shorter than in the AlgoX version einde = 1 ELSE Task(%L50_dozZ).freq = 1 + (gesture.velocity(2) * 16) ' gesture dependent END IF END SUB ' now, an orchestration for Spiro, Vibi, Hybr SUB L50_Meta () ' this task should start the x,y,z, tasks on collision detection STATIC sens AS SINGLE STATIC slnr AS LONG IF ISFALSE Task(%L50_meta).tog THEN IF ISFALSE Task(%L50_AlgoMeta).hParam THEN ' not a bug! DIM TaskParamLabels(0) AS STATIC ASCIIZ * 8 TaskParamLabels(0) = "sens" ' trigger level MakeTaskParameterDialog %L50_AlgoMeta,1,Slider(),0,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(%L50_AlgoMeta).SliderNumbers(0) Slider(slnr).value = 12 SendMessage Slider(slnr).h, %TBM_SETPOS,%True, Slider(slnr).value END IF Task(%L50_meta).tog = %True END IF sens = Slider(slnr).value / 10.0 IF Gesture.collision(0) > sens THEN IF ISFALSE Task(%L50_X).tog THEN Task(%L50_X).freq = 4 starttask %L50_X END IF END IF IF Gesture.collision(1) > sens THEN IF ISFALSE Task(%L50_Y).tog THEN Task(%L50_Y).freq = 4 starttask %L50_Y END IF END IF IF Gesture.collision(2) > sens THEN IF ISFALSE Task(%L50_Z).tog THEN Task(%L50_Z).freq = 4 starttask %L50_Z END IF END IF END SUB SUB L50_X () ' melodic patterns based on repeating sequences in rational numbers ' using dozenal numbers ' Spiro part STATIC pat$, d$ STATIC num, tog, i, cnt, init AS LONG STATIC oldnote, newnote, einde AS INTEGER DIM Mel(0) AS STATIC INTEGER IF ISFALSE task(%L50_X).tog THEN IF ISFALSE init THEN ' send controllers for Spiro once Controller Spiro.channel, 66, 127 init = %True END IF einde = 0 IF ISFALSE num THEN num = 5 ' zo dat we met 7 starten: patroon = 142857 MM_Spiro_On %MM_Lights Task(%L50_X).tog = %True END IF IF einde = 1 THEN einde = 0 IF oldnote THEN NoteOff Spiro.channel, oldnote oldnote = %False MM_Spiro_Off %MM_Lights stoptask %L50_X EXIT SUB END IF IF tog = %False THEN ' get a new pattern num = NextPrime(num) pat$ = RatNumPat(num) ' convert this to a dozenal number string: pat$ = DecStr2DuoDec(pat$) ' new in g_indep.dll ' now turn this into a melody REDIM Mel(LEN(pat$)) AS STATIC INTEGER FOR i = 1 TO LEN(pat$) d$ = MID$(pat$,i,1) d$ = "&H" & d$ Mel(i) = 67 + VAL(d$) NEXT i RESET cnt tog = %True END IF newnote = Mel(cnt) IF newnote = oldnote THEN ' dan verlengen we de duur van de noot... ' we zenden dus geen midi kommando ELSE IF oldnote THEN NoteOff Spiro.channel, oldnote oldnote = %False END IF mPlay Spiro.channel, newnote, 20 ' 17 + (@pDoppler.xa * 110) '(MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) * 110) oldnote = newnote END IF INCR cnt IF cnt > LEN(pat$) THEN ' this should stop the task. ' task start and restart should happen on collission or jump recognition 'NoteOff 0, oldnote tog = %False Task(%L50_X).freq = 0.4 ' somewhat shorter than in the AlgoX And Dozx version einde = 1 ELSE Task(%L50_X).freq = 1 + (gesture.velocity(0) * 16) ' moet gesture dependent worden END IF END SUB SUB L50_Y () ' melodic patterns based on repeating sequences in rational numbers ' using dozenal numbers ' Vibi part STATIC pat$, d$ STATIC num, tog, i, cnt, init AS LONG STATIC oldnote, newnote, einde AS INTEGER DIM Mel(0) AS STATIC INTEGER IF ISFALSE task(%L50_Y).tog THEN IF ISFALSE init THEN ' send controllers for Vibi once Controller Vibi.channel, 66, 127 init = %True END IF einde = 0 IF ISFALSE num THEN num = 5 ' zo dat we met 7 starten: patroon = 142857 MM_Vibi_On %MM_Lights Task(%L50_Y).tog = %True END IF IF einde = 1 THEN einde = 0 IF oldnote THEN NoteOff Spiro.channel, oldnote oldnote = %False MM_Vibi_Off %MM_Lights stoptask %L50_Y EXIT SUB END IF IF tog = %False THEN ' get a new pattern num = NextPrime(num) pat$ = RatNumPat(num) ' convert this to a dozenal number string: pat$ = DecStr2DuoDec(pat$) ' new in g_indep.dll ' now turn this into a melody REDIM Mel(LEN(pat$)) AS STATIC INTEGER FOR i = 1 TO LEN(pat$) d$ = MID$(pat$,i,1) d$ = "&H" & d$ ' 0 - 11 Mel(i) = 60 + VAL(d$) ' 60 has to become movement speed dependent NEXT i RESET cnt tog = %True END IF newnote = Mel(cnt) IF newnote = oldnote THEN ' dan verlengen we de duur van de noot... ' we zenden dus geen midi kommando ELSE IF oldnote THEN NoteOff Vibi.channel, oldnote oldnote = %False END IF mPlay Vibi.channel, newnote,17 + (@pDoppler.ya * 110) '(MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) * 110) oldnote = newnote END IF INCR cnt IF cnt > LEN(pat$) THEN ' this should stop the task. ' task start and restart should happen on collission or jump recognition 'NoteOff 0, oldnote tog = %False Task(%L50_Y).freq = 0.4 ' somewhat shorter than in the AlgoY version einde = 1 ELSE Task(%L50_Y).freq = 1 + (gesture.velocity(1) * 16) 'gesture dependent END IF END SUB SUB L50_Z () ' melodic patterns based on repeating sequences in rational numbers ' using dozenal numbers ' Hybr mapping STATIC pat$, d$ STATIC num, tog, i, cnt, init AS LONG STATIC oldnote, newnote, einde AS INTEGER DIM Mel(0) AS STATIC INTEGER IF ISFALSE task(%L50_Z).tog THEN IF ISFALSE init THEN ' send no controllers for Hybr for now... MM_Hybr_On init = %True END IF einde = 0 IF ISFALSE num THEN num = 5 ' zo dat we met 7 starten: patroon = 142857 MM_Hybr_On %MM_Lights Task(%L50_Z).tog = %True END IF IF einde = 1 THEN einde = 0 IF oldnote THEN NoteOff Hybr.channel, oldnote oldnote = %False MM_Hybr_Off %MM_Lights stoptask %L50_Z EXIT SUB END IF IF tog = %False THEN ' get a new pattern num = NextPrime(num) pat$ = RatNumPat(num) ' convert this to a dozenal number string: pat$ = DecStr2DuoDec(pat$) ' new in g_indep.dll ' now turn this into a melody REDIM Mel(LEN(pat$)) AS STATIC INTEGER FOR i = 1 TO LEN(pat$) d$ = MID$(pat$,i,1) d$ = "&H" & d$ ' 0 - 11 Mel(i) = 43 + VAL(d$) NEXT i RESET cnt tog = %True END IF newnote = Mel(cnt) IF newnote = oldnote THEN ' dan verlengen we de duur van de noot... ' we zenden dus geen midi kommando ELSE IF oldnote THEN NoteOff Hybr.channel, oldnote oldnote = %False END IF mPlay Hybr.channel, newnote,20 + (@pDoppler.za * 100) oldnote = newnote END IF INCR cnt IF cnt > LEN(pat$) THEN ' this should stop the task. ' task start and restart should happen on collission or jump recognition 'NoteOff 0, oldnote tog = %False Task(%L50_Z).freq = 0.4 ' somewhat shorter than in the AlgoX version einde = 1 ELSE Task(%L50_Z).freq = 1 + (gesture.velocity(2) * 16) ' gesture dependent END IF END SUB SUB L50_chi () 'niet interactief - gewoon over en weer STATIC note AS BYTE LOCAL cc74 AS BYTE LOCAL cc75 AS BYTE IF ISFALSE Task(%L50_Chi).tog THEN MM_Chi_On note = 100 'apparently notes 100 and 101 only start working after 102 has been sent??? mPlay chi.channel, 102, 40 Task(%L50_Chi).tog = %True EXIT SUB END IF SELECT CASE note CASE 100 note = 101 CASE ELSE note = 100 END SELECT 'randomize end points a bit cc74 = 10 + RND * 20 cc75 = cc74 + 30 + RND * 40 controller chi.channel, 74, cc74 controller chi.channel, 75,cc75 mPlay Chi.channel, note, 1 + RND * 10 'keep it slow task(%L50_chi).freq = .1 + RND^2 'CONTROL SET TEXT gh.cockpit, %GMT_MSG1, STR$(note) END SUB SUB L50_Tinti () 'overgenomen uit koudvuur 'blijkt niet goed te werken... STATIC n AS INTEGER STATIC mtv AS SINGLE STATIC tt AS DWORD IF ISFALSE Task(%L50_Tinti).tog THEN n = tinti.lowtes MM_Tinti_On MM_Tinti_On %MM_Tungsten controller tinti.channel, 30, 0 Controller Tinti.channel, 31, 16 mtv = .1 'amp trigger value (freeze itself is 0/1 Task(%L50_Tinti).tog = %True END IF ' logfile FUNCNAME$ + STR$(Gesture.freeze(0)) + STR$(Gesture.freeze(1)) + STR$(Gesture.freeze(2)) IF ((Gesture.freeze(0) + gesture.freeze(1) + gesture.freeze(2)) >= 1) AND (MAX(@pDoppler.xa, @pDoppler.ya,@pDoppler.za) > mtv) THEN mPlay Tinti.channel, n, 40 n = n + CHOOSE(1 + INT(RND * 4), -1, 0 ,0, 1) ' logfile FUNCNAME$ + "n"+ STR$(n) IF n < Tinti.Lowtes THEN n = n + 12 IF n > Tinti.Hightes THEN n = n - 12 Bend Tinti.channel, 0 , MIN(127, 512 * @pDoppler.xa) controller Tinti.channel, 7, MIN(127, 512 * MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za)) ' logfile "bnd:"+ STR$(MIN(127, 512 * @pDoppler.xa)) + "- cc7: " + STR$( MIN(127, 512 * MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za)) ) ELSEIF timegettime > tt THEN tt = timegettime + 1000 + (RND * 2000) ' logfile "tinti d carrier" Controller Tinti.channel, 31, 12 + (RND * 7) END IF END SUB SUB L50_Tinti_Stop () MM_Tinti_Off END SUB SUB L50_ThCol_Chi () ' theatrical collision op Chi STATIC mintrigval AS SINGLE, colval AS SINGLE IF ISFALSE Task(%L50_ThCol_Chi).tog THEN controller chi.channel, 66, 127 controller chi.channel, 74, 10 controller chi.channel, 75, 107 'MM_Chi_On mintrigval = .2 colval = 2.2 Task(%L50_ThCol_Chi).tog = %True END IF ' logfile FUNCNAME$ + STR$(gesture.TheaCol(0)) + STR$(gesture.TheaCol(1)) + STR$(gesture.TheaCol(2)) IF ((@pDoppler.xa > mintrigval) AND (gesture.TheaCol(0) > colval)) THEN mPlay Chi.channel, 96, @pDoppler.xa * 127 EXIT SUB ' ávoid simult left and right END IF IF ((@pDoppler.ya > mintrigval) AND (gesture.TheaCol(1) > colval)) THEN mPlay Chi.channel, 97, @pDoppler.ya * 127 EXIT SUB END IF IF ((@pDoppler.za > mintrigval) AND (gesture.TheaCol(2) > colval)) THEN mPlay Chi.channel, 99, @pDoppler.ya * 127 EXIT SUB END IF Controller Chi.channel, 123, 1 ' notes off END SUB SUB L50_Tinti_Smt () ' from begin, 2017 STATIC n AS INTEGER STATIC mtv AS SINGLE IF ISFALSE Task(%L50_Tinti_Smt).tog THEN n = tinti.lowtes MM_Tinti_On %MM_Tungsten Controller Tinti.channel, 66,127 Controller Tinti.channel, 65, 127 controller Tinti.channel, 7, 100 Controller Tinti.channel, 8, 100 controller Tinti.channel, 30, 90 Tinti.ctrl(31) = 10 mtv = .1 'amp trigger value (freeze itself is 0/1 Task(%L50_Tinti_Smt).tog = %True END IF IF (gesture.smooth_dur(3)) AND (MAX(@pDoppler.xa, @pdoppler.ya, @pDoppler.za) > .1) THEN AddNote2Har Tinti.Har(1), n, MAX(@pDoppler.xa, @pdoppler.ya, @pDoppler.za) * 100 n = n + CHOOSE(1 + INT(RND * 4), -1, 0 ,0, 1) IF n < Tinti.Lowtes THEN n = n + 12 IF n > Tinti.Hightes THEN n = n - 12 END IF InstrumPlay Tinti Tinti.ctrl(31) = (3 * Tinti.ctrl(31) + MIN(28, @pDoppler.xf + @pDoppler.yf)) / 4 controller Tinti.channel, 31, Tinti.ctrl(31) END SUB