' ************************************************* ' * * ' * for clarinet and interactive robot(s) * ' * 2010 * ' * Godfried-Willem RAES * ' * A composition commissioned by * ' * Daniel Pastene * ' ************************************************* ' 05.06.2001 started off from Lickstick code framework. ' 29.07.2001 cannot be compiled without LickStick ! ' 13.06.2002 adapted to version 5.82 ' 11.10.2003 adepted to version 7.20 ' 27.03.2005 adapted to PBWIN8.0 ' 03.10.2006: adapted to new paths for audiofiles ' 26.01.2010: Based on the original code, Woodstock_Jazz is written for Daniel Pastene ' for the Jazz&Sounds Festival, march 2010. ' Output is on the M&M robots. ' 25.02.2010: Further modification of code in order to use it for Jazz&Sounds ' 5.03.2010: listen task now working.. but without proper initialisation, CQT produces nonsense! %WoodstockJazz_Score_Task = 17 %WoodstockJazz_V1_Task = 25 ' Voice 1 / Stimme 1 %WoodstockJazz_V2_Task = 26 ' Voice 2 / Stimme 2 #IF NOT %DEF(%Pattern1_Task) %Pattern1_Task = 28 ' Formula 1 %Pattern2_Task = 29 ' Formula 2 %Pattern3_Task = 30 ' Formula 3 #ENDIF '%ClarDetune_Task = 32 ' delay line 1 ' as in cellopi, lickstick and Woodstock %InvFast_Task = 33 ' midi delay line players %BackInv_Task = 34 %BackSlow_Task = 35 %Gerade_Task = 36 ' straight delay line ' '%LS_RingModulator_Task = %AudioRingModulator_Task ' =53 specific for LickStick/WoodStock '%LS_PitchShift_Task = %AudioVarspeed_Task ' =56 split off from %AudioProcess Task 07.03.2000 GLOBAL Clarinet AS MUSICIAN DECLARE FUNCTION InitWoodStockJazz () AS LONG 'DECLARE SUB WoodstockJazzInitSynth () DECLARE SUB ButnSW_WoodstockJazzStartStop () DECLARE SUB WoodstockJazzScore() DECLARE SUB WoodstockJazzListen () ' midi input listening task DECLARE SUB WoodstockJazzPatternAlgo (pattern AS BYTE) ' input score calculation DECLARE SUB SetJazzContext (noot?, velo?) ' as in cellopi DECLARE SUB WoodstockJazzDoEvent () ' interactive score ' following is borrowed from Lickstick module... 'DECLARE SUB GetLastNote(noot?, velo?, Instrument AS musician) ' generalized version to replace former individual procedures ' in Cellopi, Cohiba, Obotek, Toverfluit... DECLARE SUB WoodstockJazzPattern1 () ' Formel 1 DECLARE SUB WoodstockJazzPattern2 () ' Formel 2 DECLARE SUB WoodstockJazzPattern3 () ' Formel 3 ' borrowed from Lickstick: DECLARE SUB Woodstockjazz_Stock1 () ' stimme1 / voice1 / stick1 DECLARE SUB Woodstockjazz_Stock2 () ' audio tasks 'DECLARE SUB WoodstockJazzPitchShift () ' speeds up/down recorded sample 'DECLARE SUB WoodstockJazzPlaySample () ' plays prerecorded samples from disk - WoodstockJazzSpecific 'DECLARE SUB WoodstockJazzRingModulator () ' midi delaylines: 'DECLARE SUB ClarDetune() ' uses midi pitchshift DECLARE SUB WoodstockJazzDelayInvertFast () DECLARE SUB WoodstockJazzDelayBackInvert () DECLARE SUB WoodstockJazzDelayBackSlow () DECLARE SUB WoodstockJazzDelayPlayerNormal () ' generalizable: ' borrowed from lickstick module: DECLARE FUNCTION Woodstockjazz_GetDifferentPatternNote (PatternSeq() AS PatternSequenceType, pattern AS BYTE) AS INTEGER '------------------------------------------------------------------- FUNCTION InitWoodstockJazz () AS LONG LOCAL tasknr AS INTEGER LOCAL nr AS LONG LOCAL CockpitLayo AS CockpitLabels LOCAL i AS LONG FUNCTION = %False IF ISFALSE hMidiI(0) THEN ErrorMidiIn : EXIT FUNCTION IF ISFALSE hMidiO(0) THEN ErrorMidiOut : EXIT FUNCTION ' SelectMidiEquipment $WOODSTOCKINI, Meq() ' Update_MidiEquipment Meq() ReadPatternRecognitionDataFile $WOODSTOCKINI ' ReadSynthConfigFile $WOODSTOCKINI ,Meq() ' should know the Meq() selected!!! ReadCockpitLabelsFromFile $WOODSTOCKINI, CockpitLayo Recording_Available = %False ' false on init. - global variable GetInstrumentParams Clarinet, %ID_Clarinet Clarinet.channel = 0 ' midi input listening channel Clarinet.patch = %ID_Clarinet ' gm patch is 71 Recog.Cptr = CODEPTR(WoodstockJazzDoEvent) ' input recognition callback Init_MM MM_Panicbuttonwindow MM_Harmo_On ButnSW(1).tag0 = "START" ' start/stop toggle ButnSW(1).tag1 = "STOP" ButnSW(1).cptr = CODEPTR(ButnSW_WoodstockJazzStartStop) ' change the default routing !!! ButnSW(2).tag0 = "" ' "STAFF" ' creates/kills a music monitoring window ButnSW(3).tag0 = "" ' "USER" ' creates/kills a user feedback window ButnSW(7).tag0 = "" ButnSW(8).tag0 = "" ButnSW(9).tag0 = "" ButnSW(10).tag0 = "" ButnSW(11).tag0 = "" ' ONE SHOT FUNCTIONS: ButnOS(1).tag = "" ButnOS(2).tag = "" ButnOS(3).tag = "" ButnOS(4).tag = "" ButnOS(5).tag = "" ButnOS(6).tag = "" ButnOS(8).tag = "Clear" ' clears delay lines ButnOS(7).tag = "" ButnOS(9).tag = "" ButnOS(10).tag = "" ' declaration of specific tasks: Task(%Listen_Task).naam = "Listen" Task(%Listen_Task).freq = 30 Task(%Listen_Task).channel = &H0400 'Clarinet.channel Task(%Listen_Task).cptr = CODEPTR(WoodstockJazzListen) Task(%Listen_Task).starttime = 0 Task(%Listen_Task).stoptime = 1000 Task(%Listen_Task).Rit.minduur = Clarinet.minduur/1000 ' in ms in type Task(%Listen_Task).Rit.maxduur = Clarinet.maxduur/1000 Task(%Listen_Task).flags = Task(%Listen_Task).flags OR %MIDI_TASK OR %HARM_TASK OR %SCORE_TASK SetMidiListenChannel Task(%Listen_Task).channel, 1 InitP2M "GI10",Task(%Listen_Task).channel Task(%WoodstockJazz_Score_Task).naam = "Scoring" ' for automatic playing - scheduler Task(%WoodstockJazz_Score_Task).freq = 1 Task(%WoodstockJazz_Score_Task).tempo = 60 Task(%WoodstockJazz_Score_Task).cptr = CODEPTR(WoodstockJazzScore) Task(%WoodstockJazz_V1_Task).naam = "wStock 1" ' vertical harmony stimme 1 Task(%WoodstockJazz_V1_Task).cptr = CODEPTR(Woodstockjazz_Stock1) Task(%WoodstockJazz_V1_Task).freq = 1 Task(%WoodstockJazz_V1_Task).tempo = 20 Task(%WoodstockJazz_V1_Task).flags = Task(%WoodstockJazz_V1_Task).flags OR %MIDI_TASK OR %SCORE_TASK Task(%WoodstockJazz_V2_Task).naam = "wStock 2" ' vertical harmony stimme 2 Task(%WoodstockJazz_V2_Task).cptr = CODEPTR(Woodstockjazz_Stock2) Task(%WoodstockJazz_V2_Task).freq = 1 Task(%WoodstockJazz_V2_Task).tempo = 20 Task(%WoodstockJazz_V2_Task).flags = Task(%WoodstockJazz_V2_Task).flags OR %MIDI_TASK OR %SCORE_TASK Task(%Pattern1_Task).naam = "Formula1" Task(%Pattern1_Task).freq = 20 Task(%Pattern1_Task).tempo = 60 Task(%Pattern1_Task).cptr = CODEPTR(WoodstockJazzPattern1) Task(%Pattern1_Task).starttime = -1 Task(%Pattern1_Task).stoptime = 1000 Task(%Pattern1_Task).Rit.minduur = .035 Task(%Pattern1_Task).Rit.maxduur = 4 ' in s Task(%Pattern1_Task).flags = Task(%Pattern1_Task).flags OR %MIDI_TASK Task(%Pattern2_Task).naam = "Formula2" Task(%Pattern2_Task).freq = 30 Task(%Pattern2_Task).tempo = 61 Task(%Pattern2_Task).cptr = CODEPTR(WoodstockJazzPattern2) Task(%Pattern2_Task).starttime = -1 Task(%Pattern2_Task).stoptime = 1000 Task(%Pattern2_Task).Rit.minduur = .025 Task(%Pattern2_Task).Rit.maxduur = 4 ' in s Task(%Pattern2_Task).flags = Task(%Pattern2_Task).flags OR %MIDI_TASK Task(%Pattern3_Task).naam = "Formula3" Task(%Pattern3_Task).freq = 16 Task(%Pattern3_Task).tempo = 62 Task(%Pattern3_Task).cptr = CODEPTR(WoodstockJazzPattern3) Task(%Pattern3_Task).starttime = -1 Task(%Pattern3_Task).stoptime = 1000 Task(%Pattern3_Task).Rit.minduur = .045 Task(%Pattern3_Task).Rit.maxduur = 4 ' in s Task(%Pattern3_Task).flags = Task(%Pattern3_Task).flags OR %MIDI_TASK ' Task(%ClarDetune_Task).naam = "Detune" ' Task(%ClarDetune_Task).freq = 24 ' Task(%ClarDetune_Task).cptr = CODEPTR(ClarDetune) ' Task(%ClarDetune_Task).Rit.minduur = 0.035 ' in s ' Task(%ClarDetune_Task).Rit.maxduur = 5.000 ' in s ' Task(%ClarDetune_Task).flags = Task(%ClarDetune_Task).flags OR %MIDI_TASK Task(%InvFast_Task).naam = "FastInv" Task(%InvFast_Task).freq = 60 Task(%InvFast_Task).cptr = CODEPTR(WoodstockJazzDelayInvertFast) Task(%InvFast_Task).Rit.minduur = 0.050 ' in s Task(%InvFast_Task).Rit.maxduur = 5.000 ' in s Task(%InvFast_Task).flags = Task(%InvFast_Task).flags OR %MIDI_TASK OR %HARM_TASK Task(%BackInv_Task).naam = "InvCanc" Task(%BackInv_Task).freq = 58 Task(%BackInv_Task).cptr = CODEPTR(WoodstockJazzDelayBackInvert) Task(%BackInv_Task).Rit.minduur = 0.050 ' in s Task(%BackInv_Task).Rit.maxduur = 5.000 ' in s Task(%BackInv_Task).flags = Task(%BackInv_Task).flags OR %MIDI_TASK OR %HARM_TASK Task(%BackSlow_Task).naam = "SloCanc" Task(%BackSlow_Task).freq = 31 Task(%BackSlow_Task).cptr = CODEPTR(WoodstockJazzDelayBackSlow) Task(%BackSlow_Task).Rit.minduur = 0.10 ' in s Task(%BackSlow_Task).Rit.maxduur = 10.000 ' in s Task(%BackSlow_Task).flags = Task(%BackSlow_Task).flags OR %MIDI_TASK OR %HARM_TASK Task(%Gerade_Task).naam = "Straight" Task(%Gerade_Task).freq = 35 Task(%Gerade_Task).cptr = CODEPTR(WoodstockJazzDelayPlayerNormal) Task(%Gerade_Task).Rit.minduur = 0.10 ' in s Task(%Gerade_Task).Rit.maxduur = 10.000 ' in s Task(%Gerade_Task).flags = Task(%Gerade_Task).flags OR %MIDI_TASK OR %HARM_TASK ' realtime audio tasks:----------------------------------------------- 'Task(%AudioDelay_Task).naam = "Delay" ' = 48 ' Task(%AudioDelay_Task).cPtr = CODEPTR(gwrAudioDelay) ' in gmt_gwr.bas ' Task(%AudioDelay_Task).freq = 20 ' Task(%AudioDelay_Task).duur = 8000 'Task(%AudioSample_Task).naam = "Record" ' =49 ' Task(%AudioSample_Task).cPtr = CODEPTR(gwrRecordSample) ' in gmt_gwr.bas ' Task(%AudioSample_Task).freq = 20 ' Task(%AudioSample_Task).duur = 4000 ' was 3000 on 28.02.2000 ' this time is increased during the piece. ' (cfr. do-event code) 'Task(%AudioPlayReversed_Task).naam = "Reverse" '50 ' Task(%AudioPlayReversed_Task).cPtr = CODEPTR(gwrPlayReversed) ' backwards ' Task(%AudioPlayReversed_Task).freq = 20 Task(%AudioPlaySample_Task).naam = "PlaySamp" ' = 51 - playback of prerecorded samples Task(%AudioPlaySample_Task).cPtr = CODEPTR(WoodstockJazzPlaySample) ' - specific code for WoodstockJazz Task(%AudioPlaySample_Task).freq = 20 Task(%AudioPlayRecordedSample_Task).naam = "PlayBack" '[ = 52] Task(%AudioPlayRecordedSample_Task).cPtr = CODEPTR(gwrPlayRecordedSample) ' in gmt_gwr.bas Task(%AudioPlayRecordedSample_Task).freq = 22 ' Task(%LS_RingModulator_Task).naam = "RingMod" ' 53 ' Task(%LS_RingModulator_Task).cPtr = CODEPTR(WoodstockJazzRingModulator) ' Task(%Ls_RingModulator_Task).freq = 7 ' Task(%AudioCrossModulator_Task).naam = "CrossMod" ' 54 ' Task(%AudioCrossModulator_Task).cPtr = CODEPTR(gwrCrossModulator) ' in gmt_gwr.bas ' Task(%AudioCrossModulator_Task).freq = 6 ' Task(%AudioCrossTimeModulator_Task).naam = "CrossTim" ' 55 ' in gmt_gwr.bas ' Task(%AudioCrossTimeModulator_Task).cPtr = CODEPTR(gwrCrossTimeModulator) ' Task(%AudioCrossTimeModulator_Task).freq = 6 ' Task(%LS_PitchShift_Task).naam = "VarSpeed" ' split of from audioprocess 07.03.2000 ' Task(%LS_PitchShift_Task).cPtr = CODEPTR(WoodstockJazzPitchShift) ' Task(%LS_PitchShift_Task).freq = 8 ' nr = ReadAudioDataFromFile ($WoodStockINI, AudioFader()) ' dll call ' for now, lets delete audiofader tasks... ' Task(0).naam = "" ' Task(0).cPtr = %False ' Task(AudioFader(0).TaskNr).naam = "" ' Task(AudioFader(0).TaskNr).cPtr = %False ' Task(AudioFader(1).TaskNr).naam = "" ' Task(AudioFader(1).TaskNr).cPtr = %False ' WoodstockJazzInitSynth FOR i = %WoodstockJazz_V1_Task TO %gerade_task Task(i).channel = Harmo.channel NEXT LastNotePlayed = 50 'Bb Clarinet. ' create the melody window automatically on startup: LOCAL msg AS tagMSG msg.hWnd = gh.Cockpit msg.message = %WM_COMMAND msg.wParam = %GMT_BUTNSW_ID + 5 ' creates score display window. msg.lParam = %Null DispatchMessage msg DrawAllPatterns gh.MelPat ' display the score... (this only prepares the window size!) ' write caption bars: LOCAL m AS ASCIIZ * 40 m = "GMT: " Sendmessage gh.Cockpit, %WM_SETTEXT,0, VARPTR(m) m = " Score" SendMessage gh.MelPat, %WM_SETTEXT,0, VARPTR(m) FUNCTION = %True END FUNCTION SUB WoodstockJazzDoEvent () ' recognition wave playing waits for device available, so that the sample always plays, even if too late... ' however, in the present version, there is no cueing up of files/ tracks to be played... STATIC delaytimecounter AS BYTE LOCAL chk AS BYTE IF ISFALSE Task(%AudioPlaySample_Task).swit THEN StartTask %AudioPlaySample_Task ' specific version for WoodstockJazz. DrawAllPatterns gh.MelPat SELECT CASE Recog.nr CASE 1 ' samples: detunes IF Task(%ClarDetune_Task).swit THEN 'StartTask %ClarDetune_Task ' starts/stops velo-dependent detuning on recognition of La IF BIT(Task(%BackInv_Task).swit,%TASK_ONOFF) THEN StopTask %BackInv_Task ReadDelayLine% %BackInv_Task, 0, 0 ' force a reset END IF ELSE 'StopTask %ClarDetune_Task 'ReadDelayLine% %ClarDetune_Task, 0,0 ' force reset IF ISFALSE Task(%BackInv_Task).swit THEN StartTask %BackInv_Task ELSE StopTask %BackInv_Task ReadDelayLine% %BackInv_Task, 0, 0 ' force a reset END IF END IF WoodstockJazzPatternAlgo Recog.nr - 1 ' recalculate new pattern CASE 2 ' samples: ademklasse chk = %False '' IF ISFALSE Task(%AudioSample_Task).swit THEN ''IF ISFALSE Task(%AudioDelay_Task).swit THEN '' Task(%AudioSample_Task).duur = Task(%AudioSample_Task).duur * 1.5 ' recording duration ' was set to 5000 ms before 29.02.2000. '' StartTask %AudioSample_Task ' autostops. '' chk = %True IF BIT(Task(%Gerade_Task).swit,%TASK_ONOFF) THEN StopTask %Gerade_Task ReadDelayLine% %Gerade_Task, 0, 0 ' force a reset END IF '' END IF '' END IF IF ISFALSE chk THEN IF ISFALSE Task(%Gerade_Task).swit THEN StartTask %Gerade_Task ELSE StopTask %Gerade_Task ReadDelayLine% %Gerade_Task, 0, 0 ' force a reset END IF END IF WoodstockJazzPatternAlgo Recog.nr -1 CASE 3 ' samples: multiphonics ' play RT recorded sample. only if a recorded sample is available... '' IF Recording_Available THEN ' flag to signal availibility of a recorded sample. '' IF ISFALSE Task(%AudioPlayRecordedSample_Task).swit THEN '' StartTask %AudioPlayRecordedSample_Task ' autostops '' IF BIT(Task(%BackSlow_Task).swit,%TASK_ONOFF) THEN '' StopTask %BackSlow_Task '' ReadDelayLine% %BackSlow_Task, 0, 0 ' force a reset '' END IF '' ELSE '' IF BIT(Task(%BackSlow_Task).swit,%TASK_ONOFF) THEN '' StopTask %BackSlow_Task '' ReadDelayLine% %Backslow_Task, 0,0 ' reset '' END IF '' END IF '' ELSE IF ISFALSE Task(%BackSlow_Task).swit THEN StartTask %BackSlow_Task 'WoodstockJazzDelayBackSlow ELSE StopTask %BackSlow_Task ReadDelayLine% %BackSlow_Task, 0, 0 ' force a reset END IF ''END IF WoodstockJazzPatternAlgo Recog.nr -1 CASE 4 ' samples: Pitched clicks ' start audio delay line... ' we pass the delay time in Task().duur , expressed in milliseconds ' the duration of the delay event in Task().stoptime, expressed in seconds ''IF ISFALSE Task(%AudioDelay_Task).swit THEN '' INCR delaytimecounter '' Task(%AudioDelay_Task).duur = 2000 - (delaytimecounter * 100) ' in ms. '' IF Task(%AudioDelay_Task).duur < 255 THEN Task(%AudioDelay_Task).duur = 255 '' Task(%AudioDelay_Task).stoptime = 30 - (delaytimecounter) ' in seconds '' IF Task(%AudioDelay_Task).stoptime < 1 THEN Task(%AudioDelay_Task).stoptime = 1 '' StartTask %AudioDelay_Task '' ' SetDlgItemText hCockpit, %GMT_MSG1, "Audio-delay " & STR$(Task(%AudioDelay_Task).duur) & "ms " & STR$(Task(%AudioDelay_Task).stoptime) & " s " ''ELSE ' start a midi-delay... IF ISFALSE Task(%InvFast_Task).swit THEN StartTask %InvFast_Task ' autostops ELSE StopTask %InvFast_Task ReadDelayLine% %InvFast_Task, 0, 0 ' force a reset END IF ''END IF WoodstockJazzPatternAlgo Recog.nr -1 CASE 5 ' samples: artikulaties IF ISFALSE Task(%Pattern1_Task).swit THEN StartTask %Pattern1_Task ' pattern 1 chk = %True ELSE StopTask %Pattern1_Task ''IF Recording_Available THEN '' IF ISFALSE Task(%AudioPlayReversed_Task).swit THEN '' StartTask %AudioPlayReversed_Task ' reverse playback audio '' chk = %True '' IF BIT(Task(%InvFast_Task).swit,%TASK_ONOFF) THEN '' StopTask %InvFast_Task '' ReadDelayLine% %InvFast_Task, 0, 0 ' force a reset '' END IF '' ELSE '' chk = %False '' END IF ''ELSE '' chk = %False ''END IF END IF ''IF ISFALSE chk THEN IF ISFALSE Task(%InvFast_Task).swit THEN StartTask %InvFast_Task ELSE StopTask %InvFast_Task ReadDelayLine% %InvFast_Task, 0, 0 ' force a reset END IF ''END IF WoodstockJazzPatternAlgo Recog.nr -1 CASE 6 ' samples: noiseclicks IF ISFALSE Task(%Pattern2_Task).swit THEN StartTask %Pattern2_Task ELSE StopTask %Pattern2_Task '' IF Recording_Available THEN '' IF ISFALSE Task(%AudioCrossTimeModulator_Task).swit THEN '' StartTask %AudioCrossTimeModulator_Task '' END IF '' END IF END IF WoodstockJazzPatternAlgo Recog.nr -1 CASE 7 ' samples: flatterzunge IF ISFALSE Task(%Pattern3_Task).swit THEN StartTask %Pattern3_Task ' pattern 3 ''IF Recording_Available THEN ' added 07.03.2000 '' IF ISFALSE Task(%LS_PitchShift_Task).swit THEN '' StartTask %LS_PitchShift_Task '' END IF ''END IF ELSE StopTask %Pattern3_Task ''IF Recording_Available THEN '' IF ISFALSE Task(%AudioCrossModulator_Task).swit THEN '' StartTask %AudioCrossModulator_Task '' END IF ''END IF END IF CASE 8 ' samples: Noise ''IF Recording_Available THEN '' IF ISFALSE Task(%LS_RingModulator_Task).swit THEN '' StartTask %LS_RingModulator_Task '' IF BIT(Task(%InvFast_Task).swit,%TASK_ONOFF) THEN '' StopTask %InvFast_Task '' ReadDelayLine% %InvFast_Task, 0, 0 ' force a reset '' END IF '' END IF ''ELSE IF ISFALSE Task(%InvFast_Task).swit THEN StartTask %InvFast_Task ELSE StopTask %InvFast_Task ReadDelayLine% %InvFast_Task, 0, 0 ' force a reset END IF ''END IF END SELECT END SUB SUB WoodstockJazzListen () EXPORT LOCAL nv% LOCAL noot? LOCAL velo? LOCAL Xlatv AS WORD STATIC oldnote% IF ISFALSE Task(%Listen_Task).tog THEN IF (Task(%Listen_Task).swit AND %TASK_BUSY) = %d1 THEN EXIT SUB oldnote% = %False Task(%Listen_Task).tog = %True END IF nv% = GetMidiNote% (Task(%Listen_Task).channel, %Remove OR %Oldest) IF nv% = %NotFalse THEN EXIT SUB ' no new note in buffer velo? = LOBYT (nv%) noot? = HIBYT (nv%) ' if note within range... SetDlgItemText gh.Cockpit, %GMT_MSG2, STR$(noot) + STR$(velo) IF (noot? >= Clarinet.lowtes) AND (noot? <= Clarinet.hightes) THEN ' if note-on.... IF velo? > %False THEN IF oldnote% THEN DelNote2Har Task(%Listen_Task).Har, oldnote% ' remove oldnote ... This implies monophonic instrument. WriteDelayLine oldnote%, 0 GetLastNote LOBYT(oldnote%), 0 , Clarinet ' sets/updates the global var LastNotePlayed END IF AddNote2Har Task(%Listen_Task).Har, (noot?), (velo?) WriteDelayLine noot?, velo? GetLastNote noot?, velo?, Clarinet oldnote% = noot? ELSE ' if note off... WriteDelayLine noot?, 0 GetLastNote noot?, 0, Clarinet DelNote2Har Task(%Listen_Task).Har, (noot?) ' we delete the note after calling GetLastNote and its ' implied MatchPattern call, since we need the velo value of the ' note just switched of there! oldnote% = %False END IF SetJazzContext noot?, velo? ' following should become part of a monitoring task... SetDlgItemText gh.Cockpit, %GMT_TEXT_TES, STR$(INT(WoodstockJazz.tes)) SetDlgItemText gh.Cockpit, %GMT_MSG1, "V=" & STR$(WoodstockJazz.vol) & " d=" & FORMAT$(WoodstockJazz.dens,"##.#") END IF END SUB SUB WoodstockJazzScore() EXPORT STATIC msduration AS DWORD ' scoring task. IF ISFALSE Task(%WoodstockJazz_Score_Task).tog THEN IF (Task(%WoodstockJazz_Score_Task).swit AND %TASK_BUSY) = %d1 THEN EXIT SUB Task(%WoodstockJazz_Score_Task).tog = %True msduration = App.komposduur * 1000 ' convert to milliseconds Task(%WoodstockJazz_Score_Task).freq = 1 END IF IF Getpromil% < 0 THEN EXIT SUB 'Normprop = (tnow - tstart)/ msduration WoodstockJazz.Angle = ((timeGetTime - App.tstart) * Pi2)/ msduration ' 0 to Pi2 (radians) IF WoodstockJazz.Angle > Pi2 THEN WoodstockJazz.Angle = WoodstockJazz.Angle - Pi2 ' circles ' here we should add all code for linear scoring (if any...) ' If Getpromil% < 10 END SUB SUB ButnSW_WoodstockJazzStartStop () LOCAL ButtonNr AS LONG LOCAL i AS DWORD ButtonNr = App.butnSWparam - %GMT_BUTNSW_ID IF ButnSW(Buttonnr).flag THEN App.MTstart = %True App.tstart = timeGetTime ' start the chronometerfunction SetDlgItemText gh.Cockpit, %GMT_BUTNSW_ID + ButtonNr, "STOP" ClearMiBuf 0 ' start with a blank midi input buffer BlockSysExReception hMidiI(0) 'SxThread ' dll proc ' StartTask App.PromilTasknr Promil %True ' StartTask App.RunTimeTaskNr runtime %True StartTask %Listen_Task StartTask %WoodstockJazz_Score_Task StartTask App.GlobalHarmonyTaskNr DrawAllPatterns gh.MelPat ' does not work here!, only on a second push on the button... ELSE App.MTstart = %False SetDlgItemText gh.Cockpit, %GMT_BUTNSW_ID + ButtonNr, "CONT" END IF App.butnSWparam = %False END SUB SUB SetJazzContext (noot?, velo?) EXPORT STATIC tog AS BYTE STATIC Cnt() AS BYTE STATIC oldwijzer AS DWORD LOCAL wijzer AS DWORD LOCAL nrevents AS LONG IF ISFALSE tog THEN WoodstockJazz.vol = 24 ' midi level WoodstockJazz.tes = 440 ' in Hz WoodstockJazz.dens = 0.5 ' in events/sec (Hz) tog = %True DIM Cnt(0 TO 255) ' 1 byte for every cs. - so we integrate over 2,56 seconds END IF ' bereken de gemiddelde geluidsterkte van de input (integration) IF velo? THEN WoodstockJazz.Vol = WoodstockJazz.Vol + WoodstockJazz.Vol + WoodstockJazz.Vol + velo? SHIFT RIGHT WoodstockJazz.Vol, 2 END IF ' ' bereken de gemiddelde tessituurligging van de input IF noot? THEN WoodstockJazz.tes = ((WoodstockJazz.tes * 3) + N2F(noot?)) / 4 END IF ' calculate the density of the input over a timeframe of 255cs. ' The result is returned in WoodstockJazz.dens wijzer = (timeGetTime / 10) 'MOD 256 wijzer = wijzer AND 255 IF wijzer <> oldwijzer THEN DO INCR oldwijzer oldwijzer = oldwijzer AND 255 Cnt(oldwijzer) = %False LOOP UNTIL oldwijzer = wijzer END IF Cnt(wijzer) = %True ' now count the number of events in the buffer: FOR wijzer = 0 TO 255 IF Cnt(wijzer) THEN INCR nrevents NEXT wijzer WoodstockJazz.dens = nrevents / 2.56! ' express result in events/second ' max.value = 100 ' note that these values should be halved for approximate tempo ' derivation, since here we count both note-ons and note-offs. END SUB SUB Woodstockjazz_Stock1 () EXPORT STATIC Ritmeteller% STATIC HarV1 AS HarmType STATIC starttempo AS SINGLE LOCAL tiks! IF ISFALSE Task(%WoodstockJazz_V1_Task).tog THEN IF (Task(%WoodstockJazz_V1_Task).swit AND %TASK_BUSY) = %d1 THEN EXIT SUB Task(%WoodstockJazz_V1_Task).tog = %True HarV1.vel = STRING$(128,0) starttempo = Task(%WoodstockJazz_V1_Task).tempo ' should become dependent on input tempo! END IF ' This procedure is polyphonic. IF Task(%WoodstockJazz_V1_Task).Rit.pattern(Ritmeteller%) = 0 THEN Ritmeteller% = 0 ' get new parameters: Task(%WoodstockJazz_V1_Task).tempo = WoodstockJazz.dens / 8 IF Task(%WoodstockJazz_V1_Task).tempo < 5 THEN Task(%WoodstockJazz_V1_Task).tempo = 5 ' return a new pattern for the rhythm as soon as the actual one has been completed. (new bar): Iprop2Rit Task(App.GlobalHarmonyTasknr).Har, %WoodstockJazz_V1_Task, 3 END IF tiks! = RitmSigma!(Task(%WoodstockJazz_V1_Task).Rit) IF tiks! <= 0 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(%WoodstockJazz_V1_Task).freq = (tiks! * Task(%WoodstockJazz_V1_Task).tempo ) / (60 * ABS(Task(%WoodstockJazz_V1_Task).Rit.pattern(Ritmeteller%))) IF Task(%WoodstockJazz_V1_Task).Rit.pattern(Ritmeteller%) < 0 THEN ' this means we have to play a rest... Task(%WoodstockJazz_V1_Task).Har.vel = STRING$(128,0) ELSE ' now we have to find a new chord to play for our task... IF Task(App.GlobalHarmonyTasknr).Har.vel <> STRING$(128, 0) THEN SELECT CASE Ritmeteller% MOD 3 CASE %False Task(%WoodstockJazz_V1_Task).Har.vel = SolveHar$ (Task(App.GlobalHarmonyTasknr).Har, BYCOPY LastNotePlayed, 0.05) CASE %True Task(%WoodstockJazz_V1_Task).Har.vel = InBetweenHar$(HarV1, Task(App.GlobalHarmonyTaskNr).Har) CASE 2 Task(%WoodstockJazz_V1_Task).Har.vel = DiminuteHar$(HarV1,LastNotePlayed MOD 12,11,1) ' aug END SELECT ELSE Task(%WoodstockJazz_V1_Task).Har.vel = STRING$(128,0) END IF END IF INCR Ritmeteller% IF Task(%WoodstockJazz_V1_Task).Har.vel <> HarV1.vel THEN IF Task(%WoodstockJazz_V1_Task).Har.vel <> Task(App.GlobalHarmonyTasknr).Har.vel THEN PlayHar Task(%WoodstockJazz_V1_Task).Har, Task(%WoodstockJazz_V1_Task).channel ' playhar keeps track of oldnotes internally... IF Task(%WoodstockJazz_V1_Task).Har.vel <> STRING$(128,0) THEN HarV1.vel = Task(%WoodstockJazz_V1_Task).Har.vel ' remember previous output. END IF END IF END IF END SUB SUB Woodstockjazz_Stock2 () EXPORT STATIC Ritmeteller% STATIC HarV2 AS HarmType STATIC starttempo AS SINGLE LOCAL tiks! IF ISFALSE Task(%WoodstockJazz_V2_Task).tog THEN IF (Task(%WoodstockJazz_V2_Task).swit AND %TASK_BUSY) = %d1 THEN EXIT SUB Task(%WoodstockJazz_V2_Task).tog = %True HarV2.vel = STRING$(128,0) starttempo = Task(%WoodstockJazz_V2_Task).tempo ' should be dependent on input tempo! END IF ' modelled after VoicePrototype in GMT.BAS / Cohiba.bas ' This procedure is polyphonic. IF Task(%WoodstockJazz_V2_Task).Rit.pattern(Ritmeteller%) = 0 THEN Ritmeteller% = 0 ' get new parameters: Task(%WoodstockJazz_V2_Task).tempo = WoodstockJazz.dens / 8 IF Task(%WoodstockJazz_V2_Task).tempo < 4 THEN Task(%WoodstockJazz_V2_Task).tempo = 4 ' return a new pattern for the rhythm as soon as the actual one has been completed. (new bar): Iprop2Rit Task(App.GlobalHarmonyTasknr).Har, %WoodstockJazz_V2_Task, 2 END IF tiks! = RitmSigma!(Task(%WoodstockJazz_V2_Task).Rit) IF tiks! <= 0 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(%WoodstockJazz_V2_Task).freq = (tiks! * Task(%WoodstockJazz_V2_Task).tempo ) / (60 * ABS(Task(%WoodstockJazz_V2_Task).Rit.pattern(Ritmeteller%))) IF Task(%WoodstockJazz_V2_Task).Rit.pattern(Ritmeteller%) < 0 THEN ' this means we have to play a rest... Task(%WoodstockJazz_V2_Task).Har.vel = STRING$(128,0) ELSE ' now we have to find a new chord to play for our task... IF Task(App.GlobalHarmonyTasknr).Har.vel <> STRING$(128, 0) THEN SELECT CASE Ritmeteller% MOD 4 CASE %False Task(%WoodstockJazz_V2_Task).Har.vel = SolveHar$ (Task(App.GlobalHarmonyTasknr).Har, BYCOPY LastNotePlayed, 0.05) CASE %True Task(%WoodstockJazz_V2_Task).Har.vel = InBetweenHar$(HarV2, Task(App.GlobalHarmonyTaskNr).Har) CASE 2 Task(%WoodstockJazz_V2_Task).Har.vel = DiminuteHar$(HarV2,LastNotePlayed MOD 12,11,1) ' aug CASE 3 Task(%WoodstockJazz_V2_Task).Har.vel = SymDimHar$(HarV2,LastNotePlayed MOD 12,-1) ' dim END SELECT ELSE Task(%WoodstockJazz_V2_Task).Har.vel = STRING$(128,0) END IF END IF INCR Ritmeteller% IF Task(%WoodstockJazz_V2_Task).Har.vel <> HarV2.vel THEN IF Task(%WoodstockJazz_V2_Task).Har.vel <> Task(App.GlobalHarmonyTasknr).Har.vel THEN PlayHar Task(%WoodstockJazz_V2_Task).Har, Task(%WoodstockJazz_V2_Task).channel ' playhar keeps track of oldnotes internally... IF Task(%WoodstockJazz_V2_Task).Har.vel <> STRING$(128,0) THEN HarV2.vel = Task(%WoodstockJazz_V2_Task).Har.vel ' remember previous output. END IF END IF END IF END SUB SUB WoodstockJazzPattern1 () EXPORT STATIC i% STATIC toets% STATIC Initpattern AS BYTE STATIC Melody() AS INTEGER STATIC stoptijd AS DWORD LOCAL j% IF ISFALSE Task(%Pattern1_Task).tog THEN IF (Task(%Pattern1_Task).swit AND %TASK_BUSY) = %d1 THEN EXIT SUB i% = %False toets% = %True IF ISFALSE Initpattern THEN DIM Melody (0 TO 12) ' 13 notes (14 in lickstick) FOR i = 0 TO UBOUND(Melody) Melody(i) = 52 '60 NEXT i Initpattern = %True END IF Task(%Pattern1_Task).tog = %True stoptijd = timeGetTime + 20000 ' 20 sec. max. END IF IF toets% THEN Play Task(%Pattern1_Task).channel, Melody(i%),WoodstockJazz.vol OR 1 ' midi level depends on input level toets% = %False AddNote2Har Task(%Pattern1_Task).Har,Melody(i%), WoodstockJazz.vol OR 1 ELSE NoteOff Task(%Pattern1_Task).channel, Melody(i%) toets% = %True Task(%Pattern1_Task).Har.vel = STRING$(128, 0) INCR i% IF i% > UBOUND(Melody) THEN i% = 0 j% = RND(1) * UBOUND(Melody) IF LastNotePlayed <> Melody(j%) THEN Melody(j%)= LastNotePlayed END IF IF timeGetTime > stoptijd THEN Task(%Pattern1_Task).tog = %False StopTask %Pattern1_Task END IF END IF ' tempo also depends on input density!: Task(%Pattern1_Task).freq = WoodstockJazz.dens ' in events/sec (Hz) END SUB SUB WoodstockJazzPattern2 () EXPORT STATIC i%, toets% STATIC Melody() AS INTEGER STATIC Initpattern AS BYTE STATIC stoptijd AS DWORD LOCAL j% IF ISFALSE Task(%Pattern2_Task).tog THEN IF (Task(%Pattern2_Task).swit AND %TASK_BUSY) = %d1 THEN EXIT SUB i% = 0 toets% = %NotFalse IF ISFALSE Initpattern THEN DIM Melody (0 TO 6) '7, 11 notes in lickstick FOR i = 0 TO UBOUND(Melody) Melody(i) = 65 '61 NEXT i InitPattern = %True END IF Task(%Pattern2_Task).tog = %True stoptijd = timeGettime + 16000 END IF IF toets% THEN Play Task(%Pattern2_Task).channel, Melody(i%), WoodstockJazz.vol OR 1 toets% = %False AddNote2Har Task(%Pattern2_Task).Har,Melody(i%), WoodstockJazz.Vol OR 1 ELSE Play Task(%Pattern2_Task).channel, Melody(i%), %False toets% = %NotFalse Task(%Pattern2_Task).Har.vel = STRING$(128, 0) INCR i% IF i% > UBOUND(Melody) THEN i% = 0 j% = RND(1) * UBOUND(Melody) IF LastNotePlayed <> Melody(j%) THEN Melody(j%)= LastNotePlayed ELSE Melody(j%) = LastNotePlayed - 12 IF Melody(j%) < 24 THEN Melody(j%) = 24 ' your never know... END IF END IF IF timeGetTime > stoptijd THEN Task(%Pattern2_Task).tog = %False StopTask %Pattern2_Task END IF END IF ' tempo also depends on input density!: Task(%Pattern2_Task).freq = (WoodstockJazz.dens * 3 / 2) ' in events/sec (Hz) END SUB SUB WoodstockJazzPattern3 () EXPORT STATIC i%, toets% STATIC Melody() AS INTEGER STATIC Initpattern AS BYTE STATIC stoptijd AS DWORD LOCAL j% IF ISFALSE Task(%Pattern3_Task).tog THEN IF (Task(%Pattern3_Task).swit AND %TASK_BUSY) = %d1 THEN EXIT SUB i% = 0 toets% = %NotFalse IF ISFALSE Initpattern THEN DIM Melody (0 TO 10) ' 11, in lickstick 7 notes FOR i = 0 TO UBOUND(Melody) Melody(i) = 78 '62 NEXT i Initpattern = %True END IF Task(%Pattern3_Task).tog = %True stoptijd = timeGetTime + 18000 ' 18 sec. END IF IF toets% THEN Play Task(%Pattern3_Task).channel, Melody(i%), WoodstockJazz.vol OR 1 toets% = %False AddNote2Har Task(%Pattern3_Task).Har,Melody(i%), WoodstockJazz.vol OR 1 ELSE Play Task(%Pattern3_Task).channel, Melody(i%), %False toets% = %NotFalse Task(%Pattern3_Task).Har.vel = STRING$(128, 0) INCR i% IF i% > UBOUND(Melody) THEN i% = 0 j% = RND(1) * UBOUND(Melody) IF LastNotePlayed <> Melody(j%) THEN Melody(j%)= LastNotePlayed END IF IF timeGetTime > stoptijd THEN Task(%Pattern3_Task).tog = %False StopTask %Pattern3_Task END IF END IF ' tempo also depends on input density!: Task(%Pattern3_Task).freq = (WoodstockJazz.dens * 2 / 3) ' in events/sec (Hz) END SUB SUB WoodstockJazzPatternAlgo (pattern AS BYTE) ' in this piece we recalculate patterns dynamically ' every time a pattern is recognized, it is extended with a single note value. ' pattern = Recog.nr + 1 ' recog.nr starts at 1 , whilst LBOUND(PatternSeq) = 0 LOCAL i AS LONG LOCAL noot AS INTEGER STATIC patduur4 AS SINGLE STATIC tog AS BYTE IF ISFALSE tog THEN patduur4 = PatternSeq(4).duur(0) + PatternSeq(4).duur(1) tog = %True END IF SELECT CASE pattern CASE 0 FOR i = 0 TO PatternSeq(pattern).lengte IF i > 0 THEN PatternSeq(pattern).noot(i)= PatternSeq(pattern).noot(i-1) + i PatternSeq(pattern).velo(i)= PatternSeq(pattern).velo(i-1) PatternSeq(pattern).duur(i)= PatternSeq(pattern).duur(i-1) END IF NEXT i IF PatternSeq(pattern).noot(PatternSeq(pattern).lengte) > Clarinet.Hightes THEN EXIT SUB ' end reached. IF PatternSeq(pattern).lengte < 14 THEN INCR PatternSeq(pattern).lengte END IF CASE 1 FOR i = 0 TO PatternSeq(pattern).lengte IF i > 0 THEN PatternSeq(pattern).noot(i)= PatternSeq(pattern).noot(i-1) - i PatternSeq(pattern).velo(i)= PatternSeq(pattern).velo(i-1) PatternSeq(pattern).duur(i)= PatternSeq(pattern).duur(i-1) END IF NEXT i IF PatternSeq(pattern).noot(PatternSeq(pattern).lengte) < Clarinet.LowTes THEN EXIT SUB ' end reached IF PatternSeq(pattern).lengte < 14 THEN INCR PatternSeq(pattern).lengte END IF CASE 2 FOR i = 0 TO PatternSeq(pattern).lengte IF i > 0 THEN IF BIT(i,0) THEN PatternSeq(pattern).noot(i)= PatternSeq(pattern).noot(i-1) - i ELSE PatternSeq(pattern).noot(i)= PatternSeq(pattern).noot(i-1) + i END IF PatternSeq(pattern).velo(i)= PatternSeq(pattern).velo(i-1) PatternSeq(pattern).duur(i)= PatternSeq(pattern).duur(i-1) END IF NEXT i IF PatternSeq(pattern).noot(PatternSeq(pattern).lengte) < Clarinet.LowTes THEN EXIT SUB ' end reached IF PatternSeq(pattern).noot(PatternSeq(pattern).lengte) > Clarinet.HighTes THEN EXIT SUB IF PatternSeq(pattern).lengte < 14 THEN INCR PatternSeq(pattern).lengte END IF CASE 3 FOR i = 0 TO PatternSeq(pattern).lengte IF i > 0 THEN IF BIT(i,0) THEN PatternSeq(pattern).noot(i)= PatternSeq(pattern).noot(i-1) + i ELSE PatternSeq(pattern).noot(i)= PatternSeq(pattern).noot(i-1) - i END IF PatternSeq(pattern).velo(i)= PatternSeq(pattern).velo(i-1) PatternSeq(pattern).duur(i)= PatternSeq(pattern).duur(i-1) END IF NEXT i IF PatternSeq(pattern).noot(PatternSeq(pattern).lengte) < Clarinet.LowTes THEN EXIT SUB ' end reached IF PatternSeq(pattern).noot(PatternSeq(pattern).lengte) > Clarinet.HighTes THEN EXIT SUB IF PatternSeq(pattern).lengte < 14 THEN INCR PatternSeq(pattern).lengte END IF CASE 4 ' mi - sol at start ' we add 1 whole tone up on each recognition - and shorten the durations ' first calculate the total duration now: ' patduur = 0 ' FOR i = 0 TO PatternSeq(4).lengte -1 ' patduur = patduur + PatternSeq(4).duur(i) ' bereken huidige totale tijdsduur ' NEXT i ' patduur = 2 'PatternSeq(4).duur(0) * PatternSeq(4).lengte -1 FOR i = 0 TO PatternSeq(4).lengte ' 27.02.2000 PatternSeq(4).duur(i) = patduur4 / PatternSeq(4).lengte NEXT i noot = GetDifferentPatternNote(PatternSeq(),4) IF noot >= Clarinet.LowTes THEN PatternSeq(4).noot(PatternSeq(4).lengte) = noot PatternSeq(4).velo(PatternSeq(4).lengte)= PatternSeq(4).velo(PatternSeq(4).lengte -1) ELSE PatternSeq(4).noot(PatternSeq(4).lengte)= PatternSeq(4).noot(PatternSeq(4).lengte -1) + 2 PatternSeq(4).velo(PatternSeq(4).lengte)= PatternSeq(4).velo(PatternSeq(4).lengte -1) END IF IF PatternSeq(4).noot(PatternSeq(4).lengte) < Clarinet.LowTes THEN EXIT SUB ' end reached IF PatternSeq(4).noot(PatternSeq(4).lengte) > Clarinet.HighTes THEN EXIT SUB IF PatternSeq(4).lengte < 14 THEN INCR PatternSeq(4).lengte ' so the last element is zero. END IF CASE 5 ' la at start - changes dynamically noot = GetDifferentPatternNote(PatternSeq(),5) IF noot >= Clarinet.LowTes THEN PatternSeq(5).noot(0) = noot END IF ' CASE 6 ' no change ' CASE 7 ' no change END SELECT DrawAllPatterns gh.MelPat END SUB FUNCTION Woodstockjazz_GetDifferentPatternNote (PatternSeq() AS PatternSequenceType, pattern AS BYTE) AS INTEGER ' we pass the pointer to the type such that -at a later moment- we may place ' this procedure in our dll. ' the pattern number passed is the destination pattern for the note, such that the proc. takes ' melodiousness into consideration. LOCAL H AS Harmtype LOCAL H2 AS HarmType LOCAL PatCnt AS LONG LOCAL i AS LONG H.vel = STRING$(128,0) H2.vel = STRING$(128,0) ' this function returns a note missing in the patterns as they are on the moment of the call. FOR patCnt = 0 TO UBOUND(PatternSeq) FOR i = 0 TO PatternSeq(patCnt).lengte IF PatternSeq(patCnt).velo(i) > 0 THEN AddNote2Har H, PatternSeq(patCnt).noot(i), PatternSeq(patCnt).velo(i) END IF NEXT i NEXT patCnt H2.vel = ComplementHar$ (H,Clarinet.lowtes, Clarinet.hightes) ' returns the notes not present in ' the Har$ passed. FUNCTION = StealNoteFromHar(H2, PatternSeq(pattern).noot(PatternSeq(pattern).lengte-1), Clarinet.lowtes, Clarinet.hightes) END FUNCTION SUB WoodstockJazzPlaySample () ' this task plays the prerecorded wave files on disk. ' This task has very specific WoodstockJazz code, since we use a large set of changing sample-files. STATIC Jumpval AS BYTE STATIC CatIdx1 AS BYTE STATIC CatIdx2 AS BYTE STATIC CatIdx3 AS BYTE STATIC CatIdx4 AS BYTE STATIC CatIdx5 AS BYTE STATIC CatIdx6 AS BYTE STATIC CatIdx7 AS BYTE STATIC CatIdx8 AS BYTE LOCAL Filnam AS ASCIIZ * 40 LOCAL retval AS LONG STATIC tracknr AS LONG STATIC duur AS DWORD IF ISFALSE Task(%AudioPlaySample_Task).tog THEN IF (Task(%AudioPlaySample_Task).swit AND %TASK_BUSY) = %d1 THEN EXIT SUB IF ISFALSE Audio.hWo THEN Stoptask %AudioPlaySample_Task EXIT SUB END IF Task(%AudioPlaySample_Task).tog = %True Jumpval = %False ' calculate the filename for the sample to be played...: SELECT CASE Recog.nr CASE 1 ' detunes Filnam = "WS0" & TRIM$(STR$(CatIdx1)) & ".WAV" 'INCR CatIdx1 'IF CatIdx1 > 2 THEN CatIdx1 = 0 CASE 2 Filnam = "WS1" & TRIM$(STR$(CatIdx2)) & ".WAV" 'INCR CatIdx2 'IF CatIdx2 > 10 THEN CatIdx2 = 0 CASE 3 Filnam = "WS2" & TRIM$(STR$(CatIdx3)) & ".WAV" 'INCR CatIdx3 'IF CatIdx3 > 7 THEN CatIdx3 = 0 CASE 4 Filnam = "WS3" & TRIM$(STR$(CatIdx4)) & ".WAV" 'INCR CatIdx4 'IF CatIdx4 > 17 THEN CatIdx4 = 0 CASE 5 Filnam = "WS4" & TRIM$(STR$(CatIdx5)) & ".WAV" 'INCR CatIdx5 'IF CatIdx5 > 4 THEN CatIdx5 = 0 CASE 6 Filnam = "WS5" & TRIM$(STR$(CatIdx6)) & ".WAV" 'INCR CatIdx6 'IF CatIdx6 > 3 THEN CatIdx6 = 0 CASE 7 Filnam = "WS6" & TRIM$(STR$(CatIdx7)) & ".WAV" 'INCR CatIdx7 'IF CatIdx7 > 4 THEN CatIdx7 = 0 CASE 8 Filnam = "WS7" & TRIM$(STR$(CatIdx8)) & ".WAV" 'INCR CatIdx8 'IF CatIdx8 > 15 THEN CatIdx8 = 0 END SELECT Filnam = ".\WoodSt~1\" + TRIM$(LCASE$(Filnam)) + CHR$(0) ' here we check for the existence of these files... IF ISFALSE Existfile(UCASE$(Filnam)) THEN StopTask %AudioPlaySample_Task EXIT SUB END IF ' sofar we know that the file exists... ' so, lets try loading it into a free track: END IF SELECT CASE Jumpval CASE %False retval = PlayWaveFile (Filnam, %MODULATE_VOLUME OR %MODULATE_PANNING) SELECT CASE retval CASE > 15 ' means we played the file without using the waveouthandle. StopTask %AudioPlaySample_Task EXIT SUB CASE 0 TO 15 ' bereken de duur van het te spelen sample... tracknr = retval duur = TrackDuration(Tracknr) ' in milliseconds Jumpval = %True Task(%AudioPlaySample_Task).freq = 1000 / duur EXIT SUB CASE -2 ' no need to try again... StopTask %AudioPlaySample_Task EXIT SUB CASE -1 ' wait until device becomes available... Jumpval = %False Task(%AudioPlaySample_Task).freq = 5 EXIT SUB END SELECT CASE %True IF TrackStatus.playing(tracknr) THEN Task(%AudioPlaySample_Task).freq = 36 EXIT SUB END IF ' now we can stop the task and free its resources: Task(%AudioPlaySample_Task).tog = %False Task(%AudioPlaySample_Task).freq = 20 StopTask %AudioPlaySample_Task END SELECT END SUB SUB WoodstockJazzDelayInvertFast () ' This delay plays at always increasing speed. ' All intervals are inverted. ' The mirror note for the inversion depends on ' the momentaneous note played by the Clarinet. LOCAL nv% LOCAL noot? LOCAL velo? STATIC delaytime AS DWORD STATIC SPEED AS SINGLE IF ISFALSE Task(%InvFast_Task).tog THEN IF (Task(%InvFast_Task).swit AND %TASK_BUSY) = %d1 THEN EXIT SUB nv% = GetPromil% IF nv% <= %False THEN StopTask %InvFast_Task EXIT SUB END IF Task(%InvFast_Task).tog = %True delaytime = nv% * App.Komposduur SPEED = 1.3! * (1! + (SPEED/10!)) ' 1.5 = double speed - this goes accellerando! ' the value changes for each new call to the task. END IF nv% = ReadDelayLine%(%InvFast_Task, delaytime, SPEED) SELECT CASE nv% CASE %False, %NotFalse EXIT SUB ' if no note came in, exit the task CASE -2 ' read past present. Task(%InvFast_Task).Har.vel = STRING$(128,0) PlayHar Task(%InvFast_Task).Har, Task(%InvFast_Task).channel nv% = ReadDelayLine%(%InvFast_Task, 0, 0) ' force a reset Task(%InvFast_Task).tog = %False ' force calculation of a new delay time StopTask %InvFast_Task ' stop the task. EXIT SUB END SELECT velo? = LOBYT (nv%) noot? = HIBYT (nv%) noot? = LastNotePlayed + LastNotePlayed - noot? IF noot? > 127 THEN EXIT SUB IF noot? <=0 THEN EXIT SUB Task(%InvFast_Task).Har.vel = STRING$(128,0) ' monophonic IF velo? THEN AddNote2Har Task(%InvFast_Task).Har, (noot?),(velo?) PlayHar Task(%InvFast_Task).Har , Task(%InvFast_Task).channel END SUB SUB WoodstockJazzDelayBackInvert () ' plays backwards with inverted intervals LOCAL nv% LOCAL noot? LOCAL velo? STATIC delaytime AS DWORD STATIC SPEED AS SINGLE IF ISFALSE Task(%BackInv_Task).tog THEN IF (Task(%BackInv_Task).swit AND %TASK_BUSY) = %d1 THEN EXIT SUB nv% = GetPromil% ' nv just used to save another variable... IF nv% <= %False THEN StopTask %BackInv_Task EXIT SUB END IF Task(%BackInv_Task).tog = %True delaytime = nv% * App.Komposduur SPEED = 1.3! * (1! + (ABS(SPEED)/10!)) ' 1.5 = double speed - this goes accellerando! ' the value changes for each new call to the task. SPEED = - SPEED END IF nv% = ReadDelayLine%(%BackInv_Task, delaytime, SPEED) ' speed is negative, so we play backwards SELECT CASE nv% CASE %False, %NotFalse, -2 EXIT SUB ' if no note came in, exit the task CASE -3 ' read past delay in backwardsmode: force reset, stop task. Task(%BackInv_Task).Har.vel = STRING$(128,0) PlayHar Task(%BackInv_Task).Har, Task(%BackInv_Task).channel ' notes off nv% = ReadDelayLine%(%BackInv_Task, 0, 0) ' force a reset Task(%BackInv_Task).tog = %False ' force calculation of a new delay time StopTask %BackInv_Task ' stop the task. EXIT SUB END SELECT velo? = LOBYT (nv%) noot? = HIBYT (nv%) noot? = LastNotePlayed + LastNotePlayed - noot? ' we mirror/invert the intervals IF noot? > 127 THEN EXIT SUB IF noot? <=0 THEN EXIT SUB Task(%BackInv_Task).Har.vel = STRING$(128,0) ' monophonic IF velo? THEN AddNote2Har Task(%BackInv_Task).Har, (noot?),(velo?) PlayHar Task(%BackInv_Task).Har , Task(%BackInv_Task).channel END SUB SUB WoodstockJazzDelayBackSlow () ' plays backwards at decreasing lower speed ' This task does not always stop before the end of the piece, if not stopped by an interactive event. LOCAL nv% LOCAL noot? LOCAL velo? STATIC delaytime AS DWORD ' in ms STATIC COUNT AS DWORD STATIC SPEED AS SINGLE IF ISFALSE Task(%BackSlow_Task).tog THEN IF (Task(%BackSlow_Task).swit AND %TASK_BUSY) = %d1 THEN EXIT SUB nv% = GetPromil% ' nv just used to save another variable... IF nv% <= %False THEN StopTask %BackSlow_Task EXIT SUB END IF Task(%BackSlow_Task).tog = %True delaytime = 500 'keep it constant to 500ms instead of doing delaytime = nv% * App.Komposduur INCR COUNT SPEED = -(1 -COUNT/Pi) 'slower & negative ' TO BE CHECKED!!!!!!!!!!!!!!!!! ' -0.68169 , -0.3633, -0.045 IF SPEED < -0.045 THEN SPEED = -0.045 ' the value changes for each new call to the task. END IF nv% = ReadDelayLine%(%BackSlow_Task, delaytime, SPEED) ' speed is negative, so we play backwards SELECT CASE nv% CASE %False, %NotFalse, -2 EXIT SUB ' if no note came in, exit the task CASE -3 ' read past delay in backwardsmode: force reset, stop task. cannot happen... Task(%BackSlow_Task).Har.vel = STRING$(128,0) PlayHar Task(%BackSlow_Task).Har, Task(%BackSlow_Task).channel ' notes off nv% = ReadDelayLine%(%BackSlow_Task, 0, 0) ' force a reset Task(%BackSlow_Task).tog = %False ' force calculation of a new delay time StopTask %BackSlow_Task ' stop the task. EXIT SUB END SELECT velo? = LOBYT (nv%) noot? = HIBYT (nv%) - 12 ' octave down ' no inversion of intervals. IF noot? > 127 THEN EXIT SUB IF noot? <= 0 THEN EXIT SUB Task(%BackSlow_Task).Har.vel = STRING$(128,0) ' monophonic IF velo? THEN AddNote2Har Task(%BackSlow_Task).Har, (noot?),(velo?) PlayHar Task(%BackSlow_Task).Har , Task(%BackSlow_Task).channel END SUB SUB WoodstockJazzDelayPlayerNormal () ' this taskprocedure demonstrates how to build a delay-line for ' midi input. This one outputs at normal speed. LOCAL nv% LOCAL noot? LOCAL velo? IF ISFALSE Task(%Gerade_Task).tog THEN IF (Task(%Gerade_Task).swit AND %TASK_BUSY) = %d1 THEN EXIT SUB Task(%Gerade_Task).tog = %True END IF nv% = ReadDelayLine%(%Gerade_Task, 5000, 1!) ' 5 second delay ' > 1 speed-up ' < 1 slow down SELECT CASE nv% CASE %False EXIT SUB CASE %NotFalse EXIT SUB ' if no note came in, exit the task CASE -2 ' read past present. ' This can only happen if speed! > 1! nv% = ReadDelayLine%(%Gerade_Task, 0, 0) ' force a reset StopTask %Gerade_Task ' switch task off on error. EXIT SUB END SELECT velo? = LOBYT (nv%) noot? = HIBYT (nv%) - 24 IF noot? <= %False THEN velo? = %False : Noot? = %False ' lets implement full polyphonic playing: IF velo? = %False THEN DelNote2Har Task(%Gerade_Task).Har, (noot?) PlayHar Task(%Gerade_Task).Har, Task(%Gerade_Task).channel ELSE DelNote2Har Task(%Gerade_Task).Har, (noot) PlayHar Task(%Gerade_Task).Har, Task(%Gerade_Task).channel AddNote2Har Task(%Gerade_Task).Har, (noot?), (velo?) PlayHar Task(%Gerade_Task).Har , Task(%Gerade_Task).channel END IF END SUB '[EOF] _ _