' *************************************************************************** ' * * ' * an automated serinette by dr.Godfried-Willem Raes * ' * first working version 2017 * ' *************************************************************************** ' 15.02.2017: Project started. ' 28.02.2017: all four boards ready and programmed with version 1.0 ' 03.03.2017: to do: add procedure for microtuning of the notes ' Firmware version 1.1 on the PIC's ' 04.03.2017: microtuning tests added. ' 08.03.2017: just intonation tunings added ' none of the tuning procedures seem to work... ' 10.03.2017: debugged ok now. ' 13.03.2017: Pipi demo piece finished. ' 16.08.2017: Pipi for Pi performed again. ' 01.09.2018: Test code for 2Pi added in this module. %Pi_Test = 18 %Pi_Params = 19 %Pi_Scale = 20 %Pi_Lite = 21 %Pi_Tune = 22 %Pi_Just = 23 %Pi_Poly = 24 ' 'Pipi' demostukje: (loopt automatisch) %Pipi_Intro = 32 %Pipi_Perc = 33 %Pipi_Triads = 34 %Pipi_Burst = 35 %Pipi = 36 %Pipi_end = 37 ' specific tasks for 2Pi, range 48 to 63 %Pi2_Scale = 48 %Pi2_Test = 49 %Pi2_Lites = 63 GLOBAL hwCtrlPi AS DWORD DECLARE FUNCTION Init_Pi () AS DWORD DECLARE SUB Pi_Test () FUNCTION Init_Pi () EXPORT AS DWORD LOCAL CockpitLayo AS CockpitLabels LOCAL i AS DWORD LOCAL m AS ASCIIZ * 40 LOCAL zText AS ASCIIZ * 25 LOCAL retval AS LONG GetInstrumentParams Pi_, %IDM_Pi retval = SetRobotport (Pi_, Inifilename, hMidiO()) GetInstrumentParams Pi2_, %IDM_2Pi retval = SetRobotport (Pi2_, Inifilename, hMidiO()) Task(App.ReadSeqScoreTaskNr).cPtr = %False ' remove from cockpit. ' delete buttons that are not required or functional: ButnSW(2).tag0 = "Power On" ' CC66 ButnSW(2).tag1 = "Power Off" ButnSW(2).cptr = %False IF ISFALSE hMidiI(0) THEN Task(16).naam = "" Task(16).cptr = %False END IF Task(%Pi_Test).cPtr = CODEPTR(Pi_Test) ' repetitions Task(%Pi_Test).freq = 2 Task(%Pi_Test).naam = "Pi_Reps" Task(%Pi_Test).flags = %False Task(%Pi_Params).cPtr = CODEPTR(Pi_Params) Task(%Pi_Params).freq = 20 Task(%Pi_Params).naam = "Pi_Ctrl" Task(%Pi_Params).flags = %False Task(%Pi_Scale).cPtr = CODEPTR(Pi_Scale) Task(%Pi_Scale).freq = 4 Task(%Pi_Scale).naam = "Pi_Scale" Task(%Pi_Scale).flags = %False Task(%Pi_Lite).cPtr = CODEPTR(Pi_Lite) Task(%Pi_Lite).freq = 4 Task(%Pi_Lite).naam = "Pi_Lite" Task(%Pi_Lite).flags = %False Task(%Pi_Tune).cPtr = CODEPTR(Pi_Tune) Task(%Pi_Tune).freq = 10 Task(%Pi_Tune).naam = "Pi_Tune" Task(%Pi_Tune).flags = %False TaskEX(%Pi_Tune).stopcptr = CODEPTR(Pi_Tune_stop) ' makes tuning logfile Task(%Pi_Just).cPtr = CODEPTR(Pi_Just) Task(%Pi_Just).freq = 2 Task(%Pi_Just).naam = "Pi_Just" Task(%Pi_Just).flags = %False TaskEX(%Pi_Just).stopcptr = CODEPTR(Pi_Just_stop) Task(%Pi_Poly).cPtr = CODEPTR(Pi_Poly) Task(%Pi_Poly).freq = 4 Task(%Pi_Poly).naam = "Pi_Poly" Task(%Pi_Poly).flags = %False ' demo piece gwr: Task(%Pipi_Intro).cPtr = CODEPTR(Pipi_Intro) Task(%Pipi_Intro).freq = 4 Task(%PiPi_Intro).naam = "Pi_Intro" Task(%Pipi_Intro).flags = %False TaskEX(%Pipi_Intro).stopcptr = CODEPTR(Pipi_Intro_Stop) Task(%Pipi_Triads).cPtr = CODEPTR(Pipi_Triads) Task(%Pipi_Triads).freq = 4 Task(%PiPi_Triads).naam = "Pi_3ths" Task(%Pipi_Triads).flags = %False TaskEX(%Pipi_Triads).stopcptr = CODEPTR(Pipi_Triads_Stop) Task(%Pipi_Perc).cPtr = CODEPTR(Pipi_Perc) Task(%Pipi_Perc).freq = 4 Task(%PiPi_Perc).naam = "Pi_Perc" Task(%Pipi_Perc).flags = %False TaskEX(%Pipi_Perc).stopcptr = CODEPTR(Pipi_Perc_Stop) Task(%Pipi_Burst).cPtr = CODEPTR(Pipi_Burst) Task(%Pipi_Burst).freq = 3 Task(%PiPi_Burst).naam = "Pi_Burst" Task(%Pipi_Burst).flags = %False TaskEX(%Pipi_Burst).stopcptr = CODEPTR(Pipi_Burst_Stop) Task(%Pipi).naam = "Pipi" Task(%Pipi).freq = 0.2 Task(%Pipi).channel = Pi_.channel Task(%Pipi).tempo = 12 Task(%Pipi).level = 46 Task(%Pipi).cPtr = CODEPTR(Pipi) Task(%Pipi).flags = %MIDI_TASK OR %HARM_TASK OR %SCORE_TASK Task(%Pipi_end).naam = "Pipi_end" Task(%Pipi_end).freq = 0.2 Task(%Pipi_end).channel = Pi_.channel Task(%Pipi_end).tempo = 8 Task(%Pipi_end).level = 46 Task(%Pipi_end).cPtr = CODEPTR(Pipi_ending) Task(%Pipi_end).flags = %False '--------------------------------------------------------------------------------- App.MidiPlayerTasknr = %h_fileplay 'the playertask expects itself to be located here - if we don't set the ReadSeqscoreTasknr we get a crash! Task(%h_fileplay).naam = "PlayMid" task(%h_fileplay).cptr = GetProcAddress(GetModuleHandle("g_lib.dll"),"MM_MIDIPLAYER") task(%h_fileplay).freq = 100 taskEX(%h_fileplay).stopcptr = GetProcAddress(GetModuleHandle("g_lib.dll"),"MM_MIDIPLAYERSTOP") ' 2Pi procedures: Task(%Pi2_Scale).cPtr = CODEPTR(Pi2_Scale) Task(%Pi2_Scale).freq = 4 Task(%Pi2_Scale).naam = "2Pi_Scal" Task(%Pi2_Scale).flags = %False Task(%Pi2_Test).cPtr = CODEPTR(Pi2_Test) ' repetitions Task(%Pi2_Test).freq = 2 Task(%Pi2_Test).naam = "Pi2_Reps" Task(%Pi2_Test).flags = %False Task(%Pi2_Lites).cPtr = CODEPTR(Pi2_Lites) Task(%Pi2_Lites).freq = 4 Task(%Pi2_Lites).naam = "Pi2_Lite" Task(%Pi2_Lites).flags = %False ButnSW(7).tag0 = "PiCtrl tog" ButnSW(7).tag1 = "PiCtrl tog" ButnSW(7).cptr = CODEPTR(Pi_Controlroom) App.id = %IDM_PI m = " & <2Pi>" SendMessage gh.Cockpit, %WM_SETTEXT,0, VARPTR(m) FUNCTION = %True END FUNCTION SUB Pi_Test () ' tests repeated notes. ' parameters: repetition rate ' push-time ' release-time ' note STATIC slnr AS DWORD STATIC i,j AS INTEGER LOCAL onoff AS SINGLE LOCAL period AS SINGLE IF ISFALSE Task(%Pi_Test).tog THEN DIM TaskParamLabels(0 TO 4) AS ASCIIZ * 8 TaskParamLabels(0) = "Tempo" ' repeat rate TaskParamlabels(1) = "On/Off" ' puls-pause proportion TaskParamlabels(2) = "velo" TaskParamlabels(3) = "release" TaskParamLabels(4) = "Note" ' note IF ISFALSE Task(%Pi_Test).hParam THEN slnr = %False MakeTaskParameterDialog %Pi_Test,4,Slider(),1,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(%Pi_Test).SliderNumbers(0) UDctrl(TaskEX(%Pi_Test).UpdownNumbers(0)).cptr = CODEPTR(Pi_Note_UD1) i = 84 UDctrl(TaskEX(%Pi_Test).UpDownNumbers(0)).value = i Task(%Pi_Test).freq = 2 Slider(slnr).value = Task(%Pi_Test).freq SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value Slider(slnr+1).value = 64 SendMessage Slider(Slnr+1).h, %TBM_SETPOS,%True, 64 ' mid position END IF j = %False Controller Pi_.channel, 66, 64 Task(%Pi_Test).tog = %True EXIT SUB END IF OnOff = Slider(slnr+1).value / 128 ' 0- 0.99218 IF OnOff < 0.0078 THEN OnOff = 0.0078125 period = 1! / (32! * ((Slider(slnr).value+1) / 128!)) ' tempo - duur in sekonden. IF ISFALSE j THEN mPlay Pi_.channel, i, Slider(slnr+2).value period = period * OnOff ELSE Release Pi_.channel, i, Slider(slnr+3).value ' allways overrides ctrl #19 i = UDctrl(TaskEX(%Pi_Test).UpDownNumbers(0)).value period = period * (1! - OnOff) END IF Task(%Pi_Test).freq = MAX(MIN(1! / period, 1000),1) INCR j j = j MOD 2 END SUB SUB Pi_Note_UD1 () ' controls the note to be played. LOCAL noot AS BYTE LOCAL udnr AS DWORD udnr = TaskEX(%Pi_Test).UpDownNumbers(0) noot = UDCtrl(udnr).value IF noot < 84 THEN UDctrl(udnr).value = 84 : noot = 84 IF noot > 127 THEN UDctrl(udnr).value = 127 : noot = 127 SetDlgItemText Task(%Pi_Test).hparam, %GMT_TEXT0_ID + 16, "n=" & STR$(noot) END SUB SUB Pi_params() STATIC i% STATIC oldnote AS INTEGER STATIC slnr, udnr AS DWORD IF ISFALSE Task(%Pi_Params).tog THEN i% = Pi_.lowtes ' create a parameter window: DIM TaskParamLabels(6) AS ASCIIZ * 8 'Pi__ControlRoom TaskParamLabels(0) = "Attack" ' duration - ctrl 17 TaskParamLabels(1) = "Decay" ' duration - ctrl 18 TaskParamLabels(2) = "Sustain" ' level - ctrl 7 TaskParamlabels(3) = "Release" ' duration - ctrl. 19 TaskParamLabels(4) = "Wave" ' ctrl 15 TaskParamLabels(5) = "Noise" ' ctrl 1 IF ISFALSE Task(%Pi_Params).hParam THEN MakeTaskParameterDialog %Pi_params,6,Slider(),0,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(%Pi_params).SliderNumbers(0) Slider(slnr).value = 10 ' attack SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value Slider(slnr+1).value = 6 ' decay SendMessage Slider(Slnr+1).h, %TBM_SETPOS,%True, Slider(Slnr+1).value Slider(slnr+2).value = 64 'sustain SendMessage Slider(Slnr+2).h, %TBM_SETPOS,%True, Slider(Slnr+2).value Slider(slnr+3).value = 24 ' release SendMessage Slider(Slnr+3).h, %TBM_SETPOS,%True, Slider(Slnr+3).value Slider(slnr+4).value = 100 ' wave duty cycle SendMessage Slider(Slnr+4).h, %TBM_SETPOS,%True, Slider(Slnr+4).value Slider(slnr+5).value = 1 ' noise jitter SendMessage Slider(Slnr+5).h, %TBM_SETPOS,%True, Slider(Slnr+5).value END IF Task(%Pi_params).tog = %True END IF IF Pi_.ctrl(17) <> Slider(slnr).value THEN ' attack duration Pi_.ctrl(17) = Slider(slnr).value Controller Pi_.channel, 17, Pi_.ctrl(17) END IF IF Pi_.ctrl(18) <> Slider(slnr+1).value THEN ' decay duration Pi_.ctrl(18) = Slider(slnr+1).value Controller Pi_.channel, 18, Pi_.ctrl(18) END IF IF Pi_.ctrl(7) <> Slider(slnr+2).value THEN ' sustain level Pi_.ctrl(7) = Slider(slnr+2).value Controller Pi_.channel, 7, Pi_.ctrl(7) END IF IF Pi_.ctrl(19) <> Slider(slnr+3).value THEN ' release duration Pi_.ctrl(19) = Slider(slnr+3).value Controller Pi_.channel, 19, Pi_.ctrl(19) END IF IF Pi_.ctrl(15) <> Slider(slnr+4).value THEN ' wave shape Pi_.ctrl(15) = Slider(slnr+4).value Controller Pi_.channel, 15, Pi_.ctrl(15) END IF IF Pi_.ctrl(1) <> Slider(slnr+5).value THEN ' wave shape Pi_.ctrl(1) = Slider(slnr+5).value Controller Pi_.channel, 1, Pi_.ctrl(1) END IF END SUB SUB Pi_scale() STATIC i% STATIC oldnote AS INTEGER STATIC slnr, udnr AS DWORD IF ISFALSE Task(%Pi_scale).tog THEN i% = 72 'Pi_.lowtes ' 84 ' create a parameter window: DIM TaskParamLabels(6) AS ASCIIZ * 8 TaskParamLabels(0) = "Tempo" TaskParamlabels(1) = "Velo" TaskParamlabels(2) = "Release" ' can also be done with ctrl. 19 TaskParamLabels(3) = "Attack" ' duration - ctrl 17 TaskParamLabels(4) = "Decay" ' duration - ctrl 18 TaskParamLabels(5) = "Sustain" ' level - ctrl 7 TaskParamLabels(6) = "Wave" ' ctrl 15 IF ISFALSE Task(%Pi_scale).hParam THEN MakeTaskParameterDialog %Pi_scale,7,Slider(),0,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(%Pi_scale).SliderNumbers(1) Slider(slnr).value = 80 ' velo SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value Slider(slnr+1).value = %False ' release SendMessage Slider(Slnr+1).h, %TBM_SETPOS,%True, Slider(Slnr+1).value Slider(slnr+2).value = 5 ' attack SendMessage Slider(Slnr+2).h, %TBM_SETPOS,%True, Slider(Slnr+2).value Slider(slnr+3).value = 10 ' decay SendMessage Slider(Slnr+3).h, %TBM_SETPOS,%True, Slider(Slnr+3).value Slider(slnr+4).value = 68 ' sustain SendMessage Slider(Slnr+4).h, %TBM_SETPOS,%True, Slider(Slnr+4).value Slider(slnr+5).value = 48 ' wave SendMessage Slider(Slnr+5).h, %TBM_SETPOS,%True, Slider(Slnr+5).value END IF Controller Pi_.channel, 66, 127 Task(%Pi_scale).tog = %True END IF IF Pi_.ctrl(7) <> Slider(slnr+4).value THEN ' level sustain Pi_.ctrl(7) = Slider(slnr+4).value Controller Pi_.channel, 7, Pi_.ctrl(7) END IF IF Pi_.ctrl(17) <> Slider(slnr+2).value THEN ' attack duration Pi_.ctrl(17) = Slider(slnr+2).value Controller Pi_.channel, 17, Pi_.ctrl(17) END IF IF Pi_.ctrl(18) <> Slider(slnr+3).value THEN ' decay duration Pi_.ctrl(18) = Slider(slnr+3).value Controller Pi_.channel, 18, Pi_.ctrl(18) END IF IF Pi_.ctrl(15) <> Slider(slnr+5).value THEN ' wave shape Pi_.ctrl(15) = Slider(slnr+5).value Controller Pi_.channel, 15, Pi_.ctrl(15) END IF IF ISFALSE oldnote THEN mPlay Pi_.channel,i%, Slider(slnr).value oldnote = i% INCR i% IF i% > Pi_.Hightes THEN i% = Pi_.Lowtes ELSE IF ISFALSE slider(slnr+1).value THEN ' release value (duration) NoteOff Pi_.channel, oldnote ELSE Release Pi_.channel, oldnote, slider(slnr+1).value END IF oldnote = %False END IF Task(%Pi_scale).freq = Slider(slnr-1).value / 8 IF Task(%Pi_scale).freq < 0.1 THEN Task(%Pi_scale).freq = 0.1 END SUB SUB pi_controlroom LOCAL i AS LONG LOCAL x AS LONG IF ISFALSE hwCtrlpi THEN DIALOG NEW 0, "pi_ Control",1,1 ,560, 80, %WS_CAPTION OR %WS_POPUP OR %WS_SYSMENU TO hwCtrlpi x = 5 FOR i = pi_.lowtes TO pi_.HighTes SELECT CASE (i MOD 12) CASE 0 CONTROL ADD CHECKBOX, hwCtrlpi, i, "C", x, 24, 18, 12, %BS_PUSHLIKE x = x + 10 CASE 1 CONTROL ADD CHECKBOX, hwCtrlpi, i, "C#", x, 12, 18, 12, %BS_PUSHLIKE x = x + 10 CASE 2 CONTROL ADD CHECKBOX, hwCtrlpi, i, "D", x, 24, 18, 12, %BS_PUSHLIKE x = x + 10 CASE 3 CONTROL ADD CHECKBOX, hwCtrlpi, i, "D#", x, 12, 18, 12, %BS_PUSHLIKE x = x + 10 CASE 4 CONTROL ADD CHECKBOX, hwCtrlpi, i, "E", x, 24, 18, 12, %BS_PUSHLIKE x = x + 20 CASE 5 CONTROL ADD CHECKBOX, hwCtrlpi, i, "F", x, 24, 18, 12, %BS_PUSHLIKE x = x + 10 CASE 6 CONTROL ADD CHECKBOX, hwCtrlpi, i, "F#", x, 12, 18, 12, %BS_PUSHLIKE x = x + 10 CASE 7 CONTROL ADD CHECKBOX, hwCtrlpi, i, "G", x, 24, 18, 12, %BS_PUSHLIKE x = x + 10 CASE 8 CONTROL ADD CHECKBOX, hwCtrlpi, i, "G#", x, 12, 18, 12, %BS_PUSHLIKE x = x + 10 CASE 9 CONTROL ADD CHECKBOX, hwCtrlpi, i, "A", x, 24, 18, 12, %BS_PUSHLIKE x = x + 10 CASE 10 CONTROL ADD CHECKBOX, hwCtrlpi, i, "Bb", x, 12, 18, 12, %BS_PUSHLIKE x = x + 10 CASE 11 CONTROL ADD CHECKBOX, hwCtrlpi, i, "B", x, 24, 18, 12, %BS_PUSHLIKE x = x + 20 END SELECT NEXT CONTROL ADD LABEL, hwCtrlpi, 500, "Wind:", 5, 45, 30, 12 CONTROL ADD "msctls_trackbar32", hwCtrlpi, 501, "Wind", 36, 45, 135, 12, %WS_CHILD OR %WS_VISIBLE OR %TBS_HORZ OR %TBS_BOTTOM CONTROL ADD LABEL, hwCtrlpi, 503, "?", 174, 45, 30, 12 CONTROL ADD LABEL, hwCtrlpi, 510, "Velo:", 5, 60, 30, 12 CONTROL SEND hwCtrlPi, 501, %TBM_SETRANGEMAX, %true,127 CONTROL ADD "msctls_trackbar32", hwCtrlpi, 511, "Velo", 36, 60, 135, 12, %WS_CHILD OR %WS_VISIBLE OR %TBS_HORZ OR %TBS_BOTTOM CONTROL ADD LABEL, hwCtrlpi, 513, "?", 174, 60, 30, 12 ' control send hwCtrlPi, 511, %TBM_SETPOS, %true, 64 CONTROL SEND hwCtrlPi, 511, %TBM_SETRANGEMAX, %true,127 CONTROL ADD BUTTON, hwCtrlpi, 600, "All Off", 206, 45, 30, 12 CONTROL ADD CHECKBOX, hwCtrlPi, 610, "CC66", 206, 60, 30, 12, %BS_PUSHLIKE DIALOG SHOW MODELESS hwCtrlpi CALL CB_pi_Controlroom ELSE DIALOG END hwCtrlpi hwCtrlpi = 0 END IF END SUB CALLBACK FUNCTION CB_pi_Controlroom LOCAL wind AS BYTE LOCAL i AS LONG STATIC hTrackWind AS DWORD STATIC hTrackVelo AS DWORD STATIC velo AS BYTE LOCAL note AS BYTE SELECT CASE CBMSG CASE %WM_COMMAND SELECT CASE CBCTL CASE pi_.Lowtes TO pi_.hightes 'checkboxes CONTROL GET CHECK CBHNDL, CBCTL TO i note = CBCTL mPlay pi_.channel, note, IIF( i, velo, 0) CONTROL SET TEXT gh.cockpit, %GMT_MSG1,"note"+ STR$(note) + STR$(IIF( i, velo, 0) ) CASE 600 FOR i = pi_.lowtes TO pi_.hightes CONTROL SET CHECK CBHNDL, i, 0 DIALOG DOEVENTS NEXT Controller pi_.channel, 123, %False CASE 610 CONTROL GET CHECK CBHNDL, CBCTL TO i Controller Pi_.channel, 66, i * 127 END SELECT CASE %WM_HSCROLL, %WM_VSCROLL 'note: id doesn't correspond at all with the one given at creation 'more then one slider.. so we have to track which one.. CONTROL HANDLE CBHNDL, 501 TO htrackwind CONTROL HANDLE CBHNDL, 511 TO htrackvelo CONTROL SET TEXT gh.cockpit, %GMT_MSG2, STR$(htrackwind) +STR$(htrackvelo) +STR$(CBLPARAM) IF CBLPARAM = htrackWind THEN IF (LOWRD(CBWPARAM) = %TB_THUMBPOSITION) OR (LOWRD(CBWPARAM) = %TB_THUMBTRACK) THEN wind = HIWRD(CBWPARAM) ELSE wind = SendMessage (CBLPARAM, %TBM_GETPOS,%Null, %Null) END IF 'wind = wind * 1.27 CONTROL SET TEXT CBHNDL, 503, STR$(wind) pi_.ctrl(7) = wind Controller Pi_.channel, 7, Pi_.ctrl(7) CONTROL SET TEXT gh.cockpit, %GMT_MSG1, "cc7"+ STR$(Pi_.ctrl(7) ) ELSEIF CBLPARAM = htrackVelo THEN IF (LOWRD(CBWPARAM) = %TB_THUMBPOSITION) OR (LOWRD(CBWPARAM) = %TB_THUMBTRACK) THEN velo = HIWRD(CBWPARAM) ELSE velo = SendMessage (CBLPARAM, %TBM_GETPOS,%Null, %Null) END IF 'velo = velo * 1.27 CONTROL SET TEXT CBHNDL, 513, STR$(velo) END IF CASE %WM_CLOSE, %WM_QUIT hwCtrlpi = 0 FOR i = pi_.lowtes TO pi_.hightes DIALOG DOEVENTS NEXT Controller pi_.channel, 123, %False 'MM_pi_Off %MM_Motor END SELECT END FUNCTION SUB Pi_Lite () ' note 0. yellow light STATIC slnr AS DWORD STATIC cnt AS BYTE IF ISFALSE Task(%Pi_lite).tog THEN ' create a parameter window: DIM TaskParamLabels(1) AS ASCIIZ * 8 TaskParamLabels(0) = "Tempo" TaskParamlabels(1) = "Level" IF ISFALSE Task(%Pi_lite).hParam THEN MakeTaskParameterDialog %Pi_lite,2,Slider(),0,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(%Pi_lite).SliderNumbers(1) Slider(slnr).value = 127 ' velo SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Controller Pi_.channel, 66, 127 Task(%Pi_lite).tog = %True END IF IF ISFALSE cnt THEN mPlay Pi_.channel,0, Slider(slnr).value ELSE Release Pi_.channel, 0, 64 END IF INCR cnt IF cnt > 1 THEN cnt = %False Task(%Pi_lite).freq = Slider(slnr-1).value / 8 IF Task(%Pi_lite).freq < 0.1 THEN Task(%Pi_lite).freq = 0.1 END SUB SUB Pi_Tune () ' test for ctrl's 72 to 116, microtuning for the notes ' needs 1 U/D controller for the note and 1 slider for tuning ' microtuning controllers use the range 72 to 116 STATIC slnr, udnr AS DWORD STATIC noot AS INTEGER IF ISFALSE Task(%Pi_Tune).tog THEN DIM TaskParamLabels(0 TO 1) AS ASCIIZ * 8 TaskParamLabels(0) = "Tune" ' microtuning slider TaskParamLabels(1) = "Note" ' note UD IF ISFALSE Task(%Pi_Tune).hParam THEN slnr = %False MakeTaskParameterDialog %Pi_Tune,1,Slider(),1,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(%Pi_Tune).SliderNumbers(0) udnr = TaskEX(%Pi_tune).UpDownNumbers(0) UDctrl(TaskEX(%Pi_Tune).UpdownNumbers(0)).cptr = CODEPTR(Pi_Tune_UD1) UDctrl(TaskEX(%Pi_Tune).UpDownNumbers(0)).value = 84 Task(%Pi_Tune).freq = 20 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, 64 FOR noot = 84 TO 127 Pi_.ctrl(noot - 12) = 64 ' defaults NEXT noot END IF Controller Pi_.channel, 66, 64 Task(%Pi_Tune).tog = %True END IF noot = UDctrl(udnr).value IF noot >= 84 THEN IF Pi_.ctrl(noot-12) <> Slider(slnr).value THEN Controller Pi_.channel, noot - 12, Slider(slnr).value Pi_.ctrl(noot-12) = slider(slnr).value END IF END IF END SUB SUB Pi_Tune_UD1 () ' controls the note to be microtuned. LOCAL noot AS BYTE LOCAL udnr AS DWORD udnr = TaskEX(%Pi_Tune).UpDownNumbers(0) noot = UDCtrl(udnr).value IF noot < 84 THEN UDctrl(udnr).value = 84 : noot = 84 IF noot > 127 THEN UDctrl(udnr).value = 127 : noot = 127 SetDlgItemText Task(%Pi_Tune).hparam, %GMT_TEXT0_ID + 16, "n=" & STR$(noot) END SUB SUB Pi_Tune_Stop () LOCAL i AS INTEGER Logfile "Microtuning settings for " Logfile DATE$ Logfile TIME$ FOR i = 72 TO 116 Logfile "Note = " & STR$(i+12) & " tuning= " & STR$(Pi_.ctrl(i)- 64) NEXT i END SUB SUB Pi_Just () ' test for ctrl 21 EQ or Just intonation tunings ' needs 1 U/D controller for the basenote STATIC slnr, udnr AS DWORD STATIC noot, oldnoot AS INTEGER IF ISFALSE Task(%Pi_Just).tog THEN DIM TaskParamLabels(0 TO 1) AS ASCIIZ * 8 TaskParamLabels(0) = "---" TaskParamLabels(1) = "Tun" ' note IF ISFALSE Task(%Pi_Just).hParam THEN slnr = %False MakeTaskParameterDialog %Pi_Just,1,Slider(),1,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(%Pi_Just).SliderNumbers(0) udnr = TaskEx(%Pi_Just).UpDownNumbers(0) UDctrl(TaskEX(%Pi_Just).UpdownNumbers(0)).cptr = CODEPTR(Pi_Just_UD1) UDctrl(TaskEX(%Pi_Just).UpDownNumbers(0)).value = 0 Task(%Pi_Just).freq = 4 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, 0 Pi_.ctrl(21) = 0 ' defaults END IF Controller Pi_.channel, 21, 0 RESET oldnoot Task(%Pi_Just).tog = %True END IF noot = UDctrl(udnr).value IF noot <> oldnoot THEN oldnoot = noot SELECT CASE noot CASE 0 Controller Pi_.channel, 21, noot Pi_.ctrl(21) = noot CASE 12 TO 23 Controller Pi_.channel, 21, noot Pi_.ctrl(21) = noot END SELECT END IF END SUB SUB Pi_Just_UD1 () ' controls the base note for just intonation LOCAL noot AS BYTE LOCAL udnr AS DWORD udnr = TaskEX(%Pi_Just).UpDownNumbers(0) noot = UDCtrl(udnr).value 'IF noot < 12 THEN UDctrl(udnr).value = 0 : noot = 0 ' resets to EQ IF noot > 23 THEN UDctrl(udnr).value = 23 : noot = 23 SetDlgItemText Task(%Pi_Just).hparam, %GMT_TEXT0_ID + 16, "JI" & STR$(noot) END SUB SUB Pi_Just_Stop () Controller Pi_.channel, 21, 0 ' reset to EQ Pi_.ctrl(21) = 0 END SUB SUB Pi_Poly () ' Written to test polyphonic limits of the hardware. ' parameters: speed ' nr of notes ' legato/staccato STATIC slnr AS DWORD STATIC j AS DWORD STATIC i AS INTEGER LOCAL onoff AS SINGLE LOCAL period AS SINGLE LOCAL n AS INTEGER IF ISFALSE Task(%Pi_Poly).tog THEN DIM TaskParamLabels(0 TO 2) AS ASCIIZ * 8 TaskParamLabels(0) = "Tempo" ' playing speed TaskParamlabels(1) = "On/Off" ' legato-staccato proportion TaskParamLabels(2) = "Nr" ' nr of notes IF ISFALSE Task(%Pi_Poly).hParam THEN slnr = %False MakeTaskParameterDialog %Pi_Poly,2,Slider(),1,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(%Pi_Poly).SliderNumbers(0) UDctrl(TaskEX(%Pi_Poly).UpdownNumbers(0)).cptr = CODEPTR(Pi_NrNotes_UD1) ' aantal noten i = 4 UDctrl(TaskEX(%Pi_Poly).UpDownNumbers(0)).value = 4 j = 0 Task(%Pi_Poly).freq = 2 Slider(slnr).value = Task(%Pi_Poly).freq SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value Slider(slnr+1).value = 64 SendMessage Slider(Slnr+1).h, %TBM_SETPOS,%True, 64 ' mid position END IF j = %False Task(%Pi_Poly).tog = %True Controller Pi_.channel, 66, 64 Pi_.ctrl(66) = 64 EXIT SUB END IF OnOff = Slider(slnr+1).value / 128 ' 0- 0.99218 IF OnOff < 0.0078 THEN OnOff = 0.0078125 period = 1! / (8! * ((Slider(slnr).value+1) / 128!)) ' tempo - duur in sekonden. IF ISFALSE j THEN Pi_.Har(1).vel = STRING$(128,0) i = MAX(UDctrl(TaskEX(%Pi_Poly).UpDownNumbers(0)).value , 1) DO n = 84 + (RND(1) * 43) IF IsNoteInHar( Pi_.Har(1), n) THEN ITERATE DO ' avoiding twice the same note AddNote2Har Pi_.Har(1),n , 64 LOOP UNTIL GetNrNotesInHar (Pi_.Har(1)) = i InstrumPlay Pi_ period = period * OnOff ELSE 'NoteOff Pi_.Har(1).vel = STRING$(128,0) InstrumPlay Pi_ period = period * (1! - OnOff) END IF Task(%Pi_Poly).freq = MAX(MIN(1! / period, 1000),1) INCR j j = j MOD 2 END SUB SUB Pi_NrNotes_UD1 () ' controls the number of notes to be played. LOCAL n AS BYTE LOCAL udnr AS DWORD udnr = TaskEX(%Pi_Poly).UpDownNumbers(0) n = UDCtrl(udnr).value IF n < 1 THEN UDctrl(udnr).value = 1 : n = 1 IF n > 44 THEN UDctrl(udnr).value = 44 : n = 44 SetDlgItemText Task(%Pi_Poly).hparam, %GMT_TEXT0_ID + 16, "Nr=" & STR$(n) END SUB ' *************************************************************************** SUB Pipi_Intro () ' 11.03.2017: first coding ' to do: moet versnellen en volumes voor board 2 moeten naar beneden. ' done 12.03.2017 ' should restart at the point it was stopped, so that we can ' use the sounds at different point in the piece. ' 12.03.2017: Now 3 minutes STATIC noot, oldnoot, ofnoot, level, i AS INTEGER STATIC j , rise, fall, nrnotes, init, lite, nv AS INTEGER ' BYTE STATIC tfakt AS SINGLE STATIC cnt AS LONG IF ISFALSE Task(%Pipi_Intro).tog THEN Controller Pi_.channel, 66, 83 Controller Pi_.channel, 21, 0 Controller Pi_.channel, 17, 12 Controller Pi_.Channel, 18, 4 Controller Pi_.channel, 19, 20 Controller Pi_.channel, 15, 127 '100 Controller Pi_.channel, 1, 0 Pi_.ctrl(7) = 126 Controller Pi_.channel, 7, 126 IF cnt THEN logfile "Pipi Intro restart at:" & TIME$ & STR$(cnt) END IF Task(%Pipi_Intro).tog = %True END IF ' proc. to make restart possible at the point the task was interrupted IF ISFALSE init THEN RESET cnt Pi_.Har(1).vel = NUL$(128) i = 0 oldnoot = 0 noot = 127 ofnoot = 127 rise = %True fall = %False logfile "Pipi Intro start at:" & TIME$ & STR$(cnt) IF ISFALSE lite THEN mPlay Pi_.channel, 0, 100 ' lite lite = %True END IF Task(%Pipi_Intro).freq = 4 ' 24 '32 init = %True END IF ' musical coding: IF noot <> oldnoot THEN Controller Pi_.channel, 7, Pi_.ctrl(7) mPlay Pi_.channel, noot, 127 - Pi_.ctrl(7) oldnoot = noot AddNote2Har Pi_.Har(1), noot, 127 - Pi_.ctrl(7) INCR nrnotes END IF IF rise = %True THEN INCR i IF i <= 127 THEN Pi_.ctrl(1) = MIN(MAX(i,0),127) Controller Pi_.channel, 1, Pi_.ctrl(15) ' noise ELSE rise = %False fall = %True END IF END IF IF fall = %True THEN DECR i 'i = i - 2 IF i >= 0 THEN Pi_.ctrl(1) = MIN(MAX(i,0),127) Controller Pi_.channel, 1, Pi_.ctrl(1) ' noise ELSE rise = %True fall = %False DO noot = noot - RND(1,3) '(1 + (cnt MOD 2)) LOOP UNTIL noot < oldnoot IF noot < 84 THEN logfile "Pipi Intro full stop at :" & TIME$ RESET init stoptask %Pipi_Intro END IF END IF END IF IF nrnotes > 4 THEN nv = GetHighestNote (Pi_.Har(1), 0, 127) NoteOff Pi_.channel, HIBYT(nv) ',LOBYT(nv) DelNote2Har Pi_.Har(1), HIBYT(nv) DECR nrnotes END IF ' volume decrescendo in functie van de toonhoogte: 'level = 20 + ((noot - 84) * 2) ' noot - 84: loopt van 43 naar 0 ' * 2 = van 83 naar 0 ' + 20 = van 103 naar 20 'level = 44 + (( noot - 84) *2) ' van 127 naar 44 'level = 44 + (( noot - 84) *2) ' van 127 naar 44 IF noot > 97 THEN ' decrescendo level = MIN(106 + ((noot - 84) /2), 126) ' 127 tot 113 'level = 44 + (( noot - 84) *2) ' van 127 naar 44 ELSE ' crescendo level = 44 + ((1.0 - ((noot-84)/ 13.0))* 13.0) ' noot -84: loopt van 13 naar 0 ' / 13: loopt van 1 naar 0 ' 1 - : loopt van 0 naar 1 ' * 13: loopt van 0 naar 13 level = MIN(level, 126) END IF IF level <> Pi_.ctrl(7) THEN Pi_.ctrl(7) = level END IF INCR cnt ' accellerando: tfakt = 1.0 + (((noot - 84)/ 43.0) * (Pi * 2)) Task(%Pipi_Intro).freq = 10 * tfakt '24 * tfakt ' tfakt: 1- pi/2, float END SUB SUB Pipi_Intro_stop () logfile "Pipi Intro interrupted at: " & TIME$ controller Pi_.channel, 123, 0 starttask %Pipi_Perc END SUB SUB Pipi_Triads () ' 12.03.2017 ' should play triads where the lowest note makes a downslide ' the highest note an upslide and the middle note always stays stable ' based on - the complete catalogue of different chords, each chord having a different interval ' constellation. Ordering is in increasing level of dissonance. cfr. Belly_Cat in belly testcode ' 13.03.2017: restart bug to be solved. STATIC i, j, cnt, trans AS LONG STATIC init AS BYTE STATIC tog AS INTEGER STATIC Akk() AS INTEGER STATIC n AS INTEGER STATIC lownote, highnote AS INTEGER 'LOCAL zandloper AS ASCIIZ PTR ' silly !!! (caused by declaration of WinApi) 'LOCAL hCursor AS LONG IF ISFALSE Task(%Pipi_Triads).tog THEN IF ISFALSE init THEN REDIM Akk(&HFFF) AS STATIC INTEGER ' hCursor = GetCursor () ' zandloper = %IDC_WAIT ' SetCursor LoadCursor (%Null, BYVAL(zandloper)) ' cfr. declaration PB WinApi SortChordsOnDissonance Akk(), &HF33C, 127 ' dll procedure ' parameters: %SortNoIsomorphs OR %SortPsyChord, only chords with 3-notes 'MSGBOX "Chords sorted. Ubound Akk = " & STR$(UBOUND(Akk)) ' 19 chords! as chordnumbers init = %True ' SetCursor hCursor 'EXIT SUB END IF Controller Pi_.channel, 123, 0 ' controllers: Controller Pi_.channel, 66, 83 Controller Pi_.channel, 21, 0 Controller Pi_.channel, 17, 1 Controller Pi_.Channel, 18, 1 Controller Pi_.channel, 19, 1 Controller Pi_.channel, 15, 83 Controller Pi_.channel, 1, 0 Pi_.ctrl(7) = 127 Controller Pi_.channel, 7, Pi_.ctrl(7) RESET cnt tog = 1 logfile "Pipi_Triads start at: " & TIME$ Task(%Pipi_Triads).tog = %True END IF ' now we can start playing the iterated chords... ' and play with the controllers 72 to 116 IF tog = 1 THEN Task(%Pipi_Triads).Har.vel = STRING$(128,0) ' mPlay all those 19 triads on all possible pipes... ' Akk(cnt) = TransChordNum (Akk(cnt), trans) ' chordnumber transposition ' trans = (trans + 5) MOD 12 AddCnr2Har Task(%Pipi_Triads).Har , Akk(cnt), 84,127, 120 Pi_.Har(1) = Task(%Pipi_Triads).Har InstrumPlay Pi_ lownote = GetLowestNote (Task(%Pipi_Triads).Har, 0, 127) lownote = HIBYT(lownote) highnote = GetHighestNote (Task(%Pipi_Triads).Har, 0, 127) highnote = HIBYT(Highnote) Controller Pi_.channel, lownote -12, 64 Pi_.ctrl(lownote -12) = 64 ' reset Controller Pi_.channel, highnote - 12, 64 Pi_.ctrl(highnote - 12) = 64 INCR cnt RESET tog RESET j ELSE ' slides: Pi_.Har(1).vel = NUL$(128) InstrumPlay Pi_ Controller Pi_.Channel, lownote - 12, 64 - j Controller Pi_.Channel, highnote - 12, 64 + j Pi_.Har(1) = Task(%Pipi_Triads).Har InstrumPlay Pi_ INCR j IF j >= 63 THEN tog = 1 END IF END IF IF tog = 0 THEN IF cnt > 19 THEN ' UBOUND(Akk) then IF j >= 63 THEN stoptask %Pipi_Triads EXIT SUB END IF END IF END IF IF tog = 1 THEN Task(%Pipi_Triads).freq = 8 + (cnt/4.0) ELSE Task(%Pipi_Triads).freq = 10.0 + (cnt/4.0) - (j/8.0) ' slowdown to 2 END IF SetDlgItemText gh.Cockpit, %GMT_MSG1, "Count= " & STR$(cnt) IF cnt > 19 THEN Stoptask %Pipi_Triads ' to make sure it does not restart END IF END SUB SUB Pipi_Triads_Stop () LOCAL i AS BYTE controller Pi_.channel, 123, 0 FOR i = 72 TO 115 '84 -12 TO 127 - 12 Controller Pi_.channel, i, 64 Pi_.ctrl(i) = 64 NEXT i starttask %Pipi_Burst END SUB SUB Pipi_Perc () ' 12.03.2017 ' very short clouds of pitches ' needs further refinement. ' 13.03.2017: improved. STATIC note, velo AS INTEGER STATIC t, krono, duur AS LONG STATIC prop AS SINGLE ' normalised 0-1 timer IF ISFALSE Task(%Pipi_Perc).tog THEN Controller Pi_.channel, 17, 2 Controller Pi_.channel, 18, 0 Controller Pi_.channel, 7, 2 ' very low sustain velo = 127 t = TimeGetTime ' in ms RESET krono RESET note duur =30 ' 30 seconds duration Logfile "Pipi_Perc start at " & TIME$ Task(%Pipi_perc).tog = %True END IF IF note THEN noteoff Pi_.channel, note krono = (TimeGetTime - t)/ 1000 ' in seconds prop = krono / duur ' 0-1 IF krono >= duur THEN Logfile "Pipi_Perc stop at " & TIME$ Logfile "Duration was : " & STR$(krono) stoptask %Pipi_Perc EXIT SUB END IF note = RND(83,127) IF note >=84 THEN mPlay Pi_.channel, note, velo ELSE mPlay Pi_.channel, 0, 127 ' yellow LED flashes END IF Task(%Pipi_Perc).freq = 4 + RND(0,64 * prop) END SUB SUB Pipi_Perc_Stop () Controller Pi_.channel, 123, 0 starttask %Pipi_Triads END SUB SUB Pipi_Burst () ' very short clouds of noises ' needs further refinement. STATIC note, velo AS INTEGER STATIC t, krono, duur AS LONG STATIC prop AS SINGLE ' normalised 0-1 timer IF ISFALSE Task(%Pipi_Burst).tog THEN Controller Pi_.channel, 17, 10 Controller Pi_.channel, 18, 4 Controller Pi_.channel, 19, 64 Controller Pi_.channel, 7, 90 Controller Pi_.channel, 1, 120 ' noise velo = 127 t = TimeGetTime ' in ms RESET krono RESET note duur =30 ' 30 seconds duration Logfile "Pipi_Burst start at " & TIME$ Task(%Pipi_burst).tog = %True END IF IF note THEN noteoff Pi_.channel, note krono = (TimeGetTime - t)/ 1000 ' in seconds prop = krono / duur ' 0-1 IF krono >= duur THEN Logfile "Pipi_Burst stop at " & TIME$ Logfile "Duration was : " & STR$(krono) stoptask %Pipi_Burst EXIT SUB END IF note = RND(83,127) IF note >=84 THEN mPlay Pi_.channel, note, velo ELSE mPlay Pi_.channel, 0, 127 ' yellow LED flashes END IF Task(%Pipi_Burst).freq = 2 + RND(1,48 * prop) END SUB SUB Pipi_Burst_Stop () Controller Pi_.channel, 123, 0 starttask %Pipi END SUB SUB PiPi () ' demostukje voor solo ' based on: ' - the complete catalogue of different chords, each chord having a different interval ' constellation. Ordering is in increasing level of dissonance. ' chords are followed by their solutions. ' adapted from Melodrama for Melauton. (06.02.2017) STATIC i AS WORD ' akkoordenteller 0-350 STATIC temposlnr AS BYTE STATIC ppslnr AS BYTE STATIC levelslnr, veloslnr AS BYTE STATIC Ritmeteller% STATIC init AS BYTE STATIC Akk() AS INTEGER STATIC tc AS INTEGER GLOBAL Mh AS harmtype LOCAL tiks! LOCAL zandloper AS ASCIIZ PTR ' silly !!! (caused by declaration of WinApi) LOCAL hCursor AS LONG IF (Task(%Pipi).swit AND %TASK_BUSY) = %d1 THEN EXIT SUB IF ISFALSE init THEN REDIM Akk(0 TO &HFFF) AS STATIC INTEGER hCursor = GetCursor () zandloper = %IDC_WAIT SetCursor LoadCursor (%Null, BYVAL(zandloper)) ' cfr. declaration PB WinApi SortChordsOnDissonance Akk(), &HFC1C, 127 ' dll procedure ' parameters: %SortNoIsomorphs OR %SortPsyChord ' MSGBOX "Chords sorted. Ubound Akk = " & STR$(UBOUND(Akk)) ' = 350 ' since this takes pretty long, it would be better to save the lookup to a diskfile init = %True DIM TaskParamLabels(0 TO 3) AS ASCIIZ * 8 TaskParamLabels(0) = "Tempo" TaskParamLabels(1) = "0/1 rit" TaskParamLabels(2) = "#7" TaskParamLabels(3) = "velo" IF Task(%Pipi).hParam = %Null THEN MakeTaskParameterDialog BYVAL %Pipi,4,Slider(),0,UDctrl(),TaskParamLabels() END IF temposlnr = TaskEX(%Pipi).SliderNumbers(0) ppslnr = TaskEX(%Pipi).SliderNumbers(1) levelslnr = TaskEX(%Pipi).SliderNumbers(2) veloslnr = TaskEX(%Pipi).SliderNumbers(3) Controller Pi_.channel, 66, 0 ' power off - reset controllers Slider(temposlnr).value = 22 ' starttempo SendMessage Slider(temposlnr).h, %TBM_SETPOS,%True,Slider(temposlnr).value SendMessage Slider(ppslnr).h, %TBM_SETPOS,%True, 127 ' legato Slider(ppslnr).value = 127 ' full legato SendMessage Slider(levelslnr).h, %TBM_SETPOS,%True, 42 ' ctrl7 Slider(levelslnr).value = 42 Slider(veloslnr).value = 120 SendMessage Slider(veloslnr).h, %TBM_SETPOS,%True, 120 ' velocity SetDlgItemText gh.Cockpit, %GMT_TEXT_TEMPO, STR$(App.tempo) Task(%Pipi).freq = App.tempo / 60! SetCursor hCursor Task(%Pipi).tog = %False Controller Pi_.channel, 66, 65 ' power on 'Stoptask %Pipi - would cause ending to start... EXIT SUB END IF '------------------------------------------------- IF ISFALSE Task(%Pipi).tog THEN Task(%Pipi).tog = %True SetDlgItemText gh.Cockpit, %GMT_MSG1, "350 chords and progressions" SetDlgItemText gh.Cockpit, %GMT_TITLE, "PiPi" SetDlgItemText gh.Cockpit, %GMT_AUTHOR, $gwr Controller Pi_.channel, 17, 60 Controller Pi_.Channel, 18, 10 Controller Pi_.channel, 19, 110 Controller Pi_.channel, 15, 100 Controller Pi_.channel, 1, 0 Controller Pi_.channel, 7, 46 i = %False ' reset akkoordenteller logfile "'Pipi' starttime = " & TIME$ END IF IF Task(%Pipi).tempo <> Slider(temposlnr).value THEN Task(%Pipi).tempo = Slider(temposlnr).value IF ISFALSE Task(%Pipi).tempo THEN Task(%Pipi).tempo = %True SetDlgItemText gh.Cockpit, %GMT_TEXT_TEMPO, STR$(Task(%Pipi).tempo) ' tempo display END IF IF ISFALSE Task(%Pipi).Rit.pattern(Ritmeteller%) THEN Ritmeteller% = %False ' select case i ' case < 12 ' Task(%Pipi).Rit.pattern(0)= Slider(ppslnr).value + 1 ' ON time ' Task(%Pipi).Rit.pattern(1)= -(128 - Slider(ppslnr).value) ' OFF time ' Task(%Pipi).Rit.pattern(2)= Slider(ppslnr).value + 1 ' ON time ' Task(%Pipi).Rit.pattern(3)= -(128 - Slider(ppslnr).value) ' OFF time ' Task(%Pipi).Rit.pattern(4)= Slider(ppslnr).value + 1 ' ON time ' Task(%Pipi).Rit.pattern(5)= -(128 - Slider(ppslnr).value) ' OFF time ' Task(%Pipi).Rit.pattern(6)= Slider(ppslnr).value + 1 ' ON time ' Task(%Pipi).Rit.pattern(7)= -(128 - Slider(ppslnr).value) ' OFF time ' Task(%Pipi).Rit.pattern(8)= Slider(ppslnr).value + 1 ' ON time ' Task(%Pipi).Rit.pattern(9)= -(128 - Slider(ppslnr).value) ' OFF time ' Task(%Pipi).Rit.pattern(10)= %False Task(%Pipi).Rit.pattern(0)= (Slider(ppslnr).value + 1)*2 ' ON time Task(%Pipi).Rit.pattern(1)= Slider(ppslnr).value + 1 ' ON time Task(%Pipi).Rit.pattern(2)= Slider(ppslnr).value + 1 ' ON time Task(%Pipi).Rit.pattern(3)= Slider(ppslnr).value + 1 ' ON time Task(%Pipi).Rit.pattern(4)= Slider(ppslnr).value + 1 ' ON time Task(%Pipi).Rit.pattern(5)= -(128 - Slider(ppslnr).value) ' OFF time Task(%Pipi).Rit.pattern(6)= %False ' end select END IF tiks! = RitmSigma!(Task(%Pipi).Rit) IF tiks! < 1 THEN EXIT SUB ' het tempo voor een gehele maat is frq = task(tasknr%).tempo / 60 ' zo'n gehele maat beslaat een aantal eenheden gegeven in tiks! Task(%Pipi).freq = (tiks! * Task(%Pipi).tempo ) / (60 * ABS(Task(%Pipi).Rit.pattern(Ritmeteller%))) IF Task(%Pipi).Rit.pattern(Ritmeteller%) > 0 THEN SELECT CASE Ritmeteller% CASE %False AddCnr2Har Task(%Pipi).Har, Akk(i) OR &HF000, 84, 127, Slider(veloslnr).value ' velo from slider IF tc > 0 THEN TransHarm Task(%Pipi).Har, tc IF tc + 12 <> Pi_.ctrl(21) THEN Controller Pi_.channel, 21, tc + 12 ' set just intonation tuning base Pi_.ctrl(21) = tc + 12 END IF FillHarType Task(%Pipi).Har , %use_fuzzypsy SetDlgItemText gh.Cockpit, %GMT_MSG1, "Solve "& STR$(i) mH = Task(%Pipi).Har Pi_.Har(1) = Task(%Pipi).Har Instrumplay Pi_ INCR i ' akkoordenteller CASE 1 'ELSE ' solve the chord Task(%Pipi).har = mH IF tc > 0 THEN TransHarm Task(%Pipi).Har, tc IF tc + 12 <> Pi_.ctrl(21) THEN Controller Pi_.channel, 21, tc + 12 ' set just intonation tuning base Pi_.ctrl(21) = tc + 12 END IF Task(%Pipi).har.vel = SolveHar$ (Task(%Pipi).Har, -1, 0) Pi_.Har(1) = Task(%Pipi).Har SELECT CASE GetNrNotesInHar (Pi_.Har(1)) CASE 0 Task(%Pipi).Rit.pattern(Ritmeteller%+1)= %False CASE 1 mH = Pi_.Har(1) Task(%Pipi).Rit.pattern(Ritmeteller%+1)= - Task(%Pipi).Rit.pattern(Ritmeteller%) Task(%Pipi).Rit.pattern(Ritmeteller%+2)= %False InstrumPlay Pi_ tc = QuestTcHar (Task(%Pipi).Har, 0.3) CASE ELSE mH = Pi_.Har(1) InstrumPlay Pi_ tc = QuestTcHar (Task(%Pipi).Har, 0.3) END SELECT CASE 2 ' further solve step: Task(%Pipi).har = mH IF tc > 0 THEN TransHarm Task(%Pipi).har, tc IF tc + 12 <> Pi_.ctrl(21) THEN Controller Pi_.channel, 21, tc + 12 ' set just intonation tuning base Pi_.ctrl(21) = tc + 12 END IF Pi_.Har(1).vel = SolveHar$ (Task(%Pipi).Har, -1, 0) Task(%Pipi).Har = Pi_.Har(1) mH = Pi_.Har(1) SELECT CASE GetNrNotesInHar (Pi_.Har(1)) CASE 0 Task(%Pipi).Rit.pattern(Ritmeteller%+1)= %False CASE 1 mH = Pi_.Har(1) Task(%Pipi).Rit.pattern(Ritmeteller%+1)= - Task(%Pipi).Rit.pattern(Ritmeteller%) Task(%Pipi).Rit.pattern(Ritmeteller%+2)= %False 'Task(%Pipi).Rit.pattern(Ritmeteller%+1)= %False InstrumPlay Pi_ tc = QuestTcHar (Task(%Pipi).Har, 0.3) CASE ELSE mH = Pi_.Har(1) InstrumPlay Pi_ tc = QuestTcHar (Task(%Pipi).Har, 0.3) END SELECT 'InstrumPlay Pi_ 'tc = QuestTcHar (Task(%Pipi).Har, 0.3) CASE 3 ' further solve step: Task(%Pipi).har = mH IF tc > 0 THEN TransHarm Task(%Pipi).har, tc IF tc + 12 <> Pi_.ctrl(21) THEN Controller Pi_.channel, 21, tc + 12 ' set just intonation tuning base Pi_.ctrl(21) = tc + 12 END IF Pi_.Har(1).vel = SolveHar$ (Task(%Pipi).Har, -1, 0) Task(%Pipi).Har = Pi_.Har(1) mH = Pi_.Har(1) SELECT CASE GetNrNotesInHar (Pi_.Har(1)) CASE 0 Task(%Pipi).Rit.pattern(Ritmeteller%+1)= %False CASE 1 mH = Pi_.Har(1) Task(%Pipi).Rit.pattern(Ritmeteller%+1)= - Task(%Pipi).Rit.pattern(Ritmeteller%) Task(%Pipi).Rit.pattern(Ritmeteller%+2)= %False 'Task(%Pipi).Rit.pattern(Ritmeteller%+1)= %False InstrumPlay Pi_ tc = QuestTcHar (Task(%Pipi).Har, 0.3) CASE ELSE mH = Pi_.Har(1) InstrumPlay Pi_ tc = QuestTcHar (Task(%Pipi).Har, 0.3) END SELECT 'InstrumPlay Pi_ 'tc = QuestTcHar (Task(%Pipi).Har, 0.3) CASE 4 ' further solve step: Task(%Pipi).har = mH IF tc > 0 THEN TransHarm Task(%Pipi).har, tc IF tc + 12 <> Pi_.ctrl(21) THEN Controller Pi_.channel, 21, tc + 12 ' set just intonation tuning base Pi_.ctrl(21) = tc + 12 END IF Pi_.Har(1).vel = SolveHar$ (Task(%Pipi).Har, -1, 0) Task(%Pipi).Har = Pi_.Har(1) mH = Pi_.Har(1) SELECT CASE GetNrNotesInHar (Pi_.Har(1)) CASE 0 Task(%Pipi).Rit.pattern(Ritmeteller%+1)= %False CASE 1 mH = Pi_.Har(1) Task(%Pipi).Rit.pattern(Ritmeteller%+1)= - Task(%Pipi).Rit.pattern(Ritmeteller%) Task(%Pipi).Rit.pattern(Ritmeteller%+2)= %False 'Task(%Pipi).Rit.pattern(Ritmeteller%+1)= %False InstrumPlay Pi_ tc = QuestTcHar (Task(%Pipi).Har, 0.3) CASE ELSE mH = Pi_.Har(1) InstrumPlay Pi_ tc = QuestTcHar (Task(%Pipi).Har, 0.3) END SELECT 'InstrumPlay Pi_ 'tc = QuestTcHar (Task(%Pipi).Har, 0.3) END SELECT ELSEIF Task(%Pipi).Rit.pattern(Ritmeteller%) < 0 THEN ' rust Task(%Pipi).Har.vel = NUL$(128) Pi_.Har(1).vel = NUL$(128) Pi_.Har(0).vel = NUL$(128) Controller Pi_.channel, 123, 0 ' voortijdig einde na akoord 47: IF i = 48 THEN Task(%Pipi_end).Har = mH Stoptask %Pipi StartTask %Pipi_end END IF ' voor de volledige versie...: IF i > UBOUND(Akk) THEN Task(%Pipi_end).Har = mH Stoptask %Pipi StartTask %Pipi_end END IF END IF INCR Ritmeteller% IF Slider(levelslnr).value <> Task(%Pipi).level THEN Task(%Pipi).level = Slider(levelslnr).value Controller Task(%Pipi).channel, 7 , Task(%Pipi).level ' changes sustain, but these values are used for velo as well... END IF END SUB SUB pipi_ending () STATIC levelslnr AS LONG IF ISFALSE Task(%Pipi_end).tog THEN levelslnr = TaskEX(%Pipi).SliderNumbers(2) Task(%Pipi_end).freq = 1 Pi_.ctrl(7) = Slider(levelslnr).value Controller Pi_.channel, 7, Pi_.ctrl(7) Pi_.har(1) = mH ' mH is global InstrumPlay Pi_ Task(%Pipi_end).freq = Pi_.ctrl(7) / 10 '30 ' so duration will be 30 seconds Task(%Pipi_end).tog = %True END IF DECR Pi_.ctrl(7) INCR Pi_.ctrl(1) Pi_.har(1) = mH Instrumplay Pi_ IF Pi_.ctrl(1) > 127 THEN Pi_.Ctrl(1) = 127 IF Pi_.ctrl(7) <= 0 THEN Controller Pi_.channel, 123, %False Controller Pi_.channel, 66, %False logfile "'Pipi' endtime = " & TIME$ stoptask %Pipi_end ELSE Controller Pi_.channel, 7, Pi_.ctrl(7) Controller Pi_.channel, 1, Pi_.ctrl(1) END IF END SUB SUB Pi2_scale() STATIC i% STATIC oldnote AS INTEGER STATIC slnr, udnr AS DWORD IF ISFALSE Task(%Pi2_scale).tog THEN i% = 72 ' create a parameter window: DIM TaskParamLabels(6) AS ASCIIZ * 8 TaskParamLabels(0) = "Tempo" TaskParamlabels(1) = "Velo" TaskParamlabels(2) = "Release" ' can also be done with ctrl. 19 TaskParamLabels(3) = "Attack" ' duration - ctrl 17 TaskParamLabels(4) = "Decay" ' duration - ctrl 18 TaskParamLabels(5) = "Sustain" ' level - ctrl 7 TaskParamLabels(6) = "Wave" ' ctrl 15 IF ISFALSE Task(%Pi2_scale).hParam THEN MakeTaskParameterDialog %Pi2_scale,7,Slider(),0,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(%Pi2_scale).SliderNumbers(1) Slider(slnr).value = 80 ' velo SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value Slider(slnr+1).value = %False ' release SendMessage Slider(Slnr+1).h, %TBM_SETPOS,%True, Slider(Slnr+1).value Slider(slnr+2).value = 5 ' attack SendMessage Slider(Slnr+2).h, %TBM_SETPOS,%True, Slider(Slnr+2).value Slider(slnr+3).value = 10 ' decay SendMessage Slider(Slnr+3).h, %TBM_SETPOS,%True, Slider(Slnr+3).value Slider(slnr+4).value = 68 ' sustain SendMessage Slider(Slnr+4).h, %TBM_SETPOS,%True, Slider(Slnr+4).value Slider(slnr+5).value = 48 ' wave SendMessage Slider(Slnr+5).h, %TBM_SETPOS,%True, Slider(Slnr+5).value END IF Controller Pi2_.channel, 66, 127 ' same as Pi Task(%Pi2_scale).tog = %True END IF IF Pi2_.ctrl(7) <> Slider(slnr+4).value THEN ' level sustain Pi2_.ctrl(7) = Slider(slnr+4).value Controller Pi2_.channel, 7, Pi2_.ctrl(7) END IF IF Pi2_.ctrl(17) <> Slider(slnr+2).value THEN ' attack duration Pi2_.ctrl(17) = Slider(slnr+2).value Controller Pi2_.channel, 17, Pi2_.ctrl(17) END IF IF Pi2_.ctrl(18) <> Slider(slnr+3).value THEN ' decay duration Pi2_.ctrl(18) = Slider(slnr+3).value Controller Pi2_.channel, 18, Pi2_.ctrl(18) END IF IF Pi2_.ctrl(15) <> Slider(slnr+5).value THEN ' wave shape Pi2_.ctrl(15) = Slider(slnr+5).value Controller Pi2_.channel, 15, Pi2_.ctrl(15) END IF IF ISFALSE oldnote THEN mPlay Pi2_.channel,i%, Slider(slnr).value oldnote = i% INCR i% IF i% > 101 THEN i% = 72 ' 2Pi range ELSE IF ISFALSE slider(slnr+1).value THEN ' release value (duration) NoteOff Pi2_.channel, oldnote ELSE Release Pi2_.channel, oldnote, slider(slnr+1).value END IF oldnote = %False END IF Task(%Pi2_scale).freq = Slider(slnr-1).value / 8 IF Task(%Pi2_scale).freq < 0.1 THEN Task(%Pi2_scale).freq = 0.1 END SUB SUB Pi2_Lites () ' notes 1 and 2 blue light STATIC slnr AS DWORD STATIC cnt AS BYTE IF ISFALSE Task(%Pi2_lites).tog THEN ' create a parameter window: DIM TaskParamLabels(0) AS ASCIIZ * 8 TaskParamLabels(0) = "Tempo" IF ISFALSE Task(%Pi2_lites).hParam THEN MakeTaskParameterDialog %Pi2_lites,1,Slider(),0,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(%Pi2_lites).SliderNumbers(0) Slider(slnr).value = 10 SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value END IF Controller Pi2_.channel, 66, 127 Task(%Pi2_lites).tog = %True END IF IF ISFALSE cnt THEN NoteOff Pi2_.channel, 1 mPlay Pi2_.channel,2, 127 ELSE NoteOff Pi2_.channel,2 mPlay Pi2_.channel, 1, 127 END IF INCR cnt IF cnt > 1 THEN cnt = %False Task(%Pi2_lites).freq = Slider(slnr).value / 8 IF Task(%Pi2_lites).freq < 0.1 THEN Task(%Pi2_lites).freq = 0.1 END SUB SUB Pi2_Test () ' tests repeated notes. ' parameters: repetition rate ' push-time ' release-time ' note STATIC slnr AS DWORD STATIC i,j AS INTEGER LOCAL onoff AS SINGLE LOCAL period AS SINGLE IF ISFALSE Task(%Pi2_Test).tog THEN DIM TaskParamLabels(0 TO 4) AS ASCIIZ * 8 TaskParamLabels(0) = "Tempo" ' repeat rate TaskParamlabels(1) = "On/Off" ' puls-pause proportion TaskParamlabels(2) = "velo" TaskParamlabels(3) = "release" TaskParamLabels(4) = "Note" ' note IF ISFALSE Task(%Pi2_Test).hParam THEN slnr = %False MakeTaskParameterDialog %Pi2_Test,4,Slider(),1,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(%Pi2_Test).SliderNumbers(0) UDctrl(TaskEX(%Pi2_Test).UpdownNumbers(0)).cptr = CODEPTR(Pi2_Note_UD1) i = 72 UDctrl(TaskEX(%Pi2_Test).UpDownNumbers(0)).value = i Task(%Pi2_Test).freq = 2 Slider(slnr).value = Task(%Pi2_Test).freq SendMessage Slider(Slnr).h, %TBM_SETPOS,%True, Slider(Slnr).value Slider(slnr+1).value = 64 SendMessage Slider(Slnr+1).h, %TBM_SETPOS,%True, 64 ' mid position END IF j = %False Controller Pi2_.channel, 66, 64 Task(%Pi2_Test).tog = %True EXIT SUB END IF OnOff = Slider(slnr+1).value / 128 ' 0- 0.99218 IF OnOff < 0.0078 THEN OnOff = 0.0078125 period = 1! / (32! * ((Slider(slnr).value+1) / 128!)) ' tempo - duur in sekonden. IF ISFALSE j THEN mPlay Pi2_.channel, i, Slider(slnr+2).value period = period * OnOff ELSE Release Pi2_.channel, i, Slider(slnr+3).value ' allways overrides ctrl #19 i = UDctrl(TaskEX(%Pi2_Test).UpDownNumbers(0)).value period = period * (1! - OnOff) END IF Task(%Pi2_Test).freq = MAX(MIN(1! / period, 1000),1) INCR j j = j MOD 2 END SUB SUB Pi2_Note_UD1 () ' controls the note to be played. LOCAL noot AS BYTE LOCAL udnr AS DWORD udnr = TaskEX(%Pi2_Test).UpDownNumbers(0) noot = UDCtrl(udnr).value IF noot < 72 THEN UDctrl(udnr).value = 72 : noot = 72 IF noot > 101 THEN UDctrl(udnr).value = 101 : noot = 101 SetDlgItemText Task(%Pi2_Test).hparam, %GMT_TEXT0_ID + 16, "n=" & STR$(noot) END SUB '[eof]