ϒL      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                       ?Hugs makes trouble here because it performs UTF-8 conversions. E.g. [255] is output as [195,191] SIt would be easy to replace these routines by FastPackedString(fps).ByteList.Lazy, 2however this introduces a new package dependency. )This datatype is the result of a parser. (First it stores a sequence of warnings. >Warnings are for corruptions of the input which can be fixed. )After encountering a series of warnings, there is finally an end, ,either a successful one, with the result as (Right result) 0or an eventual non-fixable problem indicated by (Left errorMessage).   )This function is also used in alsa-midi, !we could give it the result type Parser.PossiblyIncomplete T otherwise.   !"#$%&'()*+,-'()*+ !"#$%&,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~     .  /0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~   DIt is not checked whether SysEx messages contain only 7-bit values.   We do not define  ( as enumeration with many constructors, Dbecause some controller have multiple names and some are undefined. $It is also more efficient this way. Thus you cannot use case" for processing controller types, but you can use Data.List.lookup instead. 6 maybe (putStrLn "unsupported controller") putStrLn $  lookup ctrl $ ! (portamento, "portamento") : ! (modulation, "modulation") :  [] 4QNoteOn with zero velocity is considered NoteOff according to MIDI specification. 5QNoteOn with zero velocity is considered NoteOff according to MIDI specification. 6 Convert all  NoteOn p 0 to  NoteOff p 64. %The latter one is easier to process. 7 Convert all  NoteOff p 64 to  NoteOn p 0. IThe latter one can be encoded more efficiently using the running status. >/A MIDI problem is that one cannot uniquely map a MIDI key to a frequency. )The frequency depends on the instrument. I don'7t know if the deviations are defined for General MIDI. 8If this applies one could add transposition information to the use patch map. @For now I have chosen a value that leads to the right frequency "for some piano sound in my setup. @+The velocity of an ordinary key stroke and the maximum possible velocity. A764 is given as default value by the MIDI specification and thus we map it to 1. 0 is mapped to 0. ,All other values are interpolated linearly. B<Map integral MIDI controller value to floating point value. ;Maximum integral MIDI controller value 127 is mapped to 1. 9Minimum integral MIDI controller value 0 is mapped to 0. e !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~e+,-./012(*)345>67BCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~&'8$%9"#: !;<=@?A Parse an event. FNote that in the case of a regular MIDI Event, the tag is the status, 2and we read the first byte of data before we call  . 0In the case of a MIDIEvent with running status, 'we find out the status from the parser (it'0s been nice enough to keep track of it for us), and the tag that we'-ve already gotten is the first byte of data. for internal use Parse a MIDI Channel message. ;Note that since getting the first byte is a little complex ((there are issues with running status), &the code, channel and first data byte "must be determined by the caller.  output a channel + message code  !"#$%&'89:;&'8$%9"#: !;  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~   BThere are three forms of System Exclusive Messages in MIDI files: Omonolithic, chopped into packets, escape form (with unrestricted binary data). :Currently we only support first and last type explicitly. 'But we leave the trailing 0xF7 markers Pwhich can be used to detect whether the messages are actually meant as packets.  Since I don'>t know where manufacturer information is in the packets form, &I omit manufacturer handling for now. ;The Key Signature specifies a mode, either major or minor. GThe following enumerated type lists all the keys in order of their key !signatures from flats to sharps. (Cf = 7 flats, Gf = 6 flats ... F = 1 flat, C = 0 flats/sharps, G = 1 sharp, ... Cs = 7 sharps.) Useful for transposition. GDefault duration of a whole note, in seconds; and the default SetTempo Fvalue, in microseconds per quarter note. Both express the default of 120 beats per minute. 33HEach event is preceded by the delta time: the time in ticks between the Glast event and the current event. Parse a time and an event, ignoring System Exclusive messages. 'The following functions encode various  MIDIFile.T elements +into the raw data of a standard MIDI file.  -The datatypes for MIDI Files and MIDI Events An empty MIDI file.  Apply a function to each track.  Convert all  NoteOn p 0 to  NoteOff p 64. %The latter one is easier to process.  Convert all  NoteOff p 64 to  NoteOn p 0. IThe latter one can be encoded more efficiently using the running status.  Show the  with one event per line, $suited for comparing MIDIFiles with diff. Can this be replaced by Sound.MIDI.Load.showFile? 9A hack that changes the velocities by a rational factor. Change the time base. )Sort MIDI note events lexicographically. "This is to make MIDI files unique /and robust against changes in the computation. 2In principle Performance.merge should handle this $but due to rounding errors in Float @the order of note events still depends on some internal issues. 7The sample rate of MIDI events should be coarse enough to assert unique results. Old versions of Haskore.Interface.MIDI.Write wrote MIDIEvent.ProgramChange and  /once at the beginning of a file in that order. &The current version supports multiple MIDIEvent.ProgramChanges in a track and thus a MIDIEvent.ProgramChange# is set immediately before a note. Because of this a MIDIEvent.ProgramChange is now always after a . FFor checking equivalence with old MIDI files we can switch this back.  The main load function. .Warnings are written to standard error output .and an error is signaled by a user exception. ;This function will not be appropriate in GUI applications. For these, use  instead. >This function ignores warnings, turns exceptions into errors, -and return partial results without warnings. 7Use this only in testing but never in production code! A MIDI file is made of chunks, each of which is either a  header chunk or a  track chunk6. To be correct, it must consist of one header chunk :followed by any number of track chunks, but for robustness's sake we ignore Lany non-header chunks that come before a header chunk. The header tells us 1the number of tracks to come, which is passed to . 1There are two ways to mark the end of the track: -The end of the event list and the meta event  EndOfTrack. 1Thus the end marker is redundant and we remove a  EndOfTrack at the end of the track and complain about all  EndOfTracks within the event list. DParse a chunk, whether a header chunk, a track chunk, or otherwise. *A chunk consists of a four-byte type code  (a header is MThd ; a track is MTrk), ,four bytes for the size of the coming data, and the data itself. CParse a Header Chunk. A header consists of a format (0, 1, or 2), Cthe number of track chunks to come, and the smallest time division ,to be used in reading the rest of the file. EThe division is implemented thus: the most significant bit is 0 if it's "in ticks per quarter note; 1 if it's an SMPTE value. FA track is a series of events. Parse a track, stopping when the size  is zero.  QFunctions to show the decoded contents of a MIDI file in an easy-to-read format. JThis is for debugging purposes and should not be used in production code. The two functions, the  and  parsers, 5do not combine directly into a single master parser. 9Rather, they should be used to chop parts of a midi file ;up into chunks of bytes which can be outputted separately. (Chop a MIDI file into chunks returning:  list of  chunk-type-contents pairs; and >* leftover slop (should be empty in correctly formatted file)    Directly write to a file. 3Since chunks lengths are not known before writing, we need to seek in a file. 3Thus you cannot write to pipes with this function.   The function   is the main function  for writing  values to an actual file.  Convert a MIDI file to a .  Convert a MIDI file to a lazy . Convert a MIDI file to a lazy .  It converts  NoteOff p 64 to  NoteOn p 0 Eand then uses the running MIDI status in order to compress the file.          !"#$%&'()*+,$-%./0123456789:;$%<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~     $%$%$% ! " # $ % & ' ( ) * + , - .  / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~        $           $ %                    ! $    %      $ %$%$%9:                                       ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                             midi-0.1.3 Sound.MIDI.IOSound.MIDI.Parser.Report"Sound.MIDI.Message.System.RealTimeSound.MIDI.Message.Channel.Mode Sound.MIDI.Message.System.CommonSound.MIDI.Manufacturer#Sound.MIDI.Message.System.ExclusiveSound.MIDI.Message.SystemSound.MIDI.Message.Channel Sound.MIDI.Message.Channel.VoiceSound.MIDI.GeneralSound.MIDI.Message%Sound.MIDI.File.Event.SystemExclusiveSound.MIDI.File.Event.MetaSound.MIDI.File.EventSound.MIDI.FileSound.MIDI.File.LoadSound.MIDI.File.Savebytestring-0.9.1.4Data.ByteString.Lazy.InternalByteListwriteBinaryFilelistCharFromBytereadBinaryFilelistByteFromChar UserMessageTwarningsresultReset ActiveSensingStopContinueStart TimingClockgetputPolyModeMonoModeOmniMode AllNotesOff LocalControlResetAllControllers AllSoundOfffromControllerValuetoControllerValueTimeNibbleTypeHoursMSHoursLS MinutesMS MinutesLS SecondsMS SecondsLSFrameMSFrameLS TuneRequest SongSelectSongPositionPointerTimeCodeQuarterFrame sequentialidp octavePlateaumoogpassportlexiconkurzweilfender gulbransenakgvoyce waveframeadagarfieldensoniqoberheimapple greyMatter digidesignpalmTreejlCooperlowrey adamsSmithemuharmonyartbaldwineventide inventronics keyConceptsclarity timeWarner digitalMusiciota newEnglandartisynivl southernMusic lakeButleralesisdod studerEditech perfectFretkatopcoderaneanadikmxbrenellpeavey systems360spectrummarquiszetaaxxesorbankti breakawaycaerocktron pianoDisccannonrogers blueSkyLogicencoreuptownvocecti ssResearch broderbund allenOrgan musicQuestaphexgallienKruegeribmhotzInstruments etaLightingnsiadLibrichmond microsoftsoftwareToolworks rjmgNicheintone grooveTubeseuphonix interMIDIloneWolfmusonixtaHorngeTek electrovoicemidisoft qSoundLabswestrexnVidiaess mediaTrix brooktreeotarikeyElectronics crystalakecrystalrockwellsiliconGraphicsmidimanpreSonustopaz castLightingmicrosoftConsumer fastForward headspace vanKoeveringaltechvlsichromaticResearchsapphireidrcjustonictorCompnewteksoundSculpturewalkerpavoinVision tSquareDesignnemesysdbxsyndynebitheadzcakewalkstaccatonationalSemiconductor boomTheory virtualDSPantares angelSoftwarestLouislyrruspassacsielsynthaxehohnertwistersolton jellinghaus southworthppgjensslaudioVeritriebelkadynacordviscountclaviaaudioArchitect generalMusic soundcraftwersiavabdigigramwaldorf quasimididreamstrandLightingamekdrBohmtridentrealWorldDesign yesTechnology audiomaticabontempiFarfisafbtElectronicamiditemp larkingAudiozero88lighting miconAudio forefrontkentonadb jimMarshallddabssAudio tcElectronicmedeli charlieLabblueChipbeeOHlgSemiconductortesiemagic behringeraccesssynoptic hanmesoftterratecproelibkkawairolandkorgyamahacasiokamiyaakai japanVictormesosha hoshinoGakki fujitsuElectsony nisshinOnpateacmatsushitaElecfostexzoommidorimatsushitaCommsuzuki nonCommercial nonRealTimerealTimeRealTime NonRealTime NonCommercial Commercial getIncompleteCommon ExclusiveSound.MIDI.Parser.StatusChannel fromChannel toChannel ControllerfromControllerProgram fromProgramVelocity fromVelocityPitch fromPitchControllerValuePressurePitchBendRangeMonoAftertouch PitchBendControl ProgramChangePolyAftertouchNoteOnNoteOffisNoteisNoteOn isNoteOffexplicitNoteOffimplicitNoteOfftoPitch toVelocity toProgram toController increasePitch subtractPitchzeroKeynormalVelocitymaximumVelocitytoFloatVelocitytoFloatController bankSelect modulation breathControl footControlportamentoTime dataEntry mainVolumebalancepanorama expressiongeneralPurpose1generalPurpose2generalPurpose3generalPurpose4vectorXvectorY bankSelectMSB modulationMSBbreathControlMSBfootControlMSBportamentoTimeMSB dataEntryMSB mainVolumeMSB balanceMSB panoramaMSB expressionMSBgeneralPurpose1MSBgeneralPurpose2MSBgeneralPurpose3MSBgeneralPurpose4MSB bankSelectLSB modulationLSBbreathControlLSBfootControlLSBportamentoTimeLSB dataEntryLSB mainVolumeLSB balanceLSB panoramaLSB expressionLSBgeneralPurpose1LSBgeneralPurpose2LSBgeneralPurpose3LSBgeneralPurpose4LSBsustainporta sustenuto softPedalhold2generalPurpose5generalPurpose6generalPurpose7generalPurpose8extDepth tremoloDepth chorusDepth celesteDepth phaserDepth dataIncrement dataDecrementnonRegisteredParameterLSBnonRegisteredParameterMSBregisteredParameterLSBregisteredParameterMSB putWithStatusBodyModeVoiceConsmessageChannel messageBody getWithStatus decodeStatusDrum InstrumentinstrumentNameToPrograminstrumentNamesinstrumentProgramsinstrumentFromPrograminstrumentToPrograminstrumentChannels instruments drumChannel drumProgram drumMinKey drumKeyTable drumFromKey drumToKeydrumsSystemgetIncompleteWithStatusmaybeFromByteString toByteStringEscapeRegularScaleMinorMajorKeyKeyCsKeyFsKeyBKeyEKeyAKeyDKeyGKeyCKeyFKeyBfKeyEfKeyAfKeyDfKeyGfKeyCfUnknownSequencerSpecificKeySigTimeSig SMPTEOffsetSetTempo EndOfTrack MIDIPrefixCuePointMarkerLyricInstrumentName TrackName Copyright TextEvent SequenceNum SMPTEBits SMPTEFrames SMPTESeconds SMPTEMinutes SMPTEHoursTempo ElapsedTime defltDurTdefltST toElapsedTimefromElapsedTimetoTempo fromTempoSystemExclusive MetaEvent MIDIEvent TrackEventmapBodymaybeMIDIEventmaybeMetaEvent maybeVoicemapVoice getTrackEventTrackDivisionSMPTETicksTypeSerialParallelMixedempty showLinesshowTime showEventchangeVelocity resampleTime getTracks sortEventsprogChangeBeforeSetTempofromFile fromByteListmaybeFromByteListshowFiletoSeekableFiletoFile toByteListtoCompressedByteStringbase GHC.HandleopenBinaryFile putChannel OpenTriangle MuteTriangle OpenCuica MuteCuica LowWoodBlock HiWoodBlockClaves LongGuiro ShortGuiro LongWhistle ShortWhistleMaracasCabasaLowAgogo HighAgogo LowTimbale HighTimbaleLowConga OpenHiConga MuteHiCongaLowBongoHiBongo RideCymbal2 Vibraslap CrashCymbal2Cowbell SplashCymbal TambourineRideBell ChineseCymbal RideCymbal1HighTom CrashCymbal1HiMidTom LowMidTom OpenHiHatLowTom PedalHiHat HighFloorTom ClosedHiHat LowFloorTom ElectricSnareHandClap AcousticSnare SideStick BassDrum1AcousticBassDrumGunshotApplause Helicopter TelephoneRing BirdTweetSeashore BreathNoiseGuitarFretNoise ReverseCymbal SynthDrum MelodicTom TaikoDrum Woodblock SteelDrumsAgogo TinkleBellShanaiFiddleBagpipeKalimbaKotoShamisenBanjoSitarFX8SciFi FX7Echoes FX6Goblins FX5Brightness FX4Atmosphere FX3Crystal FX2SoundtrackFX1Rain Pad8SweepPad7Halo Pad6Metallic Pad5Bowed Pad4Choir Pad3PolysynthPad2Warm Pad1NewAge Lead8BassLead Lead7Fifths Lead6Voice Lead5Charang Lead4Chiff Lead3Calliope Lead2Sawtooth Lead1SquareOcarinaWhistle Skakuhachi BlownBottlePanFluteRecorderFlutePiccoloClarinetBassoon EnglishHornOboe BaritoneSaxTenorSaxAltoSax SopranoSax SynthBrass2 SynthBrass1 BrassSection FrenchHorn MutedTrumpetTubaTromboneTrumpet OrchestraHit SynthVoice VoiceOohs ChoirAahs SynthStrings2 SynthStrings1StringEnsemble2StringEnsemble1TimpaniOrchestralHarpPizzicatoStringsTremoloStrings ContrabassCelloViolaViolin SynthBass2 SynthBass1 SlapBass2 SlapBass1 FretlessBassElectricBassPickElectricBassFinger AcousticBassGuitarHarmonicsDistortionGuitarOverdrivenGuitarElectricGuitarMutedElectricGuitarCleanElectricGuitarJazzAcousticGuitarSteelAcousticGuitarNylonTangoAccordian Harmonica Accordion ReedOrgan ChurchOrgan RockOrganPercussiveOrgan DrawbarOrganDulcimer TubularBells XylophoneMarimba VibraphoneMusicBox GlockenspielCelestaClavinet HarpsichordElectricPiano2ElectricPiano1 HonkyTonkElectricGrandPianoBrightAcousticPianoAcousticGrandPianomapTrackparseremoveEndOfTrackgetChunk getHeader getDivisiongetTrack getChunks ByteString