i@`      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~^ 7The times are relative to the start time of the bundle and do not need to be ordered. The 1 types are used instead of floating point types, -because the latter ones caused unpredictable 'negative number' errors. .The denominator must always be a power of 10, 8this way we can prevent unlimited grow of denominators. 1make ALSA set the time stamps in incoming events  !"#$%&'()*+,-./9Transpose a note event by the given number of semitones. 3Non-note events are returned without modification. IIf by transposition a note leaves the range of representable MIDI notes, then we return Nothing. 01 , > replaceProgram [1,2,3,4] 5 [10,11,12,13]  (True,[10,11,2,13]) 235Interpret program changes as a kind of bank switches .in order to increase the range of instruments :that can be selected via a block of patch select buttons. programAsBanks ns divides the first sum ns instruments into sections of sizes ns!!0, ns!!1, .... HEach program in those sections is interpreted as a bank in a hierarchy, Awhere the lower program numbers are the least significant banks. Programs from sum ns$ on are passed through as they are.  product ns is the number of instruments 'that you can address using this trick. 7In order to avoid overflow it should be less than 128. E.g. programAsBanks [n,m]* interprets subsequent program changes to a (0<=a<n) and n+b (0<=b<m) as a program change to b*n+a. programAsBanks [8,8]! allows to select 64 instruments by 16 program change buttons, whereas programAsBanks [8,4,4] 9allows to address the full range of MIDI 128 instruments !with the same number of buttons. 45/Before every note switch to another instrument Caccording to a list of programs given as state of the State monad. CI do not know how to handle multiple channels in a reasonable way. ECurrently I just switch the instrument independent from the channel, Gand send the program switch to the same channel as the beginning note. 6This function extends 5. &It reacts on external program changes -by seeking an according program in the list. <This way we can reset the pointer into the instrument list. HHowever the search must be limited in order to prevent an infinite loop ;if we receive a program that is not contained in the list. 789:;<)Generate notes according to the key set, /where notes for negative and too large indices 5are padded with keys that are transposed by octaves. =>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ !"#$%&'()*+ ,-./0123456789 :;<=>?@ABC DEFHIJGLMNKPQORSUTVWXYZ[\]^  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\],^_`abcdefgh&Sends (drain) each event individually Bsince the events in the bundle might be created in a lazy manner. ijkl7This function distinguishes between events from portIn %and events that are generated by us. >Our generated events must also send an echo to the input port in order to break  event_input" and thus trigger their delivery. mnopqrs4This allows more complex patterns including pauses, 3notes of different lengths and simultaneous notes. t5Automatically changes the value of a MIDI controller every period' seconds according to a periodic wave. The wave function is a mapping from the phase in [0,1) #to a controller value in the range (-1,1). ?The generation of the wave is controlled by a speed controller (minSpeed and maxSpeed are in waves per second), +the modulation depth and the center value. >The center controller is also the one where we emit our wave. 'That is, when modulation depth is zero $then this effect is almost the same 3as forwarding the controller without modification. OThe small difference is, that we emit a controller value at a regular pattern, "whereas direct control would mean 3that only controller value changes are transfered.   sweep channel B period (speedCtrl, (minSpeed, maxSpeed)) depthCtrl centerCtrl ' (ctrlRange (-1,1) (sin . (2*pi*))) EWe could use the nice Wave abstraction from the synthesizer package, but that'>s a heavy dependency because of multi-parameter type classes. u%The function maintains empty bundles &in order to maintain laziness breaks. :These breaks are import for later merging of the streams. vwxyz{|}~ 3 runCyclePrograms (map VoiceMsg.toProgram [8..12])   runProgramsAsBanks [8,4,4]   runPattern 0.12 (cycleUp 4)  " runPatternTempo 0.12 (cycleUp 4) F runPatternTempo 0.2 (selectFromOctaveChord, cycle [0,1,2,0,1,2,0,1])   runPatternMultiTempo 0.1 (selectFromLimittedChord, let pat = [item 0 1] ./ 1 /. [item 1 1] ./ 2 /. [item 1 1] ./ 1 /. [item 0 1] ./ 2 /. pat in 0 /. pat) ,^_`abcdefghijklmnopqrstuvwxyz{|}~,bcdefghi_a`^jklmnopqrstuvwxyz{|}~,^_a``abcdefghijklmnopqrstuvwxyz{|}~(The returned event list must be finite. &Run two stream processor in parallel. We cannot use the Arrow method &&& since we cannot the first method of the Arrow class.  Consider 'first :: arrow a b -> arrow (c,a) (c,b) and a trigger where  arrow a b generates an event of type b. 4How could we generate additionally an event of type c without having an input event?   cycleProgramsDefer t -After a note that triggers a program change, we won'!t change the program in the next t seconds. .This is in order to allow chords being played 0and in order to skip accidentally played notes.        !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^__`abcdefghijklmnopqrstuvwxyz{|}~w/8pqrs streamed-0.1Sound.MIDI.ALSA.CommonSound.MIDI.ALSA.EventListSound.MIDI.ALSA.Causal SweepState sweepSpeed sweepDepth sweepCenter sweepPhase PatternMulti IndexNotePatternSelectorKeyQueueKeySetEventDataBundleBundleTime deconsTimeTimeAbsHandlesequclientportInportOutqueueinitexitwithsetTimeStamping startQueueconnectconnectTimidity connectLLVMchannelpitchvelocity controllerprogramconsTimeincTimenano makeEventmakeEchosingletonBundle timeFromStampdefaultTempoCtrl transpose setChannelreplaceProgramprogramFromBanksprogramsAsBanks nextProgramtraverseProgramstraverseProgramsSeekreduceNoteVelocitydelayAdd simpleNote eventsFromKeyselectFromLimittedChordselectFromOctaveChordselectFromChordselectFromChordRatio increasePitchselectInversion updateChordcontrollerMatch updateDuritemfractionflipSeqcycleUp cycleDownpingPongcrossSum cycleUpAuto cycleDownAuto pingPongAuto crossSumAutobinaryStaccato binaryLegatobinaryAccidentdecomposePositional cycleUpOctaverandomrandomInversionscycleUpInversions inversionsexamplePatternMultiTempo0examplePatternMultiTempo1 checkChannel checkPitchcheckController checkProgramEventDataTriggerTriggerRegular ioToLazyListinputEventsCore inputEventspairListFromRelativeEvents outputEvent outputEventsoutputEventBundlesoutputEventBundledmakeTriggerEventmakeTriggerEventsoutputTriggerEventsmergeGeneratedequidistantEventswhirlmergeGeneratedAtomspattern patternTempopatternMultiTemposweepfilter filterSimplemergeprocess processSimplerunWhirlrunDelayrunKeyboardSplitrunKeyboardSplitLowrunKeyboardSplitHighrunNoterunKey runController runProgramrunCycleProgramsrunProgramsAsBanks runPatternrunPatternTemporunPatternMultiTemporunFilterSweepmainTConsmapmapMaybecomposeparalleltraversetransposeBundleupdateChordDurupdateSerialChordupdateSerialChordDurpatternSerialTempo partitionmaybeInguide cycleProgramscycleProgramsDefer