'****************************************** '* * '* a microtonal oboe playing robot by * '* dr.Godfried-Willem Raes * '* 2008 - 2010 * '****************************************** ' hardware tests and development code ' 28.12.2008: key pressure fingering implementation added. ' 31.12.2008: test session and coding debug. ' 06.01.2009: Key's adjusted. Software fingering tests. ' 01.06.2009: First firmware version Midihub PIC: lights and motor pwm ' 20.10.2010: Development of new firmware for midihub board. ' 22.10.2010: Interfaces added for testing of new firmware. ' first movement tests withj V2.0 firmware in PIC1 ' 23.10.2010: Version 2.6 firmware. Lite implementation changed. ' 24.10.2010: Version 2.7 firmware. White LED spotlite added. %Ob_scale = 32 %Ob_17 = 33 ' ctrl 17 ' attack amplitude %Ob_18 = 34 ' ctrl 18 ' attack time %Ob_19 = 35 ' ctrl 19 ' release time %Ob_20 = 36 ' ctrl 20 ' main tuning to diapason %Ob_test = 37 ' repeated note test %Ob_Tremolo = 38 %Ob_Vibrato = 39 %Ob_KeyPress = 40 'motor tasks: %Ob_CC21 = 17 ' ctrl 21 - minimum motorspeed (for research) %Ob_Move = 18 'ctrl 22 - position 0-64-127 64= vertical 127= to the front, 0= backwards. %Ob_CC23 = 19 'ctrl 23 - PWM frequency - for research only %Ob_CC24 = 20 'ctrl24 - maximum motorspeed (for research)) %Ob_Pendulum = 22 'to do 'lights: %Ob_lites = 48 'on-off test %Ob0 = 49 %Ob1 = 50 %Ob2 = 51 %Ob3 = 52 %Ob4 = 53 'white LED spotlite %Ob5 = 54 GLOBAL OBKeyPress AS LONG DECLARE FUNCTION Init_Ob () AS LONG DECLARE SUB Ob_Scale () DECLARE SUB Ob_Scale_UD0 () DECLARE SUB Ob_Scale_UD1 () DECLARE SUB Ob_Scale_UD2 () DECLARE SUB Ob_Move () DECLARE SUB Ob_SL21 () DECLARE SUB Ob_Vibrato () DECLARE SUB Ob_Tremolo () DECLARE SUB Ob_18 () DECLARE SUB Ob_SL18 () DECLARE SUB Ob_19 () DECLARE SUB Ob_SL19 () DECLARE SUB Ob_20 () ' tuning DECLARE SUB Ob_SL20 () DECLARE SUB Ob_lites () DECLARE SUB Ob_Lites_UD () DECLARE SUB Ob_Test () DECLARE SUB Ob_UD0 () DECLARE SUB Ob_UD1 () DECLARE SUB Ob_UD2 () DECLARE FUNCTION Ob_Finger (n AS BYTE) AS WORD ' finger table in 16 bit format, left adjusted. DECLARE SUB Ob_KeyPress () DECLARE SUB Ob_Pendulum () DECLARE SUB Ob_Pendulum_Stop () DECLARE SUB Ob_CC21 () DECLARE SUB Ob_CC23 () DECLARE SUB Ob_CC24 () DECLARE SUB Ob0 () DECLARE SUB Ob1 () DECLARE SUB Ob2 () DECLARE SUB Ob3 () DECLARE SUB Ob4 () DECLARE SUB Ob5 () FUNCTION Init_Ob () AS LONG LOCAL retval AS LONG ' GetInstrumentParams Ob, %IDM_Ob ' retval = SetRobotPort (Ob, Inifilename, hMidiO()) OBKeyPRess = -1 Task(%Ob_Scale).naam = "Scale" Task(%Ob_Scale).cptr = CODEPTR(Ob_Scale) Task(%Ob_Scale).freq = 2 Task(%Ob_Scale).flags = %False Task(%Ob_Test).naam = "Test" Task(%Ob_Test).cptr = CODEPTR(Ob_Test) Task(%Ob_Test).freq = 4 Task(%Ob_Test).flags = %False Task(%Ob_Move).naam = "Move" Task(%Ob_Move).cptr = CODEPTR(Ob_Move) 'CC22 Task(%Ob_Move).freq = 2 Task(%Ob_Move).flags = %False Task(%Ob_Lites).naam = "lites" Task(%Ob_Lites).cptr = CODEPTR(Ob_Lites) Task(%Ob_Lites).freq = 2 Task(%Ob_Lites).flags = %False Task(%Ob_17).naam = "Aa_C17" Task(%Ob_17).cptr = CODEPTR(Ob_17) Task(%Ob_17).freq = 10 Task(%Ob_17).flags = %False Task(%Ob_tremolo).naam = "Tremolo" Task(%Ob_tremolo).cptr = CODEPTR(Ob_Tremolo) Task(%Ob_tremolo).freq = 16 Task(%Ob_tremolo).flags = %False Task(%Ob_18).naam = "At_C18" Task(%Ob_18).cptr = CODEPTR(Ob_18) Task(%Ob_18).freq = 10 Task(%Ob_18).flags = %False Task(%Ob_19).naam = "Re_C19" Task(%Ob_19).cptr = CODEPTR(Ob_19) Task(%Ob_19).freq = 9.7 Task(%Ob_19).flags = %False Task(%Ob_20).naam = "Tun_C20" Task(%Ob_20).cptr = CODEPTR(Ob_20) Task(%Ob_20).freq = 10 Task(%Ob_20).flags = %False Task(%Ob_vibrato).naam = "Vibrato" Task(%Ob_vibrato).freq = 12 Task(%Ob_vibrato).cptr = CODEPTR(Ob_Vibrato) Task(%Ob_CC21).naam = "C21" Task(%Ob_CC21).cptr = CODEPTR(Ob_CC21) 'sets minimum speed Task(%Ob_CC21).freq = 20 Task(%Ob_CC21).flags = %False Task(%Ob_CC23).naam = "C23" Task(%Ob_CC23).cptr = CODEPTR(Ob_CC23) Task(%Ob_CC23).freq = 20 Task(%Ob_CC23).flags = %False Task(%Ob_CC24).naam = "C24" Task(%Ob_CC24).cptr = CODEPTR(Ob_CC24) Task(%Ob_CC24).freq = 20 Task(%Ob_CC24).flags = %False Task(%Ob_Pendulum).naam = "Slinger" Task(%Ob_Pendulum).cptr = CODEPTR(Ob_Pendulum) Task(%Ob_Pendulum).freq = 0.25 Task(%Ob_Pendulum).flags = %False TaskEX(%Ob_Pendulum).stopcptr = CODEPTR(Ob_Pendulum_Stop) Task(%Ob0).naam = "Li-0" 'white LED's Task(%Ob0).cptr = CODEPTR(Ob0) Task(%Ob0).freq = 20 Task(%Ob0).flags = %False TaskEX(%Ob0).StopCptr = CODEPTR(Ob0_Stop) Task(%Ob1).naam = "Li-1" 'nc Task(%Ob1).cptr = CODEPTR(Ob1) Task(%Ob1).freq = 20 Task(%Ob1).flags = %False TaskEX(%Ob1).StopCptr = CODEPTR(Ob1_Stop) Task(%Ob2).naam = "Li-2" 'back yellow strip Task(%Ob2).cptr = CODEPTR(Ob2) Task(%Ob2).freq = 20 Task(%Ob2).flags = %False TaskEX(%Ob2).StopCptr = CODEPTR(Ob2_Stop) Task(%Ob3).naam = "Li-3" Task(%Ob3).cptr = CODEPTR(Ob3) 'center yellow strip Task(%Ob3).freq = 20 Task(%Ob3).flags = %False TaskEX(%Ob3).StopCptr = CODEPTR(Ob3_Stop) Task(%Ob4).naam = "Li-4" 'nc Task(%Ob4).cptr = CODEPTR(Ob4) Task(%Ob4).freq = 20 Task(%Ob4).flags = %False TaskEX(%Ob4).StopCptr = CODEPTR(Ob4_Stop) Task(%Ob5).naam = "Li-5" 'front yellow strip Task(%Ob5).cptr = CODEPTR(Ob5) Task(%Ob5).freq = 20 Task(%Ob5).flags = %False TaskEX(%Ob5).StopCptr = CODEPTR(Ob5_Stop) ' Task(%Ob_keypress).naam = "Keying" 'using a task for this makes no sense. mapped to ButnSw(9) ' Task(%Ob_keypress).freq = 12 ' Task(%Ob_keypress).cptr = CODEPTR(Ob_Keypress) ButnOS(10).tag = "Ob Off" ButnOS(10).cptr = CODEPTR(MM_Ob_Off) ButnSw(9).tag0 = "Fingerings" ButnSw(9).tag1 = "Fngrs off" ButnSw(9).cptr = CODEPTR(OB_KeyPress) ' calibration button for motors - ctrl.70 ' ButnOS(11).tag = "MotPos" ' ButnOS(11).cptr = CODEPTR(Ob_MotPosCal) ' FUNCTION = %True END FUNCTION SUB Ob_Scale () LOCAL i AS DWORD STATIC onoff AS DWORD STATIC cnt AS LONG STATIC TaskParamLabels() AS ASCIIZ*8 STATIC slnr AS INTEGER STATIC udnr AS INTEGER STATIC n AS INTEGER IF ISFALSE Task(%Ob_Scale).tog THEN IF ISFALSE Task(%Ob_Scale).hParam THEN DIM TaskParamLabels(5) TaskParamLabels(0)="velo" TaskParamLabels(1)="speed" TaskParamLabels(2)="legato" TaskParamLabels(3)="step" TaskParamLabels(4)= "hilim" TaskParamLabels(5)="lowlim" MakeTaskParameterDialog %Ob_Scale,3, Slider(),3,UdCtrl(), TaskParamLabels() slnr = TaskEX(%Ob_Scale).SliderNumbers(0) Slider(slnr).value = 64 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value Slider(slnr+1).value = 36 SendMessage Slider(Slnr+1).h, %TBM_SETPOS,%True, Slider(Slnr+1).value Slider(slnr+2).value = 64 ' stacc-legato Sendmessage Slider(slnr+2).h, %TBM_SETPOS, %True, Slider(slnr+2).value IF udnr = %False THEN udnr = TaskEX(%Ob_Scale).UpDownNumbers(0) UDctrl(udnr).cptr = CODEPTR(Ob_Scale_UD0) ' step size UDctrl(udnr).value = 1 UDctrl(udnr).minval = 0 UDctrl(udnr).maxval = 12 UDctrl(udnr).stap = 1 UDctrl(udnr+1).cptr = CODEPTR(Ob_Scale_UD1) ' high note limit UDctrl(udnr+1).value = Ob.hightes UDctrl(udnr+1).minval = Ob.lowtes UDctrl(udnr+1).maxval = Ob.Hightes UDctrl(udnr+2).cptr = CODEPTR(Ob_Scale_UD2) ' low note limit UDctrl(udnr+2).value = 52 UDctrl(udnr+2).minval = Ob.lowtes '0 UDctrl(udnr+2).maxval = Ob.Hightes '96, maar goede klank tot 89 END IF END IF Task(%Ob_Scale).tog = %True cnt = Ob.Lowtes EXIT SUB END IF IF ISFALSE onoff THEN IF Slider(slnr+2).value < 127 THEN IF n THEN NoteOff Ob.channel, n n = %False onoff = %True Task(%Ob_Scale).freq = MAX(2,Slider(slnr+2).value * 6) ELSE ' in dit geval puur legato zonder note-off's onoff = %True Task(%Ob_Scale).freq = 1000 END IF ELSE n = cnt Play Ob.channel, n, Slider(slnr).value cnt = cnt + UDCtrl(udnr).value IF cnt > UDctrl(udnr+1).value THEN cnt = UDctrl(udnr+2).value onoff = %False Task(%Ob_Scale).freq = MAX(0.25,Slider(slnr+1).value / 8) END IF END SUB SUB Ob_Scale_UD0 () ' callback on parameter UpDowns step size LOCAL value AS BYTE LOCAL udnr AS DWORD udnr = TaskEX(%Ob_Scale).UpdownNumbers(0) value = UDCtrl(udnr).value IF value > 12 THEN UDctrl(udnr).value = 12 : value = 12 IF value < 0 THEN UDCTRL(udnr).value = 0 : value = 0 SetDlgItemText Task(%Ob_Scale).hparam, %GMT_TEXT0_ID + 16, "s=" & STR$(value) END SUB SUB Ob_Scale_UD1 () ' controls the high limit of the note scale to be played. LOCAL noot AS BYTE LOCAL udnr AS DWORD udnr = TaskEX(%Ob_Scale).UpDownNumbers(1) noot = UDCtrl(udnr).value IF noot < UDctrl(udnr+1).value THEN UDctrl(udnr).value = UDctrl(udnr+1).value : noot = UDctrl(udnr+1).value IF noot > Ob.HighTes THEN UDctrl(udnr).value = Ob.HighTes : noot = Ob.hightes SetDlgItemText Task(%Ob_Scale).hparam, %GMT_TEXT0_ID + 17, "Hi=" & STR$(noot) END SUB SUB Ob_Scale_UD2 () ' controls the low limit of the note scale to be played. LOCAL noot AS BYTE LOCAL udnr AS DWORD udnr = TaskEX(%Ob_Scale).UpDownNumbers(2) noot = UDCtrl(udnr).value IF noot < Ob.lowtes THEN UDctrl(udnr).value = Ob.lowtes : noot = Ob.lowtes IF noot > UDctrl(udnr-1).value THEN UDctrl(udnr).value = UDctrl(udnr-1).value : noot = UDctrl(udnr-1).value SetDlgItemText Task(%Ob_Scale).hparam, %GMT_TEXT0_ID + 18, "Lo=" & STR$(noot) END SUB SUB Ob_CC21 () ' controller 21 test - motor speed - minimum ' for test only, motor speed will finaly become out of user control. STATIC slnr AS DWORD STATIC TaskParamLabels() AS ASCIIZ*8 IF ISFALSE Task(%Ob_CC21).tog THEN IF ISFALSE Task(%Ob_CC21).hParam THEN DIM TaskParamLabels(0) TaskParamLabels(0)="CC21" MakeTaskParameterDialog %Ob_CC21,1, Slider(),0,UdCtrl(), TaskParamLabels() slnr = TaskEX(%Ob_CC21).SliderNumbers(0) Slider(slnr).cptr = CODEPTR(Ob_SL21) Slider(slnr).value = 0 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Task(%Ob_CC21).freq = 10 Task(%Ob_CC21).tog = %TRue END IF Task(%Ob_CC21).freq = 0.5 END SUB SUB Ob_SL21 () ' slider callback - movement speed STATIC slnr AS DWORD slnr = TaskEX(%Ob_CC21).SliderNumbers(0) IF slider(slnr).value <> Ob.ctrl(21) THEN Ob.ctrl(21) = Slider(slnr).value Controller Ob.channel, 21, Ob.ctrl(21) END IF END SUB SUB Ob_Move () ' controller 22 test - firmware version 2.0 ' slider = position of Ob in the cradle ' problem here: we should not send intermediate values of the slider to Ob... STATIC slnr AS DWORD STATIC TaskParamLabels() AS ASCIIZ*8 IF ISFALSE Task(%Ob_Move).tog THEN IF ISFALSE Task(%Ob_Move).hParam THEN DIM TaskParamLabels(0) TaskParamLabels(0)="Move" MakeTaskParameterDialog %Ob_Move,1, Slider(),0,UdCtrl(), TaskParamLabels() slnr = TaskEX(%Ob_move).SliderNumbers(0) Slider(slnr).value = 64 'vertical SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Task(%Ob_move).freq = 10 Task(%Ob_move).tog = %TRue END IF IF slider(slnr).value <> Ob.ctrl(22) THEN Ob.ctrl(22) = Slider(slnr).value Controller Ob.channel, 22, Ob.ctrl(22) END IF Task(%Ob_move).freq = 1 'slow to avoid intermediate values.... END SUB SUB Ob_Vibrato () ' vibrato test met de pitchbend STATIC slnr AS DWORD STATIC TaskParamLabels() AS ASCIIZ*8 STATIC cnt AS DWORD IF ISFALSE Task(%Ob_vibrato).tog THEN IF ISFALSE Task(%Ob_vibrato).hParam THEN DIM TaskParamLabels(1) TaskParamLabels(0)="Speed" TaskParamlabels(1)="Depth" ' pitch deviation MakeTaskParameterDialog %Ob_vibrato,2, Slider(),0,UdCtrl(), TaskParamLabels() slnr = TaskEX(%Ob_vibrato).SliderNumbers(0) Slider(slnr).value = 63 Task(%Ob_vibrato).freq = 64/4 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value Slider(slnr+1).value = 0 ' geen vibrato SendMessage Slider(Slnr+1).h, %TBM_SETPOS,%True, Slider(Slnr+1).value END IF cnt = %False Task(%Ob_vibrato).tog = %True END IF ' not very good code yet! we should do it much more gradually IF slider(slnr).value THEN Task(%Ob_vibrato).freq = slider(slnr).value / 4 ' max 32Hz IF ISFALSE cnt MOD 2 THEN bend Ob.channel, 0, 63 + (slider(slnr+1).value/ 2) ELSE bend Ob.channel, 0, 64 - (slider(slnr+1).value /2) END IF INCR cnt ELSE Bend Ob.channel, 0, 64 ' reset stoptask %Ob_Vibrato END IF END SUB SUB Ob_17 () ' controller 17 test ' This controls the maximum amplitude of the attack STATIC slnr AS DWORD STATIC TaskParamLabels() AS ASCIIZ*8 IF ISFALSE Task(%Ob_17).tog THEN IF ISFALSE Task(%Ob_17).hParam THEN DIM TaskParamLabels(0) TaskParamLabels(0)="C17" MakeTaskParameterDialog %Ob_17,1, Slider(),0,UdCtrl(), TaskParamLabels() slnr = TaskEX(%Ob_17).SliderNumbers(0) Slider(slnr).cptr = CODEPTR(Ob_SL17) Slider(slnr).value = 86 Ob.ctrl(17) = 86 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Task(%Ob_17).freq = 10 Task(%Ob_17).tog = %TRue END IF Task(%Ob_17).freq = 0.5 END SUB SUB Ob_SL17 () ' slider callback STATIC slnr AS DWORD slnr = TaskEX(%Ob_17).SliderNumbers(0) IF slider(slnr).value <> Ob.ctrl(17) THEN Ob.ctrl(17) = Slider(slnr).value Controller Ob.channel, 17, Ob.ctrl(17) END IF END SUB SUB Ob_18 () ' controller 18 test - this sets the duration of the attack pulse ' ds pic board. STATIC slnr AS DWORD STATIC TaskParamLabels() AS ASCIIZ*8 IF ISFALSE Task(%Ob_18).tog THEN IF ISFALSE Task(%Ob_18).hParam THEN DIM TaskParamLabels(0) TaskParamLabels(0)="C18" MakeTaskParameterDialog %Ob_18,1, Slider(),0,UdCtrl(), TaskParamLabels() slnr = TaskEX(%Ob_18).SliderNumbers(0) slider(slnr).cptr = CODEPTR(Ob_sl18) Slider(slnr).value = 100 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Task(%Ob_18).freq = 0.4 Task(%Ob_18).tog = %TRue END IF END SUB SUB Ob_SL18 () ' slider callback STATIC slnr AS DWORD slnr = TaskEX(%Ob_18).SliderNumbers(0) IF slider(slnr).value <> Ob.ctrl(18) THEN Ob.ctrl(18) = Slider(slnr).value Controller Ob.channel, 18, Ob.ctrl(18) END IF END SUB SUB Ob_19 () ' controller 19 test - this sets the duration of the release sound ' ds pic board. Implemented 11.11.2008 on dsPIC STATIC slnr AS DWORD STATIC TaskParamLabels() AS ASCIIZ*8 IF ISFALSE Task(%Ob_19).tog THEN IF ISFALSE Task(%Ob_19).hParam THEN DIM TaskParamLabels(0) TaskParamLabels(0)="C19" MakeTaskParameterDialog %Ob_19,1, Slider(),0,UdCtrl(), TaskParamLabels() slnr = TaskEX(%Ob_19).SliderNumbers(0) slider(slnr).cptr = CODEPTR(Ob_sl19) Slider(slnr).value = 100 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Task(%Ob_19).freq = 0.4 Task(%Ob_19).tog = %TRue END IF END SUB SUB Ob_SL19 () ' slider callback STATIC slnr AS DWORD slnr = TaskEX(%Ob_19).SliderNumbers(0) IF slider(slnr).value <> Ob.ctrl(19) THEN Ob.ctrl(19) = Slider(slnr).value Controller Ob.channel, 19, Ob.ctrl(19) END IF END SUB SUB Ob_Tremolo () ' controller 17 test for tremolo - DS pic controlled. STATIC slnr AS DWORD STATIC TaskParamLabels() AS ASCIIZ*8 STATIC cnt AS DWORD IF ISFALSE Task(%Ob_tremolo).tog THEN IF ISFALSE Task(%Ob_tremolo).hParam THEN DIM TaskParamLabels(1) TaskParamLabels(0)="Speed" TaskParamlabels(1)="Depth" MakeTaskParameterDialog %Ob_tremolo,2, Slider(),0,UdCtrl(), TaskParamLabels() slnr = TaskEX(%Ob_tremolo).SliderNumbers(0) Slider(slnr).value = 8 Slider(slnr+1).value = 20 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value Sendmessage Slider(slnr+1).h, %TBM_SETPOS,%True, Slider(slnr+1).value END IF cnt = %False Task(%Ob_Tremolo).tog = %True END IF IF Slider(slnr).value THEN Task(%Ob_Tremolo).freq = Slider(slnr).value ELSE EXIT SUB END IF IF Slider(slnr+1).value THEN IF cnt MOD 2 THEN Controller Ob.channel, 17, Ob.ctrl(17) ELSE Controller Ob.channel, 17, Ob.ctrl(17) * (Slider(slnr+1).value / 127) END IF INCR cnt END IF END SUB SUB Ob_20 () ' tuning to diapason. [quartertone up max. range] ' controller 20 STATIC slnr AS DWORD STATIC TaskParamLabels() AS ASCIIZ*8 IF ISFALSE Task(%Ob_20).tog THEN IF ISFALSE Task(%Ob_20).hParam THEN DIM TaskParamLabels(0) TaskParamLabels(0)="tune" MakeTaskParameterDialog %Ob_20,1, Slider(),0,UdCtrl(), TaskParamLabels() slnr = TaskEX(%Ob_20).SliderNumbers(0) Slider(slnr).cptr = CODEPTR(Ob_SL20) Slider(slnr).value = Ob.ctrl(20) ' 0 = 440Hz SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Task(%Ob_20).freq = 0.45 Task(%Ob_20).tog = %True END IF END SUB SUB Ob_SL20 () ' slider callback STATIC slnr AS DWORD slnr = TaskEX(%Ob_20).SliderNumbers(0) IF slider(slnr).value <> Ob.ctrl(20) THEN Ob.ctrl(20) = Slider(slnr).value Controller Ob.channel, 20, Ob.ctrl(20) END IF END SUB SUB Ob_Lites () ' implemented 01.06.2009 ' updated 24.10.2010 STATIC cnt AS LONG STATIC udnr AS DWORD STATIC slnr AS DWORD STATIC lite AS BYTE IF ISFALSE Task(%Ob_Lites).tog THEN DIM TaskParamLabels(0 TO 1) AS ASCIIZ * 8 TaskParamLabels(0) = "Speed" TaskParamLabels(1) = "Nr." IF ISFALSE Task(%Ob_Lites).hParam THEN MakeTaskParameterDialog %Ob_Lites,1,Slider(),1,UDctrl(),TaskParamLabels() END IF IF slnr = %False THEN slnr = TaskEX(%Ob_Lites).SliderNumbers(0) Slider(slnr).minval =1 ' tempo Slider(slnr).maxval = 127 Slider(slnr).value = 16 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF IF udnr = %False THEN udnr = TaskEX(%Ob_Lites).UpDownNumbers(0) UDctrl(udnr).cptr = CODEPTR(Ob_Lites_UD) ' nr. updown UDctrl(udnr).value = 0 UDctrl(udnr).minval = 0 UDctrl(udnr).maxval = 7 UDctrl(udnr).stap = 1 END IF Task(%Ob_Lites).tog = %True END IF ' lites controlled by PIC1 IF lite <> UDctrl(udnr).value THEN NoteOff Ob.channel, lite lite = UDctrl(udnr).value END IF IF ISFALSE cnt MOD 2 THEN Play Ob.channel, lite, 127 ELSE Play Ob.channel, lite, 0 END IF INCR cnt Task(%Ob_Lites).freq = MAX(1,(Slider(slnr).value / 4)) END SUB SUB Ob_Lites_UD () ' callback on parameter UpDowns. : lite number LOCAL value AS BYTE LOCAL udnr AS DWORD udnr = TaskEX(%Ob_Lites).UpdownNumbers(0) value = UDCtrl(udnr).value SetDlgItemText Task(%Ob_Lites).hparam, %GMT_TEXT0_ID + 16, STR$(value) END SUB SUB Ob_Test() STATIC slnr AS DWORD STATIC udnr AS DWORD LOCAL value AS LONG STATIC noot AS BYTE STATIC onfreq AS SINGLE STATIC offFreq AS SINGLE STATIC oldnote AS BYTE STATIC resetval AS BYTE LOCAL velo AS BYTE LOCAL period AS SINGLE LOCAL onpart AS SINGLE LOCAL offpart AS SINGLE LOCAL fingers AS WORD LOCAL msb AS WORD ' could be byte LOCAL lsb AS WORD ' cannot be byte IF ISFALSE Task(%Ob_Test).tog THEN DIM TaskParamLabels(0 TO 5) AS ASCIIZ * 8 TaskParamLabels(0) = "Tempo" ' rescaled in proc. TaskParamLabels(1) = "Velo" ' drive volume 0-127 - velocity byte TaskParamLabels(2) = "Bend" ' pitch-bend value 'SL2 - was UD2 - quartertone down or up. TaskParamLabels(3) = "Stac" ' staccato - legato up down ' UD0 TaskParamLabels(4) = "Note" ' pitch ' UD1 TaskParamLabels(5) = "Fing" ' vingerzetting via key-pressure ' UD2 IF ISFALSE Task(%Ob_Test).hParam THEN MakeTaskParameterDialog %Ob_Test,3,Slider(),3,UDctrl(),TaskParamLabels() END IF IF slnr = %False THEN slnr = TaskEX(%Ob_Test).SliderNumbers(0) Slider(slnr).minval =1 ' tempo Slider(slnr).maxval = 127 Slider(slnr).value = 8 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value Slider(slnr+2).value = 64 'pitch bend reset Slider(slnr+2).minval = 0 Slider(slnr+2).maxval = 127 SendMessage Slider(slnr + 2).h, %TBM_SETPOS, %True, SlideR(slnr + 2).value END IF IF udnr = %False THEN udnr = TaskEX(%Ob_Test).UpDownNumbers(0) UDctrl(udnr).cptr = CODEPTR(Ob_UD0) ' staccato - legato updown UDctrl(udnr).value = 50 UDctrl(udnr).minval = 0 UDctrl(udnr).maxval = 100 UDctrl(udnr).stap = 1 UDctrl(udnr+1).cptr = CODEPTR(Ob_UD1) ' pitch up down (note) UDctrl(udnr+1).value = Ob.lowtes UDctrl(udnr+1).minval = Ob.lowtes UDctrl(udnr+1).maxval = Ob.Hightes UDctrl(udnr+2).cptr = CODEPTR(Ob_UD2) ' fingering via aftertouch on/off UDctrl(udnr+2).value = 0 UDctrl(udnr+2).minval = 0 UDctrl(udnr+2).maxval = 1 resetval = 64 END IF Task(%Ob_Test).tog = %True EXIT SUB END IF period = 1! / (Slider(slnr).value / 10!) ' tempo Task(%Ob_Test).tempo = 60 / period ' on-off periods: onpart = period * (UDctrl(udnr).value / 100!) ' 0 - 100 offpart = period - onpart ' 100 - 0 IF UDctrl(udnr).value < 1 THEN ' silence IF oldnote THEN NoteOff Ob.channel, oldnote oldnote = %False END IF offFreq = 1! / period Task(%Ob_Test).freq = OffFreq EXIT SUB ELSE onfreq = 1!/onpart END IF IF UDctrl(udnr).value > 99 THEN ' legato, no note offs oldnote = %False ELSE offFreq = 1! /Offpart END IF IF oldnote THEN NoteOff Ob.channel, oldnote Task(%Ob_Test).freq = OffFreq oldnote = %False ELSE noot = UDctrl(udnr+1).value velo = Slider(slnr+1).value Play Ob.channel, noot, velo Bend Ob.channel, 0, Slider(slnr + 2).value IF UDctrl(udnr+2).value THEN fingers = Ob_Finger (noot) msb = Fingers AND &B1111111000000000 ' mask, eigenlijk hier niet nodig SHIFT RIGHT msb, 9 ' 7 bits msb ' format 0xxx xxxx lsb = fingers AND &B0000000111111111 ' mask &B0000000111111000 kan ook SHIFT RIGHT lsb, 2 ' 7 bits lsb ' format 0xxx xxx0 Keypress Ob.channel, msb, lsb ' violating the midi standard, where msb = note END IF IF OBKeyPress > -1 THEN KeyPress Ob.channel, HIBYT(LOWRD(OBKeyPress)), LOBYT(OBKeyPress) 'if we use the OB_KeyPess dialog, it overrides other settings for the fingerings. close the dialog with the button to revertt to normal fingerings Task(%Ob_Test).freq = OnFreq oldnote = noot END IF IF Task(%Ob_Test).freq < 0.2 THEN Task(%Ob_Test).freq = 0.2 END SUB SUB Ob_UD0 () ' callback on parameter UpDowns. : on/off proportion LOCAL value AS BYTE LOCAL udnr AS DWORD udnr = TaskEX(%Ob_Test).UpdownNumbers(0) value = UDCtrl(udnr).value IF value > 99 THEN UDctrl(udnr).value = 100 : value = 100 IF value < 0 THEN UDCTRL(udnr).value = 0 : value = 0 SetDlgItemText Task(%Ob_Test).hparam, %GMT_TEXT0_ID + 16, "L=" & STR$(value) END SUB SUB Ob_UD1 () ' controls the notes to be played. LOCAL noot AS BYTE LOCAL udnr AS DWORD udnr = TaskEX(%Ob_Test).UpDownNumbers(1) noot = UDCtrl(udnr).value SetDlgItemText Task(%Ob_Test).hparam, %GMT_TEXT0_ID + 17, "N=" & STR$(noot) END SUB SUB Ob_UD2 () ' ' fingering UD switch - has to be send for each note!!! LOCAL value AS BYTE LOCAL udnr AS DWORD udnr = TaskEX(%Ob_Test).UpDownNumbers(2) value = UDCtrl(udnr).value IF value > 1 THEN value = 1 IF value < 0 THEN value = 0 SetDlgItemText Task(%Ob_Test).hparam, %GMT_TEXT0_ID + 18, "F=" & STR$(value) ' sending is in the main task. END SUB FUNCTION Ob_Finger (n AS BYTE) AS WORD ' finger table - lookup as descibed on the webpage for Ob ' the fingering can be send to Ob using a note aftertouch command ' &H160 + k, HIBYTE(7hibitsfunction), LOWBYTE(6lowerbitsfunction) ' msb = low valves, 7 bits = msb = shift right, value, 9 ' lsb = high valves, 6 bits = lsb = shift left, value,7 ' lsb = shift right, lsb, 9 ' we use only 13 bits. IF n < Ob.lowtes THEN FUNCTION = %False : EXIT FUNCTION IF n > Ob.hightes THEN FUNCTION = %False: EXIT FUNCTION SELECT CASE n CASE 58 FUNCTION = &HD770 ' binary 1101 0111 0111 0000 CASE 59 FUNCTION = &H5770 ' binary 0101 0111 0111 0000 CASE 60 FUNCTION = &H1770 ' binary 0001 0111 0111 0000 CASE 61,73,85 FUNCTION = &H0F70 ' binary 0000 1111 0111 0000 CASE 62,74 FUNCTION = &H0770 ' binary 0000 0111 0111 0000 CASE 63,75 FUNCTION = &H2770 ' kan ook: &H3370 te testen CASE 64,76,83 FUNCTION = &H0370 CASE 65,77 FUNCTION = &H0570 ' fork CASE 66,78 FUNCTION = &H0170 CASE 67,79 FUNCTION = &H0070 CASE 68,80 FUNCTION = &H00F0 CASE 69,81 FUNCTION = &H0030 CASE 70 FUNCTION = &H0530 CASE 71 FUNCTION = &H0660 CASE 72,84 FUNCTION = &H0110 CASE 82 FUNCTION = &H0130 CASE 86 FUNCTION = &H0070 CASE 87 FUNCTION = &H00F0 CASE 88 FUNCTION = &H20F0 CASE 89 FUNCTION = &H00B0 CASE 90 FUNCTION = &H1130 CASE 91 FUNCTION = &H1310 CASE 92 FUNCTION = &H0650 CASE 93 FUNCTION = &H0250 CASE 94 FUNCTION = &H22D0 CASE 95 FUNCTION = &H4368 ' &H4361 is mistake in the lookups: must be &H4368 CASE 96 FUNCTION = &H0328 ' &H0321 is mistake in the lookups: must be &H0328 CASE ELSE FUNCTION = %False END SELECT END FUNCTION SUB Ob_KeyPress () ' test for finding optimum fingerings 'interacts with OB_test 'close the dialog with the button to revert to normal fingerings ' must be an interface with the 13 valves, each clickable... STATIC fingering AS WORD STATIC hw AS DWORD LOCAL i AS LONG IF hw THEN DIALOG END hw hw = 0 OBKeyPRess = -1 'disable EXIT SUB END IF DIALOG NEW 0, "Keypress",,,72, 217 TO hw 'to be filled in.. FOR i = 1 TO 13 'not 0 to 12!!! CONTROL ADD CHECKBOX, hw, i, "key" + STR$(i), 1, 1 + (i-1) * 15, 70, 12, %BS_PUSHLIKE,,CALL cb_ob_keypress NEXT CONTROL ADD LABEL, hw, 100, HEX$(OBKeyPRess), 1, 203, 70, 12 DIALOG SHOW MODELESS hw END SUB CALLBACK FUNCTION CB_ob_KeyPress LOCAL i AS LONG LOCAL v AS LONG IF CBMSG <> %WM_COMMAND THEN EXIT FUNCTION IF CBCTLMSG <> %BN_CLICKED THEN EXIT FUNCTION IF OBKeyPRess = -1 THEN OBKeyPRess = 0 i = CBCTL CONTROL GET CHECK CBHNDL, CBCTL TO v IF i > 6 THEN INCR i IF v THEN BIT SET OBkeyPRess, i ELSE BIT RESET OBKeyPress, i END IF CONTROL SET TEXT CBHNDL, 100, HEX$(OBKeyPress) ' + " -" + bin$(lowrd(OBKeyPRess)) END FUNCTION SUB Ob_Pendulum () STATIC slnr, tog AS DWORD STATIC TaskParamLabels() AS ASCIIZ*8 LOCAL excursie AS BYTE IF ISFALSE task(%Ob_Pendulum).tog THEN ' required: slider for frequency ' slider for amplitude IF ISFALSE Task(%Ob_Pendulum).hParam THEN DIM TaskParamLabels(1) TaskParamLabels(0)="speed" TaskParamLabels(1)="amplitude" MakeTaskParameterDialog %Ob_Pendulum,2, Slider(),0,UdCtrl(), TaskParamLabels() slnr = TaskEX(%Ob_Pendulum).SliderNumbers(0) Slider(slnr).value = 20 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Task(%Ob_Pendulum).freq = 0.2 Task(%Ob_Pendulum).tog = %True END IF excursie = Slider(slnr+1).value \2 '0 - 63 IF ISFALSE tog THEN Controller Ob.channel, 22, 64 - excursie '20 is minimum ELSE Controller Ob.channel, 22, 64 + excursie '100 is maximum END IF INCR tog tog = tog MOD 2 Task(%Ob_Pendulum).freq = MAX(Slider(slnr).value/ 127, 0.01) END SUB SUB Ob_Pendulum_Stop () Controller Ob.channel, 22, 64 END SUB SUB Ob_CC23 () ' controller 23 test - motor speed - maximum ' for test only, motor speed will finaly become out of user control. STATIC slnr AS DWORD STATIC TaskParamLabels() AS ASCIIZ*8 IF ISFALSE Task(%Ob_CC23).tog THEN IF ISFALSE Task(%Ob_CC23).hParam THEN DIM TaskParamLabels(0) TaskParamLabels(0)="CC23" MakeTaskParameterDialog %Ob_CC23,1, Slider(),0,UdCtrl(), TaskParamLabels() slnr = TaskEX(%Ob_CC23).SliderNumbers(0) Slider(slnr).cptr = CODEPTR(Ob_SL23) Slider(slnr).value = 0 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Task(%Ob_CC23).freq = 10 Task(%Ob_CC23).tog = %TRue END IF Task(%Ob_CC23).freq = 0.5 END SUB SUB Ob_SL23 () ' slider callback - movement speed maximum STATIC slnr AS DWORD slnr = TaskEX(%Ob_CC23).SliderNumbers(0) IF slider(slnr).value <> Ob.ctrl(23) THEN Ob.ctrl(23) = Slider(slnr).value Controller Ob.channel, 23, Ob.ctrl(23) END IF END SUB SUB Ob_CC24 () ' controller 24 test - motor ctrl. pwm frequency ' for test only, motor pwm will finaly become out of user control. STATIC slnr AS DWORD STATIC TaskParamLabels() AS ASCIIZ*8 IF ISFALSE Task(%Ob_CC24).tog THEN IF ISFALSE Task(%Ob_CC24).hParam THEN DIM TaskParamLabels(0) TaskParamLabels(0)="CC24" MakeTaskParameterDialog %Ob_CC24,1, Slider(),0,UdCtrl(), TaskParamLabels() slnr = TaskEX(%Ob_CC24).SliderNumbers(0) Slider(slnr).cptr = CODEPTR(Ob_SL24) Slider(slnr).value = 0 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Task(%Ob_CC24).freq = 10 Task(%Ob_CC24).tog = %TRue END IF Task(%Ob_CC24).freq = 0.5 END SUB SUB Ob_SL24 () ' slider callback - pwm freq. STATIC slnr AS DWORD slnr = TaskEX(%Ob_CC24).SliderNumbers(0) IF slider(slnr).value <> Ob.ctrl(24) THEN Ob.ctrl(24) = Slider(slnr).value Controller Ob.channel, 24, Ob.ctrl(24) END IF END SUB SUB Ob0 () ' white LED's on the Oboe STATIC n AS INTEGER STATIC slnr AS DWORD IF ISFALSE Task(%Ob0).tog THEN DIM TaskParamLabels(0) AS ASCIIZ * 8 ARRAY ASSIGN TaskParamLabels() = "L0" IF ISFALSE Task(%Ob0).hParam THEN MakeTaskParameterDialog %Ob0,1,Slider(),0,UDctrl(),TaskParamLabels() slnr = TaskEX(%Ob0).SliderNumbers(0) Slider(slnr).value = 127 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Play Ob.channel, 0,127 Task(%Ob0).tog = %True END IF IF slider(slnr).value <> n THEN n = Slider(slnr).value Play Ob.channel, 0, n END IF Task(%Ob0).freq = 10 END SUB SUB Ob0_Stop () NoteOff Ob.channel, 0 END SUB SUB Ob1 () 'not yet mounted STATIC n AS INTEGER STATIC slnr AS DWORD IF ISFALSE Task(%Ob1).tog THEN DIM TaskParamLabels(0) AS ASCIIZ * 8 ARRAY ASSIGN TaskParamLabels() = "L1" IF ISFALSE Task(%Ob1).hParam THEN MakeTaskParameterDialog %Ob1,1,Slider(),0,UDctrl(),TaskParamLabels() slnr = TaskEX(%Ob1).SliderNumbers(0) Slider(slnr).value = 127 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Play Ob.channel, 1, 127 'KeyPress Ob.channel,1, slider(slnr).value Task(%Ob1).tog = %True END IF IF slider(slnr).value <> n THEN n = Slider(slnr).value Play Ob.channel, 1, n 'KeyPress Ob.channel, 1, n END IF Task(%Ob1).freq = 10 END SUB SUB Ob1_Stop () NoteOff Ob.channel, 1 END SUB SUB Ob2 () 'back LED strip yellow STATIC n AS INTEGER STATIC slnr AS DWORD IF ISFALSE Task(%Ob2).tog THEN DIM TaskParamLabels(0) AS ASCIIZ * 8 ARRAY ASSIGN TaskParamLabels() = "L2" IF ISFALSE Task(%Ob2).hParam THEN MakeTaskParameterDialog %Ob2,1,Slider(),0,UDctrl(),TaskParamLabels() slnr = TaskEX(%Ob2).SliderNumbers(0) Slider(slnr).value = 127 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Play Ob.channel, 2, 127 'KeyPress Ob.channel,2, slider(slnr).value Task(%Ob2).tog = %True END IF IF slider(slnr).value <> n THEN n = Slider(slnr).value Play Ob.channel, 2, n END IF Task(%Ob2).freq = 10 END SUB SUB Ob2_Stop () NoteOff Ob.channel, 2 END SUB SUB Ob3 () 'mid yellow LED strip STATIC n AS INTEGER STATIC slnr AS DWORD IF ISFALSE Task(%Ob3).tog THEN DIM TaskParamLabels(0) AS ASCIIZ * 8 ARRAY ASSIGN TaskParamLabels() = "L3" IF ISFALSE Task(%Ob3).hParam THEN MakeTaskParameterDialog %Ob3,1,Slider(),0,UDctrl(),TaskParamLabels() slnr = TaskEX(%Ob3).SliderNumbers(0) Slider(slnr).value = 127 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Play Ob.channel, 3, 127 'KeyPress Ob.channel,3, slider(slnr).value Task(%Ob3).tog = %True END IF IF slider(slnr).value <> n THEN n = Slider(slnr).value Play Ob.channel, 3, n END IF Task(%Ob3).freq = 10 END SUB SUB Ob3_Stop () NoteOff Ob.channel, 3 END SUB SUB Ob4 () 'white LED spotlight STATIC n AS INTEGER STATIC slnr AS DWORD IF ISFALSE Task(%Ob4).tog THEN DIM TaskParamLabels(0) AS ASCIIZ * 8 ARRAY ASSIGN TaskParamLabels() = "L4" IF ISFALSE Task(%Ob4).hParam THEN MakeTaskParameterDialog %Ob4,1,Slider(),0,UDctrl(),TaskParamLabels() slnr = TaskEX(%Ob4).SliderNumbers(0) Slider(slnr).value = 127 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Play Ob.channel, 4, 127 'KeyPress Ob.channel,4, slider(slnr).value Task(%Ob4).tog = %True END IF IF slider(slnr).value <> n THEN n = Slider(slnr).value Play Ob.channel, 4, n END IF Task(%Ob4).freq = 10 END SUB SUB Ob4_Stop () NoteOff Ob.channel, 4 END SUB SUB Ob5 () 'frontal yellow LED strip STATIC n AS INTEGER STATIC slnr AS DWORD IF ISFALSE Task(%Ob5).tog THEN DIM TaskParamLabels(0) AS ASCIIZ * 8 ARRAY ASSIGN TaskParamLabels() = "L5" IF ISFALSE Task(%Ob5).hParam THEN MakeTaskParameterDialog %Ob5,1,Slider(),0,UDctrl(),TaskParamLabels() slnr = TaskEX(%Ob5).SliderNumbers(0) Slider(slnr).value = 127 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Play Ob.channel, 5, 127 'KeyPress Ob.channel,5, slider(slnr).value Task(%Ob5).tog = %True END IF IF slider(slnr).value <> n THEN n = Slider(slnr).value Play Ob.channel, 5, n END IF Task(%Ob5).freq = 10 END SUB SUB Ob5_Stop () NoteOff Ob.channel, 5 END SUB