' *************************************************** ' * < V I B I > * ' * an automated vibraphone by Godfried-Willem Raes * ' *************************************************** ' 16.09.2001: first creation of this module. ' 05.10.2001: Hardware tests with all pc boards. ' 09.10.2001: Vibi played its very first scales... ' 12.10.2001: new vibi_holdup added in dll. ' 22.10.2001: afgewerkt. ' 05.11.2001: tests on handshaking hardware ' 11.11.2001: composed. - commisioned by Paul Koek. ' 14.11.2001: this piece expanded to become for 5 to 6 automats and optional musicians ' 19.11.2001: ready. ' 20.11.2001: changing cockpit implemented. (changed in DLL) ' 10.02.2002: to be changed: use only pointer to vibi structure here! ' 21.06.2002: all code for paradiso moved to technofaustus... ' 22.06.2002: This now is the version integrated in the roboko compilation. ' 12.12.2002: Code runs on Vaio - Windows 2000 ' 05.05.2003: slight revisions. ' 11.10.2003: Ported to V7.2 ' 24.07.2004: midi in upgraded for better speed performance. ' 29.01.2005: start calculations and coding for pure midi implementation of vibi. ' 30.01.2005: recoded for midi implementation - hardware version now in vibi.inc ' 02.02.2005: Vibi now works as midi robot. Some adjusting work needed on velo scaling. ' holdup mode and controllers still to be implemented. ' 28.06.2005: hardware revised. %vbt0 = 32 ' start-up task for ' following tasks may be overwritten: (They are created only when needed) %vbt1 = 17 ' 'Vibes' for 5 tasks: 18,19,20,21,22 - %vbt2 = %vbt1 + 1 ' can be used as environmental music, musique d'ameublement. %vbt3 = %vbt1 + 2 %vbt4 = %vbt1 + 3 %vbt5 = %vbt1 + 4 ' motor task for 'Vibes' for . %vbt6 = %vbt1 + 5 ' piperola & harma task... DECLARE FUNCTION Init_Vibi () AS LONG DECLARE SUB Vibi_Start_Button () DECLARE SUB Vibi_Motoren_Test () ' task 48 DECLARE SUB Vibi_Motor0_CB () ' slider callback motor 0 DECLARE SUB Vibi_Motor1_CB () ' slider callback motor 1 DECLARE SUB Vibi_Scale_Test () ' task 49 DECLARE SUB Vibi_Holdup_Test () ' task 50 DECLARE SUB Vibi_Repeat_Test () ' task 51 DECLARE SUB Vibi_ScaleDamp_Test () ' task 52 DECLARE SUB Vibi_t0 () DECLARE SUB Vibi_t1 () DECLARE SUB Vibi_t2 () DECLARE SUB Vibi_t3 () DECLARE SUB Vibi_t4 () DECLARE SUB Vibi_t5 () DECLARE SUB Vibi_t6 () DECLARE SUB Vibes_Start () DECLARE SUB Vibes_Stop () FUNCTION Init_Vibi () AS LONG LOCAL note AS BYTE LOCAL retval AS LONG LOCAL m AS ASCIIZ * 30 LOCAL CockpitLayo AS CockpitLabels ReadCockpitLabelsFromFile $VibiIni, CockpitLayo ' vibes for Task(%vbt0).naam = "" Task(%vbt0).cptr = CODEPTR(Vibi_t0) Task(%vbt0).freq = 5 Task(%vbt0).Har.vel = STRING$(128,0) TaskEX(%vbt0).startCptr = CODEPTR(Vibes_Start) ' creates the cockpit TaskEX(%vbt0).stopCptr =CODEPTR(Vibes_Stop) ' hardware testcode: Task(48).freq = 50 Task(48).naam = "Motors" Task(48).cptr = CODEPTR(Vibi_Motoren_Test) Task(49).freq = 47 Task(49).naam ="Scales" Task(49).cptr = CODEPTR(Vibi_Scale_Test) Task(50).freq = 48 Task(50).naam ="HoldUp" Task(50).cptr = CODEPTR(Vibi_Holdup_Test) Task(51).freq = 4 Task(51).naam ="Repeat" Task(51).cptr = CODEPTR(Vibi_Repeat_Test) Task(52).freq = 30 Task(52).naam = "ScalDamp" Task(52).cptr = CODEPTR(Vibi_ScaleDamp_Test) ' end hardware testcode. 'delete unnecessary buttons IF ISFALSE hMidiI(0) THEN ButnSW(0).tag0 = "" ButnSW(0).cptr = %False END IF IF ISFALSE hMidiO(0) THEN ButnOS(0).tag = "" ButnOS(0).cptr = %False END IF ButnSW(1).tag0 = "START" ButnSW(1).tag1 = "STOP" ButnSW(1).cptr = CODEPTR(Vibi_Start_Button) ButnSW(2).tag0 = "" ButnSW(3).tag0 = "" ButnSW(4).tag0 = "" ' ButnSW(5).tag0 = "" '- melody window needed for paradiso ButnSW(6).tag0 = "" ButnSW(7).tag0 = "" ButnSW(8).tag0 = "" ButnSW(9).tag0 = "" ButnSW(10).tag0 = "" IF hMidiO(0) THEN ButnSW(11).tag0 = "MiSim" ButnSW(11).tag1 = "MiSimOff" ButnSW(11).cPtr = CODEPTR(Vibi_Midi_Sim) ELSE ButnSW(11).tag0 = "" END IF ButnOS(10).tag ="" '"N-Off" 'ButnOS(10).cptr = %False 'CODEPTR(Vibi_AllNotesOff) ButnOS(11).tag ="" '"D-Off" 'ButnOS(11).cptr = %False 'CODEPTR(Vibi_AllDampersOff) App.id = %IDM_VIBI ' return true if init successfull: FUNCTION = %True END FUNCTION SUB Vibi_Start_Button () STATIC tog AS BYTE IF ButnSW(1).Flag THEN SetDlgItemText gh.Cockpit, App.butnSWparam, "Stop" App.MTstart = %True IF ISFALSE tog THEN IF hMidiI(0) THEN ClearMiBuf 0 ' start with a blank midi input buffer BlockSysExReception hMidiI(0) ' SxThread END IF App.tstart = timeGetTime ' start the chronometerfunction Runtime %True tog = %True Controller Vibi.channel, 66, 127 Vibi.ctrl(66) = %True SLEEP 10 END IF ELSE App.MTstart = %False SetDlgItemText gh.Cockpit, App.butnSWparam, "Cont" END IF END SUB SUB Vibi_Midi_Sim () ' implemented only for Paradiso. IF ButnSW(11).Flag THEN ' Vibi.simulator = %KlungSimMid ProgChange Vibi.channel,%ID_VIBRAPHONE ' gm patch SetDlgItemText gh.Cockpit, App.butnSWparam, "MidiOFF" ELSE 'Vibi.simulator = %False SetDlgItemText gh.Cockpit, App.butnSWparam, "Midi ON" END IF END SUB ' tests for hardware: SUB Vibi_Motoren_Test () STATIC NrSl AS LONG STATIC id AS LONG STATIC oldspeed0 AS BYTE STATIC oldspeed1 AS BYTE STATIC slnr() AS INTEGER STATIC TaskParamLabels() AS ASCIIZ*8 LOCAL i AS LONG IF ISFALSE NrSL THEN id = 48 ' tasknumber NrSl = 2 DIM Slnr(0 TO 1) AS STATIC INTEGER DIM TaskParamLabels(0 TO 1) AS STATIC ASCIIZ*8 TaskParamLabels(0)="Mot0" TaskParamLabels(1)="Mot1" IF Task(id).hParam = %Null THEN MakeTaskParameterDialog BYVAL id,NrSl, Slider(),0,UdCtrl(), TaskParamLabels() END IF FOR i = 0 TO 1 slnr(i) = TaskEX(id).SliderNumbers(i) 'get slidernumber given in GMT-code Slider(Slnr(i)).value = 0 SendMessage Slider(Slnr(i)).h, %TBM_SETPOS,%True, Slider(Slnr(i)).value NEXT Slider(Slnr(0)).cptr = CODEPTR(Vibi_Motor0_CB) Slider(Slnr(1)).cptr = CODEPTR(Vibi_Motor1_CB) END IF Task(id).freq = 0.1 END SUB SUB Vibi_Motor0_CB () LOCAL slnr AS DWORD 'id = 48 ' tasknumber slnr = TaskEX(48).SliderNumbers(0) Controller Vibi.channel, 20, Slider(slnr).value END SUB SUB Vibi_Motor1_CB () LOCAL slnr AS DWORD slnr = TaskEX(48).SliderNumbers(1) Controller Vibi.channel, 21, Slider(slnr).value END SUB SUB Vibi_Scale_Test () ' using damper-pulse coding. STATIC id AS INTEGER STATIC note AS BYTE LOCAL n AS BYTE LOCAL i AS LONG LOCAL velo AS BYTE STATIC tim AS DWORD STATIC timvals() AS DWORD STATIC slnr() AS INTEGER IF ISFALSE id THEN id = 49 ' tasknumber Task(id).har.vel = STRING$(128,0) note = 60 DIM timvals(60 TO 97) AS STATIC DWORD ' create sliders: DIM Slnr(0 TO 3) AS STATIC INTEGER DIM TaskParamLabels(0 TO 3) AS STATIC ASCIIZ*8 TaskParamLabels(0)="Velo" ' attack force for beaters TaskParamLabels(1)="Duur" ' duration for sustained notes, time before damping TaskParamLabels(2)="Damp" ' damping force TaskParamLabels(3)="Freq" ' speed IF Task(id).hParam = %Null THEN MakeTaskParameterDialog BYVAL id,4, Slider(),0,UdCtrl(), TaskParamLabels() END IF FOR i = 0 TO 3 slnr(i) = TaskEX(id).SliderNumbers(i) 'get slidernumber given in GMT-code Slider(Slnr(i)).value = 0 SendMessage Slider(Slnr(i)).h, %TBM_SETPOS,%True, Slider(Slnr(i)).value NEXT ' send midi controller for this playing mode: controller Vibi.channel, 24, %True ' enable note off + release controller Vibi.channel, 64, %False ' sustain off END IF tim = Timegettime velo = Slider(slnr(2)).value FOR n = 60 TO 96 IF timvals(n) THEN IF tim > timvals(n) THEN IF velo THEN 'Vibi_Damp n, velo Release Vibi.channel, n, velo DelNote2Har Task(id).har, n Timvals(n) = %False END IF END IF END IF NEXT n ' note on's: velo = Slider(Slnr(0)).value IF velo THEN AddNote2Har Task(id).Har, note, velo 'Vibi_Beat note, velo Play Vibi.channel, note, velo Timvals(note) = tim + (Slider(Slnr(1)).value * 20) ' in milliseconds - range: 1/Task().freq to 2.5 sec. ELSE Timvals(note) = %False END IF INCR note IF note > 96 THEN note = 60 Task(id).freq = Slider(Slnr(3)).value / 4! IF Task(id).freq < 0.2 THEN Task(id).freq = 0.2 END SUB SUB Vibi_ScaleDamp_Test () ' task 52 STATIC id AS INTEGER STATIC note AS BYTE LOCAL n AS BYTE LOCAL i AS LONG LOCAL velo AS BYTE LOCAL dempduur AS BYTE STATIC tim AS DWORD STATIC timvals() AS DWORD STATIC slnr() AS INTEGER IF ISFALSE id THEN id = 52 ' tasknumber Task(id).har.vel = STRING$(128,0) note = 60 DIM timvals(60 TO 97) AS STATIC DWORD ' create sliders: DIM Slnr(0 TO 4) AS STATIC INTEGER DIM TaskParamLabels(0 TO 4) AS STATIC ASCIIZ*8 TaskParamLabels(0)="Velo" ' attack force for beaters TaskParamLabels(1)="Duur" ' duration for sustained notes, time before damping TaskParamLabels(2)="Damp" ' damping force TaskParamLabels(3)="Dtim" ' damping time TaskParamLabels(4)="Freq" ' speed IF Task(id).hParam = %Null THEN MakeTaskParameterDialog BYVAL id,5, Slider(),0,UdCtrl(), TaskParamLabels() END IF FOR i = 0 TO 4 slnr(i) = TaskEX(id).SliderNumbers(i) 'get slidernumber given in GMT-code Slider(Slnr(i)).value = 0 SendMessage Slider(Slnr(i)).h, %TBM_SETPOS,%True, Slider(Slnr(i)).value NEXT END IF tim = Timegettime velo = Slider(slnr(2)).value dempduur = Slider(slnr(3)).value FOR n = 60 TO 96 IF timvals(n) THEN IF tim > timvals(n) THEN IF velo THEN 'Vibi_HoldUp n, velo, dempduur ' not yet implemented on PIC's Release Vibi.channel, n, velo DelNote2Har Task(id).har, n Timvals(n) = %False ELSE DelNote2Har Task(id).har,n Timvals(n) = %False END IF END IF END IF NEXT n ' note on's: velo = Slider(Slnr(0)).value tim = Timegettime IF velo THEN AddNote2Har Task(id).Har, note, velo 'Vibi_Beat note, velo Play Vibi.channel, note, velo Timvals(note) = tim + (Slider(Slnr(1)).value * 20) ' in milliseconds - range: 1/Task().freq to 2.5 sec. ELSE Timvals(note) = %False END IF INCR note IF note > 96 THEN note = 60 Task(id).freq = Slider(Slnr(4)).value / 4! IF Task(id).freq < 0.2 THEN Task(id).freq = 0.2 END SUB SUB Vibi_Holdup_Test () ' test voor de demper hold's STATIC id AS INTEGER STATIC note AS BYTE LOCAL i AS BYTE IF ISFALSE id THEN id = 50 ' tasknumber Task(id).har.vel = STRING$(128,0) note = 60 ' create sliders: DIM Slnr(0 TO 2) AS STATIC INTEGER DIM TaskParamLabels(0 TO 2) AS STATIC ASCIIZ*8 TaskParamLabels(0)="Force" ' pushing force for dampers TaskParamLabels(1)="Duur" ' pushing time for dampers TaskParamLabels(2)="Freq" IF Task(id).hParam = %Null THEN MakeTaskParameterDialog BYVAL id,3, Slider(),0,UdCtrl(), TaskParamLabels() END IF FOR i = 0 TO 2 slnr(i) = TaskEX(id).SliderNumbers(i) 'get slidernumber given in GMT-code Slider(Slnr(i)).value = 0 SendMessage Slider(Slnr(i)).h, %TBM_SETPOS,%True, Slider(Slnr(i)).value NEXT warning "This is not yet implemented on the vibi PIC!", 5000 END IF ' Vibi_HoldUp note, Slider(Slnr(0)).value, Slider(slnr(1)).value not yet implemented INCR note IF note > 96 THEN note = 60 Task(id).freq = Slider(Slnr(2)).value / 12! IF Task(id).freq < 4 THEN Task(id).freq = 4 END SUB SUB Vibi_Repeat_Test () ' test for maximum repeat frequency on individual notes. STATIC id AS INTEGER LOCAL note AS BYTE LOCAL velo AS BYTE LOCAL i AS LONG IF ISFALSE id THEN id = 51 ' tasknumber ' create sliders: DIM Slnr(0 TO 2) AS STATIC INTEGER DIM TaskParamLabels(0 TO 2) AS STATIC ASCIIZ*8 TaskParamLabels(0)="Note" ' note for iteration TaskParamLabels(1)="Velo" TaskParamLabels(2)="Freq" IF Task(id).hParam = %Null THEN MakeTaskParameterDialog BYVAL id,3, Slider(),0,UdCtrl(), TaskParamLabels() END IF FOR i = 0 TO 2 slnr(i) = TaskEX(id).SliderNumbers(i) 'get slidernumber given in GMT-code Slider(Slnr(i)).value = 0 SendMessage Slider(Slnr(i)).h, %TBM_SETPOS,%True, Slider(Slnr(i)).value NEXT END IF Task(id).freq = Slider(Slnr(2)).value / 8! ' tot 16Hz IF Task(id).freq < 1 THEN Task(id).freq = 1 note = Slider(Slnr(0)).value IF note THEN note = 60 + (note MOD 38) ELSE EXIT SUB END IF velo = Slider(Slnr(1)).value IF velo THEN Play Vibi.channel, note, velo ' no damping. ELSE EXIT SUB END IF END SUB SUB Vibi_t0 () ' meta-task for by Godfried-Willem Raes, october 2001. STATIC denscnt AS BYTE STATIC dynacnt AS BYTE LOCAL seconds AS DWORD IF ISFALSE Task(%vbt0).tog THEN IF Task(%vbt1).tog THEN stoptask %vbt1 IF Task(%vbt2).tog THEN stoptask %vbt2 IF Task(%vbt3).tog THEN stoptask %vbt3 IF Task(%vbt4).tog THEN stoptask %vbt4 IF Task(%vbt5).tog THEN stoptask %vbt5 Slider(0).tag = "Dens" Slider(1).tag = "Dyna" SetDlgItemText gh.Cockpit, %GMT_TEXT_SLIDER0, Slider(0).tag SetDlgItemText gh.Cockpit, %GMT_TEXT_SLIDER1, Slider(1).tag Slider(0).value = 1 denscnt = 1 SendMessage Slider(0).h, %TBM_SETPOS,%True, Slider(0).value Slider(1).value = 10 dynacnt = 10 SendMessage Slider(1).h, %TBM_SETPOS,%True, Slider(1).value SetDlgItemText gh.Cockpit, %GMT_MSG1, " for vibi, harma and piperola" App.komposduur = 390'was 675 = 11'25" Task(%vbt0).tog = %True App.tstart = timeGetTime Runtime %True EXIT SUB END IF Task(%vbt0).freq = 0.15 ' scoring for automatic build up at start and stop... seconds = ((timegettime-App.tstart) \ 1000) SELECT CASE seconds CASE >= App.Komposduur '675 StopTask %vbt0 EXIT SUB 'IF hMidi(0) THEN ' IF Task(%vbt6).tog THEN stoptask %vbt6 'END IF CASE >= App.Komposduur * 0.98518 '665 IF task(%vbt1).tog THEN stoptask %vbt1 task(%vbt0).freq = 1.5 CASE > = App.Komposduur * 0.9674 '653 IF task(%vbt2).tog THEN stoptask %vbt2 task(%vbt0).freq = 1.1 CASE >= App.Komposduur * 0.9451 '638 IF task(%vbt3).tog THEN stoptask %vbt3 Task(%vbt0).freq = 0.9 CASE >= App.Komposduur * 0.91852 '620 IF task(%vbt4).tog THEN stoptask %vbt4 Task(%vbt0).freq = 0.6 CASE >= App.Komposduur * 0.8888 '600 IF task(%vbt5).tog THEN stoptask %vbt5 Task(%vbt0).freq = 0.6 CASE >= App.Komposduur * 0.22222'150 Task(%vbt0).freq = seconds / App.Komposduur 'was: (seconds/1000) '0.15Hz to 0.6Hz CASE >= App.Komposduur * 0.1 '67 IF ISFALSE Task(%vbt5).tog THEN starttask %vbt5 CASE >= App.Komposduur * 0.08148 '55 IF ISFALSE Task(%vbt4).tog THEN starttask %vbt4 CASE >= App.Komposduur * 0.058259 '40 IF ISFALSE Task(%vbt3).tog THEN starttask %vbt3 CASE >= App.Komposduur * 0.0326 '22 IF hMidiO(0) THEN IF ISFALSE Task(%vbt6).tog THEN starttask %vbt6 END IF IF ISFALSE Task(%vbt2).tog THEN starttask %vbt2 CASE > =0 IF ISFALSE Task(%vbt1).tog THEN starttask %vbt1 END SELECT dynacnt = (seconds \2) AND &H7F ' was (seconds \ 3) AND &H7F ' - minumum duration for 1 cycle = 381" = 6'21" IF dynacnt < 2 THEN dynacnt = 2 denscnt = (seconds \3) AND &H7F ' was (seconds \ 5) AND &H7F ' - minimum duration for 1 cycle = 635" = 10'35" IF denscnt <1 THEN denscnt = 1 IF Slider(0).value <> denscnt THEN slider(0).value = denscnt SendMessage Slider(0).h, %TBM_SETPOS,%True, Slider(0).value END IF IF Slider(1).value <> dynacnt THEN slider(1).value = dynacnt SendMessage Slider(1).h, %TBM_SETPOS,%True, Slider(1).value END IF END SUB SUB Vibes_Start () Runtime %False ' creates the cockpit tasks on startup Task(%vbt1).naam = "ViTim1" Task(%vbt1).freq = 1 Task(%vbt1).cptr = CODEPTR(Vibi_t1) Task(%vbt1).Har.vel = STRING$(128,0) Task(%vbt2).naam = "ViTim2" Task(%vbt2).freq = 1 Task(%vbt2).cptr = CODEPTR(Vibi_t2) Task(%vbt2).Har.vel = STRING$(128,0) Task(%vbt3).naam = "ViTim3" Task(%vbt3).freq = 1 Task(%vbt3).cptr = CODEPTR(Vibi_t3) Task(%vbt3).Har.vel = STRING$(128,0) Task(%vbt4).naam = "ViTim4" Task(%vbt4).freq = 1 Task(%vbt4).cptr = CODEPTR(Vibi_t4) Task(%vbt4).Har.vel = STRING$(128,0) Task(%vbt5).naam = "ViMots" Task(%vbt5).freq = 1 Task(%vbt5).cptr = CODEPTR(Vibi_t5) Task(%vbt5).Har.vel = STRING$(128,0) IF hMidiO(0) THEN ' for harma & piperola in Task(%vbt6).naam = "PipHar" Task(%vbt6).freq = 3 Task(%vbt6).cptr = CODEPTR(Vibi_t6) Task(%vbt6).Har.vel = STRING$(128,0) Task(%vbt6).flags = %MIDI_TASK END IF ChangeCockpitTasks %vbt0 END SUB SUB Vibes_Stop () ' stopcode for IF Task(%vbt1).tog THEN stoptask %vbt1 IF Task(%vbt2).tog THEN stoptask %vbt2 IF Task(%vbt3).tog THEN stoptask %vbt3 IF Task(%vbt4).tog THEN stoptask %vbt4 IF Task(%vbt5).tog THEN stoptask %vbt5 IF hMidiO(0) THEN IF task(%vbt6).tog THEN stoptask %vbt6 MM_PIperola_Off %MM_Notes MM_Harma_Off %MM_Notes END IF END IF Slider(0).tag = "---" Slider(1).tag = "---" SetDlgItemText gh.Cockpit, %GMT_TEXT_SLIDER0, Slider(0).tag SetDlgItemText gh.Cockpit, %GMT_TEXT_SLIDER1, Slider(1).tag ' delete the tasks from the cockpit: Task(%vbt1).naam = "" Task(%vbt1).cptr = %False Task(%vbt2).naam = "" Task(%vbt2).cptr = %False Task(%vbt3).naam = "" Task(%vbt3).cptr = %False Task(%vbt4).naam = "" Task(%vbt4).cptr = %False Task(%vbt5).naam = "" Task(%vbt5).cptr = %False Task(%vbt6).naam = "" Task(%vbt6).cPtr = %False ChangeCockpitTasks -1 '%vbt0 ' parameter= calling task, otherwize the check in the task gets lost. runtime %False END SUB SUB Vibi_t1 () LOCAL demping AS BYTE LOCAL note AS BYTE LOCAL velo AS BYTE STATIC oldnote AS BYTE STATIC oldvelo AS BYTE IF ISFALSE task(%vbt1).tog THEN task(%vbt1).tog = %True DO note = 60 + (RND(1) * 37) IF IsNoteInHar (Task(%Vbt1).Har, note) THEN note = %False LOOP UNTIL note > %False demping = 60 + (oldvelo /2) IF oldnote THEN 'Vibi_HoldUp oldnote, demping, 64 ' not yet implemented Release Vibi.channel, oldnote, demping ' replacement... DelNote2Har Task(%Vbt1).Har, oldnote oldnote = %False END IF Velo = 1 + (RND(1) * Slider(1).value) '120) ' cockpit slider 1 = dynamics IF Velo > 127 THEN velo = 127 Play Vibi.channel, note, velo AddNote2Har Task(%Vbt1).Har, note, velo oldnote = note oldvelo = velo Task(%vbt1).Freq = 0.05 + (RND(1) * Slider(0).value / 32!) '2) ' cockpit slider 0 = density END SUB SUB Vibi_t2 () LOCAL demping AS BYTE LOCAL note AS BYTE LOCAL velo AS BYTE STATIC oldnote AS BYTE IF ISFALSE task(%vbt2).tog THEN task(%vbt2).tog = %True DO note = 60 + (RND(1) * 37) IF IsNoteInHar (Task(%Vbt1).Har, note) THEN note = %False LOOP UNTIL note > %False demping = 18 + (RND(1) * 80) IF oldnote THEN 'Vibi_HoldUp oldnote, demping, 64 Release Vibi.channel, oldnote, demping DelNote2Har Task(%Vbt1).Har, oldnote oldnote = %False END IF Velo = 1 + (RND(1) * Slider(1).value) '126) IF velo > 127 THEN velo = 127 Play Vibi.channel, note, velo AddNote2Har Task(%Vbt1).Har, note, velo oldnote = note Task(%vbt2).Freq = 0.05 + (RND(1) * Slider(0).value/ 32!) '* 2) END SUB SUB Vibi_t3 () LOCAL demping AS BYTE LOCAL note AS BYTE LOCAL velo AS BYTE STATIC oldnote AS BYTE IF ISFALSE task(%vbt3).tog THEN task(%vbt3).tog = %True DO note = 60 + (RND(1) * 37) IF IsNoteInHar (Task(%Vbt1).Har, note) THEN note = %False LOOP UNTIL note > %False demping = 18 + (RND(1) * 64) IF oldnote THEN 'Vibi_HoldUp oldnote, demping ,64 Release Vibi.channel, oldnote, demping DelNote2Har Task(%Vbt1).Har, oldnote oldnote = %False END IF Velo = 1 + (RND(1) * Slider(1).value) '126) IF velo > 127 THEN velo = 127 Play Vibi.channel, note, velo AddNote2Har Task(%Vbt1).Har, note, velo oldnote = note Task(%vbt3).Freq = 0.05 + (RND(1) * Slider(0).value / 32!) '2) END SUB SUB Vibi_t4 () LOCAL demping AS BYTE LOCAL note AS BYTE LOCAL velo AS BYTE STATIC oldnote AS BYTE IF ISFALSE task(%vbt4).tog THEN task(%vbt4).tog = %True DO note = 60 + (RND(1) * 37) IF IsNoteInHar (Task(%Vbt1).Har, note) THEN note = %False LOOP UNTIL note > %False demping = 16 + (RND(1) * 80) IF oldnote THEN 'Vibi_HoldUp oldnote, demping ,64 Release Vibi.channel, oldnote, demping DelNote2Har Task(%Vbt1).Har, oldnote oldnote = %False END IF Velo = 1 + (RND(1) * Slider(1).value) '126) IF velo > 127 THEN velo =127 Play Vibi.channel, note, velo AddNote2Har Task(%Vbt1).Har, note, velo oldnote = note Task(%vbt4).Freq = 0.05 + (RND(1) * Slider(0).value / 32!) '2) END SUB SUB Vibi_t5 () ' motor control task... LOCAL n AS BYTE LOCAL nrdiat AS BYTE LOCAL nrkrom AS BYTE STATIC oldkrom AS BYTE STATIC olddiat AS BYTE IF ISFALSE task(%vbt5).tog THEN task(%vbt5).tog = %True FOR n = 60 TO 96 SELECT CASE n MOD 12 CASE 0,2,4,5,7,9,11 IF IsNoteInHar (Task(%Vbt1).Har, n) THEN INCR nrdiat CASE ELSE IF IsNoteInHar (Task(%Vbt1).Har, n) THEN INCR nrkrom END SELECT NEXT n IF nrdiat <> olddiat THEN Controller Vibi.channel, 20, RND(1) * 127 '00 olddiat = nrdiat END IF IF nrkrom <> oldkrom THEN Controller Vibi.channel, 21, RND(1) * 127 '00 oldkrom = nrkrom END IF Task(%vbt5).freq = 1.5 + RND(1) END SUB SUB Vibi_t6 () ' piperola & harma task - plays the difference tones between the strongest 2 vibraphone pitches. ' we also use harma, for fractional pitches here... LOCAL note AS INTEGER LOCAL pipflag AS BYTE LOCAL notefrac AS SINGLE STATIC note1 AS BYTE ' oldnote for piperola STATIC note2 AS BYTE ' oldnote for Harma LOCAL nv AS INTEGER LOCAL hi_note AS BYTE LOCAL hi_velo AS BYTE LOCAL lo_note AS BYTE LOCAL lo_velo AS BYTE LOCAL dif AS SINGLE STATIC pipduur AS DWORD STATIC harduur AS DWORD IF ISFALSE Task(%vbt6).tog THEN Task(%vbt6).channel = 2 Task(%vbt6).tog = %True Task(%vbt6).freq = 4 ProgChange Harma.channel,&B00001111 MM_Harma_On %MM_Motor Controller Harma.channel,7,8 ' motor low value MM_Piperola_ON %MM_Motor END IF IF Pipduur THEN IF TimegetTime > Pipduur THEN noteoff Piperola.channel, note1 note1 = %False pipduur = %False END IF END IF IF Harduur THEN IF timegetTime > Harduur THEN ' note off harma noteoff Harma.channel, note2 note2 = %False Harduur = %False END IF END IF Task(%vbt6).Har.vel = Task(%vbt1).Har.vel FillHarType Task(%vbt6).Har fillHarType Task(%vbt1).har note = GetStrongest(Task(%vbt1).Har,1) ' returns 0-11 IF note = -1 THEN EXIT SUB DelShNo2Har Task(%vbt6).Har,note fillHarType Task(%vbt6).Har note = GetStrongest(Task(%vbt6).Har,1) IF note = -1 THEN EXIT SUB DelShNo2Har Task(%vbt6).Har,note fillHarType Task(%vbt6).Har Task(%vbt5).har.vel = CommonHar$(Task(%vbt1).Har,Task(%vbt6).Har) ' this now contains only the weakest notes... Task(%vbt6).Har.vel = AbsDifHar$(Task(%vbt1).Har,Task(%vbt5).Har) ' returns the notes in vbt1 that are NOT also in vbt5 ' so now we should have isolated the 2 strongest notes in their original position... ' lets now retrieve these two notes: nv = GetHighestNote (Task(%vbt6).Har,60,96) IF nv = -1 THEN EXIT SUB ELSE hi_note = HIBYT(nv) hi_velo = LOBYT(nv) DelNote2Har Task(%vbt6).Har, hi_note END IF nv = GetHighestNote (Task(%vbt6).Har,60,96) IF nv = -1 THEN EXIT SUB ELSE lo_note = HIBYT(nv) lo_velo = LOBYT(nv) 'DelNote2Har Task(%vbt6).Har, lo_note END IF dif = DifTone(hi_note,lo_note) IF dif = %False THEN EXIT SUB notefrac = F2NF(dif) IF notefrac =< %False THEN EXIT SUB SELECT CASE notefrac CASE < piperola.lowtes pipflag = %False note = FIX(notefrac) CASE ELSE SELECT CASE FRAC(notefrac) CASE < 0.25 '33 note = FIX(notefrac) pipflag = %True CASE > 0.75 '66 note = FIX(notefrac) + 1 pipflag = %True CASE ELSE ' quartertones for harma... note = FIX(notefrac) + 1 pipflag = %False END SELECT END SELECT IF pipflag THEN IF note > piperola.hightes THEN DO note = note - 12 LOOP UNTIL note < piperola.hightes END IF IF note < piperola.lowtes THEN DO note = note + 12 LOOP UNTIL note > piperola.lowtes END IF ELSE ' harma case... ' here we can use the average velo value to steer the motor! IF note > Harma.hightes THEN DO note = note - 12 LOOP UNTIL note < Harma.hightes END IF IF note < Harma.lowtes THEN DO note = note + 12 LOOP UNTIL note > Harma.lowtes END IF END IF IF note1 THEN IF note <> note1 THEN noteoff Piperola.channel,note1 note1 = %False ELSE EXIT SUB END IF END IF IF note2 THEN IF note <> note2 THEN noteoff Harma.channel, note2 note2 = %False ELSE EXIT SUB END IF END IF IF pipflag THEN IF note <> note1 THEN Play Piperola.channel,note,64 pipduur = Timegettime + 150 + (RND(1) * 3000) note1 = note END IF ELSE Modemess Harma.channel,7,(lo_velo + hi_velo)/ 2 ' motor pressure IF note <> note2 THEN Play Harma.channel,note,MAX(lo_velo,hi_velo) IF note < 48 THEN harduur = TimegetTime + 1000 + (RND(1) * 6000) ELSE harduur = Timegettime + 500 + (RND(1) * 4000) END IF note2 = note END IF END IF Task(%vbt6).freq = 4 END SUB '[EOF]