' ***************************************** ' * Namuda Study #43 * ' * "Derivatives" * ' * february 2014 * ' * Namuda Study #44 * ' * "Rods for Rodo" * ' * april 2014 * ' ***************************************** ' testbed for higher order derivates as tool for gesture recognition ' start coding: january 2014 ' 07.02.2014: Workable demo's ready ' 08.02.2014: demo's for up to the third derivative ready. ' generalisable function for derivatives added. ' 09.02.2014: Gesture_type extended for inclusion of the derivatives ' 1th, 2nd and 3th derivative calculation added in gesture analyser ' First test and rehearsal session with Dominica Eyckmans ' 11.02.2014: frequency calculation based on the first derivative added in g_h.dll ' dopplertype extended. ' This caused the entire engine to crash! ' so we took it out again. ' We will have to try coding it as a separate procedure in g_h.dll ' 12.02.2014: all derivative code in the gesture analyser now works. ' 13.02.2014: Rehearsal with Dominica. ' to do: add ending with whispers. ' task names in cockpit changed for ease of performance. ' Code cleanup. ' ending added for #43 ' 06.04.2014 Namuda Study #44 added: for Rodo solo... ' first rehearsal with dominica '**************************************************************************************** 'NOTE: score for 'Namuda Study #43' goes as follows: ' 1.- %deriv_1 piano, xy, troms (bring sensit. for xy down gradually) #43.1 ' 2.- %deriv_2 vibi - toypi #43.2 ' 3.- %deriv_3 winds dF based #43.3 ' 4.- %ds_tst piano, klung, dF based #43.4 ' 5.- %deriv_5 organs on dS #43.5 ' 6.- %deriv_4 on puff and tubi, dS3 based. Switch off tubi near the end #43.6 ' stopping this will start whisper shakers '**************************************************************************************** 'TYPE Derivatives_Type DWORD ' only for code development and testing ' dS1x AS SINGLE ' dS1y AS SINGLE ' dS1z AS SINGLE ' dS1max AS SINGLE ' dS1min AS SINGLE ' ds1scalefactor_pos AS SINGLE ' dS1Scalefactor_neg AS SINGLE ' dS2x AS SINGLE ' dS2y AS SINGLE ' dS2z AS SINGLE ' dS2max AS SINGLE ' dS2min AS SINGLE ' dS2Scalefactor AS SINGLE ' dS3x AS SINGLE ' dS3y AS SINGLE ' dS3z AS SINGLE ' dS3max AS SINGLE ' dS3min AS SINGLE ' dS3Scalefactor AS SINGLE 'END TYPE ' if found meaningfull, we could add these data to the gesture_type by adding: ' dS1(3) ' dS2(3) ' dS3(3) ' and the calculation parameters too ' Done 09.02.2014 'GLOBAL Derivatives AS Derivatives_Type DECLARE FUNCTION Init_Deriv () AS LONG DECLARE SUB Deriv_1 () DECLARE SUB Deriv_1_new () DECLARE SUB Deriv_2 () ' vibi-toypi DECLARE SUB Shakes () ' ending 'DECLARE SUB Calc_Derivatives %deriv_1 = 17 ' piano... first coding %deriv_3 = 18 ' winds , mapped on second derivative of speed ' #43.3 %ds_tst = 19 ' test for the first and second derivative of speed in xf(), yf(), zf() - the procedure is called F_test ' #43.4 '%deriv_4_old = 21 '%ds_Calc = 31 %deriv_1_new = 32 ' rewrite of %deriv_1 - #43.1 %deriv_2 = 33 ' vibi-toypi - #43.2 %deriv_5 = 36 ' this one uses the newly added fields for surface derivatives in the gesture type ' #43.5 %deriv_4 = 37 ' puff-tubi demo for 3th derivative of surface ' #43.6 %shakes = 38 ' ending with whisper %d_speed = 40 ' experiment with speed calculation derived from the first derivative of the buffer ' this code should find a place in the gesture analyser itself. %d_accel = 41 %d_3 = 42 %display_deriv = 63 '************************************ 'procedures for Rods for Rodo * ' Namuda Study #44 * '************************************ '05.04.2014 '06.04.2014: First rehearsal with dominica TYPE RodoRods_Type DWORD note AS SINGLE f0 AS SINGLE f1 AS SINGLE f2 AS SINGLE f3 AS SINGLE f4 AS SINGLE f5 AS SINGLE n0 AS CUR n1 AS CUR n2 AS CUR n3 AS CUR n4 AS CUR n5 AS CUR END TYPE GLOBAL Rods() AS RodoRods_Type '4e kolom: %Rodo_Pt1 = 48 ' 3 playing tasks %Rodo_Pt2 = 49 %Rodo_Pt3 = 50 %Rodo_P1 = 52 %Rodo_P2 = 53 %Rodo_P3 = 54 %Rodo_P4 = 55 %Rodo_P5 = 56 %Rodo_P6 = 57 FUNCTION Init_Deriv () AS LONG Task(%deriv_1).naam = "dS1" ' uses troms, piano and xy Task(%deriv_1).cptr = CODEPTR(Deriv_1) ' testcoding Task(%deriv_1).freq = 256 Task(%deriv_1).flags = %False TaskEX(%deriv_1).stopCptr = CODEPTR(MM_Piano_Off) Task(%deriv_1_new).naam = "#43.1" ' uses troms, piano and xy Task(%deriv_1_new).cptr = CODEPTR(Deriv_1_new) Task(%deriv_1_new).freq = 256 Task(%deriv_1_new).flags = %False TaskEX(%deriv_1_new).stopCptr = CODEPTR(MM_Piano_Off) ' Task(%deriv_2).naam = "#43.2" ' vibi - toypi Task(%deriv_2).cptr = CODEPTR(Deriv_2) Task(%deriv_2).freq = 256 Task(%deriv_2).flags = %False ' Task(%deriv_3).naam = "#43.3" ' second derivative of speed Task(%deriv_3).cptr = CODEPTR(Deriv_3) Task(%deriv_3).freq = 32 '64 '256 Task(%deriv_3).flags = %False TaskEX(%deriv_3).stopCptr = CODEPTR(Deriv_3_Stop) Task(%dS_tst).naam = "#43.4" ' test for xf,yf,zf 1th and 2nd derivatives Task(%dS_tst).cptr = CODEPTR(F_test) Task(%dS_tst).freq = 256 Task(%dS_tst).flags = %False Task(%deriv_5).naam = "#43.5" ' ds5 derivatives of surface Task(%deriv_5).cptr = CODEPTR(Deriv_5) Task(%deriv_5).freq = 64 '256 Task(%deriv_5).flags = %False TaskEX(%deriv_5).stopcptr = CODEPTR(Deriv_5_Stop) Task(%deriv_4).naam = "#43.6" ' ds3 third derivative of surface Task(%deriv_4).cptr = CODEPTR(Deriv_4) ' test kode on Puff en Tubi Task(%deriv_4).freq = 100 '256 Task(%deriv_4).flags = %False TaskEX(%deriv_4).stopcptr = CODEPTR(Deriv_4_Stop) Task(%shakes).naam = "#43-end" ' ending with Whisper Task(%shakes).cptr = CODEPTR(Shakes) Task(%shakes).freq = 2 Task(%shakes).flags = %False ' Task(%dS_Calc).naam = "Calc" ' calculating all derivatives - only used as a testbed for code development ' Task(%dS_Calc).cptr = CODEPTR(Calc_Derivatives) ' Task(%dS_Calc).freq = 256 ' Task(%dS_Calc).flags = %False ' testing the F-derivatives integrated in gesture_type: Task(%d_speed).naam = "Speed" ' - only used as a testbed for code development Task(%d_speed).cptr = CODEPTR(Deriv_Speed) Task(%d_speed).freq = 16 Task(%d_speed).flags = %False Task(%d_accel).naam = "Accel" ' - only used as a testbed for code development Task(%d_accel).cptr = CODEPTR(Deriv_Accel) Task(%d_accel).freq = 16 Task(%d_accel).flags = %False Task(%d_3).naam = "dAcc" ' - only used as a testbed for code development Task(%d_3).cptr = CODEPTR(Deriv_dAcc) Task(%d_3).freq = 16 Task(%d_3).flags = %False Task(%display_deriv).naam = "displays" Task(%display_deriv).freq = 12 Task(%display_deriv).cptr = CODEPTR(Display_derivs) Task(%display_deriv).flags = %PERTIM_TASK ' for rodo piece... DIM Rods(0 TO 30) AS GLOBAL RodoRods_Type Task(%Rodo_P1).naam = "Rodo1" Task(%Rodo_P1).cptr = CODEPTR(Rodo_P1) Task(%Rodo_P1).freq = 0.5 Task(%Rodo_P1).flags = %False Taskex(%Rodo_P1).stopcptr = CODEPTR(Rodo_p1_Stop) Task(%Rodo_P2).naam = "Rodo2" Task(%Rodo_P2).cptr = CODEPTR(Rodo_P2) Task(%Rodo_P2).freq = 0.4 Task(%Rodo_P2).flags = %False Taskex(%Rodo_P2).stopcptr = CODEPTR(Rodo_P1_Stop) ' not a bug! Task(%Rodo_P3).naam = "Rodo3" Task(%Rodo_P3).cptr = CODEPTR(Rodo_P3) Task(%Rodo_P3).freq = 1 Task(%Rodo_P3).flags = %False Taskex(%Rodo_P3).stopcptr = CODEPTR(Rodo_P3_Stop) Task(%Rodo_P4).naam = "Rodo4" Task(%Rodo_P4).cptr = CODEPTR(Rodo_P4) Task(%Rodo_P4).freq = 100 Task(%Rodo_P4).flags = %False Taskex(%Rodo_P4).stopcptr = CODEPTR(MM_Rodo_off) Task(%Rodo_P5).naam = "Rodo5" ' - rodo on slowdown Task(%Rodo_P5).cptr = CODEPTR(Rodo_P5) Task(%Rodo_P5).freq = 128 Task(%Rodo_P5).flags = %False TaskEX(%Rodo_P5).stopCptr = CODEPTR(Rodo_P5_Stop) Task(%Rodo_P6).naam = "Rodo6" ' - rodo on slowdown Task(%Rodo_P6).cptr = CODEPTR(Rodo_P6) Task(%Rodo_P6).freq = 110 Task(%Rodo_P6).flags = %False TaskEX(%Rodo_P6).stopCptr = CODEPTR(Rodo_P6_Stop) Task(%rodo_Pt1).naam = "Rd1" Task(%rodo_Pt1).freq = 10 Task(%rodo_Pt1).cptr = CODEPTR(Rodo_Pt1) Task(%rodo_Pt1).flags = %False 'PERTIM_TASK Task(%rodo_Pt2).naam = "Rd2" Task(%rodo_Pt2).freq = 11 Task(%rodo_Pt2).cptr = CODEPTR(Rodo_Pt2) Task(%rodo_Pt2).flags = %False Task(%rodo_Pt3).naam = "Rd3" Task(%rodo_Pt3).freq = 12 Task(%rodo_Pt3).cptr = CODEPTR(Rodo_Pt3) Task(%rodo_Pt3).flags = %False IF ISFALSE Task(%Gesture_Analyser).tog THEN starttask %Gesture_Analyser FUNCTION = %True END FUNCTION SUB Deriv_5 () ' also used to test the scaling factors for gesture analysis based on the derivatives of surface vectors STATIC noot1, noot2, noot3, slnr, cnt1, cnt2, cnt3 AS INTEGER STATIC d1max, d2max,d3max AS SINGLE IF ISFALSE Task(%Deriv_5).tog THEN IF ISFALSE Task(%Deriv_5).hParam THEN DIM TaskParamLabels(0 TO 2) AS STATIC ASCIIZ * 8 TaskParamLabels(0) = "dS1" ' sensit. Bomi TaskParamLabels(1) = "dS2" ' sensit. for Piperola TaskParamLabels(2) = "dS3" ' sensit for Qt MakeTaskParameterDialog %Deriv_5,3,Slider(),0,UDctrl(),TaskParamLabels() ' 3 sliders! END IF IF ISFALSE slnr THEN slnr = TaskEX(%Deriv_5).SliderNumbers(0) Slider(slnr).value = 10 SendMessage Slider(slnr).h, %TBM_SETPOS,%True, Slider(slnr).value slider(slnr+1).value = 20 SendMessage Slider(slnr+1).h, %TBM_SETPOS,%True, Slider(slnr+1).value slider(slnr+2).value = 20 SendMessage Slider(slnr+2).h, %TBM_SETPOS,%True, Slider(slnr+2).value END IF logfile "Testing gesture derivatives" MM_Qt_On MM_Piperola_On MM_Bomi_On Task(%Deriv_5).tog = %True END IF ' first derivative mapped on Bomi IF gesture.dS1(3) > slider(slnr).value / 128 THEN IF gesture.dS1(3) >= 1 THEN INCR cnt1 'gesture.dS1Scalefactor = gesture.dS1Scalefactor * 0.9 - do not change this anymore. Now set at 24 ' was 22.5 logfile "d1 scaling = " & STR$(gesture.dS1Scalefactor) & " clipping to 1 " & STR$(cnt1) & "th time" RESET d1max END IF IF gesture.dS1(3) > d1max THEN logfile "gesture.dS1(3)= " & STR$(gesture.dS1(3)) & " scaling= " & STR$(gesture.dS1Scalefactor) d1max = gesture.dS1(3) END IF IF noot1 THEN NoteOff Bomi.channel, noot1 noot1 = %False END IF noot1 = bomi.lowtes + (SQR(gesture.dS1(3)- (slider(slnr).value/ 128)) * 36) mPlay Bomi.channel, noot1, 36 ELSE IF noot1 THEN NoteOff Bomi.channel, noot1 RESET noot1 END IF END IF ' second derivative mapped on Piperola IF gesture.dS2(3) > slider(slnr+1).value / 128 THEN IF gesture.dS2(3) >= 1 THEN INCR cnt2 logfile "d2 scaling = " & STR$(gesture.dS2Scalefactor) & " clipping to 1 " & STR$(cnt2) & "th time" 'gesture.dS2Scalefactor *= 0.9 'logfile "d2 scaling = " & STR$(gesture.dS2Scalefactor) RESET d2max END IF IF gesture.dS2(3) > d2max THEN logfile "gesture.dS2(3)= " & STR$(gesture.dS2(3)) & " scaling= " & STR$(gesture.dS2Scalefactor) d2max = gesture.dS2(3) END IF IF noot2 THEN NoteOff Piperola.channel, noot2 noot2 = %False END IF noot2 = Piperola.lowtes + (SQR(gesture.dS2(3)- (slider(slnr+1).value/128)) * 36) mPlay Piperola.channel, noot2, 64 ELSE IF noot2 THEN mPlay Piperola.channel, noot2, %False RESET noot2 END IF END IF ' third derivative mapped op Qt IF gesture.dS3(3) > slider(slnr+2).value / 128 THEN IF gesture.dS3(3) >= 1 THEN INCR cnt3 logfile "d3 scaling = " & STR$(gesture.dS3Scalefactor) & " clipping to 1 " & STR$(cnt3) & "th time" 'gesture.dS3Scalefactor *= 0.9 'logfile "d3 scaling = " & str$(gesture.dS3Scalefactor) RESET d3max END IF IF gesture.dS3(3) > d3max THEN logfile "gesture.dS3(3)= " & STR$(gesture.dS3(3)) & " scaling= " & STR$(gesture.dS3Scalefactor) d3max = gesture.dS3(3) END IF IF noot3 THEN mPlay Qt.channel, noot3, %False noot3 = %False END IF noot3 = qt.lowtes + (SQR(gesture.dS3(3) - (slider(slnr+2).value / 128)) * 60) mPlay Qt.channel, noot3, 36 ELSE IF noot3 THEN mPlay Qt.channel, noot3, %False RESET noot3 END IF END IF END SUB SUB Deriv_5_stop () MM_Qt_Off %MM_Notes OR %MM_Wind MM_Bomi_Off %MM_Notes OR %MM_Wind MM_Piperola_Off %MM_Notes OR %MM_Wind END SUB SUB Deriv_1 () ' written before the integration of the derivatives in the gesture_type itself. ' could be rewritten using these, but it's still usefull as a test-bed. ' 09.02.2014: Used as opening for Namuda Study #43 DIM dS1x (0 TO UBOUND (xp)) AS STATIC SINGLE DIM dS1y (0 TO UBOUND (yp)) AS STATIC SINGLE DIM dS1z (0 TO UBOUND (zp)) AS STATIC SINGLE DIM dS1max (0 TO UBOUND (xp)) AS STATIC SINGLE ' first derivative DIM dS1min (0 TO UBOUND (xp)) AS STATIC SINGLE STATIC oldmax, oldmin, scalefactor_pos, scalefactor_neg, oldd2max, oldd2min AS SINGLE STATIC oldnoot, noot, cnt, puffnoot, oldpuffnoot, slnr AS INTEGER LOCAL dS2max, dS2min AS SINGLE ' second derivative LOCAL expantie, kontraktie AS SINGLE LOCAL i AS LONG IF ISFALSE Task(%Deriv_1).tog THEN scalefactor_pos = 25 scalefactor_neg = 150 IF ISFALSE Task(%Deriv_1).hParam THEN DIM TaskParamLabels(0 TO 1) AS STATIC ASCIIZ * 8 TaskParamLabels(0) = "dS1" ' sensit. for piano TaskParamLabels(1) = "Xy" ' sensit. for Xy MakeTaskParameterDialog %Deriv_1,2,Slider(),0,UDctrl(),TaskParamLabels() ' 2 sliders! END IF IF ISFALSE slnr THEN slnr = TaskEX(%Deriv_1).SliderNumbers(0) Slider(slnr).value = 17 SendMessage Slider(slnr).h, %TBM_SETPOS,%True, Slider(slnr).value slider(slnr+1).value = 10 SendMessage Slider(slnr+1).h, %TBM_SETPOS,%True, Slider(slnr+1).value END IF Task(%Deriv_1).tog = %True END IF ' calculates the first derivative of the surface data: FOR i = 1 TO UBOUND(xp) dS1x(i) = xp(i) - xp(i-1) dS1y(i) = yp(i) - yp(i-1) dS1z(i) = zp(i) - zp(i-1) dS1max(i) = MAX(dS1x(i), dS1y(i), dS1z(i)) ' take the maximum of the absolute value dS1min(i) = MIN(dS1x(i), dS1y(i), dS1z(i)) IF dS1max(i) < 4.2E-4 THEN dS1max(i) = 0.0 ' removing noise at -40dB IF ds1min(i) < -1.8E-4 THEN ds1min(i) = 0.0 NEXT i ' in this further coding we use only the most recent first derivative in a very direct mapping i = UBOUND(xp) ' normalisation/ rescaling: IF dS1max(i) > oldmax THEN oldmax = dS1max(i) IF 1/oldmax < scalefactor_pos THEN scalefactor_pos = 1 / oldmax logfile "max=" & STR$(oldmax) & " scalefactor=" & STR$(scalefactor_pos) ' 0.042 END IF IF dS1min(i) < oldmin THEN oldmin = dS1min(i) IF 1/ ABS(oldmin) < scalefactor_neg THEN scalefactor_neg = 1 / ABS(oldmin) logfile "min=" & STR$(oldmin) & " scalefactor=" & STR$(scalefactor_neg) END IF ' genormaliseerde expantie: expantie = dS1max(i) * scalefactor_pos ' genormaliseerde kontraktie kontraktie = ABS(ds1min(i)) * scalefactor_neg ' so always positive 0-1 INCR cnt IF expantie > (Slider(slnr).value / 127) THEN IF noot < piano.lowtes + (expantie * 88) THEN noot = piano.lowtes + (expantie * 88) ' try to map on something musical: IF oldnoot THEN NoteOff Piano.channel, oldnoot : RESET oldnoot IF noot THEN mPlay Piano.channel, noot, MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) * 90 oldnoot =noot RESET noot END IF END IF IF kontraktie > (Slider(slnr+1).value / 127) THEN mPlay Xy.channel, xy.lowtes + (kontraktie * 36),MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) * 48 END IF ' try to do something with the second derivative now: dS2max = dS1max(i) - dS1max(i-1) ' will be bipolar again ' dS2min = dS1min(i) - ds1min(i-1) ' has probably no significance IF dS2max > oldd2max THEN oldd2max = dS2max logfile "dS2max = " & STR$(dS2max) ' gives 0.0373 so scale factor can be 25 for normalisation ' gives 0.0433 --> scalefactor 23 END IF IF dS2max > 2.984E-3 THEN ' 7.46E-4 then ' mPlay Troms.channel, min(24 + (ds2max * 3174), 127), 30 ' 3174 = 25 x 127 mPlay Troms.channel, MIN(24 + (ds2max * 23 * 24),127), 30 ' should track movement very well END IF END SUB SUB Deriv_1_new () ' written before the integration of the derivatives in the gesture_type itself. ' could be rewritten using these, but it's still usefull as a test-bed. ' 09.02.2014: Used as opening for Namuda Study #43 ' attempt to rewrite it using the gesture type ' 13.02.2014: rewritten for gesturetype derivatives d1S and d2S ' now #43.1 STATIC oldnoot, noot, cnt, slnr AS INTEGER LOCAL expantie, kontraktie AS SINGLE IF ISFALSE Task(%Deriv_1_new).tog THEN IF ISFALSE Task(%Deriv_1_new).hParam THEN DIM TaskParamLabels(0 TO 2) AS STATIC ASCIIZ * 8 TaskParamLabels(0) = "dS1+pn" ' sensit. for piano TaskParamLabels(1) = "ds1-xy" ' sensit. for Xy TaskParamLabels(2) = "dS2-Tr" ' sensit. voor Troms MakeTaskParameterDialog %Deriv_1_new,3,Slider(),0,UDctrl(),TaskParamLabels() ' 2 sliders! END IF IF ISFALSE slnr THEN slnr = TaskEX(%Deriv_1_new).SliderNumbers(0) Slider(slnr).value = 17 SendMessage Slider(slnr).h, %TBM_SETPOS,%True, Slider(slnr).value slider(slnr+1).value = 100 ' lower in the course of this section. SendMessage Slider(slnr+1).h, %TBM_SETPOS,%True, Slider(slnr+1).value slider(slnr+2).value = 14 ' higher up after the start SendMessage Slider(slnr+2).h, %TBM_SETPOS,%True, Slider(slnr+2).value END IF ProgChange Piano.channel, %False MM_Xy_On Task(%Deriv_1_new).tog = %True END IF ' genormaliseerde expantie: expantie = gesture.dS1(3) ' genormaliseerde kontraktie kontraktie =gesture.ds1(4) ' always positive 0-1 INCR cnt IF expantie > (Slider(slnr).value / 127) THEN IF noot < piano.lowtes + (expantie * 88) THEN noot = piano.lowtes + (expantie * 88) ' try to map on something musical: IF oldnoot THEN NoteOff Piano.channel, oldnoot : RESET oldnoot IF noot THEN mPlay Piano.channel, noot, MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) * 90 oldnoot =noot RESET noot END IF END IF IF kontraktie > (Slider(slnr+1).value / 127) THEN mPlay Xy.channel, xy.lowtes + (kontraktie * 36),MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) * 48 END IF ' try to do something with the second derivative now: IF gesture.dS2(3) > slider(slnr+2).value / 128 THEN ' scaling to be checked mPlay Troms.channel, MIN(24 + (gesture.ds2(3)* 24),127), 30 ' should track movement very well END IF END SUB SUB Deriv_2_old () ' using only the second derivative of the surface vectors ' development code STATIC dS2x, dS2y, dS2z, dS2max, dS2min AS SINGLE STATIC scalefactor_max, scalefactor_min AS SINGLE STATIC oldmax, oldmin AS SINGLE STATIC noot, oldnoot, Tnoot, oldTnoot, slnr AS INTEGER LOCAL i AS LONG IF ISFALSE Task(%Deriv_2).tog THEN scalefactor_max = 40 scalefactor_min = 40 IF ISFALSE Task(%Deriv_2).hParam THEN DIM TaskParamLabels(0 TO 1) AS STATIC ASCIIZ * 8 TaskParamLabels(0) = "dS2" ' sensit. for vibi TaskParamLabels(1) = "Tp" ' sensit. for Toypi MakeTaskParameterDialog %Deriv_2,2,Slider(),0,UDctrl(),TaskParamLabels() ' 2 sliders! END IF IF ISFALSE slnr THEN slnr = TaskEX(%Deriv_2).SliderNumbers(0) Slider(slnr).value = 14 SendMessage Slider(slnr).h, %TBM_SETPOS,%True, Slider(slnr).value slider(slnr+1).value = 10 SendMessage Slider(slnr+1).h, %TBM_SETPOS,%True, Slider(slnr+1).value END IF MM_Vibi_On Task(%Deriv_2).tog = %True END IF i = UBOUND (xp) dS2x = xp(i) - xp(i-1) - xp(i-1) + xp(i-2) dS2y = yp(i) - yp(i-1) - yp(i-1) + yp(i-2) dS2z = zp(i) - zp(i-1) - zp(i-1) + zp(i-2) dS2max = MAX(ds2x, ds2y,ds2z) ds2min = ABS(MIN(ds2x, ds2y,ds2z)) ' made positive here! ' normalising: ds2Max = MIN(ds2Max * scalefactor_max, 1) ds2Min = MIN(ds2Min * scalefactor_min, 1) ' noise removal: IF dS2max < 0.01 THEN dS2max = 0.0 ' removing noise at -40dB IF ds2min < 0.01 THEN ds2min = 0.0 IF ds2max > oldmax THEN oldmax = ds2max IF oldmax > 0.5 THEN Logfile "dS2max=" & STR$(oldmax) END IF END IF IF ds2min > oldmin THEN oldmin = ds2min IF oldmin > 0.5 THEN Logfile "dSmin=" & STR$(oldmin) END IF END IF ' test mapping: IF ds2max > Slider(slnr).value / 128 THEN 'if oldnoot then ' mPlay Vibi.channel, oldnoot, %False 'end if noot = Vibi.lowtes + ( SQR(dS2Max) * 36) IF noot <> oldnoot THEN mPlay Vibi.channel, noot, 60 * MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) oldnoot = noot END IF ELSE IF oldnoot THEN mPlay Vibi.channel, oldnoot, %False oldnoot = %False END IF END IF ' negative peaks: IF ds2min > Slider(slnr+1).value / 128 THEN Tnoot = Toypi.lowtes + (SQR(dS2Min) * 36) IF Tnoot <> oldTnoot THEN mPlay Toypi.channel, Tnoot, 30 * MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) oldTnoot = Tnoot END IF ELSE IF oldTnoot THEN oldTnoot = %False END IF END IF END SUB SUB Deriv_2 () ' using only the second derivative of the surface vectors ' development code ' rewritten to use the data acquired in gesture type. 'STATIC dS2x, dS2y, dS2z, dS2max, dS2min AS SINGLE 'STATIC scalefactor_max, scalefactor_min AS SINGLE 'STATIC oldmax, oldmin AS SINGLE STATIC noot, oldnoot, Tnoot, oldTnoot, slnr AS INTEGER 'LOCAL i AS LONG IF ISFALSE Task(%Deriv_2).tog THEN 'scalefactor_max = 40 'scalefactor_min = 40 IF ISFALSE Task(%Deriv_2).hParam THEN DIM TaskParamLabels(0 TO 1) AS STATIC ASCIIZ * 8 TaskParamLabels(0) = "Vib" ' sensit. for vibi ' lower slider in the course of the section TaskParamLabels(1) = "Toy" ' sensit. for Toypi ' lower slider in the course of the section MakeTaskParameterDialog %Deriv_2,2,Slider(),0,UDctrl(),TaskParamLabels() ' 2 sliders! END IF IF ISFALSE slnr THEN slnr = TaskEX(%Deriv_2).SliderNumbers(0) Slider(slnr).value = 20 SendMessage Slider(slnr).h, %TBM_SETPOS,%True, Slider(slnr).value slider(slnr+1).value = 18 ' SendMessage Slider(slnr+1).h, %TBM_SETPOS,%True, Slider(slnr+1).value END IF MM_Vibi_On Task(%Deriv_2).tog = %True END IF ' i = UBOUND (xp) ' dS2x = xp(i) - xp(i-1) - xp(i-1) + xp(i-2) ' dS2y = yp(i) - yp(i-1) - yp(i-1) + yp(i-2) ' dS2z = zp(i) - zp(i-1) - zp(i-1) + zp(i-2) ' dS2max = MAX(ds2x, ds2y,ds2z) ' ds2min = ABS(MIN(ds2x, ds2y,ds2z)) ' made positive here! ' normalising: ' ds2Max = MIN(ds2Max * scalefactor_max, 1) ' ds2Min = MIN(ds2Min * scalefactor_min, 1) ' noise removal: ' IF dS2max < 0.01 THEN dS2max = 0.0 ' removing noise at -40dB ' IF ds2min < 0.01 THEN ds2min = 0.0 ' IF ds2max > oldmax THEN ' oldmax = ds2max ' IF oldmax > 0.5 THEN ' Logfile "dS2max=" & STR$(oldmax) ' END IF ' END IF ' IF ds2min > oldmin THEN ' oldmin = ds2min ' IF oldmin > 0.5 THEN ' Logfile "dSmin=" & STR$(oldmin) ' END IF ' END IF ' test mapping: IF gesture.dS2(3) > Slider(slnr).value / 128 THEN 'if oldnoot then ' mPlay Vibi.channel, oldnoot, %False 'end if noot = Vibi.lowtes + ( SQR(gesture.dS2(3)) * 36) IF noot <> oldnoot THEN mPlay Vibi.channel, noot, 60 * MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) oldnoot = noot END IF ELSE IF oldnoot THEN mPlay Vibi.channel, oldnoot, %False oldnoot = %False END IF END IF ' negative peaks: IF gesture.ds2(4) > Slider(slnr+1).value / 128 THEN Tnoot = Toypi.lowtes + (SQR(gesture.ds2(4)) * 36) IF Tnoot <> oldTnoot THEN mPlay Toypi.channel, Tnoot, 30 * MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) oldTnoot = Tnoot END IF ELSE IF oldTnoot THEN oldTnoot = %False END IF END IF END SUB SUB Deriv_3 () ' using only the second derivative of the speed vectors ' this is the first derivative of accelleration ' not very convincing result... ' used in Namuda #43, with all its bugs and faults. It fits the theme 'Shakes'... ' #43.3 STATIC dF2x, dF2y, dF2z, dF2max, dF2min AS SINGLE STATIC scalefactor_max, scalefactor_min, ovmax, ovmin AS SINGLE STATIC oldmax, oldmin AS SINGLE STATIC noot, oldnoot, Tnoot, oldTnoot, slnr, Fanoot, Obnoot, Kornnoot AS INTEGER LOCAL i AS LONG IF ISFALSE Task(%Deriv_3).tog THEN scalefactor_max = 0.0625 '0.025 ' determined after the logfiles scalefactor_min = 0.0625 '0.025 IF ISFALSE Task(%Deriv_3).hParam THEN DIM TaskParamLabels(0 TO 1) AS STATIC ASCIIZ * 8 TaskParamLabels(0) = "Klar" ' sensit. for Klar TaskParamLabels(1) = "Asa" ' sensit. for Asa MakeTaskParameterDialog %Deriv_3,2,Slider(),0,UDctrl(),TaskParamLabels() ' 2 sliders! END IF IF ISFALSE slnr THEN slnr = TaskEX(%Deriv_3).SliderNumbers(0) Slider(slnr).value = 14 SendMessage Slider(slnr).h, %TBM_SETPOS,%True, Slider(slnr).value slider(slnr+1).value = 10 SendMessage Slider(slnr+1).h, %TBM_SETPOS,%True, Slider(slnr+1).value END IF MM_Klar_On MM_Asa_On MM_Ob_On MM_Fa_On MM_Korn_On Task(%Deriv_3).tog = %True END IF i = UBOUND (xf) dF2x = xf(i) - xf(i-1) - xf(i-1) + xf(i-2) dF2y = yf(i) - yf(i-1) - yf(i-1) + yf(i-2) dF2z = zf(i) - zf(i-1) - zf(i-1) + zf(i-2) dF2max = MAX(dF2x, dF2y,dF2z) ' for scaling research: IF dF2max > ovmax THEN ovmax = dF2max logfile "scaling factor d2Fmax = " & STR$( 1/ovmax) END IF dF2min = ABS(MIN(dF2x, dF2y,dF2z)) ' made positive here! ' for scaling research: IF dF2min > ovmin THEN ovmin = dF2min logfile "scaling factor d2Fmin = " & STR$( 1/ovmin) END IF ' normalising: dF2Max = MIN(dF2Max * scalefactor_max, 1) ' with ceiling! dF2Min = MIN(dF2Min * scalefactor_min, 1) ' noise removal: IF dF2max < 0.02 THEN dF2max = 0.0 ' 0.01 = removing noise at -40dB IF dF2min < 0.02 THEN dF2min = 0.0 ' 0.02 = = 34dB IF dF2max > oldmax THEN oldmax = dF2max IF oldmax > 0.5 THEN Logfile "dF2max=" & STR$(oldmax) ' scalefactor should be 1/oldmax END IF END IF IF dF2min > oldmin THEN oldmin = dF2min IF oldmin > 0.5 THEN Logfile "dF2min=" & STR$(oldmin) END IF END IF ' test mapping: ' positive peaks: IF dF2max > Slider(slnr).value / 128 THEN noot = Klar.lowtes + ((dF2Max - (Slider(slnr).value/128)) * 48) IF noot <> oldnoot THEN mPlay Klar.channel, noot, 127 * MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) oldnoot = noot END IF ELSE IF oldnoot THEN Noteoff Klar.channel, oldnoot oldnoot = %False noot = %False END IF END IF ' negative peaks: IF dF2min > Slider(slnr+1).value / 128 THEN Tnoot = Asa.lowtes + ((dF2Min - (Slider(slnr+1).value / 128)) * 48) IF Tnoot <> oldTnoot THEN mPlay Asa.channel, Tnoot, 127 * MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) oldTnoot = Tnoot END IF ELSE IF oldTnoot THEN NoteOff Asa.channel, oldTnoot oldTnoot = %False Tnoot = %False END IF END IF ' mapping of individual vectors: IF dF2x * scalefactor_max > 0.1 THEN Obnoot = MIN(Ob.lowtes + ((dF2x * scalefactor_max) * 48), 127) mPlay Ob.channel, Obnoot, 127 * @pDoppler.xa ELSE IF Obnoot THEN NoteOff Ob.channel, Obnoot RESET Obnoot END IF END IF IF dF2y * scalefactor_max > 0.1 THEN Kornnoot = MIN(Korn.lowtes + ((dF2y * scalefactor_max) * 48), 127) mPlay Korn.channel, Kornnoot, 80 + (47 * @pDoppler.ya) ELSE IF kornnoot THEN NoteOff Korn.channel, Kornnoot RESET Kornnoot END IF END IF IF dF2z * scalefactor_max > 0.1 THEN Fanoot = MIN(Fa.lowtes + ((dF2z * scalefactor_max) * 48), 127) mPlay Fa.channel, Fanoot, 120 * @pDoppler.za ELSE IF Fanoot THEN NoteOff Fa.channel, Fanoot RESET Fanoot END IF END IF END SUB SUB Deriv_3_Stop () MM_Fa_Off %MM_Notes MM_Korn_Off %MM_Notes MM_Klar_Off %MM_Notes MM_Ob_Off %MM_Notes MM_Asa_Off %MM_Notes END SUB SUB Deriv_4 () ' using only the third derivative of the surface vectors ' this works very well and is extremely responsive and fast. ' should be rewitten using the extensions of the gesture type. ' 13.02.2014: Rehearsal with dominica eyckmans ' 13.02.2014: Rewritten using the daq in the gesture type ' tested ok. STATIC noot1, oldnoot1, noot2, oldnoot2, slnr, udnr AS INTEGER IF ISFALSE Task(%Deriv_4).tog THEN IF ISFALSE Task(%Deriv_4).hParam THEN DIM TaskParamLabels(0 TO 3) AS STATIC ASCIIZ * 8 TaskParamLabels(0) = "dS3+" ' sensit. for puff TaskParamLabels(1) = "dS3-" ' sensit. for Tubi TaskParamLabels(2) = "0/1" ' on of for puff TaskParamLabels(3) = "0/1" ' on off for tubi MakeTaskParameterDialog %Deriv_4,2,Slider(),2,UDctrl(),TaskParamLabels() ' 2 sliders! END IF IF ISFALSE slnr THEN slnr = TaskEX(%Deriv_4).SliderNumbers(0) Slider(slnr).value = 10 SendMessage Slider(slnr).h, %TBM_SETPOS,%True, Slider(slnr).value slider(slnr+1).value = 10 SendMessage Slider(slnr+1).h, %TBM_SETPOS,%True, Slider(slnr+1).value END IF IF ISFALSE udnr THEN udnr = TaskEX(%Deriv_4).UpDownNumbers(0) UDctrl(udnr).cPtr = CODEPTR(Deriv4_Puff_UD) UDctrl(udnr).value = 1 UDctrl(udnr).maxval = 1 UDctrl(udnr).minval = 0 UDctrl(udnr).resetval = 1 UDctrl(udnr+1).cPtr = CODEPTR(Deriv4_Tubi_UD) UDctrl(udnr+1).value = 1 UDctrl(udnr+1).maxval = 1 UDctrl(udnr+1).minval = 0 UDctrl(udnr+1).resetval = 1 END IF MM_Tubi_On MM_Whisper_Off Task(%Deriv_4).tog = %True END IF ' test mapping: IF UDctrl(udnr).value THEN IF gesture.ds3(3) > Slider(slnr).value / 128 THEN noot1 = 55 + ( SQR(gesture.ds3(3)) * 36) ' puff IF noot1 <> oldnoot1 THEN IF noot1 < 127 THEN mPlay Puff.channel, noot1, 48 * MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) oldnoot1 = noot1 ELSE logfile "Midi overflow bug on Puff" END IF END IF ELSE IF oldnoot1 THEN oldnoot1 = %False noot1 = %False END IF END IF END IF IF UDctrl(udnr+1).value THEN ' negative peaks: IF gesture.ds3(4) > Slider(slnr+1).value / 128 THEN noot2 = 72 + (SQR(gesture.ds3(4)) * 36) IF noot2 <> oldnoot2 THEN IF noot2 < 127 THEN mPlay Tubi.channel, noot2, 64 * MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) oldnoot2 = noot2 ELSE logfile "Midi overflow bug on Tubi" END IF END IF ELSE IF oldnoot2 THEN oldnoot2 = %False noot2 = %False END IF END IF END IF END SUB SUB Deriv_4_Stop () ' start whisper from here... StartTask %Shakes ' MM_Whisper_On ' mPlay Whisper.channel, 83, 20 ' shakers ' mPlay Whisper.channel, 84, 30 ' mPlay Whisper.channel, 85, 35 END SUB SUB Deriv_4_old () ' using only the third derivative of the surface vectors ' this works very well and is extremely responsive and fast. ' rewitten using the extensions of the gesture type. STATIC dS3x, dS3y, dS3z, dS3max, dS3min AS SINGLE STATIC scalefactor_max, scalefactor_min AS SINGLE STATIC oldmax, oldmin, ovmax, ovmin AS SINGLE STATIC noot1, oldnoot1, noot2, oldnoot2, slnr, udnr AS INTEGER LOCAL i AS LONG IF ISFALSE Task(%Deriv_4).tog THEN scalefactor_max = 30 ' determined after the log files. scalefactor_min = 30 IF ISFALSE Task(%Deriv_4).hParam THEN DIM TaskParamLabels(0 TO 1) AS STATIC ASCIIZ * 8 TaskParamLabels(0) = "dS3+" ' sensit. for puff TaskParamLabels(1) = "dS3-" ' sensit. for Tubi TaskParamLabels(2) = "0/1" ' on of for puff TaskParamLabels(3) = "0/1" ' on off for tubi MakeTaskParameterDialog %Deriv_4,2,Slider(),2,UDctrl(),TaskParamLabels() ' 2 sliders! END IF IF ISFALSE slnr THEN slnr = TaskEX(%Deriv_4).SliderNumbers(0) Slider(slnr).value = 10 SendMessage Slider(slnr).h, %TBM_SETPOS,%True, Slider(slnr).value slider(slnr+1).value = 10 SendMessage Slider(slnr+1).h, %TBM_SETPOS,%True, Slider(slnr+1).value END IF IF ISFALSE udnr THEN udnr = TaskEX(%Deriv_4).UpDownNumbers(0) UDctrl(udnr).cPtr = CODEPTR(Deriv4_Puff_UD) UDctrl(udnr).value = 1 UDctrl(udnr).maxval = 1 UDctrl(udnr).minval = 0 UDctrl(udnr).resetval = 1 UDctrl(udnr+1).cPtr = CODEPTR(Deriv4_Tubi_UD) UDctrl(udnr+1).value = 1 UDctrl(udnr+1).maxval = 1 UDctrl(udnr+1).minval = 0 UDctrl(udnr+1).resetval = 1 END IF MM_Tubi_On Task(%Deriv_4).tog = %True END IF i = UBOUND (xp) dS3x = xp(i) - xp(i-1) - xp(i-1) + xp(i-2) - (xp(i-1) - xp(i-2) - xp(i-2) + xp(i-3)) ' = xp(i) - xp(i-1) - xp(i-1) + xp(i-2) - xp(i-1) + xp(i-2) + xp(i-2) - xp(i-3) ' = xp(i) - 3(xp(i-1)) + 3(xp(i-2) - xp(i-3) dS3y = yp(i) - yp(i-1) - yp(i-1) + yp(i-2) - (yp(i-1) - yp(i-2) - yp(i-2) + yp(i-3)) dS3z = zp(i) - zp(i-1) - zp(i-1) + zp(i-2) - (zp(i-1) - zp(i-2) - zp(i-2) + zp(i-3)) dS3max = MAX(ds3x, ds3y,ds3z) ds3min = ABS(MIN(ds3x, ds3y,ds3z)) ' made positive here! ' for scaling research: ' IF dS3max > ovmax THEN ' ovmax = dS3max ' logfile "scaling factor dS3max = " & STR$( 1/ovmax) ' END IF ' IF dS3min > ovmin THEN ' ovmin = dS3min ' logfile "scaling factor dS3min = " & STR$( 1/ovmin) ' END IF ' normalising: ds3Max = MIN(ds3Max * scalefactor_max, 1) ds3Min = MIN(ds3Min * scalefactor_min, 1) ' noise removal: IF dS3max < 0.01 THEN dS3max = 0.0 ' removing noise at -40dB IF ds3min < 0.01 THEN ds3min = 0.0 IF ds3max > oldmax THEN oldmax = ds3max ' IF oldmax > 0.5 THEN ' Logfile "dS3max=" & STR$(oldmax) ' END IF ' calculate the scaling factor END IF IF ds3min > oldmin THEN oldmin = ds3min ' IF oldmin > 0.5 THEN ' Logfile "dS3min=" & STR$(oldmin) ' END IF END IF ' test mapping: IF UDctrl(udnr).value THEN IF ds3max > Slider(slnr).value / 128 THEN noot1 = 55 + ( SQR(dS3Max) * 36) ' puff IF noot1 <> oldnoot1 THEN mPlay Puff.channel, noot1, 48 * MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) oldnoot1 = noot1 END IF ELSE IF oldnoot1 THEN oldnoot1 = %False noot1 = %False END IF END IF END IF IF UDctrl(udnr+1).value THEN ' negative peaks: IF ds3min > Slider(slnr+1).value / 128 THEN noot2 = 72 + (SQR(dS3Min) * 36) IF noot2 <> oldnoot2 THEN mPlay Tubi.channel, noot2, 64 * MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) oldnoot2 = noot2 END IF ELSE IF oldnoot2 THEN oldnoot2 = %False noot2 = %False END IF END IF END IF END SUB SUB Deriv4_Puff_UD () ' call back for UpDown LOCAL value AS LONG value = UDCtrl(TaskEX(%Deriv_4).UpdownNumbers(0)).value SetDlgItemText Task(%Deriv_4).hparam, %GMT_TEXT0_ID + 16, STR$(value) END SUB SUB Deriv4_Tubi_UD () ' call back for UpDown LOCAL value AS LONG value = UDCtrl(TaskEX(%Deriv_4).UpdownNumbers(1)).value SetDlgItemText Task(%Deriv_4).hparam, %GMT_TEXT0_ID + 17, STR$(value) END SUB 'SUB Calc_Derivatives () ' ' data input is from xp(), yp(), zp() and xf(), yf(), zf(), arrays shared and global in Namuda.inc ' ' calculates the momentaneous values of the first, second and third derivatives ' ' we put the noise level at -40dB, so normalized 0.01 ' ' As the derivatives for the F-vektors do not seem to work, we may consider to ' ' calculate the derivatives of the spectra. ' STATIC Noise40dB AS SINGLE ' STATIC init, i AS LONG ' IF ISFALSE init THEN ' Derivatives.ds1scalefactor_pos = 25 ' Derivatives.dS1Scalefactor_neg = 150 ' Derivatives.ds2scalefactor = 40 ' Derivatives.ds3Scalefactor = 30 ' Noise40dB = 0.01 ' i = UBOUND (xp) ' init = %True ' END IF ' ' ' first we calculate all derivates for the surface vectors ' ' first derivative ' Derivatives.dS1x = xp(i) - xp(i-1) ' Derivatives.dS1y = yp(i) - yp(i-1) ' Derivatives.dS1z = zp(i) - zp(i-1) ' Derivatives.dS1max = MAX(Derivatives.dS1x, Derivatives.dS1y, Derivatives.dS1z) ' take the maximum of the absolute value ' Derivatives.dS1min = ABS(MIN(Derivatives.dS1x, Derivatives.dS1y, Derivatives.dS1z)) ' ' second derivative ' Derivatives.dS2x = Derivatives.dS1x - (xp(i-1) - xp(i-2)) ' Derivatives.dS2y = Derivatives.dS1y - (yp(i-1) - yp(i-2)) ' Derivatives.dS2z = Derivatives.dS1z - (zp(i-1) - zp(i-2)) ' Derivatives.dS2max = MAX(Derivatives.dS2x, Derivatives.dS2y, Derivatives.dS2z) ' take the maximum of the absolute value ' Derivatives.dS2min = ABS(MIN(Derivatives.dS2x, Derivatives.dS2y, Derivatives.dS2z)) ' ' third derivative: ' 'Derivatives.dS3x = Derivatives.dS2x - (xp(i-2) - xp(i-3)) ' check math! ' 'Derivatives.dS3y = Derivatives.dS2y - (yp(i-2) - yp(i-3)) ' 'Derivatives.dS3z = Derivatives.dS2z - (zp(i-2) - zp(i-3)) ' Derivatives.ds3x = xp(i) - (3*xp(i-1)) + (3*xp(i-2)) - xp(i-3) ' Derivatives.ds3y = yp(i) - (3*yp(i-1)) + (3*yp(i-2)) - yp(i-3) ' Derivatives.ds3z = zp(i) - (3*zp(i-1)) + (3*zp(i-2)) - zp(i-3) ' Derivatives.dS3max = MAX(Derivatives.dS3x, Derivatives.dS3y, Derivatives.dS3z) ' take the maximum of the absolute value ' Derivatives.dS3min = ABS(MIN(Derivatives.dS3x, Derivatives.dS3y, Derivatives.dS3z)) ' ' now we can rescale and normalize to 0-1: ' Derivatives.dS1x = MIN(Derivatives.ds1x * Derivatives.dS1scalefactor_pos, 1) ' Derivatives.dS1y = MIN(Derivatives.ds1y * Derivatives.dS1scalefactor_pos, 1) ' Derivatives.dS1z = MIN(Derivatives.ds1z * Derivatives.dS1scalefactor_pos, 1) ' Derivatives.dS1max = MIN(Derivatives.ds1max * Derivatives.dS1scalefactor_pos, 1) ' Derivatives.dS1min = MIN(Derivatives.ds1min * Derivatives.dS1scalefactor_neg, 1) ' Derivatives.dS2x = MIN(Derivatives.ds2x * Derivatives.dS2scalefactor, 1) ' Derivatives.dS2y = MIN(Derivatives.ds2y * Derivatives.dS2scalefactor, 1) ' Derivatives.dS2z = MIN(Derivatives.ds2z * Derivatives.dS2scalefactor, 1) ' Derivatives.dS2max = MIN(Derivatives.ds2max * Derivatives.dS2scalefactor, 1) ' Derivatives.dS2min = MIN(Derivatives.ds2min * Derivatives.dS2scalefactor, 1) ' Derivatives.dS3x = MIN(Derivatives.ds3x * Derivatives.dS3scalefactor, 1) ' Derivatives.dS3y = MIN(Derivatives.ds3y * Derivatives.dS3scalefactor, 1) ' Derivatives.dS3z = MIN(Derivatives.ds3z * Derivatives.dS3scalefactor, 1) ' Derivatives.dS3max = MIN(Derivatives.ds3max * Derivatives.dS3scalefactor, 1) ' Derivatives.dS3min = MIN(Derivatives.ds3min * Derivatives.dS3scalefactor, 1) ' ' apply the noise filter now ' IF Derivatives.dS1x < Noise40dB THEN Derivatives.dS1x = %False ' IF Derivatives.dS1y < Noise40dB THEN Derivatives.dS1y = %False ' IF Derivatives.dS1z < Noise40dB THEN Derivatives.dS1z = %False ' IF Derivatives.dS1max < Noise40dB THEN Derivatives.dS1max = %False ' IF Derivatives.dS1min < Noise40dB THEN Derivatives.dS1min = %False ' IF Derivatives.dS2x < Noise40dB THEN Derivatives.dS2x = %False ' IF Derivatives.dS2y < Noise40dB THEN Derivatives.dS2y = %False ' IF Derivatives.dS2z < Noise40dB THEN Derivatives.dS2z = %False ' IF Derivatives.dS2max < Noise40dB THEN Derivatives.dS2max = %False ' IF Derivatives.dS2min < Noise40dB THEN Derivatives.dS2min = %False ' IF Derivatives.dS3x < Noise40dB THEN Derivatives.dS3x = %False ' IF Derivatives.dS3y < Noise40dB THEN Derivatives.dS3y = %False ' IF Derivatives.dS3z < Noise40dB THEN Derivatives.dS3z = %False ' IF Derivatives.dS3max < Noise40dB THEN Derivatives.dS3max = %False ' IF Derivatives.dS3min < Noise40dB THEN Derivatives.dS3min = %False ' 'END SUB SUB F_Test () 'logfile "xf=" & str$(xf(127)) & " yf=" & STR$(yf(127)) & " zf=" & STR$(zf(127)) ' divide by 200 for normalisation. ' speed resolution is only 4Hz!!! ' so dynamic range is 1:50, or 34dB ' testing derivatives on the speed vektors ' as the results here are quite deceptive, the final version in the gesture recognition works on ' the 1 second medium speed databuffers (256 S/s) with derivates derived from the. ' However this coding, using piano , temblo and klung, is used in Namuda Study #43. ' #43.4 STATIC dF1x, dF1y, dF1z, dF1max, dF1min AS SINGLE STATIC dF2x, dF2y, dF2z, dF2max, dF2min AS SINGLE STATIC dF3x, dF3y, dF3z, dF3max, dF3min AS SINGLE STATIC scalefactor, scalefactor2, scalefactor3, ovmax, ovmin, ov2max, ov2min, ov3max, ov3min AS SINGLE STATIC noot1 , oldnoot1 , noot2, oldnoot2, noot3, oldnoot3, noot4, oldnoot4, slnr AS INTEGER STATIC i AS LONG IF ISFALSE task(%ds_tst).tog THEN i = UBOUND (xf) ' = 127 scalefactor = 0.125 ' 0.0625 '0.125 scalefactor2 = 0.05 ' 0.0625 ' 0.03125 '0.0625 scalefactor3 = 0.06896 ' 0.3125 ovmax = 0 ovmin = 0 ov2max = 0 ov2min = 0 MM_Temblo_On Task(%ds_tst).tog = %True END IF 'first derivative = accelleration: dF1x = MAX(MIN((xf(i-1) - ((xf(i-2) + xf(i))/2)) * scalefactor, 1),-1) dF1y = MAX(MIN((yf(i-1) - ((yf(i-2) + yf(i))/2)) * scalefactor, 1),-1) dF1z = MAX(MIN((zf(i-1) - ((zf(i-2) + zf(i))/2)) * scalefactor, 1),-1) dF1max = (dF1max + MAX(dF1x, dF1y, dF1z))/2 ' slightly integrated dF1min = (dF1min + ABS(MIN(dF1x, dF1y, dF1z)))/2 ' make positive ' range checking: IF dF1max > ovmax THEN ovmax = dF1max logfile "ovmax= " & STR$(ovmax) & " scalefactor_pos: " & STR$(scalefactor/ovmax) END IF IF dF1min > ovmin THEN ovmin = dF1min logfile "ovmin= " & STR$(ovmin) & " scalefactor_neg: " & STR$(scalefactor/ovmin) END IF ' second derivative: change of acceleration: dF2x = MAX(MIN(((dF1x/scalefactor) - (xf(i-2) - ((xf(i-3) + xf(i-1))/2))) * scalefactor2,1),-1) dF2y = MAX(MIN(((dF1y/ scalefactor) - (yf(i-2) - ((yf(i-3) + yf(i-1))/2))) * scalefactor2,1),-1) dF2z = MAX(MIN(((dF1z/scalefactor) - (zf(i-2) - ((zf(i-3) + zf(i-1))/2))) * scalefactor2,1),-1) dF2max = (dF2Max + MAX(dF2x, dF2y, dF2z))/2 ' slightly integrated dF2min = (dF2min + ABS(MIN(dF2x, dF2y, dF2z)))/2 ' range checking: IF dF2max > ov2max THEN ov2max = dF2max logfile "ov2max= " & STR$(ov2max) & " scalefactor2_pos: " & STR$(scalefactor2/ov2max) END IF IF dF2min > ov2min THEN ov2min = dF2min logfile "ov2min= " & STR$(ov2min) & " scalefactor2_neg: " & STR$(scalefactor2/ov2min) END IF ' test map for the first derivative: IF (ABS(dF1max) > 0.02) OR (dF1min > 0.02) THEN ' 0.02 is the dynamic range limit at -34dB IF dF1max > 0.02 AND dF1max > dF1min THEN noot1 = 60 + (SQR(dF1max) * 44) IF noot1 <> oldnoot1 THEN IF oldnoot1 THEN NoteOff Piano.channel, oldnoot1 oldnoot1 = %False END IF mPlay Piano.channel, noot1, @pDoppler.xa * 60 oldnoot1 = noot1 END IF ELSEIF dF1min > 0.02 AND dF1min > dF1max THEN noot1 = 60 - (SQR(dF1min) * 44) IF noot1 <> oldnoot1 THEN IF oldnoot1 THEN NoteOff Piano.channel, oldnoot1 oldnoot1 = %False END IF mPlay Piano.channel, noot1, @pDoppler.xa * 60 oldnoot1 = noot1 END IF END IF ELSE IF oldnoot1 THEN NoteOff Piano.channel, oldnoot1 RESET oldnoot1, noot1 END IF END IF 'test map second derivative of speed: - positive peaks: IF dF2max > 0.1 THEN SELECT CASE SQR(df1max-0.1) CASE < 0.5 noot2 = temblo.lowtes + (SQR(dF2max-0.1) * 6) ' note: there is a gap in the ambitus of temblo! CASE ELSE noot2 = temblo.lowtes + 12 + ((SQR(dF2Max-0.1) - 0.5) * 6) END SELECT IF noot2 <> oldnoot2 THEN mPlay Temblo.channel, noot2, MAX(@pDoppler.xa,@pDoppler.ya, @pDoppler.za) * 64 oldnoot2 = noot2 END IF ELSE RESET oldnoot2, noot2 END IF 'test map second derivative of speed, negative peaks: IF dF2min > 0.1 THEN noot3 = psch.lowtes + (SQR(dF2min) * 12) IF noot3 <> oldnoot3 THEN mPlay psch.channel, noot3, MAX(@pDoppler.xa, @pDoppler.ya,@pDoppler.za) * 64 oldnoot3 = noot3 END IF ELSE RESET oldnoot3,noot3 END IF ' third derivative of speed: (using the forward algorithm) dF3x = xf(i) - xf(i-1) - xf(i-1) + xf(i-2) - (xf(i-1) - xf(i-2) - xf(i-2) + xf(i-3)) dF3y = yf(i) - yf(i-1) - yf(i-1) + yf(i-2) - (yf(i-1) - yf(i-2) - yf(i-2) + yf(i-3)) dF3z = zf(i) - zf(i-1) - zf(i-1) + zf(i-2) - (zf(i-1) - zf(i-2) - zf(i-2) + zf(i-3)) dF3max = (dF3Max + MAX(dF3x, dF3y,dF3z))/2 ' with slight integrator dF3min = (dF3min + ABS(MIN(dF3x, dF3y,dF3z))/2) ' made positive here! ' for scaling research: IF dF3max > ov3max THEN ov3max = dF3max logfile "dF3max= " & STR$(dF3max) & " scaling factor for dF3max = " & STR$( 1/ov3max) 'scalefactor3 = 1/ov3max END IF IF dF3min > ov3min THEN ov3min = dF3min logfile "dF3min = " & STR$(dF3min) & " scaling factor for dF3min = " & STR$( 1/ov3min) 'scalefactor3 = 1/ov3min END IF ' normalising: dF3Max = MAX(MIN(dF3Max * scalefactor3, 1),-1) dF3Min = MAX(MIN(dF3Min * scalefactor3, 1),-1) ' noise removal: IF dF3max < 0.02 THEN dF3max = 0.0 ' removing noise at -34dB IF dF3min < 0.02 THEN dF3min = 0.0 ' test mapping on Klung: IF dF3max > 0.2 THEN noot4 = klung.lowtes + (SQR((dF3max-0.2) * 1.2) * 21) IF noot4 <> oldnoot4 THEN mPlay Klung.channel, noot4, MAX(@pDoppler.xa, @pDoppler.ya,@pDoppler.za) * 127 oldnoot4 = noot4 END IF ELSE RESET oldnoot4, noot4 END IF END SUB SUB Deriv_Speed () ' code remmed out here has been copied to Gesture_Derivatives in Namuda.inc ' the procedure is called from Gesture_Analyser ' now, in this code, we just test the results. ' velocity is calculated over a 1 second timeframe. STATIC noot, oldnoot AS LONG IF ISFALSE Task(%d_speed).tog THEN Task(%d_speed).tog = %True END IF ' test mapping for first derivative, speed: IF gesture.velocity(3) > 0.02 THEN noot = MIN(piano.lowtes + Gesture.velocity(3) * 88, 127) IF oldnoot THEN mPlay piano.channel, oldnoot, %False oldnoot = %False END IF mPlay Piano.channel, noot, MAX(@pDoppler.za, @pDoppler.ya, @pDoppler.xa) * 64 oldnoot = noot ELSE IF oldnoot THEN NoteOff Piano.channel, oldnoot RESET oldnoot END IF END IF END SUB SUB Deriv_Accel () STATIC noot1, noot2, slnr AS LONG ' test mapping for accelleration IF ISFALSE Task(%d_accel).tog THEN IF ISFALSE Task(%d_accel).hParam THEN DIM TaskParamLabels(1) AS STATIC ASCIIZ * 8 TaskParamLabels(0) = "sens+" TaskParamLabels(1) = "sens-" MakeTaskParameterDialog %d_accel,2,Slider(),0,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(%d_accel).SliderNumbers(0) Slider(slnr).value = 15 Slider(slnr+1).value = 15 SendMessage Slider(slnr).h, %TBM_SETPOS,%True, Slider(slnr).value SendMessage Slider(slnr+1).h, %TBM_SETPOS,%True, Slider(slnr+1).value END IF Task(%d_accel).tog = %True END IF 'logfile "acc=" & STR$(Gesture.accelleration(3)) IF gesture.accelleration(3) > slider(slnr).value / 128 THEN noot1 = klar.lowtes + (gesture.accelleration(3) * 36) mPlay Klar.channel, noot1, MAX(@pDoppler.za, @pDoppler.ya, @pDoppler.xa) * 127 ELSE IF noot1 THEN MM_Klar_Off %MM_Notes RESET noot1 END IF END IF ' deccelaration: IF gesture.accelleration(4) > slider(slnr+1).value/ 128 THEN noot2 = 72 - (gesture.accelleration(4) * 36) mPlay Bono.channel, noot2, MAX(@pDoppler.za, @pDoppler.ya, @pDoppler.xa) * 100 ELSE IF noot2 THEN MM_Bono_Off %MM_Notes RESET noot2 END IF END IF END SUB SUB Deriv_dAcc () STATIC noot1, noot2, noot3,slnr AS LONG LOCAL n AS SINGLE ' renormalisation factor ' IF cnt MOD 16 = 12 THEN ' logging: ' logfile "dacc=" & STR$(Gesture.dF3(3)) IF ISFALSE Task(%d_3).tog THEN IF ISFALSE Task(%d_3).hParam THEN DIM TaskParamLabels(1) AS STATIC ASCIIZ * 8 TaskParamLabels(0) = "sens+" TaskParamLabels(1) = "sens-" MakeTaskParameterDialog %d_3,2,Slider(),0,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(%d_3).SliderNumbers(0) Slider(slnr).value = 34 Slider(slnr+1).value = 46 SendMessage Slider(slnr).h, %TBM_SETPOS,%True, Slider(slnr).value SendMessage Slider(slnr+1).h, %TBM_SETPOS,%True, Slider(slnr+1).value END IF Task(%d_3).tog = %True END IF ' mapping of the maxima: IF gesture.dF3(3) > slider(slnr).value / 128 THEN n = (gesture.dF3(3) - (slider(slnr).value/ 128)) * (1/ (1 - (slider(slnr).value/128))) noot1 = Ob.lowtes + (n * 36) mPlay Ob.channel, noot1, MAX(@pDoppler.za, @pDoppler.ya, @pDoppler.xa) * 127 ELSE IF noot1 THEN MM_Ob_Off %MM_Notes RESET noot1 END IF END IF ' mapping of the negative peaks: IF gesture.dF3(4) > slider(slnr+1).value / 128 THEN n = (gesture.dF3(4) - (slider(slnr+1).value/128)) * (1/ (1 - (slider(slnr+1).value/128))) noot2 = 84 - (n * 36) mPlay Fa.channel, noot2, MAX(@pDoppler.za, @pDoppler.ya, @pDoppler.xa) * 90 ELSE IF noot2 THEN MM_Fa_Off %MM_Notes RESET noot2 END IF END IF END SUB SUB Shakes() ' just a little ending for Namuda Study #43 ' 15.02.2014: tested o.k. STATIC i AS LONG IF ISFALSE Task(%Shakes).tog THEN i = 60 MM_Whisper_On Task(%Shakes).tog = %True END IF SELECT CASE i MOD 3 CASE 0 mPlay Whisper.channel, 83, i Noteoff Whisper.channel, 84 CASE 1 mPlay Whisper.channel, 84, i NoteOff Whisper.channel, 85 CASE 2 mPlay Whisper.channel, 85, i NoteOff Whisper.channel, 83 END SELECT DECR i IF i = 0 THEN NoteOff Whisper.channel, 83 NoteOff Whisper.channel, 84 NoteOff Whisper.channel, 85 stoptask %Shakes MM_Whisper_Off END IF END SUB SUB Display_derivs 'to be tested STATIC hw AS DWORD STATIC shw AS DWORD STATIC pd AS SINGLE PTR STATIC lb$() LOCAL x AS LONG 'things to display: ' gesture.pdF1(0) = VARPTR(dF1x(0)) ' vector pointers to the speed data 0-255 buffer for all parama, normalized -1 - 1 ' gesture.pdF1(1) = VARPTR(dF1y(0)) ' gesture.pdF1(2) = VARPTR(dF1z(0)) ' ' gesture.pdF2(0) = VARPTR(df2x(0)) ' vector pointers to the accelleration data ' gesture.pdF2(1) = VARPTR(df2y(0)) ' gesture.pdF2(2) = VARPTR(df2z(0)) ' ' gesture.pdF3(0) = VARPTR(dF3x(0)) ' vector pointers to the change of accelleration data ' gesture.pdF3(1) = VARPTR(dF3y(0)) ' gesture.pdF3(2) = VARPTR(dF3z(0)) IF ISFALSE hw THEN DIALOG NEW 0, "displays",,, 258, 400, %DS_MODALFRAME OR %WS_BORDER OR %WS_CAPTION OR %WS_MAXIMIZEBOX OR %WS_MINIMIZEBOX OR %WS_POPUP OR %WS_THICKFRAME TO hw DIM lb$(2) ARRAY ASSIGN lb$() = "Speed", "Acceleration","Change of acceleration" CONTROL ADD COMBOBOX, hw, 1001, lb$(), 1, 1, 100, 60, %CBS_DROPDOWNLIST COMBOBOX SELECT hw, 1001, 1 CONTROL ADD GRAPHIC, hw, 1100, "", 1,14, 256, 100, %WS_BORDER DIALOG SHOW MODELESS hw shw = 1 END IF COMBOBOX GET SELECT hw, 1001 TO shw GRAPHIC ATTACH hw, 1100, REDRAW GRAPHIC SCALE (0, 1) - (255, -1) GRAPHIC CLEAR %WHITE 'x GRAPHIC COLOR %RGB_DARKRED, %WHITE pd = CHOOSE (shw, gesture.pdf1(0), gesture.pdf2(0), gesture.pdf3(0)) GRAPHIC SET PIXEL(0,0) FOR x = 0 TO 255 GRAPHIC LINE STEP - (x, @pd) INCR pd NEXT 'y GRAPHIC COLOR %RGB_DARKGREEN, %WHITE pd = CHOOSE (shw, gesture.pdf1(1), gesture.pdf2(1), gesture.pdf3(1)) GRAPHIC SET PIXEL(0,0) FOR x = 0 TO 255 GRAPHIC LINE STEP - (x, @pd) INCR pd NEXT 'z GRAPHIC COLOR %RGB_DARKBLUE, %WHITE pd = CHOOSE (shw, gesture.pdf1(2), gesture.pdf2(2), gesture.pdf3(2)) GRAPHIC SET PIXEL(0,0) FOR x = 0 TO 255 GRAPHIC LINE STEP - (x, @pd) INCR pd NEXT GRAPHIC REDRAW END SUB '******************************************************************************************* '* Rods for Rodo Code '******************************************************************************************* SUB Rodo_P1 () LOCAL n, i AS LONG STATIC noot1, noot2,noot3, cnt AS LONG STATIC sound1, sound2, sound3 AS SINGLE IF ISFALSE Task(%Rodo_P1).tog THEN ' calculate frequency lookup table FOR n = 48 TO 78 ' 31 rods/notes Rods(n-48).note = n Rods(n-48).f4 = NF2F(n) * 2 Rods(n-48).f5 = rods(n-48).f4 * 1.483 Rods(n-48).f3 = Rods(n-48).f4 / 1.6631 Rods(n-48).f2 = Rods(n-48).f4 / 3.254 Rods(n-48).f1 = Rods(n-48).f4 / 9.088 Rods(n-48).f0 = Rods(n-48).f1 / 6.276 IF Rods(n-48).f0 > 8 THEN Rods(n-48).n0 = F2NF(Rods(n-48).f0) IF Rods(n-48).f1 > 8 THEN Rods(n-48).n1 = F2NF(Rods(n-48).f1) Rods(n-48).n2 = F2NF(Rods(n-48).f2) Rods(n-48).n3 = F2NF(Rods(n-48).f3) Rods(n-48).n4 = F2NF(Rods(n-48).f4) Rods(n-48).n5 = F2NF(Rods(n-48).f5) NEXT n 'logfile "passed lookup type" ' to make this usefull, we need a sort: DIM Rnt(0 TO 186) AS STATIC CUR ' fractional midi notes, 6 for each rod. DIM Rnr(0 TO 186) AS STATIC INTEGER ' tagarray, rod midi base notes 48-78 RESET i , cnt FOR n = 0 TO 30 'i wordt al geincrementeerd, dus n hoeft niet meer in de indexberekening? Rnt(i) = Rods(n).n0 : Rnr(i) = n + 48 Rnt(i+1) = Rods(n).n1 : Rnr(i+1) = n + 48 Rnt(i+2) = Rods(n).n2 : Rnr(i+2) = n + 48 Rnt(i+3) = Rods(n).n3 : Rnr(i+3) = n + 48 Rnt(i+4) = Rods(n).n4 : Rnr(i+4) = n + 48 Rnt(i+5) = Rods(n).n5 : Rnr(i+5) = n + 48 i = i + 6 NEXT n ARRAY SORT Rnt(), TAGARRAY Rnr() RESET noot1, noot2, noot3 Controller Rodo.channel, 13, %False RESET Rodo.ctrl(13) Controller Rodo.channel, 64, 127 ' sustain ON Rodo.ctrl(64) = 127 MM_Rodo_On %MM_White Task(%Rodo_P1).tog = %True END IF SELECT CASE cnt MOD 9 '32 CASE 0 IF ISFALSE noot1 THEN noot1= 48 ' for startup ELSE FOR i = 0 TO UBOUND(rnt) IF (Rnt(i) > sound2) AND (rnt(i) > sound3) THEN IF (rnr(i) = noot2) OR (Rnr(i) = noot3) THEN ITERATE FOR sound1 = Rnt(i) noot1 = Rnr(i) 'logfile "selected n1"+ STR$(noot1) + "- "+ STR$(sound1) EXIT FOR END IF NEXT i END IF ' one rod playing at startup , later 2 rods playing Task(%Rodo_Pt1).freq = Rods(noot1-48).f0 Task(%Rodo_Pt1).pan = noot1 IF ISFALSE Task(%Rodo_Pt1).tog THEN Starttask %Rodo_Pt1 CASE 1 ' look for a different rod with a minimal frequency deviation IF ISFALSE Task(%Rodo_Pt2).tog THEN FOR i = 0 TO UBOUND(rnt) IF (Rnt(i) > sound1) AND (Rnt(i) > sound3) THEN IF (Rnr(i) = noot1) OR (rnr(i) = noot3) THEN ITERATE FOR 'overtone is from the same rod.. sound2 = Rnt(i) noot2 = Rnr(i) '?? dit is de noot waarvan rnt(i) een boventoon was IF noot2 > 92 THEN ' reset noot to 30 sound2 = rnt(0) noot2 = rnt(0) END IF 'logfile "selected n2"+ STR$(noot2) + "- "+ STR$(sound2) EXIT FOR END IF NEXT i Task(%Rodo_Pt2).freq = Rods(noot2-48).f0 Task(%Rodo_Pt2).pan = noot2 Starttask %Rodo_Pt2 ' two rods playing END IF CASE 2 ' look for a third rod: IF ISFALSE Task(%Rodo_Pt3).tog THEN FOR i = 0 TO UBOUND(rnt) IF (Rnt(i) > sound2) AND (rnt(i) > sound1) THEN ' this is wrong! IF (Rnr(i) = noot2) OR (Rnr(i) = noot1) THEN ITERATE FOR 'overtone is from the same rod.. sound3 = Rnt(i) noot3 = Rnr(i) '?? dit is de noot waarvan rnt(i) een boventoon was IF noot3 > 92 THEN ' reset noot to 30 sound3 = rnt(0) noot3 = rnt(0) END IF 'logfile "selected n3"+ STR$(noot3) + "- "+ STR$(sound3) EXIT FOR END IF NEXT i Task(%Rodo_Pt3).freq = Rods(noot3-48).f0 Task(%Rodo_Pt3).pan = noot3 Starttask %Rodo_Pt3 ' three rods playing END IF CASE 3 IF Task(%Rodo_Pt1).tog THEN stoptask %Rodo_Pt1 ' two rods playing CASE 4 ' find new note for noot1: IF ISFALSE Task(%Rodo_Pt1).tog THEN FOR i = 0 TO UBOUND(rnt) IF (Rnt(i) > sound2) AND (rnt(i) > sound3) THEN IF (rnr(i) = noot2) OR (Rnr(i) = noot3) THEN ITERATE FOR sound1 = Rnt(i) noot1 = Rnr(i) 'logfile "selected n1"+ STR$(noot1) + "- "+ STR$(sound1) EXIT FOR END IF NEXT i Task(%Rodo_Pt1).freq = Rods(noot1-48).f0 Task(%Rodo_Pt1).pan = noot1 Starttask %Rodo_Pt1 ' three rods playing END IF CASE 5 IF Task(%Rodo_Pt2).tog THEN stoptask %Rodo_Pt2 ' two rods playing CASE 6 ' find new rod for note2 IF ISFALSE Task(%Rodo_Pt2).tog THEN FOR i = 0 TO UBOUND(rnt) IF (Rnt(i) > sound3) AND (Rnt(i) > sound1) THEN IF (rnr(i) = noot1) OR (Rnr(i) = noot3) THEN ITERATE FOR sound2 = Rnt(i) noot2 = Rnr(i) 'logfile "selected n2"+ STR$(noot2) + "- "+ STR$(sound1) EXIT FOR END IF NEXT i Task(%Rodo_Pt2).freq = Rods(noot2-48).f0 Task(%Rodo_Pt2).pan = noot2 Starttask %Rodo_Pt2 ' three rods playing END IF CASE 7 IF Task(%Rodo_Pt3).tog THEN stoptask %Rodo_Pt3 ' two rods playing CASE 8 IF Task(%Rodo_Pt1).tog THEN stoptask %Rodo_Pt1 ' one rod playing END SELECT logfile "freqs" + STR$(Task(%Rodo_Pt1).freq) + STR$(Task(%Rodo_Pt2).freq) + STR$(Task(%Rodo_Pt3).freq) logfile "notes" + STR$(Task(%Rodo_Pt1).pan) + STR$(Task(%Rodo_Pt2).pan) + STR$(Task(%Rodo_Pt3).pan) INCR cnt END SUB SUB Rodo_P1_Stop () IF Task(%Rodo_Pt1).tog THEN StopTask %Rodo_Pt1 IF Task(%Rodo_Pt2).tog THEN StopTask %Rodo_Pt2 IF Task(%Rodo_Pt3).tog THEN StopTask %Rodo_Pt3 ' reset controllers: Controller Rodo.channel, 13, %False Rodo.ctrl(13)= %False Controller Rodo.channel, 64, %False Rodo.ctrl(64) = %False Controller Rodo.channel, 123, %False ' also lights END SUB SUB Rodo_P2 () 'looks for most consonant combinations '2014.04.04 prevention from looping too soon.. to be tested.. STATIC rod1 AS BYTE, rod2 AS BYTE STATIC lastr AS STRING * 10 LOCAL consl() AS SINGLE LOCAL maxcons AS SINGLE LOCAL h AS harmtype LOCAL n AS LONG LOCAL i AS LONG STATIC noot1, noot2, cnt AS LONG STATIC sound1 AS SINGLE, sound2 AS SINGLE DIM consl(UBOUND(rods)) IF ISFALSE Task(%Rodo_P2).tog THEN ' calculate frequency lookup table FOR n = 48 TO 78 ' 31 rods/notes Rods(n-48).note = n Rods(n-48).f4 = NF2F(n) * 2 Rods(n-48).f5 = rods(n-48).f4 * 1.483 Rods(n-48).f3 = Rods(n-48).f4 / 1.6631 Rods(n-48).f2 = Rods(n-48).f4 / 3.254 Rods(n-48).f1 = Rods(n-48).f4 / 9.088 Rods(n-48).f0 = Rods(n-48).f1 / 6.276 IF Rods(n-48).f0 > 8 THEN Rods(n-48).n0 = F2NF(Rods(n-48).f0) IF Rods(n-48).f1 > 8 THEN Rods(n-48).n1 = F2NF(Rods(n-48).f1) Rods(n-48).n2 = F2NF(Rods(n-48).f2) Rods(n-48).n3 = F2NF(Rods(n-48).f3) Rods(n-48).n4 = F2NF(Rods(n-48).f4) Rods(n-48).n5 = F2NF(Rods(n-48).f5) NEXT n noot1 = 50 Controller Rodo.channel, 64, 127 ' sustain ON Rodo.ctrl(64) = 127 MM_Rodo_On %MM_Yellow Task(%Rodo_P2).tog = %True END IF SELECT CASE cnt MOD 5 '32 CASE 0 ' one rod playing Task(%Rodo_Pt1).freq = Rods(noot1-48).f0 Task(%Rodo_Pt1).pan = noot1 IF ISFALSE Task(%Rodo_Pt1).tog THEN Starttask %Rodo_Pt1 CASE 1 IF ISFALSE Task(%Rodo_Pt2).tog THEN FOR i = 0 TO UBOUND(Rods) IF INSTR(lastr, CHR$(i)) THEN ITERATE FOR 'prevent short loops, exclude last played notes.. IF i = rod1 THEN ITERATE FOR IF i = rod2 THEN ITERATE FOR RESET h AddNote2Har h, Rods(rod1).note, 64 AddNote2Har h, Rods(rod1).n2, 64 AddNote2Har h, Rods(rod1).n3, 64 AddNote2Har h, Rods(rod1).n4, 64 AddNote2Har h, Rods(rod1).n5, 64 AddNote2Har h, Rods(i).note, 64 AddNote2Har h, Rods(i).n2, 64 AddNote2Har h, Rods(i).n3, 64 AddNote2Har h, Rods(i).n4, 64 AddNote2Har h, Rods(i).n5, 64 consl(i) = GetAkuCons(h) maxcons = MAX(consl(i), maxcons) NEXT FOR i = 0 TO UBOUND(consl) IF consl(i) = maxcons THEN EXIT FOR NEXT rod2 = i lastr = CHR$(i) + lastr noot2 = Rods(rod2).note logfile "selected n2"+ STR$(noot2) Task(%Rodo_Pt2).freq = Rods(noot2-48).f0 Task(%Rodo_Pt2).pan = noot2 Starttask %Rodo_Pt2 ' two rods playing END IF CASE 2 IF Task(%Rodo_Pt1).tog THEN stoptask %Rodo_Pt1 ' one rod playing CASE 3 IF ISFALSE Task(%Rodo_Pt1).tog THEN FOR i = 0 TO UBOUND(Rods) IF i = rod2 THEN ITERATE FOR IF i = rod1 THEN ITERATE FOR 'we deliberatly skip the check for repeating notes here, so a combination may come back, 'but then the combination following it will not be the same as the last time.. RESET h AddNote2Har h, Rods(rod2).note, 64 AddNote2Har h, Rods(rod2).n2, 64 AddNote2Har h, Rods(rod2).n3, 64 AddNote2Har h, Rods(rod2).n4, 64 AddNote2Har h, Rods(rod2).n5, 64 AddNote2Har h, Rods(i).note, 64 AddNote2Har h, Rods(i).n2, 64 AddNote2Har h, Rods(i).n3, 64 AddNote2Har h, Rods(i).n4, 64 AddNote2Har h, Rods(i).n5, 64 consl(i) = GetAkuCons(h) maxcons = MAX(consl(i), maxcons) ' logfile STR$(i) + STR$(consl(i)) + STR$(maxcons) NEXT ' logfile "mx" +str$(maxcons) FOR i = 0 TO UBOUND(consl) IF consl(i) = maxcons THEN EXIT FOR NEXT rod1 = i ' logfile "sel"+ str$(i) noot1 = Rods(rod1).note logfile "selected n1"+ STR$(noot1) Task(%Rodo_Pt1).freq = Rods(noot1-48).f0 Task(%Rodo_Pt1).pan = noot1 Starttask %Rodo_Pt1 ' two rods playing END IF CASE 4 IF Task(%Rodo_Pt2).tog THEN stoptask %Rodo_Pt2 ' one rod playing 'case 5 END SELECT INCR cnt END SUB SUB Rodo_P3 () ' 09.02.2014: Used as opening for Namuda Study #43, mapped on piano ' 13.02.2014: rewritten for gesturetype derivatives d1S and d2S ' now #43.1 ' 05.04.2014: Rewritten for use with rodo ' we may have to add ctrl.11 for volume control here. ' Singing Rods. STATIC oldnoot, noot, cnt, slnr AS INTEGER LOCAL expantie, kontraktie AS SINGLE ' kontraktie not used here. IF ISFALSE Task(%Rodo_P3).tog THEN IF ISFALSE Task(%Rodo_P3).hParam THEN DIM TaskParamLabels(0) AS STATIC ASCIIZ * 8 TaskParamLabels(0) = "dS1rodo" ' sensit. for rodo MakeTaskParameterDialog %Rodo_P3,1,Slider(),0,UDctrl(),TaskParamLabels() ' 1 sliders! END IF IF ISFALSE slnr THEN slnr = TaskEX(%Rodo_P3).SliderNumbers(0) Slider(slnr).value = 1 SendMessage Slider(slnr).h, %TBM_SETPOS,%True, Slider(slnr).value END IF MM_Rodo_On Controller Rodo.channel, 11, 127 Rodo.ctrl(11) = 127 Controller Rodo.channel, 13, 1 ' note injection ON Rodo.ctrl(13) = 1 mPlay Rodo.channel, 126, 127 ' rotating red light Task(%Rodo_P3).tog = %True END IF ' genormaliseerde expantie: expantie = gesture.dS1(3) ' genormaliseerde kontraktie kontraktie =gesture.ds1(4) ' always positive 0-1 logfile "exp" + STR$(expantie) INCR cnt IF expantie > (Slider(slnr).value / 127) THEN ' IF noot < rodo.lowtes + (expantie * 62) THEN noot = rodo.lowtes + (expantie * 62) '62 was 31, in welk geval de range te klein bleef ' try to map on something lyrical: IF Rodo.ctrl(11) < 127 THEN Rodo.ctrl(11) = 127 Controller Rodo.channel, 11, 127 END IF IF oldnoot THEN NoteOff Rodo.channel, oldnoot : RESET oldnoot IF noot THEN mPlay Rodo.channel, noot, MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) * 127 oldnoot =noot RESET noot END IF ELSEIF Rodo.ctrl(11)> 60 THEN 'gebeurt alleen als slider op max staat?? Rodo.ctrl(11) = MAX(0, Rodo.ctrl(11) - 4) logfile "decr" + STR$(rodo.ctrl(11)) controller Rodo.channel, 11, Rodo.ctrl(11) IF Rodo.ctrl(11) < 60 THEN NoteOff Rodo.channel, oldnoot END IF ' IF kontraktie > (Slider(slnr+1).value / 127) THEN ' mPlay Xy.channel, xy.lowtes + (kontraktie * 36),MAX(@pDoppler.xa, @pDoppler.ya, @pDoppler.za) * 48 ' END IF ' try to do something with the second derivative now: 'IF gesture.dS2(3) > slider(slnr+2).value / 128 THEN ' scaling to be checked ' mPlay Troms.channel, MIN(24 + (gesture.ds2(3)* 24),127), 30 ' should track movement very well 'END IF END SUB SUB Rodo_P3_Stop () MM_Rodo_Off END SUB SUB Rodo_P4 () ' should become edgy-smooth on fast note repeats versus long injected notes ' started off with the coding used for glasgow 'combined gesture properties gesture.edgy, gesture.smooth ... '05.04.2014: first testing '06.04.2014: further development. LOCAL i AS LONG STATIC noot1, noot2, noot3 AS CUR STATIC tog, cnt, cnth, note, lites1, lites2 AS INTEGER STATIC wind, d, mx AS SINGLE STATIC ni(), no() AS CUR STATIC zh AS HarmType IF ISFALSE Task(%Rodo_P4).tog THEN REDIM ni(3) AS STATIC CUR REDIM no(3) AS STATIC CUR DIM sp(127) AS STATIC DOUBLE AT gesture.pspf(3) 'sum of fast spectra. DIM spi(128) AS STATIC SINGLE DIM aro(127) AS STATIC SINGLE zh.vel = NUL$(128) MM_Rodo_On cnt = %False cnth = 1 ' check this... Controller Rodo.channel, 11, 127 Rodo.ctrl(11) = 127 wind = 127 Task(%Rodo_P4).tog = %True END IF IF (gesture.edgy_dur(3)) AND (gesture.edgy(3)) THEN 'if edgy, we select the beaters with repeats logfile "edgy" + STR$(timegettime/1000) IF Rodo.ctrl(13) <> 0 THEN Controller Rodo.channel, 13, 0 ' no e-bow Rodo.ctrl(13) = %False END IF IF Rodo.ctrl(64) <> 0 THEN Controller Rodo.channel, 64, 0 ' use the dampers Rodo.ctrl(64) = %False END IF IF ni(0) < Rodo.lowtes THEN ni(0) = MIN(rodo.lowtes + (gesture.edgy(0) * 32), rodo.hightes) ' 32 was 128 in the piano version ni(1) = MIN(rodo.lowtes + (gesture.edgy(1) * 32), rodo.hightes) ni(2) = MIN(rodo.lowtes + (gesture.edgy(2) * 32), rodo.hightes) d = HH_Tetrad (0, ni(0), ni(1), ni(2), ni(3), gesture.edgy(3)) 'Helmholtz harmony function, calculates ni(3) addnote2har rodo.har(1), ni(0), (@pDoppler.xa * 127) addnote2har rodo.har(1), ni(1), (@pDoppler.ya * 127) addnote2har rodo.har(1), ni(2), (@pDoppler.za * 127) addnote2Har rodo.har(1), ni(3), (@pDoppler.xa * 127) Instrumplay Rodo ' is this properly implemented? ELSE 'sekwens berekenen... INCR cnt cnt = cnt MOD 3 '0,1,2 IF ISFALSE no(0) THEN no(0) = MIN(rodo.lowtes + (gesture.edgy(cnt) * 32), rodo.hightes) 'no(0) = ni(0) d = HH_Chord_Progres(0, ni(), no(), (gesture.edgy(0) + gesture.edgy(1) + gesture.edgy(2) + gesture.edgy(3)) / 8) 'Helmholtz harmony function addnote2har rodo.har(1), no(0), (@pDoppler.xa * 127) addnote2har rodo.har(1), no(1), (@pDoppler.ya * 127) addnote2har rodo.har(1), no(2), (@pDoppler.za * 127) addnote2Har rodo.har(1), no(3), (@pDoppler.xa * 127) Instrumplay Rodo ni(0) = no(0) : ni(1) = no(1) : ni(2) = no(2) : ni(3)= no(3) ' shouldn't we reset no()? (try, 06.07.2010... gwr) indeed. no(0) = no(0) + cnt 'making progressions... IF no(0) > Rodo.hightes THEN no(0) = ni(0) END IF RESET no(1), no(2), no(3) END IF IF ISFALSE lites1 THEN MM_Rodo_On %MM_White lites1 = %True END IF Task(%Rodo_P4).freq = MAX(2, gesture.fixspeed_val(3)/10) EXIT SUB ELSE IF ni(0) THEN Controller Rodo.channel, 123, 0 RESET Lites1 RESET Rodo.Har(1) 'Instrumplay Rodo 'notes off RESET no() RESET ni() END IF END IF IF gesture.smooth_dur(3) THEN 'íf smooth, we select 'sung' notes based on the strongest component from the movement spectrum. logfile "smooth" + STR$(timegettime/1000) IF Rodo.ctrl(13) <> 1 THEN controller Rodo.channel, 13, 1 ' e drive ON Rodo.ctrl(13) = 1 END IF IF Rodo.ctrl(64) <> 127 THEN Controller Rodo.channel, 64, 127 ' sustain ON Rodo.ctrl(64) = 127 END IF FOR i = 0 TO 127 mx = MAX(mx, sp(i)) 'mx is never zero. NEXT i FOR i = 0 TO 127 Spi(i) = sp(i) * @pDoppler.za/mx NEXT i ArrayReduce_SNG (spi(), 2, aro()) ' if we just need a single value, we better use ArrayMax_SNG IF cnth > 32 THEN cnth = 32 LinSpec2Har (aro(), zh, cnth ) '64 was Slider(slnr).value) ' in g_mus ' cnth is the unit bandwidth 'Rodo.Har(1).vel = ReScaleHarvel (zh, 0.5) 'velocities need to be scaled down: (now -50%) ' was: Rodo.Har(1).vel = zh.vel ' in fact we only need the strongest component here... ' we can retrieve the strongest spectral note as: note = GetstrongestNoteVelo (zh) ROTATE RIGHT note, 8 IF note > 0 THEN IF note < Rodo.lowtes THEN DO note = note + 12 LOOP UNTIL note >= Rodo.lowtes END IF IF note > Rodo.hightes THEN DO note = note -12 LOOP UNTIL note <= Rodo.Hightes END IF mPlay Rodo.channel, note, MAX(@pDoppler.za, @pDoppler.ya, @pDoppler.xa) * 127 ELSE Controller Rodo.channel, 123, %False RESET lites2 END IF ' was: InstrumPlay Rodo 'range for gesture.smooth_val(3) checked. wind = (wind * 0.9375) + (gesture.smooth_val(3) * 7.9375) ' could be used for ctrl.11, e drive volume. wind = MAX(MIN(wind, 127), 115) IF rodo.ctrl(11) <> INT(wind) THEN controller rodo.channel, 11, INT(wind) Rodo.ctrl(11) = INT(wind) END IF 'light: IF ISFALSE lites2 THEN MM_Rodo_On %MM_Red lites2 = %True END IF tog = %True Task(%Rodo_P4).freq = MAX(2, gesture.fixspeed_val(3) / 50) INCR cnth EXIT SUB ELSE Controller Rodo.channel, 123, %False lites2 = %False IF tog THEN 'MM_Rodo_Off %MM_Red RESET tog cnth = 1 '32 ' was 40 in the piano coding, reset value END IF END IF Task(%Rodo_P4).freq = 8 ' MAX(2, gesture.fixspeed_val(3) / 25) END SUB SUB Rodo_P5 () ' SLOWDOWN mapping ' 06.04.2014 rewritten ' speedup --> incr. notes(3) - sustain ON (= Rodo_P6 task) ' slowdown --> decr. notes(3) = sustain OFF -descending ' else... NIKS, ? all dampers down? ' started from coding Rob6 in Dunkeldark or RoboDomi STATIC xtrig, ytrig, ztrig AS LONG STATIC xnoot, ynoot, znoot, lites AS WORD STATIC sens AS SINGLE IF ISFALSE Task(%Rodo_P5).tog THEN sens = 6 '10 '12 MM_Rodo_On Task(%Rodo_P5).tog = %True END IF ' logfile str$(Gesture.slowdown(0)) + STR$(Gesture.slowdown(1)) + STR$(Gesture.slowdown(2)) 'unipolar?? jup IF Gesture.slowdown(0) > sens THEN ' frequency is unipolar data! - under algo1, can go up to 230 IF ISFALSE xtrig THEN IF Rodo.ctrl(64) <> %False THEN ' dempers ON Controller Rodo.channel, 64, %False RESET Rodo.ctrl(64) END IF xnoot = MIN(Rodo.lowtes - sens + 5+ ( gesture.slowdown_val(0)), Rodo.hightes) 'independent from sens 15.04 logfile "x" + STR$(xnoot) IF xnoot > Task(%Rodo_Pt1).pan THEN xnoot = MAX(Rodo.lowtes, Task(%Rodo_Pt1).pan - 1) ' so melody should always go down ELSE xnoot = (xnoot + 2 *Task(%Rodo_Pt1).pan) / 3 END IF logfile "pan" + STR$(xnoot) IF xnoot = ynoot THEN DECR xnoot IF xnoot = znoot THEN DECR xnoot IF xnoot = ynoot THEN DECR xnoot 'sic voor eht geval znoot = ynoot + 1.. Task(%Rodo_Pt1).pan = xnoot logfile STR$(xnoot) IF xnoot >= Rodo.lowtes THEN mPlay Rodo.channel, xnoot, (@pDoppler.xa * 127) '64 xtrig = %True ELSE RESET xtrig, xnoot Task(%Rodo_Pt1).pan = Rodo.HighTes '(Rodo.lowtes + Rodo.hightes) / 2 END IF END IF ELSE IF xtrig THEN IF xnoot THEN mPlay Rodo.channel, xnoot, %False RESET xnoot END IF END IF RESET xtrig END IF IF Gesture.slowdown(1) > sens THEN IF ISFALSE ytrig THEN IF Rodo.ctrl(64) <> %False THEN ' dempers ON Controller Rodo.channel, 64, %False RESET Rodo.ctrl(64) END IF ynoot = MIN(Rodo.lowtes - sens + 5+ ( gesture.slowdown_val(1)), Rodo.hightes) logfile "y" + STR$(ynoot) IF ynoot > Task(%Rodo_Pt2).pan THEN ynoot = MAX(Rodo.lowtes, Task(%Rodo_Pt2).pan - 1) ' so melody will always go down ELSE ynoot = (ynoot + 2 * Task(%Rodo_Pt2).pan) / 3 END IF logfile "pan" + STR$(ynoot) IF ynoot = xnoot THEN DECR ynoot IF ynoot = znoot THEN DECR ynoot IF ynoot = xnoot THEN DECR ynoot 'sic voor het geval znoot = ynoot + 1.. logfile STR$(ynoot) Task(%Rodo_Pt2).pan = ynoot IF ynoot >= Rodo.lowtes THEN mPlay Rodo.channel, ynoot,(@pDoppler.ya * 127) ' 64 ytrig = %true ELSE RESET ytrig, ynoot Task(%Rodo_Pt2).pan = Rodo.HighTes - 1 '(Rodo.lowtes + Rodo.hightes+ 2) / 2 END IF END IF ELSE IF ytrig THEN IF ynoot THEN mPlay Rodo.channel, ynoot, %False RESET ynoot END IF END IF RESET ytrig END IF IF Gesture.slowdown(2) > sens THEN IF ISFALSE ztrig THEN ' avoiding multiple triggers IF Rodo.ctrl(64) <> %False THEN ' dempers ON Controller Rodo.channel, 64, %False RESET Rodo.ctrl(64) END IF znoot = MIN(Rodo.lowtes - sens + 5+(gesture.slowdown_val(2)),Rodo.hightes) 'slowdown_val can get over 30, but usually stays rather small! logfile "z" + STR$(znoot) IF znoot > Task(%Rodo_Pt3).pan THEN znoot = MAX(Rodo.lowtes, Task(%Rodo_Pt3).pan - 1) ' so melody will always go down ELSE znoot = (znoot + 2 * Task(%Rodo_Pt3).pan) / 3 END IF logfile "pan" + STR$(znoot) IF znoot = ynoot THEN DECR znoot IF znoot = xnoot THEN DECR znoot IF znoot = ynoot THEN DECR znoot 'sic voor eht geval znoot = ynoot + 1.. logfile STR$(znoot) Task(%Rodo_Pt3).pan = znoot IF znoot >= Rodo.lowtes THEN mPlay Rodo.channel, znoot, (@pDoppler.za * 127) ztrig = %True ELSE RESET ztrig, znoot Task(%Rodo_Pt3).pan = Rodo.HighTes - 3 '(Rodo.lowtes + Rodo.hightes+ 4) / 2 END IF END IF ELSE IF ztrig THEN IF znoot THEN mPlay Rodo.channel, znoot , %False RESET znoot END IF END IF RESET ztrig END IF IF (gesture.slowdown(3) > sens) AND (gesture.slowdown(3) > gesture.speedup(3)) THEN IF ISFALSE lites THEN ' switch on feedback? IF Rodo.ctrl(13) <> 2 THEN Controller Rodo.channel, 13, 2 Rodo.ctrl(13) = 2 END IF MM_Rodo_On %MM_Red lites = %True END IF ELSE IF lites THEN ' feedback OFF IF Rodo.ctrl(13) <> 0 THEN Controller Rodo.channel, 13, 0 Rodo.ctrl(13) = 0 END IF MM_Rodo_Off %MM_Red RESET lites END IF END IF END SUB SUB Rodo_P5_Stop () ' reset the notes to lowest: Task(%Rodo_Pt1).pan = Rodo.Lowtes Task(%Rodo_Pt2).pan = Rodo.Lowtes + 2 Task(%Rodo_Pt3).pan = Rodo.Lowtes + 4 END SUB SUB Rodo_P6 () '06.04.2014: based on Rob5 in robodomi en dunkeldark ' gesture property SPEEDUP ' here we look only into the frequency data in order to detect accelerating gesture ' melody will go UP ' repetition rate dependent on speedup value ' uses the playing tasks. STATIC xtrig, ytrig, ztrig, xnoot, ynoot, znoot, lites AS LONG STATIC sens AS SINGLE IF ISFALSE Task(%Rodo_P6).tog THEN sens = 18 'in Hz units MM_Rodo_On Task(%Rodo_P6).tog = %True END IF ' on accelerating body speed, do something... ' X-vektor: IF gesture.speedup(0) > gesture.slowdown(0) + sens THEN IF ISFALSE xtrig THEN IF Rodo.ctrl(64) <> 127 THEN ' sustain ON Controller Rodo.channel, 64, 127 Rodo.ctrl(64) = 127 END IF xnoot = MIN(Rodo.lowtes - sens + (gesture.speedup(0)* 1.5), Rodo.Hightes) IF xnoot < Task(%Rodo_Pt1).pan THEN xnoot = MIN(Task(%Rodo_Pt1).pan + 1, Rodo.Hightes) END IF Task(%Rodo_Pt1).pan = xnoot Task(%Rodo_Pt1).freq = MAX(3,MIN(gesture.speedup_val(0), 48)) 'mPlay Rodo.channel,xnoot, MIN(gesture.speedup_val(0) * 2, 127) IF ISFALSE Task(%Rodo_Pt1).tog THEN Starttask %Rodo_Pt1 xtrig = %True END IF ELSE RESET xtrig IF xnoot THEN IF ISFALSE gesture.speedup_dur(0) THEN IF Task(%Rodo_Pt1).tog THEN stoptask %Rodo_Pt1 RESET xnoot END IF END IF END IF IF gesture.speedup(1) > gesture.slowdown(1) + sens THEN IF ISFALSE ytrig THEN IF Rodo.ctrl(64) <> 127 THEN ' sustain ON Controller Rodo.channel, 64, 127 Rodo.ctrl(64) = 127 END IF ynoot = MIN(Rodo.lowtes - sens + (gesture.speedup(1)* 1.5), Rodo.Hightes) IF ynoot < Task(%Rodo_Pt2).pan THEN ynoot = MIN(Task(%Rodo_Pt2).pan + 1, Rodo.Hightes) END IF Task(%Rodo_Pt2).pan = ynoot Task(%Rodo_Pt2).freq = MAX(3,MIN(gesture.speedup_val(1), 48)) IF ISFALSE Task(%Rodo_Pt2).tog THEN Starttask %Rodo_Pt2 ytrig = %true END IF ELSE IF ynoot THEN IF ISFALSE gesture.speedup_dur(1) THEN IF Task(%Rodo_Pt2).tog THEN stoptask %Rodo_Pt2 RESET ynoot END IF END IF RESET ytrig END IF IF gesture.speedup(2) > gesture.slowdown(2) + sens THEN IF ISFALSE ztrig THEN IF Rodo.ctrl(64) <> 127 THEN ' sustain ON Controller Rodo.channel, 64, 127 Rodo.ctrl(64) = 127 END IF znoot = MIN(Rodo.lowtes - sens + (gesture.speedup(2)* 1.5), Rodo.Hightes) IF znoot < Task(%Rodo_Pt3).pan THEN znoot = MIN(Task(%Rodo_Pt3).pan + 1, Rodo.Hightes) END IF Task(%Rodo_Pt3).pan = znoot Task(%Rodo_Pt3).freq = MAX(3,MIN(gesture.speedup_val(2), 48)) IF ISFALSE Task(%Rodo_Pt3).tog THEN Starttask %Rodo_Pt3 ztrig = %True END IF ELSE IF znoot THEN IF ISFALSE gesture.speedup_dur(2) THEN IF Task(%Rodo_Pt3).tog THEN stoptask %Rodo_Pt3 RESET znoot END IF END IF RESET ztrig END IF ' lites: IF gesture.speedup(3) > gesture.slowdown(3) + sens THEN IF ISFALSE lites THEN MM_Rodo_On %MM_Blue lites = %True END IF ELSE IF lites THEN MM_Rodo_Off %MM_Blue RESET lites END IF END IF END SUB SUB Rodo_P6_Stop () IF Task(%Rodo_Pt1).tog THEN stoptask %Rodo_Pt1 IF Task(%Rodo_Pt2).tog THEN stoptask %Rodo_Pt2 IF Task(%Rodo_Pt3).tog THEN stoptask %Rodo_Pt3 ' reset the notes to highest: Task(%Rodo_Pt1).pan = Rodo.Hightes Task(%Rodo_Pt2).pan = Rodo.Hightes - 2 Task(%Rodo_Pt3).pan = Rodo.Hightes - 4 END SUB SUB Rodo_Pt1 () ' the note to be played is passed in the Task().pan field ' the repetition rate in the Task().freq field STATIC velo AS BYTE ' we may have to use task().level instead. STATIC freq AS SINGLE IF ISFALSE Task(%Rodo_Pt1).tog THEN freq = Task(%Rodo_Pt1).freq ' save init value as reference IF freq < 0.5 THEN logfile "Pt1 freq too low" & STR$(freq) Task(%Rodo_Pt1).tog = %True END IF velo = MAX(@pDoppler.za, @pDoppler.ya, @pDoppler.xa) * 127 IF velo THEN mPlay Rodo.channel, Task(%Rodo_Pt1).pan, velo END IF Task(%Rodo_Pt1).freq = freq + (1.5 * freq * (gesture.velocity(3) - 0.5)) END SUB SUB Rodo_Pt2 () STATIC velo AS BYTE STATIC freq AS SINGLE IF ISFALSE Task(%Rodo_Pt2).tog THEN freq = Task(%Rodo_Pt2).freq IF freq < 0.5 THEN logfile "Pt2 freq too low" & STR$(freq) Task(%Rodo_Pt2).tog = %True END IF velo =MAX(@pDoppler.za, @pDoppler.ya, @pDoppler.xa) * 127 ' 20 IF velo THEN mPlay Rodo.channel, Task(%Rodo_Pt2).pan, velo END IF Task(%Rodo_Pt2).freq = freq + (1.5* freq * (gesture.velocity(3) - 0.5)) END SUB SUB Rodo_Pt3 () STATIC velo AS BYTE STATIC freq AS SINGLE IF ISFALSE Task(%Rodo_Pt3).tog THEN freq = Task(%Rodo_Pt3).freq IF freq < 0.5 THEN logfile "Pt3 freq too low" & STR$(freq) Task(%Rodo_Pt3).tog = %True END IF velo = MAX(@pDoppler.za, @pDoppler.ya, @pDoppler.xa) * 127 '20 IF velo THEN mPlay Rodo.channel, Task(%Rodo_Pt3).pan, velo END IF Task(%Rodo_Pt3).freq = freq + (1.5 * freq * (gesture.velocity(3) - 0.5)) END SUB