{-# OPTIONS -Wall #-}
module ZMidi.Core.Internal.ExtraTypes
(
SplitByte(..)
, splitByte
, joinByte
, Varlen(..)
, fromVarlen
, toVarlen
, hexStr
) where
import Data.Bits
import Data.Word
import Numeric (showHex)
data SplitByte = SB { upper4 :: !Word8, lower4 :: !Word8 }
deriving (Eq,Ord,Show)
splitByte :: Word8 -> SplitByte
splitByte i = SB (i .&. 0xF0) (i .&. 0x0F)
joinByte :: SplitByte -> Word8
joinByte (SB a b) = (a .&. 0xF0) + (b .&. 0x0F)
data Varlen = V1 !Word8
| V2 !Word8 !Word8
| V3 !Word8 !Word8 !Word8
| V4 !Word8 !Word8 !Word8 !Word8
deriving (Eq,Ord,Show)
up :: Word8 -> Word32
up = fromIntegral . (0x7f .&.)
down :: Word32 -> Word8
down = (0x80 .|.) . fromIntegral
downl :: Word32 -> Word8
downl = (0x7f .&.) . fromIntegral
fromVarlen :: Varlen -> Word32
fromVarlen (V1 a) = up a
fromVarlen (V2 a b) = (left7 $ up a) + up b
fromVarlen (V3 a b c) = (left14 $ up a) + (left7 $ up b) + up c
fromVarlen (V4 a b c d) = (left21 $ up a) + (left14 $ up b)
+ (left7 $ up c) + up d
left7 :: Word32 -> Word32
left7 = (`shiftL` 7)
left14 :: Word32 -> Word32
left14 = (`shiftL` 14)
left21 :: Word32 -> Word32
left21 = (`shiftL` 21)
right7 :: Word32 -> Word32
right7 = (`shiftR` 7)
right14 :: Word32 -> Word32
right14 = (`shiftR` 14)
right21 :: Word32 -> Word32
right21 = (`shiftR` 21)
toVarlen :: Word32 -> Varlen
toVarlen i
| i < 0x80 = V1 (downl i)
| i < 0x4000 = V2 (down $ right7 i) (downl i)
| i < 0x200000 = V3 (down $ right14 i) (down $ right7 i) (downl i)
| otherwise = V4 (down $ right21 i) (down $ right14 i)
(down $ right7 i) (downl i)
hexStr :: (Show a, Integral a) => a -> String
hexStr i = (showString "0x" . showHex i) ""