-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Handling of MIDI messages and files -- -- MIDI is the Musical Instrument Digital Interface. The package contains -- definition of realtime and file MIDI messages, reading and writing -- MIDI files, and some definitions from the General MIDI standard. It -- contains no sending and receiving of MIDI messages. For this purpose -- see the alsa-seq, jack, PortMidi, -- hmidi packages. For music composition with MIDI output, see -- haskore. Alternative packages are HCodecs, -- zmidi-core. @package midi @version 0.2 -- | Definition of a datatype that reports on the success of a parser. module Sound.MIDI.Parser.Report -- | 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) or an eventual non-fixable problem indicated by (Left -- errorMessage). data T a Cons :: [UserMessage] -> Either UserMessage a -> T a warnings :: T a -> [UserMessage] result :: T a -> Either UserMessage a type UserMessage = String instance Show a => Show (T a) instance Eq a => Eq (T a) -- | Taken from Haskore. module Sound.MIDI.IO -- | Like openFile, but open the file in binary mode. On Windows, -- reading a file in text mode (which is the default) will translate CRLF -- to LF, and writing will translate LF to CRLF. This is usually what you -- want with text files. With binary files this is undesirable; also, as -- usual under Microsoft operating systems, text mode treats control-Z as -- EOF. Binary mode turns off all special treatment of end-of-line and -- end-of-file characters. (See also hSetBinaryMode.) openBinaryFile :: FilePath -> IOMode -> IO Handle readBinaryFile :: FilePath -> IO ByteList -- | Hugs makes trouble here because it performs UTF-8 conversions. E.g. -- [255] is output as [195,191] It would be easy to -- replace these routines by FastPackedString(fps).ByteList.Lazy, however -- this introduces a new package dependency. writeBinaryFile :: FilePath -> ByteList -> IO () type ByteList = [Word8] listCharFromByte :: ByteList -> String listByteFromChar :: String -> ByteList -- | MIDI controller data type and common controller definitions. -- -- See http://www.midi.org/techspecs/midimessages.php. module Sound.MIDI.Controller type T = Controller type Value = Int fromInt :: Int -> T toInt :: T -> Int bankSelect, generalPurpose4, generalPurpose3, generalPurpose2, generalPurpose1, effectControl2, effectControl1, expression, panorama, balance, volume, dataEntry, portamentoTime, footControl, breathControl, modulation :: T vectorX, phaserDepth, celesteDepth, chorusDepth, tremoloDepth, externalEffectDepth, chorusSendLevel, reverbSendLevel, vibratoDelay, vibratoDepth, vibratoRate, decayTime, brightness, attackTime, releaseTime, harmonicIntensity, timbre, soundVariation, vectorY :: T sustain, effect5Depth, effect4Depth, effect3Depth, effect2Depth, effect1Depth, portamentoControl, generalPurpose8, generalPurpose7, generalPurpose6, generalPurpose5, soundController10, soundController9, soundController8, soundController7, soundController6, soundController5, soundController4, soundController3, soundController2, soundController1, hold2, legato, softPedal, sustenuto, portamento :: T bankSelectMSB, generalPurpose4MSB, generalPurpose3MSB, generalPurpose2MSB, generalPurpose1MSB, effectControl2MSB, effectControl1MSB, expressionMSB, panoramaMSB, balanceMSB, volumeMSB, dataEntryMSB, portamentoTimeMSB, footControlMSB, breathControlMSB, modulationMSB :: T bankSelectLSB, generalPurpose4LSB, generalPurpose3LSB, generalPurpose2LSB, generalPurpose1LSB, effectControl2LSB, effectControl1LSB, expressionLSB, panoramaLSB, balanceLSB, volumeLSB, dataEntryLSB, portamentoTimeLSB, footControlLSB, breathControlLSB, modulationLSB :: T dataIncrement, registeredParameterMSB, registeredParameterLSB, nonRegisteredParameterMSB, nonRegisteredParameterLSB, dataDecrement :: T -- | System Real Time messages module Sound.MIDI.Message.System.RealTime data T TimingClock :: T Start :: T Continue :: T Stop :: T ActiveSensing :: T Reset :: T get :: C parser => Int -> Fallible parser T put :: C writer => T -> writer instance Eq T instance Ord T instance Show T instance Enum T instance Ix T module Sound.MIDI.KeySignature data T Cons :: Mode -> Accidentals -> T -- | Accidentals as used in key signature. newtype Accidentals Accidentals :: Int -> Accidentals -- | The Key Signature specifies a mode, either major or minor. data Mode Major :: Mode Minor :: Mode keyName :: Mode -> Accidentals -> String cfMajor, csMajor, fsMajor, bMajor, eMajor, aMajor, dMajor, gMajor, cMajor, fMajor, bfMajor, efMajor, afMajor, dfMajor, gfMajor :: T afMinor, asMinor, dsMinor, gsMinor, csMinor, fsMinor, bMinor, eMinor, aMinor, dMinor, gMinor, cMinor, fMinor, bfMinor, efMinor :: T get :: C parser => Fallible parser T toBytes :: T -> [Int] instance Show Mode instance Eq Mode instance Ord Mode instance Ix Mode instance Enum Mode instance Bounded Mode instance Show Accidentals instance Eq Accidentals instance Ord Accidentals instance Ix Accidentals instance Eq T instance Ord T instance Arbitrary Accidentals instance Random Accidentals instance Enum Accidentals instance Bounded Accidentals instance Arbitrary Mode instance Random Mode instance Arbitrary T instance Show T -- | Channel mode messages module Sound.MIDI.Message.Channel.Mode data T AllSoundOff :: T ResetAllControllers :: T LocalControl :: Bool -> T AllNotesOff :: T OmniMode :: Bool -> T MonoMode :: Int -> T PolyMode :: T get :: C parser => Int -> Fallible parser T put :: C writer => T -> writer -- | This function is also used in alsa-midi, we could give it the result -- type Parser.PossiblyIncomplete T otherwise. fromControllerValue :: (Show a, Integral a) => (a, a) -> (Maybe UserMessage, T) toControllerValue :: Integral a => T -> (a, a) instance Show T instance Eq T instance Ord T instance Arbitrary T -- | System Common messages module Sound.MIDI.Message.System.Common data T TimeCodeQuarterFrame :: TimeNibbleType -> Int -> T SongPositionPointer :: Int -> T SongSelect :: Int -> T TuneRequest :: T data TimeNibbleType FrameLS :: TimeNibbleType FrameMS :: TimeNibbleType SecondsLS :: TimeNibbleType SecondsMS :: TimeNibbleType MinutesLS :: TimeNibbleType MinutesMS :: TimeNibbleType HoursLS :: TimeNibbleType -- | also includes SMPTE type HoursMS :: TimeNibbleType get :: C parser => Int -> Fallible parser T put :: C writer => T -> writer instance Eq TimeNibbleType instance Ord TimeNibbleType instance Show TimeNibbleType instance Enum TimeNibbleType instance Ix TimeNibbleType -- | MIDI device manufacturers and their id's. module Sound.MIDI.Manufacturer data T get :: C parser => Fallible parser T put :: C writer => T -> writer sequential, lyrrus, stLouis, angelSoftware, antares, virtualDSP, boomTheory, nationalSemiconductor, staccato, cakewalk, bitheadz, syndyne, dbx, nemesys, tSquareDesign, inVision, pavo, walker, soundSculpture, newtek, torComp, justonic, idrc, sapphire, chromaticResearch, vlsi, altech, vanKoevering, headspace, fastForward, microsoftConsumer, castLighting, topaz, preSonus, midiman, siliconGraphics, rockwell, crystal, crystalake, keyElectronics, otari, brooktree, mediaTrix, ess, nVidia, westrex, qSoundLabs, midisoft, electrovoice, eTek, taHorng, musonix, loneWolf, interMIDI, euphonix, grooveTubes, intone, rjmgNiche, softwareToolworks, microsoft, richmond, adLib, nsi, etaLighting, hotzInstruments, ibm, gallienKrueger, aphex, musicQuest, allenOrgan, broderbund, ssResearch, cti, voce, uptown, encore, blueSkyLogic, rogers, cannon, pianoDisc, rocktron, cae, breakaway, kti, orban, axxes, zeta, marquis, spectrum, systems360, peavey, brenell, kmx, anadi, rane, opcode, kat, perfectFret, studerEditech, dod, alesis, lakeButler, southernMusic, ivl, artisyn, newEngland, iota, digitalMusic, timeWarner, clarity, keyConcepts, inventronics, eventide, baldwin, art, harmony, emu, adamsSmith, lowrey, jlCooper, palmTree, digidesign, greyMatter, apple, oberheim, ensoniq, garfield, ada, waveframe, voyce, akg, gulbransen, fender, kurzweil, lexicon, passport, moog, octavePlateau, idp :: T passac, ibk, proel, terratec, hanmesoft, synoptic, access, behringer, emagic, tesi, lgSemiconductor, beeOH, blueChip, charlieLab, medeli, tcElectronic, bssAudio, dda, jimMarshall, adb, kenton, forefront, miconAudio, zero88lighting, larkingAudio, miditemp, fbtElectronica, bontempiFarfisa, audiomatica, yesTechnology, realWorldDesign, trident, drBohm, amek, strandLighting, dream, quasimidi, waldorf, digigram, avab, wersi, soundcraft, generalMusic, audioArchitect, clavia, viscount, dynacord, elka, audioVeritrieb, ssl, jen, ppg, southworth, jellinghaus, solton, twister, hohner, synthaxe, siel :: T kawai, suzuki, matsushitaComm, midori, zoom, fostex, matsushitaElec, teac, nisshinOnpa, sony, fujitsuElect, hoshinoGakki, mesosha, japanVictor, akai, kamiya, casio, yamaha, korg, roland :: T nonCommercial, realTime, nonRealTime :: T instance Show T instance Eq T instance Ord T -- | System Exclusive messages module Sound.MIDI.Message.System.Exclusive data T Commercial :: T -> ByteList -> T NonCommercial :: ByteList -> T NonRealTime :: NonRealTime -> T RealTime :: RealTime -> T get :: C parser => Fallible parser T getIncomplete :: C parser => Partial (Fallible parser) T -- | It is not checked whether SysEx messages contain only 7-bit values. put :: C writer => T -> writer -- | System messages module Sound.MIDI.Message.System data T Exclusive :: T -> T Common :: T -> T RealTime :: T -> T get :: C parser => Int -> Fallible parser T getIncomplete :: C parser => Int -> Partial (Fallible parser) T put :: C writer => T -> writer module Sound.MIDI.File.Event.SystemExclusive -- | There are three forms of System Exclusive Messages in MIDI files: -- monolithic, 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 which 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. data T Regular :: ByteList -> T Escape :: ByteList -> T get :: C parser => Int -> Fallible parser T put :: C writer => T -> writer instance Show T instance Eq T instance Ord T -- | Channel voice messages module Sound.MIDI.Message.Channel.Voice data T NoteOff :: Pitch -> Velocity -> T NoteOn :: Pitch -> Velocity -> T PolyAftertouch :: Pitch -> Pressure -> T ProgramChange :: Program -> T Control :: T -> ControllerValue -> T PitchBend :: PitchBendRange -> T MonoAftertouch :: Pressure -> T get :: C parser => Int -> Int -> Fallible parser T putWithStatus :: C writer => (Int -> T writer) -> T -> T writer type ControllerValue = Value type PitchBendRange = Int type Pressure = Int isNote :: T -> Bool -- | NoteOn with zero velocity is considered NoteOff according to MIDI -- specification. isNoteOn :: T -> Bool -- | NoteOn with zero velocity is considered NoteOff according to MIDI -- specification. isNoteOff :: T -> Bool -- | A MIDI problem is that one cannot uniquely map a MIDI key to a -- frequency. The frequency depends on the instrument. I don't know if -- the deviations are defined for General MIDI. If 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. zeroKey :: Pitch -- | Convert all NoteOn p 0 to NoteOff p 64. The latter -- one is easier to process. explicitNoteOff :: T -> T -- | Convert all NoteOff p 64 to NoteOn p 0. The latter -- one can be encoded more efficiently using the running status. implicitNoteOff :: T -> T -- | Map integral MIDI controller value to floating point value. Maximum -- integral MIDI controller value 127 is mapped to 1. Minimum integral -- MIDI controller value 0 is mapped to 0. realFromControllerValue :: (Integral a, Fractional b) => a -> b bankSelect, vectorY, vectorX, generalPurpose4, generalPurpose3, generalPurpose2, generalPurpose1, expression, panorama, balance, mainVolume, dataEntry, portamentoTime, footControl, breathControl, modulation :: T bankSelectMSB, generalPurpose4MSB, generalPurpose3MSB, generalPurpose2MSB, generalPurpose1MSB, expressionMSB, panoramaMSB, balanceMSB, mainVolumeMSB, dataEntryMSB, portamentoTimeMSB, footControlMSB, breathControlMSB, modulationMSB :: T bankSelectLSB, generalPurpose4LSB, generalPurpose3LSB, generalPurpose2LSB, generalPurpose1LSB, expressionLSB, panoramaLSB, balanceLSB, mainVolumeLSB, dataEntryLSB, portamentoTimeLSB, footControlLSB, breathControlLSB, modulationLSB :: T sustain, phaserDepth, celesteDepth, chorusDepth, tremoloDepth, extDepth, generalPurpose8, generalPurpose7, generalPurpose6, generalPurpose5, hold2, softPedal, sustenuto, porta :: T dataIncrement, registeredParameterMSB, registeredParameterLSB, nonRegisteredParameterMSB, nonRegisteredParameterLSB, dataDecrement :: T data Pitch fromPitch :: Pitch -> Int toPitch :: Int -> Pitch data Velocity fromVelocity :: Velocity -> Int toVelocity :: Int -> Velocity data Program fromProgram :: Program -> Int toProgram :: Int -> Program -- | We do not define Controller as enumeration with many -- constructors, because some controllers 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 -- lookup instead. -- --
-- maybe (putStrLn "unsupported controller") putStrLn $ -- lookup ctrl $ -- (portamento, "portamento") : -- (modulation, "modulation") : -- [] --data Controller fromController :: Controller -> Int toController :: Int -> Controller increasePitch :: Int -> Pitch -> Pitch subtractPitch :: Pitch -> Pitch -> Int -- | Convert pitch to frequency according to the default tuning given in -- MIDI 1.0 Detailed Specification. frequencyFromPitch :: Floating a => Pitch -> a -- | The velocity of an ordinary key stroke and the maximum possible -- velocity. normalVelocity, maximumVelocity :: Velocity -- | MIDI specification says, if velocity is simply mapped to amplitude, -- then this should be done by an exponential function. Thus we map -- normalVelocity (64) to 0, maximumVelocity (127) to 1, -- and minimumVelocity (1) to -1. That is, normally you should -- write something like amplitude = 2 ** realFromVelocity vel or -- 3 ** realFromVelocity vel. realFromVelocity :: Fractional b => Velocity -> b instance Show Pitch instance Eq Pitch instance Ord Pitch instance Ix Pitch instance Show Velocity instance Eq Velocity instance Ord Velocity instance Show Program instance Eq Program instance Ord Program instance Ix Program instance Show T instance Eq T instance Ord T instance Bounded Program instance Bounded Velocity instance Bounded Pitch instance Enum Program instance Enum Pitch instance Arbitrary Program instance Random Program instance Arbitrary Velocity instance Random Velocity instance Arbitrary Pitch instance Random Pitch instance Arbitrary T -- | Channel messages module Sound.MIDI.Message.Channel data T Cons :: Channel -> Body -> T messageChannel :: T -> Channel messageBody :: T -> Body data Body Voice :: T -> Body Mode :: T -> Body -- | 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. get :: C parser => Int -> Channel -> Int -> Fallible parser T -- | Parse an event. Note that in the case of a regular MIDI Event, the tag -- is the status, and we read the first byte of data before we call -- get. In the case of a MIDIEvent with running status, we find -- out the status from the parser (it's been nice enough to keep track of -- it for us), and the tag that we've already gotten is the first byte of -- data. getWithStatus :: C parser => Int -> Fallible (T parser) T put :: C writer => T -> writer putWithStatus :: C writer => T -> T writer -- | This definition should be in Message.Channel, but this results in a -- cyclic import. data Channel fromChannel :: Channel -> Int toChannel :: Int -> Channel data Pitch fromPitch :: Pitch -> Int toPitch :: Int -> Pitch data Velocity fromVelocity :: Velocity -> Int toVelocity :: Int -> Velocity data Program fromProgram :: Program -> Int toProgram :: Int -> Program -- | We do not define Controller as enumeration with many -- constructors, because some controllers 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 -- lookup instead. -- --
-- maybe (putStrLn "unsupported controller") putStrLn $ -- lookup ctrl $ -- (portamento, "portamento") : -- (modulation, "modulation") : -- [] --data Controller fromController :: Controller -> Int toController :: Int -> Controller -- | for internal use decodeStatus :: Int -> (Int, Channel) instance Show Body instance Eq Body instance Ord Body instance Show T instance Eq T instance Ord T instance Arbitrary T -- | MIDI messages for real-time communication with MIDI devices. This does -- not cover MIDI file events. For these refer to -- Sound.MIDI.File.Event. module Sound.MIDI.Message data T Channel :: T -> T System :: T -> T get :: C parser => Fallible parser T getWithStatus :: C parser => Fallible (T parser) T getIncompleteWithStatus :: C parser => Partial (Fallible (T parser)) T put :: C writer => T -> writer putWithStatus :: C writer => T -> T writer maybeFromByteString :: ByteString -> T T toByteString :: T -> ByteString module Sound.MIDI.File.Event.Meta data T SequenceNum :: Int -> T TextEvent :: String -> T Copyright :: String -> T TrackName :: String -> T InstrumentName :: String -> T Lyric :: String -> T Marker :: String -> T CuePoint :: String -> T MIDIPrefix :: Channel -> T EndOfTrack :: T SetTempo :: Tempo -> T SMPTEOffset :: SMPTEHours -> SMPTEMinutes -> SMPTESeconds -> SMPTEFrames -> SMPTEBits -> T TimeSig :: Int -> Int -> Int -> Int -> T KeySig :: T -> T SequencerSpecific :: ByteList -> T Unknown :: Int -> ByteList -> T type ElapsedTime = Integer fromElapsedTime :: ElapsedTime -> Integer toElapsedTime :: Integer -> ElapsedTime type Tempo = Int fromTempo :: Tempo -> Int toTempo :: Int -> Tempo -- | The default SetTempo value, in microseconds per quarter note. This -- expresses the default of 120 beats per minute. defltTempo :: Tempo type SMPTEHours = Int type SMPTEMinutes = Int type SMPTESeconds = Int type SMPTEFrames = Int type SMPTEBits = Int get :: C parser => Fallible parser T put :: C writer => T -> writer instance Show T instance Eq T instance Ord T instance Arbitrary T -- | MIDI messages in MIDI files. They are not a superset of the messages, -- that are used for real-time communication between MIDI devices. For -- these refer to Sound.MIDI.Message. Namely System Common and -- System Real Time messages are missing. If you need both real-time and -- file messages (say for ALSA sequencer), you need a custom datatype. module Sound.MIDI.File.Event data T MIDIEvent :: T -> T MetaEvent :: T -> T SystemExclusive :: T -> T get :: C parser => Fallible (T parser) T -- | The following functions encode various T elements into the raw -- data of a standard MIDI file. put :: C writer => T -> T writer type TrackEvent = (ElapsedTime, T) -- | Each event is preceded by the delta time: the time in ticks between -- the last event and the current event. Parse a time and an event, -- ignoring System Exclusive messages. getTrackEvent :: C parser => Fallible (T parser) TrackEvent type ElapsedTime = Integer fromElapsedTime :: ElapsedTime -> Integer toElapsedTime :: Integer -> ElapsedTime mapBody :: (T -> T) -> (TrackEvent -> TrackEvent) maybeMIDIEvent :: T -> Maybe T maybeMetaEvent :: T -> Maybe T maybeVoice :: T -> Maybe (Channel, T) mapVoice :: (T -> T) -> T -> T instance Show T instance Eq T instance Ord T instance Arbitrary T module Sound.MIDI.Message.Class.Check -- | All methods have default implementations that return Nothing. -- This helps implementing event data types that support only a subset of -- types of events. -- -- Maybe a better approach is to provide type classes for every type of -- event and make C a subclass of all of them. class C event where note _chan _ev = Nothing program _chan _ev = Nothing anyController _chan _ev = Nothing pitchBend _chan _ev = Nothing channelPressure _chan _ev = Nothing mode _chan _ev = Nothing note :: C event => Channel -> event -> Maybe (Velocity, Pitch, Bool) program :: C event => Channel -> event -> Maybe Program anyController :: C event => Channel -> event -> Maybe (Controller, Int) pitchBend :: C event => Channel -> event -> Maybe Int channelPressure :: C event => Channel -> event -> Maybe Int mode :: C event => Channel -> event -> Maybe T controller :: C event => Channel -> Controller -> event -> Maybe Int liftMidi :: (Channel -> T -> Maybe a) -> (Channel -> T -> Maybe a) instance C T instance C T module Sound.MIDI.Message.Class.Query -- | All methods have default implementations that return Nothing. -- This helps implementing event data types that support only a subset of -- types of events. -- -- Maybe a better approach is to provide type classes for every type of -- event and make C a subclass of all of them. class C event where note _ev = Nothing program _ev = Nothing anyController _ev = Nothing pitchBend _ev = Nothing channelPressure _ev = Nothing mode _ev = Nothing note :: C event => event -> Maybe (Channel, (Velocity, Pitch, Bool)) program :: C event => event -> Maybe (Channel, Program) anyController :: C event => event -> Maybe (Channel, (Controller, Int)) pitchBend :: C event => event -> Maybe (Channel, Int) channelPressure :: C event => event -> Maybe (Channel, Int) mode :: C event => event -> Maybe (Channel, T) liftMidi :: (T -> Maybe (Channel, a)) -> (T -> Maybe (Channel, a)) instance C T instance C T -- | General-MIDI definitions. -- -- Taken from Haskore. module Sound.MIDI.General instrumentNameToProgram :: String -> Maybe Program instrumentNames :: [String] instrumentPrograms :: [(String, Program)] instrumentFromProgram :: Program -> Instrument instrumentToProgram :: Instrument -> Program instrumentChannels :: [Channel] instruments :: [Instrument] data Instrument AcousticGrandPiano :: Instrument BrightAcousticPiano :: Instrument ElectricGrandPiano :: Instrument HonkyTonk :: Instrument ElectricPiano1 :: Instrument ElectricPiano2 :: Instrument Harpsichord :: Instrument Clavinet :: Instrument Celesta :: Instrument Glockenspiel :: Instrument MusicBox :: Instrument Vibraphone :: Instrument Marimba :: Instrument Xylophone :: Instrument TubularBells :: Instrument Dulcimer :: Instrument DrawbarOrgan :: Instrument PercussiveOrgan :: Instrument RockOrgan :: Instrument ChurchOrgan :: Instrument ReedOrgan :: Instrument Accordion :: Instrument Harmonica :: Instrument TangoAccordian :: Instrument AcousticGuitarNylon :: Instrument AcousticGuitarSteel :: Instrument ElectricGuitarJazz :: Instrument ElectricGuitarClean :: Instrument ElectricGuitarMuted :: Instrument OverdrivenGuitar :: Instrument DistortionGuitar :: Instrument GuitarHarmonics :: Instrument AcousticBass :: Instrument ElectricBassFinger :: Instrument ElectricBassPick :: Instrument FretlessBass :: Instrument SlapBass1 :: Instrument SlapBass2 :: Instrument SynthBass1 :: Instrument SynthBass2 :: Instrument Violin :: Instrument Viola :: Instrument Cello :: Instrument Contrabass :: Instrument TremoloStrings :: Instrument PizzicatoStrings :: Instrument OrchestralHarp :: Instrument Timpani :: Instrument StringEnsemble1 :: Instrument StringEnsemble2 :: Instrument SynthStrings1 :: Instrument SynthStrings2 :: Instrument ChoirAahs :: Instrument VoiceOohs :: Instrument SynthVoice :: Instrument OrchestraHit :: Instrument Trumpet :: Instrument Trombone :: Instrument Tuba :: Instrument MutedTrumpet :: Instrument FrenchHorn :: Instrument BrassSection :: Instrument SynthBrass1 :: Instrument SynthBrass2 :: Instrument SopranoSax :: Instrument AltoSax :: Instrument TenorSax :: Instrument BaritoneSax :: Instrument Oboe :: Instrument EnglishHorn :: Instrument Bassoon :: Instrument Clarinet :: Instrument Piccolo :: Instrument Flute :: Instrument Recorder :: Instrument PanFlute :: Instrument BlownBottle :: Instrument Skakuhachi :: Instrument Whistle :: Instrument Ocarina :: Instrument Lead1Square :: Instrument Lead2Sawtooth :: Instrument Lead3Calliope :: Instrument Lead4Chiff :: Instrument Lead5Charang :: Instrument Lead6Voice :: Instrument Lead7Fifths :: Instrument Lead8BassLead :: Instrument Pad1NewAge :: Instrument Pad2Warm :: Instrument Pad3Polysynth :: Instrument Pad4Choir :: Instrument Pad5Bowed :: Instrument Pad6Metallic :: Instrument Pad7Halo :: Instrument Pad8Sweep :: Instrument FX1Rain :: Instrument FX2Soundtrack :: Instrument FX3Crystal :: Instrument FX4Atmosphere :: Instrument FX5Brightness :: Instrument FX6Goblins :: Instrument FX7Echoes :: Instrument FX8SciFi :: Instrument Sitar :: Instrument Banjo :: Instrument Shamisen :: Instrument Koto :: Instrument Kalimba :: Instrument Bagpipe :: Instrument Fiddle :: Instrument Shanai :: Instrument TinkleBell :: Instrument Agogo :: Instrument SteelDrums :: Instrument Woodblock :: Instrument TaikoDrum :: Instrument MelodicTom :: Instrument SynthDrum :: Instrument ReverseCymbal :: Instrument GuitarFretNoise :: Instrument BreathNoise :: Instrument Seashore :: Instrument BirdTweet :: Instrument TelephoneRing :: Instrument Helicopter :: Instrument Applause :: Instrument Gunshot :: Instrument drumChannel :: Channel drumProgram :: Program drumMinKey :: Pitch drumKeyTable :: [(Drum, Pitch)] drumFromKey :: Pitch -> Drum drumToKey :: Drum -> Pitch drums :: [Drum] data Drum AcousticBassDrum :: Drum BassDrum1 :: Drum SideStick :: Drum AcousticSnare :: Drum HandClap :: Drum ElectricSnare :: Drum LowFloorTom :: Drum ClosedHiHat :: Drum HighFloorTom :: Drum PedalHiHat :: Drum LowTom :: Drum OpenHiHat :: Drum LowMidTom :: Drum HiMidTom :: Drum CrashCymbal1 :: Drum HighTom :: Drum RideCymbal1 :: Drum ChineseCymbal :: Drum RideBell :: Drum Tambourine :: Drum SplashCymbal :: Drum Cowbell :: Drum CrashCymbal2 :: Drum Vibraslap :: Drum RideCymbal2 :: Drum HiBongo :: Drum LowBongo :: Drum MuteHiConga :: Drum OpenHiConga :: Drum LowConga :: Drum HighTimbale :: Drum LowTimbale :: Drum HighAgogo :: Drum LowAgogo :: Drum Cabasa :: Drum Maracas :: Drum ShortWhistle :: Drum LongWhistle :: Drum ShortGuiro :: Drum LongGuiro :: Drum Claves :: Drum HiWoodBlock :: Drum LowWoodBlock :: Drum MuteCuica :: Drum OpenCuica :: Drum MuteTriangle :: Drum OpenTriangle :: Drum instance Show Instrument instance Eq Instrument instance Ord Instrument instance Ix Instrument instance Enum Instrument instance Bounded Instrument instance Show Drum instance Eq Drum instance Ord Drum instance Ix Drum instance Enum Drum instance Bounded Drum instance Arbitrary Drum instance Random Drum instance Arbitrary Instrument instance Random Instrument -- | MIDI-File Datatype -- -- Taken from Haskore. module Sound.MIDI.File -- | The datatypes for MIDI Files and MIDI Events data T Cons :: Type -> Division -> [Track] -> T data Division Ticks :: Tempo -> Division SMPTE :: Int -> Int -> Division type Track = T ElapsedTime T data Type Mixed :: Type Parallel :: Type Serial :: Type -- | An empty MIDI file. Tempo is set to one tick per quarter note. empty :: T type ElapsedTime = Integer fromElapsedTime :: ElapsedTime -> Integer toElapsedTime :: Integer -> ElapsedTime type Tempo = Int fromTempo :: Tempo -> Int toTempo :: Int -> Tempo -- | Convert all NoteOn p 0 to NoteOff p 64. The latter -- one is easier to process. explicitNoteOff :: T -> T -- | Convert all NoteOff p 64 to NoteOn p 0. The latter -- one can be encoded more efficiently using the running status. implicitNoteOff :: T -> T getTracks :: T -> [Track] -- | Merge all tracks into a single track according to the MIDI file type. mergeTracks :: C time => Type -> [T time event] -> T time event -- | Process and remove all SetTempo events. The result is an -- event list where the times are measured in seconds. secondsFromTicks :: Division -> T ElapsedTime T -> T Rational T ticksPerQuarterNote :: Division -> Tempo -- | Show the T with one event per line, suited for comparing -- MIDIFiles with diff. Can this be replaced by showFile? showLines :: T -> String -- | A hack that changes the velocities by a rational factor. changeVelocity :: Double -> T -> T -- | Change the time base. resampleTime :: Double -> T -> T showEvent :: T -> ShowS showTime :: ElapsedTime -> ShowS -- | Sort MIDI note events lexicographically. This is to make MIDI files -- unique and robust against changes in the computation. In principle -- Performance.merge should handle this but due to rounding errors in -- Float the order of note events still depends on some internal issues. -- The sample rate of MIDI events should be coarse enough to assert -- unique results. sortEvents :: T -> T -- | Old versions of Haskore.Interface.MIDI.Write wrote -- ProgramChange and SetTempo once at the beginning of a -- file in that order. The current version supports multiple -- ProgramChanges in a track and thus a ProgramChange is -- set immediately before a note. Because of this a ProgramChange -- is now always after a SetTempo. For checking equivalence with -- old MIDI files we can switch this back. progChangeBeforeSetTempo :: T -> T instance Show Type instance Eq Type instance Ord Type instance Ix Type instance Enum Type instance Bounded Type instance Show Division instance Eq Division instance Show T instance Eq T instance Arbitrary Division instance Arbitrary T -- | Loading MIDI Files -- -- This module loads and parses a MIDI File. It can convert it into a -- T data type object or simply print out the contents of the -- file. module Sound.MIDI.File.Load -- | 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 -- maybeFromByteString instead. fromFile :: FilePath -> IO T -- | This function ignores warnings, turns exceptions into errors, and -- return partial results without warnings. Use this only in testing but -- never in production code! fromByteList :: ByteList -> T maybeFromByteList :: ByteList -> T T maybeFromByteString :: ByteString -> T T -- | Functions to show the decoded contents of a MIDI file in an -- easy-to-read format. This is for debugging purposes and should not be -- used in production code. showFile :: FilePath -> IO () -- | Save MIDI data to files. -- -- The functions in this module allow Ts to be written into -- Standard MIDI files (*.mid) that can be read and played by -- music programs such as Cakewalk. module Sound.MIDI.File.Save -- | Directly write to a file. Since chunks lengths are not known before -- writing, we need to seek in a file. Thus you cannot write to pipes -- with this function. toSeekableFile :: FilePath -> T -> IO () -- | The function toFile is the main function for writing T -- values to an actual file. toFile :: FilePath -> T -> IO () -- | Convert a MIDI file to a ByteList. toByteList :: T -> ByteList -- | Convert a MIDI file to a lazy ByteString. toByteString :: T -> ByteString -- | Convert a MIDI file to a lazy ByteString. It converts -- NoteOff p 64 to NoteOn p 0 and then uses the running -- MIDI status in order to compress the file. toCompressedByteString :: T -> ByteString