vivid-0.4.2.0: Vivid/Envelopes.hs
-- | Envelopes. **This module is the least mature in vivid and is likely to
-- change a lot in the future!**
{-# OPTIONS_HADDOCK show-extensions #-}
{-# LANGUAGE
DataKinds
, ExistentialQuantification
, KindSignatures
, LambdaCase
, NoIncoherentInstances
, NoMonomorphismRestriction
, NoUndecidableInstances
, FlexibleContexts
#-}
module Vivid.Envelopes (
EnvLiterally(..)
, envLiterallyToSignals
, env
, EnvCurve(..)
, EnvSegment(..)
, shapeNumber
, curveNumber
) where
import Vivid.SynthDef.ToSig (ToSig(..)) -- , SDBody)
import Vivid.SynthDef.Types
-- import Vivid.SynthDef.FromUA (fromUA, Args)
-- import Data.Int
import Data.Monoid
import GHC.TypeLits
import Prelude -- BBP
data EnvLiterally (args :: [Symbol])
= forall initial. (ToSig initial args) =>
EnvLiterally {
_envLiterally_initialVal :: initial
-- ,_envLiterally_numSegments :: Int -- i know this is a 'Literally' but it's so computable...
, _envLiterally_releaseNode :: Maybe Int
, _envLiterally_offset :: Float -- ?? -- only used for 'IEnvGen', which i dont have
-- invariant: releasenode must be larger (or equal?) to/than loopnode
-- also, if one is Just, i think the other must be -- so if that's true, use
-- a different data structure
-- at least for the non-'Literally' one
, _envLiterally_loopNode :: Maybe Int
, _envLiterally_curveSegments :: [EnvSegment]
}
-- deriving (Show, Eq)
{-
InputSpec_UGen {_inputSpec_uGen_index = 2, _inputSpec_uGen_outputIndex = 0}
Constant: 2.0 (index 2) -- length segments
Constant: 1.0 (index 1) -- release node
Constant: -99.0 (index 3) -- loop node
signals?:
Constant: 1.0 (index 1)
Constant: 1.0 (index 1)
Constant: 3.0 (index 4)
Constant: 0.0 (index 0)
Constant: 0.0 (index 0)
Constant: 1.0 (index 1)
Constant: 3.0 (index 4)
Constant: 0.0 (index 0)
-}
-- i think this is (only) for the arguments to EnvGen:
envLiterallyToSignals :: EnvLiterally (b::[Symbol]) -> SDBody' b [Signal]
envLiterallyToSignals envLiterally@(EnvLiterally a _ _ _ _) = do
{-
foo <- case _envLiterally_initialVal envLiterally of
x -> toSigM $ x
-}
foo <- toSig a
return $ [
foo
, Constant . toEnum . (length::[a]->Int) $ _envLiterally_curveSegments envLiterally
, Constant $ case _envLiterally_releaseNode envLiterally of
Just x -> toEnum x
Nothing -> (-99)
, Constant $ case _envLiterally_loopNode envLiterally of
Just x -> toEnum x
Nothing -> (-99)
] <> concatMap envSegmentToSignals (_envLiterally_curveSegments envLiterally)
where
envSegmentToSignals :: EnvSegment -> [Signal]
envSegmentToSignals envSegment = [
_envSegment_targetVal envSegment
, _envSegment_timeToGetThere envSegment
, Constant $ envCurveNumber $ _envSegment_curve envSegment
, Constant $ envCurveFloatNumber $ _envSegment_curve envSegment
]
data EnvSegment
= EnvSegment {
_envSegment_targetVal :: Signal
, _envSegment_timeToGetThere :: Signal
, _envSegment_curve :: EnvCurve
}
deriving (Show, Eq)
data EnvCurve
= Curve_Step
| Curve_Linear
| Curve_Lin
| Curve_Exponential
| Curve_Exp
| Curve_Sine
| Curve_Sin
| Curve_Welch
| Curve_Wel
| Curve_Squared
| Curve_Sqr
| Curve_Cubed
| Curve_Cub
| Curve_Curve Float -- ^ 0 is linear, positive curves up, negative curves down
deriving (Show, Eq)
-- | Same as \"Env.shapeNumber\" in SC.
--
-- This is useful if you want to set a the env shape of a running synth
shapeNumber :: EnvCurve -> Float
shapeNumber = envCurveNumber
-- | "shapeNumber" with a name I like better
curveNumber :: EnvCurve -> Float
curveNumber = shapeNumber
envCurveNumber :: EnvCurve -> Float
envCurveNumber = \case
Curve_Step -> 0
Curve_Linear -> 1
Curve_Lin -> 1
Curve_Exponential -> 2
Curve_Exp -> 2
Curve_Sine -> 3
Curve_Sin -> 3
Curve_Welch -> 4
Curve_Wel -> 4
Curve_Squared -> 6
Curve_Sqr -> 6
Curve_Cubed -> 7
Curve_Cub -> 7
Curve_Curve _ -> 5
envCurveFloatNumber :: EnvCurve -> Float
envCurveFloatNumber = \case
Curve_Curve f -> f
_ -> 0
env :: Float -> [(Float, Float)] -> EnvCurve -> EnvLiterally a
env firstPoint pointsAndLengths curve = EnvLiterally {
_envLiterally_initialVal = firstPoint
, _envLiterally_releaseNode = Nothing
, _envLiterally_offset = 0
, _envLiterally_loopNode = Nothing
, _envLiterally_curveSegments = map foo pointsAndLengths
}
where
foo :: (Float, Float) -> EnvSegment
foo (point, dur) = EnvSegment {
_envSegment_targetVal = Constant point
, _envSegment_timeToGetThere = Constant dur
-- this is, of course, limiting:
, _envSegment_curve = curve
}