-- | Operating rate definitions and utilities.
module Sound.SC3.Common.Rate where

import Data.Char {- base -}

-- | Operating rate of unit generator.
--   I = initialisation, K = control, A = audio, D = demand.
--
-- > Data.List.sort [DR,AR,KR,IR] == [IR,KR,AR,DR]
data Rate = IR | KR | AR | DR
            deriving (Rate -> Rate -> Bool
(Rate -> Rate -> Bool) -> (Rate -> Rate -> Bool) -> Eq Rate
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Rate -> Rate -> Bool
$c/= :: Rate -> Rate -> Bool
== :: Rate -> Rate -> Bool
$c== :: Rate -> Rate -> Bool
Eq,Eq Rate
Eq Rate
-> (Rate -> Rate -> Ordering)
-> (Rate -> Rate -> Bool)
-> (Rate -> Rate -> Bool)
-> (Rate -> Rate -> Bool)
-> (Rate -> Rate -> Bool)
-> (Rate -> Rate -> Rate)
-> (Rate -> Rate -> Rate)
-> Ord Rate
Rate -> Rate -> Bool
Rate -> Rate -> Ordering
Rate -> Rate -> Rate
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Rate -> Rate -> Rate
$cmin :: Rate -> Rate -> Rate
max :: Rate -> Rate -> Rate
$cmax :: Rate -> Rate -> Rate
>= :: Rate -> Rate -> Bool
$c>= :: Rate -> Rate -> Bool
> :: Rate -> Rate -> Bool
$c> :: Rate -> Rate -> Bool
<= :: Rate -> Rate -> Bool
$c<= :: Rate -> Rate -> Bool
< :: Rate -> Rate -> Bool
$c< :: Rate -> Rate -> Bool
compare :: Rate -> Rate -> Ordering
$ccompare :: Rate -> Rate -> Ordering
$cp1Ord :: Eq Rate
Ord,Int -> Rate
Rate -> Int
Rate -> [Rate]
Rate -> Rate
Rate -> Rate -> [Rate]
Rate -> Rate -> Rate -> [Rate]
(Rate -> Rate)
-> (Rate -> Rate)
-> (Int -> Rate)
-> (Rate -> Int)
-> (Rate -> [Rate])
-> (Rate -> Rate -> [Rate])
-> (Rate -> Rate -> [Rate])
-> (Rate -> Rate -> Rate -> [Rate])
-> Enum Rate
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Rate -> Rate -> Rate -> [Rate]
$cenumFromThenTo :: Rate -> Rate -> Rate -> [Rate]
enumFromTo :: Rate -> Rate -> [Rate]
$cenumFromTo :: Rate -> Rate -> [Rate]
enumFromThen :: Rate -> Rate -> [Rate]
$cenumFromThen :: Rate -> Rate -> [Rate]
enumFrom :: Rate -> [Rate]
$cenumFrom :: Rate -> [Rate]
fromEnum :: Rate -> Int
$cfromEnum :: Rate -> Int
toEnum :: Int -> Rate
$ctoEnum :: Int -> Rate
pred :: Rate -> Rate
$cpred :: Rate -> Rate
succ :: Rate -> Rate
$csucc :: Rate -> Rate
Enum,Rate
Rate -> Rate -> Bounded Rate
forall a. a -> a -> Bounded a
maxBound :: Rate
$cmaxBound :: Rate
minBound :: Rate
$cminBound :: Rate
Bounded,Int -> Rate -> ShowS
[Rate] -> ShowS
Rate -> String
(Int -> Rate -> ShowS)
-> (Rate -> String) -> ([Rate] -> ShowS) -> Show Rate
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Rate] -> ShowS
$cshowList :: [Rate] -> ShowS
show :: Rate -> String
$cshow :: Rate -> String
showsPrec :: Int -> Rate -> ShowS
$cshowsPrec :: Int -> Rate -> ShowS
Show,ReadPrec [Rate]
ReadPrec Rate
Int -> ReadS Rate
ReadS [Rate]
(Int -> ReadS Rate)
-> ReadS [Rate] -> ReadPrec Rate -> ReadPrec [Rate] -> Read Rate
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Rate]
$creadListPrec :: ReadPrec [Rate]
readPrec :: ReadPrec Rate
$creadPrec :: ReadPrec Rate
readList :: ReadS [Rate]
$creadList :: ReadS [Rate]
readsPrec :: Int -> ReadS Rate
$creadsPrec :: Int -> ReadS Rate
Read)

-- | Integer rate identifier, as required for scsynth bytecode.
rateId :: Rate -> Int
rateId :: Rate -> Int
rateId = Rate -> Int
forall a. Enum a => a -> Int
fromEnum

