module Sound.MED.Raw.InstrHdr where

import qualified Sound.MED.Raw.HybridInstr as HybridInstr
import Sound.MED.Raw.HybridInstr(HybridInstr)
import qualified Sound.MED.Raw.SynthInstr as SynthInstr
import Sound.MED.Raw.SynthInstr(SynthInstr)
import qualified Sound.MED.Raw.SampleInstr as SampleInstr
import Sound.MED.Raw.SampleInstr(SampleInstr)

import Sound.MED.Basic.Amiga

import Data.Bits ((.&.))

data Instrument =
    Unknown
  | Hybrid HybridInstr
  | Synthetic SynthInstr
  | Sample SampleInstr
  deriving (Int -> Instrument -> ShowS
[Instrument] -> ShowS
Instrument -> String
(Int -> Instrument -> ShowS)
-> (Instrument -> String)
-> ([Instrument] -> ShowS)
-> Show Instrument
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Instrument] -> ShowS
$cshowList :: [Instrument] -> ShowS
show :: Instrument -> String
$cshow :: Instrument -> String
showsPrec :: Int -> Instrument -> ShowS
$cshowsPrec :: Int -> Instrument -> ShowS
Show)

data InstrHdr = InstrHdr
  { InstrHdr -> ULONG
len    :: ULONG
  , InstrHdr -> WORD
stype  :: WORD
  , InstrHdr -> Bool
s16    :: Bool
  , InstrHdr -> Bool
stereo :: Bool
  , InstrHdr -> Bool
md16   :: Bool
  , InstrHdr -> Instrument
dat    :: Instrument
  }
  deriving (Int -> InstrHdr -> ShowS
[InstrHdr] -> ShowS
InstrHdr -> String
(Int -> InstrHdr -> ShowS)
-> (InstrHdr -> String) -> ([InstrHdr] -> ShowS) -> Show InstrHdr
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [InstrHdr] -> ShowS
$cshowList :: [InstrHdr] -> ShowS
show :: InstrHdr -> String
$cshow :: InstrHdr -> String
showsPrec :: Int -> InstrHdr -> ShowS
$cshowsPrec :: Int -> InstrHdr -> ShowS
Show)

{-# SPECIALISE peek :: PTR -> StorableReader InstrHdr #-}
{-# SPECIALISE peek :: PTR -> ByteStringReader InstrHdr #-}
peek :: (Reader m) => PTR -> m InstrHdr
peek :: ULONG -> m InstrHdr
peek ULONG
p = do
  ULONG
len'   <- Peek m ULONG
forall (m :: * -> *). Reader m => Peek m ULONG
peekULONG  ULONG
p
  WORD
itype' <- Peek m WORD
forall (m :: * -> *). Reader m => Peek m WORD
peekWORD  (ULONG
pULONG -> ULONG -> ULONG
forall a. Num a => a -> a -> a
+ULONG
4)
  let s16' :: Bool
s16'    = (WORD
itype' WORD -> WORD -> WORD
forall a. Bits a => a -> a -> a
.&. WORD
0x10) WORD -> WORD -> Bool
forall a. Eq a => a -> a -> Bool
== WORD
0x10
  let stereo' :: Bool
stereo' = (WORD
itype' WORD -> WORD -> WORD
forall a. Bits a => a -> a -> a
.&. WORD
0x20) WORD -> WORD -> Bool
forall a. Eq a => a -> a -> Bool
== WORD
0x20
  let md16' :: Bool
md16'   = WORD
itype'            WORD -> WORD -> Bool
forall a. Eq a => a -> a -> Bool
== WORD
0x18
  let stype' :: WORD
stype'  = if WORD
itype' WORD -> WORD -> Bool
forall a. Ord a => a -> a -> Bool
< WORD
0 then WORD
itype' else WORD
itype' WORD -> WORD -> WORD
forall a. Bits a => a -> a -> a
.&. WORD
0x7
  Instrument
dat' <- case WORD
stype' of
    (-2) -> do
      HybridInstr
hybridinstr' <- ULONG -> m HybridInstr
forall (m :: * -> *). Reader m => ULONG -> m HybridInstr
HybridInstr.peek ULONG
p
      Instrument -> m Instrument
forall (m :: * -> *) a. Monad m => a -> m a
return (Instrument -> m Instrument) -> Instrument -> m Instrument
forall a b. (a -> b) -> a -> b
$ HybridInstr -> Instrument
Hybrid HybridInstr
hybridinstr'
    (-1) -> do
      SynthInstr
synthinstr' <- ULONG -> m SynthInstr
forall (m :: * -> *). Reader m => ULONG -> m SynthInstr
SynthInstr.peek ULONG
p
      Instrument -> m Instrument
forall (m :: * -> *) a. Monad m => a -> m a
return (Instrument -> m Instrument) -> Instrument -> m Instrument
forall a b. (a -> b) -> a -> b
$ SynthInstr -> Instrument
Synthetic SynthInstr
synthinstr'
    WORD
_ -> if WORD
stype' WORD -> WORD -> Bool
forall a. Ord a => a -> a -> Bool
< WORD
0 Bool -> Bool -> Bool
|| WORD
7 WORD -> WORD -> Bool
forall a. Ord a => a -> a -> Bool
< WORD
stype' then Instrument -> m Instrument
forall (m :: * -> *) a. Monad m => a -> m a
return Instrument
Unknown else do
      SampleInstr
sampleinstr' <- ULONG -> WORD -> Bool -> Bool -> ULONG -> m SampleInstr
forall (m :: * -> *).
Reader m =>
ULONG -> WORD -> Bool -> Bool -> ULONG -> m SampleInstr
SampleInstr.peek ULONG
len' WORD
stype' Bool
s16' Bool
stereo' ULONG
p
      Instrument -> m Instrument
forall (m :: * -> *) a. Monad m => a -> m a
return (Instrument -> m Instrument) -> Instrument -> m Instrument
forall a b. (a -> b) -> a -> b
$ SampleInstr -> Instrument
Sample SampleInstr
sampleinstr'
  InstrHdr -> m InstrHdr
forall (m :: * -> *) a. Monad m => a -> m a
return (InstrHdr -> m InstrHdr) -> InstrHdr -> m InstrHdr
forall a b. (a -> b) -> a -> b
$ ULONG -> WORD -> Bool -> Bool -> Bool -> Instrument -> InstrHdr
InstrHdr
    ULONG
len' WORD
stype' Bool
s16' Bool
stereo' Bool
md16' Instrument
dat'