hsc3-db-0.15: Sound/SC3/UGen/DB/Record.hs
-- | UGen DB record definitions.
module Sound.SC3.UGen.DB.Record where
import Data.List {- base -}
import Data.Maybe {- base -}
import Safe {- safe -}
import Sound.SC3.UGen.Rate {- hsc3 -}
import Sound.SC3.UGen.DB.Meta {- hsc3-db -}
-- | UGen input descriptor
data I = I {input_name :: String
,input_default :: Double}
deriving (Eq,Show)
-- | UGen descriptor
data U = U {ugen_name :: String
,ugen_operating_rates :: [Rate]
,ugen_default_rate :: Rate
,ugen_inputs :: [I]
,ugen_outputs :: Maybe Int
,ugen_summary :: String
,ugen_std_mce :: Bool
,ugen_nc_input :: Bool
,ugen_nc_mce :: Maybe Int
,ugen_filter :: Maybe [Int]
,ugen_reorder :: Maybe [Int]
,ugen_enumerations :: Maybe [(Int,String)]
,ugen_nondet :: Bool
,ugen_pseudo_inputs :: Maybe [Int]
,ugen_fixed_rate :: Maybe Rate
}
deriving (Eq,Show)
-- | (nm,rr,rt,inp,outp,dsc)
--
-- nm = name, rr = possible rates, rt = default rate, inp = list of
-- inputs, outp = output, dsc = description (synopsis)
type SC3_U = (String,[Rate],Rate,[I],Int,String)
remove_nc_inputs :: [I] -> [I]
remove_nc_inputs = let f i = input_name i `notElem` ["numChannels","numChans"] in filter f
-- this is the way the permutations are written...
reorder_f :: Show a => a -> [a1] -> [Int] -> [a1]
reorder_f u inp n =
let f i = let j = fromMaybe (error "read_meta: input reorder") (findIndex (== i) n)
in atNote (show u) inp j
in map f [0 .. length inp - 1]
read_meta :: SC3_U -> U
read_meta sc3_u =
let (nm,rr,rt,inp,outp,dsc) = sc3_u
nc = meta_has_nc_input nm
inp' = if nc then remove_nc_inputs inp else inp
srt = lookup nm meta_input_reorder
inp'' = case srt of
Nothing -> inp'
Just n -> reorder_f sc3_u inp' n
fx = meta_is_fixed_rate nm
ir = if meta_allows_i_rate nm then [IR] else []
rr' = nub (sort (ir ++ rr ++ maybe [] return fx))
in U {ugen_name = nm
,ugen_operating_rates = rr'
,ugen_default_rate = rt
,ugen_inputs = inp''
,ugen_outputs = if meta_has_var_inputs nm then Nothing else Just outp
,ugen_summary = dsc
,ugen_std_mce = meta_is_std_mce nm
,ugen_nc_input = nc
,ugen_nc_mce = lookup nm meta_nc_mce
,ugen_filter = lookup nm meta_filters
,ugen_reorder = srt
,ugen_enumerations = lookup nm meta_enumeration_inputs
,ugen_nondet = meta_is_nondet nm
,ugen_pseudo_inputs = lookup nm meta_pseudo_inputs
,ugen_fixed_rate = fx}
input_enumeration :: U -> Int -> Maybe String
input_enumeration u ix =
case ugen_enumerations u of
Just e -> lookup ix e
Nothing -> Nothing
-- | Infinite default value
inf :: Double
inf = 10 ** 8
-- | Enumeration for @Onsets@ UGen @odftype@ input.
rcomplex :: Double
rcomplex = 3
-- | 'true' is @1@.
true :: Double
true = 1
-- | 'false' is @0@.
false :: Double
false = 0
-- | Alternate view of 'ugen_nc_input' and 'ugen_nc_mce'.
u_fixed_outputs :: U -> Maybe Int
u_fixed_outputs u =
case (ugen_nc_input u,ugen_nc_mce u) of
(False,Nothing) -> ugen_outputs u
_ -> Nothing
-- | Is 'DR' the only allowed 'Rate'?
u_is_demand_rate :: U -> Bool
u_is_demand_rate = (== [DR]) . ugen_operating_rates
-- | List of input names.
--
-- > import Sound.SC3.UGen.DB
-- > fmap u_input_names (uLookup "SinOsc") == Just ["freq","phase"]
-- > fmap u_input_names (uLookup "BufRd") == Just ["bufnum","phase","loop","interpolation"]
-- > fmap u_input_names (uLookup "Dseq") == Just ["list","repeats"]
u_input_names :: U -> [String]
u_input_names = map input_name . ugen_inputs
-- | Is the input 'I' mce collapsed at 'U'.
i_is_mce :: U -> I -> Bool
i_is_mce u i = ugen_std_mce u && i == last (ugen_inputs u)
-- | Pretty printer for 'I'.
--
-- > let Just u = uLookup "SinOsc"
-- > in i_pp u (I 0 "freq" 440.0) == "freq=440.0"
--
-- > let Just u = uLookup "Out"
-- > in i_pp u (I 1 "channelsArray" 0) == "*channelsArray=0.0"
i_pp :: U -> I -> String
i_pp u i =
let m = if i_is_mce u i then "*" else ""
in m ++ input_name i ++ "=" ++ show (input_default i)
-- | Generate simple summary string for 'U'.
u_summary :: U -> String
u_summary u =
let commas = intercalate ", "
mce n = if n then Just "MCE" else Nothing
nc n = if n then Just ("NC INPUT: " ++ show n) else Nothing
flt _ = "FILTER: TRUE"
sq l = "REORDERS INPUTS: " ++ show l
en l = "ENUMERATION INPUTS: " ++ commas (map (\(ix,nm) -> show ix ++ "=" ++ nm) l)
ps l = "PSUEDO INPUTS: " ++ show l
gen f p = fmap f (p u)
nd (d,b) = if d then Just "DEMAND/NONDET" else if b then Just "NONDET" else Nothing
secondary = commas (catMaybes [mce (ugen_std_mce u)
,nc (ugen_nc_input u)
,gen flt ugen_filter
,gen sq ugen_reorder
,gen en ugen_enumerations
,gen ps ugen_pseudo_inputs
,nd (u_is_demand_rate u,ugen_nondet u)])
secondary' = if null secondary then [] else "\n " ++ secondary
in unwords [ugen_name u
,show (ugen_operating_rates u)
,unwords (map (i_pp u) (ugen_inputs u))] ++ secondary'