vivid-0.2.0.0: Vivid/UGens/Maths.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
-- {-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE NoIncoherentInstances #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE NoUndecidableInstances #-}
module Vivid.UGens.Maths (
clip
--- , fold -- rename cuz of haskell clashes!
, inRange
-- , inRect
-- In Vivid.UGens.Filters:
-- , integrator
, leastChange
, linExp
--- , linLin
--- , modDif
, mostChange
, mulAdd
--- , runningMax
--- , runningMin
--- , runningSum
--- , schmidt
-- In Vivid.UGens.Analysis:
-- , slope
--- , wrap
) where
import Vivid.SynthDef
import Vivid.SynthDef.FromUA
-- import Vivid.UGens.Algebraic
import Vivid.UGens.Args
import qualified Data.ByteString.Char8 as BS8 (pack)
import Data.Proxy
-- |
-- **Note this has different behavior than 0.1!**
-- \"lo\" is not implied by
-- \"hi\".
--
-- If you know you always want \"lo\" to be negative \"hi\" (like -1 to 1)
-- you can use @'biOp' 'Clip2'@
clip :: (Args '["in"] '["lo", "hi"] a) => a -> SDBody a Signal
clip = makeUGen
"Clip" AR
(Vs::Vs '["in","lo","hi"])
(lo_ (0::Float), hi_ (1::Float))
--- fold ::
--- fold =
-- | Returns 1.0 if \"in\" is between \"lo\" and \"hi\" (including
-- equalling "lo" or "hi"). Else 0.0.
--
-- Can be audio rate (AR), control rate (KR), or fixed (IR)
--
-- Lo and hi default to 0 and 1
inRange :: (Args '["in"] '["lo", "hi"] a) => a -> SDBody a Signal
inRange = makeUGen
"InRange" AR
(Vs::Vs '["in", "lo", "hi"])
(lo_ (0::Float), hi_ (1::Float))
--- -- inRect =
-- | Returns the value of whichever of the 2 signals is changing
-- least
--
-- Its default calculation rate is the highest of its 2 inputs
leastChange :: (ToSig s0 as, ToSig s1 as) => s0 -> s1 -> SDBody' as Signal
leastChange = leastOrMostChange "LeastChange"
leastOrMostChange :: (ToSig s0 as, ToSig s1 as) => String -> s0 -> s1 -> SDBody' as Signal
leastOrMostChange sdName s0 s1 = do
s0' <- toSig s0
s1' <- toSig s1
calcRate <- (maximum::Ord a=>[a]->a) <$> sequence (map getCalcRate [s0', s1'])
addUGen $ UGen (UGName_S . BS8.pack $ sdName) calcRate [s0',s1'] 1
-- | "Converts a linear range of values to an exponential range of values."
--
-- Args:
--
-- * *in* - The input signal to convert.
--
-- * *srclo* - Lower limit of input range.
--
-- * *srchi* - Upper limit of input range.
--
-- * *dstlo* - Lower limit of output range.
--
-- * *dsthi* - Upper limit of output range.
--
-- **"The dstlo and dsthi arguments must be nonzero and have the same sign."**
--
-- This will have the same calculation rate as its \"in\" argument
linExp :: Args '["in"] '["srclo", "srchi", "dstlo", "dsthi"] a => a -> SDBody a Signal
linExp as = do
in' <- as `uaArgVal` (Proxy::Proxy "in")
getCalcRate in' >>= \case
AR -> successGraph AR
KR -> successGraph KR
_ -> error "linExp: 'in' value must be at AR/KR"
where
successGraph calcRate = (flip ($)) as $ makeUGen
"LinExp" calcRate
(Vs::Vs '["in", "srclo", "srchi", "dstlo", "dsthi"])
(srclo_ (0::Float), srchi_ (1::Float), dstlo_ (1::Float), dsthi_ (2::Float))
-- linLin ::
-- linLin =
--- modDif ::
--- modDif =
-- | Opposite of 'leastChange'
mostChange :: (ToSig s0 as, ToSig s1 as) => s0 -> s1 -> SDBody' as Signal
mostChange = leastOrMostChange "MostChange"
mulAdd :: (Args '["in"] '["mul", "add"] a) => a -> SDBody a Signal
mulAdd = makeUGen
"MulAdd" AR
(Vs::Vs '["in", "mul", "add"])
(mul_ (1::Float), add_ (0::Float))
--- runningMax ::
--- runningMax =
--- runningMin ::
--- runningMin =
--- runningSum ::
--- runningSum =
--- schmidt ::
--- schmidt =
--- wrap ::
--- wrap =