-- | Color identifiers for each 'Rate'.
rate_color :: Rate -> String
rate_color :: Rate -> String
rate_color Rate
r =
    case Rate
r of
      Rate
AR -> String
"black"
      Rate
KR -> String
"blue"
      Rate
IR -> String
"yellow"
      Rate
DR -> String
"red"

-- | Set of all 'Rate' values.
all_rates :: [Rate]
all_rates :: [Rate]
all_rates = [Rate
forall a. Bounded a => a
minBound .. Rate
forall a. Bounded a => a
maxBound]

-- | Case insensitive parser for rate.
--
-- > Data.Maybe.mapMaybe rate_parse (words "ar kR IR Dr") == [AR,KR,IR,DR]
rate_parse :: String -> Maybe Rate
rate_parse :: String -> Maybe Rate
rate_parse String
r =
    case (Char -> Char) -> ShowS
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toUpper String
r of
      String
"AR" -> Rate -> Maybe Rate
forall a. a -> Maybe a
Just Rate
AR
      String
"KR" -> Rate -> Maybe Rate
forall a. a -> Maybe a
Just Rate
KR
      String
"IR" -> Rate -> Maybe Rate
forall a. a -> Maybe a
Just Rate
IR
      String
"DR" -> Rate -> Maybe Rate
forall a. a -> Maybe a
Just Rate
DR
      String
_ -> Maybe Rate
forall a. Maybe a
Nothing

-- * Control rates

-- | Enumeration of the four operating rates for controls.
--   I = initialisation, K = control, T = trigger, A = audio.
data K_Type = K_IR | K_KR | K_TR | K_AR
             deriving (K_Type -> K_Type -> Bool
(K_Type -> K_Type -> Bool)
-> (K_Type -> K_Type -> Bool) -> Eq K_Type
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: K_Type -> K_Type -> Bool
$c/= :: K_Type -> K_Type -> Bool
== :: K_Type -> K_Type -> Bool
$c== :: K_Type -> K_Type -> Bool
Eq,Int -> K_Type -> ShowS
[K_Type] -> ShowS
K_Type -> String
(Int -> K_Type -> ShowS)
-> (K_Type -> String) -> ([K_Type] -> ShowS) -> Show K_Type
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [K_Type] -> ShowS
$cshowList :: [K_Type] -> ShowS
show :: K_Type -> String
$cshow :: K_Type -> String
showsPrec :: Int -> K_Type -> ShowS
$cshowsPrec :: Int -> K_Type -> ShowS
Show,Eq K_Type
Eq K_Type
-> (K_Type -> K_Type -> Ordering)
-> (K_Type -> K_Type -> Bool)
-> (K_Type -> K_Type -> Bool)
-> (K_Type -> K_Type -> Bool)
-> (K_Type -> K_Type -> Bool)
-> (K_Type -> K_Type -> K_Type)
-> (K_Type -> K_Type -> K_Type)
-> Ord K_Type
K_Type -> K_Type -> Bool
K_Type -> K_Type -> Ordering
K_Type -> K_Type -> K_Type
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: K_Type -> K_Type -> K_Type
$cmin :: K_Type -> K_Type -> K_Type
max :: K_Type -> K_Type -> K_Type
$cmax :: K_Type -> K_Type -> K_Type
>= :: K_Type -> K_Type -> Bool
$c>= :: K_Type -> K_Type -> Bool
> :: K_Type -> K_Type -> Bool
$c> :: K_Type -> K_Type -> Bool
<= :: K_Type -> K_Type -> Bool
$c<= :: K_Type -> K_Type -> Bool
< :: K_Type -> K_Type -> Bool
$c< :: K_Type -> K_Type -> Bool
compare :: K_Type -> K_Type -> Ordering
$ccompare :: K_Type -> K_Type -> Ordering
$cp1Ord :: Eq K_Type
Ord)

-- | Determine class of control given 'Rate' and /trigger/ status.
ktype :: Rate -> Bool -> K_Type
ktype :: Rate -> Bool -> K_Type
ktype Rate
r Bool
tr =
    if Bool
tr
    then case Rate
r of
           Rate
KR -> K_Type
K_TR
           Rate
_ -> String -> K_Type
forall a. HasCallStack => String -> a
error String
"ktype: non KR trigger control"
    else case Rate
r of
           Rate
IR -> K_Type
K_IR
           Rate
KR -> K_Type
K_KR
           Rate
AR -> K_Type
K_AR
           Rate
DR -> String -> K_Type
forall a. HasCallStack => String -> a
error String
"ktype: DR control"