'******************************************** '* < RODO > * '* musical robot by dr.Godfried-Willem Raes * '* 2014 * '* User interface test code * '******************************************** '12.01.2014: start coding, modelled after Toypi. '04.03.2014: test code for lights added '12.03.2014: First tests on Rodo '16.03.2014: tests with dampers '22.03.2014: Test for for lights extended. '05.04.2014: Some further work on a rodo piece... '17.03.2017: Revision of the e-drive implementation and hardware on Rodo. '%Radar_listen = 17 ' 9.45GHz system Picra - tasknr. transferred to dll (g_lib.dll - g_midi.inc) %Rodo_Scale_Test = 18 '24 %Rodo_Dyna_Test = 19 '25 %Rodo_Damp_Test = 20 %Rodo_Edrive = 21 %Rodo_KP = 22 %Rodo_Ctrl_Test = 22 ' controller 14,15,16,64 %Rodo_Lites = 26 %Rodo_Blue = 27 %Rodo_Yellow = 28 %Rodo_White = 29 %Rodo_Red = 30 %Rodo_Rot = 31 %Rodo_Piece = 48 %Rodo_Pt1 = 49 ' playtask 1 %Rodo_Pt2 = 50 ' playtask 2 %rodo_piece2 = 51 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 'GLOBAL pRadPic() AS RadarPicController PTR ' in g_lib.dll - g_midi.inc DECLARE FUNCTION Init_Rodo () AS LONG DECLARE SUB Rodo_Scale_Test () DECLARE SUB Rodo_Dyna_Test () ' without note-off's DECLARE SUB Rodo_Damp_Test () ' using nothing but note-off + release commands DECLARE SUB Rodo_Edrive () DECLARE SUB Rodo_Lites () DECLARE SUB Rodo_Lites_Off () DECLARE SUB Rodo_Ctrl_Test () ' dempers DECLARE SUB Rodo_Blue () DECLARE SUB Rodo_Yellow () DECLARE SUB Rodo_White () DECLARE SUB Rodo_Rot () DECLARE SUB Rodo_KP () DECLARE SUB Rodo_Piece () FUNCTION Init_Rodo () AS LONG LOCAL m AS ASCIIZ * 40 LOCAL i AS DWORD LOCAL j AS LONG LOCAL retval AS LONG LOCAL pmask AS QUAD PTR DIM Rods(0 TO 30) AS GLOBAL RodoRods_Type 'picra init - copied from sire ' pmask = SetMidiListenChannel (15, %False) ' returns pointer ' FOR i = 0 TO 255: BIT RESET @pmask, i: NEXT i 'reset 4 quads!! ' DIM pRadPic(7) AS GLOBAL RadarPicController PTR ' FOR i = 0 TO 3 '(%MaxNr of devices...) ' pRadPic(i) = GetPicRadarPointer (i, %Radar_listen, 256 * i + i) ' dev.nr, listentasknr, port/channel word ' IF ISFALSE pRadPic(i) THEN ' IF i < 3 THEN ' FUNCTION = %False ' Warning "failed intialsing radpics!",2000 ' EXIT FUNCTION ' here we need at least 3 devices ' ELSE ' REDIM PRESERVE pRadPic(i-1) AS GLOBAL RadarPicController PTR ' EXIT FOR ' END IF ' END IF ' NEXT i ' Create_PicRadar_Control (Slider(), UDctrl()) ' create user interface for the PIC listen-task CONTROL SET TEXT gh.Cockpit,0, " test code " IF ISFALSE hMidiI(0) THEN ButnSw(0).tag0 = "" ButnSw(0).cptr = %False END IF ButnSW(2).tag0 = "Pow On" ' switches solenoid voltage on/off - not yet implemented ButnSW(2).tag1 = "Pow Off" ButnSW(2).cptr = CODEPTR(Rodo_Power) ButnSW(3).tag0 = "" ButnSW(4).tag0 = "" ' harm ButnSW(5).tag0 = "" ' melo ButnSW(6).tag0 = "" ' psy ButnSW(7).tag0 = "" 'spec ButnSW(8).tag0 = "" ButnSW(9).tag0 = "" ButnSW(10).tag0 = "" ButnSW(11).tag0 = "" ButnOS(5).tag = "" ButnOS(6).tag = "" CONTROL SET TEXT gh.cockpit, %GMT_TITLE, " CONTROL SET TEXT gh.cockpit, %GMT_AUTHOR, $gwr Task(%Rodo_Scale_Test).naam = "Scale" Task(%Rodo_Scale_Test).cptr = CODEPTR(Rodo_Scale_Test) Task(%Rodo_Scale_Test).freq = 4 Task(%Rodo_Scale_Test).flags = %False Task(%Rodo_Dyna_Test).naam = "Dyna" Task(%Rodo_Dyna_Test).cptr = CODEPTR(Rodo_Dyna_Test) Task(%Rodo_Dyna_Test).freq = 4 Task(%Rodo_Dyna_Test).flags = %False Task(%Rodo_Damp_Test).naam = "Damp" Task(%Rodo_Damp_Test).cptr = CODEPTR(Rodo_Damp_Test) Task(%Rodo_Damp_Test).freq = 2 Task(%Rodo_Damp_Test).flags = %False Task(%Rodo_Ctrl_Test).naam = "Ctrl" Task(%Rodo_Ctrl_Test).cptr = CODEPTR(Rodo_Ctrl_Test) Task(%Rodo_Ctrl_Test).freq = 4 Task(%Rodo_Ctrl_Test).flags = %False Task(%Rodo_Edrive).naam = "E-drive" Task(%Rodo_Edrive).cptr = CODEPTR(Rodo_Edrive) Task(%Rodo_Edrive).freq = 10 Task(%Rodo_Edrive).flags = %False Task(%Rodo_KP).naam = "e_KPtst" Task(%Rodo_KP).cptr = CODEPTR(Rodo_KP) Task(%Rodo_KP).freq = 4 Task(%Rodo_KP).flags = %False Task(%Rodo_lites).naam = "Lights" Task(%Rodo_lites).cptr = CODEPTR(Rodo_lites) Task(%Rodo_lites).freq = 4 Task(%Rodo_lites).flags = %False Taskex(%Rodo_lites).stopcptr = CODEPTR(Rodo_lites_off) Task(%Rodo_Yellow).naam = "Yellow" Task(%Rodo_Yellow).cptr = CODEPTR(Rodo_Yellow) Task(%Rodo_Yellow).freq = 1 Task(%Rodo_Yellow).flags = %False Taskex(%Rodo_Yellow).stopcptr = CODEPTR(Rodo_Yellow_off) Task(%Rodo_White).naam = "White" Task(%Rodo_White).cptr = CODEPTR(Rodo_White) Task(%Rodo_White).freq = 1 Task(%Rodo_White).flags = %False Taskex(%Rodo_White).stopcptr = CODEPTR(Rodo_White_off) Task(%Rodo_Blue).naam = "Blue" Task(%Rodo_Blue).cptr = CODEPTR(Rodo_Blue) Task(%Rodo_Blue).freq = 1 Task(%Rodo_Blue).flags = %False Taskex(%Rodo_Blue).stopcptr = CODEPTR(Rodo_Blue_off) Task(%Rodo_Red).naam = "Red" Task(%Rodo_Red).cptr = CODEPTR(Rodo_Red) Task(%Rodo_Red).freq = 1 Task(%Rodo_Red).flags = %False Taskex(%Rodo_Red).stopcptr = CODEPTR(Rodo_Red_off) Task(%Rodo_Rot).naam = "RedRot" Task(%Rodo_Rot).cptr = CODEPTR(Rodo_Rot) Task(%Rodo_Rot).freq = 1 Task(%Rodo_Rot).flags = %False Taskex(%Rodo_Rot).stopcptr = CODEPTR(Rodo_Rot_off) Task(%Rodo_Piece).naam = "Piece" Task(%Rodo_Piece).cptr = CODEPTR(Rodo_Piece) Task(%Rodo_Piece).freq = 0.2 Task(%Rodo_Piece).flags = %False Taskex(%Rodo_Piece).stopcptr = CODEPTR(MM_Rodo_off) Task(%Rodo_Pt1).naam = "Pt-1" Task(%Rodo_Pt1).cptr = CODEPTR(Rodo_Pt1) Task(%Rodo_Pt1).freq = 50 Task(%Rodo_Pt1).flags = %False Task(%Rodo_Pt2).naam = "Pt-2" Task(%Rodo_Pt2).cptr = CODEPTR(Rodo_Pt2) Task(%Rodo_Pt2).freq = 48 Task(%Rodo_Pt2).flags = %False Task(%Rodo_Piece2).naam = "Piece2" Task(%Rodo_Piece2).cptr = CODEPTR(Rodo_Piece2) Task(%Rodo_Piece2).freq = 0.4 Task(%Rodo_Piece2).flags = %False Taskex(%Rodo_Piece).stopcptr = CODEPTR(MM_Rodo_off) FUNCTION = %true END FUNCTION SUB Rodo_Power () ' buttonswitch handler IF ISFALSE ButnSW(2).flag THEN Rodo.ctrl(66) = %False 'Controller Rodo.channel, 123, %False Controller Rodo.channel, 66, Rodo.ctrl(66) ELSE Rodo.ctrl(66) = %True Controller Rodo.channel, 66, Rodo.ctrl(66) END IF END SUB SUB Rodo_Scale_test () ' test note on/off with dampers. STATIC note, oldnote AS INTEGER STATIC init, cnt AS LONG LOCAL velo AS DWORD STATIC slnr() AS INTEGER IF ISFALSE init THEN 'Task(%Rodo_Scale_Test).tog THEN init = 1 note = Rodo.lowtes ' create sliders: DIM Slnr(0 TO 2) AS STATIC INTEGER DIM TaskParamLabels(0 TO 2) AS STATIC ASCIIZ*8 TaskParamLabels(0)="Velo" ' attack force for beaters TaskParamLabels(1)="Freq" ' speed TaskParamLabels(2)="Demp" ' damping time for release IF ISFALSE Task(%Rodo_Scale_Test).hParam THEN MakeTaskParameterDialog BYVAL %Rodo_Scale_Test,3, Slider(),0,UdCtrl(), TaskParamLabels() END IF slnr(0) = TaskEX(%Rodo_Scale_Test).SliderNumbers(0) slnr(1) = TaskEX(%Rodo_Scale_Test).SliderNumbers(1) slnr(2) = TaskEX(%Rodo_Scale_Test).SliderNumbers(2) Slider(Slnr(0)).value = 1 Slider(Slnr(1)).value = 4 Slider(Slnr(2)).value = 40 SendMessage Slider(Slnr(0)).h, %TBM_SETPOS,%True, Slider(Slnr(0)).value SendMessage Slider(Slnr(1)).h, %TBM_SETPOS,%True, Slider(Slnr(1)).value SendMessage Slider(Slnr(2)).h, %TBM_SETPOS,%True, Slider(Slnr(2)).value Task(%Rodo_Scale_Test).tog = %True END IF IF cnt = 0 THEN velo = Slider(Slnr(0)).value IF velo THEN CONTROL SET TEXT gh.cockpit,%GMT_MSG1, STR$(note) mPlay Rodo.channel, note, velo oldnote = note INCR note IF note > Rodo.hightes THEN note = Rodo.lowtes ELSE IF oldnote THEN Release Rodo.channel, oldnote, Slider(Slnr(2)).value 'Rodo.ctrl(14) 'should be equivalent to mPlay Rodo.channel, oldnote, %False oldnote = %False END IF END IF ELSE IF oldnote THEN Release rodo.channel, oldnote, Slider(Slnr(2)).value 'Rodo.ctrl(14) oldnote = %False END IF END IF INCR cnt cnt = cnt MOD 2 Task(%Rodo_Scale_Test).freq = MAX(.5, Slider(Slnr(1)).value / 2!) END SUB SUB Rodo_Dyna_Test () ' this proc. does not send any note-off's ' test for the beater-pic's, to check the velocity scaling in the firmware. STATIC note AS INTEGER LOCAL velo AS DWORD STATIC slnr() AS INTEGER STATIC ud AS INTEGER STATIC init AS LONG IF ISFALSE init THEN init = 1 ' create sliders: DIM Slnr(0 TO 1) AS STATIC INTEGER DIM TaskParamLabels(0 TO 2) AS STATIC ASCIIZ*8 TaskParamLabels(0)="Velo" ' attack force for beaters TaskParamLabels(1)="Freq" ' speed TaskParamLabels(2)="Note" ' up down for the note IF Task(%Rodo_Dyna_Test).hParam = %Null THEN MakeTaskParameterDialog BYVAL %Rodo_Dyna_Test,2, Slider(),1,UdCtrl(), TaskParamLabels() END IF slnr(0) = TaskEX(%Rodo_Dyna_Test).SliderNumbers(0) slnr(1) = TaskEX(%Rodo_Dyna_Test).SliderNumbers(1) ud = TaskEX(%Rodo_Dyna_Test).UpDownNumbers(0) Slider(Slnr(0)).value = 1 Slider(Slnr(1)).value = 4 UdCtrl(ud).value = Rodo.lowtes UdCtrl(ud).minval = Rodo.lowtes UdCtrl(ud).maxval = Rodo.hightes UdCtrl(ud).resetval = Rodo.lowtes UdCtrl(ud).stap = 1 UDctrl(ud).cptr = CODEPTR(Rodo_UD_Noot_CB) SendMessage Slider(Slnr(0)).h, %TBM_SETPOS,%True, Slider(Slnr(0)).value SendMessage Slider(Slnr(1)).h, %TBM_SETPOS,%True, Slider(Slnr(1)).value Task(%Rodo_Dyna_Test).tog = %True END IF note = UdCtrl(ud).value velo = Slider(Slnr(0)).value IF velo THEN mPlay Rodo.channel, note, velo Task(%Rodo_Dyna_Test).freq = MAX(.5, Slider(Slnr(1)).value / 2!) END SUB SUB Rodo_UD_Noot_CB () ' for callback on parameter UpDown. LOCAL note AS SINGLE note = UDCtrl(TaskEX(%Rodo_Dyna_Test).UpdownNumbers(0)).value CONTROL SET TEXT Task(%Rodo_Dyna_Test).hparam, %GMT_TEXT0_ID + 16, "N=" & STR$(note) END SUB SUB Rodo_Edrive () ' test for the Axo board, to check the ARM firmware. ' 17.03.2017: rewritten for the PIC 24 coding by gwr. ' ctrl 13: bit 0 turns ebow on of off, so all even values turn it off ' bit 1 sets feedback mode on or off ' bit 2 switches note injection mode on or off ' bit 3 if bit 2 is on, switches between notes using noteon/noteoff commands or key pressure commands ' ctrl 11 was e-drive amplitude in the old implementation (Volume) ' ctrl 7 sets the sustain level for e-drive ' ctrl 2 sets the duty cycle for the waveform ' ctrl 12 e-drive jitter ' ctrl 17 attack time ' ctrl 18 decay time ' ctrl 19 release time ' Tuning lookups can be changed withj program change commands now STATIC note AS INTEGER LOCAL velo AS DWORD STATIC slnr AS INTEGER STATIC ud AS INTEGER STATIC init AS LONG IF ISFALSE init THEN init = 1 ' create sliders: DIM TaskParamLabels(0 TO 7) AS STATIC ASCIIZ*8 TaskParamLabels(0)="CC2" ' duty cycle TaskParamLabels(1)="CC7" ' sustain level TaskParamLabels(2)="CC11" ' e drive amplitude TaskParamLabels(3)="CC12" ' e-drive jitter TaskParamLabels(4)="CC17" ' attack time TaskParamlabels(5)="CC18" ' decay time TaskParamLabels(6)="CC19" ' release time TaskParamLabels(7)="CC13" ' mode UD IF Task(%Rodo_Edrive).hParam = %Null THEN MakeTaskParameterDialog BYVAL %Rodo_Edrive,7, Slider(),1,UdCtrl(), TaskParamLabels() END IF slnr = TaskEX(%Rodo_Edrive).SliderNumbers(0) ud = TaskEX(%Rodo_Edrive).UpDownNumbers(0) Slider(Slnr).value = 127 UdCtrl(ud).value = 0 UdCtrl(ud).minval = 0 UdCtrl(ud).maxval = 15 ' 4 bits UdCtrl(ud).resetval = 0 UdCtrl(ud).stap = 1 UDctrl(ud).cptr = CODEPTR(Rodo_UD_Edrive_CB) SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value Task(%Rodo_Edrive).tog = %True END IF IF Rodo.ctrl(2) <> Slider(slnr).value THEN Controller Rodo.channel, 2, Slider(slnr).value Rodo.ctrl(2) = Slider(slnr).value END IF IF Rodo.ctrl(7) <> Slider(slnr+1).value THEN Controller Rodo.channel, 7, Slider(slnr+1).value Rodo.ctrl(7) = Slider(slnr+1).value END IF IF Rodo.ctrl(11) <> Slider(slnr+2).value THEN Controller Rodo.channel, 11, Slider(slnr+2).value Rodo.ctrl(11) = Slider(slnr+2).value END IF IF Rodo.ctrl(12) <> Slider(slnr+3).value THEN Controller Rodo.channel, 12, Slider(slnr+3).value Rodo.ctrl(12) = Slider(slnr+3).value END IF IF Rodo.ctrl(17) <> Slider(slnr+4).value THEN Controller Rodo.channel, 17, Slider(slnr+4).value Rodo.ctrl(17) = Slider(slnr+4).value END IF IF Rodo.ctrl(18) <> Slider(slnr+5).value THEN Controller Rodo.channel, 18, Slider(slnr+5).value Rodo.ctrl(18) = Slider(slnr+5).value END IF IF Rodo.ctrl(19) <> Slider(slnr+6).value THEN Controller Rodo.channel, 19,Slider(slnr+6).value Rodo.ctrl(19) = Slider(slnr+6).value END IF END SUB SUB Rodo_UD_Edrive_CB () ' for callback on parameter UpDown. ' the callback sends the midi message LOCAL modus AS SINGLE modus = UDCtrl(TaskEX(%Rodo_Edrive).UpdownNumbers(0)).value CONTROL SET TEXT Task(%Rodo_Edrive).hparam, %GMT_TEXT0_ID + 16, "m=" & STR$(modus) Controller Rodo.channel, 13, modus Rodo.ctrl(13) = modus END SUB SUB Rodo_Damp_Test () ' this proc. does not send any note-on's ' test for the damper-pic's, to check the velocity scaling in the firmware. STATIC note AS INTEGER LOCAL velo AS DWORD STATIC slnr() AS INTEGER STATIC ud AS INTEGER STATIC init AS LONG IF ISFALSE init THEN init = 1 ' create sliders: DIM Slnr(0 TO 1) AS STATIC INTEGER DIM TaskParamLabels(0 TO 2) AS STATIC ASCIIZ*8 TaskParamLabels(0)="Velo" ' contact time for the dampers TaskParamLabels(1)="Freq" ' speed TaskParamLabels(2)="Note" ' up down for the note IF Task(%Rodo_Damp_Test).hParam = %Null THEN MakeTaskParameterDialog BYVAL %Rodo_Damp_Test,2, Slider(),1,UdCtrl(), TaskParamLabels() END IF slnr(0) = TaskEX(%Rodo_Damp_Test).SliderNumbers(0) slnr(1) = TaskEX(%Rodo_Damp_Test).SliderNumbers(1) ud = TaskEX(%Rodo_Damp_Test).UpDownNumbers(0) Slider(Slnr(0)).value = 1 Slider(Slnr(1)).value = 4 UdCtrl(ud).value = Rodo.lowtes UdCtrl(ud).minval = Rodo.lowtes UdCtrl(ud).maxval = Rodo.hightes UdCtrl(ud).resetval = Rodo.lowtes UdCtrl(ud).stap = 1 UDctrl(ud).cptr = CODEPTR(Rodo_UD_Damp_CB) SendMessage Slider(Slnr(0)).h, %TBM_SETPOS,%True, Slider(Slnr(0)).value SendMessage Slider(Slnr(1)).h, %TBM_SETPOS,%True, Slider(Slnr(1)).value Task(%Rodo_Damp_Test).tog = %True END IF note = UdCtrl(ud).value velo = Slider(Slnr(0)).value Release Rodo.channel, note, velo ' noteoff + release only!!! Task(%Rodo_Damp_Test).freq = MAX(.2, Slider(Slnr(1)).value / 8!) END SUB SUB Rodo_UD_Damp_CB () ' for callback on parameter UpDown. LOCAL note AS SINGLE note = UDCtrl(TaskEX(%Rodo_Damp_Test).UpdownNumbers(0)).value CONTROL SET TEXT Task(%Rodo_Damp_Test).hparam, %GMT_TEXT0_ID + 16, "N=" & STR$(note) END SUB SUB Rodo_Lites () ' to be updated as we add more lights ' Yellow LED spotlites: - Dampers1 PIC, notes 114,115 ' Blue LED spotlites: - Dampers1 PIC. notes 112, 113 ' White LED strip on the beaters: - note 124, 24V beaters1 pic ' White LED strip on the back: - note 125, works on 24V beaters1 pic ' Beaters1 PIC = lites 124-127 ' Beaters2 PIC = lites 120-123 ' Dampers2 PIC = lites 116,117,118,119 STATIC n AS DWORD IF ISFALSE Task(%Rodo_lites).tog THEN n = 111 Task(%Rodo_lites).tog = %True END IF NoteOff Rodo.channel, n INCR n IF n > 127 THEN n = 112 mPlay Rodo.channel, n, 127 END SUB SUB Rodo_Blue () IF ISFALSE Task(%Rodo_Blue).tog THEN Task(%Rodo_Blue).tog = %True END IF mPlay Rodo.channel, 112, 127 mPlay Rodo.channel, 113, 127 END SUB SUB Rodo_Blue_Off () NoteOff Rodo.channel, 112 NoteOff Rodo.channel, 113 END SUB SUB Rodo_Yellow () IF ISFALSE Task(%Rodo_Yellow).tog THEN Task(%Rodo_Yellow).tog = %True END IF mPlay Rodo.channel, 114, 127 mPlay Rodo.channel, 115, 127 END SUB SUB Rodo_Yellow_Off () NoteOff Rodo.channel, 114 NoteOff Rodo.channel, 115 END SUB SUB Rodo_White () IF ISFALSE Task(%Rodo_White).tog THEN Task(%Rodo_White).tog = %True END IF mPlay Rodo.channel, 124, 127 mPlay Rodo.channel, 125, 127 END SUB SUB Rodo_White_Off () NoteOff Rodo.channel, 124 NoteOff Rodo.channel, 125 END SUB SUB Rodo_Red () mPlay Rodo.channel, 120, 127 mPlay Rodo.channel, 121, 127 END SUB SUB Rodo_Red_Off() NoteOff Rodo.channel, 120 NoteOff Rodo.channel, 121 END SUB SUB Rodo_Rot () mPlay Rodo.channel, 126, 127 END SUB SUB Rodo_Rot_Off() NoteOff Rodo.channel, 126 END SUB SUB Rodo_Ctrl_Test () STATIC CC14, CC15, CC16, CC64 AS INTEGER STATIC slnr() AS INTEGER STATIC ud, ud2 AS INTEGER STATIC init AS LONG IF ISFALSE init THEN init = 1 ' create sliders: DIM Slnr(0 TO 1) AS STATIC INTEGER DIM TaskParamLabels(0 TO 3) AS STATIC ASCIIZ*8 TaskParamLabels(0)="CC14" ' damping time TaskParamLabels(1)="CC15" ' damping TaskParamLabels(2)="CC64" ' sustain on/off TaskParamLabels(3)="CC16" ' damping override for note on's IF Task(%Rodo_Ctrl_Test).hParam = %Null THEN MakeTaskParameterDialog BYVAL %Rodo_Ctrl_Test,2, Slider(),2,UdCtrl(), TaskParamLabels() END IF slnr(0) = TaskEX(%Rodo_Ctrl_Test).SliderNumbers(0) slnr(1) = TaskEX(%Rodo_Ctrl_Test).SliderNumbers(1) ud = TaskEX(%Rodo_Ctrl_Test).UpDownNumbers(0) ud2 = TaskEX(%Rodo_Ctrl_Test).UpDownNumbers(1) Slider(Slnr(0)).value = 64 Slider(Slnr(1)).value = 0 UdCtrl(ud).value = 0 UdCtrl(ud).minval = 0 UdCtrl(ud).maxval = 127 UdCtrl(ud).resetval = 0 UdCtrl(ud).stap = 32 UDctrl(ud).cptr = CODEPTR(Rodo_UD_Sustain_CB) UdCtrl(ud2).value = 0 UdCtrl(ud2).minval = 0 UdCtrl(ud2).maxval = 1 UdCtrl(ud2).resetval = 0 UdCtrl(ud2).stap = 1 UDctrl(ud2).cptr = CODEPTR(Rodo_UD_CC16_CB) SendMessage Slider(Slnr(0)).h, %TBM_SETPOS,%True, Slider(Slnr(0)).value SendMessage Slider(Slnr(1)).h, %TBM_SETPOS,%True, Slider(Slnr(1)).value Task(%Rodo_Ctrl_Test).tog = %True END IF CC64 = UdCtrl(ud).value CC14 = Slider(Slnr(0)).value CC15 = Slider(slnr(1)).value CC16 = Udctrl(ud2).value IF Rodo.ctrl(64) <> CC64 THEN Controller Rodo.channel, 64, CC64 Rodo.ctrl(64) = CC64 END IF IF Rodo.ctrl(14) <> CC14 THEN Controller Rodo.channel, 14, CC14 Rodo.ctrl(14) = CC14 END IF IF Rodo.ctrl(15) <> CC15 THEN Controller Rodo.channel, 15, CC15 Rodo.ctrl(15) = CC15 END IF IF Rodo.ctrl(16) <> CC16 THEN Controller Rodo.channel, 16, CC16 Rodo.ctrl(16) = CC16 END IF Task(%Rodo_Ctrl_Test).freq = 20 END SUB SUB Rodo_UD_Sustain_CB () ' for callback on parameter UpDown. LOCAL sustain AS SINGLE sustain = UDCtrl(TaskEX(%Rodo_Ctrl_Test).UpdownNumbers(0)).value CONTROL SET TEXT Task(%Rodo_Ctrl_Test).hparam, %GMT_TEXT0_ID + 16, "S=" & STR$(sustain) END SUB SUB Rodo_UD_CC16_CB () ' for callback on parameter UpDown. LOCAL cc16 AS SINGLE cc16 = UDCtrl(TaskEX(%Rodo_Ctrl_Test).UpdownNumbers(1)).value CONTROL SET TEXT Task(%Rodo_Ctrl_Test).hparam, %GMT_TEXT0_ID + 17, "c=" & STR$(cc16) END SUB SUB Rodo_Lites_Off () ' all lites ' this also works simply with ctrl 123. LOCAL n AS BYTE FOR n = 112 TO 127 Noteoff Rodo.channel, n NEXT n END SUB SUB Rodo_KP () ' this proc. does not send any note-off's ' test for the beater-pic's, to check the velocity scaling in the firmware. STATIC note AS INTEGER LOCAL velo AS DWORD STATIC slnr() AS INTEGER STATIC ud AS INTEGER STATIC init AS LONG STATIC cnt AS LONG IF ISFALSE init THEN init = 1 ' create sliders: DIM Slnr(0 TO 1) AS STATIC INTEGER DIM TaskParamLabels(0 TO 2) AS STATIC ASCIIZ*8 TaskParamLabels(0)="Velo" ' attack force for beaters TaskParamLabels(1)="Freq" ' speed TaskParamLabels(2)="Note" ' up down for the note IF Task(%Rodo_Dyna_Test).hParam = %Null THEN MakeTaskParameterDialog BYVAL %Rodo_KP,2, Slider(),1,UdCtrl(), TaskParamLabels() END IF slnr(0) = TaskEX(%Rodo_KP).SliderNumbers(0) slnr(1) = TaskEX(%Rodo_KP).SliderNumbers(1) ud = TaskEX(%Rodo_KP).UpDownNumbers(0) Slider(Slnr(0)).value = 127 Slider(Slnr(1)).value = 4 UdCtrl(ud).value = Rodo.lowtes UdCtrl(ud).minval = Rodo.lowtes UdCtrl(ud).maxval = 97 'Rodo.hightes UdCtrl(ud).resetval = Rodo.lowtes UdCtrl(ud).stap = 1 UDctrl(ud).cptr = CODEPTR(Rodo_UD_KPNoot_CB) SendMessage Slider(Slnr(0)).h, %TBM_SETPOS,%True, Slider(Slnr(0)).value SendMessage Slider(Slnr(1)).h, %TBM_SETPOS,%True, Slider(Slnr(1)).value Controller Rodo.channel, 13, &B1101 Rodo.ctrl(13) = &B1101 Task(%Rodo_KP).tog = %True END IF note = UdCtrl(ud).value velo = Slider(Slnr(0)).value IF ISFALSE cnt THEN KeyPress Rodo.channel, note, velo ELSE KeyPress Rodo.channel, note, %False END IF INCR cnt IF cnt > 1 THEN RESET cnt Task(%Rodo_KP).freq = MAX(.5, Slider(Slnr(1)).value / 2!) END SUB SUB Rodo_UD_KPNoot_CB () ' for callback on parameter UpDown. LOCAL note AS SINGLE note = UDCtrl(TaskEX(%Rodo_KP).UpdownNumbers(0)).value CONTROL SET TEXT Task(%Rodo_KP).hparam, %GMT_TEXT0_ID + 16, "N=" & STR$(note) END SUB SUB Rodo_Piece () LOCAL n, i AS LONG STATIC noot1, noot2, cnt AS LONG IF ISFALSE Task(%Rodo_Piece).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 192) AS STATIC CUR ' fractional midi notes, 6 for each rod. ' DIM Rnr(0 TO 192) AS STATIC INTEGER ' tagarray, rod midi base notes 48-78 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 ' Rnt(n+i) = Rods(n).n0 : Rnr(n+i) = n + 48 ' Rnt(n+i+1) = Rods(n).n1 : Rnr(n+i+1) = n + 48 ' Rnt(n+i+2) = Rods(n).n2 : Rnr(n+i+2) = n + 48 ' Rnt(n+i+3) = Rods(n).n3 : Rnr(n+i+3) = n + 48 ' Rnt(n+i+4) = Rods(n).n4 : Rnr(n+i+4) = n + 48 ' Rnt(n+i+5) = Rods(n).n5 : Rnr(n+i+5) = n + 48 '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() ' check this now... FOR i = 0 TO UBOUND(rnt) IF Rnt(i) > 0 THEN logfile "n=" & STR$(Rnt(i)) & " rod=" & STR$(Rnr(i)) END IF NEXT i noot1 = 48 Task(%Rodo_Piece).tog = %True END IF 'logfile "Task stopped" 'stoptask %Rodo_Piece 'tempi can be use for all f' values < 30 STATIC sound1 AS SINGLE, sound2 AS SINGLE 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 ' look for a different rod with a minimal frequency deviation 'wat is hier precies de bedoeling? noot1 blijft ongewijzigd, dus er wordt steeds dezelfde noot2 geselecteerd.. IF ISFALSE Task(%Rodo_Pt2).tog THEN FOR i = 0 TO UBOUND(rnt) IF Rnt(i) > sound1 THEN ' this is wrong! IF Rnr(i) = noot1 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 IF Task(%Rodo_Pt1).tog THEN stoptask %Rodo_Pt1 ' one rod playing CASE 3 ' find new note for noot1: IF ISFALSE Task(%Rodo_Pt1).tog THEN FOR i = 0 TO UBOUND(rnt) IF Rnt(i) > sound2 THEN IF rnr(i) = noot2 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 ' 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_Pt1 () STATIC velo AS BYTE ' we may have to use task().level instead. IF ISFALSE Task(%Rodo_Pt1).tog THEN Task(%Rodo_Pt1).tog = %True END IF velo = 20 mPlay Rodo.channel, Task(%Rodo_Pt1).pan, velo ' logfile str$(timegettime) + str$(Task(%rodo_pt1).pan) END SUB SUB Rodo_Pt2 () STATIC velo AS BYTE IF ISFALSE Task(%Rodo_Pt2).tog THEN Task(%Rodo_Pt2).tog = %True END IF velo = 20 mPlay Rodo.channel, Task(%Rodo_Pt2).pan, velo ' logfile STR$(timegettime) + STR$(Task(%rodo_pt2).pan) END SUB SUB Rodo_Piece2 '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, sound2 AS SINGLE DIM consl(UBOUND(rods)) IF ISFALSE Task(%Rodo_Piece2).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 Task(%Rodo_Piece2).tog = %True END IF 'logfile "Task stopped" 'stoptask %Rodo_Piece 'tempi can be use for all f' values < 30 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 ther 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