Taken from Haskore.
- data T = Cons Type Division [Track]
- data Division
- type Track = T ElapsedTime T
- data Type
- empty :: T
- type ElapsedTime = Integer
- fromElapsedTime :: ElapsedTime -> Integer
- toElapsedTime :: Integer -> ElapsedTime
- type Tempo = Int
- fromTempo :: Tempo -> Int
- toTempo :: Int -> Tempo
- explicitNoteOff :: T -> T
- implicitNoteOff :: T -> T
- getTracks :: T -> [Track]
- mergeTracks :: C time => Type -> [T time event] -> T time event
- secondsFromTicks :: Division -> T ElapsedTime T -> T Rational T
- ticksPerQuarterNote :: Division -> Tempo
- showLines :: T -> String
- changeVelocity :: Double -> T -> T
- resampleTime :: Double -> T -> T
- showEvent :: T -> ShowS
- showTime :: ElapsedTime -> ShowS
- sortEvents :: T -> T
- progChangeBeforeSetTempo :: T -> T
The datatypes for MIDI Files and MIDI Events
NoteOn p 0 to
NoteOff p 64.
The latter one is easier to process.
NoteOff p 64 to
NoteOn p 0.
The latter one can be encoded more efficiently using the running status.
Merge all tracks into a single track according to the MIDI file type.
Process and remove all
The result is an event list where the times are measured in seconds.
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.
Old versions of Haskore.Interface.MIDI.Write
once at the beginning of a file in that order.
The current version supports multiple
ProgramChanges in a track and
ProgramChange is set immediately before a note.
Because of this a
ProgramChange is now always after a
For checking equivalence with old MIDI files we can switch this back.