{- |
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.
-}moduleSound.MIDI.File.Event(T(..),get,put,TrackEvent,getTrackEvent,ElapsedTime,fromElapsedTime,toElapsedTime,mapBody,maybeMIDIEvent,maybeMetaEvent,maybeVoice,mapVoice,)whereimportqualifiedSound.MIDI.Message.ChannelasChannelMsgimportqualifiedSound.MIDI.Message.Channel.VoiceasVoiceimportqualifiedSound.MIDI.File.Event.SystemExclusiveasSysEximportqualifiedSound.MIDI.File.Event.MetaasMetaEventimportSound.MIDI.Message.Channel(Channel)importSound.MIDI.File.Event.Meta(ElapsedTime,fromElapsedTime,toElapsedTime,)importSound.MIDI.Parser.PrimitiveimportqualifiedSound.MIDI.Parser.StatusasStatusParserimportqualifiedSound.MIDI.Parser.ClassasParserimportControl.Monad(liftM,liftM2,)importqualifiedSound.MIDI.Writer.StatusasStatusWriterimportqualifiedSound.MIDI.Writer.BasicasWriterimportSound.MIDI.Monoid((+#+))importSound.MIDI.Utility(mapSnd)importTest.QuickCheck(Arbitrary(arbitrary),)importqualifiedTest.QuickCheckasQCtypeTrackEvent=(ElapsedTime,T)mapBody::(T->T)->(TrackEvent->TrackEvent)mapBody=mapSnddataT=MIDIEventChannelMsg.T|MetaEventMetaEvent.T|SystemExclusiveSysEx.Tderiving(Show,Eq,Ord)instanceArbitraryTwherearbitrary=QC.frequency$(100,liftMMIDIEventarbitrary):(1,liftMMetaEventarbitrary):[]maybeMIDIEvent::T->MaybeChannelMsg.TmaybeMIDIEvent(MIDIEventmsg)=JustmsgmaybeMIDIEvent_=NothingmaybeMetaEvent::T->MaybeMetaEvent.TmaybeMetaEvent(MetaEventmev)=JustmevmaybeMetaEvent_=NothingmaybeVoice::T->Maybe(Channel,Voice.T)maybeVoice(MIDIEvent(ChannelMsg.Consch(ChannelMsg.Voiceev)))=Just(ch,ev)maybeVoice_=NothingmapVoice::(Voice.T->Voice.T)->T->TmapVoicef(MIDIEvent(ChannelMsg.Consch(ChannelMsg.Voiceev)))=MIDIEvent(ChannelMsg.Consch(ChannelMsg.Voice(fev)))mapVoice_msg=msg-- * serializationget::Parser.Cparser=>Parser.Fallible(StatusParser.Tparser)Tget=StatusParser.liftget1>>=\tag->iftag<0xF0thenliftMMIDIEvent$ChannelMsg.getWithStatustagelseStatusParser.setNothing>>(StatusParser.lift$iftag==0xFFthenliftMMetaEvent$MetaEvent.getelseliftMSystemExclusive$SysEx.gettag){- |
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::Parser.Cparser=>Parser.Fallible(StatusParser.Tparser)TrackEventgetTrackEvent=liftM2(,)(StatusParser.liftgetVar)get{- |
The following functions encode various 'MIDIFile.T' elements
into the raw data of a standard MIDI file.
-}put::Writer.Cwriter=>T->StatusWriter.Twriterpute=caseeofMIDIEventm->StatusWriter.lift(ChannelMsg.putm)MetaEventm->StatusWriter.clear+#+StatusWriter.lift(MetaEvent.putm)SystemExclusivem->StatusWriter.clear+#+StatusWriter.lift(SysEx.putm)