module Sound.MIDI.Message.Class.Utility where

import Sound.MIDI.Message.Channel.Voice (Pitch, Velocity, Program, Controller, )

import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg
import qualified Sound.MIDI.Message.Channel.Mode as Mode
import qualified Sound.MIDI.Message.Channel as ChannelMsg


note :: Maybe ChannelMsg.Body -> Maybe (Velocity, Pitch, Bool)
program :: Maybe ChannelMsg.Body -> Maybe Program
anyController :: Maybe ChannelMsg.Body -> Maybe (Controller, Int)
pitchBend :: Maybe ChannelMsg.Body -> Maybe Int
channelPressure :: Maybe ChannelMsg.Body -> Maybe Int
mode :: Maybe ChannelMsg.Body -> Maybe Mode.T

note :: Maybe Body -> Maybe (Velocity, Pitch, Bool)
note Maybe Body
msg = do
   ChannelMsg.Voice voice <- Maybe Body
msg
   case voice of
      VoiceMsg.NoteOn  Pitch
pitch Velocity
velocity -> (Velocity, Pitch, Bool) -> Maybe (Velocity, Pitch, Bool)
forall a. a -> Maybe a
Just (Velocity
velocity, Pitch
pitch, Bool
True)
      VoiceMsg.NoteOff Pitch
pitch Velocity
velocity -> (Velocity, Pitch, Bool) -> Maybe (Velocity, Pitch, Bool)
forall a. a -> Maybe a
Just (Velocity
velocity, Pitch
pitch, Bool
False)
      T
_ -> Maybe (Velocity, Pitch, Bool)
forall a. Maybe a
Nothing

program :: Maybe Body -> Maybe Program
program Maybe Body
msg = do
   ChannelMsg.Voice (VoiceMsg.ProgramChange pgm) <- Maybe Body
msg
   return pgm

anyController :: Maybe Body -> Maybe (Controller, Int)
anyController Maybe Body
msg = do
   ChannelMsg.Voice (VoiceMsg.Control ctrl val) <- Maybe Body
msg
   return (ctrl, val)

pitchBend :: Maybe Body -> Maybe Int
pitchBend Maybe Body
msg = do
   ChannelMsg.Voice (VoiceMsg.PitchBend bend) <- Maybe Body
msg
   return bend

channelPressure :: Maybe Body -> Maybe Int
channelPressure Maybe Body
msg = do
   ChannelMsg.Voice (VoiceMsg.MonoAftertouch pressure) <- Maybe Body
msg
   return pressure

mode :: Maybe Body -> Maybe T
mode Maybe Body
msg = do
   ChannelMsg.Mode m <- Maybe Body
msg
   return m


explicitNoteOff ::
   (Velocity, Pitch, Bool) -> (Velocity, Pitch, Bool)
explicitNoteOff :: (Velocity, Pitch, Bool) -> (Velocity, Pitch, Bool)
explicitNoteOff x :: (Velocity, Pitch, Bool)
x@(Velocity
v,Pitch
p,Bool
b) =
   if Bool
b Bool -> Bool -> Bool
&& Velocity
v Velocity -> Velocity -> Bool
forall a. Eq a => a -> a -> Bool
== Int -> Velocity
VoiceMsg.toVelocity Int
0
     then (Int -> Velocity
VoiceMsg.toVelocity Int
64, Pitch
p, Bool
False)
     else (Velocity, Pitch, Bool)
x

implicitNoteOff ::
   (Velocity, Pitch, Bool) -> (Velocity, Pitch, Bool)
implicitNoteOff :: (Velocity, Pitch, Bool) -> (Velocity, Pitch, Bool)
implicitNoteOff x :: (Velocity, Pitch, Bool)
x@(Velocity
v,Pitch
p,Bool
b) =
   if Bool -> Bool
not Bool
b Bool -> Bool -> Bool
&& Velocity
v Velocity -> Velocity -> Bool
forall a. Eq a => a -> a -> Bool
== Int -> Velocity
VoiceMsg.toVelocity Int
64
     then (Int -> Velocity
VoiceMsg.toVelocity Int
0, Pitch
p, Bool
True)
     else (Velocity, Pitch, Bool)
x