packages feed

midi 0.0.6 → 0.0.7

raw patch · 6 files changed

+329/−40 lines, 6 files

Files

midi.cabal view
@@ -1,5 +1,5 @@ Name:             midi-Version:          0.0.6+Version:          0.0.7 License:          GPL License-File:     LICENSE Author:           Henning Thielemann <haskell@henning-thielemann.de>
src/Sound/MIDI/Event.hs view
@@ -18,6 +18,22 @@    generalPurpose1, generalPurpose2, generalPurpose3, generalPurpose4,    vectorX, vectorY, +   bankSelectMSB, modulationMSB, breathControlMSB, footControlMSB,+   portamentoTimeMSB, dataEntryMSB, mainVolumeMSB, balanceMSB,+   panoramaMSB, expressionMSB, generalPurpose1MSB, generalPurpose2MSB,+   generalPurpose3MSB, generalPurpose4MSB, bankSelectLSB, modulationLSB,+   breathControlLSB, footControlLSB, portamentoTimeLSB, dataEntryLSB,+   mainVolumeLSB, balanceLSB, panoramaLSB, expressionLSB,+   generalPurpose1LSB, generalPurpose2LSB, generalPurpose3LSB, generalPurpose4LSB,++   sustain, porta, sustenuto, softPedal, hold2,+   generalPurpose5, generalPurpose6, generalPurpose7, generalPurpose8,+   extDepth, tremoloDepth, chorusDepth, celesteDepth, phaserDepth,++   dataIncrement, dataDecrement,+   nonRegisteredParameterLSB, nonRegisteredParameterMSB,+   registeredParameterLSB, registeredParameterMSB,+    fromPitch,     toPitch,    fromVelocity,  toVelocity,    fromProgram,   toProgram,@@ -25,14 +41,16 @@    increasePitch, subtractPitch,   ) where +import Data.Ix (Ix)  + {- * MIDI Events -} -newtype Pitch       = Pitch    {fromPitch    :: Int} deriving (Show, Eq, Ord)+newtype Pitch       = Pitch    {fromPitch    :: Int} deriving (Show, Eq, Ord, Ix) newtype Velocity    = Velocity {fromVelocity :: Int} deriving (Show, Eq, Ord)-newtype Program     = Program  {fromProgram  :: Int} deriving (Show, Eq, Ord)-newtype Channel     = Channel  {fromChannel  :: Int} deriving (Show, Eq, Ord)+newtype Program     = Program  {fromProgram  :: Int} deriving (Show, Eq, Ord, Ix)+newtype Channel     = Channel  {fromChannel  :: Int} deriving (Show, Eq, Ord, Ix)  toPitch :: Int -> Pitch toPitch = checkRange "Pitch" Pitch@@ -119,6 +137,8 @@ {- | 64 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. -} toFloatVelocity :: (Integral a, Fractional b) => a -> b toFloatVelocity x = fromIntegral x / normalVelocity@@ -126,6 +146,11 @@ maximumControllerValue :: Num quant => quant maximumControllerValue = 127 +{- |+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.+-} toFloatController :: (Integral a, Fractional b) => a -> b toFloatController x = fromIntegral x / maximumControllerValue @@ -160,6 +185,139 @@ isNoteOff _             = False  ++{-# DEPRECATED BankSelectMSB             "use bankSelectMSB instead" #-}+{-# DEPRECATED ModulationMSB             "use modulationMSB instead" #-}+{-# DEPRECATED BreathControlMSB          "use breathControlMSB instead" #-}+{-# DEPRECATED Controller03              "use toEnum 0x03 instead" #-}+{-# DEPRECATED FootControlMSB            "use footControlMSB instead" #-}+{-# DEPRECATED PortamentoTimeMSB         "use portamentoTimeMSB instead" #-}+{-# DEPRECATED DataEntryMSB              "use dataEntryMSB instead" #-}+{-# DEPRECATED MainVolumeMSB             "use mainVolumeMSB instead" #-}+{-# DEPRECATED BalanceMSB                "use balanceMSB instead" #-}+{-# DEPRECATED Controller09              "use toEnum 0x09 instead" #-}+{-# DEPRECATED PanoramaMSB               "use panoramaMSB instead" #-}+{-# DEPRECATED ExpressionMSB             "use expressionMSB instead" #-}+{-# DEPRECATED Controller0C              "use toEnum 0x0C instead" #-}+{-# DEPRECATED Controller0D              "use toEnum 0x0D instead" #-}+{-# DEPRECATED Controller0E              "use toEnum 0x0E instead" #-}+{-# DEPRECATED Controller0F              "use toEnum 0x0F instead" #-}+{-# DEPRECATED GeneralPurpose1MSB        "use generalPurpose1MSB instead" #-}+{-# DEPRECATED GeneralPurpose2MSB        "use generalPurpose2MSB instead" #-}+{-# DEPRECATED GeneralPurpose3MSB        "use generalPurpose3MSB instead" #-}+{-# DEPRECATED GeneralPurpose4MSB        "use generalPurpose4MSB instead" #-}+{-# DEPRECATED Controller14              "use toEnum 0x14 instead" #-}+{-# DEPRECATED Controller15              "use toEnum 0x15 instead" #-}+{-# DEPRECATED Controller16              "use toEnum 0x16 instead" #-}+{-# DEPRECATED Controller17              "use toEnum 0x17 instead" #-}+{-# DEPRECATED Controller18              "use toEnum 0x18 instead" #-}+{-# DEPRECATED Controller19              "use toEnum 0x19 instead" #-}+{-# DEPRECATED Controller1A              "use toEnum 0x1A instead" #-}+{-# DEPRECATED Controller1B              "use toEnum 0x1B instead" #-}+{-# DEPRECATED Controller1C              "use toEnum 0x1C instead" #-}+{-# DEPRECATED Controller1D              "use toEnum 0x1D instead" #-}+{-# DEPRECATED Controller1E              "use toEnum 0x1E instead" #-}+{-# DEPRECATED Controller1F              "use toEnum 0x1F instead" #-}+{-# DEPRECATED BankSelectLSB             "use bankSelectLSB instead" #-}+{-# DEPRECATED ModulationLSB             "use modulationLSB instead" #-}+{-# DEPRECATED BreathControlLSB          "use breathControlLSB instead" #-}+{-# DEPRECATED Controller23              "use toEnum 0x23 instead" #-}+{-# DEPRECATED FootControlLSB            "use footControlLSB instead" #-}+{-# DEPRECATED PortamentoTimeLSB         "use portamentoTimeLSB instead" #-}+{-# DEPRECATED DataEntryLSB              "use dataEntryLSB instead" #-}+{-# DEPRECATED MainVolumeLSB             "use mainVolumeLSB instead" #-}+{-# DEPRECATED BalanceLSB                "use balanceLSB instead" #-}+{-# DEPRECATED Controller29              "use toEnum 0x29 instead" #-}+{-# DEPRECATED PanoramaLSB               "use panoramaLSB instead" #-}+{-# DEPRECATED ExpressionLSB             "use expressionLSB instead" #-}+{-# DEPRECATED Controller2C              "use toEnum 0x2C instead" #-}+{-# DEPRECATED Controller2D              "use toEnum 0x2D instead" #-}+{-# DEPRECATED Controller2E              "use toEnum 0x2E instead" #-}+{-# DEPRECATED Controller2F              "use toEnum 0x2F instead" #-}+{-# DEPRECATED GeneralPurpose1LSB        "use generalPurpose1LSB instead" #-}+{-# DEPRECATED GeneralPurpose2LSB        "use generalPurpose2LSB instead" #-}+{-# DEPRECATED GeneralPurpose3LSB        "use generalPurpose3LSB instead" #-}+{-# DEPRECATED GeneralPurpose4LSB        "use generalPurpose4LSB instead" #-}+{-# DEPRECATED Controller34              "use toEnum 0x34 instead" #-}+{-# DEPRECATED Controller35              "use toEnum 0x35 instead" #-}+{-# DEPRECATED Controller36              "use toEnum 0x36 instead" #-}+{-# DEPRECATED Controller37              "use toEnum 0x37 instead" #-}+{-# DEPRECATED Controller38              "use toEnum 0x38 instead" #-}+{-# DEPRECATED Controller39              "use toEnum 0x39 instead" #-}+{-# DEPRECATED Controller3A              "use toEnum 0x3A instead" #-}+{-# DEPRECATED Controller3B              "use toEnum 0x3B instead" #-}+{-# DEPRECATED Controller3C              "use toEnum 0x3C instead" #-}+{-# DEPRECATED Controller3D              "use toEnum 0x3D instead" #-}+{-# DEPRECATED Controller3E              "use toEnum 0x3E instead" #-}+{-# DEPRECATED Controller3F              "use toEnum 0x3F instead" #-}++{-# DEPRECATED Sustain                   "use sustain instead" #-}+{-# DEPRECATED Porta                     "use porta instead" #-}+{-# DEPRECATED Sustenuto                 "use sustenuto instead" #-}+{-# DEPRECATED SoftPedal                 "use softPedal instead" #-}+{-# DEPRECATED Controller44              "use toEnum 0x44 instead" #-}+{-# DEPRECATED Hold2                     "use hold2 instead" #-}+{-# DEPRECATED Controller46              "use toEnum 0x46 instead" #-}+{-# DEPRECATED Controller47              "use toEnum 0x47 instead" #-}+{-# DEPRECATED Controller48              "use toEnum 0x48 instead" #-}+{-# DEPRECATED Controller49              "use toEnum 0x49 instead" #-}+{-# DEPRECATED Controller4A              "use toEnum 0x4A instead" #-}+{-# DEPRECATED Controller4B              "use toEnum 0x4B instead" #-}+{-# DEPRECATED Controller4C              "use toEnum 0x4C instead" #-}+{-# DEPRECATED Controller4D              "use toEnum 0x4D instead" #-}+{-# DEPRECATED Controller4E              "use toEnum 0x4E instead" #-}+{-# DEPRECATED Controller4F              "use toEnum 0x4F instead" #-}+{-# DEPRECATED GeneralPurpose5           "use generalPurpose5 instead" #-}+{-# DEPRECATED GeneralPurpose6           "use generalPurpose6 instead" #-}+{-# DEPRECATED GeneralPurpose7           "use generalPurpose7 instead" #-}+{-# DEPRECATED GeneralPurpose8           "use generalPurpose8 instead" #-}+{-# DEPRECATED Controller54              "use toEnum 0x54 instead" #-}+{-# DEPRECATED Controller55              "use toEnum 0x55 instead" #-}+{-# DEPRECATED Controller56              "use toEnum 0x56 instead" #-}+{-# DEPRECATED Controller57              "use toEnum 0x57 instead" #-}+{-# DEPRECATED Controller58              "use toEnum 0x58 instead" #-}+{-# DEPRECATED Controller59              "use toEnum 0x59 instead" #-}+{-# DEPRECATED Controller5A              "use toEnum 0x5A instead" #-}+{-# DEPRECATED ExtDepth                  "use extDepth instead" #-}+{-# DEPRECATED TremoloDepth              "use tremoloDepth instead" #-}+{-# DEPRECATED ChorusDepth               "use chorusDepth instead" #-}+{-# DEPRECATED CelesteDepth              "use celesteDepth instead" #-}+{-# DEPRECATED PhaserDepth               "use phaserDepth instead" #-}++{-# DEPRECATED DataIncrement             "use dataIncrement instead" #-}+{-# DEPRECATED DataDecrement             "use dataDecrement instead" #-}+{-# DEPRECATED NonRegisteredParameterLSB "use nonRegisteredParameterLSB instead" #-}+{-# DEPRECATED NonRegisteredParameterMSB "use nonRegisteredParameterMSB instead" #-}+{-# DEPRECATED RegisteredParameterLSB    "use registeredParameterLSB instead" #-}+{-# DEPRECATED RegisteredParameterMSB    "use registeredParameterMSB instead" #-}+{-# DEPRECATED Controller66              "use toEnum 0x66 instead" #-}+{-# DEPRECATED Controller67              "use toEnum 0x67 instead" #-}+{-# DEPRECATED Controller68              "use toEnum 0x68 instead" #-}+{-# DEPRECATED Controller69              "use toEnum 0x69 instead" #-}+{-# DEPRECATED Controller6A              "use toEnum 0x6A instead" #-}+{-# DEPRECATED Controller6B              "use toEnum 0x6B instead" #-}+{-# DEPRECATED Controller6C              "use toEnum 0x6C instead" #-}+{-# DEPRECATED Controller6D              "use toEnum 0x6D instead" #-}+{-# DEPRECATED Controller6E              "use toEnum 0x6E instead" #-}+{-# DEPRECATED Controller6F              "use toEnum 0x6F instead" #-}+{-# DEPRECATED Controller70              "use toEnum 0x70 instead" #-}+{-# DEPRECATED Controller71              "use toEnum 0x71 instead" #-}+{-# DEPRECATED Controller72              "use toEnum 0x72 instead" #-}+{-# DEPRECATED Controller73              "use toEnum 0x73 instead" #-}+{-# DEPRECATED Controller74              "use toEnum 0x74 instead" #-}+{-# DEPRECATED Controller75              "use toEnum 0x75 instead" #-}+{-# DEPRECATED Controller76              "use toEnum 0x76 instead" #-}+{-# DEPRECATED Controller77              "use toEnum 0x77 instead" #-}+{-# DEPRECATED Controller78              "use toEnum 0x78 instead" #-}+{-# DEPRECATED Controller79              "use toEnum 0x79 instead" #-}+{-# DEPRECATED Controller7A              "use toEnum 0x7A instead" #-}+{-# DEPRECATED Controller7B              "use toEnum 0x7B instead" #-}+{-# DEPRECATED Controller7C              "use toEnum 0x7C instead" #-}+{-# DEPRECATED Controller7D              "use toEnum 0x7D instead" #-}+{-# DEPRECATED Controller7E              "use toEnum 0x7E instead" #-}+{-# DEPRECATED Controller7F              "use toEnum 0x7F instead" #-}++ {- | Types of predefined MIDI controllers. -}@@ -296,25 +454,99 @@    | {- 127 7F -} Controller7F        deriving (Show, Eq, Ord, Enum) +++++ bankSelect, modulation, breathControl, footControl, portamentoTime,    dataEntry, mainVolume, balance, panorama, expression,    generalPurpose1, generalPurpose2, generalPurpose3, generalPurpose4,    vectorX, vectorY :: Controller-bankSelect      = BankSelectMSB-modulation      = ModulationMSB-breathControl   = BreathControlMSB-footControl     = FootControlMSB-portamentoTime  = PortamentoTimeMSB-dataEntry       = DataEntryMSB-mainVolume      = MainVolumeMSB-balance         = BalanceMSB-panorama        = PanoramaMSB-expression      = ExpressionMSB-generalPurpose1 = GeneralPurpose1MSB-generalPurpose2 = GeneralPurpose2MSB-generalPurpose3 = GeneralPurpose3MSB-generalPurpose4 = GeneralPurpose4MSB+bankSelect      = bankSelectMSB+modulation      = modulationMSB+breathControl   = breathControlMSB+footControl     = footControlMSB+portamentoTime  = portamentoTimeMSB+dataEntry       = dataEntryMSB+mainVolume      = mainVolumeMSB+balance         = balanceMSB+panorama        = panoramaMSB+expression      = expressionMSB+generalPurpose1 = generalPurpose1MSB+generalPurpose2 = generalPurpose2MSB+generalPurpose3 = generalPurpose3MSB+generalPurpose4 = generalPurpose4MSB  vectorX = generalPurpose1 vectorY = generalPurpose2 +++bankSelectMSB, modulationMSB, breathControlMSB, footControlMSB,+  portamentoTimeMSB, dataEntryMSB, mainVolumeMSB, balanceMSB,+  panoramaMSB, expressionMSB, generalPurpose1MSB, generalPurpose2MSB,+  generalPurpose3MSB, generalPurpose4MSB, bankSelectLSB, modulationLSB,+  breathControlLSB, footControlLSB, portamentoTimeLSB, dataEntryLSB,+  mainVolumeLSB, balanceLSB, panoramaLSB, expressionLSB,+  generalPurpose1LSB, generalPurpose2LSB, generalPurpose3LSB, generalPurpose4LSB :: Controller++sustain, porta, sustenuto, softPedal, hold2,+  generalPurpose5, generalPurpose6, generalPurpose7, generalPurpose8,+  extDepth, tremoloDepth, chorusDepth, celesteDepth, phaserDepth :: Controller++dataIncrement, dataDecrement,+  nonRegisteredParameterLSB, nonRegisteredParameterMSB,+  registeredParameterLSB, registeredParameterMSB :: Controller+++bankSelectMSB             = BankSelectMSB                 {-  00 00 -}+modulationMSB             = ModulationMSB                 {-  01 01 -}+breathControlMSB          = BreathControlMSB              {-  02 02 -}+footControlMSB            = FootControlMSB                {-  04 04 -}+portamentoTimeMSB         = PortamentoTimeMSB             {-  05 05 -}+dataEntryMSB              = DataEntryMSB                  {-  06 06 -}+mainVolumeMSB             = MainVolumeMSB                 {-  07 07 -}+balanceMSB                = BalanceMSB                    {-  08 08 -}+panoramaMSB               = PanoramaMSB                   {-  10 0A -}+expressionMSB             = ExpressionMSB                 {-  11 0B -}+generalPurpose1MSB        = GeneralPurpose1MSB            {-  16 10 -}+generalPurpose2MSB        = GeneralPurpose2MSB            {-  17 11 -}+generalPurpose3MSB        = GeneralPurpose3MSB            {-  18 12 -}+generalPurpose4MSB        = GeneralPurpose4MSB            {-  19 13 -}+bankSelectLSB             = BankSelectLSB                 {-  32 20 -}+modulationLSB             = ModulationLSB                 {-  33 21 -}+breathControlLSB          = BreathControlLSB              {-  34 22 -}+footControlLSB            = FootControlLSB                {-  36 24 -}+portamentoTimeLSB         = PortamentoTimeLSB             {-  37 25 -}+dataEntryLSB              = DataEntryLSB                  {-  38 26 -}+mainVolumeLSB             = MainVolumeLSB                 {-  39 27 -}+balanceLSB                = BalanceLSB                    {-  40 28 -}+panoramaLSB               = PanoramaLSB                   {-  42 2A -}+expressionLSB             = ExpressionLSB                 {-  43 2B -}+generalPurpose1LSB        = GeneralPurpose1LSB            {-  48 30 -}+generalPurpose2LSB        = GeneralPurpose2LSB            {-  49 31 -}+generalPurpose3LSB        = GeneralPurpose3LSB            {-  50 32 -}+generalPurpose4LSB        = GeneralPurpose4LSB            {-  51 33 -}++sustain                   = Sustain                       {-  64 40 -}+porta                     = Porta                         {-  65 41 -}+sustenuto                 = Sustenuto                     {-  66 42 -}+softPedal                 = SoftPedal                     {-  67 43 -}+hold2                     = Hold2                         {-  69 45 -}+generalPurpose5           = GeneralPurpose5               {-  80 50 -}+generalPurpose6           = GeneralPurpose6               {-  81 51 -}+generalPurpose7           = GeneralPurpose7               {-  82 52 -}+generalPurpose8           = GeneralPurpose8               {-  83 53 -}+extDepth                  = ExtDepth                      {-  91 5B -}+tremoloDepth              = TremoloDepth                  {-  92 5C -}+chorusDepth               = ChorusDepth                   {-  93 5D -}+celesteDepth              = CelesteDepth                  {-  94 5E -}+phaserDepth               = PhaserDepth                   {-  95 5F -}++dataIncrement             = DataIncrement                 {-  96 60 -}+dataDecrement             = DataDecrement                 {-  97 61 -}+nonRegisteredParameterLSB = NonRegisteredParameterLSB     {-  98 62 -}+nonRegisteredParameterMSB = NonRegisteredParameterMSB     {-  99 63 -}+registeredParameterLSB    = RegisteredParameterLSB        {- 100 64 -}+registeredParameterMSB    = RegisteredParameterMSB        {- 101 65 -}
src/Sound/MIDI/File/Load.hs view
@@ -12,8 +12,10 @@ But it seems to be not sensible to re-use functionality from the @iff@ package. -}-module Sound.MIDI.File.Load (fromFile, fromStream, maybeFromStream, showFile)- where+module Sound.MIDI.File.Load+   (fromFile, fromStream, maybeFromStream,+    maybeEventFromStream,+    showFile, ) where  import           Sound.MIDI.File import qualified Sound.MIDI.File as MIDIFile@@ -198,7 +200,37 @@ getSchedEvent :: TrackParser MIDIFile.SchedEvent getSchedEvent  =  liftM2 (,) (lift getVar) getEvent +++maybeEventFromStream :: ByteString -> Either String (MIDIFile.Event, ByteString)+maybeEventFromStream = evalParser getIndividualEvent++ {- |+Parse an event, but without a state for the current type of events+like in 'getEvent'.+-}+getIndividualEvent :: ByteParser MIDIFile.Event+getIndividualEvent =+   do+      tag <- get1+      case tag of+        240 -> liftM SysExStart $ getBigN =<< getVar+        247 -> liftM SysExCont  $ getBigN =<< getVar+{-+        255 ->+           do+              code <- get1+              size <- getVar+              liftM MetaEvent (getMetaEvent code size)+-}+        _ -> if tag>127+               then let parseEv = decodeStatus tag+                    in  get1 >>= parseEvent parseEv+               else fail "There is no default MIDI event type when parsing individual MIDI events."+++{- | 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 'getMIDIEvent'. In the case of a MIDIEvent with running status, we find out the status from@@ -217,7 +249,7 @@               code <- get1               size <- getVar               liftM MetaEvent (getMetaEvent code size)-        x -> if x>127+        _ -> if tag>127                then let parseEv = decodeStatus tag                     in  putEventParser parseEv >> lift (get1 >>= parseEvent parseEv)                else -- running status@@ -385,6 +417,7 @@  {- | 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 () showFile fileName = putStr . showChunks =<< readBinaryFile fileName@@ -453,7 +486,7 @@ the type and channel can be omitted for all but the first event. To implement this /feature/, the parser must keep track of the type and channel of the most recent MIDI Event.-This is done by setting a 'EventParser' parser,+This is done by setting an 'EventParser' parser, which parses the data bytes according to the currently active event type. -} type TrackParser a = ParserState.T EventParser ByteString a
src/Sound/MIDI/File/Save.hs view
@@ -2,11 +2,12 @@ Save MIDI data to files.  The functions in this module allow 'Sound.MIDI.File.T's-to be made into Standard MIDI files (@*.mid@)+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 (toFile, toStream, toOpenStream) where+module Sound.MIDI.File.Save+   (toFile, toStream, toOpenStream, eventToStream, ) where  import           Sound.MIDI.File import qualified Sound.MIDI.File   as MIDIFile@@ -23,23 +24,35 @@  {- | The function 'toFile' is the main function-for writing 'MIDIFile.T' values to an actual file;-its first argument is the filename:+for writing 'MIDIFile.T' values to an actual file. -}--toFile :: FilePath -> MIDIFile.T -> IO ()+toFile :: FilePath {- ^ file name -} -> MIDIFile.T -> IO () toFile fn mf = writeBinaryFile fn (toStream mf) -{- |+{- MIDI files are first converted to a monadic string computation using the function 'outMF', and then \"executed\" using 'execWriter'. -} -toStream, toOpenStream :: MIDIFile.T -> ByteString-toStream     = execWriter . outMF outChunk+{- |+Convert a MIDI file to a ByteString.+-}+toStream :: MIDIFile.T -> ByteString+toStream = execWriter . outMF outChunk++{- |+Convert a MIDI file to a ByteString+while replacing chunk lengths by (-1).+This way writing the file is more lazy.+I don't know whether this is useful for anything,+thus simply don't use it.+-}+{-# DEPRECATED toOpenStream "use toStream instead" #-}+toOpenStream :: MIDIFile.T -> ByteString toOpenStream = execWriter . outMF outOpenChunk + outMF :: OutChunk -> MIDIFile.T -> MIDIWriter () outMF outChk (MIDIFile.Cons mft divisn trks) =   do@@ -63,6 +76,10 @@    EventList.mapM_ outVar outputEvent $    EventList.snoc trk 0 (MetaEvent EndOfTrack) ++eventToStream :: MIDIFile.Event -> ByteString+eventToStream = execWriter . outputEvent+ {- | The following functions encode various 'MIDIFile.T' elements into the raw data of a standard MIDI file.@@ -73,7 +90,8 @@    case e of       MIDIEvent ch mevent -> outputMIDIEvent ch mevent       MetaEvent mevent    -> outputMetaEvent mevent-      _                   -> error ("don't know, how to write a "++show e++".")+      SysExStart bytes -> outInt 1 240 >> outLenByteStr bytes+      SysExCont  bytes -> outInt 1 247 >> outLenByteStr bytes  outputMIDIEvent :: MIDIEvent.Channel -> MIDIEvent.T -> MIDIWriter () outputMIDIEvent c e =@@ -100,8 +118,7 @@    do       outInt 1 255       outInt 1 code-      outVar (genericLength bytes)-      outByteStr bytes+      outLenByteStr bytes  outMetaStr :: Int -> String -> MIDIWriter () outMetaStr code =@@ -156,6 +173,11 @@  outByteStr :: ByteString -> MIDIWriter () outByteStr = tell++outLenByteStr :: ByteString -> MIDIWriter ()+outLenByteStr bytes =+   do outVar (genericLength bytes)+      outByteStr bytes  {- | Numbers of variable size are represented by sequences of 7-bit blocks
src/Sound/MIDI/Parser.hs view
@@ -3,12 +3,13 @@ -}  module Sound.MIDI.Parser-   (T, zeroOrMore, oneOrMore, StateT(..), force) where+   (T, zeroOrMore, oneOrMore, StateT(..), force, ) where -import Control.Monad.State (StateT(StateT, runStateT), liftM2, mplus)+import Control.Monad.State (StateT(StateT, runStateT), liftM2, mplus, ) import Control.Monad.Error () -type T s a = StateT s (Either String) a+type T s = StateT s (Either String)+  {- | Wadler's force function
src/Sound/MIDI/ParserState.hs view
@@ -3,13 +3,14 @@ -}  module Sound.MIDI.ParserState-   (T, zeroOrMore, oneOrMore, StateT(..)) where+   (T, zeroOrMore, oneOrMore, StateT(..), ) where  import qualified Sound.MIDI.Parser as Parser -import Control.Monad.State (StateT(..), mapStateT, liftM2, mplus)+import Control.Monad.State (StateT(..), mapStateT, liftM2, mplus, ) -type T st s a = StateT st (StateT s (Either String)) a+type T st s = StateT st (Parser.T s)+  {- | Wadler's force function