module Sound.MIDI.Message.Class.Construct where
import qualified Sound.MIDI.Message.Class.Utility as CU
import Sound.MIDI.Message.Channel (Channel, )
import Sound.MIDI.Message.Channel.Voice (Pitch, Velocity, Program, Controller, )
import qualified Sound.MIDI.File.Event as FileEvent
import qualified Sound.MIDI.Message as MidiMsg
import qualified Sound.MIDI.Message.Channel as ChannelMsg
import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg
import qualified Sound.MIDI.Message.Channel.Mode as Mode
class C event where
note :: Channel -> (Velocity, Pitch, Bool) -> event
program :: Channel -> Program -> event
anyController :: Channel -> (Controller, Int) -> event
pitchBend :: Channel -> Int -> event
channelPressure :: Channel -> Int -> event
mode :: Channel -> Mode.T -> event
liftChannel ::
(a -> ChannelMsg.Body) ->
(Channel -> a -> ChannelMsg.T)
liftChannel makeMsg channel param =
ChannelMsg.Cons channel $ makeMsg param
instance C ChannelMsg.T where
note =
liftChannel $ \(velocity, pitch, on) ->
ChannelMsg.Voice $
(if on then VoiceMsg.NoteOn else VoiceMsg.NoteOff) pitch velocity
program =
liftChannel $ \pgm ->
ChannelMsg.Voice $ VoiceMsg.ProgramChange pgm
anyController =
liftChannel $ \(ctrl, val) ->
ChannelMsg.Voice $ VoiceMsg.Control ctrl val
pitchBend =
liftChannel $ \bend ->
ChannelMsg.Voice $ VoiceMsg.PitchBend bend
channelPressure =
liftChannel $ \pressure ->
ChannelMsg.Voice $ VoiceMsg.MonoAftertouch pressure
mode =
liftChannel $ \m ->
ChannelMsg.Mode m
noteExplicitOff ::
(C event) =>
Channel -> (Velocity, Pitch, Bool) -> event
noteExplicitOff channel =
note channel . CU.explicitNoteOff
noteImplicitOff ::
(C event) =>
Channel -> (Velocity, Pitch, Bool) -> event
noteImplicitOff channel =
note channel . CU.implicitNoteOff
liftMidi ::
(Channel -> a -> ChannelMsg.T) ->
(Channel -> a -> MidiMsg.T)
liftMidi makeMsg channel msg =
MidiMsg.Channel $ makeMsg channel msg
instance C MidiMsg.T where
note = liftMidi note
program = liftMidi program
anyController = liftMidi anyController
pitchBend = liftMidi pitchBend
channelPressure = liftMidi channelPressure
mode = liftMidi mode
liftFile ::
(Channel -> a -> ChannelMsg.T) ->
(Channel -> a -> FileEvent.T)
liftFile makeMsg channel msg =
FileEvent.MIDIEvent $ makeMsg channel msg
instance C FileEvent.T where
note = liftFile note
program = liftFile program
anyController = liftFile anyController
pitchBend = liftFile pitchBend
channelPressure = liftFile channelPressure
mode = liftFile mode